diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 28 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 304 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 220 |
6 files changed, 570 insertions, 1 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/Makefile b/drivers/net/ethernet/broadcom/bnx2x/Makefile index d862ea699e9f..2ef6803a0fa7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/Makefile +++ b/drivers/net/ethernet/broadcom/bnx2x/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_BNX2X) += bnx2x.o | 5 | obj-$(CONFIG_BNX2X) += bnx2x.o |
6 | 6 | ||
7 | bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o bnx2x_vfpf.o | 7 | bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o bnx2x_vfpf.o bnx2x_sriov.o |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 2fe1908e94d7..027a4a31dd20 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -13,9 +13,12 @@ | |||
13 | 13 | ||
14 | #ifndef BNX2X_H | 14 | #ifndef BNX2X_H |
15 | #define BNX2X_H | 15 | #define BNX2X_H |
16 | |||
17 | #include <linux/pci.h> | ||
16 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
17 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
18 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/pci_regs.h> | ||
19 | 22 | ||
20 | /* compilation time flags */ | 23 | /* compilation time flags */ |
21 | 24 | ||
@@ -966,6 +969,7 @@ extern struct workqueue_struct *bnx2x_wq; | |||
966 | #define BNX2X_MAX_NUM_OF_VFS 64 | 969 | #define BNX2X_MAX_NUM_OF_VFS 64 |
967 | #define BNX2X_VF_CID_WND 0 | 970 | #define BNX2X_VF_CID_WND 0 |
968 | #define BNX2X_CIDS_PER_VF (1 << BNX2X_VF_CID_WND) | 971 | #define BNX2X_CIDS_PER_VF (1 << BNX2X_VF_CID_WND) |
972 | #define BNX2X_FIRST_VF_CID 256 | ||
969 | #define BNX2X_VF_CIDS (BNX2X_MAX_NUM_OF_VFS * BNX2X_CIDS_PER_VF) | 973 | #define BNX2X_VF_CIDS (BNX2X_MAX_NUM_OF_VFS * BNX2X_CIDS_PER_VF) |
970 | #define BNX2X_VF_ID_INVALID 0xFF | 974 | #define BNX2X_VF_ID_INVALID 0xFF |
971 | 975 | ||
@@ -1117,6 +1121,7 @@ struct hw_context { | |||
1117 | /* forward */ | 1121 | /* forward */ |
1118 | struct bnx2x_ilt; | 1122 | struct bnx2x_ilt; |
1119 | 1123 | ||
1124 | struct bnx2x_vfdb; | ||
1120 | 1125 | ||
1121 | enum bnx2x_recovery_state { | 1126 | enum bnx2x_recovery_state { |
1122 | BNX2X_RECOVERY_DONE, | 1127 | BNX2X_RECOVERY_DONE, |
@@ -1606,6 +1611,9 @@ struct bnx2x { | |||
1606 | char fw_ver[32]; | 1611 | char fw_ver[32]; |
1607 | const struct firmware *firmware; | 1612 | const struct firmware *firmware; |
1608 | 1613 | ||
1614 | struct bnx2x_vfdb *vfdb; | ||
1615 | #define IS_SRIOV(bp) ((bp)->vfdb) | ||
1616 | |||
1609 | /* DCB support on/off */ | 1617 | /* DCB support on/off */ |
1610 | u16 dcb_state; | 1618 | u16 dcb_state; |
1611 | #define BNX2X_DCB_STATE_OFF 0 | 1619 | #define BNX2X_DCB_STATE_OFF 0 |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index aafcaf610c15..6188ec68b45d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -7270,12 +7270,21 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) | |||
7270 | ilt = BP_ILT(bp); | 7270 | ilt = BP_ILT(bp); |
7271 | cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start; | 7271 | cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start; |
7272 | 7272 | ||
7273 | if (IS_SRIOV(bp)) | ||
7274 | cdu_ilt_start += BNX2X_FIRST_VF_CID/ILT_PAGE_CIDS; | ||
7275 | cdu_ilt_start = bnx2x_iov_init_ilt(bp, cdu_ilt_start); | ||
7276 | |||
7277 | /* since BNX2X_FIRST_VF_CID > 0 the PF L2 cids precedes | ||
7278 | * those of the VFs, so start line should be reset | ||
7279 | */ | ||
7280 | cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start; | ||
7273 | for (i = 0; i < L2_ILT_LINES(bp); i++) { | 7281 | for (i = 0; i < L2_ILT_LINES(bp); i++) { |
7274 | ilt->lines[cdu_ilt_start + i].page = bp->context[i].vcxt; | 7282 | ilt->lines[cdu_ilt_start + i].page = bp->context[i].vcxt; |
7275 | ilt->lines[cdu_ilt_start + i].page_mapping = | 7283 | ilt->lines[cdu_ilt_start + i].page_mapping = |
7276 | bp->context[i].cxt_mapping; | 7284 | bp->context[i].cxt_mapping; |
7277 | ilt->lines[cdu_ilt_start + i].size = bp->context[i].size; | 7285 | ilt->lines[cdu_ilt_start + i].size = bp->context[i].size; |
7278 | } | 7286 | } |
7287 | |||
7279 | bnx2x_ilt_init_op(bp, INITOP_SET); | 7288 | bnx2x_ilt_init_op(bp, INITOP_SET); |
7280 | 7289 | ||
7281 | if (!CONFIGURE_NIC_MODE(bp)) { | 7290 | if (!CONFIGURE_NIC_MODE(bp)) { |
@@ -7881,6 +7890,8 @@ int bnx2x_set_int_mode(struct bnx2x *bp) | |||
7881 | /* must be called prior to any HW initializations */ | 7890 | /* must be called prior to any HW initializations */ |
7882 | static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp) | 7891 | static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp) |
7883 | { | 7892 | { |
7893 | if (IS_SRIOV(bp)) | ||
7894 | return (BNX2X_FIRST_VF_CID + BNX2X_VF_CIDS)/ILT_PAGE_CIDS; | ||
7884 | return L2_ILT_LINES(bp); | 7895 | return L2_ILT_LINES(bp); |
7885 | } | 7896 | } |
7886 | 7897 | ||
@@ -12106,8 +12117,12 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp) | |||
12106 | { | 12117 | { |
12107 | int cid_count = BNX2X_L2_MAX_CID(bp); | 12118 | int cid_count = BNX2X_L2_MAX_CID(bp); |
12108 | 12119 | ||
12120 | if (IS_SRIOV(bp)) | ||
12121 | cid_count += BNX2X_VF_CIDS; | ||
12122 | |||
12109 | if (CNIC_SUPPORT(bp)) | 12123 | if (CNIC_SUPPORT(bp)) |
12110 | cid_count += CNIC_CID_MAX; | 12124 | cid_count += CNIC_CID_MAX; |
12125 | |||
12111 | return roundup(cid_count, QM_CID_ROUND); | 12126 | return roundup(cid_count, QM_CID_ROUND); |
12112 | } | 12127 | } |
12113 | 12128 | ||
@@ -12312,6 +12327,16 @@ static int bnx2x_init_one(struct pci_dev *pdev, | |||
12312 | goto init_one_exit; | 12327 | goto init_one_exit; |
12313 | } | 12328 | } |
12314 | 12329 | ||
12330 | /* Enable SRIOV if capability found in configuration space. | ||
12331 | * Once the generic SR-IOV framework makes it in from the | ||
12332 | * pci tree this will be revised, to allow dynamic control | ||
12333 | * over the number of VFs. Right now, change the num of vfs | ||
12334 | * param below to enable SR-IOV. | ||
12335 | */ | ||
12336 | rc = bnx2x_iov_init_one(bp, int_mode, 0/*num vfs*/); | ||
12337 | if (rc) | ||
12338 | goto init_one_exit; | ||
12339 | |||
12315 | /* calc qm_cid_count */ | 12340 | /* calc qm_cid_count */ |
12316 | bp->qm_cid_count = bnx2x_set_qm_cid_count(bp); | 12341 | bp->qm_cid_count = bnx2x_set_qm_cid_count(bp); |
12317 | BNX2X_DEV_INFO("qm_cid_count %d\n", bp->qm_cid_count); | 12342 | BNX2X_DEV_INFO("qm_cid_count %d\n", bp->qm_cid_count); |
@@ -12435,6 +12460,9 @@ static void bnx2x_remove_one(struct pci_dev *pdev) | |||
12435 | 12460 | ||
12436 | /* Make sure RESET task is not scheduled before continuing */ | 12461 | /* Make sure RESET task is not scheduled before continuing */ |
12437 | cancel_delayed_work_sync(&bp->sp_rtnl_task); | 12462 | cancel_delayed_work_sync(&bp->sp_rtnl_task); |
12463 | |||
12464 | bnx2x_iov_remove_one(bp); | ||
12465 | |||
12438 | /* send message via vfpf channel to release the resources of this vf */ | 12466 | /* send message via vfpf channel to release the resources of this vf */ |
12439 | if (IS_VF(bp)) | 12467 | if (IS_VF(bp)) |
12440 | bnx2x_vfpf_release(bp); | 12468 | bnx2x_vfpf_release(bp); |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index 3f01526dec2a..00e439891241 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | |||
@@ -6305,6 +6305,15 @@ | |||
6305 | #define PCI_PM_DATA_B 0x414 | 6305 | #define PCI_PM_DATA_B 0x414 |
6306 | #define PCI_ID_VAL1 0x434 | 6306 | #define PCI_ID_VAL1 0x434 |
6307 | #define PCI_ID_VAL2 0x438 | 6307 | #define PCI_ID_VAL2 0x438 |
6308 | #define GRC_CONFIG_REG_PF_INIT_VF 0x624 | ||
6309 | #define GRC_CR_PF_INIT_VF_PF_FIRST_VF_NUM_MASK 0xf | ||
6310 | /* First VF_NUM for PF is encoded in this register. | ||
6311 | * The number of VFs assigned to a PF is assumed to be a multiple of 8. | ||
6312 | * Software should program these bits based on Total Number of VFs \ | ||
6313 | * programmed for each PF. | ||
6314 | * Since registers from 0x000-0x7ff are split across functions, each PF will | ||
6315 | * have the same location for the same 4 bits | ||
6316 | */ | ||
6308 | 6317 | ||
6309 | #define PXPCS_TL_CONTROL_5 0x814 | 6318 | #define PXPCS_TL_CONTROL_5 0x814 |
6310 | #define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN (1 << 29) /*WC*/ | 6319 | #define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN (1 << 29) /*WC*/ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c new file mode 100644 index 000000000000..f92bf8b738fb --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* bnx2x_sriov.c: Broadcom Everest network driver. | ||
2 | * | ||
3 | * Copyright 2009-2012 Broadcom Corporation | ||
4 | * | ||
5 | * Unless you and Broadcom execute a separate written software license | ||
6 | * agreement governing use of this software, this software is licensed to you | ||
7 | * under the terms of the GNU General Public License version 2, available | ||
8 | * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"). | ||
9 | * | ||
10 | * Notwithstanding the above, under no circumstances may you combine this | ||
11 | * software in any way with any other Broadcom software provided under a | ||
12 | * license other than the GPL, without Broadcom's express prior written | ||
13 | * consent. | ||
14 | * | ||
15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | ||
16 | * Written by: Shmulik Ravid <shmulikr@broadcom.com> | ||
17 | * Ariel Elior <ariele@broadcom.com> | ||
18 | * | ||
19 | */ | ||
20 | #include "bnx2x.h" | ||
21 | #include "bnx2x_init.h" | ||
22 | #include "bnx2x_sriov.h" | ||
23 | int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid) | ||
24 | { | ||
25 | int idx; | ||
26 | |||
27 | for_each_vf(bp, idx) | ||
28 | if (bnx2x_vf(bp, idx, abs_vfid) == abs_vfid) | ||
29 | break; | ||
30 | return idx; | ||
31 | } | ||
32 | |||
33 | static | ||
34 | struct bnx2x_virtf *bnx2x_vf_by_abs_fid(struct bnx2x *bp, u16 abs_vfid) | ||
35 | { | ||
36 | u16 idx = (u16)bnx2x_vf_idx_by_abs_fid(bp, abs_vfid); | ||
37 | return (idx < BNX2X_NR_VIRTFN(bp)) ? BP_VF(bp, idx) : NULL; | ||
38 | } | ||
39 | |||
40 | static int bnx2x_ari_enabled(struct pci_dev *dev) | ||
41 | { | ||
42 | return dev->bus->self && dev->bus->self->ari_enabled; | ||
43 | } | ||
44 | |||
45 | static void | ||
46 | bnx2x_vf_set_igu_info(struct bnx2x *bp, u8 igu_sb_id, u8 abs_vfid) | ||
47 | { | ||
48 | struct bnx2x_virtf *vf = bnx2x_vf_by_abs_fid(bp, abs_vfid); | ||
49 | if (vf) { | ||
50 | if (!vf_sb_count(vf)) | ||
51 | vf->igu_base_id = igu_sb_id; | ||
52 | ++vf_sb_count(vf); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static void | ||
57 | bnx2x_get_vf_igu_cam_info(struct bnx2x *bp) | ||
58 | { | ||
59 | int sb_id; | ||
60 | u32 val; | ||
61 | u8 fid; | ||
62 | |||
63 | /* IGU in normal mode - read CAM */ | ||
64 | for (sb_id = 0; sb_id < IGU_REG_MAPPING_MEMORY_SIZE; sb_id++) { | ||
65 | val = REG_RD(bp, IGU_REG_MAPPING_MEMORY + sb_id * 4); | ||
66 | if (!(val & IGU_REG_MAPPING_MEMORY_VALID)) | ||
67 | continue; | ||
68 | fid = GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID); | ||
69 | if (!(fid & IGU_FID_ENCODE_IS_PF)) | ||
70 | bnx2x_vf_set_igu_info(bp, sb_id, | ||
71 | (fid & IGU_FID_VF_NUM_MASK)); | ||
72 | |||
73 | DP(BNX2X_MSG_IOV, "%s[%d], igu_sb_id=%d, msix=%d\n", | ||
74 | ((fid & IGU_FID_ENCODE_IS_PF) ? "PF" : "VF"), | ||
75 | ((fid & IGU_FID_ENCODE_IS_PF) ? (fid & IGU_FID_PF_NUM_MASK) : | ||
76 | (fid & IGU_FID_VF_NUM_MASK)), sb_id, | ||
77 | GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static void __bnx2x_iov_free_vfdb(struct bnx2x *bp) | ||
82 | { | ||
83 | if (bp->vfdb) { | ||
84 | kfree(bp->vfdb->vfqs); | ||
85 | kfree(bp->vfdb->vfs); | ||
86 | kfree(bp->vfdb); | ||
87 | } | ||
88 | bp->vfdb = NULL; | ||
89 | } | ||
90 | |||
91 | static int bnx2x_sriov_pci_cfg_info(struct bnx2x *bp, struct bnx2x_sriov *iov) | ||
92 | { | ||
93 | int pos; | ||
94 | struct pci_dev *dev = bp->pdev; | ||
95 | |||
96 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); | ||
97 | if (!pos) { | ||
98 | BNX2X_ERR("failed to find SRIOV capability in device\n"); | ||
99 | return -ENODEV; | ||
100 | } | ||
101 | |||
102 | iov->pos = pos; | ||
103 | DP(BNX2X_MSG_IOV, "sriov ext pos %d\n", pos); | ||
104 | pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &iov->ctrl); | ||
105 | pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &iov->total); | ||
106 | pci_read_config_word(dev, pos + PCI_SRIOV_INITIAL_VF, &iov->initial); | ||
107 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &iov->offset); | ||
108 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &iov->stride); | ||
109 | pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &iov->pgsz); | ||
110 | pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); | ||
111 | pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int bnx2x_sriov_info(struct bnx2x *bp, struct bnx2x_sriov *iov) | ||
117 | { | ||
118 | u32 val; | ||
119 | |||
120 | /* read the SRIOV capability structure | ||
121 | * The fields can be read via configuration read or | ||
122 | * directly from the device (starting at offset PCICFG_OFFSET) | ||
123 | */ | ||
124 | if (bnx2x_sriov_pci_cfg_info(bp, iov)) | ||
125 | return -ENODEV; | ||
126 | |||
127 | /* get the number of SRIOV bars */ | ||
128 | iov->nres = 0; | ||
129 | |||
130 | /* read the first_vfid */ | ||
131 | val = REG_RD(bp, PCICFG_OFFSET + GRC_CONFIG_REG_PF_INIT_VF); | ||
132 | iov->first_vf_in_pf = ((val & GRC_CR_PF_INIT_VF_PF_FIRST_VF_NUM_MASK) | ||
133 | * 8) - (BNX2X_MAX_NUM_OF_VFS * BP_PATH(bp)); | ||
134 | |||
135 | DP(BNX2X_MSG_IOV, | ||
136 | "IOV info[%d]: first vf %d, nres %d, cap 0x%x, ctrl 0x%x, total %d, initial %d, num vfs %d, offset %d, stride %d, page size 0x%x\n", | ||
137 | BP_FUNC(bp), | ||
138 | iov->first_vf_in_pf, iov->nres, iov->cap, iov->ctrl, iov->total, | ||
139 | iov->initial, iov->nr_virtfn, iov->offset, iov->stride, iov->pgsz); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static u8 bnx2x_iov_get_max_queue_count(struct bnx2x *bp) | ||
145 | { | ||
146 | int i; | ||
147 | u8 queue_count = 0; | ||
148 | |||
149 | if (IS_SRIOV(bp)) | ||
150 | for_each_vf(bp, i) | ||
151 | queue_count += bnx2x_vf(bp, i, alloc_resc.num_sbs); | ||
152 | |||
153 | return queue_count; | ||
154 | } | ||
155 | |||
156 | /* must be called after PF bars are mapped */ | ||
157 | int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, | ||
158 | int num_vfs_param) | ||
159 | { | ||
160 | int err, i, qcount; | ||
161 | struct bnx2x_sriov *iov; | ||
162 | struct pci_dev *dev = bp->pdev; | ||
163 | |||
164 | bp->vfdb = NULL; | ||
165 | |||
166 | /* verify sriov capability is present in configuration space */ | ||
167 | if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV)) { | ||
168 | DP(BNX2X_MSG_IOV, "no sriov - capability not found\n"); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* verify is pf */ | ||
173 | if (IS_VF(bp)) | ||
174 | return 0; | ||
175 | |||
176 | /* verify chip revision */ | ||
177 | if (CHIP_IS_E1x(bp)) | ||
178 | return 0; | ||
179 | |||
180 | /* check if SRIOV support is turned off */ | ||
181 | if (!num_vfs_param) | ||
182 | return 0; | ||
183 | |||
184 | /* SRIOV assumes that num of PF CIDs < BNX2X_FIRST_VF_CID */ | ||
185 | if (BNX2X_L2_MAX_CID(bp) >= BNX2X_FIRST_VF_CID) { | ||
186 | BNX2X_ERR("PF cids %d are overspilling into vf space (starts at %d). Abort SRIOV\n", | ||
187 | BNX2X_L2_MAX_CID(bp), BNX2X_FIRST_VF_CID); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /* SRIOV can be enabled only with MSIX */ | ||
192 | if (int_mode_param == BNX2X_INT_MODE_MSI || | ||
193 | int_mode_param == BNX2X_INT_MODE_INTX) { | ||
194 | BNX2X_ERR("Forced MSI/INTx mode is incompatible with SRIOV\n"); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | /* verify ari is enabled */ | ||
199 | if (!bnx2x_ari_enabled(bp->pdev)) { | ||
200 | BNX2X_ERR("ARI not supported, SRIOV can not be enabled\n"); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* verify igu is in normal mode */ | ||
205 | if (CHIP_INT_MODE_IS_BC(bp)) { | ||
206 | BNX2X_ERR("IGU not normal mode, SRIOV can not be enabled\n"); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | /* allocate the vfs database */ | ||
211 | bp->vfdb = kzalloc(sizeof(*(bp->vfdb)), GFP_KERNEL); | ||
212 | if (!bp->vfdb) { | ||
213 | BNX2X_ERR("failed to allocate vf database\n"); | ||
214 | err = -ENOMEM; | ||
215 | goto failed; | ||
216 | } | ||
217 | |||
218 | /* get the sriov info - Linux already collected all the pertinent | ||
219 | * information, however the sriov structure is for the private use | ||
220 | * of the pci module. Also we want this information regardless | ||
221 | * of the hyper-visor. | ||
222 | */ | ||
223 | iov = &(bp->vfdb->sriov); | ||
224 | err = bnx2x_sriov_info(bp, iov); | ||
225 | if (err) | ||
226 | goto failed; | ||
227 | |||
228 | /* SR-IOV capability was enabled but there are no VFs*/ | ||
229 | if (iov->total == 0) | ||
230 | goto failed; | ||
231 | |||
232 | /* calcuate the actual number of VFs */ | ||
233 | iov->nr_virtfn = min_t(u16, iov->total, (u16)num_vfs_param); | ||
234 | |||
235 | /* allcate the vf array */ | ||
236 | bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) * | ||
237 | BNX2X_NR_VIRTFN(bp), GFP_KERNEL); | ||
238 | if (!bp->vfdb->vfs) { | ||
239 | BNX2X_ERR("failed to allocate vf array\n"); | ||
240 | err = -ENOMEM; | ||
241 | goto failed; | ||
242 | } | ||
243 | |||
244 | /* Initial VF init - index and abs_vfid - nr_virtfn must be set */ | ||
245 | for_each_vf(bp, i) { | ||
246 | bnx2x_vf(bp, i, index) = i; | ||
247 | bnx2x_vf(bp, i, abs_vfid) = iov->first_vf_in_pf + i; | ||
248 | bnx2x_vf(bp, i, state) = VF_FREE; | ||
249 | INIT_LIST_HEAD(&bnx2x_vf(bp, i, op_list_head)); | ||
250 | mutex_init(&bnx2x_vf(bp, i, op_mutex)); | ||
251 | bnx2x_vf(bp, i, op_current) = CHANNEL_TLV_NONE; | ||
252 | } | ||
253 | |||
254 | /* re-read the IGU CAM for VFs - index and abs_vfid must be set */ | ||
255 | bnx2x_get_vf_igu_cam_info(bp); | ||
256 | |||
257 | /* get the total queue count and allocate the global queue arrays */ | ||
258 | qcount = bnx2x_iov_get_max_queue_count(bp); | ||
259 | |||
260 | /* allocate the queue arrays for all VFs */ | ||
261 | bp->vfdb->vfqs = kzalloc(qcount * sizeof(struct bnx2x_vf_queue), | ||
262 | GFP_KERNEL); | ||
263 | if (!bp->vfdb->vfqs) { | ||
264 | BNX2X_ERR("failed to allocate vf queue array\n"); | ||
265 | err = -ENOMEM; | ||
266 | goto failed; | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | failed: | ||
271 | DP(BNX2X_MSG_IOV, "Failed err=%d\n", err); | ||
272 | __bnx2x_iov_free_vfdb(bp); | ||
273 | return err; | ||
274 | } | ||
275 | |||
276 | /* called by bnx2x_init_hw_func, returns the next ilt line */ | ||
277 | int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line) | ||
278 | { | ||
279 | int i; | ||
280 | struct bnx2x_ilt *ilt = BP_ILT(bp); | ||
281 | |||
282 | if (!IS_SRIOV(bp)) | ||
283 | return line; | ||
284 | |||
285 | /* set vfs ilt lines */ | ||
286 | for (i = 0; i < BNX2X_VF_CIDS/ILT_PAGE_CIDS; i++) { | ||
287 | struct hw_dma *hw_cxt = BP_VF_CXT_PAGE(bp, i); | ||
288 | |||
289 | ilt->lines[line+i].page = hw_cxt->addr; | ||
290 | ilt->lines[line+i].page_mapping = hw_cxt->mapping; | ||
291 | ilt->lines[line+i].size = hw_cxt->size; /* doesn't matter */ | ||
292 | } | ||
293 | return line + i; | ||
294 | } | ||
295 | |||
296 | void bnx2x_iov_remove_one(struct bnx2x *bp) | ||
297 | { | ||
298 | /* if SRIOV is not enabled there's nothing to do */ | ||
299 | if (!IS_SRIOV(bp)) | ||
300 | return; | ||
301 | |||
302 | /* free vf database */ | ||
303 | __bnx2x_iov_free_vfdb(bp); | ||
304 | } | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 6d0df334124a..97275aa08ca9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | |||
@@ -19,11 +19,231 @@ | |||
19 | #ifndef BNX2X_SRIOV_H | 19 | #ifndef BNX2X_SRIOV_H |
20 | #define BNX2X_SRIOV_H | 20 | #define BNX2X_SRIOV_H |
21 | 21 | ||
22 | /* The bnx2x device structure holds vfdb structure described below. | ||
23 | * The VF array is indexed by the relative vfid. | ||
24 | */ | ||
25 | struct bnx2x_sriov { | ||
26 | u32 first_vf_in_pf; | ||
27 | |||
28 | /* standard SRIOV capability fields, mostly for debugging */ | ||
29 | int pos; /* capability position */ | ||
30 | int nres; /* number of resources */ | ||
31 | u32 cap; /* SR-IOV Capabilities */ | ||
32 | u16 ctrl; /* SR-IOV Control */ | ||
33 | u16 total; /* total VFs associated with the PF */ | ||
34 | u16 initial; /* initial VFs associated with the PF */ | ||
35 | u16 nr_virtfn; /* number of VFs available */ | ||
36 | u16 offset; /* first VF Routing ID offset */ | ||
37 | u16 stride; /* following VF stride */ | ||
38 | u32 pgsz; /* page size for BAR alignment */ | ||
39 | u8 link; /* Function Dependency Link */ | ||
40 | }; | ||
41 | |||
42 | /* bars */ | ||
43 | struct bnx2x_vf_bar { | ||
44 | u64 bar; | ||
45 | u32 size; | ||
46 | }; | ||
47 | |||
48 | /* vf queue (used both for rx or tx) */ | ||
49 | struct bnx2x_vf_queue { | ||
50 | struct eth_context *cxt; | ||
51 | |||
52 | /* MACs object */ | ||
53 | struct bnx2x_vlan_mac_obj mac_obj; | ||
54 | |||
55 | /* VLANs object */ | ||
56 | struct bnx2x_vlan_mac_obj vlan_obj; | ||
57 | atomic_t vlan_count; /* 0 means vlan-0 is set ~ untagged */ | ||
58 | |||
59 | /* Queue Slow-path State object */ | ||
60 | struct bnx2x_queue_sp_obj sp_obj; | ||
61 | |||
62 | u32 cid; | ||
63 | u16 index; | ||
64 | u16 sb_idx; | ||
65 | }; | ||
66 | |||
67 | /* struct bnx2x_vfop_qctor_params - prepare queue construction parameters: | ||
68 | * q-init, q-setup and SB index | ||
69 | */ | ||
70 | struct bnx2x_vfop_qctor_params { | ||
71 | struct bnx2x_queue_state_params qstate; | ||
72 | struct bnx2x_queue_setup_params prep_qsetup; | ||
73 | }; | ||
74 | |||
75 | /* VFOP parameters (one copy per VF) */ | ||
76 | union bnx2x_vfop_params { | ||
77 | struct bnx2x_vlan_mac_ramrod_params vlan_mac; | ||
78 | struct bnx2x_rx_mode_ramrod_params rx_mode; | ||
79 | struct bnx2x_mcast_ramrod_params mcast; | ||
80 | struct bnx2x_config_rss_params rss; | ||
81 | struct bnx2x_vfop_qctor_params qctor; | ||
82 | }; | ||
83 | |||
84 | /* forward */ | ||
85 | struct bnx2x_virtf; | ||
86 | /* vf context */ | ||
87 | struct bnx2x_virtf { | ||
88 | u16 cfg_flags; | ||
89 | #define VF_CFG_STATS 0x0001 | ||
90 | #define VF_CFG_FW_FC 0x0002 | ||
91 | #define VF_CFG_TPA 0x0004 | ||
92 | #define VF_CFG_INT_SIMD 0x0008 | ||
93 | #define VF_CACHE_LINE 0x0010 | ||
94 | |||
95 | u8 state; | ||
96 | #define VF_FREE 0 /* VF ready to be acquired holds no resc */ | ||
97 | #define VF_ACQUIRED 1 /* VF aquired, but not initalized */ | ||
98 | #define VF_ENABLED 2 /* VF Enabled */ | ||
99 | #define VF_RESET 3 /* VF FLR'd, pending cleanup */ | ||
100 | |||
101 | /* non 0 during flr cleanup */ | ||
102 | u8 flr_clnup_stage; | ||
103 | #define VF_FLR_CLN 1 /* reclaim resources and do 'final cleanup' | ||
104 | * sans the end-wait | ||
105 | */ | ||
106 | #define VF_FLR_ACK 2 /* ACK flr notification */ | ||
107 | #define VF_FLR_EPILOG 3 /* wait for VF remnants to dissipate in the HW | ||
108 | * ~ final cleanup' end wait | ||
109 | */ | ||
110 | |||
111 | /* dma */ | ||
112 | dma_addr_t fw_stat_map; /* valid iff VF_CFG_STATS */ | ||
113 | dma_addr_t spq_map; | ||
114 | dma_addr_t bulletin_map; | ||
115 | |||
116 | /* Allocated resources counters. Before the VF is acquired, the | ||
117 | * counters hold the following values: | ||
118 | * | ||
119 | * - xxq_count = 0 as the queues memory is not allocated yet. | ||
120 | * | ||
121 | * - sb_count = The number of status blocks configured for this VF in | ||
122 | * the IGU CAM. Initially read during probe. | ||
123 | * | ||
124 | * - xx_rules_count = The number of rules statically and equally | ||
125 | * allocated for each VF, during PF load. | ||
126 | */ | ||
127 | struct vf_pf_resc_request alloc_resc; | ||
128 | #define vf_rxq_count(vf) ((vf)->alloc_resc.num_rxqs) | ||
129 | #define vf_txq_count(vf) ((vf)->alloc_resc.num_txqs) | ||
130 | #define vf_sb_count(vf) ((vf)->alloc_resc.num_sbs) | ||
131 | #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) | ||
132 | #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) | ||
133 | #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) | ||
134 | |||
135 | u8 sb_count; /* actual number of SBs */ | ||
136 | u8 igu_base_id; /* base igu status block id */ | ||
137 | |||
138 | struct bnx2x_vf_queue *vfqs; | ||
139 | #define bnx2x_vfq(vf, nr, var) ((vf)->vfqs[(nr)].var) | ||
140 | |||
141 | u8 index; /* index in the vf array */ | ||
142 | u8 abs_vfid; | ||
143 | u8 sp_cl_id; | ||
144 | u32 error; /* 0 means all's-well */ | ||
145 | |||
146 | /* BDF */ | ||
147 | unsigned int bus; | ||
148 | unsigned int devfn; | ||
149 | |||
150 | /* bars */ | ||
151 | struct bnx2x_vf_bar bars[PCI_SRIOV_NUM_BARS]; | ||
152 | |||
153 | /* set-mac ramrod state 1-pending, 0-done */ | ||
154 | unsigned long filter_state; | ||
155 | |||
156 | /* leading rss client id ~~ the client id of the first rxq, must be | ||
157 | * set for each txq. | ||
158 | */ | ||
159 | int leading_rss; | ||
160 | |||
161 | /* MCAST object */ | ||
162 | struct bnx2x_mcast_obj mcast_obj; | ||
163 | |||
164 | /* RSS configuration object */ | ||
165 | struct bnx2x_rss_config_obj rss_conf_obj; | ||
166 | |||
167 | /* slow-path operations */ | ||
168 | atomic_t op_in_progress; | ||
169 | int op_rc; | ||
170 | bool op_wait_blocking; | ||
171 | struct list_head op_list_head; | ||
172 | union bnx2x_vfop_params op_params; | ||
173 | struct mutex op_mutex; /* one vfop at a time mutex */ | ||
174 | enum channel_tlvs op_current; | ||
175 | }; | ||
176 | |||
177 | #define BNX2X_NR_VIRTFN(bp) ((bp)->vfdb->sriov.nr_virtfn) | ||
178 | |||
179 | #define for_each_vf(bp, var) \ | ||
180 | for ((var) = 0; (var) < BNX2X_NR_VIRTFN(bp); (var)++) | ||
181 | |||
22 | struct bnx2x_vf_mbx_msg { | 182 | struct bnx2x_vf_mbx_msg { |
23 | union vfpf_tlvs req; | 183 | union vfpf_tlvs req; |
24 | union pfvf_tlvs resp; | 184 | union pfvf_tlvs resp; |
25 | }; | 185 | }; |
26 | 186 | ||
187 | struct bnx2x_vf_mbx { | ||
188 | struct bnx2x_vf_mbx_msg *msg; | ||
189 | dma_addr_t msg_mapping; | ||
190 | |||
191 | /* VF GPA address */ | ||
192 | u32 vf_addr_lo; | ||
193 | u32 vf_addr_hi; | ||
194 | |||
195 | struct vfpf_first_tlv first_tlv; /* saved VF request header */ | ||
196 | |||
197 | u8 flags; | ||
198 | #define VF_MSG_INPROCESS 0x1 /* failsafe - the FW should prevent | ||
199 | * more then one pending msg | ||
200 | */ | ||
201 | }; | ||
202 | |||
203 | struct hw_dma { | ||
204 | void *addr; | ||
205 | dma_addr_t mapping; | ||
206 | size_t size; | ||
207 | }; | ||
208 | |||
209 | struct bnx2x_vfdb { | ||
210 | #define BP_VFDB(bp) ((bp)->vfdb) | ||
211 | /* vf array */ | ||
212 | struct bnx2x_virtf *vfs; | ||
213 | #define BP_VF(bp, idx) (&((bp)->vfdb->vfs[(idx)])) | ||
214 | #define bnx2x_vf(bp, idx, var) ((bp)->vfdb->vfs[(idx)].var) | ||
215 | |||
216 | /* queue array - for all vfs */ | ||
217 | struct bnx2x_vf_queue *vfqs; | ||
218 | |||
219 | /* vf HW contexts */ | ||
220 | struct hw_dma context[BNX2X_VF_CIDS/ILT_PAGE_CIDS]; | ||
221 | #define BP_VF_CXT_PAGE(bp, i) (&(bp)->vfdb->context[(i)]) | ||
222 | |||
223 | /* SR-IOV information */ | ||
224 | struct bnx2x_sriov sriov; | ||
225 | struct hw_dma mbx_dma; | ||
226 | #define BP_VF_MBX_DMA(bp) (&((bp)->vfdb->mbx_dma)) | ||
227 | struct bnx2x_vf_mbx mbxs[BNX2X_MAX_NUM_OF_VFS]; | ||
228 | #define BP_VF_MBX(bp, vfid) (&((bp)->vfdb->mbxs[(vfid)])) | ||
229 | |||
230 | struct hw_dma sp_dma; | ||
231 | #define bnx2x_vf_sp(bp, vf, field) ((bp)->vfdb->sp_dma.addr + \ | ||
232 | (vf)->index * sizeof(struct bnx2x_vf_sp) + \ | ||
233 | offsetof(struct bnx2x_vf_sp, field)) | ||
234 | #define bnx2x_vf_sp_map(bp, vf, field) ((bp)->vfdb->sp_dma.mapping + \ | ||
235 | (vf)->index * sizeof(struct bnx2x_vf_sp) + \ | ||
236 | offsetof(struct bnx2x_vf_sp, field)) | ||
237 | |||
238 | #define FLRD_VFS_DWORDS (BNX2X_MAX_NUM_OF_VFS / 32) | ||
239 | u32 flrd_vfs[FLRD_VFS_DWORDS]; | ||
240 | }; | ||
241 | |||
242 | /* global iov routines */ | ||
243 | int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line); | ||
244 | int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, int num_vfs_param); | ||
245 | void bnx2x_iov_remove_one(struct bnx2x *bp); | ||
246 | int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); | ||
27 | void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type, | 247 | void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type, |
28 | u16 length); | 248 | u16 length); |
29 | void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv, | 249 | void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv, |