netxen: improve msi support
authorDhananjay Phadke <dhananjay@netxen.com>
Tue, 18 Mar 2008 02:59:48 +0000 (19:59 -0700)
committerJeff Garzik <jeff@garzik.org>
Wed, 26 Mar 2008 03:16:15 +0000 (23:16 -0400)
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: Dhananjay Phadke <dhananjay@netxen.com>
Tested-by: Vernon Mauery <mauery@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_phan_reg.h

index 2bc5eaae141fd083a19e4d80c08add20d2d2ee5b..876cd0635f2e8c67cf25b7056dcf9e07a7ecc9ed 100644 (file)
@@ -942,6 +942,7 @@ struct netxen_adapter {
        struct pci_dev *ctx_desc_pdev;
        dma_addr_t ctx_desc_phys_addr;
        int intr_scheme;
+       int msi_mode;
        int (*enable_phy_interrupts) (struct netxen_adapter *);
        int (*disable_phy_interrupts) (struct netxen_adapter *);
        void (*handle_phy_intr) (struct netxen_adapter *);
index d72f8f8fcb50b58f1ffce626dd6da44a6de31216..160f605e58db1fb9508f5bc44e9a83c8372e0b8f 100644 (file)
@@ -456,6 +456,12 @@ enum {
 #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_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_DDR_NET     (0x00000000UL)
@@ -662,6 +668,12 @@ enum {
 
 #define PCIX_TARGET_STATUS     (0x10118)
 #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_F1            (0x13004)
index 01355701bf8ecb9701d2f2d4b46186b774d1bf82..05748ca6f216831543574dda76d0778883365865 100644 (file)
@@ -398,6 +398,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
        printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
                        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");
 
        addr = netxen_alloc(adapter->ahw.pdev,
index 9e38bcb3fba9ac7fe1d25f28015cbd231d4a936e..43eb1f65152d9594eec0813b2780b4046c749e78 100644 (file)
@@ -145,6 +145,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
        /* Window 1 call */
        writel(INTR_SCHEME_PERPORT,
               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,
               NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
        writel(PHAN_INITIALIZE_ACK,
index 9737eae5ef111f265345e1747d008cad953fb7db..cd665da85c7f72978bafa2cfe92b90653ee558bf 100644 (file)
@@ -149,33 +149,31 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
 
 #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)
 {
-       uint32_t        mask = 0x7ff;
+       u32 mask = 0x7ff;
        int retries = 32;
+       int port = adapter->portnum;
+       int pci_fn = adapter->ahw.pci_func;
 
-       DPRINTK(1, INFO, "Entered ISR Disable \n");
-
-       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->msi_mode != MSI_MODE_MULTIFUNC) {
+               writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
        }
 
        if (adapter->intr_scheme != -1 &&
            adapter->intr_scheme != INTR_SCHEME_PERPORT)
                writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
 
-       /* Window = 0 or 1 */
        if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
                do {
                        writel(0xffffffff,
@@ -190,14 +188,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
                        printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
                                        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)
 {
        u32 mask;
+       int port = adapter->portnum;
 
        DPRINTK(1, INFO, "Entered ISR Enable \n");
 
@@ -218,20 +220,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
                writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
        }
 
-       switch (adapter->portnum) {
-       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;
-       }
+       writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
 
        if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
                mask = 0xbff;
@@ -401,6 +390,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* this will be read from FW later */
        adapter->intr_scheme = -1;
+       adapter->msi_mode = -1;
 
        /* This will be reset for mezz cards  */
        adapter->portnum = pci_func_id;
index ffa3b7215ce8eb3dd909da585b4f93b89c50a1a7..a566b50f36f5dac6b3f20b320e479ad75f15712f 100644 (file)
  */
 #define CRB_NIC_CAPABILITIES_HOST      NETXEN_NIC_REG(0x1a8)
 #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 MSI_MODE_MULTIFUNC             0x1
 
 /* used for ethtool tests */
 #define CRB_SCRATCHPAD_TEST        NETXEN_NIC_REG(0x280)