bnxt_en: Enable NPAR (NIC Partitioning) Support.
[deliverable/linux.git] / drivers / net / ethernet / broadcom / bnxt / bnxt.c
index c777cde85ce416d98f3959178c193c0cca4b6c1c..9d785e6d194fd288c3d62765e656f3e260078cc3 100644 (file)
@@ -125,6 +125,7 @@ static const u16 bnxt_async_events_arr[] = {
        HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
        HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
        HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
+       HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
        HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
 };
 
@@ -1358,6 +1359,11 @@ static int bnxt_async_event_process(struct bnxt *bp,
                set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
                break;
        }
+       case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
+               if (BNXT_PF(bp))
+                       goto async_event_process_exit;
+               set_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event);
+               break;
        default:
                netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n",
                           event_id);
@@ -3277,6 +3283,7 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
        unsigned int ring = 0, grp_idx;
        struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
        struct hwrm_vnic_cfg_input req = {0};
+       u16 def_vlan = 0;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_CFG, -1, -1);
        /* Only RSS support for now TBD: COS & LB */
@@ -3297,7 +3304,11 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
        req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN +
                              VLAN_HLEN);
 
-       if (bp->flags & BNXT_FLAG_STRIP_VLAN)
+#ifdef CONFIG_BNXT_SRIOV
+       if (BNXT_VF(bp))
+               def_vlan = bp->vf.vlan;
+#endif
+       if ((bp->flags & BNXT_FLAG_STRIP_VLAN) || def_vlan)
                req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
 
        return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -3836,6 +3847,39 @@ static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp)
        return 0;
 }
 
+static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
+{
+       struct hwrm_func_qcfg_input req = {0};
+       struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+       int rc;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
+       req.fid = cpu_to_le16(0xffff);
+       mutex_lock(&bp->hwrm_cmd_lock);
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (rc)
+               goto func_qcfg_exit;
+
+#ifdef CONFIG_BNXT_SRIOV
+       if (BNXT_VF(bp)) {
+               struct bnxt_vf_info *vf = &bp->vf;
+
+               vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
+       }
+#endif
+       switch (resp->port_partition_type) {
+       case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0:
+       case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5:
+       case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR2_0:
+               bp->port_partition_type = resp->port_partition_type;
+               break;
+       }
+
+func_qcfg_exit:
+       mutex_unlock(&bp->hwrm_cmd_lock);
+       return rc;
+}
+
 int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 {
        int rc = 0;
@@ -4230,6 +4274,11 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
                netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
                            rc);
 
+       if (BNXT_VF(bp)) {
+               bnxt_hwrm_func_qcfg(bp);
+               netdev_update_features(bp->dev);
+       }
+
        return 0;
 
 err_out:
@@ -4923,7 +4972,7 @@ static int bnxt_hwrm_shutdown_link(struct bnxt *bp)
 {
        struct hwrm_port_phy_cfg_input req = {0};
 
-       if (BNXT_VF(bp))
+       if (!BNXT_SINGLE_PF(bp))
                return 0;
 
        if (pci_num_vf(bp->pdev))
@@ -5469,7 +5518,14 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
                        features |= NETIF_F_HW_VLAN_CTAG_RX |
                                    NETIF_F_HW_VLAN_STAG_RX;
        }
-
+#ifdef CONFIG_BNXT_SRIOV
+       if (BNXT_VF(bp)) {
+               if (bp->vf.vlan) {
+                       features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
+                                     NETIF_F_HW_VLAN_STAG_RX);
+               }
+       }
+#endif
        return features;
 }
 
@@ -5585,9 +5641,10 @@ static void bnxt_dbg_dump_states(struct bnxt *bp)
        }
 }
 
-static void bnxt_reset_task(struct bnxt *bp)
+static void bnxt_reset_task(struct bnxt *bp, bool silent)
 {
-       bnxt_dbg_dump_states(bp);
+       if (!silent)
+               bnxt_dbg_dump_states(bp);
        if (netif_running(bp->dev)) {
                bnxt_close_nic(bp, false, false);
                bnxt_open_nic(bp, false, false);
@@ -5638,6 +5695,23 @@ bnxt_restart_timer:
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
+/* Only called from bnxt_sp_task() */
+static void bnxt_reset(struct bnxt *bp, bool silent)
+{
+       /* bnxt_reset_task() calls bnxt_close_nic() which waits
+        * for BNXT_STATE_IN_SP_TASK to clear.
+        * If there is a parallel dev_close(), bnxt_close() may be holding
+        * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
+        * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
+        */
+       clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       rtnl_lock();
+       if (test_bit(BNXT_STATE_OPEN, &bp->state))
+               bnxt_reset_task(bp, silent);
+       set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       rtnl_unlock();
+}
+
 static void bnxt_cfg_ntp_filters(struct bnxt *);
 
 static void bnxt_sp_task(struct work_struct *work)
@@ -5674,16 +5748,11 @@ static void bnxt_sp_task(struct work_struct *work)
                bnxt_hwrm_tunnel_dst_port_free(
                        bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
        }
-       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) {
-               /* bnxt_reset_task() calls bnxt_close_nic() which waits
-                * for BNXT_STATE_IN_SP_TASK to clear.
-                */
-               clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
-               rtnl_lock();
-               bnxt_reset_task(bp);
-               set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
-               rtnl_unlock();
-       }
+       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+               bnxt_reset(bp, false);
+
+       if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
+               bnxt_reset(bp, true);
 
        if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
                bnxt_get_port_module_status(bp);
@@ -6365,6 +6434,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto init_err;
        }
 
+       bnxt_hwrm_func_qcfg(bp);
+
        bnxt_set_tpa_flags(bp);
        bnxt_set_ring_params(bp);
        if (BNXT_PF(bp))
This page took 0.032943 seconds and 5 git commands to generate.