Merge tag 'rdma-for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
Pull InfiniBand/RDMA changes from Roland Dreier: - Updates to the qib low-level driver - First chunk of changes for SR-IOV support for mlx4 IB - RDMA CM support for IPv6-only binding - Other misc cleanups and fixes Fix up some add-add conflicts in include/linux/mlx4/device.h and drivers/net/ethernet/mellanox/mlx4/main.c * tag 'rdma-for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (30 commits) IB/qib: checkpatch fixes IB/qib: Add congestion control agent implementation IB/qib: Reduce sdma_lock contention IB/qib: Fix an incorrect log message IB/qib: Fix QP RCU sparse warnings mlx4: Put physical GID and P_Key table sizes in mlx4_phys_caps struct and paravirtualize them mlx4_core: Allow guests to have IB ports mlx4_core: Implement mechanism for reserved Q_Keys net/mlx4_core: Free ICM table in case of error IB/cm: Destroy idr as part of the module init error flow mlx4_core: Remove double function declarations IB/mlx4: Fill the masked_atomic_cap attribute in query device IB/mthca: Fill in sq_sig_type in query QP IB/mthca: Warning about event for non-existent QPs should show event type IB/qib: Fix sparse RCU warnings in qib_keys.c net/mlx4_core: Initialize IB port capabilities for all slaves mlx4: Use port management change event instead of smp_snoop IB/qib: RCU locking for MR validation IB/qib: Avoid returning EBUSY from MR deregister IB/qib: Fix UC MR refs for immediate operations ...
Este commit está contenido en:
@@ -129,7 +129,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
|
||||
dev_put(dev);
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
case AF_INET6:
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(&init_net, dev) {
|
||||
@@ -243,7 +243,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static int addr6_resolve(struct sockaddr_in6 *src_in,
|
||||
struct sockaddr_in6 *dst_in,
|
||||
struct rdma_dev_addr *addr)
|
||||
|
@@ -3848,24 +3848,28 @@ static int __init ib_cm_init(void)
|
||||
INIT_LIST_HEAD(&cm.timewait_list);
|
||||
|
||||
ret = class_register(&cm_class);
|
||||
if (ret)
|
||||
return -ENOMEM;
|
||||
|
||||
cm.wq = create_workqueue("ib_cm");
|
||||
if (!cm.wq) {
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
goto error1;
|
||||
}
|
||||
|
||||
cm.wq = create_workqueue("ib_cm");
|
||||
if (!cm.wq) {
|
||||
ret = -ENOMEM;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
ret = ib_register_client(&cm_client);
|
||||
if (ret)
|
||||
goto error2;
|
||||
goto error3;
|
||||
|
||||
return 0;
|
||||
error2:
|
||||
error3:
|
||||
destroy_workqueue(cm.wq);
|
||||
error1:
|
||||
error2:
|
||||
class_unregister(&cm_class);
|
||||
error1:
|
||||
idr_destroy(&cm.local_id_table);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -44,18 +44,6 @@
|
||||
|
||||
#define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */
|
||||
|
||||
#define CM_REQ_ATTR_ID cpu_to_be16(0x0010)
|
||||
#define CM_MRA_ATTR_ID cpu_to_be16(0x0011)
|
||||
#define CM_REJ_ATTR_ID cpu_to_be16(0x0012)
|
||||
#define CM_REP_ATTR_ID cpu_to_be16(0x0013)
|
||||
#define CM_RTU_ATTR_ID cpu_to_be16(0x0014)
|
||||
#define CM_DREQ_ATTR_ID cpu_to_be16(0x0015)
|
||||
#define CM_DREP_ATTR_ID cpu_to_be16(0x0016)
|
||||
#define CM_SIDR_REQ_ATTR_ID cpu_to_be16(0x0017)
|
||||
#define CM_SIDR_REP_ATTR_ID cpu_to_be16(0x0018)
|
||||
#define CM_LAP_ATTR_ID cpu_to_be16(0x0019)
|
||||
#define CM_APR_ATTR_ID cpu_to_be16(0x001A)
|
||||
|
||||
enum cm_msg_sequence {
|
||||
CM_MSG_SEQUENCE_REQ,
|
||||
CM_MSG_SEQUENCE_LAP,
|
||||
|
@@ -99,6 +99,10 @@ struct rdma_bind_list {
|
||||
unsigned short port;
|
||||
};
|
||||
|
||||
enum {
|
||||
CMA_OPTION_AFONLY,
|
||||
};
|
||||
|
||||
/*
|
||||
* Device removal can occur at anytime, so we need extra handling to
|
||||
* serialize notifying the user of device removal with other callbacks.
|
||||
@@ -137,9 +141,11 @@ struct rdma_id_private {
|
||||
u32 qkey;
|
||||
u32 qp_num;
|
||||
pid_t owner;
|
||||
u32 options;
|
||||
u8 srq;
|
||||
u8 tos;
|
||||
u8 reuseaddr;
|
||||
u8 afonly;
|
||||
};
|
||||
|
||||
struct cma_multicast {
|
||||
@@ -1297,8 +1303,10 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
|
||||
} else {
|
||||
cma_set_ip_ver(cma_data, 4);
|
||||
cma_set_ip_ver(cma_mask, 0xF);
|
||||
cma_data->dst_addr.ip4.addr = ip4_addr;
|
||||
cma_mask->dst_addr.ip4.addr = htonl(~0);
|
||||
if (!cma_any_addr(addr)) {
|
||||
cma_data->dst_addr.ip4.addr = ip4_addr;
|
||||
cma_mask->dst_addr.ip4.addr = htonl(~0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
@@ -1312,9 +1320,11 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
|
||||
} else {
|
||||
cma_set_ip_ver(cma_data, 6);
|
||||
cma_set_ip_ver(cma_mask, 0xF);
|
||||
cma_data->dst_addr.ip6 = ip6_addr;
|
||||
memset(&cma_mask->dst_addr.ip6, 0xFF,
|
||||
sizeof cma_mask->dst_addr.ip6);
|
||||
if (!cma_any_addr(addr)) {
|
||||
cma_data->dst_addr.ip6 = ip6_addr;
|
||||
memset(&cma_mask->dst_addr.ip6, 0xFF,
|
||||
sizeof cma_mask->dst_addr.ip6);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1499,7 +1509,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
|
||||
|
||||
addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
|
||||
svc_id = cma_get_service_id(id_priv->id.ps, addr);
|
||||
if (cma_any_addr(addr))
|
||||
if (cma_any_addr(addr) && !id_priv->afonly)
|
||||
ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
|
||||
else {
|
||||
cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
|
||||
@@ -1573,6 +1583,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
|
||||
list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
|
||||
atomic_inc(&id_priv->refcount);
|
||||
dev_id_priv->internal_id = 1;
|
||||
dev_id_priv->afonly = id_priv->afonly;
|
||||
|
||||
ret = rdma_listen(id, id_priv->backlog);
|
||||
if (ret)
|
||||
@@ -2098,6 +2109,26 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse)
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_set_reuseaddr);
|
||||
|
||||
int rdma_set_afonly(struct rdma_cm_id *id, int afonly)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
id_priv = container_of(id, struct rdma_id_private, id);
|
||||
spin_lock_irqsave(&id_priv->lock, flags);
|
||||
if (id_priv->state == RDMA_CM_IDLE || id_priv->state == RDMA_CM_ADDR_BOUND) {
|
||||
id_priv->options |= (1 << CMA_OPTION_AFONLY);
|
||||
id_priv->afonly = afonly;
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
spin_unlock_irqrestore(&id_priv->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_set_afonly);
|
||||
|
||||
static void cma_bind_port(struct rdma_bind_list *bind_list,
|
||||
struct rdma_id_private *id_priv)
|
||||
{
|
||||
@@ -2187,22 +2218,24 @@ static int cma_check_port(struct rdma_bind_list *bind_list,
|
||||
struct hlist_node *node;
|
||||
|
||||
addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
|
||||
if (cma_any_addr(addr) && !reuseaddr)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
|
||||
if (id_priv == cur_id)
|
||||
continue;
|
||||
|
||||
if ((cur_id->state == RDMA_CM_LISTEN) ||
|
||||
!reuseaddr || !cur_id->reuseaddr) {
|
||||
cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
|
||||
if (cma_any_addr(cur_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
if ((cur_id->state != RDMA_CM_LISTEN) && reuseaddr &&
|
||||
cur_id->reuseaddr)
|
||||
continue;
|
||||
|
||||
if (!cma_addr_cmp(addr, cur_addr))
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
|
||||
if (id_priv->afonly && cur_id->afonly &&
|
||||
(addr->sa_family != cur_addr->sa_family))
|
||||
continue;
|
||||
|
||||
if (cma_any_addr(addr) || cma_any_addr(cur_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (!cma_addr_cmp(addr, cur_addr))
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2278,7 +2311,7 @@ static int cma_get_port(struct rdma_id_private *id_priv)
|
||||
static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
|
||||
struct sockaddr *addr)
|
||||
{
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
if (addr->sa_family != AF_INET6)
|
||||
@@ -2371,6 +2404,14 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
|
||||
}
|
||||
|
||||
memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
|
||||
if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) {
|
||||
if (addr->sa_family == AF_INET)
|
||||
id_priv->afonly = 1;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
else if (addr->sa_family == AF_INET6)
|
||||
id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
|
||||
#endif
|
||||
}
|
||||
ret = cma_get_port(id_priv);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
@@ -94,6 +94,12 @@ struct ib_sa_path_query {
|
||||
struct ib_sa_query sa_query;
|
||||
};
|
||||
|
||||
struct ib_sa_guidinfo_query {
|
||||
void (*callback)(int, struct ib_sa_guidinfo_rec *, void *);
|
||||
void *context;
|
||||
struct ib_sa_query sa_query;
|
||||
};
|
||||
|
||||
struct ib_sa_mcmember_query {
|
||||
void (*callback)(int, struct ib_sa_mcmember_rec *, void *);
|
||||
void *context;
|
||||
@@ -347,6 +353,34 @@ static const struct ib_field service_rec_table[] = {
|
||||
.size_bits = 2*64 },
|
||||
};
|
||||
|
||||
#define GUIDINFO_REC_FIELD(field) \
|
||||
.struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \
|
||||
.struct_size_bytes = sizeof((struct ib_sa_guidinfo_rec *) 0)->field, \
|
||||
.field_name = "sa_guidinfo_rec:" #field
|
||||
|
||||
static const struct ib_field guidinfo_rec_table[] = {
|
||||
{ GUIDINFO_REC_FIELD(lid),
|
||||
.offset_words = 0,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 16 },
|
||||
{ GUIDINFO_REC_FIELD(block_num),
|
||||
.offset_words = 0,
|
||||
.offset_bits = 16,
|
||||
.size_bits = 8 },
|
||||
{ GUIDINFO_REC_FIELD(res1),
|
||||
.offset_words = 0,
|
||||
.offset_bits = 24,
|
||||
.size_bits = 8 },
|
||||
{ GUIDINFO_REC_FIELD(res2),
|
||||
.offset_words = 1,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 32 },
|
||||
{ GUIDINFO_REC_FIELD(guid_info_list),
|
||||
.offset_words = 2,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 512 },
|
||||
};
|
||||
|
||||
static void free_sm_ah(struct kref *kref)
|
||||
{
|
||||
struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
|
||||
@@ -945,6 +979,105 @@ err1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Support GuidInfoRecord */
|
||||
static void ib_sa_guidinfo_rec_callback(struct ib_sa_query *sa_query,
|
||||
int status,
|
||||
struct ib_sa_mad *mad)
|
||||
{
|
||||
struct ib_sa_guidinfo_query *query =
|
||||
container_of(sa_query, struct ib_sa_guidinfo_query, sa_query);
|
||||
|
||||
if (mad) {
|
||||
struct ib_sa_guidinfo_rec rec;
|
||||
|
||||
ib_unpack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table),
|
||||
mad->data, &rec);
|
||||
query->callback(status, &rec, query->context);
|
||||
} else
|
||||
query->callback(status, NULL, query->context);
|
||||
}
|
||||
|
||||
static void ib_sa_guidinfo_rec_release(struct ib_sa_query *sa_query)
|
||||
{
|
||||
kfree(container_of(sa_query, struct ib_sa_guidinfo_query, sa_query));
|
||||
}
|
||||
|
||||
int ib_sa_guid_info_rec_query(struct ib_sa_client *client,
|
||||
struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_guidinfo_rec *rec,
|
||||
ib_sa_comp_mask comp_mask, u8 method,
|
||||
int timeout_ms, gfp_t gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_guidinfo_rec *resp,
|
||||
void *context),
|
||||
void *context,
|
||||
struct ib_sa_query **sa_query)
|
||||
{
|
||||
struct ib_sa_guidinfo_query *query;
|
||||
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
|
||||
struct ib_sa_port *port;
|
||||
struct ib_mad_agent *agent;
|
||||
struct ib_sa_mad *mad;
|
||||
int ret;
|
||||
|
||||
if (!sa_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (method != IB_MGMT_METHOD_GET &&
|
||||
method != IB_MGMT_METHOD_SET &&
|
||||
method != IB_SA_METHOD_DELETE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port = &sa_dev->port[port_num - sa_dev->start_port];
|
||||
agent = port->agent;
|
||||
|
||||
query = kmalloc(sizeof *query, gfp_mask);
|
||||
if (!query)
|
||||
return -ENOMEM;
|
||||
|
||||
query->sa_query.port = port;
|
||||
ret = alloc_mad(&query->sa_query, gfp_mask);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
ib_sa_client_get(client);
|
||||
query->sa_query.client = client;
|
||||
query->callback = callback;
|
||||
query->context = context;
|
||||
|
||||
mad = query->sa_query.mad_buf->mad;
|
||||
init_mad(mad, agent);
|
||||
|
||||
query->sa_query.callback = callback ? ib_sa_guidinfo_rec_callback : NULL;
|
||||
query->sa_query.release = ib_sa_guidinfo_rec_release;
|
||||
|
||||
mad->mad_hdr.method = method;
|
||||
mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_GUID_INFO_REC);
|
||||
mad->sa_hdr.comp_mask = comp_mask;
|
||||
|
||||
ib_pack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), rec,
|
||||
mad->data);
|
||||
|
||||
*sa_query = &query->sa_query;
|
||||
|
||||
ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
|
||||
return ret;
|
||||
|
||||
err2:
|
||||
*sa_query = NULL;
|
||||
ib_sa_client_put(query->sa_query.client);
|
||||
free_mad(&query->sa_query);
|
||||
|
||||
err1:
|
||||
kfree(query);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_sa_guid_info_rec_query);
|
||||
|
||||
static void send_handler(struct ib_mad_agent *agent,
|
||||
struct ib_mad_send_wc *mad_send_wc)
|
||||
{
|
||||
|
@@ -909,6 +909,13 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname,
|
||||
}
|
||||
ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
|
||||
break;
|
||||
case RDMA_OPTION_ID_AFONLY:
|
||||
if (optlen != sizeof(int)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = rdma_set_afonly(ctx->cm_id, *((int *) optval) ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
Referencia en una nueva incidencia
Block a user