diff options
Diffstat (limited to 'arch/cris/arch-v32/drivers/sync_serial.c')
-rw-r--r-- | arch/cris/arch-v32/drivers/sync_serial.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index 47c377df6fb3..d2a0fbf5341f 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/major.h> | 14 | #include <linux/major.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/smp_lock.h> | ||
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
@@ -429,23 +430,26 @@ static inline int sync_data_avail_to_end(struct sync_port *port) | |||
429 | static int sync_serial_open(struct inode *inode, struct file *file) | 430 | static int sync_serial_open(struct inode *inode, struct file *file) |
430 | { | 431 | { |
431 | int dev = iminor(inode); | 432 | int dev = iminor(inode); |
433 | int ret = -EBUSY; | ||
432 | sync_port *port; | 434 | sync_port *port; |
433 | reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; | 435 | reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; |
434 | reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes}; | 436 | reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes}; |
435 | 437 | ||
438 | lock_kernel(); | ||
436 | DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); | 439 | DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); |
437 | 440 | ||
438 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) | 441 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) |
439 | { | 442 | { |
440 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | 443 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); |
441 | return -ENODEV; | 444 | ret = -ENODEV; |
445 | goto out; | ||
442 | } | 446 | } |
443 | port = &ports[dev]; | 447 | port = &ports[dev]; |
444 | /* Allow open this device twice (assuming one reader and one writer) */ | 448 | /* Allow open this device twice (assuming one reader and one writer) */ |
445 | if (port->busy == 2) | 449 | if (port->busy == 2) |
446 | { | 450 | { |
447 | DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); | 451 | DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); |
448 | return -EBUSY; | 452 | goto out; |
449 | } | 453 | } |
450 | 454 | ||
451 | 455 | ||
@@ -459,7 +463,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
459 | "synchronous serial 0 dma tr", | 463 | "synchronous serial 0 dma tr", |
460 | &ports[0])) { | 464 | &ports[0])) { |
461 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | 465 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); |
462 | return -EBUSY; | 466 | goto out; |
463 | } else if (request_irq(DMA_IN_INTR_VECT, | 467 | } else if (request_irq(DMA_IN_INTR_VECT, |
464 | rx_interrupt, | 468 | rx_interrupt, |
465 | 0, | 469 | 0, |
@@ -467,7 +471,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
467 | &ports[0])) { | 471 | &ports[0])) { |
468 | free_irq(DMA_OUT_INTR_VECT, &port[0]); | 472 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
469 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | 473 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); |
470 | return -EBUSY; | 474 | goto out; |
471 | } else if (crisv32_request_dma(OUT_DMA_NBR, | 475 | } else if (crisv32_request_dma(OUT_DMA_NBR, |
472 | "synchronous serial 0 dma tr", | 476 | "synchronous serial 0 dma tr", |
473 | DMA_VERBOSE_ON_ERROR, | 477 | DMA_VERBOSE_ON_ERROR, |
@@ -476,7 +480,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
476 | free_irq(DMA_OUT_INTR_VECT, &port[0]); | 480 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
477 | free_irq(DMA_IN_INTR_VECT, &port[0]); | 481 | free_irq(DMA_IN_INTR_VECT, &port[0]); |
478 | printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel"); | 482 | printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel"); |
479 | return -EBUSY; | 483 | goto out; |
480 | } else if (crisv32_request_dma(IN_DMA_NBR, | 484 | } else if (crisv32_request_dma(IN_DMA_NBR, |
481 | "synchronous serial 0 dma rec", | 485 | "synchronous serial 0 dma rec", |
482 | DMA_VERBOSE_ON_ERROR, | 486 | DMA_VERBOSE_ON_ERROR, |
@@ -486,7 +490,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
486 | free_irq(DMA_OUT_INTR_VECT, &port[0]); | 490 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
487 | free_irq(DMA_IN_INTR_VECT, &port[0]); | 491 | free_irq(DMA_IN_INTR_VECT, &port[0]); |
488 | printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel"); | 492 | printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel"); |
489 | return -EBUSY; | 493 | goto out; |
490 | } | 494 | } |
491 | #endif | 495 | #endif |
492 | } | 496 | } |
@@ -499,7 +503,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
499 | "synchronous serial 1 dma tr", | 503 | "synchronous serial 1 dma tr", |
500 | &ports[1])) { | 504 | &ports[1])) { |
501 | printk(KERN_CRIT "Can't allocate sync serial port 1 IRQ"); | 505 | printk(KERN_CRIT "Can't allocate sync serial port 1 IRQ"); |
502 | return -EBUSY; | 506 | goto out; |
503 | } else if (request_irq(DMA7_INTR_VECT, | 507 | } else if (request_irq(DMA7_INTR_VECT, |
504 | rx_interrupt, | 508 | rx_interrupt, |
505 | 0, | 509 | 0, |
@@ -507,7 +511,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
507 | &ports[1])) { | 511 | &ports[1])) { |
508 | free_irq(DMA6_INTR_VECT, &ports[1]); | 512 | free_irq(DMA6_INTR_VECT, &ports[1]); |
509 | printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ"); | 513 | printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ"); |
510 | return -EBUSY; | 514 | goto out; |
511 | } else if (crisv32_request_dma( | 515 | } else if (crisv32_request_dma( |
512 | SYNC_SER1_TX_DMA_NBR, | 516 | SYNC_SER1_TX_DMA_NBR, |
513 | "synchronous serial 1 dma tr", | 517 | "synchronous serial 1 dma tr", |
@@ -517,7 +521,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
517 | free_irq(DMA6_INTR_VECT, &ports[1]); | 521 | free_irq(DMA6_INTR_VECT, &ports[1]); |
518 | free_irq(DMA7_INTR_VECT, &ports[1]); | 522 | free_irq(DMA7_INTR_VECT, &ports[1]); |
519 | printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel"); | 523 | printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel"); |
520 | return -EBUSY; | 524 | goto out; |
521 | } else if (crisv32_request_dma( | 525 | } else if (crisv32_request_dma( |
522 | SYNC_SER1_RX_DMA_NBR, | 526 | SYNC_SER1_RX_DMA_NBR, |
523 | "synchronous serial 3 dma rec", | 527 | "synchronous serial 3 dma rec", |
@@ -528,7 +532,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
528 | free_irq(DMA6_INTR_VECT, &ports[1]); | 532 | free_irq(DMA6_INTR_VECT, &ports[1]); |
529 | free_irq(DMA7_INTR_VECT, &ports[1]); | 533 | free_irq(DMA7_INTR_VECT, &ports[1]); |
530 | printk(KERN_CRIT "Can't allocate sync serial port 3 RX DMA channel"); | 534 | printk(KERN_CRIT "Can't allocate sync serial port 3 RX DMA channel"); |
531 | return -EBUSY; | 535 | goto out; |
532 | } | 536 | } |
533 | #endif | 537 | #endif |
534 | } | 538 | } |
@@ -554,7 +558,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
554 | "synchronous serial manual irq", | 558 | "synchronous serial manual irq", |
555 | &ports[0])) { | 559 | &ports[0])) { |
556 | printk("Can't allocate sync serial manual irq"); | 560 | printk("Can't allocate sync serial manual irq"); |
557 | return -EBUSY; | 561 | goto out; |
558 | } | 562 | } |
559 | } | 563 | } |
560 | #ifdef CONFIG_ETRAXFS | 564 | #ifdef CONFIG_ETRAXFS |
@@ -565,7 +569,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
565 | "synchronous serial manual irq", | 569 | "synchronous serial manual irq", |
566 | &ports[1])) { | 570 | &ports[1])) { |
567 | printk(KERN_CRIT "Can't allocate sync serial manual irq"); | 571 | printk(KERN_CRIT "Can't allocate sync serial manual irq"); |
568 | return -EBUSY; | 572 | goto out; |
569 | } | 573 | } |
570 | } | 574 | } |
571 | #endif | 575 | #endif |
@@ -578,7 +582,10 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
578 | } /* port->init_irqs */ | 582 | } /* port->init_irqs */ |
579 | 583 | ||
580 | port->busy++; | 584 | port->busy++; |
581 | return 0; | 585 | ret = 0; |
586 | out: | ||
587 | unlock_kernel(); | ||
588 | return ret; | ||
582 | } | 589 | } |
583 | 590 | ||
584 | static int sync_serial_release(struct inode *inode, struct file *file) | 591 | static int sync_serial_release(struct inode *inode, struct file *file) |