| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ |
|---|
| 2 | +/* |
|---|
| 3 | + * Copyright(c) 2016 - 2019 Intel Corporation. |
|---|
| 4 | + */ |
|---|
| 5 | + |
|---|
| 1 | 6 | #ifndef DEF_RDMA_VT_H |
|---|
| 2 | 7 | #define DEF_RDMA_VT_H |
|---|
| 3 | | - |
|---|
| 4 | | -/* |
|---|
| 5 | | - * Copyright(c) 2016 - 2018 Intel Corporation. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This file is provided under a dual BSD/GPLv2 license. When using or |
|---|
| 8 | | - * redistributing this file, you may do so under either license. |
|---|
| 9 | | - * |
|---|
| 10 | | - * GPL LICENSE SUMMARY |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of version 2 of the GNU General Public License as |
|---|
| 14 | | - * published by the Free Software Foundation. |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 17 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 19 | | - * General Public License for more details. |
|---|
| 20 | | - * |
|---|
| 21 | | - * BSD LICENSE |
|---|
| 22 | | - * |
|---|
| 23 | | - * Redistribution and use in source and binary forms, with or without |
|---|
| 24 | | - * modification, are permitted provided that the following conditions |
|---|
| 25 | | - * are met: |
|---|
| 26 | | - * |
|---|
| 27 | | - * - Redistributions of source code must retain the above copyright |
|---|
| 28 | | - * notice, this list of conditions and the following disclaimer. |
|---|
| 29 | | - * - Redistributions in binary form must reproduce the above copyright |
|---|
| 30 | | - * notice, this list of conditions and the following disclaimer in |
|---|
| 31 | | - * the documentation and/or other materials provided with the |
|---|
| 32 | | - * distribution. |
|---|
| 33 | | - * - Neither the name of Intel Corporation nor the names of its |
|---|
| 34 | | - * contributors may be used to endorse or promote products derived |
|---|
| 35 | | - * from this software without specific prior written permission. |
|---|
| 36 | | - * |
|---|
| 37 | | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|---|
| 38 | | - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|---|
| 39 | | - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|---|
| 40 | | - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|---|
| 41 | | - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|---|
| 42 | | - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|---|
| 43 | | - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|---|
| 44 | | - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|---|
| 45 | | - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|---|
| 46 | | - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|---|
| 47 | | - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 48 | | - * |
|---|
| 49 | | - */ |
|---|
| 50 | 8 | |
|---|
| 51 | 9 | /* |
|---|
| 52 | 10 | * Structure that low level drivers will populate in order to register with the |
|---|
| .. | .. |
|---|
| 59 | 17 | #include <rdma/ib_verbs.h> |
|---|
| 60 | 18 | #include <rdma/ib_mad.h> |
|---|
| 61 | 19 | #include <rdma/rdmavt_mr.h> |
|---|
| 62 | | -#include <rdma/rdmavt_qp.h> |
|---|
| 63 | 20 | |
|---|
| 64 | 21 | #define RVT_MAX_PKEY_VALUES 16 |
|---|
| 65 | 22 | |
|---|
| .. | .. |
|---|
| 72 | 29 | struct list_head list; |
|---|
| 73 | 30 | }; |
|---|
| 74 | 31 | |
|---|
| 32 | +struct rvt_qp; |
|---|
| 33 | +struct rvt_qpn_table; |
|---|
| 75 | 34 | struct rvt_ibport { |
|---|
| 76 | 35 | struct rvt_qp __rcu *qp[2]; |
|---|
| 77 | 36 | struct ib_mad_agent *send_agent; /* agent for SMI (traps) */ |
|---|
| .. | .. |
|---|
| 115 | 74 | u64 n_unaligned; |
|---|
| 116 | 75 | u64 n_rc_dupreq; |
|---|
| 117 | 76 | u64 n_rc_seqnak; |
|---|
| 77 | + u64 n_rc_crwaits; |
|---|
| 118 | 78 | u16 pkey_violations; |
|---|
| 119 | 79 | u16 qkey_violations; |
|---|
| 120 | 80 | u16 mkey_violations; |
|---|
| .. | .. |
|---|
| 149 | 109 | |
|---|
| 150 | 110 | #define RVT_CQN_MAX 16 /* maximum length of cq name */ |
|---|
| 151 | 111 | |
|---|
| 112 | +#define RVT_SGE_COPY_MEMCPY 0 |
|---|
| 113 | +#define RVT_SGE_COPY_CACHELESS 1 |
|---|
| 114 | +#define RVT_SGE_COPY_ADAPTIVE 2 |
|---|
| 115 | + |
|---|
| 152 | 116 | /* |
|---|
| 153 | 117 | * Things that are driver specific, module parameters in hfi1 and qib |
|---|
| 154 | 118 | */ |
|---|
| .. | .. |
|---|
| 161 | 125 | */ |
|---|
| 162 | 126 | unsigned int lkey_table_size; |
|---|
| 163 | 127 | unsigned int qp_table_size; |
|---|
| 128 | + unsigned int sge_copy_mode; |
|---|
| 129 | + unsigned int wss_threshold; |
|---|
| 130 | + unsigned int wss_clean_period; |
|---|
| 164 | 131 | int qpn_start; |
|---|
| 165 | 132 | int qpn_inc; |
|---|
| 166 | 133 | int qpn_res_start; |
|---|
| .. | .. |
|---|
| 175 | 142 | u32 max_mad_size; |
|---|
| 176 | 143 | u8 qos_shift; |
|---|
| 177 | 144 | u8 max_rdma_atomic; |
|---|
| 145 | + u8 extra_rdma_atomic; |
|---|
| 178 | 146 | u8 reserved_operations; |
|---|
| 147 | +}; |
|---|
| 148 | + |
|---|
| 149 | +/* User context */ |
|---|
| 150 | +struct rvt_ucontext { |
|---|
| 151 | + struct ib_ucontext ibucontext; |
|---|
| 179 | 152 | }; |
|---|
| 180 | 153 | |
|---|
| 181 | 154 | /* Protection domain */ |
|---|
| .. | .. |
|---|
| 188 | 161 | struct rvt_ah { |
|---|
| 189 | 162 | struct ib_ah ibah; |
|---|
| 190 | 163 | struct rdma_ah_attr attr; |
|---|
| 191 | | - atomic_t refcount; |
|---|
| 192 | 164 | u8 vl; |
|---|
| 193 | 165 | u8 log_pmtu; |
|---|
| 166 | +}; |
|---|
| 167 | + |
|---|
| 168 | +/* |
|---|
| 169 | + * This structure is used by rvt_mmap() to validate an offset |
|---|
| 170 | + * when an mmap() request is made. The vm_area_struct then uses |
|---|
| 171 | + * this as its vm_private_data. |
|---|
| 172 | + */ |
|---|
| 173 | +struct rvt_mmap_info { |
|---|
| 174 | + struct list_head pending_mmaps; |
|---|
| 175 | + struct ib_ucontext *context; |
|---|
| 176 | + void *obj; |
|---|
| 177 | + __u64 offset; |
|---|
| 178 | + struct kref ref; |
|---|
| 179 | + u32 size; |
|---|
| 180 | +}; |
|---|
| 181 | + |
|---|
| 182 | +/* memory working set size */ |
|---|
| 183 | +struct rvt_wss { |
|---|
| 184 | + unsigned long *entries; |
|---|
| 185 | + atomic_t total_count; |
|---|
| 186 | + atomic_t clean_counter; |
|---|
| 187 | + atomic_t clean_entry; |
|---|
| 188 | + |
|---|
| 189 | + int threshold; |
|---|
| 190 | + int num_entries; |
|---|
| 191 | + long pages_mask; |
|---|
| 192 | + unsigned int clean_period; |
|---|
| 194 | 193 | }; |
|---|
| 195 | 194 | |
|---|
| 196 | 195 | struct rvt_dev_info; |
|---|
| .. | .. |
|---|
| 211 | 210 | * version requires the s_lock not to be held. The other assumes the |
|---|
| 212 | 211 | * s_lock is held. |
|---|
| 213 | 212 | */ |
|---|
| 214 | | - void (*schedule_send)(struct rvt_qp *qp); |
|---|
| 215 | | - void (*schedule_send_no_lock)(struct rvt_qp *qp); |
|---|
| 213 | + bool (*schedule_send)(struct rvt_qp *qp); |
|---|
| 214 | + bool (*schedule_send_no_lock)(struct rvt_qp *qp); |
|---|
| 216 | 215 | |
|---|
| 217 | | - /* Driver specific work request checking */ |
|---|
| 218 | | - int (*check_send_wqe)(struct rvt_qp *qp, struct rvt_swqe *wqe); |
|---|
| 216 | + /* |
|---|
| 217 | + * Driver specific work request setup and checking. |
|---|
| 218 | + * This function is allowed to perform any setup, checks, or |
|---|
| 219 | + * adjustments required to the SWQE in order to be usable by |
|---|
| 220 | + * underlying protocols. This includes private data structure |
|---|
| 221 | + * allocations. |
|---|
| 222 | + */ |
|---|
| 223 | + int (*setup_wqe)(struct rvt_qp *qp, struct rvt_swqe *wqe, |
|---|
| 224 | + bool *call_send); |
|---|
| 219 | 225 | |
|---|
| 220 | 226 | /* |
|---|
| 221 | 227 | * Sometimes rdmavt needs to kick the driver's send progress. That is |
|---|
| 222 | 228 | * done by this call back. |
|---|
| 223 | 229 | */ |
|---|
| 224 | 230 | void (*do_send)(struct rvt_qp *qp); |
|---|
| 225 | | - |
|---|
| 226 | | - /* Passed to ib core registration. Callback to create syfs files */ |
|---|
| 227 | | - int (*port_callback)(struct ib_device *, u8, struct kobject *); |
|---|
| 228 | 231 | |
|---|
| 229 | 232 | /* |
|---|
| 230 | 233 | * Returns a pointer to the undelying hardware's PCI device. This is |
|---|
| .. | .. |
|---|
| 240 | 243 | * pointer. |
|---|
| 241 | 244 | */ |
|---|
| 242 | 245 | void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp); |
|---|
| 246 | + |
|---|
| 247 | + /* |
|---|
| 248 | + * Init a struture allocated with qp_priv_alloc(). This should be |
|---|
| 249 | + * called after all qp fields have been initialized in rdmavt. |
|---|
| 250 | + */ |
|---|
| 251 | + int (*qp_priv_init)(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
|---|
| 252 | + struct ib_qp_init_attr *init_attr); |
|---|
| 243 | 253 | |
|---|
| 244 | 254 | /* |
|---|
| 245 | 255 | * Free the driver's private qp structure. |
|---|
| .. | .. |
|---|
| 371 | 381 | /* post send table */ |
|---|
| 372 | 382 | const struct rvt_operation_params *post_parms; |
|---|
| 373 | 383 | |
|---|
| 384 | + /* opcode translation table */ |
|---|
| 385 | + const enum ib_wc_opcode *wc_opcode; |
|---|
| 386 | + |
|---|
| 374 | 387 | /* Driver specific helper functions */ |
|---|
| 375 | 388 | struct rvt_driver_provided driver_f; |
|---|
| 376 | 389 | |
|---|
| .. | .. |
|---|
| 411 | 424 | u32 n_mcast_grps_allocated; /* number of mcast groups allocated */ |
|---|
| 412 | 425 | spinlock_t n_mcast_grps_lock; |
|---|
| 413 | 426 | |
|---|
| 427 | + /* Memory Working Set Size */ |
|---|
| 428 | + struct rvt_wss *wss; |
|---|
| 414 | 429 | }; |
|---|
| 415 | 430 | |
|---|
| 416 | 431 | /** |
|---|
| .. | .. |
|---|
| 423 | 438 | const char *fmt, const char *name, |
|---|
| 424 | 439 | const int unit) |
|---|
| 425 | 440 | { |
|---|
| 426 | | - snprintf(rdi->ibdev.name, sizeof(rdi->ibdev.name), fmt, name, unit); |
|---|
| 441 | + /* |
|---|
| 442 | + * FIXME: rvt and its users want to touch the ibdev before |
|---|
| 443 | + * registration and have things like the name work. We don't have the |
|---|
| 444 | + * infrastructure in the core to support this directly today, hack it |
|---|
| 445 | + * to work by setting the name manually here. |
|---|
| 446 | + */ |
|---|
| 447 | + dev_set_name(&rdi->ibdev.dev, fmt, name, unit); |
|---|
| 448 | + strlcpy(rdi->ibdev.name, dev_name(&rdi->ibdev.dev), IB_DEVICE_NAME_MAX); |
|---|
| 427 | 449 | } |
|---|
| 428 | 450 | |
|---|
| 429 | 451 | /** |
|---|
| .. | .. |
|---|
| 434 | 456 | */ |
|---|
| 435 | 457 | static inline const char *rvt_get_ibdev_name(const struct rvt_dev_info *rdi) |
|---|
| 436 | 458 | { |
|---|
| 437 | | - return rdi->ibdev.name; |
|---|
| 459 | + return dev_name(&rdi->ibdev.dev); |
|---|
| 438 | 460 | } |
|---|
| 439 | 461 | |
|---|
| 440 | 462 | static inline struct rvt_pd *ibpd_to_rvtpd(struct ib_pd *ibpd) |
|---|
| .. | .. |
|---|
| 452 | 474 | return container_of(ibdev, struct rvt_dev_info, ibdev); |
|---|
| 453 | 475 | } |
|---|
| 454 | 476 | |
|---|
| 455 | | -static inline struct rvt_srq *ibsrq_to_rvtsrq(struct ib_srq *ibsrq) |
|---|
| 456 | | -{ |
|---|
| 457 | | - return container_of(ibsrq, struct rvt_srq, ibsrq); |
|---|
| 458 | | -} |
|---|
| 459 | | - |
|---|
| 460 | | -static inline struct rvt_qp *ibqp_to_rvtqp(struct ib_qp *ibqp) |
|---|
| 461 | | -{ |
|---|
| 462 | | - return container_of(ibqp, struct rvt_qp, ibqp); |
|---|
| 463 | | -} |
|---|
| 464 | | - |
|---|
| 465 | 477 | static inline unsigned rvt_get_npkeys(struct rvt_dev_info *rdi) |
|---|
| 466 | 478 | { |
|---|
| 467 | 479 | /* |
|---|
| .. | .. |
|---|
| 476 | 488 | */ |
|---|
| 477 | 489 | static inline unsigned int rvt_max_atomic(struct rvt_dev_info *rdi) |
|---|
| 478 | 490 | { |
|---|
| 479 | | - return rdi->dparms.max_rdma_atomic + 1; |
|---|
| 491 | + return rdi->dparms.max_rdma_atomic + |
|---|
| 492 | + rdi->dparms.extra_rdma_atomic + 1; |
|---|
| 493 | +} |
|---|
| 494 | + |
|---|
| 495 | +static inline unsigned int rvt_size_atomic(struct rvt_dev_info *rdi) |
|---|
| 496 | +{ |
|---|
| 497 | + return rdi->dparms.max_rdma_atomic + |
|---|
| 498 | + rdi->dparms.extra_rdma_atomic; |
|---|
| 480 | 499 | } |
|---|
| 481 | 500 | |
|---|
| 482 | 501 | /* |
|---|
| .. | .. |
|---|
| 492 | 511 | return rdi->ports[port_index]->pkey_table[index]; |
|---|
| 493 | 512 | } |
|---|
| 494 | 513 | |
|---|
| 495 | | -/** |
|---|
| 496 | | - * rvt_lookup_qpn - return the QP with the given QPN |
|---|
| 497 | | - * @ibp: the ibport |
|---|
| 498 | | - * @qpn: the QP number to look up |
|---|
| 499 | | - * |
|---|
| 500 | | - * The caller must hold the rcu_read_lock(), and keep the lock until |
|---|
| 501 | | - * the returned qp is no longer in use. |
|---|
| 502 | | - */ |
|---|
| 503 | | -/* TODO: Remove this and put in rdmavt/qp.h when no longer needed by drivers */ |
|---|
| 504 | | -static inline struct rvt_qp *rvt_lookup_qpn(struct rvt_dev_info *rdi, |
|---|
| 505 | | - struct rvt_ibport *rvp, |
|---|
| 506 | | - u32 qpn) __must_hold(RCU) |
|---|
| 507 | | -{ |
|---|
| 508 | | - struct rvt_qp *qp = NULL; |
|---|
| 509 | | - |
|---|
| 510 | | - if (unlikely(qpn <= 1)) { |
|---|
| 511 | | - qp = rcu_dereference(rvp->qp[qpn]); |
|---|
| 512 | | - } else { |
|---|
| 513 | | - u32 n = hash_32(qpn, rdi->qp_dev->qp_table_bits); |
|---|
| 514 | | - |
|---|
| 515 | | - for (qp = rcu_dereference(rdi->qp_dev->qp_table[n]); qp; |
|---|
| 516 | | - qp = rcu_dereference(qp->next)) |
|---|
| 517 | | - if (qp->ibqp.qp_num == qpn) |
|---|
| 518 | | - break; |
|---|
| 519 | | - } |
|---|
| 520 | | - return qp; |
|---|
| 521 | | -} |
|---|
| 522 | | - |
|---|
| 523 | | -/** |
|---|
| 524 | | - * rvt_mod_retry_timer - mod a retry timer |
|---|
| 525 | | - * @qp - the QP |
|---|
| 526 | | - * Modify a potentially already running retry timer |
|---|
| 527 | | - */ |
|---|
| 528 | | -static inline void rvt_mod_retry_timer(struct rvt_qp *qp) |
|---|
| 529 | | -{ |
|---|
| 530 | | - struct ib_qp *ibqp = &qp->ibqp; |
|---|
| 531 | | - struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); |
|---|
| 532 | | - |
|---|
| 533 | | - lockdep_assert_held(&qp->s_lock); |
|---|
| 534 | | - qp->s_flags |= RVT_S_TIMER; |
|---|
| 535 | | - /* 4.096 usec. * (1 << qp->timeout) */ |
|---|
| 536 | | - mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies + |
|---|
| 537 | | - rdi->busy_jiffies); |
|---|
| 538 | | -} |
|---|
| 539 | | - |
|---|
| 540 | 514 | struct rvt_dev_info *rvt_alloc_device(size_t size, int nports); |
|---|
| 541 | 515 | void rvt_dealloc_device(struct rvt_dev_info *rdi); |
|---|
| 542 | | -int rvt_register_device(struct rvt_dev_info *rvd, u32 driver_id); |
|---|
| 516 | +int rvt_register_device(struct rvt_dev_info *rvd); |
|---|
| 543 | 517 | void rvt_unregister_device(struct rvt_dev_info *rvd); |
|---|
| 544 | 518 | int rvt_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr); |
|---|
| 545 | 519 | int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port, |
|---|