Commit | Line | Data |
---|---|---|
1532e31f GC |
1 | // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) |
2 | /* Copyright(c) 2014 - 2020 Intel Corporation */ | |
dd0f3683 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> | |
dd0f3683 | 19 | #include "adf_dh895xccvf_hw_data.h" |
dd0f3683 | 20 | |
dd0f3683 | 21 | static const struct pci_device_id adf_pci_tbl[] = { |
37b15fa9 GC |
22 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF), }, |
23 | { } | |
dd0f3683 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, | |
1a72d3a6 | 32 | .name = ADF_DH895XCCVF_DEVICE_NAME, |
dd0f3683 TS |
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_DH895XCC_VF: |
dd0f3683 TS |
59 | adf_clean_hw_data_dh895xcciov(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 | ||
dd0f3683 TS |
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; | |
dd0f3683 TS |
83 | |
84 | switch (ent->device) { | |
92db3198 | 85 | case PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF: |
dd0f3683 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; | |
c52b6733 | 119 | adf_init_hw_data_dh895xcciov(accel_dev->hw_device); |
dd0f3683 TS |
120 | |
121 | /* Get Accelerators and Accelerators Engines masks */ | |
122 | hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses); | |
123 | hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses); | |
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)); | |
dd0f3683 TS |
129 | |
130 | accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); | |
dd0f3683 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 */ | |
144 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | |
145 | if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { | |
146 | dev_err(&pdev->dev, "No usable DMA configuration\n"); | |
147 | ret = -EFAULT; | |
148 | goto out_err_disable; | |
149 | } else { | |
150 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | |
151 | } | |
152 | ||
153 | } else { | |
154 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | |
155 | } | |
156 | ||
1a72d3a6 | 157 | if (pci_request_regions(pdev, ADF_DH895XCCVF_DEVICE_NAME)) { |
dd0f3683 TS |
158 | ret = -EFAULT; |
159 | goto out_err_disable; | |
160 | } | |
161 | ||
162 | /* Find and map all the device's BARS */ | |
163 | i = 0; | |
164 | bar_mask = pci_select_bars(pdev, IORESOURCE_MEM); | |
ba439a6c | 165 | for_each_set_bit(bar_nr, &bar_mask, ADF_PCI_MAX_BARS * 2) { |
dd0f3683 TS |
166 | struct adf_bar *bar = &accel_pci_dev->pci_bars[i++]; |
167 | ||
168 | bar->base_addr = pci_resource_start(pdev, bar_nr); | |
169 | if (!bar->base_addr) | |
170 | break; | |
171 | bar->size = pci_resource_len(pdev, bar_nr); | |
172 | bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); | |
173 | if (!bar->virt_addr) { | |
174 | dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); | |
175 | ret = -EFAULT; | |
176 | goto out_err_free_reg; | |
177 | } | |
178 | } | |
179 | pci_set_master(pdev); | |
180 | /* Completion for VF2PF request/response message exchange */ | |
181 | init_completion(&accel_dev->vf.iov_msg_completion); | |
182 | ||
1a72d3a6 | 183 | ret = qat_crypto_dev_config(accel_dev); |
dd0f3683 TS |
184 | if (ret) |
185 | goto out_err_free_reg; | |
186 | ||
25c6ffb2 TS |
187 | set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); |
188 | ||
dd0f3683 TS |
189 | ret = adf_dev_init(accel_dev); |
190 | if (ret) | |
191 | goto out_err_dev_shutdown; | |
192 | ||
193 | ret = adf_dev_start(accel_dev); | |
194 | if (ret) | |
195 | goto out_err_dev_stop; | |
196 | ||
197 | return ret; | |
198 | ||
199 | out_err_dev_stop: | |
200 | adf_dev_stop(accel_dev); | |
201 | out_err_dev_shutdown: | |
202 | adf_dev_shutdown(accel_dev); | |
203 | out_err_free_reg: | |
204 | pci_release_regions(accel_pci_dev->pci_dev); | |
205 | out_err_disable: | |
206 | pci_disable_device(accel_pci_dev->pci_dev); | |
207 | out_err: | |
208 | adf_cleanup_accel(accel_dev); | |
209 | kfree(accel_dev); | |
210 | return ret; | |
211 | } | |
212 | ||
213 | static void adf_remove(struct pci_dev *pdev) | |
214 | { | |
215 | struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); | |
216 | ||
217 | if (!accel_dev) { | |
218 | pr_err("QAT: Driver removal failed\n"); | |
219 | return; | |
220 | } | |
f1420cee | 221 | adf_dev_stop(accel_dev); |
dd0f3683 TS |
222 | adf_dev_shutdown(accel_dev); |
223 | adf_cleanup_accel(accel_dev); | |
224 | adf_cleanup_pci_dev(accel_dev); | |
225 | kfree(accel_dev); | |
226 | } | |
227 | ||
228 | static int __init adfdrv_init(void) | |
229 | { | |
230 | request_module("intel_qat"); | |
231 | ||
232 | if (pci_register_driver(&adf_driver)) { | |
233 | pr_err("QAT: Driver initialization failed\n"); | |
234 | return -EFAULT; | |
235 | } | |
236 | return 0; | |
237 | } | |
238 | ||
239 | static void __exit adfdrv_release(void) | |
240 | { | |
241 | pci_unregister_driver(&adf_driver); | |
242 | adf_clean_vf_map(true); | |
243 | } | |
244 | ||
245 | module_init(adfdrv_init); | |
246 | module_exit(adfdrv_release); | |
247 | ||
248 | MODULE_LICENSE("Dual BSD/GPL"); | |
249 | MODULE_AUTHOR("Intel"); | |
250 | MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); | |
251 | MODULE_VERSION(ADF_DRV_VERSION); |