blob: ca2c464c15df2496aa5cdb02efa5459fe1c0330b [file] [log] [blame]
Jakub Kicinski2633beb2017-02-09 09:17:28 -08001/*
2 * Copyright (C) 2015-2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/*
35 * nfp_main.c
36 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
37 * Alejandro Lucero <alejandro.lucero@netronome.com>
38 * Jason McMullan <jason.mcmullan@netronome.com>
39 * Rolf Neugebauer <rolf.neugebauer@netronome.com>
40 */
41
42#include <linux/kernel.h>
43#include <linux/module.h>
44#include <linux/pci.h>
45#include <linux/firmware.h>
46#include <linux/vermagic.h>
47
Jakub Kicinski63461a02017-02-09 09:17:38 -080048#include "nfpcore/nfp.h"
49#include "nfpcore/nfp_cpp.h"
50#include "nfpcore/nfp_nsp_eth.h"
51
52#include "nfpcore/nfp6000_pcie.h"
53
Jakub Kicinski2633beb2017-02-09 09:17:28 -080054#include "nfp_main.h"
55#include "nfp_net.h"
56
57static const char nfp_driver_name[] = "nfp";
58const char nfp_driver_version[] = VERMAGIC_STRING;
59
Jakub Kicinski63461a02017-02-09 09:17:38 -080060static const struct pci_device_id nfp_pci_device_ids[] = {
Simon Horman3b473522017-02-17 08:57:54 +010061 { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000,
Jakub Kicinski63461a02017-02-09 09:17:38 -080062 PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
63 PCI_ANY_ID, 0,
64 },
Simon Horman3b473522017-02-17 08:57:54 +010065 { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000,
Jakub Kicinski63461a02017-02-09 09:17:38 -080066 PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
67 PCI_ANY_ID, 0,
68 },
69 { 0, } /* Required last entry. */
70};
71MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
72
73static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs)
74{
75#ifdef CONFIG_PCI_IOV
76 struct nfp_pf *pf = pci_get_drvdata(pdev);
77 int err;
78
79 err = pci_enable_sriov(pdev, num_vfs);
80 if (err) {
81 dev_warn(&pdev->dev, "Failed to enable PCI sriov: %d\n", err);
82 return err;
83 }
84
85 pf->num_vfs = num_vfs;
86
87 dev_dbg(&pdev->dev, "Created %d VFs.\n", pf->num_vfs);
88
89 return num_vfs;
90#endif
91 return 0;
92}
93
94static int nfp_pcie_sriov_disable(struct pci_dev *pdev)
95{
96#ifdef CONFIG_PCI_IOV
97 struct nfp_pf *pf = pci_get_drvdata(pdev);
98
99 /* If the VFs are assigned we cannot shut down SR-IOV without
100 * causing issues, so just leave the hardware available but
101 * disabled
102 */
103 if (pci_vfs_assigned(pdev)) {
104 dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n");
105 return -EPERM;
106 }
107
108 pf->num_vfs = 0;
109
110 pci_disable_sriov(pdev);
111 dev_dbg(&pdev->dev, "Removed VFs.\n");
112#endif
113 return 0;
114}
115
116static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs)
117{
118 if (num_vfs == 0)
119 return nfp_pcie_sriov_disable(pdev);
120 else
121 return nfp_pcie_sriov_enable(pdev, num_vfs);
122}
123
124/**
125 * nfp_net_fw_find() - Find the correct firmware image for netdev mode
126 * @pdev: PCI Device structure
127 * @pf: NFP PF Device structure
128 *
129 * Return: firmware if found and requested successfully.
130 */
131static const struct firmware *
132nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf)
133{
134 const struct firmware *fw = NULL;
135 struct nfp_eth_table_port *port;
136 const char *fw_model;
137 char fw_name[256];
138 int spc, err = 0;
139 int i, j;
140
141 if (!pf->eth_tbl) {
142 dev_err(&pdev->dev, "Error: can't identify media config\n");
143 return NULL;
144 }
145
146 fw_model = nfp_hwinfo_lookup(pf->cpp, "assembly.partno");
147 if (!fw_model) {
148 dev_err(&pdev->dev, "Error: can't read part number\n");
149 return NULL;
150 }
151
152 spc = ARRAY_SIZE(fw_name);
153 spc -= snprintf(fw_name, spc, "netronome/nic_%s", fw_model);
154
155 for (i = 0; spc > 0 && i < pf->eth_tbl->count; i += j) {
156 port = &pf->eth_tbl->ports[i];
157 j = 1;
158 while (i + j < pf->eth_tbl->count &&
159 port->speed == port[j].speed)
160 j++;
161
162 spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc,
163 "_%dx%d", j, port->speed / 1000);
164 }
165
166 if (spc <= 0)
167 return NULL;
168
169 spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, ".nffw");
170 if (spc <= 0)
171 return NULL;
172
173 err = request_firmware(&fw, fw_name, &pdev->dev);
174 if (err)
175 return NULL;
176
177 dev_info(&pdev->dev, "Loading FW image: %s\n", fw_name);
178
179 return fw;
180}
181
182/**
183 * nfp_net_fw_load() - Load the firmware image
184 * @pdev: PCI Device structure
185 * @pf: NFP PF Device structure
186 * @nsp: NFP SP handle
187 *
188 * Return: -ERRNO, 0 for no firmware loaded, 1 for firmware loaded
189 */
190static int
191nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp)
192{
193 const struct firmware *fw;
194 u16 interface;
195 int err;
196
197 interface = nfp_cpp_interface(pf->cpp);
198 if (NFP_CPP_INTERFACE_UNIT_of(interface) != 0) {
199 /* Only Unit 0 should reset or load firmware */
200 dev_info(&pdev->dev, "Firmware will be loaded by partner\n");
201 return 0;
202 }
203
204 fw = nfp_net_fw_find(pdev, pf);
205 if (!fw)
206 return 0;
207
208 dev_info(&pdev->dev, "Soft-reset, loading FW image\n");
209 err = nfp_nsp_device_soft_reset(nsp);
210 if (err < 0) {
211 dev_err(&pdev->dev, "Failed to soft reset the NFP: %d\n",
212 err);
213 goto exit_release_fw;
214 }
215
216 err = nfp_nsp_load_fw(nsp, fw);
217
218 if (err < 0) {
219 dev_err(&pdev->dev, "FW loading failed: %d\n", err);
220 goto exit_release_fw;
221 }
222
223 dev_info(&pdev->dev, "Finished loading FW image\n");
224
225exit_release_fw:
226 release_firmware(fw);
227
228 return err < 0 ? err : 1;
229}
230
Jakub Kicinskia9c83f72017-02-19 11:58:08 -0800231static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
232{
233 struct nfp_nsp *nsp;
234 int err;
235
236 nsp = nfp_nsp_open(pf->cpp);
237 if (IS_ERR(nsp)) {
238 err = PTR_ERR(nsp);
239 dev_err(&pdev->dev, "Failed to access the NSP: %d\n", err);
240 return err;
241 }
242
243 err = nfp_nsp_wait(nsp);
244 if (err < 0)
245 goto exit_close_nsp;
246
247 pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
248
249 err = nfp_fw_load(pdev, pf, nsp);
250 if (err < 0) {
251 kfree(pf->eth_tbl);
252 dev_err(&pdev->dev, "Failed to load FW\n");
253 goto exit_close_nsp;
254 }
255
256 pf->fw_loaded = !!err;
257 err = 0;
258
259exit_close_nsp:
260 nfp_nsp_close(nsp);
261
262 return err;
263}
264
Jakub Kicinski63461a02017-02-09 09:17:38 -0800265static void nfp_fw_unload(struct nfp_pf *pf)
266{
267 struct nfp_nsp *nsp;
268 int err;
269
270 nsp = nfp_nsp_open(pf->cpp);
271 if (IS_ERR(nsp)) {
272 nfp_err(pf->cpp, "Reset failed, can't open NSP\n");
273 return;
274 }
275
276 err = nfp_nsp_device_soft_reset(nsp);
277 if (err < 0)
278 dev_warn(&pf->pdev->dev, "Couldn't unload firmware: %d\n", err);
279 else
280 dev_info(&pf->pdev->dev, "Firmware safely unloaded\n");
281
282 nfp_nsp_close(nsp);
283}
284
285static int nfp_pci_probe(struct pci_dev *pdev,
286 const struct pci_device_id *pci_id)
287{
Jakub Kicinski63461a02017-02-09 09:17:38 -0800288 struct nfp_pf *pf;
289 int err;
290
291 err = pci_enable_device(pdev);
292 if (err < 0)
293 return err;
294
295 pci_set_master(pdev);
296
297 err = dma_set_mask_and_coherent(&pdev->dev,
298 DMA_BIT_MASK(NFP_NET_MAX_DMA_BITS));
299 if (err)
300 goto err_pci_disable;
301
302 err = pci_request_regions(pdev, nfp_driver_name);
303 if (err < 0) {
304 dev_err(&pdev->dev, "Unable to reserve pci resources.\n");
305 goto err_pci_disable;
306 }
307
308 pf = kzalloc(sizeof(*pf), GFP_KERNEL);
309 if (!pf) {
310 err = -ENOMEM;
311 goto err_rel_regions;
312 }
313 INIT_LIST_HEAD(&pf->ports);
314 pci_set_drvdata(pdev, pf);
315 pf->pdev = pdev;
316
317 pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev);
318 if (IS_ERR_OR_NULL(pf->cpp)) {
319 err = PTR_ERR(pf->cpp);
320 if (err >= 0)
321 err = -ENOMEM;
322 goto err_disable_msix;
323 }
324
Jakub Kicinskia9c83f72017-02-19 11:58:08 -0800325 err = nfp_nsp_init(pdev, pf);
326 if (err)
Jakub Kicinski63461a02017-02-09 09:17:38 -0800327 goto err_cpp_free;
Jakub Kicinski63461a02017-02-09 09:17:38 -0800328
329 err = nfp_net_pci_probe(pf);
330 if (err)
331 goto err_fw_unload;
332
333 return 0;
334
335err_fw_unload:
336 if (pf->fw_loaded)
337 nfp_fw_unload(pf);
Jakub Kicinski63461a02017-02-09 09:17:38 -0800338 kfree(pf->eth_tbl);
339err_cpp_free:
340 nfp_cpp_free(pf->cpp);
341err_disable_msix:
342 pci_set_drvdata(pdev, NULL);
343 kfree(pf);
344err_rel_regions:
345 pci_release_regions(pdev);
346err_pci_disable:
347 pci_disable_device(pdev);
348
349 return err;
350}
351
352static void nfp_pci_remove(struct pci_dev *pdev)
353{
354 struct nfp_pf *pf = pci_get_drvdata(pdev);
355
356 if (!list_empty(&pf->ports))
357 nfp_net_pci_remove(pf);
358
359 nfp_pcie_sriov_disable(pdev);
360
361 if (pf->fw_loaded)
362 nfp_fw_unload(pf);
363
364 pci_set_drvdata(pdev, NULL);
365 nfp_cpp_free(pf->cpp);
366
367 kfree(pf->eth_tbl);
368 kfree(pf);
369 pci_release_regions(pdev);
370 pci_disable_device(pdev);
371}
372
373static struct pci_driver nfp_pci_driver = {
374 .name = nfp_driver_name,
375 .id_table = nfp_pci_device_ids,
376 .probe = nfp_pci_probe,
377 .remove = nfp_pci_remove,
378 .sriov_configure = nfp_pcie_sriov_configure,
379};
380
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800381static int __init nfp_main_init(void)
382{
383 int err;
384
385 pr_info("%s: NFP PCIe Driver, Copyright (C) 2014-2017 Netronome Systems\n",
386 nfp_driver_name);
387
388 nfp_net_debugfs_create();
389
Jakub Kicinski63461a02017-02-09 09:17:38 -0800390 err = pci_register_driver(&nfp_pci_driver);
391 if (err < 0)
392 goto err_destroy_debugfs;
393
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800394 err = pci_register_driver(&nfp_netvf_pci_driver);
395 if (err)
Jakub Kicinski63461a02017-02-09 09:17:38 -0800396 goto err_unreg_pf;
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800397
398 return err;
399
Jakub Kicinski63461a02017-02-09 09:17:38 -0800400err_unreg_pf:
401 pci_unregister_driver(&nfp_pci_driver);
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800402err_destroy_debugfs:
403 nfp_net_debugfs_destroy();
404 return err;
405}
406
407static void __exit nfp_main_exit(void)
408{
409 pci_unregister_driver(&nfp_netvf_pci_driver);
Jakub Kicinski63461a02017-02-09 09:17:38 -0800410 pci_unregister_driver(&nfp_pci_driver);
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800411 nfp_net_debugfs_destroy();
412}
413
414module_init(nfp_main_init);
415module_exit(nfp_main_exit);
416
Jakub Kicinski63461a02017-02-09 09:17:38 -0800417MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw");
418MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw");
419MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw");
420MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_2x40.nffw");
421MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_4x10_1x40.nffw");
422MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_8x10.nffw");
423MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x10.nffw");
424MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x25.nffw");
425
Jakub Kicinski2633beb2017-02-09 09:17:28 -0800426MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
427MODULE_LICENSE("GPL");
428MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver.");