From patchwork Thu Nov 15 16:47:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Elior X-Patchwork-Id: 199359 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 28CAD2C0395 for ; Fri, 16 Nov 2012 03:46:51 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1768532Ab2KOQqs (ORCPT ); Thu, 15 Nov 2012 11:46:48 -0500 Received: from mms2.broadcom.com ([216.31.210.18]:3472 "EHLO mms2.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1768443Ab2KOQqn (ORCPT ); Thu, 15 Nov 2012 11:46:43 -0500 Received: from [10.9.200.133] by mms2.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.5)); Thu, 15 Nov 2012 08:43:29 -0800 X-Server-Uuid: 4500596E-606A-40F9-852D-14843D8201B2 Received: from mail-irva-13.broadcom.com (10.11.16.103) by IRVEXCHHUB02.corp.ad.broadcom.com (10.9.200.133) with Microsoft SMTP Server id 8.2.247.2; Thu, 15 Nov 2012 08:45:21 -0800 Received: from lb-tlvb-pcie37.il.broadcom.com ( lb-tlvb-pcie37.il.broadcom.com [10.185.6.30]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id AC9EB40FE3; Thu, 15 Nov 2012 08:45:45 -0800 (PST) From: "Ariel Elior" To: "David Miller" cc: netdev , "Ariel Elior" , "Eilon Greenstein" Subject: [PATCH v2 net-next 17/22] bnx2x: Support of PF driver of a VF q_teardown request Date: Thu, 15 Nov 2012 18:47:42 +0200 Message-ID: <1352998067-9707-18-git-send-email-ariele@broadcom.com> X-Mailer: git-send-email 1.7.9.GIT In-Reply-To: <1352998067-9707-1-git-send-email-ariele@broadcom.com> References: <1352998067-9707-1-git-send-email-ariele@broadcom.com> MIME-Version: 1.0 X-WSS-ID: 7CBBC43B3R02911195-04-01 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The 'q_teardown' request is basically the opposite of the 'q_setup'. Here the PF driver removes from the device the queue it opened against the VF fastpath ring at 'setup_q' stage, along with all related rx_mode info. Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 268 +++++++++++++++++++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 5 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 20 ++ 3 files changed, 293 insertions(+), 0 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 82a9654..146ad65 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -109,6 +109,13 @@ enum bnx2x_vfop_qctor_state { BNX2X_VFOP_QCTOR_INT_EN }; +enum bnx2x_vfop_qdtor_state { + BNX2X_VFOP_QDTOR_HALT, + BNX2X_VFOP_QDTOR_TERMINATE, + BNX2X_VFOP_QDTOR_CFCDEL, + BNX2X_VFOP_QDTOR_DONE +}; + enum bnx2x_vfop_vlan_mac_state { BNX2X_VFOP_VLAN_MAC_CONFIG_SINGLE, BNX2X_VFOP_VLAN_MAC_CLEAR, @@ -135,6 +142,14 @@ enum bnx2x_vfop_rxmode_state { BNX2X_VFOP_RXMODE_DONE }; +enum bnx2x_vfop_qteardown_state { + BNX2X_VFOP_QTEARDOWN_RXMODE, + BNX2X_VFOP_QTEARDOWN_CLR_VLAN, + BNX2X_VFOP_QTEARDOWN_CLR_MAC, + BNX2X_VFOP_QTEARDOWN_QDTOR, + BNX2X_VFOP_QTEARDOWN_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, @@ -341,6 +356,102 @@ static int bnx2x_vfop_qctor_cmd(struct bnx2x *bp, return -ENOMEM; } +/* VFOP queue destruction */ +static void bnx2x_vfop_qdtor(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf); + struct bnx2x_vfop_args_qdtor *qdtor = &vfop->args.qdtor; + struct bnx2x_queue_state_params *q_params = &vfop->op_p->qctor.qstate; + enum bnx2x_vfop_qdtor_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_QDTOR_HALT: + + /* has this queue already been stopped? */ + if (bnx2x_get_q_logical_state(bp, q_params->q_obj) == + BNX2X_Q_LOGICAL_STATE_STOPPED) { + DP(BNX2X_MSG_IOV, + "Entered qdtor but queue was already stopped. Aborting gracefully\n"); + goto op_done; + } + + /* next state */ + vfop->state = BNX2X_VFOP_QDTOR_TERMINATE; + + q_params->cmd = BNX2X_Q_CMD_HALT; + vfop->rc = bnx2x_queue_state_change(bp, q_params); + + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT); + + case BNX2X_VFOP_QDTOR_TERMINATE: + /* next state */ + vfop->state = BNX2X_VFOP_QDTOR_CFCDEL; + + q_params->cmd = BNX2X_Q_CMD_TERMINATE; + vfop->rc = bnx2x_queue_state_change(bp, q_params); + + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT); + + case BNX2X_VFOP_QDTOR_CFCDEL: + /* next state */ + vfop->state = BNX2X_VFOP_QDTOR_DONE; + + q_params->cmd = BNX2X_Q_CMD_CFC_DEL; + vfop->rc = bnx2x_queue_state_change(bp, q_params); + + bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE); +op_err: + BNX2X_ERR("QDTOR[%d:%d] error: cmd %d, rc %d\n", + vf->abs_vfid, qdtor->qid, q_params->cmd, vfop->rc); +op_done: + case BNX2X_VFOP_QDTOR_DONE: + /* invalidate the context */ + qdtor->cxt->ustorm_ag_context.cdu_usage = 0; + qdtor->cxt->xstorm_ag_context.cdu_reserved = 0; + bnx2x_vfop_end(bp, vf, vfop); + return; + default: + bnx2x_vfop_default(state); + } +op_pending: + return; +} + +static int bnx2x_vfop_qdtor_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + + if (vfop) { + struct bnx2x_queue_state_params *qstate = + &vf->op_params.qctor.qstate; + + memset(qstate, 0, sizeof(*qstate)); + qstate->q_obj = &bnx2x_vfq(vf, qid, sp_obj); + + vfop->args.qdtor.qid = qid; + vfop->args.qdtor.cxt = bnx2x_vfq(vf, qid, cxt); + + bnx2x_vfop_opset(BNX2X_VFOP_QDTOR_HALT, + bnx2x_vfop_qdtor, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_qdtor, + cmd->block); + } + DP(BNX2X_MSG_IOV, "VF[%d] failed to add a vfop. rc %d\n", + vf->abs_vfid, vfop->rc); + return -ENOMEM; +} + static void __devinit bnx2x_vf_set_igu_info(struct bnx2x *bp, u8 igu_sb_id, u8 abs_vfid) { @@ -592,6 +703,44 @@ bnx2x_vfop_mac_prep_ramrod(struct bnx2x_vlan_mac_ramrod_params *ramrod, set_bit(BNX2X_ETH_MAC, &ramrod->user_req.vlan_mac_flags); } +static int bnx2x_vfop_mac_delall_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid, bool drv_only) +{ + + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + struct bnx2x_vfop_args_filters filters = { + .multi_filter = NULL, /* single */ + .credit = NULL, /* consume credit */ + }; + struct bnx2x_vfop_vlan_mac_flags flags = { + .drv_only = drv_only, + .dont_consume = (filters.credit != NULL), + .single_cmd = true, + .add = false /* don't care */, + }; + 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 */ + vfop->args.filters = filters; + + bnx2x_vfop_opset(BNX2X_VFOP_VLAN_MAC_CLEAR, + bnx2x_vfop_vlan_mac, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_vlan_mac, + cmd->block); + } + return -ENOMEM; +} int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vfop_cmd *cmd, @@ -674,6 +823,44 @@ int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp, return -ENOMEM; } +static int bnx2x_vfop_vlan_delall_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid, bool drv_only) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + struct bnx2x_vfop_args_filters filters = { + .multi_filter = NULL, /* single command */ + .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 = true, + .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 */ + vfop->args.filters = filters; + + bnx2x_vfop_opset(BNX2X_VFOP_VLAN_MAC_CLEAR, + bnx2x_vfop_vlan_mac, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_vlan_mac, + cmd->block); + } + return -ENOMEM; +} + int bnx2x_vfop_vlan_list_cmd(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vfop_cmd *cmd, @@ -958,6 +1145,87 @@ int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp, } +/* VFOP queue tear-down ('drop all' rx-mode, clear vlans, clear macs, + * queue destructor) + */ +static void bnx2x_vfop_qdown(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf); + int qid = vfop->args.qx.qid; + enum bnx2x_vfop_qteardown_state state = vfop->state; + struct bnx2x_vfop_cmd cmd; + + if (vfop->rc < 0) + goto op_err; + + DP(BNX2X_MSG_IOV, "vf[%d] STATE: %d\n", vf->abs_vfid, state); + + cmd.done = bnx2x_vfop_qdown; + cmd.block = false; + + switch (state) { + case BNX2X_VFOP_QTEARDOWN_RXMODE: + /* Drop all */ + vfop->state = BNX2X_VFOP_QTEARDOWN_CLR_VLAN; + vfop->rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd, qid, 0); + if (vfop->rc) + goto op_err; + return; + + case BNX2X_VFOP_QTEARDOWN_CLR_VLAN: + /* vlan-clear-all: don't consume credit */ + vfop->state = BNX2X_VFOP_QTEARDOWN_CLR_MAC; + vfop->rc = bnx2x_vfop_vlan_delall_cmd(bp, vf, &cmd, qid, false); + if (vfop->rc) + goto op_err; + return; + + case BNX2X_VFOP_QTEARDOWN_CLR_MAC: + /* mac-clear-all: consume credit */ + vfop->state = BNX2X_VFOP_QTEARDOWN_QDTOR; + vfop->rc = bnx2x_vfop_mac_delall_cmd(bp, vf, &cmd, qid, false); + if (vfop->rc) + goto op_err; + return; + + case BNX2X_VFOP_QTEARDOWN_QDTOR: + /* run the queue destruction flow */ + DP(BNX2X_MSG_IOV, "case: BNX2X_VFOP_QTEARDOWN_QDTOR\n"); + vfop->state = BNX2X_VFOP_QTEARDOWN_DONE; + DP(BNX2X_MSG_IOV, "new state: BNX2X_VFOP_QTEARDOWN_DONE\n"); + vfop->rc = bnx2x_vfop_qdtor_cmd(bp, vf, &cmd, qid); + DP(BNX2X_MSG_IOV, "returned from cmd"); + if (vfop->rc) + goto op_err; + return; +op_err: + BNX2X_ERR("QTEARDOWN[%d:%d] error: rc %d\n", + vf->abs_vfid, qid, vfop->rc); + + case BNX2X_VFOP_QTEARDOWN_DONE: + bnx2x_vfop_end(bp, vf, vfop); + return; + default: + bnx2x_vfop_default(state); + } +} + +int bnx2x_vfop_qdown_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + + if (vfop) { + vfop->args.qx.qid = qid; + bnx2x_vfop_opset(BNX2X_VFOP_QTEARDOWN_RXMODE, + bnx2x_vfop_qdown, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_qdown, + cmd->block); + } + return -ENOMEM; +} /* VF enable primitives * * when pretend is required the caller is responsible diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index a18cef6..4a79741 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -645,6 +645,11 @@ int bnx2x_vfop_qsetup_cmd(struct bnx2x *bp, struct bnx2x_vfop_cmd *cmd, int qid); +int bnx2x_vfop_qdown_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd, + int qid); + int bnx2x_vfop_mcast_cmd(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vfop_cmd *cmd, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 8dddb02..832aa31 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -794,6 +794,23 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp, response: bnx2x_vf_mbx_resp(bp, vf); } +static void bnx2x_vf_mbx_teardown_q(struct bnx2x *bp, struct bnx2x_virtf *vf, + struct bnx2x_vf_mbx *mbx) +{ + int qid = mbx->msg->req.q_op.vf_qid; + struct bnx2x_vfop_cmd cmd = { + .done = bnx2x_vf_mbx_resp, + .block = false, + }; + + DP(BNX2X_MSG_IOV, "VF[%d] Q_TEARDOWN: vf_qid=%d\n", + vf->abs_vfid, qid); + + vf->op_rc = bnx2x_vfop_qdown_cmd(bp, vf, &cmd, qid); + if (vf->op_rc) + bnx2x_vf_mbx_resp(bp, vf); +} + /* dispatch request */ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vf_mbx *mbx) @@ -822,6 +839,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, case CHANNEL_TLV_SET_Q_FILTERS: bnx2x_vf_mbx_set_q_filters(bp, vf, mbx); break; + case CHANNEL_TLV_TEARDOWN_Q: + bnx2x_vf_mbx_teardown_q(bp, vf, mbx); + break; } /* unknown TLV - this may belong to a VF driver from the future - a