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