diff options
Diffstat (limited to 'include/rdma')
-rw-r--r-- | include/rdma/ib_addr.h | 6 | ||||
-rw-r--r-- | include/rdma/ib_hdrs.h | 6 | ||||
-rw-r--r-- | include/rdma/ib_umem_odp.h | 21 | ||||
-rw-r--r-- | include/rdma/ib_verbs.h | 90 | ||||
-rw-r--r-- | include/rdma/rdma_vt.h | 21 | ||||
-rw-r--r-- | include/rdma/rdmavt_mr.h | 60 | ||||
-rw-r--r-- | include/rdma/rdmavt_qp.h | 46 |
7 files changed, 229 insertions, 21 deletions
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 1beab5532035..4b34c51f859e 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -160,8 +160,7 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr) static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev) { - return dev->priv_flags & IFF_802_1Q_VLAN ? - vlan_dev_vlan_id(dev) : 0xffff; + return is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 0xffff; } static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid) @@ -326,8 +325,7 @@ static inline u16 rdma_get_vlan_id(union ib_gid *dgid) static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev) { - return dev->priv_flags & IFF_802_1Q_VLAN ? - vlan_dev_real_dev(dev) : NULL; + return is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : NULL; } #endif /* IB_ADDR_H */ diff --git a/include/rdma/ib_hdrs.h b/include/rdma/ib_hdrs.h index 408439fe911e..c755325f0831 100644 --- a/include/rdma/ib_hdrs.h +++ b/include/rdma/ib_hdrs.h @@ -75,6 +75,12 @@ #define IB_GRH_FLOW_SHIFT 0 #define IB_GRH_NEXT_HDR 0x1B +#define IB_AETH_CREDIT_SHIFT 24 +#define IB_AETH_CREDIT_MASK 0x1F +#define IB_AETH_CREDIT_INVAL 0x1F +#define IB_AETH_NAK_SHIFT 29 +#define IB_MSN_MASK 0xFFFFFF + struct ib_reth { __be64 vaddr; /* potentially unaligned */ __be32 rkey; diff --git a/include/rdma/ib_umem_odp.h b/include/rdma/ib_umem_odp.h index 3da0b167041b..542cd8b3414c 100644 --- a/include/rdma/ib_umem_odp.h +++ b/include/rdma/ib_umem_odp.h @@ -79,11 +79,15 @@ struct ib_umem_odp { struct completion notifier_completion; int dying; + struct work_struct work; }; #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem); +struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, + unsigned long addr, + size_t size); void ib_umem_odp_release(struct ib_umem *umem); @@ -117,10 +121,12 @@ typedef int (*umem_call_back)(struct ib_umem *item, u64 start, u64 end, int rbt_ib_umem_for_each_in_range(struct rb_root *root, u64 start, u64 end, umem_call_back cb, void *cookie); -struct umem_odp_node *rbt_ib_umem_iter_first(struct rb_root *root, - u64 start, u64 last); -struct umem_odp_node *rbt_ib_umem_iter_next(struct umem_odp_node *node, - u64 start, u64 last); +/* + * Find first region intersecting with address range. + * Return NULL if not found + */ +struct ib_umem_odp *rbt_ib_umem_lookup(struct rb_root *root, + u64 addr, u64 length); static inline int ib_umem_mmu_notifier_retry(struct ib_umem *item, unsigned long mmu_seq) @@ -153,6 +159,13 @@ static inline int ib_umem_odp_get(struct ib_ucontext *context, return -EINVAL; } +static inline struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, + unsigned long addr, + size_t size) +{ + return ERR_PTR(-EINVAL); +} + static inline void ib_umem_odp_release(struct ib_umem *umem) {} #endif /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index f199c42b9a86..d84849c5dc05 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -207,6 +207,7 @@ enum ib_device_cap_flags { IB_DEVICE_MEM_WINDOW_TYPE_2A = (1 << 23), IB_DEVICE_MEM_WINDOW_TYPE_2B = (1 << 24), IB_DEVICE_RC_IP_CSUM = (1 << 25), + /* Deprecated. Please use IB_RAW_PACKET_CAP_IP_CSUM. */ IB_DEVICE_RAW_IP_CSUM = (1 << 26), /* * Devices should set IB_DEVICE_CROSS_CHANNEL if they @@ -220,6 +221,7 @@ enum ib_device_cap_flags { IB_DEVICE_ON_DEMAND_PAGING = (1ULL << 31), IB_DEVICE_SG_GAPS_REG = (1ULL << 32), IB_DEVICE_VIRTUAL_FUNCTION = (1ULL << 33), + /* Deprecated. Please use IB_RAW_PACKET_CAP_SCATTER_FCS. */ IB_DEVICE_RAW_SCATTER_FCS = (1ULL << 34), }; @@ -241,7 +243,8 @@ enum ib_atomic_cap { }; enum ib_odp_general_cap_bits { - IB_ODP_SUPPORT = 1 << 0, + IB_ODP_SUPPORT = 1 << 0, + IB_ODP_SUPPORT_IMPLICIT = 1 << 1, }; enum ib_odp_transport_cap_bits { @@ -330,6 +333,7 @@ struct ib_device_attr { uint64_t hca_core_clock; /* in KHZ */ struct ib_rss_caps rss_caps; u32 max_wq_type_rq; + u32 raw_packet_caps; /* Use ib_raw_packet_caps enum */ }; enum ib_mtu { @@ -352,6 +356,20 @@ static inline int ib_mtu_enum_to_int(enum ib_mtu mtu) } } +static inline enum ib_mtu ib_mtu_int_to_enum(int mtu) +{ + if (mtu >= 4096) + return IB_MTU_4096; + else if (mtu >= 2048) + return IB_MTU_2048; + else if (mtu >= 1024) + return IB_MTU_1024; + else if (mtu >= 512) + return IB_MTU_512; + else + return IB_MTU_256; +} + enum ib_port_state { IB_PORT_NOP = 0, IB_PORT_DOWN = 1, @@ -485,6 +503,8 @@ static inline struct rdma_hw_stats *rdma_alloc_hw_stats_struct( #define RDMA_CORE_CAP_PROT_ROCE 0x00200000 #define RDMA_CORE_CAP_PROT_IWARP 0x00400000 #define RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP 0x00800000 +#define RDMA_CORE_CAP_PROT_RAW_PACKET 0x01000000 +#define RDMA_CORE_CAP_PROT_USNIC 0x02000000 #define RDMA_CORE_PORT_IBA_IB (RDMA_CORE_CAP_PROT_IB \ | RDMA_CORE_CAP_IB_MAD \ @@ -508,6 +528,10 @@ static inline struct rdma_hw_stats *rdma_alloc_hw_stats_struct( #define RDMA_CORE_PORT_INTEL_OPA (RDMA_CORE_PORT_IBA_IB \ | RDMA_CORE_CAP_OPA_MAD) +#define RDMA_CORE_PORT_RAW_PACKET (RDMA_CORE_CAP_PROT_RAW_PACKET) + +#define RDMA_CORE_PORT_USNIC (RDMA_CORE_CAP_PROT_USNIC) + struct ib_port_attr { u64 subnet_prefix; enum ib_port_state state; @@ -1005,6 +1029,7 @@ enum ib_qp_create_flags { IB_QP_CREATE_SIGNATURE_EN = 1 << 6, IB_QP_CREATE_USE_GFP_NOIO = 1 << 7, IB_QP_CREATE_SCATTER_FCS = 1 << 8, + IB_QP_CREATE_CVLAN_STRIPPING = 1 << 9, /* reserve bits 26-31 for low level drivers' internal use */ IB_QP_CREATE_RESERVED_START = 1 << 26, IB_QP_CREATE_RESERVED_END = 1 << 31, @@ -1456,6 +1481,18 @@ struct ib_srq { } ext; }; +enum ib_raw_packet_caps { + /* Strip cvlan from incoming packet and report it in the matching work + * completion is supported. + */ + IB_RAW_PACKET_CAP_CVLAN_STRIPPING = (1 << 0), + /* Scatter FCS field of an incoming packet to host memory is supported. + */ + IB_RAW_PACKET_CAP_SCATTER_FCS = (1 << 1), + /* Checksum offloads are supported (for both send and receive). */ + IB_RAW_PACKET_CAP_IP_CSUM = (1 << 2), +}; + enum ib_wq_type { IB_WQT_RQ }; @@ -1479,6 +1516,11 @@ struct ib_wq { atomic_t usecnt; }; +enum ib_wq_flags { + IB_WQ_FLAGS_CVLAN_STRIPPING = 1 << 0, + IB_WQ_FLAGS_SCATTER_FCS = 1 << 1, +}; + struct ib_wq_init_attr { void *wq_context; enum ib_wq_type wq_type; @@ -1486,16 +1528,20 @@ struct ib_wq_init_attr { u32 max_sge; struct ib_cq *cq; void (*event_handler)(struct ib_event *, void *); + u32 create_flags; /* Use enum ib_wq_flags */ }; enum ib_wq_attr_mask { - IB_WQ_STATE = 1 << 0, - IB_WQ_CUR_STATE = 1 << 1, + IB_WQ_STATE = 1 << 0, + IB_WQ_CUR_STATE = 1 << 1, + IB_WQ_FLAGS = 1 << 2, }; struct ib_wq_attr { enum ib_wq_state wq_state; enum ib_wq_state curr_wq_state; + u32 flags; /* Use enum ib_wq_flags */ + u32 flags_mask; /* Use enum ib_wq_flags */ }; struct ib_rwq_ind_table { @@ -1604,6 +1650,8 @@ enum ib_flow_spec_type { IB_FLOW_SPEC_UDP = 0x41, IB_FLOW_SPEC_VXLAN_TUNNEL = 0x50, IB_FLOW_SPEC_INNER = 0x100, + /* Actions */ + IB_FLOW_SPEC_ACTION_TAG = 0x1000, }; #define IB_FLOW_SPEC_LAYER_MASK 0xF0 #define IB_FLOW_SPEC_SUPPORT_LAYERS 8 @@ -1726,6 +1774,12 @@ struct ib_flow_spec_tunnel { struct ib_flow_tunnel_filter mask; }; +struct ib_flow_spec_action_tag { + enum ib_flow_spec_type type; + u16 size; + u32 tag_id; +}; + union ib_flow_spec { struct { u32 type; @@ -1737,6 +1791,7 @@ union ib_flow_spec { struct ib_flow_spec_tcp_udp tcp_udp; struct ib_flow_spec_ipv6 ipv6; struct ib_flow_spec_tunnel tunnel; + struct ib_flow_spec_action_tag flow_tag; }; struct ib_flow_attr { @@ -1775,13 +1830,17 @@ enum ib_mad_result { #define IB_DEVICE_NAME_MAX 64 +struct ib_port_cache { + struct ib_pkey_cache *pkey; + struct ib_gid_table *gid; + u8 lmc; + enum ib_port_state port_state; +}; + struct ib_cache { rwlock_t lock; struct ib_event_handler event_handler; - struct ib_pkey_cache **pkey_cache; - struct ib_gid_table **gid_cache; - u8 *lmc_cache; - enum ib_port_state *port_state_cache; + struct ib_port_cache *ports; }; struct iw_cm_verbs; @@ -2226,6 +2285,13 @@ static inline u8 rdma_end_port(const struct ib_device *device) return rdma_cap_ib_switch(device) ? 0 : device->phys_port_cnt; } +static inline int rdma_is_port_valid(const struct ib_device *device, + unsigned int port) +{ + return (port >= rdma_start_port(device) && + port <= rdma_end_port(device)); +} + static inline bool rdma_protocol_ib(const struct ib_device *device, u8 port_num) { return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IB; @@ -2258,6 +2324,16 @@ static inline bool rdma_ib_or_roce(const struct ib_device *device, u8 port_num) rdma_protocol_roce(device, port_num); } +static inline bool rdma_protocol_raw_packet(const struct ib_device *device, u8 port_num) +{ + return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_RAW_PACKET; +} + +static inline bool rdma_protocol_usnic(const struct ib_device *device, u8 port_num) +{ + return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_USNIC; +} + /** * rdma_cap_ib_mad - Check if the port of a device supports Infiniband * Management Datagrams. diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index 861e23eaebda..8fc1ca7b6f23 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h @@ -164,7 +164,7 @@ struct rvt_driver_params { /* Protection domain */ struct rvt_pd { struct ib_pd ibpd; - int user; /* non-zero if created from user space */ + bool user; }; /* Address handle */ @@ -335,6 +335,8 @@ struct rvt_driver_provided { /* Notify driver a mad agent has been removed */ void (*notify_free_mad_agent)(struct rvt_dev_info *rdi, int port_idx); + /* Notify driver to restart rc */ + void (*notify_restart_rc)(struct rvt_qp *qp, u32 psn, int wait); }; struct rvt_dev_info { @@ -483,6 +485,23 @@ static inline struct rvt_qp *rvt_lookup_qpn(struct rvt_dev_info *rdi, return qp; } +/** + * rvt_mod_retry_timer - mod a retry timer + * @qp - the QP + * Modify a potentially already running retry timer + */ +static inline void rvt_mod_retry_timer(struct rvt_qp *qp) +{ + struct ib_qp *ibqp = &qp->ibqp; + struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); + + lockdep_assert_held(&qp->s_lock); + qp->s_flags |= RVT_S_TIMER; + /* 4.096 usec. * (1 << qp->timeout) */ + mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies + + rdi->busy_jiffies); +} + struct rvt_dev_info *rvt_alloc_device(size_t size, int nports); void rvt_dealloc_device(struct rvt_dev_info *rdi); int rvt_register_device(struct rvt_dev_info *rvd); diff --git a/include/rdma/rdmavt_mr.h b/include/rdma/rdmavt_mr.h index de59de28b6a2..f418bd5571a5 100644 --- a/include/rdma/rdmavt_mr.h +++ b/include/rdma/rdmavt_mr.h @@ -52,6 +52,7 @@ * For Memory Regions. This stuff should probably be moved into rdmavt/mr.h once * drivers no longer need access to the MR directly. */ +#include <linux/percpu-refcount.h> /* * A segment is a linear region of low physical memory. @@ -79,11 +80,11 @@ struct rvt_mregion { int access_flags; u32 max_segs; /* number of rvt_segs in all the arrays */ u32 mapsz; /* size of the map array */ + atomic_t lkey_invalid; /* true if current lkey is invalid */ u8 page_shift; /* 0 - non unform/non powerof2 sizes */ u8 lkey_published; /* in global table */ - atomic_t lkey_invalid; /* true if current lkey is invalid */ + struct percpu_ref refcount; struct completion comp; /* complete when refcount goes to zero */ - atomic_t refcount; struct rvt_segarray *map[0]; /* the segments */ }; @@ -123,13 +124,12 @@ struct rvt_sge_state { static inline void rvt_put_mr(struct rvt_mregion *mr) { - if (unlikely(atomic_dec_and_test(&mr->refcount))) - complete(&mr->comp); + percpu_ref_put(&mr->refcount); } static inline void rvt_get_mr(struct rvt_mregion *mr) { - atomic_inc(&mr->refcount); + percpu_ref_get(&mr->refcount); } static inline void rvt_put_ss(struct rvt_sge_state *ss) @@ -141,4 +141,54 @@ static inline void rvt_put_ss(struct rvt_sge_state *ss) } } +static inline u32 rvt_get_sge_length(struct rvt_sge *sge, u32 length) +{ + u32 len = sge->length; + + if (len > length) + len = length; + if (len > sge->sge_length) + len = sge->sge_length; + + return len; +} + +static inline void rvt_update_sge(struct rvt_sge_state *ss, u32 length, + bool release) +{ + struct rvt_sge *sge = &ss->sge; + + sge->vaddr += length; + sge->length -= length; + sge->sge_length -= length; + if (sge->sge_length == 0) { + if (release) + rvt_put_mr(sge->mr); + if (--ss->num_sge) + *sge = *ss->sg_list++; + } else if (sge->length == 0 && sge->mr->lkey) { + if (++sge->n >= RVT_SEGSZ) { + if (++sge->m >= sge->mr->mapsz) + return; + sge->n = 0; + } + sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr; + sge->length = sge->mr->map[sge->m]->segs[sge->n].length; + } +} + +static inline void rvt_skip_sge(struct rvt_sge_state *ss, u32 length, + bool release) +{ + struct rvt_sge *sge = &ss->sge; + + while (length) { + u32 len = rvt_get_sge_length(sge, length); + + WARN_ON_ONCE(len == 0); + rvt_update_sge(ss, len, release); + length -= len; + } +} + #endif /* DEF_RDMAVT_INCMRH */ diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h index f3dbd157ae5c..f3816396c76a 100644 --- a/include/rdma/rdmavt_qp.h +++ b/include/rdma/rdmavt_qp.h @@ -144,6 +144,8 @@ #define RVT_FLUSH_RECV 0x40 #define RVT_PROCESS_OR_FLUSH_SEND \ (RVT_PROCESS_SEND_OK | RVT_FLUSH_SEND) +#define RVT_SEND_OR_FLUSH_OR_RECV_OK \ + (RVT_PROCESS_SEND_OK | RVT_FLUSH_SEND | RVT_PROCESS_RECV_OK) /* * Internal send flags @@ -370,6 +372,7 @@ struct rvt_qp { struct rvt_sge_state s_ack_rdma_sge; struct timer_list s_timer; + struct hrtimer s_rnr_timer; atomic_t local_ops_pending; /* number of fast_reg/local_inv reqs */ @@ -467,6 +470,15 @@ static inline struct rvt_rwqe *rvt_get_rwqe_ptr(struct rvt_rq *rq, unsigned n) } /** + * rvt_is_user_qp - return if this is user mode QP + * @qp - the target QP + */ +static inline bool rvt_is_user_qp(struct rvt_qp *qp) +{ + return !!qp->pid; +} + +/** * rvt_get_qp - get a QP reference * @qp - the QP to hold */ @@ -582,6 +594,32 @@ static inline void rvt_qp_swqe_complete( } } +/* + * Compare the lower 24 bits of the msn values. + * Returns an integer <, ==, or > than zero. + */ +static inline int rvt_cmp_msn(u32 a, u32 b) +{ + return (((int)a) - ((int)b)) << 8; +} + +/** + * rvt_compute_aeth - compute the AETH (syndrome + MSN) + * @qp: the queue pair to compute the AETH for + * + * Returns the AETH. + */ +__be32 rvt_compute_aeth(struct rvt_qp *qp); + +/** + * rvt_get_credit - flush the send work queue of a QP + * @qp: the qp who's send work queue to flush + * @aeth: the Acknowledge Extended Transport Header + * + * The QP s_lock should be held. + */ +void rvt_get_credit(struct rvt_qp *qp, u32 aeth); + /** * @qp - the qp pair * @len - the length @@ -607,6 +645,14 @@ static inline u32 rvt_div_mtu(struct rvt_qp *qp, u32 len) extern const int ib_rvt_state_ops[]; struct rvt_dev_info; +void rvt_comm_est(struct rvt_qp *qp); int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err); +void rvt_rc_error(struct rvt_qp *qp, enum ib_wc_status err); +unsigned long rvt_rnr_tbl_to_usec(u32 index); +enum hrtimer_restart rvt_rc_rnr_retry(struct hrtimer *t); +void rvt_add_rnr_timer(struct rvt_qp *qp, u32 aeth); +void rvt_del_timers_sync(struct rvt_qp *qp); +void rvt_stop_rc_timers(struct rvt_qp *qp); +void rvt_add_retry_timer(struct rvt_qp *qp); #endif /* DEF_RDMAVT_INCQP_H */ |