bnx2x: Add iproute2 support for vfs
authorAriel Elior <ariele@broadcom.com>
Mon, 11 Mar 2013 05:17:45 +0000 (05:17 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 12 Mar 2013 11:54:23 +0000 (07:54 -0400)
This patch adds support for iproute2 callbacks allowing querying a physical
function as to its child virtual functions, and setting the macs and vlans
of said virtual functions.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h

index 8ddc78bada4979d66b4c78aa470d30f3846d1efc..d62d037b292805267d277f1a5a39d91de5e11cca 100644 (file)
@@ -1214,6 +1214,7 @@ enum {
        BNX2X_SP_RTNL_ENABLE_SRIOV,
        BNX2X_SP_RTNL_VFPF_MCAST,
        BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
+       BNX2X_SP_RTNL_HYPERVISOR_VLAN,
 };
 
 
index 8d158d8240a2e6ecdb82a51b46488cf346d35f8d..4620fa5666e5b30bfcdca2c17d85831151991bbf 100644 (file)
@@ -496,7 +496,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 /* setup_tc callback */
 int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
 
+int bnx2x_get_vf_config(struct net_device *dev, int vf,
+                       struct ifla_vf_info *ivi);
 int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
+int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
index 423b5a074c80d8e4c37754b4f1af016c77b93e37..9be9b0373ca9c7943c77f22c53f59b56be76defd 100644 (file)
@@ -75,8 +75,6 @@
 #define FW_FILE_NAME_E1H       "bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw"
 #define FW_FILE_NAME_E2                "bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw"
 
-#define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
-
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT             (5*HZ)
 
@@ -3227,16 +3225,29 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 {
        struct eth_stats_info *ether_stat =
                &bp->slowpath->drv_info_to_mcp.ether_stat;
+       struct bnx2x_vlan_mac_obj *mac_obj =
+               &bp->sp_objs->mac_obj;
+       int i;
 
        strlcpy(ether_stat->version, DRV_MODULE_VERSION,
                ETH_STAT_INFO_VERSION_LEN);
 
-       bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj,
-                                       DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,
-                                       ether_stat->mac_local);
-
+       /* get DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED macs, placing them in the
+        * mac_local field in ether_stat struct. The base address is offset by 2
+        * bytes to account for the field being 8 bytes but a mac address is
+        * only 6 bytes. Likewise, the stride for the get_n_elements function is
+        * 2 bytes to compensate from the 6 bytes of a mac to the 8 bytes
+        * allocated by the ether_stat struct, so the macs will land in their
+        * proper positions.
+        */
+       for (i = 0; i < DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED; i++)
+               memset(ether_stat->mac_local + i, 0,
+                      sizeof(ether_stat->mac_local[0]));
+       mac_obj->get_n_elements(bp, &bp->sp_objs[0].mac_obj,
+                               DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,
+                               ether_stat->mac_local + MAC_PAD, MAC_PAD,
+                               ETH_ALEN);
        ether_stat->mtu_size = bp->dev->mtu;
-
        if (bp->dev->features & NETIF_F_RXCSUM)
                ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK;
        if (bp->dev->features & NETIF_F_TSO)
@@ -3258,8 +3269,7 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
        if (!CNIC_LOADED(bp))
                return;
 
-       memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT,
-              bp->fip_mac, ETH_ALEN);
+       memcpy(fcoe_stat->mac_local + MAC_PAD, bp->fip_mac, ETH_ALEN);
 
        fcoe_stat->qos_priority =
                app->traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE];
@@ -3361,8 +3371,8 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
        if (!CNIC_LOADED(bp))
                return;
 
-       memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT,
-              bp->cnic_eth_dev.iscsi_mac, ETH_ALEN);
+       memcpy(iscsi_stat->mac_local + MAC_PAD, bp->cnic_eth_dev.iscsi_mac,
+              ETH_ALEN);
 
        iscsi_stat->qos_priority =
                app->traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI];
@@ -9525,6 +9535,10 @@ sp_rtnl_not_reset:
                bnx2x_vfpf_storm_rx_mode(bp);
        }
 
+       if (test_and_clear_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+                              &bp->sp_rtnl_state))
+               bnx2x_pf_set_vfs_vlan(bp);
+
        /* work which needs rtnl lock not-taken (as it takes the lock itself and
         * can be called from other contexts as well)
         */
@@ -11798,6 +11812,8 @@ static const struct net_device_ops bnx2x_netdev_ops = {
        .ndo_setup_tc           = bnx2x_setup_tc,
 #ifdef CONFIG_BNX2X_SRIOV
        .ndo_set_vf_mac         = bnx2x_set_vf_mac,
+       .ndo_set_vf_vlan        = bnx2x_set_vf_vlan,
+       .ndo_get_vf_config      = bnx2x_get_vf_config,
 #endif
 #ifdef NETDEV_FCOE_WWNN
        .ndo_fcoe_get_wwn       = bnx2x_fcoe_get_wwn,
index 9f2637c295c8d3421e92a175578995296da2a5be..6b03acd5d9ad1b44e8750bb0b7fc0255756744ad 100644 (file)
@@ -30,8 +30,6 @@
 
 #define BNX2X_MAX_EMUL_MULTI           16
 
-#define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
-
 /**** Exe Queue interfaces ****/
 
 /**
@@ -444,30 +442,21 @@ static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
 }
 
 static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
-                               int n, u8 *buf)
+                               int n, u8 *base, u8 stride, u8 size)
 {
        struct bnx2x_vlan_mac_registry_elem *pos;
-       u8 *next = buf;
+       u8 *next = base;
        int counter = 0;
 
        /* traverse list */
        list_for_each_entry(pos, &o->head, link) {
                if (counter < n) {
-                       /* place leading zeroes in buffer */
-                       memset(next, 0, MAC_LEADING_ZERO_CNT);
-
-                       /* place mac after leading zeroes*/
-                       memcpy(next + MAC_LEADING_ZERO_CNT, pos->u.mac.mac,
-                              ETH_ALEN);
-
-                       /* calculate address of next element and
-                        * advance counter
-                        */
+                       memcpy(next, &pos->u, size);
                        counter++;
-                       next = buf + counter * ALIGN(ETH_ALEN, sizeof(u32));
+                       DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n",
+                          counter, next);
+                       next += stride + size;
 
-                       DP(BNX2X_MSG_SP, "copied element number %d to address %p element was %pM\n",
-                          counter, next, pos->u.mac.mac);
                }
        }
        return counter * ETH_ALEN;
@@ -2013,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
                vlan_obj->check_move        = bnx2x_check_move;
                vlan_obj->ramrod_cmd        =
                        RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+               vlan_obj->get_n_elements    = bnx2x_get_n_elements;
 
                /* Exe Queue */
                bnx2x_exe_queue_init(bp,
index ff907609b9fc5cef7c975b2a28453d562e09fc02..ac57e63a08edb8ff8316af487d036758ede5a17d 100644 (file)
@@ -313,8 +313,9 @@ struct bnx2x_vlan_mac_obj {
         *
         * @return number of copied bytes
         */
-       int (*get_n_elements)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
-                             int n, u8 *buf);
+       int (*get_n_elements)(struct bnx2x *bp,
+                             struct bnx2x_vlan_mac_obj *o, int n, u8 *base,
+                             u8 stride, u8 size);
 
        /**
         * Checks if ADD-ramrod with the given params may be performed.
@@ -842,6 +843,7 @@ enum bnx2x_q_type {
 #define BNX2X_MULTI_TX_COS_E3B0                        3
 #define BNX2X_MULTI_TX_COS                     3 /* Maximum possible */
 
+#define MAC_PAD (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
 
 struct bnx2x_queue_init_params {
        struct {
index 6adfa2093581ef611960e0c9fe364b69726d6de5..7b234e41fea8575b69d723ccec2b95fd14db4db2 100644 (file)
@@ -20,7 +20,9 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 #include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
 #include <linux/crc32.h>
+#include <linux/if_vlan.h>
 
 /* General service functions */
 static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
@@ -958,6 +960,12 @@ op_err:
        BNX2X_ERR("QSETUP[%d:%d] error: rc %d\n", vf->abs_vfid, qid, vfop->rc);
 op_done:
        case BNX2X_VFOP_QSETUP_DONE:
+               vf->cfg_flags |= VF_CFG_VLAN;
+               smp_mb__before_clear_bit();
+               set_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+                       &bp->sp_rtnl_state);
+               smp_mb__after_clear_bit();
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
                bnx2x_vfop_end(bp, vf, vfop);
                return;
        default:
@@ -3029,6 +3037,88 @@ void bnx2x_enable_sriov(struct bnx2x *bp)
                DP(BNX2X_MSG_IOV, "sriov enabled\n");
 }
 
+void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp)
+{
+       int vfidx;
+       struct pf_vf_bulletin_content *bulletin;
+
+       DP(BNX2X_MSG_IOV, "configuring vlan for VFs from sp-task\n");
+       for_each_vf(bp, vfidx) {
+       bulletin = BP_VF_BULLETIN(bp, vfidx);
+               if (BP_VF(bp, vfidx)->cfg_flags & VF_CFG_VLAN)
+                       bnx2x_set_vf_vlan(bp->dev, vfidx, bulletin->vlan, 0);
+       }
+}
+
+static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
+                              struct bnx2x_virtf *vf)
+{
+       if (!IS_SRIOV(bp)) {
+               BNX2X_ERR("vf ndo called though sriov is disabled\n");
+               return -EINVAL;
+       }
+
+       if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
+               BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+                         vfidx, BNX2X_NR_VIRTFN(bp));
+               return -EINVAL;
+       }
+
+       if (!vf) {
+               BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
+                         vfidx);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
+                       struct ifla_vf_info *ivi)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+       struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+       struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       int rc;
+
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       if (rc)
+               return rc;
+
+       ivi->vf = vfidx;
+       ivi->qos = 0;
+       ivi->tx_rate = 10000; /* always 10G. TBA take from link struct */
+       ivi->spoofchk = 1; /*always enabled */
+       if (vf->state == VF_ENABLED) {
+               /* mac and vlan are in vlan_mac objects */
+               mac_obj->get_n_elements(bp, mac_obj, 1, (u8 *)&ivi->mac,
+                                       0, ETH_ALEN);
+               vlan_obj->get_n_elements(bp, vlan_obj, 1, (u8 *)&ivi->vlan,
+                                        0, VLAN_HLEN);
+       } else {
+               /* mac */
+               if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
+                       /* mac configured by ndo so its in bulletin board */
+                       memcpy(&ivi->mac, bulletin->mac, ETH_ALEN);
+               else
+                       /* funtion has not been loaded yet. Show mac as 0s */
+                       memset(&ivi->mac, 0, ETH_ALEN);
+
+               /* vlan */
+               if (bulletin->valid_bitmap & (1 << VLAN_VALID))
+                       /* vlan configured by ndo so its in bulletin board */
+                       memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN);
+               else
+                       /* funtion has not been loaded yet. Show vlans as 0s */
+                       memset(&ivi->vlan, 0, VLAN_HLEN);
+       }
+
+       return 0;
+}
+
 /* New mac for VF. Consider these cases:
  * 1. VF hasn't been acquired yet - save the mac in local bulletin board and
  *    supply at acquire.
@@ -3044,23 +3134,19 @@ void bnx2x_enable_sriov(struct bnx2x *bp)
  * VF to configure any mac for itself except for this mac. In case of a race
  * where the VF fails to see the new post on its bulletin board before sending a
  * mac configuration request, the PF will simply fail the request and VF can try
- * again after consulting its bulletin board
+ * again after consulting its bulletin board.
  */
-int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
+int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state, vfidx = queue;
+       int rc, q_logical_state;
        struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
        struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
 
-       /* if SRIOV is disabled there is nothing to do (and somewhere, someone
-        * has erred).
-        */
-       if (!IS_SRIOV(bp)) {
-               BNX2X_ERR("bnx2x_set_vf_mac called though sriov is disabled\n");
-               return -EINVAL;
-       }
-
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       if (rc)
+               return rc;
        if (!is_valid_ether_addr(mac)) {
                BNX2X_ERR("mac address invalid\n");
                return -EINVAL;
@@ -3085,7 +3171,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
        if (vf->state == VF_ENABLED &&
            q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
                /* configure the mac in device on this vf's queue */
-               unsigned long flags = 0;
+               unsigned long ramrod_flags = 0;
                struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
 
                /* must lock vfpf channel to protect against vf flows */
@@ -3106,14 +3192,133 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
                }
 
                /* configure the new mac to device */
-               __set_bit(RAMROD_COMP_WAIT, &flags);
+               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
                bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
-                                 BNX2X_ETH_MAC, &flags);
+                                 BNX2X_ETH_MAC, &ramrod_flags);
 
                bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
        }
 
-       return rc;
+       return 0;
+}
+
+int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       int rc, q_logical_state;
+       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       if (rc)
+               return rc;
+
+       if (vlan > 4095) {
+               BNX2X_ERR("illegal vlan value %d\n", vlan);
+               return -EINVAL;
+       }
+
+       DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
+          vfidx, vlan, 0);
+
+       /* update PF's copy of the VF's bulletin. No point in posting the vlan
+        * to the VF since it doesn't have anything to do with it. But it useful
+        * to store it here in case the VF is not up yet and we can only
+        * configure the vlan later when it does.
+        */
+       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       bulletin->vlan = vlan;
+
+       /* is vf initialized and queue set up? */
+       q_logical_state =
+               bnx2x_get_q_logical_state(bp, &bnx2x_vfq(vf, 0, sp_obj));
+       if (vf->state == VF_ENABLED &&
+           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
+               /* configure the vlan in device on this vf's queue */
+               unsigned long ramrod_flags = 0;
+               unsigned long vlan_mac_flags = 0;
+               struct bnx2x_vlan_mac_obj *vlan_obj =
+                       &bnx2x_vfq(vf, 0, vlan_obj);
+               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+               struct bnx2x_queue_state_params q_params = {NULL};
+               struct bnx2x_queue_update_params *update_params;
+
+               memset(&ramrod_param, 0, sizeof(ramrod_param));
+
+               /* must lock vfpf channel to protect against vf flows */
+               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
+               /* remove existing vlans */
+               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                         &ramrod_flags);
+               if (rc) {
+                       BNX2X_ERR("failed to delete vlans\n");
+                       return -EINVAL;
+               }
+
+               /* send queue update ramrod to configure default vlan and silent
+                * vlan removal
+                */
+               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+               q_params.cmd = BNX2X_Q_CMD_UPDATE;
+               q_params.q_obj = &bnx2x_vfq(vf, 0, sp_obj);
+               update_params = &q_params.params.update;
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                         &update_params->update_flags);
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                         &update_params->update_flags);
+
+               if (vlan == 0) {
+                       /* if vlan is 0 then we want to leave the VF traffic
+                        * untagged, and leave the incoming traffic untouched
+                        * (i.e. do not remove any vlan tags).
+                        */
+                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                                   &update_params->update_flags);
+                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                                   &update_params->update_flags);
+               } else {
+                       /* configure the new vlan to device */
+                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+                       ramrod_param.vlan_mac_obj = vlan_obj;
+                       ramrod_param.ramrod_flags = ramrod_flags;
+                       ramrod_param.user_req.u.vlan.vlan = vlan;
+                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+                       if (rc) {
+                               BNX2X_ERR("failed to configure vlan\n");
+                               return -EINVAL;
+                       }
+
+                       /* configure default vlan to vf queue and set silent
+                        * vlan removal (the vf remains unaware of this vlan).
+                        */
+                       update_params = &q_params.params.update;
+                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                                 &update_params->update_flags);
+                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                                 &update_params->update_flags);
+                       update_params->def_vlan = vlan;
+               }
+
+               /* Update the Queue state */
+               rc = bnx2x_queue_state_change(bp, &q_params);
+               if (rc) {
+                       BNX2X_ERR("Failed to configure default VLAN\n");
+                       return rc;
+               }
+
+               /* clear the flag indicating that this VF needs its vlan
+                * (will only be set if the HV configured th Vlan before vf was
+                * and we were called because the VF came up later
+                */
+               vf->cfg_flags &= ~VF_CFG_VLAN;
+
+               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       }
+       return 0;
 }
 
 /* crc is the first field in the bulletin board. compute the crc over the
@@ -3165,6 +3370,10 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
                memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
        }
 
+       /* the vlan in bulletin board is valid and is new */
+       if (bulletin.valid_bitmap & 1 << VLAN_VALID)
+               memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
+
        /* copy new bulletin board to bp */
        bp->old_bulletin = bulletin;
 
index b4050173add939a1ebbf164253b14b6b7e019947..33d49516fcea826dfd273a7812f7c41ddd7b138f 100644 (file)
@@ -193,6 +193,7 @@ struct bnx2x_virtf {
 #define VF_CFG_TPA             0x0004
 #define VF_CFG_INT_SIMD                0x0008
 #define VF_CACHE_LINE          0x0010
+#define VF_CFG_VLAN            0x0020
 
        u8 state;
 #define VF_FREE                0       /* VF ready to be acquired holds no resc */
@@ -757,6 +758,7 @@ static inline int bnx2x_vf_headroom(struct bnx2x *bp)
 {
        return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF;
 }
+void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp);
 
 #else /* CONFIG_BNX2X_SRIOV */
 
@@ -804,6 +806,7 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp
 
 static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; }
 static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; }
+static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {}
 
 #endif /* CONFIG_BNX2X_SRIOV */
 #endif /* bnx2x_sriov.h */
index bfc80baec00d7564628f4088be05c47ae3f9a899..41708faab5752ac00f4f59edcceebf8545f59da3 100644 (file)
@@ -328,9 +328,15 @@ struct pf_vf_bulletin_content {
 #define MAC_ADDR_VALID         0       /* alert the vf that a new mac address
                                         * is available for it
                                         */
+#define VLAN_VALID             1       /* when set, the vf should not access
+                                        * the vfpf channel
+                                        */
 
        u8 mac[ETH_ALEN];
-       u8 padding[2];
+       u8 mac_padding[2];
+
+       u16 vlan;
+       u8 vlan_padding[6];
 };
 
 union pf_vf_bulletin {
@@ -353,6 +359,7 @@ enum channel_tlvs {
        CHANNEL_TLV_LIST_END,
        CHANNEL_TLV_FLR,
        CHANNEL_TLV_PF_SET_MAC,
+       CHANNEL_TLV_PF_SET_VLAN,
        CHANNEL_TLV_MAX
 };