aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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};