Merge tag 'memory-controller-drv-tegra-5.13' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / drivers / fpga / dfl-pci.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for FPGA Device Feature List (DFL) PCIe device
4  *
5  * Copyright (C) 2017-2018 Intel Corporation, Inc.
6  *
7  * Authors:
8  *   Zhang Yi <Yi.Z.Zhang@intel.com>
9  *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
10  *   Joseph Grecco <joe.grecco@intel.com>
11  *   Enno Luebbers <enno.luebbers@intel.com>
12  *   Tim Whisonant <tim.whisonant@intel.com>
13  *   Ananda Ravuri <ananda.ravuri@intel.com>
14  *   Henry Mitchel <henry.mitchel@intel.com>
15  */
16
17 #include <linux/pci.h>
18 #include <linux/types.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/stddef.h>
22 #include <linux/errno.h>
23 #include <linux/aer.h>
24
25 #include "dfl.h"
26
27 #define DRV_VERSION     "0.8"
28 #define DRV_NAME        "dfl-pci"
29
30 #define PCI_VSEC_ID_INTEL_DFLS 0x43
31
32 #define PCI_VNDR_DFLS_CNT 0x8
33 #define PCI_VNDR_DFLS_RES 0xc
34
35 #define PCI_VNDR_DFLS_RES_BAR_MASK GENMASK(2, 0)
36 #define PCI_VNDR_DFLS_RES_OFF_MASK GENMASK(31, 3)
37
38 struct cci_drvdata {
39         struct dfl_fpga_cdev *cdev;     /* container device */
40 };
41
42 static void __iomem *cci_pci_ioremap_bar0(struct pci_dev *pcidev)
43 {
44         if (pcim_iomap_regions(pcidev, BIT(0), DRV_NAME))
45                 return NULL;
46
47         return pcim_iomap_table(pcidev)[0];
48 }
49
50 static int cci_pci_alloc_irq(struct pci_dev *pcidev)
51 {
52         int ret, nvec = pci_msix_vec_count(pcidev);
53
54         if (nvec <= 0) {
55                 dev_dbg(&pcidev->dev, "fpga interrupt not supported\n");
56                 return 0;
57         }
58
59         ret = pci_alloc_irq_vectors(pcidev, nvec, nvec, PCI_IRQ_MSIX);
60         if (ret < 0)
61                 return ret;
62
63         return nvec;
64 }
65
66 static void cci_pci_free_irq(struct pci_dev *pcidev)
67 {
68         pci_free_irq_vectors(pcidev);
69 }
70
71 /* PCI Device ID */
72 #define PCIE_DEVICE_ID_PF_INT_5_X       0xBCBD
73 #define PCIE_DEVICE_ID_PF_INT_6_X       0xBCC0
74 #define PCIE_DEVICE_ID_PF_DSC_1_X       0x09C4
75 #define PCIE_DEVICE_ID_INTEL_PAC_N3000  0x0B30
76 /* VF Device */
77 #define PCIE_DEVICE_ID_VF_INT_5_X       0xBCBF
78 #define PCIE_DEVICE_ID_VF_INT_6_X       0xBCC1
79 #define PCIE_DEVICE_ID_VF_DSC_1_X       0x09C5
80
81 static struct pci_device_id cci_pcie_id_tbl[] = {
82         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),},
83         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_5_X),},
84         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_6_X),},
85         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_6_X),},
86         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_DSC_1_X),},
87         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_DSC_1_X),},
88         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_N3000),},
89         {0,}
90 };
91 MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
92
93 static int cci_init_drvdata(struct pci_dev *pcidev)
94 {
95         struct cci_drvdata *drvdata;
96
97         drvdata = devm_kzalloc(&pcidev->dev, sizeof(*drvdata), GFP_KERNEL);
98         if (!drvdata)
99                 return -ENOMEM;
100
101         pci_set_drvdata(pcidev, drvdata);
102
103         return 0;
104 }
105
106 static void cci_remove_feature_devs(struct pci_dev *pcidev)
107 {
108         struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
109
110         /* remove all children feature devices */
111         dfl_fpga_feature_devs_remove(drvdata->cdev);
112         cci_pci_free_irq(pcidev);
113 }
114
115 static int *cci_pci_create_irq_table(struct pci_dev *pcidev, unsigned int nvec)
116 {
117         unsigned int i;
118         int *table;
119
120         table = kcalloc(nvec, sizeof(int), GFP_KERNEL);
121         if (!table)
122                 return table;
123
124         for (i = 0; i < nvec; i++)
125                 table[i] = pci_irq_vector(pcidev, i);
126
127         return table;
128 }
129
130 static int find_dfls_by_vsec(struct pci_dev *pcidev, struct dfl_fpga_enum_info *info)
131 {
132         u32 bir, offset, vndr_hdr, dfl_cnt, dfl_res;
133         int dfl_res_off, i, bars, voff = 0;
134         resource_size_t start, len;
135
136         while ((voff = pci_find_next_ext_capability(pcidev, voff, PCI_EXT_CAP_ID_VNDR))) {
137                 vndr_hdr = 0;
138                 pci_read_config_dword(pcidev, voff + PCI_VNDR_HEADER, &vndr_hdr);
139
140                 if (PCI_VNDR_HEADER_ID(vndr_hdr) == PCI_VSEC_ID_INTEL_DFLS &&
141                     pcidev->vendor == PCI_VENDOR_ID_INTEL)
142                         break;
143         }
144
145         if (!voff) {
146                 dev_dbg(&pcidev->dev, "%s no DFL VSEC found\n", __func__);
147                 return -ENODEV;
148         }
149
150         dfl_cnt = 0;
151         pci_read_config_dword(pcidev, voff + PCI_VNDR_DFLS_CNT, &dfl_cnt);
152         if (dfl_cnt > PCI_STD_NUM_BARS) {
153                 dev_err(&pcidev->dev, "%s too many DFLs %d > %d\n",
154                         __func__, dfl_cnt, PCI_STD_NUM_BARS);
155                 return -EINVAL;
156         }
157
158         dfl_res_off = voff + PCI_VNDR_DFLS_RES;
159         if (dfl_res_off + (dfl_cnt * sizeof(u32)) > PCI_CFG_SPACE_EXP_SIZE) {
160                 dev_err(&pcidev->dev, "%s DFL VSEC too big for PCIe config space\n",
161                         __func__);
162                 return -EINVAL;
163         }
164
165         for (i = 0, bars = 0; i < dfl_cnt; i++, dfl_res_off += sizeof(u32)) {
166                 dfl_res = GENMASK(31, 0);
167                 pci_read_config_dword(pcidev, dfl_res_off, &dfl_res);
168
169                 bir = dfl_res & PCI_VNDR_DFLS_RES_BAR_MASK;
170                 if (bir >= PCI_STD_NUM_BARS) {
171                         dev_err(&pcidev->dev, "%s bad bir number %d\n",
172                                 __func__, bir);
173                         return -EINVAL;
174                 }
175
176                 if (bars & BIT(bir)) {
177                         dev_err(&pcidev->dev, "%s DFL for BAR %d already specified\n",
178                                 __func__, bir);
179                         return -EINVAL;
180                 }
181
182                 bars |= BIT(bir);
183
184                 len = pci_resource_len(pcidev, bir);
185                 offset = dfl_res & PCI_VNDR_DFLS_RES_OFF_MASK;
186                 if (offset >= len) {
187                         dev_err(&pcidev->dev, "%s bad offset %u >= %pa\n",
188                                 __func__, offset, &len);
189                         return -EINVAL;
190                 }
191
192                 dev_dbg(&pcidev->dev, "%s BAR %d offset 0x%x\n", __func__, bir, offset);
193
194                 len -= offset;
195
196                 start = pci_resource_start(pcidev, bir) + offset;
197
198                 dfl_fpga_enum_info_add_dfl(info, start, len);
199         }
200
201         return 0;
202 }
203
204 /* default method of finding dfls starting at offset 0 of bar 0 */
205 static int find_dfls_by_default(struct pci_dev *pcidev,
206                                 struct dfl_fpga_enum_info *info)
207 {
208         int port_num, bar, i, ret = 0;
209         resource_size_t start, len;
210         void __iomem *base;
211         u32 offset;
212         u64 v;
213
214         /* start to find Device Feature List from Bar 0 */
215         base = cci_pci_ioremap_bar0(pcidev);
216         if (!base)
217                 return -ENOMEM;
218
219         /*
220          * PF device has FME and Ports/AFUs, and VF device only has one
221          * Port/AFU. Check them and add related "Device Feature List" info
222          * for the next step enumeration.
223          */
224         if (dfl_feature_is_fme(base)) {
225                 start = pci_resource_start(pcidev, 0);
226                 len = pci_resource_len(pcidev, 0);
227
228                 dfl_fpga_enum_info_add_dfl(info, start, len);
229
230                 /*
231                  * find more Device Feature Lists (e.g. Ports) per information
232                  * indicated by FME module.
233                  */
234                 v = readq(base + FME_HDR_CAP);
235                 port_num = FIELD_GET(FME_CAP_NUM_PORTS, v);
236
237                 WARN_ON(port_num > MAX_DFL_FPGA_PORT_NUM);
238
239                 for (i = 0; i < port_num; i++) {
240                         v = readq(base + FME_HDR_PORT_OFST(i));
241
242                         /* skip ports which are not implemented. */
243                         if (!(v & FME_PORT_OFST_IMP))
244                                 continue;
245
246                         /*
247                          * add Port's Device Feature List information for next
248                          * step enumeration.
249                          */
250                         bar = FIELD_GET(FME_PORT_OFST_BAR_ID, v);
251                         offset = FIELD_GET(FME_PORT_OFST_DFH_OFST, v);
252                         start = pci_resource_start(pcidev, bar) + offset;
253                         len = pci_resource_len(pcidev, bar) - offset;
254
255                         dfl_fpga_enum_info_add_dfl(info, start, len);
256                 }
257         } else if (dfl_feature_is_port(base)) {
258                 start = pci_resource_start(pcidev, 0);
259                 len = pci_resource_len(pcidev, 0);
260
261                 dfl_fpga_enum_info_add_dfl(info, start, len);
262         } else {
263                 ret = -ENODEV;
264         }
265
266         /* release I/O mappings for next step enumeration */
267         pcim_iounmap_regions(pcidev, BIT(0));
268
269         return ret;
270 }
271
272 /* enumerate feature devices under pci device */
273 static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
274 {
275         struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
276         struct dfl_fpga_enum_info *info;
277         struct dfl_fpga_cdev *cdev;
278         int nvec, ret = 0;
279         int *irq_table;
280
281         /* allocate enumeration info via pci_dev */
282         info = dfl_fpga_enum_info_alloc(&pcidev->dev);
283         if (!info)
284                 return -ENOMEM;
285
286         /* add irq info for enumeration if the device support irq */
287         nvec = cci_pci_alloc_irq(pcidev);
288         if (nvec < 0) {
289                 dev_err(&pcidev->dev, "Fail to alloc irq %d.\n", nvec);
290                 ret = nvec;
291                 goto enum_info_free_exit;
292         } else if (nvec) {
293                 irq_table = cci_pci_create_irq_table(pcidev, nvec);
294                 if (!irq_table) {
295                         ret = -ENOMEM;
296                         goto irq_free_exit;
297                 }
298
299                 ret = dfl_fpga_enum_info_add_irq(info, nvec, irq_table);
300                 kfree(irq_table);
301                 if (ret)
302                         goto irq_free_exit;
303         }
304
305         ret = find_dfls_by_vsec(pcidev, info);
306         if (ret == -ENODEV)
307                 ret = find_dfls_by_default(pcidev, info);
308
309         if (ret)
310                 goto irq_free_exit;
311
312         /* start enumeration with prepared enumeration information */
313         cdev = dfl_fpga_feature_devs_enumerate(info);
314         if (IS_ERR(cdev)) {
315                 dev_err(&pcidev->dev, "Enumeration failure\n");
316                 ret = PTR_ERR(cdev);
317                 goto irq_free_exit;
318         }
319
320         drvdata->cdev = cdev;
321
322 irq_free_exit:
323         if (ret)
324                 cci_pci_free_irq(pcidev);
325 enum_info_free_exit:
326         dfl_fpga_enum_info_free(info);
327
328         return ret;
329 }
330
331 static
332 int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
333 {
334         int ret;
335
336         ret = pcim_enable_device(pcidev);
337         if (ret < 0) {
338                 dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
339                 return ret;
340         }
341
342         ret = pci_enable_pcie_error_reporting(pcidev);
343         if (ret && ret != -EINVAL)
344                 dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
345
346         pci_set_master(pcidev);
347
348         if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
349                 ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
350                 if (ret)
351                         goto disable_error_report_exit;
352         } else if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
353                 ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
354                 if (ret)
355                         goto disable_error_report_exit;
356         } else {
357                 ret = -EIO;
358                 dev_err(&pcidev->dev, "No suitable DMA support available.\n");
359                 goto disable_error_report_exit;
360         }
361
362         ret = cci_init_drvdata(pcidev);
363         if (ret) {
364                 dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret);
365                 goto disable_error_report_exit;
366         }
367
368         ret = cci_enumerate_feature_devs(pcidev);
369         if (!ret)
370                 return ret;
371
372         dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
373
374 disable_error_report_exit:
375         pci_disable_pcie_error_reporting(pcidev);
376         return ret;
377 }
378
379 static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
380 {
381         struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
382         struct dfl_fpga_cdev *cdev = drvdata->cdev;
383
384         if (!num_vfs) {
385                 /*
386                  * disable SRIOV and then put released ports back to default
387                  * PF access mode.
388                  */
389                 pci_disable_sriov(pcidev);
390
391                 dfl_fpga_cdev_config_ports_pf(cdev);
392
393         } else {
394                 int ret;
395
396                 /*
397                  * before enable SRIOV, put released ports into VF access mode
398                  * first of all.
399                  */
400                 ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs);
401                 if (ret)
402                         return ret;
403
404                 ret = pci_enable_sriov(pcidev, num_vfs);
405                 if (ret) {
406                         dfl_fpga_cdev_config_ports_pf(cdev);
407                         return ret;
408                 }
409         }
410
411         return num_vfs;
412 }
413
414 static void cci_pci_remove(struct pci_dev *pcidev)
415 {
416         if (dev_is_pf(&pcidev->dev))
417                 cci_pci_sriov_configure(pcidev, 0);
418
419         cci_remove_feature_devs(pcidev);
420         pci_disable_pcie_error_reporting(pcidev);
421 }
422
423 static struct pci_driver cci_pci_driver = {
424         .name = DRV_NAME,
425         .id_table = cci_pcie_id_tbl,
426         .probe = cci_pci_probe,
427         .remove = cci_pci_remove,
428         .sriov_configure = cci_pci_sriov_configure,
429 };
430
431 module_pci_driver(cci_pci_driver);
432
433 MODULE_DESCRIPTION("FPGA DFL PCIe Device Driver");
434 MODULE_AUTHOR("Intel Corporation");
435 MODULE_LICENSE("GPL v2");