Commit | Line | Data |
---|---|---|
8cfab3cf | 1 | // SPDX-License-Identifier: GPL-2.0 |
349e7a85 KVA |
2 | /** |
3 | * Test driver to test endpoint functionality | |
4 | * | |
5 | * Copyright (C) 2017 Texas Instruments | |
6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | |
349e7a85 KVA |
7 | */ |
8 | ||
9 | #include <linux/crc32.h> | |
10 | #include <linux/delay.h> | |
11 | #include <linux/io.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/slab.h> | |
14 | #include <linux/pci_ids.h> | |
15 | #include <linux/random.h> | |
16 | ||
17 | #include <linux/pci-epc.h> | |
18 | #include <linux/pci-epf.h> | |
19 | #include <linux/pci_regs.h> | |
20 | ||
e8817de7 GP |
21 | #define IRQ_TYPE_LEGACY 0 |
22 | #define IRQ_TYPE_MSI 1 | |
c2e00e31 | 23 | #define IRQ_TYPE_MSIX 2 |
e8817de7 | 24 | |
349e7a85 KVA |
25 | #define COMMAND_RAISE_LEGACY_IRQ BIT(0) |
26 | #define COMMAND_RAISE_MSI_IRQ BIT(1) | |
c2e00e31 | 27 | #define COMMAND_RAISE_MSIX_IRQ BIT(2) |
e8817de7 GP |
28 | #define COMMAND_READ BIT(3) |
29 | #define COMMAND_WRITE BIT(4) | |
30 | #define COMMAND_COPY BIT(5) | |
349e7a85 KVA |
31 | |
32 | #define STATUS_READ_SUCCESS BIT(0) | |
33 | #define STATUS_READ_FAIL BIT(1) | |
34 | #define STATUS_WRITE_SUCCESS BIT(2) | |
35 | #define STATUS_WRITE_FAIL BIT(3) | |
36 | #define STATUS_COPY_SUCCESS BIT(4) | |
37 | #define STATUS_COPY_FAIL BIT(5) | |
38 | #define STATUS_IRQ_RAISED BIT(6) | |
39 | #define STATUS_SRC_ADDR_INVALID BIT(7) | |
40 | #define STATUS_DST_ADDR_INVALID BIT(8) | |
41 | ||
42 | #define TIMER_RESOLUTION 1 | |
43 | ||
44 | static struct workqueue_struct *kpcitest_workqueue; | |
45 | ||
46 | struct pci_epf_test { | |
47 | void *reg[6]; | |
48 | struct pci_epf *epf; | |
3235b994 | 49 | enum pci_barno test_reg_bar; |
702a3ed9 | 50 | bool linkup_notifier; |
c2e00e31 | 51 | bool msix_available; |
349e7a85 KVA |
52 | struct delayed_work cmd_handler; |
53 | }; | |
54 | ||
55 | struct pci_epf_test_reg { | |
56 | u32 magic; | |
57 | u32 command; | |
58 | u32 status; | |
59 | u64 src_addr; | |
60 | u64 dst_addr; | |
61 | u32 size; | |
62 | u32 checksum; | |
e8817de7 GP |
63 | u32 irq_type; |
64 | u32 irq_number; | |
349e7a85 KVA |
65 | } __packed; |
66 | ||
67 | static struct pci_epf_header test_header = { | |
68 | .vendorid = PCI_ANY_ID, | |
69 | .deviceid = PCI_ANY_ID, | |
70 | .baseclass_code = PCI_CLASS_OTHERS, | |
71 | .interrupt_pin = PCI_INTERRUPT_INTA, | |
72 | }; | |
73 | ||
3235b994 KVA |
74 | struct pci_epf_test_data { |
75 | enum pci_barno test_reg_bar; | |
702a3ed9 | 76 | bool linkup_notifier; |
3235b994 KVA |
77 | }; |
78 | ||
bf597574 | 79 | static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; |
349e7a85 KVA |
80 | |
81 | static int pci_epf_test_copy(struct pci_epf_test *epf_test) | |
82 | { | |
83 | int ret; | |
84 | void __iomem *src_addr; | |
85 | void __iomem *dst_addr; | |
86 | phys_addr_t src_phys_addr; | |
87 | phys_addr_t dst_phys_addr; | |
88 | struct pci_epf *epf = epf_test->epf; | |
89 | struct device *dev = &epf->dev; | |
90 | struct pci_epc *epc = epf->epc; | |
3235b994 KVA |
91 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
92 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | |
349e7a85 KVA |
93 | |
94 | src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size); | |
95 | if (!src_addr) { | |
798c0441 | 96 | dev_err(dev, "Failed to allocate source address\n"); |
349e7a85 KVA |
97 | reg->status = STATUS_SRC_ADDR_INVALID; |
98 | ret = -ENOMEM; | |
99 | goto err; | |
100 | } | |
101 | ||
4494738d CP |
102 | ret = pci_epc_map_addr(epc, epf->func_no, src_phys_addr, reg->src_addr, |
103 | reg->size); | |
349e7a85 | 104 | if (ret) { |
798c0441 | 105 | dev_err(dev, "Failed to map source address\n"); |
349e7a85 KVA |
106 | reg->status = STATUS_SRC_ADDR_INVALID; |
107 | goto err_src_addr; | |
108 | } | |
109 | ||
110 | dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size); | |
111 | if (!dst_addr) { | |
798c0441 | 112 | dev_err(dev, "Failed to allocate destination address\n"); |
349e7a85 KVA |
113 | reg->status = STATUS_DST_ADDR_INVALID; |
114 | ret = -ENOMEM; | |
115 | goto err_src_map_addr; | |
116 | } | |
117 | ||
4494738d CP |
118 | ret = pci_epc_map_addr(epc, epf->func_no, dst_phys_addr, reg->dst_addr, |
119 | reg->size); | |
349e7a85 | 120 | if (ret) { |
798c0441 | 121 | dev_err(dev, "Failed to map destination address\n"); |
349e7a85 KVA |
122 | reg->status = STATUS_DST_ADDR_INVALID; |
123 | goto err_dst_addr; | |
124 | } | |
125 | ||
126 | memcpy(dst_addr, src_addr, reg->size); | |
127 | ||
4494738d | 128 | pci_epc_unmap_addr(epc, epf->func_no, dst_phys_addr); |
349e7a85 KVA |
129 | |
130 | err_dst_addr: | |
131 | pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size); | |
132 | ||
133 | err_src_map_addr: | |
4494738d | 134 | pci_epc_unmap_addr(epc, epf->func_no, src_phys_addr); |
349e7a85 KVA |
135 | |
136 | err_src_addr: | |
137 | pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size); | |
138 | ||
139 | err: | |
140 | return ret; | |
141 | } | |
142 | ||
143 | static int pci_epf_test_read(struct pci_epf_test *epf_test) | |
144 | { | |
145 | int ret; | |
146 | void __iomem *src_addr; | |
147 | void *buf; | |
148 | u32 crc32; | |
149 | phys_addr_t phys_addr; | |
150 | struct pci_epf *epf = epf_test->epf; | |
151 | struct device *dev = &epf->dev; | |
152 | struct pci_epc *epc = epf->epc; | |
3235b994 KVA |
153 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
154 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | |
349e7a85 KVA |
155 | |
156 | src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); | |
157 | if (!src_addr) { | |
798c0441 | 158 | dev_err(dev, "Failed to allocate address\n"); |
349e7a85 KVA |
159 | reg->status = STATUS_SRC_ADDR_INVALID; |
160 | ret = -ENOMEM; | |
161 | goto err; | |
162 | } | |
163 | ||
4494738d CP |
164 | ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->src_addr, |
165 | reg->size); | |
349e7a85 | 166 | if (ret) { |
798c0441 | 167 | dev_err(dev, "Failed to map address\n"); |
349e7a85 KVA |
168 | reg->status = STATUS_SRC_ADDR_INVALID; |
169 | goto err_addr; | |
170 | } | |
171 | ||
172 | buf = kzalloc(reg->size, GFP_KERNEL); | |
173 | if (!buf) { | |
174 | ret = -ENOMEM; | |
175 | goto err_map_addr; | |
176 | } | |
177 | ||
726dabfd | 178 | memcpy_fromio(buf, src_addr, reg->size); |
349e7a85 KVA |
179 | |
180 | crc32 = crc32_le(~0, buf, reg->size); | |
181 | if (crc32 != reg->checksum) | |
182 | ret = -EIO; | |
183 | ||
184 | kfree(buf); | |
185 | ||
186 | err_map_addr: | |
4494738d | 187 | pci_epc_unmap_addr(epc, epf->func_no, phys_addr); |
349e7a85 KVA |
188 | |
189 | err_addr: | |
190 | pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size); | |
191 | ||
192 | err: | |
193 | return ret; | |
194 | } | |
195 | ||
196 | static int pci_epf_test_write(struct pci_epf_test *epf_test) | |
197 | { | |
198 | int ret; | |
199 | void __iomem *dst_addr; | |
200 | void *buf; | |
201 | phys_addr_t phys_addr; | |
202 | struct pci_epf *epf = epf_test->epf; | |
203 | struct device *dev = &epf->dev; | |
204 | struct pci_epc *epc = epf->epc; | |
3235b994 KVA |
205 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
206 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | |
349e7a85 KVA |
207 | |
208 | dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); | |
209 | if (!dst_addr) { | |
798c0441 | 210 | dev_err(dev, "Failed to allocate address\n"); |
349e7a85 KVA |
211 | reg->status = STATUS_DST_ADDR_INVALID; |
212 | ret = -ENOMEM; | |
213 | goto err; | |
214 | } | |
215 | ||
4494738d CP |
216 | ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->dst_addr, |
217 | reg->size); | |
349e7a85 | 218 | if (ret) { |
798c0441 | 219 | dev_err(dev, "Failed to map address\n"); |
349e7a85 KVA |
220 | reg->status = STATUS_DST_ADDR_INVALID; |
221 | goto err_addr; | |
222 | } | |
223 | ||
224 | buf = kzalloc(reg->size, GFP_KERNEL); | |
225 | if (!buf) { | |
226 | ret = -ENOMEM; | |
227 | goto err_map_addr; | |
228 | } | |
229 | ||
230 | get_random_bytes(buf, reg->size); | |
231 | reg->checksum = crc32_le(~0, buf, reg->size); | |
232 | ||
726dabfd | 233 | memcpy_toio(dst_addr, buf, reg->size); |
349e7a85 KVA |
234 | |
235 | /* | |
236 | * wait 1ms inorder for the write to complete. Without this delay L3 | |
237 | * error in observed in the host system. | |
238 | */ | |
9f96b9b7 | 239 | usleep_range(1000, 2000); |
349e7a85 KVA |
240 | |
241 | kfree(buf); | |
242 | ||
243 | err_map_addr: | |
4494738d | 244 | pci_epc_unmap_addr(epc, epf->func_no, phys_addr); |
349e7a85 KVA |
245 | |
246 | err_addr: | |
247 | pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size); | |
248 | ||
249 | err: | |
250 | return ret; | |
251 | } | |
252 | ||
e8817de7 GP |
253 | static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, |
254 | u16 irq) | |
349e7a85 | 255 | { |
349e7a85 | 256 | struct pci_epf *epf = epf_test->epf; |
e8817de7 | 257 | struct device *dev = &epf->dev; |
349e7a85 | 258 | struct pci_epc *epc = epf->epc; |
3235b994 KVA |
259 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
260 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | |
349e7a85 KVA |
261 | |
262 | reg->status |= STATUS_IRQ_RAISED; | |
e8817de7 GP |
263 | |
264 | switch (irq_type) { | |
265 | case IRQ_TYPE_LEGACY: | |
4494738d | 266 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, 0); |
e8817de7 GP |
267 | break; |
268 | case IRQ_TYPE_MSI: | |
4494738d | 269 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, irq); |
e8817de7 | 270 | break; |
c2e00e31 GP |
271 | case IRQ_TYPE_MSIX: |
272 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSIX, irq); | |
273 | break; | |
e8817de7 GP |
274 | default: |
275 | dev_err(dev, "Failed to raise IRQ, unknown type\n"); | |
276 | break; | |
277 | } | |
349e7a85 KVA |
278 | } |
279 | ||
280 | static void pci_epf_test_cmd_handler(struct work_struct *work) | |
281 | { | |
282 | int ret; | |
e8817de7 | 283 | int count; |
3ecf3232 | 284 | u32 command; |
349e7a85 KVA |
285 | struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, |
286 | cmd_handler.work); | |
287 | struct pci_epf *epf = epf_test->epf; | |
e8817de7 | 288 | struct device *dev = &epf->dev; |
349e7a85 | 289 | struct pci_epc *epc = epf->epc; |
3235b994 KVA |
290 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
291 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | |
349e7a85 | 292 | |
3ecf3232 KVA |
293 | command = reg->command; |
294 | if (!command) | |
349e7a85 KVA |
295 | goto reset_handler; |
296 | ||
3ecf3232 | 297 | reg->command = 0; |
3235b994 | 298 | reg->status = 0; |
3ecf3232 | 299 | |
c2e00e31 | 300 | if (reg->irq_type > IRQ_TYPE_MSIX) { |
e8817de7 GP |
301 | dev_err(dev, "Failed to detect IRQ type\n"); |
302 | goto reset_handler; | |
303 | } | |
749aaf33 | 304 | |
3ecf3232 | 305 | if (command & COMMAND_RAISE_LEGACY_IRQ) { |
349e7a85 | 306 | reg->status = STATUS_IRQ_RAISED; |
4494738d | 307 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, 0); |
349e7a85 KVA |
308 | goto reset_handler; |
309 | } | |
310 | ||
3ecf3232 | 311 | if (command & COMMAND_WRITE) { |
349e7a85 KVA |
312 | ret = pci_epf_test_write(epf_test); |
313 | if (ret) | |
314 | reg->status |= STATUS_WRITE_FAIL; | |
315 | else | |
316 | reg->status |= STATUS_WRITE_SUCCESS; | |
e8817de7 GP |
317 | pci_epf_test_raise_irq(epf_test, reg->irq_type, |
318 | reg->irq_number); | |
349e7a85 KVA |
319 | goto reset_handler; |
320 | } | |
321 | ||
3ecf3232 | 322 | if (command & COMMAND_READ) { |
349e7a85 KVA |
323 | ret = pci_epf_test_read(epf_test); |
324 | if (!ret) | |
325 | reg->status |= STATUS_READ_SUCCESS; | |
326 | else | |
327 | reg->status |= STATUS_READ_FAIL; | |
e8817de7 GP |
328 | pci_epf_test_raise_irq(epf_test, reg->irq_type, |
329 | reg->irq_number); | |
349e7a85 KVA |
330 | goto reset_handler; |
331 | } | |
332 | ||
3ecf3232 | 333 | if (command & COMMAND_COPY) { |
349e7a85 KVA |
334 | ret = pci_epf_test_copy(epf_test); |
335 | if (!ret) | |
336 | reg->status |= STATUS_COPY_SUCCESS; | |
337 | else | |
338 | reg->status |= STATUS_COPY_FAIL; | |
e8817de7 GP |
339 | pci_epf_test_raise_irq(epf_test, reg->irq_type, |
340 | reg->irq_number); | |
349e7a85 KVA |
341 | goto reset_handler; |
342 | } | |
343 | ||
3ecf3232 | 344 | if (command & COMMAND_RAISE_MSI_IRQ) { |
e8817de7 GP |
345 | count = pci_epc_get_msi(epc, epf->func_no); |
346 | if (reg->irq_number > count || count <= 0) | |
349e7a85 KVA |
347 | goto reset_handler; |
348 | reg->status = STATUS_IRQ_RAISED; | |
e8817de7 GP |
349 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, |
350 | reg->irq_number); | |
349e7a85 KVA |
351 | goto reset_handler; |
352 | } | |
353 | ||
c2e00e31 GP |
354 | if (command & COMMAND_RAISE_MSIX_IRQ) { |
355 | count = pci_epc_get_msix(epc, epf->func_no); | |
356 | if (reg->irq_number > count || count <= 0) | |
357 | goto reset_handler; | |
358 | reg->status = STATUS_IRQ_RAISED; | |
359 | pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSIX, | |
360 | reg->irq_number); | |
361 | goto reset_handler; | |
362 | } | |
363 | ||
349e7a85 | 364 | reset_handler: |
349e7a85 KVA |
365 | queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, |
366 | msecs_to_jiffies(1)); | |
367 | } | |
368 | ||
369 | static void pci_epf_test_linkup(struct pci_epf *epf) | |
370 | { | |
371 | struct pci_epf_test *epf_test = epf_get_drvdata(epf); | |
372 | ||
373 | queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, | |
374 | msecs_to_jiffies(1)); | |
375 | } | |
376 | ||
377 | static void pci_epf_test_unbind(struct pci_epf *epf) | |
378 | { | |
379 | struct pci_epf_test *epf_test = epf_get_drvdata(epf); | |
380 | struct pci_epc *epc = epf->epc; | |
77d08dbd | 381 | struct pci_epf_bar *epf_bar; |
349e7a85 KVA |
382 | int bar; |
383 | ||
384 | cancel_delayed_work(&epf_test->cmd_handler); | |
385 | pci_epc_stop(epc); | |
386 | for (bar = BAR_0; bar <= BAR_5; bar++) { | |
77d08dbd NC |
387 | epf_bar = &epf->bar[bar]; |
388 | ||
349e7a85 KVA |
389 | if (epf_test->reg[bar]) { |
390 | pci_epf_free_space(epf, epf_test->reg[bar], bar); | |
77d08dbd | 391 | pci_epc_clear_bar(epc, epf->func_no, epf_bar); |
349e7a85 KVA |
392 | } |
393 | } | |
394 | } | |
395 | ||
396 | static int pci_epf_test_set_bar(struct pci_epf *epf) | |
397 | { | |
349e7a85 KVA |
398 | int bar; |
399 | int ret; | |
400 | struct pci_epf_bar *epf_bar; | |
401 | struct pci_epc *epc = epf->epc; | |
402 | struct device *dev = &epf->dev; | |
403 | struct pci_epf_test *epf_test = epf_get_drvdata(epf); | |
3235b994 | 404 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
349e7a85 | 405 | |
349e7a85 KVA |
406 | for (bar = BAR_0; bar <= BAR_5; bar++) { |
407 | epf_bar = &epf->bar[bar]; | |
bf597574 | 408 | |
bc4a4897 | 409 | ret = pci_epc_set_bar(epc, epf->func_no, epf_bar); |
349e7a85 KVA |
410 | if (ret) { |
411 | pci_epf_free_space(epf, epf_test->reg[bar], bar); | |
798c0441 | 412 | dev_err(dev, "Failed to set BAR%d\n", bar); |
3235b994 | 413 | if (bar == test_reg_bar) |
349e7a85 KVA |
414 | return ret; |
415 | } | |
fca83058 NC |
416 | /* |
417 | * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 | |
418 | * if the specific implementation required a 64-bit BAR, | |
419 | * even if we only requested a 32-bit BAR. | |
420 | */ | |
421 | if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) | |
422 | bar++; | |
349e7a85 KVA |
423 | } |
424 | ||
425 | return 0; | |
426 | } | |
427 | ||
428 | static int pci_epf_test_alloc_space(struct pci_epf *epf) | |
429 | { | |
430 | struct pci_epf_test *epf_test = epf_get_drvdata(epf); | |
431 | struct device *dev = &epf->dev; | |
b866c56b | 432 | struct pci_epf_bar *epf_bar; |
349e7a85 KVA |
433 | void *base; |
434 | int bar; | |
3235b994 | 435 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
349e7a85 KVA |
436 | |
437 | base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg), | |
3235b994 | 438 | test_reg_bar); |
349e7a85 | 439 | if (!base) { |
798c0441 | 440 | dev_err(dev, "Failed to allocated register space\n"); |
349e7a85 KVA |
441 | return -ENOMEM; |
442 | } | |
3235b994 | 443 | epf_test->reg[test_reg_bar] = base; |
349e7a85 | 444 | |
3235b994 | 445 | for (bar = BAR_0; bar <= BAR_5; bar++) { |
b866c56b | 446 | epf_bar = &epf->bar[bar]; |
3235b994 KVA |
447 | if (bar == test_reg_bar) |
448 | continue; | |
449 | base = pci_epf_alloc_space(epf, bar_size[bar], bar); | |
349e7a85 | 450 | if (!base) |
798c0441 | 451 | dev_err(dev, "Failed to allocate space for BAR%d\n", |
349e7a85 KVA |
452 | bar); |
453 | epf_test->reg[bar] = base; | |
b866c56b KVA |
454 | if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) |
455 | bar++; | |
349e7a85 KVA |
456 | } |
457 | ||
458 | return 0; | |
459 | } | |
460 | ||
461 | static int pci_epf_test_bind(struct pci_epf *epf) | |
462 | { | |
463 | int ret; | |
702a3ed9 | 464 | struct pci_epf_test *epf_test = epf_get_drvdata(epf); |
349e7a85 KVA |
465 | struct pci_epf_header *header = epf->header; |
466 | struct pci_epc *epc = epf->epc; | |
467 | struct device *dev = &epf->dev; | |
468 | ||
469 | if (WARN_ON_ONCE(!epc)) | |
470 | return -EINVAL; | |
471 | ||
1d906b22 GP |
472 | if (epc->features & EPC_FEATURE_NO_LINKUP_NOTIFIER) |
473 | epf_test->linkup_notifier = false; | |
474 | else | |
475 | epf_test->linkup_notifier = true; | |
476 | ||
c2e00e31 GP |
477 | epf_test->msix_available = epc->features & EPC_FEATURE_MSIX_AVAILABLE; |
478 | ||
1d906b22 GP |
479 | epf_test->test_reg_bar = EPC_FEATURE_GET_BAR(epc->features); |
480 | ||
4494738d | 481 | ret = pci_epc_write_header(epc, epf->func_no, header); |
349e7a85 | 482 | if (ret) { |
798c0441 | 483 | dev_err(dev, "Configuration header write failed\n"); |
349e7a85 KVA |
484 | return ret; |
485 | } | |
486 | ||
487 | ret = pci_epf_test_alloc_space(epf); | |
488 | if (ret) | |
489 | return ret; | |
490 | ||
491 | ret = pci_epf_test_set_bar(epf); | |
492 | if (ret) | |
493 | return ret; | |
494 | ||
4494738d | 495 | ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts); |
e8817de7 GP |
496 | if (ret) { |
497 | dev_err(dev, "MSI configuration failed\n"); | |
349e7a85 | 498 | return ret; |
e8817de7 | 499 | } |
349e7a85 | 500 | |
c2e00e31 GP |
501 | if (epf_test->msix_available) { |
502 | ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts); | |
503 | if (ret) { | |
504 | dev_err(dev, "MSI-X configuration failed\n"); | |
505 | return ret; | |
506 | } | |
507 | } | |
508 | ||
702a3ed9 KVA |
509 | if (!epf_test->linkup_notifier) |
510 | queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work); | |
511 | ||
349e7a85 KVA |
512 | return 0; |
513 | } | |
514 | ||
3235b994 KVA |
515 | static const struct pci_epf_device_id pci_epf_test_ids[] = { |
516 | { | |
517 | .name = "pci_epf_test", | |
518 | }, | |
519 | {}, | |
520 | }; | |
521 | ||
349e7a85 KVA |
522 | static int pci_epf_test_probe(struct pci_epf *epf) |
523 | { | |
524 | struct pci_epf_test *epf_test; | |
525 | struct device *dev = &epf->dev; | |
3235b994 KVA |
526 | const struct pci_epf_device_id *match; |
527 | struct pci_epf_test_data *data; | |
528 | enum pci_barno test_reg_bar = BAR_0; | |
702a3ed9 | 529 | bool linkup_notifier = true; |
3235b994 KVA |
530 | |
531 | match = pci_epf_match_device(pci_epf_test_ids, epf); | |
532 | data = (struct pci_epf_test_data *)match->driver_data; | |
702a3ed9 | 533 | if (data) { |
3235b994 | 534 | test_reg_bar = data->test_reg_bar; |
702a3ed9 KVA |
535 | linkup_notifier = data->linkup_notifier; |
536 | } | |
349e7a85 KVA |
537 | |
538 | epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL); | |
539 | if (!epf_test) | |
540 | return -ENOMEM; | |
541 | ||
542 | epf->header = &test_header; | |
543 | epf_test->epf = epf; | |
3235b994 | 544 | epf_test->test_reg_bar = test_reg_bar; |
702a3ed9 | 545 | epf_test->linkup_notifier = linkup_notifier; |
349e7a85 KVA |
546 | |
547 | INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler); | |
548 | ||
549 | epf_set_drvdata(epf, epf_test); | |
550 | return 0; | |
551 | } | |
552 | ||
349e7a85 KVA |
553 | static struct pci_epf_ops ops = { |
554 | .unbind = pci_epf_test_unbind, | |
555 | .bind = pci_epf_test_bind, | |
556 | .linkup = pci_epf_test_linkup, | |
557 | }; | |
558 | ||
349e7a85 KVA |
559 | static struct pci_epf_driver test_driver = { |
560 | .driver.name = "pci_epf_test", | |
561 | .probe = pci_epf_test_probe, | |
349e7a85 KVA |
562 | .id_table = pci_epf_test_ids, |
563 | .ops = &ops, | |
564 | .owner = THIS_MODULE, | |
565 | }; | |
566 | ||
567 | static int __init pci_epf_test_init(void) | |
568 | { | |
569 | int ret; | |
570 | ||
571 | kpcitest_workqueue = alloc_workqueue("kpcitest", | |
572 | WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); | |
573 | ret = pci_epf_register_driver(&test_driver); | |
574 | if (ret) { | |
798c0441 | 575 | pr_err("Failed to register pci epf test driver --> %d\n", ret); |
349e7a85 KVA |
576 | return ret; |
577 | } | |
578 | ||
579 | return 0; | |
580 | } | |
581 | module_init(pci_epf_test_init); | |
582 | ||
583 | static void __exit pci_epf_test_exit(void) | |
584 | { | |
585 | pci_epf_unregister_driver(&test_driver); | |
586 | } | |
587 | module_exit(pci_epf_test_exit); | |
588 | ||
589 | MODULE_DESCRIPTION("PCI EPF TEST DRIVER"); | |
590 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | |
591 | MODULE_LICENSE("GPL v2"); |