bnxt_en: Add function for VF driver to query default VLAN.
authorMichael Chan <michael.chan@broadcom.com>
Mon, 13 Jun 2016 06:25:28 +0000 (02:25 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Jun 2016 23:16:13 +0000 (19:16 -0400)
The PF can setup a default VLAN for a VF.  The default VLAN tag is
automatically inserted and stripped without the knowledge of the
stack running on the VF.  The VF driver needs to know that default
VLAN is enabled as VLAN acceleration on the RX side is no longer
supported.  Call netdev_update_features() to fix up the VLAN features
as necessary.  Also, VLAN strip mode must be enabled to strip out
the default VLAN tag.

Only allow VF default VLAN to be set if the firmware spec is >= 1.2.1.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c

index c777cde85ce416d98f3959178c193c0cca4b6c1c..67608d57c5f09d50528d843f043fc0b5a8e34adc 100644 (file)
@@ -3277,6 +3277,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 +3298,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 +3841,32 @@ 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};
+       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 hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+               struct bnxt_vf_info *vf = &bp->vf;
+
+               vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
+       }
+#endif
+
+func_qcfg_exit:
+       mutex_unlock(&bp->hwrm_cmd_lock);
+       return rc;
+}
+
 int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 {
        int rc = 0;
@@ -4230,6 +4261,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:
@@ -5469,7 +5505,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;
 }
 
index 363884dd9e8ad6f0801dfa29c5b0c648fec34a4e..50d2007a2640c6a83808e1423a1a7f1e26f6f72e 100644 (file)
@@ -143,6 +143,9 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos)
        u16 vlan_tag;
        int rc;
 
+       if (bp->hwrm_spec_code < 0x10201)
+               return -ENOTSUPP;
+
        rc = bnxt_vf_ndo_prep(bp, vf_id);
        if (rc)
                return rc;