2299 lines · c
1/*2 * Copyright (c) 2004 Topspin Communications. All rights reserved.3 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.4 * Copyright (c) 2006 Intel Corporation. All rights reserved.5 *6 * This software is available to you under a choice of one of two7 * licenses. You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 * Redistribution and use in source and binary forms, with or13 * without modification, are permitted provided that the following14 * conditions are met:15 *16 * - Redistributions of source code must retain the above17 * copyright notice, this list of conditions and the following18 * disclaimer.19 *20 * - Redistributions in binary form must reproduce the above21 * copyright notice, this list of conditions and the following22 * disclaimer in the documentation and/or other materials23 * provided with the distribution.24 *25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * SOFTWARE.33 */34 35#include <linux/init.h>36#include <linux/err.h>37#include <linux/random.h>38#include <linux/spinlock.h>39#include <linux/slab.h>40#include <linux/dma-mapping.h>41#include <linux/kref.h>42#include <linux/xarray.h>43#include <linux/workqueue.h>44#include <uapi/linux/if_ether.h>45#include <rdma/ib_pack.h>46#include <rdma/ib_cache.h>47#include <rdma/rdma_netlink.h>48#include <net/netlink.h>49#include <uapi/rdma/ib_user_sa.h>50#include <rdma/ib_marshall.h>51#include <rdma/ib_addr.h>52#include <rdma/opa_addr.h>53#include <rdma/rdma_cm.h>54#include "sa.h"55#include "core_priv.h"56 57#define IB_SA_LOCAL_SVC_TIMEOUT_MIN 10058#define IB_SA_LOCAL_SVC_TIMEOUT_DEFAULT 200059#define IB_SA_LOCAL_SVC_TIMEOUT_MAX 20000060#define IB_SA_CPI_MAX_RETRY_CNT 361#define IB_SA_CPI_RETRY_WAIT 1000 /*msecs */62static int sa_local_svc_timeout_ms = IB_SA_LOCAL_SVC_TIMEOUT_DEFAULT;63 64struct ib_sa_sm_ah {65 struct ib_ah *ah;66 struct kref ref;67 u16 pkey_index;68 u8 src_path_mask;69};70 71enum rdma_class_port_info_type {72 RDMA_CLASS_PORT_INFO_IB,73 RDMA_CLASS_PORT_INFO_OPA74};75 76struct rdma_class_port_info {77 enum rdma_class_port_info_type type;78 union {79 struct ib_class_port_info ib;80 struct opa_class_port_info opa;81 };82};83 84struct ib_sa_classport_cache {85 bool valid;86 int retry_cnt;87 struct rdma_class_port_info data;88};89 90struct ib_sa_port {91 struct ib_mad_agent *agent;92 struct ib_sa_sm_ah *sm_ah;93 struct work_struct update_task;94 struct ib_sa_classport_cache classport_info;95 struct delayed_work ib_cpi_work;96 spinlock_t classport_lock; /* protects class port info set */97 spinlock_t ah_lock;98 u32 port_num;99};100 101struct ib_sa_device {102 int start_port, end_port;103 struct ib_event_handler event_handler;104 struct ib_sa_port port[];105};106 107struct ib_sa_query {108 void (*callback)(struct ib_sa_query *sa_query, int status,109 struct ib_sa_mad *mad);110 void (*release)(struct ib_sa_query *);111 struct ib_sa_client *client;112 struct ib_sa_port *port;113 struct ib_mad_send_buf *mad_buf;114 struct ib_sa_sm_ah *sm_ah;115 int id;116 u32 flags;117 struct list_head list; /* Local svc request list */118 u32 seq; /* Local svc request sequence number */119 unsigned long timeout; /* Local svc timeout */120 u8 path_use; /* How will the pathrecord be used */121};122 123#define IB_SA_ENABLE_LOCAL_SERVICE 0x00000001124#define IB_SA_CANCEL 0x00000002125#define IB_SA_QUERY_OPA 0x00000004126 127struct ib_sa_path_query {128 void (*callback)(int status, struct sa_path_rec *rec,129 unsigned int num_paths, void *context);130 void *context;131 struct ib_sa_query sa_query;132 struct sa_path_rec *conv_pr;133};134 135struct ib_sa_guidinfo_query {136 void (*callback)(int, struct ib_sa_guidinfo_rec *, void *);137 void *context;138 struct ib_sa_query sa_query;139};140 141struct ib_sa_classport_info_query {142 void (*callback)(void *);143 void *context;144 struct ib_sa_query sa_query;145};146 147struct ib_sa_mcmember_query {148 void (*callback)(int, struct ib_sa_mcmember_rec *, void *);149 void *context;150 struct ib_sa_query sa_query;151};152 153static LIST_HEAD(ib_nl_request_list);154static DEFINE_SPINLOCK(ib_nl_request_lock);155static atomic_t ib_nl_sa_request_seq;156static struct workqueue_struct *ib_nl_wq;157static struct delayed_work ib_nl_timed_work;158static const struct nla_policy ib_nl_policy[LS_NLA_TYPE_MAX] = {159 [LS_NLA_TYPE_PATH_RECORD] = {.type = NLA_BINARY,160 .len = sizeof(struct ib_path_rec_data)},161 [LS_NLA_TYPE_TIMEOUT] = {.type = NLA_U32},162 [LS_NLA_TYPE_SERVICE_ID] = {.type = NLA_U64},163 [LS_NLA_TYPE_DGID] = {.type = NLA_BINARY,164 .len = sizeof(struct rdma_nla_ls_gid)},165 [LS_NLA_TYPE_SGID] = {.type = NLA_BINARY,166 .len = sizeof(struct rdma_nla_ls_gid)},167 [LS_NLA_TYPE_TCLASS] = {.type = NLA_U8},168 [LS_NLA_TYPE_PKEY] = {.type = NLA_U16},169 [LS_NLA_TYPE_QOS_CLASS] = {.type = NLA_U16},170};171 172 173static int ib_sa_add_one(struct ib_device *device);174static void ib_sa_remove_one(struct ib_device *device, void *client_data);175 176static struct ib_client sa_client = {177 .name = "sa",178 .add = ib_sa_add_one,179 .remove = ib_sa_remove_one180};181 182static DEFINE_XARRAY_FLAGS(queries, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);183 184static DEFINE_SPINLOCK(tid_lock);185static u32 tid;186 187#define PATH_REC_FIELD(field) \188 .struct_offset_bytes = offsetof(struct sa_path_rec, field), \189 .struct_size_bytes = sizeof_field(struct sa_path_rec, field), \190 .field_name = "sa_path_rec:" #field191 192static const struct ib_field path_rec_table[] = {193 { PATH_REC_FIELD(service_id),194 .offset_words = 0,195 .offset_bits = 0,196 .size_bits = 64 },197 { PATH_REC_FIELD(dgid),198 .offset_words = 2,199 .offset_bits = 0,200 .size_bits = 128 },201 { PATH_REC_FIELD(sgid),202 .offset_words = 6,203 .offset_bits = 0,204 .size_bits = 128 },205 { PATH_REC_FIELD(ib.dlid),206 .offset_words = 10,207 .offset_bits = 0,208 .size_bits = 16 },209 { PATH_REC_FIELD(ib.slid),210 .offset_words = 10,211 .offset_bits = 16,212 .size_bits = 16 },213 { PATH_REC_FIELD(ib.raw_traffic),214 .offset_words = 11,215 .offset_bits = 0,216 .size_bits = 1 },217 { RESERVED,218 .offset_words = 11,219 .offset_bits = 1,220 .size_bits = 3 },221 { PATH_REC_FIELD(flow_label),222 .offset_words = 11,223 .offset_bits = 4,224 .size_bits = 20 },225 { PATH_REC_FIELD(hop_limit),226 .offset_words = 11,227 .offset_bits = 24,228 .size_bits = 8 },229 { PATH_REC_FIELD(traffic_class),230 .offset_words = 12,231 .offset_bits = 0,232 .size_bits = 8 },233 { PATH_REC_FIELD(reversible),234 .offset_words = 12,235 .offset_bits = 8,236 .size_bits = 1 },237 { PATH_REC_FIELD(numb_path),238 .offset_words = 12,239 .offset_bits = 9,240 .size_bits = 7 },241 { PATH_REC_FIELD(pkey),242 .offset_words = 12,243 .offset_bits = 16,244 .size_bits = 16 },245 { PATH_REC_FIELD(qos_class),246 .offset_words = 13,247 .offset_bits = 0,248 .size_bits = 12 },249 { PATH_REC_FIELD(sl),250 .offset_words = 13,251 .offset_bits = 12,252 .size_bits = 4 },253 { PATH_REC_FIELD(mtu_selector),254 .offset_words = 13,255 .offset_bits = 16,256 .size_bits = 2 },257 { PATH_REC_FIELD(mtu),258 .offset_words = 13,259 .offset_bits = 18,260 .size_bits = 6 },261 { PATH_REC_FIELD(rate_selector),262 .offset_words = 13,263 .offset_bits = 24,264 .size_bits = 2 },265 { PATH_REC_FIELD(rate),266 .offset_words = 13,267 .offset_bits = 26,268 .size_bits = 6 },269 { PATH_REC_FIELD(packet_life_time_selector),270 .offset_words = 14,271 .offset_bits = 0,272 .size_bits = 2 },273 { PATH_REC_FIELD(packet_life_time),274 .offset_words = 14,275 .offset_bits = 2,276 .size_bits = 6 },277 { PATH_REC_FIELD(preference),278 .offset_words = 14,279 .offset_bits = 8,280 .size_bits = 8 },281 { RESERVED,282 .offset_words = 14,283 .offset_bits = 16,284 .size_bits = 48 },285};286 287#define OPA_PATH_REC_FIELD(field) \288 .struct_offset_bytes = \289 offsetof(struct sa_path_rec, field), \290 .struct_size_bytes = \291 sizeof_field(struct sa_path_rec, field), \292 .field_name = "sa_path_rec:" #field293 294static const struct ib_field opa_path_rec_table[] = {295 { OPA_PATH_REC_FIELD(service_id),296 .offset_words = 0,297 .offset_bits = 0,298 .size_bits = 64 },299 { OPA_PATH_REC_FIELD(dgid),300 .offset_words = 2,301 .offset_bits = 0,302 .size_bits = 128 },303 { OPA_PATH_REC_FIELD(sgid),304 .offset_words = 6,305 .offset_bits = 0,306 .size_bits = 128 },307 { OPA_PATH_REC_FIELD(opa.dlid),308 .offset_words = 10,309 .offset_bits = 0,310 .size_bits = 32 },311 { OPA_PATH_REC_FIELD(opa.slid),312 .offset_words = 11,313 .offset_bits = 0,314 .size_bits = 32 },315 { OPA_PATH_REC_FIELD(opa.raw_traffic),316 .offset_words = 12,317 .offset_bits = 0,318 .size_bits = 1 },319 { RESERVED,320 .offset_words = 12,321 .offset_bits = 1,322 .size_bits = 3 },323 { OPA_PATH_REC_FIELD(flow_label),324 .offset_words = 12,325 .offset_bits = 4,326 .size_bits = 20 },327 { OPA_PATH_REC_FIELD(hop_limit),328 .offset_words = 12,329 .offset_bits = 24,330 .size_bits = 8 },331 { OPA_PATH_REC_FIELD(traffic_class),332 .offset_words = 13,333 .offset_bits = 0,334 .size_bits = 8 },335 { OPA_PATH_REC_FIELD(reversible),336 .offset_words = 13,337 .offset_bits = 8,338 .size_bits = 1 },339 { OPA_PATH_REC_FIELD(numb_path),340 .offset_words = 13,341 .offset_bits = 9,342 .size_bits = 7 },343 { OPA_PATH_REC_FIELD(pkey),344 .offset_words = 13,345 .offset_bits = 16,346 .size_bits = 16 },347 { OPA_PATH_REC_FIELD(opa.l2_8B),348 .offset_words = 14,349 .offset_bits = 0,350 .size_bits = 1 },351 { OPA_PATH_REC_FIELD(opa.l2_10B),352 .offset_words = 14,353 .offset_bits = 1,354 .size_bits = 1 },355 { OPA_PATH_REC_FIELD(opa.l2_9B),356 .offset_words = 14,357 .offset_bits = 2,358 .size_bits = 1 },359 { OPA_PATH_REC_FIELD(opa.l2_16B),360 .offset_words = 14,361 .offset_bits = 3,362 .size_bits = 1 },363 { RESERVED,364 .offset_words = 14,365 .offset_bits = 4,366 .size_bits = 2 },367 { OPA_PATH_REC_FIELD(opa.qos_type),368 .offset_words = 14,369 .offset_bits = 6,370 .size_bits = 2 },371 { OPA_PATH_REC_FIELD(opa.qos_priority),372 .offset_words = 14,373 .offset_bits = 8,374 .size_bits = 8 },375 { RESERVED,376 .offset_words = 14,377 .offset_bits = 16,378 .size_bits = 3 },379 { OPA_PATH_REC_FIELD(sl),380 .offset_words = 14,381 .offset_bits = 19,382 .size_bits = 5 },383 { RESERVED,384 .offset_words = 14,385 .offset_bits = 24,386 .size_bits = 8 },387 { OPA_PATH_REC_FIELD(mtu_selector),388 .offset_words = 15,389 .offset_bits = 0,390 .size_bits = 2 },391 { OPA_PATH_REC_FIELD(mtu),392 .offset_words = 15,393 .offset_bits = 2,394 .size_bits = 6 },395 { OPA_PATH_REC_FIELD(rate_selector),396 .offset_words = 15,397 .offset_bits = 8,398 .size_bits = 2 },399 { OPA_PATH_REC_FIELD(rate),400 .offset_words = 15,401 .offset_bits = 10,402 .size_bits = 6 },403 { OPA_PATH_REC_FIELD(packet_life_time_selector),404 .offset_words = 15,405 .offset_bits = 16,406 .size_bits = 2 },407 { OPA_PATH_REC_FIELD(packet_life_time),408 .offset_words = 15,409 .offset_bits = 18,410 .size_bits = 6 },411 { OPA_PATH_REC_FIELD(preference),412 .offset_words = 15,413 .offset_bits = 24,414 .size_bits = 8 },415};416 417#define MCMEMBER_REC_FIELD(field) \418 .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field), \419 .struct_size_bytes = sizeof_field(struct ib_sa_mcmember_rec, field), \420 .field_name = "sa_mcmember_rec:" #field421 422static const struct ib_field mcmember_rec_table[] = {423 { MCMEMBER_REC_FIELD(mgid),424 .offset_words = 0,425 .offset_bits = 0,426 .size_bits = 128 },427 { MCMEMBER_REC_FIELD(port_gid),428 .offset_words = 4,429 .offset_bits = 0,430 .size_bits = 128 },431 { MCMEMBER_REC_FIELD(qkey),432 .offset_words = 8,433 .offset_bits = 0,434 .size_bits = 32 },435 { MCMEMBER_REC_FIELD(mlid),436 .offset_words = 9,437 .offset_bits = 0,438 .size_bits = 16 },439 { MCMEMBER_REC_FIELD(mtu_selector),440 .offset_words = 9,441 .offset_bits = 16,442 .size_bits = 2 },443 { MCMEMBER_REC_FIELD(mtu),444 .offset_words = 9,445 .offset_bits = 18,446 .size_bits = 6 },447 { MCMEMBER_REC_FIELD(traffic_class),448 .offset_words = 9,449 .offset_bits = 24,450 .size_bits = 8 },451 { MCMEMBER_REC_FIELD(pkey),452 .offset_words = 10,453 .offset_bits = 0,454 .size_bits = 16 },455 { MCMEMBER_REC_FIELD(rate_selector),456 .offset_words = 10,457 .offset_bits = 16,458 .size_bits = 2 },459 { MCMEMBER_REC_FIELD(rate),460 .offset_words = 10,461 .offset_bits = 18,462 .size_bits = 6 },463 { MCMEMBER_REC_FIELD(packet_life_time_selector),464 .offset_words = 10,465 .offset_bits = 24,466 .size_bits = 2 },467 { MCMEMBER_REC_FIELD(packet_life_time),468 .offset_words = 10,469 .offset_bits = 26,470 .size_bits = 6 },471 { MCMEMBER_REC_FIELD(sl),472 .offset_words = 11,473 .offset_bits = 0,474 .size_bits = 4 },475 { MCMEMBER_REC_FIELD(flow_label),476 .offset_words = 11,477 .offset_bits = 4,478 .size_bits = 20 },479 { MCMEMBER_REC_FIELD(hop_limit),480 .offset_words = 11,481 .offset_bits = 24,482 .size_bits = 8 },483 { MCMEMBER_REC_FIELD(scope),484 .offset_words = 12,485 .offset_bits = 0,486 .size_bits = 4 },487 { MCMEMBER_REC_FIELD(join_state),488 .offset_words = 12,489 .offset_bits = 4,490 .size_bits = 4 },491 { MCMEMBER_REC_FIELD(proxy_join),492 .offset_words = 12,493 .offset_bits = 8,494 .size_bits = 1 },495 { RESERVED,496 .offset_words = 12,497 .offset_bits = 9,498 .size_bits = 23 },499};500 501#define CLASSPORTINFO_REC_FIELD(field) \502 .struct_offset_bytes = offsetof(struct ib_class_port_info, field), \503 .struct_size_bytes = sizeof_field(struct ib_class_port_info, field), \504 .field_name = "ib_class_port_info:" #field505 506static const struct ib_field ib_classport_info_rec_table[] = {507 { CLASSPORTINFO_REC_FIELD(base_version),508 .offset_words = 0,509 .offset_bits = 0,510 .size_bits = 8 },511 { CLASSPORTINFO_REC_FIELD(class_version),512 .offset_words = 0,513 .offset_bits = 8,514 .size_bits = 8 },515 { CLASSPORTINFO_REC_FIELD(capability_mask),516 .offset_words = 0,517 .offset_bits = 16,518 .size_bits = 16 },519 { CLASSPORTINFO_REC_FIELD(cap_mask2_resp_time),520 .offset_words = 1,521 .offset_bits = 0,522 .size_bits = 32 },523 { CLASSPORTINFO_REC_FIELD(redirect_gid),524 .offset_words = 2,525 .offset_bits = 0,526 .size_bits = 128 },527 { CLASSPORTINFO_REC_FIELD(redirect_tcslfl),528 .offset_words = 6,529 .offset_bits = 0,530 .size_bits = 32 },531 { CLASSPORTINFO_REC_FIELD(redirect_lid),532 .offset_words = 7,533 .offset_bits = 0,534 .size_bits = 16 },535 { CLASSPORTINFO_REC_FIELD(redirect_pkey),536 .offset_words = 7,537 .offset_bits = 16,538 .size_bits = 16 },539 540 { CLASSPORTINFO_REC_FIELD(redirect_qp),541 .offset_words = 8,542 .offset_bits = 0,543 .size_bits = 32 },544 { CLASSPORTINFO_REC_FIELD(redirect_qkey),545 .offset_words = 9,546 .offset_bits = 0,547 .size_bits = 32 },548 549 { CLASSPORTINFO_REC_FIELD(trap_gid),550 .offset_words = 10,551 .offset_bits = 0,552 .size_bits = 128 },553 { CLASSPORTINFO_REC_FIELD(trap_tcslfl),554 .offset_words = 14,555 .offset_bits = 0,556 .size_bits = 32 },557 558 { CLASSPORTINFO_REC_FIELD(trap_lid),559 .offset_words = 15,560 .offset_bits = 0,561 .size_bits = 16 },562 { CLASSPORTINFO_REC_FIELD(trap_pkey),563 .offset_words = 15,564 .offset_bits = 16,565 .size_bits = 16 },566 567 { CLASSPORTINFO_REC_FIELD(trap_hlqp),568 .offset_words = 16,569 .offset_bits = 0,570 .size_bits = 32 },571 { CLASSPORTINFO_REC_FIELD(trap_qkey),572 .offset_words = 17,573 .offset_bits = 0,574 .size_bits = 32 },575};576 577#define OPA_CLASSPORTINFO_REC_FIELD(field) \578 .struct_offset_bytes =\579 offsetof(struct opa_class_port_info, field), \580 .struct_size_bytes = \581 sizeof_field(struct opa_class_port_info, field), \582 .field_name = "opa_class_port_info:" #field583 584static const struct ib_field opa_classport_info_rec_table[] = {585 { OPA_CLASSPORTINFO_REC_FIELD(base_version),586 .offset_words = 0,587 .offset_bits = 0,588 .size_bits = 8 },589 { OPA_CLASSPORTINFO_REC_FIELD(class_version),590 .offset_words = 0,591 .offset_bits = 8,592 .size_bits = 8 },593 { OPA_CLASSPORTINFO_REC_FIELD(cap_mask),594 .offset_words = 0,595 .offset_bits = 16,596 .size_bits = 16 },597 { OPA_CLASSPORTINFO_REC_FIELD(cap_mask2_resp_time),598 .offset_words = 1,599 .offset_bits = 0,600 .size_bits = 32 },601 { OPA_CLASSPORTINFO_REC_FIELD(redirect_gid),602 .offset_words = 2,603 .offset_bits = 0,604 .size_bits = 128 },605 { OPA_CLASSPORTINFO_REC_FIELD(redirect_tc_fl),606 .offset_words = 6,607 .offset_bits = 0,608 .size_bits = 32 },609 { OPA_CLASSPORTINFO_REC_FIELD(redirect_lid),610 .offset_words = 7,611 .offset_bits = 0,612 .size_bits = 32 },613 { OPA_CLASSPORTINFO_REC_FIELD(redirect_sl_qp),614 .offset_words = 8,615 .offset_bits = 0,616 .size_bits = 32 },617 { OPA_CLASSPORTINFO_REC_FIELD(redirect_qkey),618 .offset_words = 9,619 .offset_bits = 0,620 .size_bits = 32 },621 { OPA_CLASSPORTINFO_REC_FIELD(trap_gid),622 .offset_words = 10,623 .offset_bits = 0,624 .size_bits = 128 },625 { OPA_CLASSPORTINFO_REC_FIELD(trap_tc_fl),626 .offset_words = 14,627 .offset_bits = 0,628 .size_bits = 32 },629 { OPA_CLASSPORTINFO_REC_FIELD(trap_lid),630 .offset_words = 15,631 .offset_bits = 0,632 .size_bits = 32 },633 { OPA_CLASSPORTINFO_REC_FIELD(trap_hl_qp),634 .offset_words = 16,635 .offset_bits = 0,636 .size_bits = 32 },637 { OPA_CLASSPORTINFO_REC_FIELD(trap_qkey),638 .offset_words = 17,639 .offset_bits = 0,640 .size_bits = 32 },641 { OPA_CLASSPORTINFO_REC_FIELD(trap_pkey),642 .offset_words = 18,643 .offset_bits = 0,644 .size_bits = 16 },645 { OPA_CLASSPORTINFO_REC_FIELD(redirect_pkey),646 .offset_words = 18,647 .offset_bits = 16,648 .size_bits = 16 },649 { OPA_CLASSPORTINFO_REC_FIELD(trap_sl_rsvd),650 .offset_words = 19,651 .offset_bits = 0,652 .size_bits = 8 },653 { RESERVED,654 .offset_words = 19,655 .offset_bits = 8,656 .size_bits = 24 },657};658 659#define GUIDINFO_REC_FIELD(field) \660 .struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \661 .struct_size_bytes = sizeof_field(struct ib_sa_guidinfo_rec, field), \662 .field_name = "sa_guidinfo_rec:" #field663 664static const struct ib_field guidinfo_rec_table[] = {665 { GUIDINFO_REC_FIELD(lid),666 .offset_words = 0,667 .offset_bits = 0,668 .size_bits = 16 },669 { GUIDINFO_REC_FIELD(block_num),670 .offset_words = 0,671 .offset_bits = 16,672 .size_bits = 8 },673 { GUIDINFO_REC_FIELD(res1),674 .offset_words = 0,675 .offset_bits = 24,676 .size_bits = 8 },677 { GUIDINFO_REC_FIELD(res2),678 .offset_words = 1,679 .offset_bits = 0,680 .size_bits = 32 },681 { GUIDINFO_REC_FIELD(guid_info_list),682 .offset_words = 2,683 .offset_bits = 0,684 .size_bits = 512 },685};686 687#define RDMA_PRIMARY_PATH_MAX_REC_NUM 3688 689static inline void ib_sa_disable_local_svc(struct ib_sa_query *query)690{691 query->flags &= ~IB_SA_ENABLE_LOCAL_SERVICE;692}693 694static inline int ib_sa_query_cancelled(struct ib_sa_query *query)695{696 return (query->flags & IB_SA_CANCEL);697}698 699static void ib_nl_set_path_rec_attrs(struct sk_buff *skb,700 struct ib_sa_query *query)701{702 struct sa_path_rec *sa_rec = query->mad_buf->context[1];703 struct ib_sa_mad *mad = query->mad_buf->mad;704 ib_sa_comp_mask comp_mask = mad->sa_hdr.comp_mask;705 u16 val16;706 u64 val64;707 struct rdma_ls_resolve_header *header;708 709 query->mad_buf->context[1] = NULL;710 711 /* Construct the family header first */712 header = skb_put(skb, NLMSG_ALIGN(sizeof(*header)));713 strscpy_pad(header->device_name,714 dev_name(&query->port->agent->device->dev),715 LS_DEVICE_NAME_MAX);716 header->port_num = query->port->port_num;717 718 if ((comp_mask & IB_SA_PATH_REC_REVERSIBLE) &&719 sa_rec->reversible != 0)720 query->path_use = LS_RESOLVE_PATH_USE_ALL;721 else722 query->path_use = LS_RESOLVE_PATH_USE_UNIDIRECTIONAL;723 header->path_use = query->path_use;724 725 /* Now build the attributes */726 if (comp_mask & IB_SA_PATH_REC_SERVICE_ID) {727 val64 = be64_to_cpu(sa_rec->service_id);728 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_SERVICE_ID,729 sizeof(val64), &val64);730 }731 if (comp_mask & IB_SA_PATH_REC_DGID)732 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_DGID,733 sizeof(sa_rec->dgid), &sa_rec->dgid);734 if (comp_mask & IB_SA_PATH_REC_SGID)735 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_SGID,736 sizeof(sa_rec->sgid), &sa_rec->sgid);737 if (comp_mask & IB_SA_PATH_REC_TRAFFIC_CLASS)738 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_TCLASS,739 sizeof(sa_rec->traffic_class), &sa_rec->traffic_class);740 741 if (comp_mask & IB_SA_PATH_REC_PKEY) {742 val16 = be16_to_cpu(sa_rec->pkey);743 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_PKEY,744 sizeof(val16), &val16);745 }746 if (comp_mask & IB_SA_PATH_REC_QOS_CLASS) {747 val16 = be16_to_cpu(sa_rec->qos_class);748 nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_QOS_CLASS,749 sizeof(val16), &val16);750 }751}752 753static int ib_nl_get_path_rec_attrs_len(ib_sa_comp_mask comp_mask)754{755 int len = 0;756 757 if (comp_mask & IB_SA_PATH_REC_SERVICE_ID)758 len += nla_total_size(sizeof(u64));759 if (comp_mask & IB_SA_PATH_REC_DGID)760 len += nla_total_size(sizeof(struct rdma_nla_ls_gid));761 if (comp_mask & IB_SA_PATH_REC_SGID)762 len += nla_total_size(sizeof(struct rdma_nla_ls_gid));763 if (comp_mask & IB_SA_PATH_REC_TRAFFIC_CLASS)764 len += nla_total_size(sizeof(u8));765 if (comp_mask & IB_SA_PATH_REC_PKEY)766 len += nla_total_size(sizeof(u16));767 if (comp_mask & IB_SA_PATH_REC_QOS_CLASS)768 len += nla_total_size(sizeof(u16));769 770 /*771 * Make sure that at least some of the required comp_mask bits are772 * set.773 */774 if (WARN_ON(len == 0))775 return len;776 777 /* Add the family header */778 len += NLMSG_ALIGN(sizeof(struct rdma_ls_resolve_header));779 780 return len;781}782 783static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)784{785 struct sk_buff *skb = NULL;786 struct nlmsghdr *nlh;787 void *data;788 struct ib_sa_mad *mad;789 int len;790 unsigned long flags;791 unsigned long delay;792 gfp_t gfp_flag;793 int ret;794 795 INIT_LIST_HEAD(&query->list);796 query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);797 798 mad = query->mad_buf->mad;799 len = ib_nl_get_path_rec_attrs_len(mad->sa_hdr.comp_mask);800 if (len <= 0)801 return -EMSGSIZE;802 803 skb = nlmsg_new(len, gfp_mask);804 if (!skb)805 return -ENOMEM;806 807 /* Put nlmsg header only for now */808 data = ibnl_put_msg(skb, &nlh, query->seq, 0, RDMA_NL_LS,809 RDMA_NL_LS_OP_RESOLVE, NLM_F_REQUEST);810 if (!data) {811 nlmsg_free(skb);812 return -EMSGSIZE;813 }814 815 /* Add attributes */816 ib_nl_set_path_rec_attrs(skb, query);817 818 /* Repair the nlmsg header length */819 nlmsg_end(skb, nlh);820 821 gfp_flag = ((gfp_mask & GFP_ATOMIC) == GFP_ATOMIC) ? GFP_ATOMIC :822 GFP_NOWAIT;823 824 spin_lock_irqsave(&ib_nl_request_lock, flags);825 ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_flag);826 827 if (ret)828 goto out;829 830 /* Put the request on the list.*/831 delay = msecs_to_jiffies(sa_local_svc_timeout_ms);832 query->timeout = delay + jiffies;833 list_add_tail(&query->list, &ib_nl_request_list);834 /* Start the timeout if this is the only request */835 if (ib_nl_request_list.next == &query->list)836 queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);837 838out:839 spin_unlock_irqrestore(&ib_nl_request_lock, flags);840 841 return ret;842}843 844static int ib_nl_cancel_request(struct ib_sa_query *query)845{846 unsigned long flags;847 struct ib_sa_query *wait_query;848 int found = 0;849 850 spin_lock_irqsave(&ib_nl_request_lock, flags);851 list_for_each_entry(wait_query, &ib_nl_request_list, list) {852 /* Let the timeout to take care of the callback */853 if (query == wait_query) {854 query->flags |= IB_SA_CANCEL;855 query->timeout = jiffies;856 list_move(&query->list, &ib_nl_request_list);857 found = 1;858 mod_delayed_work(ib_nl_wq, &ib_nl_timed_work, 1);859 break;860 }861 }862 spin_unlock_irqrestore(&ib_nl_request_lock, flags);863 864 return found;865}866 867static void send_handler(struct ib_mad_agent *agent,868 struct ib_mad_send_wc *mad_send_wc);869 870static void ib_nl_process_good_resolve_rsp(struct ib_sa_query *query,871 const struct nlmsghdr *nlh)872{873 struct sa_path_rec recs[RDMA_PRIMARY_PATH_MAX_REC_NUM];874 struct ib_sa_path_query *path_query;875 struct ib_path_rec_data *rec_data;876 struct ib_mad_send_wc mad_send_wc;877 const struct nlattr *head, *curr;878 struct ib_sa_mad *mad = NULL;879 int len, rem, status = -EIO;880 unsigned int num_prs = 0;881 u32 mask = 0;882 883 if (!query->callback)884 goto out;885 886 path_query = container_of(query, struct ib_sa_path_query, sa_query);887 mad = query->mad_buf->mad;888 889 head = (const struct nlattr *) nlmsg_data(nlh);890 len = nlmsg_len(nlh);891 switch (query->path_use) {892 case LS_RESOLVE_PATH_USE_UNIDIRECTIONAL:893 mask = IB_PATH_PRIMARY | IB_PATH_OUTBOUND;894 break;895 896 case LS_RESOLVE_PATH_USE_ALL:897 mask = IB_PATH_PRIMARY;898 break;899 900 case LS_RESOLVE_PATH_USE_GMP:901 default:902 mask = IB_PATH_PRIMARY | IB_PATH_GMP |903 IB_PATH_BIDIRECTIONAL;904 break;905 }906 907 nla_for_each_attr(curr, head, len, rem) {908 if (curr->nla_type != LS_NLA_TYPE_PATH_RECORD)909 continue;910 911 rec_data = nla_data(curr);912 if ((rec_data->flags & mask) != mask)913 continue;914 915 if ((query->flags & IB_SA_QUERY_OPA) ||916 path_query->conv_pr) {917 mad->mad_hdr.method |= IB_MGMT_METHOD_RESP;918 memcpy(mad->data, rec_data->path_rec,919 sizeof(rec_data->path_rec));920 query->callback(query, 0, mad);921 goto out;922 }923 924 status = 0;925 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),926 rec_data->path_rec, &recs[num_prs]);927 recs[num_prs].flags = rec_data->flags;928 recs[num_prs].rec_type = SA_PATH_REC_TYPE_IB;929 sa_path_set_dmac_zero(&recs[num_prs]);930 931 num_prs++;932 if (num_prs >= RDMA_PRIMARY_PATH_MAX_REC_NUM)933 break;934 }935 936 if (!status) {937 mad->mad_hdr.method |= IB_MGMT_METHOD_RESP;938 path_query->callback(status, recs, num_prs,939 path_query->context);940 } else941 query->callback(query, status, mad);942 943out:944 mad_send_wc.send_buf = query->mad_buf;945 mad_send_wc.status = IB_WC_SUCCESS;946 send_handler(query->mad_buf->mad_agent, &mad_send_wc);947}948 949static void ib_nl_request_timeout(struct work_struct *work)950{951 unsigned long flags;952 struct ib_sa_query *query;953 unsigned long delay;954 struct ib_mad_send_wc mad_send_wc;955 int ret;956 957 spin_lock_irqsave(&ib_nl_request_lock, flags);958 while (!list_empty(&ib_nl_request_list)) {959 query = list_entry(ib_nl_request_list.next,960 struct ib_sa_query, list);961 962 if (time_after(query->timeout, jiffies)) {963 delay = query->timeout - jiffies;964 if ((long)delay <= 0)965 delay = 1;966 queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);967 break;968 }969 970 list_del(&query->list);971 ib_sa_disable_local_svc(query);972 /* Hold the lock to protect against query cancellation */973 if (ib_sa_query_cancelled(query))974 ret = -1;975 else976 ret = ib_post_send_mad(query->mad_buf, NULL);977 if (ret) {978 mad_send_wc.send_buf = query->mad_buf;979 mad_send_wc.status = IB_WC_WR_FLUSH_ERR;980 spin_unlock_irqrestore(&ib_nl_request_lock, flags);981 send_handler(query->port->agent, &mad_send_wc);982 spin_lock_irqsave(&ib_nl_request_lock, flags);983 }984 }985 spin_unlock_irqrestore(&ib_nl_request_lock, flags);986}987 988int ib_nl_handle_set_timeout(struct sk_buff *skb,989 struct nlmsghdr *nlh,990 struct netlink_ext_ack *extack)991{992 int timeout, delta, abs_delta;993 const struct nlattr *attr;994 unsigned long flags;995 struct ib_sa_query *query;996 long delay = 0;997 struct nlattr *tb[LS_NLA_TYPE_MAX];998 int ret;999 1000 if (!(nlh->nlmsg_flags & NLM_F_REQUEST) ||1001 !(NETLINK_CB(skb).sk))1002 return -EPERM;1003 1004 ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),1005 nlmsg_len(nlh), ib_nl_policy, NULL);1006 attr = (const struct nlattr *)tb[LS_NLA_TYPE_TIMEOUT];1007 if (ret || !attr)1008 goto settimeout_out;1009 1010 timeout = *(int *) nla_data(attr);1011 if (timeout < IB_SA_LOCAL_SVC_TIMEOUT_MIN)1012 timeout = IB_SA_LOCAL_SVC_TIMEOUT_MIN;1013 if (timeout > IB_SA_LOCAL_SVC_TIMEOUT_MAX)1014 timeout = IB_SA_LOCAL_SVC_TIMEOUT_MAX;1015 1016 delta = timeout - sa_local_svc_timeout_ms;1017 if (delta < 0)1018 abs_delta = -delta;1019 else1020 abs_delta = delta;1021 1022 if (delta != 0) {1023 spin_lock_irqsave(&ib_nl_request_lock, flags);1024 sa_local_svc_timeout_ms = timeout;1025 list_for_each_entry(query, &ib_nl_request_list, list) {1026 if (delta < 0 && abs_delta > query->timeout)1027 query->timeout = 0;1028 else1029 query->timeout += delta;1030 1031 /* Get the new delay from the first entry */1032 if (!delay) {1033 delay = query->timeout - jiffies;1034 if (delay <= 0)1035 delay = 1;1036 }1037 }1038 if (delay)1039 mod_delayed_work(ib_nl_wq, &ib_nl_timed_work,1040 (unsigned long)delay);1041 spin_unlock_irqrestore(&ib_nl_request_lock, flags);1042 }1043 1044settimeout_out:1045 return 0;1046}1047 1048static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh)1049{1050 struct nlattr *tb[LS_NLA_TYPE_MAX];1051 int ret;1052 1053 if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)1054 return 0;1055 1056 ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),1057 nlmsg_len(nlh), ib_nl_policy, NULL);1058 if (ret)1059 return 0;1060 1061 return 1;1062}1063 1064int ib_nl_handle_resolve_resp(struct sk_buff *skb,1065 struct nlmsghdr *nlh,1066 struct netlink_ext_ack *extack)1067{1068 unsigned long flags;1069 struct ib_sa_query *query = NULL, *iter;1070 struct ib_mad_send_buf *send_buf;1071 struct ib_mad_send_wc mad_send_wc;1072 int ret;1073 1074 if ((nlh->nlmsg_flags & NLM_F_REQUEST) ||1075 !(NETLINK_CB(skb).sk))1076 return -EPERM;1077 1078 spin_lock_irqsave(&ib_nl_request_lock, flags);1079 list_for_each_entry(iter, &ib_nl_request_list, list) {1080 /*1081 * If the query is cancelled, let the timeout routine1082 * take care of it.1083 */1084 if (nlh->nlmsg_seq == iter->seq) {1085 if (!ib_sa_query_cancelled(iter)) {1086 list_del(&iter->list);1087 query = iter;1088 }1089 break;1090 }1091 }1092 1093 if (!query) {1094 spin_unlock_irqrestore(&ib_nl_request_lock, flags);1095 goto resp_out;1096 }1097 1098 send_buf = query->mad_buf;1099 1100 if (!ib_nl_is_good_resolve_resp(nlh)) {1101 /* if the result is a failure, send out the packet via IB */1102 ib_sa_disable_local_svc(query);1103 ret = ib_post_send_mad(query->mad_buf, NULL);1104 spin_unlock_irqrestore(&ib_nl_request_lock, flags);1105 if (ret) {1106 mad_send_wc.send_buf = send_buf;1107 mad_send_wc.status = IB_WC_GENERAL_ERR;1108 send_handler(query->port->agent, &mad_send_wc);1109 }1110 } else {1111 spin_unlock_irqrestore(&ib_nl_request_lock, flags);1112 ib_nl_process_good_resolve_rsp(query, nlh);1113 }1114 1115resp_out:1116 return 0;1117}1118 1119static void free_sm_ah(struct kref *kref)1120{1121 struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);1122 1123 rdma_destroy_ah(sm_ah->ah, 0);1124 kfree(sm_ah);1125}1126 1127void ib_sa_register_client(struct ib_sa_client *client)1128{1129 atomic_set(&client->users, 1);1130 init_completion(&client->comp);1131}1132EXPORT_SYMBOL(ib_sa_register_client);1133 1134void ib_sa_unregister_client(struct ib_sa_client *client)1135{1136 ib_sa_client_put(client);1137 wait_for_completion(&client->comp);1138}1139EXPORT_SYMBOL(ib_sa_unregister_client);1140 1141/**1142 * ib_sa_cancel_query - try to cancel an SA query1143 * @id:ID of query to cancel1144 * @query:query pointer to cancel1145 *1146 * Try to cancel an SA query. If the id and query don't match up or1147 * the query has already completed, nothing is done. Otherwise the1148 * query is canceled and will complete with a status of -EINTR.1149 */1150void ib_sa_cancel_query(int id, struct ib_sa_query *query)1151{1152 unsigned long flags;1153 struct ib_mad_send_buf *mad_buf;1154 1155 xa_lock_irqsave(&queries, flags);1156 if (xa_load(&queries, id) != query) {1157 xa_unlock_irqrestore(&queries, flags);1158 return;1159 }1160 mad_buf = query->mad_buf;1161 xa_unlock_irqrestore(&queries, flags);1162 1163 /*1164 * If the query is still on the netlink request list, schedule1165 * it to be cancelled by the timeout routine. Otherwise, it has been1166 * sent to the MAD layer and has to be cancelled from there.1167 */1168 if (!ib_nl_cancel_request(query))1169 ib_cancel_mad(mad_buf);1170}1171EXPORT_SYMBOL(ib_sa_cancel_query);1172 1173static u8 get_src_path_mask(struct ib_device *device, u32 port_num)1174{1175 struct ib_sa_device *sa_dev;1176 struct ib_sa_port *port;1177 unsigned long flags;1178 u8 src_path_mask;1179 1180 sa_dev = ib_get_client_data(device, &sa_client);1181 if (!sa_dev)1182 return 0x7f;1183 1184 port = &sa_dev->port[port_num - sa_dev->start_port];1185 spin_lock_irqsave(&port->ah_lock, flags);1186 src_path_mask = port->sm_ah ? port->sm_ah->src_path_mask : 0x7f;1187 spin_unlock_irqrestore(&port->ah_lock, flags);1188 1189 return src_path_mask;1190}1191 1192static int init_ah_attr_grh_fields(struct ib_device *device, u32 port_num,1193 struct sa_path_rec *rec,1194 struct rdma_ah_attr *ah_attr,1195 const struct ib_gid_attr *gid_attr)1196{1197 enum ib_gid_type type = sa_conv_pathrec_to_gid_type(rec);1198 1199 if (!gid_attr) {1200 gid_attr = rdma_find_gid_by_port(device, &rec->sgid, type,1201 port_num, NULL);1202 if (IS_ERR(gid_attr))1203 return PTR_ERR(gid_attr);1204 } else1205 rdma_hold_gid_attr(gid_attr);1206 1207 rdma_move_grh_sgid_attr(ah_attr, &rec->dgid,1208 be32_to_cpu(rec->flow_label),1209 rec->hop_limit, rec->traffic_class,1210 gid_attr);1211 return 0;1212}1213 1214/**1215 * ib_init_ah_attr_from_path - Initialize address handle attributes based on1216 * an SA path record.1217 * @device: Device associated ah attributes initialization.1218 * @port_num: Port on the specified device.1219 * @rec: path record entry to use for ah attributes initialization.1220 * @ah_attr: address handle attributes to initialization from path record.1221 * @gid_attr: SGID attribute to consider during initialization.1222 *1223 * When ib_init_ah_attr_from_path() returns success,1224 * (a) for IB link layer it optionally contains a reference to SGID attribute1225 * when GRH is present for IB link layer.1226 * (b) for RoCE link layer it contains a reference to SGID attribute.1227 * User must invoke rdma_destroy_ah_attr() to release reference to SGID1228 * attributes which are initialized using ib_init_ah_attr_from_path().1229 */1230int ib_init_ah_attr_from_path(struct ib_device *device, u32 port_num,1231 struct sa_path_rec *rec,1232 struct rdma_ah_attr *ah_attr,1233 const struct ib_gid_attr *gid_attr)1234{1235 int ret = 0;1236 1237 memset(ah_attr, 0, sizeof(*ah_attr));1238 ah_attr->type = rdma_ah_find_type(device, port_num);1239 rdma_ah_set_sl(ah_attr, rec->sl);1240 rdma_ah_set_port_num(ah_attr, port_num);1241 rdma_ah_set_static_rate(ah_attr, rec->rate);1242 1243 if (sa_path_is_roce(rec)) {1244 ret = roce_resolve_route_from_path(rec, gid_attr);1245 if (ret)1246 return ret;1247 1248 memcpy(ah_attr->roce.dmac, sa_path_get_dmac(rec), ETH_ALEN);1249 } else {1250 rdma_ah_set_dlid(ah_attr, be32_to_cpu(sa_path_get_dlid(rec)));1251 if (sa_path_is_opa(rec) &&1252 rdma_ah_get_dlid(ah_attr) == be16_to_cpu(IB_LID_PERMISSIVE))1253 rdma_ah_set_make_grd(ah_attr, true);1254 1255 rdma_ah_set_path_bits(ah_attr,1256 be32_to_cpu(sa_path_get_slid(rec)) &1257 get_src_path_mask(device, port_num));1258 }1259 1260 if (rec->hop_limit > 0 || sa_path_is_roce(rec))1261 ret = init_ah_attr_grh_fields(device, port_num,1262 rec, ah_attr, gid_attr);1263 return ret;1264}1265EXPORT_SYMBOL(ib_init_ah_attr_from_path);1266 1267static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)1268{1269 struct rdma_ah_attr ah_attr;1270 unsigned long flags;1271 1272 spin_lock_irqsave(&query->port->ah_lock, flags);1273 if (!query->port->sm_ah) {1274 spin_unlock_irqrestore(&query->port->ah_lock, flags);1275 return -EAGAIN;1276 }1277 kref_get(&query->port->sm_ah->ref);1278 query->sm_ah = query->port->sm_ah;1279 spin_unlock_irqrestore(&query->port->ah_lock, flags);1280 1281 /*1282 * Always check if sm_ah has valid dlid assigned,1283 * before querying for class port info1284 */1285 if ((rdma_query_ah(query->sm_ah->ah, &ah_attr) < 0) ||1286 !rdma_is_valid_unicast_lid(&ah_attr)) {1287 kref_put(&query->sm_ah->ref, free_sm_ah);1288 return -EAGAIN;1289 }1290 query->mad_buf = ib_create_send_mad(query->port->agent, 1,1291 query->sm_ah->pkey_index,1292 0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,1293 gfp_mask,1294 ((query->flags & IB_SA_QUERY_OPA) ?1295 OPA_MGMT_BASE_VERSION :1296 IB_MGMT_BASE_VERSION));1297 if (IS_ERR(query->mad_buf)) {1298 kref_put(&query->sm_ah->ref, free_sm_ah);1299 return -ENOMEM;1300 }1301 1302 query->mad_buf->ah = query->sm_ah->ah;1303 1304 return 0;1305}1306 1307static void free_mad(struct ib_sa_query *query)1308{1309 ib_free_send_mad(query->mad_buf);1310 kref_put(&query->sm_ah->ref, free_sm_ah);1311}1312 1313static void init_mad(struct ib_sa_query *query, struct ib_mad_agent *agent)1314{1315 struct ib_sa_mad *mad = query->mad_buf->mad;1316 unsigned long flags;1317 1318 memset(mad, 0, sizeof *mad);1319 1320 if (query->flags & IB_SA_QUERY_OPA) {1321 mad->mad_hdr.base_version = OPA_MGMT_BASE_VERSION;1322 mad->mad_hdr.class_version = OPA_SA_CLASS_VERSION;1323 } else {1324 mad->mad_hdr.base_version = IB_MGMT_BASE_VERSION;1325 mad->mad_hdr.class_version = IB_SA_CLASS_VERSION;1326 }1327 mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;1328 spin_lock_irqsave(&tid_lock, flags);1329 mad->mad_hdr.tid =1330 cpu_to_be64(((u64) agent->hi_tid) << 32 | tid++);1331 spin_unlock_irqrestore(&tid_lock, flags);1332}1333 1334static int send_mad(struct ib_sa_query *query, unsigned long timeout_ms,1335 gfp_t gfp_mask)1336{1337 unsigned long flags;1338 int ret, id;1339 const int nmbr_sa_query_retries = 10;1340 1341 xa_lock_irqsave(&queries, flags);1342 ret = __xa_alloc(&queries, &id, query, xa_limit_32b, gfp_mask);1343 xa_unlock_irqrestore(&queries, flags);1344 if (ret < 0)1345 return ret;1346 1347 query->mad_buf->timeout_ms = timeout_ms / nmbr_sa_query_retries;1348 query->mad_buf->retries = nmbr_sa_query_retries;1349 if (!query->mad_buf->timeout_ms) {1350 /* Special case, very small timeout_ms */1351 query->mad_buf->timeout_ms = 1;1352 query->mad_buf->retries = timeout_ms;1353 }1354 query->mad_buf->context[0] = query;1355 query->id = id;1356 1357 if ((query->flags & IB_SA_ENABLE_LOCAL_SERVICE) &&1358 (!(query->flags & IB_SA_QUERY_OPA))) {1359 if (rdma_nl_chk_listeners(RDMA_NL_GROUP_LS)) {1360 if (!ib_nl_make_request(query, gfp_mask))1361 return id;1362 }1363 ib_sa_disable_local_svc(query);1364 }1365 1366 ret = ib_post_send_mad(query->mad_buf, NULL);1367 if (ret) {1368 xa_lock_irqsave(&queries, flags);1369 __xa_erase(&queries, id);1370 xa_unlock_irqrestore(&queries, flags);1371 }1372 1373 /*1374 * It's not safe to dereference query any more, because the1375 * send may already have completed and freed the query in1376 * another context.1377 */1378 return ret ? ret : id;1379}1380 1381void ib_sa_unpack_path(void *attribute, struct sa_path_rec *rec)1382{1383 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), attribute, rec);1384}1385EXPORT_SYMBOL(ib_sa_unpack_path);1386 1387void ib_sa_pack_path(struct sa_path_rec *rec, void *attribute)1388{1389 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, attribute);1390}1391EXPORT_SYMBOL(ib_sa_pack_path);1392 1393static bool ib_sa_opa_pathrecord_support(struct ib_sa_client *client,1394 struct ib_sa_device *sa_dev,1395 u32 port_num)1396{1397 struct ib_sa_port *port;1398 unsigned long flags;1399 bool ret = false;1400 1401 port = &sa_dev->port[port_num - sa_dev->start_port];1402 spin_lock_irqsave(&port->classport_lock, flags);1403 if (!port->classport_info.valid)1404 goto ret;1405 1406 if (port->classport_info.data.type == RDMA_CLASS_PORT_INFO_OPA)1407 ret = opa_get_cpi_capmask2(&port->classport_info.data.opa) &1408 OPA_CLASS_PORT_INFO_PR_SUPPORT;1409ret:1410 spin_unlock_irqrestore(&port->classport_lock, flags);1411 return ret;1412}1413 1414enum opa_pr_supported {1415 PR_NOT_SUPPORTED,1416 PR_OPA_SUPPORTED,1417 PR_IB_SUPPORTED1418};1419 1420/*1421 * opa_pr_query_possible - Check if current PR query can be an OPA query.1422 *1423 * Returns PR_NOT_SUPPORTED if a path record query is not1424 * possible, PR_OPA_SUPPORTED if an OPA path record query1425 * is possible and PR_IB_SUPPORTED if an IB path record1426 * query is possible.1427 */1428static int opa_pr_query_possible(struct ib_sa_client *client,1429 struct ib_sa_device *sa_dev,1430 struct ib_device *device, u32 port_num)1431{1432 struct ib_port_attr port_attr;1433 1434 if (ib_query_port(device, port_num, &port_attr))1435 return PR_NOT_SUPPORTED;1436 1437 if (ib_sa_opa_pathrecord_support(client, sa_dev, port_num))1438 return PR_OPA_SUPPORTED;1439 1440 if (port_attr.lid >= be16_to_cpu(IB_MULTICAST_LID_BASE))1441 return PR_NOT_SUPPORTED;1442 else1443 return PR_IB_SUPPORTED;1444}1445 1446static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,1447 int status, struct ib_sa_mad *mad)1448{1449 struct ib_sa_path_query *query =1450 container_of(sa_query, struct ib_sa_path_query, sa_query);1451 struct sa_path_rec rec = {};1452 1453 if (!mad) {1454 query->callback(status, NULL, 0, query->context);1455 return;1456 }1457 1458 if (sa_query->flags & IB_SA_QUERY_OPA) {1459 ib_unpack(opa_path_rec_table, ARRAY_SIZE(opa_path_rec_table),1460 mad->data, &rec);1461 rec.rec_type = SA_PATH_REC_TYPE_OPA;1462 query->callback(status, &rec, 1, query->context);1463 return;1464 }1465 1466 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),1467 mad->data, &rec);1468 rec.rec_type = SA_PATH_REC_TYPE_IB;1469 sa_path_set_dmac_zero(&rec);1470 1471 if (query->conv_pr) {1472 struct sa_path_rec opa;1473 1474 memset(&opa, 0, sizeof(struct sa_path_rec));1475 sa_convert_path_ib_to_opa(&opa, &rec);1476 query->callback(status, &opa, 1, query->context);1477 } else {1478 query->callback(status, &rec, 1, query->context);1479 }1480}1481 1482static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)1483{1484 struct ib_sa_path_query *query =1485 container_of(sa_query, struct ib_sa_path_query, sa_query);1486 1487 kfree(query->conv_pr);1488 kfree(query);1489}1490 1491/**1492 * ib_sa_path_rec_get - Start a Path get query1493 * @client:SA client1494 * @device:device to send query on1495 * @port_num: port number to send query on1496 * @rec:Path Record to send in query1497 * @comp_mask:component mask to send in query1498 * @timeout_ms:time to wait for response1499 * @gfp_mask:GFP mask to use for internal allocations1500 * @callback:function called when query completes, times out or is1501 * canceled1502 * @context:opaque user context passed to callback1503 * @sa_query:query context, used to cancel query1504 *1505 * Send a Path Record Get query to the SA to look up a path. The1506 * callback function will be called when the query completes (or1507 * fails); status is 0 for a successful response, -EINTR if the query1508 * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error1509 * occurred sending the query. The resp parameter of the callback is1510 * only valid if status is 0.1511 *1512 * If the return value of ib_sa_path_rec_get() is negative, it is an1513 * error code. Otherwise it is a query ID that can be used to cancel1514 * the query.1515 */1516int ib_sa_path_rec_get(struct ib_sa_client *client,1517 struct ib_device *device, u32 port_num,1518 struct sa_path_rec *rec,1519 ib_sa_comp_mask comp_mask,1520 unsigned long timeout_ms, gfp_t gfp_mask,1521 void (*callback)(int status,1522 struct sa_path_rec *resp,1523 unsigned int num_paths, void *context),1524 void *context,1525 struct ib_sa_query **sa_query)1526{1527 struct ib_sa_path_query *query;1528 struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);1529 struct ib_sa_port *port;1530 struct ib_mad_agent *agent;1531 struct ib_sa_mad *mad;1532 enum opa_pr_supported status;1533 int ret;1534 1535 if (!sa_dev)1536 return -ENODEV;1537 1538 if ((rec->rec_type != SA_PATH_REC_TYPE_IB) &&1539 (rec->rec_type != SA_PATH_REC_TYPE_OPA))1540 return -EINVAL;1541 1542 port = &sa_dev->port[port_num - sa_dev->start_port];1543 agent = port->agent;1544 1545 query = kzalloc(sizeof(*query), gfp_mask);1546 if (!query)1547 return -ENOMEM;1548 1549 query->sa_query.port = port;1550 if (rec->rec_type == SA_PATH_REC_TYPE_OPA) {1551 status = opa_pr_query_possible(client, sa_dev, device, port_num);1552 if (status == PR_NOT_SUPPORTED) {1553 ret = -EINVAL;1554 goto err1;1555 } else if (status == PR_OPA_SUPPORTED) {1556 query->sa_query.flags |= IB_SA_QUERY_OPA;1557 } else {1558 query->conv_pr =1559 kmalloc(sizeof(*query->conv_pr), gfp_mask);1560 if (!query->conv_pr) {1561 ret = -ENOMEM;1562 goto err1;1563 }1564 }1565 }1566 1567 ret = alloc_mad(&query->sa_query, gfp_mask);1568 if (ret)1569 goto err2;1570 1571 ib_sa_client_get(client);1572 query->sa_query.client = client;1573 query->callback = callback;1574 query->context = context;1575 1576 mad = query->sa_query.mad_buf->mad;1577 init_mad(&query->sa_query, agent);1578 1579 query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;1580 query->sa_query.release = ib_sa_path_rec_release;1581 mad->mad_hdr.method = IB_MGMT_METHOD_GET;1582 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);1583 mad->sa_hdr.comp_mask = comp_mask;1584 1585 if (query->sa_query.flags & IB_SA_QUERY_OPA) {1586 ib_pack(opa_path_rec_table, ARRAY_SIZE(opa_path_rec_table),1587 rec, mad->data);1588 } else if (query->conv_pr) {1589 sa_convert_path_opa_to_ib(query->conv_pr, rec);1590 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),1591 query->conv_pr, mad->data);1592 } else {1593 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),1594 rec, mad->data);1595 }1596 1597 *sa_query = &query->sa_query;1598 1599 query->sa_query.flags |= IB_SA_ENABLE_LOCAL_SERVICE;1600 query->sa_query.mad_buf->context[1] = (query->conv_pr) ?1601 query->conv_pr : rec;1602 1603 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);1604 if (ret < 0)1605 goto err3;1606 1607 return ret;1608 1609err3:1610 *sa_query = NULL;1611 ib_sa_client_put(query->sa_query.client);1612 free_mad(&query->sa_query);1613err2:1614 kfree(query->conv_pr);1615err1:1616 kfree(query);1617 return ret;1618}1619EXPORT_SYMBOL(ib_sa_path_rec_get);1620 1621static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,1622 int status, struct ib_sa_mad *mad)1623{1624 struct ib_sa_mcmember_query *query =1625 container_of(sa_query, struct ib_sa_mcmember_query, sa_query);1626 1627 if (mad) {1628 struct ib_sa_mcmember_rec rec;1629 1630 ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),1631 mad->data, &rec);1632 query->callback(status, &rec, query->context);1633 } else1634 query->callback(status, NULL, query->context);1635}1636 1637static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)1638{1639 kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));1640}1641 1642int ib_sa_mcmember_rec_query(struct ib_sa_client *client,1643 struct ib_device *device, u32 port_num,1644 u8 method,1645 struct ib_sa_mcmember_rec *rec,1646 ib_sa_comp_mask comp_mask,1647 unsigned long timeout_ms, gfp_t gfp_mask,1648 void (*callback)(int status,1649 struct ib_sa_mcmember_rec *resp,1650 void *context),1651 void *context,1652 struct ib_sa_query **sa_query)1653{1654 struct ib_sa_mcmember_query *query;1655 struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);1656 struct ib_sa_port *port;1657 struct ib_mad_agent *agent;1658 struct ib_sa_mad *mad;1659 int ret;1660 1661 if (!sa_dev)1662 return -ENODEV;1663 1664 port = &sa_dev->port[port_num - sa_dev->start_port];1665 agent = port->agent;1666 1667 query = kzalloc(sizeof(*query), gfp_mask);1668 if (!query)1669 return -ENOMEM;1670 1671 query->sa_query.port = port;1672 ret = alloc_mad(&query->sa_query, gfp_mask);1673 if (ret)1674 goto err1;1675 1676 ib_sa_client_get(client);1677 query->sa_query.client = client;1678 query->callback = callback;1679 query->context = context;1680 1681 mad = query->sa_query.mad_buf->mad;1682 init_mad(&query->sa_query, agent);1683 1684 query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;1685 query->sa_query.release = ib_sa_mcmember_rec_release;1686 mad->mad_hdr.method = method;1687 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);1688 mad->sa_hdr.comp_mask = comp_mask;1689 1690 ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),1691 rec, mad->data);1692 1693 *sa_query = &query->sa_query;1694 1695 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);1696 if (ret < 0)1697 goto err2;1698 1699 return ret;1700 1701err2:1702 *sa_query = NULL;1703 ib_sa_client_put(query->sa_query.client);1704 free_mad(&query->sa_query);1705 1706err1:1707 kfree(query);1708 return ret;1709}1710 1711/* Support GuidInfoRecord */1712static void ib_sa_guidinfo_rec_callback(struct ib_sa_query *sa_query,1713 int status, struct ib_sa_mad *mad)1714{1715 struct ib_sa_guidinfo_query *query =1716 container_of(sa_query, struct ib_sa_guidinfo_query, sa_query);1717 1718 if (mad) {1719 struct ib_sa_guidinfo_rec rec;1720 1721 ib_unpack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table),1722 mad->data, &rec);1723 query->callback(status, &rec, query->context);1724 } else1725 query->callback(status, NULL, query->context);1726}1727 1728static void ib_sa_guidinfo_rec_release(struct ib_sa_query *sa_query)1729{1730 kfree(container_of(sa_query, struct ib_sa_guidinfo_query, sa_query));1731}1732 1733int ib_sa_guid_info_rec_query(struct ib_sa_client *client,1734 struct ib_device *device, u32 port_num,1735 struct ib_sa_guidinfo_rec *rec,1736 ib_sa_comp_mask comp_mask, u8 method,1737 unsigned long timeout_ms, gfp_t gfp_mask,1738 void (*callback)(int status,1739 struct ib_sa_guidinfo_rec *resp,1740 void *context),1741 void *context,1742 struct ib_sa_query **sa_query)1743{1744 struct ib_sa_guidinfo_query *query;1745 struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);1746 struct ib_sa_port *port;1747 struct ib_mad_agent *agent;1748 struct ib_sa_mad *mad;1749 int ret;1750 1751 if (!sa_dev)1752 return -ENODEV;1753 1754 if (method != IB_MGMT_METHOD_GET &&1755 method != IB_MGMT_METHOD_SET &&1756 method != IB_SA_METHOD_DELETE) {1757 return -EINVAL;1758 }1759 1760 port = &sa_dev->port[port_num - sa_dev->start_port];1761 agent = port->agent;1762 1763 query = kzalloc(sizeof(*query), gfp_mask);1764 if (!query)1765 return -ENOMEM;1766 1767 query->sa_query.port = port;1768 ret = alloc_mad(&query->sa_query, gfp_mask);1769 if (ret)1770 goto err1;1771 1772 ib_sa_client_get(client);1773 query->sa_query.client = client;1774 query->callback = callback;1775 query->context = context;1776 1777 mad = query->sa_query.mad_buf->mad;1778 init_mad(&query->sa_query, agent);1779 1780 query->sa_query.callback = callback ? ib_sa_guidinfo_rec_callback : NULL;1781 query->sa_query.release = ib_sa_guidinfo_rec_release;1782 1783 mad->mad_hdr.method = method;1784 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_GUID_INFO_REC);1785 mad->sa_hdr.comp_mask = comp_mask;1786 1787 ib_pack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), rec,1788 mad->data);1789 1790 *sa_query = &query->sa_query;1791 1792 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);1793 if (ret < 0)1794 goto err2;1795 1796 return ret;1797 1798err2:1799 *sa_query = NULL;1800 ib_sa_client_put(query->sa_query.client);1801 free_mad(&query->sa_query);1802 1803err1:1804 kfree(query);1805 return ret;1806}1807EXPORT_SYMBOL(ib_sa_guid_info_rec_query);1808 1809struct ib_classport_info_context {1810 struct completion done;1811 struct ib_sa_query *sa_query;1812};1813 1814static void ib_classportinfo_cb(void *context)1815{1816 struct ib_classport_info_context *cb_ctx = context;1817 1818 complete(&cb_ctx->done);1819}1820 1821static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,1822 int status, struct ib_sa_mad *mad)1823{1824 unsigned long flags;1825 struct ib_sa_classport_info_query *query =1826 container_of(sa_query, struct ib_sa_classport_info_query, sa_query);1827 struct ib_sa_classport_cache *info = &sa_query->port->classport_info;1828 1829 if (mad) {1830 if (sa_query->flags & IB_SA_QUERY_OPA) {1831 struct opa_class_port_info rec;1832 1833 ib_unpack(opa_classport_info_rec_table,1834 ARRAY_SIZE(opa_classport_info_rec_table),1835 mad->data, &rec);1836 1837 spin_lock_irqsave(&sa_query->port->classport_lock,1838 flags);1839 if (!status && !info->valid) {1840 memcpy(&info->data.opa, &rec,1841 sizeof(info->data.opa));1842 1843 info->valid = true;1844 info->data.type = RDMA_CLASS_PORT_INFO_OPA;1845 }1846 spin_unlock_irqrestore(&sa_query->port->classport_lock,1847 flags);1848 1849 } else {1850 struct ib_class_port_info rec;1851 1852 ib_unpack(ib_classport_info_rec_table,1853 ARRAY_SIZE(ib_classport_info_rec_table),1854 mad->data, &rec);1855 1856 spin_lock_irqsave(&sa_query->port->classport_lock,1857 flags);1858 if (!status && !info->valid) {1859 memcpy(&info->data.ib, &rec,1860 sizeof(info->data.ib));1861 1862 info->valid = true;1863 info->data.type = RDMA_CLASS_PORT_INFO_IB;1864 }1865 spin_unlock_irqrestore(&sa_query->port->classport_lock,1866 flags);1867 }1868 }1869 query->callback(query->context);1870}1871 1872static void ib_sa_classport_info_rec_release(struct ib_sa_query *sa_query)1873{1874 kfree(container_of(sa_query, struct ib_sa_classport_info_query,1875 sa_query));1876}1877 1878static int ib_sa_classport_info_rec_query(struct ib_sa_port *port,1879 unsigned long timeout_ms,1880 void (*callback)(void *context),1881 void *context,1882 struct ib_sa_query **sa_query)1883{1884 struct ib_mad_agent *agent;1885 struct ib_sa_classport_info_query *query;1886 struct ib_sa_mad *mad;1887 gfp_t gfp_mask = GFP_KERNEL;1888 int ret;1889 1890 agent = port->agent;1891 1892 query = kzalloc(sizeof(*query), gfp_mask);1893 if (!query)1894 return -ENOMEM;1895 1896 query->sa_query.port = port;1897 query->sa_query.flags |= rdma_cap_opa_ah(port->agent->device,1898 port->port_num) ?1899 IB_SA_QUERY_OPA : 0;1900 ret = alloc_mad(&query->sa_query, gfp_mask);1901 if (ret)1902 goto err_free;1903 1904 query->callback = callback;1905 query->context = context;1906 1907 mad = query->sa_query.mad_buf->mad;1908 init_mad(&query->sa_query, agent);1909 1910 query->sa_query.callback = ib_sa_classport_info_rec_callback;1911 query->sa_query.release = ib_sa_classport_info_rec_release;1912 mad->mad_hdr.method = IB_MGMT_METHOD_GET;1913 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_CLASS_PORTINFO);1914 mad->sa_hdr.comp_mask = 0;1915 *sa_query = &query->sa_query;1916 1917 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);1918 if (ret < 0)1919 goto err_free_mad;1920 1921 return ret;1922 1923err_free_mad:1924 *sa_query = NULL;1925 free_mad(&query->sa_query);1926 1927err_free:1928 kfree(query);1929 return ret;1930}1931 1932static void update_ib_cpi(struct work_struct *work)1933{1934 struct ib_sa_port *port =1935 container_of(work, struct ib_sa_port, ib_cpi_work.work);1936 struct ib_classport_info_context *cb_context;1937 unsigned long flags;1938 int ret;1939 1940 /* If the classport info is valid, nothing1941 * to do here.1942 */1943 spin_lock_irqsave(&port->classport_lock, flags);1944 if (port->classport_info.valid) {1945 spin_unlock_irqrestore(&port->classport_lock, flags);1946 return;1947 }1948 spin_unlock_irqrestore(&port->classport_lock, flags);1949 1950 cb_context = kmalloc(sizeof(*cb_context), GFP_KERNEL);1951 if (!cb_context)1952 goto err_nomem;1953 1954 init_completion(&cb_context->done);1955 1956 ret = ib_sa_classport_info_rec_query(port, 3000,1957 ib_classportinfo_cb, cb_context,1958 &cb_context->sa_query);1959 if (ret < 0)1960 goto free_cb_err;1961 wait_for_completion(&cb_context->done);1962free_cb_err:1963 kfree(cb_context);1964 spin_lock_irqsave(&port->classport_lock, flags);1965 1966 /* If the classport info is still not valid, the query should have1967 * failed for some reason. Retry issuing the query1968 */1969 if (!port->classport_info.valid) {1970 port->classport_info.retry_cnt++;1971 if (port->classport_info.retry_cnt <=1972 IB_SA_CPI_MAX_RETRY_CNT) {1973 unsigned long delay =1974 msecs_to_jiffies(IB_SA_CPI_RETRY_WAIT);1975 1976 queue_delayed_work(ib_wq, &port->ib_cpi_work, delay);1977 }1978 }1979 spin_unlock_irqrestore(&port->classport_lock, flags);1980 1981err_nomem:1982 return;1983}1984 1985static void send_handler(struct ib_mad_agent *agent,1986 struct ib_mad_send_wc *mad_send_wc)1987{1988 struct ib_sa_query *query = mad_send_wc->send_buf->context[0];1989 unsigned long flags;1990 1991 if (query->callback)1992 switch (mad_send_wc->status) {1993 case IB_WC_SUCCESS:1994 /* No callback -- already got recv */1995 break;1996 case IB_WC_RESP_TIMEOUT_ERR:1997 query->callback(query, -ETIMEDOUT, NULL);1998 break;1999 case IB_WC_WR_FLUSH_ERR:2000 query->callback(query, -EINTR, NULL);2001 break;2002 default:2003 query->callback(query, -EIO, NULL);2004 break;2005 }2006 2007 xa_lock_irqsave(&queries, flags);2008 __xa_erase(&queries, query->id);2009 xa_unlock_irqrestore(&queries, flags);2010 2011 free_mad(query);2012 if (query->client)2013 ib_sa_client_put(query->client);2014 query->release(query);2015}2016 2017static void recv_handler(struct ib_mad_agent *mad_agent,2018 struct ib_mad_send_buf *send_buf,2019 struct ib_mad_recv_wc *mad_recv_wc)2020{2021 struct ib_sa_query *query;2022 2023 if (!send_buf)2024 return;2025 2026 query = send_buf->context[0];2027 if (query->callback) {2028 if (mad_recv_wc->wc->status == IB_WC_SUCCESS)2029 query->callback(query,2030 mad_recv_wc->recv_buf.mad->mad_hdr.status ?2031 -EINVAL : 0,2032 (struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);2033 else2034 query->callback(query, -EIO, NULL);2035 }2036 2037 ib_free_recv_mad(mad_recv_wc);2038}2039 2040static void update_sm_ah(struct work_struct *work)2041{2042 struct ib_sa_port *port =2043 container_of(work, struct ib_sa_port, update_task);2044 struct ib_sa_sm_ah *new_ah;2045 struct ib_port_attr port_attr;2046 struct rdma_ah_attr ah_attr;2047 bool grh_required;2048 2049 if (ib_query_port(port->agent->device, port->port_num, &port_attr)) {2050 pr_warn("Couldn't query port\n");2051 return;2052 }2053 2054 new_ah = kmalloc(sizeof(*new_ah), GFP_KERNEL);2055 if (!new_ah)2056 return;2057 2058 kref_init(&new_ah->ref);2059 new_ah->src_path_mask = (1 << port_attr.lmc) - 1;2060 2061 new_ah->pkey_index = 0;2062 if (ib_find_pkey(port->agent->device, port->port_num,2063 IB_DEFAULT_PKEY_FULL, &new_ah->pkey_index))2064 pr_err("Couldn't find index for default PKey\n");2065 2066 memset(&ah_attr, 0, sizeof(ah_attr));2067 ah_attr.type = rdma_ah_find_type(port->agent->device,2068 port->port_num);2069 rdma_ah_set_dlid(&ah_attr, port_attr.sm_lid);2070 rdma_ah_set_sl(&ah_attr, port_attr.sm_sl);2071 rdma_ah_set_port_num(&ah_attr, port->port_num);2072 2073 grh_required = rdma_is_grh_required(port->agent->device,2074 port->port_num);2075 2076 /*2077 * The OPA sm_lid of 0xFFFF needs special handling so that it can be2078 * differentiated from a permissive LID of 0xFFFF. We set the2079 * grh_required flag here so the SA can program the DGID in the2080 * address handle appropriately2081 */2082 if (ah_attr.type == RDMA_AH_ATTR_TYPE_OPA &&2083 (grh_required ||2084 port_attr.sm_lid == be16_to_cpu(IB_LID_PERMISSIVE)))2085 rdma_ah_set_make_grd(&ah_attr, true);2086 2087 if (ah_attr.type == RDMA_AH_ATTR_TYPE_IB && grh_required) {2088 rdma_ah_set_ah_flags(&ah_attr, IB_AH_GRH);2089 rdma_ah_set_subnet_prefix(&ah_attr,2090 cpu_to_be64(port_attr.subnet_prefix));2091 rdma_ah_set_interface_id(&ah_attr,2092 cpu_to_be64(IB_SA_WELL_KNOWN_GUID));2093 }2094 2095 new_ah->ah = rdma_create_ah(port->agent->qp->pd, &ah_attr,2096 RDMA_CREATE_AH_SLEEPABLE);2097 if (IS_ERR(new_ah->ah)) {2098 pr_warn("Couldn't create new SM AH\n");2099 kfree(new_ah);2100 return;2101 }2102 2103 spin_lock_irq(&port->ah_lock);2104 if (port->sm_ah)2105 kref_put(&port->sm_ah->ref, free_sm_ah);2106 port->sm_ah = new_ah;2107 spin_unlock_irq(&port->ah_lock);2108}2109 2110static void ib_sa_event(struct ib_event_handler *handler,2111 struct ib_event *event)2112{2113 if (event->event == IB_EVENT_PORT_ERR ||2114 event->event == IB_EVENT_PORT_ACTIVE ||2115 event->event == IB_EVENT_LID_CHANGE ||2116 event->event == IB_EVENT_PKEY_CHANGE ||2117 event->event == IB_EVENT_SM_CHANGE ||2118 event->event == IB_EVENT_CLIENT_REREGISTER) {2119 unsigned long flags;2120 struct ib_sa_device *sa_dev =2121 container_of(handler, typeof(*sa_dev), event_handler);2122 u32 port_num = event->element.port_num - sa_dev->start_port;2123 struct ib_sa_port *port = &sa_dev->port[port_num];2124 2125 if (!rdma_cap_ib_sa(handler->device, port->port_num))2126 return;2127 2128 spin_lock_irqsave(&port->ah_lock, flags);2129 if (port->sm_ah)2130 kref_put(&port->sm_ah->ref, free_sm_ah);2131 port->sm_ah = NULL;2132 spin_unlock_irqrestore(&port->ah_lock, flags);2133 2134 if (event->event == IB_EVENT_SM_CHANGE ||2135 event->event == IB_EVENT_CLIENT_REREGISTER ||2136 event->event == IB_EVENT_LID_CHANGE ||2137 event->event == IB_EVENT_PORT_ACTIVE) {2138 unsigned long delay =2139 msecs_to_jiffies(IB_SA_CPI_RETRY_WAIT);2140 2141 spin_lock_irqsave(&port->classport_lock, flags);2142 port->classport_info.valid = false;2143 port->classport_info.retry_cnt = 0;2144 spin_unlock_irqrestore(&port->classport_lock, flags);2145 queue_delayed_work(ib_wq,2146 &port->ib_cpi_work, delay);2147 }2148 queue_work(ib_wq, &sa_dev->port[port_num].update_task);2149 }2150}2151 2152static int ib_sa_add_one(struct ib_device *device)2153{2154 struct ib_sa_device *sa_dev;2155 int s, e, i;2156 int count = 0;2157 int ret;2158 2159 s = rdma_start_port(device);2160 e = rdma_end_port(device);2161 2162 sa_dev = kzalloc(struct_size(sa_dev, port,2163 size_add(size_sub(e, s), 1)),2164 GFP_KERNEL);2165 if (!sa_dev)2166 return -ENOMEM;2167 2168 sa_dev->start_port = s;2169 sa_dev->end_port = e;2170 2171 for (i = 0; i <= e - s; ++i) {2172 spin_lock_init(&sa_dev->port[i].ah_lock);2173 if (!rdma_cap_ib_sa(device, i + 1))2174 continue;2175 2176 sa_dev->port[i].sm_ah = NULL;2177 sa_dev->port[i].port_num = i + s;2178 2179 spin_lock_init(&sa_dev->port[i].classport_lock);2180 sa_dev->port[i].classport_info.valid = false;2181 2182 sa_dev->port[i].agent =2183 ib_register_mad_agent(device, i + s, IB_QPT_GSI,2184 NULL, 0, send_handler,2185 recv_handler, sa_dev, 0);2186 if (IS_ERR(sa_dev->port[i].agent)) {2187 ret = PTR_ERR(sa_dev->port[i].agent);2188 goto err;2189 }2190 2191 INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);2192 INIT_DELAYED_WORK(&sa_dev->port[i].ib_cpi_work,2193 update_ib_cpi);2194 2195 count++;2196 }2197 2198 if (!count) {2199 ret = -EOPNOTSUPP;2200 goto free;2201 }2202 2203 ib_set_client_data(device, &sa_client, sa_dev);2204 2205 /*2206 * We register our event handler after everything is set up,2207 * and then update our cached info after the event handler is2208 * registered to avoid any problems if a port changes state2209 * during our initialization.2210 */2211 2212 INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);2213 ib_register_event_handler(&sa_dev->event_handler);2214 2215 for (i = 0; i <= e - s; ++i) {2216 if (rdma_cap_ib_sa(device, i + 1))2217 update_sm_ah(&sa_dev->port[i].update_task);2218 }2219 2220 return 0;2221 2222err:2223 while (--i >= 0) {2224 if (rdma_cap_ib_sa(device, i + 1))2225 ib_unregister_mad_agent(sa_dev->port[i].agent);2226 }2227free:2228 kfree(sa_dev);2229 return ret;2230}2231 2232static void ib_sa_remove_one(struct ib_device *device, void *client_data)2233{2234 struct ib_sa_device *sa_dev = client_data;2235 int i;2236 2237 ib_unregister_event_handler(&sa_dev->event_handler);2238 flush_workqueue(ib_wq);2239 2240 for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {2241 if (rdma_cap_ib_sa(device, i + 1)) {2242 cancel_delayed_work_sync(&sa_dev->port[i].ib_cpi_work);2243 ib_unregister_mad_agent(sa_dev->port[i].agent);2244 if (sa_dev->port[i].sm_ah)2245 kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);2246 }2247 2248 }2249 2250 kfree(sa_dev);2251}2252 2253int ib_sa_init(void)2254{2255 int ret;2256 2257 get_random_bytes(&tid, sizeof tid);2258 2259 atomic_set(&ib_nl_sa_request_seq, 0);2260 2261 ret = ib_register_client(&sa_client);2262 if (ret) {2263 pr_err("Couldn't register ib_sa client\n");2264 goto err1;2265 }2266 2267 ret = mcast_init();2268 if (ret) {2269 pr_err("Couldn't initialize multicast handling\n");2270 goto err2;2271 }2272 2273 ib_nl_wq = alloc_ordered_workqueue("ib_nl_sa_wq", WQ_MEM_RECLAIM);2274 if (!ib_nl_wq) {2275 ret = -ENOMEM;2276 goto err3;2277 }2278 2279 INIT_DELAYED_WORK(&ib_nl_timed_work, ib_nl_request_timeout);2280 2281 return 0;2282 2283err3:2284 mcast_cleanup();2285err2:2286 ib_unregister_client(&sa_client);2287err1:2288 return ret;2289}2290 2291void ib_sa_cleanup(void)2292{2293 cancel_delayed_work(&ib_nl_timed_work);2294 destroy_workqueue(ib_nl_wq);2295 mcast_cleanup();2296 ib_unregister_client(&sa_client);2297 WARN_ON(!xa_empty(&queries));2298}2299