diff options
author | Eli Cohen <eli@mellanox.co.il> | 2006-03-02 15:40:46 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-03-20 13:08:22 -0500 |
commit | 651eaac92894f8b6761c51b6637ea9cacea7fba2 (patch) | |
tree | 8be06461ef870b7d130ebce39f55fe93af6ac542 /drivers/infiniband | |
parent | 27d56300647f6e76847bc2407d7abc782fe87495 (diff) |
IB/mthca: Optimize large messages on Sinai HCAs
Sinai (one-port PCI Express) HCAs get improved throughput for messages
bigger than 80 KB in DDR mode if memory keys are formatted in a
specific way. The enhancement only works if the memory key table is
smaller than 2^24 entries. For larger tables, the enhancement is off
and a warning is printed (to avoid silent performance loss).
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Michael Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_cmd.c | 12 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_dev.h | 3 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_main.c | 23 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_mr.c | 20 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_profile.c | 10 |
5 files changed, 51 insertions, 17 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 948a2861cae3..343eca507870 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -1277,7 +1277,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev, | |||
1277 | int err; | 1277 | int err; |
1278 | 1278 | ||
1279 | #define INIT_HCA_IN_SIZE 0x200 | 1279 | #define INIT_HCA_IN_SIZE 0x200 |
1280 | #define INIT_HCA_FLAGS_OFFSET 0x014 | 1280 | #define INIT_HCA_FLAGS1_OFFSET 0x00c |
1281 | #define INIT_HCA_FLAGS2_OFFSET 0x014 | ||
1281 | #define INIT_HCA_QPC_OFFSET 0x020 | 1282 | #define INIT_HCA_QPC_OFFSET 0x020 |
1282 | #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) | 1283 | #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) |
1283 | #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) | 1284 | #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) |
@@ -1320,15 +1321,18 @@ int mthca_INIT_HCA(struct mthca_dev *dev, | |||
1320 | 1321 | ||
1321 | memset(inbox, 0, INIT_HCA_IN_SIZE); | 1322 | memset(inbox, 0, INIT_HCA_IN_SIZE); |
1322 | 1323 | ||
1324 | if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) | ||
1325 | MTHCA_PUT(inbox, 0x1, INIT_HCA_FLAGS1_OFFSET); | ||
1326 | |||
1323 | #if defined(__LITTLE_ENDIAN) | 1327 | #if defined(__LITTLE_ENDIAN) |
1324 | *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); | 1328 | *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) &= ~cpu_to_be32(1 << 1); |
1325 | #elif defined(__BIG_ENDIAN) | 1329 | #elif defined(__BIG_ENDIAN) |
1326 | *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); | 1330 | *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1 << 1); |
1327 | #else | 1331 | #else |
1328 | #error Host endianness not defined | 1332 | #error Host endianness not defined |
1329 | #endif | 1333 | #endif |
1330 | /* Check port for UD address vector: */ | 1334 | /* Check port for UD address vector: */ |
1331 | *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); | 1335 | *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1); |
1332 | 1336 | ||
1333 | /* We leave wqe_quota, responder_exu, etc as 0 (default) */ | 1337 | /* We leave wqe_quota, responder_exu, etc as 0 (default) */ |
1334 | 1338 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index ea48c897c7ce..ad52edbefe98 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -64,7 +64,8 @@ enum { | |||
64 | MTHCA_FLAG_NO_LAM = 1 << 5, | 64 | MTHCA_FLAG_NO_LAM = 1 << 5, |
65 | MTHCA_FLAG_FMR = 1 << 6, | 65 | MTHCA_FLAG_FMR = 1 << 6, |
66 | MTHCA_FLAG_MEMFREE = 1 << 7, | 66 | MTHCA_FLAG_MEMFREE = 1 << 7, |
67 | MTHCA_FLAG_PCIE = 1 << 8 | 67 | MTHCA_FLAG_PCIE = 1 << 8, |
68 | MTHCA_FLAG_SINAI_OPT = 1 << 9 | ||
68 | }; | 69 | }; |
69 | 70 | ||
70 | enum { | 71 | enum { |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 9c849d27b06e..d94837fbf162 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -935,13 +935,19 @@ enum { | |||
935 | 935 | ||
936 | static struct { | 936 | static struct { |
937 | u64 latest_fw; | 937 | u64 latest_fw; |
938 | int is_memfree; | 938 | u32 flags; |
939 | int is_pcie; | ||
940 | } mthca_hca_table[] = { | 939 | } mthca_hca_table[] = { |
941 | [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 }, | 940 | [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), |
942 | [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 }, | 941 | .flags = 0 }, |
943 | [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 }, | 942 | [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), |
944 | [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 } | 943 | .flags = MTHCA_FLAG_PCIE }, |
944 | [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), | ||
945 | .flags = MTHCA_FLAG_MEMFREE | | ||
946 | MTHCA_FLAG_PCIE }, | ||
947 | [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), | ||
948 | .flags = MTHCA_FLAG_MEMFREE | | ||
949 | MTHCA_FLAG_PCIE | | ||
950 | MTHCA_FLAG_SINAI_OPT } | ||
945 | }; | 951 | }; |
946 | 952 | ||
947 | static int __devinit mthca_init_one(struct pci_dev *pdev, | 953 | static int __devinit mthca_init_one(struct pci_dev *pdev, |
@@ -1031,12 +1037,9 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, | |||
1031 | 1037 | ||
1032 | mdev->pdev = pdev; | 1038 | mdev->pdev = pdev; |
1033 | 1039 | ||
1040 | mdev->mthca_flags = mthca_hca_table[id->driver_data].flags; | ||
1034 | if (ddr_hidden) | 1041 | if (ddr_hidden) |
1035 | mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; | 1042 | mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; |
1036 | if (mthca_hca_table[id->driver_data].is_memfree) | ||
1037 | mdev->mthca_flags |= MTHCA_FLAG_MEMFREE; | ||
1038 | if (mthca_hca_table[id->driver_data].is_pcie) | ||
1039 | mdev->mthca_flags |= MTHCA_FLAG_PCIE; | ||
1040 | 1043 | ||
1041 | /* | 1044 | /* |
1042 | * Now reset the HCA before we touch the PCI capabilities or | 1045 | * Now reset the HCA before we touch the PCI capabilities or |
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 0b48048ad0f8..698b62125765 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c | |||
@@ -76,6 +76,8 @@ struct mthca_mpt_entry { | |||
76 | #define MTHCA_MPT_STATUS_SW 0xF0 | 76 | #define MTHCA_MPT_STATUS_SW 0xF0 |
77 | #define MTHCA_MPT_STATUS_HW 0x00 | 77 | #define MTHCA_MPT_STATUS_HW 0x00 |
78 | 78 | ||
79 | #define SINAI_FMR_KEY_INC 0x1000000 | ||
80 | |||
79 | /* | 81 | /* |
80 | * Buddy allocator for MTT segments (currently not very efficient | 82 | * Buddy allocator for MTT segments (currently not very efficient |
81 | * since it doesn't keep a free list and just searches linearly | 83 | * since it doesn't keep a free list and just searches linearly |
@@ -330,6 +332,14 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key) | |||
330 | return tavor_key_to_hw_index(key); | 332 | return tavor_key_to_hw_index(key); |
331 | } | 333 | } |
332 | 334 | ||
335 | static inline u32 adjust_key(struct mthca_dev *dev, u32 key) | ||
336 | { | ||
337 | if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) | ||
338 | return ((key << 20) & 0x800000) | (key & 0x7fffff); | ||
339 | else | ||
340 | return key; | ||
341 | } | ||
342 | |||
333 | int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, | 343 | int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, |
334 | u64 iova, u64 total_size, u32 access, struct mthca_mr *mr) | 344 | u64 iova, u64 total_size, u32 access, struct mthca_mr *mr) |
335 | { | 345 | { |
@@ -345,6 +355,7 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, | |||
345 | key = mthca_alloc(&dev->mr_table.mpt_alloc); | 355 | key = mthca_alloc(&dev->mr_table.mpt_alloc); |
346 | if (key == -1) | 356 | if (key == -1) |
347 | return -ENOMEM; | 357 | return -ENOMEM; |
358 | key = adjust_key(dev, key); | ||
348 | mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); | 359 | mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); |
349 | 360 | ||
350 | if (mthca_is_memfree(dev)) { | 361 | if (mthca_is_memfree(dev)) { |
@@ -504,6 +515,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, | |||
504 | key = mthca_alloc(&dev->mr_table.mpt_alloc); | 515 | key = mthca_alloc(&dev->mr_table.mpt_alloc); |
505 | if (key == -1) | 516 | if (key == -1) |
506 | return -ENOMEM; | 517 | return -ENOMEM; |
518 | key = adjust_key(dev, key); | ||
507 | 519 | ||
508 | idx = key & (dev->limits.num_mpts - 1); | 520 | idx = key & (dev->limits.num_mpts - 1); |
509 | mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); | 521 | mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); |
@@ -687,7 +699,10 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, | |||
687 | ++fmr->maps; | 699 | ++fmr->maps; |
688 | 700 | ||
689 | key = arbel_key_to_hw_index(fmr->ibmr.lkey); | 701 | key = arbel_key_to_hw_index(fmr->ibmr.lkey); |
690 | key += dev->limits.num_mpts; | 702 | if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) |
703 | key += SINAI_FMR_KEY_INC; | ||
704 | else | ||
705 | key += dev->limits.num_mpts; | ||
691 | fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key); | 706 | fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key); |
692 | 707 | ||
693 | *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW; | 708 | *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW; |
@@ -760,6 +775,9 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev) | |||
760 | else | 775 | else |
761 | dev->mthca_flags |= MTHCA_FLAG_FMR; | 776 | dev->mthca_flags |= MTHCA_FLAG_FMR; |
762 | 777 | ||
778 | if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) | ||
779 | mthca_dbg(dev, "Memory key throughput optimization activated.\n"); | ||
780 | |||
763 | err = mthca_buddy_init(&dev->mr_table.mtt_buddy, | 781 | err = mthca_buddy_init(&dev->mr_table.mtt_buddy, |
764 | fls(dev->limits.num_mtt_segs - 1)); | 782 | fls(dev->limits.num_mtt_segs - 1)); |
765 | 783 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c index 08a909371b0a..58d44aa3c302 100644 --- a/drivers/infiniband/hw/mthca/mthca_profile.c +++ b/drivers/infiniband/hw/mthca/mthca_profile.c | |||
@@ -152,7 +152,7 @@ u64 mthca_make_profile(struct mthca_dev *dev, | |||
152 | } | 152 | } |
153 | if (total_size > mem_avail) { | 153 | if (total_size > mem_avail) { |
154 | mthca_err(dev, "Profile requires 0x%llx bytes; " | 154 | mthca_err(dev, "Profile requires 0x%llx bytes; " |
155 | "won't in 0x%llx bytes of context memory.\n", | 155 | "won't fit in 0x%llx bytes of context memory.\n", |
156 | (unsigned long long) total_size, | 156 | (unsigned long long) total_size, |
157 | (unsigned long long) mem_avail); | 157 | (unsigned long long) mem_avail); |
158 | kfree(profile); | 158 | kfree(profile); |
@@ -262,6 +262,14 @@ u64 mthca_make_profile(struct mthca_dev *dev, | |||
262 | */ | 262 | */ |
263 | dev->limits.num_pds = MTHCA_NUM_PDS; | 263 | dev->limits.num_pds = MTHCA_NUM_PDS; |
264 | 264 | ||
265 | if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT && | ||
266 | init_hca->log_mpt_sz > 23) { | ||
267 | mthca_warn(dev, "MPT table too large (requested size 2^%d >= 2^24)\n", | ||
268 | init_hca->log_mpt_sz); | ||
269 | mthca_warn(dev, "Disabling memory key throughput optimization.\n"); | ||
270 | dev->mthca_flags &= ~MTHCA_FLAG_SINAI_OPT; | ||
271 | } | ||
272 | |||
265 | /* | 273 | /* |
266 | * For Tavor, FMRs use ioremapped PCI memory. For 32 bit | 274 | * For Tavor, FMRs use ioremapped PCI memory. For 32 bit |
267 | * systems it may use too much vmalloc space to map all MTT | 275 | * systems it may use too much vmalloc space to map all MTT |