// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright(c) 2016 - 2020 Intel Corporation. */ #include <linux/hash.h> #include <linux/bitops.h> #include <linux/lockdep.h> #include <linux/vmalloc.h> #include <linux/slab.h> #include <rdma/ib_verbs.h> #include <rdma/ib_hdrs.h> #include <rdma/opa_addr.h> #include <rdma/uverbs_ioctl.h> #include "qp.h" #include "vt.h" #include "trace.h" #define RVT_RWQ_COUNT_THRESHOLD … static void rvt_rc_timeout(struct timer_list *t); static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, enum ib_qp_type type); /* * Convert the AETH RNR timeout code into the number of microseconds. */ static const u32 ib_rvt_rnr_table[32] = …; /* * Note that it is OK to post send work requests in the SQE and ERR * states; rvt_do_send() will process them and generate error * completions as per IB 1.2 C10-96. */ const int ib_rvt_state_ops[IB_QPS_ERR + 1] = …; EXPORT_SYMBOL(…); /* platform specific: return the last level cache (llc) size, in KiB */ static int rvt_wss_llc_size(void) { … } /* platform specific: cacheless copy */ static void cacheless_memcpy(void *dst, void *src, size_t n) { … } void rvt_wss_exit(struct rvt_dev_info *rdi) { … } /* * rvt_wss_init - Init wss data structures * * Return: 0 on success */ int rvt_wss_init(struct rvt_dev_info *rdi) { … } /* * Advance the clean counter. When the clean period has expired, * clean an entry. * * This is implemented in atomics to avoid locking. Because multiple * variables are involved, it can be racy which can lead to slightly * inaccurate information. Since this is only a heuristic, this is * OK. Any innaccuracies will clean themselves out as the counter * advances. That said, it is unlikely the entry clean operation will * race - the next possible racer will not start until the next clean * period. * * The clean counter is implemented as a decrement to zero. When zero * is reached an entry is cleaned. */ static void wss_advance_clean_counter(struct rvt_wss *wss) { … } /* * Insert the given address into the working set array. */ static void wss_insert(struct rvt_wss *wss, void *address) { … } /* * Is the working set larger than the threshold? */ static inline bool wss_exceeds_threshold(struct rvt_wss *wss) { … } static void get_map_page(struct rvt_qpn_table *qpt, struct rvt_qpn_map *map) { … } /** * init_qpn_table - initialize the QP number table for a device * @rdi: rvt dev struct * @qpt: the QPN table */ static int init_qpn_table(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt) { … } /** * free_qpn_table - free the QP number table for a device * @qpt: the QPN table */ static void free_qpn_table(struct rvt_qpn_table *qpt) { … } /** * rvt_driver_qp_init - Init driver qp resources * @rdi: rvt dev strucutre * * Return: 0 on success */ int rvt_driver_qp_init(struct rvt_dev_info *rdi) { … } /** * rvt_free_qp_cb - callback function to reset a qp * @qp: the qp to reset * @v: a 64-bit value * * This function resets the qp and removes it from the * qp hash table. */ static void rvt_free_qp_cb(struct rvt_qp *qp, u64 v) { … } /** * rvt_free_all_qps - check for QPs still in use * @rdi: rvt device info structure * * There should not be any QPs still in use. * Free memory for table. * Return the number of QPs still in use. */ static unsigned rvt_free_all_qps(struct rvt_dev_info *rdi) { … } /** * rvt_qp_exit - clean up qps on device exit * @rdi: rvt dev structure * * Check for qp leaks and free resources. */ void rvt_qp_exit(struct rvt_dev_info *rdi) { … } static inline unsigned mk_qpn(struct rvt_qpn_table *qpt, struct rvt_qpn_map *map, unsigned off) { … } /** * alloc_qpn - Allocate the next available qpn or zero/one for QP type * IB_QPT_SMI/IB_QPT_GSI * @rdi: rvt device info structure * @qpt: queue pair number table pointer * @type: the QP type * @port_num: IB port number, 1 based, comes from core * @exclude_prefix: prefix of special queue pair number being allocated * * Return: The queue pair number */ static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, enum ib_qp_type type, u8 port_num, u8 exclude_prefix) { … } /** * rvt_clear_mr_refs - Drop help mr refs * @qp: rvt qp data structure * @clr_sends: If shoudl clear send side or not */ static void rvt_clear_mr_refs(struct rvt_qp *qp, int clr_sends) { … } /** * rvt_swqe_has_lkey - return true if lkey is used by swqe * @wqe: the send wqe * @lkey: the lkey * * Test the swqe for using lkey */ static bool rvt_swqe_has_lkey(struct rvt_swqe *wqe, u32 lkey) { … } /** * rvt_qp_sends_has_lkey - return true is qp sends use lkey * @qp: the rvt_qp * @lkey: the lkey */ static bool rvt_qp_sends_has_lkey(struct rvt_qp *qp, u32 lkey) { … } /** * rvt_qp_acks_has_lkey - return true if acks have lkey * @qp: the qp * @lkey: the lkey */ static bool rvt_qp_acks_has_lkey(struct rvt_qp *qp, u32 lkey) { … } /** * rvt_qp_mr_clean - clean up remote ops for lkey * @qp: the qp * @lkey: the lkey that is being de-registered * * This routine checks if the lkey is being used by * the qp. * * If so, the qp is put into an error state to elminate * any references from the qp. */ void rvt_qp_mr_clean(struct rvt_qp *qp, u32 lkey) { … } /** * rvt_remove_qp - remove qp form table * @rdi: rvt dev struct * @qp: qp to remove * * Remove the QP from the table so it can't be found asynchronously by * the receive routine. */ static void rvt_remove_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp) { … } /** * rvt_alloc_rq - allocate memory for user or kernel buffer * @rq: receive queue data structure * @size: number of request queue entries * @node: The NUMA node * @udata: True if user data is available or not false * * Return: If memory allocation failed, return -ENONEM * This function is used by both shared receive * queues and non-shared receive queues to allocate * memory. */ int rvt_alloc_rq(struct rvt_rq *rq, u32 size, int node, struct ib_udata *udata) { … } /** * rvt_init_qp - initialize the QP state to the reset state * @rdi: rvt dev struct * @qp: the QP to init or reinit * @type: the QP type * * This function is called from both rvt_create_qp() and * rvt_reset_qp(). The difference is that the reset * patch the necessary locks to protect against concurent * access. */ static void rvt_init_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, enum ib_qp_type type) { … } /** * _rvt_reset_qp - initialize the QP state to the reset state * @rdi: rvt dev struct * @qp: the QP to reset * @type: the QP type * * r_lock, s_hlock, and s_lock are required to be held by the caller */ static void _rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, enum ib_qp_type type) __must_hold(&qp->s_lock) __must_hold(&qp->s_hlock) __must_hold(&qp->r_lock) { … } /** * rvt_reset_qp - initialize the QP state to the reset state * @rdi: the device info * @qp: the QP to reset * @type: the QP type * * This is the wrapper function to acquire the r_lock, s_hlock, and s_lock * before calling _rvt_reset_qp(). */ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, enum ib_qp_type type) { … } /** * rvt_free_qpn - Free a qpn from the bit map * @qpt: QP table * @qpn: queue pair number to free */ static void rvt_free_qpn(struct rvt_qpn_table *qpt, u32 qpn) { … } /** * get_allowed_ops - Given a QP type return the appropriate allowed OP * @type: valid, supported, QP type */ static u8 get_allowed_ops(enum ib_qp_type type) { … } /** * free_ud_wq_attr - Clean up AH attribute cache for UD QPs * @qp: Valid QP with allowed_ops set * * The rvt_swqe data structure being used is a union, so this is * only valid for UD QPs. */ static void free_ud_wq_attr(struct rvt_qp *qp) { … } /** * alloc_ud_wq_attr - AH attribute cache for UD QPs * @qp: Valid QP with allowed_ops set * @node: Numa node for allocation * * The rvt_swqe data structure being used is a union, so this is * only valid for UD QPs. */ static int alloc_ud_wq_attr(struct rvt_qp *qp, int node) { … } /** * rvt_create_qp - create a queue pair for a device * @ibqp: the queue pair * @init_attr: the attributes of the queue pair * @udata: user data for libibverbs.so * * Queue pair creation is mostly an rvt issue. However, drivers have their own * unique idea of what queue pair numbers mean. For instance there is a reserved * range for PSM. * * Return: 0 on success, otherwise returns an errno. * * Called by the ib_create_qp() core verbs function. */ int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr, struct ib_udata *udata) { … } /** * rvt_error_qp - put a QP into the error state * @qp: the QP to put into the error state * @err: the receive completion error to signal if a RWQE is active * * Flushes both send and receive work queues. * * Return: true if last WQE event should be generated. * The QP r_lock and s_lock should be held and interrupts disabled. * If we are already in error state, just return. */ int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err) { … } EXPORT_SYMBOL(…); /* * Put the QP into the hash table. * The hash table holds a reference to the QP. */ static void rvt_insert_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp) { … } /** * rvt_modify_qp - modify the attributes of a queue pair * @ibqp: the queue pair who's attributes we're modifying * @attr: the new attributes * @attr_mask: the mask of attributes to modify * @udata: user data for libibverbs.so * * Return: 0 on success, otherwise returns an errno. */ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { … } /** * rvt_destroy_qp - destroy a queue pair * @ibqp: the queue pair to destroy * @udata: unused by the driver * * Note that this can be called while the QP is actively sending or * receiving! * * Return: 0 on success. */ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) { … } /** * rvt_query_qp - query an ipbq * @ibqp: IB qp to query * @attr: attr struct to fill in * @attr_mask: attr mask ignored * @init_attr: struct to fill in * * Return: always 0 */ int rvt_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_qp_init_attr *init_attr) { … } /** * rvt_post_recv - post a receive on a QP * @ibqp: the QP to post the receive on * @wr: the WR to post * @bad_wr: the first bad WR is put here * * This may be called from interrupt context. * * Return: 0 on success otherwise errno */ int rvt_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr, const struct ib_recv_wr **bad_wr) { … } /** * rvt_qp_valid_operation - validate post send wr request * @qp: the qp * @post_parms: the post send table for the driver * @wr: the work request * * The routine validates the operation based on the * validation table an returns the length of the operation * which can extend beyond the ib_send_bw. Operation * dependent flags key atomic operation validation. * * There is an exception for UD qps that validates the pd and * overrides the length to include the additional UD specific * length. * * Returns a negative error or the length of the work request * for building the swqe. */ static inline int rvt_qp_valid_operation( struct rvt_qp *qp, const struct rvt_operation_params *post_parms, const struct ib_send_wr *wr) { … } /** * rvt_qp_is_avail - determine queue capacity * @qp: the qp * @rdi: the rdmavt device * @reserved_op: is reserved operation * * This assumes the s_hlock is held but the s_last * qp variable is uncontrolled. * * For non reserved operations, the qp->s_avail * may be changed. * * The return value is zero or a -ENOMEM. */ static inline int rvt_qp_is_avail( struct rvt_qp *qp, struct rvt_dev_info *rdi, bool reserved_op) { … } /** * rvt_post_one_wr - post one RC, UC, or UD send work request * @qp: the QP to post on * @wr: the work request to send * @call_send: kick the send engine into gear */ static int rvt_post_one_wr(struct rvt_qp *qp, const struct ib_send_wr *wr, bool *call_send) { … } /** * rvt_post_send - post a send on a QP * @ibqp: the QP to post the send on * @wr: the list of work requests to post * @bad_wr: the first bad WR is put here * * This may be called from interrupt context. * * Return: 0 on success else errno */ int rvt_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, const struct ib_send_wr **bad_wr) { … } /** * rvt_post_srq_recv - post a receive on a shared receive queue * @ibsrq: the SRQ to post the receive on * @wr: the list of work requests to post * @bad_wr: A pointer to the first WR to cause a problem is put here * * This may be called from interrupt context. * * Return: 0 on success else errno */ int rvt_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr, const struct ib_recv_wr **bad_wr) { … } /* * rvt used the internal kernel struct as part of its ABI, for now make sure * the kernel struct does not change layout. FIXME: rvt should never cast the * user struct to a kernel struct. */ static struct ib_sge *rvt_cast_sge(struct rvt_wqe_sge *sge) { … } /* * Validate a RWQE and fill in the SGE state. * Return 1 if OK. */ static int init_sge(struct rvt_qp *qp, struct rvt_rwqe *wqe) { … } /** * get_rvt_head - get head indices of the circular buffer * @rq: data structure for request queue entry * @ip: the QP * * Return - head index value */ static inline u32 get_rvt_head(struct rvt_rq *rq, void *ip) { … } /** * rvt_get_rwqe - copy the next RWQE into the QP's RWQE * @qp: the QP * @wr_id_only: update qp->r_wr_id only, not qp->r_sge * * Return -1 if there is a local error, 0 if no RWQE is available, * otherwise return 1. * * Can be called from interrupt level. */ int rvt_get_rwqe(struct rvt_qp *qp, bool wr_id_only) { … } EXPORT_SYMBOL(…); /** * rvt_comm_est - handle trap with QP established * @qp: the QP */ void rvt_comm_est(struct rvt_qp *qp) { … } EXPORT_SYMBOL(…); void rvt_rc_error(struct rvt_qp *qp, enum ib_wc_status err) { … } EXPORT_SYMBOL(…); /* * rvt_rnr_tbl_to_usec - return index into ib_rvt_rnr_table * @index - the index * return usec from an index into ib_rvt_rnr_table */ unsigned long rvt_rnr_tbl_to_usec(u32 index) { … } EXPORT_SYMBOL(…); static inline unsigned long rvt_aeth_to_usec(u32 aeth) { … } /* * rvt_add_retry_timer_ext - add/start a retry timer * @qp - the QP * @shift - timeout shift to wait for multiple packets * add a retry timer on the QP */ void rvt_add_retry_timer_ext(struct rvt_qp *qp, u8 shift) { … } EXPORT_SYMBOL(…); /** * rvt_add_rnr_timer - add/start an rnr timer on the QP * @qp: the QP * @aeth: aeth of RNR timeout, simulated aeth for loopback */ void rvt_add_rnr_timer(struct rvt_qp *qp, u32 aeth) { … } EXPORT_SYMBOL(…); /** * rvt_stop_rc_timers - stop all timers * @qp: the QP * stop any pending timers */ void rvt_stop_rc_timers(struct rvt_qp *qp) { … } EXPORT_SYMBOL(…); /** * rvt_stop_rnr_timer - stop an rnr timer * @qp: the QP * * stop an rnr timer and return if the timer * had been pending. */ static void rvt_stop_rnr_timer(struct rvt_qp *qp) { … } /** * rvt_del_timers_sync - wait for any timeout routines to exit * @qp: the QP */ void rvt_del_timers_sync(struct rvt_qp *qp) { … } EXPORT_SYMBOL(…); /* * This is called from s_timer for missing responses. */ static void rvt_rc_timeout(struct timer_list *t) { … } /* * This is called from s_timer for RNR timeouts. */ enum hrtimer_restart rvt_rc_rnr_retry(struct hrtimer *t) { … } EXPORT_SYMBOL(…); /** * rvt_qp_iter_init - initial for QP iteration * @rdi: rvt devinfo * @v: u64 value * @cb: user-defined callback * * This returns an iterator suitable for iterating QPs * in the system. * * The @cb is a user-defined callback and @v is a 64-bit * value passed to and relevant for processing in the * @cb. An example use case would be to alter QP processing * based on criteria not part of the rvt_qp. * * Use cases that require memory allocation to succeed * must preallocate appropriately. * * Return: a pointer to an rvt_qp_iter or NULL */ struct rvt_qp_iter *rvt_qp_iter_init(struct rvt_dev_info *rdi, u64 v, void (*cb)(struct rvt_qp *qp, u64 v)) { … } EXPORT_SYMBOL(…); /** * rvt_qp_iter_next - return the next QP in iter * @iter: the iterator * * Fine grained QP iterator suitable for use * with debugfs seq_file mechanisms. * * Updates iter->qp with the current QP when the return * value is 0. * * Return: 0 - iter->qp is valid 1 - no more QPs */ int rvt_qp_iter_next(struct rvt_qp_iter *iter) __must_hold(RCU) { … } EXPORT_SYMBOL(…); /** * rvt_qp_iter - iterate all QPs * @rdi: rvt devinfo * @v: a 64-bit value * @cb: a callback * * This provides a way for iterating all QPs. * * The @cb is a user-defined callback and @v is a 64-bit * value passed to and relevant for processing in the * cb. An example use case would be to alter QP processing * based on criteria not part of the rvt_qp. * * The code has an internal iterator to simplify * non seq_file use cases. */ void rvt_qp_iter(struct rvt_dev_info *rdi, u64 v, void (*cb)(struct rvt_qp *qp, u64 v)) { … } EXPORT_SYMBOL(…); /* * This should be called with s_lock and r_lock held. */ void rvt_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe, enum ib_wc_status status) { … } EXPORT_SYMBOL(…); /** * rvt_copy_sge - copy data to SGE memory * @qp: associated QP * @ss: the SGE state * @data: the data to copy * @length: the length of the data * @release: boolean to release MR * @copy_last: do a separate copy of the last 8 bytes */ void rvt_copy_sge(struct rvt_qp *qp, struct rvt_sge_state *ss, void *data, u32 length, bool release, bool copy_last) { … } EXPORT_SYMBOL(…); static enum ib_wc_status loopback_qp_drop(struct rvt_ibport *rvp, struct rvt_qp *sqp) { … } /** * rvt_ruc_loopback - handle UC and RC loopback requests * @sqp: the sending QP * * This is called from rvt_do_send() to forward a WQE addressed to the same HFI * Note that although we are single threaded due to the send engine, we still * have to protect against post_send(). We don't have to worry about * receive interrupts since this is a connected protocol and all packets * will pass through here. */ void rvt_ruc_loopback(struct rvt_qp *sqp) { … } EXPORT_SYMBOL(…);