diff options
author | Geoff Levand <geoffrey.levand@am.sony.com> | 2007-02-13 20:37:28 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-15 22:00:19 -0500 |
commit | 75c86e7422751c5be3caaf448d802839ec685725 (patch) | |
tree | 9372526aa0722b9d1bac8341025873cb9e545999 /drivers | |
parent | 724339d76d9407cd1a8ad32a9c1fdf64840cc51b (diff) |
[POWERPC] PS3: Vuart cleanups
Cleanups for the PS3 vuart driver.
- Hide driver private data from external interface with new structure
ps3_vuart_port_priv.
- Fix masking bug in ps3_vuart_get_interrupt_status().
- Add new helper routine ps3_vuart_clear_rx_bytes() to flush rx buffer.
- Add new variable probe_mutex to serialize probe and destroy routines.
- Rename some symbols.
- Add platform check in ps3_vuart_bus_init().
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ps3/vuart.c | 347 | ||||
-rw-r--r-- | drivers/ps3/vuart.h | 30 |
2 files changed, 245 insertions, 132 deletions
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c index ef8fd4c30875..90b3d1ca5172 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/vuart.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <asm/ps3.h> | 24 | #include <asm/ps3.h> |
25 | 25 | ||
26 | #include <asm/firmware.h> | ||
26 | #include <asm/lv1call.h> | 27 | #include <asm/lv1call.h> |
27 | #include <asm/bitops.h> | 28 | #include <asm/bitops.h> |
28 | 29 | ||
@@ -30,7 +31,7 @@ | |||
30 | 31 | ||
31 | MODULE_AUTHOR("Sony Corporation"); | 32 | MODULE_AUTHOR("Sony Corporation"); |
32 | MODULE_LICENSE("GPL v2"); | 33 | MODULE_LICENSE("GPL v2"); |
33 | MODULE_DESCRIPTION("ps3 vuart"); | 34 | MODULE_DESCRIPTION("PS3 vuart"); |
34 | 35 | ||
35 | /** | 36 | /** |
36 | * vuart - An inter-partition data link service. | 37 | * vuart - An inter-partition data link service. |
@@ -157,7 +158,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
157 | unsigned long size; | 158 | unsigned long size; |
158 | unsigned long val; | 159 | unsigned long val; |
159 | 160 | ||
160 | result = lv1_get_virtual_uart_param(dev->port_number, | 161 | result = lv1_get_virtual_uart_param(dev->priv->port_number, |
161 | PARAM_TX_TRIGGER, &trig->tx); | 162 | PARAM_TX_TRIGGER, &trig->tx); |
162 | 163 | ||
163 | if (result) { | 164 | if (result) { |
@@ -166,7 +167,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
166 | return result; | 167 | return result; |
167 | } | 168 | } |
168 | 169 | ||
169 | result = lv1_get_virtual_uart_param(dev->port_number, | 170 | result = lv1_get_virtual_uart_param(dev->priv->port_number, |
170 | PARAM_RX_BUF_SIZE, &size); | 171 | PARAM_RX_BUF_SIZE, &size); |
171 | 172 | ||
172 | if (result) { | 173 | if (result) { |
@@ -175,7 +176,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | |||
175 | return result; | 176 | return result; |
176 | } | 177 | } |
177 | 178 | ||
178 | result = lv1_get_virtual_uart_param(dev->port_number, | 179 | result = lv1_get_virtual_uart_param(dev->priv->port_number, |
179 | PARAM_RX_TRIGGER, &val); | 180 | PARAM_RX_TRIGGER, &val); |
180 | 181 | ||
181 | if (result) { | 182 | if (result) { |
@@ -198,7 +199,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
198 | int result; | 199 | int result; |
199 | unsigned long size; | 200 | unsigned long size; |
200 | 201 | ||
201 | result = lv1_set_virtual_uart_param(dev->port_number, | 202 | result = lv1_set_virtual_uart_param(dev->priv->port_number, |
202 | PARAM_TX_TRIGGER, tx); | 203 | PARAM_TX_TRIGGER, tx); |
203 | 204 | ||
204 | if (result) { | 205 | if (result) { |
@@ -207,7 +208,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
207 | return result; | 208 | return result; |
208 | } | 209 | } |
209 | 210 | ||
210 | result = lv1_get_virtual_uart_param(dev->port_number, | 211 | result = lv1_get_virtual_uart_param(dev->priv->port_number, |
211 | PARAM_RX_BUF_SIZE, &size); | 212 | PARAM_RX_BUF_SIZE, &size); |
212 | 213 | ||
213 | if (result) { | 214 | if (result) { |
@@ -216,7 +217,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
216 | return result; | 217 | return result; |
217 | } | 218 | } |
218 | 219 | ||
219 | result = lv1_set_virtual_uart_param(dev->port_number, | 220 | result = lv1_set_virtual_uart_param(dev->priv->port_number, |
220 | PARAM_RX_TRIGGER, size - rx); | 221 | PARAM_RX_TRIGGER, size - rx); |
221 | 222 | ||
222 | if (result) { | 223 | if (result) { |
@@ -232,9 +233,9 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | |||
232 | } | 233 | } |
233 | 234 | ||
234 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, | 235 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, |
235 | unsigned long *bytes_waiting) | 236 | u64 *bytes_waiting) |
236 | { | 237 | { |
237 | int result = lv1_get_virtual_uart_param(dev->port_number, | 238 | int result = lv1_get_virtual_uart_param(dev->priv->port_number, |
238 | PARAM_RX_BYTES, bytes_waiting); | 239 | PARAM_RX_BYTES, bytes_waiting); |
239 | 240 | ||
240 | if (result) | 241 | if (result) |
@@ -253,10 +254,10 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, | |||
253 | 254 | ||
254 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); | 255 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); |
255 | 256 | ||
256 | dev->interrupt_mask = mask; | 257 | dev->priv->interrupt_mask = mask; |
257 | 258 | ||
258 | result = lv1_set_virtual_uart_param(dev->port_number, | 259 | result = lv1_set_virtual_uart_param(dev->priv->port_number, |
259 | PARAM_INTERRUPT_MASK, dev->interrupt_mask); | 260 | PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask); |
260 | 261 | ||
261 | if (result) | 262 | if (result) |
262 | dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", | 263 | dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", |
@@ -265,62 +266,64 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, | |||
265 | return result; | 266 | return result; |
266 | } | 267 | } |
267 | 268 | ||
268 | static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev, | 269 | static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, |
269 | unsigned long *status) | 270 | unsigned long *status) |
270 | { | 271 | { |
271 | int result = lv1_get_virtual_uart_param(dev->port_number, | 272 | u64 tmp; |
272 | PARAM_INTERRUPT_STATUS, status); | 273 | int result = lv1_get_virtual_uart_param(dev->priv->port_number, |
274 | PARAM_INTERRUPT_STATUS, &tmp); | ||
273 | 275 | ||
274 | if (result) | 276 | if (result) |
275 | dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", | 277 | dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", |
276 | __func__, __LINE__, ps3_result(result)); | 278 | __func__, __LINE__, ps3_result(result)); |
277 | 279 | ||
280 | *status = tmp & dev->priv->interrupt_mask; | ||
281 | |||
278 | dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", | 282 | dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", |
279 | __func__, __LINE__, dev->interrupt_mask, *status, | 283 | __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status); |
280 | dev->interrupt_mask & *status); | ||
281 | 284 | ||
282 | return result; | 285 | return result; |
283 | } | 286 | } |
284 | 287 | ||
285 | int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) | 288 | int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) |
286 | { | 289 | { |
287 | return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0 | 290 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 |
288 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 291 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
289 | | INTERRUPT_MASK_TX); | 292 | | INTERRUPT_MASK_TX); |
290 | } | 293 | } |
291 | 294 | ||
292 | int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) | 295 | int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) |
293 | { | 296 | { |
294 | return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0 | 297 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 |
295 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 298 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
296 | | INTERRUPT_MASK_RX); | 299 | | INTERRUPT_MASK_RX); |
297 | } | 300 | } |
298 | 301 | ||
299 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 302 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) |
300 | { | 303 | { |
301 | return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 | 304 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 |
302 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 305 | : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
303 | | INTERRUPT_MASK_DISCONNECT); | 306 | | INTERRUPT_MASK_DISCONNECT); |
304 | } | 307 | } |
305 | 308 | ||
306 | int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) | 309 | int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) |
307 | { | 310 | { |
308 | return (dev->interrupt_mask & INTERRUPT_MASK_TX) | 311 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) |
309 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 312 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
310 | & ~INTERRUPT_MASK_TX) : 0; | 313 | & ~INTERRUPT_MASK_TX) : 0; |
311 | } | 314 | } |
312 | 315 | ||
313 | int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) | 316 | int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) |
314 | { | 317 | { |
315 | return (dev->interrupt_mask & INTERRUPT_MASK_RX) | 318 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) |
316 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 319 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
317 | & ~INTERRUPT_MASK_RX) : 0; | 320 | & ~INTERRUPT_MASK_RX) : 0; |
318 | } | 321 | } |
319 | 322 | ||
320 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 323 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) |
321 | { | 324 | { |
322 | return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) | 325 | return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) |
323 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | 326 | ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask |
324 | & ~INTERRUPT_MASK_DISCONNECT) : 0; | 327 | & ~INTERRUPT_MASK_DISCONNECT) : 0; |
325 | } | 328 | } |
326 | 329 | ||
@@ -335,9 +338,7 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | |||
335 | { | 338 | { |
336 | int result; | 339 | int result; |
337 | 340 | ||
338 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); | 341 | result = lv1_write_virtual_uart(dev->priv->port_number, |
339 | |||
340 | result = lv1_write_virtual_uart(dev->port_number, | ||
341 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); | 342 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); |
342 | 343 | ||
343 | if (result) { | 344 | if (result) { |
@@ -346,10 +347,10 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | |||
346 | return result; | 347 | return result; |
347 | } | 348 | } |
348 | 349 | ||
349 | dev->stats.bytes_written += *bytes_written; | 350 | dev->priv->stats.bytes_written += *bytes_written; |
350 | 351 | ||
351 | dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, | 352 | dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, |
352 | __LINE__, *bytes_written, bytes, dev->stats.bytes_written); | 353 | *bytes_written, bytes, dev->priv->stats.bytes_written); |
353 | 354 | ||
354 | return result; | 355 | return result; |
355 | } | 356 | } |
@@ -367,7 +368,7 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | |||
367 | 368 | ||
368 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); | 369 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); |
369 | 370 | ||
370 | result = lv1_read_virtual_uart(dev->port_number, | 371 | result = lv1_read_virtual_uart(dev->priv->port_number, |
371 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); | 372 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); |
372 | 373 | ||
373 | if (result) { | 374 | if (result) { |
@@ -376,15 +377,58 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | |||
376 | return result; | 377 | return result; |
377 | } | 378 | } |
378 | 379 | ||
379 | dev->stats.bytes_read += *bytes_read; | 380 | dev->priv->stats.bytes_read += *bytes_read; |
380 | 381 | ||
381 | dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, | 382 | dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, |
382 | *bytes_read, bytes, dev->stats.bytes_read); | 383 | *bytes_read, bytes, dev->priv->stats.bytes_read); |
383 | 384 | ||
384 | return result; | 385 | return result; |
385 | } | 386 | } |
386 | 387 | ||
387 | /** | 388 | /** |
389 | * ps3_vuart_clear_rx_bytes - Discard bytes received. | ||
390 | * @bytes: Max byte count to discard, zero = all pending. | ||
391 | * | ||
392 | * Used to clear pending rx interrupt source. Will not block. | ||
393 | */ | ||
394 | |||
395 | void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, | ||
396 | unsigned int bytes) | ||
397 | { | ||
398 | int result; | ||
399 | u64 bytes_waiting; | ||
400 | void* tmp; | ||
401 | |||
402 | result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting); | ||
403 | |||
404 | BUG_ON(result); | ||
405 | |||
406 | bytes = bytes ? min(bytes, (unsigned int)bytes_waiting) : bytes_waiting; | ||
407 | |||
408 | dev_dbg(&dev->core, "%s:%d: %u\n", __func__, __LINE__, bytes); | ||
409 | |||
410 | if (!bytes) | ||
411 | return; | ||
412 | |||
413 | /* Add some extra space for recently arrived data. */ | ||
414 | |||
415 | bytes += 128; | ||
416 | |||
417 | tmp = kmalloc(bytes, GFP_KERNEL); | ||
418 | |||
419 | if (!tmp) | ||
420 | return; | ||
421 | |||
422 | ps3_vuart_raw_read(dev, tmp, bytes, &bytes_waiting); | ||
423 | |||
424 | kfree(tmp); | ||
425 | |||
426 | /* Don't include these bytes in the stats. */ | ||
427 | |||
428 | dev->priv->stats.bytes_read -= bytes_waiting; | ||
429 | } | ||
430 | |||
431 | /** | ||
388 | * struct list_buffer - An element for a port device fifo buffer list. | 432 | * struct list_buffer - An element for a port device fifo buffer list. |
389 | */ | 433 | */ |
390 | 434 | ||
@@ -416,14 +460,14 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | |||
416 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | 460 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, |
417 | bytes, bytes); | 461 | bytes, bytes); |
418 | 462 | ||
419 | spin_lock_irqsave(&dev->tx_list.lock, flags); | 463 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); |
420 | 464 | ||
421 | if (list_empty(&dev->tx_list.head)) { | 465 | if (list_empty(&dev->priv->tx_list.head)) { |
422 | unsigned long bytes_written; | 466 | unsigned long bytes_written; |
423 | 467 | ||
424 | result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); | 468 | result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); |
425 | 469 | ||
426 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | 470 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); |
427 | 471 | ||
428 | if (result) { | 472 | if (result) { |
429 | dev_dbg(&dev->core, | 473 | dev_dbg(&dev->core, |
@@ -441,7 +485,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | |||
441 | bytes -= bytes_written; | 485 | bytes -= bytes_written; |
442 | buf += bytes_written; | 486 | buf += bytes_written; |
443 | } else | 487 | } else |
444 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | 488 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); |
445 | 489 | ||
446 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); | 490 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); |
447 | 491 | ||
@@ -454,10 +498,10 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | |||
454 | lb->tail = lb->data + bytes; | 498 | lb->tail = lb->data + bytes; |
455 | lb->dbg_number = ++dbg_number; | 499 | lb->dbg_number = ++dbg_number; |
456 | 500 | ||
457 | spin_lock_irqsave(&dev->tx_list.lock, flags); | 501 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); |
458 | list_add_tail(&lb->link, &dev->tx_list.head); | 502 | list_add_tail(&lb->link, &dev->priv->tx_list.head); |
459 | ps3_vuart_enable_interrupt_tx(dev); | 503 | ps3_vuart_enable_interrupt_tx(dev); |
460 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | 504 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); |
461 | 505 | ||
462 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", | 506 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", |
463 | __func__, __LINE__, lb->dbg_number, bytes); | 507 | __func__, __LINE__, lb->dbg_number, bytes); |
@@ -484,44 +528,42 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | |||
484 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | 528 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, |
485 | bytes, bytes); | 529 | bytes, bytes); |
486 | 530 | ||
487 | spin_lock_irqsave(&dev->rx_list.lock, flags); | 531 | spin_lock_irqsave(&dev->priv->rx_list.lock, flags); |
488 | 532 | ||
489 | if (dev->rx_list.bytes_held < bytes) { | 533 | if (dev->priv->rx_list.bytes_held < bytes) { |
490 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | 534 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); |
491 | dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", | 535 | dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", |
492 | __func__, __LINE__, bytes - dev->rx_list.bytes_held); | 536 | __func__, __LINE__, |
537 | bytes - dev->priv->rx_list.bytes_held); | ||
493 | return -EAGAIN; | 538 | return -EAGAIN; |
494 | } | 539 | } |
495 | 540 | ||
496 | list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) { | 541 | list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) { |
497 | bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); | 542 | bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); |
498 | 543 | ||
499 | memcpy(buf, lb->head, bytes_read); | 544 | memcpy(buf, lb->head, bytes_read); |
500 | buf += bytes_read; | 545 | buf += bytes_read; |
501 | bytes -= bytes_read; | 546 | bytes -= bytes_read; |
502 | dev->rx_list.bytes_held -= bytes_read; | 547 | dev->priv->rx_list.bytes_held -= bytes_read; |
503 | 548 | ||
504 | if (bytes_read < lb->tail - lb->head) { | 549 | if (bytes_read < lb->tail - lb->head) { |
505 | lb->head += bytes_read; | 550 | lb->head += bytes_read; |
506 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | 551 | dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " |
507 | 552 | "bytes\n", __func__, __LINE__, lb->dbg_number, | |
508 | dev_dbg(&dev->core, | 553 | bytes_read); |
509 | "%s:%d: dequeued buf_%lu, %lxh bytes\n", | 554 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); |
510 | __func__, __LINE__, lb->dbg_number, bytes_read); | ||
511 | return 0; | 555 | return 0; |
512 | } | 556 | } |
513 | 557 | ||
514 | dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__, | 558 | dev_dbg(&dev->core, "%s:%d: buf_%lu: free, dequeued %lxh " |
515 | lb->dbg_number); | 559 | "bytes\n", __func__, __LINE__, lb->dbg_number, |
560 | bytes_read); | ||
516 | 561 | ||
517 | list_del(&lb->link); | 562 | list_del(&lb->link); |
518 | kfree(lb); | 563 | kfree(lb); |
519 | } | 564 | } |
520 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | ||
521 | |||
522 | dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n", | ||
523 | __func__, __LINE__, lb->dbg_number, bytes); | ||
524 | 565 | ||
566 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); | ||
525 | return 0; | 567 | return 0; |
526 | } | 568 | } |
527 | 569 | ||
@@ -542,9 +584,9 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | |||
542 | 584 | ||
543 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | 585 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); |
544 | 586 | ||
545 | spin_lock_irqsave(&dev->tx_list.lock, flags); | 587 | spin_lock_irqsave(&dev->priv->tx_list.lock, flags); |
546 | 588 | ||
547 | list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) { | 589 | list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) { |
548 | 590 | ||
549 | unsigned long bytes_written; | 591 | unsigned long bytes_written; |
550 | 592 | ||
@@ -578,7 +620,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | |||
578 | 620 | ||
579 | ps3_vuart_disable_interrupt_tx(dev); | 621 | ps3_vuart_disable_interrupt_tx(dev); |
580 | port_full: | 622 | port_full: |
581 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | 623 | spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); |
582 | dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", | 624 | dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", |
583 | __func__, __LINE__, bytes_total); | 625 | __func__, __LINE__, bytes_total); |
584 | return result; | 626 | return result; |
@@ -609,7 +651,7 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) | |||
609 | 651 | ||
610 | BUG_ON(!bytes); | 652 | BUG_ON(!bytes); |
611 | 653 | ||
612 | /* add some extra space for recently arrived data */ | 654 | /* Add some extra space for recently arrived data. */ |
613 | 655 | ||
614 | bytes += 128; | 656 | bytes += 128; |
615 | 657 | ||
@@ -624,12 +666,12 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) | |||
624 | lb->tail = lb->data + bytes; | 666 | lb->tail = lb->data + bytes; |
625 | lb->dbg_number = ++dbg_number; | 667 | lb->dbg_number = ++dbg_number; |
626 | 668 | ||
627 | spin_lock_irqsave(&dev->rx_list.lock, flags); | 669 | spin_lock_irqsave(&dev->priv->rx_list.lock, flags); |
628 | list_add_tail(&lb->link, &dev->rx_list.head); | 670 | list_add_tail(&lb->link, &dev->priv->rx_list.head); |
629 | dev->rx_list.bytes_held += bytes; | 671 | dev->priv->rx_list.bytes_held += bytes; |
630 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | 672 | spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); |
631 | 673 | ||
632 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n", | 674 | dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n", |
633 | __func__, __LINE__, lb->dbg_number, bytes); | 675 | __func__, __LINE__, lb->dbg_number, bytes); |
634 | 676 | ||
635 | return 0; | 677 | return 0; |
@@ -656,7 +698,7 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | |||
656 | int result; | 698 | int result; |
657 | unsigned long status; | 699 | unsigned long status; |
658 | 700 | ||
659 | result = ps3_vuart_get_interrupt_mask(dev, &status); | 701 | result = ps3_vuart_get_interrupt_status(dev, &status); |
660 | 702 | ||
661 | if (result) | 703 | if (result) |
662 | return result; | 704 | return result; |
@@ -665,21 +707,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | |||
665 | status); | 707 | status); |
666 | 708 | ||
667 | if (status & INTERRUPT_MASK_DISCONNECT) { | 709 | if (status & INTERRUPT_MASK_DISCONNECT) { |
668 | dev->stats.disconnect_interrupts++; | 710 | dev->priv->stats.disconnect_interrupts++; |
669 | result = ps3_vuart_handle_interrupt_disconnect(dev); | 711 | result = ps3_vuart_handle_interrupt_disconnect(dev); |
670 | if (result) | 712 | if (result) |
671 | ps3_vuart_disable_interrupt_disconnect(dev); | 713 | ps3_vuart_disable_interrupt_disconnect(dev); |
672 | } | 714 | } |
673 | 715 | ||
674 | if (status & INTERRUPT_MASK_TX) { | 716 | if (status & INTERRUPT_MASK_TX) { |
675 | dev->stats.tx_interrupts++; | 717 | dev->priv->stats.tx_interrupts++; |
676 | result = ps3_vuart_handle_interrupt_tx(dev); | 718 | result = ps3_vuart_handle_interrupt_tx(dev); |
677 | if (result) | 719 | if (result) |
678 | ps3_vuart_disable_interrupt_tx(dev); | 720 | ps3_vuart_disable_interrupt_tx(dev); |
679 | } | 721 | } |
680 | 722 | ||
681 | if (status & INTERRUPT_MASK_RX) { | 723 | if (status & INTERRUPT_MASK_RX) { |
682 | dev->stats.rx_interrupts++; | 724 | dev->priv->stats.rx_interrupts++; |
683 | result = ps3_vuart_handle_interrupt_rx(dev); | 725 | result = ps3_vuart_handle_interrupt_rx(dev); |
684 | if (result) | 726 | if (result) |
685 | ps3_vuart_disable_interrupt_rx(dev); | 727 | ps3_vuart_disable_interrupt_rx(dev); |
@@ -688,12 +730,13 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | |||
688 | return 0; | 730 | return 0; |
689 | } | 731 | } |
690 | 732 | ||
691 | struct vuart_private { | 733 | struct vuart_bus_priv { |
692 | unsigned int in_use; | 734 | const struct ports_bmp bmp; |
693 | unsigned int virq; | 735 | unsigned int virq; |
736 | struct semaphore probe_mutex; | ||
737 | int use_count; | ||
694 | struct ps3_vuart_port_device *devices[PORT_COUNT]; | 738 | struct ps3_vuart_port_device *devices[PORT_COUNT]; |
695 | const struct ports_bmp bmp; | 739 | } static vuart_bus_priv; |
696 | }; | ||
697 | 740 | ||
698 | /** | 741 | /** |
699 | * ps3_vuart_irq_handler - first stage interrupt handler | 742 | * ps3_vuart_irq_handler - first stage interrupt handler |
@@ -705,25 +748,25 @@ struct vuart_private { | |||
705 | 748 | ||
706 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) | 749 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) |
707 | { | 750 | { |
708 | struct vuart_private *private; | 751 | struct vuart_bus_priv *bus_priv; |
709 | 752 | ||
710 | BUG_ON(!_private); | 753 | BUG_ON(!_private); |
711 | private = (struct vuart_private *)_private; | 754 | bus_priv = (struct vuart_bus_priv *)_private; |
712 | 755 | ||
713 | while (1) { | 756 | while (1) { |
714 | unsigned int port; | 757 | unsigned int port; |
715 | 758 | ||
716 | dump_ports_bmp(&private->bmp); | 759 | dump_ports_bmp(&bus_priv->bmp); |
717 | 760 | ||
718 | port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status); | 761 | port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status); |
719 | 762 | ||
720 | if (port == BITS_PER_LONG) | 763 | if (port == BITS_PER_LONG) |
721 | break; | 764 | break; |
722 | 765 | ||
723 | BUG_ON(port >= PORT_COUNT); | 766 | BUG_ON(port >= PORT_COUNT); |
724 | BUG_ON(!private->devices[port]); | 767 | BUG_ON(!bus_priv->devices[port]); |
725 | 768 | ||
726 | ps3_vuart_handle_port_interrupt(private->devices[port]); | 769 | ps3_vuart_handle_port_interrupt(bus_priv->devices[port]); |
727 | } | 770 | } |
728 | 771 | ||
729 | return IRQ_HANDLED; | 772 | return IRQ_HANDLED; |
@@ -744,12 +787,10 @@ static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) | |||
744 | return result; | 787 | return result; |
745 | } | 788 | } |
746 | 789 | ||
747 | static struct vuart_private vuart_private; | ||
748 | |||
749 | static int ps3_vuart_probe(struct device *_dev) | 790 | static int ps3_vuart_probe(struct device *_dev) |
750 | { | 791 | { |
751 | int result; | 792 | int result; |
752 | unsigned long tmp; | 793 | unsigned int port_number; |
753 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | 794 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); |
754 | struct ps3_vuart_port_driver *drv = | 795 | struct ps3_vuart_port_driver *drv = |
755 | to_ps3_vuart_port_driver(_dev->driver); | 796 | to_ps3_vuart_port_driver(_dev->driver); |
@@ -758,7 +799,12 @@ static int ps3_vuart_probe(struct device *_dev) | |||
758 | 799 | ||
759 | BUG_ON(!drv); | 800 | BUG_ON(!drv); |
760 | 801 | ||
761 | result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number); | 802 | down(&vuart_bus_priv.probe_mutex); |
803 | |||
804 | /* Setup vuart_bus_priv.devices[]. */ | ||
805 | |||
806 | result = ps3_vuart_match_id_to_port(dev->match_id, | ||
807 | &port_number); | ||
762 | 808 | ||
763 | if (result) { | 809 | if (result) { |
764 | dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", | 810 | dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", |
@@ -767,24 +813,36 @@ static int ps3_vuart_probe(struct device *_dev) | |||
767 | goto fail_match; | 813 | goto fail_match; |
768 | } | 814 | } |
769 | 815 | ||
770 | if (vuart_private.devices[dev->port_number]) { | 816 | if (vuart_bus_priv.devices[port_number]) { |
771 | dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, | 817 | dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, |
772 | __LINE__, dev->port_number); | 818 | __LINE__, port_number); |
773 | result = -EBUSY; | 819 | result = -EBUSY; |
774 | goto fail_match; | 820 | goto fail_match; |
775 | } | 821 | } |
776 | 822 | ||
777 | vuart_private.devices[dev->port_number] = dev; | 823 | vuart_bus_priv.devices[port_number] = dev; |
824 | |||
825 | /* Setup dev->priv. */ | ||
826 | |||
827 | dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL); | ||
828 | |||
829 | if (!dev->priv) { | ||
830 | result = -ENOMEM; | ||
831 | goto fail_alloc; | ||
832 | } | ||
833 | |||
834 | dev->priv->port_number = port_number; | ||
778 | 835 | ||
779 | INIT_LIST_HEAD(&dev->tx_list.head); | 836 | INIT_LIST_HEAD(&dev->priv->tx_list.head); |
780 | spin_lock_init(&dev->tx_list.lock); | 837 | spin_lock_init(&dev->priv->tx_list.lock); |
781 | INIT_LIST_HEAD(&dev->rx_list.head); | 838 | |
782 | spin_lock_init(&dev->rx_list.lock); | 839 | INIT_LIST_HEAD(&dev->priv->rx_list.head); |
840 | spin_lock_init(&dev->priv->rx_list.lock); | ||
841 | |||
842 | if (++vuart_bus_priv.use_count == 1) { | ||
783 | 843 | ||
784 | vuart_private.in_use++; | ||
785 | if (vuart_private.in_use == 1) { | ||
786 | result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY, | 844 | result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY, |
787 | (void*)&vuart_private.bmp.status, &vuart_private.virq); | 845 | (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq); |
788 | 846 | ||
789 | if (result) { | 847 | if (result) { |
790 | dev_dbg(&dev->core, | 848 | dev_dbg(&dev->core, |
@@ -794,8 +852,8 @@ static int ps3_vuart_probe(struct device *_dev) | |||
794 | goto fail_alloc_irq; | 852 | goto fail_alloc_irq; |
795 | } | 853 | } |
796 | 854 | ||
797 | result = request_irq(vuart_private.virq, ps3_vuart_irq_handler, | 855 | result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, |
798 | IRQF_DISABLED, "vuart", &vuart_private); | 856 | IRQF_DISABLED, "vuart", &vuart_bus_priv); |
799 | 857 | ||
800 | if (result) { | 858 | if (result) { |
801 | dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", | 859 | dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", |
@@ -804,10 +862,11 @@ static int ps3_vuart_probe(struct device *_dev) | |||
804 | } | 862 | } |
805 | } | 863 | } |
806 | 864 | ||
807 | ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX); | ||
808 | |||
809 | /* clear stale pending interrupts */ | 865 | /* clear stale pending interrupts */ |
810 | ps3_vuart_get_interrupt_mask(dev, &tmp); | 866 | |
867 | ps3_vuart_clear_rx_bytes(dev, 0); | ||
868 | |||
869 | ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX); | ||
811 | 870 | ||
812 | ps3_vuart_set_triggers(dev, 1, 1); | 871 | ps3_vuart_set_triggers(dev, 1, 1); |
813 | 872 | ||
@@ -822,20 +881,27 @@ static int ps3_vuart_probe(struct device *_dev) | |||
822 | if (result) { | 881 | if (result) { |
823 | dev_dbg(&dev->core, "%s:%d: drv->probe failed\n", | 882 | dev_dbg(&dev->core, "%s:%d: drv->probe failed\n", |
824 | __func__, __LINE__); | 883 | __func__, __LINE__); |
884 | down(&vuart_bus_priv.probe_mutex); | ||
825 | goto fail_probe; | 885 | goto fail_probe; |
826 | } | 886 | } |
827 | 887 | ||
888 | up(&vuart_bus_priv.probe_mutex); | ||
889 | |||
828 | return result; | 890 | return result; |
829 | 891 | ||
830 | fail_probe: | 892 | fail_probe: |
893 | ps3_vuart_set_interrupt_mask(dev, 0); | ||
831 | fail_request_irq: | 894 | fail_request_irq: |
832 | vuart_private.in_use--; | 895 | ps3_free_vuart_irq(vuart_bus_priv.virq); |
833 | if (!vuart_private.in_use) { | 896 | vuart_bus_priv.virq = NO_IRQ; |
834 | ps3_free_vuart_irq(vuart_private.virq); | ||
835 | vuart_private.virq = NO_IRQ; | ||
836 | } | ||
837 | fail_alloc_irq: | 897 | fail_alloc_irq: |
898 | --vuart_bus_priv.use_count; | ||
899 | kfree(dev->priv); | ||
900 | dev->priv = NULL; | ||
901 | fail_alloc: | ||
902 | vuart_bus_priv.devices[port_number] = 0; | ||
838 | fail_match: | 903 | fail_match: |
904 | up(&vuart_bus_priv.probe_mutex); | ||
839 | dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); | 905 | dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); |
840 | return result; | 906 | return result; |
841 | } | 907 | } |
@@ -846,10 +912,12 @@ static int ps3_vuart_remove(struct device *_dev) | |||
846 | struct ps3_vuart_port_driver *drv = | 912 | struct ps3_vuart_port_driver *drv = |
847 | to_ps3_vuart_port_driver(_dev->driver); | 913 | to_ps3_vuart_port_driver(_dev->driver); |
848 | 914 | ||
915 | down(&vuart_bus_priv.probe_mutex); | ||
916 | |||
849 | dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, | 917 | dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, |
850 | dev->core.bus_id); | 918 | dev->core.bus_id); |
851 | 919 | ||
852 | BUG_ON(vuart_private.in_use < 1); | 920 | BUG_ON(vuart_bus_priv.use_count < 1); |
853 | 921 | ||
854 | if (drv->remove) | 922 | if (drv->remove) |
855 | drv->remove(dev); | 923 | drv->remove(dev); |
@@ -857,13 +925,19 @@ static int ps3_vuart_remove(struct device *_dev) | |||
857 | dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, | 925 | dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, |
858 | __LINE__, dev->core.bus_id); | 926 | __LINE__, dev->core.bus_id); |
859 | 927 | ||
860 | vuart_private.in_use--; | 928 | vuart_bus_priv.devices[dev->priv->port_number] = 0; |
861 | 929 | ||
862 | if (!vuart_private.in_use) { | 930 | if (--vuart_bus_priv.use_count == 0) { |
863 | free_irq(vuart_private.virq, &vuart_private); | 931 | BUG(); |
864 | ps3_free_vuart_irq(vuart_private.virq); | 932 | free_irq(vuart_bus_priv.virq, &vuart_bus_priv); |
865 | vuart_private.virq = NO_IRQ; | 933 | ps3_free_vuart_irq(vuart_bus_priv.virq); |
934 | vuart_bus_priv.virq = NO_IRQ; | ||
866 | } | 935 | } |
936 | |||
937 | kfree(dev->priv); | ||
938 | dev->priv = NULL; | ||
939 | |||
940 | up(&vuart_bus_priv.probe_mutex); | ||
867 | return 0; | 941 | return 0; |
868 | } | 942 | } |
869 | 943 | ||
@@ -884,12 +958,12 @@ static void ps3_vuart_shutdown(struct device *_dev) | |||
884 | } | 958 | } |
885 | 959 | ||
886 | /** | 960 | /** |
887 | * ps3_vuart - The vuart instance. | 961 | * ps3_vuart_bus - The vuart bus instance. |
888 | * | 962 | * |
889 | * The vuart is managed as a bus that port devices connect to. | 963 | * The vuart is managed as a bus that port devices connect to. |
890 | */ | 964 | */ |
891 | 965 | ||
892 | struct bus_type ps3_vuart = { | 966 | struct bus_type ps3_vuart_bus = { |
893 | .name = "ps3_vuart", | 967 | .name = "ps3_vuart", |
894 | .match = ps3_vuart_match, | 968 | .match = ps3_vuart_match, |
895 | .probe = ps3_vuart_probe, | 969 | .probe = ps3_vuart_probe, |
@@ -897,24 +971,30 @@ struct bus_type ps3_vuart = { | |||
897 | .shutdown = ps3_vuart_shutdown, | 971 | .shutdown = ps3_vuart_shutdown, |
898 | }; | 972 | }; |
899 | 973 | ||
900 | int __init ps3_vuart_init(void) | 974 | int __init ps3_vuart_bus_init(void) |
901 | { | 975 | { |
902 | int result; | 976 | int result; |
903 | 977 | ||
904 | pr_debug("%s:%d:\n", __func__, __LINE__); | 978 | pr_debug("%s:%d:\n", __func__, __LINE__); |
905 | result = bus_register(&ps3_vuart); | 979 | |
980 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
981 | return 0; | ||
982 | |||
983 | init_MUTEX(&vuart_bus_priv.probe_mutex); | ||
984 | result = bus_register(&ps3_vuart_bus); | ||
906 | BUG_ON(result); | 985 | BUG_ON(result); |
986 | |||
907 | return result; | 987 | return result; |
908 | } | 988 | } |
909 | 989 | ||
910 | void __exit ps3_vuart_exit(void) | 990 | void __exit ps3_vuart_bus_exit(void) |
911 | { | 991 | { |
912 | pr_debug("%s:%d:\n", __func__, __LINE__); | 992 | pr_debug("%s:%d:\n", __func__, __LINE__); |
913 | bus_unregister(&ps3_vuart); | 993 | bus_unregister(&ps3_vuart_bus); |
914 | } | 994 | } |
915 | 995 | ||
916 | core_initcall(ps3_vuart_init); | 996 | core_initcall(ps3_vuart_bus_init); |
917 | module_exit(ps3_vuart_exit); | 997 | module_exit(ps3_vuart_bus_exit); |
918 | 998 | ||
919 | /** | 999 | /** |
920 | * ps3_vuart_port_release_device - Remove a vuart port device. | 1000 | * ps3_vuart_port_release_device - Remove a vuart port device. |
@@ -922,11 +1002,14 @@ module_exit(ps3_vuart_exit); | |||
922 | 1002 | ||
923 | static void ps3_vuart_port_release_device(struct device *_dev) | 1003 | static void ps3_vuart_port_release_device(struct device *_dev) |
924 | { | 1004 | { |
925 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
926 | #if defined(DEBUG) | 1005 | #if defined(DEBUG) |
927 | memset(dev, 0xad, sizeof(struct ps3_vuart_port_device)); | 1006 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); |
1007 | |||
1008 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
1009 | |||
1010 | BUG_ON(dev->priv && "forgot to free"); | ||
1011 | memset(&dev->core, 0, sizeof(dev->core)); | ||
928 | #endif | 1012 | #endif |
929 | kfree(dev); | ||
930 | } | 1013 | } |
931 | 1014 | ||
932 | /** | 1015 | /** |
@@ -935,11 +1018,12 @@ static void ps3_vuart_port_release_device(struct device *_dev) | |||
935 | 1018 | ||
936 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) | 1019 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) |
937 | { | 1020 | { |
938 | int result; | ||
939 | static unsigned int dev_count = 1; | 1021 | static unsigned int dev_count = 1; |
940 | 1022 | ||
1023 | BUG_ON(dev->priv && "forgot to free"); | ||
1024 | |||
941 | dev->core.parent = NULL; | 1025 | dev->core.parent = NULL; |
942 | dev->core.bus = &ps3_vuart; | 1026 | dev->core.bus = &ps3_vuart_bus; |
943 | dev->core.release = ps3_vuart_port_release_device; | 1027 | dev->core.release = ps3_vuart_port_release_device; |
944 | 1028 | ||
945 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", | 1029 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", |
@@ -947,9 +1031,7 @@ int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) | |||
947 | 1031 | ||
948 | dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); | 1032 | dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); |
949 | 1033 | ||
950 | result = device_register(&dev->core); | 1034 | return device_register(&dev->core); |
951 | |||
952 | return result; | ||
953 | } | 1035 | } |
954 | 1036 | ||
955 | EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); | 1037 | EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); |
@@ -963,7 +1045,7 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) | |||
963 | int result; | 1045 | int result; |
964 | 1046 | ||
965 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); | 1047 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); |
966 | drv->core.bus = &ps3_vuart; | 1048 | drv->core.bus = &ps3_vuart_bus; |
967 | result = driver_register(&drv->core); | 1049 | result = driver_register(&drv->core); |
968 | return result; | 1050 | return result; |
969 | } | 1051 | } |
@@ -976,6 +1058,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); | |||
976 | 1058 | ||
977 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) | 1059 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) |
978 | { | 1060 | { |
1061 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); | ||
979 | driver_unregister(&drv->core); | 1062 | driver_unregister(&drv->core); |
980 | } | 1063 | } |
981 | 1064 | ||
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h index 2cbf728a3a0b..34b360da9ff9 100644 --- a/drivers/ps3/vuart.h +++ b/drivers/ps3/vuart.h | |||
@@ -21,6 +21,36 @@ | |||
21 | #if !defined(_PS3_VUART_H) | 21 | #if !defined(_PS3_VUART_H) |
22 | #define _PS3_VUART_H | 22 | #define _PS3_VUART_H |
23 | 23 | ||
24 | #include <asm/ps3.h> | ||
25 | |||
26 | struct ps3_vuart_stats { | ||
27 | unsigned long bytes_written; | ||
28 | unsigned long bytes_read; | ||
29 | unsigned long tx_interrupts; | ||
30 | unsigned long rx_interrupts; | ||
31 | unsigned long disconnect_interrupts; | ||
32 | }; | ||
33 | |||
34 | /** | ||
35 | * struct ps3_vuart_port_priv - private vuart device data. | ||
36 | */ | ||
37 | |||
38 | struct ps3_vuart_port_priv { | ||
39 | unsigned int port_number; | ||
40 | u64 interrupt_mask; | ||
41 | |||
42 | struct { | ||
43 | spinlock_t lock; | ||
44 | struct list_head head; | ||
45 | } tx_list; | ||
46 | struct { | ||
47 | unsigned long bytes_held; | ||
48 | spinlock_t lock; | ||
49 | struct list_head head; | ||
50 | } rx_list; | ||
51 | struct ps3_vuart_stats stats; | ||
52 | }; | ||
53 | |||
24 | /** | 54 | /** |
25 | * struct ps3_vuart_port_driver - a driver for a device on a vuart port | 55 | * struct ps3_vuart_port_driver - a driver for a device on a vuart port |
26 | */ | 56 | */ |