1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Microsemi Switchtec(tm) PCIe Management Driver |
4 | * Copyright (c) 2017, Microsemi Corporation |
5 | */ |
6 | |
7 | #include <linux/switchtec.h> |
8 | #include <linux/switchtec_ioctl.h> |
9 | |
10 | #include <linux/interrupt.h> |
11 | #include <linux/module.h> |
12 | #include <linux/fs.h> |
13 | #include <linux/uaccess.h> |
14 | #include <linux/poll.h> |
15 | #include <linux/wait.h> |
16 | #include <linux/io-64-nonatomic-lo-hi.h> |
17 | #include <linux/nospec.h> |
18 | |
19 | MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver" ); |
20 | MODULE_VERSION("0.1" ); |
21 | MODULE_LICENSE("GPL" ); |
22 | MODULE_AUTHOR("Microsemi Corporation" ); |
23 | |
24 | static int max_devices = 16; |
25 | module_param(max_devices, int, 0644); |
26 | MODULE_PARM_DESC(max_devices, "max number of switchtec device instances" ); |
27 | |
28 | static bool use_dma_mrpc = true; |
29 | module_param(use_dma_mrpc, bool, 0644); |
30 | MODULE_PARM_DESC(use_dma_mrpc, |
31 | "Enable the use of the DMA MRPC feature" ); |
32 | |
33 | static int nirqs = 32; |
34 | module_param(nirqs, int, 0644); |
35 | MODULE_PARM_DESC(nirqs, "number of interrupts to allocate (more may be useful for NTB applications)" ); |
36 | |
37 | static dev_t switchtec_devt; |
38 | static DEFINE_IDA(switchtec_minor_ida); |
39 | |
40 | struct class *switchtec_class; |
41 | EXPORT_SYMBOL_GPL(switchtec_class); |
42 | |
43 | enum mrpc_state { |
44 | MRPC_IDLE = 0, |
45 | MRPC_QUEUED, |
46 | MRPC_RUNNING, |
47 | MRPC_DONE, |
48 | MRPC_IO_ERROR, |
49 | }; |
50 | |
51 | struct switchtec_user { |
52 | struct switchtec_dev *stdev; |
53 | |
54 | enum mrpc_state state; |
55 | |
56 | wait_queue_head_t cmd_comp; |
57 | struct kref kref; |
58 | struct list_head list; |
59 | |
60 | bool cmd_done; |
61 | u32 cmd; |
62 | u32 status; |
63 | u32 return_code; |
64 | size_t data_len; |
65 | size_t read_len; |
66 | unsigned char data[SWITCHTEC_MRPC_PAYLOAD_SIZE]; |
67 | int event_cnt; |
68 | }; |
69 | |
70 | /* |
71 | * The MMIO reads to the device_id register should always return the device ID |
72 | * of the device, otherwise the firmware is probably stuck or unreachable |
73 | * due to a firmware reset which clears PCI state including the BARs and Memory |
74 | * Space Enable bits. |
75 | */ |
76 | static int is_firmware_running(struct switchtec_dev *stdev) |
77 | { |
78 | u32 device = ioread32(&stdev->mmio_sys_info->device_id); |
79 | |
80 | return stdev->pdev->device == device; |
81 | } |
82 | |
83 | static struct switchtec_user *stuser_create(struct switchtec_dev *stdev) |
84 | { |
85 | struct switchtec_user *stuser; |
86 | |
87 | stuser = kzalloc(size: sizeof(*stuser), GFP_KERNEL); |
88 | if (!stuser) |
89 | return ERR_PTR(error: -ENOMEM); |
90 | |
91 | get_device(dev: &stdev->dev); |
92 | stuser->stdev = stdev; |
93 | kref_init(kref: &stuser->kref); |
94 | INIT_LIST_HEAD(list: &stuser->list); |
95 | init_waitqueue_head(&stuser->cmd_comp); |
96 | stuser->event_cnt = atomic_read(v: &stdev->event_cnt); |
97 | |
98 | dev_dbg(&stdev->dev, "%s: %p\n" , __func__, stuser); |
99 | |
100 | return stuser; |
101 | } |
102 | |
103 | static void stuser_free(struct kref *kref) |
104 | { |
105 | struct switchtec_user *stuser; |
106 | |
107 | stuser = container_of(kref, struct switchtec_user, kref); |
108 | |
109 | dev_dbg(&stuser->stdev->dev, "%s: %p\n" , __func__, stuser); |
110 | |
111 | put_device(dev: &stuser->stdev->dev); |
112 | kfree(objp: stuser); |
113 | } |
114 | |
115 | static void stuser_put(struct switchtec_user *stuser) |
116 | { |
117 | kref_put(kref: &stuser->kref, release: stuser_free); |
118 | } |
119 | |
120 | static void stuser_set_state(struct switchtec_user *stuser, |
121 | enum mrpc_state state) |
122 | { |
123 | /* requires the mrpc_mutex to already be held when called */ |
124 | |
125 | static const char * const state_names[] = { |
126 | [MRPC_IDLE] = "IDLE" , |
127 | [MRPC_QUEUED] = "QUEUED" , |
128 | [MRPC_RUNNING] = "RUNNING" , |
129 | [MRPC_DONE] = "DONE" , |
130 | [MRPC_IO_ERROR] = "IO_ERROR" , |
131 | }; |
132 | |
133 | stuser->state = state; |
134 | |
135 | dev_dbg(&stuser->stdev->dev, "stuser state %p -> %s" , |
136 | stuser, state_names[state]); |
137 | } |
138 | |
139 | static void mrpc_complete_cmd(struct switchtec_dev *stdev); |
140 | |
141 | static void flush_wc_buf(struct switchtec_dev *stdev) |
142 | { |
143 | struct ntb_dbmsg_regs __iomem *mmio_dbmsg; |
144 | |
145 | /* |
146 | * odb (outbound doorbell) register is processed by low latency |
147 | * hardware and w/o side effect |
148 | */ |
149 | mmio_dbmsg = (void __iomem *)stdev->mmio_ntb + |
150 | SWITCHTEC_NTB_REG_DBMSG_OFFSET; |
151 | ioread32(&mmio_dbmsg->odb); |
152 | } |
153 | |
154 | static void mrpc_cmd_submit(struct switchtec_dev *stdev) |
155 | { |
156 | /* requires the mrpc_mutex to already be held when called */ |
157 | |
158 | struct switchtec_user *stuser; |
159 | |
160 | if (stdev->mrpc_busy) |
161 | return; |
162 | |
163 | if (list_empty(head: &stdev->mrpc_queue)) |
164 | return; |
165 | |
166 | stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, |
167 | list); |
168 | |
169 | if (stdev->dma_mrpc) { |
170 | stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS; |
171 | memset(stdev->dma_mrpc->data, 0xFF, SWITCHTEC_MRPC_PAYLOAD_SIZE); |
172 | } |
173 | |
174 | stuser_set_state(stuser, state: MRPC_RUNNING); |
175 | stdev->mrpc_busy = 1; |
176 | memcpy_toio(&stdev->mmio_mrpc->input_data, |
177 | stuser->data, stuser->data_len); |
178 | flush_wc_buf(stdev); |
179 | iowrite32(stuser->cmd, &stdev->mmio_mrpc->cmd); |
180 | |
181 | schedule_delayed_work(dwork: &stdev->mrpc_timeout, |
182 | delay: msecs_to_jiffies(m: 500)); |
183 | } |
184 | |
185 | static int mrpc_queue_cmd(struct switchtec_user *stuser) |
186 | { |
187 | /* requires the mrpc_mutex to already be held when called */ |
188 | |
189 | struct switchtec_dev *stdev = stuser->stdev; |
190 | |
191 | kref_get(kref: &stuser->kref); |
192 | stuser->read_len = sizeof(stuser->data); |
193 | stuser_set_state(stuser, state: MRPC_QUEUED); |
194 | stuser->cmd_done = false; |
195 | list_add_tail(new: &stuser->list, head: &stdev->mrpc_queue); |
196 | |
197 | mrpc_cmd_submit(stdev); |
198 | |
199 | return 0; |
200 | } |
201 | |
202 | static void mrpc_cleanup_cmd(struct switchtec_dev *stdev) |
203 | { |
204 | /* requires the mrpc_mutex to already be held when called */ |
205 | |
206 | struct switchtec_user *stuser = list_entry(stdev->mrpc_queue.next, |
207 | struct switchtec_user, list); |
208 | |
209 | stuser->cmd_done = true; |
210 | wake_up_interruptible(&stuser->cmd_comp); |
211 | list_del_init(entry: &stuser->list); |
212 | stuser_put(stuser); |
213 | stdev->mrpc_busy = 0; |
214 | |
215 | mrpc_cmd_submit(stdev); |
216 | } |
217 | |
218 | static void mrpc_complete_cmd(struct switchtec_dev *stdev) |
219 | { |
220 | /* requires the mrpc_mutex to already be held when called */ |
221 | |
222 | struct switchtec_user *stuser; |
223 | |
224 | if (list_empty(head: &stdev->mrpc_queue)) |
225 | return; |
226 | |
227 | stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, |
228 | list); |
229 | |
230 | if (stdev->dma_mrpc) |
231 | stuser->status = stdev->dma_mrpc->status; |
232 | else |
233 | stuser->status = ioread32(&stdev->mmio_mrpc->status); |
234 | |
235 | if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS) |
236 | return; |
237 | |
238 | stuser_set_state(stuser, state: MRPC_DONE); |
239 | stuser->return_code = 0; |
240 | |
241 | if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE && |
242 | stuser->status != SWITCHTEC_MRPC_STATUS_ERROR) |
243 | goto out; |
244 | |
245 | if (stdev->dma_mrpc) |
246 | stuser->return_code = stdev->dma_mrpc->rtn_code; |
247 | else |
248 | stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value); |
249 | if (stuser->return_code != 0) |
250 | goto out; |
251 | |
252 | if (stdev->dma_mrpc) |
253 | memcpy(stuser->data, &stdev->dma_mrpc->data, |
254 | stuser->read_len); |
255 | else |
256 | memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data, |
257 | stuser->read_len); |
258 | out: |
259 | mrpc_cleanup_cmd(stdev); |
260 | } |
261 | |
262 | static void mrpc_event_work(struct work_struct *work) |
263 | { |
264 | struct switchtec_dev *stdev; |
265 | |
266 | stdev = container_of(work, struct switchtec_dev, mrpc_work); |
267 | |
268 | dev_dbg(&stdev->dev, "%s\n" , __func__); |
269 | |
270 | mutex_lock(&stdev->mrpc_mutex); |
271 | cancel_delayed_work(dwork: &stdev->mrpc_timeout); |
272 | mrpc_complete_cmd(stdev); |
273 | mutex_unlock(lock: &stdev->mrpc_mutex); |
274 | } |
275 | |
276 | static void mrpc_error_complete_cmd(struct switchtec_dev *stdev) |
277 | { |
278 | /* requires the mrpc_mutex to already be held when called */ |
279 | |
280 | struct switchtec_user *stuser; |
281 | |
282 | if (list_empty(head: &stdev->mrpc_queue)) |
283 | return; |
284 | |
285 | stuser = list_entry(stdev->mrpc_queue.next, |
286 | struct switchtec_user, list); |
287 | |
288 | stuser_set_state(stuser, state: MRPC_IO_ERROR); |
289 | |
290 | mrpc_cleanup_cmd(stdev); |
291 | } |
292 | |
293 | static void mrpc_timeout_work(struct work_struct *work) |
294 | { |
295 | struct switchtec_dev *stdev; |
296 | u32 status; |
297 | |
298 | stdev = container_of(work, struct switchtec_dev, mrpc_timeout.work); |
299 | |
300 | dev_dbg(&stdev->dev, "%s\n" , __func__); |
301 | |
302 | mutex_lock(&stdev->mrpc_mutex); |
303 | |
304 | if (!is_firmware_running(stdev)) { |
305 | mrpc_error_complete_cmd(stdev); |
306 | goto out; |
307 | } |
308 | |
309 | if (stdev->dma_mrpc) |
310 | status = stdev->dma_mrpc->status; |
311 | else |
312 | status = ioread32(&stdev->mmio_mrpc->status); |
313 | if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) { |
314 | schedule_delayed_work(dwork: &stdev->mrpc_timeout, |
315 | delay: msecs_to_jiffies(m: 500)); |
316 | goto out; |
317 | } |
318 | |
319 | mrpc_complete_cmd(stdev); |
320 | out: |
321 | mutex_unlock(lock: &stdev->mrpc_mutex); |
322 | } |
323 | |
324 | static ssize_t device_version_show(struct device *dev, |
325 | struct device_attribute *attr, char *buf) |
326 | { |
327 | struct switchtec_dev *stdev = to_stdev(dev); |
328 | u32 ver; |
329 | |
330 | ver = ioread32(&stdev->mmio_sys_info->device_version); |
331 | |
332 | return sysfs_emit(buf, fmt: "%x\n" , ver); |
333 | } |
334 | static DEVICE_ATTR_RO(device_version); |
335 | |
336 | static ssize_t fw_version_show(struct device *dev, |
337 | struct device_attribute *attr, char *buf) |
338 | { |
339 | struct switchtec_dev *stdev = to_stdev(dev); |
340 | u32 ver; |
341 | |
342 | ver = ioread32(&stdev->mmio_sys_info->firmware_version); |
343 | |
344 | return sysfs_emit(buf, fmt: "%08x\n" , ver); |
345 | } |
346 | static DEVICE_ATTR_RO(fw_version); |
347 | |
348 | static ssize_t io_string_show(char *buf, void __iomem *attr, size_t len) |
349 | { |
350 | int i; |
351 | |
352 | memcpy_fromio(buf, attr, len); |
353 | buf[len] = '\n'; |
354 | buf[len + 1] = 0; |
355 | |
356 | for (i = len - 1; i > 0; i--) { |
357 | if (buf[i] != ' ') |
358 | break; |
359 | buf[i] = '\n'; |
360 | buf[i + 1] = 0; |
361 | } |
362 | |
363 | return strlen(buf); |
364 | } |
365 | |
366 | #define DEVICE_ATTR_SYS_INFO_STR(field) \ |
367 | static ssize_t field ## _show(struct device *dev, \ |
368 | struct device_attribute *attr, char *buf) \ |
369 | { \ |
370 | struct switchtec_dev *stdev = to_stdev(dev); \ |
371 | struct sys_info_regs __iomem *si = stdev->mmio_sys_info; \ |
372 | if (stdev->gen == SWITCHTEC_GEN3) \ |
373 | return io_string_show(buf, &si->gen3.field, \ |
374 | sizeof(si->gen3.field)); \ |
375 | else if (stdev->gen >= SWITCHTEC_GEN4) \ |
376 | return io_string_show(buf, &si->gen4.field, \ |
377 | sizeof(si->gen4.field)); \ |
378 | else \ |
379 | return -EOPNOTSUPP; \ |
380 | } \ |
381 | \ |
382 | static DEVICE_ATTR_RO(field) |
383 | |
384 | DEVICE_ATTR_SYS_INFO_STR(vendor_id); |
385 | DEVICE_ATTR_SYS_INFO_STR(product_id); |
386 | DEVICE_ATTR_SYS_INFO_STR(product_revision); |
387 | |
388 | static ssize_t component_vendor_show(struct device *dev, |
389 | struct device_attribute *attr, char *buf) |
390 | { |
391 | struct switchtec_dev *stdev = to_stdev(dev); |
392 | struct sys_info_regs __iomem *si = stdev->mmio_sys_info; |
393 | |
394 | /* component_vendor field not supported after gen3 */ |
395 | if (stdev->gen != SWITCHTEC_GEN3) |
396 | return sysfs_emit(buf, fmt: "none\n" ); |
397 | |
398 | return io_string_show(buf, attr: &si->gen3.component_vendor, |
399 | len: sizeof(si->gen3.component_vendor)); |
400 | } |
401 | static DEVICE_ATTR_RO(component_vendor); |
402 | |
403 | static ssize_t component_id_show(struct device *dev, |
404 | struct device_attribute *attr, char *buf) |
405 | { |
406 | struct switchtec_dev *stdev = to_stdev(dev); |
407 | int id = ioread16(&stdev->mmio_sys_info->gen3.component_id); |
408 | |
409 | /* component_id field not supported after gen3 */ |
410 | if (stdev->gen != SWITCHTEC_GEN3) |
411 | return sysfs_emit(buf, fmt: "none\n" ); |
412 | |
413 | return sysfs_emit(buf, fmt: "PM%04X\n" , id); |
414 | } |
415 | static DEVICE_ATTR_RO(component_id); |
416 | |
417 | static ssize_t component_revision_show(struct device *dev, |
418 | struct device_attribute *attr, char *buf) |
419 | { |
420 | struct switchtec_dev *stdev = to_stdev(dev); |
421 | int rev = ioread8(&stdev->mmio_sys_info->gen3.component_revision); |
422 | |
423 | /* component_revision field not supported after gen3 */ |
424 | if (stdev->gen != SWITCHTEC_GEN3) |
425 | return sysfs_emit(buf, fmt: "255\n" ); |
426 | |
427 | return sysfs_emit(buf, fmt: "%d\n" , rev); |
428 | } |
429 | static DEVICE_ATTR_RO(component_revision); |
430 | |
431 | static ssize_t partition_show(struct device *dev, |
432 | struct device_attribute *attr, char *buf) |
433 | { |
434 | struct switchtec_dev *stdev = to_stdev(dev); |
435 | |
436 | return sysfs_emit(buf, fmt: "%d\n" , stdev->partition); |
437 | } |
438 | static DEVICE_ATTR_RO(partition); |
439 | |
440 | static ssize_t partition_count_show(struct device *dev, |
441 | struct device_attribute *attr, char *buf) |
442 | { |
443 | struct switchtec_dev *stdev = to_stdev(dev); |
444 | |
445 | return sysfs_emit(buf, fmt: "%d\n" , stdev->partition_count); |
446 | } |
447 | static DEVICE_ATTR_RO(partition_count); |
448 | |
449 | static struct attribute *switchtec_device_attrs[] = { |
450 | &dev_attr_device_version.attr, |
451 | &dev_attr_fw_version.attr, |
452 | &dev_attr_vendor_id.attr, |
453 | &dev_attr_product_id.attr, |
454 | &dev_attr_product_revision.attr, |
455 | &dev_attr_component_vendor.attr, |
456 | &dev_attr_component_id.attr, |
457 | &dev_attr_component_revision.attr, |
458 | &dev_attr_partition.attr, |
459 | &dev_attr_partition_count.attr, |
460 | NULL, |
461 | }; |
462 | |
463 | ATTRIBUTE_GROUPS(switchtec_device); |
464 | |
465 | static int switchtec_dev_open(struct inode *inode, struct file *filp) |
466 | { |
467 | struct switchtec_dev *stdev; |
468 | struct switchtec_user *stuser; |
469 | |
470 | stdev = container_of(inode->i_cdev, struct switchtec_dev, cdev); |
471 | |
472 | stuser = stuser_create(stdev); |
473 | if (IS_ERR(ptr: stuser)) |
474 | return PTR_ERR(ptr: stuser); |
475 | |
476 | filp->private_data = stuser; |
477 | stream_open(inode, filp); |
478 | |
479 | dev_dbg(&stdev->dev, "%s: %p\n" , __func__, stuser); |
480 | |
481 | return 0; |
482 | } |
483 | |
484 | static int switchtec_dev_release(struct inode *inode, struct file *filp) |
485 | { |
486 | struct switchtec_user *stuser = filp->private_data; |
487 | |
488 | stuser_put(stuser); |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | static int lock_mutex_and_test_alive(struct switchtec_dev *stdev) |
494 | { |
495 | if (mutex_lock_interruptible(&stdev->mrpc_mutex)) |
496 | return -EINTR; |
497 | |
498 | if (!stdev->alive) { |
499 | mutex_unlock(lock: &stdev->mrpc_mutex); |
500 | return -ENODEV; |
501 | } |
502 | |
503 | return 0; |
504 | } |
505 | |
506 | static ssize_t switchtec_dev_write(struct file *filp, const char __user *data, |
507 | size_t size, loff_t *off) |
508 | { |
509 | struct switchtec_user *stuser = filp->private_data; |
510 | struct switchtec_dev *stdev = stuser->stdev; |
511 | int rc; |
512 | |
513 | if (size < sizeof(stuser->cmd) || |
514 | size > sizeof(stuser->cmd) + sizeof(stuser->data)) |
515 | return -EINVAL; |
516 | |
517 | stuser->data_len = size - sizeof(stuser->cmd); |
518 | |
519 | rc = lock_mutex_and_test_alive(stdev); |
520 | if (rc) |
521 | return rc; |
522 | |
523 | if (stuser->state != MRPC_IDLE) { |
524 | rc = -EBADE; |
525 | goto out; |
526 | } |
527 | |
528 | rc = copy_from_user(to: &stuser->cmd, from: data, n: sizeof(stuser->cmd)); |
529 | if (rc) { |
530 | rc = -EFAULT; |
531 | goto out; |
532 | } |
533 | if (((MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_WRITE) || |
534 | (MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_READ)) && |
535 | !capable(CAP_SYS_ADMIN)) { |
536 | rc = -EPERM; |
537 | goto out; |
538 | } |
539 | |
540 | data += sizeof(stuser->cmd); |
541 | rc = copy_from_user(to: &stuser->data, from: data, n: size - sizeof(stuser->cmd)); |
542 | if (rc) { |
543 | rc = -EFAULT; |
544 | goto out; |
545 | } |
546 | |
547 | rc = mrpc_queue_cmd(stuser); |
548 | |
549 | out: |
550 | mutex_unlock(lock: &stdev->mrpc_mutex); |
551 | |
552 | if (rc) |
553 | return rc; |
554 | |
555 | return size; |
556 | } |
557 | |
558 | static ssize_t switchtec_dev_read(struct file *filp, char __user *data, |
559 | size_t size, loff_t *off) |
560 | { |
561 | struct switchtec_user *stuser = filp->private_data; |
562 | struct switchtec_dev *stdev = stuser->stdev; |
563 | int rc; |
564 | |
565 | if (size < sizeof(stuser->cmd) || |
566 | size > sizeof(stuser->cmd) + sizeof(stuser->data)) |
567 | return -EINVAL; |
568 | |
569 | rc = lock_mutex_and_test_alive(stdev); |
570 | if (rc) |
571 | return rc; |
572 | |
573 | if (stuser->state == MRPC_IDLE) { |
574 | mutex_unlock(lock: &stdev->mrpc_mutex); |
575 | return -EBADE; |
576 | } |
577 | |
578 | stuser->read_len = size - sizeof(stuser->return_code); |
579 | |
580 | mutex_unlock(lock: &stdev->mrpc_mutex); |
581 | |
582 | if (filp->f_flags & O_NONBLOCK) { |
583 | if (!stuser->cmd_done) |
584 | return -EAGAIN; |
585 | } else { |
586 | rc = wait_event_interruptible(stuser->cmd_comp, |
587 | stuser->cmd_done); |
588 | if (rc < 0) |
589 | return rc; |
590 | } |
591 | |
592 | rc = lock_mutex_and_test_alive(stdev); |
593 | if (rc) |
594 | return rc; |
595 | |
596 | if (stuser->state == MRPC_IO_ERROR) { |
597 | mutex_unlock(lock: &stdev->mrpc_mutex); |
598 | return -EIO; |
599 | } |
600 | |
601 | if (stuser->state != MRPC_DONE) { |
602 | mutex_unlock(lock: &stdev->mrpc_mutex); |
603 | return -EBADE; |
604 | } |
605 | |
606 | rc = copy_to_user(to: data, from: &stuser->return_code, |
607 | n: sizeof(stuser->return_code)); |
608 | if (rc) { |
609 | mutex_unlock(lock: &stdev->mrpc_mutex); |
610 | return -EFAULT; |
611 | } |
612 | |
613 | data += sizeof(stuser->return_code); |
614 | rc = copy_to_user(to: data, from: &stuser->data, |
615 | n: size - sizeof(stuser->return_code)); |
616 | if (rc) { |
617 | mutex_unlock(lock: &stdev->mrpc_mutex); |
618 | return -EFAULT; |
619 | } |
620 | |
621 | stuser_set_state(stuser, state: MRPC_IDLE); |
622 | |
623 | mutex_unlock(lock: &stdev->mrpc_mutex); |
624 | |
625 | if (stuser->status == SWITCHTEC_MRPC_STATUS_DONE || |
626 | stuser->status == SWITCHTEC_MRPC_STATUS_ERROR) |
627 | return size; |
628 | else if (stuser->status == SWITCHTEC_MRPC_STATUS_INTERRUPTED) |
629 | return -ENXIO; |
630 | else |
631 | return -EBADMSG; |
632 | } |
633 | |
634 | static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait) |
635 | { |
636 | struct switchtec_user *stuser = filp->private_data; |
637 | struct switchtec_dev *stdev = stuser->stdev; |
638 | __poll_t ret = 0; |
639 | |
640 | poll_wait(filp, wait_address: &stuser->cmd_comp, p: wait); |
641 | poll_wait(filp, wait_address: &stdev->event_wq, p: wait); |
642 | |
643 | if (lock_mutex_and_test_alive(stdev)) |
644 | return EPOLLIN | EPOLLRDHUP | EPOLLOUT | EPOLLERR | EPOLLHUP; |
645 | |
646 | mutex_unlock(lock: &stdev->mrpc_mutex); |
647 | |
648 | if (stuser->cmd_done) |
649 | ret |= EPOLLIN | EPOLLRDNORM; |
650 | |
651 | if (stuser->event_cnt != atomic_read(v: &stdev->event_cnt)) |
652 | ret |= EPOLLPRI | EPOLLRDBAND; |
653 | |
654 | return ret; |
655 | } |
656 | |
657 | static int ioctl_flash_info(struct switchtec_dev *stdev, |
658 | struct switchtec_ioctl_flash_info __user *uinfo) |
659 | { |
660 | struct switchtec_ioctl_flash_info info = {0}; |
661 | struct flash_info_regs __iomem *fi = stdev->mmio_flash_info; |
662 | |
663 | if (stdev->gen == SWITCHTEC_GEN3) { |
664 | info.flash_length = ioread32(&fi->gen3.flash_length); |
665 | info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN3; |
666 | } else if (stdev->gen >= SWITCHTEC_GEN4) { |
667 | info.flash_length = ioread32(&fi->gen4.flash_length); |
668 | info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN4; |
669 | } else { |
670 | return -EOPNOTSUPP; |
671 | } |
672 | |
673 | if (copy_to_user(to: uinfo, from: &info, n: sizeof(info))) |
674 | return -EFAULT; |
675 | |
676 | return 0; |
677 | } |
678 | |
679 | static void set_fw_info_part(struct switchtec_ioctl_flash_part_info *info, |
680 | struct partition_info __iomem *pi) |
681 | { |
682 | info->address = ioread32(&pi->address); |
683 | info->length = ioread32(&pi->length); |
684 | } |
685 | |
686 | static int flash_part_info_gen3(struct switchtec_dev *stdev, |
687 | struct switchtec_ioctl_flash_part_info *info) |
688 | { |
689 | struct flash_info_regs_gen3 __iomem *fi = |
690 | &stdev->mmio_flash_info->gen3; |
691 | struct sys_info_regs_gen3 __iomem *si = &stdev->mmio_sys_info->gen3; |
692 | u32 active_addr = -1; |
693 | |
694 | switch (info->flash_partition) { |
695 | case SWITCHTEC_IOCTL_PART_CFG0: |
696 | active_addr = ioread32(&fi->active_cfg); |
697 | set_fw_info_part(info, pi: &fi->cfg0); |
698 | if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG0_RUNNING) |
699 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
700 | break; |
701 | case SWITCHTEC_IOCTL_PART_CFG1: |
702 | active_addr = ioread32(&fi->active_cfg); |
703 | set_fw_info_part(info, pi: &fi->cfg1); |
704 | if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG1_RUNNING) |
705 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
706 | break; |
707 | case SWITCHTEC_IOCTL_PART_IMG0: |
708 | active_addr = ioread32(&fi->active_img); |
709 | set_fw_info_part(info, pi: &fi->img0); |
710 | if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG0_RUNNING) |
711 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
712 | break; |
713 | case SWITCHTEC_IOCTL_PART_IMG1: |
714 | active_addr = ioread32(&fi->active_img); |
715 | set_fw_info_part(info, pi: &fi->img1); |
716 | if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG1_RUNNING) |
717 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
718 | break; |
719 | case SWITCHTEC_IOCTL_PART_NVLOG: |
720 | set_fw_info_part(info, pi: &fi->nvlog); |
721 | break; |
722 | case SWITCHTEC_IOCTL_PART_VENDOR0: |
723 | set_fw_info_part(info, pi: &fi->vendor[0]); |
724 | break; |
725 | case SWITCHTEC_IOCTL_PART_VENDOR1: |
726 | set_fw_info_part(info, pi: &fi->vendor[1]); |
727 | break; |
728 | case SWITCHTEC_IOCTL_PART_VENDOR2: |
729 | set_fw_info_part(info, pi: &fi->vendor[2]); |
730 | break; |
731 | case SWITCHTEC_IOCTL_PART_VENDOR3: |
732 | set_fw_info_part(info, pi: &fi->vendor[3]); |
733 | break; |
734 | case SWITCHTEC_IOCTL_PART_VENDOR4: |
735 | set_fw_info_part(info, pi: &fi->vendor[4]); |
736 | break; |
737 | case SWITCHTEC_IOCTL_PART_VENDOR5: |
738 | set_fw_info_part(info, pi: &fi->vendor[5]); |
739 | break; |
740 | case SWITCHTEC_IOCTL_PART_VENDOR6: |
741 | set_fw_info_part(info, pi: &fi->vendor[6]); |
742 | break; |
743 | case SWITCHTEC_IOCTL_PART_VENDOR7: |
744 | set_fw_info_part(info, pi: &fi->vendor[7]); |
745 | break; |
746 | default: |
747 | return -EINVAL; |
748 | } |
749 | |
750 | if (info->address == active_addr) |
751 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
752 | |
753 | return 0; |
754 | } |
755 | |
756 | static int flash_part_info_gen4(struct switchtec_dev *stdev, |
757 | struct switchtec_ioctl_flash_part_info *info) |
758 | { |
759 | struct flash_info_regs_gen4 __iomem *fi = &stdev->mmio_flash_info->gen4; |
760 | struct sys_info_regs_gen4 __iomem *si = &stdev->mmio_sys_info->gen4; |
761 | struct active_partition_info_gen4 __iomem *af = &fi->active_flag; |
762 | |
763 | switch (info->flash_partition) { |
764 | case SWITCHTEC_IOCTL_PART_MAP_0: |
765 | set_fw_info_part(info, pi: &fi->map0); |
766 | break; |
767 | case SWITCHTEC_IOCTL_PART_MAP_1: |
768 | set_fw_info_part(info, pi: &fi->map1); |
769 | break; |
770 | case SWITCHTEC_IOCTL_PART_KEY_0: |
771 | set_fw_info_part(info, pi: &fi->key0); |
772 | if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY0_ACTIVE) |
773 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
774 | if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY0_RUNNING) |
775 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
776 | break; |
777 | case SWITCHTEC_IOCTL_PART_KEY_1: |
778 | set_fw_info_part(info, pi: &fi->key1); |
779 | if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY1_ACTIVE) |
780 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
781 | if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY1_RUNNING) |
782 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
783 | break; |
784 | case SWITCHTEC_IOCTL_PART_BL2_0: |
785 | set_fw_info_part(info, pi: &fi->bl2_0); |
786 | if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_0_ACTIVE) |
787 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
788 | if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_0_RUNNING) |
789 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
790 | break; |
791 | case SWITCHTEC_IOCTL_PART_BL2_1: |
792 | set_fw_info_part(info, pi: &fi->bl2_1); |
793 | if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_1_ACTIVE) |
794 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
795 | if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_1_RUNNING) |
796 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
797 | break; |
798 | case SWITCHTEC_IOCTL_PART_CFG0: |
799 | set_fw_info_part(info, pi: &fi->cfg0); |
800 | if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG0_ACTIVE) |
801 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
802 | if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG0_RUNNING) |
803 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
804 | break; |
805 | case SWITCHTEC_IOCTL_PART_CFG1: |
806 | set_fw_info_part(info, pi: &fi->cfg1); |
807 | if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG1_ACTIVE) |
808 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
809 | if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG1_RUNNING) |
810 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
811 | break; |
812 | case SWITCHTEC_IOCTL_PART_IMG0: |
813 | set_fw_info_part(info, pi: &fi->img0); |
814 | if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG0_ACTIVE) |
815 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
816 | if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG0_RUNNING) |
817 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
818 | break; |
819 | case SWITCHTEC_IOCTL_PART_IMG1: |
820 | set_fw_info_part(info, pi: &fi->img1); |
821 | if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG1_ACTIVE) |
822 | info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
823 | if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG1_RUNNING) |
824 | info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
825 | break; |
826 | case SWITCHTEC_IOCTL_PART_NVLOG: |
827 | set_fw_info_part(info, pi: &fi->nvlog); |
828 | break; |
829 | case SWITCHTEC_IOCTL_PART_VENDOR0: |
830 | set_fw_info_part(info, pi: &fi->vendor[0]); |
831 | break; |
832 | case SWITCHTEC_IOCTL_PART_VENDOR1: |
833 | set_fw_info_part(info, pi: &fi->vendor[1]); |
834 | break; |
835 | case SWITCHTEC_IOCTL_PART_VENDOR2: |
836 | set_fw_info_part(info, pi: &fi->vendor[2]); |
837 | break; |
838 | case SWITCHTEC_IOCTL_PART_VENDOR3: |
839 | set_fw_info_part(info, pi: &fi->vendor[3]); |
840 | break; |
841 | case SWITCHTEC_IOCTL_PART_VENDOR4: |
842 | set_fw_info_part(info, pi: &fi->vendor[4]); |
843 | break; |
844 | case SWITCHTEC_IOCTL_PART_VENDOR5: |
845 | set_fw_info_part(info, pi: &fi->vendor[5]); |
846 | break; |
847 | case SWITCHTEC_IOCTL_PART_VENDOR6: |
848 | set_fw_info_part(info, pi: &fi->vendor[6]); |
849 | break; |
850 | case SWITCHTEC_IOCTL_PART_VENDOR7: |
851 | set_fw_info_part(info, pi: &fi->vendor[7]); |
852 | break; |
853 | default: |
854 | return -EINVAL; |
855 | } |
856 | |
857 | return 0; |
858 | } |
859 | |
860 | static int ioctl_flash_part_info(struct switchtec_dev *stdev, |
861 | struct switchtec_ioctl_flash_part_info __user *uinfo) |
862 | { |
863 | int ret; |
864 | struct switchtec_ioctl_flash_part_info info = {0}; |
865 | |
866 | if (copy_from_user(to: &info, from: uinfo, n: sizeof(info))) |
867 | return -EFAULT; |
868 | |
869 | if (stdev->gen == SWITCHTEC_GEN3) { |
870 | ret = flash_part_info_gen3(stdev, info: &info); |
871 | if (ret) |
872 | return ret; |
873 | } else if (stdev->gen >= SWITCHTEC_GEN4) { |
874 | ret = flash_part_info_gen4(stdev, info: &info); |
875 | if (ret) |
876 | return ret; |
877 | } else { |
878 | return -EOPNOTSUPP; |
879 | } |
880 | |
881 | if (copy_to_user(to: uinfo, from: &info, n: sizeof(info))) |
882 | return -EFAULT; |
883 | |
884 | return 0; |
885 | } |
886 | |
887 | static int ioctl_event_summary(struct switchtec_dev *stdev, |
888 | struct switchtec_user *stuser, |
889 | struct switchtec_ioctl_event_summary __user *usum, |
890 | size_t size) |
891 | { |
892 | struct switchtec_ioctl_event_summary *s; |
893 | int i; |
894 | u32 reg; |
895 | int ret = 0; |
896 | |
897 | s = kzalloc(size: sizeof(*s), GFP_KERNEL); |
898 | if (!s) |
899 | return -ENOMEM; |
900 | |
901 | s->global = ioread32(&stdev->mmio_sw_event->global_summary); |
902 | s->part_bitmap = ioread64(addr: &stdev->mmio_sw_event->part_event_bitmap); |
903 | s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary); |
904 | |
905 | for (i = 0; i < stdev->partition_count; i++) { |
906 | reg = ioread32(&stdev->mmio_part_cfg_all[i].part_event_summary); |
907 | s->part[i] = reg; |
908 | } |
909 | |
910 | for (i = 0; i < stdev->pff_csr_count; i++) { |
911 | reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary); |
912 | s->pff[i] = reg; |
913 | } |
914 | |
915 | if (copy_to_user(to: usum, from: s, n: size)) { |
916 | ret = -EFAULT; |
917 | goto error_case; |
918 | } |
919 | |
920 | stuser->event_cnt = atomic_read(v: &stdev->event_cnt); |
921 | |
922 | error_case: |
923 | kfree(objp: s); |
924 | return ret; |
925 | } |
926 | |
927 | static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev, |
928 | size_t offset, int index) |
929 | { |
930 | return (void __iomem *)stdev->mmio_sw_event + offset; |
931 | } |
932 | |
933 | static u32 __iomem *part_ev_reg(struct switchtec_dev *stdev, |
934 | size_t offset, int index) |
935 | { |
936 | return (void __iomem *)&stdev->mmio_part_cfg_all[index] + offset; |
937 | } |
938 | |
939 | static u32 __iomem *pff_ev_reg(struct switchtec_dev *stdev, |
940 | size_t offset, int index) |
941 | { |
942 | return (void __iomem *)&stdev->mmio_pff_csr[index] + offset; |
943 | } |
944 | |
945 | #define EV_GLB(i, r)[i] = {offsetof(struct sw_event_regs, r), global_ev_reg} |
946 | #define EV_PAR(i, r)[i] = {offsetof(struct part_cfg_regs, r), part_ev_reg} |
947 | #define EV_PFF(i, r)[i] = {offsetof(struct pff_csr_regs, r), pff_ev_reg} |
948 | |
949 | static const struct event_reg { |
950 | size_t offset; |
951 | u32 __iomem *(*map_reg)(struct switchtec_dev *stdev, |
952 | size_t offset, int index); |
953 | } event_regs[] = { |
954 | EV_GLB(SWITCHTEC_IOCTL_EVENT_STACK_ERROR, stack_error_event_hdr), |
955 | EV_GLB(SWITCHTEC_IOCTL_EVENT_PPU_ERROR, ppu_error_event_hdr), |
956 | EV_GLB(SWITCHTEC_IOCTL_EVENT_ISP_ERROR, isp_error_event_hdr), |
957 | EV_GLB(SWITCHTEC_IOCTL_EVENT_SYS_RESET, sys_reset_event_hdr), |
958 | EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_EXC, fw_exception_hdr), |
959 | EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NMI, fw_nmi_hdr), |
960 | EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NON_FATAL, fw_non_fatal_hdr), |
961 | EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_FATAL, fw_fatal_hdr), |
962 | EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP, twi_mrpc_comp_hdr), |
963 | EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP_ASYNC, |
964 | twi_mrpc_comp_async_hdr), |
965 | EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP, cli_mrpc_comp_hdr), |
966 | EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP_ASYNC, |
967 | cli_mrpc_comp_async_hdr), |
968 | EV_GLB(SWITCHTEC_IOCTL_EVENT_GPIO_INT, gpio_interrupt_hdr), |
969 | EV_GLB(SWITCHTEC_IOCTL_EVENT_GFMS, gfms_event_hdr), |
970 | EV_PAR(SWITCHTEC_IOCTL_EVENT_PART_RESET, part_reset_hdr), |
971 | EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP, mrpc_comp_hdr), |
972 | EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP_ASYNC, mrpc_comp_async_hdr), |
973 | EV_PAR(SWITCHTEC_IOCTL_EVENT_DYN_PART_BIND_COMP, dyn_binding_hdr), |
974 | EV_PAR(SWITCHTEC_IOCTL_EVENT_INTERCOMM_REQ_NOTIFY, |
975 | intercomm_notify_hdr), |
976 | EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_P2P, aer_in_p2p_hdr), |
977 | EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_VEP, aer_in_vep_hdr), |
978 | EV_PFF(SWITCHTEC_IOCTL_EVENT_DPC, dpc_hdr), |
979 | EV_PFF(SWITCHTEC_IOCTL_EVENT_CTS, cts_hdr), |
980 | EV_PFF(SWITCHTEC_IOCTL_EVENT_UEC, uec_hdr), |
981 | EV_PFF(SWITCHTEC_IOCTL_EVENT_HOTPLUG, hotplug_hdr), |
982 | EV_PFF(SWITCHTEC_IOCTL_EVENT_IER, ier_hdr), |
983 | EV_PFF(SWITCHTEC_IOCTL_EVENT_THRESH, threshold_hdr), |
984 | EV_PFF(SWITCHTEC_IOCTL_EVENT_POWER_MGMT, power_mgmt_hdr), |
985 | EV_PFF(SWITCHTEC_IOCTL_EVENT_TLP_THROTTLING, tlp_throttling_hdr), |
986 | EV_PFF(SWITCHTEC_IOCTL_EVENT_FORCE_SPEED, force_speed_hdr), |
987 | EV_PFF(SWITCHTEC_IOCTL_EVENT_CREDIT_TIMEOUT, credit_timeout_hdr), |
988 | EV_PFF(SWITCHTEC_IOCTL_EVENT_LINK_STATE, link_state_hdr), |
989 | }; |
990 | |
991 | static u32 __iomem *event_hdr_addr(struct switchtec_dev *stdev, |
992 | int event_id, int index) |
993 | { |
994 | size_t off; |
995 | |
996 | if (event_id < 0 || event_id >= SWITCHTEC_IOCTL_MAX_EVENTS) |
997 | return (u32 __iomem *)ERR_PTR(error: -EINVAL); |
998 | |
999 | off = event_regs[event_id].offset; |
1000 | |
1001 | if (event_regs[event_id].map_reg == part_ev_reg) { |
1002 | if (index == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX) |
1003 | index = stdev->partition; |
1004 | else if (index < 0 || index >= stdev->partition_count) |
1005 | return (u32 __iomem *)ERR_PTR(error: -EINVAL); |
1006 | } else if (event_regs[event_id].map_reg == pff_ev_reg) { |
1007 | if (index < 0 || index >= stdev->pff_csr_count) |
1008 | return (u32 __iomem *)ERR_PTR(error: -EINVAL); |
1009 | } |
1010 | |
1011 | return event_regs[event_id].map_reg(stdev, off, index); |
1012 | } |
1013 | |
1014 | static int event_ctl(struct switchtec_dev *stdev, |
1015 | struct switchtec_ioctl_event_ctl *ctl) |
1016 | { |
1017 | int i; |
1018 | u32 __iomem *reg; |
1019 | u32 hdr; |
1020 | |
1021 | reg = event_hdr_addr(stdev, event_id: ctl->event_id, index: ctl->index); |
1022 | if (IS_ERR(ptr: reg)) |
1023 | return PTR_ERR(ptr: reg); |
1024 | |
1025 | hdr = ioread32(reg); |
1026 | if (hdr & SWITCHTEC_EVENT_NOT_SUPP) |
1027 | return -EOPNOTSUPP; |
1028 | |
1029 | for (i = 0; i < ARRAY_SIZE(ctl->data); i++) |
1030 | ctl->data[i] = ioread32(®[i + 1]); |
1031 | |
1032 | ctl->occurred = hdr & SWITCHTEC_EVENT_OCCURRED; |
1033 | ctl->count = (hdr >> 5) & 0xFF; |
1034 | |
1035 | if (!(ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_CLEAR)) |
1036 | hdr &= ~SWITCHTEC_EVENT_CLEAR; |
1037 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL) |
1038 | hdr |= SWITCHTEC_EVENT_EN_IRQ; |
1039 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_POLL) |
1040 | hdr &= ~SWITCHTEC_EVENT_EN_IRQ; |
1041 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG) |
1042 | hdr |= SWITCHTEC_EVENT_EN_LOG; |
1043 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_LOG) |
1044 | hdr &= ~SWITCHTEC_EVENT_EN_LOG; |
1045 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI) |
1046 | hdr |= SWITCHTEC_EVENT_EN_CLI; |
1047 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_CLI) |
1048 | hdr &= ~SWITCHTEC_EVENT_EN_CLI; |
1049 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL) |
1050 | hdr |= SWITCHTEC_EVENT_FATAL; |
1051 | if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_FATAL) |
1052 | hdr &= ~SWITCHTEC_EVENT_FATAL; |
1053 | |
1054 | if (ctl->flags) |
1055 | iowrite32(hdr, reg); |
1056 | |
1057 | ctl->flags = 0; |
1058 | if (hdr & SWITCHTEC_EVENT_EN_IRQ) |
1059 | ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL; |
1060 | if (hdr & SWITCHTEC_EVENT_EN_LOG) |
1061 | ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG; |
1062 | if (hdr & SWITCHTEC_EVENT_EN_CLI) |
1063 | ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI; |
1064 | if (hdr & SWITCHTEC_EVENT_FATAL) |
1065 | ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL; |
1066 | |
1067 | return 0; |
1068 | } |
1069 | |
1070 | static int ioctl_event_ctl(struct switchtec_dev *stdev, |
1071 | struct switchtec_ioctl_event_ctl __user *uctl) |
1072 | { |
1073 | int ret; |
1074 | int nr_idxs; |
1075 | unsigned int event_flags; |
1076 | struct switchtec_ioctl_event_ctl ctl; |
1077 | |
1078 | if (copy_from_user(to: &ctl, from: uctl, n: sizeof(ctl))) |
1079 | return -EFAULT; |
1080 | |
1081 | if (ctl.event_id >= SWITCHTEC_IOCTL_MAX_EVENTS) |
1082 | return -EINVAL; |
1083 | |
1084 | if (ctl.flags & SWITCHTEC_IOCTL_EVENT_FLAG_UNUSED) |
1085 | return -EINVAL; |
1086 | |
1087 | if (ctl.index == SWITCHTEC_IOCTL_EVENT_IDX_ALL) { |
1088 | if (event_regs[ctl.event_id].map_reg == global_ev_reg) |
1089 | nr_idxs = 1; |
1090 | else if (event_regs[ctl.event_id].map_reg == part_ev_reg) |
1091 | nr_idxs = stdev->partition_count; |
1092 | else if (event_regs[ctl.event_id].map_reg == pff_ev_reg) |
1093 | nr_idxs = stdev->pff_csr_count; |
1094 | else |
1095 | return -EINVAL; |
1096 | |
1097 | event_flags = ctl.flags; |
1098 | for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) { |
1099 | ctl.flags = event_flags; |
1100 | ret = event_ctl(stdev, ctl: &ctl); |
1101 | if (ret < 0 && ret != -EOPNOTSUPP) |
1102 | return ret; |
1103 | } |
1104 | } else { |
1105 | ret = event_ctl(stdev, ctl: &ctl); |
1106 | if (ret < 0) |
1107 | return ret; |
1108 | } |
1109 | |
1110 | if (copy_to_user(to: uctl, from: &ctl, n: sizeof(ctl))) |
1111 | return -EFAULT; |
1112 | |
1113 | return 0; |
1114 | } |
1115 | |
1116 | static int ioctl_pff_to_port(struct switchtec_dev *stdev, |
1117 | struct switchtec_ioctl_pff_port __user *up) |
1118 | { |
1119 | int i, part; |
1120 | u32 reg; |
1121 | struct part_cfg_regs __iomem *pcfg; |
1122 | struct switchtec_ioctl_pff_port p; |
1123 | |
1124 | if (copy_from_user(to: &p, from: up, n: sizeof(p))) |
1125 | return -EFAULT; |
1126 | |
1127 | p.port = -1; |
1128 | for (part = 0; part < stdev->partition_count; part++) { |
1129 | pcfg = &stdev->mmio_part_cfg_all[part]; |
1130 | p.partition = part; |
1131 | |
1132 | reg = ioread32(&pcfg->usp_pff_inst_id); |
1133 | if (reg == p.pff) { |
1134 | p.port = 0; |
1135 | break; |
1136 | } |
1137 | |
1138 | reg = ioread32(&pcfg->vep_pff_inst_id) & 0xFF; |
1139 | if (reg == p.pff) { |
1140 | p.port = SWITCHTEC_IOCTL_PFF_VEP; |
1141 | break; |
1142 | } |
1143 | |
1144 | for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) { |
1145 | reg = ioread32(&pcfg->dsp_pff_inst_id[i]); |
1146 | if (reg != p.pff) |
1147 | continue; |
1148 | |
1149 | p.port = i + 1; |
1150 | break; |
1151 | } |
1152 | |
1153 | if (p.port != -1) |
1154 | break; |
1155 | } |
1156 | |
1157 | if (copy_to_user(to: up, from: &p, n: sizeof(p))) |
1158 | return -EFAULT; |
1159 | |
1160 | return 0; |
1161 | } |
1162 | |
1163 | static int ioctl_port_to_pff(struct switchtec_dev *stdev, |
1164 | struct switchtec_ioctl_pff_port __user *up) |
1165 | { |
1166 | struct switchtec_ioctl_pff_port p; |
1167 | struct part_cfg_regs __iomem *pcfg; |
1168 | |
1169 | if (copy_from_user(to: &p, from: up, n: sizeof(p))) |
1170 | return -EFAULT; |
1171 | |
1172 | if (p.partition == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX) |
1173 | pcfg = stdev->mmio_part_cfg; |
1174 | else if (p.partition < stdev->partition_count) |
1175 | pcfg = &stdev->mmio_part_cfg_all[p.partition]; |
1176 | else |
1177 | return -EINVAL; |
1178 | |
1179 | switch (p.port) { |
1180 | case 0: |
1181 | p.pff = ioread32(&pcfg->usp_pff_inst_id); |
1182 | break; |
1183 | case SWITCHTEC_IOCTL_PFF_VEP: |
1184 | p.pff = ioread32(&pcfg->vep_pff_inst_id) & 0xFF; |
1185 | break; |
1186 | default: |
1187 | if (p.port > ARRAY_SIZE(pcfg->dsp_pff_inst_id)) |
1188 | return -EINVAL; |
1189 | p.port = array_index_nospec(p.port, |
1190 | ARRAY_SIZE(pcfg->dsp_pff_inst_id) + 1); |
1191 | p.pff = ioread32(&pcfg->dsp_pff_inst_id[p.port - 1]); |
1192 | break; |
1193 | } |
1194 | |
1195 | if (copy_to_user(to: up, from: &p, n: sizeof(p))) |
1196 | return -EFAULT; |
1197 | |
1198 | return 0; |
1199 | } |
1200 | |
1201 | static long switchtec_dev_ioctl(struct file *filp, unsigned int cmd, |
1202 | unsigned long arg) |
1203 | { |
1204 | struct switchtec_user *stuser = filp->private_data; |
1205 | struct switchtec_dev *stdev = stuser->stdev; |
1206 | int rc; |
1207 | void __user *argp = (void __user *)arg; |
1208 | |
1209 | rc = lock_mutex_and_test_alive(stdev); |
1210 | if (rc) |
1211 | return rc; |
1212 | |
1213 | switch (cmd) { |
1214 | case SWITCHTEC_IOCTL_FLASH_INFO: |
1215 | rc = ioctl_flash_info(stdev, uinfo: argp); |
1216 | break; |
1217 | case SWITCHTEC_IOCTL_FLASH_PART_INFO: |
1218 | rc = ioctl_flash_part_info(stdev, uinfo: argp); |
1219 | break; |
1220 | case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY: |
1221 | rc = ioctl_event_summary(stdev, stuser, usum: argp, |
1222 | size: sizeof(struct switchtec_ioctl_event_summary_legacy)); |
1223 | break; |
1224 | case SWITCHTEC_IOCTL_EVENT_CTL: |
1225 | rc = ioctl_event_ctl(stdev, uctl: argp); |
1226 | break; |
1227 | case SWITCHTEC_IOCTL_PFF_TO_PORT: |
1228 | rc = ioctl_pff_to_port(stdev, up: argp); |
1229 | break; |
1230 | case SWITCHTEC_IOCTL_PORT_TO_PFF: |
1231 | rc = ioctl_port_to_pff(stdev, up: argp); |
1232 | break; |
1233 | case SWITCHTEC_IOCTL_EVENT_SUMMARY: |
1234 | rc = ioctl_event_summary(stdev, stuser, usum: argp, |
1235 | size: sizeof(struct switchtec_ioctl_event_summary)); |
1236 | break; |
1237 | default: |
1238 | rc = -ENOTTY; |
1239 | break; |
1240 | } |
1241 | |
1242 | mutex_unlock(lock: &stdev->mrpc_mutex); |
1243 | return rc; |
1244 | } |
1245 | |
1246 | static const struct file_operations switchtec_fops = { |
1247 | .owner = THIS_MODULE, |
1248 | .open = switchtec_dev_open, |
1249 | .release = switchtec_dev_release, |
1250 | .write = switchtec_dev_write, |
1251 | .read = switchtec_dev_read, |
1252 | .poll = switchtec_dev_poll, |
1253 | .unlocked_ioctl = switchtec_dev_ioctl, |
1254 | .compat_ioctl = compat_ptr_ioctl, |
1255 | }; |
1256 | |
1257 | static void link_event_work(struct work_struct *work) |
1258 | { |
1259 | struct switchtec_dev *stdev; |
1260 | |
1261 | stdev = container_of(work, struct switchtec_dev, link_event_work); |
1262 | |
1263 | if (stdev->link_notifier) |
1264 | stdev->link_notifier(stdev); |
1265 | } |
1266 | |
1267 | static void check_link_state_events(struct switchtec_dev *stdev) |
1268 | { |
1269 | int idx; |
1270 | u32 reg; |
1271 | int count; |
1272 | int occurred = 0; |
1273 | |
1274 | for (idx = 0; idx < stdev->pff_csr_count; idx++) { |
1275 | reg = ioread32(&stdev->mmio_pff_csr[idx].link_state_hdr); |
1276 | dev_dbg(&stdev->dev, "link_state: %d->%08x\n" , idx, reg); |
1277 | count = (reg >> 5) & 0xFF; |
1278 | |
1279 | if (count != stdev->link_event_count[idx]) { |
1280 | occurred = 1; |
1281 | stdev->link_event_count[idx] = count; |
1282 | } |
1283 | } |
1284 | |
1285 | if (occurred) |
1286 | schedule_work(work: &stdev->link_event_work); |
1287 | } |
1288 | |
1289 | static void enable_link_state_events(struct switchtec_dev *stdev) |
1290 | { |
1291 | int idx; |
1292 | |
1293 | for (idx = 0; idx < stdev->pff_csr_count; idx++) { |
1294 | iowrite32(SWITCHTEC_EVENT_CLEAR | |
1295 | SWITCHTEC_EVENT_EN_IRQ, |
1296 | &stdev->mmio_pff_csr[idx].link_state_hdr); |
1297 | } |
1298 | } |
1299 | |
1300 | static void enable_dma_mrpc(struct switchtec_dev *stdev) |
1301 | { |
1302 | writeq(val: stdev->dma_mrpc_dma_addr, addr: &stdev->mmio_mrpc->dma_addr); |
1303 | flush_wc_buf(stdev); |
1304 | iowrite32(SWITCHTEC_DMA_MRPC_EN, &stdev->mmio_mrpc->dma_en); |
1305 | } |
1306 | |
1307 | static void stdev_release(struct device *dev) |
1308 | { |
1309 | struct switchtec_dev *stdev = to_stdev(dev); |
1310 | |
1311 | kfree(objp: stdev); |
1312 | } |
1313 | |
1314 | static void stdev_kill(struct switchtec_dev *stdev) |
1315 | { |
1316 | struct switchtec_user *stuser, *tmpuser; |
1317 | |
1318 | pci_clear_master(dev: stdev->pdev); |
1319 | |
1320 | cancel_delayed_work_sync(dwork: &stdev->mrpc_timeout); |
1321 | |
1322 | /* Mark the hardware as unavailable and complete all completions */ |
1323 | mutex_lock(&stdev->mrpc_mutex); |
1324 | stdev->alive = false; |
1325 | |
1326 | /* Wake up and kill any users waiting on an MRPC request */ |
1327 | list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) { |
1328 | stuser->cmd_done = true; |
1329 | wake_up_interruptible(&stuser->cmd_comp); |
1330 | list_del_init(entry: &stuser->list); |
1331 | stuser_put(stuser); |
1332 | } |
1333 | |
1334 | mutex_unlock(lock: &stdev->mrpc_mutex); |
1335 | |
1336 | /* Wake up any users waiting on event_wq */ |
1337 | wake_up_interruptible(&stdev->event_wq); |
1338 | } |
1339 | |
1340 | static struct switchtec_dev *stdev_create(struct pci_dev *pdev) |
1341 | { |
1342 | struct switchtec_dev *stdev; |
1343 | int minor; |
1344 | struct device *dev; |
1345 | struct cdev *cdev; |
1346 | int rc; |
1347 | |
1348 | stdev = kzalloc_node(size: sizeof(*stdev), GFP_KERNEL, |
1349 | node: dev_to_node(dev: &pdev->dev)); |
1350 | if (!stdev) |
1351 | return ERR_PTR(error: -ENOMEM); |
1352 | |
1353 | stdev->alive = true; |
1354 | stdev->pdev = pci_dev_get(dev: pdev); |
1355 | INIT_LIST_HEAD(list: &stdev->mrpc_queue); |
1356 | mutex_init(&stdev->mrpc_mutex); |
1357 | stdev->mrpc_busy = 0; |
1358 | INIT_WORK(&stdev->mrpc_work, mrpc_event_work); |
1359 | INIT_DELAYED_WORK(&stdev->mrpc_timeout, mrpc_timeout_work); |
1360 | INIT_WORK(&stdev->link_event_work, link_event_work); |
1361 | init_waitqueue_head(&stdev->event_wq); |
1362 | atomic_set(v: &stdev->event_cnt, i: 0); |
1363 | |
1364 | dev = &stdev->dev; |
1365 | device_initialize(dev); |
1366 | dev->class = switchtec_class; |
1367 | dev->parent = &pdev->dev; |
1368 | dev->groups = switchtec_device_groups; |
1369 | dev->release = stdev_release; |
1370 | |
1371 | minor = ida_alloc(ida: &switchtec_minor_ida, GFP_KERNEL); |
1372 | if (minor < 0) { |
1373 | rc = minor; |
1374 | goto err_put; |
1375 | } |
1376 | |
1377 | dev->devt = MKDEV(MAJOR(switchtec_devt), minor); |
1378 | dev_set_name(dev, name: "switchtec%d" , minor); |
1379 | |
1380 | cdev = &stdev->cdev; |
1381 | cdev_init(cdev, &switchtec_fops); |
1382 | cdev->owner = THIS_MODULE; |
1383 | |
1384 | return stdev; |
1385 | |
1386 | err_put: |
1387 | pci_dev_put(dev: stdev->pdev); |
1388 | put_device(dev: &stdev->dev); |
1389 | return ERR_PTR(error: rc); |
1390 | } |
1391 | |
1392 | static int mask_event(struct switchtec_dev *stdev, int eid, int idx) |
1393 | { |
1394 | size_t off = event_regs[eid].offset; |
1395 | u32 __iomem *hdr_reg; |
1396 | u32 hdr; |
1397 | |
1398 | hdr_reg = event_regs[eid].map_reg(stdev, off, idx); |
1399 | hdr = ioread32(hdr_reg); |
1400 | |
1401 | if (hdr & SWITCHTEC_EVENT_NOT_SUPP) |
1402 | return 0; |
1403 | |
1404 | if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ)) |
1405 | return 0; |
1406 | |
1407 | dev_dbg(&stdev->dev, "%s: %d %d %x\n" , __func__, eid, idx, hdr); |
1408 | hdr &= ~(SWITCHTEC_EVENT_EN_IRQ | SWITCHTEC_EVENT_OCCURRED); |
1409 | iowrite32(hdr, hdr_reg); |
1410 | |
1411 | return 1; |
1412 | } |
1413 | |
1414 | static int mask_all_events(struct switchtec_dev *stdev, int eid) |
1415 | { |
1416 | int idx; |
1417 | int count = 0; |
1418 | |
1419 | if (event_regs[eid].map_reg == part_ev_reg) { |
1420 | for (idx = 0; idx < stdev->partition_count; idx++) |
1421 | count += mask_event(stdev, eid, idx); |
1422 | } else if (event_regs[eid].map_reg == pff_ev_reg) { |
1423 | for (idx = 0; idx < stdev->pff_csr_count; idx++) { |
1424 | if (!stdev->pff_local[idx]) |
1425 | continue; |
1426 | |
1427 | count += mask_event(stdev, eid, idx); |
1428 | } |
1429 | } else { |
1430 | count += mask_event(stdev, eid, idx: 0); |
1431 | } |
1432 | |
1433 | return count; |
1434 | } |
1435 | |
1436 | static irqreturn_t switchtec_event_isr(int irq, void *dev) |
1437 | { |
1438 | struct switchtec_dev *stdev = dev; |
1439 | u32 reg; |
1440 | irqreturn_t ret = IRQ_NONE; |
1441 | int eid, event_count = 0; |
1442 | |
1443 | reg = ioread32(&stdev->mmio_part_cfg->mrpc_comp_hdr); |
1444 | if (reg & SWITCHTEC_EVENT_OCCURRED) { |
1445 | dev_dbg(&stdev->dev, "%s: mrpc comp\n" , __func__); |
1446 | ret = IRQ_HANDLED; |
1447 | schedule_work(work: &stdev->mrpc_work); |
1448 | iowrite32(reg, &stdev->mmio_part_cfg->mrpc_comp_hdr); |
1449 | } |
1450 | |
1451 | check_link_state_events(stdev); |
1452 | |
1453 | for (eid = 0; eid < SWITCHTEC_IOCTL_MAX_EVENTS; eid++) { |
1454 | if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE || |
1455 | eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP) |
1456 | continue; |
1457 | |
1458 | event_count += mask_all_events(stdev, eid); |
1459 | } |
1460 | |
1461 | if (event_count) { |
1462 | atomic_inc(v: &stdev->event_cnt); |
1463 | wake_up_interruptible(&stdev->event_wq); |
1464 | dev_dbg(&stdev->dev, "%s: %d events\n" , __func__, |
1465 | event_count); |
1466 | return IRQ_HANDLED; |
1467 | } |
1468 | |
1469 | return ret; |
1470 | } |
1471 | |
1472 | |
1473 | static irqreturn_t switchtec_dma_mrpc_isr(int irq, void *dev) |
1474 | { |
1475 | struct switchtec_dev *stdev = dev; |
1476 | |
1477 | iowrite32(SWITCHTEC_EVENT_CLEAR | |
1478 | SWITCHTEC_EVENT_EN_IRQ, |
1479 | &stdev->mmio_part_cfg->mrpc_comp_hdr); |
1480 | schedule_work(work: &stdev->mrpc_work); |
1481 | |
1482 | return IRQ_HANDLED; |
1483 | } |
1484 | |
1485 | static int switchtec_init_isr(struct switchtec_dev *stdev) |
1486 | { |
1487 | int nvecs; |
1488 | int event_irq; |
1489 | int dma_mrpc_irq; |
1490 | int rc; |
1491 | |
1492 | if (nirqs < 4) |
1493 | nirqs = 4; |
1494 | |
1495 | nvecs = pci_alloc_irq_vectors(dev: stdev->pdev, min_vecs: 1, max_vecs: nirqs, |
1496 | PCI_IRQ_MSIX | PCI_IRQ_MSI | |
1497 | PCI_IRQ_VIRTUAL); |
1498 | if (nvecs < 0) |
1499 | return nvecs; |
1500 | |
1501 | event_irq = ioread16(&stdev->mmio_part_cfg->vep_vector_number); |
1502 | if (event_irq < 0 || event_irq >= nvecs) |
1503 | return -EFAULT; |
1504 | |
1505 | event_irq = pci_irq_vector(dev: stdev->pdev, nr: event_irq); |
1506 | if (event_irq < 0) |
1507 | return event_irq; |
1508 | |
1509 | rc = devm_request_irq(dev: &stdev->pdev->dev, irq: event_irq, |
1510 | handler: switchtec_event_isr, irqflags: 0, |
1511 | KBUILD_MODNAME, dev_id: stdev); |
1512 | |
1513 | if (rc) |
1514 | return rc; |
1515 | |
1516 | if (!stdev->dma_mrpc) |
1517 | return rc; |
1518 | |
1519 | dma_mrpc_irq = ioread32(&stdev->mmio_mrpc->dma_vector); |
1520 | if (dma_mrpc_irq < 0 || dma_mrpc_irq >= nvecs) |
1521 | return -EFAULT; |
1522 | |
1523 | dma_mrpc_irq = pci_irq_vector(dev: stdev->pdev, nr: dma_mrpc_irq); |
1524 | if (dma_mrpc_irq < 0) |
1525 | return dma_mrpc_irq; |
1526 | |
1527 | rc = devm_request_irq(dev: &stdev->pdev->dev, irq: dma_mrpc_irq, |
1528 | handler: switchtec_dma_mrpc_isr, irqflags: 0, |
1529 | KBUILD_MODNAME, dev_id: stdev); |
1530 | |
1531 | return rc; |
1532 | } |
1533 | |
1534 | static void init_pff(struct switchtec_dev *stdev) |
1535 | { |
1536 | int i; |
1537 | u32 reg; |
1538 | struct part_cfg_regs __iomem *pcfg = stdev->mmio_part_cfg; |
1539 | |
1540 | for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) { |
1541 | reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id); |
1542 | if (reg != PCI_VENDOR_ID_MICROSEMI) |
1543 | break; |
1544 | } |
1545 | |
1546 | stdev->pff_csr_count = i; |
1547 | |
1548 | reg = ioread32(&pcfg->usp_pff_inst_id); |
1549 | if (reg < stdev->pff_csr_count) |
1550 | stdev->pff_local[reg] = 1; |
1551 | |
1552 | reg = ioread32(&pcfg->vep_pff_inst_id) & 0xFF; |
1553 | if (reg < stdev->pff_csr_count) |
1554 | stdev->pff_local[reg] = 1; |
1555 | |
1556 | for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) { |
1557 | reg = ioread32(&pcfg->dsp_pff_inst_id[i]); |
1558 | if (reg < stdev->pff_csr_count) |
1559 | stdev->pff_local[reg] = 1; |
1560 | } |
1561 | } |
1562 | |
1563 | static int switchtec_init_pci(struct switchtec_dev *stdev, |
1564 | struct pci_dev *pdev) |
1565 | { |
1566 | int rc; |
1567 | void __iomem *map; |
1568 | unsigned long res_start, res_len; |
1569 | u32 __iomem *part_id; |
1570 | |
1571 | rc = pcim_enable_device(pdev); |
1572 | if (rc) |
1573 | return rc; |
1574 | |
1575 | rc = dma_set_mask_and_coherent(dev: &pdev->dev, DMA_BIT_MASK(64)); |
1576 | if (rc) |
1577 | return rc; |
1578 | |
1579 | pci_set_master(dev: pdev); |
1580 | |
1581 | res_start = pci_resource_start(pdev, 0); |
1582 | res_len = pci_resource_len(pdev, 0); |
1583 | |
1584 | if (!devm_request_mem_region(&pdev->dev, res_start, |
1585 | res_len, KBUILD_MODNAME)) |
1586 | return -EBUSY; |
1587 | |
1588 | stdev->mmio_mrpc = devm_ioremap_wc(dev: &pdev->dev, offset: res_start, |
1589 | size: SWITCHTEC_GAS_TOP_CFG_OFFSET); |
1590 | if (!stdev->mmio_mrpc) |
1591 | return -ENOMEM; |
1592 | |
1593 | map = devm_ioremap(dev: &pdev->dev, |
1594 | offset: res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET, |
1595 | size: res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET); |
1596 | if (!map) |
1597 | return -ENOMEM; |
1598 | |
1599 | stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET; |
1600 | stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET; |
1601 | stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET; |
1602 | stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET; |
1603 | stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET; |
1604 | |
1605 | if (stdev->gen == SWITCHTEC_GEN3) |
1606 | part_id = &stdev->mmio_sys_info->gen3.partition_id; |
1607 | else if (stdev->gen >= SWITCHTEC_GEN4) |
1608 | part_id = &stdev->mmio_sys_info->gen4.partition_id; |
1609 | else |
1610 | return -EOPNOTSUPP; |
1611 | |
1612 | stdev->partition = ioread8(part_id); |
1613 | stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count); |
1614 | stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET; |
1615 | stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition]; |
1616 | stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET; |
1617 | |
1618 | if (stdev->partition_count < 1) |
1619 | stdev->partition_count = 1; |
1620 | |
1621 | init_pff(stdev); |
1622 | |
1623 | pci_set_drvdata(pdev, data: stdev); |
1624 | |
1625 | if (!use_dma_mrpc) |
1626 | return 0; |
1627 | |
1628 | if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0) |
1629 | return 0; |
1630 | |
1631 | stdev->dma_mrpc = dma_alloc_coherent(dev: &stdev->pdev->dev, |
1632 | size: sizeof(*stdev->dma_mrpc), |
1633 | dma_handle: &stdev->dma_mrpc_dma_addr, |
1634 | GFP_KERNEL); |
1635 | if (stdev->dma_mrpc == NULL) |
1636 | return -ENOMEM; |
1637 | |
1638 | return 0; |
1639 | } |
1640 | |
1641 | static void switchtec_exit_pci(struct switchtec_dev *stdev) |
1642 | { |
1643 | if (stdev->dma_mrpc) { |
1644 | iowrite32(0, &stdev->mmio_mrpc->dma_en); |
1645 | flush_wc_buf(stdev); |
1646 | writeq(val: 0, addr: &stdev->mmio_mrpc->dma_addr); |
1647 | dma_free_coherent(dev: &stdev->pdev->dev, size: sizeof(*stdev->dma_mrpc), |
1648 | cpu_addr: stdev->dma_mrpc, dma_handle: stdev->dma_mrpc_dma_addr); |
1649 | stdev->dma_mrpc = NULL; |
1650 | } |
1651 | } |
1652 | |
1653 | static int switchtec_pci_probe(struct pci_dev *pdev, |
1654 | const struct pci_device_id *id) |
1655 | { |
1656 | struct switchtec_dev *stdev; |
1657 | int rc; |
1658 | |
1659 | if (pdev->class == (PCI_CLASS_BRIDGE_OTHER << 8)) |
1660 | request_module_nowait("ntb_hw_switchtec" ); |
1661 | |
1662 | stdev = stdev_create(pdev); |
1663 | if (IS_ERR(ptr: stdev)) |
1664 | return PTR_ERR(ptr: stdev); |
1665 | |
1666 | stdev->gen = id->driver_data; |
1667 | |
1668 | rc = switchtec_init_pci(stdev, pdev); |
1669 | if (rc) |
1670 | goto err_put; |
1671 | |
1672 | rc = switchtec_init_isr(stdev); |
1673 | if (rc) { |
1674 | dev_err(&stdev->dev, "failed to init isr.\n" ); |
1675 | goto err_exit_pci; |
1676 | } |
1677 | |
1678 | iowrite32(SWITCHTEC_EVENT_CLEAR | |
1679 | SWITCHTEC_EVENT_EN_IRQ, |
1680 | &stdev->mmio_part_cfg->mrpc_comp_hdr); |
1681 | enable_link_state_events(stdev); |
1682 | |
1683 | if (stdev->dma_mrpc) |
1684 | enable_dma_mrpc(stdev); |
1685 | |
1686 | rc = cdev_device_add(cdev: &stdev->cdev, dev: &stdev->dev); |
1687 | if (rc) |
1688 | goto err_devadd; |
1689 | |
1690 | dev_info(&stdev->dev, "Management device registered.\n" ); |
1691 | |
1692 | return 0; |
1693 | |
1694 | err_devadd: |
1695 | stdev_kill(stdev); |
1696 | err_exit_pci: |
1697 | switchtec_exit_pci(stdev); |
1698 | err_put: |
1699 | ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt)); |
1700 | put_device(dev: &stdev->dev); |
1701 | return rc; |
1702 | } |
1703 | |
1704 | static void switchtec_pci_remove(struct pci_dev *pdev) |
1705 | { |
1706 | struct switchtec_dev *stdev = pci_get_drvdata(pdev); |
1707 | |
1708 | pci_set_drvdata(pdev, NULL); |
1709 | |
1710 | cdev_device_del(cdev: &stdev->cdev, dev: &stdev->dev); |
1711 | ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt)); |
1712 | dev_info(&stdev->dev, "unregistered.\n" ); |
1713 | stdev_kill(stdev); |
1714 | switchtec_exit_pci(stdev); |
1715 | pci_dev_put(dev: stdev->pdev); |
1716 | stdev->pdev = NULL; |
1717 | put_device(dev: &stdev->dev); |
1718 | } |
1719 | |
1720 | #define SWITCHTEC_PCI_DEVICE(device_id, gen) \ |
1721 | { \ |
1722 | .vendor = PCI_VENDOR_ID_MICROSEMI, \ |
1723 | .device = device_id, \ |
1724 | .subvendor = PCI_ANY_ID, \ |
1725 | .subdevice = PCI_ANY_ID, \ |
1726 | .class = (PCI_CLASS_MEMORY_OTHER << 8), \ |
1727 | .class_mask = 0xFFFFFFFF, \ |
1728 | .driver_data = gen, \ |
1729 | }, \ |
1730 | { \ |
1731 | .vendor = PCI_VENDOR_ID_MICROSEMI, \ |
1732 | .device = device_id, \ |
1733 | .subvendor = PCI_ANY_ID, \ |
1734 | .subdevice = PCI_ANY_ID, \ |
1735 | .class = (PCI_CLASS_BRIDGE_OTHER << 8), \ |
1736 | .class_mask = 0xFFFFFFFF, \ |
1737 | .driver_data = gen, \ |
1738 | } |
1739 | |
1740 | static const struct pci_device_id switchtec_pci_tbl[] = { |
1741 | SWITCHTEC_PCI_DEVICE(0x8531, SWITCHTEC_GEN3), /* PFX 24xG3 */ |
1742 | SWITCHTEC_PCI_DEVICE(0x8532, SWITCHTEC_GEN3), /* PFX 32xG3 */ |
1743 | SWITCHTEC_PCI_DEVICE(0x8533, SWITCHTEC_GEN3), /* PFX 48xG3 */ |
1744 | SWITCHTEC_PCI_DEVICE(0x8534, SWITCHTEC_GEN3), /* PFX 64xG3 */ |
1745 | SWITCHTEC_PCI_DEVICE(0x8535, SWITCHTEC_GEN3), /* PFX 80xG3 */ |
1746 | SWITCHTEC_PCI_DEVICE(0x8536, SWITCHTEC_GEN3), /* PFX 96xG3 */ |
1747 | SWITCHTEC_PCI_DEVICE(0x8541, SWITCHTEC_GEN3), /* PSX 24xG3 */ |
1748 | SWITCHTEC_PCI_DEVICE(0x8542, SWITCHTEC_GEN3), /* PSX 32xG3 */ |
1749 | SWITCHTEC_PCI_DEVICE(0x8543, SWITCHTEC_GEN3), /* PSX 48xG3 */ |
1750 | SWITCHTEC_PCI_DEVICE(0x8544, SWITCHTEC_GEN3), /* PSX 64xG3 */ |
1751 | SWITCHTEC_PCI_DEVICE(0x8545, SWITCHTEC_GEN3), /* PSX 80xG3 */ |
1752 | SWITCHTEC_PCI_DEVICE(0x8546, SWITCHTEC_GEN3), /* PSX 96xG3 */ |
1753 | SWITCHTEC_PCI_DEVICE(0x8551, SWITCHTEC_GEN3), /* PAX 24XG3 */ |
1754 | SWITCHTEC_PCI_DEVICE(0x8552, SWITCHTEC_GEN3), /* PAX 32XG3 */ |
1755 | SWITCHTEC_PCI_DEVICE(0x8553, SWITCHTEC_GEN3), /* PAX 48XG3 */ |
1756 | SWITCHTEC_PCI_DEVICE(0x8554, SWITCHTEC_GEN3), /* PAX 64XG3 */ |
1757 | SWITCHTEC_PCI_DEVICE(0x8555, SWITCHTEC_GEN3), /* PAX 80XG3 */ |
1758 | SWITCHTEC_PCI_DEVICE(0x8556, SWITCHTEC_GEN3), /* PAX 96XG3 */ |
1759 | SWITCHTEC_PCI_DEVICE(0x8561, SWITCHTEC_GEN3), /* PFXL 24XG3 */ |
1760 | SWITCHTEC_PCI_DEVICE(0x8562, SWITCHTEC_GEN3), /* PFXL 32XG3 */ |
1761 | SWITCHTEC_PCI_DEVICE(0x8563, SWITCHTEC_GEN3), /* PFXL 48XG3 */ |
1762 | SWITCHTEC_PCI_DEVICE(0x8564, SWITCHTEC_GEN3), /* PFXL 64XG3 */ |
1763 | SWITCHTEC_PCI_DEVICE(0x8565, SWITCHTEC_GEN3), /* PFXL 80XG3 */ |
1764 | SWITCHTEC_PCI_DEVICE(0x8566, SWITCHTEC_GEN3), /* PFXL 96XG3 */ |
1765 | SWITCHTEC_PCI_DEVICE(0x8571, SWITCHTEC_GEN3), /* PFXI 24XG3 */ |
1766 | SWITCHTEC_PCI_DEVICE(0x8572, SWITCHTEC_GEN3), /* PFXI 32XG3 */ |
1767 | SWITCHTEC_PCI_DEVICE(0x8573, SWITCHTEC_GEN3), /* PFXI 48XG3 */ |
1768 | SWITCHTEC_PCI_DEVICE(0x8574, SWITCHTEC_GEN3), /* PFXI 64XG3 */ |
1769 | SWITCHTEC_PCI_DEVICE(0x8575, SWITCHTEC_GEN3), /* PFXI 80XG3 */ |
1770 | SWITCHTEC_PCI_DEVICE(0x8576, SWITCHTEC_GEN3), /* PFXI 96XG3 */ |
1771 | SWITCHTEC_PCI_DEVICE(0x4000, SWITCHTEC_GEN4), /* PFX 100XG4 */ |
1772 | SWITCHTEC_PCI_DEVICE(0x4084, SWITCHTEC_GEN4), /* PFX 84XG4 */ |
1773 | SWITCHTEC_PCI_DEVICE(0x4068, SWITCHTEC_GEN4), /* PFX 68XG4 */ |
1774 | SWITCHTEC_PCI_DEVICE(0x4052, SWITCHTEC_GEN4), /* PFX 52XG4 */ |
1775 | SWITCHTEC_PCI_DEVICE(0x4036, SWITCHTEC_GEN4), /* PFX 36XG4 */ |
1776 | SWITCHTEC_PCI_DEVICE(0x4028, SWITCHTEC_GEN4), /* PFX 28XG4 */ |
1777 | SWITCHTEC_PCI_DEVICE(0x4100, SWITCHTEC_GEN4), /* PSX 100XG4 */ |
1778 | SWITCHTEC_PCI_DEVICE(0x4184, SWITCHTEC_GEN4), /* PSX 84XG4 */ |
1779 | SWITCHTEC_PCI_DEVICE(0x4168, SWITCHTEC_GEN4), /* PSX 68XG4 */ |
1780 | SWITCHTEC_PCI_DEVICE(0x4152, SWITCHTEC_GEN4), /* PSX 52XG4 */ |
1781 | SWITCHTEC_PCI_DEVICE(0x4136, SWITCHTEC_GEN4), /* PSX 36XG4 */ |
1782 | SWITCHTEC_PCI_DEVICE(0x4128, SWITCHTEC_GEN4), /* PSX 28XG4 */ |
1783 | SWITCHTEC_PCI_DEVICE(0x4200, SWITCHTEC_GEN4), /* PAX 100XG4 */ |
1784 | SWITCHTEC_PCI_DEVICE(0x4284, SWITCHTEC_GEN4), /* PAX 84XG4 */ |
1785 | SWITCHTEC_PCI_DEVICE(0x4268, SWITCHTEC_GEN4), /* PAX 68XG4 */ |
1786 | SWITCHTEC_PCI_DEVICE(0x4252, SWITCHTEC_GEN4), /* PAX 52XG4 */ |
1787 | SWITCHTEC_PCI_DEVICE(0x4236, SWITCHTEC_GEN4), /* PAX 36XG4 */ |
1788 | SWITCHTEC_PCI_DEVICE(0x4228, SWITCHTEC_GEN4), /* PAX 28XG4 */ |
1789 | SWITCHTEC_PCI_DEVICE(0x4352, SWITCHTEC_GEN4), /* PFXA 52XG4 */ |
1790 | SWITCHTEC_PCI_DEVICE(0x4336, SWITCHTEC_GEN4), /* PFXA 36XG4 */ |
1791 | SWITCHTEC_PCI_DEVICE(0x4328, SWITCHTEC_GEN4), /* PFXA 28XG4 */ |
1792 | SWITCHTEC_PCI_DEVICE(0x4452, SWITCHTEC_GEN4), /* PSXA 52XG4 */ |
1793 | SWITCHTEC_PCI_DEVICE(0x4436, SWITCHTEC_GEN4), /* PSXA 36XG4 */ |
1794 | SWITCHTEC_PCI_DEVICE(0x4428, SWITCHTEC_GEN4), /* PSXA 28XG4 */ |
1795 | SWITCHTEC_PCI_DEVICE(0x4552, SWITCHTEC_GEN4), /* PAXA 52XG4 */ |
1796 | SWITCHTEC_PCI_DEVICE(0x4536, SWITCHTEC_GEN4), /* PAXA 36XG4 */ |
1797 | SWITCHTEC_PCI_DEVICE(0x4528, SWITCHTEC_GEN4), /* PAXA 28XG4 */ |
1798 | SWITCHTEC_PCI_DEVICE(0x5000, SWITCHTEC_GEN5), /* PFX 100XG5 */ |
1799 | SWITCHTEC_PCI_DEVICE(0x5084, SWITCHTEC_GEN5), /* PFX 84XG5 */ |
1800 | SWITCHTEC_PCI_DEVICE(0x5068, SWITCHTEC_GEN5), /* PFX 68XG5 */ |
1801 | SWITCHTEC_PCI_DEVICE(0x5052, SWITCHTEC_GEN5), /* PFX 52XG5 */ |
1802 | SWITCHTEC_PCI_DEVICE(0x5036, SWITCHTEC_GEN5), /* PFX 36XG5 */ |
1803 | SWITCHTEC_PCI_DEVICE(0x5028, SWITCHTEC_GEN5), /* PFX 28XG5 */ |
1804 | SWITCHTEC_PCI_DEVICE(0x5100, SWITCHTEC_GEN5), /* PSX 100XG5 */ |
1805 | SWITCHTEC_PCI_DEVICE(0x5184, SWITCHTEC_GEN5), /* PSX 84XG5 */ |
1806 | SWITCHTEC_PCI_DEVICE(0x5168, SWITCHTEC_GEN5), /* PSX 68XG5 */ |
1807 | SWITCHTEC_PCI_DEVICE(0x5152, SWITCHTEC_GEN5), /* PSX 52XG5 */ |
1808 | SWITCHTEC_PCI_DEVICE(0x5136, SWITCHTEC_GEN5), /* PSX 36XG5 */ |
1809 | SWITCHTEC_PCI_DEVICE(0x5128, SWITCHTEC_GEN5), /* PSX 28XG5 */ |
1810 | SWITCHTEC_PCI_DEVICE(0x5200, SWITCHTEC_GEN5), /* PAX 100XG5 */ |
1811 | SWITCHTEC_PCI_DEVICE(0x5284, SWITCHTEC_GEN5), /* PAX 84XG5 */ |
1812 | SWITCHTEC_PCI_DEVICE(0x5268, SWITCHTEC_GEN5), /* PAX 68XG5 */ |
1813 | SWITCHTEC_PCI_DEVICE(0x5252, SWITCHTEC_GEN5), /* PAX 52XG5 */ |
1814 | SWITCHTEC_PCI_DEVICE(0x5236, SWITCHTEC_GEN5), /* PAX 36XG5 */ |
1815 | SWITCHTEC_PCI_DEVICE(0x5228, SWITCHTEC_GEN5), /* PAX 28XG5 */ |
1816 | SWITCHTEC_PCI_DEVICE(0x5300, SWITCHTEC_GEN5), /* PFXA 100XG5 */ |
1817 | SWITCHTEC_PCI_DEVICE(0x5384, SWITCHTEC_GEN5), /* PFXA 84XG5 */ |
1818 | SWITCHTEC_PCI_DEVICE(0x5368, SWITCHTEC_GEN5), /* PFXA 68XG5 */ |
1819 | SWITCHTEC_PCI_DEVICE(0x5352, SWITCHTEC_GEN5), /* PFXA 52XG5 */ |
1820 | SWITCHTEC_PCI_DEVICE(0x5336, SWITCHTEC_GEN5), /* PFXA 36XG5 */ |
1821 | SWITCHTEC_PCI_DEVICE(0x5328, SWITCHTEC_GEN5), /* PFXA 28XG5 */ |
1822 | SWITCHTEC_PCI_DEVICE(0x5400, SWITCHTEC_GEN5), /* PSXA 100XG5 */ |
1823 | SWITCHTEC_PCI_DEVICE(0x5484, SWITCHTEC_GEN5), /* PSXA 84XG5 */ |
1824 | SWITCHTEC_PCI_DEVICE(0x5468, SWITCHTEC_GEN5), /* PSXA 68XG5 */ |
1825 | SWITCHTEC_PCI_DEVICE(0x5452, SWITCHTEC_GEN5), /* PSXA 52XG5 */ |
1826 | SWITCHTEC_PCI_DEVICE(0x5436, SWITCHTEC_GEN5), /* PSXA 36XG5 */ |
1827 | SWITCHTEC_PCI_DEVICE(0x5428, SWITCHTEC_GEN5), /* PSXA 28XG5 */ |
1828 | SWITCHTEC_PCI_DEVICE(0x5500, SWITCHTEC_GEN5), /* PAXA 100XG5 */ |
1829 | SWITCHTEC_PCI_DEVICE(0x5584, SWITCHTEC_GEN5), /* PAXA 84XG5 */ |
1830 | SWITCHTEC_PCI_DEVICE(0x5568, SWITCHTEC_GEN5), /* PAXA 68XG5 */ |
1831 | SWITCHTEC_PCI_DEVICE(0x5552, SWITCHTEC_GEN5), /* PAXA 52XG5 */ |
1832 | SWITCHTEC_PCI_DEVICE(0x5536, SWITCHTEC_GEN5), /* PAXA 36XG5 */ |
1833 | SWITCHTEC_PCI_DEVICE(0x5528, SWITCHTEC_GEN5), /* PAXA 28XG5 */ |
1834 | {0} |
1835 | }; |
1836 | MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl); |
1837 | |
1838 | static struct pci_driver switchtec_pci_driver = { |
1839 | .name = KBUILD_MODNAME, |
1840 | .id_table = switchtec_pci_tbl, |
1841 | .probe = switchtec_pci_probe, |
1842 | .remove = switchtec_pci_remove, |
1843 | }; |
1844 | |
1845 | static int __init switchtec_init(void) |
1846 | { |
1847 | int rc; |
1848 | |
1849 | rc = alloc_chrdev_region(&switchtec_devt, 0, max_devices, |
1850 | "switchtec" ); |
1851 | if (rc) |
1852 | return rc; |
1853 | |
1854 | switchtec_class = class_create(name: "switchtec" ); |
1855 | if (IS_ERR(ptr: switchtec_class)) { |
1856 | rc = PTR_ERR(ptr: switchtec_class); |
1857 | goto err_create_class; |
1858 | } |
1859 | |
1860 | rc = pci_register_driver(&switchtec_pci_driver); |
1861 | if (rc) |
1862 | goto err_pci_register; |
1863 | |
1864 | pr_info(KBUILD_MODNAME ": loaded.\n" ); |
1865 | |
1866 | return 0; |
1867 | |
1868 | err_pci_register: |
1869 | class_destroy(cls: switchtec_class); |
1870 | |
1871 | err_create_class: |
1872 | unregister_chrdev_region(switchtec_devt, max_devices); |
1873 | |
1874 | return rc; |
1875 | } |
1876 | module_init(switchtec_init); |
1877 | |
1878 | static void __exit switchtec_exit(void) |
1879 | { |
1880 | pci_unregister_driver(dev: &switchtec_pci_driver); |
1881 | class_destroy(cls: switchtec_class); |
1882 | unregister_chrdev_region(switchtec_devt, max_devices); |
1883 | ida_destroy(ida: &switchtec_minor_ida); |
1884 | |
1885 | pr_info(KBUILD_MODNAME ": unloaded.\n" ); |
1886 | } |
1887 | module_exit(switchtec_exit); |
1888 | |