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