diff options
author | Christoph Hellwig <hch@lst.de> | 2005-04-16 18:25:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:25:44 -0400 |
commit | 614a7d6a76b7fb37bb399047eb3ccf86cafbf60d (patch) | |
tree | e7e85414691ef0f85509f1084c0cecc99f588418 /drivers/serial/jsm | |
parent | a299738283a654544c75167d190d9e87b77e5fb7 (diff) |
[PATCH] fix up newly added jsm driver
- plug various leaks and use after frees in the remove and
initialization failure path (some still left)
- remove useless global list of boards and use pci_set_drvdata instead
- unobsfucate init path by merging functions together
- kill various totally useless state variables
- .. probably more I forgot
Note that the tty part still generates lots of sparse warnings and there's
still a totally useless layer of function pointer indirections, but maybe
someone else will fix that bit up.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/serial/jsm')
-rw-r--r-- | drivers/serial/jsm/jsm.h | 38 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_driver.c | 340 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 24 |
3 files changed, 91 insertions, 311 deletions
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index b12ee02a0f7c..e0717611c940 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
@@ -93,28 +93,6 @@ enum { | |||
93 | #define JSM_VERSION "jsm: 1.1-1-INKERNEL" | 93 | #define JSM_VERSION "jsm: 1.1-1-INKERNEL" |
94 | #define JSM_PARTNUM "40002438_A-INKERNEL" | 94 | #define JSM_PARTNUM "40002438_A-INKERNEL" |
95 | 95 | ||
96 | /* | ||
97 | * All the possible states the driver can be while being loaded. | ||
98 | */ | ||
99 | enum { | ||
100 | DRIVER_INITIALIZED = 0, | ||
101 | DRIVER_READY | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * All the possible states the board can be while booting up. | ||
106 | */ | ||
107 | enum { | ||
108 | BOARD_FAILED = 0, | ||
109 | BOARD_FOUND, | ||
110 | BOARD_READY | ||
111 | }; | ||
112 | |||
113 | struct board_id { | ||
114 | u8 *name; | ||
115 | u32 maxports; | ||
116 | }; | ||
117 | |||
118 | struct jsm_board; | 96 | struct jsm_board; |
119 | struct jsm_channel; | 97 | struct jsm_channel; |
120 | 98 | ||
@@ -149,7 +127,6 @@ struct jsm_board | |||
149 | int boardnum; /* Board number: 0-32 */ | 127 | int boardnum; /* Board number: 0-32 */ |
150 | 128 | ||
151 | int type; /* Type of board */ | 129 | int type; /* Type of board */ |
152 | char *name; /* Product Name */ | ||
153 | u8 rev; /* PCI revision ID */ | 130 | u8 rev; /* PCI revision ID */ |
154 | struct pci_dev *pci_dev; | 131 | struct pci_dev *pci_dev; |
155 | u32 maxports; /* MAX ports this board can handle */ | 132 | u32 maxports; /* MAX ports this board can handle */ |
@@ -160,9 +137,6 @@ struct jsm_board | |||
160 | * the interrupt routine from each other. | 137 | * the interrupt routine from each other. |
161 | */ | 138 | */ |
162 | 139 | ||
163 | u32 state; /* State of card. */ | ||
164 | wait_queue_head_t state_wait; /* Place to sleep on for state change */ | ||
165 | |||
166 | u32 nasync; /* Number of ports on card */ | 140 | u32 nasync; /* Number of ports on card */ |
167 | 141 | ||
168 | u32 irq; /* Interrupt request number */ | 142 | u32 irq; /* Interrupt request number */ |
@@ -181,9 +155,6 @@ struct jsm_board | |||
181 | struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */ | 155 | struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */ |
182 | char *flipbuf; /* Our flip buffer, alloced if board is found */ | 156 | char *flipbuf; /* Our flip buffer, alloced if board is found */ |
183 | 157 | ||
184 | u16 dpatype; /* The board "type", as defined by DPA */ | ||
185 | u16 dpastatus; /* The board "status", as defined by DPA */ | ||
186 | |||
187 | u32 bd_dividend; /* Board/UARTs specific dividend */ | 158 | u32 bd_dividend; /* Board/UARTs specific dividend */ |
188 | 159 | ||
189 | struct board_ops *bd_ops; | 160 | struct board_ops *bd_ops; |
@@ -412,12 +383,6 @@ extern struct board_ops jsm_neo_ops; | |||
412 | extern int jsm_debug; | 383 | extern int jsm_debug; |
413 | extern int jsm_rawreadok; | 384 | extern int jsm_rawreadok; |
414 | 385 | ||
415 | extern int jsm_driver_state; /* The state of the driver */ | ||
416 | extern char *jsm_driver_state_text[];/* Array of driver state text */ | ||
417 | |||
418 | extern spinlock_t jsm_board_head_lock; | ||
419 | extern struct list_head jsm_board_head; | ||
420 | |||
421 | /************************************************************************* | 386 | /************************************************************************* |
422 | * | 387 | * |
423 | * Prototypes for non-static functions used in more than one module | 388 | * Prototypes for non-static functions used in more than one module |
@@ -431,7 +396,4 @@ void jsm_input(struct jsm_channel *ch); | |||
431 | void jsm_carrier(struct jsm_channel *ch); | 396 | void jsm_carrier(struct jsm_channel *ch); |
432 | void jsm_check_queue_flow_control(struct jsm_channel *ch); | 397 | void jsm_check_queue_flow_control(struct jsm_channel *ch); |
433 | 398 | ||
434 | void jsm_create_driver_sysfiles(struct device_driver *); | ||
435 | void jsm_remove_driver_sysfiles(struct device_driver *); | ||
436 | |||
437 | #endif | 399 | #endif |
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index d4847d4f1473..cc5d21300ed3 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -29,7 +29,9 @@ | |||
29 | #include "jsm.h" | 29 | #include "jsm.h" |
30 | 30 | ||
31 | MODULE_AUTHOR("Digi International, http://www.digi.com"); | 31 | MODULE_AUTHOR("Digi International, http://www.digi.com"); |
32 | MODULE_DESCRIPTION("Driver for the Digi International Neo PCI based product line"); | 32 | MODULE_DESCRIPTION("Driver for the Digi International " |
33 | "Neo PCI based product line"); | ||
34 | MODULE_LICENSE("GPL"); | ||
33 | MODULE_SUPPORTED_DEVICE("jsm"); | 35 | MODULE_SUPPORTED_DEVICE("jsm"); |
34 | 36 | ||
35 | #define JSM_DRIVER_NAME "jsm" | 37 | #define JSM_DRIVER_NAME "jsm" |
@@ -43,7 +45,6 @@ struct uart_driver jsm_uart_driver = { | |||
43 | .major = 253, | 45 | .major = 253, |
44 | .minor = JSM_MINOR_START, | 46 | .minor = JSM_MINOR_START, |
45 | .nr = NR_PORTS, | 47 | .nr = NR_PORTS, |
46 | .cons = NULL, | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | int jsm_debug; | 50 | int jsm_debug; |
@@ -53,193 +54,99 @@ module_param(jsm_rawreadok, int, 0); | |||
53 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 54 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); |
54 | MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input"); | 55 | MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input"); |
55 | 56 | ||
56 | /* | 57 | static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
57 | * Globals | ||
58 | */ | ||
59 | int jsm_driver_state = DRIVER_INITIALIZED; | ||
60 | spinlock_t jsm_board_head_lock = SPIN_LOCK_UNLOCKED; | ||
61 | LIST_HEAD(jsm_board_head); | ||
62 | |||
63 | static struct pci_device_id jsm_pci_tbl[] = { | ||
64 | { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 }, | ||
65 | { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 }, | ||
66 | { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 }, | ||
67 | { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 }, | ||
68 | { 0,} /* 0 terminated list. */ | ||
69 | }; | ||
70 | MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); | ||
71 | |||
72 | static struct board_id jsm_Ids[] = { | ||
73 | { PCI_DEVICE_NEO_2DB9_PCI_NAME, 2 }, | ||
74 | { PCI_DEVICE_NEO_2DB9PRI_PCI_NAME, 2 }, | ||
75 | { PCI_DEVICE_NEO_2RJ45_PCI_NAME, 2 }, | ||
76 | { PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME, 2 }, | ||
77 | { NULL, 0 } | ||
78 | }; | ||
79 | |||
80 | char *jsm_driver_state_text[] = { | ||
81 | "Driver Initialized", | ||
82 | "Driver Ready." | ||
83 | }; | ||
84 | |||
85 | static int jsm_finalize_board_init(struct jsm_board *brd) | ||
86 | { | 58 | { |
87 | int rc = 0; | 59 | int rc = 0; |
60 | struct jsm_board *brd; | ||
61 | static int adapter_count = 0; | ||
62 | int retval; | ||
88 | 63 | ||
89 | jsm_printk(INIT, INFO, &brd->pci_dev, "start\n"); | 64 | rc = pci_enable_device(pdev); |
90 | 65 | if (rc) { | |
91 | if (brd->irq) { | 66 | dev_err(&pdev->dev, "Device enable FAILED\n"); |
92 | rc = request_irq(brd->irq, brd->bd_ops->intr, SA_INTERRUPT|SA_SHIRQ, "JSM", brd); | 67 | goto out; |
93 | |||
94 | if (rc) { | ||
95 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | ||
96 | brd->state = BOARD_FAILED; | ||
97 | brd->dpastatus = BD_NOFEP; | ||
98 | rc = -ENODEV; | ||
99 | } else | ||
100 | jsm_printk(INIT, INFO, &brd->pci_dev, | ||
101 | "Requested and received usage of IRQ %d\n", brd->irq); | ||
102 | } | 68 | } |
103 | return rc; | ||
104 | } | ||
105 | 69 | ||
106 | /* | 70 | rc = pci_request_regions(pdev, "jsm"); |
107 | * jsm_found_board() | 71 | if (rc) { |
108 | * | 72 | dev_err(&pdev->dev, "pci_request_region FAILED\n"); |
109 | * A board has been found, init it. | 73 | goto out_disable_device; |
110 | */ | 74 | } |
111 | static int jsm_found_board(struct pci_dev *pdev, int id) | ||
112 | { | ||
113 | struct jsm_board *brd; | ||
114 | int i = 0; | ||
115 | int rc = 0; | ||
116 | struct list_head *tmp; | ||
117 | struct jsm_board *cur_board_entry; | ||
118 | unsigned long lock_flags; | ||
119 | int adapter_count = 0; | ||
120 | int retval; | ||
121 | 75 | ||
122 | brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL); | 76 | brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL); |
123 | if (!brd) { | 77 | if (!brd) { |
124 | dev_err(&pdev->dev, "memory allocation for board structure failed\n"); | 78 | dev_err(&pdev->dev, |
125 | return -ENOMEM; | 79 | "memory allocation for board structure failed\n"); |
80 | rc = -ENOMEM; | ||
81 | goto out_release_regions; | ||
126 | } | 82 | } |
127 | memset(brd, 0, sizeof(struct jsm_board)); | 83 | memset(brd, 0, sizeof(struct jsm_board)); |
128 | 84 | ||
129 | spin_lock_irqsave(&jsm_board_head_lock, lock_flags); | ||
130 | list_for_each(tmp, &jsm_board_head) { | ||
131 | cur_board_entry = | ||
132 | list_entry(tmp, struct jsm_board, | ||
133 | jsm_board_entry); | ||
134 | if (cur_board_entry->boardnum != adapter_count) { | ||
135 | break; | ||
136 | } | ||
137 | adapter_count++; | ||
138 | } | ||
139 | |||
140 | list_add_tail(&brd->jsm_board_entry, &jsm_board_head); | ||
141 | spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags); | ||
142 | |||
143 | /* store the info for the board we've found */ | 85 | /* store the info for the board we've found */ |
144 | brd->boardnum = adapter_count; | 86 | brd->boardnum = adapter_count++; |
145 | brd->pci_dev = pdev; | 87 | brd->pci_dev = pdev; |
146 | brd->name = jsm_Ids[id].name; | 88 | brd->maxports = 2; |
147 | brd->maxports = jsm_Ids[id].maxports; | ||
148 | brd->dpastatus = BD_NOFEP; | ||
149 | init_waitqueue_head(&brd->state_wait); | ||
150 | 89 | ||
151 | spin_lock_init(&brd->bd_lock); | 90 | spin_lock_init(&brd->bd_lock); |
152 | spin_lock_init(&brd->bd_intr_lock); | 91 | spin_lock_init(&brd->bd_intr_lock); |
153 | 92 | ||
154 | brd->state = BOARD_FOUND; | ||
155 | |||
156 | for (i = 0; i < brd->maxports; i++) | ||
157 | brd->channels[i] = NULL; | ||
158 | |||
159 | /* store which revision we have */ | 93 | /* store which revision we have */ |
160 | pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); | 94 | pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); |
161 | 95 | ||
162 | brd->irq = pdev->irq; | 96 | brd->irq = pdev->irq; |
163 | 97 | ||
164 | switch(brd->pci_dev->device) { | 98 | jsm_printk(INIT, INFO, &brd->pci_dev, |
165 | 99 | "jsm_found_board - NEO adapter\n"); | |
166 | case PCI_DEVICE_ID_NEO_2DB9: | ||
167 | case PCI_DEVICE_ID_NEO_2DB9PRI: | ||
168 | case PCI_DEVICE_ID_NEO_2RJ45: | ||
169 | case PCI_DEVICE_ID_NEO_2RJ45PRI: | ||
170 | |||
171 | /* | ||
172 | * This chip is set up 100% when we get to it. | ||
173 | * No need to enable global interrupts or anything. | ||
174 | */ | ||
175 | brd->dpatype = T_NEO | T_PCIBUS; | ||
176 | 100 | ||
177 | jsm_printk(INIT, INFO, &brd->pci_dev, | 101 | /* get the PCI Base Address Registers */ |
178 | "jsm_found_board - NEO adapter\n"); | 102 | brd->membase = pci_resource_start(pdev, 0); |
103 | brd->membase_end = pci_resource_end(pdev, 0); | ||
179 | 104 | ||
180 | /* get the PCI Base Address Registers */ | 105 | if (brd->membase & 1) |
181 | brd->membase = pci_resource_start(pdev, 0); | 106 | brd->membase &= ~3; |
182 | brd->membase_end = pci_resource_end(pdev, 0); | 107 | else |
108 | brd->membase &= ~15; | ||
183 | 109 | ||
184 | if (brd->membase & 1) | 110 | /* Assign the board_ops struct */ |
185 | brd->membase &= ~3; | 111 | brd->bd_ops = &jsm_neo_ops; |
186 | else | ||
187 | brd->membase &= ~15; | ||
188 | 112 | ||
189 | /* Assign the board_ops struct */ | 113 | brd->bd_uart_offset = 0x200; |
190 | brd->bd_ops = &jsm_neo_ops; | 114 | brd->bd_dividend = 921600; |
191 | 115 | ||
192 | brd->bd_uart_offset = 0x200; | 116 | brd->re_map_membase = ioremap(brd->membase, 0x1000); |
193 | brd->bd_dividend = 921600; | 117 | if (!brd->re_map_membase) { |
194 | 118 | dev_err(&pdev->dev, | |
195 | brd->re_map_membase = ioremap(brd->membase, 0x1000); | 119 | "card has no PCI Memory resources, " |
196 | jsm_printk(INIT, INFO, &brd->pci_dev, | 120 | "failing board.\n"); |
197 | "remapped mem: 0x%p\n", brd->re_map_membase); | 121 | rc = -ENOMEM; |
198 | if (!brd->re_map_membase) { | 122 | goto out_kfree_brd; |
199 | kfree(brd); | ||
200 | dev_err(&pdev->dev, "card has no PCI Memory resources, failing board.\n"); | ||
201 | return -ENOMEM; | ||
202 | } | ||
203 | break; | ||
204 | |||
205 | default: | ||
206 | dev_err(&pdev->dev, "Did not find any compatible Neo or Classic PCI boards in system.\n"); | ||
207 | kfree(brd); | ||
208 | return -ENXIO; | ||
209 | } | 123 | } |
210 | 124 | ||
211 | /* | 125 | rc = request_irq(brd->irq, brd->bd_ops->intr, |
212 | * Do tty device initialization. | 126 | SA_INTERRUPT|SA_SHIRQ, "JSM", brd); |
213 | */ | 127 | if (rc) { |
214 | rc = jsm_finalize_board_init(brd); | 128 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); |
215 | if (rc < 0) { | 129 | goto out_iounmap; |
216 | dev_err(&pdev->dev, "Can't finalize board init (%d)\n", rc); | ||
217 | brd->state = BOARD_FAILED; | ||
218 | retval = -ENXIO; | ||
219 | goto failed0; | ||
220 | } | 130 | } |
221 | 131 | ||
222 | rc = jsm_tty_init(brd); | 132 | rc = jsm_tty_init(brd); |
223 | if (rc < 0) { | 133 | if (rc < 0) { |
224 | dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc); | 134 | dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc); |
225 | brd->state = BOARD_FAILED; | ||
226 | retval = -ENXIO; | 135 | retval = -ENXIO; |
227 | goto failed1; | 136 | goto out_free_irq; |
228 | } | 137 | } |
229 | 138 | ||
230 | rc = jsm_uart_port_init(brd); | 139 | rc = jsm_uart_port_init(brd); |
231 | if (rc < 0) { | 140 | if (rc < 0) { |
141 | /* XXX: leaking all resources from jsm_tty_init here! */ | ||
232 | dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc); | 142 | dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc); |
233 | brd->state = BOARD_FAILED; | ||
234 | retval = -ENXIO; | 143 | retval = -ENXIO; |
235 | goto failed1; | 144 | goto out_free_irq; |
236 | } | 145 | } |
237 | 146 | ||
238 | brd->state = BOARD_READY; | ||
239 | brd->dpastatus = BD_RUNNING; | ||
240 | |||
241 | /* Log the information about the board */ | 147 | /* Log the information about the board */ |
242 | dev_info(&pdev->dev, "board %d: %s (rev %d), irq %d\n",adapter_count, brd->name, brd->rev, brd->irq); | 148 | dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", |
149 | adapter_count, brd->rev, brd->irq); | ||
243 | 150 | ||
244 | /* | 151 | /* |
245 | * allocate flip buffer for board. | 152 | * allocate flip buffer for board. |
@@ -249,156 +156,91 @@ static int jsm_found_board(struct pci_dev *pdev, int id) | |||
249 | */ | 156 | */ |
250 | brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); | 157 | brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); |
251 | if (!brd->flipbuf) { | 158 | if (!brd->flipbuf) { |
159 | /* XXX: leaking all resources from jsm_tty_init and | ||
160 | jsm_uart_port_init here! */ | ||
252 | dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); | 161 | dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); |
253 | brd->state = BOARD_FAILED; | ||
254 | retval = -ENOMEM; | 162 | retval = -ENOMEM; |
255 | goto failed1; | 163 | goto out_free_irq; |
256 | } | 164 | } |
257 | memset(brd->flipbuf, 0, MYFLIPLEN); | 165 | memset(brd->flipbuf, 0, MYFLIPLEN); |
258 | 166 | ||
259 | jsm_create_driver_sysfiles(pdev->dev.driver); | 167 | pci_set_drvdata(pdev, brd); |
260 | 168 | ||
261 | wake_up_interruptible(&brd->state_wait); | ||
262 | return 0; | 169 | return 0; |
263 | failed1: | 170 | out_free_irq: |
264 | free_irq(brd->irq, brd); | 171 | free_irq(brd->irq, brd); |
265 | failed0: | 172 | out_iounmap: |
266 | kfree(brd); | ||
267 | iounmap(brd->re_map_membase); | 173 | iounmap(brd->re_map_membase); |
268 | return retval; | 174 | out_kfree_brd: |
269 | } | 175 | kfree(brd); |
270 | 176 | out_release_regions: | |
271 | /* returns count (>= 0), or negative on error */ | 177 | pci_release_regions(pdev); |
272 | static int jsm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 178 | out_disable_device: |
273 | { | 179 | pci_disable_device(pdev); |
274 | int rc; | 180 | out: |
275 | |||
276 | rc = pci_enable_device(pdev); | ||
277 | if (rc) { | ||
278 | dev_err(&pdev->dev, "Device enable FAILED\n"); | ||
279 | return rc; | ||
280 | } | ||
281 | |||
282 | if ((rc = pci_request_regions(pdev, "jsm"))) { | ||
283 | dev_err(&pdev->dev, "pci_request_region FAILED\n"); | ||
284 | pci_disable_device(pdev); | ||
285 | return rc; | ||
286 | } | ||
287 | |||
288 | if ((rc = jsm_found_board(pdev, ent->driver_data))) { | ||
289 | dev_err(&pdev->dev, "jsm_found_board FAILED\n"); | ||
290 | pci_release_regions(pdev); | ||
291 | pci_disable_device(pdev); | ||
292 | return rc; | ||
293 | } | ||
294 | return rc; | 181 | return rc; |
295 | } | 182 | } |
296 | 183 | ||
297 | 184 | static void jsm_remove_one(struct pci_dev *pdev) | |
298 | /* | ||
299 | * jsm_cleanup_board() | ||
300 | * | ||
301 | * Free all the memory associated with a board | ||
302 | */ | ||
303 | static void jsm_cleanup_board(struct jsm_board *brd) | ||
304 | { | 185 | { |
186 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
305 | int i = 0; | 187 | int i = 0; |
306 | 188 | ||
189 | jsm_remove_uart_port(brd); | ||
190 | |||
307 | free_irq(brd->irq, brd); | 191 | free_irq(brd->irq, brd); |
308 | iounmap(brd->re_map_membase); | 192 | iounmap(brd->re_map_membase); |
309 | 193 | ||
310 | /* Free all allocated channels structs */ | 194 | /* Free all allocated channels structs */ |
311 | for (i = 0; i < brd->maxports; i++) { | 195 | for (i = 0; i < brd->maxports; i++) { |
312 | if (brd->channels[i]) { | 196 | if (brd->channels[i]) { |
313 | if (brd->channels[i]->ch_rqueue) | 197 | kfree(brd->channels[i]->ch_rqueue); |
314 | kfree(brd->channels[i]->ch_rqueue); | 198 | kfree(brd->channels[i]->ch_equeue); |
315 | if (brd->channels[i]->ch_equeue) | 199 | kfree(brd->channels[i]->ch_wqueue); |
316 | kfree(brd->channels[i]->ch_equeue); | ||
317 | if (brd->channels[i]->ch_wqueue) | ||
318 | kfree(brd->channels[i]->ch_wqueue); | ||
319 | kfree(brd->channels[i]); | 200 | kfree(brd->channels[i]); |
320 | } | 201 | } |
321 | } | 202 | } |
322 | 203 | ||
323 | pci_release_regions(brd->pci_dev); | 204 | pci_release_regions(pdev); |
324 | pci_disable_device(brd->pci_dev); | 205 | pci_disable_device(pdev); |
325 | kfree(brd->flipbuf); | 206 | kfree(brd->flipbuf); |
326 | kfree(brd); | 207 | kfree(brd); |
327 | } | 208 | } |
328 | 209 | ||
329 | static void jsm_remove_one(struct pci_dev *dev) | 210 | static struct pci_device_id jsm_pci_tbl[] = { |
330 | { | 211 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 }, |
331 | unsigned long lock_flags; | 212 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 }, |
332 | struct list_head *tmp; | 213 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 }, |
333 | struct jsm_board *brd; | 214 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 }, |
334 | 215 | { 0, } | |
335 | spin_lock_irqsave(&jsm_board_head_lock, lock_flags); | 216 | }; |
336 | list_for_each(tmp, &jsm_board_head) { | 217 | MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); |
337 | brd = list_entry(tmp, struct jsm_board, | ||
338 | jsm_board_entry); | ||
339 | if ( brd != NULL && brd->pci_dev == dev) { | ||
340 | jsm_remove_uart_port(brd); | ||
341 | jsm_cleanup_board(brd); | ||
342 | list_del(&brd->jsm_board_entry); | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags); | ||
347 | return; | ||
348 | } | ||
349 | 218 | ||
350 | struct pci_driver jsm_driver = { | 219 | static struct pci_driver jsm_driver = { |
351 | .name = "jsm", | 220 | .name = "jsm", |
352 | .probe = jsm_init_one, | ||
353 | .id_table = jsm_pci_tbl, | 221 | .id_table = jsm_pci_tbl, |
222 | .probe = jsm_probe_one, | ||
354 | .remove = __devexit_p(jsm_remove_one), | 223 | .remove = __devexit_p(jsm_remove_one), |
355 | }; | 224 | }; |
356 | 225 | ||
357 | /* | ||
358 | * jsm_init_module() | ||
359 | * | ||
360 | * Module load. This is where it all starts. | ||
361 | */ | ||
362 | static int __init jsm_init_module(void) | 226 | static int __init jsm_init_module(void) |
363 | { | 227 | { |
364 | int rc = 0; | 228 | int rc; |
365 | |||
366 | printk(KERN_INFO "%s, Digi International Part Number %s\n", | ||
367 | JSM_VERSION, JSM_VERSION); | ||
368 | |||
369 | /* | ||
370 | * Initialize global stuff | ||
371 | */ | ||
372 | 229 | ||
373 | rc = uart_register_driver(&jsm_uart_driver); | 230 | rc = uart_register_driver(&jsm_uart_driver); |
374 | if (rc < 0) { | 231 | if (!rc) { |
375 | return rc; | 232 | rc = pci_register_driver(&jsm_driver); |
376 | } | 233 | if (rc) |
377 | 234 | uart_unregister_driver(&jsm_uart_driver); | |
378 | rc = pci_register_driver(&jsm_driver); | ||
379 | if (rc < 0) { | ||
380 | uart_unregister_driver(&jsm_uart_driver); | ||
381 | return rc; | ||
382 | } | 235 | } |
383 | jsm_driver_state = DRIVER_READY; | ||
384 | |||
385 | return rc; | 236 | return rc; |
386 | } | 237 | } |
387 | 238 | ||
388 | module_init(jsm_init_module); | ||
389 | |||
390 | /* | ||
391 | * jsm_exit_module() | ||
392 | * | ||
393 | * Module unload. This is where it all ends. | ||
394 | */ | ||
395 | static void __exit jsm_exit_module(void) | 239 | static void __exit jsm_exit_module(void) |
396 | { | 240 | { |
397 | jsm_remove_driver_sysfiles(&jsm_driver.driver); | ||
398 | |||
399 | pci_unregister_driver(&jsm_driver); | 241 | pci_unregister_driver(&jsm_driver); |
400 | |||
401 | uart_unregister_driver(&jsm_uart_driver); | 242 | uart_unregister_driver(&jsm_uart_driver); |
402 | } | 243 | } |
244 | |||
245 | module_init(jsm_init_module); | ||
403 | module_exit(jsm_exit_module); | 246 | module_exit(jsm_exit_module); |
404 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7fb7cc07074b..24fe76c28833 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -1012,27 +1012,3 @@ int jsm_tty_write(struct uart_port *port) | |||
1012 | 1012 | ||
1013 | return data_count; | 1013 | return data_count; |
1014 | } | 1014 | } |
1015 | |||
1016 | static ssize_t jsm_driver_version_show(struct device_driver *ddp, char *buf) | ||
1017 | { | ||
1018 | return snprintf(buf, PAGE_SIZE, "%s\n", JSM_VERSION); | ||
1019 | } | ||
1020 | static DRIVER_ATTR(version, S_IRUSR, jsm_driver_version_show, NULL); | ||
1021 | |||
1022 | static ssize_t jsm_driver_state_show(struct device_driver *ddp, char *buf) | ||
1023 | { | ||
1024 | return snprintf(buf, PAGE_SIZE, "%s\n", jsm_driver_state_text[jsm_driver_state]); | ||
1025 | } | ||
1026 | static DRIVER_ATTR(state, S_IRUSR, jsm_driver_state_show, NULL); | ||
1027 | |||
1028 | void jsm_create_driver_sysfiles(struct device_driver *driverfs) | ||
1029 | { | ||
1030 | driver_create_file(driverfs, &driver_attr_version); | ||
1031 | driver_create_file(driverfs, &driver_attr_state); | ||
1032 | } | ||
1033 | |||
1034 | void jsm_remove_driver_sysfiles(struct device_driver *driverfs) | ||
1035 | { | ||
1036 | driver_remove_file(driverfs, &driver_attr_version); | ||
1037 | driver_remove_file(driverfs, &driver_attr_state); | ||
1038 | } | ||