Commit b62a294f authored by Mithlesh Thukral's avatar Mithlesh Thukral Committed by Greg Kroah-Hartman

Staging: sxg: Add NAPI feature to Sahara SXG Driver

* Add NAPI support for SXG driver for Alacritech's 10Gbe products.
  The driver will now work in NAPI mode by default.
Signed-off-by: default avatarLinSysSoft Sahara Team <saharaproj@linsyssoft.com>
Signed-off-by: default avatarMithlesh Thukral <mithlesh@linsyssoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b040b07b
...@@ -112,9 +112,13 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb); ...@@ -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, static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
struct sxg_scatter_gather *SxgSgl); 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 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 void sxg_complete_slow_send(struct adapter_t *adapter, int irq_context);
static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
struct sxg_event *Event); struct sxg_event *Event);
...@@ -743,7 +747,6 @@ static inline int sxg_read_config(struct adapter_t *adapter) ...@@ -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->dev_addr, adapter->currmacaddr, 6);
memcpy(adapter->netdev->perm_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); sxg_dbg_macaddrs(adapter);
return status; return status;
...@@ -955,6 +958,8 @@ static int sxg_entry_probe(struct pci_dev *pcidev, ...@@ -955,6 +958,8 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
goto err_out_unmap; goto err_out_unmap;
} }
netif_napi_add(netdev, &adapter->napi,
sxg_poll, SXG_NETDEV_WEIGHT);
DBG_ERROR DBG_ERROR
("sxg: %s addr 0x%lx, irq %d, MAC addr \ ("sxg: %s addr 0x%lx, irq %d, MAC addr \
%02X:%02X:%02X:%02X:%02X:%02X\n", %02X:%02X:%02X:%02X:%02X:%02X\n",
...@@ -1090,9 +1095,6 @@ static irqreturn_t sxg_isr(int irq, void *dev_id) ...@@ -1090,9 +1095,6 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
* Move the Isr contents and clear the value in * Move the Isr contents and clear the value in
* shared memory, and mask interrupts * 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); */ /* ASSERT(adapter->IsrDpcsPending == 0); */
#if XXXTODO /* RSS Stuff */ #if XXXTODO /* RSS Stuff */
/* /*
...@@ -1127,27 +1129,42 @@ static irqreturn_t sxg_isr(int irq, void *dev_id) ...@@ -1127,27 +1129,42 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
} }
*TargetCpus = CpuMask; *TargetCpus = CpuMask;
#endif #endif
/* There are no DPCs in Linux, so call the handler now */ sxg_interrupt(adapter);
sxg_handle_interrupt(adapter);
return IRQ_HANDLED; 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; */ /* unsigned char RssId = 0; */
u32 NewIsr; u32 NewIsr;
int sxg_napi_continue = 1;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr", SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr",
adapter, adapter->IsrCopy[0], 0, 0); adapter, adapter->IsrCopy[0], 0, 0);
/* For now, RSS is disabled with line based interrupts */ /* For now, RSS is disabled with line based interrupts */
ASSERT(adapter->RssEnabled == FALSE); ASSERT(adapter->RssEnabled == FALSE);
ASSERT(adapter->MsiEnabled == FALSE); ASSERT(adapter->MsiEnabled == FALSE);
ASSERT(adapter->IsrCopy[0]);
adapter->IsrCopy[0] = adapter->Isr[0];
adapter->Isr[0] = 0;
/* Always process the event queue. */ /* Always process the event queue. */
sxg_process_event_queue(adapter, while (sxg_napi_continue)
(adapter->RssEnabled ? /*RssId */ 0 : 0)); {
sxg_process_event_queue(adapter,
(adapter->RssEnabled ? /*RssId */ 0 : 0),
&sxg_napi_continue, work_done, budget);
}
#if XXXTODO /* RSS stuff */ #if XXXTODO /* RSS stuff */
if (--adapter->IsrDpcsPending) { if (--adapter->IsrDpcsPending) {
...@@ -1165,11 +1182,23 @@ static void sxg_handle_interrupt(struct adapter_t *adapter) ...@@ -1165,11 +1182,23 @@ static void sxg_handle_interrupt(struct adapter_t *adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr", SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr",
adapter, NewIsr, 0, 0); adapter, NewIsr, 0, 0);
WRITE_REG(adapter->UcodeRegs[0].Isr, NewIsr, TRUE);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt", SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt",
adapter, 0, 0, 0); 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 * 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) ...@@ -1285,7 +1314,8 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId)
* Return Value: * Return Value:
* None. * 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_ring *EventRing = &adapter->EventRings[RssId];
struct sxg_event *Event = &EventRing->Ring[adapter->NextEvent[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) ...@@ -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. * we shouldn't need a lock for any of this.
*/ */
while (Event->Status & EVENT_STATUS_VALID) { while (Event->Status & EVENT_STATUS_VALID) {
(*sxg_napi_continue) = 1;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event", SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event",
Event, Event->Code, Event->Status, Event, Event->Code, Event->Status,
adapter->NextEvent); adapter->NextEvent);
...@@ -1327,6 +1358,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) ...@@ -1327,6 +1358,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
Event->CommandIndex); Event->CommandIndex);
break; break;
case EVENT_CODE_SLOWRCV: case EVENT_CODE_SLOWRCV:
(*work_done)++;
--adapter->RcvBuffersOnCard; --adapter->RcvBuffersOnCard;
if ((skb = sxg_slow_receive(adapter, Event))) { if ((skb = sxg_slow_receive(adapter, Event))) {
u32 rx_bytes; u32 rx_bytes;
...@@ -1349,7 +1381,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) ...@@ -1349,7 +1381,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif #endif
skb->dev = adapter->netdev; skb->dev = adapter->netdev;
netif_rx(skb); netif_receive_skb(skb);
#endif #endif
} }
break; break;
...@@ -1409,7 +1441,17 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) ...@@ -1409,7 +1441,17 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
break; 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 #ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
/* Indicate any received dumb-nic frames */ /* Indicate any received dumb-nic frames */
SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs); SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs);
...@@ -1907,6 +1949,20 @@ static int sxg_if_init(struct adapter_t *adapter) ...@@ -1907,6 +1949,20 @@ static int sxg_if_init(struct adapter_t *adapter)
return (STATUS_SUCCESS); 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) static int sxg_entry_open(struct net_device *dev)
{ {
struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
...@@ -1959,6 +2015,8 @@ static int sxg_entry_open(struct net_device *dev) ...@@ -1959,6 +2015,8 @@ static int sxg_entry_open(struct net_device *dev)
return (status); return (status);
} }
DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__); DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__);
sxg_set_interrupt_aggregation(adapter);
napi_enable(&adapter->napi);
/* Enable interrupts */ /* Enable interrupts */
SXG_ENABLE_ALL_INTERRUPTS(adapter); SXG_ENABLE_ALL_INTERRUPTS(adapter);
...@@ -1972,12 +2030,16 @@ static int sxg_entry_open(struct net_device *dev) ...@@ -1972,12 +2030,16 @@ static int sxg_entry_open(struct net_device *dev)
int sxg_second_open(struct net_device * dev) int sxg_second_open(struct net_device * dev)
{ {
struct adapter_t *adapter = (struct adapter_t*) netdev_priv(dev); struct adapter_t *adapter = (struct adapter_t*) netdev_priv(dev);
int status = 0;
spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
netif_start_queue(adapter->netdev); netif_start_queue(adapter->netdev);
adapter->state = ADAPT_UP; adapter->state = ADAPT_UP;
adapter->linkstate = LINK_UP; adapter->linkstate = LINK_UP;
status = sxg_initialize_adapter(adapter);
sxg_set_interrupt_aggregation(adapter);
napi_enable(&adapter->napi);
/* Re-enable interrupts */ /* Re-enable interrupts */
SXG_ENABLE_ALL_INTERRUPTS(adapter); SXG_ENABLE_ALL_INTERRUPTS(adapter);
...@@ -2029,6 +2091,7 @@ static int sxg_entry_halt(struct net_device *dev) ...@@ -2029,6 +2091,7 @@ static int sxg_entry_halt(struct net_device *dev)
{ {
struct adapter_t *adapter = (struct adapter_t *) netdev_priv(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); spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name); 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) ...@@ -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__, * DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__,
* skb); * skb);
*/ */
printk("ASK:sxg_send_packets: skb[%p]\n", skb);
/* Check the adapter state */ /* Check the adapter state */
switch (adapter->State) { switch (adapter->State) {
......
...@@ -48,6 +48,9 @@ ...@@ -48,6 +48,9 @@
#define SXG_DRV_VERSION "1.0.1" #define SXG_DRV_VERSION "1.0.1"
extern char sxg_driver_name[]; extern char sxg_driver_name[];
#define SXG_NETDEV_WEIGHT 64
/* /*
* struct sxg_stats - Probably move these to someplace where * struct sxg_stats - Probably move these to someplace where
* the slicstat (sxgstat?) program can get them. * the slicstat (sxgstat?) program can get them.
...@@ -524,6 +527,7 @@ struct sxgbase_driver { ...@@ -524,6 +527,7 @@ struct sxgbase_driver {
struct adapter_t { struct adapter_t {
void * ifp; void * ifp;
unsigned int port; unsigned int port;
struct napi_struct napi;
struct physcard *physcard; struct physcard *physcard;
unsigned int physport; unsigned int physport;
unsigned int slotnumber; unsigned int slotnumber;
...@@ -701,6 +705,8 @@ struct adapter_t { ...@@ -701,6 +705,8 @@ struct adapter_t {
#if defined(CONFIG_X86) #if defined(CONFIG_X86)
u32 AddrUpper; /* Upper 32 bits of 64-bit register */ u32 AddrUpper; /* Upper 32 bits of 64-bit register */
#endif #endif
unsigned short max_aggregation;
unsigned short min_aggregation;
/*#if SXG_FAILURE_DUMP */ /*#if SXG_FAILURE_DUMP */
/* NDIS_EVENT DumpThreadEvent; */ /* syncronize dump thread */ /* NDIS_EVENT DumpThreadEvent; */ /* syncronize dump thread */
/* BOOLEAN DumpThreadRunning; */ /* termination flag */ /* BOOLEAN DumpThreadRunning; */ /* termination flag */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment