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/bnx2x/bnx2x_sriov.c | |
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/bnx2x/bnx2x_sriov.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 87 |
1 files changed, 73 insertions, 14 deletions
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 | } | ||