From patchwork Tue Jan 1 15:22:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Elior X-Patchwork-Id: 208948 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 1FB4C2C00A6 for ; Wed, 2 Jan 2013 02:21:07 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752491Ab3AAPUu (ORCPT ); Tue, 1 Jan 2013 10:20:50 -0500 Received: from mms1.broadcom.com ([216.31.210.17]:4568 "EHLO mms1.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752463Ab3AAPUc (ORCPT ); Tue, 1 Jan 2013 10:20:32 -0500 Received: from [10.9.200.133] by mms1.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.5)); Tue, 01 Jan 2013 07:18:26 -0800 X-Server-Uuid: 06151B78-6688-425E-9DE2-57CB27892261 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; Tue, 1 Jan 2013 07:20:11 -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 8333A40FF2; Tue, 1 Jan 2013 07:20:21 -0800 (PST) From: "Ariel Elior" To: "David Miller" cc: netdev , eilong@broadcom.com, "Ariel Elior" Subject: [PATCH net-next v5 19/22] bnx2x: Support of PF driver of a VF release request Date: Tue, 1 Jan 2013 17:22:41 +0200 Message-ID: <1357053764-8187-20-git-send-email-ariele@broadcom.com> X-Mailer: git-send-email 1.7.9.GIT In-Reply-To: <1357053764-8187-1-git-send-email-ariele@broadcom.com> References: <1357053764-8187-1-git-send-email-ariele@broadcom.com> MIME-Version: 1.0 X-WSS-ID: 7CFC21C81ZK8083371-01-01 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The 'release' request is the opposite of the 'acquire' request. At release, all the resources allocated to the VF are reclaimed. The release flow applies the close flow if applicable. Note that there are actually two types of release: 1. The VF has been removed, and so issued a 'release' request over the VF <-> PF Channel. 2. The PF is going down and so has to release all of it's VFs. Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 123 +++++++++++++++++++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 21 ++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 25 ++++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 1 + 5 files changed, 170 insertions(+), 1 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6f21a09..249ba70 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8626,6 +8626,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link) netif_addr_unlock_bh(bp->dev); + bnx2x_iov_chip_cleanup(bp); /* diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 3dd3a6a..71d0976 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1422,6 +1422,14 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct vf_pf_resc_request *resc) /* num_sbs already set */ } +/* FLR routines: */ +static void bnx2x_vf_free_resc(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + /* reset the state variables */ + bnx2x_iov_static_resc(bp, &vf->alloc_resc); + vf->state = VF_FREE; +} + /* IOV global initialization routines */ void bnx2x_iov_init_dq(struct bnx2x *bp) { @@ -1947,6 +1955,21 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) return 0; } +/* called by bnx2x_chip_cleanup */ +int bnx2x_iov_chip_cleanup(struct bnx2x *bp) +{ + int i; + + if (!IS_SRIOV(bp)) + return 0; + + /* release all the VFs */ + for_each_vf(bp, i) + bnx2x_vf_release(bp, BP_VF(bp, i), true); /* blocking */ + + return 0; +} + /* called by bnx2x_init_hw_func, returns the next ilt line */ int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line) { @@ -2566,6 +2589,106 @@ int bnx2x_vfop_close_cmd(struct bnx2x *bp, return -ENOMEM; } +/* VF release can be called either: 1. the VF was acquired but + * not enabled 2. the vf was enabled or in the process of being + * enabled + */ +static void bnx2x_vfop_release(struct bnx2x *bp, struct bnx2x_virtf *vf) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf); + struct bnx2x_vfop_cmd cmd = { + .done = bnx2x_vfop_release, + .block = false, + }; + + DP(BNX2X_MSG_IOV, "vfop->rc %d\n", vfop->rc); + + if (vfop->rc < 0) + goto op_err; + + DP(BNX2X_MSG_IOV, "VF[%d] STATE: %s\n", vf->abs_vfid, + vf->state == VF_FREE ? "Free" : + vf->state == VF_ACQUIRED ? "Acquired" : + vf->state == VF_ENABLED ? "Enabled" : + vf->state == VF_RESET ? "Reset" : + "Unknown"); + + switch (vf->state) { + case VF_ENABLED: + vfop->rc = bnx2x_vfop_close_cmd(bp, vf, &cmd); + if (vfop->rc) + goto op_err; + return; + + case VF_ACQUIRED: + DP(BNX2X_MSG_IOV, "about to free resources\n"); + bnx2x_vf_free_resc(bp, vf); + DP(BNX2X_MSG_IOV, "vfop->rc %d\n", vfop->rc); + goto op_done; + + case VF_FREE: + case VF_RESET: + /* do nothing */ + goto op_done; + default: + bnx2x_vfop_default(vf->state); + } +op_err: + BNX2X_ERR("VF[%d] RELEASE error: rc %d\n", vf->abs_vfid, vfop->rc); +op_done: + bnx2x_vfop_end(bp, vf, vfop); +} + +int bnx2x_vfop_release_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd) +{ + struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf); + if (vfop) { + bnx2x_vfop_opset(-1, /* use vf->state */ + bnx2x_vfop_release, cmd->done); + return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_release, + cmd->block); + } + return -ENOMEM; +} + +/* VF release ~ VF close + VF release-resources + * Release is the ultimate SW shutdown and is called whenever an + * irrecoverable error is encountered. + */ +void bnx2x_vf_release(struct bnx2x *bp, struct bnx2x_virtf *vf, bool block) +{ + struct bnx2x_vfop_cmd cmd = { + .done = NULL, + .block = block, + }; + int rc; + bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_RELEASE_VF); + + rc = bnx2x_vfop_release_cmd(bp, vf, &cmd); + if (rc) + WARN(rc, + "VF[%d] Failed to allocate resources for release op- rc=%d\n", + vf->abs_vfid, rc); +} + +static inline void bnx2x_vf_get_sbdf(struct bnx2x *bp, + struct bnx2x_virtf *vf, u32 *sbdf) +{ + *sbdf = vf->devfn | (vf->bus << 8); +} + +static inline void bnx2x_vf_get_bars(struct bnx2x *bp, struct bnx2x_virtf *vf, + struct bnx2x_vf_bar_info *bar_info) +{ + int n; + + bar_info->nr_bars = bp->vfdb->sriov.nres; + for (n = 0; n < bar_info->nr_bars; n++) + bar_info->bars[n] = vf->bars[n]; +} + void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, enum channel_tlvs tlv) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index d2a65d6..a09db28 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -51,6 +51,11 @@ struct bnx2x_vf_bar { u32 size; }; +struct bnx2x_vf_bar_info { + struct bnx2x_vf_bar bars[PCI_SRIOV_NUM_BARS]; + u8 nr_bars; +}; + /* vf queue (used both for rx or tx) */ struct bnx2x_vf_queue { struct eth_context *cxt; @@ -429,6 +434,7 @@ void bnx2x_iov_remove_one(struct bnx2x *bp); void bnx2x_iov_free_mem(struct bnx2x *bp); int bnx2x_iov_alloc_mem(struct bnx2x *bp); int bnx2x_iov_nic_init(struct bnx2x *bp); +int bnx2x_iov_chip_cleanup(struct bnx2x *bp); void bnx2x_iov_init_dq(struct bnx2x *bp); void bnx2x_iov_init_dmae(struct bnx2x *bp); void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid, @@ -546,6 +552,11 @@ static inline void bnx2x_vfop_end(struct bnx2x *bp, struct bnx2x_virtf *vf, if (vfop->done) { DP(BNX2X_MSG_IOV, "calling done handler\n"); vfop->done(bp, vf); + } else { + /* there is no done handler for the operation to unlock + * the mutex. Must have gotten here from PF initiated VF RELEASE + */ + bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_RELEASE_VF); } DP(BNX2X_MSG_IOV, "done handler complete. vf->op_rc %d, vfop->rc %d\n", @@ -661,6 +672,16 @@ int bnx2x_vfop_close_cmd(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vfop_cmd *cmd); +int bnx2x_vfop_release_cmd(struct bnx2x *bp, + struct bnx2x_virtf *vf, + struct bnx2x_vfop_cmd *cmd); + +/* VF release ~ VF close + VF release-resources + * + * Release is the ultimate SW shutdown and is called whenever an + * irrecoverable error is encountered. + */ +void bnx2x_vf_release(struct bnx2x *bp, struct bnx2x_virtf *vf, bool block); int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf); /* VF FLR helpers */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 73368aa..ba8b95d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -228,7 +228,7 @@ static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf) if (rc) { BNX2X_ERR("Failed to copy response body to VF %d\n", vf->abs_vfid); - return; + goto mbx_error; } vf_addr -= sizeof(u64); pf_addr -= sizeof(u64); @@ -255,8 +255,12 @@ static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf) if (rc) { BNX2X_ERR("Failed to copy response status to VF %d\n", vf->abs_vfid); + goto mbx_error; } return; + +mbx_error: + bnx2x_vf_release(bp, vf, false); /* non blocking */ } static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, @@ -819,6 +823,21 @@ static void bnx2x_vf_mbx_close_vf(struct bnx2x *bp, struct bnx2x_virtf *vf, bnx2x_vf_mbx_resp(bp, vf); } +static void bnx2x_vf_mbx_release_vf(struct bnx2x *bp, struct bnx2x_virtf *vf, + struct bnx2x_vf_mbx *mbx) +{ + struct bnx2x_vfop_cmd cmd = { + .done = bnx2x_vf_mbx_resp, + .block = false, + }; + + DP(BNX2X_MSG_IOV, "VF[%d] VF_RELEASE\n", vf->abs_vfid); + + vf->op_rc = bnx2x_vfop_release_cmd(bp, vf, &cmd); + 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) @@ -852,6 +871,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, case CHANNEL_TLV_CLOSE: bnx2x_vf_mbx_close_vf(bp, vf, mbx); break; + case CHANNEL_TLV_RELEASE: + bnx2x_vf_mbx_release_vf(bp, vf, mbx); + break; } } else { @@ -942,6 +964,7 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event) goto mbx_done; mbx_error: + bnx2x_vf_release(bp, vf, false); /* non blocking */ mbx_done: return; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index bf11e08..6278a9e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h @@ -310,6 +310,7 @@ enum channel_tlvs { CHANNEL_TLV_TEARDOWN_Q, CHANNEL_TLV_CLOSE, CHANNEL_TLV_RELEASE, + CHANNEL_TLV_PF_RELEASE_VF, CHANNEL_TLV_LIST_END, CHANNEL_TLV_MAX };