diff options
author | Alexandre Bounine <alexandre.bounine@idt.com> | 2016-03-22 17:26:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-22 18:36:02 -0400 |
commit | 748353cc2d03d0514a3bf6d0752244ce657f197c (patch) | |
tree | add9bf2705e262905ad3486d2b41dfed6fe61277 /drivers/rapidio | |
parent | b77a2030dface6ea6b0d900bd8496ef41a9f3323 (diff) |
rapidio/tsi721: add HW specific mport removal
Add hardware-specific device removal support for Tsi721 PCIe-to-RapidIO
bridge. To avoid excessive data type conversions, parameters passed to
some internal functions have been revised. Dynamic memory allocations
of rio_mport and rio_ops have been replaced to reduce references between
data structures.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Aurelien Jacquiot <a-jacquiot@ti.com>
Cc: Andre van Herk <andre.van.herk@prodrive-technologies.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r-- | drivers/rapidio/devices/tsi721.c | 302 | ||||
-rw-r--r-- | drivers/rapidio/devices/tsi721.h | 4 | ||||
-rw-r--r-- | drivers/rapidio/devices/tsi721_dma.c | 28 |
3 files changed, 212 insertions, 122 deletions
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 1fc9663ae3b5..db95d71ba4e9 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c | |||
@@ -236,16 +236,15 @@ static int tsi721_cwrite_dma(struct rio_mport *mport, int index, u16 destid, | |||
236 | 236 | ||
237 | /** | 237 | /** |
238 | * tsi721_pw_handler - Tsi721 inbound port-write interrupt handler | 238 | * tsi721_pw_handler - Tsi721 inbound port-write interrupt handler |
239 | * @mport: RapidIO master port structure | 239 | * @priv: tsi721 device private structure |
240 | * | 240 | * |
241 | * Handles inbound port-write interrupts. Copies PW message from an internal | 241 | * Handles inbound port-write interrupts. Copies PW message from an internal |
242 | * buffer into PW message FIFO and schedules deferred routine to process | 242 | * buffer into PW message FIFO and schedules deferred routine to process |
243 | * queued messages. | 243 | * queued messages. |
244 | */ | 244 | */ |
245 | static int | 245 | static int |
246 | tsi721_pw_handler(struct rio_mport *mport) | 246 | tsi721_pw_handler(struct tsi721_device *priv) |
247 | { | 247 | { |
248 | struct tsi721_device *priv = mport->priv; | ||
249 | u32 pw_stat; | 248 | u32 pw_stat; |
250 | u32 pw_buf[TSI721_RIO_PW_MSG_SIZE/sizeof(u32)]; | 249 | u32 pw_buf[TSI721_RIO_PW_MSG_SIZE/sizeof(u32)]; |
251 | 250 | ||
@@ -363,16 +362,15 @@ static int tsi721_dsend(struct rio_mport *mport, int index, | |||
363 | 362 | ||
364 | /** | 363 | /** |
365 | * tsi721_dbell_handler - Tsi721 doorbell interrupt handler | 364 | * tsi721_dbell_handler - Tsi721 doorbell interrupt handler |
366 | * @mport: RapidIO master port structure | 365 | * @priv: tsi721 device-specific data structure |
367 | * | 366 | * |
368 | * Handles inbound doorbell interrupts. Copies doorbell entry from an internal | 367 | * Handles inbound doorbell interrupts. Copies doorbell entry from an internal |
369 | * buffer into DB message FIFO and schedules deferred routine to process | 368 | * buffer into DB message FIFO and schedules deferred routine to process |
370 | * queued DBs. | 369 | * queued DBs. |
371 | */ | 370 | */ |
372 | static int | 371 | static int |
373 | tsi721_dbell_handler(struct rio_mport *mport) | 372 | tsi721_dbell_handler(struct tsi721_device *priv) |
374 | { | 373 | { |
375 | struct tsi721_device *priv = mport->priv; | ||
376 | u32 regval; | 374 | u32 regval; |
377 | 375 | ||
378 | /* Disable IDB interrupts */ | 376 | /* Disable IDB interrupts */ |
@@ -404,7 +402,7 @@ static void tsi721_db_dpc(struct work_struct *work) | |||
404 | /* | 402 | /* |
405 | * Process queued inbound doorbells | 403 | * Process queued inbound doorbells |
406 | */ | 404 | */ |
407 | mport = priv->mport; | 405 | mport = &priv->mport; |
408 | 406 | ||
409 | wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; | 407 | wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; |
410 | rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE; | 408 | rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE; |
@@ -457,15 +455,14 @@ static void tsi721_db_dpc(struct work_struct *work) | |||
457 | /** | 455 | /** |
458 | * tsi721_irqhandler - Tsi721 interrupt handler | 456 | * tsi721_irqhandler - Tsi721 interrupt handler |
459 | * @irq: Linux interrupt number | 457 | * @irq: Linux interrupt number |
460 | * @ptr: Pointer to interrupt-specific data (mport structure) | 458 | * @ptr: Pointer to interrupt-specific data (tsi721_device structure) |
461 | * | 459 | * |
462 | * Handles Tsi721 interrupts signaled using MSI and INTA. Checks reported | 460 | * Handles Tsi721 interrupts signaled using MSI and INTA. Checks reported |
463 | * interrupt events and calls an event-specific handler(s). | 461 | * interrupt events and calls an event-specific handler(s). |
464 | */ | 462 | */ |
465 | static irqreturn_t tsi721_irqhandler(int irq, void *ptr) | 463 | static irqreturn_t tsi721_irqhandler(int irq, void *ptr) |
466 | { | 464 | { |
467 | struct rio_mport *mport = (struct rio_mport *)ptr; | 465 | struct tsi721_device *priv = (struct tsi721_device *)ptr; |
468 | struct tsi721_device *priv = mport->priv; | ||
469 | u32 dev_int; | 466 | u32 dev_int; |
470 | u32 dev_ch_int; | 467 | u32 dev_ch_int; |
471 | u32 intval; | 468 | u32 intval; |
@@ -488,7 +485,7 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) | |||
488 | intval = ioread32(priv->regs + | 485 | intval = ioread32(priv->regs + |
489 | TSI721_SR_CHINT(IDB_QUEUE)); | 486 | TSI721_SR_CHINT(IDB_QUEUE)); |
490 | if (intval & TSI721_SR_CHINT_IDBQRCV) | 487 | if (intval & TSI721_SR_CHINT_IDBQRCV) |
491 | tsi721_dbell_handler(mport); | 488 | tsi721_dbell_handler(priv); |
492 | else | 489 | else |
493 | dev_info(&priv->pdev->dev, | 490 | dev_info(&priv->pdev->dev, |
494 | "Unsupported SR_CH_INT %x\n", intval); | 491 | "Unsupported SR_CH_INT %x\n", intval); |
@@ -545,7 +542,7 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) | |||
545 | /* Service SRIO MAC interrupts */ | 542 | /* Service SRIO MAC interrupts */ |
546 | intval = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT); | 543 | intval = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT); |
547 | if (intval & TSI721_RIO_EM_INT_STAT_PW_RX) | 544 | if (intval & TSI721_RIO_EM_INT_STAT_PW_RX) |
548 | tsi721_pw_handler(mport); | 545 | tsi721_pw_handler(priv); |
549 | } | 546 | } |
550 | 547 | ||
551 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 548 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
@@ -613,13 +610,13 @@ static void tsi721_interrupts_init(struct tsi721_device *priv) | |||
613 | /** | 610 | /** |
614 | * tsi721_omsg_msix - MSI-X interrupt handler for outbound messaging | 611 | * tsi721_omsg_msix - MSI-X interrupt handler for outbound messaging |
615 | * @irq: Linux interrupt number | 612 | * @irq: Linux interrupt number |
616 | * @ptr: Pointer to interrupt-specific data (mport structure) | 613 | * @ptr: Pointer to interrupt-specific data (tsi721_device structure) |
617 | * | 614 | * |
618 | * Handles outbound messaging interrupts signaled using MSI-X. | 615 | * Handles outbound messaging interrupts signaled using MSI-X. |
619 | */ | 616 | */ |
620 | static irqreturn_t tsi721_omsg_msix(int irq, void *ptr) | 617 | static irqreturn_t tsi721_omsg_msix(int irq, void *ptr) |
621 | { | 618 | { |
622 | struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv; | 619 | struct tsi721_device *priv = (struct tsi721_device *)ptr; |
623 | int mbox; | 620 | int mbox; |
624 | 621 | ||
625 | mbox = (irq - priv->msix[TSI721_VECT_OMB0_DONE].vector) % RIO_MAX_MBOX; | 622 | mbox = (irq - priv->msix[TSI721_VECT_OMB0_DONE].vector) % RIO_MAX_MBOX; |
@@ -630,13 +627,13 @@ static irqreturn_t tsi721_omsg_msix(int irq, void *ptr) | |||
630 | /** | 627 | /** |
631 | * tsi721_imsg_msix - MSI-X interrupt handler for inbound messaging | 628 | * tsi721_imsg_msix - MSI-X interrupt handler for inbound messaging |
632 | * @irq: Linux interrupt number | 629 | * @irq: Linux interrupt number |
633 | * @ptr: Pointer to interrupt-specific data (mport structure) | 630 | * @ptr: Pointer to interrupt-specific data (tsi721_device structure) |
634 | * | 631 | * |
635 | * Handles inbound messaging interrupts signaled using MSI-X. | 632 | * Handles inbound messaging interrupts signaled using MSI-X. |
636 | */ | 633 | */ |
637 | static irqreturn_t tsi721_imsg_msix(int irq, void *ptr) | 634 | static irqreturn_t tsi721_imsg_msix(int irq, void *ptr) |
638 | { | 635 | { |
639 | struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv; | 636 | struct tsi721_device *priv = (struct tsi721_device *)ptr; |
640 | int mbox; | 637 | int mbox; |
641 | 638 | ||
642 | mbox = (irq - priv->msix[TSI721_VECT_IMB0_RCV].vector) % RIO_MAX_MBOX; | 639 | mbox = (irq - priv->msix[TSI721_VECT_IMB0_RCV].vector) % RIO_MAX_MBOX; |
@@ -647,19 +644,19 @@ static irqreturn_t tsi721_imsg_msix(int irq, void *ptr) | |||
647 | /** | 644 | /** |
648 | * tsi721_srio_msix - Tsi721 MSI-X SRIO MAC interrupt handler | 645 | * tsi721_srio_msix - Tsi721 MSI-X SRIO MAC interrupt handler |
649 | * @irq: Linux interrupt number | 646 | * @irq: Linux interrupt number |
650 | * @ptr: Pointer to interrupt-specific data (mport structure) | 647 | * @ptr: Pointer to interrupt-specific data (tsi721_device structure) |
651 | * | 648 | * |
652 | * Handles Tsi721 interrupts from SRIO MAC. | 649 | * Handles Tsi721 interrupts from SRIO MAC. |
653 | */ | 650 | */ |
654 | static irqreturn_t tsi721_srio_msix(int irq, void *ptr) | 651 | static irqreturn_t tsi721_srio_msix(int irq, void *ptr) |
655 | { | 652 | { |
656 | struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv; | 653 | struct tsi721_device *priv = (struct tsi721_device *)ptr; |
657 | u32 srio_int; | 654 | u32 srio_int; |
658 | 655 | ||
659 | /* Service SRIO MAC interrupts */ | 656 | /* Service SRIO MAC interrupts */ |
660 | srio_int = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT); | 657 | srio_int = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT); |
661 | if (srio_int & TSI721_RIO_EM_INT_STAT_PW_RX) | 658 | if (srio_int & TSI721_RIO_EM_INT_STAT_PW_RX) |
662 | tsi721_pw_handler((struct rio_mport *)ptr); | 659 | tsi721_pw_handler(priv); |
663 | 660 | ||
664 | return IRQ_HANDLED; | 661 | return IRQ_HANDLED; |
665 | } | 662 | } |
@@ -667,7 +664,7 @@ static irqreturn_t tsi721_srio_msix(int irq, void *ptr) | |||
667 | /** | 664 | /** |
668 | * tsi721_sr2pc_ch_msix - Tsi721 MSI-X SR2PC Channel interrupt handler | 665 | * tsi721_sr2pc_ch_msix - Tsi721 MSI-X SR2PC Channel interrupt handler |
669 | * @irq: Linux interrupt number | 666 | * @irq: Linux interrupt number |
670 | * @ptr: Pointer to interrupt-specific data (mport structure) | 667 | * @ptr: Pointer to interrupt-specific data (tsi721_device structure) |
671 | * | 668 | * |
672 | * Handles Tsi721 interrupts from SR2PC Channel. | 669 | * Handles Tsi721 interrupts from SR2PC Channel. |
673 | * NOTE: At this moment services only one SR2PC channel associated with inbound | 670 | * NOTE: At this moment services only one SR2PC channel associated with inbound |
@@ -675,13 +672,13 @@ static irqreturn_t tsi721_srio_msix(int irq, void *ptr) | |||
675 | */ | 672 | */ |
676 | static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr) | 673 | static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr) |
677 | { | 674 | { |
678 | struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv; | 675 | struct tsi721_device *priv = (struct tsi721_device *)ptr; |
679 | u32 sr_ch_int; | 676 | u32 sr_ch_int; |
680 | 677 | ||
681 | /* Service Inbound DB interrupt from SR2PC channel */ | 678 | /* Service Inbound DB interrupt from SR2PC channel */ |
682 | sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE)); | 679 | sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE)); |
683 | if (sr_ch_int & TSI721_SR_CHINT_IDBQRCV) | 680 | if (sr_ch_int & TSI721_SR_CHINT_IDBQRCV) |
684 | tsi721_dbell_handler((struct rio_mport *)ptr); | 681 | tsi721_dbell_handler(priv); |
685 | 682 | ||
686 | /* Clear interrupts */ | 683 | /* Clear interrupts */ |
687 | iowrite32(sr_ch_int, priv->regs + TSI721_SR_CHINT(IDB_QUEUE)); | 684 | iowrite32(sr_ch_int, priv->regs + TSI721_SR_CHINT(IDB_QUEUE)); |
@@ -693,32 +690,31 @@ static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr) | |||
693 | 690 | ||
694 | /** | 691 | /** |
695 | * tsi721_request_msix - register interrupt service for MSI-X mode. | 692 | * tsi721_request_msix - register interrupt service for MSI-X mode. |
696 | * @mport: RapidIO master port structure | 693 | * @priv: tsi721 device-specific data structure |
697 | * | 694 | * |
698 | * Registers MSI-X interrupt service routines for interrupts that are active | 695 | * Registers MSI-X interrupt service routines for interrupts that are active |
699 | * immediately after mport initialization. Messaging interrupt service routines | 696 | * immediately after mport initialization. Messaging interrupt service routines |
700 | * should be registered during corresponding open requests. | 697 | * should be registered during corresponding open requests. |
701 | */ | 698 | */ |
702 | static int tsi721_request_msix(struct rio_mport *mport) | 699 | static int tsi721_request_msix(struct tsi721_device *priv) |
703 | { | 700 | { |
704 | struct tsi721_device *priv = mport->priv; | ||
705 | int err = 0; | 701 | int err = 0; |
706 | 702 | ||
707 | err = request_irq(priv->msix[TSI721_VECT_IDB].vector, | 703 | err = request_irq(priv->msix[TSI721_VECT_IDB].vector, |
708 | tsi721_sr2pc_ch_msix, 0, | 704 | tsi721_sr2pc_ch_msix, 0, |
709 | priv->msix[TSI721_VECT_IDB].irq_name, (void *)mport); | 705 | priv->msix[TSI721_VECT_IDB].irq_name, (void *)priv); |
710 | if (err) | 706 | if (err) |
711 | goto out; | 707 | return err; |
712 | 708 | ||
713 | err = request_irq(priv->msix[TSI721_VECT_PWRX].vector, | 709 | err = request_irq(priv->msix[TSI721_VECT_PWRX].vector, |
714 | tsi721_srio_msix, 0, | 710 | tsi721_srio_msix, 0, |
715 | priv->msix[TSI721_VECT_PWRX].irq_name, (void *)mport); | 711 | priv->msix[TSI721_VECT_PWRX].irq_name, (void *)priv); |
716 | if (err) | 712 | if (err) { |
717 | free_irq( | 713 | free_irq(priv->msix[TSI721_VECT_IDB].vector, (void *)priv); |
718 | priv->msix[TSI721_VECT_IDB].vector, | 714 | return err; |
719 | (void *)mport); | 715 | } |
720 | out: | 716 | |
721 | return err; | 717 | return 0; |
722 | } | 718 | } |
723 | 719 | ||
724 | /** | 720 | /** |
@@ -831,19 +827,18 @@ static int tsi721_enable_msix(struct tsi721_device *priv) | |||
831 | } | 827 | } |
832 | #endif /* CONFIG_PCI_MSI */ | 828 | #endif /* CONFIG_PCI_MSI */ |
833 | 829 | ||
834 | static int tsi721_request_irq(struct rio_mport *mport) | 830 | static int tsi721_request_irq(struct tsi721_device *priv) |
835 | { | 831 | { |
836 | struct tsi721_device *priv = mport->priv; | ||
837 | int err; | 832 | int err; |
838 | 833 | ||
839 | #ifdef CONFIG_PCI_MSI | 834 | #ifdef CONFIG_PCI_MSI |
840 | if (priv->flags & TSI721_USING_MSIX) | 835 | if (priv->flags & TSI721_USING_MSIX) |
841 | err = tsi721_request_msix(mport); | 836 | err = tsi721_request_msix(priv); |
842 | else | 837 | else |
843 | #endif | 838 | #endif |
844 | err = request_irq(priv->pdev->irq, tsi721_irqhandler, | 839 | err = request_irq(priv->pdev->irq, tsi721_irqhandler, |
845 | (priv->flags & TSI721_USING_MSI) ? 0 : IRQF_SHARED, | 840 | (priv->flags & TSI721_USING_MSI) ? 0 : IRQF_SHARED, |
846 | DRV_NAME, (void *)mport); | 841 | DRV_NAME, (void *)priv); |
847 | 842 | ||
848 | if (err) | 843 | if (err) |
849 | dev_err(&priv->pdev->dev, | 844 | dev_err(&priv->pdev->dev, |
@@ -852,6 +847,17 @@ static int tsi721_request_irq(struct rio_mport *mport) | |||
852 | return err; | 847 | return err; |
853 | } | 848 | } |
854 | 849 | ||
850 | static void tsi721_free_irq(struct tsi721_device *priv) | ||
851 | { | ||
852 | #ifdef CONFIG_PCI_MSI | ||
853 | if (priv->flags & TSI721_USING_MSIX) { | ||
854 | free_irq(priv->msix[TSI721_VECT_IDB].vector, (void *)priv); | ||
855 | free_irq(priv->msix[TSI721_VECT_PWRX].vector, (void *)priv); | ||
856 | } else | ||
857 | #endif | ||
858 | free_irq(priv->pdev->irq, (void *)priv); | ||
859 | } | ||
860 | |||
855 | /** | 861 | /** |
856 | * tsi721_init_pc2sr_mapping - initializes outbound (PCIe->SRIO) | 862 | * tsi721_init_pc2sr_mapping - initializes outbound (PCIe->SRIO) |
857 | * translation regions. | 863 | * translation regions. |
@@ -1103,6 +1109,26 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv) | |||
1103 | priv->ibwin_cnt = TSI721_IBWIN_NUM; | 1109 | priv->ibwin_cnt = TSI721_IBWIN_NUM; |
1104 | } | 1110 | } |
1105 | 1111 | ||
1112 | /* | ||
1113 | * tsi721_close_sr2pc_mapping - closes all active inbound (SRIO->PCIe) | ||
1114 | * translation regions. | ||
1115 | * @priv: pointer to tsi721 device private data | ||
1116 | */ | ||
1117 | static void tsi721_close_sr2pc_mapping(struct tsi721_device *priv) | ||
1118 | { | ||
1119 | struct tsi721_ib_win *ib_win; | ||
1120 | int i; | ||
1121 | |||
1122 | /* Disable all active SR2PC inbound windows */ | ||
1123 | for (i = 0; i < TSI721_IBWIN_NUM; i++) { | ||
1124 | ib_win = &priv->ib_win[i]; | ||
1125 | if (ib_win->active) { | ||
1126 | iowrite32(0, priv->regs + TSI721_IBWIN_LB(i)); | ||
1127 | ib_win->active = false; | ||
1128 | } | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1106 | /** | 1132 | /** |
1107 | * tsi721_port_write_init - Inbound port write interface init | 1133 | * tsi721_port_write_init - Inbound port write interface init |
1108 | * @priv: pointer to tsi721 private data | 1134 | * @priv: pointer to tsi721 private data |
@@ -1126,6 +1152,11 @@ static int tsi721_port_write_init(struct tsi721_device *priv) | |||
1126 | return 0; | 1152 | return 0; |
1127 | } | 1153 | } |
1128 | 1154 | ||
1155 | static void tsi721_port_write_free(struct tsi721_device *priv) | ||
1156 | { | ||
1157 | kfifo_free(&priv->pw_fifo); | ||
1158 | } | ||
1159 | |||
1129 | static int tsi721_doorbell_init(struct tsi721_device *priv) | 1160 | static int tsi721_doorbell_init(struct tsi721_device *priv) |
1130 | { | 1161 | { |
1131 | /* Outbound Doorbells do not require any setup. | 1162 | /* Outbound Doorbells do not require any setup. |
@@ -1496,6 +1527,7 @@ tsi721_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
1496 | static void tsi721_omsg_handler(struct tsi721_device *priv, int ch) | 1527 | static void tsi721_omsg_handler(struct tsi721_device *priv, int ch) |
1497 | { | 1528 | { |
1498 | u32 omsg_int; | 1529 | u32 omsg_int; |
1530 | struct rio_mport *mport = &priv->mport; | ||
1499 | 1531 | ||
1500 | spin_lock(&priv->omsg_ring[ch].lock); | 1532 | spin_lock(&priv->omsg_ring[ch].lock); |
1501 | 1533 | ||
@@ -1537,7 +1569,7 @@ static void tsi721_omsg_handler(struct tsi721_device *priv, int ch) | |||
1537 | priv->omsg_ring[ch].sts_rdptr = srd_ptr; | 1569 | priv->omsg_ring[ch].sts_rdptr = srd_ptr; |
1538 | iowrite32(srd_ptr, priv->regs + TSI721_OBDMAC_DSRP(ch)); | 1570 | iowrite32(srd_ptr, priv->regs + TSI721_OBDMAC_DSRP(ch)); |
1539 | 1571 | ||
1540 | if (!priv->mport->outb_msg[ch].mcback) | 1572 | if (!mport->outb_msg[ch].mcback) |
1541 | goto no_sts_update; | 1573 | goto no_sts_update; |
1542 | 1574 | ||
1543 | /* Inform upper layer about transfer completion */ | 1575 | /* Inform upper layer about transfer completion */ |
@@ -1564,7 +1596,7 @@ static void tsi721_omsg_handler(struct tsi721_device *priv, int ch) | |||
1564 | if (tx_slot == priv->omsg_ring[ch].size) | 1596 | if (tx_slot == priv->omsg_ring[ch].size) |
1565 | tx_slot = 0; | 1597 | tx_slot = 0; |
1566 | BUG_ON(tx_slot >= priv->omsg_ring[ch].size); | 1598 | BUG_ON(tx_slot >= priv->omsg_ring[ch].size); |
1567 | priv->mport->outb_msg[ch].mcback(priv->mport, | 1599 | mport->outb_msg[ch].mcback(mport, |
1568 | priv->omsg_ring[ch].dev_id, ch, | 1600 | priv->omsg_ring[ch].dev_id, ch, |
1569 | tx_slot); | 1601 | tx_slot); |
1570 | } | 1602 | } |
@@ -1587,8 +1619,8 @@ no_sts_update: | |||
1587 | ioread32(priv->regs + TSI721_OBDMAC_CTL(ch)); | 1619 | ioread32(priv->regs + TSI721_OBDMAC_CTL(ch)); |
1588 | 1620 | ||
1589 | /* Inform upper level to clear all pending tx slots */ | 1621 | /* Inform upper level to clear all pending tx slots */ |
1590 | if (priv->mport->outb_msg[ch].mcback) | 1622 | if (mport->outb_msg[ch].mcback) |
1591 | priv->mport->outb_msg[ch].mcback(priv->mport, | 1623 | mport->outb_msg[ch].mcback(mport, |
1592 | priv->omsg_ring[ch].dev_id, ch, | 1624 | priv->omsg_ring[ch].dev_id, ch, |
1593 | priv->omsg_ring[ch].tx_slot); | 1625 | priv->omsg_ring[ch].tx_slot); |
1594 | /* Synch tx_slot tracking */ | 1626 | /* Synch tx_slot tracking */ |
@@ -1710,12 +1742,11 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, | |||
1710 | 1742 | ||
1711 | #ifdef CONFIG_PCI_MSI | 1743 | #ifdef CONFIG_PCI_MSI |
1712 | if (priv->flags & TSI721_USING_MSIX) { | 1744 | if (priv->flags & TSI721_USING_MSIX) { |
1745 | int idx = TSI721_VECT_OMB0_DONE + mbox; | ||
1746 | |||
1713 | /* Request interrupt service if we are in MSI-X mode */ | 1747 | /* Request interrupt service if we are in MSI-X mode */ |
1714 | rc = request_irq( | 1748 | rc = request_irq(priv->msix[idx].vector, tsi721_omsg_msix, 0, |
1715 | priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector, | 1749 | priv->msix[idx].irq_name, (void *)priv); |
1716 | tsi721_omsg_msix, 0, | ||
1717 | priv->msix[TSI721_VECT_OMB0_DONE + mbox].irq_name, | ||
1718 | (void *)mport); | ||
1719 | 1750 | ||
1720 | if (rc) { | 1751 | if (rc) { |
1721 | dev_dbg(&priv->pdev->dev, | 1752 | dev_dbg(&priv->pdev->dev, |
@@ -1724,18 +1755,16 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, | |||
1724 | goto out_stat; | 1755 | goto out_stat; |
1725 | } | 1756 | } |
1726 | 1757 | ||
1727 | rc = request_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector, | 1758 | idx = TSI721_VECT_OMB0_INT + mbox; |
1728 | tsi721_omsg_msix, 0, | 1759 | rc = request_irq(priv->msix[idx].vector, tsi721_omsg_msix, 0, |
1729 | priv->msix[TSI721_VECT_OMB0_INT + mbox].irq_name, | 1760 | priv->msix[idx].irq_name, (void *)priv); |
1730 | (void *)mport); | ||
1731 | 1761 | ||
1732 | if (rc) { | 1762 | if (rc) { |
1733 | dev_dbg(&priv->pdev->dev, | 1763 | dev_dbg(&priv->pdev->dev, |
1734 | "Unable to allocate MSI-X interrupt for " | 1764 | "Unable to allocate MSI-X interrupt for " |
1735 | "MBOX%d-INT\n", mbox); | 1765 | "MBOX%d-INT\n", mbox); |
1736 | free_irq( | 1766 | idx = TSI721_VECT_OMB0_DONE + mbox; |
1737 | priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector, | 1767 | free_irq(priv->msix[idx].vector, (void *)priv); |
1738 | (void *)mport); | ||
1739 | goto out_stat; | 1768 | goto out_stat; |
1740 | } | 1769 | } |
1741 | } | 1770 | } |
@@ -1819,9 +1848,9 @@ static void tsi721_close_outb_mbox(struct rio_mport *mport, int mbox) | |||
1819 | #ifdef CONFIG_PCI_MSI | 1848 | #ifdef CONFIG_PCI_MSI |
1820 | if (priv->flags & TSI721_USING_MSIX) { | 1849 | if (priv->flags & TSI721_USING_MSIX) { |
1821 | free_irq(priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector, | 1850 | free_irq(priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector, |
1822 | (void *)mport); | 1851 | (void *)priv); |
1823 | free_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector, | 1852 | free_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector, |
1824 | (void *)mport); | 1853 | (void *)priv); |
1825 | } | 1854 | } |
1826 | #endif /* CONFIG_PCI_MSI */ | 1855 | #endif /* CONFIG_PCI_MSI */ |
1827 | 1856 | ||
@@ -1866,6 +1895,7 @@ static void tsi721_imsg_handler(struct tsi721_device *priv, int ch) | |||
1866 | { | 1895 | { |
1867 | u32 mbox = ch - 4; | 1896 | u32 mbox = ch - 4; |
1868 | u32 imsg_int; | 1897 | u32 imsg_int; |
1898 | struct rio_mport *mport = &priv->mport; | ||
1869 | 1899 | ||
1870 | spin_lock(&priv->imsg_ring[mbox].lock); | 1900 | spin_lock(&priv->imsg_ring[mbox].lock); |
1871 | 1901 | ||
@@ -1888,8 +1918,8 @@ static void tsi721_imsg_handler(struct tsi721_device *priv, int ch) | |||
1888 | 1918 | ||
1889 | /* If an IB Msg is received notify the upper layer */ | 1919 | /* If an IB Msg is received notify the upper layer */ |
1890 | if (imsg_int & TSI721_IBDMAC_INT_DQ_RCV && | 1920 | if (imsg_int & TSI721_IBDMAC_INT_DQ_RCV && |
1891 | priv->mport->inb_msg[mbox].mcback) | 1921 | mport->inb_msg[mbox].mcback) |
1892 | priv->mport->inb_msg[mbox].mcback(priv->mport, | 1922 | mport->inb_msg[mbox].mcback(mport, |
1893 | priv->imsg_ring[mbox].dev_id, mbox, -1); | 1923 | priv->imsg_ring[mbox].dev_id, mbox, -1); |
1894 | 1924 | ||
1895 | if (!(priv->flags & TSI721_USING_MSIX)) { | 1925 | if (!(priv->flags & TSI721_USING_MSIX)) { |
@@ -1994,7 +2024,7 @@ static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id, | |||
1994 | * once when first inbound mailbox is requested. | 2024 | * once when first inbound mailbox is requested. |
1995 | */ | 2025 | */ |
1996 | if (!(priv->flags & TSI721_IMSGID_SET)) { | 2026 | if (!(priv->flags & TSI721_IMSGID_SET)) { |
1997 | iowrite32((u32)priv->mport->host_deviceid, | 2027 | iowrite32((u32)priv->mport.host_deviceid, |
1998 | priv->regs + TSI721_IB_DEVID); | 2028 | priv->regs + TSI721_IB_DEVID); |
1999 | priv->flags |= TSI721_IMSGID_SET; | 2029 | priv->flags |= TSI721_IMSGID_SET; |
2000 | } | 2030 | } |
@@ -2025,11 +2055,11 @@ static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id, | |||
2025 | 2055 | ||
2026 | #ifdef CONFIG_PCI_MSI | 2056 | #ifdef CONFIG_PCI_MSI |
2027 | if (priv->flags & TSI721_USING_MSIX) { | 2057 | if (priv->flags & TSI721_USING_MSIX) { |
2058 | int idx = TSI721_VECT_IMB0_RCV + mbox; | ||
2059 | |||
2028 | /* Request interrupt service if we are in MSI-X mode */ | 2060 | /* Request interrupt service if we are in MSI-X mode */ |
2029 | rc = request_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector, | 2061 | rc = request_irq(priv->msix[idx].vector, tsi721_imsg_msix, 0, |
2030 | tsi721_imsg_msix, 0, | 2062 | priv->msix[idx].irq_name, (void *)priv); |
2031 | priv->msix[TSI721_VECT_IMB0_RCV + mbox].irq_name, | ||
2032 | (void *)mport); | ||
2033 | 2063 | ||
2034 | if (rc) { | 2064 | if (rc) { |
2035 | dev_dbg(&priv->pdev->dev, | 2065 | dev_dbg(&priv->pdev->dev, |
@@ -2038,10 +2068,9 @@ static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id, | |||
2038 | goto out_desc; | 2068 | goto out_desc; |
2039 | } | 2069 | } |
2040 | 2070 | ||
2041 | rc = request_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector, | 2071 | idx = TSI721_VECT_IMB0_INT + mbox; |
2042 | tsi721_imsg_msix, 0, | 2072 | rc = request_irq(priv->msix[idx].vector, tsi721_imsg_msix, 0, |
2043 | priv->msix[TSI721_VECT_IMB0_INT + mbox].irq_name, | 2073 | priv->msix[idx].irq_name, (void *)priv); |
2044 | (void *)mport); | ||
2045 | 2074 | ||
2046 | if (rc) { | 2075 | if (rc) { |
2047 | dev_dbg(&priv->pdev->dev, | 2076 | dev_dbg(&priv->pdev->dev, |
@@ -2049,7 +2078,7 @@ static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id, | |||
2049 | "IBOX%d-INT\n", mbox); | 2078 | "IBOX%d-INT\n", mbox); |
2050 | free_irq( | 2079 | free_irq( |
2051 | priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector, | 2080 | priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector, |
2052 | (void *)mport); | 2081 | (void *)priv); |
2053 | goto out_desc; | 2082 | goto out_desc; |
2054 | } | 2083 | } |
2055 | } | 2084 | } |
@@ -2120,9 +2149,9 @@ static void tsi721_close_inb_mbox(struct rio_mport *mport, int mbox) | |||
2120 | #ifdef CONFIG_PCI_MSI | 2149 | #ifdef CONFIG_PCI_MSI |
2121 | if (priv->flags & TSI721_USING_MSIX) { | 2150 | if (priv->flags & TSI721_USING_MSIX) { |
2122 | free_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector, | 2151 | free_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector, |
2123 | (void *)mport); | 2152 | (void *)priv); |
2124 | free_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector, | 2153 | free_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector, |
2125 | (void *)mport); | 2154 | (void *)priv); |
2126 | } | 2155 | } |
2127 | #endif /* CONFIG_PCI_MSI */ | 2156 | #endif /* CONFIG_PCI_MSI */ |
2128 | 2157 | ||
@@ -2371,6 +2400,32 @@ static void tsi721_disable_ints(struct tsi721_device *priv) | |||
2371 | iowrite32(0, priv->regs + TSI721_RIO_EM_DEV_INT_EN); | 2400 | iowrite32(0, priv->regs + TSI721_RIO_EM_DEV_INT_EN); |
2372 | } | 2401 | } |
2373 | 2402 | ||
2403 | static struct rio_ops tsi721_rio_ops = { | ||
2404 | .lcread = tsi721_lcread, | ||
2405 | .lcwrite = tsi721_lcwrite, | ||
2406 | .cread = tsi721_cread_dma, | ||
2407 | .cwrite = tsi721_cwrite_dma, | ||
2408 | .dsend = tsi721_dsend, | ||
2409 | .open_inb_mbox = tsi721_open_inb_mbox, | ||
2410 | .close_inb_mbox = tsi721_close_inb_mbox, | ||
2411 | .open_outb_mbox = tsi721_open_outb_mbox, | ||
2412 | .close_outb_mbox = tsi721_close_outb_mbox, | ||
2413 | .add_outb_message = tsi721_add_outb_message, | ||
2414 | .add_inb_buffer = tsi721_add_inb_buffer, | ||
2415 | .get_inb_message = tsi721_get_inb_message, | ||
2416 | .map_inb = tsi721_rio_map_inb_mem, | ||
2417 | .unmap_inb = tsi721_rio_unmap_inb_mem, | ||
2418 | .pwenable = tsi721_pw_enable, | ||
2419 | .query_mport = tsi721_query_mport, | ||
2420 | }; | ||
2421 | |||
2422 | static void tsi721_mport_release(struct device *dev) | ||
2423 | { | ||
2424 | struct rio_mport *mport = to_rio_mport(dev); | ||
2425 | |||
2426 | dev_dbg(dev, "RIO: %s %s id=%d\n", __func__, mport->name, mport->id); | ||
2427 | } | ||
2428 | |||
2374 | /** | 2429 | /** |
2375 | * tsi721_setup_mport - Setup Tsi721 as RapidIO subsystem master port | 2430 | * tsi721_setup_mport - Setup Tsi721 as RapidIO subsystem master port |
2376 | * @priv: pointer to tsi721 private data | 2431 | * @priv: pointer to tsi721 private data |
@@ -2381,47 +2436,20 @@ static int tsi721_setup_mport(struct tsi721_device *priv) | |||
2381 | { | 2436 | { |
2382 | struct pci_dev *pdev = priv->pdev; | 2437 | struct pci_dev *pdev = priv->pdev; |
2383 | int err = 0; | 2438 | int err = 0; |
2384 | struct rio_ops *ops; | 2439 | struct rio_mport *mport = &priv->mport; |
2385 | |||
2386 | struct rio_mport *mport; | ||
2387 | |||
2388 | ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL); | ||
2389 | if (!ops) { | ||
2390 | dev_dbg(&pdev->dev, "Unable to allocate memory for rio_ops\n"); | ||
2391 | return -ENOMEM; | ||
2392 | } | ||
2393 | 2440 | ||
2394 | ops->lcread = tsi721_lcread; | 2441 | err = rio_mport_initialize(mport); |
2395 | ops->lcwrite = tsi721_lcwrite; | 2442 | if (err) |
2396 | ops->cread = tsi721_cread_dma; | 2443 | return err; |
2397 | ops->cwrite = tsi721_cwrite_dma; | ||
2398 | ops->dsend = tsi721_dsend; | ||
2399 | ops->open_inb_mbox = tsi721_open_inb_mbox; | ||
2400 | ops->close_inb_mbox = tsi721_close_inb_mbox; | ||
2401 | ops->open_outb_mbox = tsi721_open_outb_mbox; | ||
2402 | ops->close_outb_mbox = tsi721_close_outb_mbox; | ||
2403 | ops->add_outb_message = tsi721_add_outb_message; | ||
2404 | ops->add_inb_buffer = tsi721_add_inb_buffer; | ||
2405 | ops->get_inb_message = tsi721_get_inb_message; | ||
2406 | ops->map_inb = tsi721_rio_map_inb_mem; | ||
2407 | ops->unmap_inb = tsi721_rio_unmap_inb_mem; | ||
2408 | ops->query_mport = tsi721_query_mport; | ||
2409 | |||
2410 | mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); | ||
2411 | if (!mport) { | ||
2412 | kfree(ops); | ||
2413 | dev_dbg(&pdev->dev, "Unable to allocate memory for mport\n"); | ||
2414 | return -ENOMEM; | ||
2415 | } | ||
2416 | 2444 | ||
2417 | mport->ops = ops; | 2445 | mport->ops = &tsi721_rio_ops; |
2418 | mport->index = 0; | 2446 | mport->index = 0; |
2419 | mport->sys_size = 0; /* small system */ | 2447 | mport->sys_size = 0; /* small system */ |
2420 | mport->phy_type = RIO_PHY_SERIAL; | 2448 | mport->phy_type = RIO_PHY_SERIAL; |
2421 | mport->priv = (void *)priv; | 2449 | mport->priv = (void *)priv; |
2422 | mport->phys_efptr = 0x100; | 2450 | mport->phys_efptr = 0x100; |
2423 | mport->dev.parent = &pdev->dev; | 2451 | mport->dev.parent = &pdev->dev; |
2424 | priv->mport = mport; | 2452 | mport->dev.release = tsi721_mport_release; |
2425 | 2453 | ||
2426 | INIT_LIST_HEAD(&mport->dbells); | 2454 | INIT_LIST_HEAD(&mport->dbells); |
2427 | 2455 | ||
@@ -2443,27 +2471,24 @@ static int tsi721_setup_mport(struct tsi721_device *priv) | |||
2443 | "MSI/MSI-X is not available. Using legacy INTx.\n"); | 2471 | "MSI/MSI-X is not available. Using legacy INTx.\n"); |
2444 | #endif /* CONFIG_PCI_MSI */ | 2472 | #endif /* CONFIG_PCI_MSI */ |
2445 | 2473 | ||
2446 | err = tsi721_request_irq(mport); | 2474 | err = tsi721_request_irq(priv); |
2447 | 2475 | ||
2448 | if (!err) { | 2476 | if (err) { |
2449 | tsi721_interrupts_init(priv); | ||
2450 | ops->pwenable = tsi721_pw_enable; | ||
2451 | } else { | ||
2452 | dev_err(&pdev->dev, "Unable to get assigned PCI IRQ " | 2477 | dev_err(&pdev->dev, "Unable to get assigned PCI IRQ " |
2453 | "vector %02X err=0x%x\n", pdev->irq, err); | 2478 | "vector %02X err=0x%x\n", pdev->irq, err); |
2454 | goto err_exit; | 2479 | return err; |
2455 | } | 2480 | } |
2456 | 2481 | ||
2457 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 2482 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
2458 | tsi721_register_dma(priv); | 2483 | err = tsi721_register_dma(priv); |
2484 | if (err) | ||
2485 | goto err_exit; | ||
2459 | #endif | 2486 | #endif |
2460 | /* Enable SRIO link */ | 2487 | /* Enable SRIO link */ |
2461 | iowrite32(ioread32(priv->regs + TSI721_DEVCTL) | | 2488 | iowrite32(ioread32(priv->regs + TSI721_DEVCTL) | |
2462 | TSI721_DEVCTL_SRBOOT_CMPL, | 2489 | TSI721_DEVCTL_SRBOOT_CMPL, |
2463 | priv->regs + TSI721_DEVCTL); | 2490 | priv->regs + TSI721_DEVCTL); |
2464 | 2491 | ||
2465 | rio_register_mport(mport); | ||
2466 | |||
2467 | if (mport->host_deviceid >= 0) | 2492 | if (mport->host_deviceid >= 0) |
2468 | iowrite32(RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER | | 2493 | iowrite32(RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER | |
2469 | RIO_PORT_GEN_DISCOVERED, | 2494 | RIO_PORT_GEN_DISCOVERED, |
@@ -2471,11 +2496,16 @@ static int tsi721_setup_mport(struct tsi721_device *priv) | |||
2471 | else | 2496 | else |
2472 | iowrite32(0, priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR)); | 2497 | iowrite32(0, priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR)); |
2473 | 2498 | ||
2499 | err = rio_register_mport(mport); | ||
2500 | if (err) { | ||
2501 | tsi721_unregister_dma(priv); | ||
2502 | goto err_exit; | ||
2503 | } | ||
2504 | |||
2474 | return 0; | 2505 | return 0; |
2475 | 2506 | ||
2476 | err_exit: | 2507 | err_exit: |
2477 | kfree(mport); | 2508 | tsi721_free_irq(priv); |
2478 | kfree(ops); | ||
2479 | return err; | 2509 | return err; |
2480 | } | 2510 | } |
2481 | 2511 | ||
@@ -2639,10 +2669,12 @@ static int tsi721_probe(struct pci_dev *pdev, | |||
2639 | goto err_free_consistent; | 2669 | goto err_free_consistent; |
2640 | 2670 | ||
2641 | pci_set_drvdata(pdev, priv); | 2671 | pci_set_drvdata(pdev, priv); |
2672 | tsi721_interrupts_init(priv); | ||
2642 | 2673 | ||
2643 | return 0; | 2674 | return 0; |
2644 | 2675 | ||
2645 | err_free_consistent: | 2676 | err_free_consistent: |
2677 | tsi721_port_write_free(priv); | ||
2646 | tsi721_doorbell_free(priv); | 2678 | tsi721_doorbell_free(priv); |
2647 | err_free_bdma: | 2679 | err_free_bdma: |
2648 | tsi721_bdma_maint_free(priv); | 2680 | tsi721_bdma_maint_free(priv); |
@@ -2662,6 +2694,40 @@ err_exit: | |||
2662 | return err; | 2694 | return err; |
2663 | } | 2695 | } |
2664 | 2696 | ||
2697 | static void tsi721_remove(struct pci_dev *pdev) | ||
2698 | { | ||
2699 | struct tsi721_device *priv = pci_get_drvdata(pdev); | ||
2700 | |||
2701 | dev_dbg(&pdev->dev, "%s enter\n", __func__); | ||
2702 | |||
2703 | tsi721_disable_ints(priv); | ||
2704 | tsi721_free_irq(priv); | ||
2705 | rio_unregister_mport(&priv->mport); | ||
2706 | |||
2707 | tsi721_unregister_dma(priv); | ||
2708 | tsi721_bdma_maint_free(priv); | ||
2709 | tsi721_doorbell_free(priv); | ||
2710 | tsi721_port_write_free(priv); | ||
2711 | tsi721_close_sr2pc_mapping(priv); | ||
2712 | |||
2713 | if (priv->regs) | ||
2714 | iounmap(priv->regs); | ||
2715 | if (priv->odb_base) | ||
2716 | iounmap(priv->odb_base); | ||
2717 | #ifdef CONFIG_PCI_MSI | ||
2718 | if (priv->flags & TSI721_USING_MSIX) | ||
2719 | pci_disable_msix(priv->pdev); | ||
2720 | else if (priv->flags & TSI721_USING_MSI) | ||
2721 | pci_disable_msi(priv->pdev); | ||
2722 | #endif | ||
2723 | pci_release_regions(pdev); | ||
2724 | pci_clear_master(pdev); | ||
2725 | pci_disable_device(pdev); | ||
2726 | pci_set_drvdata(pdev, NULL); | ||
2727 | kfree(priv); | ||
2728 | dev_dbg(&pdev->dev, "%s exit\n", __func__); | ||
2729 | } | ||
2730 | |||
2665 | static void tsi721_shutdown(struct pci_dev *pdev) | 2731 | static void tsi721_shutdown(struct pci_dev *pdev) |
2666 | { | 2732 | { |
2667 | struct tsi721_device *priv = pci_get_drvdata(pdev); | 2733 | struct tsi721_device *priv = pci_get_drvdata(pdev); |
@@ -2685,15 +2751,11 @@ static struct pci_driver tsi721_driver = { | |||
2685 | .name = "tsi721", | 2751 | .name = "tsi721", |
2686 | .id_table = tsi721_pci_tbl, | 2752 | .id_table = tsi721_pci_tbl, |
2687 | .probe = tsi721_probe, | 2753 | .probe = tsi721_probe, |
2754 | .remove = tsi721_remove, | ||
2688 | .shutdown = tsi721_shutdown, | 2755 | .shutdown = tsi721_shutdown, |
2689 | }; | 2756 | }; |
2690 | 2757 | ||
2691 | static int __init tsi721_init(void) | 2758 | module_pci_driver(tsi721_driver); |
2692 | { | ||
2693 | return pci_register_driver(&tsi721_driver); | ||
2694 | } | ||
2695 | |||
2696 | device_initcall(tsi721_init); | ||
2697 | 2759 | ||
2698 | MODULE_DESCRIPTION("IDT Tsi721 PCIExpress-to-SRIO bridge driver"); | 2760 | MODULE_DESCRIPTION("IDT Tsi721 PCIExpress-to-SRIO bridge driver"); |
2699 | MODULE_AUTHOR("Integrated Device Technology, Inc."); | 2761 | MODULE_AUTHOR("Integrated Device Technology, Inc."); |
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index ce2fb1193869..58637295a34c 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h | |||
@@ -824,7 +824,7 @@ struct tsi721_ib_win { | |||
824 | 824 | ||
825 | struct tsi721_device { | 825 | struct tsi721_device { |
826 | struct pci_dev *pdev; | 826 | struct pci_dev *pdev; |
827 | struct rio_mport *mport; | 827 | struct rio_mport mport; |
828 | u32 flags; | 828 | u32 flags; |
829 | void __iomem *regs; | 829 | void __iomem *regs; |
830 | #ifdef CONFIG_PCI_MSI | 830 | #ifdef CONFIG_PCI_MSI |
@@ -866,9 +866,11 @@ struct tsi721_device { | |||
866 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 866 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
867 | extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan); | 867 | extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan); |
868 | extern int tsi721_register_dma(struct tsi721_device *priv); | 868 | extern int tsi721_register_dma(struct tsi721_device *priv); |
869 | extern void tsi721_unregister_dma(struct tsi721_device *priv); | ||
869 | extern void tsi721_dma_stop_all(struct tsi721_device *priv); | 870 | extern void tsi721_dma_stop_all(struct tsi721_device *priv); |
870 | #else | 871 | #else |
871 | #define tsi721_dma_stop_all(priv) do {} while (0) | 872 | #define tsi721_dma_stop_all(priv) do {} while (0) |
873 | #define tsi721_unregister_dma(priv) do {} while (0) | ||
872 | #endif | 874 | #endif |
873 | 875 | ||
874 | #endif | 876 | #endif |
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index b490ec36f018..31bb61b43c3f 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c | |||
@@ -887,7 +887,7 @@ int tsi721_register_dma(struct tsi721_device *priv) | |||
887 | int i; | 887 | int i; |
888 | int nr_channels = 0; | 888 | int nr_channels = 0; |
889 | int err; | 889 | int err; |
890 | struct rio_mport *mport = priv->mport; | 890 | struct rio_mport *mport = &priv->mport; |
891 | 891 | ||
892 | INIT_LIST_HEAD(&mport->dma.channels); | 892 | INIT_LIST_HEAD(&mport->dma.channels); |
893 | 893 | ||
@@ -937,3 +937,29 @@ int tsi721_register_dma(struct tsi721_device *priv) | |||
937 | 937 | ||
938 | return err; | 938 | return err; |
939 | } | 939 | } |
940 | |||
941 | void tsi721_unregister_dma(struct tsi721_device *priv) | ||
942 | { | ||
943 | struct rio_mport *mport = &priv->mport; | ||
944 | struct dma_chan *chan, *_c; | ||
945 | struct tsi721_bdma_chan *bdma_chan; | ||
946 | |||
947 | tsi721_dma_stop_all(priv); | ||
948 | dma_async_device_unregister(&mport->dma); | ||
949 | |||
950 | list_for_each_entry_safe(chan, _c, &mport->dma.channels, | ||
951 | device_node) { | ||
952 | bdma_chan = to_tsi721_chan(chan); | ||
953 | if (bdma_chan->active) { | ||
954 | tsi721_bdma_interrupt_enable(bdma_chan, 0); | ||
955 | bdma_chan->active = false; | ||
956 | tsi721_sync_dma_irq(bdma_chan); | ||
957 | tasklet_kill(&bdma_chan->tasklet); | ||
958 | INIT_LIST_HEAD(&bdma_chan->free_list); | ||
959 | kfree(bdma_chan->tx_desc); | ||
960 | tsi721_bdma_ch_free(bdma_chan); | ||
961 | } | ||
962 | |||
963 | list_del(&chan->device_node); | ||
964 | } | ||
965 | } | ||