bnxt_en: Enable NPAR (NIC Partitioning) Support.
[deliverable/linux.git] / drivers / net / ethernet / broadcom / bnxt / bnxt.c
index 72a2efff8e494c7f077b2ee1311bdd54e857ca03..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,
 };
 
@@ -286,7 +287,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
                txr->tx_prod = prod;
 
+               tx_buf->is_push = 1;
                netdev_tx_sent_queue(txq, skb->len);
+               wmb();  /* Sync is_push and byte queue before pushing data */
 
                push_len = (length + sizeof(*tx_push) + 7) / 8;
                if (push_len > 16) {
@@ -298,7 +301,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                         push_len);
                }
 
-               tx_buf->is_push = 1;
                goto tx_done;
        }
 
@@ -1112,19 +1114,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
        if (tpa_info->hash_type != PKT_HASH_TYPE_NONE)
                skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type);
 
-       if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) {
-               netdev_features_t features = skb->dev->features;
+       if ((tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u16 vlan_proto = tpa_info->metadata >>
                        RX_CMP_FLAGS2_METADATA_TPID_SFT;
+               u16 vtag = tpa_info->metadata & RX_CMP_FLAGS2_METADATA_VID_MASK;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD)) {
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              tpa_info->metadata &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
-               }
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -1277,19 +1273,14 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 
        skb->protocol = eth_type_trans(skb, dev);
 
-       if (rxcmp1->rx_cmp_flags2 &
-           cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) {
-               netdev_features_t features = skb->dev->features;
+       if ((rxcmp1->rx_cmp_flags2 &
+            cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data);
+               u16 vtag = meta_data & RX_CMP_FLAGS2_METADATA_VID_MASK;
                u16 vlan_proto = meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD))
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              meta_data &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -1368,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);
@@ -3287,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 */
@@ -3307,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);
@@ -3846,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;
@@ -4240,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:
@@ -4933,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))
@@ -5466,6 +5505,27 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 
        if (!bnxt_rfs_capable(bp))
                features &= ~NETIF_F_NTUPLE;
+
+       /* Both CTAG and STAG VLAN accelaration on the RX side have to be
+        * turned on or off together.
+        */
+       if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) !=
+           (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) {
+               if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
+                       features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
+                                     NETIF_F_HW_VLAN_STAG_RX);
+               else
+                       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;
 }
 
@@ -5581,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);
@@ -5634,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)
@@ -5670,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);
@@ -6361,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.030687 seconds and 5 git commands to generate.