From patchwork Tue Dec 4 13:33:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sony Chacko X-Patchwork-Id: 203642 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 86B4A2C008F for ; Wed, 5 Dec 2012 00:53:02 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754001Ab2LDNw4 (ORCPT ); Tue, 4 Dec 2012 08:52:56 -0500 Received: from mvnat01.qlogic.com ([198.186.3.73]:9937 "HELO linux-zupk.site" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with SMTP id S1753217Ab2LDNwm (ORCPT ); Tue, 4 Dec 2012 08:52:42 -0500 Received: by linux-zupk.site (Postfix, from userid 0) id 82D9B521EAB; Tue, 4 Dec 2012 08:34:01 -0500 (EST) From: Sony Chacko To: davem@davemloft.net Cc: netdev@vger.kernel.org, Dept_NX_Linux_NIC_Driver@qlogic.com, Sony Chacko Subject: [PATCH 5/7] qlcnic: update NIC partition interface routines Date: Tue, 4 Dec 2012 08:33:56 -0500 Message-Id: <1354628038-2234-6-git-send-email-sony.chacko@qlogic.com> X-Mailer: git-send-email 1.7.7 In-Reply-To: <1354628038-2234-1-git-send-email-sony.chacko@qlogic.com> References: <1354628038-2234-1-git-send-email-sony.chacko@qlogic.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Sony Chacko Refactor 82xx driver to support new adapter Update routines to support variable number of NIC partitions Signed-off-by: Rajesh Borundia Signed-off-by: Sony Chacko --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 + drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 39 +++++++-- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 97 +++++++++++++--------- 3 files changed, 89 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 4d85c70..5379024 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1051,6 +1051,7 @@ struct qlcnic_npar_info { u8 mac_anti_spoof; u8 promisc_mode; u8 offload_flags; + u8 pci_func; }; struct qlcnic_eswitch { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index c5cfbaa..58f094c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -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)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index bfcd004..d94d3e9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -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; }