RDMA/mlx5: Split the WR setup out of mlx5_ib_update_xlt()
[linux-2.6-microblaze.git] / drivers / infiniband / hw / mlx5 / mlx5_ib.h
index 5287fc8..d92afbd 100644 (file)
@@ -384,6 +384,22 @@ struct mlx5_ib_dct {
        u32                     *in;
 };
 
+struct mlx5_ib_gsi_qp {
+       struct ib_qp *rx_qp;
+       u8 port_num;
+       struct ib_qp_cap cap;
+       struct ib_cq *cq;
+       struct mlx5_ib_gsi_wr *outstanding_wrs;
+       u32 outstanding_pi, outstanding_ci;
+       int num_qps;
+       /* Protects access to the tx_qps. Post send operations synchronize
+        * with tx_qp creation in setup_qp(). Also protects the
+        * outstanding_wrs array and indices.
+        */
+       spinlock_t lock;
+       struct ib_qp **tx_qps;
+};
+
 struct mlx5_ib_qp {
        struct ib_qp            ibqp;
        union {
@@ -391,6 +407,7 @@ struct mlx5_ib_qp {
                struct mlx5_ib_raw_packet_qp raw_packet_qp;
                struct mlx5_ib_rss_qp rss_qp;
                struct mlx5_ib_dct dct;
+               struct mlx5_ib_gsi_qp gsi;
        };
        struct mlx5_frag_buf    buf;
 
@@ -580,13 +597,12 @@ struct mlx5_ib_mr {
        int                     max_descs;
        int                     desc_size;
        int                     access_mode;
+       unsigned int            page_shift;
        struct mlx5_core_mkey   mmkey;
        struct ib_umem         *umem;
        struct mlx5_shared_mr_info      *smr_info;
        struct list_head        list;
-       unsigned int            order;
        struct mlx5_cache_ent  *cache_ent;
-       int                     npages;
        struct mlx5_ib_dev     *dev;
        u32 out[MLX5_ST_SZ_DW(create_mkey_out)];
        struct mlx5_core_sig_ctx    *sig;
@@ -693,10 +709,7 @@ struct mlx5_mr_cache {
        unsigned long           last_add;
 };
 
-struct mlx5_ib_gsi_qp;
-
 struct mlx5_ib_port_resources {
-       struct mlx5_ib_resources *devr;
        struct mlx5_ib_gsi_qp *gsi;
        struct work_struct pkey_change_work;
 };
@@ -1119,13 +1132,16 @@ void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
 int mlx5_ib_create_ah(struct ib_ah *ah, struct rdma_ah_init_attr *init_attr,
                      struct ib_udata *udata);
 int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
-void mlx5_ib_destroy_ah(struct ib_ah *ah, u32 flags);
+static inline int mlx5_ib_destroy_ah(struct ib_ah *ah, u32 flags)
+{
+       return 0;
+}
 int mlx5_ib_create_srq(struct ib_srq *srq, struct ib_srq_init_attr *init_attr,
                       struct ib_udata *udata);
 int mlx5_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                       enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
 int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr);
-void mlx5_ib_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
+int mlx5_ib_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
 int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
                          const struct ib_recv_wr **bad_wr);
 int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
@@ -1148,7 +1164,7 @@ int mlx5_ib_read_wqe_srq(struct mlx5_ib_srq *srq, int wqe_index, void *buffer,
                         size_t buflen, size_t *bc);
 int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                      struct ib_udata *udata);
-void mlx5_ib_destroy_cq(struct ib_cq *cq, struct ib_udata *udata);
+int mlx5_ib_destroy_cq(struct ib_cq *cq, struct ib_udata *udata);
 int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
 int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
 int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
@@ -1163,8 +1179,7 @@ int mlx5_ib_advise_mr(struct ib_pd *pd,
                      struct ib_sge *sg_list,
                      u32 num_sge,
                      struct uverbs_attr_bundle *attrs);
-struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
-                              struct ib_udata *udata);
+int mlx5_ib_alloc_mw(struct ib_mw *mw, struct ib_udata *udata);
 int mlx5_ib_dealloc_mw(struct ib_mw *mw);
 int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
                       int page_shift, int flags);
@@ -1193,7 +1208,7 @@ int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
                        const struct ib_mad *in, struct ib_mad *out,
                        size_t *out_mad_size, u16 *out_mad_pkey_index);
 int mlx5_ib_alloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata);
-void mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata);
+int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata);
 int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset);
 int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port);
 int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
@@ -1216,20 +1231,19 @@ int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
                       struct ib_port_attr *props);
 void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
                        unsigned long max_page_shift,
-                       int *count, int *shift,
-                       int *ncont, int *order);
+                       int *shift);
 void __mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem,
                            int page_shift, size_t offset, size_t num_pages,
                            __be64 *pas, int access_flags);
-void mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem,
-                         int page_shift, __be64 *pas, int access_flags);
+void mlx5_ib_populate_pas(struct ib_umem *umem, size_t page_size, __be64 *pas,
+                         u64 access_flags);
 void mlx5_ib_copy_pas(u64 *old, u64 *new, int step, int num);
 int mlx5_ib_get_cqe_size(struct ib_cq *ibcq);
 int mlx5_mr_cache_init(struct mlx5_ib_dev *dev);
 int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev);
 
 struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
-                                      unsigned int entry);
+                                      unsigned int entry, int access_flags);
 void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
 int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr);
 
@@ -1238,12 +1252,12 @@ int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
 struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
                                struct ib_wq_init_attr *init_attr,
                                struct ib_udata *udata);
-void mlx5_ib_destroy_wq(struct ib_wq *wq, struct ib_udata *udata);
+int mlx5_ib_destroy_wq(struct ib_wq *wq, struct ib_udata *udata);
 int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
                      u32 wq_attr_mask, struct ib_udata *udata);
-struct ib_rwq_ind_table *mlx5_ib_create_rwq_ind_table(struct ib_device *device,
-                                                     struct ib_rwq_ind_table_init_attr *init_attr,
-                                                     struct ib_udata *udata);
+int mlx5_ib_create_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_table,
+                                struct ib_rwq_ind_table_init_attr *init_attr,
+                                struct ib_udata *udata);
 int mlx5_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *wq_ind_table);
 struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
                               struct ib_ucontext *context,
@@ -1267,6 +1281,7 @@ void mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries,
 int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
                               enum ib_uverbs_advise_mr_advice advice,
                               u32 flags, struct ib_sge *sg_list, u32 num_sge);
+int mlx5_ib_init_odp_mr(struct mlx5_ib_mr *mr, bool enable);
 #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */
 static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 {
@@ -1288,6 +1303,10 @@ mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
 {
        return -EOPNOTSUPP;
 }
+static inline int mlx5_ib_init_odp_mr(struct mlx5_ib_mr *mr, bool enable)
+{
+       return -EOPNOTSUPP;
+}
 #endif /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */
 
 extern const struct mmu_interval_notifier_ops mlx5_mn_ops;
@@ -1318,9 +1337,9 @@ void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev *dev, u8 port_num);
 void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u8 port_num);
 
 /* GSI QP helper functions */
-struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
-                                   struct ib_qp_init_attr *init_attr);
-int mlx5_ib_gsi_destroy_qp(struct ib_qp *qp);
+int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
+                      struct ib_qp_init_attr *attr);
+int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp);
 int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
                          int attr_mask);
 int mlx5_ib_gsi_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
@@ -1358,7 +1377,7 @@ static inline void init_query_mad(struct ib_smp *mad)
 
 static inline int is_qp1(enum ib_qp_type qp_type)
 {
-       return qp_type == MLX5_IB_QPT_HW_GSI;
+       return qp_type == MLX5_IB_QPT_HW_GSI || qp_type == IB_QPT_GSI;
 }
 
 #define MLX5_MAX_UMR_SHIFT 16
@@ -1435,32 +1454,60 @@ static inline int get_num_static_uars(struct mlx5_ib_dev *dev,
        return get_uars_per_sys_page(dev, bfregi->lib_uar_4k) * bfregi->num_static_sys_pages;
 }
 
-unsigned long mlx5_ib_get_xlt_emergency_page(void);
-void mlx5_ib_put_xlt_emergency_page(void);
+extern void *xlt_emergency_page;
 
 int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
                        struct mlx5_bfreg_info *bfregi, u32 bfregn,
                        bool dyn_bfreg);
 
-static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev,
-                                      bool do_modify_atomic, int access_flags)
+static inline bool mlx5_ib_can_load_pas_with_umr(struct mlx5_ib_dev *dev,
+                                                size_t length)
 {
+       /*
+        * umr_check_mkey_mask() rejects MLX5_MKEY_MASK_PAGE_SIZE which is
+        * always set if MLX5_IB_SEND_UMR_UPDATE_TRANSLATION (aka
+        * MLX5_IB_UPD_XLT_ADDR and MLX5_IB_UPD_XLT_ENABLE) is set. Thus, a mkey
+        * can never be enabled without this capability. Simplify this weird
+        * quirky hardware by just saying it can't use PAS lists with UMR at
+        * all.
+        */
        if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
                return false;
 
-       if (do_modify_atomic &&
+       /*
+        * length is the size of the MR in bytes when mlx5_ib_update_xlt() is
+        * used.
+        */
+       if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
+           length >= MLX5_MAX_UMR_PAGES * PAGE_SIZE)
+               return false;
+       return true;
+}
+
+/*
+ * true if an existing MR can be reconfigured to new access_flags using UMR.
+ * Older HW cannot use UMR to update certain elements of the MKC. See
+ * umr_check_mkey_mask(), get_umr_update_access_mask() and umr_check_mkey_mask()
+ */
+static inline bool mlx5_ib_can_reconfig_with_umr(struct mlx5_ib_dev *dev,
+                                                unsigned int current_access_flags,
+                                                unsigned int target_access_flags)
+{
+       unsigned int diffs = current_access_flags ^ target_access_flags;
+
+       if ((diffs & IB_ACCESS_REMOTE_ATOMIC) &&
            MLX5_CAP_GEN(dev->mdev, atomic) &&
            MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
                return false;
 
-       if (access_flags & IB_ACCESS_RELAXED_ORDERING &&
+       if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
            MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write) &&
            !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
                return false;
 
-       if (access_flags & IB_ACCESS_RELAXED_ORDERING &&
-            MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) &&
-            !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
+       if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
+           MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) &&
+           !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
                return false;
 
        return true;