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

Staging: sxg: Make SXG driver use MSI-X interrupts if possible

Make Sahara SXG driver use MSI-X interrupts instead of line based interrupts
if possible. In case of problems in getting MSI-X vectors or MSI-X not being
supported, driver will fall back to use previous line based interrupts.
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 c5e5cf5a
...@@ -132,6 +132,9 @@ void sxg_free_sgl_buffers(struct adapter_t *adapter); ...@@ -132,6 +132,9 @@ void sxg_free_sgl_buffers(struct adapter_t *adapter);
void sxg_unmap_resources(struct adapter_t *adapter); void sxg_unmap_resources(struct adapter_t *adapter);
void sxg_free_mcast_addrs(struct adapter_t *adapter); void sxg_free_mcast_addrs(struct adapter_t *adapter);
void sxg_collect_statistics(struct adapter_t *adapter); void sxg_collect_statistics(struct adapter_t *adapter);
static int sxg_register_interrupt(struct adapter_t *adapter);
static void sxg_remove_isr(struct adapter_t *adapter);
static irqreturn_t sxg_isr(int irq, void *dev_id);
#define XXXTODO 0 #define XXXTODO 0
...@@ -250,6 +253,131 @@ static struct sxg_trace_buffer LSxgTraceBuffer; ...@@ -250,6 +253,131 @@ static struct sxg_trace_buffer LSxgTraceBuffer;
#endif /* ATKDBG */ #endif /* ATKDBG */
static struct sxg_trace_buffer *SxgTraceBuffer = NULL; static struct sxg_trace_buffer *SxgTraceBuffer = NULL;
/*
* MSI Related API's
*/
int sxg_register_intr(struct adapter_t *adapter);
int sxg_enable_msi_x(struct adapter_t *adapter);
int sxg_add_msi_isr(struct adapter_t *adapter);
void sxg_remove_msix_isr(struct adapter_t *adapter);
int sxg_set_interrupt_capability(struct adapter_t *adapter);
int sxg_set_interrupt_capability(struct adapter_t *adapter)
{
int ret;
ret = sxg_enable_msi_x(adapter);
if (ret != STATUS_SUCCESS) {
adapter->msi_enabled = FALSE;
DBG_ERROR("sxg_set_interrupt_capability MSI-X Disable\n");
} else {
adapter->msi_enabled = TRUE;
DBG_ERROR("sxg_set_interrupt_capability MSI-X Enable\n");
}
return ret;
}
int sxg_register_intr(struct adapter_t *adapter)
{
int ret = 0;
if (adapter->msi_enabled) {
ret = sxg_add_msi_isr(adapter);
}
else {
DBG_ERROR("MSI-X Enable Failed. Using Pin INT\n");
ret = sxg_register_interrupt(adapter);
if (ret != STATUS_SUCCESS) {
DBG_ERROR("sxg_register_interrupt Failed\n");
}
}
return ret;
}
int sxg_enable_msi_x(struct adapter_t *adapter)
{
int ret;
adapter->nr_msix_entries = 1;
adapter->msi_entries = kmalloc(adapter->nr_msix_entries *
sizeof(struct msix_entry),GFP_KERNEL);
if (!adapter->msi_entries) {
DBG_ERROR("%s:MSI Entries memory allocation Failed\n",__func__);
return -ENOMEM;
}
memset(adapter->msi_entries, 0, adapter->nr_msix_entries *
sizeof(struct msix_entry));
ret = pci_enable_msix(adapter->pcidev, adapter->msi_entries,
adapter->nr_msix_entries);
if (ret) {
DBG_ERROR("Enabling MSI-X with %d vectors failed\n",
adapter->nr_msix_entries);
/*Should try with less vector returned.*/
kfree(adapter->msi_entries);
return STATUS_FAILURE; /*MSI-X Enable failed.*/
}
return (STATUS_SUCCESS);
}
int sxg_add_msi_isr(struct adapter_t *adapter)
{
int ret,i;
if (!adapter->intrregistered) {
for (i=0; i<adapter->nr_msix_entries; i++) {
ret = request_irq (adapter->msi_entries[i].vector,
sxg_isr,
IRQF_SHARED,
adapter->netdev->name,
adapter->netdev);
if (ret) {
DBG_ERROR("sxg: MSI-X request_irq (%s) "
"FAILED [%x]\n", adapter->netdev->name,
ret);
return (ret);
}
}
}
adapter->msi_enabled = TRUE;
adapter->intrregistered = 1;
adapter->IntRegistered = TRUE;
return (STATUS_SUCCESS);
}
void sxg_remove_msix_isr(struct adapter_t *adapter)
{
int i,vector;
struct net_device *netdev = adapter->netdev;
for(i=0; i< adapter->nr_msix_entries;i++)
{
vector = adapter->msi_entries[i].vector;
DBG_ERROR("%s : Freeing IRQ vector#%d\n",__FUNCTION__,vector);
free_irq(vector,netdev);
}
}
static void sxg_remove_isr(struct adapter_t *adapter)
{
struct net_device *netdev = adapter->netdev;
if (adapter->msi_enabled)
sxg_remove_msix_isr(adapter);
else
free_irq(adapter->netdev->irq, netdev);
}
void sxg_reset_interrupt_capability(struct adapter_t *adapter)
{
if (adapter->msi_enabled) {
pci_disable_msix(adapter->pcidev);
kfree(adapter->msi_entries);
adapter->msi_entries = NULL;
}
return;
}
/* /*
* sxg_download_microcode * sxg_download_microcode
* *
...@@ -462,7 +590,7 @@ static int sxg_allocate_resources(struct adapter_t *adapter) ...@@ -462,7 +590,7 @@ static int sxg_allocate_resources(struct adapter_t *adapter)
/* Windows tells us how many CPUs it plans to use for */ /* Windows tells us how many CPUs it plans to use for */
/* RSS */ /* RSS */
RssIds = SXG_RSS_CPU_COUNT(adapter); RssIds = SXG_RSS_CPU_COUNT(adapter);
IsrCount = adapter->MsiEnabled ? RssIds : 1; IsrCount = adapter->msi_enabled ? RssIds : 1;
DBG_ERROR("%s Setup the spinlocks\n", __func__); DBG_ERROR("%s Setup the spinlocks\n", __func__);
...@@ -950,6 +1078,9 @@ static int sxg_entry_probe(struct pci_dev *pcidev, ...@@ -950,6 +1078,9 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
netdev->get_stats = sxg_get_stats; netdev->get_stats = sxg_get_stats;
netdev->set_multicast_list = sxg_mcast_set_list; netdev->set_multicast_list = sxg_mcast_set_list;
SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops); SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops);
err = sxg_set_interrupt_capability(adapter);
if (err != STATUS_SUCCESS)
DBG_ERROR("Cannot enable MSI-X capability\n");
strcpy(netdev->name, "eth%d"); strcpy(netdev->name, "eth%d");
/* strcpy(netdev->name, pci_name(pcidev)); */ /* strcpy(netdev->name, pci_name(pcidev)); */
...@@ -1025,7 +1156,6 @@ static void sxg_disable_interrupt(struct adapter_t *adapter) ...@@ -1025,7 +1156,6 @@ static void sxg_disable_interrupt(struct adapter_t *adapter)
adapter, adapter->InterruptsEnabled, 0, 0); adapter, adapter->InterruptsEnabled, 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);
/* Turn off interrupts by writing to the icr register. */ /* Turn off interrupts by writing to the icr register. */
WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE); WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE);
...@@ -1053,7 +1183,6 @@ static void sxg_enable_interrupt(struct adapter_t *adapter) ...@@ -1053,7 +1183,6 @@ static void sxg_enable_interrupt(struct adapter_t *adapter)
adapter, adapter->InterruptsEnabled, 0, 0); adapter, adapter->InterruptsEnabled, 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);
/* Turn on interrupts by writing to the icr register. */ /* Turn on interrupts by writing to the icr register. */
WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE); WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE);
...@@ -1154,7 +1283,6 @@ static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done, ...@@ -1154,7 +1283,6 @@ static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done,
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);
adapter->IsrCopy[0] = adapter->Isr[0]; adapter->IsrCopy[0] = adapter->Isr[0];
adapter->Isr[0] = 0; adapter->Isr[0] = 0;
...@@ -1197,7 +1325,6 @@ static int sxg_poll(struct napi_struct *napi, int budget) ...@@ -1197,7 +1325,6 @@ static int sxg_poll(struct napi_struct *napi, int budget)
netif_rx_complete(napi); netif_rx_complete(napi);
WRITE_REG(adapter->UcodeRegs[0].Isr, 0, TRUE); WRITE_REG(adapter->UcodeRegs[0].Isr, 0, TRUE);
} }
return work_done; return work_done;
} }
...@@ -1845,7 +1972,6 @@ static int sxg_register_interrupt(struct adapter_t *adapter) ...@@ -1845,7 +1972,6 @@ static int sxg_register_interrupt(struct adapter_t *adapter)
adapter->intrregistered = 1; adapter->intrregistered = 1;
adapter->IntRegistered = TRUE; adapter->IntRegistered = TRUE;
/* Disable RSS with line-based interrupts */ /* Disable RSS with line-based interrupts */
adapter->MsiEnabled = FALSE;
adapter->RssEnabled = FALSE; adapter->RssEnabled = FALSE;
DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n", DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n",
__func__, adapter, adapter->netdev->irq); __func__, adapter, adapter->netdev->irq);
...@@ -1919,9 +2045,9 @@ static int sxg_if_init(struct adapter_t *adapter) ...@@ -1919,9 +2045,9 @@ static int sxg_if_init(struct adapter_t *adapter)
} }
DBG_ERROR("\n"); DBG_ERROR("\n");
} }
status = sxg_register_interrupt(adapter); status = sxg_register_intr(adapter);
if (status != STATUS_SUCCESS) { if (status != STATUS_SUCCESS) {
DBG_ERROR("sxg_if_init: sxg_register_interrupt FAILED %x\n", DBG_ERROR("sxg_if_init: sxg_register_intr FAILED %x\n",
status); status);
sxg_deregister_interrupt(adapter); sxg_deregister_interrupt(adapter);
return (status); return (status);
...@@ -2081,8 +2207,8 @@ int sxg_second_open(struct net_device * dev) ...@@ -2081,8 +2207,8 @@ int sxg_second_open(struct net_device * dev)
SXG_ENABLE_ALL_INTERRUPTS(adapter); SXG_ENABLE_ALL_INTERRUPTS(adapter);
netif_carrier_on(dev); netif_carrier_on(dev);
spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
sxg_register_interrupt(adapter); sxg_register_interrupt(adapter);
spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
return (STATUS_SUCCESS); return (STATUS_SUCCESS);
} }
...@@ -2099,6 +2225,7 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev) ...@@ -2099,6 +2225,7 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
/* Deallocate Resources */ /* Deallocate Resources */
unregister_netdev(dev); unregister_netdev(dev);
sxg_reset_interrupt_capability(adapter);
sxg_free_resources(adapter); sxg_free_resources(adapter);
ASSERT(adapter); ASSERT(adapter);
...@@ -2133,7 +2260,7 @@ static int sxg_entry_halt(struct net_device *dev) ...@@ -2133,7 +2260,7 @@ static int sxg_entry_halt(struct net_device *dev)
unsigned long flags; unsigned long flags;
RssIds = SXG_RSS_CPU_COUNT(adapter); RssIds = SXG_RSS_CPU_COUNT(adapter);
IsrCount = adapter->MsiEnabled ? RssIds : 1; IsrCount = adapter->msi_enabled ? RssIds : 1;
napi_disable(&adapter->napi); napi_disable(&adapter->napi);
spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
...@@ -2147,9 +2274,6 @@ static int sxg_entry_halt(struct net_device *dev) ...@@ -2147,9 +2274,6 @@ static int sxg_entry_halt(struct net_device *dev)
DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n", DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n",
__func__, dev->name, adapter, adapter->state); __func__, dev->name, adapter, adapter->state);
DBG_ERROR("sxg: %s (%s) EXIT\n", __func__, dev->name);
DBG_ERROR("sxg: %s EXIT\n", __func__);
/* Disable interrupts */ /* Disable interrupts */
SXG_DISABLE_ALL_INTERRUPTS(adapter); SXG_DISABLE_ALL_INTERRUPTS(adapter);
...@@ -2196,11 +2320,13 @@ static int sxg_entry_halt(struct net_device *dev) ...@@ -2196,11 +2320,13 @@ static int sxg_entry_halt(struct net_device *dev)
memset(adapter->XmtRingZeroIndex, 0, sizeof(u32)); memset(adapter->XmtRingZeroIndex, 0, sizeof(u32));
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
for (i = 0; i < SXG_MAX_RSS; i++) { for (i = 0; i < SXG_MAX_RSS; i++) {
adapter->NextEvent[i] = 0; adapter->NextEvent[i] = 0;
} }
atomic_set(&adapter->pending_allocations, 0); atomic_set(&adapter->pending_allocations, 0);
adapter->intrregistered = 0;
sxg_remove_isr(adapter);
DBG_ERROR("sxg: %s (%s) EXIT\n", __FUNCTION__, dev->name);
return (STATUS_SUCCESS); return (STATUS_SUCCESS);
} }
...@@ -3451,9 +3577,8 @@ void sxg_unmap_resources(struct adapter_t *adapter) ...@@ -3451,9 +3577,8 @@ void sxg_unmap_resources(struct adapter_t *adapter)
void sxg_free_resources(struct adapter_t *adapter) void sxg_free_resources(struct adapter_t *adapter)
{ {
u32 RssIds, IsrCount; u32 RssIds, IsrCount;
struct net_device *netdev = adapter->netdev;
RssIds = SXG_RSS_CPU_COUNT(adapter); RssIds = SXG_RSS_CPU_COUNT(adapter);
IsrCount = adapter->MsiEnabled ? RssIds : 1; IsrCount = adapter->msi_enabled ? RssIds : 1;
if (adapter->BasicAllocations == FALSE) { if (adapter->BasicAllocations == FALSE) {
/* /*
...@@ -3463,9 +3588,6 @@ void sxg_free_resources(struct adapter_t *adapter) ...@@ -3463,9 +3588,6 @@ void sxg_free_resources(struct adapter_t *adapter)
return; return;
} }
/* Free Irq */
free_irq(adapter->netdev->irq, netdev);
if (!(IsListEmpty(&adapter->AllRcvBlocks))) { if (!(IsListEmpty(&adapter->AllRcvBlocks))) {
sxg_free_rcvblocks(adapter); sxg_free_rcvblocks(adapter);
} }
...@@ -3877,7 +3999,7 @@ static int sxg_initialize_adapter(struct adapter_t *adapter) ...@@ -3877,7 +3999,7 @@ static int sxg_initialize_adapter(struct adapter_t *adapter)
adapter, 0, 0, 0); adapter, 0, 0, 0);
RssIds = 1; /* XXXTODO SXG_RSS_CPU_COUNT(adapter); */ RssIds = 1; /* XXXTODO SXG_RSS_CPU_COUNT(adapter); */
IsrCount = adapter->MsiEnabled ? RssIds : 1; IsrCount = adapter->msi_enabled ? RssIds : 1;
/* /*
* Sanity check SXG_UCODE_REGS structure definition to * Sanity check SXG_UCODE_REGS structure definition to
......
...@@ -676,7 +676,7 @@ struct adapter_t { ...@@ -676,7 +676,7 @@ struct adapter_t {
u32 DumpCmdRunning:1; /* Dump command in progress */ u32 DumpCmdRunning:1; /* Dump command in progress */
u32 DebugRunning:1; /* AGDB debug in progress */ u32 DebugRunning:1; /* AGDB debug in progress */
u32 JumboEnabled:1; /* Jumbo frames enabled */ u32 JumboEnabled:1; /* Jumbo frames enabled */
u32 MsiEnabled:1; /* MSI interrupt enabled */ u32 msi_enabled:1; /* MSI interrupt enabled */
u32 RssEnabled:1; /* RSS Enabled */ u32 RssEnabled:1; /* RSS Enabled */
u32 FailOnBadEeprom:1; /* Fail on Bad Eeprom */ u32 FailOnBadEeprom:1; /* Fail on Bad Eeprom */
u32 DiagStart:1; /* Init adapter for diagnostic start */ u32 DiagStart:1; /* Init adapter for diagnostic start */
...@@ -709,6 +709,9 @@ struct adapter_t { ...@@ -709,6 +709,9 @@ struct adapter_t {
/* PSXG_DUMP_CMD DumpBuffer; */ /* 68k - Cmd and Buffer */ /* PSXG_DUMP_CMD DumpBuffer; */ /* 68k - Cmd and Buffer */
/* dma_addr_t PDumpBuffer; */ /* Physical address */ /* dma_addr_t PDumpBuffer; */ /* Physical address */
/*#endif */ /* SXG_FAILURE_DUMP */ /*#endif */ /* SXG_FAILURE_DUMP */
/*MSI-X related data elements*/
u32 nr_msix_entries;
struct msix_entry *msi_entries;
}; };
#if SLIC_DUMP_ENABLED #if SLIC_DUMP_ENABLED
......
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