diff options
author | Ariel Elior <ariele@broadcom.com> | 2013-01-01 05:22:38 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-02 01:45:07 -0800 |
commit | 954ea7480b11e67266c760c8c67fc337a3a6d5b9 (patch) | |
tree | c8153cddc8794428ce4a99a6052bda806ee1456a /drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |
parent | 8db573baa5cf1f65ed94039ac3100ea5a94260de (diff) |
bnx2x: Support of PF driver of a VF q_filters request
The VF driver uses the 'q_filters' message on the VF <-> PF channel
for configuring an open queue, for example when the rxmode changes.
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 5b47b0849a58..e63925cbe501 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -102,6 +102,8 @@ static void bnx2x_vf_igu_ack_sb(struct bnx2x *bp, struct bnx2x_virtf *vf, } /* VFOP - VF slow-path operation support */ +#define BNX2X_VFOP_FILTER_ADD_CNT_MAX 0x10000 + /* VFOP operations states */ enum bnx2x_vfop_qctor_state { BNX2X_VFOP_QCTOR_INIT, @@ -124,6 +126,17 @@ enum bnx2x_vfop_qsetup_state { BNX2X_VFOP_QSETUP_DONE }; +enum bnx2x_vfop_mcast_state { + BNX2X_VFOP_MCAST_DEL, + BNX2X_VFOP_MCAST_ADD, + BNX2X_VFOP_MCAST_CHK_DONE +}; + +enum bnx2x_vfop_rxmode_state { + BNX2X_VFOP_RXMODE_CONFIG, + BNX2X_VFOP_RXMODE_DONE +}; + #define bnx2x_vfop_reset_wq(vf) atomic_set(&vf->op_in_progress, 0) void bnx2x_vfop_qctor_dump_tx(struct bnx2x *bp, struct bnx2x_virtf *vf, @@ -572,6 +585,57 @@ bnx2x_vfop_vlan_mac_prep_ramrod(struct bnx2x_vlan_mac_ramrod_params *ramrod, ureq->cmd = flags->add ? BNX2X_VLAN_MAC_ADD : BNX2X_VLAN_MAC_DEL; } +static inline void +bnx2x_vfop_mac_prep_ramrod(struct bnx2x_vlan_mac_ramrod_params *ramrod, + struct bnx2x_vfop_vlan_mac_flags *flags) +{ + bnx2x_vfop_vlan_mac_prep_ramrod(ramrod, flags); + set_bit(BNX2X_ETH_MAC, &ramrod->user_req.vlan_mac_flags); +} + +int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + struct bnx2x_vfop_filters *macs, + int qid, bool drv_only) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + struct bnx2x_vfop_args_filters filters = { + .multi_filter = macs, + .credit = NULL, /* consume credit */ + }; + struct bnx2x_vfop_vlan_mac_flags flags = { + .drv_only = drv_only, + .dont_consume = (filters.credit != NULL), + .single_cmd = false, + .add = false, /* don't care since only the items in the + * filters list affect the sp operation, + * not the list itself + */ + }; + struct bnx2x_vlan_mac_ramrod_params *ramrod = + &vf->op_params.vlan_mac; + + /* set ramrod params */ + bnx2x_vfop_mac_prep_ramrod(ramrod, &flags); + + /* set object */ + ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, mac_obj); + + /* set extra args */ + filters.multi_filter->add_cnt = BNX2X_VFOP_FILTER_ADD_CNT_MAX; + vfop->args.filters = filters; + + bnx2x_vfop_opset(BNX2X_VFOP_MAC_CONFIG_LIST, + bnx2x_vfop_vlan_mac, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_vlan_mac, + cmd->block); + } + return -ENOMEM; +} + int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vfop_cmd *cmd, @@ -611,6 +675,48 @@ int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp, return -ENOMEM; } +int bnx2x_vfop_vlan_list_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + struct bnx2x_vfop_filters *vlans, + int qid, bool drv_only) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + struct bnx2x_vfop_args_filters filters = { + .multi_filter = vlans, + .credit = &bnx2x_vfq(vf, qid, vlan_count), + }; + struct bnx2x_vfop_vlan_mac_flags flags = { + .drv_only = drv_only, + .dont_consume = (filters.credit != NULL), + .single_cmd = false, + .add = false, /* don't care */ + }; + struct bnx2x_vlan_mac_ramrod_params *ramrod = + &vf->op_params.vlan_mac; + + /* set ramrod params */ + bnx2x_vfop_vlan_mac_prep_ramrod(ramrod, &flags); + + /* set object */ + ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj); + + /* set extra args */ + filters.multi_filter->add_cnt = vf_vlan_rules_cnt(vf) - + atomic_read(filters.credit); + + vfop->args.filters = filters; + + bnx2x_vfop_opset(BNX2X_VFOP_VLAN_CONFIG_LIST, + bnx2x_vfop_vlan_mac, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_vlan_mac, + cmd->block); + } + return -ENOMEM; +} + /* VFOP queue setup (queue constructor + set vlan 0) */ static void bnx2x_vfop_qsetup(struct bnx2x *bp, struct bnx2x_virtf *vf) { @@ -676,6 +782,180 @@ int bnx2x_vfop_qsetup_cmd(struct bnx2x *bp, return -ENOMEM; } +/* VFOP multi-casts */ +static void bnx2x_vfop_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf); + struct bnx2x_mcast_ramrod_params *mcast = &vfop->op_p->mcast; + struct bnx2x_raw_obj *raw = &mcast->mcast_obj->raw; + struct bnx2x_vfop_args_mcast *args = &vfop->args.mc_list; + enum bnx2x_vfop_mcast_state state = vfop->state; + int i; + + bnx2x_vfop_reset_wq(vf); + + if (vfop->rc < 0) + goto op_err; + + DP(BNX2X_MSG_IOV, "vf[%d] STATE: %d\n", vf->abs_vfid, state); + + switch (state) { + case BNX2X_VFOP_MCAST_DEL: + /* clear existing mcasts */ + vfop->state = BNX2X_VFOP_MCAST_ADD; + vfop->rc = bnx2x_config_mcast(bp, mcast, BNX2X_MCAST_CMD_DEL); + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT); + + case BNX2X_VFOP_MCAST_ADD: + if (raw->check_pending(raw)) + goto op_pending; + + if (args->mc_num) { + /* update mcast list on the ramrod params */ + INIT_LIST_HEAD(&mcast->mcast_list); + for (i = 0; i < args->mc_num; i++) + list_add_tail(&(args->mc[i].link), + &mcast->mcast_list); + /* add new mcasts */ + vfop->state = BNX2X_VFOP_MCAST_CHK_DONE; + vfop->rc = bnx2x_config_mcast(bp, mcast, + BNX2X_MCAST_CMD_ADD); + } + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE); + + case BNX2X_VFOP_MCAST_CHK_DONE: + vfop->rc = raw->check_pending(raw) ? 1 : 0; + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE); + default: + bnx2x_vfop_default(state); + } +op_err: + BNX2X_ERR("MCAST CONFIG error: rc %d\n", vfop->rc); +op_done: + kfree(args->mc); + bnx2x_vfop_end(bp, vf, vfop); +op_pending: + return; +} + +int bnx2x_vfop_mcast_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + bnx2x_mac_addr_t *mcasts, + int mcast_num, bool drv_only) +{ + struct bnx2x_vfop *vfop = NULL; + size_t mc_sz = mcast_num * sizeof(struct bnx2x_mcast_list_elem); + struct bnx2x_mcast_list_elem *mc = mc_sz ? kzalloc(mc_sz, GFP_KERNEL) : + NULL; + + if (!mc_sz || mc) { + vfop = bnx2x_vfop_add(bp, vf); + if (vfop) { + int i; + struct bnx2x_mcast_ramrod_params *ramrod = + &vf->op_params.mcast; + + /* set ramrod params */ + memset(ramrod, 0, sizeof(*ramrod)); + ramrod->mcast_obj = &vf->mcast_obj; + if (drv_only) + set_bit(RAMROD_DRV_CLR_ONLY, + &ramrod->ramrod_flags); + + /* copy mcasts pointers */ + vfop->args.mc_list.mc_num = mcast_num; + vfop->args.mc_list.mc = mc; + for (i = 0; i < mcast_num; i++) + mc[i].mac = mcasts[i]; + + bnx2x_vfop_opset(BNX2X_VFOP_MCAST_DEL, + bnx2x_vfop_mcast, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_mcast, + cmd->block); + } else { + kfree(mc); + } + } + return -ENOMEM; +} + +/* VFOP rx-mode */ +static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf); + struct bnx2x_rx_mode_ramrod_params *ramrod = &vfop->op_p->rx_mode; + enum bnx2x_vfop_rxmode_state state = vfop->state; + + bnx2x_vfop_reset_wq(vf); + + if (vfop->rc < 0) + goto op_err; + + DP(BNX2X_MSG_IOV, "vf[%d] STATE: %d\n", vf->abs_vfid, state); + + switch (state) { + case BNX2X_VFOP_RXMODE_CONFIG: + /* next state */ + vfop->state = BNX2X_VFOP_RXMODE_DONE; + + vfop->rc = bnx2x_config_rx_mode(bp, ramrod); + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE); +op_err: + BNX2X_ERR("RXMODE error: rc %d\n", vfop->rc); +op_done: + case BNX2X_VFOP_RXMODE_DONE: + bnx2x_vfop_end(bp, vf, vfop); + return; + default: + bnx2x_vfop_default(state); + } +op_pending: + return; +} + +int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid, unsigned long accept_flags) +{ + struct bnx2x_vf_queue *vfq = vfq_get(vf, qid); + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + struct bnx2x_rx_mode_ramrod_params *ramrod = + &vf->op_params.rx_mode; + + memset(ramrod, 0, sizeof(*ramrod)); + + /* Prepare ramrod parameters */ + ramrod->cid = vfq->cid; + ramrod->cl_id = vfq_cl_id(vf, vfq); + ramrod->rx_mode_obj = &bp->rx_mode_obj; + ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid); + + ramrod->rx_accept_flags = accept_flags; + ramrod->tx_accept_flags = accept_flags; + ramrod->pstate = &vf->filter_state; + ramrod->state = BNX2X_FILTER_RX_MODE_PENDING; + + set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state); + set_bit(RAMROD_RX, &ramrod->ramrod_flags); + set_bit(RAMROD_TX, &ramrod->ramrod_flags); + + ramrod->rdata = + bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2); + ramrod->rdata_mapping = + bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2); + + bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG, + bnx2x_vfop_rxmode, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_rxmode, + cmd->block); + } + return -ENOMEM; +} + /* VF enable primitives * when pretend is required the caller is responsible * for calling pretend prior to calling these routines |