diff options
author | Sean Hefty <sean.hefty@intel.com> | 2011-06-02 12:01:33 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-10-13 12:43:03 -0400 |
commit | 012a8ff577f95211c6ffd3b77a94c34ebae009b6 (patch) | |
tree | 7d1e8d3ca131cc46ca12e879c4554870e0be76f2 /drivers | |
parent | 2622e18ef407a8e8e3ddc3d6f0c77b756c493798 (diff) |
IB/mlx4: Add support for XRC domains
Support creating and destroying XRC domains. Any sharing of the XRCD
is managed above the low-level driver.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 59 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 12 | ||||
-rw-r--r-- | drivers/net/mlx4/fw.c | 6 | ||||
-rw-r--r-- | drivers/net/mlx4/fw.h | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/main.c | 18 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4.h | 3 | ||||
-rw-r--r-- | drivers/net/mlx4/pd.c | 30 |
7 files changed, 129 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index fa643f4f4e28..23e45df9ae36 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -566,6 +566,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd) | |||
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
568 | 568 | ||
569 | static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev, | ||
570 | struct ib_ucontext *context, | ||
571 | struct ib_udata *udata) | ||
572 | { | ||
573 | struct mlx4_ib_xrcd *xrcd; | ||
574 | int err; | ||
575 | |||
576 | if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) | ||
577 | return ERR_PTR(-ENOSYS); | ||
578 | |||
579 | xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL); | ||
580 | if (!xrcd) | ||
581 | return ERR_PTR(-ENOMEM); | ||
582 | |||
583 | err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn); | ||
584 | if (err) | ||
585 | goto err1; | ||
586 | |||
587 | xrcd->pd = ib_alloc_pd(ibdev); | ||
588 | if (IS_ERR(xrcd->pd)) { | ||
589 | err = PTR_ERR(xrcd->pd); | ||
590 | goto err2; | ||
591 | } | ||
592 | |||
593 | xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0); | ||
594 | if (IS_ERR(xrcd->cq)) { | ||
595 | err = PTR_ERR(xrcd->cq); | ||
596 | goto err3; | ||
597 | } | ||
598 | |||
599 | return &xrcd->ibxrcd; | ||
600 | |||
601 | err3: | ||
602 | ib_dealloc_pd(xrcd->pd); | ||
603 | err2: | ||
604 | mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn); | ||
605 | err1: | ||
606 | kfree(xrcd); | ||
607 | return ERR_PTR(err); | ||
608 | } | ||
609 | |||
610 | static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd) | ||
611 | { | ||
612 | ib_destroy_cq(to_mxrcd(xrcd)->cq); | ||
613 | ib_dealloc_pd(to_mxrcd(xrcd)->pd); | ||
614 | mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn); | ||
615 | kfree(xrcd); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
569 | static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) | 620 | static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) |
570 | { | 621 | { |
571 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); | 622 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); |
@@ -1093,6 +1144,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
1093 | ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; | 1144 | ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; |
1094 | ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; | 1145 | ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; |
1095 | 1146 | ||
1147 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) { | ||
1148 | ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd; | ||
1149 | ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd; | ||
1150 | ibdev->ib_dev.uverbs_cmd_mask |= | ||
1151 | (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) | | ||
1152 | (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD); | ||
1153 | } | ||
1154 | |||
1096 | spin_lock_init(&iboe->lock); | 1155 | spin_lock_init(&iboe->lock); |
1097 | 1156 | ||
1098 | if (init_node_data(ibdev)) | 1157 | if (init_node_data(ibdev)) |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index e4bf2cff8662..ce150b0e2cc8 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -56,6 +56,13 @@ struct mlx4_ib_pd { | |||
56 | u32 pdn; | 56 | u32 pdn; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | struct mlx4_ib_xrcd { | ||
60 | struct ib_xrcd ibxrcd; | ||
61 | u32 xrcdn; | ||
62 | struct ib_pd *pd; | ||
63 | struct ib_cq *cq; | ||
64 | }; | ||
65 | |||
59 | struct mlx4_ib_cq_buf { | 66 | struct mlx4_ib_cq_buf { |
60 | struct mlx4_buf buf; | 67 | struct mlx4_buf buf; |
61 | struct mlx4_mtt mtt; | 68 | struct mlx4_mtt mtt; |
@@ -211,6 +218,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd) | |||
211 | return container_of(ibpd, struct mlx4_ib_pd, ibpd); | 218 | return container_of(ibpd, struct mlx4_ib_pd, ibpd); |
212 | } | 219 | } |
213 | 220 | ||
221 | static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd) | ||
222 | { | ||
223 | return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd); | ||
224 | } | ||
225 | |||
214 | static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq) | 226 | static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq) |
215 | { | 227 | { |
216 | return container_of(ibcq, struct mlx4_ib_cq, ibcq); | 228 | return container_of(ibcq, struct mlx4_ib_cq, ibcq); |
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index 7eb8ba822e97..875838b8799c 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c | |||
@@ -204,6 +204,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
204 | #define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 | 204 | #define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 |
205 | #define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 | 205 | #define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 |
206 | #define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 | 206 | #define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 |
207 | #define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66 | ||
208 | #define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67 | ||
207 | #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 | 209 | #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 |
208 | #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 | 210 | #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 |
209 | #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 | 211 | #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 |
@@ -318,6 +320,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
318 | dev_cap->reserved_pds = field >> 4; | 320 | dev_cap->reserved_pds = field >> 4; |
319 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); | 321 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); |
320 | dev_cap->max_pds = 1 << (field & 0x3f); | 322 | dev_cap->max_pds = 1 << (field & 0x3f); |
323 | MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET); | ||
324 | dev_cap->reserved_xrcds = field >> 4; | ||
325 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); | ||
326 | dev_cap->max_xrcds = 1 << (field & 0x1f); | ||
321 | 327 | ||
322 | MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); | 328 | MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); |
323 | dev_cap->rdmarc_entry_sz = size; | 329 | dev_cap->rdmarc_entry_sz = size; |
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 1e8ecc3708e2..bf5ec2286528 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h | |||
@@ -93,6 +93,8 @@ struct mlx4_dev_cap { | |||
93 | int max_mcgs; | 93 | int max_mcgs; |
94 | int reserved_pds; | 94 | int reserved_pds; |
95 | int max_pds; | 95 | int max_pds; |
96 | int reserved_xrcds; | ||
97 | int max_xrcds; | ||
96 | int qpc_entry_sz; | 98 | int qpc_entry_sz; |
97 | int rdmarc_entry_sz; | 99 | int rdmarc_entry_sz; |
98 | int altc_entry_sz; | 100 | int altc_entry_sz; |
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index f0ee35df4dd7..660b691ede76 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
@@ -220,6 +220,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
220 | dev->caps.reserved_mrws = dev_cap->reserved_mrws; | 220 | dev->caps.reserved_mrws = dev_cap->reserved_mrws; |
221 | dev->caps.reserved_uars = dev_cap->reserved_uars; | 221 | dev->caps.reserved_uars = dev_cap->reserved_uars; |
222 | dev->caps.reserved_pds = dev_cap->reserved_pds; | 222 | dev->caps.reserved_pds = dev_cap->reserved_pds; |
223 | dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ? | ||
224 | dev_cap->reserved_xrcds : 0; | ||
225 | dev->caps.max_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ? | ||
226 | dev_cap->max_xrcds : 0; | ||
223 | dev->caps.mtt_entry_sz = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; | 227 | dev->caps.mtt_entry_sz = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; |
224 | dev->caps.max_msg_sz = dev_cap->max_msg_sz; | 228 | dev->caps.max_msg_sz = dev_cap->max_msg_sz; |
225 | dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); | 229 | dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); |
@@ -912,11 +916,18 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) | |||
912 | goto err_kar_unmap; | 916 | goto err_kar_unmap; |
913 | } | 917 | } |
914 | 918 | ||
919 | err = mlx4_init_xrcd_table(dev); | ||
920 | if (err) { | ||
921 | mlx4_err(dev, "Failed to initialize " | ||
922 | "reliable connection domain table, aborting.\n"); | ||
923 | goto err_pd_table_free; | ||
924 | } | ||
925 | |||
915 | err = mlx4_init_mr_table(dev); | 926 | err = mlx4_init_mr_table(dev); |
916 | if (err) { | 927 | if (err) { |
917 | mlx4_err(dev, "Failed to initialize " | 928 | mlx4_err(dev, "Failed to initialize " |
918 | "memory region table, aborting.\n"); | 929 | "memory region table, aborting.\n"); |
919 | goto err_pd_table_free; | 930 | goto err_xrcd_table_free; |
920 | } | 931 | } |
921 | 932 | ||
922 | err = mlx4_init_eq_table(dev); | 933 | err = mlx4_init_eq_table(dev); |
@@ -1033,6 +1044,9 @@ err_eq_table_free: | |||
1033 | err_mr_table_free: | 1044 | err_mr_table_free: |
1034 | mlx4_cleanup_mr_table(dev); | 1045 | mlx4_cleanup_mr_table(dev); |
1035 | 1046 | ||
1047 | err_xrcd_table_free: | ||
1048 | mlx4_cleanup_xrcd_table(dev); | ||
1049 | |||
1036 | err_pd_table_free: | 1050 | err_pd_table_free: |
1037 | mlx4_cleanup_pd_table(dev); | 1051 | mlx4_cleanup_pd_table(dev); |
1038 | 1052 | ||
@@ -1355,6 +1369,7 @@ err_port: | |||
1355 | mlx4_cmd_use_polling(dev); | 1369 | mlx4_cmd_use_polling(dev); |
1356 | mlx4_cleanup_eq_table(dev); | 1370 | mlx4_cleanup_eq_table(dev); |
1357 | mlx4_cleanup_mr_table(dev); | 1371 | mlx4_cleanup_mr_table(dev); |
1372 | mlx4_cleanup_xrcd_table(dev); | ||
1358 | mlx4_cleanup_pd_table(dev); | 1373 | mlx4_cleanup_pd_table(dev); |
1359 | mlx4_cleanup_uar_table(dev); | 1374 | mlx4_cleanup_uar_table(dev); |
1360 | 1375 | ||
@@ -1416,6 +1431,7 @@ static void mlx4_remove_one(struct pci_dev *pdev) | |||
1416 | mlx4_cmd_use_polling(dev); | 1431 | mlx4_cmd_use_polling(dev); |
1417 | mlx4_cleanup_eq_table(dev); | 1432 | mlx4_cleanup_eq_table(dev); |
1418 | mlx4_cleanup_mr_table(dev); | 1433 | mlx4_cleanup_mr_table(dev); |
1434 | mlx4_cleanup_xrcd_table(dev); | ||
1419 | mlx4_cleanup_pd_table(dev); | 1435 | mlx4_cleanup_pd_table(dev); |
1420 | 1436 | ||
1421 | iounmap(priv->kar); | 1437 | iounmap(priv->kar); |
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index a2fcd8402d37..fee2d05aa1dc 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
@@ -335,6 +335,7 @@ struct mlx4_priv { | |||
335 | struct mlx4_cmd cmd; | 335 | struct mlx4_cmd cmd; |
336 | 336 | ||
337 | struct mlx4_bitmap pd_bitmap; | 337 | struct mlx4_bitmap pd_bitmap; |
338 | struct mlx4_bitmap xrcd_bitmap; | ||
338 | struct mlx4_uar_table uar_table; | 339 | struct mlx4_uar_table uar_table; |
339 | struct mlx4_mr_table mr_table; | 340 | struct mlx4_mr_table mr_table; |
340 | struct mlx4_cq_table cq_table; | 341 | struct mlx4_cq_table cq_table; |
@@ -384,6 +385,7 @@ int mlx4_alloc_eq_table(struct mlx4_dev *dev); | |||
384 | void mlx4_free_eq_table(struct mlx4_dev *dev); | 385 | void mlx4_free_eq_table(struct mlx4_dev *dev); |
385 | 386 | ||
386 | int mlx4_init_pd_table(struct mlx4_dev *dev); | 387 | int mlx4_init_pd_table(struct mlx4_dev *dev); |
388 | int mlx4_init_xrcd_table(struct mlx4_dev *dev); | ||
387 | int mlx4_init_uar_table(struct mlx4_dev *dev); | 389 | int mlx4_init_uar_table(struct mlx4_dev *dev); |
388 | int mlx4_init_mr_table(struct mlx4_dev *dev); | 390 | int mlx4_init_mr_table(struct mlx4_dev *dev); |
389 | int mlx4_init_eq_table(struct mlx4_dev *dev); | 391 | int mlx4_init_eq_table(struct mlx4_dev *dev); |
@@ -393,6 +395,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev); | |||
393 | int mlx4_init_mcg_table(struct mlx4_dev *dev); | 395 | int mlx4_init_mcg_table(struct mlx4_dev *dev); |
394 | 396 | ||
395 | void mlx4_cleanup_pd_table(struct mlx4_dev *dev); | 397 | void mlx4_cleanup_pd_table(struct mlx4_dev *dev); |
398 | void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev); | ||
396 | void mlx4_cleanup_uar_table(struct mlx4_dev *dev); | 399 | void mlx4_cleanup_uar_table(struct mlx4_dev *dev); |
397 | void mlx4_cleanup_mr_table(struct mlx4_dev *dev); | 400 | void mlx4_cleanup_mr_table(struct mlx4_dev *dev); |
398 | void mlx4_cleanup_eq_table(struct mlx4_dev *dev); | 401 | void mlx4_cleanup_eq_table(struct mlx4_dev *dev); |
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c index 1286b886dcea..3736163e30e9 100644 --- a/drivers/net/mlx4/pd.c +++ b/drivers/net/mlx4/pd.c | |||
@@ -61,6 +61,24 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) | |||
61 | } | 61 | } |
62 | EXPORT_SYMBOL_GPL(mlx4_pd_free); | 62 | EXPORT_SYMBOL_GPL(mlx4_pd_free); |
63 | 63 | ||
64 | int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn) | ||
65 | { | ||
66 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
67 | |||
68 | *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap); | ||
69 | if (*xrcdn == -1) | ||
70 | return -ENOMEM; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc); | ||
75 | |||
76 | void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) | ||
77 | { | ||
78 | mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn); | ||
79 | } | ||
80 | EXPORT_SYMBOL_GPL(mlx4_xrcd_free); | ||
81 | |||
64 | int mlx4_init_pd_table(struct mlx4_dev *dev) | 82 | int mlx4_init_pd_table(struct mlx4_dev *dev) |
65 | { | 83 | { |
66 | struct mlx4_priv *priv = mlx4_priv(dev); | 84 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -74,6 +92,18 @@ void mlx4_cleanup_pd_table(struct mlx4_dev *dev) | |||
74 | mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); | 92 | mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); |
75 | } | 93 | } |
76 | 94 | ||
95 | int mlx4_init_xrcd_table(struct mlx4_dev *dev) | ||
96 | { | ||
97 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
98 | |||
99 | return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16), | ||
100 | (1 << 16) - 1, dev->caps.reserved_xrcds + 1, 0); | ||
101 | } | ||
102 | |||
103 | void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev) | ||
104 | { | ||
105 | mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap); | ||
106 | } | ||
77 | 107 | ||
78 | int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) | 108 | int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) |
79 | { | 109 | { |