xref: /OK3568_Linux_fs/kernel/drivers/fpga/dfl-pci.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Driver for FPGA Device Feature List (DFL) PCIe device
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2017-2018 Intel Corporation, Inc.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Authors:
8*4882a593Smuzhiyun  *   Zhang Yi <Yi.Z.Zhang@intel.com>
9*4882a593Smuzhiyun  *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
10*4882a593Smuzhiyun  *   Joseph Grecco <joe.grecco@intel.com>
11*4882a593Smuzhiyun  *   Enno Luebbers <enno.luebbers@intel.com>
12*4882a593Smuzhiyun  *   Tim Whisonant <tim.whisonant@intel.com>
13*4882a593Smuzhiyun  *   Ananda Ravuri <ananda.ravuri@intel.com>
14*4882a593Smuzhiyun  *   Henry Mitchel <henry.mitchel@intel.com>
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/pci.h>
18*4882a593Smuzhiyun #include <linux/types.h>
19*4882a593Smuzhiyun #include <linux/kernel.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/stddef.h>
22*4882a593Smuzhiyun #include <linux/errno.h>
23*4882a593Smuzhiyun #include <linux/aer.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include "dfl.h"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define DRV_VERSION	"0.8"
28*4882a593Smuzhiyun #define DRV_NAME	"dfl-pci"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct cci_drvdata {
31*4882a593Smuzhiyun 	struct dfl_fpga_cdev *cdev;	/* container device */
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
cci_pci_ioremap_bar0(struct pci_dev * pcidev)34*4882a593Smuzhiyun static void __iomem *cci_pci_ioremap_bar0(struct pci_dev *pcidev)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	if (pcim_iomap_regions(pcidev, BIT(0), DRV_NAME))
37*4882a593Smuzhiyun 		return NULL;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	return pcim_iomap_table(pcidev)[0];
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
cci_pci_alloc_irq(struct pci_dev * pcidev)42*4882a593Smuzhiyun static int cci_pci_alloc_irq(struct pci_dev *pcidev)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	int ret, nvec = pci_msix_vec_count(pcidev);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (nvec <= 0) {
47*4882a593Smuzhiyun 		dev_dbg(&pcidev->dev, "fpga interrupt not supported\n");
48*4882a593Smuzhiyun 		return 0;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	ret = pci_alloc_irq_vectors(pcidev, nvec, nvec, PCI_IRQ_MSIX);
52*4882a593Smuzhiyun 	if (ret < 0)
53*4882a593Smuzhiyun 		return ret;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	return nvec;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
cci_pci_free_irq(struct pci_dev * pcidev)58*4882a593Smuzhiyun static void cci_pci_free_irq(struct pci_dev *pcidev)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	pci_free_irq_vectors(pcidev);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /* PCI Device ID */
64*4882a593Smuzhiyun #define PCIE_DEVICE_ID_PF_INT_5_X		0xBCBD
65*4882a593Smuzhiyun #define PCIE_DEVICE_ID_PF_INT_6_X		0xBCC0
66*4882a593Smuzhiyun #define PCIE_DEVICE_ID_PF_DSC_1_X		0x09C4
67*4882a593Smuzhiyun #define PCIE_DEVICE_ID_INTEL_PAC_N3000		0x0B30
68*4882a593Smuzhiyun #define PCIE_DEVICE_ID_INTEL_PAC_D5005		0x0B2B
69*4882a593Smuzhiyun /* VF Device */
70*4882a593Smuzhiyun #define PCIE_DEVICE_ID_VF_INT_5_X		0xBCBF
71*4882a593Smuzhiyun #define PCIE_DEVICE_ID_VF_INT_6_X		0xBCC1
72*4882a593Smuzhiyun #define PCIE_DEVICE_ID_VF_DSC_1_X		0x09C5
73*4882a593Smuzhiyun #define PCIE_DEVICE_ID_INTEL_PAC_D5005_VF	0x0B2C
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun static struct pci_device_id cci_pcie_id_tbl[] = {
76*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),},
77*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_5_X),},
78*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_6_X),},
79*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_6_X),},
80*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_DSC_1_X),},
81*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_DSC_1_X),},
82*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_N3000),},
83*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005),},
84*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
85*4882a593Smuzhiyun 	{0,}
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
88*4882a593Smuzhiyun 
cci_init_drvdata(struct pci_dev * pcidev)89*4882a593Smuzhiyun static int cci_init_drvdata(struct pci_dev *pcidev)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct cci_drvdata *drvdata;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	drvdata = devm_kzalloc(&pcidev->dev, sizeof(*drvdata), GFP_KERNEL);
94*4882a593Smuzhiyun 	if (!drvdata)
95*4882a593Smuzhiyun 		return -ENOMEM;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	pci_set_drvdata(pcidev, drvdata);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return 0;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
cci_remove_feature_devs(struct pci_dev * pcidev)102*4882a593Smuzhiyun static void cci_remove_feature_devs(struct pci_dev *pcidev)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	/* remove all children feature devices */
107*4882a593Smuzhiyun 	dfl_fpga_feature_devs_remove(drvdata->cdev);
108*4882a593Smuzhiyun 	cci_pci_free_irq(pcidev);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
cci_pci_create_irq_table(struct pci_dev * pcidev,unsigned int nvec)111*4882a593Smuzhiyun static int *cci_pci_create_irq_table(struct pci_dev *pcidev, unsigned int nvec)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	unsigned int i;
114*4882a593Smuzhiyun 	int *table;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	table = kcalloc(nvec, sizeof(int), GFP_KERNEL);
117*4882a593Smuzhiyun 	if (!table)
118*4882a593Smuzhiyun 		return table;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	for (i = 0; i < nvec; i++)
121*4882a593Smuzhiyun 		table[i] = pci_irq_vector(pcidev, i);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	return table;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /* enumerate feature devices under pci device */
cci_enumerate_feature_devs(struct pci_dev * pcidev)127*4882a593Smuzhiyun static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
130*4882a593Smuzhiyun 	int port_num, bar, i, nvec, ret = 0;
131*4882a593Smuzhiyun 	struct dfl_fpga_enum_info *info;
132*4882a593Smuzhiyun 	struct dfl_fpga_cdev *cdev;
133*4882a593Smuzhiyun 	resource_size_t start, len;
134*4882a593Smuzhiyun 	void __iomem *base;
135*4882a593Smuzhiyun 	int *irq_table;
136*4882a593Smuzhiyun 	u32 offset;
137*4882a593Smuzhiyun 	u64 v;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/* allocate enumeration info via pci_dev */
140*4882a593Smuzhiyun 	info = dfl_fpga_enum_info_alloc(&pcidev->dev);
141*4882a593Smuzhiyun 	if (!info)
142*4882a593Smuzhiyun 		return -ENOMEM;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/* add irq info for enumeration if the device support irq */
145*4882a593Smuzhiyun 	nvec = cci_pci_alloc_irq(pcidev);
146*4882a593Smuzhiyun 	if (nvec < 0) {
147*4882a593Smuzhiyun 		dev_err(&pcidev->dev, "Fail to alloc irq %d.\n", nvec);
148*4882a593Smuzhiyun 		ret = nvec;
149*4882a593Smuzhiyun 		goto enum_info_free_exit;
150*4882a593Smuzhiyun 	} else if (nvec) {
151*4882a593Smuzhiyun 		irq_table = cci_pci_create_irq_table(pcidev, nvec);
152*4882a593Smuzhiyun 		if (!irq_table) {
153*4882a593Smuzhiyun 			ret = -ENOMEM;
154*4882a593Smuzhiyun 			goto irq_free_exit;
155*4882a593Smuzhiyun 		}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 		ret = dfl_fpga_enum_info_add_irq(info, nvec, irq_table);
158*4882a593Smuzhiyun 		kfree(irq_table);
159*4882a593Smuzhiyun 		if (ret)
160*4882a593Smuzhiyun 			goto irq_free_exit;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* start to find Device Feature List in Bar 0 */
164*4882a593Smuzhiyun 	base = cci_pci_ioremap_bar0(pcidev);
165*4882a593Smuzhiyun 	if (!base) {
166*4882a593Smuzhiyun 		ret = -ENOMEM;
167*4882a593Smuzhiyun 		goto irq_free_exit;
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/*
171*4882a593Smuzhiyun 	 * PF device has FME and Ports/AFUs, and VF device only has one
172*4882a593Smuzhiyun 	 * Port/AFU. Check them and add related "Device Feature List" info
173*4882a593Smuzhiyun 	 * for the next step enumeration.
174*4882a593Smuzhiyun 	 */
175*4882a593Smuzhiyun 	if (dfl_feature_is_fme(base)) {
176*4882a593Smuzhiyun 		start = pci_resource_start(pcidev, 0);
177*4882a593Smuzhiyun 		len = pci_resource_len(pcidev, 0);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		dfl_fpga_enum_info_add_dfl(info, start, len);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 		/*
182*4882a593Smuzhiyun 		 * find more Device Feature Lists (e.g. Ports) per information
183*4882a593Smuzhiyun 		 * indicated by FME module.
184*4882a593Smuzhiyun 		 */
185*4882a593Smuzhiyun 		v = readq(base + FME_HDR_CAP);
186*4882a593Smuzhiyun 		port_num = FIELD_GET(FME_CAP_NUM_PORTS, v);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 		WARN_ON(port_num > MAX_DFL_FPGA_PORT_NUM);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 		for (i = 0; i < port_num; i++) {
191*4882a593Smuzhiyun 			v = readq(base + FME_HDR_PORT_OFST(i));
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 			/* skip ports which are not implemented. */
194*4882a593Smuzhiyun 			if (!(v & FME_PORT_OFST_IMP))
195*4882a593Smuzhiyun 				continue;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 			/*
198*4882a593Smuzhiyun 			 * add Port's Device Feature List information for next
199*4882a593Smuzhiyun 			 * step enumeration.
200*4882a593Smuzhiyun 			 */
201*4882a593Smuzhiyun 			bar = FIELD_GET(FME_PORT_OFST_BAR_ID, v);
202*4882a593Smuzhiyun 			offset = FIELD_GET(FME_PORT_OFST_DFH_OFST, v);
203*4882a593Smuzhiyun 			start = pci_resource_start(pcidev, bar) + offset;
204*4882a593Smuzhiyun 			len = pci_resource_len(pcidev, bar) - offset;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 			dfl_fpga_enum_info_add_dfl(info, start, len);
207*4882a593Smuzhiyun 		}
208*4882a593Smuzhiyun 	} else if (dfl_feature_is_port(base)) {
209*4882a593Smuzhiyun 		start = pci_resource_start(pcidev, 0);
210*4882a593Smuzhiyun 		len = pci_resource_len(pcidev, 0);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		dfl_fpga_enum_info_add_dfl(info, start, len);
213*4882a593Smuzhiyun 	} else {
214*4882a593Smuzhiyun 		ret = -ENODEV;
215*4882a593Smuzhiyun 		goto irq_free_exit;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* release I/O mappings for next step enumeration */
219*4882a593Smuzhiyun 	pcim_iounmap_regions(pcidev, BIT(0));
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	/* start enumeration with prepared enumeration information */
222*4882a593Smuzhiyun 	cdev = dfl_fpga_feature_devs_enumerate(info);
223*4882a593Smuzhiyun 	if (IS_ERR(cdev)) {
224*4882a593Smuzhiyun 		dev_err(&pcidev->dev, "Enumeration failure\n");
225*4882a593Smuzhiyun 		ret = PTR_ERR(cdev);
226*4882a593Smuzhiyun 		goto irq_free_exit;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	drvdata->cdev = cdev;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun irq_free_exit:
232*4882a593Smuzhiyun 	if (ret)
233*4882a593Smuzhiyun 		cci_pci_free_irq(pcidev);
234*4882a593Smuzhiyun enum_info_free_exit:
235*4882a593Smuzhiyun 	dfl_fpga_enum_info_free(info);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	return ret;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun static
cci_pci_probe(struct pci_dev * pcidev,const struct pci_device_id * pcidevid)241*4882a593Smuzhiyun int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	int ret;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	ret = pcim_enable_device(pcidev);
246*4882a593Smuzhiyun 	if (ret < 0) {
247*4882a593Smuzhiyun 		dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
248*4882a593Smuzhiyun 		return ret;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	ret = pci_enable_pcie_error_reporting(pcidev);
252*4882a593Smuzhiyun 	if (ret && ret != -EINVAL)
253*4882a593Smuzhiyun 		dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	pci_set_master(pcidev);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
258*4882a593Smuzhiyun 		ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
259*4882a593Smuzhiyun 		if (ret)
260*4882a593Smuzhiyun 			goto disable_error_report_exit;
261*4882a593Smuzhiyun 	} else if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
262*4882a593Smuzhiyun 		ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
263*4882a593Smuzhiyun 		if (ret)
264*4882a593Smuzhiyun 			goto disable_error_report_exit;
265*4882a593Smuzhiyun 	} else {
266*4882a593Smuzhiyun 		ret = -EIO;
267*4882a593Smuzhiyun 		dev_err(&pcidev->dev, "No suitable DMA support available.\n");
268*4882a593Smuzhiyun 		goto disable_error_report_exit;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	ret = cci_init_drvdata(pcidev);
272*4882a593Smuzhiyun 	if (ret) {
273*4882a593Smuzhiyun 		dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret);
274*4882a593Smuzhiyun 		goto disable_error_report_exit;
275*4882a593Smuzhiyun 	}
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	ret = cci_enumerate_feature_devs(pcidev);
278*4882a593Smuzhiyun 	if (!ret)
279*4882a593Smuzhiyun 		return ret;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun disable_error_report_exit:
284*4882a593Smuzhiyun 	pci_disable_pcie_error_reporting(pcidev);
285*4882a593Smuzhiyun 	return ret;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
cci_pci_sriov_configure(struct pci_dev * pcidev,int num_vfs)288*4882a593Smuzhiyun static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
291*4882a593Smuzhiyun 	struct dfl_fpga_cdev *cdev = drvdata->cdev;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (!num_vfs) {
294*4882a593Smuzhiyun 		/*
295*4882a593Smuzhiyun 		 * disable SRIOV and then put released ports back to default
296*4882a593Smuzhiyun 		 * PF access mode.
297*4882a593Smuzhiyun 		 */
298*4882a593Smuzhiyun 		pci_disable_sriov(pcidev);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 		dfl_fpga_cdev_config_ports_pf(cdev);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	} else {
303*4882a593Smuzhiyun 		int ret;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 		/*
306*4882a593Smuzhiyun 		 * before enable SRIOV, put released ports into VF access mode
307*4882a593Smuzhiyun 		 * first of all.
308*4882a593Smuzhiyun 		 */
309*4882a593Smuzhiyun 		ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs);
310*4882a593Smuzhiyun 		if (ret)
311*4882a593Smuzhiyun 			return ret;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 		ret = pci_enable_sriov(pcidev, num_vfs);
314*4882a593Smuzhiyun 		if (ret) {
315*4882a593Smuzhiyun 			dfl_fpga_cdev_config_ports_pf(cdev);
316*4882a593Smuzhiyun 			return ret;
317*4882a593Smuzhiyun 		}
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	return num_vfs;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
cci_pci_remove(struct pci_dev * pcidev)323*4882a593Smuzhiyun static void cci_pci_remove(struct pci_dev *pcidev)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	if (dev_is_pf(&pcidev->dev))
326*4882a593Smuzhiyun 		cci_pci_sriov_configure(pcidev, 0);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	cci_remove_feature_devs(pcidev);
329*4882a593Smuzhiyun 	pci_disable_pcie_error_reporting(pcidev);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun static struct pci_driver cci_pci_driver = {
333*4882a593Smuzhiyun 	.name = DRV_NAME,
334*4882a593Smuzhiyun 	.id_table = cci_pcie_id_tbl,
335*4882a593Smuzhiyun 	.probe = cci_pci_probe,
336*4882a593Smuzhiyun 	.remove = cci_pci_remove,
337*4882a593Smuzhiyun 	.sriov_configure = cci_pci_sriov_configure,
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun module_pci_driver(cci_pci_driver);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun MODULE_DESCRIPTION("FPGA DFL PCIe Device Driver");
343*4882a593Smuzhiyun MODULE_AUTHOR("Intel Corporation");
344*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
345