bnx2x: VF RSS support - VF side

In this patch capabilities are added to the Vf driver to request
multiple queues over the VF PF channel, and the logic for requesting
rss configuration for said queues.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilong Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ariel Elior 2013-09-04 14:09:22 +03:00 committed by David S. Miller
parent b9871bcfd2
commit 60cad4e67b
6 changed files with 145 additions and 60 deletions

View File

@ -1942,7 +1942,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
} }
} }
static int bnx2x_init_rss_pf(struct bnx2x *bp) static int bnx2x_init_rss(struct bnx2x *bp)
{ {
int i; int i;
u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp); u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
@ -1966,8 +1966,8 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp)
return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp)); return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
} }
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
bool config_hash) bool config_hash, bool enable)
{ {
struct bnx2x_config_rss_params params = {NULL}; struct bnx2x_config_rss_params params = {NULL};
@ -1982,17 +1982,21 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags); __set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
__set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags); if (enable) {
__set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
/* RSS configuration */ /* RSS configuration */
__set_bit(BNX2X_RSS_IPV4, &params.rss_flags); __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
__set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
__set_bit(BNX2X_RSS_IPV6, &params.rss_flags); __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
__set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
if (rss_obj->udp_rss_v4) if (rss_obj->udp_rss_v4)
__set_bit(BNX2X_RSS_IPV4_UDP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV4_UDP, &params.rss_flags);
if (rss_obj->udp_rss_v6) if (rss_obj->udp_rss_v6)
__set_bit(BNX2X_RSS_IPV6_UDP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV6_UDP, &params.rss_flags);
} else {
__set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
}
/* Hash bits */ /* Hash bits */
params.rss_result_mask = MULTI_MASK; params.rss_result_mask = MULTI_MASK;
@ -2001,11 +2005,14 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
if (config_hash) { if (config_hash) {
/* RSS keys */ /* RSS keys */
prandom_bytes(params.rss_key, sizeof(params.rss_key)); prandom_bytes(params.rss_key, T_ETH_RSS_KEY * 4);
__set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags); __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
} }
return bnx2x_config_rss(bp, &params); if (IS_PF(bp))
return bnx2x_config_rss(bp, &params);
else
return bnx2x_vfpf_config_rss(bp, &params);
} }
static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
@ -2645,38 +2652,32 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* initialize FW coalescing state machines in RAM */ /* initialize FW coalescing state machines in RAM */
bnx2x_update_coalesce(bp); bnx2x_update_coalesce(bp);
}
/* setup the leading queue */ /* setup the leading queue */
rc = bnx2x_setup_leading(bp); rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
LOAD_ERROR_EXIT(bp, load_error3);
}
/* set up the rest of the queues */
for_each_nondefault_eth_queue(bp, i) {
if (IS_PF(bp))
rc = bnx2x_setup_queue(bp, &bp->fp[i], false);
else /* VF */
rc = bnx2x_vfpf_setup_q(bp, &bp->fp[i], false);
if (rc) { if (rc) {
BNX2X_ERR("Setup leading failed!\n"); BNX2X_ERR("Queue %d setup failed\n", i);
LOAD_ERROR_EXIT(bp, load_error3); LOAD_ERROR_EXIT(bp, load_error3);
} }
}
/* set up the rest of the queues */ /* setup rss */
for_each_nondefault_eth_queue(bp, i) { rc = bnx2x_init_rss(bp);
rc = bnx2x_setup_queue(bp, &bp->fp[i], 0); if (rc) {
if (rc) { BNX2X_ERR("PF RSS init failed\n");
BNX2X_ERR("Queue setup failed\n"); LOAD_ERROR_EXIT(bp, load_error3);
LOAD_ERROR_EXIT(bp, load_error3);
}
}
/* setup rss */
rc = bnx2x_init_rss_pf(bp);
if (rc) {
BNX2X_ERR("PF RSS init failed\n");
LOAD_ERROR_EXIT(bp, load_error3);
}
} else { /* vf */
for_each_eth_queue(bp, i) {
rc = bnx2x_vfpf_setup_q(bp, i);
if (rc) {
BNX2X_ERR("Queue setup failed\n");
LOAD_ERROR_EXIT(bp, load_error3);
}
}
} }
/* Now when Clients are configured we are ready to work */ /* Now when Clients are configured we are ready to work */

View File

@ -105,9 +105,10 @@ void bnx2x_send_unload_done(struct bnx2x *bp, bool keep_link);
* @rss_obj: RSS object to use * @rss_obj: RSS object to use
* @ind_table: indirection table to configure * @ind_table: indirection table to configure
* @config_hash: re-configure RSS hash keys configuration * @config_hash: re-configure RSS hash keys configuration
* @enable: enabled or disabled configuration
*/ */
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
bool config_hash); bool config_hash, bool enable);
/** /**
* bnx2x__init_func_obj - init function object * bnx2x__init_func_obj - init function object
@ -980,7 +981,7 @@ static inline int func_by_vn(struct bnx2x *bp, int vn)
static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash) static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash)
{ {
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, config_hash); return bnx2x_rss(bp, &bp->rss_conf_obj, config_hash, true);
} }
/** /**

View File

@ -3281,14 +3281,14 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
DP(BNX2X_MSG_ETHTOOL, DP(BNX2X_MSG_ETHTOOL,
"rss re-configured, UDP 4-tupple %s\n", "rss re-configured, UDP 4-tupple %s\n",
udp_rss_requested ? "enabled" : "disabled"); udp_rss_requested ? "enabled" : "disabled");
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); return bnx2x_rss(bp, &bp->rss_conf_obj, false, true);
} else if ((info->flow_type == UDP_V6_FLOW) && } else if ((info->flow_type == UDP_V6_FLOW) &&
(bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
DP(BNX2X_MSG_ETHTOOL, DP(BNX2X_MSG_ETHTOOL,
"rss re-configured, UDP 4-tupple %s\n", "rss re-configured, UDP 4-tupple %s\n",
udp_rss_requested ? "enabled" : "disabled"); udp_rss_requested ? "enabled" : "disabled");
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); return bnx2x_rss(bp, &bp->rss_conf_obj, false, true);
} }
return 0; return 0;

View File

@ -8060,7 +8060,10 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
int bnx2x_setup_leading(struct bnx2x *bp) int bnx2x_setup_leading(struct bnx2x *bp)
{ {
return bnx2x_setup_queue(bp, &bp->fp[0], 1); if (IS_PF(bp))
return bnx2x_setup_queue(bp, &bp->fp[0], true);
else /* VF */
return bnx2x_vfpf_setup_q(bp, &bp->fp[0], true);
} }
/** /**
@ -8074,8 +8077,10 @@ int bnx2x_set_int_mode(struct bnx2x *bp)
{ {
int rc = 0; int rc = 0;
if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX) if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX) {
BNX2X_ERR("VF not loaded since interrupt mode not msix\n");
return -EINVAL; return -EINVAL;
}
switch (int_mode) { switch (int_mode) {
case BNX2X_INT_MODE_MSIX: case BNX2X_INT_MODE_MSIX:
@ -11658,9 +11663,11 @@ static int bnx2x_init_bp(struct bnx2x *bp)
* second status block for the L2 queue, and a third status block for * second status block for the L2 queue, and a third status block for
* CNIC if supported. * CNIC if supported.
*/ */
if (CNIC_SUPPORT(bp)) if (IS_VF(bp))
bp->min_msix_vec_cnt = 1;
else if (CNIC_SUPPORT(bp))
bp->min_msix_vec_cnt = 3; bp->min_msix_vec_cnt = 3;
else else /* PF w/o cnic */
bp->min_msix_vec_cnt = 2; bp->min_msix_vec_cnt = 2;
BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt); BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
@ -12571,8 +12578,7 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
* @dev: pci device * @dev: pci device
* *
*/ */
static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev, static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev, int cnic_cnt)
int cnic_cnt, bool is_vf)
{ {
int index; int index;
u16 control = 0; u16 control = 0;
@ -12598,7 +12604,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
index = control & PCI_MSIX_FLAGS_QSIZE; index = control & PCI_MSIX_FLAGS_QSIZE;
return is_vf ? index + 1 : index; return index;
} }
static int set_max_cos_est(int chip_id) static int set_max_cos_est(int chip_id)
@ -12678,10 +12684,13 @@ static int bnx2x_init_one(struct pci_dev *pdev,
is_vf = set_is_vf(ent->driver_data); is_vf = set_is_vf(ent->driver_data);
cnic_cnt = is_vf ? 0 : 1; cnic_cnt = is_vf ? 0 : 1;
max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt, is_vf); max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
/* add another SB for VF as it has no default SB */
max_non_def_sbs += is_vf ? 1 : 0;
/* Maximum number of RSS queues: one IGU SB goes to CNIC */ /* Maximum number of RSS queues: one IGU SB goes to CNIC */
rss_count = is_vf ? 1 : max_non_def_sbs - cnic_cnt; rss_count = max_non_def_sbs - cnic_cnt;
if (rss_count < 1) if (rss_count < 1)
return -EINVAL; return -EINVAL;

View File

@ -746,9 +746,12 @@ int bnx2x_vfpf_release(struct bnx2x *bp);
int bnx2x_vfpf_release(struct bnx2x *bp); int bnx2x_vfpf_release(struct bnx2x *bp);
int bnx2x_vfpf_init(struct bnx2x *bp); int bnx2x_vfpf_init(struct bnx2x *bp);
void bnx2x_vfpf_close_vf(struct bnx2x *bp); void bnx2x_vfpf_close_vf(struct bnx2x *bp);
int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx); int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
bool is_leading);
int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx); int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx);
int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set); int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set);
int bnx2x_vfpf_config_rss(struct bnx2x *bp,
struct bnx2x_config_rss_params *params);
int bnx2x_vfpf_set_mcast(struct net_device *dev); int bnx2x_vfpf_set_mcast(struct net_device *dev);
int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp); int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp);
@ -809,7 +812,7 @@ static inline int bnx2x_vfpf_acquire(struct bnx2x *bp,
static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; } static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; } static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; }
static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {} static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {}
static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx) {return 0; } static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading) {return 0; }
static inline int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx) {return 0; } static inline int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx) {return 0; }
static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr,
u8 vf_qid, bool set) {return 0; } u8 vf_qid, bool set) {return 0; }

View File

@ -379,6 +379,8 @@ int bnx2x_vfpf_init(struct bnx2x *bp)
req->stats_addr = bp->fw_stats_data_mapping + req->stats_addr = bp->fw_stats_data_mapping +
offsetof(struct bnx2x_fw_stats_data, queue_stats); offsetof(struct bnx2x_fw_stats_data, queue_stats);
req->stats_stride = sizeof(struct per_queue_stats);
/* add list termination tlv */ /* add list termination tlv */
bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END, bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
sizeof(struct channel_list_end_tlv)); sizeof(struct channel_list_end_tlv));
@ -506,11 +508,12 @@ static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
} }
/* ask the pf to open a queue for the vf */ /* ask the pf to open a queue for the vf */
int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx) int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
bool is_leading)
{ {
struct vfpf_setup_q_tlv *req = &bp->vf2pf_mbox->req.setup_q; struct vfpf_setup_q_tlv *req = &bp->vf2pf_mbox->req.setup_q;
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp; struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
struct bnx2x_fastpath *fp = &bp->fp[fp_idx]; u8 fp_idx = fp->index;
u16 tpa_agg_size = 0, flags = 0; u16 tpa_agg_size = 0, flags = 0;
int rc; int rc;
@ -526,6 +529,9 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
tpa_agg_size = TPA_AGG_SIZE; tpa_agg_size = TPA_AGG_SIZE;
} }
if (is_leading)
flags |= VFPF_QUEUE_FLG_LEADING_RSS;
/* calculate queue flags */ /* calculate queue flags */
flags |= VFPF_QUEUE_FLG_STATS; flags |= VFPF_QUEUE_FLG_STATS;
flags |= VFPF_QUEUE_FLG_CACHE_ALIGN; flags |= VFPF_QUEUE_FLG_CACHE_ALIGN;
@ -699,6 +705,71 @@ out:
return 0; return 0;
} }
/* request pf to config rss table for vf queues*/
int bnx2x_vfpf_config_rss(struct bnx2x *bp,
struct bnx2x_config_rss_params *params)
{
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
struct vfpf_rss_tlv *req = &bp->vf2pf_mbox->req.update_rss;
int rc = 0;
/* clear mailbox and prep first tlv */
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_UPDATE_RSS,
sizeof(*req));
/* add list termination tlv */
bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
memcpy(req->ind_table, params->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
memcpy(req->rss_key, params->rss_key, sizeof(params->rss_key));
req->ind_table_size = T_ETH_INDIRECTION_TABLE_SIZE;
req->rss_key_size = T_ETH_RSS_KEY;
req->rss_result_mask = params->rss_result_mask;
/* flags handled individually for backward/forward compatability */
if (params->rss_flags & (1 << BNX2X_RSS_MODE_DISABLED))
req->rss_flags |= VFPF_RSS_MODE_DISABLED;
if (params->rss_flags & (1 << BNX2X_RSS_MODE_REGULAR))
req->rss_flags |= VFPF_RSS_MODE_REGULAR;
if (params->rss_flags & (1 << BNX2X_RSS_SET_SRCH))
req->rss_flags |= VFPF_RSS_SET_SRCH;
if (params->rss_flags & (1 << BNX2X_RSS_IPV4))
req->rss_flags |= VFPF_RSS_IPV4;
if (params->rss_flags & (1 << BNX2X_RSS_IPV4_TCP))
req->rss_flags |= VFPF_RSS_IPV4_TCP;
if (params->rss_flags & (1 << BNX2X_RSS_IPV4_UDP))
req->rss_flags |= VFPF_RSS_IPV4_UDP;
if (params->rss_flags & (1 << BNX2X_RSS_IPV6))
req->rss_flags |= VFPF_RSS_IPV6;
if (params->rss_flags & (1 << BNX2X_RSS_IPV6_TCP))
req->rss_flags |= VFPF_RSS_IPV6_TCP;
if (params->rss_flags & (1 << BNX2X_RSS_IPV6_UDP))
req->rss_flags |= VFPF_RSS_IPV6_UDP;
DP(BNX2X_MSG_IOV, "rss flags %x\n", req->rss_flags);
/* output tlvs list */
bnx2x_dp_tlv_list(bp, req);
/* send message to pf */
rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
if (rc) {
BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
goto out;
}
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
BNX2X_ERR("failed to send rss message to PF over Vf PF channel %d\n",
resp->hdr.status);
rc = -EINVAL;
}
out:
bnx2x_vfpf_finalize(bp, &req->first_tlv);
return 0;
}
int bnx2x_vfpf_set_mcast(struct net_device *dev) int bnx2x_vfpf_set_mcast(struct net_device *dev)
{ {
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);