Commit 05cc5a39 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

bnx2x: add vlan filtering offload

Current driver always uses vlan-promisc mode, i.e., it receives both
tagged and untagged traffic and lets the network stack drop packets
tagged with unrequested vlan tags.

This patch implements vlan-filtering offload in the driver -
Unless explicitly configured to promisc mode, only untagged packets or
packets tagged with requested vlans would reach the Rx flow.
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarAriel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e82a08b0
...@@ -1228,6 +1228,10 @@ struct bnx2x_slowpath { ...@@ -1228,6 +1228,10 @@ struct bnx2x_slowpath {
struct eth_classify_rules_ramrod_data e2; struct eth_classify_rules_ramrod_data e2;
} mac_rdata; } mac_rdata;
union {
struct eth_classify_rules_ramrod_data e2;
} vlan_rdata;
union { union {
struct tstorm_eth_mac_filter_config e1x; struct tstorm_eth_mac_filter_config e1x;
struct eth_filter_rules_ramrod_data e2; struct eth_filter_rules_ramrod_data e2;
...@@ -1410,6 +1414,9 @@ struct bnx2x_sp_objs { ...@@ -1410,6 +1414,9 @@ struct bnx2x_sp_objs {
/* Queue State object */ /* Queue State object */
struct bnx2x_queue_sp_obj q_obj; struct bnx2x_queue_sp_obj q_obj;
/* VLANs object */
struct bnx2x_vlan_mac_obj vlan_obj;
}; };
struct bnx2x_fp_stats { struct bnx2x_fp_stats {
...@@ -1427,6 +1434,12 @@ enum { ...@@ -1427,6 +1434,12 @@ enum {
SUB_MF_MODE_BD, SUB_MF_MODE_BD,
}; };
struct bnx2x_vlan_entry {
struct list_head link;
u16 vid;
bool hw;
};
struct bnx2x { struct bnx2x {
/* Fields used in the tx and intr/napi performance paths /* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure * are grouped together in the beginning of the structure
...@@ -1865,8 +1878,6 @@ struct bnx2x { ...@@ -1865,8 +1878,6 @@ struct bnx2x {
int dcb_version; int dcb_version;
/* CAM credit pools */ /* CAM credit pools */
/* used only in sriov */
struct bnx2x_credit_pool_obj vlans_pool; struct bnx2x_credit_pool_obj vlans_pool;
struct bnx2x_credit_pool_obj macs_pool; struct bnx2x_credit_pool_obj macs_pool;
...@@ -1929,6 +1940,11 @@ struct bnx2x { ...@@ -1929,6 +1940,11 @@ struct bnx2x {
u16 rx_filter; u16 rx_filter;
struct bnx2x_link_report_data vf_link_vars; struct bnx2x_link_report_data vf_link_vars;
struct list_head vlan_reg;
u16 vlan_cnt;
u16 vlan_credit;
u16 vxlan_dst_port;
bool accept_any_vlan;
}; };
/* Tx queues may be less or equal to Rx queues */ /* Tx queues may be less or equal to Rx queues */
...@@ -1956,23 +1972,14 @@ extern int num_queues; ...@@ -1956,23 +1972,14 @@ extern int num_queues;
#define RSS_IPV6_TCP_CAP_MASK \ #define RSS_IPV6_TCP_CAP_MASK \
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
/* func init flags */
#define FUNC_FLG_RSS 0x0001
#define FUNC_FLG_STATS 0x0002
/* removed FUNC_FLG_UNMATCHED 0x0004 */
#define FUNC_FLG_TPA 0x0008
#define FUNC_FLG_SPQ 0x0010
#define FUNC_FLG_LEADING 0x0020 /* PF only */
#define FUNC_FLG_LEADING_STATS 0x0040
struct bnx2x_func_init_params { struct bnx2x_func_init_params {
/* dma */ /* dma */
dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */ bool spq_active;
dma_addr_t spq_map; /* valid iff FUNC_FLG_SPQ */ dma_addr_t spq_map;
u16 spq_prod;
u16 func_flgs;
u16 func_id; /* abs fid */ u16 func_id; /* abs fid */
u16 pf_id; u16 pf_id;
u16 spq_prod; /* valid iff FUNC_FLG_SPQ */
}; };
#define for_each_cnic_queue(bp, var) \ #define for_each_cnic_queue(bp, var) \
...@@ -2082,6 +2089,11 @@ struct bnx2x_func_init_params { ...@@ -2082,6 +2089,11 @@ struct bnx2x_func_init_params {
int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
struct bnx2x_vlan_mac_obj *obj, bool set, struct bnx2x_vlan_mac_obj *obj, bool set,
int mac_type, unsigned long *ramrod_flags); int mac_type, unsigned long *ramrod_flags);
int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
struct bnx2x_vlan_mac_obj *obj, bool set,
unsigned long *ramrod_flags);
/** /**
* bnx2x_del_all_macs - delete all MACs configured for the specific MAC object * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
* *
...@@ -2486,6 +2498,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, ...@@ -2486,6 +2498,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
#define VF_ACQUIRE_THRESH 3 #define VF_ACQUIRE_THRESH 3
#define VF_ACQUIRE_MAC_FILTERS 1 #define VF_ACQUIRE_MAC_FILTERS 1
#define VF_ACQUIRE_MC_FILTERS 10 #define VF_ACQUIRE_MC_FILTERS 10
#define VF_ACQUIRE_VLAN_FILTERS 2 /* VLAN0 + 'real' VLAN */
#define GOOD_ME_REG(me_reg) (((me_reg) & ME_REG_VF_VALID) && \ #define GOOD_ME_REG(me_reg) (((me_reg) & ME_REG_VF_VALID) && \
(!((me_reg) & ME_REG_VF_ERR))) (!((me_reg) & ME_REG_VF_ERR)))
...@@ -2596,4 +2609,9 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, struct sk_buff *skb); ...@@ -2596,4 +2609,9 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, struct sk_buff *skb);
#define BNX2X_MAX_PHC_DRIFT 31000000 #define BNX2X_MAX_PHC_DRIFT 31000000
#define BNX2X_PTP_TX_TIMEOUT #define BNX2X_PTP_TX_TIMEOUT
/* Re-configure all previously configured vlan filters.
* Meant for implicit re-load flows.
*/
int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp);
#endif /* bnx2x.h */ #endif /* bnx2x.h */
...@@ -2848,6 +2848,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -2848,6 +2848,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Start fast path */ /* Start fast path */
/* Re-configure vlan filters */
rc = bnx2x_vlan_reconfigure_vid(bp);
if (rc)
LOAD_ERROR_EXIT(bp, load_error3);
/* Initialize Rx filter. */ /* Initialize Rx filter. */
bnx2x_set_rx_mode_inner(bp); bnx2x_set_rx_mode_inner(bp);
......
...@@ -1066,6 +1066,15 @@ static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp, ...@@ -1066,6 +1066,15 @@ static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
BNX2X_FILTER_MAC_PENDING, BNX2X_FILTER_MAC_PENDING,
&bp->sp_state, obj_type, &bp->sp_state, obj_type,
&bp->macs_pool); &bp->macs_pool);
if (!CHIP_IS_E1x(bp))
bnx2x_init_vlan_obj(bp, &bnx2x_sp_obj(bp, fp).vlan_obj,
fp->cl_id, fp->cid, BP_FUNC(bp),
bnx2x_sp(bp, vlan_rdata),
bnx2x_sp_mapping(bp, vlan_rdata),
BNX2X_FILTER_VLAN_PENDING,
&bp->sp_state, obj_type,
&bp->vlans_pool);
} }
/** /**
...@@ -1125,7 +1134,7 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp) ...@@ -1125,7 +1134,7 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp), bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
bnx2x_get_path_func_num(bp)); bnx2x_get_path_func_num(bp));
bnx2x_init_vlan_credit_pool(bp, &bp->vlans_pool, BP_ABS_FUNC(bp)>>1, bnx2x_init_vlan_credit_pool(bp, &bp->vlans_pool, BP_FUNC(bp),
bnx2x_get_path_func_num(bp)); bnx2x_get_path_func_num(bp));
/* RSS configuration object */ /* RSS configuration object */
...@@ -1135,6 +1144,8 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp) ...@@ -1135,6 +1144,8 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
bnx2x_sp_mapping(bp, rss_rdata), bnx2x_sp_mapping(bp, rss_rdata),
BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state, BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
BNX2X_OBJ_TYPE_RX); BNX2X_OBJ_TYPE_RX);
bp->vlan_credit = PF_VLAN_CREDIT_E2(bp, bnx2x_get_path_func_num(bp));
} }
static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp) static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
......
...@@ -3067,7 +3067,7 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) ...@@ -3067,7 +3067,7 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
storm_memset_func_en(bp, p->func_id, 1); storm_memset_func_en(bp, p->func_id, 1);
/* spq */ /* spq */
if (p->func_flgs & FUNC_FLG_SPQ) { if (p->spq_active) {
storm_memset_spq_addr(bp, p->spq_map, p->func_id); storm_memset_spq_addr(bp, p->spq_map, p->func_id);
REG_WR(bp, XSEM_REG_FAST_MEMORY + REG_WR(bp, XSEM_REG_FAST_MEMORY +
XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod); XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
...@@ -3283,7 +3283,6 @@ static void bnx2x_pf_init(struct bnx2x *bp) ...@@ -3283,7 +3283,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
{ {
struct bnx2x_func_init_params func_init = {0}; struct bnx2x_func_init_params func_init = {0};
struct event_ring_data eq_data = { {0} }; struct event_ring_data eq_data = { {0} };
u16 flags;
if (!CHIP_IS_E1x(bp)) { if (!CHIP_IS_E1x(bp)) {
/* reset IGU PF statistics: MSIX + ATTN */ /* reset IGU PF statistics: MSIX + ATTN */
...@@ -3300,15 +3299,7 @@ static void bnx2x_pf_init(struct bnx2x *bp) ...@@ -3300,15 +3299,7 @@ static void bnx2x_pf_init(struct bnx2x *bp)
BP_FUNC(bp) : BP_VN(bp))*4, 0); BP_FUNC(bp) : BP_VN(bp))*4, 0);
} }
/* function setup flags */ func_init.spq_active = true;
flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
/* This flag is relevant for E1x only.
* E2 doesn't have a TPA configuration in a function level.
*/
flags |= (bp->dev->features & NETIF_F_LRO) ? FUNC_FLG_TPA : 0;
func_init.func_flgs = flags;
func_init.pf_id = BP_FUNC(bp); func_init.pf_id = BP_FUNC(bp);
func_init.func_id = BP_FUNC(bp); func_init.func_id = BP_FUNC(bp);
func_init.spq_map = bp->spq_mapping; func_init.spq_map = bp->spq_mapping;
...@@ -5303,6 +5294,10 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp, ...@@ -5303,6 +5294,10 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
else else
vlan_mac_obj = &bp->sp_objs[cid].mac_obj; vlan_mac_obj = &bp->sp_objs[cid].mac_obj;
break;
case BNX2X_FILTER_VLAN_PENDING:
DP(BNX2X_MSG_SP, "Got SETUP_VLAN completions\n");
vlan_mac_obj = &bp->sp_objs[cid].vlan_obj;
break; break;
case BNX2X_FILTER_MCAST_PENDING: case BNX2X_FILTER_MCAST_PENDING:
DP(BNX2X_MSG_SP, "Got SETUP_MCAST completions\n"); DP(BNX2X_MSG_SP, "Got SETUP_MCAST completions\n");
...@@ -5617,7 +5612,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) ...@@ -5617,7 +5612,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
BNX2X_STATE_DIAG): BNX2X_STATE_DIAG):
case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
BNX2X_STATE_CLOSING_WAIT4_HALT): BNX2X_STATE_CLOSING_WAIT4_HALT):
DP(BNX2X_MSG_SP, "got (un)set mac ramrod\n"); DP(BNX2X_MSG_SP, "got (un)set vlan/mac ramrod\n");
bnx2x_handle_classification_eqe(bp, elem); bnx2x_handle_classification_eqe(bp, elem);
break; break;
...@@ -6205,6 +6200,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode, ...@@ -6205,6 +6200,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
__set_bit(BNX2X_ACCEPT_MULTICAST, tx_accept_flags); __set_bit(BNX2X_ACCEPT_MULTICAST, tx_accept_flags);
__set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags); __set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags);
if (bp->accept_any_vlan) {
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
}
break; break;
case BNX2X_RX_MODE_ALLMULTI: case BNX2X_RX_MODE_ALLMULTI:
__set_bit(BNX2X_ACCEPT_UNICAST, rx_accept_flags); __set_bit(BNX2X_ACCEPT_UNICAST, rx_accept_flags);
...@@ -6216,6 +6216,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode, ...@@ -6216,6 +6216,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, tx_accept_flags); __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, tx_accept_flags);
__set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags); __set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags);
if (bp->accept_any_vlan) {
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
}
break; break;
case BNX2X_RX_MODE_PROMISC: case BNX2X_RX_MODE_PROMISC:
/* According to definition of SI mode, iface in promisc mode /* According to definition of SI mode, iface in promisc mode
...@@ -6236,18 +6241,15 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode, ...@@ -6236,18 +6241,15 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
else else
__set_bit(BNX2X_ACCEPT_UNICAST, tx_accept_flags); __set_bit(BNX2X_ACCEPT_UNICAST, tx_accept_flags);
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
break; break;
default: default:
BNX2X_ERR("Unknown rx_mode: %d\n", rx_mode); BNX2X_ERR("Unknown rx_mode: %d\n", rx_mode);
return -EINVAL; return -EINVAL;
} }
/* Set ACCEPT_ANY_VLAN as we do not enable filtering by VLAN */
if (rx_mode != BNX2X_RX_MODE_NONE) {
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
}
return 0; return 0;
} }
...@@ -8441,6 +8443,42 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, ...@@ -8441,6 +8443,42 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
return rc; return rc;
} }
int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
struct bnx2x_vlan_mac_obj *obj, bool set,
unsigned long *ramrod_flags)
{
int rc;
struct bnx2x_vlan_mac_ramrod_params ramrod_param;
memset(&ramrod_param, 0, sizeof(ramrod_param));
/* Fill general parameters */
ramrod_param.vlan_mac_obj = obj;
ramrod_param.ramrod_flags = *ramrod_flags;
/* Fill a user request section if needed */
if (!test_bit(RAMROD_CONT, ramrod_flags)) {
ramrod_param.user_req.u.vlan.vlan = vlan;
/* Set the command: ADD or DEL */
if (set)
ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
else
ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
}
rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
if (rc == -EEXIST) {
/* Do not treat adding same vlan as error. */
DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc);
rc = 0;
} else if (rc < 0) {
BNX2X_ERR("%s VLAN failed\n", (set ? "Set" : "Del"));
}
return rc;
}
int bnx2x_del_all_macs(struct bnx2x *bp, int bnx2x_del_all_macs(struct bnx2x *bp,
struct bnx2x_vlan_mac_obj *mac_obj, struct bnx2x_vlan_mac_obj *mac_obj,
int mac_type, bool wait_for_comp) int mac_type, bool wait_for_comp)
...@@ -12140,6 +12178,7 @@ static int bnx2x_init_bp(struct bnx2x *bp) ...@@ -12140,6 +12178,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->drv_info_mutex); mutex_init(&bp->drv_info_mutex);
sema_init(&bp->stats_lock, 1); sema_init(&bp->stats_lock, 1);
bp->drv_info_mng_owner = false; bp->drv_info_mng_owner = false;
INIT_LIST_HEAD(&bp->vlan_reg);
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
...@@ -12658,6 +12697,169 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb, ...@@ -12658,6 +12697,169 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
return vxlan_features_check(skb, features); return vxlan_features_check(skb, features);
} }
static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
{
int rc;
if (IS_PF(bp)) {
unsigned long ramrod_flags = 0;
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
rc = bnx2x_set_vlan_one(bp, vid, &bp->sp_objs->vlan_obj,
add, &ramrod_flags);
} else {
rc = bnx2x_vfpf_update_vlan(bp, vid, bp->fp->index, add);
}
return rc;
}
int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
{
struct bnx2x_vlan_entry *vlan;
int rc = 0;
if (!bp->vlan_cnt) {
DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n");
return 0;
}
list_for_each_entry(vlan, &bp->vlan_reg, link) {
/* Prepare for cleanup in case of errors */
if (rc) {
vlan->hw = false;
continue;
}
if (!vlan->hw)
continue;
DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid);
rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
if (rc) {
BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid);
vlan->hw = false;
rc = -EINVAL;
continue;
}
}
return rc;
}
static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct bnx2x *bp = netdev_priv(dev);
struct bnx2x_vlan_entry *vlan;
bool hw = false;
int rc = 0;
if (!netif_running(bp->dev)) {
DP(NETIF_MSG_IFUP,
"Ignoring VLAN configuration the interface is down\n");
return -EFAULT;
}
DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid);
vlan = kmalloc(sizeof(*vlan), GFP_KERNEL);
if (!vlan)
return -ENOMEM;
bp->vlan_cnt++;
if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) {
DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n");
bp->accept_any_vlan = true;
if (IS_PF(bp))
bnx2x_set_rx_mode_inner(bp);
else
bnx2x_vfpf_storm_rx_mode(bp);
} else if (bp->vlan_cnt <= bp->vlan_credit) {
rc = __bnx2x_vlan_configure_vid(bp, vid, true);
hw = true;
}
vlan->vid = vid;
vlan->hw = hw;
if (!rc) {
list_add(&vlan->link, &bp->vlan_reg);
} else {
bp->vlan_cnt--;
kfree(vlan);
}
DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc);
return rc;
}
static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct bnx2x *bp = netdev_priv(dev);
struct bnx2x_vlan_entry *vlan;
int rc = 0;
if (!netif_running(bp->dev)) {
DP(NETIF_MSG_IFUP,
"Ignoring VLAN configuration the interface is down\n");
return -EFAULT;
}
DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid);
if (!bp->vlan_cnt) {
BNX2X_ERR("Unable to kill VLAN %d\n", vid);
return -EINVAL;
}
list_for_each_entry(vlan, &bp->vlan_reg, link)
if (vlan->vid == vid)
break;
if (vlan->vid != vid) {
BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid);
return -EINVAL;
}
if (vlan->hw)
rc = __bnx2x_vlan_configure_vid(bp, vid, false);
list_del(&vlan->link);
kfree(vlan);
bp->vlan_cnt--;
if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) {
/* Configure all non-configured entries */
list_for_each_entry(vlan, &bp->vlan_reg, link) {
if (vlan->hw)
continue;
rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
if (rc) {
BNX2X_ERR("Unable to config VLAN %d\n",
vlan->vid);
continue;
}
DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n",
vlan->vid);
vlan->hw = true;
}
DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n");
bp->accept_any_vlan = false;
if (IS_PF(bp))
bnx2x_set_rx_mode_inner(bp);
else
bnx2x_vfpf_storm_rx_mode(bp);
}
DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc);
return rc;
}
static const struct net_device_ops bnx2x_netdev_ops = { static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_open = bnx2x_open, .ndo_open = bnx2x_open,
.ndo_stop = bnx2x_close, .ndo_stop = bnx2x_close,
...@@ -12671,6 +12873,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { ...@@ -12671,6 +12873,8 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_fix_features = bnx2x_fix_features, .ndo_fix_features = bnx2x_fix_features,
.ndo_set_features = bnx2x_set_features, .ndo_set_features = bnx2x_set_features,
.ndo_tx_timeout = bnx2x_tx_timeout, .ndo_tx_timeout = bnx2x_tx_timeout,
.ndo_vlan_rx_add_vid = bnx2x_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bnx2x_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2x, .ndo_poll_controller = poll_bnx2x,
#endif #endif
...@@ -12881,6 +13085,16 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, ...@@ -12881,6 +13085,16 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA; NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
/* VF with OLD Hypervisor or old PF do not support filtering */
if (IS_PF(bp)) {
if (CHIP_IS_E1x(bp))
bp->accept_any_vlan = true;
else
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
} else if (bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER) {
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
}
dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX; dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_HIGHDMA;
......
...@@ -1413,6 +1413,14 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp, ...@@ -1413,6 +1413,14 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
unsigned long *pstate, bnx2x_obj_type type, unsigned long *pstate, bnx2x_obj_type type,
struct bnx2x_credit_pool_obj *vlans_pool); struct bnx2x_credit_pool_obj *vlans_pool);
void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
struct bnx2x_vlan_mac_obj *vlan_mac_obj,
u8 cl_id, u32 cid, u8 func_id, void *rdata,
dma_addr_t rdata_mapping, int state,
unsigned long *pstate, bnx2x_obj_type type,
struct bnx2x_credit_pool_obj *macs_pool,
struct bnx2x_credit_pool_obj *vlans_pool);
int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp, int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
struct bnx2x_vlan_mac_obj *o); struct bnx2x_vlan_mac_obj *o);
void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp, void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
...@@ -1483,6 +1491,8 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp, ...@@ -1483,6 +1491,8 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
void bnx2x_init_vlan_credit_pool(struct bnx2x *bp, void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
struct bnx2x_credit_pool_obj *p, u8 func_id, struct bnx2x_credit_pool_obj *p, u8 func_id,
u8 func_num); u8 func_num);
void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
int base, int credit);
/****************** RSS CONFIGURATION ****************/ /****************** RSS CONFIGURATION ****************/
void bnx2x_init_rss_config_obj(struct bnx2x *bp, void bnx2x_init_rss_config_obj(struct bnx2x *bp,
...@@ -1510,4 +1520,12 @@ int bnx2x_config_rss(struct bnx2x *bp, ...@@ -1510,4 +1520,12 @@ int bnx2x_config_rss(struct bnx2x *bp,
void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj, void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
u8 *ind_table); u8 *ind_table);
#define PF_MAC_CREDIT_E2(bp, func_num) \
((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_MAC_CREDIT_CNT) / \
func_num + GET_NUM_VFS_PER_PF(bp) * VF_MAC_CREDIT_CNT)
#define PF_VLAN_CREDIT_E2(bp, func_num) \
((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_VLAN_CREDIT_CNT) / \
func_num + GET_NUM_VFS_PER_PF(bp) * VF_VLAN_CREDIT_CNT)
#endif /* BNX2X_SP_VERBS */ #endif /* BNX2X_SP_VERBS */
...@@ -77,7 +77,10 @@ struct bnx2x_vf_queue { ...@@ -77,7 +77,10 @@ struct bnx2x_vf_queue {
/* VLANs object */ /* VLANs object */
struct bnx2x_vlan_mac_obj vlan_obj; struct bnx2x_vlan_mac_obj vlan_obj;
atomic_t vlan_count; /* 0 means vlan-0 is set ~ untagged */
/* VLAN-MACs object */
struct bnx2x_vlan_mac_obj vlan_mac_obj;
unsigned long accept_flags; /* last accept flags configured */ unsigned long accept_flags; /* last accept flags configured */
/* Queue Slow-path State object */ /* Queue Slow-path State object */
...@@ -105,8 +108,10 @@ struct bnx2x_virtf; ...@@ -105,8 +108,10 @@ struct bnx2x_virtf;
struct bnx2x_vf_mac_vlan_filter { struct bnx2x_vf_mac_vlan_filter {
int type; int type;
#define BNX2X_VF_FILTER_MAC 1 #define BNX2X_VF_FILTER_MAC BIT(0)
#define BNX2X_VF_FILTER_VLAN 2 #define BNX2X_VF_FILTER_VLAN BIT(1)
#define BNX2X_VF_FILTER_VLAN_MAC \
(BNX2X_VF_FILTER_MAC | BNX2X_VF_FILTER_VLAN) /*shortcut*/
bool add; bool add;
u8 *mac; u8 *mac;
...@@ -121,14 +126,9 @@ struct bnx2x_vf_mac_vlan_filters { ...@@ -121,14 +126,9 @@ struct bnx2x_vf_mac_vlan_filters {
/* vf context */ /* vf context */
struct bnx2x_virtf { struct bnx2x_virtf {
u16 cfg_flags; u16 cfg_flags;
#define VF_CFG_STATS 0x0001 #define VF_CFG_STATS_COALESCE 0x1
#define VF_CFG_FW_FC 0x0002 #define VF_CFG_EXT_BULLETIN 0x2
#define VF_CFG_TPA 0x0004 #define VF_CFG_VLAN_FILTER 0x4
#define VF_CFG_INT_SIMD 0x0008
#define VF_CACHE_LINE 0x0010
#define VF_CFG_VLAN 0x0020
#define VF_CFG_STATS_COALESCE 0x0040
#define VF_CFG_EXT_BULLETIN 0x0080
u8 link_cfg; /* IFLA_VF_LINK_STATE_AUTO u8 link_cfg; /* IFLA_VF_LINK_STATE_AUTO
* IFLA_VF_LINK_STATE_ENABLE * IFLA_VF_LINK_STATE_ENABLE
* IFLA_VF_LINK_STATE_DISABLE * IFLA_VF_LINK_STATE_DISABLE
...@@ -142,9 +142,8 @@ struct bnx2x_virtf { ...@@ -142,9 +142,8 @@ struct bnx2x_virtf {
bool flr_clnup_stage; /* true during flr cleanup */ bool flr_clnup_stage; /* true during flr cleanup */
/* dma */ /* dma */
dma_addr_t fw_stat_map; /* valid iff VF_CFG_STATS */ dma_addr_t fw_stat_map;
u16 stats_stride; u16 stats_stride;
dma_addr_t spq_map;
dma_addr_t bulletin_map; dma_addr_t bulletin_map;
/* Allocated resources counters. Before the VF is acquired, the /* Allocated resources counters. Before the VF is acquired, the
...@@ -165,8 +164,6 @@ struct bnx2x_virtf { ...@@ -165,8 +164,6 @@ struct bnx2x_virtf {
#define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters)
#define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters)
#define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters)
/* Hide a single vlan filter credit for the hypervisor */
#define vf_vlan_rules_visible_cnt(vf) (vf_vlan_rules_cnt(vf) - 1)
u8 sb_count; /* actual number of SBs */ u8 sb_count; /* actual number of SBs */
u8 igu_base_id; /* base igu status block id */ u8 igu_base_id; /* base igu status block id */
...@@ -209,6 +206,9 @@ struct bnx2x_virtf { ...@@ -209,6 +206,9 @@ struct bnx2x_virtf {
enum channel_tlvs op_current; enum channel_tlvs op_current;
u8 fp_hsi; u8 fp_hsi;
struct bnx2x_credit_pool_obj vf_vlans_pool;
struct bnx2x_credit_pool_obj vf_macs_pool;
}; };
#define BNX2X_NR_VIRTFN(bp) ((bp)->vfdb->sriov.nr_virtfn) #define BNX2X_NR_VIRTFN(bp) ((bp)->vfdb->sriov.nr_virtfn)
...@@ -232,6 +232,12 @@ struct bnx2x_virtf { ...@@ -232,6 +232,12 @@ struct bnx2x_virtf {
#define FW_VF_HANDLE(abs_vfid) \ #define FW_VF_HANDLE(abs_vfid) \
(abs_vfid + FW_PF_MAX_HANDLE) (abs_vfid + FW_PF_MAX_HANDLE)
#define GET_NUM_VFS_PER_PATH(bp) 64 /* use max possible value */
#define GET_NUM_VFS_PER_PF(bp) ((bp)->vfdb ? (bp)->vfdb->sriov.total \
: 0)
#define VF_MAC_CREDIT_CNT 1
#define VF_VLAN_CREDIT_CNT 2 /* VLAN0 + 'real' VLAN */
/* locking and unlocking the channel mutex */ /* locking and unlocking the channel mutex */
void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
enum channel_tlvs tlv); enum channel_tlvs tlv);
...@@ -275,6 +281,10 @@ struct bnx2x_vf_sp { ...@@ -275,6 +281,10 @@ struct bnx2x_vf_sp {
struct eth_classify_rules_ramrod_data e2; struct eth_classify_rules_ramrod_data e2;
} vlan_rdata; } vlan_rdata;
union {
struct eth_classify_rules_ramrod_data e2;
} vlan_mac_rdata;
union { union {
struct eth_filter_rules_ramrod_data e2; struct eth_filter_rules_ramrod_data e2;
} rx_mode_rdata; } rx_mode_rdata;
...@@ -538,6 +548,7 @@ int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx); ...@@ -538,6 +548,7 @@ int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx);
int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state); int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state);
int bnx2x_vfpf_update_vlan(struct bnx2x *bp, u16 vid, u8 vf_qid, bool add);
#else /* CONFIG_BNX2X_SRIOV */ #else /* CONFIG_BNX2X_SRIOV */
static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid, static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
...@@ -606,5 +617,7 @@ struct pf_vf_bulletin_content; ...@@ -606,5 +617,7 @@ struct pf_vf_bulletin_content;
static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin, static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
bool support_long) {} bool support_long) {}
static inline int bnx2x_vfpf_update_vlan(struct bnx2x *bp, u16 vid, u8 vf_qid, bool add) {return 0; }
#endif /* CONFIG_BNX2X_SRIOV */ #endif /* CONFIG_BNX2X_SRIOV */
#endif /* bnx2x_sriov.h */ #endif /* bnx2x_sriov.h */
...@@ -70,6 +70,8 @@ struct hw_sb_info { ...@@ -70,6 +70,8 @@ struct hw_sb_info {
#define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004 #define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004
#define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008 #define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008
#define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010 #define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010
#define VFPF_RX_MASK_ACCEPT_ANY_VLAN 0x00000020
#define BULLETIN_CONTENT_SIZE (sizeof(struct pf_vf_bulletin_content)) #define BULLETIN_CONTENT_SIZE (sizeof(struct pf_vf_bulletin_content))
#define BULLETIN_CONTENT_LEGACY_SIZE (32) #define BULLETIN_CONTENT_LEGACY_SIZE (32)
#define BULLETIN_ATTEMPTS 5 /* crc failures before throwing towel */ #define BULLETIN_ATTEMPTS 5 /* crc failures before throwing towel */
...@@ -133,6 +135,7 @@ struct vfpf_acquire_tlv { ...@@ -133,6 +135,7 @@ struct vfpf_acquire_tlv {
u8 fp_hsi_ver; u8 fp_hsi_ver;
u8 caps; u8 caps;
#define VF_CAP_SUPPORT_EXT_BULLETIN (1 << 0) #define VF_CAP_SUPPORT_EXT_BULLETIN (1 << 0)
#define VF_CAP_SUPPORT_VLAN_FILTER (1 << 1)
} vfdev_info; } vfdev_info;
struct vf_pf_resc_request resc_request; struct vf_pf_resc_request resc_request;
...@@ -174,10 +177,12 @@ struct pfvf_acquire_resp_tlv { ...@@ -174,10 +177,12 @@ struct pfvf_acquire_resp_tlv {
struct pf_vf_pfdev_info { struct pf_vf_pfdev_info {
u32 chip_num; u32 chip_num;
u32 pf_cap; u32 pf_cap;
#define PFVF_CAP_RSS 0x00000001 #define PFVF_CAP_RSS 0x00000001
#define PFVF_CAP_DHC 0x00000002 #define PFVF_CAP_DHC 0x00000002
#define PFVF_CAP_TPA 0x00000004 #define PFVF_CAP_TPA 0x00000004
#define PFVF_CAP_TPA_UPDATE 0x00000008 #define PFVF_CAP_TPA_UPDATE 0x00000008
#define PFVF_CAP_VLAN_FILTER 0x00000010
char fw_ver[32]; char fw_ver[32];
u16 db_size; u16 db_size;
u8 indices_per_sb; u8 indices_per_sb;
...@@ -294,7 +299,7 @@ struct vfpf_q_mac_vlan_filter { ...@@ -294,7 +299,7 @@ struct vfpf_q_mac_vlan_filter {
u32 flags; u32 flags;
#define VFPF_Q_FILTER_DEST_MAC_VALID 0x01 #define VFPF_Q_FILTER_DEST_MAC_VALID 0x01
#define VFPF_Q_FILTER_VLAN_TAG_VALID 0x02 #define VFPF_Q_FILTER_VLAN_TAG_VALID 0x02
#define VFPF_Q_FILTER_SET_MAC 0x100 /* set/clear */ #define VFPF_Q_FILTER_SET 0x100 /* set/clear */
u8 mac[ETH_ALEN]; u8 mac[ETH_ALEN];
u16 vlan_tag; u16 vlan_tag;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment