diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 123 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 25 | ||||
-rw-r--r-- | 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 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: */ | ||
1426 | static 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 */ |
1426 | void bnx2x_iov_init_dq(struct bnx2x *bp) | 1434 | void 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 */ | ||
1959 | int 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 */ |
1951 | int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line) | 1974 | int 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 | */ | ||
2596 | static 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 | } | ||
2636 | op_err: | ||
2637 | BNX2X_ERR("VF[%d] RELEASE error: rc %d\n", vf->abs_vfid, vfop->rc); | ||
2638 | op_done: | ||
2639 | bnx2x_vfop_end(bp, vf, vfop); | ||
2640 | } | ||
2641 | |||
2642 | int 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 | */ | ||
2660 | void 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 | |||
2676 | static 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 | |||
2682 | static 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 | |||
2569 | void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, | 2692 | void 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 | ||
54 | struct 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) */ |
55 | struct bnx2x_vf_queue { | 60 | struct 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); | |||
429 | void bnx2x_iov_free_mem(struct bnx2x *bp); | 434 | void bnx2x_iov_free_mem(struct bnx2x *bp); |
430 | int bnx2x_iov_alloc_mem(struct bnx2x *bp); | 435 | int bnx2x_iov_alloc_mem(struct bnx2x *bp); |
431 | int bnx2x_iov_nic_init(struct bnx2x *bp); | 436 | int bnx2x_iov_nic_init(struct bnx2x *bp); |
437 | int bnx2x_iov_chip_cleanup(struct bnx2x *bp); | ||
432 | void bnx2x_iov_init_dq(struct bnx2x *bp); | 438 | void bnx2x_iov_init_dq(struct bnx2x *bp); |
433 | void bnx2x_iov_init_dmae(struct bnx2x *bp); | 439 | void bnx2x_iov_init_dmae(struct bnx2x *bp); |
434 | void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid, | 440 | 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, | |||
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 | ||
675 | int 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 | */ | ||
684 | void bnx2x_vf_release(struct bnx2x *bp, struct bnx2x_virtf *vf, bool block); | ||
664 | int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); | 685 | int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); |
665 | u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf); | 686 | u8 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 | |||
262 | mbx_error: | ||
263 | bnx2x_vf_release(bp, vf, false); /* non blocking */ | ||
260 | } | 264 | } |
261 | 265 | ||
262 | static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, | 266 | 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, | |||
819 | bnx2x_vf_mbx_resp(bp, vf); | 823 | bnx2x_vf_mbx_resp(bp, vf); |
820 | } | 824 | } |
821 | 825 | ||
826 | static 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 */ |
823 | static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, | 842 | static 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 | ||
944 | mbx_error: | 966 | mbx_error: |
967 | bnx2x_vf_release(bp, vf, false); /* non blocking */ | ||
945 | mbx_done: | 968 | mbx_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 | }; |