diff options
author | Ariel Elior <ariele@broadcom.com> | 2013-03-11 01:17:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-12 07:54:23 -0400 |
commit | 3c76feff68559bf9ec08d4d86abe57bc56a9847a (patch) | |
tree | af826ebde6b7f036fc916739cf87a47b5518446d /drivers/net/ethernet/broadcom | |
parent | 3ec9f9ca79757c54b12f87e51a6664ba1e597b17 (diff) |
bnx2x: Control number of vfs dynamically
1. Support sysfs interface for getting the maximal number of virtual functions
of a given physical function.
2. Support sysfs interface for getting and setting the current number of
virtual functions.
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@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.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 87 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 10 |
4 files changed, 91 insertions, 44 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index d62d037b2928..33fbdfdc8e12 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -1281,6 +1281,8 @@ struct bnx2x { | |||
1281 | dma_addr_t pf2vf_bulletin_mapping; | 1281 | dma_addr_t pf2vf_bulletin_mapping; |
1282 | 1282 | ||
1283 | struct pf_vf_bulletin_content old_bulletin; | 1283 | struct pf_vf_bulletin_content old_bulletin; |
1284 | |||
1285 | u16 requested_nr_virtfn; | ||
1284 | #endif /* CONFIG_BNX2X_SRIOV */ | 1286 | #endif /* CONFIG_BNX2X_SRIOV */ |
1285 | 1287 | ||
1286 | struct net_device *dev; | 1288 | struct net_device *dev; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 9be9b0373ca9..f685d2e77fcb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -9546,8 +9546,10 @@ sp_rtnl_not_reset: | |||
9546 | 9546 | ||
9547 | /* enable SR-IOV if applicable */ | 9547 | /* enable SR-IOV if applicable */ |
9548 | if (IS_SRIOV(bp) && test_and_clear_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, | 9548 | if (IS_SRIOV(bp) && test_and_clear_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, |
9549 | &bp->sp_rtnl_state)) | 9549 | &bp->sp_rtnl_state)) { |
9550 | bnx2x_disable_sriov(bp); | ||
9550 | bnx2x_enable_sriov(bp); | 9551 | bnx2x_enable_sriov(bp); |
9552 | } | ||
9551 | } | 9553 | } |
9552 | 9554 | ||
9553 | static void bnx2x_period_task(struct work_struct *work) | 9555 | static void bnx2x_period_task(struct work_struct *work) |
@@ -11423,26 +11425,6 @@ static int bnx2x_init_bp(struct bnx2x *bp) | |||
11423 | * net_device service functions | 11425 | * net_device service functions |
11424 | */ | 11426 | */ |
11425 | 11427 | ||
11426 | static int bnx2x_open_epilog(struct bnx2x *bp) | ||
11427 | { | ||
11428 | /* Enable sriov via delayed work. This must be done via delayed work | ||
11429 | * because it causes the probe of the vf devices to be run, which invoke | ||
11430 | * register_netdevice which must have rtnl lock taken. As we are holding | ||
11431 | * the lock right now, that could only work if the probe would not take | ||
11432 | * the lock. However, as the probe of the vf may be called from other | ||
11433 | * contexts as well (such as passthrough to vm failes) it can't assume | ||
11434 | * the lock is being held for it. Using delayed work here allows the | ||
11435 | * probe code to simply take the lock (i.e. wait for it to be released | ||
11436 | * if it is being held). | ||
11437 | */ | ||
11438 | smp_mb__before_clear_bit(); | ||
11439 | set_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, &bp->sp_rtnl_state); | ||
11440 | smp_mb__after_clear_bit(); | ||
11441 | schedule_delayed_work(&bp->sp_rtnl_task, 0); | ||
11442 | |||
11443 | return 0; | ||
11444 | } | ||
11445 | |||
11446 | /* called with rtnl_lock */ | 11428 | /* called with rtnl_lock */ |
11447 | static int bnx2x_open(struct net_device *dev) | 11429 | static int bnx2x_open(struct net_device *dev) |
11448 | { | 11430 | { |
@@ -12498,13 +12480,8 @@ static int bnx2x_init_one(struct pci_dev *pdev, | |||
12498 | goto init_one_exit; | 12480 | goto init_one_exit; |
12499 | } | 12481 | } |
12500 | 12482 | ||
12501 | /* Enable SRIOV if capability found in configuration space. | 12483 | /* Enable SRIOV if capability found in configuration space */ |
12502 | * Once the generic SR-IOV framework makes it in from the | 12484 | rc = bnx2x_iov_init_one(bp, int_mode, BNX2X_MAX_NUM_OF_VFS); |
12503 | * pci tree this will be revised, to allow dynamic control | ||
12504 | * over the number of VFs. Right now, change the num of vfs | ||
12505 | * param below to enable SR-IOV. | ||
12506 | */ | ||
12507 | rc = bnx2x_iov_init_one(bp, int_mode, 0/*num vfs*/); | ||
12508 | if (rc) | 12485 | if (rc) |
12509 | goto init_one_exit; | 12486 | goto init_one_exit; |
12510 | 12487 | ||
@@ -12820,6 +12797,9 @@ static struct pci_driver bnx2x_pci_driver = { | |||
12820 | .suspend = bnx2x_suspend, | 12797 | .suspend = bnx2x_suspend, |
12821 | .resume = bnx2x_resume, | 12798 | .resume = bnx2x_resume, |
12822 | .err_handler = &bnx2x_err_handler, | 12799 | .err_handler = &bnx2x_err_handler, |
12800 | #ifdef CONFIG_BNX2X_SRIOV | ||
12801 | .sriov_configure = bnx2x_sriov_configure, | ||
12802 | #endif | ||
12823 | }; | 12803 | }; |
12824 | 12804 | ||
12825 | static int __init bnx2x_init(void) | 12805 | static int __init bnx2x_init(void) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 7b234e41fea8..df930e30e1b1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
@@ -1467,7 +1467,6 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) | |||
1467 | return bnx2x_is_pcie_pending(dev); | 1467 | return bnx2x_is_pcie_pending(dev); |
1468 | 1468 | ||
1469 | unknown_dev: | 1469 | unknown_dev: |
1470 | BNX2X_ERR("Unknown device\n"); | ||
1471 | return false; | 1470 | return false; |
1472 | } | 1471 | } |
1473 | 1472 | ||
@@ -1972,8 +1971,10 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, | |||
1972 | if (iov->total == 0) | 1971 | if (iov->total == 0) |
1973 | goto failed; | 1972 | goto failed; |
1974 | 1973 | ||
1975 | /* calculate the actual number of VFs */ | 1974 | iov->nr_virtfn = min_t(u16, iov->total, num_vfs_param); |
1976 | iov->nr_virtfn = min_t(u16, iov->total, (u16)num_vfs_param); | 1975 | |
1976 | DP(BNX2X_MSG_IOV, "num_vfs_param was %d, nr_virtfn was %d\n", | ||
1977 | num_vfs_param, iov->nr_virtfn); | ||
1977 | 1978 | ||
1978 | /* allocate the vf array */ | 1979 | /* allocate the vf array */ |
1979 | bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) * | 1980 | bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) * |
@@ -3020,21 +3021,47 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, | |||
3020 | vf->op_current = CHANNEL_TLV_NONE; | 3021 | vf->op_current = CHANNEL_TLV_NONE; |
3021 | } | 3022 | } |
3022 | 3023 | ||
3023 | void bnx2x_enable_sriov(struct bnx2x *bp) | 3024 | int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param) |
3024 | { | 3025 | { |
3025 | int rc = 0; | ||
3026 | 3026 | ||
3027 | /* disbale sriov in case it is still enabled */ | 3027 | struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev)); |
3028 | pci_disable_sriov(bp->pdev); | ||
3029 | DP(BNX2X_MSG_IOV, "sriov disabled\n"); | ||
3030 | 3028 | ||
3031 | /* enable sriov */ | 3029 | DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n", |
3032 | DP(BNX2X_MSG_IOV, "vf num (%d)\n", (bp->vfdb->sriov.nr_virtfn)); | 3030 | num_vfs_param, BNX2X_NR_VIRTFN(bp)); |
3033 | rc = pci_enable_sriov(bp->pdev, (bp->vfdb->sriov.nr_virtfn)); | 3031 | |
3034 | if (rc) | 3032 | /* HW channel is only operational when PF is up */ |
3033 | if (bp->state != BNX2X_STATE_OPEN) { | ||
3034 | BNX2X_ERR("VF num configurtion via sysfs not supported while PF is down"); | ||
3035 | return -EINVAL; | ||
3036 | } | ||
3037 | |||
3038 | /* we are always bound by the total_vfs in the configuration space */ | ||
3039 | if (num_vfs_param > BNX2X_NR_VIRTFN(bp)) { | ||
3040 | BNX2X_ERR("truncating requested number of VFs (%d) down to maximum allowed (%d)\n", | ||
3041 | num_vfs_param, BNX2X_NR_VIRTFN(bp)); | ||
3042 | num_vfs_param = BNX2X_NR_VIRTFN(bp); | ||
3043 | } | ||
3044 | |||
3045 | bp->requested_nr_virtfn = num_vfs_param; | ||
3046 | if (num_vfs_param == 0) { | ||
3047 | pci_disable_sriov(dev); | ||
3048 | return 0; | ||
3049 | } else { | ||
3050 | return bnx2x_enable_sriov(bp); | ||
3051 | } | ||
3052 | } | ||
3053 | |||
3054 | int bnx2x_enable_sriov(struct bnx2x *bp) | ||
3055 | { | ||
3056 | int rc = 0, req_vfs = bp->requested_nr_virtfn; | ||
3057 | |||
3058 | rc = pci_enable_sriov(bp->pdev, req_vfs); | ||
3059 | if (rc) { | ||
3035 | BNX2X_ERR("pci_enable_sriov failed with %d\n", rc); | 3060 | BNX2X_ERR("pci_enable_sriov failed with %d\n", rc); |
3036 | else | 3061 | return rc; |
3037 | DP(BNX2X_MSG_IOV, "sriov enabled\n"); | 3062 | } |
3063 | DP(BNX2X_MSG_IOV, "sriov enabled (%d vfs)\n", req_vfs); | ||
3064 | return req_vfs; | ||
3038 | } | 3065 | } |
3039 | 3066 | ||
3040 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) | 3067 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) |
@@ -3050,6 +3077,11 @@ void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) | |||
3050 | } | 3077 | } |
3051 | } | 3078 | } |
3052 | 3079 | ||
3080 | void bnx2x_disable_sriov(struct bnx2x *bp) | ||
3081 | { | ||
3082 | pci_disable_sriov(bp->pdev); | ||
3083 | } | ||
3084 | |||
3053 | static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, | 3085 | static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, |
3054 | struct bnx2x_virtf *vf) | 3086 | struct bnx2x_virtf *vf) |
3055 | { | 3087 | { |
@@ -3087,6 +3119,10 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx, | |||
3087 | rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); | 3119 | rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); |
3088 | if (rc) | 3120 | if (rc) |
3089 | return rc; | 3121 | return rc; |
3122 | if (!mac_obj || !vlan_obj || !bulletin) { | ||
3123 | BNX2X_ERR("VF partially initialized\n"); | ||
3124 | return -EINVAL; | ||
3125 | } | ||
3090 | 3126 | ||
3091 | ivi->vf = vfidx; | 3127 | ivi->vf = vfidx; |
3092 | ivi->qos = 0; | 3128 | ivi->qos = 0; |
@@ -3405,3 +3441,26 @@ alloc_mem_err: | |||
3405 | sizeof(union pf_vf_bulletin)); | 3441 | sizeof(union pf_vf_bulletin)); |
3406 | return -ENOMEM; | 3442 | return -ENOMEM; |
3407 | } | 3443 | } |
3444 | |||
3445 | int bnx2x_open_epilog(struct bnx2x *bp) | ||
3446 | { | ||
3447 | /* Enable sriov via delayed work. This must be done via delayed work | ||
3448 | * because it causes the probe of the vf devices to be run, which invoke | ||
3449 | * register_netdevice which must have rtnl lock taken. As we are holding | ||
3450 | * the lock right now, that could only work if the probe would not take | ||
3451 | * the lock. However, as the probe of the vf may be called from other | ||
3452 | * contexts as well (such as passthrough to vm failes) it can't assume | ||
3453 | * the lock is being held for it. Using delayed work here allows the | ||
3454 | * probe code to simply take the lock (i.e. wait for it to be released | ||
3455 | * if it is being held). We only want to do this if the number of VFs | ||
3456 | * was set before PF driver was loaded. | ||
3457 | */ | ||
3458 | if (IS_SRIOV(bp) && BNX2X_NR_VIRTFN(bp)) { | ||
3459 | smp_mb__before_clear_bit(); | ||
3460 | set_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, &bp->sp_rtnl_state); | ||
3461 | smp_mb__after_clear_bit(); | ||
3462 | schedule_delayed_work(&bp->sp_rtnl_task, 0); | ||
3463 | } | ||
3464 | |||
3465 | return 0; | ||
3466 | } | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 33d49516fcea..a10bdb2fd900 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | |||
@@ -753,12 +753,15 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp, | |||
753 | enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); | 753 | enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); |
754 | void bnx2x_vf_map_doorbells(struct bnx2x *bp); | 754 | void bnx2x_vf_map_doorbells(struct bnx2x *bp); |
755 | int bnx2x_vf_pci_alloc(struct bnx2x *bp); | 755 | int bnx2x_vf_pci_alloc(struct bnx2x *bp); |
756 | void bnx2x_enable_sriov(struct bnx2x *bp); | 756 | int bnx2x_enable_sriov(struct bnx2x *bp); |
757 | void bnx2x_disable_sriov(struct bnx2x *bp); | ||
757 | static inline int bnx2x_vf_headroom(struct bnx2x *bp) | 758 | static inline int bnx2x_vf_headroom(struct bnx2x *bp) |
758 | { | 759 | { |
759 | return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF; | 760 | return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF; |
760 | } | 761 | } |
761 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp); | 762 | void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp); |
763 | int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs); | ||
764 | int bnx2x_open_epilog(struct bnx2x *bp); | ||
762 | 765 | ||
763 | #else /* CONFIG_BNX2X_SRIOV */ | 766 | #else /* CONFIG_BNX2X_SRIOV */ |
764 | 767 | ||
@@ -781,7 +784,8 @@ static inline void bnx2x_iov_init_dmae(struct bnx2x *bp) {} | |||
781 | static inline int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, | 784 | static inline int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, |
782 | int num_vfs_param) {return 0; } | 785 | int num_vfs_param) {return 0; } |
783 | static inline void bnx2x_iov_remove_one(struct bnx2x *bp) {} | 786 | static inline void bnx2x_iov_remove_one(struct bnx2x *bp) {} |
784 | static inline void bnx2x_enable_sriov(struct bnx2x *bp) {} | 787 | static inline int bnx2x_enable_sriov(struct bnx2x *bp) {return 0; } |
788 | static inline void bnx2x_disable_sriov(struct bnx2x *bp) {} | ||
785 | static inline int bnx2x_vfpf_acquire(struct bnx2x *bp, | 789 | static inline int bnx2x_vfpf_acquire(struct bnx2x *bp, |
786 | u8 tx_count, u8 rx_count) {return 0; } | 790 | u8 tx_count, u8 rx_count) {return 0; } |
787 | static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; } | 791 | static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; } |
@@ -807,6 +811,8 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp | |||
807 | static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; } | 811 | static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; } |
808 | static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } | 812 | static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } |
809 | static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} | 813 | static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} |
814 | static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; } | ||
815 | static inline int bnx2x_open_epilog(struct bnx2x *bp) {return 0; } | ||
810 | 816 | ||
811 | #endif /* CONFIG_BNX2X_SRIOV */ | 817 | #endif /* CONFIG_BNX2X_SRIOV */ |
812 | #endif /* bnx2x_sriov.h */ | 818 | #endif /* bnx2x_sriov.h */ |