Commit 443be796 authored by Dhananjay Phadke's avatar Dhananjay Phadke Committed by Jeff Garzik

netxen: improve msi support

Recent netxen firmware has new scheme of generating MSI interrupts, it
raises interrupt and blocks itself, waiting for driver to unmask. This
reduces chance of spurious interrupts.

The driver will be able to deal with older firmware as well.
Signed-off-by: default avatarDhananjay Phadke <dhananjay@netxen.com>
Tested-by: default avatarVernon Mauery <mauery@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 9e6db608
...@@ -942,6 +942,7 @@ struct netxen_adapter { ...@@ -942,6 +942,7 @@ struct netxen_adapter {
struct pci_dev *ctx_desc_pdev; struct pci_dev *ctx_desc_pdev;
dma_addr_t ctx_desc_phys_addr; dma_addr_t ctx_desc_phys_addr;
int intr_scheme; int intr_scheme;
int msi_mode;
int (*enable_phy_interrupts) (struct netxen_adapter *); int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *);
void (*handle_phy_intr) (struct netxen_adapter *); void (*handle_phy_intr) (struct netxen_adapter *);
......
...@@ -456,6 +456,12 @@ enum { ...@@ -456,6 +456,12 @@ enum {
#define ISR_INT_MASK_SLOW (NETXEN_PCIX_PS_REG(PCIX_INT_MASK)) #define ISR_INT_MASK_SLOW (NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
#define ISR_INT_TARGET_STATUS (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS)) #define ISR_INT_TARGET_STATUS (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS))
#define ISR_INT_TARGET_MASK (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK)) #define ISR_INT_TARGET_MASK (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK))
#define ISR_INT_TARGET_STATUS_F1 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F1))
#define ISR_INT_TARGET_MASK_F1 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F1))
#define ISR_INT_TARGET_STATUS_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F2))
#define ISR_INT_TARGET_MASK_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
#define ISR_INT_TARGET_STATUS_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
#define ISR_INT_TARGET_MASK_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
#define NETXEN_PCI_MAPSIZE 128 #define NETXEN_PCI_MAPSIZE 128
#define NETXEN_PCI_DDR_NET (0x00000000UL) #define NETXEN_PCI_DDR_NET (0x00000000UL)
...@@ -662,6 +668,12 @@ enum { ...@@ -662,6 +668,12 @@ enum {
#define PCIX_TARGET_STATUS (0x10118) #define PCIX_TARGET_STATUS (0x10118)
#define PCIX_TARGET_MASK (0x10128) #define PCIX_TARGET_MASK (0x10128)
#define PCIX_TARGET_STATUS_F1 (0x10160)
#define PCIX_TARGET_MASK_F1 (0x10170)
#define PCIX_TARGET_STATUS_F2 (0x10164)
#define PCIX_TARGET_MASK_F2 (0x10174)
#define PCIX_TARGET_STATUS_F3 (0x10168)
#define PCIX_TARGET_MASK_F3 (0x10178)
#define PCIX_MSI_F0 (0x13000) #define PCIX_MSI_F0 (0x13000)
#define PCIX_MSI_F1 (0x13004) #define PCIX_MSI_F1 (0x13004)
......
...@@ -398,6 +398,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) ...@@ -398,6 +398,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name, printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
adapter->intr_scheme); adapter->intr_scheme);
adapter->msi_mode = readl(
NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
DPRINTK(INFO, "Receive Peg ready too. starting stuff\n"); DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");
addr = netxen_alloc(adapter->ahw.pdev, addr = netxen_alloc(adapter->ahw.pdev,
......
...@@ -145,6 +145,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) ...@@ -145,6 +145,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
/* Window 1 call */ /* Window 1 call */
writel(INTR_SCHEME_PERPORT, writel(INTR_SCHEME_PERPORT,
NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST)); NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
writel(MSI_MODE_MULTIFUNC,
NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
writel(MPORT_MULTI_FUNCTION_MODE, writel(MPORT_MULTI_FUNCTION_MODE,
NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
writel(PHAN_INITIALIZE_ACK, writel(PHAN_INITIALIZE_ACK,
......
...@@ -149,33 +149,31 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, ...@@ -149,33 +149,31 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
#define ADAPTER_LIST_SIZE 12 #define ADAPTER_LIST_SIZE 12
static uint32_t msi_tgt_status[4] = {
ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
};
static uint32_t sw_int_mask[4] = {
CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
};
static void netxen_nic_disable_int(struct netxen_adapter *adapter) static void netxen_nic_disable_int(struct netxen_adapter *adapter)
{ {
uint32_t mask = 0x7ff; u32 mask = 0x7ff;
int retries = 32; int retries = 32;
int port = adapter->portnum;
int pci_fn = adapter->ahw.pci_func;
DPRINTK(1, INFO, "Entered ISR Disable \n"); if (adapter->msi_mode != MSI_MODE_MULTIFUNC) {
writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
switch (adapter->portnum) {
case 0:
writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
break;
case 1:
writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
break;
case 2:
writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
break;
case 3:
writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
break;
} }
if (adapter->intr_scheme != -1 && if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT) adapter->intr_scheme != INTR_SCHEME_PERPORT)
writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
/* Window = 0 or 1 */
if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
do { do {
writel(0xffffffff, writel(0xffffffff,
...@@ -190,14 +188,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter) ...@@ -190,14 +188,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
netxen_nic_driver_name); netxen_nic_driver_name);
} }
} else {
if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
msi_tgt_status[pci_fn]));
}
} }
DPRINTK(1, INFO, "Done with Disable Int\n");
} }
static void netxen_nic_enable_int(struct netxen_adapter *adapter) static void netxen_nic_enable_int(struct netxen_adapter *adapter)
{ {
u32 mask; u32 mask;
int port = adapter->portnum;
DPRINTK(1, INFO, "Entered ISR Enable \n"); DPRINTK(1, INFO, "Entered ISR Enable \n");
...@@ -218,20 +220,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter) ...@@ -218,20 +220,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
} }
switch (adapter->portnum) { writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
case 0:
writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
break;
case 1:
writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
break;
case 2:
writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
break;
case 3:
writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
break;
}
if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
mask = 0xbff; mask = 0xbff;
...@@ -401,6 +390,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -401,6 +390,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* this will be read from FW later */ /* this will be read from FW later */
adapter->intr_scheme = -1; adapter->intr_scheme = -1;
adapter->msi_mode = -1;
/* This will be reset for mezz cards */ /* This will be reset for mezz cards */
adapter->portnum = pci_func_id; adapter->portnum = pci_func_id;
......
...@@ -126,8 +126,11 @@ ...@@ -126,8 +126,11 @@
*/ */
#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8)
#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc)
#define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270)
#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274)
#define INTR_SCHEME_PERPORT 0x1 #define INTR_SCHEME_PERPORT 0x1
#define MSI_MODE_MULTIFUNC 0x1
/* used for ethtool tests */ /* used for ethtool tests */
#define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) #define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280)
......
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