]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Staging: sxg: Add NAPI feature to Sahara SXG Driver
authorMithlesh Thukral <mithlesh@linsyssoft.com>
Fri, 30 Jan 2009 14:49:03 +0000 (20:19 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 3 Apr 2009 21:53:11 +0000 (14:53 -0700)
* Add NAPI support for SXG driver for Alacritech's 10Gbe products.
  The driver will now work in NAPI mode by default.

Signed-off-by: LinSysSoft Sahara Team <saharaproj@linsyssoft.com>
Signed-off-by: Mithlesh Thukral <mithlesh@linsyssoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/sxg/sxg.c
drivers/staging/sxg/sxg.h

index 312931d4f61a59ee1c3f88beb5c790456065555b..500e30ce3bdeacd2a22966adec125424941fd817 100644 (file)
@@ -112,9 +112,13 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb);
 static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
                                struct sxg_scatter_gather *SxgSgl);
 
-static void sxg_handle_interrupt(struct adapter_t *adapter);
+static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done,
+                                        int budget);
+static void sxg_interrupt(struct adapter_t *adapter);
+static int sxg_poll(struct napi_struct *napi, int budget);
 static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId);
-static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId);
+static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId,
+                        int *sxg_napi_continue, int *work_done, int budget);
 static void sxg_complete_slow_send(struct adapter_t *adapter, int irq_context);
 static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
                                        struct sxg_event *Event);
@@ -743,7 +747,6 @@ static inline int sxg_read_config(struct adapter_t *adapter)
                memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6);
                memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6);
        }
-       printk("LINSYS : These are the new MAC address\n");
        sxg_dbg_macaddrs(adapter);
 
        return status;
@@ -955,6 +958,8 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
                goto err_out_unmap;
        }
 
+       netif_napi_add(netdev, &adapter->napi,
+               sxg_poll, SXG_NETDEV_WEIGHT);
        DBG_ERROR
            ("sxg: %s addr 0x%lx, irq %d, MAC addr \
                %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1090,9 +1095,6 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
         * Move the Isr contents and clear the value in
         * shared memory, and mask interrupts
         */
-       adapter->IsrCopy[0] = adapter->Isr[0];
-       adapter->Isr[0] = 0;
-       WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE);
        /* ASSERT(adapter->IsrDpcsPending == 0); */
 #if XXXTODO                    /* RSS Stuff */
        /*
@@ -1127,27 +1129,42 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
        }
        *TargetCpus = CpuMask;
 #endif
-       /*  There are no DPCs in Linux, so call the handler now */
-       sxg_handle_interrupt(adapter);
+       sxg_interrupt(adapter);
 
        return IRQ_HANDLED;
 }
 
-static void sxg_handle_interrupt(struct adapter_t *adapter)
+static void sxg_interrupt(struct adapter_t *adapter)
+{
+       WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE);
+
+       if (netif_rx_schedule_prep(&adapter->napi)) {
+               __netif_rx_schedule(&adapter->napi);
+       }
+}
+
+static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done,
+                                        int budget)
 {
        /* unsigned char           RssId   = 0; */
        u32 NewIsr;
-
+       int sxg_napi_continue = 1;
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr",
                  adapter, adapter->IsrCopy[0], 0, 0);
        /* For now, RSS is disabled with line based interrupts */
        ASSERT(adapter->RssEnabled == FALSE);
        ASSERT(adapter->MsiEnabled == FALSE);
-       ASSERT(adapter->IsrCopy[0]);
+
+       adapter->IsrCopy[0] = adapter->Isr[0];
+       adapter->Isr[0] = 0;
 
        /* Always process the event queue. */
-       sxg_process_event_queue(adapter,
-                               (adapter->RssEnabled ? /*RssId */ 0 : 0));
+       while (sxg_napi_continue)
+       {
+               sxg_process_event_queue(adapter,
+                               (adapter->RssEnabled ? /*RssId */ 0 : 0),
+                                &sxg_napi_continue, work_done, budget);
+       }
 
 #if XXXTODO                    /* RSS stuff */
        if (--adapter->IsrDpcsPending) {
@@ -1165,11 +1182,23 @@ static void sxg_handle_interrupt(struct adapter_t *adapter)
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr",
                  adapter, NewIsr, 0, 0);
 
-       WRITE_REG(adapter->UcodeRegs[0].Isr, NewIsr, TRUE);
-
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt",
                  adapter, 0, 0, 0);
 }
+static int sxg_poll(struct napi_struct *napi, int budget)
+{
+       struct adapter_t *adapter = container_of(napi, struct adapter_t, napi);
+       int work_done = 0;
+
+       sxg_handle_interrupt(adapter, &work_done, budget);
+
+       if (work_done < budget) {
+               netif_rx_complete(napi);
+               WRITE_REG(adapter->UcodeRegs[0].Isr, 0, TRUE);
+       }
+
+       return work_done;
+}
 
 /*
  * sxg_process_isr - Process an interrupt.  Called from the line-based and
@@ -1285,7 +1314,8 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId)
  * Return Value:
  *     None.
  */
-static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
+static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId,
+                        int *sxg_napi_continue, int *work_done, int budget)
 {
        struct sxg_event_ring *EventRing = &adapter->EventRings[RssId];
        struct sxg_event *Event = &EventRing->Ring[adapter->NextEvent[RssId]];
@@ -1316,6 +1346,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
         * we shouldn't need a lock for any of this.
         */
        while (Event->Status & EVENT_STATUS_VALID) {
+               (*sxg_napi_continue) = 1;
                SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event",
                          Event, Event->Code, Event->Status,
                          adapter->NextEvent);
@@ -1327,6 +1358,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
                                                       Event->CommandIndex);
                        break;
                case EVENT_CODE_SLOWRCV:
+                       (*work_done)++;
                        --adapter->RcvBuffersOnCard;
                        if ((skb = sxg_slow_receive(adapter, Event))) {
                                u32 rx_bytes;
@@ -1349,7 +1381,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
 #endif
                                skb->dev = adapter->netdev;
-                               netif_rx(skb);
+                               netif_receive_skb(skb);
 #endif
                        }
                        break;
@@ -1409,7 +1441,17 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
                                break;
                        }
                }
+               if (*work_done >= budget) {
+                       WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
+                                 EventsProcessed, FALSE);
+                       EventsProcessed = 0;
+                       (*sxg_napi_continue) = 0;
+                       break;
+               }
        }
+       if (!(Event->Status & EVENT_STATUS_VALID))
+               (*sxg_napi_continue) = 0;
+
 #ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
        /* Indicate any received dumb-nic frames */
        SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs);
@@ -1907,6 +1949,20 @@ static int sxg_if_init(struct adapter_t *adapter)
        return (STATUS_SUCCESS);
 }
 
+void sxg_set_interrupt_aggregation(struct adapter_t *adapter)
+{
+       /*
+        * Top bit disables aggregation on xmt (SXG_AGG_XMT_DISABLE).
+        * Make sure Max is less than 0x8000.
+        */
+       adapter->max_aggregation = SXG_MAX_AGG_DEFAULT;
+       adapter->min_aggregation = SXG_MIN_AGG_DEFAULT;
+       WRITE_REG(adapter->UcodeRegs[0].Aggregation,
+               ((adapter->max_aggregation << SXG_MAX_AGG_SHIFT) |
+                       adapter->min_aggregation),
+                       TRUE);
+}
+
 static int sxg_entry_open(struct net_device *dev)
 {
        struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
@@ -1959,6 +2015,8 @@ static int sxg_entry_open(struct net_device *dev)
                return (status);
        }
        DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__);
+       sxg_set_interrupt_aggregation(adapter);
+       napi_enable(&adapter->napi);
 
        /* Enable interrupts */
        SXG_ENABLE_ALL_INTERRUPTS(adapter);
@@ -1972,12 +2030,16 @@ static int sxg_entry_open(struct net_device *dev)
 int sxg_second_open(struct net_device * dev)
 {
        struct adapter_t *adapter = (struct adapter_t*) netdev_priv(dev);
+       int status = 0;
 
        spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
        netif_start_queue(adapter->netdev);
         adapter->state = ADAPT_UP;
         adapter->linkstate = LINK_UP;
 
+       status = sxg_initialize_adapter(adapter);
+       sxg_set_interrupt_aggregation(adapter);
+       napi_enable(&adapter->napi);
         /* Re-enable interrupts */
         SXG_ENABLE_ALL_INTERRUPTS(adapter);
 
@@ -2029,6 +2091,7 @@ static int sxg_entry_halt(struct net_device *dev)
 {
        struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
 
+       napi_disable(&adapter->napi);
        spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
        DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name);
 
@@ -2105,7 +2168,6 @@ static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev)
         * DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__,
         *        skb);
         */
-       printk("ASK:sxg_send_packets: skb[%p]\n", skb);
 
        /* Check the adapter state */
        switch (adapter->State) {
index 2d969736c8f55a8b1f14d4c2432bab376bc4c6a7..ae77903c4aef1ee99a4946ab6aec14606c3bd68f 100644 (file)
@@ -48,6 +48,9 @@
 #define SXG_DRV_VERSION        "1.0.1"
 
 extern char sxg_driver_name[];
+
+#define SXG_NETDEV_WEIGHT 64
+
 /*
  * struct sxg_stats - Probably move these to someplace where
  * the slicstat (sxgstat?) program can get them.
@@ -524,6 +527,7 @@ struct sxgbase_driver {
 struct adapter_t {
        void *               ifp;
        unsigned int                port;
+       struct napi_struct      napi;
        struct physcard        *physcard;
        unsigned int                physport;
        unsigned int                slotnumber;
@@ -701,6 +705,8 @@ struct adapter_t {
 #if defined(CONFIG_X86)
        u32             AddrUpper;                      /* Upper 32 bits of 64-bit register */
 #endif
+       unsigned short max_aggregation;
+       unsigned short min_aggregation;
        /*#if SXG_FAILURE_DUMP */
        /*      NDIS_EVENT      DumpThreadEvent; */     /* syncronize dump thread */
        /*      BOOLEAN         DumpThreadRunning; */   /* termination flag */