| .. | .. |
|---|
| 40 | 40 | #include <linux/slab.h> |
|---|
| 41 | 41 | #include <linux/dma-mapping.h> |
|---|
| 42 | 42 | #include <linux/kref.h> |
|---|
| 43 | | -#include <linux/idr.h> |
|---|
| 43 | +#include <linux/xarray.h> |
|---|
| 44 | 44 | #include <linux/workqueue.h> |
|---|
| 45 | 45 | #include <uapi/linux/if_ether.h> |
|---|
| 46 | 46 | #include <rdma/ib_pack.h> |
|---|
| .. | .. |
|---|
| 101 | 101 | struct ib_sa_device { |
|---|
| 102 | 102 | int start_port, end_port; |
|---|
| 103 | 103 | struct ib_event_handler event_handler; |
|---|
| 104 | | - struct ib_sa_port port[0]; |
|---|
| 104 | + struct ib_sa_port port[]; |
|---|
| 105 | 105 | }; |
|---|
| 106 | 106 | |
|---|
| 107 | 107 | struct ib_sa_query { |
|---|
| .. | .. |
|---|
| 174 | 174 | }; |
|---|
| 175 | 175 | |
|---|
| 176 | 176 | |
|---|
| 177 | | -static void ib_sa_add_one(struct ib_device *device); |
|---|
| 177 | +static int ib_sa_add_one(struct ib_device *device); |
|---|
| 178 | 178 | static void ib_sa_remove_one(struct ib_device *device, void *client_data); |
|---|
| 179 | 179 | |
|---|
| 180 | 180 | static struct ib_client sa_client = { |
|---|
| .. | .. |
|---|
| 183 | 183 | .remove = ib_sa_remove_one |
|---|
| 184 | 184 | }; |
|---|
| 185 | 185 | |
|---|
| 186 | | -static DEFINE_SPINLOCK(idr_lock); |
|---|
| 187 | | -static DEFINE_IDR(query_idr); |
|---|
| 186 | +static DEFINE_XARRAY_FLAGS(queries, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); |
|---|
| 188 | 187 | |
|---|
| 189 | 188 | static DEFINE_SPINLOCK(tid_lock); |
|---|
| 190 | 189 | static u32 tid; |
|---|
| 191 | 190 | |
|---|
| 192 | 191 | #define PATH_REC_FIELD(field) \ |
|---|
| 193 | 192 | .struct_offset_bytes = offsetof(struct sa_path_rec, field), \ |
|---|
| 194 | | - .struct_size_bytes = sizeof((struct sa_path_rec *)0)->field, \ |
|---|
| 193 | + .struct_size_bytes = sizeof_field(struct sa_path_rec, field), \ |
|---|
| 195 | 194 | .field_name = "sa_path_rec:" #field |
|---|
| 196 | 195 | |
|---|
| 197 | 196 | static const struct ib_field path_rec_table[] = { |
|---|
| .. | .. |
|---|
| 293 | 292 | .struct_offset_bytes = \ |
|---|
| 294 | 293 | offsetof(struct sa_path_rec, field), \ |
|---|
| 295 | 294 | .struct_size_bytes = \ |
|---|
| 296 | | - sizeof((struct sa_path_rec *)0)->field, \ |
|---|
| 295 | + sizeof_field(struct sa_path_rec, field), \ |
|---|
| 297 | 296 | .field_name = "sa_path_rec:" #field |
|---|
| 298 | 297 | |
|---|
| 299 | 298 | static const struct ib_field opa_path_rec_table[] = { |
|---|
| .. | .. |
|---|
| 421 | 420 | |
|---|
| 422 | 421 | #define MCMEMBER_REC_FIELD(field) \ |
|---|
| 423 | 422 | .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field), \ |
|---|
| 424 | | - .struct_size_bytes = sizeof ((struct ib_sa_mcmember_rec *) 0)->field, \ |
|---|
| 423 | + .struct_size_bytes = sizeof_field(struct ib_sa_mcmember_rec, field), \ |
|---|
| 425 | 424 | .field_name = "sa_mcmember_rec:" #field |
|---|
| 426 | 425 | |
|---|
| 427 | 426 | static const struct ib_field mcmember_rec_table[] = { |
|---|
| .. | .. |
|---|
| 505 | 504 | |
|---|
| 506 | 505 | #define SERVICE_REC_FIELD(field) \ |
|---|
| 507 | 506 | .struct_offset_bytes = offsetof(struct ib_sa_service_rec, field), \ |
|---|
| 508 | | - .struct_size_bytes = sizeof ((struct ib_sa_service_rec *) 0)->field, \ |
|---|
| 507 | + .struct_size_bytes = sizeof_field(struct ib_sa_service_rec, field), \ |
|---|
| 509 | 508 | .field_name = "sa_service_rec:" #field |
|---|
| 510 | 509 | |
|---|
| 511 | 510 | static const struct ib_field service_rec_table[] = { |
|---|
| .. | .. |
|---|
| 553 | 552 | |
|---|
| 554 | 553 | #define CLASSPORTINFO_REC_FIELD(field) \ |
|---|
| 555 | 554 | .struct_offset_bytes = offsetof(struct ib_class_port_info, field), \ |
|---|
| 556 | | - .struct_size_bytes = sizeof((struct ib_class_port_info *)0)->field, \ |
|---|
| 555 | + .struct_size_bytes = sizeof_field(struct ib_class_port_info, field), \ |
|---|
| 557 | 556 | .field_name = "ib_class_port_info:" #field |
|---|
| 558 | 557 | |
|---|
| 559 | 558 | static const struct ib_field ib_classport_info_rec_table[] = { |
|---|
| .. | .. |
|---|
| 631 | 630 | .struct_offset_bytes =\ |
|---|
| 632 | 631 | offsetof(struct opa_class_port_info, field), \ |
|---|
| 633 | 632 | .struct_size_bytes = \ |
|---|
| 634 | | - sizeof((struct opa_class_port_info *)0)->field, \ |
|---|
| 633 | + sizeof_field(struct opa_class_port_info, field), \ |
|---|
| 635 | 634 | .field_name = "opa_class_port_info:" #field |
|---|
| 636 | 635 | |
|---|
| 637 | 636 | static const struct ib_field opa_classport_info_rec_table[] = { |
|---|
| .. | .. |
|---|
| 711 | 710 | |
|---|
| 712 | 711 | #define GUIDINFO_REC_FIELD(field) \ |
|---|
| 713 | 712 | .struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \ |
|---|
| 714 | | - .struct_size_bytes = sizeof((struct ib_sa_guidinfo_rec *) 0)->field, \ |
|---|
| 713 | + .struct_size_bytes = sizeof_field(struct ib_sa_guidinfo_rec, field), \ |
|---|
| 715 | 714 | .field_name = "sa_guidinfo_rec:" #field |
|---|
| 716 | 715 | |
|---|
| 717 | 716 | static const struct ib_field guidinfo_rec_table[] = { |
|---|
| .. | .. |
|---|
| 761 | 760 | |
|---|
| 762 | 761 | /* Construct the family header first */ |
|---|
| 763 | 762 | header = skb_put(skb, NLMSG_ALIGN(sizeof(*header))); |
|---|
| 764 | | - memcpy(header->device_name, query->port->agent->device->name, |
|---|
| 765 | | - LS_DEVICE_NAME_MAX); |
|---|
| 763 | + strscpy_pad(header->device_name, |
|---|
| 764 | + dev_name(&query->port->agent->device->dev), |
|---|
| 765 | + LS_DEVICE_NAME_MAX); |
|---|
| 766 | 766 | header->port_num = query->port->port_num; |
|---|
| 767 | 767 | |
|---|
| 768 | 768 | if ((comp_mask & IB_SA_PATH_REC_REVERSIBLE) && |
|---|
| .. | .. |
|---|
| 830 | 830 | return len; |
|---|
| 831 | 831 | } |
|---|
| 832 | 832 | |
|---|
| 833 | | -static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask) |
|---|
| 833 | +static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask) |
|---|
| 834 | 834 | { |
|---|
| 835 | 835 | struct sk_buff *skb = NULL; |
|---|
| 836 | 836 | struct nlmsghdr *nlh; |
|---|
| 837 | 837 | void *data; |
|---|
| 838 | | - int ret = 0; |
|---|
| 839 | 838 | struct ib_sa_mad *mad; |
|---|
| 840 | 839 | int len; |
|---|
| 840 | + unsigned long flags; |
|---|
| 841 | + unsigned long delay; |
|---|
| 842 | + gfp_t gfp_flag; |
|---|
| 843 | + int ret; |
|---|
| 844 | + |
|---|
| 845 | + INIT_LIST_HEAD(&query->list); |
|---|
| 846 | + query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq); |
|---|
| 841 | 847 | |
|---|
| 842 | 848 | mad = query->mad_buf->mad; |
|---|
| 843 | 849 | len = ib_nl_get_path_rec_attrs_len(mad->sa_hdr.comp_mask); |
|---|
| .. | .. |
|---|
| 862 | 868 | /* Repair the nlmsg header length */ |
|---|
| 863 | 869 | nlmsg_end(skb, nlh); |
|---|
| 864 | 870 | |
|---|
| 865 | | - ret = rdma_nl_multicast(skb, RDMA_NL_GROUP_LS, gfp_mask); |
|---|
| 866 | | - if (!ret) |
|---|
| 867 | | - ret = len; |
|---|
| 868 | | - else |
|---|
| 869 | | - ret = 0; |
|---|
| 871 | + gfp_flag = ((gfp_mask & GFP_ATOMIC) == GFP_ATOMIC) ? GFP_ATOMIC : |
|---|
| 872 | + GFP_NOWAIT; |
|---|
| 870 | 873 | |
|---|
| 871 | | - return ret; |
|---|
| 872 | | -} |
|---|
| 873 | | - |
|---|
| 874 | | -static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask) |
|---|
| 875 | | -{ |
|---|
| 876 | | - unsigned long flags; |
|---|
| 877 | | - unsigned long delay; |
|---|
| 878 | | - int ret; |
|---|
| 879 | | - |
|---|
| 880 | | - INIT_LIST_HEAD(&query->list); |
|---|
| 881 | | - query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq); |
|---|
| 882 | | - |
|---|
| 883 | | - /* Put the request on the list first.*/ |
|---|
| 884 | 874 | spin_lock_irqsave(&ib_nl_request_lock, flags); |
|---|
| 875 | + ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_flag); |
|---|
| 876 | + |
|---|
| 877 | + if (ret) |
|---|
| 878 | + goto out; |
|---|
| 879 | + |
|---|
| 880 | + /* Put the request on the list.*/ |
|---|
| 885 | 881 | delay = msecs_to_jiffies(sa_local_svc_timeout_ms); |
|---|
| 886 | 882 | query->timeout = delay + jiffies; |
|---|
| 887 | 883 | list_add_tail(&query->list, &ib_nl_request_list); |
|---|
| 888 | 884 | /* Start the timeout if this is the only request */ |
|---|
| 889 | 885 | if (ib_nl_request_list.next == &query->list) |
|---|
| 890 | 886 | queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay); |
|---|
| 891 | | - spin_unlock_irqrestore(&ib_nl_request_lock, flags); |
|---|
| 892 | 887 | |
|---|
| 893 | | - ret = ib_nl_send_msg(query, gfp_mask); |
|---|
| 894 | | - if (ret <= 0) { |
|---|
| 895 | | - ret = -EIO; |
|---|
| 896 | | - /* Remove the request */ |
|---|
| 897 | | - spin_lock_irqsave(&ib_nl_request_lock, flags); |
|---|
| 898 | | - list_del(&query->list); |
|---|
| 899 | | - spin_unlock_irqrestore(&ib_nl_request_lock, flags); |
|---|
| 900 | | - } else { |
|---|
| 901 | | - ret = 0; |
|---|
| 902 | | - } |
|---|
| 888 | +out: |
|---|
| 889 | + spin_unlock_irqrestore(&ib_nl_request_lock, flags); |
|---|
| 903 | 890 | |
|---|
| 904 | 891 | return ret; |
|---|
| 905 | 892 | } |
|---|
| .. | .. |
|---|
| 1037 | 1024 | !(NETLINK_CB(skb).sk)) |
|---|
| 1038 | 1025 | return -EPERM; |
|---|
| 1039 | 1026 | |
|---|
| 1040 | | - ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh), |
|---|
| 1041 | | - nlmsg_len(nlh), ib_nl_policy, NULL); |
|---|
| 1027 | + ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh), |
|---|
| 1028 | + nlmsg_len(nlh), ib_nl_policy, NULL); |
|---|
| 1042 | 1029 | attr = (const struct nlattr *)tb[LS_NLA_TYPE_TIMEOUT]; |
|---|
| 1043 | 1030 | if (ret || !attr) |
|---|
| 1044 | 1031 | goto settimeout_out; |
|---|
| .. | .. |
|---|
| 1089 | 1076 | if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR) |
|---|
| 1090 | 1077 | return 0; |
|---|
| 1091 | 1078 | |
|---|
| 1092 | | - ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh), |
|---|
| 1093 | | - nlmsg_len(nlh), ib_nl_policy, NULL); |
|---|
| 1079 | + ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh), |
|---|
| 1080 | + nlmsg_len(nlh), ib_nl_policy, NULL); |
|---|
| 1094 | 1081 | if (ret) |
|---|
| 1095 | 1082 | return 0; |
|---|
| 1096 | 1083 | |
|---|
| .. | .. |
|---|
| 1156 | 1143 | { |
|---|
| 1157 | 1144 | struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref); |
|---|
| 1158 | 1145 | |
|---|
| 1159 | | - rdma_destroy_ah(sm_ah->ah); |
|---|
| 1146 | + rdma_destroy_ah(sm_ah->ah, 0); |
|---|
| 1160 | 1147 | kfree(sm_ah); |
|---|
| 1161 | 1148 | } |
|---|
| 1162 | 1149 | |
|---|
| .. | .. |
|---|
| 1189 | 1176 | struct ib_mad_agent *agent; |
|---|
| 1190 | 1177 | struct ib_mad_send_buf *mad_buf; |
|---|
| 1191 | 1178 | |
|---|
| 1192 | | - spin_lock_irqsave(&idr_lock, flags); |
|---|
| 1193 | | - if (idr_find(&query_idr, id) != query) { |
|---|
| 1194 | | - spin_unlock_irqrestore(&idr_lock, flags); |
|---|
| 1179 | + xa_lock_irqsave(&queries, flags); |
|---|
| 1180 | + if (xa_load(&queries, id) != query) { |
|---|
| 1181 | + xa_unlock_irqrestore(&queries, flags); |
|---|
| 1195 | 1182 | return; |
|---|
| 1196 | 1183 | } |
|---|
| 1197 | 1184 | agent = query->port->agent; |
|---|
| 1198 | 1185 | mad_buf = query->mad_buf; |
|---|
| 1199 | | - spin_unlock_irqrestore(&idr_lock, flags); |
|---|
| 1186 | + xa_unlock_irqrestore(&queries, flags); |
|---|
| 1200 | 1187 | |
|---|
| 1201 | 1188 | /* |
|---|
| 1202 | 1189 | * If the query is still on the netlink request list, schedule |
|---|
| .. | .. |
|---|
| 1225 | 1212 | spin_unlock_irqrestore(&port->ah_lock, flags); |
|---|
| 1226 | 1213 | |
|---|
| 1227 | 1214 | return src_path_mask; |
|---|
| 1228 | | -} |
|---|
| 1229 | | - |
|---|
| 1230 | | -static int roce_resolve_route_from_path(struct sa_path_rec *rec, |
|---|
| 1231 | | - const struct ib_gid_attr *attr) |
|---|
| 1232 | | -{ |
|---|
| 1233 | | - struct rdma_dev_addr dev_addr = {}; |
|---|
| 1234 | | - union { |
|---|
| 1235 | | - struct sockaddr_in _sockaddr_in; |
|---|
| 1236 | | - struct sockaddr_in6 _sockaddr_in6; |
|---|
| 1237 | | - } sgid_addr, dgid_addr; |
|---|
| 1238 | | - int ret; |
|---|
| 1239 | | - |
|---|
| 1240 | | - if (rec->roce.route_resolved) |
|---|
| 1241 | | - return 0; |
|---|
| 1242 | | - if (!attr || !attr->ndev) |
|---|
| 1243 | | - return -EINVAL; |
|---|
| 1244 | | - |
|---|
| 1245 | | - dev_addr.bound_dev_if = attr->ndev->ifindex; |
|---|
| 1246 | | - /* TODO: Use net from the ib_gid_attr once it is added to it, |
|---|
| 1247 | | - * until than, limit itself to init_net. |
|---|
| 1248 | | - */ |
|---|
| 1249 | | - dev_addr.net = &init_net; |
|---|
| 1250 | | - |
|---|
| 1251 | | - rdma_gid2ip((struct sockaddr *)&sgid_addr, &rec->sgid); |
|---|
| 1252 | | - rdma_gid2ip((struct sockaddr *)&dgid_addr, &rec->dgid); |
|---|
| 1253 | | - |
|---|
| 1254 | | - /* validate the route */ |
|---|
| 1255 | | - ret = rdma_resolve_ip_route((struct sockaddr *)&sgid_addr, |
|---|
| 1256 | | - (struct sockaddr *)&dgid_addr, &dev_addr); |
|---|
| 1257 | | - if (ret) |
|---|
| 1258 | | - return ret; |
|---|
| 1259 | | - |
|---|
| 1260 | | - if ((dev_addr.network == RDMA_NETWORK_IPV4 || |
|---|
| 1261 | | - dev_addr.network == RDMA_NETWORK_IPV6) && |
|---|
| 1262 | | - rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2) |
|---|
| 1263 | | - return -EINVAL; |
|---|
| 1264 | | - |
|---|
| 1265 | | - rec->roce.route_resolved = true; |
|---|
| 1266 | | - return 0; |
|---|
| 1267 | 1215 | } |
|---|
| 1268 | 1216 | |
|---|
| 1269 | 1217 | static int init_ah_attr_grh_fields(struct ib_device *device, u8 port_num, |
|---|
| .. | .. |
|---|
| 1295 | 1243 | * @port_num: Port on the specified device. |
|---|
| 1296 | 1244 | * @rec: path record entry to use for ah attributes initialization. |
|---|
| 1297 | 1245 | * @ah_attr: address handle attributes to initialization from path record. |
|---|
| 1298 | | - * @sgid_attr: SGID attribute to consider during initialization. |
|---|
| 1246 | + * @gid_attr: SGID attribute to consider during initialization. |
|---|
| 1299 | 1247 | * |
|---|
| 1300 | 1248 | * When ib_init_ah_attr_from_path() returns success, |
|---|
| 1301 | 1249 | * (a) for IB link layer it optionally contains a reference to SGID attribute |
|---|
| .. | .. |
|---|
| 1408 | 1356 | spin_unlock_irqrestore(&tid_lock, flags); |
|---|
| 1409 | 1357 | } |
|---|
| 1410 | 1358 | |
|---|
| 1411 | | -static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) |
|---|
| 1359 | +static int send_mad(struct ib_sa_query *query, unsigned long timeout_ms, |
|---|
| 1360 | + gfp_t gfp_mask) |
|---|
| 1412 | 1361 | { |
|---|
| 1413 | | - bool preload = gfpflags_allow_blocking(gfp_mask); |
|---|
| 1414 | 1362 | unsigned long flags; |
|---|
| 1415 | 1363 | int ret, id; |
|---|
| 1416 | 1364 | |
|---|
| 1417 | | - if (preload) |
|---|
| 1418 | | - idr_preload(gfp_mask); |
|---|
| 1419 | | - spin_lock_irqsave(&idr_lock, flags); |
|---|
| 1420 | | - |
|---|
| 1421 | | - id = idr_alloc(&query_idr, query, 0, 0, GFP_NOWAIT); |
|---|
| 1422 | | - |
|---|
| 1423 | | - spin_unlock_irqrestore(&idr_lock, flags); |
|---|
| 1424 | | - if (preload) |
|---|
| 1425 | | - idr_preload_end(); |
|---|
| 1426 | | - if (id < 0) |
|---|
| 1427 | | - return id; |
|---|
| 1365 | + xa_lock_irqsave(&queries, flags); |
|---|
| 1366 | + ret = __xa_alloc(&queries, &id, query, xa_limit_32b, gfp_mask); |
|---|
| 1367 | + xa_unlock_irqrestore(&queries, flags); |
|---|
| 1368 | + if (ret < 0) |
|---|
| 1369 | + return ret; |
|---|
| 1428 | 1370 | |
|---|
| 1429 | 1371 | query->mad_buf->timeout_ms = timeout_ms; |
|---|
| 1430 | 1372 | query->mad_buf->context[0] = query; |
|---|
| .. | .. |
|---|
| 1432 | 1374 | |
|---|
| 1433 | 1375 | if ((query->flags & IB_SA_ENABLE_LOCAL_SERVICE) && |
|---|
| 1434 | 1376 | (!(query->flags & IB_SA_QUERY_OPA))) { |
|---|
| 1435 | | - if (!rdma_nl_chk_listeners(RDMA_NL_GROUP_LS)) { |
|---|
| 1377 | + if (rdma_nl_chk_listeners(RDMA_NL_GROUP_LS)) { |
|---|
| 1436 | 1378 | if (!ib_nl_make_request(query, gfp_mask)) |
|---|
| 1437 | 1379 | return id; |
|---|
| 1438 | 1380 | } |
|---|
| .. | .. |
|---|
| 1441 | 1383 | |
|---|
| 1442 | 1384 | ret = ib_post_send_mad(query->mad_buf, NULL); |
|---|
| 1443 | 1385 | if (ret) { |
|---|
| 1444 | | - spin_lock_irqsave(&idr_lock, flags); |
|---|
| 1445 | | - idr_remove(&query_idr, id); |
|---|
| 1446 | | - spin_unlock_irqrestore(&idr_lock, flags); |
|---|
| 1386 | + xa_lock_irqsave(&queries, flags); |
|---|
| 1387 | + __xa_erase(&queries, id); |
|---|
| 1388 | + xa_unlock_irqrestore(&queries, flags); |
|---|
| 1447 | 1389 | } |
|---|
| 1448 | 1390 | |
|---|
| 1449 | 1391 | /* |
|---|
| .. | .. |
|---|
| 1467 | 1409 | EXPORT_SYMBOL(ib_sa_pack_path); |
|---|
| 1468 | 1410 | |
|---|
| 1469 | 1411 | static bool ib_sa_opa_pathrecord_support(struct ib_sa_client *client, |
|---|
| 1470 | | - struct ib_device *device, |
|---|
| 1412 | + struct ib_sa_device *sa_dev, |
|---|
| 1471 | 1413 | u8 port_num) |
|---|
| 1472 | 1414 | { |
|---|
| 1473 | | - struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); |
|---|
| 1474 | 1415 | struct ib_sa_port *port; |
|---|
| 1475 | 1416 | unsigned long flags; |
|---|
| 1476 | 1417 | bool ret = false; |
|---|
| 1477 | | - |
|---|
| 1478 | | - if (!sa_dev) |
|---|
| 1479 | | - return ret; |
|---|
| 1480 | 1418 | |
|---|
| 1481 | 1419 | port = &sa_dev->port[port_num - sa_dev->start_port]; |
|---|
| 1482 | 1420 | spin_lock_irqsave(&port->classport_lock, flags); |
|---|
| .. | .. |
|---|
| 1505 | 1443 | * query is possible. |
|---|
| 1506 | 1444 | */ |
|---|
| 1507 | 1445 | static int opa_pr_query_possible(struct ib_sa_client *client, |
|---|
| 1508 | | - struct ib_device *device, |
|---|
| 1509 | | - u8 port_num, |
|---|
| 1446 | + struct ib_sa_device *sa_dev, |
|---|
| 1447 | + struct ib_device *device, u8 port_num, |
|---|
| 1510 | 1448 | struct sa_path_rec *rec) |
|---|
| 1511 | 1449 | { |
|---|
| 1512 | 1450 | struct ib_port_attr port_attr; |
|---|
| .. | .. |
|---|
| 1514 | 1452 | if (ib_query_port(device, port_num, &port_attr)) |
|---|
| 1515 | 1453 | return PR_NOT_SUPPORTED; |
|---|
| 1516 | 1454 | |
|---|
| 1517 | | - if (ib_sa_opa_pathrecord_support(client, device, port_num)) |
|---|
| 1455 | + if (ib_sa_opa_pathrecord_support(client, sa_dev, port_num)) |
|---|
| 1518 | 1456 | return PR_OPA_SUPPORTED; |
|---|
| 1519 | 1457 | |
|---|
| 1520 | 1458 | if (port_attr.lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) |
|---|
| .. | .. |
|---|
| 1598 | 1536 | struct ib_device *device, u8 port_num, |
|---|
| 1599 | 1537 | struct sa_path_rec *rec, |
|---|
| 1600 | 1538 | ib_sa_comp_mask comp_mask, |
|---|
| 1601 | | - int timeout_ms, gfp_t gfp_mask, |
|---|
| 1539 | + unsigned long timeout_ms, gfp_t gfp_mask, |
|---|
| 1602 | 1540 | void (*callback)(int status, |
|---|
| 1603 | 1541 | struct sa_path_rec *resp, |
|---|
| 1604 | 1542 | void *context), |
|---|
| .. | .. |
|---|
| 1629 | 1567 | |
|---|
| 1630 | 1568 | query->sa_query.port = port; |
|---|
| 1631 | 1569 | if (rec->rec_type == SA_PATH_REC_TYPE_OPA) { |
|---|
| 1632 | | - status = opa_pr_query_possible(client, device, port_num, rec); |
|---|
| 1570 | + status = opa_pr_query_possible(client, sa_dev, device, port_num, |
|---|
| 1571 | + rec); |
|---|
| 1633 | 1572 | if (status == PR_NOT_SUPPORTED) { |
|---|
| 1634 | 1573 | ret = -EINVAL; |
|---|
| 1635 | 1574 | goto err1; |
|---|
| .. | .. |
|---|
| 1752 | 1691 | struct ib_device *device, u8 port_num, u8 method, |
|---|
| 1753 | 1692 | struct ib_sa_service_rec *rec, |
|---|
| 1754 | 1693 | ib_sa_comp_mask comp_mask, |
|---|
| 1755 | | - int timeout_ms, gfp_t gfp_mask, |
|---|
| 1694 | + unsigned long timeout_ms, gfp_t gfp_mask, |
|---|
| 1756 | 1695 | void (*callback)(int status, |
|---|
| 1757 | 1696 | struct ib_sa_service_rec *resp, |
|---|
| 1758 | 1697 | void *context), |
|---|
| .. | .. |
|---|
| 1849 | 1788 | u8 method, |
|---|
| 1850 | 1789 | struct ib_sa_mcmember_rec *rec, |
|---|
| 1851 | 1790 | ib_sa_comp_mask comp_mask, |
|---|
| 1852 | | - int timeout_ms, gfp_t gfp_mask, |
|---|
| 1791 | + unsigned long timeout_ms, gfp_t gfp_mask, |
|---|
| 1853 | 1792 | void (*callback)(int status, |
|---|
| 1854 | 1793 | struct ib_sa_mcmember_rec *resp, |
|---|
| 1855 | 1794 | void *context), |
|---|
| .. | .. |
|---|
| 1940 | 1879 | struct ib_device *device, u8 port_num, |
|---|
| 1941 | 1880 | struct ib_sa_guidinfo_rec *rec, |
|---|
| 1942 | 1881 | ib_sa_comp_mask comp_mask, u8 method, |
|---|
| 1943 | | - int timeout_ms, gfp_t gfp_mask, |
|---|
| 1882 | + unsigned long timeout_ms, gfp_t gfp_mask, |
|---|
| 1944 | 1883 | void (*callback)(int status, |
|---|
| 1945 | 1884 | struct ib_sa_guidinfo_rec *resp, |
|---|
| 1946 | 1885 | void *context), |
|---|
| .. | .. |
|---|
| 2107 | 2046 | } |
|---|
| 2108 | 2047 | |
|---|
| 2109 | 2048 | static int ib_sa_classport_info_rec_query(struct ib_sa_port *port, |
|---|
| 2110 | | - int timeout_ms, |
|---|
| 2049 | + unsigned long timeout_ms, |
|---|
| 2111 | 2050 | void (*callback)(void *context), |
|---|
| 2112 | 2051 | void *context, |
|---|
| 2113 | 2052 | struct ib_sa_query **sa_query) |
|---|
| .. | .. |
|---|
| 2235 | 2174 | break; |
|---|
| 2236 | 2175 | } |
|---|
| 2237 | 2176 | |
|---|
| 2238 | | - spin_lock_irqsave(&idr_lock, flags); |
|---|
| 2239 | | - idr_remove(&query_idr, query->id); |
|---|
| 2240 | | - spin_unlock_irqrestore(&idr_lock, flags); |
|---|
| 2177 | + xa_lock_irqsave(&queries, flags); |
|---|
| 2178 | + __xa_erase(&queries, query->id); |
|---|
| 2179 | + xa_unlock_irqrestore(&queries, flags); |
|---|
| 2241 | 2180 | |
|---|
| 2242 | 2181 | free_mad(query); |
|---|
| 2243 | 2182 | if (query->client) |
|---|
| .. | .. |
|---|
| 2323 | 2262 | cpu_to_be64(IB_SA_WELL_KNOWN_GUID)); |
|---|
| 2324 | 2263 | } |
|---|
| 2325 | 2264 | |
|---|
| 2326 | | - new_ah->ah = rdma_create_ah(port->agent->qp->pd, &ah_attr); |
|---|
| 2265 | + new_ah->ah = rdma_create_ah(port->agent->qp->pd, &ah_attr, |
|---|
| 2266 | + RDMA_CREATE_AH_SLEEPABLE); |
|---|
| 2327 | 2267 | if (IS_ERR(new_ah->ah)) { |
|---|
| 2328 | 2268 | pr_warn("Couldn't create new SM AH\n"); |
|---|
| 2329 | 2269 | kfree(new_ah); |
|---|
| .. | .. |
|---|
| 2379 | 2319 | } |
|---|
| 2380 | 2320 | } |
|---|
| 2381 | 2321 | |
|---|
| 2382 | | -static void ib_sa_add_one(struct ib_device *device) |
|---|
| 2322 | +static int ib_sa_add_one(struct ib_device *device) |
|---|
| 2383 | 2323 | { |
|---|
| 2384 | 2324 | struct ib_sa_device *sa_dev; |
|---|
| 2385 | 2325 | int s, e, i; |
|---|
| 2386 | 2326 | int count = 0; |
|---|
| 2327 | + int ret; |
|---|
| 2387 | 2328 | |
|---|
| 2388 | 2329 | s = rdma_start_port(device); |
|---|
| 2389 | 2330 | e = rdma_end_port(device); |
|---|
| 2390 | 2331 | |
|---|
| 2391 | | - sa_dev = kzalloc(sizeof *sa_dev + |
|---|
| 2392 | | - (e - s + 1) * sizeof (struct ib_sa_port), |
|---|
| 2393 | | - GFP_KERNEL); |
|---|
| 2332 | + sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL); |
|---|
| 2394 | 2333 | if (!sa_dev) |
|---|
| 2395 | | - return; |
|---|
| 2334 | + return -ENOMEM; |
|---|
| 2396 | 2335 | |
|---|
| 2397 | 2336 | sa_dev->start_port = s; |
|---|
| 2398 | 2337 | sa_dev->end_port = e; |
|---|
| .. | .. |
|---|
| 2412 | 2351 | ib_register_mad_agent(device, i + s, IB_QPT_GSI, |
|---|
| 2413 | 2352 | NULL, 0, send_handler, |
|---|
| 2414 | 2353 | recv_handler, sa_dev, 0); |
|---|
| 2415 | | - if (IS_ERR(sa_dev->port[i].agent)) |
|---|
| 2354 | + if (IS_ERR(sa_dev->port[i].agent)) { |
|---|
| 2355 | + ret = PTR_ERR(sa_dev->port[i].agent); |
|---|
| 2416 | 2356 | goto err; |
|---|
| 2357 | + } |
|---|
| 2417 | 2358 | |
|---|
| 2418 | 2359 | INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); |
|---|
| 2419 | 2360 | INIT_DELAYED_WORK(&sa_dev->port[i].ib_cpi_work, |
|---|
| .. | .. |
|---|
| 2422 | 2363 | count++; |
|---|
| 2423 | 2364 | } |
|---|
| 2424 | 2365 | |
|---|
| 2425 | | - if (!count) |
|---|
| 2366 | + if (!count) { |
|---|
| 2367 | + ret = -EOPNOTSUPP; |
|---|
| 2426 | 2368 | goto free; |
|---|
| 2369 | + } |
|---|
| 2427 | 2370 | |
|---|
| 2428 | 2371 | ib_set_client_data(device, &sa_client, sa_dev); |
|---|
| 2429 | 2372 | |
|---|
| .. | .. |
|---|
| 2442 | 2385 | update_sm_ah(&sa_dev->port[i].update_task); |
|---|
| 2443 | 2386 | } |
|---|
| 2444 | 2387 | |
|---|
| 2445 | | - return; |
|---|
| 2388 | + return 0; |
|---|
| 2446 | 2389 | |
|---|
| 2447 | 2390 | err: |
|---|
| 2448 | 2391 | while (--i >= 0) { |
|---|
| .. | .. |
|---|
| 2451 | 2394 | } |
|---|
| 2452 | 2395 | free: |
|---|
| 2453 | 2396 | kfree(sa_dev); |
|---|
| 2454 | | - return; |
|---|
| 2397 | + return ret; |
|---|
| 2455 | 2398 | } |
|---|
| 2456 | 2399 | |
|---|
| 2457 | 2400 | static void ib_sa_remove_one(struct ib_device *device, void *client_data) |
|---|
| 2458 | 2401 | { |
|---|
| 2459 | 2402 | struct ib_sa_device *sa_dev = client_data; |
|---|
| 2460 | 2403 | int i; |
|---|
| 2461 | | - |
|---|
| 2462 | | - if (!sa_dev) |
|---|
| 2463 | | - return; |
|---|
| 2464 | 2404 | |
|---|
| 2465 | 2405 | ib_unregister_event_handler(&sa_dev->event_handler); |
|---|
| 2466 | 2406 | flush_workqueue(ib_wq); |
|---|
| .. | .. |
|---|
| 2523 | 2463 | destroy_workqueue(ib_nl_wq); |
|---|
| 2524 | 2464 | mcast_cleanup(); |
|---|
| 2525 | 2465 | ib_unregister_client(&sa_client); |
|---|
| 2526 | | - idr_destroy(&query_idr); |
|---|
| 2466 | + WARN_ON(!xa_empty(&queries)); |
|---|
| 2527 | 2467 | } |
|---|