]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2018 Chelsio Communications. | |
3 | * All rights reserved. | |
4 | */ | |
5 | ||
6 | #include <rte_ethdev_driver.h> | |
7 | #include <rte_ethdev_pci.h> | |
8 | #include <rte_malloc.h> | |
9 | ||
9f95a23c TL |
10 | #include "base/common.h" |
11 | #include "base/t4_regs.h" | |
12 | #include "base/t4_msg.h" | |
11fdf7f2 | 13 | #include "cxgbe.h" |
f67539c2 | 14 | #include "cxgbe_pfvf.h" |
9f95a23c | 15 | #include "mps_tcam.h" |
11fdf7f2 TL |
16 | |
17 | /* | |
18 | * Figure out how many Ports and Queue Sets we can support. This depends on | |
19 | * knowing our Virtual Function Resources and may be called a second time if | |
20 | * we fall back from MSI-X to MSI Interrupt Mode. | |
21 | */ | |
22 | static void size_nports_qsets(struct adapter *adapter) | |
23 | { | |
24 | struct vf_resources *vfres = &adapter->params.vfres; | |
25 | unsigned int pmask_nports; | |
26 | ||
27 | /* | |
28 | * The number of "ports" which we support is equal to the number of | |
29 | * Virtual Interfaces with which we've been provisioned. | |
30 | */ | |
31 | adapter->params.nports = vfres->nvi; | |
32 | if (adapter->params.nports > MAX_NPORTS) { | |
33 | dev_warn(adapter->pdev_dev, "only using %d of %d maximum" | |
34 | " allowed virtual interfaces\n", MAX_NPORTS, | |
35 | adapter->params.nports); | |
36 | adapter->params.nports = MAX_NPORTS; | |
37 | } | |
38 | ||
39 | /* | |
40 | * We may have been provisioned with more VIs than the number of | |
41 | * ports we're allowed to access (our Port Access Rights Mask). | |
42 | * This is obviously a configuration conflict but we don't want to | |
43 | * do anything silly just because of that. | |
44 | */ | |
45 | pmask_nports = hweight32(adapter->params.vfres.pmask); | |
46 | if (pmask_nports < adapter->params.nports) { | |
47 | dev_warn(adapter->pdev_dev, "only using %d of %d provissioned" | |
48 | " virtual interfaces; limited by Port Access Rights" | |
49 | " mask %#x\n", pmask_nports, adapter->params.nports, | |
50 | adapter->params.vfres.pmask); | |
51 | adapter->params.nports = pmask_nports; | |
52 | } | |
53 | ||
9f95a23c | 54 | cxgbe_configure_max_ethqsets(adapter); |
11fdf7f2 TL |
55 | if (adapter->sge.max_ethqsets < adapter->params.nports) { |
56 | dev_warn(adapter->pdev_dev, "only using %d of %d available" | |
57 | " virtual interfaces (too few Queue Sets)\n", | |
58 | adapter->sge.max_ethqsets, adapter->params.nports); | |
59 | adapter->params.nports = adapter->sge.max_ethqsets; | |
60 | } | |
61 | } | |
62 | ||
63 | void cxgbevf_stats_get(struct port_info *pi, struct port_stats *stats) | |
64 | { | |
65 | t4vf_get_port_stats(pi->adapter, pi->pidx, stats); | |
66 | } | |
67 | ||
68 | static int adap_init0vf(struct adapter *adapter) | |
69 | { | |
70 | u32 param, val = 0; | |
71 | int err; | |
72 | ||
73 | err = t4vf_fw_reset(adapter); | |
74 | if (err < 0) { | |
75 | dev_err(adapter->pdev_dev, "FW reset failed: err=%d\n", err); | |
76 | return err; | |
77 | } | |
78 | ||
79 | /* | |
80 | * Grab basic operational parameters. These will predominantly have | |
81 | * been set up by the Physical Function Driver or will be hard coded | |
82 | * into the adapter. We just have to live with them ... Note that | |
83 | * we _must_ get our VPD parameters before our SGE parameters because | |
84 | * we need to know the adapter's core clock from the VPD in order to | |
85 | * properly decode the SGE Timer Values. | |
86 | */ | |
87 | err = t4vf_get_dev_params(adapter); | |
88 | if (err) { | |
89 | dev_err(adapter->pdev_dev, "unable to retrieve adapter" | |
90 | " device parameters: err=%d\n", err); | |
91 | return err; | |
92 | } | |
93 | ||
94 | err = t4vf_get_vpd_params(adapter); | |
95 | if (err) { | |
96 | dev_err(adapter->pdev_dev, "unable to retrieve adapter" | |
97 | " VPD parameters: err=%d\n", err); | |
98 | return err; | |
99 | } | |
100 | ||
101 | adapter->pf = t4vf_get_pf_from_vf(adapter); | |
102 | err = t4vf_sge_init(adapter); | |
103 | if (err) { | |
104 | dev_err(adapter->pdev_dev, "error in sge init\n"); | |
105 | return err; | |
106 | } | |
107 | ||
108 | err = t4vf_get_rss_glb_config(adapter); | |
109 | if (err) { | |
110 | dev_err(adapter->pdev_dev, "unable to retrieve adapter" | |
111 | " RSS parameters: err=%d\n", err); | |
112 | return err; | |
113 | } | |
114 | if (adapter->params.rss.mode != | |
115 | FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) { | |
116 | dev_err(adapter->pdev_dev, "unable to operate with global RSS" | |
117 | " mode %d\n", adapter->params.rss.mode); | |
118 | return -EINVAL; | |
119 | } | |
120 | ||
121 | /* If we're running on newer firmware, let it know that we're | |
122 | * prepared to deal with encapsulated CPL messages. Older | |
123 | * firmware won't understand this and we'll just get | |
124 | * unencapsulated messages ... | |
125 | */ | |
f67539c2 | 126 | param = CXGBE_FW_PARAM_PFVF(CPLFW4MSG_ENCAP); |
11fdf7f2 TL |
127 | val = 1; |
128 | t4vf_set_params(adapter, 1, ¶m, &val); | |
129 | ||
f67539c2 TL |
130 | /* Query for max number of packets that can be coalesced for Tx */ |
131 | param = CXGBE_FW_PARAM_PFVF(MAX_PKTS_PER_ETH_TX_PKTS_WR); | |
132 | err = t4vf_query_params(adapter, 1, ¶m, &val); | |
133 | if (!err && val > 0) | |
134 | adapter->params.max_tx_coalesce_num = val; | |
135 | else | |
136 | adapter->params.max_tx_coalesce_num = ETH_COALESCE_VF_PKT_NUM; | |
137 | ||
11fdf7f2 TL |
138 | /* |
139 | * Grab our Virtual Interface resource allocation, extract the | |
140 | * features that we're interested in and do a bit of sanity testing on | |
141 | * what we discover. | |
142 | */ | |
143 | err = t4vf_get_vfres(adapter); | |
144 | if (err) { | |
145 | dev_err(adapter->pdev_dev, "unable to get virtual interface" | |
146 | " resources: err=%d\n", err); | |
147 | return err; | |
148 | } | |
149 | ||
150 | /* | |
151 | * Check for various parameter sanity issues. | |
152 | */ | |
153 | if (adapter->params.vfres.pmask == 0) { | |
154 | dev_err(adapter->pdev_dev, "no port access configured\n" | |
155 | "usable!\n"); | |
156 | return -EINVAL; | |
157 | } | |
158 | if (adapter->params.vfres.nvi == 0) { | |
159 | dev_err(adapter->pdev_dev, "no virtual interfaces configured/" | |
160 | "usable!\n"); | |
161 | return -EINVAL; | |
162 | } | |
163 | ||
164 | /* | |
165 | * Initialize nports and max_ethqsets now that we have our Virtual | |
166 | * Function Resources. | |
167 | */ | |
168 | size_nports_qsets(adapter); | |
169 | adapter->flags |= FW_OK; | |
170 | return 0; | |
171 | } | |
172 | ||
173 | int cxgbevf_probe(struct adapter *adapter) | |
174 | { | |
175 | struct port_info *pi; | |
176 | unsigned int pmask; | |
177 | int err = 0; | |
178 | int i; | |
179 | ||
180 | t4_os_lock_init(&adapter->mbox_lock); | |
181 | TAILQ_INIT(&adapter->mbox_list); | |
182 | err = t4vf_prep_adapter(adapter); | |
183 | if (err) | |
184 | return err; | |
185 | ||
186 | if (!is_t4(adapter->params.chip)) { | |
187 | adapter->bar2 = (void *)adapter->pdev->mem_resource[2].addr; | |
188 | if (!adapter->bar2) { | |
189 | dev_err(adapter, "cannot map device bar2 region\n"); | |
190 | err = -ENOMEM; | |
191 | return err; | |
192 | } | |
193 | } | |
194 | ||
195 | err = adap_init0vf(adapter); | |
196 | if (err) { | |
197 | dev_err(adapter, "%s: Adapter initialization failed, error %d\n", | |
198 | __func__, err); | |
199 | goto out_free; | |
200 | } | |
201 | ||
202 | pmask = adapter->params.vfres.pmask; | |
203 | for_each_port(adapter, i) { | |
204 | const unsigned int numa_node = rte_socket_id(); | |
205 | char name[RTE_ETH_NAME_MAX_LEN]; | |
206 | struct rte_eth_dev *eth_dev; | |
207 | int port_id; | |
208 | ||
209 | if (pmask == 0) | |
210 | break; | |
211 | port_id = ffs(pmask) - 1; | |
212 | pmask &= ~(1 << port_id); | |
213 | ||
214 | snprintf(name, sizeof(name), "%s_%d", | |
215 | adapter->pdev->device.name, i); | |
216 | ||
217 | if (i == 0) { | |
218 | /* First port is already allocated by DPDK */ | |
219 | eth_dev = adapter->eth_dev; | |
220 | goto allocate_mac; | |
221 | } | |
222 | ||
223 | /* | |
224 | * now do all data allocation - for eth_dev structure, | |
225 | * and internal (private) data for the remaining ports | |
226 | */ | |
227 | ||
228 | /* reserve an ethdev entry */ | |
229 | eth_dev = rte_eth_dev_allocate(name); | |
230 | if (!eth_dev) { | |
231 | err = -ENOMEM; | |
232 | goto out_free; | |
233 | } | |
234 | eth_dev->data->dev_private = | |
235 | rte_zmalloc_socket(name, sizeof(struct port_info), | |
236 | RTE_CACHE_LINE_SIZE, numa_node); | |
237 | if (!eth_dev->data->dev_private) | |
238 | goto out_free; | |
239 | ||
240 | allocate_mac: | |
f67539c2 | 241 | pi = eth_dev->data->dev_private; |
11fdf7f2 TL |
242 | adapter->port[i] = pi; |
243 | pi->eth_dev = eth_dev; | |
244 | pi->adapter = adapter; | |
245 | pi->xact_addr_filt = -1; | |
246 | pi->port_id = port_id; | |
247 | pi->pidx = i; | |
248 | ||
249 | pi->eth_dev->device = &adapter->pdev->device; | |
250 | pi->eth_dev->dev_ops = adapter->eth_dev->dev_ops; | |
251 | pi->eth_dev->tx_pkt_burst = adapter->eth_dev->tx_pkt_burst; | |
252 | pi->eth_dev->rx_pkt_burst = adapter->eth_dev->rx_pkt_burst; | |
253 | ||
254 | rte_eth_copy_pci_info(pi->eth_dev, adapter->pdev); | |
255 | pi->eth_dev->data->mac_addrs = rte_zmalloc(name, | |
f67539c2 | 256 | RTE_ETHER_ADDR_LEN, 0); |
11fdf7f2 TL |
257 | if (!pi->eth_dev->data->mac_addrs) { |
258 | dev_err(adapter, "%s: Mem allocation failed for storing mac addr, aborting\n", | |
259 | __func__); | |
260 | err = -ENOMEM; | |
261 | goto out_free; | |
262 | } | |
263 | ||
264 | if (i > 0) { | |
265 | /* First port will be notified by upper layer */ | |
266 | rte_eth_dev_probing_finish(eth_dev); | |
267 | } | |
268 | } | |
269 | ||
270 | if (adapter->flags & FW_OK) { | |
271 | err = t4vf_port_init(adapter); | |
272 | if (err) { | |
273 | dev_err(adapter, "%s: t4_port_init failed with err %d\n", | |
274 | __func__, err); | |
275 | goto out_free; | |
276 | } | |
277 | } | |
278 | ||
9f95a23c TL |
279 | cxgbe_cfg_queues(adapter->eth_dev); |
280 | cxgbe_print_adapter_info(adapter); | |
281 | cxgbe_print_port_info(adapter); | |
11fdf7f2 | 282 | |
9f95a23c TL |
283 | adapter->mpstcam = t4_init_mpstcam(adapter); |
284 | if (!adapter->mpstcam) | |
285 | dev_warn(adapter, | |
286 | "VF could not allocate mps tcam table. Continuing\n"); | |
287 | ||
288 | err = cxgbe_init_rss(adapter); | |
11fdf7f2 TL |
289 | if (err) |
290 | goto out_free; | |
291 | return 0; | |
292 | ||
293 | out_free: | |
294 | for_each_port(adapter, i) { | |
295 | pi = adap2pinfo(adapter, i); | |
296 | if (pi->viid != 0) | |
297 | t4_free_vi(adapter, adapter->mbox, adapter->pf, | |
298 | 0, pi->viid); | |
9f95a23c | 299 | rte_eth_dev_release_port(pi->eth_dev); |
11fdf7f2 TL |
300 | } |
301 | return -err; | |
302 | } |