diff options
Diffstat (limited to 'drivers/ntb/ntb_hw.c')
| -rw-r--r-- | drivers/ntb/ntb_hw.c | 121 |
1 files changed, 103 insertions, 18 deletions
diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 1cb6e51e6bda..170e8e60cdb7 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c | |||
| @@ -141,6 +141,24 @@ void ntb_unregister_event_callback(struct ntb_device *ndev) | |||
| 141 | ndev->event_cb = NULL; | 141 | ndev->event_cb = NULL; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static void ntb_irq_work(unsigned long data) | ||
| 145 | { | ||
| 146 | struct ntb_db_cb *db_cb = (struct ntb_db_cb *)data; | ||
| 147 | int rc; | ||
| 148 | |||
| 149 | rc = db_cb->callback(db_cb->data, db_cb->db_num); | ||
| 150 | if (rc) | ||
| 151 | tasklet_schedule(&db_cb->irq_work); | ||
| 152 | else { | ||
| 153 | struct ntb_device *ndev = db_cb->ndev; | ||
| 154 | unsigned long mask; | ||
| 155 | |||
| 156 | mask = readw(ndev->reg_ofs.ldb_mask); | ||
| 157 | clear_bit(db_cb->db_num * ndev->bits_per_vector, &mask); | ||
| 158 | writew(mask, ndev->reg_ofs.ldb_mask); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 144 | /** | 162 | /** |
| 145 | * ntb_register_db_callback() - register a callback for doorbell interrupt | 163 | * ntb_register_db_callback() - register a callback for doorbell interrupt |
| 146 | * @ndev: pointer to ntb_device instance | 164 | * @ndev: pointer to ntb_device instance |
| @@ -155,7 +173,7 @@ void ntb_unregister_event_callback(struct ntb_device *ndev) | |||
| 155 | * RETURNS: An appropriate -ERRNO error value on error, or zero for success. | 173 | * RETURNS: An appropriate -ERRNO error value on error, or zero for success. |
| 156 | */ | 174 | */ |
| 157 | int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx, | 175 | int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx, |
| 158 | void *data, void (*func)(void *data, int db_num)) | 176 | void *data, int (*func)(void *data, int db_num)) |
| 159 | { | 177 | { |
| 160 | unsigned long mask; | 178 | unsigned long mask; |
| 161 | 179 | ||
| @@ -166,6 +184,10 @@ int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx, | |||
| 166 | 184 | ||
| 167 | ndev->db_cb[idx].callback = func; | 185 | ndev->db_cb[idx].callback = func; |
| 168 | ndev->db_cb[idx].data = data; | 186 | ndev->db_cb[idx].data = data; |
| 187 | ndev->db_cb[idx].ndev = ndev; | ||
| 188 | |||
| 189 | tasklet_init(&ndev->db_cb[idx].irq_work, ntb_irq_work, | ||
| 190 | (unsigned long) &ndev->db_cb[idx]); | ||
| 169 | 191 | ||
| 170 | /* unmask interrupt */ | 192 | /* unmask interrupt */ |
| 171 | mask = readw(ndev->reg_ofs.ldb_mask); | 193 | mask = readw(ndev->reg_ofs.ldb_mask); |
| @@ -194,6 +216,8 @@ void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx) | |||
| 194 | set_bit(idx * ndev->bits_per_vector, &mask); | 216 | set_bit(idx * ndev->bits_per_vector, &mask); |
| 195 | writew(mask, ndev->reg_ofs.ldb_mask); | 217 | writew(mask, ndev->reg_ofs.ldb_mask); |
| 196 | 218 | ||
| 219 | tasklet_disable(&ndev->db_cb[idx].irq_work); | ||
| 220 | |||
| 197 | ndev->db_cb[idx].callback = NULL; | 221 | ndev->db_cb[idx].callback = NULL; |
| 198 | } | 222 | } |
| 199 | 223 | ||
| @@ -678,6 +702,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 678 | return -EINVAL; | 702 | return -EINVAL; |
| 679 | 703 | ||
| 680 | ndev->limits.max_mw = SNB_ERRATA_MAX_MW; | 704 | ndev->limits.max_mw = SNB_ERRATA_MAX_MW; |
| 705 | ndev->limits.max_db_bits = SNB_MAX_DB_BITS; | ||
| 681 | ndev->reg_ofs.spad_write = ndev->mw[1].vbase + | 706 | ndev->reg_ofs.spad_write = ndev->mw[1].vbase + |
| 682 | SNB_SPAD_OFFSET; | 707 | SNB_SPAD_OFFSET; |
| 683 | ndev->reg_ofs.rdb = ndev->mw[1].vbase + | 708 | ndev->reg_ofs.rdb = ndev->mw[1].vbase + |
| @@ -688,8 +713,21 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 688 | */ | 713 | */ |
| 689 | writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base + | 714 | writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base + |
| 690 | SNB_PBAR4LMT_OFFSET); | 715 | SNB_PBAR4LMT_OFFSET); |
| 716 | /* HW errata on the Limit registers. They can only be | ||
| 717 | * written when the base register is 4GB aligned and | ||
| 718 | * < 32bit. This should already be the case based on the | ||
| 719 | * driver defaults, but write the Limit registers first | ||
| 720 | * just in case. | ||
| 721 | */ | ||
| 691 | } else { | 722 | } else { |
| 692 | ndev->limits.max_mw = SNB_MAX_MW; | 723 | ndev->limits.max_mw = SNB_MAX_MW; |
| 724 | |||
| 725 | /* HW Errata on bit 14 of b2bdoorbell register. Writes | ||
| 726 | * will not be mirrored to the remote system. Shrink | ||
| 727 | * the number of bits by one, since bit 14 is the last | ||
| 728 | * bit. | ||
| 729 | */ | ||
| 730 | ndev->limits.max_db_bits = SNB_MAX_DB_BITS - 1; | ||
| 693 | ndev->reg_ofs.spad_write = ndev->reg_base + | 731 | ndev->reg_ofs.spad_write = ndev->reg_base + |
| 694 | SNB_B2B_SPAD_OFFSET; | 732 | SNB_B2B_SPAD_OFFSET; |
| 695 | ndev->reg_ofs.rdb = ndev->reg_base + | 733 | ndev->reg_ofs.rdb = ndev->reg_base + |
| @@ -699,6 +737,12 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 699 | * something silly | 737 | * something silly |
| 700 | */ | 738 | */ |
| 701 | writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET); | 739 | writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET); |
| 740 | /* HW errata on the Limit registers. They can only be | ||
| 741 | * written when the base register is 4GB aligned and | ||
| 742 | * < 32bit. This should already be the case based on the | ||
| 743 | * driver defaults, but write the Limit registers first | ||
| 744 | * just in case. | ||
| 745 | */ | ||
| 702 | } | 746 | } |
| 703 | 747 | ||
| 704 | /* The Xeon errata workaround requires setting SBAR Base | 748 | /* The Xeon errata workaround requires setting SBAR Base |
| @@ -769,6 +813,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 769 | * have an equal amount. | 813 | * have an equal amount. |
| 770 | */ | 814 | */ |
| 771 | ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2; | 815 | ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2; |
| 816 | ndev->limits.max_db_bits = SNB_MAX_DB_BITS; | ||
| 772 | /* Note: The SDOORBELL is the cause of the errata. You REALLY | 817 | /* Note: The SDOORBELL is the cause of the errata. You REALLY |
| 773 | * don't want to touch it. | 818 | * don't want to touch it. |
| 774 | */ | 819 | */ |
| @@ -793,6 +838,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 793 | * have an equal amount. | 838 | * have an equal amount. |
| 794 | */ | 839 | */ |
| 795 | ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2; | 840 | ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2; |
| 841 | ndev->limits.max_db_bits = SNB_MAX_DB_BITS; | ||
| 796 | ndev->reg_ofs.rdb = ndev->reg_base + SNB_PDOORBELL_OFFSET; | 842 | ndev->reg_ofs.rdb = ndev->reg_base + SNB_PDOORBELL_OFFSET; |
| 797 | ndev->reg_ofs.ldb = ndev->reg_base + SNB_SDOORBELL_OFFSET; | 843 | ndev->reg_ofs.ldb = ndev->reg_base + SNB_SDOORBELL_OFFSET; |
| 798 | ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_SDBMSK_OFFSET; | 844 | ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_SDBMSK_OFFSET; |
| @@ -819,7 +865,6 @@ static int ntb_xeon_setup(struct ntb_device *ndev) | |||
| 819 | ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_SLINK_STATUS_OFFSET; | 865 | ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_SLINK_STATUS_OFFSET; |
| 820 | ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET; | 866 | ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET; |
| 821 | 867 | ||
| 822 | ndev->limits.max_db_bits = SNB_MAX_DB_BITS; | ||
| 823 | ndev->limits.msix_cnt = SNB_MSIX_CNT; | 868 | ndev->limits.msix_cnt = SNB_MSIX_CNT; |
| 824 | ndev->bits_per_vector = SNB_DB_BITS_PER_VEC; | 869 | ndev->bits_per_vector = SNB_DB_BITS_PER_VEC; |
| 825 | 870 | ||
| @@ -934,12 +979,16 @@ static irqreturn_t bwd_callback_msix_irq(int irq, void *data) | |||
| 934 | { | 979 | { |
| 935 | struct ntb_db_cb *db_cb = data; | 980 | struct ntb_db_cb *db_cb = data; |
| 936 | struct ntb_device *ndev = db_cb->ndev; | 981 | struct ntb_device *ndev = db_cb->ndev; |
| 982 | unsigned long mask; | ||
| 937 | 983 | ||
| 938 | dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, | 984 | dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, |
| 939 | db_cb->db_num); | 985 | db_cb->db_num); |
| 940 | 986 | ||
| 941 | if (db_cb->callback) | 987 | mask = readw(ndev->reg_ofs.ldb_mask); |
| 942 | db_cb->callback(db_cb->data, db_cb->db_num); | 988 | set_bit(db_cb->db_num * ndev->bits_per_vector, &mask); |
| 989 | writew(mask, ndev->reg_ofs.ldb_mask); | ||
| 990 | |||
| 991 | tasklet_schedule(&db_cb->irq_work); | ||
| 943 | 992 | ||
| 944 | /* No need to check for the specific HB irq, any interrupt means | 993 | /* No need to check for the specific HB irq, any interrupt means |
| 945 | * we're connected. | 994 | * we're connected. |
| @@ -955,12 +1004,16 @@ static irqreturn_t xeon_callback_msix_irq(int irq, void *data) | |||
| 955 | { | 1004 | { |
| 956 | struct ntb_db_cb *db_cb = data; | 1005 | struct ntb_db_cb *db_cb = data; |
| 957 | struct ntb_device *ndev = db_cb->ndev; | 1006 | struct ntb_device *ndev = db_cb->ndev; |
| 1007 | unsigned long mask; | ||
| 958 | 1008 | ||
| 959 | dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, | 1009 | dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, |
| 960 | db_cb->db_num); | 1010 | db_cb->db_num); |
| 961 | 1011 | ||
| 962 | if (db_cb->callback) | 1012 | mask = readw(ndev->reg_ofs.ldb_mask); |
| 963 | db_cb->callback(db_cb->data, db_cb->db_num); | 1013 | set_bit(db_cb->db_num * ndev->bits_per_vector, &mask); |
| 1014 | writew(mask, ndev->reg_ofs.ldb_mask); | ||
| 1015 | |||
| 1016 | tasklet_schedule(&db_cb->irq_work); | ||
| 964 | 1017 | ||
| 965 | /* On Sandybridge, there are 16 bits in the interrupt register | 1018 | /* On Sandybridge, there are 16 bits in the interrupt register |
| 966 | * but only 4 vectors. So, 5 bits are assigned to the first 3 | 1019 | * but only 4 vectors. So, 5 bits are assigned to the first 3 |
| @@ -986,7 +1039,7 @@ static irqreturn_t xeon_event_msix_irq(int irq, void *dev) | |||
| 986 | dev_err(&ndev->pdev->dev, "Error determining link status\n"); | 1039 | dev_err(&ndev->pdev->dev, "Error determining link status\n"); |
| 987 | 1040 | ||
| 988 | /* bit 15 is always the link bit */ | 1041 | /* bit 15 is always the link bit */ |
| 989 | writew(1 << ndev->limits.max_db_bits, ndev->reg_ofs.ldb); | 1042 | writew(1 << SNB_LINK_DB, ndev->reg_ofs.ldb); |
| 990 | 1043 | ||
| 991 | return IRQ_HANDLED; | 1044 | return IRQ_HANDLED; |
| 992 | } | 1045 | } |
| @@ -1075,6 +1128,10 @@ static int ntb_setup_msix(struct ntb_device *ndev) | |||
| 1075 | "Only %d MSI-X vectors. Limiting the number of queues to that number.\n", | 1128 | "Only %d MSI-X vectors. Limiting the number of queues to that number.\n", |
| 1076 | rc); | 1129 | rc); |
| 1077 | msix_entries = rc; | 1130 | msix_entries = rc; |
| 1131 | |||
| 1132 | rc = pci_enable_msix(pdev, ndev->msix_entries, msix_entries); | ||
| 1133 | if (rc) | ||
| 1134 | goto err1; | ||
| 1078 | } | 1135 | } |
| 1079 | 1136 | ||
| 1080 | for (i = 0; i < msix_entries; i++) { | 1137 | for (i = 0; i < msix_entries; i++) { |
| @@ -1176,9 +1233,10 @@ static int ntb_setup_interrupts(struct ntb_device *ndev) | |||
| 1176 | */ | 1233 | */ |
| 1177 | if (ndev->hw_type == BWD_HW) | 1234 | if (ndev->hw_type == BWD_HW) |
| 1178 | writeq(~0, ndev->reg_ofs.ldb_mask); | 1235 | writeq(~0, ndev->reg_ofs.ldb_mask); |
| 1179 | else | 1236 | else { |
| 1180 | writew(~(1 << ndev->limits.max_db_bits), | 1237 | u16 var = 1 << SNB_LINK_DB; |
| 1181 | ndev->reg_ofs.ldb_mask); | 1238 | writew(~var, ndev->reg_ofs.ldb_mask); |
| 1239 | } | ||
| 1182 | 1240 | ||
| 1183 | rc = ntb_setup_msix(ndev); | 1241 | rc = ntb_setup_msix(ndev); |
| 1184 | if (!rc) | 1242 | if (!rc) |
| @@ -1286,6 +1344,39 @@ static void ntb_free_debugfs(struct ntb_device *ndev) | |||
| 1286 | } | 1344 | } |
| 1287 | } | 1345 | } |
| 1288 | 1346 | ||
| 1347 | static void ntb_hw_link_up(struct ntb_device *ndev) | ||
| 1348 | { | ||
| 1349 | if (ndev->conn_type == NTB_CONN_TRANSPARENT) | ||
| 1350 | ntb_link_event(ndev, NTB_LINK_UP); | ||
| 1351 | else { | ||
| 1352 | u32 ntb_cntl; | ||
| 1353 | |||
| 1354 | /* Let's bring the NTB link up */ | ||
| 1355 | ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); | ||
| 1356 | ntb_cntl &= ~(NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK); | ||
| 1357 | ntb_cntl |= NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP; | ||
| 1358 | ntb_cntl |= NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP; | ||
| 1359 | writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); | ||
| 1360 | } | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | static void ntb_hw_link_down(struct ntb_device *ndev) | ||
| 1364 | { | ||
| 1365 | u32 ntb_cntl; | ||
| 1366 | |||
| 1367 | if (ndev->conn_type == NTB_CONN_TRANSPARENT) { | ||
| 1368 | ntb_link_event(ndev, NTB_LINK_DOWN); | ||
| 1369 | return; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | /* Bring NTB link down */ | ||
| 1373 | ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); | ||
| 1374 | ntb_cntl &= ~(NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP); | ||
| 1375 | ntb_cntl &= ~(NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP); | ||
| 1376 | ntb_cntl |= NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK; | ||
| 1377 | writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); | ||
| 1378 | } | ||
| 1379 | |||
| 1289 | static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1380 | static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 1290 | { | 1381 | { |
| 1291 | struct ntb_device *ndev; | 1382 | struct ntb_device *ndev; |
| @@ -1374,9 +1465,7 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1374 | if (rc) | 1465 | if (rc) |
| 1375 | goto err6; | 1466 | goto err6; |
| 1376 | 1467 | ||
| 1377 | /* Let's bring the NTB link up */ | 1468 | ntb_hw_link_up(ndev); |
| 1378 | writel(NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP, | ||
| 1379 | ndev->reg_ofs.lnk_cntl); | ||
| 1380 | 1469 | ||
| 1381 | return 0; | 1470 | return 0; |
| 1382 | 1471 | ||
| @@ -1406,12 +1495,8 @@ static void ntb_pci_remove(struct pci_dev *pdev) | |||
| 1406 | { | 1495 | { |
| 1407 | struct ntb_device *ndev = pci_get_drvdata(pdev); | 1496 | struct ntb_device *ndev = pci_get_drvdata(pdev); |
| 1408 | int i; | 1497 | int i; |
| 1409 | u32 ntb_cntl; | ||
| 1410 | 1498 | ||
| 1411 | /* Bring NTB link down */ | 1499 | ntb_hw_link_down(ndev); |
| 1412 | ntb_cntl = readl(ndev->reg_ofs.lnk_cntl); | ||
| 1413 | ntb_cntl |= NTB_CNTL_LINK_DISABLE; | ||
| 1414 | writel(ntb_cntl, ndev->reg_ofs.lnk_cntl); | ||
| 1415 | 1500 | ||
| 1416 | ntb_transport_free(ndev->ntb_transport); | 1501 | ntb_transport_free(ndev->ntb_transport); |
| 1417 | 1502 | ||
