Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ntb-3.18' of git://github.com/jonmason/ntb

Pull ntb (non-transparent bridge) updates from Jon Mason:
"Add support for Haswell NTB split BARs, a debugfs entry for basic
debugging info, and some code clean-ups"

* tag 'ntb-3.18' of git://github.com/jonmason/ntb:
ntb: Adding split BAR support for Haswell platforms
ntb: use errata flag set via DID to implement workaround
ntb: conslidate reading of PPD to move platform detection earlier
ntb: move platform detection to separate function
NTB: debugfs device entry

+501 -123
+459 -108
drivers/ntb/ntb_hw.c
··· 64 64 MODULE_LICENSE("Dual BSD/GPL"); 65 65 MODULE_AUTHOR("Intel Corporation"); 66 66 67 - static bool xeon_errata_workaround = true; 68 - module_param(xeon_errata_workaround, bool, 0644); 69 - MODULE_PARM_DESC(xeon_errata_workaround, "Workaround for the Xeon Errata"); 70 - 71 67 enum { 72 68 NTB_CONN_TRANSPARENT = 0, 73 69 NTB_CONN_B2B, ··· 84 88 85 89 #define BWD_LINK_RECOVERY_TIME 500 86 90 87 - /* Translate memory window 0,1 to BAR 2,4 */ 88 - #define MW_TO_BAR(mw) (mw * NTB_MAX_NUM_MW + 2) 91 + /* Translate memory window 0,1,2 to BAR 2,4,5 */ 92 + #define MW_TO_BAR(mw) (mw == 0 ? 2 : (mw == 1 ? 4 : 5)) 89 93 90 94 static const struct pci_device_id ntb_pci_tbl[] = { 91 95 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_BWD)}, ··· 104 108 {0} 105 109 }; 106 110 MODULE_DEVICE_TABLE(pci, ntb_pci_tbl); 111 + 112 + static int is_ntb_xeon(struct ntb_device *ndev) 113 + { 114 + switch (ndev->pdev->device) { 115 + case PCI_DEVICE_ID_INTEL_NTB_SS_JSF: 116 + case PCI_DEVICE_ID_INTEL_NTB_SS_SNB: 117 + case PCI_DEVICE_ID_INTEL_NTB_SS_IVT: 118 + case PCI_DEVICE_ID_INTEL_NTB_SS_HSX: 119 + case PCI_DEVICE_ID_INTEL_NTB_PS_JSF: 120 + case PCI_DEVICE_ID_INTEL_NTB_PS_SNB: 121 + case PCI_DEVICE_ID_INTEL_NTB_PS_IVT: 122 + case PCI_DEVICE_ID_INTEL_NTB_PS_HSX: 123 + case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF: 124 + case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB: 125 + case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT: 126 + case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX: 127 + return 1; 128 + default: 129 + return 0; 130 + } 131 + 132 + return 0; 133 + } 134 + 135 + static int is_ntb_atom(struct ntb_device *ndev) 136 + { 137 + switch (ndev->pdev->device) { 138 + case PCI_DEVICE_ID_INTEL_NTB_B2B_BWD: 139 + return 1; 140 + default: 141 + return 0; 142 + } 143 + 144 + return 0; 145 + } 146 + 147 + static void ntb_set_errata_flags(struct ntb_device *ndev) 148 + { 149 + switch (ndev->pdev->device) { 150 + /* 151 + * this workaround applies to all platform up to IvyBridge 152 + * Haswell has splitbar support and use a different workaround 153 + */ 154 + case PCI_DEVICE_ID_INTEL_NTB_SS_JSF: 155 + case PCI_DEVICE_ID_INTEL_NTB_SS_SNB: 156 + case PCI_DEVICE_ID_INTEL_NTB_SS_IVT: 157 + case PCI_DEVICE_ID_INTEL_NTB_SS_HSX: 158 + case PCI_DEVICE_ID_INTEL_NTB_PS_JSF: 159 + case PCI_DEVICE_ID_INTEL_NTB_PS_SNB: 160 + case PCI_DEVICE_ID_INTEL_NTB_PS_IVT: 161 + case PCI_DEVICE_ID_INTEL_NTB_PS_HSX: 162 + case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF: 163 + case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB: 164 + case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT: 165 + case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX: 166 + ndev->wa_flags |= WA_SNB_ERR; 167 + break; 168 + } 169 + } 107 170 108 171 /** 109 172 * ntb_register_event_callback() - register event callback ··· 506 451 case NTB_BAR_23: 507 452 writeq(addr, ndev->reg_ofs.bar2_xlat); 508 453 break; 509 - case NTB_BAR_45: 510 - writeq(addr, ndev->reg_ofs.bar4_xlat); 454 + case NTB_BAR_4: 455 + if (ndev->split_bar) 456 + writel(addr, ndev->reg_ofs.bar4_xlat); 457 + else 458 + writeq(addr, ndev->reg_ofs.bar4_xlat); 459 + break; 460 + case NTB_BAR_5: 461 + writel(addr, ndev->reg_ofs.bar5_xlat); 511 462 break; 512 463 } 513 464 } ··· 596 535 ndev->link_status = NTB_LINK_UP; 597 536 event = NTB_EVENT_HW_LINK_UP; 598 537 599 - if (ndev->hw_type == BWD_HW || 538 + if (is_ntb_atom(ndev) || 600 539 ndev->conn_type == NTB_CONN_TRANSPARENT) 601 540 status = readw(ndev->reg_ofs.lnk_stat); 602 541 else { ··· 627 566 { 628 567 int link_state; 629 568 630 - if (ndev->hw_type == BWD_HW) { 569 + if (is_ntb_atom(ndev)) { 631 570 u32 ntb_cntl; 632 571 633 572 ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); ··· 728 667 729 668 static int ntb_xeon_setup(struct ntb_device *ndev) 730 669 { 731 - int rc; 732 - u8 val; 733 - 734 - ndev->hw_type = SNB_HW; 735 - 736 - rc = pci_read_config_byte(ndev->pdev, NTB_PPD_OFFSET, &val); 737 - if (rc) 738 - return rc; 739 - 740 - if (val & SNB_PPD_DEV_TYPE) 741 - ndev->dev_type = NTB_DEV_USD; 742 - else 743 - ndev->dev_type = NTB_DEV_DSD; 744 - 745 - switch (val & SNB_PPD_CONN_TYPE) { 670 + switch (ndev->conn_type) { 746 671 case NTB_CONN_B2B: 747 - dev_info(&ndev->pdev->dev, "Conn Type = B2B\n"); 748 - ndev->conn_type = NTB_CONN_B2B; 749 672 ndev->reg_ofs.ldb = ndev->reg_base + SNB_PDOORBELL_OFFSET; 750 673 ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_PDBMSK_OFFSET; 751 674 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET; 752 675 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_SBAR2XLAT_OFFSET; 753 676 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_SBAR4XLAT_OFFSET; 677 + if (ndev->split_bar) 678 + ndev->reg_ofs.bar5_xlat = 679 + ndev->reg_base + SNB_SBAR5XLAT_OFFSET; 754 680 ndev->limits.max_spads = SNB_MAX_B2B_SPADS; 755 681 756 682 /* There is a Xeon hardware errata related to writes to ··· 746 698 * this use the second memory window to access the interrupt and 747 699 * scratch pad registers on the remote system. 748 700 */ 749 - if (xeon_errata_workaround) { 750 - if (!ndev->mw[1].bar_sz) 701 + if (ndev->wa_flags & WA_SNB_ERR) { 702 + if (!ndev->mw[ndev->limits.max_mw - 1].bar_sz) 751 703 return -EINVAL; 752 704 753 - ndev->limits.max_mw = SNB_ERRATA_MAX_MW; 754 705 ndev->limits.max_db_bits = SNB_MAX_DB_BITS; 755 - ndev->reg_ofs.spad_write = ndev->mw[1].vbase + 756 - SNB_SPAD_OFFSET; 757 - ndev->reg_ofs.rdb = ndev->mw[1].vbase + 758 - SNB_PDOORBELL_OFFSET; 706 + ndev->reg_ofs.spad_write = 707 + ndev->mw[ndev->limits.max_mw - 1].vbase + 708 + SNB_SPAD_OFFSET; 709 + ndev->reg_ofs.rdb = 710 + ndev->mw[ndev->limits.max_mw - 1].vbase + 711 + SNB_PDOORBELL_OFFSET; 759 712 760 713 /* Set the Limit register to 4k, the minimum size, to 761 714 * prevent an illegal access ··· 769 720 * the driver defaults, but write the Limit registers 770 721 * first just in case. 771 722 */ 772 - } else { 773 - ndev->limits.max_mw = SNB_MAX_MW; 774 723 724 + ndev->limits.max_mw = SNB_ERRATA_MAX_MW; 725 + } else { 775 726 /* HW Errata on bit 14 of b2bdoorbell register. Writes 776 727 * will not be mirrored to the remote system. Shrink 777 728 * the number of bits by one, since bit 14 is the last ··· 784 735 SNB_B2B_DOORBELL_OFFSET; 785 736 786 737 /* Disable the Limit register, just incase it is set to 787 - * something silly 738 + * something silly. A 64bit write should handle it 739 + * regardless of whether it has a split BAR or not. 788 740 */ 789 741 writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET); 790 742 /* HW errata on the Limit registers. They can only be ··· 794 744 * the driver defaults, but write the Limit registers 795 745 * first just in case. 796 746 */ 747 + if (ndev->split_bar) 748 + ndev->limits.max_mw = HSX_SPLITBAR_MAX_MW; 749 + else 750 + ndev->limits.max_mw = SNB_MAX_MW; 797 751 } 798 752 799 753 /* The Xeon errata workaround requires setting SBAR Base ··· 807 753 if (ndev->dev_type == NTB_DEV_USD) { 808 754 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base + 809 755 SNB_PBAR2XLAT_OFFSET); 810 - if (xeon_errata_workaround) 756 + if (ndev->wa_flags & WA_SNB_ERR) 811 757 writeq(SNB_MBAR01_DSD_ADDR, ndev->reg_base + 812 758 SNB_PBAR4XLAT_OFFSET); 813 759 else { 814 - writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base + 815 - SNB_PBAR4XLAT_OFFSET); 760 + if (ndev->split_bar) { 761 + writel(SNB_MBAR4_DSD_ADDR, 762 + ndev->reg_base + 763 + SNB_PBAR4XLAT_OFFSET); 764 + writel(SNB_MBAR5_DSD_ADDR, 765 + ndev->reg_base + 766 + SNB_PBAR5XLAT_OFFSET); 767 + } else 768 + writeq(SNB_MBAR4_DSD_ADDR, 769 + ndev->reg_base + 770 + SNB_PBAR4XLAT_OFFSET); 771 + 816 772 /* B2B_XLAT_OFFSET is a 64bit register, but can 817 773 * only take 32bit writes 818 774 */ ··· 836 772 SNB_SBAR0BASE_OFFSET); 837 773 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base + 838 774 SNB_SBAR2BASE_OFFSET); 839 - writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base + 840 - SNB_SBAR4BASE_OFFSET); 775 + if (ndev->split_bar) { 776 + writel(SNB_MBAR4_USD_ADDR, ndev->reg_base + 777 + SNB_SBAR4BASE_OFFSET); 778 + writel(SNB_MBAR5_USD_ADDR, ndev->reg_base + 779 + SNB_SBAR5BASE_OFFSET); 780 + } else 781 + writeq(SNB_MBAR4_USD_ADDR, ndev->reg_base + 782 + SNB_SBAR4BASE_OFFSET); 841 783 } else { 842 784 writeq(SNB_MBAR23_USD_ADDR, ndev->reg_base + 843 785 SNB_PBAR2XLAT_OFFSET); 844 - if (xeon_errata_workaround) 786 + if (ndev->wa_flags & WA_SNB_ERR) 845 787 writeq(SNB_MBAR01_USD_ADDR, ndev->reg_base + 846 788 SNB_PBAR4XLAT_OFFSET); 847 789 else { 848 - writeq(SNB_MBAR45_USD_ADDR, ndev->reg_base + 849 - SNB_PBAR4XLAT_OFFSET); 850 - /* B2B_XLAT_OFFSET is a 64bit register, but can 790 + if (ndev->split_bar) { 791 + writel(SNB_MBAR4_USD_ADDR, 792 + ndev->reg_base + 793 + SNB_PBAR4XLAT_OFFSET); 794 + writel(SNB_MBAR5_USD_ADDR, 795 + ndev->reg_base + 796 + SNB_PBAR5XLAT_OFFSET); 797 + } else 798 + writeq(SNB_MBAR4_USD_ADDR, 799 + ndev->reg_base + 800 + SNB_PBAR4XLAT_OFFSET); 801 + 802 + /* 803 + * B2B_XLAT_OFFSET is a 64bit register, but can 851 804 * only take 32bit writes 852 805 */ 853 806 writel(SNB_MBAR01_USD_ADDR & 0xffffffff, ··· 876 795 SNB_SBAR0BASE_OFFSET); 877 796 writeq(SNB_MBAR23_DSD_ADDR, ndev->reg_base + 878 797 SNB_SBAR2BASE_OFFSET); 879 - writeq(SNB_MBAR45_DSD_ADDR, ndev->reg_base + 880 - SNB_SBAR4BASE_OFFSET); 798 + if (ndev->split_bar) { 799 + writel(SNB_MBAR4_DSD_ADDR, ndev->reg_base + 800 + SNB_SBAR4BASE_OFFSET); 801 + writel(SNB_MBAR5_DSD_ADDR, ndev->reg_base + 802 + SNB_SBAR5BASE_OFFSET); 803 + } else 804 + writeq(SNB_MBAR4_DSD_ADDR, ndev->reg_base + 805 + SNB_SBAR4BASE_OFFSET); 806 + 881 807 } 882 808 break; 883 809 case NTB_CONN_RP: 884 - dev_info(&ndev->pdev->dev, "Conn Type = RP\n"); 885 - ndev->conn_type = NTB_CONN_RP; 886 - 887 - if (xeon_errata_workaround) { 810 + if (ndev->wa_flags & WA_SNB_ERR) { 888 811 dev_err(&ndev->pdev->dev, 889 - "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"); 812 + "NTB-RP disabled due to hardware errata.\n"); 890 813 return -EINVAL; 891 814 } 892 815 ··· 914 829 ndev->reg_ofs.spad_read = ndev->reg_base + SNB_SPAD_OFFSET; 915 830 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_SBAR2XLAT_OFFSET; 916 831 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_SBAR4XLAT_OFFSET; 917 - ndev->limits.max_mw = SNB_MAX_MW; 832 + if (ndev->split_bar) { 833 + ndev->reg_ofs.bar5_xlat = 834 + ndev->reg_base + SNB_SBAR5XLAT_OFFSET; 835 + ndev->limits.max_mw = HSX_SPLITBAR_MAX_MW; 836 + } else 837 + ndev->limits.max_mw = SNB_MAX_MW; 918 838 break; 919 839 case NTB_CONN_TRANSPARENT: 920 - dev_info(&ndev->pdev->dev, "Conn Type = TRANSPARENT\n"); 921 - ndev->conn_type = NTB_CONN_TRANSPARENT; 840 + if (ndev->wa_flags & WA_SNB_ERR) { 841 + dev_err(&ndev->pdev->dev, 842 + "NTB-TRANSPARENT disabled due to hardware errata.\n"); 843 + return -EINVAL; 844 + } 845 + 922 846 /* Scratch pads need to have exclusive access from the primary 923 847 * or secondary side. Halve the num spads so that each side can 924 848 * have an equal amount. ··· 946 852 ndev->reg_ofs.bar2_xlat = ndev->reg_base + SNB_PBAR2XLAT_OFFSET; 947 853 ndev->reg_ofs.bar4_xlat = ndev->reg_base + SNB_PBAR4XLAT_OFFSET; 948 854 949 - ndev->limits.max_mw = SNB_MAX_MW; 855 + if (ndev->split_bar) { 856 + ndev->reg_ofs.bar5_xlat = 857 + ndev->reg_base + SNB_PBAR5XLAT_OFFSET; 858 + ndev->limits.max_mw = HSX_SPLITBAR_MAX_MW; 859 + } else 860 + ndev->limits.max_mw = SNB_MAX_MW; 950 861 break; 951 862 default: 952 - /* Most likely caused by the remote NTB-RP device not being 953 - * configured 863 + /* 864 + * we should never hit this. the detect function should've 865 + * take cared of everything. 954 866 */ 955 - dev_err(&ndev->pdev->dev, "Unknown PPD %x\n", val); 956 867 return -EINVAL; 957 868 } 958 869 ··· 1031 932 { 1032 933 int rc; 1033 934 1034 - switch (ndev->pdev->device) { 1035 - case PCI_DEVICE_ID_INTEL_NTB_SS_JSF: 1036 - case PCI_DEVICE_ID_INTEL_NTB_SS_SNB: 1037 - case PCI_DEVICE_ID_INTEL_NTB_SS_IVT: 1038 - case PCI_DEVICE_ID_INTEL_NTB_SS_HSX: 1039 - case PCI_DEVICE_ID_INTEL_NTB_PS_JSF: 1040 - case PCI_DEVICE_ID_INTEL_NTB_PS_SNB: 1041 - case PCI_DEVICE_ID_INTEL_NTB_PS_IVT: 1042 - case PCI_DEVICE_ID_INTEL_NTB_PS_HSX: 1043 - case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF: 1044 - case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB: 1045 - case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT: 1046 - case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX: 935 + if (is_ntb_xeon(ndev)) 1047 936 rc = ntb_xeon_setup(ndev); 1048 - break; 1049 - case PCI_DEVICE_ID_INTEL_NTB_B2B_BWD: 937 + else if (is_ntb_atom(ndev)) 1050 938 rc = ntb_bwd_setup(ndev); 1051 - break; 1052 - default: 939 + else 1053 940 rc = -ENODEV; 1054 - } 1055 941 1056 942 if (rc) 1057 943 return rc; 1058 - 1059 - dev_info(&ndev->pdev->dev, "Device Type = %s\n", 1060 - ndev->dev_type == NTB_DEV_USD ? "USD/DSP" : "DSD/USP"); 1061 944 1062 945 if (ndev->conn_type == NTB_CONN_B2B) 1063 946 /* Enable Bus Master and Memory Space on the secondary side */ ··· 1051 970 1052 971 static void ntb_device_free(struct ntb_device *ndev) 1053 972 { 1054 - if (ndev->hw_type == BWD_HW) { 973 + if (is_ntb_atom(ndev)) { 1055 974 cancel_delayed_work_sync(&ndev->hb_timer); 1056 975 cancel_delayed_work_sync(&ndev->lr_timer); 1057 976 } ··· 1131 1050 struct ntb_device *ndev = dev; 1132 1051 unsigned int i = 0; 1133 1052 1134 - if (ndev->hw_type == BWD_HW) { 1053 + if (is_ntb_atom(ndev)) { 1135 1054 u64 ldb = readq(ndev->reg_ofs.ldb); 1136 1055 1137 1056 dev_dbg(&ndev->pdev->dev, "irq %d - ldb = %Lx\n", irq, ldb); ··· 1273 1192 for (i = 0; i < msix_entries; i++) 1274 1193 ndev->msix_entries[i].entry = i; 1275 1194 1276 - if (ndev->hw_type == BWD_HW) 1195 + if (is_ntb_atom(ndev)) 1277 1196 rc = ntb_setup_bwd_msix(ndev, msix_entries); 1278 1197 else 1279 1198 rc = ntb_setup_snb_msix(ndev, msix_entries); ··· 1333 1252 /* On BWD, disable all interrupts. On SNB, disable all but Link 1334 1253 * Interrupt. The rest will be unmasked as callbacks are registered. 1335 1254 */ 1336 - if (ndev->hw_type == BWD_HW) 1255 + if (is_ntb_atom(ndev)) 1337 1256 writeq(~0, ndev->reg_ofs.ldb_mask); 1338 1257 else { 1339 1258 u16 var = 1 << SNB_LINK_DB; ··· 1366 1285 struct pci_dev *pdev = ndev->pdev; 1367 1286 1368 1287 /* mask interrupts */ 1369 - if (ndev->hw_type == BWD_HW) 1288 + if (is_ntb_atom(ndev)) 1370 1289 writeq(~0, ndev->reg_ofs.ldb_mask); 1371 1290 else 1372 1291 writew(~0, ndev->reg_ofs.ldb_mask); ··· 1377 1296 1378 1297 for (i = 0; i < ndev->num_msix; i++) { 1379 1298 msix = &ndev->msix_entries[i]; 1380 - if (ndev->hw_type != BWD_HW && i == ndev->num_msix - 1) 1299 + if (is_ntb_xeon(ndev) && i == ndev->num_msix - 1) 1381 1300 free_irq(msix->vector, ndev); 1382 1301 else 1383 1302 free_irq(msix->vector, &ndev->db_cb[i]); ··· 1425 1344 kfree(ndev->db_cb); 1426 1345 } 1427 1346 1347 + static ssize_t ntb_debugfs_read(struct file *filp, char __user *ubuf, 1348 + size_t count, loff_t *offp) 1349 + { 1350 + struct ntb_device *ndev; 1351 + char *buf; 1352 + ssize_t ret, offset, out_count; 1353 + 1354 + out_count = 500; 1355 + 1356 + buf = kmalloc(out_count, GFP_KERNEL); 1357 + if (!buf) 1358 + return -ENOMEM; 1359 + 1360 + ndev = filp->private_data; 1361 + offset = 0; 1362 + offset += snprintf(buf + offset, out_count - offset, 1363 + "NTB Device Information:\n"); 1364 + offset += snprintf(buf + offset, out_count - offset, 1365 + "Connection Type - \t\t%s\n", 1366 + ndev->conn_type == NTB_CONN_TRANSPARENT ? 1367 + "Transparent" : (ndev->conn_type == NTB_CONN_B2B) ? 1368 + "Back to back" : "Root Port"); 1369 + offset += snprintf(buf + offset, out_count - offset, 1370 + "Device Type - \t\t\t%s\n", 1371 + ndev->dev_type == NTB_DEV_USD ? 1372 + "DSD/USP" : "USD/DSP"); 1373 + offset += snprintf(buf + offset, out_count - offset, 1374 + "Max Number of Callbacks - \t%u\n", 1375 + ntb_max_cbs(ndev)); 1376 + offset += snprintf(buf + offset, out_count - offset, 1377 + "Link Status - \t\t\t%s\n", 1378 + ntb_hw_link_status(ndev) ? "Up" : "Down"); 1379 + if (ntb_hw_link_status(ndev)) { 1380 + offset += snprintf(buf + offset, out_count - offset, 1381 + "Link Speed - \t\t\tPCI-E Gen %u\n", 1382 + ndev->link_speed); 1383 + offset += snprintf(buf + offset, out_count - offset, 1384 + "Link Width - \t\t\tx%u\n", 1385 + ndev->link_width); 1386 + } 1387 + 1388 + if (is_ntb_xeon(ndev)) { 1389 + u32 status32; 1390 + u16 status16; 1391 + int rc; 1392 + 1393 + offset += snprintf(buf + offset, out_count - offset, 1394 + "\nNTB Device Statistics:\n"); 1395 + offset += snprintf(buf + offset, out_count - offset, 1396 + "Upstream Memory Miss - \t%u\n", 1397 + readw(ndev->reg_base + 1398 + SNB_USMEMMISS_OFFSET)); 1399 + 1400 + offset += snprintf(buf + offset, out_count - offset, 1401 + "\nNTB Hardware Errors:\n"); 1402 + 1403 + rc = pci_read_config_word(ndev->pdev, SNB_DEVSTS_OFFSET, 1404 + &status16); 1405 + if (!rc) 1406 + offset += snprintf(buf + offset, out_count - offset, 1407 + "DEVSTS - \t%#06x\n", status16); 1408 + 1409 + rc = pci_read_config_word(ndev->pdev, SNB_LINK_STATUS_OFFSET, 1410 + &status16); 1411 + if (!rc) 1412 + offset += snprintf(buf + offset, out_count - offset, 1413 + "LNKSTS - \t%#06x\n", status16); 1414 + 1415 + rc = pci_read_config_dword(ndev->pdev, SNB_UNCERRSTS_OFFSET, 1416 + &status32); 1417 + if (!rc) 1418 + offset += snprintf(buf + offset, out_count - offset, 1419 + "UNCERRSTS - \t%#010x\n", status32); 1420 + 1421 + rc = pci_read_config_dword(ndev->pdev, SNB_CORERRSTS_OFFSET, 1422 + &status32); 1423 + if (!rc) 1424 + offset += snprintf(buf + offset, out_count - offset, 1425 + "CORERRSTS - \t%#010x\n", status32); 1426 + } 1427 + 1428 + if (offset > out_count) 1429 + offset = out_count; 1430 + 1431 + ret = simple_read_from_buffer(ubuf, count, offp, buf, offset); 1432 + kfree(buf); 1433 + return ret; 1434 + } 1435 + 1436 + static const struct file_operations ntb_debugfs_info = { 1437 + .owner = THIS_MODULE, 1438 + .open = simple_open, 1439 + .read = ntb_debugfs_read, 1440 + }; 1441 + 1428 1442 static void ntb_setup_debugfs(struct ntb_device *ndev) 1429 1443 { 1430 1444 if (!debugfs_initialized()) ··· 1530 1354 1531 1355 ndev->debugfs_dir = debugfs_create_dir(pci_name(ndev->pdev), 1532 1356 debugfs_dir); 1357 + if (ndev->debugfs_dir) 1358 + ndev->debugfs_info = debugfs_create_file("info", S_IRUSR, 1359 + ndev->debugfs_dir, 1360 + ndev, 1361 + &ntb_debugfs_info); 1533 1362 } 1534 1363 1535 1364 static void ntb_free_debugfs(struct ntb_device *ndev) ··· 1558 1377 ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); 1559 1378 ntb_cntl &= ~(NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK); 1560 1379 ntb_cntl |= NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP; 1561 - ntb_cntl |= NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP; 1380 + ntb_cntl |= NTB_CNTL_P2S_BAR4_SNOOP | NTB_CNTL_S2P_BAR4_SNOOP; 1381 + if (ndev->split_bar) 1382 + ntb_cntl |= NTB_CNTL_P2S_BAR5_SNOOP | 1383 + NTB_CNTL_S2P_BAR5_SNOOP; 1384 + 1562 1385 writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); 1563 1386 } 1564 1387 } ··· 1579 1394 /* Bring NTB link down */ 1580 1395 ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); 1581 1396 ntb_cntl &= ~(NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP); 1582 - ntb_cntl &= ~(NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP); 1397 + ntb_cntl &= ~(NTB_CNTL_P2S_BAR4_SNOOP | NTB_CNTL_S2P_BAR4_SNOOP); 1398 + if (ndev->split_bar) 1399 + ntb_cntl &= ~(NTB_CNTL_P2S_BAR5_SNOOP | 1400 + NTB_CNTL_S2P_BAR5_SNOOP); 1583 1401 ntb_cntl |= NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK; 1584 1402 writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); 1403 + } 1404 + 1405 + static void ntb_max_mw_detect(struct ntb_device *ndev) 1406 + { 1407 + if (ndev->split_bar) 1408 + ndev->limits.max_mw = HSX_SPLITBAR_MAX_MW; 1409 + else 1410 + ndev->limits.max_mw = SNB_MAX_MW; 1411 + } 1412 + 1413 + static int ntb_xeon_detect(struct ntb_device *ndev) 1414 + { 1415 + int rc, bars_mask; 1416 + u32 bars; 1417 + u8 ppd; 1418 + 1419 + ndev->hw_type = SNB_HW; 1420 + 1421 + rc = pci_read_config_byte(ndev->pdev, NTB_PPD_OFFSET, &ppd); 1422 + if (rc) 1423 + return -EIO; 1424 + 1425 + if (ppd & SNB_PPD_DEV_TYPE) 1426 + ndev->dev_type = NTB_DEV_USD; 1427 + else 1428 + ndev->dev_type = NTB_DEV_DSD; 1429 + 1430 + ndev->split_bar = (ppd & SNB_PPD_SPLIT_BAR) ? 1 : 0; 1431 + 1432 + switch (ppd & SNB_PPD_CONN_TYPE) { 1433 + case NTB_CONN_B2B: 1434 + dev_info(&ndev->pdev->dev, "Conn Type = B2B\n"); 1435 + ndev->conn_type = NTB_CONN_B2B; 1436 + break; 1437 + case NTB_CONN_RP: 1438 + dev_info(&ndev->pdev->dev, "Conn Type = RP\n"); 1439 + ndev->conn_type = NTB_CONN_RP; 1440 + break; 1441 + case NTB_CONN_TRANSPARENT: 1442 + dev_info(&ndev->pdev->dev, "Conn Type = TRANSPARENT\n"); 1443 + ndev->conn_type = NTB_CONN_TRANSPARENT; 1444 + /* 1445 + * This mode is default to USD/DSP. HW does not report 1446 + * properly in transparent mode as it has no knowledge of 1447 + * NTB. We will just force correct here. 1448 + */ 1449 + ndev->dev_type = NTB_DEV_USD; 1450 + 1451 + /* 1452 + * This is a way for transparent BAR to figure out if we 1453 + * are doing split BAR or not. There is no way for the hw 1454 + * on the transparent side to know and set the PPD. 1455 + */ 1456 + bars_mask = pci_select_bars(ndev->pdev, IORESOURCE_MEM); 1457 + bars = hweight32(bars_mask); 1458 + if (bars == (HSX_SPLITBAR_MAX_MW + 1)) 1459 + ndev->split_bar = 1; 1460 + 1461 + break; 1462 + default: 1463 + dev_err(&ndev->pdev->dev, "Unknown PPD %x\n", ppd); 1464 + return -ENODEV; 1465 + } 1466 + 1467 + ntb_max_mw_detect(ndev); 1468 + 1469 + return 0; 1470 + } 1471 + 1472 + static int ntb_atom_detect(struct ntb_device *ndev) 1473 + { 1474 + int rc; 1475 + u32 ppd; 1476 + 1477 + ndev->hw_type = BWD_HW; 1478 + 1479 + rc = pci_read_config_dword(ndev->pdev, NTB_PPD_OFFSET, &ppd); 1480 + if (rc) 1481 + return rc; 1482 + 1483 + switch ((ppd & BWD_PPD_CONN_TYPE) >> 8) { 1484 + case NTB_CONN_B2B: 1485 + dev_info(&ndev->pdev->dev, "Conn Type = B2B\n"); 1486 + ndev->conn_type = NTB_CONN_B2B; 1487 + break; 1488 + case NTB_CONN_RP: 1489 + default: 1490 + dev_err(&ndev->pdev->dev, "Unsupported NTB configuration\n"); 1491 + return -EINVAL; 1492 + } 1493 + 1494 + if (ppd & BWD_PPD_DEV_TYPE) 1495 + ndev->dev_type = NTB_DEV_DSD; 1496 + else 1497 + ndev->dev_type = NTB_DEV_USD; 1498 + 1499 + return 0; 1500 + } 1501 + 1502 + static int ntb_device_detect(struct ntb_device *ndev) 1503 + { 1504 + int rc; 1505 + 1506 + if (is_ntb_xeon(ndev)) 1507 + rc = ntb_xeon_detect(ndev); 1508 + else if (is_ntb_atom(ndev)) 1509 + rc = ntb_atom_detect(ndev); 1510 + else 1511 + rc = -ENODEV; 1512 + 1513 + dev_info(&ndev->pdev->dev, "Device Type = %s\n", 1514 + ndev->dev_type == NTB_DEV_USD ? "USD/DSP" : "DSD/USP"); 1515 + 1516 + return 0; 1585 1517 } 1586 1518 1587 1519 static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ··· 1711 1409 return -ENOMEM; 1712 1410 1713 1411 ndev->pdev = pdev; 1412 + 1413 + ntb_set_errata_flags(ndev); 1414 + 1714 1415 ndev->link_status = NTB_LINK_DOWN; 1715 1416 pci_set_drvdata(pdev, ndev); 1716 1417 ntb_setup_debugfs(ndev); ··· 1724 1419 1725 1420 pci_set_master(ndev->pdev); 1726 1421 1727 - rc = pci_request_selected_regions(pdev, NTB_BAR_MASK, KBUILD_MODNAME); 1422 + rc = ntb_device_detect(ndev); 1728 1423 if (rc) 1424 + goto err; 1425 + 1426 + ndev->mw = kcalloc(ndev->limits.max_mw, sizeof(struct ntb_mw), 1427 + GFP_KERNEL); 1428 + if (!ndev->mw) { 1429 + rc = -ENOMEM; 1729 1430 goto err1; 1431 + } 1432 + 1433 + if (ndev->split_bar) 1434 + rc = pci_request_selected_regions(pdev, NTB_SPLITBAR_MASK, 1435 + KBUILD_MODNAME); 1436 + else 1437 + rc = pci_request_selected_regions(pdev, NTB_BAR_MASK, 1438 + KBUILD_MODNAME); 1439 + 1440 + if (rc) 1441 + goto err2; 1730 1442 1731 1443 ndev->reg_base = pci_ioremap_bar(pdev, NTB_BAR_MMIO); 1732 1444 if (!ndev->reg_base) { 1733 1445 dev_warn(&pdev->dev, "Cannot remap BAR 0\n"); 1734 1446 rc = -EIO; 1735 - goto err2; 1447 + goto err3; 1736 1448 } 1737 1449 1738 - for (i = 0; i < NTB_MAX_NUM_MW; i++) { 1450 + for (i = 0; i < ndev->limits.max_mw; i++) { 1739 1451 ndev->mw[i].bar_sz = pci_resource_len(pdev, MW_TO_BAR(i)); 1740 - ndev->mw[i].vbase = 1741 - ioremap_wc(pci_resource_start(pdev, MW_TO_BAR(i)), 1742 - ndev->mw[i].bar_sz); 1452 + 1453 + /* 1454 + * with the errata we need to steal last of the memory 1455 + * windows for workarounds and they point to MMIO registers. 1456 + */ 1457 + if ((ndev->wa_flags & WA_SNB_ERR) && 1458 + (i == (ndev->limits.max_mw - 1))) { 1459 + ndev->mw[i].vbase = 1460 + ioremap_nocache(pci_resource_start(pdev, 1461 + MW_TO_BAR(i)), 1462 + ndev->mw[i].bar_sz); 1463 + } else { 1464 + ndev->mw[i].vbase = 1465 + ioremap_wc(pci_resource_start(pdev, 1466 + MW_TO_BAR(i)), 1467 + ndev->mw[i].bar_sz); 1468 + } 1469 + 1743 1470 dev_info(&pdev->dev, "MW %d size %llu\n", i, 1744 1471 (unsigned long long) ndev->mw[i].bar_sz); 1745 1472 if (!ndev->mw[i].vbase) { ··· 1786 1449 if (rc) { 1787 1450 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 1788 1451 if (rc) 1789 - goto err3; 1452 + goto err4; 1790 1453 1791 1454 dev_warn(&pdev->dev, "Cannot DMA highmem\n"); 1792 1455 } ··· 1795 1458 if (rc) { 1796 1459 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 1797 1460 if (rc) 1798 - goto err3; 1461 + goto err4; 1799 1462 1800 1463 dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n"); 1801 1464 } 1802 1465 1803 1466 rc = ntb_device_setup(ndev); 1804 1467 if (rc) 1805 - goto err3; 1468 + goto err4; 1806 1469 1807 1470 rc = ntb_create_callbacks(ndev); 1808 1471 if (rc) 1809 - goto err4; 1472 + goto err5; 1810 1473 1811 1474 rc = ntb_setup_interrupts(ndev); 1812 1475 if (rc) 1813 - goto err5; 1476 + goto err6; 1814 1477 1815 1478 /* The scratchpad registers keep the values between rmmod/insmod, 1816 1479 * blast them now ··· 1822 1485 1823 1486 rc = ntb_transport_init(pdev); 1824 1487 if (rc) 1825 - goto err6; 1488 + goto err7; 1826 1489 1827 1490 ntb_hw_link_up(ndev); 1828 1491 1829 1492 return 0; 1830 1493 1831 - err6: 1494 + err7: 1832 1495 ntb_free_interrupts(ndev); 1833 - err5: 1496 + err6: 1834 1497 ntb_free_callbacks(ndev); 1835 - err4: 1498 + err5: 1836 1499 ntb_device_free(ndev); 1837 - err3: 1500 + err4: 1838 1501 for (i--; i >= 0; i--) 1839 1502 iounmap(ndev->mw[i].vbase); 1840 1503 iounmap(ndev->reg_base); 1504 + err3: 1505 + if (ndev->split_bar) 1506 + pci_release_selected_regions(pdev, NTB_SPLITBAR_MASK); 1507 + else 1508 + pci_release_selected_regions(pdev, NTB_BAR_MASK); 1841 1509 err2: 1842 - pci_release_selected_regions(pdev, NTB_BAR_MASK); 1510 + kfree(ndev->mw); 1843 1511 err1: 1844 1512 pci_disable_device(pdev); 1845 1513 err: ··· 1868 1526 ntb_free_callbacks(ndev); 1869 1527 ntb_device_free(ndev); 1870 1528 1871 - for (i = 0; i < NTB_MAX_NUM_MW; i++) 1529 + /* need to reset max_mw limits so we can unmap properly */ 1530 + if (ndev->hw_type == SNB_HW) 1531 + ntb_max_mw_detect(ndev); 1532 + 1533 + for (i = 0; i < ndev->limits.max_mw; i++) 1872 1534 iounmap(ndev->mw[i].vbase); 1873 1535 1536 + kfree(ndev->mw); 1874 1537 iounmap(ndev->reg_base); 1875 - pci_release_selected_regions(pdev, NTB_BAR_MASK); 1538 + if (ndev->split_bar) 1539 + pci_release_selected_regions(pdev, NTB_SPLITBAR_MASK); 1540 + else 1541 + pci_release_selected_regions(pdev, NTB_BAR_MASK); 1876 1542 pci_disable_device(pdev); 1877 1543 ntb_free_debugfs(ndev); 1878 1544 kfree(ndev); ··· 1892 1542 .probe = ntb_pci_probe, 1893 1543 .remove = ntb_pci_remove, 1894 1544 }; 1545 + 1895 1546 module_pci_driver(ntb_pci_driver);
+14 -5
drivers/ntb/ntb_hw.h
··· 78 78 79 79 #define NTB_BAR_MMIO 0 80 80 #define NTB_BAR_23 2 81 - #define NTB_BAR_45 4 81 + #define NTB_BAR_4 4 82 + #define NTB_BAR_5 5 83 + 82 84 #define NTB_BAR_MASK ((1 << NTB_BAR_MMIO) | (1 << NTB_BAR_23) |\ 83 - (1 << NTB_BAR_45)) 85 + (1 << NTB_BAR_4)) 86 + #define NTB_SPLITBAR_MASK ((1 << NTB_BAR_MMIO) | (1 << NTB_BAR_23) |\ 87 + (1 << NTB_BAR_4) | (1 << NTB_BAR_5)) 84 88 85 89 #define NTB_HB_TIMEOUT msecs_to_jiffies(1000) 86 - 87 - #define NTB_MAX_NUM_MW 2 88 90 89 91 enum ntb_hw_event { 90 92 NTB_EVENT_SW_EVENT0 = 0, ··· 111 109 struct tasklet_struct irq_work; 112 110 }; 113 111 112 + #define WA_SNB_ERR 0x00000001 113 + 114 114 struct ntb_device { 115 115 struct pci_dev *pdev; 116 116 struct msix_entry *msix_entries; 117 117 void __iomem *reg_base; 118 - struct ntb_mw mw[NTB_MAX_NUM_MW]; 118 + struct ntb_mw *mw; 119 119 struct { 120 120 unsigned char max_mw; 121 121 unsigned char max_spads; ··· 130 126 void __iomem *rdb; 131 127 void __iomem *bar2_xlat; 132 128 void __iomem *bar4_xlat; 129 + void __iomem *bar5_xlat; 133 130 void __iomem *spad_write; 134 131 void __iomem *spad_read; 135 132 void __iomem *lnk_cntl; ··· 150 145 unsigned char link_width; 151 146 unsigned char link_speed; 152 147 unsigned char link_status; 148 + unsigned char split_bar; 153 149 154 150 struct delayed_work hb_timer; 155 151 unsigned long last_ts; ··· 158 152 struct delayed_work lr_timer; 159 153 160 154 struct dentry *debugfs_dir; 155 + struct dentry *debugfs_info; 156 + 157 + unsigned int wa_flags; 161 158 }; 162 159 163 160 /**
+28 -10
drivers/ntb/ntb_regs.h
··· 57 57 #define SNB_MAX_DB_BITS 15 58 58 #define SNB_LINK_DB 15 59 59 #define SNB_DB_BITS_PER_VEC 5 60 + #define HSX_SPLITBAR_MAX_MW 3 60 61 #define SNB_MAX_MW 2 61 62 #define SNB_ERRATA_MAX_MW 1 62 63 63 64 #define SNB_DB_HW_LINK 0x8000 64 65 66 + #define SNB_UNCERRSTS_OFFSET 0x014C 67 + #define SNB_CORERRSTS_OFFSET 0x0158 68 + #define SNB_LINK_STATUS_OFFSET 0x01A2 65 69 #define SNB_PCICMD_OFFSET 0x0504 66 70 #define SNB_DEVCTRL_OFFSET 0x0598 71 + #define SNB_DEVSTS_OFFSET 0x059A 67 72 #define SNB_SLINK_STATUS_OFFSET 0x05A2 68 - #define SNB_LINK_STATUS_OFFSET 0x01A2 69 73 70 74 #define SNB_PBAR2LMT_OFFSET 0x0000 71 75 #define SNB_PBAR4LMT_OFFSET 0x0008 76 + #define SNB_PBAR5LMT_OFFSET 0x000C 72 77 #define SNB_PBAR2XLAT_OFFSET 0x0010 73 78 #define SNB_PBAR4XLAT_OFFSET 0x0018 79 + #define SNB_PBAR5XLAT_OFFSET 0x001C 74 80 #define SNB_SBAR2LMT_OFFSET 0x0020 75 81 #define SNB_SBAR4LMT_OFFSET 0x0028 82 + #define SNB_SBAR5LMT_OFFSET 0x002C 76 83 #define SNB_SBAR2XLAT_OFFSET 0x0030 77 84 #define SNB_SBAR4XLAT_OFFSET 0x0038 85 + #define SNB_SBAR5XLAT_OFFSET 0x003C 78 86 #define SNB_SBAR0BASE_OFFSET 0x0040 79 87 #define SNB_SBAR2BASE_OFFSET 0x0048 80 88 #define SNB_SBAR4BASE_OFFSET 0x0050 89 + #define SNB_SBAR5BASE_OFFSET 0x0054 81 90 #define SNB_NTBCNTL_OFFSET 0x0058 82 91 #define SNB_SBDF_OFFSET 0x005C 83 92 #define SNB_PDOORBELL_OFFSET 0x0060 84 93 #define SNB_PDBMSK_OFFSET 0x0062 85 94 #define SNB_SDOORBELL_OFFSET 0x0064 86 95 #define SNB_SDBMSK_OFFSET 0x0066 87 - #define SNB_USMEMMISS 0x0070 96 + #define SNB_USMEMMISS_OFFSET 0x0070 88 97 #define SNB_SPAD_OFFSET 0x0080 89 98 #define SNB_SPADSEMA4_OFFSET 0x00c0 90 99 #define SNB_WCCNTRL_OFFSET 0x00e0 ··· 102 93 #define SNB_B2B_XLAT_OFFSETL 0x0144 103 94 #define SNB_B2B_XLAT_OFFSETU 0x0148 104 95 105 - #define SNB_MBAR01_USD_ADDR 0x000000210000000CULL 106 - #define SNB_MBAR23_USD_ADDR 0x000000410000000CULL 107 - #define SNB_MBAR45_USD_ADDR 0x000000810000000CULL 108 - #define SNB_MBAR01_DSD_ADDR 0x000000200000000CULL 109 - #define SNB_MBAR23_DSD_ADDR 0x000000400000000CULL 110 - #define SNB_MBAR45_DSD_ADDR 0x000000800000000CULL 96 + /* 97 + * The addresses are setup so the 32bit BARs can function. Thus 98 + * the addresses are all in 32bit space 99 + */ 100 + #define SNB_MBAR01_USD_ADDR 0x000000002100000CULL 101 + #define SNB_MBAR23_USD_ADDR 0x000000004100000CULL 102 + #define SNB_MBAR4_USD_ADDR 0x000000008100000CULL 103 + #define SNB_MBAR5_USD_ADDR 0x00000000A100000CULL 104 + #define SNB_MBAR01_DSD_ADDR 0x000000002000000CULL 105 + #define SNB_MBAR23_DSD_ADDR 0x000000004000000CULL 106 + #define SNB_MBAR4_DSD_ADDR 0x000000008000000CULL 107 + #define SNB_MBAR5_DSD_ADDR 0x00000000A000000CULL 111 108 112 109 #define BWD_MSIX_CNT 34 113 110 #define BWD_MAX_SPADS 16 ··· 162 147 #define NTB_CNTL_LINK_DISABLE (1 << 1) 163 148 #define NTB_CNTL_S2P_BAR23_SNOOP (1 << 2) 164 149 #define NTB_CNTL_P2S_BAR23_SNOOP (1 << 4) 165 - #define NTB_CNTL_S2P_BAR45_SNOOP (1 << 6) 166 - #define NTB_CNTL_P2S_BAR45_SNOOP (1 << 8) 150 + #define NTB_CNTL_S2P_BAR4_SNOOP (1 << 6) 151 + #define NTB_CNTL_P2S_BAR4_SNOOP (1 << 8) 152 + #define NTB_CNTL_S2P_BAR5_SNOOP (1 << 12) 153 + #define NTB_CNTL_P2S_BAR5_SNOOP (1 << 14) 167 154 #define BWD_CNTL_LINK_DOWN (1 << 16) 168 155 169 156 #define NTB_PPD_OFFSET 0x00D4 170 157 #define SNB_PPD_CONN_TYPE 0x0003 171 158 #define SNB_PPD_DEV_TYPE 0x0010 159 + #define SNB_PPD_SPLIT_BAR (1 << 6) 172 160 #define BWD_PPD_INIT_LINK 0x0008 173 161 #define BWD_PPD_CONN_TYPE 0x0300 174 162 #define BWD_PPD_DEV_TYPE 0x1000