aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ntb/ntb_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ntb/ntb_hw.c')
-rw-r--r--drivers/ntb/ntb_hw.c262
1 files changed, 160 insertions, 102 deletions
diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c
index 97b18eec3d39..2f3ff73b1d1b 100644
--- a/drivers/ntb/ntb_hw.c
+++ b/drivers/ntb/ntb_hw.c
@@ -69,7 +69,7 @@ module_param(xeon_errata_workaround, bool, 0644);
69MODULE_PARM_DESC(xeon_errata_workaround, "Workaround for the Xeon Errata"); 69MODULE_PARM_DESC(xeon_errata_workaround, "Workaround for the Xeon Errata");
70 70
71enum { 71enum {
72 NTB_CONN_CLASSIC = 0, 72 NTB_CONN_TRANSPARENT = 0,
73 NTB_CONN_B2B, 73 NTB_CONN_B2B,
74 NTB_CONN_RP, 74 NTB_CONN_RP,
75}; 75};
@@ -509,7 +509,8 @@ static void ntb_link_event(struct ntb_device *ndev, int link_state)
509 ndev->link_status = NTB_LINK_UP; 509 ndev->link_status = NTB_LINK_UP;
510 event = NTB_EVENT_HW_LINK_UP; 510 event = NTB_EVENT_HW_LINK_UP;
511 511
512 if (ndev->hw_type == BWD_HW) 512 if (ndev->hw_type == BWD_HW ||
513 ndev->conn_type == NTB_CONN_TRANSPARENT)
513 status = readw(ndev->reg_ofs.lnk_stat); 514 status = readw(ndev->reg_ofs.lnk_stat);
514 else { 515 else {
515 int rc = pci_read_config_word(ndev->pdev, 516 int rc = pci_read_config_word(ndev->pdev,
@@ -649,119 +650,174 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
649 if (rc) 650 if (rc)
650 return rc; 651 return rc;
651 652
652 switch (val & SNB_PPD_CONN_TYPE) {
653 case NTB_CONN_B2B:
654 ndev->conn_type = NTB_CONN_B2B;
655 break;
656 case NTB_CONN_CLASSIC:
657 case NTB_CONN_RP:
658 default:
659 dev_err(&ndev->pdev->dev, "Only B2B supported at this time\n");
660 return -EINVAL;
661 }
662
663 if (val & SNB_PPD_DEV_TYPE) 653 if (val & SNB_PPD_DEV_TYPE)
664 ndev->dev_type = NTB_DEV_USD; 654 ndev->dev_type = NTB_DEV_USD;
665 else 655 else
666 ndev->dev_type = NTB_DEV_DSD; 656 ndev->dev_type = NTB_DEV_DSD;
667 657
668 ndev->reg_ofs.ldb = ndev->reg_base + SNB_PDOORBELL_OFFSET; 658 switch (val & SNB_PPD_CONN_TYPE) {
669 ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_PDBMSK_OFFSET; 659 case NTB_CONN_B2B:
670 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_SBAR2XLAT_OFFSET; 660 dev_info(&ndev->pdev->dev, "Conn Type = B2B\n");
671 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_SBAR4XLAT_OFFSET; 661 ndev->conn_type = NTB_CONN_B2B;
672 ndev->reg_ofs.lnk_cntl = ndev->reg_base + SNB_NTBCNTL_OFFSET; 662 ndev->reg_ofs.ldb = ndev->reg_base + SNB_PDOORBELL_OFFSET;
673 ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_LINK_STATUS_OFFSET; 663 ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_PDBMSK_OFFSET;
674 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET; 664 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET;
675 ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET; 665 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_SBAR2XLAT_OFFSET;
676 666 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_SBAR4XLAT_OFFSET;
677 /* There is a Xeon hardware errata related to writes to 667 ndev->limits.max_spads = SNB_MAX_B2B_SPADS;
678 * SDOORBELL or B2BDOORBELL in conjunction with inbound access 668
679 * to NTB MMIO Space, which may hang the system. To workaround 669 /* There is a Xeon hardware errata related to writes to
680 * this use the second memory window to access the interrupt and 670 * SDOORBELL or B2BDOORBELL in conjunction with inbound access
681 * scratch pad registers on the remote system. 671 * to NTB MMIO Space, which may hang the system. To workaround
682 */ 672 * this use the second memory window to access the interrupt and
683 if (xeon_errata_workaround) { 673 * scratch pad registers on the remote system.
684 if (!ndev->mw[1].bar_sz)
685 return -EINVAL;
686
687 ndev->limits.max_mw = SNB_ERRATA_MAX_MW;
688 ndev->reg_ofs.spad_write = ndev->mw[1].vbase +
689 SNB_SPAD_OFFSET;
690 ndev->reg_ofs.rdb = ndev->mw[1].vbase +
691 SNB_PDOORBELL_OFFSET;
692
693 /* Set the Limit register to 4k, the minimum size, to
694 * prevent an illegal access
695 */ 674 */
696 writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base + 675 if (xeon_errata_workaround) {
697 SNB_PBAR4LMT_OFFSET); 676 if (!ndev->mw[1].bar_sz)
698 } else { 677 return -EINVAL;
699 ndev->limits.max_mw = SNB_MAX_MW; 678
700 ndev->reg_ofs.spad_write = ndev->reg_base + 679 ndev->limits.max_mw = SNB_ERRATA_MAX_MW;
701 SNB_B2B_SPAD_OFFSET; 680 ndev->reg_ofs.spad_write = ndev->mw[1].vbase +
702 ndev->reg_ofs.rdb = ndev->reg_base + 681 SNB_SPAD_OFFSET;
703 SNB_B2B_DOORBELL_OFFSET; 682 ndev->reg_ofs.rdb = ndev->mw[1].vbase +
683 SNB_PDOORBELL_OFFSET;
684
685 /* Set the Limit register to 4k, the minimum size, to
686 * prevent an illegal access
687 */
688 writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base +
689 SNB_PBAR4LMT_OFFSET);
690 } else {
691 ndev->limits.max_mw = SNB_MAX_MW;
692 ndev->reg_ofs.spad_write = ndev->reg_base +
693 SNB_B2B_SPAD_OFFSET;
694 ndev->reg_ofs.rdb = ndev->reg_base +
695 SNB_B2B_DOORBELL_OFFSET;
696
697 /* Disable the Limit register, just incase it is set to
698 * something silly
699 */
700 writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET);
701 }
704 702
705 /* Disable the Limit register, just incase it is set to 703 /* The Xeon errata workaround requires setting SBAR Base
706 * something silly 704 * addresses to known values, so that the PBAR XLAT can be
705 * pointed at SBAR0 of the remote system.
707 */ 706 */
708 writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET); 707 if (ndev->dev_type == NTB_DEV_USD) {
709 } 708 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base +
709 SNB_PBAR2XLAT_OFFSET);
710 if (xeon_errata_workaround)
711 writeq(SNB_MBAR01_DSD_ADDR, ndev->reg_base +
712 SNB_PBAR4XLAT_OFFSET);
713 else {
714 writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base +
715 SNB_PBAR4XLAT_OFFSET);
716 /* B2B_XLAT_OFFSET is a 64bit register, but can
717 * only take 32bit writes
718 */
719 writel(SNB_MBAR01_DSD_ADDR & 0xffffffff,
720 ndev->reg_base + SNB_B2B_XLAT_OFFSETL);
721 writel(SNB_MBAR01_DSD_ADDR >> 32,
722 ndev->reg_base + SNB_B2B_XLAT_OFFSETU);
723 }
710 724
711 /* The Xeon errata workaround requires setting SBAR Base 725 writeq(SNB_MBAR01_USD_ADDR, ndev->reg_base +
712 * addresses to known values, so that the PBAR XLAT can be 726 SNB_SBAR0BASE_OFFSET);
713 * pointed at SBAR0 of the remote system. 727 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base +
714 */ 728 SNB_SBAR2BASE_OFFSET);
715 if (ndev->dev_type == NTB_DEV_USD) { 729 writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base +
716 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base + 730 SNB_SBAR4BASE_OFFSET);
717 SNB_PBAR2XLAT_OFFSET); 731 } else {
718 if (xeon_errata_workaround) 732 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base +
733 SNB_PBAR2XLAT_OFFSET);
734 if (xeon_errata_workaround)
735 writeq(SNB_MBAR01_USD_ADDR, ndev->reg_base +
736 SNB_PBAR4XLAT_OFFSET);
737 else {
738 writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base +
739 SNB_PBAR4XLAT_OFFSET);
740 /* B2B_XLAT_OFFSET is a 64bit register, but can
741 * only take 32bit writes
742 */
743 writel(SNB_MBAR01_DSD_ADDR & 0xffffffff,
744 ndev->reg_base + SNB_B2B_XLAT_OFFSETL);
745 writel(SNB_MBAR01_USD_ADDR >> 32,
746 ndev->reg_base + SNB_B2B_XLAT_OFFSETU);
747 }
719 writeq(SNB_MBAR01_DSD_ADDR, ndev->reg_base + 748 writeq(SNB_MBAR01_DSD_ADDR, ndev->reg_base +
720 SNB_PBAR4XLAT_OFFSET); 749 SNB_SBAR0BASE_OFFSET);
721 else { 750 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base +
751 SNB_SBAR2BASE_OFFSET);
722 writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base + 752 writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base +
723 SNB_PBAR4XLAT_OFFSET); 753 SNB_SBAR4BASE_OFFSET);
724 /* B2B_XLAT_OFFSET is a 64bit register, but can
725 * only take 32bit writes
726 */
727 writel(SNB_MBAR01_USD_ADDR & 0xffffffff,
728 ndev->reg_base + SNB_B2B_XLAT_OFFSETL);
729 writel(SNB_MBAR01_DSD_ADDR >> 32,
730 ndev->reg_base + SNB_B2B_XLAT_OFFSETU);
731 } 754 }
755 break;
756 case NTB_CONN_RP:
757 dev_info(&ndev->pdev->dev, "Conn Type = RP\n");
758 ndev->conn_type = NTB_CONN_RP;
732 759
733 writeq(SNB_MBAR01_USD_ADDR, ndev->reg_base + 760 if (xeon_errata_workaround) {
734 SNB_SBAR0BASE_OFFSET); 761 dev_err(&ndev->pdev->dev,
735 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base + 762 "NTB-RP disabled due to hardware errata. To disregard this warning and potentially lock-up the system, add the parameter 'xeon_errata_workaround=0'.\n");
736 SNB_SBAR2BASE_OFFSET); 763 return -EINVAL;
737 writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base +
738 SNB_SBAR4BASE_OFFSET);
739 } else {
740 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base +
741 SNB_PBAR2XLAT_OFFSET);
742 if (xeon_errata_workaround)
743 writeq(SNB_MBAR01_USD_ADDR, ndev->reg_base +
744 SNB_PBAR4XLAT_OFFSET);
745 else {
746 writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base +
747 SNB_PBAR4XLAT_OFFSET);
748 /* B2B_XLAT_OFFSET is a 64bit register, but can
749 * only take 32bit writes
750 */
751 writel(SNB_MBAR01_USD_ADDR & 0xffffffff,
752 ndev->reg_base + SNB_B2B_XLAT_OFFSETL);
753 writel(SNB_MBAR01_USD_ADDR >> 32,
754 ndev->reg_base + SNB_B2B_XLAT_OFFSETU);
755 } 764 }
756 writeq(SNB_MBAR01_DSD_ADDR, ndev->reg_base + 765
757 SNB_SBAR0BASE_OFFSET); 766 /* Scratch pads need to have exclusive access from the primary
758 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base + 767 * or secondary side. Halve the num spads so that each side can
759 SNB_SBAR2BASE_OFFSET); 768 * have an equal amount.
760 writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base + 769 */
761 SNB_SBAR4BASE_OFFSET); 770 ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
771 /* Note: The SDOORBELL is the cause of the errata. You REALLY
772 * don't want to touch it.
773 */
774 ndev->reg_ofs.rdb = ndev->reg_base + SNB_SDOORBELL_OFFSET;
775 ndev->reg_ofs.ldb = ndev->reg_base + SNB_PDOORBELL_OFFSET;
776 ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_PDBMSK_OFFSET;
777 /* Offset the start of the spads to correspond to whether it is
778 * primary or secondary
779 */
780 ndev->reg_ofs.spad_write = ndev->reg_base + SNB_SPAD_OFFSET +
781 ndev->limits.max_spads * 4;
782 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET;
783 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_SBAR2XLAT_OFFSET;
784 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_SBAR4XLAT_OFFSET;
785 ndev->limits.max_mw = SNB_MAX_MW;
786 break;
787 case NTB_CONN_TRANSPARENT:
788 dev_info(&ndev->pdev->dev, "Conn Type = TRANSPARENT\n");
789 ndev->conn_type = NTB_CONN_TRANSPARENT;
790 /* Scratch pads need to have exclusive access from the primary
791 * or secondary side. Halve the num spads so that each side can
792 * have an equal amount.
793 */
794 ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
795 ndev->reg_ofs.rdb = ndev->reg_base + SNB_PDOORBELL_OFFSET;
796 ndev->reg_ofs.ldb = ndev->reg_base + SNB_SDOORBELL_OFFSET;
797 ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_SDBMSK_OFFSET;
798 ndev->reg_ofs.spad_write = ndev->reg_base + SNB_SPAD_OFFSET;
799 /* Offset the start of the spads to correspond to whether it is
800 * primary or secondary
801 */
802 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET +
803 ndev->limits.max_spads * 4;
804 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_PBAR2XLAT_OFFSET;
805 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_PBAR4XLAT_OFFSET;
806
807 ndev->limits.max_mw = SNB_MAX_MW;
808 break;
809 default:
810 /* Most likely caused by the remote NTB-RP device not being
811 * configured
812 */
813 dev_err(&ndev->pdev->dev, "Unknown PPD %x\n", val);
814 return -EINVAL;
762 } 815 }
763 816
764 ndev->limits.max_spads = SNB_MAX_B2B_SPADS; 817 ndev->reg_ofs.lnk_cntl = ndev->reg_base + SNB_NTBCNTL_OFFSET;
818 ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_SLINK_STATUS_OFFSET;
819 ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET;
820
765 ndev->limits.max_db_bits = SNB_MAX_DB_BITS; 821 ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
766 ndev->limits.msix_cnt = SNB_MSIX_CNT; 822 ndev->limits.msix_cnt = SNB_MSIX_CNT;
767 ndev->bits_per_vector = SNB_DB_BITS_PER_VEC; 823 ndev->bits_per_vector = SNB_DB_BITS_PER_VEC;
@@ -865,8 +921,10 @@ static int ntb_device_setup(struct ntb_device *ndev)
865 dev_info(&ndev->pdev->dev, "Device Type = %s\n", 921 dev_info(&ndev->pdev->dev, "Device Type = %s\n",
866 ndev->dev_type == NTB_DEV_USD ? "USD/DSP" : "DSD/USP"); 922 ndev->dev_type == NTB_DEV_USD ? "USD/DSP" : "DSD/USP");
867 923
868 /* Enable Bus Master and Memory Space on the secondary side */ 924 if (ndev->conn_type == NTB_CONN_B2B)
869 writew(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, ndev->reg_ofs.spci_cmd); 925 /* Enable Bus Master and Memory Space on the secondary side */
926 writew(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
927 ndev->reg_ofs.spci_cmd);
870 928
871 return 0; 929 return 0;
872} 930}
@@ -1360,7 +1418,7 @@ static void ntb_pci_remove(struct pci_dev *pdev)
1360 1418
1361 /* Bring NTB link down */ 1419 /* Bring NTB link down */
1362 ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); 1420 ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
1363 ntb_cntl |= NTB_LINK_DISABLE; 1421 ntb_cntl |= NTB_CNTL_LINK_DISABLE;
1364 writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); 1422 writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
1365 1423
1366 ntb_transport_free(ndev->ntb_transport); 1424 ntb_transport_free(ndev->ntb_transport);