aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:41 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:07 -0500
commitf1929b016c2161c364e45c21788aaae938ae557c (patch)
tree040f0a388de8572f298e163b7859268a25748931 /drivers/net/ethernet/broadcom
parent99e9d211a40cdd12bda7f50c2014c2fbb8f386f5 (diff)
bnx2x: Support of PF driver of a VF release request
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 <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')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c123
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h21
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c25
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h1
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 6f21a095fab7..249ba704d471 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)
8626 8626
8627 netif_addr_unlock_bh(bp->dev); 8627 netif_addr_unlock_bh(bp->dev);
8628 8628
8629 bnx2x_iov_chip_cleanup(bp);
8629 8630
8630 8631
8631 /* 8632 /*
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 3dd3a6acdf57..71d0976b14d8 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)
1422 /* num_sbs already set */ 1422 /* num_sbs already set */
1423} 1423}
1424 1424
1425/* FLR routines: */
1426static void bnx2x_vf_free_resc(struct bnx2x *bp, struct bnx2x_virtf *vf)
1427{
1428 /* reset the state variables */
1429 bnx2x_iov_static_resc(bp, &vf->alloc_resc);
1430 vf->state = VF_FREE;
1431}
1432
1425/* IOV global initialization routines */ 1433/* IOV global initialization routines */
1426void bnx2x_iov_init_dq(struct bnx2x *bp) 1434void bnx2x_iov_init_dq(struct bnx2x *bp)
1427{ 1435{
@@ -1947,6 +1955,21 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
1947 return 0; 1955 return 0;
1948} 1956}
1949 1957
1958/* called by bnx2x_chip_cleanup */
1959int bnx2x_iov_chip_cleanup(struct bnx2x *bp)
1960{
1961 int i;
1962
1963 if (!IS_SRIOV(bp))
1964 return 0;
1965
1966 /* release all the VFs */
1967 for_each_vf(bp, i)
1968 bnx2x_vf_release(bp, BP_VF(bp, i), true); /* blocking */
1969
1970 return 0;
1971}
1972
1950/* called by bnx2x_init_hw_func, returns the next ilt line */ 1973/* called by bnx2x_init_hw_func, returns the next ilt line */
1951int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line) 1974int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line)
1952{ 1975{
@@ -2566,6 +2589,106 @@ int bnx2x_vfop_close_cmd(struct bnx2x *bp,
2566 return -ENOMEM; 2589 return -ENOMEM;
2567} 2590}
2568 2591
2592/* VF release can be called either: 1. the VF was acquired but
2593 * not enabled 2. the vf was enabled or in the process of being
2594 * enabled
2595 */
2596static void bnx2x_vfop_release(struct bnx2x *bp, struct bnx2x_virtf *vf)
2597{
2598 struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf);
2599 struct bnx2x_vfop_cmd cmd = {
2600 .done = bnx2x_vfop_release,
2601 .block = false,
2602 };
2603
2604 DP(BNX2X_MSG_IOV, "vfop->rc %d\n", vfop->rc);
2605
2606 if (vfop->rc < 0)
2607 goto op_err;
2608
2609 DP(BNX2X_MSG_IOV, "VF[%d] STATE: %s\n", vf->abs_vfid,
2610 vf->state == VF_FREE ? "Free" :
2611 vf->state == VF_ACQUIRED ? "Acquired" :
2612 vf->state == VF_ENABLED ? "Enabled" :
2613 vf->state == VF_RESET ? "Reset" :
2614 "Unknown");
2615
2616 switch (vf->state) {
2617 case VF_ENABLED:
2618 vfop->rc = bnx2x_vfop_close_cmd(bp, vf, &cmd);
2619 if (vfop->rc)
2620 goto op_err;
2621 return;
2622
2623 case VF_ACQUIRED:
2624 DP(BNX2X_MSG_IOV, "about to free resources\n");
2625 bnx2x_vf_free_resc(bp, vf);
2626 DP(BNX2X_MSG_IOV, "vfop->rc %d\n", vfop->rc);
2627 goto op_done;
2628
2629 case VF_FREE:
2630 case VF_RESET:
2631 /* do nothing */
2632 goto op_done;
2633 default:
2634 bnx2x_vfop_default(vf->state);
2635 }
2636op_err:
2637 BNX2X_ERR("VF[%d] RELEASE error: rc %d\n", vf->abs_vfid, vfop->rc);
2638op_done:
2639 bnx2x_vfop_end(bp, vf, vfop);
2640}
2641
2642int bnx2x_vfop_release_cmd(struct bnx2x *bp,
2643 struct bnx2x_virtf *vf,
2644 struct bnx2x_vfop_cmd *cmd)
2645{
2646 struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
2647 if (vfop) {
2648 bnx2x_vfop_opset(-1, /* use vf->state */
2649 bnx2x_vfop_release, cmd->done);
2650 return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_release,
2651 cmd->block);
2652 }
2653 return -ENOMEM;
2654}
2655
2656/* VF release ~ VF close + VF release-resources
2657 * Release is the ultimate SW shutdown and is called whenever an
2658 * irrecoverable error is encountered.
2659 */
2660void bnx2x_vf_release(struct bnx2x *bp, struct bnx2x_virtf *vf, bool block)
2661{
2662 struct bnx2x_vfop_cmd cmd = {
2663 .done = NULL,
2664 .block = block,
2665 };
2666 int rc;
2667 bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_RELEASE_VF);
2668
2669 rc = bnx2x_vfop_release_cmd(bp, vf, &cmd);
2670 if (rc)
2671 WARN(rc,
2672 "VF[%d] Failed to allocate resources for release op- rc=%d\n",
2673 vf->abs_vfid, rc);
2674}
2675
2676static inline void bnx2x_vf_get_sbdf(struct bnx2x *bp,
2677 struct bnx2x_virtf *vf, u32 *sbdf)
2678{
2679 *sbdf = vf->devfn | (vf->bus << 8);
2680}
2681
2682static inline void bnx2x_vf_get_bars(struct bnx2x *bp, struct bnx2x_virtf *vf,
2683 struct bnx2x_vf_bar_info *bar_info)
2684{
2685 int n;
2686
2687 bar_info->nr_bars = bp->vfdb->sriov.nres;
2688 for (n = 0; n < bar_info->nr_bars; n++)
2689 bar_info->bars[n] = vf->bars[n];
2690}
2691
2569void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, 2692void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
2570 enum channel_tlvs tlv) 2693 enum channel_tlvs tlv)
2571{ 2694{
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index d2a65d66c325..a09db28f76c2 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 {
51 u32 size; 51 u32 size;
52}; 52};
53 53
54struct bnx2x_vf_bar_info {
55 struct bnx2x_vf_bar bars[PCI_SRIOV_NUM_BARS];
56 u8 nr_bars;
57};
58
54/* vf queue (used both for rx or tx) */ 59/* vf queue (used both for rx or tx) */
55struct bnx2x_vf_queue { 60struct bnx2x_vf_queue {
56 struct eth_context *cxt; 61 struct eth_context *cxt;
@@ -429,6 +434,7 @@ void bnx2x_iov_remove_one(struct bnx2x *bp);
429void bnx2x_iov_free_mem(struct bnx2x *bp); 434void bnx2x_iov_free_mem(struct bnx2x *bp);
430int bnx2x_iov_alloc_mem(struct bnx2x *bp); 435int bnx2x_iov_alloc_mem(struct bnx2x *bp);
431int bnx2x_iov_nic_init(struct bnx2x *bp); 436int bnx2x_iov_nic_init(struct bnx2x *bp);
437int bnx2x_iov_chip_cleanup(struct bnx2x *bp);
432void bnx2x_iov_init_dq(struct bnx2x *bp); 438void bnx2x_iov_init_dq(struct bnx2x *bp);
433void bnx2x_iov_init_dmae(struct bnx2x *bp); 439void bnx2x_iov_init_dmae(struct bnx2x *bp);
434void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid, 440void 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,
546 if (vfop->done) { 552 if (vfop->done) {
547 DP(BNX2X_MSG_IOV, "calling done handler\n"); 553 DP(BNX2X_MSG_IOV, "calling done handler\n");
548 vfop->done(bp, vf); 554 vfop->done(bp, vf);
555 } else {
556 /* there is no done handler for the operation to unlock
557 * the mutex. Must have gotten here from PF initiated VF RELEASE
558 */
559 bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_RELEASE_VF);
549 } 560 }
550 561
551 DP(BNX2X_MSG_IOV, "done handler complete. vf->op_rc %d, vfop->rc %d\n", 562 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,
661 struct bnx2x_virtf *vf, 672 struct bnx2x_virtf *vf,
662 struct bnx2x_vfop_cmd *cmd); 673 struct bnx2x_vfop_cmd *cmd);
663 674
675int bnx2x_vfop_release_cmd(struct bnx2x *bp,
676 struct bnx2x_virtf *vf,
677 struct bnx2x_vfop_cmd *cmd);
678
679/* VF release ~ VF close + VF release-resources
680 *
681 * Release is the ultimate SW shutdown and is called whenever an
682 * irrecoverable error is encountered.
683 */
684void bnx2x_vf_release(struct bnx2x *bp, struct bnx2x_virtf *vf, bool block);
664int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); 685int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid);
665u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf); 686u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf);
666/* VF FLR helpers */ 687/* VF FLR helpers */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 73368aa28e26..ba8b95d016b0 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)
228 if (rc) { 228 if (rc) {
229 BNX2X_ERR("Failed to copy response body to VF %d\n", 229 BNX2X_ERR("Failed to copy response body to VF %d\n",
230 vf->abs_vfid); 230 vf->abs_vfid);
231 return; 231 goto mbx_error;
232 } 232 }
233 vf_addr -= sizeof(u64); 233 vf_addr -= sizeof(u64);
234 pf_addr -= sizeof(u64); 234 pf_addr -= sizeof(u64);
@@ -255,8 +255,12 @@ static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
255 if (rc) { 255 if (rc) {
256 BNX2X_ERR("Failed to copy response status to VF %d\n", 256 BNX2X_ERR("Failed to copy response status to VF %d\n",
257 vf->abs_vfid); 257 vf->abs_vfid);
258 goto mbx_error;
258 } 259 }
259 return; 260 return;
261
262mbx_error:
263 bnx2x_vf_release(bp, vf, false); /* non blocking */
260} 264}
261 265
262static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, 266static 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,
819 bnx2x_vf_mbx_resp(bp, vf); 823 bnx2x_vf_mbx_resp(bp, vf);
820} 824}
821 825
826static void bnx2x_vf_mbx_release_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
827 struct bnx2x_vf_mbx *mbx)
828{
829 struct bnx2x_vfop_cmd cmd = {
830 .done = bnx2x_vf_mbx_resp,
831 .block = false,
832 };
833
834 DP(BNX2X_MSG_IOV, "VF[%d] VF_RELEASE\n", vf->abs_vfid);
835
836 vf->op_rc = bnx2x_vfop_release_cmd(bp, vf, &cmd);
837 if (vf->op_rc)
838 bnx2x_vf_mbx_resp(bp, vf);
839}
840
822/* dispatch request */ 841/* dispatch request */
823static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, 842static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
824 struct bnx2x_vf_mbx *mbx) 843 struct bnx2x_vf_mbx *mbx)
@@ -852,6 +871,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
852 case CHANNEL_TLV_CLOSE: 871 case CHANNEL_TLV_CLOSE:
853 bnx2x_vf_mbx_close_vf(bp, vf, mbx); 872 bnx2x_vf_mbx_close_vf(bp, vf, mbx);
854 break; 873 break;
874 case CHANNEL_TLV_RELEASE:
875 bnx2x_vf_mbx_release_vf(bp, vf, mbx);
876 break;
855 } 877 }
856 878
857 } else { 879 } else {
@@ -942,6 +964,7 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event)
942 goto mbx_done; 964 goto mbx_done;
943 965
944mbx_error: 966mbx_error:
967 bnx2x_vf_release(bp, vf, false); /* non blocking */
945mbx_done: 968mbx_done:
946 return; 969 return;
947} 970}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index bf11e084c215..6278a9ed4639 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 {
310 CHANNEL_TLV_TEARDOWN_Q, 310 CHANNEL_TLV_TEARDOWN_Q,
311 CHANNEL_TLV_CLOSE, 311 CHANNEL_TLV_CLOSE,
312 CHANNEL_TLV_RELEASE, 312 CHANNEL_TLV_RELEASE,
313 CHANNEL_TLV_PF_RELEASE_VF,
313 CHANNEL_TLV_LIST_END, 314 CHANNEL_TLV_LIST_END,
314 CHANNEL_TLV_MAX 315 CHANNEL_TLV_MAX
315}; 316};