diff options
author | Ariel Elior <ariele@broadcom.com> | 2013-03-11 01:17:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-12 07:54:23 -0400 |
commit | 3ec9f9ca79757c54b12f87e51a6664ba1e597b17 (patch) | |
tree | 5ab793d7fa40f08845adc48c1d7e846a10093813 | |
parent | 3786b9426d943ef167575be2ba20dab3d858243e (diff) |
bnx2x: Add iproute2 support for vfs
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>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 24 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 239 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 9 |
8 files changed, 277 insertions, 46 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 8ddc78bada49..d62d037b2928 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -1214,6 +1214,7 @@ enum { | |||
1214 | BNX2X_SP_RTNL_ENABLE_SRIOV, | 1214 | BNX2X_SP_RTNL_ENABLE_SRIOV, |
1215 | BNX2X_SP_RTNL_VFPF_MCAST, | 1215 | BNX2X_SP_RTNL_VFPF_MCAST, |
1216 | BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, | 1216 | BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, |
1217 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, | ||
1217 | }; | 1218 | }; |
1218 | 1219 | ||
1219 | 1220 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 8d158d8240a2..4620fa5666e5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | |||
@@ -496,7 +496,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev); | |||
496 | /* setup_tc callback */ | 496 | /* setup_tc callback */ |
497 | int bnx2x_setup_tc(struct net_device *dev, u8 num_tc); | 497 | int bnx2x_setup_tc(struct net_device *dev, u8 num_tc); |
498 | 498 | ||
499 | int bnx2x_get_vf_config(struct net_device *dev, int vf, | ||
500 | struct ifla_vf_info *ivi); | ||
499 | int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac); | 501 | int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac); |
502 | int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos); | ||
500 | 503 | ||
501 | /* select_queue callback */ | 504 | /* select_queue callback */ |
502 | u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb); | 505 | u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb); |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 423b5a074c80..9be9b0373ca9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -75,8 +75,6 @@ | |||
75 | #define FW_FILE_NAME_E1H "bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw" | 75 | #define FW_FILE_NAME_E1H "bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw" |
76 | #define FW_FILE_NAME_E2 "bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw" | 76 | #define FW_FILE_NAME_E2 "bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw" |
77 | 77 | ||
78 | #define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN) | ||
79 | |||
80 | /* Time in jiffies before concluding the transmitter is hung */ | 78 | /* Time in jiffies before concluding the transmitter is hung */ |
81 | #define TX_TIMEOUT (5*HZ) | 79 | #define TX_TIMEOUT (5*HZ) |
82 | 80 | ||
@@ -3227,16 +3225,29 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp) | |||
3227 | { | 3225 | { |
3228 | struct eth_stats_info *ether_stat = | 3226 | struct eth_stats_info *ether_stat = |
3229 | &bp->slowpath->drv_info_to_mcp.ether_stat; | 3227 | &bp->slowpath->drv_info_to_mcp.ether_stat; |
3228 | struct bnx2x_vlan_mac_obj *mac_obj = | ||
3229 | &bp->sp_objs->mac_obj; | ||
3230 | int i; | ||
3230 | 3231 | ||
3231 | strlcpy(ether_stat->version, DRV_MODULE_VERSION, | 3232 | strlcpy(ether_stat->version, DRV_MODULE_VERSION, |
3232 | ETH_STAT_INFO_VERSION_LEN); | 3233 | ETH_STAT_INFO_VERSION_LEN); |
3233 | 3234 | ||
3234 | bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj, | 3235 | /* get DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED macs, placing them in the |
3235 | DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED, | 3236 | * mac_local field in ether_stat struct. The base address is offset by 2 |
3236 | ether_stat->mac_local); | 3237 | * bytes to account for the field being 8 bytes but a mac address is |
3237 | 3238 | * only 6 bytes. Likewise, the stride for the get_n_elements function is | |
3239 | * 2 bytes to compensate from the 6 bytes of a mac to the 8 bytes | ||
3240 | * allocated by the ether_stat struct, so the macs will land in their | ||
3241 | * proper positions. | ||
3242 | */ | ||
3243 | for (i = 0; i < DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED; i++) | ||
3244 | memset(ether_stat->mac_local + i, 0, | ||
3245 | sizeof(ether_stat->mac_local[0])); | ||
3246 | mac_obj->get_n_elements(bp, &bp->sp_objs[0].mac_obj, | ||
3247 | DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED, | ||
3248 | ether_stat->mac_local + MAC_PAD, MAC_PAD, | ||
3249 | ETH_ALEN); | ||
3238 | ether_stat->mtu_size = bp->dev->mtu; | 3250 | ether_stat->mtu_size = bp->dev->mtu; |
3239 | |||
3240 | if (bp->dev->features & NETIF_F_RXCSUM) | 3251 | if (bp->dev->features & NETIF_F_RXCSUM) |
3241 | ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK; | 3252 | ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK; |
3242 | if (bp->dev->features & NETIF_F_TSO) | 3253 | if (bp->dev->features & NETIF_F_TSO) |
@@ -3258,8 +3269,7 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp) | |||
3258 | if (!CNIC_LOADED(bp)) | 3269 | if (!CNIC_LOADED(bp)) |
3259 | return; | 3270 | return; |
3260 | 3271 | ||
3261 | memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT, | 3272 | memcpy(fcoe_stat->mac_local + MAC_PAD, bp->fip_mac, ETH_ALEN); |
3262 | bp->fip_mac, ETH_ALEN); | ||
3263 | 3273 | ||
3264 | fcoe_stat->qos_priority = | 3274 | fcoe_stat->qos_priority = |
3265 | app->traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE]; | 3275 | app->traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE]; |
@@ -3361,8 +3371,8 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp) | |||
3361 | if (!CNIC_LOADED(bp)) | 3371 | if (!CNIC_LOADED(bp)) |
3362 | return; | 3372 | return; |
3363 | 3373 | ||
3364 | memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT, | 3374 | memcpy(iscsi_stat->mac_local + MAC_PAD, bp->cnic_eth_dev.iscsi_mac, |
3365 | bp->cnic_eth_dev.iscsi_mac, ETH_ALEN); | 3375 | ETH_ALEN); |
3366 | 3376 | ||
3367 | iscsi_stat->qos_priority = | 3377 | iscsi_stat->qos_priority = |
3368 | app->traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI]; | 3378 | app->traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI]; |
@@ -9525,6 +9535,10 @@ sp_rtnl_not_reset: | |||
9525 | bnx2x_vfpf_storm_rx_mode(bp); | 9535 | bnx2x_vfpf_storm_rx_mode(bp); |
9526 | } | 9536 | } |
9527 | 9537 | ||
9538 | if (test_and_clear_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN, | ||
9539 | &bp->sp_rtnl_state)) | ||
9540 | bnx2x_pf_set_vfs_vlan(bp); | ||
9541 | |||
9528 | /* work which needs rtnl lock not-taken (as it takes the lock itself and | 9542 | /* work which needs rtnl lock not-taken (as it takes the lock itself and |
9529 | * can be called from other contexts as well) | 9543 | * can be called from other contexts as well) |
9530 | */ | 9544 | */ |
@@ -11798,6 +11812,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { | |||
11798 | .ndo_setup_tc = bnx2x_setup_tc, | 11812 | .ndo_setup_tc = bnx2x_setup_tc, |
11799 | #ifdef CONFIG_BNX2X_SRIOV | 11813 | #ifdef CONFIG_BNX2X_SRIOV |
11800 | .ndo_set_vf_mac = bnx2x_set_vf_mac, | 11814 | .ndo_set_vf_mac = bnx2x_set_vf_mac, |
11815 | .ndo_set_vf_vlan = bnx2x_set_vf_vlan, | ||
11816 | .ndo_get_vf_config = bnx2x_get_vf_config, | ||
11801 | #endif | 11817 | #endif |
11802 | #ifdef NETDEV_FCOE_WWNN | 11818 | #ifdef NETDEV_FCOE_WWNN |
11803 | .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn, | 11819 | .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn, |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 9f2637c295c8..6b03acd5d9ad 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | |||
@@ -30,8 +30,6 @@ | |||
30 | 30 | ||
31 | #define BNX2X_MAX_EMUL_MULTI 16 | 31 | #define BNX2X_MAX_EMUL_MULTI 16 |
32 | 32 | ||
33 | #define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN) | ||
34 | |||
35 | /**** Exe Queue interfaces ****/ | 33 | /**** Exe Queue interfaces ****/ |
36 | 34 | ||
37 | /** | 35 | /** |
@@ -444,30 +442,21 @@ static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o) | |||
444 | } | 442 | } |
445 | 443 | ||
446 | static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, | 444 | static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, |
447 | int n, u8 *buf) | 445 | int n, u8 *base, u8 stride, u8 size) |
448 | { | 446 | { |
449 | struct bnx2x_vlan_mac_registry_elem *pos; | 447 | struct bnx2x_vlan_mac_registry_elem *pos; |
450 | u8 *next = buf; | 448 | u8 *next = base; |
451 | int counter = 0; | 449 | int counter = 0; |
452 | 450 | ||
453 | /* traverse list */ | 451 | /* traverse list */ |
454 | list_for_each_entry(pos, &o->head, link) { | 452 | list_for_each_entry(pos, &o->head, link) { |
455 | if (counter < n) { | 453 | if (counter < n) { |
456 | /* place leading zeroes in buffer */ | 454 | memcpy(next, &pos->u, size); |
457 | memset(next, 0, MAC_LEADING_ZERO_CNT); | ||
458 | |||
459 | /* place mac after leading zeroes*/ | ||
460 | memcpy(next + MAC_LEADING_ZERO_CNT, pos->u.mac.mac, | ||
461 | ETH_ALEN); | ||
462 | |||
463 | /* calculate address of next element and | ||
464 | * advance counter | ||
465 | */ | ||
466 | counter++; | 455 | counter++; |
467 | next = buf + counter * ALIGN(ETH_ALEN, sizeof(u32)); | 456 | DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n", |
457 | counter, next); | ||
458 | next += stride + size; | ||
468 | 459 | ||
469 | DP(BNX2X_MSG_SP, "copied element number %d to address %p element was %pM\n", | ||
470 | counter, next, pos->u.mac.mac); | ||
471 | } | 460 | } |
472 | } | 461 | } |
473 | return counter * ETH_ALEN; | 462 | return counter * ETH_ALEN; |
@@ -2013,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp, | |||
2013 | vlan_obj->check_move = bnx2x_check_move; | 2002 | vlan_obj->check_move = bnx2x_check_move; |
2014 | vlan_obj->ramrod_cmd = | 2003 | vlan_obj->ramrod_cmd = |
2015 | RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; | 2004 | RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; |
2005 | vlan_obj->get_n_elements = bnx2x_get_n_elements; | ||
2016 | 2006 | ||
2017 | /* Exe Queue */ | 2007 | /* Exe Queue */ |
2018 | bnx2x_exe_queue_init(bp, | 2008 | bnx2x_exe_queue_init(bp, |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index ff907609b9fc..ac57e63a08ed 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h | |||
@@ -313,8 +313,9 @@ struct bnx2x_vlan_mac_obj { | |||
313 | * | 313 | * |
314 | * @return number of copied bytes | 314 | * @return number of copied bytes |
315 | */ | 315 | */ |
316 | int (*get_n_elements)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, | 316 | int (*get_n_elements)(struct bnx2x *bp, |
317 | int n, u8 *buf); | 317 | struct bnx2x_vlan_mac_obj *o, int n, u8 *base, |
318 | u8 stride, u8 size); | ||
318 | 319 | ||
319 | /** | 320 | /** |
320 | * Checks if ADD-ramrod with the given params may be performed. | 321 | * Checks if ADD-ramrod with the given params may be performed. |
@@ -842,6 +843,7 @@ enum bnx2x_q_type { | |||
842 | #define BNX2X_MULTI_TX_COS_E3B0 3 | 843 | #define BNX2X_MULTI_TX_COS_E3B0 3 |
843 | #define BNX2X_MULTI_TX_COS 3 /* Maximum possible */ | 844 | #define BNX2X_MULTI_TX_COS 3 /* Maximum possible */ |
844 | 845 | ||
846 | #define MAC_PAD (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN) | ||
845 | 847 | ||
846 | struct bnx2x_queue_init_params { | 848 | struct bnx2x_queue_init_params { |
847 | struct { | 849 | struct { |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 6adfa2093581..7b234e41fea8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
@@ -20,7 +20,9 @@ | |||
20 | #include "bnx2x.h" | 20 | #include "bnx2x.h" |
21 | #include "bnx2x_init.h" | 21 | #include "bnx2x_init.h" |
22 | #include "bnx2x_cmn.h" | 22 | #include "bnx2x_cmn.h" |
23 | #include "bnx2x_sp.h" | ||
23 | #include <linux/crc32.h> | 24 | #include <linux/crc32.h> |
25 | #include <linux/if_vlan.h> | ||
24 | 26 | ||
25 | /* General service functions */ | 27 | /* General service functions */ |
26 | static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid, | 28 | static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid, |
@@ -958,6 +960,12 @@ op_err: | |||
958 | BNX2X_ERR("QSETUP[%d:%d] error: rc %d\n", vf->abs_vfid, qid, vfop->rc); | 960 | BNX2X_ERR("QSETUP[%d:%d] error: rc %d\n", vf->abs_vfid, qid, vfop->rc); |
959 | op_done: | 961 | op_done: |
960 | case BNX2X_VFOP_QSETUP_DONE: | 962 | case BNX2X_VFOP_QSETUP_DONE: |
963 | vf->cfg_flags |= VF_CFG_VLAN; | ||
964 | smp_mb__before_clear_bit(); | ||
965 | set_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN, | ||
966 | &bp->sp_rtnl_state); | ||
967 | smp_mb__after_clear_bit(); | ||
968 | schedule_delayed_work(&bp->sp_rtnl_task, 0); | ||
961 | bnx2x_vfop_end(bp, vf, vfop); | 969 | bnx2x_vfop_end(bp, vf, vfop); |
962 | return; | 970 | return; |
963 | default: | 971 | default: |
@@ -3029,6 +3037,88 @@ void bnx2x_enable_sriov(struct bnx2x *bp) | |||
3029 | DP(BNX2X_MSG_IOV, "sriov enabled\n"); | 3037 | DP(BNX2X_MSG_IOV, "sriov enabled\n"); |
3030 | } | 3038 | } |
3031 | 3039 | ||
3040 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) | ||
3041 | { | ||
3042 | int vfidx; | ||
3043 | struct pf_vf_bulletin_content *bulletin; | ||
3044 | |||
3045 | DP(BNX2X_MSG_IOV, "configuring vlan for VFs from sp-task\n"); | ||
3046 | for_each_vf(bp, vfidx) { | ||
3047 | bulletin = BP_VF_BULLETIN(bp, vfidx); | ||
3048 | if (BP_VF(bp, vfidx)->cfg_flags & VF_CFG_VLAN) | ||
3049 | bnx2x_set_vf_vlan(bp->dev, vfidx, bulletin->vlan, 0); | ||
3050 | } | ||
3051 | } | ||
3052 | |||
3053 | static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, | ||
3054 | struct bnx2x_virtf *vf) | ||
3055 | { | ||
3056 | if (!IS_SRIOV(bp)) { | ||
3057 | BNX2X_ERR("vf ndo called though sriov is disabled\n"); | ||
3058 | return -EINVAL; | ||
3059 | } | ||
3060 | |||
3061 | if (vfidx >= BNX2X_NR_VIRTFN(bp)) { | ||
3062 | BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n", | ||
3063 | vfidx, BNX2X_NR_VIRTFN(bp)); | ||
3064 | return -EINVAL; | ||
3065 | } | ||
3066 | |||
3067 | if (!vf) { | ||
3068 | BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n", | ||
3069 | vfidx); | ||
3070 | return -EINVAL; | ||
3071 | } | ||
3072 | |||
3073 | return 0; | ||
3074 | } | ||
3075 | |||
3076 | int bnx2x_get_vf_config(struct net_device *dev, int vfidx, | ||
3077 | struct ifla_vf_info *ivi) | ||
3078 | { | ||
3079 | struct bnx2x *bp = netdev_priv(dev); | ||
3080 | struct bnx2x_virtf *vf = BP_VF(bp, vfidx); | ||
3081 | struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj); | ||
3082 | struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj); | ||
3083 | struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); | ||
3084 | int rc; | ||
3085 | |||
3086 | /* sanity */ | ||
3087 | rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); | ||
3088 | if (rc) | ||
3089 | return rc; | ||
3090 | |||
3091 | ivi->vf = vfidx; | ||
3092 | ivi->qos = 0; | ||
3093 | ivi->tx_rate = 10000; /* always 10G. TBA take from link struct */ | ||
3094 | ivi->spoofchk = 1; /*always enabled */ | ||
3095 | if (vf->state == VF_ENABLED) { | ||
3096 | /* mac and vlan are in vlan_mac objects */ | ||
3097 | mac_obj->get_n_elements(bp, mac_obj, 1, (u8 *)&ivi->mac, | ||
3098 | 0, ETH_ALEN); | ||
3099 | vlan_obj->get_n_elements(bp, vlan_obj, 1, (u8 *)&ivi->vlan, | ||
3100 | 0, VLAN_HLEN); | ||
3101 | } else { | ||
3102 | /* mac */ | ||
3103 | if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID)) | ||
3104 | /* mac configured by ndo so its in bulletin board */ | ||
3105 | memcpy(&ivi->mac, bulletin->mac, ETH_ALEN); | ||
3106 | else | ||
3107 | /* funtion has not been loaded yet. Show mac as 0s */ | ||
3108 | memset(&ivi->mac, 0, ETH_ALEN); | ||
3109 | |||
3110 | /* vlan */ | ||
3111 | if (bulletin->valid_bitmap & (1 << VLAN_VALID)) | ||
3112 | /* vlan configured by ndo so its in bulletin board */ | ||
3113 | memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN); | ||
3114 | else | ||
3115 | /* funtion has not been loaded yet. Show vlans as 0s */ | ||
3116 | memset(&ivi->vlan, 0, VLAN_HLEN); | ||
3117 | } | ||
3118 | |||
3119 | return 0; | ||
3120 | } | ||
3121 | |||
3032 | /* New mac for VF. Consider these cases: | 3122 | /* New mac for VF. Consider these cases: |
3033 | * 1. VF hasn't been acquired yet - save the mac in local bulletin board and | 3123 | * 1. VF hasn't been acquired yet - save the mac in local bulletin board and |
3034 | * supply at acquire. | 3124 | * supply at acquire. |
@@ -3044,23 +3134,19 @@ void bnx2x_enable_sriov(struct bnx2x *bp) | |||
3044 | * VF to configure any mac for itself except for this mac. In case of a race | 3134 | * VF to configure any mac for itself except for this mac. In case of a race |
3045 | * where the VF fails to see the new post on its bulletin board before sending a | 3135 | * where the VF fails to see the new post on its bulletin board before sending a |
3046 | * mac configuration request, the PF will simply fail the request and VF can try | 3136 | * mac configuration request, the PF will simply fail the request and VF can try |
3047 | * again after consulting its bulletin board | 3137 | * again after consulting its bulletin board. |
3048 | */ | 3138 | */ |
3049 | int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac) | 3139 | int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac) |
3050 | { | 3140 | { |
3051 | struct bnx2x *bp = netdev_priv(dev); | 3141 | struct bnx2x *bp = netdev_priv(dev); |
3052 | int rc, q_logical_state, vfidx = queue; | 3142 | int rc, q_logical_state; |
3053 | struct bnx2x_virtf *vf = BP_VF(bp, vfidx); | 3143 | struct bnx2x_virtf *vf = BP_VF(bp, vfidx); |
3054 | struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); | 3144 | struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); |
3055 | 3145 | ||
3056 | /* if SRIOV is disabled there is nothing to do (and somewhere, someone | 3146 | /* sanity */ |
3057 | * has erred). | 3147 | rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); |
3058 | */ | 3148 | if (rc) |
3059 | if (!IS_SRIOV(bp)) { | 3149 | return rc; |
3060 | BNX2X_ERR("bnx2x_set_vf_mac called though sriov is disabled\n"); | ||
3061 | return -EINVAL; | ||
3062 | } | ||
3063 | |||
3064 | if (!is_valid_ether_addr(mac)) { | 3150 | if (!is_valid_ether_addr(mac)) { |
3065 | BNX2X_ERR("mac address invalid\n"); | 3151 | BNX2X_ERR("mac address invalid\n"); |
3066 | return -EINVAL; | 3152 | return -EINVAL; |
@@ -3085,7 +3171,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac) | |||
3085 | if (vf->state == VF_ENABLED && | 3171 | if (vf->state == VF_ENABLED && |
3086 | q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) { | 3172 | q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) { |
3087 | /* configure the mac in device on this vf's queue */ | 3173 | /* configure the mac in device on this vf's queue */ |
3088 | unsigned long flags = 0; | 3174 | unsigned long ramrod_flags = 0; |
3089 | struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj); | 3175 | struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj); |
3090 | 3176 | ||
3091 | /* must lock vfpf channel to protect against vf flows */ | 3177 | /* 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) | |||
3106 | } | 3192 | } |
3107 | 3193 | ||
3108 | /* configure the new mac to device */ | 3194 | /* configure the new mac to device */ |
3109 | __set_bit(RAMROD_COMP_WAIT, &flags); | 3195 | __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); |
3110 | bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true, | 3196 | bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true, |
3111 | BNX2X_ETH_MAC, &flags); | 3197 | BNX2X_ETH_MAC, &ramrod_flags); |
3112 | 3198 | ||
3113 | bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC); | 3199 | bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC); |
3114 | } | 3200 | } |
3115 | 3201 | ||
3116 | return rc; | 3202 | return 0; |
3203 | } | ||
3204 | |||
3205 | int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos) | ||
3206 | { | ||
3207 | struct bnx2x *bp = netdev_priv(dev); | ||
3208 | int rc, q_logical_state; | ||
3209 | struct bnx2x_virtf *vf = BP_VF(bp, vfidx); | ||
3210 | struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); | ||
3211 | |||
3212 | /* sanity */ | ||
3213 | rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); | ||
3214 | if (rc) | ||
3215 | return rc; | ||
3216 | |||
3217 | if (vlan > 4095) { | ||
3218 | BNX2X_ERR("illegal vlan value %d\n", vlan); | ||
3219 | return -EINVAL; | ||
3220 | } | ||
3221 | |||
3222 | DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n", | ||
3223 | vfidx, vlan, 0); | ||
3224 | |||
3225 | /* update PF's copy of the VF's bulletin. No point in posting the vlan | ||
3226 | * to the VF since it doesn't have anything to do with it. But it useful | ||
3227 | * to store it here in case the VF is not up yet and we can only | ||
3228 | * configure the vlan later when it does. | ||
3229 | */ | ||
3230 | bulletin->valid_bitmap |= 1 << VLAN_VALID; | ||
3231 | bulletin->vlan = vlan; | ||
3232 | |||
3233 | /* is vf initialized and queue set up? */ | ||
3234 | q_logical_state = | ||
3235 | bnx2x_get_q_logical_state(bp, &bnx2x_vfq(vf, 0, sp_obj)); | ||
3236 | if (vf->state == VF_ENABLED && | ||
3237 | q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) { | ||
3238 | /* configure the vlan in device on this vf's queue */ | ||
3239 | unsigned long ramrod_flags = 0; | ||
3240 | unsigned long vlan_mac_flags = 0; | ||
3241 | struct bnx2x_vlan_mac_obj *vlan_obj = | ||
3242 | &bnx2x_vfq(vf, 0, vlan_obj); | ||
3243 | struct bnx2x_vlan_mac_ramrod_params ramrod_param; | ||
3244 | struct bnx2x_queue_state_params q_params = {NULL}; | ||
3245 | struct bnx2x_queue_update_params *update_params; | ||
3246 | |||
3247 | memset(&ramrod_param, 0, sizeof(ramrod_param)); | ||
3248 | |||
3249 | /* must lock vfpf channel to protect against vf flows */ | ||
3250 | bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN); | ||
3251 | |||
3252 | /* remove existing vlans */ | ||
3253 | __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); | ||
3254 | rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags, | ||
3255 | &ramrod_flags); | ||
3256 | if (rc) { | ||
3257 | BNX2X_ERR("failed to delete vlans\n"); | ||
3258 | return -EINVAL; | ||
3259 | } | ||
3260 | |||
3261 | /* send queue update ramrod to configure default vlan and silent | ||
3262 | * vlan removal | ||
3263 | */ | ||
3264 | __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); | ||
3265 | q_params.cmd = BNX2X_Q_CMD_UPDATE; | ||
3266 | q_params.q_obj = &bnx2x_vfq(vf, 0, sp_obj); | ||
3267 | update_params = &q_params.params.update; | ||
3268 | __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG, | ||
3269 | &update_params->update_flags); | ||
3270 | __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG, | ||
3271 | &update_params->update_flags); | ||
3272 | |||
3273 | if (vlan == 0) { | ||
3274 | /* if vlan is 0 then we want to leave the VF traffic | ||
3275 | * untagged, and leave the incoming traffic untouched | ||
3276 | * (i.e. do not remove any vlan tags). | ||
3277 | */ | ||
3278 | __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, | ||
3279 | &update_params->update_flags); | ||
3280 | __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, | ||
3281 | &update_params->update_flags); | ||
3282 | } else { | ||
3283 | /* configure the new vlan to device */ | ||
3284 | __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); | ||
3285 | ramrod_param.vlan_mac_obj = vlan_obj; | ||
3286 | ramrod_param.ramrod_flags = ramrod_flags; | ||
3287 | ramrod_param.user_req.u.vlan.vlan = vlan; | ||
3288 | ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD; | ||
3289 | rc = bnx2x_config_vlan_mac(bp, &ramrod_param); | ||
3290 | if (rc) { | ||
3291 | BNX2X_ERR("failed to configure vlan\n"); | ||
3292 | return -EINVAL; | ||
3293 | } | ||
3294 | |||
3295 | /* configure default vlan to vf queue and set silent | ||
3296 | * vlan removal (the vf remains unaware of this vlan). | ||
3297 | */ | ||
3298 | update_params = &q_params.params.update; | ||
3299 | __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, | ||
3300 | &update_params->update_flags); | ||
3301 | __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, | ||
3302 | &update_params->update_flags); | ||
3303 | update_params->def_vlan = vlan; | ||
3304 | } | ||
3305 | |||
3306 | /* Update the Queue state */ | ||
3307 | rc = bnx2x_queue_state_change(bp, &q_params); | ||
3308 | if (rc) { | ||
3309 | BNX2X_ERR("Failed to configure default VLAN\n"); | ||
3310 | return rc; | ||
3311 | } | ||
3312 | |||
3313 | /* clear the flag indicating that this VF needs its vlan | ||
3314 | * (will only be set if the HV configured th Vlan before vf was | ||
3315 | * and we were called because the VF came up later | ||
3316 | */ | ||
3317 | vf->cfg_flags &= ~VF_CFG_VLAN; | ||
3318 | |||
3319 | bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN); | ||
3320 | } | ||
3321 | return 0; | ||
3117 | } | 3322 | } |
3118 | 3323 | ||
3119 | /* crc is the first field in the bulletin board. compute the crc over the | 3324 | /* 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) | |||
3165 | memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN); | 3370 | memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN); |
3166 | } | 3371 | } |
3167 | 3372 | ||
3373 | /* the vlan in bulletin board is valid and is new */ | ||
3374 | if (bulletin.valid_bitmap & 1 << VLAN_VALID) | ||
3375 | memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN); | ||
3376 | |||
3168 | /* copy new bulletin board to bp */ | 3377 | /* copy new bulletin board to bp */ |
3169 | bp->old_bulletin = bulletin; | 3378 | bp->old_bulletin = bulletin; |
3170 | 3379 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index b4050173add9..33d49516fcea 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | |||
@@ -193,6 +193,7 @@ struct bnx2x_virtf { | |||
193 | #define VF_CFG_TPA 0x0004 | 193 | #define VF_CFG_TPA 0x0004 |
194 | #define VF_CFG_INT_SIMD 0x0008 | 194 | #define VF_CFG_INT_SIMD 0x0008 |
195 | #define VF_CACHE_LINE 0x0010 | 195 | #define VF_CACHE_LINE 0x0010 |
196 | #define VF_CFG_VLAN 0x0020 | ||
196 | 197 | ||
197 | u8 state; | 198 | u8 state; |
198 | #define VF_FREE 0 /* VF ready to be acquired holds no resc */ | 199 | #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) | |||
757 | { | 758 | { |
758 | return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF; | 759 | return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF; |
759 | } | 760 | } |
761 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp); | ||
760 | 762 | ||
761 | #else /* CONFIG_BNX2X_SRIOV */ | 763 | #else /* CONFIG_BNX2X_SRIOV */ |
762 | 764 | ||
@@ -804,6 +806,7 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp | |||
804 | 806 | ||
805 | static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; } | 807 | static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; } |
806 | static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } | 808 | static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } |
809 | static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} | ||
807 | 810 | ||
808 | #endif /* CONFIG_BNX2X_SRIOV */ | 811 | #endif /* CONFIG_BNX2X_SRIOV */ |
809 | #endif /* bnx2x_sriov.h */ | 812 | #endif /* bnx2x_sriov.h */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index bfc80baec00d..41708faab575 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | |||
@@ -328,9 +328,15 @@ struct pf_vf_bulletin_content { | |||
328 | #define MAC_ADDR_VALID 0 /* alert the vf that a new mac address | 328 | #define MAC_ADDR_VALID 0 /* alert the vf that a new mac address |
329 | * is available for it | 329 | * is available for it |
330 | */ | 330 | */ |
331 | #define VLAN_VALID 1 /* when set, the vf should not access | ||
332 | * the vfpf channel | ||
333 | */ | ||
331 | 334 | ||
332 | u8 mac[ETH_ALEN]; | 335 | u8 mac[ETH_ALEN]; |
333 | u8 padding[2]; | 336 | u8 mac_padding[2]; |
337 | |||
338 | u16 vlan; | ||
339 | u8 vlan_padding[6]; | ||
334 | }; | 340 | }; |
335 | 341 | ||
336 | union pf_vf_bulletin { | 342 | union pf_vf_bulletin { |
@@ -353,6 +359,7 @@ enum channel_tlvs { | |||
353 | CHANNEL_TLV_LIST_END, | 359 | CHANNEL_TLV_LIST_END, |
354 | CHANNEL_TLV_FLR, | 360 | CHANNEL_TLV_FLR, |
355 | CHANNEL_TLV_PF_SET_MAC, | 361 | CHANNEL_TLV_PF_SET_MAC, |
362 | CHANNEL_TLV_PF_SET_VLAN, | ||
356 | CHANNEL_TLV_MAX | 363 | CHANNEL_TLV_MAX |
357 | }; | 364 | }; |
358 | 365 | ||