From mithlesh@linsyssoft.com Tue Feb 3 16:24:55 2009 From: Mithlesh Thukral Date: Fri, 30 Jan 2009 20:19:03 +0530 (IST) Subject: Staging: sxg: Add NAPI feature to Sahara SXG Driver To: Greg Kroah-Hartman Cc: Sahara Project , Michael Miles , Christopher Harrer Message-ID: * 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 Signed-off-by: Mithlesh Thukral Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sxg/sxg.c | 98 +++++++++++++++++++++++++++++++++++++--------- drivers/staging/sxg/sxg.h | 6 ++ 2 files changed, 86 insertions(+), 18 deletions(-) --- a/drivers/staging/sxg/sxg.c +++ b/drivers/staging/sxg/sxg.c @@ -112,9 +112,13 @@ static int sxg_transmit_packet(struct ad 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 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_de 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 * 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 } *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 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 adapte * 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(struc * 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(struc 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(struc 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(struc 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 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_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_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_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_bu * 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) { --- a/drivers/staging/sxg/sxg.h +++ b/drivers/staging/sxg/sxg.h @@ -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 */