qlcnic: update NIC partition interface routines
authorSony Chacko <sony.chacko@qlogic.com>
Tue, 4 Dec 2012 03:33:56 +0000 (03:33 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Dec 2012 18:00:12 +0000 (13:00 -0500)
Refactor 82xx driver to support new adapter
Update routines to support variable number of NIC partitions

Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

index 4d85c70..5379024 100644 (file)
@@ -1051,6 +1051,7 @@ struct qlcnic_npar_info {
        u8      mac_anti_spoof;
        u8      promisc_mode;
        u8      offload_flags;
+       u8      pci_func;
 };
 
 struct qlcnic_eswitch {
index c5cfbaa..58f094c 100644 (file)
@@ -7,6 +7,18 @@
 
 #include "qlcnic.h"
 
+static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
+{
+       int i;
+
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+               if (adapter->npars[i].pci_func == pci_func)
+                       return i;
+       }
+
+       return -1;
+}
+
 static u32
 qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
 {
@@ -817,11 +829,14 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
        qlcnic_issue_cmd(adapter, &cmd);
        err = cmd.rsp.cmd;
 
+       adapter->ahw->act_pci_func = 0;
        if (err == QLCNIC_RCODE_SUCCESS) {
                for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
                        pci_info->id = le16_to_cpu(npar->id);
                        pci_info->active = le16_to_cpu(npar->active);
                        pci_info->type = le16_to_cpu(npar->type);
+                       if (pci_info->type == QLCNIC_TYPE_NIC)
+                               adapter->ahw->act_pci_func++;
                        pci_info->default_port =
                                le16_to_cpu(npar->default_port);
                        pci_info->tx_min_bw =
@@ -1016,12 +1031,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
        esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
        esw_stats->context_id = eswitch;
 
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                if (adapter->npars[i].phy_port != eswitch)
                        continue;
 
                memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
-               if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+               if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func,
+                                         rx_tx, &port_stats))
                        continue;
 
                esw_stats->size = port_stats.size;
@@ -1120,7 +1136,7 @@ op_type = 1 for port vlan_id
 int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
                struct qlcnic_esw_func_cfg *esw_cfg)
 {
-       int err = -EIO;
+       int err = -EIO, index;
        u32 arg1, arg2 = 0;
        struct qlcnic_cmd_args cmd;
        u8 pci_func;
@@ -1128,7 +1144,10 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
        if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return err;
        pci_func = esw_cfg->pci_func;
-       arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+       index = qlcnic_is_valid_nic_func(adapter, pci_func);
+       if (index < 0)
+               return err;
+       arg1 = (adapter->npars[index].phy_port & BIT_0);
        arg1 |= (pci_func << 8);
 
        if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
@@ -1192,11 +1211,17 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
                        struct qlcnic_esw_func_cfg *esw_cfg)
 {
        u32 arg1, arg2;
+       int index;
        u8 phy_port;
-       if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
-               phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
-       else
+
+       if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+               index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func);
+               if (index < 0)
+                       return -EIO;
+               phy_port = adapter->npars[index].phy_port;
+       } else {
                phy_port = adapter->ahw->physical_port;
+       }
        arg1 = phy_port;
        arg1 |= (esw_cfg->pci_func << 8);
        if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
index 85adf0d..88084a3 100644 (file)
@@ -91,6 +91,9 @@ static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
 static int qlcnic_vlan_rx_add(struct net_device *, u16);
 static int qlcnic_vlan_rx_del(struct net_device *, u16);
 
+#define QLCNIC_IS_TSO_CAPABLE(adapter) \
+       ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
        {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -369,19 +372,25 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
                iounmap(adapter->ahw->pci_base0);
 }
 
-static int
-qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
+static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_pci_info *pci_info;
-       int i, ret = 0;
+       int i, ret = 0, j = 0;
+       u16 act_pci_func;
        u8 pfn;
 
        pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
        if (!pci_info)
                return -ENOMEM;
 
+       ret = qlcnic_get_pci_info(adapter, pci_info);
+       if (ret)
+               goto err_pci_info;
+
+       act_pci_func = adapter->ahw->act_pci_func;
+
        adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
-                               QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
+                                act_pci_func, GFP_KERNEL);
        if (!adapter->npars) {
                ret = -ENOMEM;
                goto err_pci_info;
@@ -394,21 +403,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
                goto err_npars;
        }
 
-       ret = qlcnic_get_pci_info(adapter, pci_info);
-       if (ret)
-               goto err_eswitch;
-
        for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
                pfn = pci_info[i].id;
+
                if (pfn >= QLCNIC_MAX_PCI_FUNC) {
                        ret = QL_STATUS_INVALID_PARAM;
                        goto err_eswitch;
                }
-               adapter->npars[pfn].active = (u8)pci_info[i].active;
-               adapter->npars[pfn].type = (u8)pci_info[i].type;
-               adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
-               adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
-               adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
+
+               if (!pci_info[i].active ||
+                   (pci_info[i].type != QLCNIC_TYPE_NIC))
+                       continue;
+
+               adapter->npars[j].pci_func = pfn;
+               adapter->npars[j].active = (u8)pci_info[i].active;
+               adapter->npars[j].type = (u8)pci_info[i].type;
+               adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
+               adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
+               adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
+               j++;
        }
 
        for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -436,7 +449,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
        u32 ref_count;
        int i, ret = 1;
        u32 data = QLCNIC_MGMT_FUNC;
-       void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
 
        /* If other drivers are not in use set their privilege level */
        ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
@@ -445,21 +458,20 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
                goto err_lock;
 
        if (qlcnic_config_npars) {
-               for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-                       id = i;
-                       if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
-                               id == adapter->ahw->pci_func)
+               for (i = 0; i < ahw->act_pci_func; i++) {
+                       id = adapter->npars[i].pci_func;
+                       if (id == ahw->pci_func)
                                continue;
                        data |= (qlcnic_config_npars &
                                        QLC_DEV_SET_DRV(0xf, id));
                }
        } else {
-               data = readl(priv_op);
-               data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) |
+               data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE);
+               data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
                        (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
-                       adapter->ahw->pci_func));
+                                        ahw->pci_func));
        }
-       writel(data, priv_op);
+       QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data);
        qlcnic_api_unlock(adapter);
 err_lock:
        return ret;
@@ -632,6 +644,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        int err;
        struct qlcnic_info nic_info;
 
+       memset(&nic_info, 0, sizeof(struct qlcnic_info));
        err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
        if (err)
                return err;
@@ -798,8 +811,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
        return err;
 }
 
-static int
-qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
+static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_esw_func_cfg esw_cfg;
        struct qlcnic_npar_info *npar;
@@ -808,16 +820,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
        if (adapter->need_fw_reset)
                return 0;
 
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-                       continue;
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
-               esw_cfg.pci_func = i;
-               esw_cfg.offload_flags = BIT_0;
+               esw_cfg.pci_func = adapter->npars[i].pci_func;
                esw_cfg.mac_override = BIT_0;
                esw_cfg.promisc_mode = BIT_0;
-               if (adapter->ahw->capabilities  & QLCNIC_FW_CAPABILITY_TSO)
-                       esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+               if (qlcnic_82xx_check(adapter)) {
+                       esw_cfg.offload_flags = BIT_0;
+                       if (QLCNIC_IS_TSO_CAPABLE(adapter))
+                               esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+               }
                if (qlcnic_config_switch_port(adapter, &esw_cfg))
                        return -EIO;
                npar = &adapter->npars[i];
@@ -855,22 +867,24 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
        return 0;
 }
 
-static int
-qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
 {
        int i, err;
        struct qlcnic_npar_info *npar;
        struct qlcnic_info nic_info;
+       u8 pci_func;
 
-       if (!adapter->need_fw_reset)
-               return 0;
+       if (qlcnic_82xx_check(adapter))
+               if (!adapter->need_fw_reset)
+                       return 0;
 
        /* Set the NPAR config data after FW reset */
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                npar = &adapter->npars[i];
-               if (npar->type != QLCNIC_TYPE_NIC)
-                       continue;
-               err = qlcnic_get_nic_info(adapter, &nic_info, i);
+               pci_func = npar->pci_func;
+               memset(&nic_info, 0, sizeof(struct qlcnic_info));
+               err = qlcnic_get_nic_info(adapter,
+                                         &nic_info, pci_func);
                if (err)
                        return err;
                nic_info.min_tx_bw = npar->min_bw;
@@ -881,11 +895,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
 
                if (npar->enable_pm) {
                        err = qlcnic_config_port_mirroring(adapter,
-                                                       npar->dest_npar, 1, i);
+                                                          npar->dest_npar, 1,
+                                                          pci_func);
                        if (err)
                                return err;
                }
-               err = qlcnic_reset_eswitch_config(adapter, npar, i);
+               err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
                if (err)
                        return err;
        }