diff options
| -rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 15 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx5/mr.c | 29 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx5/qp.c | 100 | ||||
| -rw-r--r-- | include/linux/mlx5/device.h | 13 |
4 files changed, 109 insertions, 48 deletions
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 29da55222070..53d19e6e69a4 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
| @@ -111,6 +111,8 @@ struct mlx5_ib_pd { | |||
| 111 | */ | 111 | */ |
| 112 | 112 | ||
| 113 | #define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START | 113 | #define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START |
| 114 | #define MLX5_IB_SEND_UMR_FAIL_IF_FREE (IB_SEND_RESERVED_START << 1) | ||
| 115 | #define MLX5_IB_SEND_UMR_UPDATE_MTT (IB_SEND_RESERVED_START << 2) | ||
| 114 | #define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1 | 116 | #define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1 |
| 115 | #define MLX5_IB_WR_UMR IB_WR_RESERVED1 | 117 | #define MLX5_IB_WR_UMR IB_WR_RESERVED1 |
| 116 | 118 | ||
| @@ -206,6 +208,19 @@ enum mlx5_ib_qp_flags { | |||
| 206 | MLX5_IB_QP_SIGNATURE_HANDLING = 1 << 1, | 208 | MLX5_IB_QP_SIGNATURE_HANDLING = 1 << 1, |
| 207 | }; | 209 | }; |
| 208 | 210 | ||
| 211 | struct mlx5_umr_wr { | ||
| 212 | union { | ||
| 213 | u64 virt_addr; | ||
| 214 | u64 offset; | ||
| 215 | } target; | ||
| 216 | struct ib_pd *pd; | ||
| 217 | unsigned int page_shift; | ||
| 218 | unsigned int npages; | ||
| 219 | u32 length; | ||
| 220 | int access_flags; | ||
| 221 | u32 mkey; | ||
| 222 | }; | ||
| 223 | |||
| 209 | struct mlx5_shared_mr_info { | 224 | struct mlx5_shared_mr_info { |
| 210 | int mr_id; | 225 | int mr_id; |
| 211 | struct ib_umem *umem; | 226 | struct ib_umem *umem; |
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 2ab081cdbca0..2de4f4448f8a 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/export.h> | 37 | #include <linux/export.h> |
| 38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
| 39 | #include <rdma/ib_umem.h> | 39 | #include <rdma/ib_umem.h> |
| 40 | #include <rdma/ib_verbs.h> | ||
| 40 | #include "mlx5_ib.h" | 41 | #include "mlx5_ib.h" |
| 41 | 42 | ||
| 42 | enum { | 43 | enum { |
| @@ -146,7 +147,7 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num) | |||
| 146 | mr->order = ent->order; | 147 | mr->order = ent->order; |
| 147 | mr->umred = 1; | 148 | mr->umred = 1; |
| 148 | mr->dev = dev; | 149 | mr->dev = dev; |
| 149 | in->seg.status = 1 << 6; | 150 | in->seg.status = MLX5_MKEY_STATUS_FREE; |
| 150 | in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2); | 151 | in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2); |
| 151 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | 152 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); |
| 152 | in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN; | 153 | in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN; |
| @@ -678,6 +679,7 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr, | |||
| 678 | { | 679 | { |
| 679 | struct mlx5_ib_dev *dev = to_mdev(pd->device); | 680 | struct mlx5_ib_dev *dev = to_mdev(pd->device); |
| 680 | struct ib_mr *mr = dev->umrc.mr; | 681 | struct ib_mr *mr = dev->umrc.mr; |
| 682 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; | ||
| 681 | 683 | ||
| 682 | sg->addr = dma; | 684 | sg->addr = dma; |
| 683 | sg->length = ALIGN(sizeof(u64) * n, 64); | 685 | sg->length = ALIGN(sizeof(u64) * n, 64); |
| @@ -692,21 +694,24 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr, | |||
| 692 | wr->num_sge = 0; | 694 | wr->num_sge = 0; |
| 693 | 695 | ||
| 694 | wr->opcode = MLX5_IB_WR_UMR; | 696 | wr->opcode = MLX5_IB_WR_UMR; |
| 695 | wr->wr.fast_reg.page_list_len = n; | 697 | |
| 696 | wr->wr.fast_reg.page_shift = page_shift; | 698 | umrwr->npages = n; |
| 697 | wr->wr.fast_reg.rkey = key; | 699 | umrwr->page_shift = page_shift; |
| 698 | wr->wr.fast_reg.iova_start = virt_addr; | 700 | umrwr->mkey = key; |
| 699 | wr->wr.fast_reg.length = len; | 701 | umrwr->target.virt_addr = virt_addr; |
| 700 | wr->wr.fast_reg.access_flags = access_flags; | 702 | umrwr->length = len; |
| 701 | wr->wr.fast_reg.page_list = (struct ib_fast_reg_page_list *)pd; | 703 | umrwr->access_flags = access_flags; |
| 704 | umrwr->pd = pd; | ||
| 702 | } | 705 | } |
| 703 | 706 | ||
| 704 | static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev, | 707 | static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev, |
| 705 | struct ib_send_wr *wr, u32 key) | 708 | struct ib_send_wr *wr, u32 key) |
| 706 | { | 709 | { |
| 707 | wr->send_flags = MLX5_IB_SEND_UMR_UNREG; | 710 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; |
| 711 | |||
| 712 | wr->send_flags = MLX5_IB_SEND_UMR_UNREG | MLX5_IB_SEND_UMR_FAIL_IF_FREE; | ||
| 708 | wr->opcode = MLX5_IB_WR_UMR; | 713 | wr->opcode = MLX5_IB_WR_UMR; |
| 709 | wr->wr.fast_reg.rkey = key; | 714 | umrwr->mkey = key; |
| 710 | } | 715 | } |
| 711 | 716 | ||
| 712 | void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context) | 717 | void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context) |
| @@ -1031,7 +1036,7 @@ struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd, | |||
| 1031 | goto err_free; | 1036 | goto err_free; |
| 1032 | } | 1037 | } |
| 1033 | 1038 | ||
| 1034 | in->seg.status = 1 << 6; /* free */ | 1039 | in->seg.status = MLX5_MKEY_STATUS_FREE; |
| 1035 | in->seg.xlt_oct_size = cpu_to_be32(ndescs); | 1040 | in->seg.xlt_oct_size = cpu_to_be32(ndescs); |
| 1036 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | 1041 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); |
| 1037 | in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); | 1042 | in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); |
| @@ -1146,7 +1151,7 @@ struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, | |||
| 1146 | goto err_free; | 1151 | goto err_free; |
| 1147 | } | 1152 | } |
| 1148 | 1153 | ||
| 1149 | in->seg.status = 1 << 6; /* free */ | 1154 | in->seg.status = MLX5_MKEY_STATUS_FREE; |
| 1150 | in->seg.xlt_oct_size = cpu_to_be32((max_page_list_len + 1) / 2); | 1155 | in->seg.xlt_oct_size = cpu_to_be32((max_page_list_len + 1) / 2); |
| 1151 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | 1156 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); |
| 1152 | in->seg.flags = MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT; | 1157 | in->seg.flags = MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT; |
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 1cae1c7132b4..36e2cfe1c2fe 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c | |||
| @@ -70,15 +70,6 @@ static const u32 mlx5_ib_opcode[] = { | |||
| 70 | [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, | 70 | [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | struct umr_wr { | ||
| 74 | u64 virt_addr; | ||
| 75 | struct ib_pd *pd; | ||
| 76 | unsigned int page_shift; | ||
| 77 | unsigned int npages; | ||
| 78 | u32 length; | ||
| 79 | int access_flags; | ||
| 80 | u32 mkey; | ||
| 81 | }; | ||
| 82 | 73 | ||
| 83 | static int is_qp0(enum ib_qp_type qp_type) | 74 | static int is_qp0(enum ib_qp_type qp_type) |
| 84 | { | 75 | { |
| @@ -1848,37 +1839,70 @@ static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | |||
| 1848 | umr->mkey_mask = frwr_mkey_mask(); | 1839 | umr->mkey_mask = frwr_mkey_mask(); |
| 1849 | } | 1840 | } |
| 1850 | 1841 | ||
| 1842 | static __be64 get_umr_reg_mr_mask(void) | ||
| 1843 | { | ||
| 1844 | u64 result; | ||
| 1845 | |||
| 1846 | result = MLX5_MKEY_MASK_LEN | | ||
| 1847 | MLX5_MKEY_MASK_PAGE_SIZE | | ||
| 1848 | MLX5_MKEY_MASK_START_ADDR | | ||
| 1849 | MLX5_MKEY_MASK_PD | | ||
| 1850 | MLX5_MKEY_MASK_LR | | ||
| 1851 | MLX5_MKEY_MASK_LW | | ||
| 1852 | MLX5_MKEY_MASK_KEY | | ||
| 1853 | MLX5_MKEY_MASK_RR | | ||
| 1854 | MLX5_MKEY_MASK_RW | | ||
| 1855 | MLX5_MKEY_MASK_A | | ||
| 1856 | MLX5_MKEY_MASK_FREE; | ||
| 1857 | |||
| 1858 | return cpu_to_be64(result); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | static __be64 get_umr_unreg_mr_mask(void) | ||
| 1862 | { | ||
| 1863 | u64 result; | ||
| 1864 | |||
| 1865 | result = MLX5_MKEY_MASK_FREE; | ||
| 1866 | |||
| 1867 | return cpu_to_be64(result); | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | static __be64 get_umr_update_mtt_mask(void) | ||
| 1871 | { | ||
| 1872 | u64 result; | ||
| 1873 | |||
| 1874 | result = MLX5_MKEY_MASK_FREE; | ||
| 1875 | |||
| 1876 | return cpu_to_be64(result); | ||
| 1877 | } | ||
| 1878 | |||
| 1851 | static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | 1879 | static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, |
| 1852 | struct ib_send_wr *wr) | 1880 | struct ib_send_wr *wr) |
| 1853 | { | 1881 | { |
| 1854 | struct umr_wr *umrwr = (struct umr_wr *)&wr->wr.fast_reg; | 1882 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; |
| 1855 | u64 mask; | ||
| 1856 | 1883 | ||
| 1857 | memset(umr, 0, sizeof(*umr)); | 1884 | memset(umr, 0, sizeof(*umr)); |
| 1858 | 1885 | ||
| 1886 | if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE) | ||
| 1887 | umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */ | ||
| 1888 | else | ||
| 1889 | umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */ | ||
| 1890 | |||
| 1859 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) { | 1891 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) { |
| 1860 | umr->flags = 1 << 5; /* fail if not free */ | ||
| 1861 | umr->klm_octowords = get_klm_octo(umrwr->npages); | 1892 | umr->klm_octowords = get_klm_octo(umrwr->npages); |
| 1862 | mask = MLX5_MKEY_MASK_LEN | | 1893 | if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT) { |
| 1863 | MLX5_MKEY_MASK_PAGE_SIZE | | 1894 | umr->mkey_mask = get_umr_update_mtt_mask(); |
| 1864 | MLX5_MKEY_MASK_START_ADDR | | 1895 | umr->bsf_octowords = get_klm_octo(umrwr->target.offset); |
| 1865 | MLX5_MKEY_MASK_PD | | 1896 | umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; |
| 1866 | MLX5_MKEY_MASK_LR | | 1897 | } else { |
| 1867 | MLX5_MKEY_MASK_LW | | 1898 | umr->mkey_mask = get_umr_reg_mr_mask(); |
| 1868 | MLX5_MKEY_MASK_KEY | | 1899 | } |
| 1869 | MLX5_MKEY_MASK_RR | | ||
| 1870 | MLX5_MKEY_MASK_RW | | ||
| 1871 | MLX5_MKEY_MASK_A | | ||
| 1872 | MLX5_MKEY_MASK_FREE; | ||
| 1873 | umr->mkey_mask = cpu_to_be64(mask); | ||
| 1874 | } else { | 1900 | } else { |
| 1875 | umr->flags = 2 << 5; /* fail if free */ | 1901 | umr->mkey_mask = get_umr_unreg_mr_mask(); |
| 1876 | mask = MLX5_MKEY_MASK_FREE; | ||
| 1877 | umr->mkey_mask = cpu_to_be64(mask); | ||
| 1878 | } | 1902 | } |
| 1879 | 1903 | ||
| 1880 | if (!wr->num_sge) | 1904 | if (!wr->num_sge) |
| 1881 | umr->flags |= (1 << 7); /* inline */ | 1905 | umr->flags |= MLX5_UMR_INLINE; |
| 1882 | } | 1906 | } |
| 1883 | 1907 | ||
| 1884 | static u8 get_umr_flags(int acc) | 1908 | static u8 get_umr_flags(int acc) |
| @@ -1895,7 +1919,7 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, | |||
| 1895 | { | 1919 | { |
| 1896 | memset(seg, 0, sizeof(*seg)); | 1920 | memset(seg, 0, sizeof(*seg)); |
| 1897 | if (li) { | 1921 | if (li) { |
| 1898 | seg->status = 1 << 6; | 1922 | seg->status = MLX5_MKEY_STATUS_FREE; |
| 1899 | return; | 1923 | return; |
| 1900 | } | 1924 | } |
| 1901 | 1925 | ||
| @@ -1912,19 +1936,23 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, | |||
| 1912 | 1936 | ||
| 1913 | static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr) | 1937 | static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr) |
| 1914 | { | 1938 | { |
| 1939 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; | ||
| 1940 | |||
| 1915 | memset(seg, 0, sizeof(*seg)); | 1941 | memset(seg, 0, sizeof(*seg)); |
| 1916 | if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) { | 1942 | if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) { |
| 1917 | seg->status = 1 << 6; | 1943 | seg->status = MLX5_MKEY_STATUS_FREE; |
| 1918 | return; | 1944 | return; |
| 1919 | } | 1945 | } |
| 1920 | 1946 | ||
| 1921 | seg->flags = convert_access(wr->wr.fast_reg.access_flags); | 1947 | seg->flags = convert_access(umrwr->access_flags); |
| 1922 | seg->flags_pd = cpu_to_be32(to_mpd((struct ib_pd *)wr->wr.fast_reg.page_list)->pdn); | 1948 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) { |
| 1923 | seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start); | 1949 | seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn); |
| 1924 | seg->len = cpu_to_be64(wr->wr.fast_reg.length); | 1950 | seg->start_addr = cpu_to_be64(umrwr->target.virt_addr); |
| 1925 | seg->log2_page_size = wr->wr.fast_reg.page_shift; | 1951 | } |
| 1952 | seg->len = cpu_to_be64(umrwr->length); | ||
| 1953 | seg->log2_page_size = umrwr->page_shift; | ||
| 1926 | seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 | | 1954 | seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 | |
| 1927 | mlx5_mkey_variant(wr->wr.fast_reg.rkey)); | 1955 | mlx5_mkey_variant(umrwr->mkey)); |
| 1928 | } | 1956 | } |
| 1929 | 1957 | ||
| 1930 | static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg, | 1958 | static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg, |
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index ea4f1c46f761..fa07bfda0e15 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h | |||
| @@ -180,6 +180,15 @@ enum { | |||
| 180 | MLX5_MKEY_MASK_FREE = 1ull << 29, | 180 | MLX5_MKEY_MASK_FREE = 1ull << 29, |
| 181 | }; | 181 | }; |
| 182 | 182 | ||
| 183 | enum { | ||
| 184 | MLX5_UMR_TRANSLATION_OFFSET_EN = (1 << 4), | ||
| 185 | |||
| 186 | MLX5_UMR_CHECK_NOT_FREE = (1 << 5), | ||
| 187 | MLX5_UMR_CHECK_FREE = (2 << 5), | ||
| 188 | |||
| 189 | MLX5_UMR_INLINE = (1 << 7), | ||
| 190 | }; | ||
| 191 | |||
| 183 | enum mlx5_event { | 192 | enum mlx5_event { |
| 184 | MLX5_EVENT_TYPE_COMP = 0x0, | 193 | MLX5_EVENT_TYPE_COMP = 0x0, |
| 185 | 194 | ||
| @@ -776,6 +785,10 @@ struct mlx5_query_eq_mbox_out { | |||
| 776 | struct mlx5_eq_context ctx; | 785 | struct mlx5_eq_context ctx; |
| 777 | }; | 786 | }; |
| 778 | 787 | ||
| 788 | enum { | ||
| 789 | MLX5_MKEY_STATUS_FREE = 1 << 6, | ||
| 790 | }; | ||
| 791 | |||
| 779 | struct mlx5_mkey_seg { | 792 | struct mlx5_mkey_seg { |
| 780 | /* This is a two bit field occupying bits 31-30. | 793 | /* This is a two bit field occupying bits 31-30. |
| 781 | * bit 31 is always 0, | 794 | * bit 31 is always 0, |
