qlcnic: avoid mixed mode interrupts for some adapter types
authorManish chopra <manish.chopra@qlogic.com>
Fri, 25 Jan 2013 10:20:37 +0000 (10:20 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 27 Jan 2013 06:00:08 +0000 (01:00 -0500)
o Some adapter types do not support co-existence of Legacy Interrupt with
  MSI-x or MSI among multiple functions. For those adapters, prevent attaching
  to a function during normal load, if MSI-x or MSI vectors are not available.
o Using module parameters use_msi=0 and use_msi_x=0, driver can be loaded in
  legacy mode for all functions in the adapter.

Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

index e460401667dff7db4ad13dccea63981e7d8ccb1b..5cbf8c64e0f3c298580eaa9f7e609c2c95a2b465 100644 (file)
@@ -395,8 +395,9 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
        return err;
 }
 
-static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
+static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
 {
+       int err = 0;
        u32 offset, mask_reg;
        const struct qlcnic_legacy_intr_set *legacy_intrp;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -409,8 +410,10 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
                                                            offset);
                dev_info(&pdev->dev, "using msi interrupts\n");
                adapter->msix_entries[0].vector = pdev->irq;
-               return;
+               return err;
        }
+       if (qlcnic_use_msi || qlcnic_use_msi_x)
+               return -EOPNOTSUPP;
 
        legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
        adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
@@ -422,11 +425,12 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
        adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG);
        dev_info(&pdev->dev, "using legacy interrupts\n");
        adapter->msix_entries[0].vector = pdev->irq;
+       return err;
 }
 
 int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
 {
-       int num_msix, err;
+       int num_msix, err = 0;
 
        if (!num_intr)
                num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
@@ -441,8 +445,11 @@ int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
        if (err == -ENOMEM || !err)
                return err;
 
-       qlcnic_enable_msi_legacy(adapter);
-       return 0;
+       err = qlcnic_enable_msi_legacy(adapter);
+       if (!err)
+               return err;
+
+       return -EIO;
 }
 
 void qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
@@ -1843,8 +1850,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        board_name, adapter->ahw->revision_id);
        }
        err = qlcnic_setup_intr(adapter, 0);
-       if (err)
+       if (err) {
+               dev_err(&pdev->dev, "Failed to setup interrupt\n");
                goto err_out_disable_msi;
+       }
 
        if (qlcnic_83xx_check(adapter)) {
                err = qlcnic_83xx_setup_mbx_intr(adapter);
@@ -2976,6 +2985,12 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
        adapter->msix_entries = NULL;
        err = qlcnic_setup_intr(adapter, 0);
 
+       if (err) {
+               kfree(adapter->msix_entries);
+               netdev_err(netdev, "failed to setup interrupt\n");
+               return err;
+       }
+
        if (qlcnic_83xx_check(adapter)) {
                err = qlcnic_83xx_setup_mbx_intr(adapter);
                if (err) {
@@ -3131,9 +3146,11 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
        qlcnic_detach(adapter);
        qlcnic_teardown_intr(adapter);
        err = qlcnic_setup_intr(adapter, data);
-       if (err)
-               dev_err(&adapter->pdev->dev,
-                       "failed setting max_rss; rss disabled\n");
+       if (err) {
+               kfree(adapter->msix_entries);
+               netdev_err(netdev, "failed to setup interrupt\n");
+               return err;
+       }
 
        if (qlcnic_83xx_check(adapter)) {
                err = qlcnic_83xx_setup_mbx_intr(adapter);