aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2016-03-22 17:26:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-22 18:36:02 -0400
commit748353cc2d03d0514a3bf6d0752244ce657f197c (patch)
treeadd9bf2705e262905ad3486d2b41dfed6fe61277 /drivers/rapidio
parentb77a2030dface6ea6b0d900bd8496ef41a9f3323 (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.c302
-rw-r--r--drivers/rapidio/devices/tsi721.h4
-rw-r--r--drivers/rapidio/devices/tsi721_dma.c28
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 */
245static int 245static int
246tsi721_pw_handler(struct rio_mport *mport) 246tsi721_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 */
372static int 371static int
373tsi721_dbell_handler(struct rio_mport *mport) 372tsi721_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 */
465static irqreturn_t tsi721_irqhandler(int irq, void *ptr) 463static 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 */
620static irqreturn_t tsi721_omsg_msix(int irq, void *ptr) 617static 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 */
637static irqreturn_t tsi721_imsg_msix(int irq, void *ptr) 634static 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 */
654static irqreturn_t tsi721_srio_msix(int irq, void *ptr) 651static 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 */
676static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr) 673static 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 */
702static int tsi721_request_msix(struct rio_mport *mport) 699static 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 }
720out: 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
834static int tsi721_request_irq(struct rio_mport *mport) 830static 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
850static 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 */
1117static 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
1155static void tsi721_port_write_free(struct tsi721_device *priv)
1156{
1157 kfifo_free(&priv->pw_fifo);
1158}
1159
1129static int tsi721_doorbell_init(struct tsi721_device *priv) 1160static 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,
1496static void tsi721_omsg_handler(struct tsi721_device *priv, int ch) 1527static 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
2403static 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
2422static 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
2476err_exit: 2507err_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
2645err_free_consistent: 2676err_free_consistent:
2677 tsi721_port_write_free(priv);
2646 tsi721_doorbell_free(priv); 2678 tsi721_doorbell_free(priv);
2647err_free_bdma: 2679err_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
2697static 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
2665static void tsi721_shutdown(struct pci_dev *pdev) 2731static 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
2691static int __init tsi721_init(void) 2758module_pci_driver(tsi721_driver);
2692{
2693 return pci_register_driver(&tsi721_driver);
2694}
2695
2696device_initcall(tsi721_init);
2697 2759
2698MODULE_DESCRIPTION("IDT Tsi721 PCIExpress-to-SRIO bridge driver"); 2760MODULE_DESCRIPTION("IDT Tsi721 PCIExpress-to-SRIO bridge driver");
2699MODULE_AUTHOR("Integrated Device Technology, Inc."); 2761MODULE_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
825struct tsi721_device { 825struct 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
867extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan); 867extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan);
868extern int tsi721_register_dma(struct tsi721_device *priv); 868extern int tsi721_register_dma(struct tsi721_device *priv);
869extern void tsi721_unregister_dma(struct tsi721_device *priv);
869extern void tsi721_dma_stop_all(struct tsi721_device *priv); 870extern 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
941void 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}