1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /************************************************************************ |
3 | * Copyright 2003 Digi International (www.digi.com) |
4 | * |
5 | * Copyright (C) 2004 IBM Corporation. All rights reserved. |
6 | * |
7 | * Contact Information: |
8 | * Scott H Kilau <Scott_Kilau@digi.com> |
9 | * Wendy Xiong <wendyx@us.ibm.com> |
10 | * |
11 | * |
12 | ***********************************************************************/ |
13 | #include <linux/module.h> |
14 | #include <linux/pci.h> |
15 | #include <linux/slab.h> |
16 | |
17 | #include "jsm.h" |
18 | |
19 | MODULE_AUTHOR("Digi International, https://www.digi.com" ); |
20 | MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line" ); |
21 | MODULE_LICENSE("GPL" ); |
22 | |
23 | #define JSM_DRIVER_NAME "jsm" |
24 | #define NR_PORTS 32 |
25 | #define JSM_MINOR_START 0 |
26 | |
27 | struct uart_driver jsm_uart_driver = { |
28 | .owner = THIS_MODULE, |
29 | .driver_name = JSM_DRIVER_NAME, |
30 | .dev_name = "ttyn" , |
31 | .major = 0, |
32 | .minor = JSM_MINOR_START, |
33 | .nr = NR_PORTS, |
34 | }; |
35 | |
36 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, |
37 | pci_channel_state_t state); |
38 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); |
39 | static void jsm_io_resume(struct pci_dev *pdev); |
40 | |
41 | static const struct pci_error_handlers jsm_err_handler = { |
42 | .error_detected = jsm_io_error_detected, |
43 | .slot_reset = jsm_io_slot_reset, |
44 | .resume = jsm_io_resume, |
45 | }; |
46 | |
47 | int jsm_debug; |
48 | module_param(jsm_debug, int, 0); |
49 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level" ); |
50 | |
51 | static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
52 | { |
53 | int rc = 0; |
54 | struct jsm_board *brd; |
55 | static int adapter_count; |
56 | |
57 | rc = pci_enable_device(dev: pdev); |
58 | if (rc) { |
59 | dev_err(&pdev->dev, "Device enable FAILED\n" ); |
60 | goto out; |
61 | } |
62 | |
63 | rc = pci_request_regions(pdev, JSM_DRIVER_NAME); |
64 | if (rc) { |
65 | dev_err(&pdev->dev, "pci_request_region FAILED\n" ); |
66 | goto out_disable_device; |
67 | } |
68 | |
69 | brd = kzalloc(size: sizeof(*brd), GFP_KERNEL); |
70 | if (!brd) { |
71 | rc = -ENOMEM; |
72 | goto out_release_regions; |
73 | } |
74 | |
75 | /* store the info for the board we've found */ |
76 | brd->boardnum = adapter_count++; |
77 | brd->pci_dev = pdev; |
78 | |
79 | switch (pdev->device) { |
80 | case PCI_DEVICE_ID_NEO_2DB9: |
81 | case PCI_DEVICE_ID_NEO_2DB9PRI: |
82 | case PCI_DEVICE_ID_NEO_2RJ45: |
83 | case PCI_DEVICE_ID_NEO_2RJ45PRI: |
84 | case PCI_DEVICE_ID_NEO_2_422_485: |
85 | brd->maxports = 2; |
86 | break; |
87 | |
88 | case PCI_DEVICE_ID_CLASSIC_4: |
89 | case PCI_DEVICE_ID_CLASSIC_4_422: |
90 | case PCI_DEVICE_ID_NEO_4: |
91 | case PCIE_DEVICE_ID_NEO_4: |
92 | case PCIE_DEVICE_ID_NEO_4RJ45: |
93 | case PCIE_DEVICE_ID_NEO_4_IBM: |
94 | brd->maxports = 4; |
95 | break; |
96 | |
97 | case PCI_DEVICE_ID_CLASSIC_8: |
98 | case PCI_DEVICE_ID_CLASSIC_8_422: |
99 | case PCI_DEVICE_ID_DIGI_NEO_8: |
100 | case PCIE_DEVICE_ID_NEO_8: |
101 | case PCIE_DEVICE_ID_NEO_8RJ45: |
102 | brd->maxports = 8; |
103 | break; |
104 | |
105 | default: |
106 | brd->maxports = 1; |
107 | break; |
108 | } |
109 | |
110 | spin_lock_init(&brd->bd_intr_lock); |
111 | |
112 | /* store which revision we have */ |
113 | brd->rev = pdev->revision; |
114 | |
115 | brd->irq = pdev->irq; |
116 | |
117 | switch (pdev->device) { |
118 | case PCI_DEVICE_ID_CLASSIC_4: |
119 | case PCI_DEVICE_ID_CLASSIC_4_422: |
120 | case PCI_DEVICE_ID_CLASSIC_8: |
121 | case PCI_DEVICE_ID_CLASSIC_8_422: |
122 | |
123 | jsm_dbg(INIT, &brd->pci_dev, |
124 | "jsm_found_board - Classic adapter\n" ); |
125 | |
126 | /* |
127 | * For PCI ClassicBoards |
128 | * PCI Local Address (.i.e. "resource" number) space |
129 | * 0 PLX Memory Mapped Config |
130 | * 1 PLX I/O Mapped Config |
131 | * 2 I/O Mapped UARTs and Status |
132 | * 3 Memory Mapped VPD |
133 | * 4 Memory Mapped UARTs and Status |
134 | */ |
135 | |
136 | /* Get the PCI Base Address Registers */ |
137 | brd->membase = pci_resource_start(pdev, 4); |
138 | brd->membase_end = pci_resource_end(pdev, 4); |
139 | |
140 | if (brd->membase & 0x1) |
141 | brd->membase &= ~0x3; |
142 | else |
143 | brd->membase &= ~0xF; |
144 | |
145 | brd->iobase = pci_resource_start(pdev, 1); |
146 | brd->iobase_end = pci_resource_end(pdev, 1); |
147 | brd->iobase = ((unsigned int)(brd->iobase)) & 0xFFFE; |
148 | |
149 | /* Assign the board_ops struct */ |
150 | brd->bd_ops = &jsm_cls_ops; |
151 | |
152 | brd->bd_uart_offset = 0x8; |
153 | brd->bd_dividend = 921600; |
154 | |
155 | brd->re_map_membase = ioremap(offset: brd->membase, |
156 | pci_resource_len(pdev, 4)); |
157 | if (!brd->re_map_membase) { |
158 | dev_err(&pdev->dev, |
159 | "Card has no PCI Memory resources, failing board.\n" ); |
160 | rc = -ENOMEM; |
161 | goto out_kfree_brd; |
162 | } |
163 | |
164 | /* |
165 | * Enable Local Interrupt 1 (0x1), |
166 | * Local Interrupt 1 Polarity Active high (0x2), |
167 | * Enable PCI interrupt (0x43) |
168 | */ |
169 | outb(value: 0x43, port: brd->iobase + 0x4c); |
170 | |
171 | break; |
172 | |
173 | case PCI_DEVICE_ID_NEO_2DB9: |
174 | case PCI_DEVICE_ID_NEO_2DB9PRI: |
175 | case PCI_DEVICE_ID_NEO_2RJ45: |
176 | case PCI_DEVICE_ID_NEO_2RJ45PRI: |
177 | case PCI_DEVICE_ID_NEO_2_422_485: |
178 | case PCI_DEVICE_ID_NEO_4: |
179 | case PCIE_DEVICE_ID_NEO_4: |
180 | case PCIE_DEVICE_ID_NEO_4RJ45: |
181 | case PCIE_DEVICE_ID_NEO_4_IBM: |
182 | case PCI_DEVICE_ID_DIGI_NEO_8: |
183 | case PCIE_DEVICE_ID_NEO_8: |
184 | case PCIE_DEVICE_ID_NEO_8RJ45: |
185 | |
186 | jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n" ); |
187 | |
188 | /* get the PCI Base Address Registers */ |
189 | brd->membase = pci_resource_start(pdev, 0); |
190 | brd->membase_end = pci_resource_end(pdev, 0); |
191 | |
192 | if (brd->membase & 1) |
193 | brd->membase &= ~0x3; |
194 | else |
195 | brd->membase &= ~0xF; |
196 | |
197 | /* Assign the board_ops struct */ |
198 | brd->bd_ops = &jsm_neo_ops; |
199 | |
200 | brd->bd_uart_offset = 0x200; |
201 | brd->bd_dividend = 921600; |
202 | |
203 | brd->re_map_membase = ioremap(offset: brd->membase, |
204 | pci_resource_len(pdev, 0)); |
205 | if (!brd->re_map_membase) { |
206 | dev_err(&pdev->dev, |
207 | "Card has no PCI Memory resources, failing board.\n" ); |
208 | rc = -ENOMEM; |
209 | goto out_kfree_brd; |
210 | } |
211 | |
212 | break; |
213 | default: |
214 | rc = -ENXIO; |
215 | goto out_kfree_brd; |
216 | } |
217 | |
218 | rc = request_irq(irq: brd->irq, handler: brd->bd_ops->intr, IRQF_SHARED, name: "JSM" , dev: brd); |
219 | if (rc) { |
220 | dev_warn(&pdev->dev, "Failed to hook IRQ %d\n" , brd->irq); |
221 | goto out_iounmap; |
222 | } |
223 | |
224 | rc = jsm_tty_init(brd); |
225 | if (rc < 0) { |
226 | dev_err(&pdev->dev, "Can't init tty devices (%d)\n" , rc); |
227 | rc = -ENXIO; |
228 | goto out_free_irq; |
229 | } |
230 | |
231 | rc = jsm_uart_port_init(brd); |
232 | if (rc < 0) { |
233 | /* XXX: leaking all resources from jsm_tty_init here! */ |
234 | dev_err(&pdev->dev, "Can't init uart port (%d)\n" , rc); |
235 | rc = -ENXIO; |
236 | goto out_free_irq; |
237 | } |
238 | |
239 | /* Log the information about the board */ |
240 | dev_info(&pdev->dev, "board %d: Digi Classic/Neo (rev %d), irq %d\n" , |
241 | adapter_count, brd->rev, brd->irq); |
242 | |
243 | pci_set_drvdata(pdev, data: brd); |
244 | pci_save_state(dev: pdev); |
245 | |
246 | return 0; |
247 | out_free_irq: |
248 | jsm_remove_uart_port(brd); |
249 | free_irq(brd->irq, brd); |
250 | out_iounmap: |
251 | iounmap(addr: brd->re_map_membase); |
252 | out_kfree_brd: |
253 | kfree(objp: brd); |
254 | out_release_regions: |
255 | pci_release_regions(pdev); |
256 | out_disable_device: |
257 | pci_disable_device(dev: pdev); |
258 | out: |
259 | return rc; |
260 | } |
261 | |
262 | static void jsm_remove_one(struct pci_dev *pdev) |
263 | { |
264 | struct jsm_board *brd = pci_get_drvdata(pdev); |
265 | int i = 0; |
266 | |
267 | switch (pdev->device) { |
268 | case PCI_DEVICE_ID_CLASSIC_4: |
269 | case PCI_DEVICE_ID_CLASSIC_4_422: |
270 | case PCI_DEVICE_ID_CLASSIC_8: |
271 | case PCI_DEVICE_ID_CLASSIC_8_422: |
272 | /* Tell card not to interrupt anymore. */ |
273 | outb(value: 0x0, port: brd->iobase + 0x4c); |
274 | break; |
275 | default: |
276 | break; |
277 | } |
278 | |
279 | jsm_remove_uart_port(brd); |
280 | |
281 | free_irq(brd->irq, brd); |
282 | iounmap(addr: brd->re_map_membase); |
283 | |
284 | /* Free all allocated channels structs */ |
285 | for (i = 0; i < brd->maxports; i++) { |
286 | if (brd->channels[i]) { |
287 | kfree(objp: brd->channels[i]->ch_rqueue); |
288 | kfree(objp: brd->channels[i]->ch_equeue); |
289 | kfree(objp: brd->channels[i]); |
290 | } |
291 | } |
292 | |
293 | pci_release_regions(pdev); |
294 | pci_disable_device(dev: pdev); |
295 | kfree(objp: brd); |
296 | } |
297 | |
298 | static const struct pci_device_id jsm_pci_tbl[] = { |
299 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 }, |
300 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 }, |
301 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 }, |
302 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 }, |
303 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 }, |
304 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_NEO_8), 0, 0, 5 }, |
305 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_4), 0, 0, 6 }, |
306 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_1_422), 0, 0, 7 }, |
307 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_1_422_485), 0, 0, 8 }, |
308 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2_422_485), 0, 0, 9 }, |
309 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_8), 0, 0, 10 }, |
310 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4), 0, 0, 11 }, |
311 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4RJ45), 0, 0, 12 }, |
312 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_8RJ45), 0, 0, 13 }, |
313 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4), 0, 0, 14 }, |
314 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4_422), 0, 0, 15 }, |
315 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8), 0, 0, 16 }, |
316 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8_422), 0, 0, 17 }, |
317 | { 0, } |
318 | }; |
319 | MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); |
320 | |
321 | static struct pci_driver jsm_driver = { |
322 | .name = JSM_DRIVER_NAME, |
323 | .id_table = jsm_pci_tbl, |
324 | .probe = jsm_probe_one, |
325 | .remove = jsm_remove_one, |
326 | .err_handler = &jsm_err_handler, |
327 | }; |
328 | |
329 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, |
330 | pci_channel_state_t state) |
331 | { |
332 | struct jsm_board *brd = pci_get_drvdata(pdev); |
333 | |
334 | jsm_remove_uart_port(brd); |
335 | |
336 | return PCI_ERS_RESULT_NEED_RESET; |
337 | } |
338 | |
339 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) |
340 | { |
341 | int rc; |
342 | |
343 | rc = pci_enable_device(dev: pdev); |
344 | |
345 | if (rc) |
346 | return PCI_ERS_RESULT_DISCONNECT; |
347 | |
348 | pci_set_master(dev: pdev); |
349 | |
350 | return PCI_ERS_RESULT_RECOVERED; |
351 | } |
352 | |
353 | static void jsm_io_resume(struct pci_dev *pdev) |
354 | { |
355 | struct jsm_board *brd = pci_get_drvdata(pdev); |
356 | |
357 | pci_restore_state(dev: pdev); |
358 | pci_save_state(dev: pdev); |
359 | |
360 | jsm_uart_port_init(brd); |
361 | } |
362 | |
363 | static int __init jsm_init_module(void) |
364 | { |
365 | int rc; |
366 | |
367 | rc = uart_register_driver(uart: &jsm_uart_driver); |
368 | if (!rc) { |
369 | rc = pci_register_driver(&jsm_driver); |
370 | if (rc) |
371 | uart_unregister_driver(uart: &jsm_uart_driver); |
372 | } |
373 | return rc; |
374 | } |
375 | |
376 | static void __exit jsm_exit_module(void) |
377 | { |
378 | pci_unregister_driver(dev: &jsm_driver); |
379 | uart_unregister_driver(uart: &jsm_uart_driver); |
380 | } |
381 | |
382 | module_init(jsm_init_module); |
383 | module_exit(jsm_exit_module); |
384 | |