]>
Commit | Line | Data |
---|---|---|
1532e31f GC |
1 | // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) |
2 | /* Copyright(c) 2014 - 2020 Intel Corporation */ | |
3771df3c TS |
3 | #include <linux/kernel.h> |
4 | #include <linux/module.h> | |
5 | #include <linux/pci.h> | |
6 | #include <linux/init.h> | |
7 | #include <linux/types.h> | |
8 | #include <linux/fs.h> | |
9 | #include <linux/slab.h> | |
10 | #include <linux/errno.h> | |
11 | #include <linux/device.h> | |
12 | #include <linux/dma-mapping.h> | |
13 | #include <linux/platform_device.h> | |
14 | #include <linux/workqueue.h> | |
15 | #include <linux/io.h> | |
16 | #include <adf_accel_devices.h> | |
17 | #include <adf_common_drv.h> | |
18 | #include <adf_cfg.h> | |
19 | #include "adf_c62xvf_hw_data.h" | |
20 | ||
3771df3c | 21 | static const struct pci_device_id adf_pci_tbl[] = { |
37b15fa9 GC |
22 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_C62X_VF), }, |
23 | { } | |
3771df3c TS |
24 | }; |
25 | MODULE_DEVICE_TABLE(pci, adf_pci_tbl); | |
26 | ||
27 | static int adf_probe(struct pci_dev *dev, const struct pci_device_id *ent); | |
28 | static void adf_remove(struct pci_dev *dev); | |
29 | ||
30 | static struct pci_driver adf_driver = { | |
31 | .id_table = adf_pci_tbl, | |
32 | .name = ADF_C62XVF_DEVICE_NAME, | |
33 | .probe = adf_probe, | |
34 | .remove = adf_remove, | |
35 | }; | |
36 | ||
37 | static void adf_cleanup_pci_dev(struct adf_accel_dev *accel_dev) | |
38 | { | |
39 | pci_release_regions(accel_dev->accel_pci_dev.pci_dev); | |
40 | pci_disable_device(accel_dev->accel_pci_dev.pci_dev); | |
41 | } | |
42 | ||
43 | static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) | |
44 | { | |
45 | struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; | |
46 | struct adf_accel_dev *pf; | |
47 | int i; | |
48 | ||
49 | for (i = 0; i < ADF_PCI_MAX_BARS; i++) { | |
50 | struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; | |
51 | ||
52 | if (bar->virt_addr) | |
53 | pci_iounmap(accel_pci_dev->pci_dev, bar->virt_addr); | |
54 | } | |
55 | ||
56 | if (accel_dev->hw_device) { | |
57 | switch (accel_pci_dev->pci_dev->device) { | |
92db3198 | 58 | case PCI_DEVICE_ID_INTEL_QAT_C62X_VF: |
3771df3c TS |
59 | adf_clean_hw_data_c62xiov(accel_dev->hw_device); |
60 | break; | |
61 | default: | |
62 | break; | |
63 | } | |
64 | kfree(accel_dev->hw_device); | |
65 | accel_dev->hw_device = NULL; | |
66 | } | |
67 | adf_cfg_dev_remove(accel_dev); | |
68 | debugfs_remove(accel_dev->debugfs_dir); | |
69 | pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); | |
70 | adf_devmgr_rm_dev(accel_dev, pf); | |
71 | } | |
72 | ||
73 | static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |
74 | { | |
75 | struct adf_accel_dev *accel_dev; | |
76 | struct adf_accel_dev *pf; | |
77 | struct adf_accel_pci *accel_pci_dev; | |
78 | struct adf_hw_device_data *hw_data; | |
79 | char name[ADF_DEVICE_NAME_LENGTH]; | |
80 | unsigned int i, bar_nr; | |
ba439a6c WL |
81 | unsigned long bar_mask; |
82 | int ret; | |
3771df3c TS |
83 | |
84 | switch (ent->device) { | |
92db3198 | 85 | case PCI_DEVICE_ID_INTEL_QAT_C62X_VF: |
3771df3c TS |
86 | break; |
87 | default: | |
88 | dev_err(&pdev->dev, "Invalid device 0x%x.\n", ent->device); | |
89 | return -ENODEV; | |
90 | } | |
91 | ||
92 | accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL, | |
93 | dev_to_node(&pdev->dev)); | |
94 | if (!accel_dev) | |
95 | return -ENOMEM; | |
96 | ||
97 | accel_dev->is_vf = true; | |
98 | pf = adf_devmgr_pci_to_accel_dev(pdev->physfn); | |
99 | accel_pci_dev = &accel_dev->accel_pci_dev; | |
100 | accel_pci_dev->pci_dev = pdev; | |
101 | ||
102 | /* Add accel device to accel table */ | |
103 | if (adf_devmgr_add_dev(accel_dev, pf)) { | |
104 | dev_err(&pdev->dev, "Failed to add new accelerator device.\n"); | |
105 | kfree(accel_dev); | |
106 | return -EFAULT; | |
107 | } | |
108 | INIT_LIST_HEAD(&accel_dev->crypto_list); | |
109 | ||
110 | accel_dev->owner = THIS_MODULE; | |
111 | /* Allocate and configure device configuration structure */ | |
112 | hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL, | |
113 | dev_to_node(&pdev->dev)); | |
114 | if (!hw_data) { | |
115 | ret = -ENOMEM; | |
116 | goto out_err; | |
117 | } | |
118 | accel_dev->hw_device = hw_data; | |
119 | adf_init_hw_data_c62xiov(accel_dev->hw_device); | |
120 | ||
121 | /* Get Accelerators and Accelerators Engines masks */ | |
7b07ed50 GC |
122 | hw_data->accel_mask = hw_data->get_accel_mask(hw_data); |
123 | hw_data->ae_mask = hw_data->get_ae_mask(hw_data); | |
3771df3c TS |
124 | accel_pci_dev->sku = hw_data->get_sku(hw_data); |
125 | ||
126 | /* Create dev top level debugfs entry */ | |
4eb3f795 GC |
127 | snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, |
128 | hw_data->dev_class->name, pci_name(pdev)); | |
3771df3c TS |
129 | |
130 | accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); | |
3771df3c TS |
131 | |
132 | /* Create device configuration table */ | |
133 | ret = adf_cfg_dev_add(accel_dev); | |
134 | if (ret) | |
135 | goto out_err; | |
136 | ||
137 | /* enable PCI device */ | |
138 | if (pci_enable_device(pdev)) { | |
139 | ret = -EFAULT; | |
140 | goto out_err; | |
141 | } | |
142 | ||
143 | /* set dma identifier */ | |
ae1f5043 | 144 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)); |
6e422cce CJ |
145 | if (ret) { |
146 | dev_err(&pdev->dev, "No usable DMA configuration\n"); | |
147 | goto out_err_disable; | |
3771df3c TS |
148 | } |
149 | ||
150 | if (pci_request_regions(pdev, ADF_C62XVF_DEVICE_NAME)) { | |
151 | ret = -EFAULT; | |
152 | goto out_err_disable; | |
153 | } | |
154 | ||
155 | /* Find and map all the device's BARS */ | |
156 | i = 0; | |
157 | bar_mask = pci_select_bars(pdev, IORESOURCE_MEM); | |
ba439a6c | 158 | for_each_set_bit(bar_nr, &bar_mask, ADF_PCI_MAX_BARS * 2) { |
3771df3c TS |
159 | struct adf_bar *bar = &accel_pci_dev->pci_bars[i++]; |
160 | ||
161 | bar->base_addr = pci_resource_start(pdev, bar_nr); | |
162 | if (!bar->base_addr) | |
163 | break; | |
164 | bar->size = pci_resource_len(pdev, bar_nr); | |
165 | bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); | |
166 | if (!bar->virt_addr) { | |
167 | dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); | |
168 | ret = -EFAULT; | |
169 | goto out_err_free_reg; | |
170 | } | |
171 | } | |
172 | pci_set_master(pdev); | |
173 | /* Completion for VF2PF request/response message exchange */ | |
174 | init_completion(&accel_dev->vf.iov_msg_completion); | |
175 | ||
176 | ret = qat_crypto_dev_config(accel_dev); | |
177 | if (ret) | |
178 | goto out_err_free_reg; | |
179 | ||
180 | ret = adf_dev_init(accel_dev); | |
181 | if (ret) | |
182 | goto out_err_dev_shutdown; | |
183 | ||
8609f5cf TZ |
184 | set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); |
185 | ||
3771df3c TS |
186 | ret = adf_dev_start(accel_dev); |
187 | if (ret) | |
188 | goto out_err_dev_stop; | |
189 | ||
190 | return ret; | |
191 | ||
192 | out_err_dev_stop: | |
193 | adf_dev_stop(accel_dev); | |
194 | out_err_dev_shutdown: | |
195 | adf_dev_shutdown(accel_dev); | |
196 | out_err_free_reg: | |
197 | pci_release_regions(accel_pci_dev->pci_dev); | |
198 | out_err_disable: | |
199 | pci_disable_device(accel_pci_dev->pci_dev); | |
200 | out_err: | |
201 | adf_cleanup_accel(accel_dev); | |
202 | kfree(accel_dev); | |
203 | return ret; | |
204 | } | |
205 | ||
206 | static void adf_remove(struct pci_dev *pdev) | |
207 | { | |
208 | struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); | |
209 | ||
210 | if (!accel_dev) { | |
211 | pr_err("QAT: Driver removal failed\n"); | |
212 | return; | |
213 | } | |
8af4a436 | 214 | adf_flush_vf_wq(accel_dev); |
f1420cee | 215 | adf_dev_stop(accel_dev); |
3771df3c TS |
216 | adf_dev_shutdown(accel_dev); |
217 | adf_cleanup_accel(accel_dev); | |
218 | adf_cleanup_pci_dev(accel_dev); | |
219 | kfree(accel_dev); | |
220 | } | |
221 | ||
222 | static int __init adfdrv_init(void) | |
223 | { | |
224 | request_module("intel_qat"); | |
225 | ||
226 | if (pci_register_driver(&adf_driver)) { | |
227 | pr_err("QAT: Driver initialization failed\n"); | |
228 | return -EFAULT; | |
229 | } | |
230 | return 0; | |
231 | } | |
232 | ||
233 | static void __exit adfdrv_release(void) | |
234 | { | |
235 | pci_unregister_driver(&adf_driver); | |
236 | adf_clean_vf_map(true); | |
237 | } | |
238 | ||
239 | module_init(adfdrv_init); | |
240 | module_exit(adfdrv_release); | |
241 | ||
242 | MODULE_LICENSE("Dual BSD/GPL"); | |
243 | MODULE_AUTHOR("Intel"); | |
244 | MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); | |
245 | MODULE_VERSION(ADF_DRV_VERSION); |