Changes for 4.2

- A large cleanup of how device capabilities are checked for various
   features
 - Additional cleanups in the MAD processing
 - Update to the srp driver
 - Creation and use of centralized log message helpers
 - Add const to a number of args to calls and clean up call chain
 - Add support for extended cq create verb
 - Add support for timestamps on cq completion
 - Add support for processing OPA MAD packets
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJVeyzqAAoJELgmozMOVy/di3wP/jml4F9crvQn7UBJjGm/rgcI
 wzZ2GZTqxQE8dn+W6gQsdKOzy0Ibxx5UYGp9ruInuxAcVh9t1PcylanasaiGMEtY
 mrGRFjipJ9jYa+yDQDTQi8EFMClZuMSvtRLKjzYITudCXQck37V+F5YlP6VphjX7
 JeiM4a+4rD0ukk5PKGvUw51sP1eawKtEdUvnqcOEI2tJgQmzJBP4mXrhVtS/0wSc
 Pi8TRN5QKi3Drom/tK9QQ/ncoYngi4BKLfszCeU373HJq6qXqsxBYvs3jX6MPzfv
 Aooj272JxBgCYxkmEfECezDpmi3PbWDJjXj/xCLjfhjISDtHHHVLGVMODZpwUEsL
 2wBgwlzdajVopSbSLvsjQNtQw25s7sDWpu+TFKbS0u+W2d0ZOyipM1Xeje+OtDHQ
 clhwvDhgSfeI/bJ1YdtNLbvINrwsfZD213zD+WH21A/9weAVr3hEfTuSaNFiTiRn
 5yywP36TM0wH90KhiWoLrztcHvoE5p7kGuqzv04MRjrMMNHEJK2/IhWvT97Ewngu
 vWrZl7QRzXYcGspCOp2aJW9Wr2rhGRrv28TF+thpNrIJOB2JM4q4koCKZCcI0s2D
 E6pY2YQSzvrA/ZSfcWIg4yhugcycIJkOf7ur2N/U43cwGXtaCzPWVnKMApmdnVOO
 ZEMwD3OZ1OGcCHLhRL8Y
 =yISf
 -----END PGP SIGNATURE-----

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma

Pull rdma updates from Doug Ledford:

 - a large cleanup of how device capabilities are checked for various
   features

 - additional cleanups in the MAD processing

 - update to the srp driver

 - creation and use of centralized log message helpers

 - add const to a number of args to calls and clean up call chain

 - add support for extended cq create verb

 - add support for timestamps on cq completion

 - add support for processing OPA MAD packets

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: (92 commits)
  IB/mad: Add final OPA MAD processing
  IB/mad: Add partial Intel OPA MAD support
  IB/mad: Add partial Intel OPA MAD support
  IB/core: Add OPA MAD core capability flag
  IB/mad: Add support for additional MAD info to/from drivers
  IB/mad: Convert allocations from kmem_cache to kzalloc
  IB/core: Add ability for drivers to report an alternate MAD size.
  IB/mad: Support alternate Base Versions when creating MADs
  IB/mad: Create a generic helper for DR forwarding checks
  IB/mad: Create a generic helper for DR SMP Recv processing
  IB/mad: Create a generic helper for DR SMP Send processing
  IB/mad: Split IB SMI handling from MAD Recv handler
  IB/mad cleanup: Generalize processing of MAD data
  IB/mad cleanup: Clean up function params -- find_mad_agent
  IB/mlx4: Add support for CQ time-stamping
  IB/mlx4: Add mmap call to map the hardware clock
  IB/core: Pass hardware specific data in query_device
  IB/core: Add timestamp_mask and hca_core_clock to query_device
  IB/core: Extend ib_uverbs_create_cq
  IB/core: Add CQ creation time-stamping flag
  ...
This commit is contained in:
Linus Torvalds 2015-06-23 15:53:26 -07:00
commit f9d1b5a31a
112 changed files with 2898 additions and 1361 deletions

View file

@ -457,8 +457,8 @@ static void resolve_cb(int status, struct sockaddr *src_addr,
complete(&((struct resolve_cb_context *)context)->comp); complete(&((struct resolve_cb_context *)context)->comp);
} }
int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac, int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgid,
u16 *vlan_id) u8 *dmac, u16 *vlan_id)
{ {
int ret = 0; int ret = 0;
struct rdma_dev_addr dev_addr; struct rdma_dev_addr dev_addr;

View file

@ -54,7 +54,7 @@ static DEFINE_SPINLOCK(ib_agent_port_list_lock);
static LIST_HEAD(ib_agent_port_list); static LIST_HEAD(ib_agent_port_list);
static struct ib_agent_port_private * static struct ib_agent_port_private *
__ib_get_agent_port(struct ib_device *device, int port_num) __ib_get_agent_port(const struct ib_device *device, int port_num)
{ {
struct ib_agent_port_private *entry; struct ib_agent_port_private *entry;
@ -67,7 +67,7 @@ __ib_get_agent_port(struct ib_device *device, int port_num)
} }
static struct ib_agent_port_private * static struct ib_agent_port_private *
ib_get_agent_port(struct ib_device *device, int port_num) ib_get_agent_port(const struct ib_device *device, int port_num)
{ {
struct ib_agent_port_private *entry; struct ib_agent_port_private *entry;
unsigned long flags; unsigned long flags;
@ -78,9 +78,9 @@ ib_get_agent_port(struct ib_device *device, int port_num)
return entry; return entry;
} }
void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh,
struct ib_wc *wc, struct ib_device *device, const struct ib_wc *wc, const struct ib_device *device,
int port_num, int qpn) int port_num, int qpn, size_t resp_mad_len, bool opa)
{ {
struct ib_agent_port_private *port_priv; struct ib_agent_port_private *port_priv;
struct ib_mad_agent *agent; struct ib_mad_agent *agent;
@ -106,15 +106,20 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
return; return;
} }
if (opa && mad_hdr->base_version != OPA_MGMT_BASE_VERSION)
resp_mad_len = IB_MGMT_MAD_SIZE;
send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0, send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, IB_MGMT_MAD_HDR,
GFP_KERNEL); resp_mad_len - IB_MGMT_MAD_HDR,
GFP_KERNEL,
mad_hdr->base_version);
if (IS_ERR(send_buf)) { if (IS_ERR(send_buf)) {
dev_err(&device->dev, "ib_create_send_mad error\n"); dev_err(&device->dev, "ib_create_send_mad error\n");
goto err1; goto err1;
} }
memcpy(send_buf->mad, mad, sizeof *mad); memcpy(send_buf->mad, mad_hdr, resp_mad_len);
send_buf->ah = ah; send_buf->ah = ah;
if (device->node_type == RDMA_NODE_IB_SWITCH) { if (device->node_type == RDMA_NODE_IB_SWITCH) {
@ -156,7 +161,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
goto error1; goto error1;
} }
if (rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND) { if (rdma_cap_ib_smi(device, port_num)) {
/* Obtain send only MAD agent for SMI QP */ /* Obtain send only MAD agent for SMI QP */
port_priv->agent[0] = ib_register_mad_agent(device, port_num, port_priv->agent[0] = ib_register_mad_agent(device, port_num,
IB_QPT_SMI, NULL, 0, IB_QPT_SMI, NULL, 0,

View file

@ -44,8 +44,8 @@ extern int ib_agent_port_open(struct ib_device *device, int port_num);
extern int ib_agent_port_close(struct ib_device *device, int port_num); extern int ib_agent_port_close(struct ib_device *device, int port_num);
extern void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, extern void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh,
struct ib_wc *wc, struct ib_device *device, const struct ib_wc *wc, const struct ib_device *device,
int port_num, int qpn); int port_num, int qpn, size_t resp_mad_len, bool opa);
#endif /* __AGENT_H_ */ #endif /* __AGENT_H_ */

View file

@ -58,17 +58,6 @@ struct ib_update_work {
u8 port_num; u8 port_num;
}; };
static inline int start_port(struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
}
static inline int end_port(struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ?
0 : device->phys_port_cnt;
}
int ib_get_cached_gid(struct ib_device *device, int ib_get_cached_gid(struct ib_device *device,
u8 port_num, u8 port_num,
int index, int index,
@ -78,12 +67,12 @@ int ib_get_cached_gid(struct ib_device *device,
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
cache = device->cache.gid_cache[port_num - start_port(device)]; cache = device->cache.gid_cache[port_num - rdma_start_port(device)];
if (index < 0 || index >= cache->table_len) if (index < 0 || index >= cache->table_len)
ret = -EINVAL; ret = -EINVAL;
@ -97,7 +86,7 @@ int ib_get_cached_gid(struct ib_device *device,
EXPORT_SYMBOL(ib_get_cached_gid); EXPORT_SYMBOL(ib_get_cached_gid);
int ib_find_cached_gid(struct ib_device *device, int ib_find_cached_gid(struct ib_device *device,
union ib_gid *gid, const union ib_gid *gid,
u8 *port_num, u8 *port_num,
u16 *index) u16 *index)
{ {
@ -112,11 +101,11 @@ int ib_find_cached_gid(struct ib_device *device,
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
for (p = 0; p <= end_port(device) - start_port(device); ++p) { for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) {
cache = device->cache.gid_cache[p]; cache = device->cache.gid_cache[p];
for (i = 0; i < cache->table_len; ++i) { for (i = 0; i < cache->table_len; ++i) {
if (!memcmp(gid, &cache->table[i], sizeof *gid)) { if (!memcmp(gid, &cache->table[i], sizeof *gid)) {
*port_num = p + start_port(device); *port_num = p + rdma_start_port(device);
if (index) if (index)
*index = i; *index = i;
ret = 0; ret = 0;
@ -140,12 +129,12 @@ int ib_get_cached_pkey(struct ib_device *device,
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
cache = device->cache.pkey_cache[port_num - start_port(device)]; cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
if (index < 0 || index >= cache->table_len) if (index < 0 || index >= cache->table_len)
ret = -EINVAL; ret = -EINVAL;
@ -169,12 +158,12 @@ int ib_find_cached_pkey(struct ib_device *device,
int ret = -ENOENT; int ret = -ENOENT;
int partial_ix = -1; int partial_ix = -1;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
cache = device->cache.pkey_cache[port_num - start_port(device)]; cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
*index = -1; *index = -1;
@ -209,12 +198,12 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
int i; int i;
int ret = -ENOENT; int ret = -ENOENT;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
cache = device->cache.pkey_cache[port_num - start_port(device)]; cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
*index = -1; *index = -1;
@ -238,11 +227,11 @@ int ib_get_cached_lmc(struct ib_device *device,
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache.lock, flags);
*lmc = device->cache.lmc_cache[port_num - start_port(device)]; *lmc = device->cache.lmc_cache[port_num - rdma_start_port(device)];
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache.lock, flags);
return ret; return ret;
@ -303,13 +292,13 @@ static void ib_cache_update(struct ib_device *device,
write_lock_irq(&device->cache.lock); write_lock_irq(&device->cache.lock);
old_pkey_cache = device->cache.pkey_cache[port - start_port(device)]; old_pkey_cache = device->cache.pkey_cache[port - rdma_start_port(device)];
old_gid_cache = device->cache.gid_cache [port - start_port(device)]; old_gid_cache = device->cache.gid_cache [port - rdma_start_port(device)];
device->cache.pkey_cache[port - start_port(device)] = pkey_cache; device->cache.pkey_cache[port - rdma_start_port(device)] = pkey_cache;
device->cache.gid_cache [port - start_port(device)] = gid_cache; device->cache.gid_cache [port - rdma_start_port(device)] = gid_cache;
device->cache.lmc_cache[port - start_port(device)] = tprops->lmc; device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc;
write_unlock_irq(&device->cache.lock); write_unlock_irq(&device->cache.lock);
@ -363,14 +352,14 @@ static void ib_cache_setup_one(struct ib_device *device)
device->cache.pkey_cache = device->cache.pkey_cache =
kmalloc(sizeof *device->cache.pkey_cache * kmalloc(sizeof *device->cache.pkey_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL); (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL);
device->cache.gid_cache = device->cache.gid_cache =
kmalloc(sizeof *device->cache.gid_cache * kmalloc(sizeof *device->cache.gid_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL); (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL);
device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache * device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache *
(end_port(device) - (rdma_end_port(device) -
start_port(device) + 1), rdma_start_port(device) + 1),
GFP_KERNEL); GFP_KERNEL);
if (!device->cache.pkey_cache || !device->cache.gid_cache || if (!device->cache.pkey_cache || !device->cache.gid_cache ||
@ -380,10 +369,10 @@ static void ib_cache_setup_one(struct ib_device *device)
goto err; goto err;
} }
for (p = 0; p <= end_port(device) - start_port(device); ++p) { for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) {
device->cache.pkey_cache[p] = NULL; device->cache.pkey_cache[p] = NULL;
device->cache.gid_cache [p] = NULL; device->cache.gid_cache [p] = NULL;
ib_cache_update(device, p + start_port(device)); ib_cache_update(device, p + rdma_start_port(device));
} }
INIT_IB_EVENT_HANDLER(&device->cache.event_handler, INIT_IB_EVENT_HANDLER(&device->cache.event_handler,
@ -394,7 +383,7 @@ static void ib_cache_setup_one(struct ib_device *device)
return; return;
err_cache: err_cache:
for (p = 0; p <= end_port(device) - start_port(device); ++p) { for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) {
kfree(device->cache.pkey_cache[p]); kfree(device->cache.pkey_cache[p]);
kfree(device->cache.gid_cache[p]); kfree(device->cache.gid_cache[p]);
} }
@ -412,7 +401,7 @@ static void ib_cache_cleanup_one(struct ib_device *device)
ib_unregister_event_handler(&device->cache.event_handler); ib_unregister_event_handler(&device->cache.event_handler);
flush_workqueue(ib_wq); flush_workqueue(ib_wq);
for (p = 0; p <= end_port(device) - start_port(device); ++p) { for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) {
kfree(device->cache.pkey_cache[p]); kfree(device->cache.pkey_cache[p]);
kfree(device->cache.gid_cache[p]); kfree(device->cache.gid_cache[p]);
} }

View file

@ -267,7 +267,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
cm_id_priv->av.pkey_index, cm_id_priv->av.pkey_index,
0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_ATOMIC); GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(m)) { if (IS_ERR(m)) {
ib_destroy_ah(ah); ib_destroy_ah(ah);
return PTR_ERR(m); return PTR_ERR(m);
@ -297,7 +298,8 @@ static int cm_alloc_response_msg(struct cm_port *port,
m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index, m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_ATOMIC); GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(m)) { if (IS_ERR(m)) {
ib_destroy_ah(ah); ib_destroy_ah(ah);
return PTR_ERR(m); return PTR_ERR(m);
@ -3759,11 +3761,9 @@ static void cm_add_one(struct ib_device *ib_device)
}; };
unsigned long flags; unsigned long flags;
int ret; int ret;
int count = 0;
u8 i; u8 i;
if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
return;
cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) * cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
ib_device->phys_port_cnt, GFP_KERNEL); ib_device->phys_port_cnt, GFP_KERNEL);
if (!cm_dev) if (!cm_dev)
@ -3782,6 +3782,9 @@ static void cm_add_one(struct ib_device *ib_device)
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= ib_device->phys_port_cnt; i++) { for (i = 1; i <= ib_device->phys_port_cnt; i++) {
if (!rdma_cap_ib_cm(ib_device, i))
continue;
port = kzalloc(sizeof *port, GFP_KERNEL); port = kzalloc(sizeof *port, GFP_KERNEL);
if (!port) if (!port)
goto error1; goto error1;
@ -3808,7 +3811,13 @@ static void cm_add_one(struct ib_device *ib_device)
ret = ib_modify_port(ib_device, i, 0, &port_modify); ret = ib_modify_port(ib_device, i, 0, &port_modify);
if (ret) if (ret)
goto error3; goto error3;
count++;
} }
if (!count)
goto free;
ib_set_client_data(ib_device, &cm_client, cm_dev); ib_set_client_data(ib_device, &cm_client, cm_dev);
write_lock_irqsave(&cm.device_lock, flags); write_lock_irqsave(&cm.device_lock, flags);
@ -3824,11 +3833,15 @@ error1:
port_modify.set_port_cap_mask = 0; port_modify.set_port_cap_mask = 0;
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) { while (--i) {
if (!rdma_cap_ib_cm(ib_device, i))
continue;
port = cm_dev->port[i-1]; port = cm_dev->port[i-1];
ib_modify_port(ib_device, port->port_num, 0, &port_modify); ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent); ib_unregister_mad_agent(port->mad_agent);
cm_remove_port_fs(port); cm_remove_port_fs(port);
} }
free:
device_unregister(cm_dev->device); device_unregister(cm_dev->device);
kfree(cm_dev); kfree(cm_dev);
} }
@ -3852,6 +3865,9 @@ static void cm_remove_one(struct ib_device *ib_device)
write_unlock_irqrestore(&cm.device_lock, flags); write_unlock_irqrestore(&cm.device_lock, flags);
for (i = 1; i <= ib_device->phys_port_cnt; i++) { for (i = 1; i <= ib_device->phys_port_cnt; i++) {
if (!rdma_cap_ib_cm(ib_device, i))
continue;
port = cm_dev->port[i-1]; port = cm_dev->port[i-1];
ib_modify_port(ib_device, port->port_num, 0, &port_modify); ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent); ib_unregister_mad_agent(port->mad_agent);

View file

@ -65,6 +65,34 @@ MODULE_LICENSE("Dual BSD/GPL");
#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24) #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
#define CMA_IBOE_PACKET_LIFETIME 18 #define CMA_IBOE_PACKET_LIFETIME 18
static const char * const cma_events[] = {
[RDMA_CM_EVENT_ADDR_RESOLVED] = "address resolved",
[RDMA_CM_EVENT_ADDR_ERROR] = "address error",
[RDMA_CM_EVENT_ROUTE_RESOLVED] = "route resolved ",
[RDMA_CM_EVENT_ROUTE_ERROR] = "route error",
[RDMA_CM_EVENT_CONNECT_REQUEST] = "connect request",
[RDMA_CM_EVENT_CONNECT_RESPONSE] = "connect response",
[RDMA_CM_EVENT_CONNECT_ERROR] = "connect error",
[RDMA_CM_EVENT_UNREACHABLE] = "unreachable",
[RDMA_CM_EVENT_REJECTED] = "rejected",
[RDMA_CM_EVENT_ESTABLISHED] = "established",
[RDMA_CM_EVENT_DISCONNECTED] = "disconnected",
[RDMA_CM_EVENT_DEVICE_REMOVAL] = "device removal",
[RDMA_CM_EVENT_MULTICAST_JOIN] = "multicast join",
[RDMA_CM_EVENT_MULTICAST_ERROR] = "multicast error",
[RDMA_CM_EVENT_ADDR_CHANGE] = "address change",
[RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit",
};
const char *rdma_event_msg(enum rdma_cm_event_type event)
{
size_t index = event;
return (index < ARRAY_SIZE(cma_events) && cma_events[index]) ?
cma_events[index] : "unrecognized event";
}
EXPORT_SYMBOL(rdma_event_msg);
static void cma_add_one(struct ib_device *device); static void cma_add_one(struct ib_device *device);
static void cma_remove_one(struct ib_device *device); static void cma_remove_one(struct ib_device *device);
@ -349,18 +377,35 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
return ret; return ret;
} }
static inline int cma_validate_port(struct ib_device *device, u8 port,
union ib_gid *gid, int dev_type)
{
u8 found_port;
int ret = -ENODEV;
if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port))
return ret;
if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
return ret;
ret = ib_find_cached_gid(device, gid, &found_port, NULL);
if (port != found_port)
return -ENODEV;
return ret;
}
static int cma_acquire_dev(struct rdma_id_private *id_priv, static int cma_acquire_dev(struct rdma_id_private *id_priv,
struct rdma_id_private *listen_id_priv) struct rdma_id_private *listen_id_priv)
{ {
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
struct cma_device *cma_dev; struct cma_device *cma_dev;
union ib_gid gid, iboe_gid; union ib_gid gid, iboe_gid, *gidp;
int ret = -ENODEV; int ret = -ENODEV;
u8 port, found_port; u8 port;
enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
if (dev_ll != IB_LINK_LAYER_INFINIBAND && if (dev_addr->dev_type != ARPHRD_INFINIBAND &&
id_priv->id.ps == RDMA_PS_IPOIB) id_priv->id.ps == RDMA_PS_IPOIB)
return -EINVAL; return -EINVAL;
@ -370,44 +415,39 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
memcpy(&gid, dev_addr->src_dev_addr + memcpy(&gid, dev_addr->src_dev_addr +
rdma_addr_gid_offset(dev_addr), sizeof gid); rdma_addr_gid_offset(dev_addr), sizeof gid);
if (listen_id_priv &&
rdma_port_get_link_layer(listen_id_priv->id.device, if (listen_id_priv) {
listen_id_priv->id.port_num) == dev_ll) {
cma_dev = listen_id_priv->cma_dev; cma_dev = listen_id_priv->cma_dev;
port = listen_id_priv->id.port_num; port = listen_id_priv->id.port_num;
if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB && gidp = rdma_protocol_roce(cma_dev->device, port) ?
rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET) &iboe_gid : &gid;
ret = ib_find_cached_gid(cma_dev->device, &iboe_gid,
&found_port, NULL);
else
ret = ib_find_cached_gid(cma_dev->device, &gid,
&found_port, NULL);
if (!ret && (port == found_port)) { ret = cma_validate_port(cma_dev->device, port, gidp,
id_priv->id.port_num = found_port; dev_addr->dev_type);
if (!ret) {
id_priv->id.port_num = port;
goto out; goto out;
} }
} }
list_for_each_entry(cma_dev, &dev_list, list) { list_for_each_entry(cma_dev, &dev_list, list) {
for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) { for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
if (listen_id_priv && if (listen_id_priv &&
listen_id_priv->cma_dev == cma_dev && listen_id_priv->cma_dev == cma_dev &&
listen_id_priv->id.port_num == port) listen_id_priv->id.port_num == port)
continue; continue;
if (rdma_port_get_link_layer(cma_dev->device, port) == dev_ll) {
if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB &&
rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET)
ret = ib_find_cached_gid(cma_dev->device, &iboe_gid, &found_port, NULL);
else
ret = ib_find_cached_gid(cma_dev->device, &gid, &found_port, NULL);
if (!ret && (port == found_port)) { gidp = rdma_protocol_roce(cma_dev->device, port) ?
id_priv->id.port_num = found_port; &iboe_gid : &gid;
ret = cma_validate_port(cma_dev->device, port, gidp,
dev_addr->dev_type);
if (!ret) {
id_priv->id.port_num = port;
goto out; goto out;
} }
} }
} }
}
out: out:
if (!ret) if (!ret)
@ -435,10 +475,10 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
pkey = ntohs(addr->sib_pkey); pkey = ntohs(addr->sib_pkey);
list_for_each_entry(cur_dev, &dev_list, list) { list_for_each_entry(cur_dev, &dev_list, list) {
if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
if (!rdma_cap_af_ib(cur_dev->device, p))
continue; continue;
for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index)) if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index))
continue; continue;
@ -633,10 +673,9 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
if (ret) if (ret)
goto out; goto out;
if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) BUG_ON(id_priv->cma_dev->device != id_priv->id.device);
== RDMA_TRANSPORT_IB &&
rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
== IB_LINK_LAYER_ETHERNET) {
ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL); ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL);
if (ret) if (ret)
@ -700,11 +739,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
int ret; int ret;
u16 pkey; u16 pkey;
if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) == if (rdma_cap_eth_ah(id_priv->id.device, id_priv->id.port_num))
IB_LINK_LAYER_INFINIBAND)
pkey = ib_addr_get_pkey(dev_addr);
else
pkey = 0xffff; pkey = 0xffff;
else
pkey = ib_addr_get_pkey(dev_addr);
ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num, ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
pkey, &qp_attr->pkey_index); pkey, &qp_attr->pkey_index);
@ -735,8 +773,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
int ret = 0; int ret = 0;
id_priv = container_of(id, struct rdma_id_private, id); id_priv = container_of(id, struct rdma_id_private, id);
switch (rdma_node_get_transport(id_priv->id.device->node_type)) { if (rdma_cap_ib_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD)) if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD))
ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask); ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
else else
@ -745,19 +782,15 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
if (qp_attr->qp_state == IB_QPS_RTR) if (qp_attr->qp_state == IB_QPS_RTR)
qp_attr->rq_psn = id_priv->seq_num; qp_attr->rq_psn = id_priv->seq_num;
break; } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IWARP:
if (!id_priv->cm_id.iw) { if (!id_priv->cm_id.iw) {
qp_attr->qp_access_flags = 0; qp_attr->qp_access_flags = 0;
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
} else } else
ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
qp_attr_mask); qp_attr_mask);
break; } else
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
return ret; return ret;
} }
@ -945,13 +978,9 @@ static inline int cma_user_data_offset(struct rdma_id_private *id_priv)
static void cma_cancel_route(struct rdma_id_private *id_priv) static void cma_cancel_route(struct rdma_id_private *id_priv)
{ {
switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) { if (rdma_cap_ib_sa(id_priv->id.device, id_priv->id.port_num)) {
case IB_LINK_LAYER_INFINIBAND:
if (id_priv->query) if (id_priv->query)
ib_sa_cancel_query(id_priv->query_id, id_priv->query); ib_sa_cancel_query(id_priv->query_id, id_priv->query);
break;
default:
break;
} }
} }
@ -1023,17 +1052,12 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
mc = container_of(id_priv->mc_list.next, mc = container_of(id_priv->mc_list.next,
struct cma_multicast, list); struct cma_multicast, list);
list_del(&mc->list); list_del(&mc->list);
switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) { if (rdma_cap_ib_mcast(id_priv->cma_dev->device,
case IB_LINK_LAYER_INFINIBAND: id_priv->id.port_num)) {
ib_sa_free_multicast(mc->multicast.ib); ib_sa_free_multicast(mc->multicast.ib);
kfree(mc); kfree(mc);
break; } else
case IB_LINK_LAYER_ETHERNET:
kref_put(&mc->mcref, release_mc); kref_put(&mc->mcref, release_mc);
break;
default:
break;
}
} }
} }
@ -1054,17 +1078,12 @@ void rdma_destroy_id(struct rdma_cm_id *id)
mutex_unlock(&id_priv->handler_mutex); mutex_unlock(&id_priv->handler_mutex);
if (id_priv->cma_dev) { if (id_priv->cma_dev) {
switch (rdma_node_get_transport(id_priv->id.device->node_type)) { if (rdma_cap_ib_cm(id_priv->id.device, 1)) {
case RDMA_TRANSPORT_IB:
if (id_priv->cm_id.ib) if (id_priv->cm_id.ib)
ib_destroy_cm_id(id_priv->cm_id.ib); ib_destroy_cm_id(id_priv->cm_id.ib);
break; } else if (rdma_cap_iw_cm(id_priv->id.device, 1)) {
case RDMA_TRANSPORT_IWARP:
if (id_priv->cm_id.iw) if (id_priv->cm_id.iw)
iw_destroy_cm_id(id_priv->cm_id.iw); iw_destroy_cm_id(id_priv->cm_id.iw);
break;
default:
break;
} }
cma_leave_mc_groups(id_priv); cma_leave_mc_groups(id_priv);
cma_release_dev(id_priv); cma_release_dev(id_priv);
@ -1610,6 +1629,7 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
if (IS_ERR(id)) if (IS_ERR(id))
return PTR_ERR(id); return PTR_ERR(id);
id->tos = id_priv->tos;
id_priv->cm_id.iw = id; id_priv->cm_id.iw = id;
memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv), memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
@ -1642,8 +1662,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
struct rdma_cm_id *id; struct rdma_cm_id *id;
int ret; int ret;
if (cma_family(id_priv) == AF_IB && if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
rdma_node_get_transport(cma_dev->device->node_type) != RDMA_TRANSPORT_IB)
return; return;
id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps, id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps,
@ -1984,26 +2003,15 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
return -EINVAL; return -EINVAL;
atomic_inc(&id_priv->refcount); atomic_inc(&id_priv->refcount);
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_sa(id->device, id->port_num))
case RDMA_TRANSPORT_IB:
switch (rdma_port_get_link_layer(id->device, id->port_num)) {
case IB_LINK_LAYER_INFINIBAND:
ret = cma_resolve_ib_route(id_priv, timeout_ms); ret = cma_resolve_ib_route(id_priv, timeout_ms);
break; else if (rdma_protocol_roce(id->device, id->port_num))
case IB_LINK_LAYER_ETHERNET:
ret = cma_resolve_iboe_route(id_priv); ret = cma_resolve_iboe_route(id_priv);
break; else if (rdma_protocol_iwarp(id->device, id->port_num))
default:
ret = -ENOSYS;
}
break;
case RDMA_TRANSPORT_IWARP:
ret = cma_resolve_iw_route(id_priv, timeout_ms); ret = cma_resolve_iw_route(id_priv, timeout_ms);
break; else
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
if (ret) if (ret)
goto err; goto err;
@ -2045,7 +2053,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv)
mutex_lock(&lock); mutex_lock(&lock);
list_for_each_entry(cur_dev, &dev_list, list) { list_for_each_entry(cur_dev, &dev_list, list) {
if (cma_family(id_priv) == AF_IB && if (cma_family(id_priv) == AF_IB &&
rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) !rdma_cap_ib_cm(cur_dev->device, 1))
continue; continue;
if (!cma_dev) if (!cma_dev)
@ -2077,7 +2085,7 @@ port_found:
goto out; goto out;
id_priv->id.route.addr.dev_addr.dev_type = id_priv->id.route.addr.dev_addr.dev_type =
(rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ? (rdma_protocol_ib(cma_dev->device, p)) ?
ARPHRD_INFINIBAND : ARPHRD_ETHER; ARPHRD_INFINIBAND : ARPHRD_ETHER;
rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
@ -2554,18 +2562,15 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
id_priv->backlog = backlog; id_priv->backlog = backlog;
if (id->device) { if (id->device) {
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_cm(id->device, 1)) {
case RDMA_TRANSPORT_IB:
ret = cma_ib_listen(id_priv); ret = cma_ib_listen(id_priv);
if (ret) if (ret)
goto err; goto err;
break; } else if (rdma_cap_iw_cm(id->device, 1)) {
case RDMA_TRANSPORT_IWARP:
ret = cma_iw_listen(id_priv, backlog); ret = cma_iw_listen(id_priv, backlog);
if (ret) if (ret)
goto err; goto err;
break; } else {
default:
ret = -ENOSYS; ret = -ENOSYS;
goto err; goto err;
} }
@ -2857,6 +2862,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
if (IS_ERR(cm_id)) if (IS_ERR(cm_id))
return PTR_ERR(cm_id); return PTR_ERR(cm_id);
cm_id->tos = id_priv->tos;
id_priv->cm_id.iw = cm_id; id_priv->cm_id.iw = cm_id;
memcpy(&cm_id->local_addr, cma_src_addr(id_priv), memcpy(&cm_id->local_addr, cma_src_addr(id_priv),
@ -2901,20 +2907,15 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
id_priv->srq = conn_param->srq; id_priv->srq = conn_param->srq;
} }
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (id->qp_type == IB_QPT_UD) if (id->qp_type == IB_QPT_UD)
ret = cma_resolve_ib_udp(id_priv, conn_param); ret = cma_resolve_ib_udp(id_priv, conn_param);
else else
ret = cma_connect_ib(id_priv, conn_param); ret = cma_connect_ib(id_priv, conn_param);
break; } else if (rdma_cap_iw_cm(id->device, id->port_num))
case RDMA_TRANSPORT_IWARP:
ret = cma_connect_iw(id_priv, conn_param); ret = cma_connect_iw(id_priv, conn_param);
break; else
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
if (ret) if (ret)
goto err; goto err;
@ -3017,8 +3018,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
id_priv->srq = conn_param->srq; id_priv->srq = conn_param->srq;
} }
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (id->qp_type == IB_QPT_UD) { if (id->qp_type == IB_QPT_UD) {
if (conn_param) if (conn_param)
ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
@ -3034,14 +3034,10 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
else else
ret = cma_rep_recv(id_priv); ret = cma_rep_recv(id_priv);
} }
break; } else if (rdma_cap_iw_cm(id->device, id->port_num))
case RDMA_TRANSPORT_IWARP:
ret = cma_accept_iw(id_priv, conn_param); ret = cma_accept_iw(id_priv, conn_param);
break; else
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
if (ret) if (ret)
goto reject; goto reject;
@ -3085,8 +3081,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
if (!id_priv->cm_id.ib) if (!id_priv->cm_id.ib)
return -EINVAL; return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (id->qp_type == IB_QPT_UD) if (id->qp_type == IB_QPT_UD)
ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0, ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0,
private_data, private_data_len); private_data, private_data_len);
@ -3094,15 +3089,12 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
ret = ib_send_cm_rej(id_priv->cm_id.ib, ret = ib_send_cm_rej(id_priv->cm_id.ib,
IB_CM_REJ_CONSUMER_DEFINED, NULL, IB_CM_REJ_CONSUMER_DEFINED, NULL,
0, private_data, private_data_len); 0, private_data, private_data_len);
break; } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IWARP:
ret = iw_cm_reject(id_priv->cm_id.iw, ret = iw_cm_reject(id_priv->cm_id.iw,
private_data, private_data_len); private_data, private_data_len);
break; } else
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
return ret; return ret;
} }
EXPORT_SYMBOL(rdma_reject); EXPORT_SYMBOL(rdma_reject);
@ -3116,22 +3108,18 @@ int rdma_disconnect(struct rdma_cm_id *id)
if (!id_priv->cm_id.ib) if (!id_priv->cm_id.ib)
return -EINVAL; return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_cap_ib_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
ret = cma_modify_qp_err(id_priv); ret = cma_modify_qp_err(id_priv);
if (ret) if (ret)
goto out; goto out;
/* Initiate or respond to a disconnect. */ /* Initiate or respond to a disconnect. */
if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
break; } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
case RDMA_TRANSPORT_IWARP:
ret = iw_cm_disconnect(id_priv->cm_id.iw, 0); ret = iw_cm_disconnect(id_priv->cm_id.iw, 0);
break; } else
default:
ret = -EINVAL; ret = -EINVAL;
break;
}
out: out:
return ret; return ret;
} }
@ -3377,24 +3365,13 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
list_add(&mc->list, &id_priv->mc_list); list_add(&mc->list, &id_priv->mc_list);
spin_unlock(&id_priv->lock); spin_unlock(&id_priv->lock);
switch (rdma_node_get_transport(id->device->node_type)) { if (rdma_protocol_roce(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
switch (rdma_port_get_link_layer(id->device, id->port_num)) {
case IB_LINK_LAYER_INFINIBAND:
ret = cma_join_ib_multicast(id_priv, mc);
break;
case IB_LINK_LAYER_ETHERNET:
kref_init(&mc->mcref); kref_init(&mc->mcref);
ret = cma_iboe_join_multicast(id_priv, mc); ret = cma_iboe_join_multicast(id_priv, mc);
break; } else if (rdma_cap_ib_mcast(id->device, id->port_num))
default: ret = cma_join_ib_multicast(id_priv, mc);
ret = -EINVAL; else
}
break;
default:
ret = -ENOSYS; ret = -ENOSYS;
break;
}
if (ret) { if (ret) {
spin_lock_irq(&id_priv->lock); spin_lock_irq(&id_priv->lock);
@ -3422,19 +3399,15 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
ib_detach_mcast(id->qp, ib_detach_mcast(id->qp,
&mc->multicast.ib->rec.mgid, &mc->multicast.ib->rec.mgid,
be16_to_cpu(mc->multicast.ib->rec.mlid)); be16_to_cpu(mc->multicast.ib->rec.mlid));
if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) {
switch (rdma_port_get_link_layer(id->device, id->port_num)) { BUG_ON(id_priv->cma_dev->device != id->device);
case IB_LINK_LAYER_INFINIBAND:
if (rdma_cap_ib_mcast(id->device, id->port_num)) {
ib_sa_free_multicast(mc->multicast.ib); ib_sa_free_multicast(mc->multicast.ib);
kfree(mc); kfree(mc);
break; } else if (rdma_protocol_roce(id->device, id->port_num))
case IB_LINK_LAYER_ETHERNET:
kref_put(&mc->mcref, release_mc); kref_put(&mc->mcref, release_mc);
break;
default:
break;
}
}
return; return;
} }
} }

View file

@ -92,7 +92,8 @@ static int ib_device_check_mandatory(struct ib_device *device)
IB_MANDATORY_FUNC(poll_cq), IB_MANDATORY_FUNC(poll_cq),
IB_MANDATORY_FUNC(req_notify_cq), IB_MANDATORY_FUNC(req_notify_cq),
IB_MANDATORY_FUNC(get_dma_mr), IB_MANDATORY_FUNC(get_dma_mr),
IB_MANDATORY_FUNC(dereg_mr) IB_MANDATORY_FUNC(dereg_mr),
IB_MANDATORY_FUNC(get_port_immutable)
}; };
int i; int i;
@ -151,18 +152,6 @@ static int alloc_name(char *name)
return 0; return 0;
} }
static int start_port(struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
}
static int end_port(struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ?
0 : device->phys_port_cnt;
}
/** /**
* ib_alloc_device - allocate an IB device struct * ib_alloc_device - allocate an IB device struct
* @size:size of structure to allocate * @size:size of structure to allocate
@ -222,42 +211,49 @@ static int add_client_context(struct ib_device *device, struct ib_client *client
return 0; return 0;
} }
static int read_port_table_lengths(struct ib_device *device) static int verify_immutable(const struct ib_device *dev, u8 port)
{ {
struct ib_port_attr *tprops = NULL; return WARN_ON(!rdma_cap_ib_mad(dev, port) &&
int num_ports, ret = -ENOMEM; rdma_max_mad_size(dev, port) != 0);
u8 port_index; }
tprops = kmalloc(sizeof *tprops, GFP_KERNEL); static int read_port_immutable(struct ib_device *device)
if (!tprops) {
goto out; int ret = -ENOMEM;
u8 start_port = rdma_start_port(device);
u8 end_port = rdma_end_port(device);
u8 port;
num_ports = end_port(device) - start_port(device) + 1; /**
* device->port_immutable is indexed directly by the port number to make
device->pkey_tbl_len = kmalloc(sizeof *device->pkey_tbl_len * num_ports, * access to this data as efficient as possible.
*
* Therefore port_immutable is declared as a 1 based array with
* potential empty slots at the beginning.
*/
device->port_immutable = kzalloc(sizeof(*device->port_immutable)
* (end_port + 1),
GFP_KERNEL); GFP_KERNEL);
device->gid_tbl_len = kmalloc(sizeof *device->gid_tbl_len * num_ports, if (!device->port_immutable)
GFP_KERNEL);
if (!device->pkey_tbl_len || !device->gid_tbl_len)
goto err; goto err;
for (port_index = 0; port_index < num_ports; ++port_index) { for (port = start_port; port <= end_port; ++port) {
ret = ib_query_port(device, port_index + start_port(device), ret = device->get_port_immutable(device, port,
tprops); &device->port_immutable[port]);
if (ret) if (ret)
goto err; goto err;
device->pkey_tbl_len[port_index] = tprops->pkey_tbl_len;
device->gid_tbl_len[port_index] = tprops->gid_tbl_len; if (verify_immutable(device, port)) {
ret = -EINVAL;
goto err;
}
} }
ret = 0; ret = 0;
goto out; goto out;
err: err:
kfree(device->gid_tbl_len); kfree(device->port_immutable);
kfree(device->pkey_tbl_len);
out: out:
kfree(tprops);
return ret; return ret;
} }
@ -294,9 +290,9 @@ int ib_register_device(struct ib_device *device,
spin_lock_init(&device->event_handler_lock); spin_lock_init(&device->event_handler_lock);
spin_lock_init(&device->client_data_lock); spin_lock_init(&device->client_data_lock);
ret = read_port_table_lengths(device); ret = read_port_immutable(device);
if (ret) { if (ret) {
printk(KERN_WARNING "Couldn't create table lengths cache for device %s\n", printk(KERN_WARNING "Couldn't create per port immutable data %s\n",
device->name); device->name);
goto out; goto out;
} }
@ -305,8 +301,7 @@ int ib_register_device(struct ib_device *device,
if (ret) { if (ret) {
printk(KERN_WARNING "Couldn't register device %s with driver model\n", printk(KERN_WARNING "Couldn't register device %s with driver model\n",
device->name); device->name);
kfree(device->gid_tbl_len); kfree(device->port_immutable);
kfree(device->pkey_tbl_len);
goto out; goto out;
} }
@ -348,9 +343,6 @@ void ib_unregister_device(struct ib_device *device)
list_del(&device->core_list); list_del(&device->core_list);
kfree(device->gid_tbl_len);
kfree(device->pkey_tbl_len);
mutex_unlock(&device_mutex); mutex_unlock(&device_mutex);
ib_device_unregister_sysfs(device); ib_device_unregister_sysfs(device);
@ -558,7 +550,11 @@ EXPORT_SYMBOL(ib_dispatch_event);
int ib_query_device(struct ib_device *device, int ib_query_device(struct ib_device *device,
struct ib_device_attr *device_attr) struct ib_device_attr *device_attr)
{ {
return device->query_device(device, device_attr); struct ib_udata uhw = {.outlen = 0, .inlen = 0};
memset(device_attr, 0, sizeof(*device_attr));
return device->query_device(device, device_attr, &uhw);
} }
EXPORT_SYMBOL(ib_query_device); EXPORT_SYMBOL(ib_query_device);
@ -575,7 +571,7 @@ int ib_query_port(struct ib_device *device,
u8 port_num, u8 port_num,
struct ib_port_attr *port_attr) struct ib_port_attr *port_attr)
{ {
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
return device->query_port(device, port_num, port_attr); return device->query_port(device, port_num, port_attr);
@ -653,7 +649,7 @@ int ib_modify_port(struct ib_device *device,
if (!device->modify_port) if (!device->modify_port)
return -ENOSYS; return -ENOSYS;
if (port_num < start_port(device) || port_num > end_port(device)) if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL; return -EINVAL;
return device->modify_port(device, port_num, port_modify_mask, return device->modify_port(device, port_num, port_modify_mask,
@ -676,8 +672,8 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid,
union ib_gid tmp_gid; union ib_gid tmp_gid;
int ret, port, i; int ret, port, i;
for (port = start_port(device); port <= end_port(device); ++port) { for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) {
for (i = 0; i < device->gid_tbl_len[port - start_port(device)]; ++i) { for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
ret = ib_query_gid(device, port, i, &tmp_gid); ret = ib_query_gid(device, port, i, &tmp_gid);
if (ret) if (ret)
return ret; return ret;
@ -709,7 +705,7 @@ int ib_find_pkey(struct ib_device *device,
u16 tmp_pkey; u16 tmp_pkey;
int partial_ix = -1; int partial_ix = -1;
for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) { for (i = 0; i < device->port_immutable[port_num].pkey_tbl_len; ++i) {
ret = ib_query_pkey(device, port_num, i, &tmp_pkey); ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
if (ret) if (ret)
return ret; return ret;

File diff suppressed because it is too large Load diff

View file

@ -41,6 +41,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <rdma/ib_mad.h> #include <rdma/ib_mad.h>
#include <rdma/ib_smi.h> #include <rdma/ib_smi.h>
#include <rdma/opa_smi.h>
#define IB_MAD_QPS_CORE 2 /* Always QP0 and QP1 as a minimum */ #define IB_MAD_QPS_CORE 2 /* Always QP0 and QP1 as a minimum */
@ -56,7 +57,7 @@
/* Registration table sizes */ /* Registration table sizes */
#define MAX_MGMT_CLASS 80 #define MAX_MGMT_CLASS 80
#define MAX_MGMT_VERSION 8 #define MAX_MGMT_VERSION 0x83
#define MAX_MGMT_OUI 8 #define MAX_MGMT_OUI 8
#define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \ #define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \
IB_MGMT_CLASS_VENDOR_RANGE2_START + 1) IB_MGMT_CLASS_VENDOR_RANGE2_START + 1)
@ -75,12 +76,9 @@ struct ib_mad_private_header {
struct ib_mad_private { struct ib_mad_private {
struct ib_mad_private_header header; struct ib_mad_private_header header;
size_t mad_size;
struct ib_grh grh; struct ib_grh grh;
union { u8 mad[0];
struct ib_mad mad;
struct ib_rmpp_mad rmpp_mad;
struct ib_smp smp;
} mad;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct ib_rmpp_segment { struct ib_rmpp_segment {
@ -150,6 +148,7 @@ struct ib_mad_local_private {
struct ib_mad_private *mad_priv; struct ib_mad_private *mad_priv;
struct ib_mad_agent_private *recv_mad_agent; struct ib_mad_agent_private *recv_mad_agent;
struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wr_private *mad_send_wr;
size_t return_wc_byte_len;
}; };
struct ib_mad_mgmt_method_table { struct ib_mad_mgmt_method_table {
@ -213,8 +212,8 @@ struct ib_mad_port_private {
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
struct ib_mad_send_wr_private * struct ib_mad_send_wr_private *
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, ib_find_send_mad(const struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_recv_wc *mad_recv_wc); const struct ib_mad_recv_wc *mad_recv_wc);
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc); struct ib_mad_send_wc *mad_send_wc);

View file

@ -1,6 +1,7 @@
/* /*
* Copyright (c) 2005 Intel Inc. All rights reserved. * Copyright (c) 2005 Intel Inc. All rights reserved.
* Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved.
* Copyright (c) 2014 Intel Corporation. All rights reserved.
* *
* This software is available to you under a choice of one of two * This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU * licenses. You may choose to be licensed under the terms of the GNU
@ -67,6 +68,7 @@ struct mad_rmpp_recv {
u8 mgmt_class; u8 mgmt_class;
u8 class_version; u8 class_version;
u8 method; u8 method;
u8 base_version;
}; };
static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv) static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
@ -139,7 +141,8 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, 1, hdr_len, recv_wc->wc->pkey_index, 1, hdr_len,
0, GFP_KERNEL); 0, GFP_KERNEL,
IB_MGMT_BASE_VERSION);
if (IS_ERR(msg)) if (IS_ERR(msg))
return; return;
@ -165,7 +168,8 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, 1, recv_wc->wc->pkey_index, 1,
hdr_len, 0, GFP_KERNEL); hdr_len, 0, GFP_KERNEL,
IB_MGMT_BASE_VERSION);
if (IS_ERR(msg)) if (IS_ERR(msg))
ib_destroy_ah(ah); ib_destroy_ah(ah);
else { else {
@ -316,6 +320,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
rmpp_recv->mgmt_class = mad_hdr->mgmt_class; rmpp_recv->mgmt_class = mad_hdr->mgmt_class;
rmpp_recv->class_version = mad_hdr->class_version; rmpp_recv->class_version = mad_hdr->class_version;
rmpp_recv->method = mad_hdr->method; rmpp_recv->method = mad_hdr->method;
rmpp_recv->base_version = mad_hdr->base_version;
return rmpp_recv; return rmpp_recv;
error: kfree(rmpp_recv); error: kfree(rmpp_recv);
@ -431,14 +436,23 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv)
{ {
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
int hdr_size, data_size, pad; int hdr_size, data_size, pad;
bool opa = rdma_cap_opa_mad(rmpp_recv->agent->qp_info->port_priv->device,
rmpp_recv->agent->qp_info->port_priv->port_num);
rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad;
hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
if (opa && rmpp_recv->base_version == OPA_MGMT_BASE_VERSION) {
data_size = sizeof(struct opa_rmpp_mad) - hdr_size;
pad = OPA_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
if (pad > OPA_MGMT_RMPP_DATA || pad < 0)
pad = 0;
} else {
data_size = sizeof(struct ib_rmpp_mad) - hdr_size; data_size = sizeof(struct ib_rmpp_mad) - hdr_size;
pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
if (pad > IB_MGMT_RMPP_DATA || pad < 0) if (pad > IB_MGMT_RMPP_DATA || pad < 0)
pad = 0; pad = 0;
}
return hdr_size + rmpp_recv->seg_num * data_size - pad; return hdr_size + rmpp_recv->seg_num * data_size - pad;
} }
@ -570,13 +584,14 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
if (mad_send_wr->seg_num == 1) { if (mad_send_wr->seg_num == 1) {
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST;
paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA - paylen = (mad_send_wr->send_buf.seg_count *
mad_send_wr->send_buf.seg_rmpp_size) -
mad_send_wr->pad; mad_send_wr->pad;
} }
if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) {
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST;
paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; paylen = mad_send_wr->send_buf.seg_rmpp_size - mad_send_wr->pad;
} }
rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);

View file

@ -780,8 +780,7 @@ static void mcast_event_handler(struct ib_event_handler *handler,
int index; int index;
dev = container_of(handler, struct mcast_device, event_handler); dev = container_of(handler, struct mcast_device, event_handler);
if (rdma_port_get_link_layer(dev->device, event->element.port_num) != if (!rdma_cap_ib_mcast(dev->device, event->element.port_num))
IB_LINK_LAYER_INFINIBAND)
return; return;
index = event->element.port_num - dev->start_port; index = event->element.port_num - dev->start_port;
@ -808,9 +807,6 @@ static void mcast_add_one(struct ib_device *device)
int i; int i;
int count = 0; int count = 0;
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return;
dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port, dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
GFP_KERNEL); GFP_KERNEL);
if (!dev) if (!dev)
@ -824,8 +820,7 @@ static void mcast_add_one(struct ib_device *device)
} }
for (i = 0; i <= dev->end_port - dev->start_port; i++) { for (i = 0; i <= dev->end_port - dev->start_port; i++) {
if (rdma_port_get_link_layer(device, dev->start_port + i) != if (!rdma_cap_ib_mcast(device, dev->start_port + i))
IB_LINK_LAYER_INFINIBAND)
continue; continue;
port = &dev->port[i]; port = &dev->port[i];
port->dev = dev; port->dev = dev;
@ -863,8 +858,7 @@ static void mcast_remove_one(struct ib_device *device)
flush_workqueue(mcast_wq); flush_workqueue(mcast_wq);
for (i = 0; i <= dev->end_port - dev->start_port; i++) { for (i = 0; i <= dev->end_port - dev->start_port; i++) {
if (rdma_port_get_link_layer(device, dev->start_port + i) == if (rdma_cap_ib_mcast(device, dev->start_port + i)) {
IB_LINK_LAYER_INFINIBAND) {
port = &dev->port[i]; port = &dev->port[i];
deref_port(port); deref_port(port);
wait_for_completion(&port->comp); wait_for_completion(&port->comp);

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2014 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifndef __OPA_SMI_H_
#define __OPA_SMI_H_
#include <rdma/ib_smi.h>
#include <rdma/opa_smi.h>
#include "smi.h"
enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type,
int port_num, int phys_port_cnt);
int opa_smi_get_fwd_port(struct opa_smp *smp);
extern enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp);
extern enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
u8 node_type, int port_num);
/*
* Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
* via process_mad
*/
static inline enum smi_action opa_smi_check_local_smp(struct opa_smp *smp,
struct ib_device *device)
{
/* C14-9:3 -- We're at the end of the DR segment of path */
/* C14-9:4 -- Hop Pointer = Hop Count + 1 -> give to SMA/SM */
return (device->process_mad &&
!opa_get_smp_direction(smp) &&
(smp->hop_ptr == smp->hop_cnt + 1)) ?
IB_SMI_HANDLE : IB_SMI_DISCARD;
}
/*
* Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
* via process_mad
*/
static inline enum smi_action opa_smi_check_local_returning_smp(struct opa_smp *smp,
struct ib_device *device)
{
/* C14-13:3 -- We're at the end of the DR segment of path */
/* C14-13:4 -- Hop Pointer == 0 -> give to SM */
return (device->process_mad &&
opa_get_smp_direction(smp) &&
!smp->hop_ptr) ? IB_SMI_HANDLE : IB_SMI_DISCARD;
}
#endif /* __OPA_SMI_H_ */

View file

@ -450,7 +450,7 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
struct ib_sa_port *port = struct ib_sa_port *port =
&sa_dev->port[event->element.port_num - sa_dev->start_port]; &sa_dev->port[event->element.port_num - sa_dev->start_port];
if (rdma_port_get_link_layer(handler->device, port->port_num) != IB_LINK_LAYER_INFINIBAND) if (!rdma_cap_ib_sa(handler->device, port->port_num))
return; return;
spin_lock_irqsave(&port->ah_lock, flags); spin_lock_irqsave(&port->ah_lock, flags);
@ -540,7 +540,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
ah_attr->port_num = port_num; ah_attr->port_num = port_num;
ah_attr->static_rate = rec->rate; ah_attr->static_rate = rec->rate;
force_grh = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_ETHERNET; force_grh = rdma_cap_eth_ah(device, port_num);
if (rec->hop_limit > 1 || force_grh) { if (rec->hop_limit > 1 || force_grh) {
ah_attr->ah_flags = IB_AH_GRH; ah_attr->ah_flags = IB_AH_GRH;
@ -583,7 +583,8 @@ static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)
query->mad_buf = ib_create_send_mad(query->port->agent, 1, query->mad_buf = ib_create_send_mad(query->port->agent, 1,
query->sm_ah->pkey_index, query->sm_ah->pkey_index,
0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA, 0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
gfp_mask); gfp_mask,
IB_MGMT_BASE_VERSION);
if (IS_ERR(query->mad_buf)) { if (IS_ERR(query->mad_buf)) {
kref_put(&query->sm_ah->ref, free_sm_ah); kref_put(&query->sm_ah->ref, free_sm_ah);
return -ENOMEM; return -ENOMEM;
@ -1153,9 +1154,7 @@ static void ib_sa_add_one(struct ib_device *device)
{ {
struct ib_sa_device *sa_dev; struct ib_sa_device *sa_dev;
int s, e, i; int s, e, i;
int count = 0;
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return;
if (device->node_type == RDMA_NODE_IB_SWITCH) if (device->node_type == RDMA_NODE_IB_SWITCH)
s = e = 0; s = e = 0;
@ -1175,7 +1174,7 @@ static void ib_sa_add_one(struct ib_device *device)
for (i = 0; i <= e - s; ++i) { for (i = 0; i <= e - s; ++i) {
spin_lock_init(&sa_dev->port[i].ah_lock); spin_lock_init(&sa_dev->port[i].ah_lock);
if (rdma_port_get_link_layer(device, i + 1) != IB_LINK_LAYER_INFINIBAND) if (!rdma_cap_ib_sa(device, i + 1))
continue; continue;
sa_dev->port[i].sm_ah = NULL; sa_dev->port[i].sm_ah = NULL;
@ -1189,8 +1188,13 @@ static void ib_sa_add_one(struct ib_device *device)
goto err; goto err;
INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);
count++;
} }
if (!count)
goto free;
ib_set_client_data(device, &sa_client, sa_dev); ib_set_client_data(device, &sa_client, sa_dev);
/* /*
@ -1204,19 +1208,20 @@ static void ib_sa_add_one(struct ib_device *device)
if (ib_register_event_handler(&sa_dev->event_handler)) if (ib_register_event_handler(&sa_dev->event_handler))
goto err; goto err;
for (i = 0; i <= e - s; ++i) for (i = 0; i <= e - s; ++i) {
if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) if (rdma_cap_ib_sa(device, i + 1))
update_sm_ah(&sa_dev->port[i].update_task); update_sm_ah(&sa_dev->port[i].update_task);
}
return; return;
err: err:
while (--i >= 0) while (--i >= 0) {
if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) if (rdma_cap_ib_sa(device, i + 1))
ib_unregister_mad_agent(sa_dev->port[i].agent); ib_unregister_mad_agent(sa_dev->port[i].agent);
}
free:
kfree(sa_dev); kfree(sa_dev);
return; return;
} }
@ -1233,7 +1238,7 @@ static void ib_sa_remove_one(struct ib_device *device)
flush_workqueue(ib_wq); flush_workqueue(ib_wq);
for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) { if (rdma_cap_ib_sa(device, i + 1)) {
ib_unregister_mad_agent(sa_dev->port[i].agent); ib_unregister_mad_agent(sa_dev->port[i].agent);
if (sa_dev->port[i].sm_ah) if (sa_dev->port[i].sm_ah)
kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);

View file

@ -5,6 +5,7 @@
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
* Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2014 Intel Corporation. All rights reserved.
* *
* This software is available to you under a choice of one of two * This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU * licenses. You may choose to be licensed under the terms of the GNU
@ -38,85 +39,82 @@
#include <rdma/ib_smi.h> #include <rdma/ib_smi.h>
#include "smi.h" #include "smi.h"
#include "opa_smi.h"
/* static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num,
* Fixup a directed route SMP for sending u8 *hop_ptr, u8 hop_cnt,
* Return 0 if the SMP should be discarded const u8 *initial_path,
*/ const u8 *return_path,
enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, u8 direction,
u8 node_type, int port_num) bool dr_dlid_is_permissive,
bool dr_slid_is_permissive)
{ {
u8 hop_ptr, hop_cnt;
hop_ptr = smp->hop_ptr;
hop_cnt = smp->hop_cnt;
/* See section 14.2.2.2, Vol 1 IB spec */ /* See section 14.2.2.2, Vol 1 IB spec */
/* C14-6 -- valid hop_cnt values are from 0 to 63 */ /* C14-6 -- valid hop_cnt values are from 0 to 63 */
if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
if (!ib_get_smp_direction(smp)) { if (!direction) {
/* C14-9:1 */ /* C14-9:1 */
if (hop_cnt && hop_ptr == 0) { if (hop_cnt && *hop_ptr == 0) {
smp->hop_ptr++; (*hop_ptr)++;
return (smp->initial_path[smp->hop_ptr] == return (initial_path[*hop_ptr] ==
port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-9:2 */ /* C14-9:2 */
if (hop_ptr && hop_ptr < hop_cnt) { if (*hop_ptr && *hop_ptr < hop_cnt) {
if (node_type != RDMA_NODE_IB_SWITCH) if (node_type != RDMA_NODE_IB_SWITCH)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
/* smp->return_path set when received */ /* return_path set when received */
smp->hop_ptr++; (*hop_ptr)++;
return (smp->initial_path[smp->hop_ptr] == return (initial_path[*hop_ptr] ==
port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-9:3 -- We're at the end of the DR segment of path */ /* C14-9:3 -- We're at the end of the DR segment of path */
if (hop_ptr == hop_cnt) { if (*hop_ptr == hop_cnt) {
/* smp->return_path set when received */ /* return_path set when received */
smp->hop_ptr++; (*hop_ptr)++;
return (node_type == RDMA_NODE_IB_SWITCH || return (node_type == RDMA_NODE_IB_SWITCH ||
smp->dr_dlid == IB_LID_PERMISSIVE ? dr_dlid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
/* C14-9:5 -- Fail unreasonable hop pointer */ /* C14-9:5 -- Fail unreasonable hop pointer */
return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} else { } else {
/* C14-13:1 */ /* C14-13:1 */
if (hop_cnt && hop_ptr == hop_cnt + 1) { if (hop_cnt && *hop_ptr == hop_cnt + 1) {
smp->hop_ptr--; (*hop_ptr)--;
return (smp->return_path[smp->hop_ptr] == return (return_path[*hop_ptr] ==
port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:2 */ /* C14-13:2 */
if (2 <= hop_ptr && hop_ptr <= hop_cnt) { if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
if (node_type != RDMA_NODE_IB_SWITCH) if (node_type != RDMA_NODE_IB_SWITCH)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
smp->hop_ptr--; (*hop_ptr)--;
return (smp->return_path[smp->hop_ptr] == return (return_path[*hop_ptr] ==
port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:3 -- at the end of the DR segment of path */ /* C14-13:3 -- at the end of the DR segment of path */
if (hop_ptr == 1) { if (*hop_ptr == 1) {
smp->hop_ptr--; (*hop_ptr)--;
/* C14-13:3 -- SMPs destined for SM shouldn't be here */ /* C14-13:3 -- SMPs destined for SM shouldn't be here */
return (node_type == RDMA_NODE_IB_SWITCH || return (node_type == RDMA_NODE_IB_SWITCH ||
smp->dr_slid == IB_LID_PERMISSIVE ? dr_slid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */ /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
if (hop_ptr == 0) if (*hop_ptr == 0)
return IB_SMI_HANDLE; return IB_SMI_HANDLE;
/* C14-13:5 -- Check for unreasonable hop pointer */ /* C14-13:5 -- Check for unreasonable hop pointer */
@ -125,105 +123,164 @@ enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
} }
/* /*
* Adjust information for a received SMP * Fixup a directed route SMP for sending
* Return 0 if the SMP should be dropped * Return IB_SMI_DISCARD if the SMP should be discarded
*/ */
enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
int port_num, int phys_port_cnt) u8 node_type, int port_num)
{ {
u8 hop_ptr, hop_cnt; return __smi_handle_dr_smp_send(node_type, port_num,
&smp->hop_ptr, smp->hop_cnt,
smp->initial_path,
smp->return_path,
ib_get_smp_direction(smp),
smp->dr_dlid == IB_LID_PERMISSIVE,
smp->dr_slid == IB_LID_PERMISSIVE);
}
hop_ptr = smp->hop_ptr; enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
hop_cnt = smp->hop_cnt; u8 node_type, int port_num)
{
return __smi_handle_dr_smp_send(node_type, port_num,
&smp->hop_ptr, smp->hop_cnt,
smp->route.dr.initial_path,
smp->route.dr.return_path,
opa_get_smp_direction(smp),
smp->route.dr.dr_dlid ==
OPA_LID_PERMISSIVE,
smp->route.dr.dr_slid ==
OPA_LID_PERMISSIVE);
}
static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num,
int phys_port_cnt,
u8 *hop_ptr, u8 hop_cnt,
const u8 *initial_path,
u8 *return_path,
u8 direction,
bool dr_dlid_is_permissive,
bool dr_slid_is_permissive)
{
/* See section 14.2.2.2, Vol 1 IB spec */ /* See section 14.2.2.2, Vol 1 IB spec */
/* C14-6 -- valid hop_cnt values are from 0 to 63 */ /* C14-6 -- valid hop_cnt values are from 0 to 63 */
if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
if (!ib_get_smp_direction(smp)) { if (!direction) {
/* C14-9:1 -- sender should have incremented hop_ptr */ /* C14-9:1 -- sender should have incremented hop_ptr */
if (hop_cnt && hop_ptr == 0) if (hop_cnt && *hop_ptr == 0)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
/* C14-9:2 -- intermediate hop */ /* C14-9:2 -- intermediate hop */
if (hop_ptr && hop_ptr < hop_cnt) { if (*hop_ptr && *hop_ptr < hop_cnt) {
if (node_type != RDMA_NODE_IB_SWITCH) if (node_type != RDMA_NODE_IB_SWITCH)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
smp->return_path[hop_ptr] = port_num; return_path[*hop_ptr] = port_num;
/* smp->hop_ptr updated when sending */ /* hop_ptr updated when sending */
return (smp->initial_path[hop_ptr+1] <= phys_port_cnt ? return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-9:3 -- We're at the end of the DR segment of path */ /* C14-9:3 -- We're at the end of the DR segment of path */
if (hop_ptr == hop_cnt) { if (*hop_ptr == hop_cnt) {
if (hop_cnt) if (hop_cnt)
smp->return_path[hop_ptr] = port_num; return_path[*hop_ptr] = port_num;
/* smp->hop_ptr updated when sending */ /* hop_ptr updated when sending */
return (node_type == RDMA_NODE_IB_SWITCH || return (node_type == RDMA_NODE_IB_SWITCH ||
smp->dr_dlid == IB_LID_PERMISSIVE ? dr_dlid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
/* C14-9:5 -- fail unreasonable hop pointer */ /* C14-9:5 -- fail unreasonable hop pointer */
return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} else { } else {
/* C14-13:1 */ /* C14-13:1 */
if (hop_cnt && hop_ptr == hop_cnt + 1) { if (hop_cnt && *hop_ptr == hop_cnt + 1) {
smp->hop_ptr--; (*hop_ptr)--;
return (smp->return_path[smp->hop_ptr] == return (return_path[*hop_ptr] ==
port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:2 */ /* C14-13:2 */
if (2 <= hop_ptr && hop_ptr <= hop_cnt) { if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
if (node_type != RDMA_NODE_IB_SWITCH) if (node_type != RDMA_NODE_IB_SWITCH)
return IB_SMI_DISCARD; return IB_SMI_DISCARD;
/* smp->hop_ptr updated when sending */ /* hop_ptr updated when sending */
return (smp->return_path[hop_ptr-1] <= phys_port_cnt ? return (return_path[*hop_ptr-1] <= phys_port_cnt ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:3 -- We're at the end of the DR segment of path */ /* C14-13:3 -- We're at the end of the DR segment of path */
if (hop_ptr == 1) { if (*hop_ptr == 1) {
if (smp->dr_slid == IB_LID_PERMISSIVE) { if (dr_slid_is_permissive) {
/* giving SMP to SM - update hop_ptr */ /* giving SMP to SM - update hop_ptr */
smp->hop_ptr--; (*hop_ptr)--;
return IB_SMI_HANDLE; return IB_SMI_HANDLE;
} }
/* smp->hop_ptr updated when sending */ /* hop_ptr updated when sending */
return (node_type == RDMA_NODE_IB_SWITCH ? return (node_type == RDMA_NODE_IB_SWITCH ?
IB_SMI_HANDLE : IB_SMI_DISCARD); IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
/* C14-13:4 -- hop_ptr = 0 -> give to SM */ /* C14-13:4 -- hop_ptr = 0 -> give to SM */
/* C14-13:5 -- Check for unreasonable hop pointer */ /* C14-13:5 -- Check for unreasonable hop pointer */
return (hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD); return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
} }
} }
enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) /*
* Adjust information for a received SMP
* Return IB_SMI_DISCARD if the SMP should be dropped
*/
enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
int port_num, int phys_port_cnt)
{ {
u8 hop_ptr, hop_cnt; return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
&smp->hop_ptr, smp->hop_cnt,
smp->initial_path,
smp->return_path,
ib_get_smp_direction(smp),
smp->dr_dlid == IB_LID_PERMISSIVE,
smp->dr_slid == IB_LID_PERMISSIVE);
}
hop_ptr = smp->hop_ptr; /*
hop_cnt = smp->hop_cnt; * Adjust information for a received SMP
* Return IB_SMI_DISCARD if the SMP should be dropped
*/
enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type,
int port_num, int phys_port_cnt)
{
return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
&smp->hop_ptr, smp->hop_cnt,
smp->route.dr.initial_path,
smp->route.dr.return_path,
opa_get_smp_direction(smp),
smp->route.dr.dr_dlid ==
OPA_LID_PERMISSIVE,
smp->route.dr.dr_slid ==
OPA_LID_PERMISSIVE);
}
if (!ib_get_smp_direction(smp)) { static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
u8 direction,
bool dr_dlid_is_permissive,
bool dr_slid_is_permissive)
{
if (!direction) {
/* C14-9:2 -- intermediate hop */ /* C14-9:2 -- intermediate hop */
if (hop_ptr && hop_ptr < hop_cnt) if (hop_ptr && hop_ptr < hop_cnt)
return IB_SMI_FORWARD; return IB_SMI_FORWARD;
/* C14-9:3 -- at the end of the DR segment of path */ /* C14-9:3 -- at the end of the DR segment of path */
if (hop_ptr == hop_cnt) if (hop_ptr == hop_cnt)
return (smp->dr_dlid == IB_LID_PERMISSIVE ? return (dr_dlid_is_permissive ?
IB_SMI_SEND : IB_SMI_LOCAL); IB_SMI_SEND : IB_SMI_LOCAL);
/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
@ -236,10 +293,29 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
/* C14-13:3 -- at the end of the DR segment of path */ /* C14-13:3 -- at the end of the DR segment of path */
if (hop_ptr == 1) if (hop_ptr == 1)
return (smp->dr_slid != IB_LID_PERMISSIVE ? return (!dr_slid_is_permissive ?
IB_SMI_SEND : IB_SMI_LOCAL); IB_SMI_SEND : IB_SMI_LOCAL);
} }
return IB_SMI_LOCAL; return IB_SMI_LOCAL;
}
enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
{
return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
ib_get_smp_direction(smp),
smp->dr_dlid == IB_LID_PERMISSIVE,
smp->dr_slid == IB_LID_PERMISSIVE);
}
enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp)
{
return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
opa_get_smp_direction(smp),
smp->route.dr.dr_dlid ==
OPA_LID_PERMISSIVE,
smp->route.dr.dr_slid ==
OPA_LID_PERMISSIVE);
} }
/* /*
@ -251,3 +327,13 @@ int smi_get_fwd_port(struct ib_smp *smp)
return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] : return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
smp->return_path[smp->hop_ptr-1]); smp->return_path[smp->hop_ptr-1]);
} }
/*
* Return the forwarding port number from initial_path for outgoing SMP and
* from return_path for returning SMP
*/
int opa_smi_get_fwd_port(struct opa_smp *smp)
{
return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] :
smp->route.dr.return_path[smp->hop_ptr-1];
}

View file

@ -326,6 +326,8 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
int width = (tab_attr->index >> 16) & 0xff; int width = (tab_attr->index >> 16) & 0xff;
struct ib_mad *in_mad = NULL; struct ib_mad *in_mad = NULL;
struct ib_mad *out_mad = NULL; struct ib_mad *out_mad = NULL;
size_t mad_size = sizeof(*out_mad);
u16 out_mad_pkey_index = 0;
ssize_t ret; ssize_t ret;
if (!p->ibdev->process_mad) if (!p->ibdev->process_mad)
@ -347,7 +349,10 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
in_mad->data[41] = p->port_num; /* PortSelect field */ in_mad->data[41] = p->port_num; /* PortSelect field */
if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY, if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY,
p->port_num, NULL, NULL, in_mad, out_mad) & p->port_num, NULL, NULL,
(const struct ib_mad_hdr *)in_mad, mad_size,
(struct ib_mad_hdr *)out_mad, &mad_size,
&out_mad_pkey_index) &
(IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) != (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
(IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) { (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
ret = -EINVAL; ret = -EINVAL;
@ -456,6 +461,7 @@ static void ib_device_release(struct device *device)
{ {
struct ib_device *dev = container_of(device, struct ib_device, dev); struct ib_device *dev = container_of(device, struct ib_device, dev);
kfree(dev->port_immutable);
kfree(dev); kfree(dev);
} }

View file

@ -1253,8 +1253,7 @@ static void ib_ucm_add_one(struct ib_device *device)
dev_t base; dev_t base;
struct ib_ucm_device *ucm_dev; struct ib_ucm_device *ucm_dev;
if (!device->alloc_ucontext || if (!device->alloc_ucontext || !rdma_cap_ib_cm(device, 1))
rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return; return;
ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL);

View file

@ -722,26 +722,13 @@ static ssize_t ucma_query_route(struct ucma_file *file,
resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid; resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
resp.port_num = ctx->cm_id->port_num; resp.port_num = ctx->cm_id->port_num;
switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
case RDMA_TRANSPORT_IB: if (rdma_cap_ib_sa(ctx->cm_id->device, ctx->cm_id->port_num))
switch (rdma_port_get_link_layer(ctx->cm_id->device,
ctx->cm_id->port_num)) {
case IB_LINK_LAYER_INFINIBAND:
ucma_copy_ib_route(&resp, &ctx->cm_id->route); ucma_copy_ib_route(&resp, &ctx->cm_id->route);
break; else if (rdma_protocol_roce(ctx->cm_id->device, ctx->cm_id->port_num))
case IB_LINK_LAYER_ETHERNET:
ucma_copy_iboe_route(&resp, &ctx->cm_id->route); ucma_copy_iboe_route(&resp, &ctx->cm_id->route);
break; else if (rdma_protocol_iwarp(ctx->cm_id->device, ctx->cm_id->port_num))
default:
break;
}
break;
case RDMA_TRANSPORT_IWARP:
ucma_copy_iw_route(&resp, &ctx->cm_id->route); ucma_copy_iw_route(&resp, &ctx->cm_id->route);
break;
default:
break;
}
out: out:
if (copy_to_user((void __user *)(unsigned long)cmd.response, if (copy_to_user((void __user *)(unsigned long)cmd.response,

View file

@ -99,7 +99,6 @@ struct ib_umad_port {
}; };
struct ib_umad_device { struct ib_umad_device {
int start_port, end_port;
struct kobject kobj; struct kobject kobj;
struct ib_umad_port port[0]; struct ib_umad_port port[0];
}; };
@ -263,20 +262,23 @@ static ssize_t copy_recv_mad(struct ib_umad_file *file, char __user *buf,
{ {
struct ib_mad_recv_buf *recv_buf; struct ib_mad_recv_buf *recv_buf;
int left, seg_payload, offset, max_seg_payload; int left, seg_payload, offset, max_seg_payload;
size_t seg_size;
recv_buf = &packet->recv_wc->recv_buf;
seg_size = packet->recv_wc->mad_seg_size;
/* We need enough room to copy the first (or only) MAD segment. */ /* We need enough room to copy the first (or only) MAD segment. */
recv_buf = &packet->recv_wc->recv_buf; if ((packet->length <= seg_size &&
if ((packet->length <= sizeof (*recv_buf->mad) &&
count < hdr_size(file) + packet->length) || count < hdr_size(file) + packet->length) ||
(packet->length > sizeof (*recv_buf->mad) && (packet->length > seg_size &&
count < hdr_size(file) + sizeof (*recv_buf->mad))) count < hdr_size(file) + seg_size))
return -EINVAL; return -EINVAL;
if (copy_to_user(buf, &packet->mad, hdr_size(file))) if (copy_to_user(buf, &packet->mad, hdr_size(file)))
return -EFAULT; return -EFAULT;
buf += hdr_size(file); buf += hdr_size(file);
seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad)); seg_payload = min_t(int, packet->length, seg_size);
if (copy_to_user(buf, recv_buf->mad, seg_payload)) if (copy_to_user(buf, recv_buf->mad, seg_payload))
return -EFAULT; return -EFAULT;
@ -293,7 +295,7 @@ static ssize_t copy_recv_mad(struct ib_umad_file *file, char __user *buf,
return -ENOSPC; return -ENOSPC;
} }
offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class);
max_seg_payload = sizeof (struct ib_mad) - offset; max_seg_payload = seg_size - offset;
for (left = packet->length - seg_payload, buf += seg_payload; for (left = packet->length - seg_payload, buf += seg_payload;
left; left -= seg_payload, buf += seg_payload) { left; left -= seg_payload, buf += seg_payload) {
@ -426,11 +428,11 @@ static int is_duplicate(struct ib_umad_file *file,
* the same TID, reject the second as a duplicate. This is more * the same TID, reject the second as a duplicate. This is more
* restrictive than required by the spec. * restrictive than required by the spec.
*/ */
if (!ib_response_mad((struct ib_mad *) hdr)) { if (!ib_response_mad(hdr)) {
if (!ib_response_mad((struct ib_mad *) sent_hdr)) if (!ib_response_mad(sent_hdr))
return 1; return 1;
continue; continue;
} else if (!ib_response_mad((struct ib_mad *) sent_hdr)) } else if (!ib_response_mad(sent_hdr))
continue; continue;
if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr)) if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr))
@ -451,6 +453,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
struct ib_rmpp_mad *rmpp_mad; struct ib_rmpp_mad *rmpp_mad;
__be64 *tid; __be64 *tid;
int ret, data_len, hdr_len, copy_offset, rmpp_active; int ret, data_len, hdr_len, copy_offset, rmpp_active;
u8 base_version;
if (count < hdr_size(file) + IB_MGMT_RMPP_HDR) if (count < hdr_size(file) + IB_MGMT_RMPP_HDR)
return -EINVAL; return -EINVAL;
@ -517,11 +520,13 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
rmpp_active = 0; rmpp_active = 0;
} }
base_version = ((struct ib_mad_hdr *)&packet->mad.data)->base_version;
data_len = count - hdr_size(file) - hdr_len; data_len = count - hdr_size(file) - hdr_len;
packet->msg = ib_create_send_mad(agent, packet->msg = ib_create_send_mad(agent,
be32_to_cpu(packet->mad.hdr.qpn), be32_to_cpu(packet->mad.hdr.qpn),
packet->mad.hdr.pkey_index, rmpp_active, packet->mad.hdr.pkey_index, rmpp_active,
hdr_len, data_len, GFP_KERNEL); hdr_len, data_len, GFP_KERNEL,
base_version);
if (IS_ERR(packet->msg)) { if (IS_ERR(packet->msg)) {
ret = PTR_ERR(packet->msg); ret = PTR_ERR(packet->msg);
goto err_ah; goto err_ah;
@ -1273,16 +1278,10 @@ static void ib_umad_add_one(struct ib_device *device)
{ {
struct ib_umad_device *umad_dev; struct ib_umad_device *umad_dev;
int s, e, i; int s, e, i;
int count = 0;
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) s = rdma_start_port(device);
return; e = rdma_end_port(device);
if (device->node_type == RDMA_NODE_IB_SWITCH)
s = e = 0;
else {
s = 1;
e = device->phys_port_cnt;
}
umad_dev = kzalloc(sizeof *umad_dev + umad_dev = kzalloc(sizeof *umad_dev +
(e - s + 1) * sizeof (struct ib_umad_port), (e - s + 1) * sizeof (struct ib_umad_port),
@ -1292,25 +1291,34 @@ static void ib_umad_add_one(struct ib_device *device)
kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype); kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype);
umad_dev->start_port = s;
umad_dev->end_port = e;
for (i = s; i <= e; ++i) { for (i = s; i <= e; ++i) {
if (!rdma_cap_ib_mad(device, i))
continue;
umad_dev->port[i - s].umad_dev = umad_dev; umad_dev->port[i - s].umad_dev = umad_dev;
if (ib_umad_init_port(device, i, umad_dev, if (ib_umad_init_port(device, i, umad_dev,
&umad_dev->port[i - s])) &umad_dev->port[i - s]))
goto err; goto err;
count++;
} }
if (!count)
goto free;
ib_set_client_data(device, &umad_client, umad_dev); ib_set_client_data(device, &umad_client, umad_dev);
return; return;
err: err:
while (--i >= s) while (--i >= s) {
ib_umad_kill_port(&umad_dev->port[i - s]); if (!rdma_cap_ib_mad(device, i))
continue;
ib_umad_kill_port(&umad_dev->port[i - s]);
}
free:
kobject_put(&umad_dev->kobj); kobject_put(&umad_dev->kobj);
} }
@ -1322,8 +1330,10 @@ static void ib_umad_remove_one(struct ib_device *device)
if (!umad_dev) if (!umad_dev)
return; return;
for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) for (i = 0; i <= rdma_end_port(device) - rdma_start_port(device); ++i) {
if (rdma_cap_ib_mad(device, i + rdma_start_port(device)))
ib_umad_kill_port(&umad_dev->port[i]); ib_umad_kill_port(&umad_dev->port[i]);
}
kobject_put(&umad_dev->kobj); kobject_put(&umad_dev->kobj);
} }

View file

@ -259,5 +259,6 @@ IB_UVERBS_DECLARE_CMD(close_xrcd);
IB_UVERBS_DECLARE_EX_CMD(create_flow); IB_UVERBS_DECLARE_EX_CMD(create_flow);
IB_UVERBS_DECLARE_EX_CMD(destroy_flow); IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
IB_UVERBS_DECLARE_EX_CMD(query_device); IB_UVERBS_DECLARE_EX_CMD(query_device);
IB_UVERBS_DECLARE_EX_CMD(create_cq);
#endif /* UVERBS_H */ #endif /* UVERBS_H */

View file

@ -1330,40 +1330,37 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
return in_len; return in_len;
} }
ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len, struct ib_udata *ucore,
int out_len) struct ib_udata *uhw,
struct ib_uverbs_ex_create_cq *cmd,
size_t cmd_sz,
int (*cb)(struct ib_uverbs_file *file,
struct ib_ucq_object *obj,
struct ib_uverbs_ex_create_cq_resp *resp,
struct ib_udata *udata,
void *context),
void *context)
{ {
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_create_cq_resp resp;
struct ib_udata udata;
struct ib_ucq_object *obj; struct ib_ucq_object *obj;
struct ib_uverbs_event_file *ev_file = NULL; struct ib_uverbs_event_file *ev_file = NULL;
struct ib_cq *cq; struct ib_cq *cq;
int ret; int ret;
struct ib_uverbs_ex_create_cq_resp resp;
struct ib_cq_init_attr attr = {};
if (out_len < sizeof resp) if (cmd->comp_vector >= file->device->num_comp_vectors)
return -ENOSPC; return ERR_PTR(-EINVAL);
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
if (cmd.comp_vector >= file->device->num_comp_vectors)
return -EINVAL;
obj = kmalloc(sizeof *obj, GFP_KERNEL); obj = kmalloc(sizeof *obj, GFP_KERNEL);
if (!obj) if (!obj)
return -ENOMEM; return ERR_PTR(-ENOMEM);
init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_class); init_uobj(&obj->uobject, cmd->user_handle, file->ucontext, &cq_lock_class);
down_write(&obj->uobject.mutex); down_write(&obj->uobject.mutex);
if (cmd.comp_channel >= 0) { if (cmd->comp_channel >= 0) {
ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel);
if (!ev_file) { if (!ev_file) {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
@ -1376,9 +1373,14 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&obj->comp_list); INIT_LIST_HEAD(&obj->comp_list);
INIT_LIST_HEAD(&obj->async_list); INIT_LIST_HEAD(&obj->async_list);
cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, attr.cqe = cmd->cqe;
cmd.comp_vector, attr.comp_vector = cmd->comp_vector;
file->ucontext, &udata);
if (cmd_sz > offsetof(typeof(*cmd), flags) + sizeof(cmd->flags))
attr.flags = cmd->flags;
cq = file->device->ib_dev->create_cq(file->device->ib_dev, &attr,
file->ucontext, uhw);
if (IS_ERR(cq)) { if (IS_ERR(cq)) {
ret = PTR_ERR(cq); ret = PTR_ERR(cq);
goto err_file; goto err_file;
@ -1397,14 +1399,15 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
goto err_free; goto err_free;
memset(&resp, 0, sizeof resp); memset(&resp, 0, sizeof resp);
resp.cq_handle = obj->uobject.id; resp.base.cq_handle = obj->uobject.id;
resp.cqe = cq->cqe; resp.base.cqe = cq->cqe;
if (copy_to_user((void __user *) (unsigned long) cmd.response, resp.response_length = offsetof(typeof(resp), response_length) +
&resp, sizeof resp)) { sizeof(resp.response_length);
ret = -EFAULT;
goto err_copy; ret = cb(file, obj, &resp, ucore, context);
} if (ret)
goto err_cb;
mutex_lock(&file->mutex); mutex_lock(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); list_add_tail(&obj->uobject.list, &file->ucontext->cq_list);
@ -1414,9 +1417,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
up_write(&obj->uobject.mutex); up_write(&obj->uobject.mutex);
return in_len; return obj;
err_copy: err_cb:
idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
err_free: err_free:
@ -1428,7 +1431,106 @@ err_file:
err: err:
put_uobj_write(&obj->uobject); put_uobj_write(&obj->uobject);
return ret;
return ERR_PTR(ret);
}
static int ib_uverbs_create_cq_cb(struct ib_uverbs_file *file,
struct ib_ucq_object *obj,
struct ib_uverbs_ex_create_cq_resp *resp,
struct ib_udata *ucore, void *context)
{
if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base)))
return -EFAULT;
return 0;
}
ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_ex_create_cq cmd_ex;
struct ib_uverbs_create_cq_resp resp;
struct ib_udata ucore;
struct ib_udata uhw;
struct ib_ucq_object *obj;
if (out_len < sizeof(resp))
return -ENOSPC;
if (copy_from_user(&cmd, buf, sizeof(cmd)))
return -EFAULT;
INIT_UDATA(&ucore, buf, cmd.response, sizeof(cmd), sizeof(resp));
INIT_UDATA(&uhw, buf + sizeof(cmd),
(unsigned long)cmd.response + sizeof(resp),
in_len - sizeof(cmd), out_len - sizeof(resp));
memset(&cmd_ex, 0, sizeof(cmd_ex));
cmd_ex.user_handle = cmd.user_handle;
cmd_ex.cqe = cmd.cqe;
cmd_ex.comp_vector = cmd.comp_vector;
cmd_ex.comp_channel = cmd.comp_channel;
obj = create_cq(file, &ucore, &uhw, &cmd_ex,
offsetof(typeof(cmd_ex), comp_channel) +
sizeof(cmd.comp_channel), ib_uverbs_create_cq_cb,
NULL);
if (IS_ERR(obj))
return PTR_ERR(obj);
return in_len;
}
static int ib_uverbs_ex_create_cq_cb(struct ib_uverbs_file *file,
struct ib_ucq_object *obj,
struct ib_uverbs_ex_create_cq_resp *resp,
struct ib_udata *ucore, void *context)
{
if (ib_copy_to_udata(ucore, resp, resp->response_length))
return -EFAULT;
return 0;
}
int ib_uverbs_ex_create_cq(struct ib_uverbs_file *file,
struct ib_udata *ucore,
struct ib_udata *uhw)
{
struct ib_uverbs_ex_create_cq_resp resp;
struct ib_uverbs_ex_create_cq cmd;
struct ib_ucq_object *obj;
int err;
if (ucore->inlen < sizeof(cmd))
return -EINVAL;
err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
if (err)
return err;
if (cmd.comp_mask)
return -EINVAL;
if (cmd.reserved)
return -EINVAL;
if (ucore->outlen < (offsetof(typeof(resp), response_length) +
sizeof(resp.response_length)))
return -ENOSPC;
obj = create_cq(file, ucore, uhw, &cmd,
min(ucore->inlen, sizeof(cmd)),
ib_uverbs_ex_create_cq_cb, NULL);
if (IS_ERR(obj))
return PTR_ERR(obj);
return 0;
} }
ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
@ -3324,7 +3426,9 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
if (ucore->outlen < resp.response_length) if (ucore->outlen < resp.response_length)
return -ENOSPC; return -ENOSPC;
err = device->query_device(device, &attr); memset(&attr, 0, sizeof(attr));
err = device->query_device(device, &attr, uhw);
if (err) if (err)
return err; return err;
@ -3348,6 +3452,18 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
#endif #endif
resp.response_length += sizeof(resp.odp_caps); resp.response_length += sizeof(resp.odp_caps);
if (ucore->outlen < resp.response_length + sizeof(resp.timestamp_mask))
goto end;
resp.timestamp_mask = attr.timestamp_mask;
resp.response_length += sizeof(resp.timestamp_mask);
if (ucore->outlen < resp.response_length + sizeof(resp.hca_core_clock))
goto end;
resp.hca_core_clock = attr.hca_core_clock;
resp.response_length += sizeof(resp.hca_core_clock);
end: end:
err = ib_copy_to_udata(ucore, &resp, resp.response_length); err = ib_copy_to_udata(ucore, &resp, resp.response_length);
if (err) if (err)

View file

@ -124,6 +124,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow, [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
[IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow, [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
[IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
[IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq,
}; };
static void ib_uverbs_add_one(struct ib_device *device); static void ib_uverbs_add_one(struct ib_device *device);

View file

@ -48,6 +48,71 @@
#include "core_priv.h" #include "core_priv.h"
static const char * const ib_events[] = {
[IB_EVENT_CQ_ERR] = "CQ error",
[IB_EVENT_QP_FATAL] = "QP fatal error",
[IB_EVENT_QP_REQ_ERR] = "QP request error",
[IB_EVENT_QP_ACCESS_ERR] = "QP access error",
[IB_EVENT_COMM_EST] = "communication established",
[IB_EVENT_SQ_DRAINED] = "send queue drained",
[IB_EVENT_PATH_MIG] = "path migration successful",
[IB_EVENT_PATH_MIG_ERR] = "path migration error",
[IB_EVENT_DEVICE_FATAL] = "device fatal error",
[IB_EVENT_PORT_ACTIVE] = "port active",
[IB_EVENT_PORT_ERR] = "port error",
[IB_EVENT_LID_CHANGE] = "LID change",
[IB_EVENT_PKEY_CHANGE] = "P_key change",
[IB_EVENT_SM_CHANGE] = "SM change",
[IB_EVENT_SRQ_ERR] = "SRQ error",
[IB_EVENT_SRQ_LIMIT_REACHED] = "SRQ limit reached",
[IB_EVENT_QP_LAST_WQE_REACHED] = "last WQE reached",
[IB_EVENT_CLIENT_REREGISTER] = "client reregister",
[IB_EVENT_GID_CHANGE] = "GID changed",
};
const char *ib_event_msg(enum ib_event_type event)
{
size_t index = event;
return (index < ARRAY_SIZE(ib_events) && ib_events[index]) ?
ib_events[index] : "unrecognized event";
}
EXPORT_SYMBOL(ib_event_msg);
static const char * const wc_statuses[] = {
[IB_WC_SUCCESS] = "success",
[IB_WC_LOC_LEN_ERR] = "local length error",
[IB_WC_LOC_QP_OP_ERR] = "local QP operation error",
[IB_WC_LOC_EEC_OP_ERR] = "local EE context operation error",
[IB_WC_LOC_PROT_ERR] = "local protection error",
[IB_WC_WR_FLUSH_ERR] = "WR flushed",
[IB_WC_MW_BIND_ERR] = "memory management operation error",
[IB_WC_BAD_RESP_ERR] = "bad response error",
[IB_WC_LOC_ACCESS_ERR] = "local access error",
[IB_WC_REM_INV_REQ_ERR] = "invalid request error",
[IB_WC_REM_ACCESS_ERR] = "remote access error",
[IB_WC_REM_OP_ERR] = "remote operation error",
[IB_WC_RETRY_EXC_ERR] = "transport retry counter exceeded",
[IB_WC_RNR_RETRY_EXC_ERR] = "RNR retry counter exceeded",
[IB_WC_LOC_RDD_VIOL_ERR] = "local RDD violation error",
[IB_WC_REM_INV_RD_REQ_ERR] = "remote invalid RD request",
[IB_WC_REM_ABORT_ERR] = "operation aborted",
[IB_WC_INV_EECN_ERR] = "invalid EE context number",
[IB_WC_INV_EEC_STATE_ERR] = "invalid EE context state",
[IB_WC_FATAL_ERR] = "fatal error",
[IB_WC_RESP_TIMEOUT_ERR] = "response timeout error",
[IB_WC_GENERAL_ERR] = "general error",
};
const char *ib_wc_status_msg(enum ib_wc_status status)
{
size_t index = status;
return (index < ARRAY_SIZE(wc_statuses) && wc_statuses[index]) ?
wc_statuses[index] : "unrecognized status";
}
EXPORT_SYMBOL(ib_wc_status_msg);
__attribute_const__ int ib_rate_to_mult(enum ib_rate rate) __attribute_const__ int ib_rate_to_mult(enum ib_rate rate)
{ {
switch (rate) { switch (rate) {
@ -192,17 +257,16 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
} }
EXPORT_SYMBOL(ib_create_ah); EXPORT_SYMBOL(ib_create_ah);
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
struct ib_grh *grh, struct ib_ah_attr *ah_attr) const struct ib_wc *wc, const struct ib_grh *grh,
struct ib_ah_attr *ah_attr)
{ {
u32 flow_class; u32 flow_class;
u16 gid_index; u16 gid_index;
int ret; int ret;
int is_eth = (rdma_port_get_link_layer(device, port_num) ==
IB_LINK_LAYER_ETHERNET);
memset(ah_attr, 0, sizeof *ah_attr); memset(ah_attr, 0, sizeof *ah_attr);
if (is_eth) { if (rdma_cap_eth_ah(device, port_num)) {
if (!(wc->wc_flags & IB_WC_GRH)) if (!(wc->wc_flags & IB_WC_GRH))
return -EPROTOTYPE; return -EPROTOTYPE;
@ -244,8 +308,8 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
} }
EXPORT_SYMBOL(ib_init_ah_from_wc); EXPORT_SYMBOL(ib_init_ah_from_wc);
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
struct ib_grh *grh, u8 port_num) const struct ib_grh *grh, u8 port_num)
{ {
struct ib_ah_attr ah_attr; struct ib_ah_attr ah_attr;
int ret; int ret;
@ -871,7 +935,7 @@ int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
union ib_gid sgid; union ib_gid sgid;
if ((*qp_attr_mask & IB_QP_AV) && if ((*qp_attr_mask & IB_QP_AV) &&
(rdma_port_get_link_layer(qp->device, qp_attr->ah_attr.port_num) == IB_LINK_LAYER_ETHERNET)) { (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) {
ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num,
qp_attr->ah_attr.grh.sgid_index, &sgid); qp_attr->ah_attr.grh.sgid_index, &sgid);
if (ret) if (ret)
@ -1012,11 +1076,12 @@ EXPORT_SYMBOL(ib_destroy_qp);
struct ib_cq *ib_create_cq(struct ib_device *device, struct ib_cq *ib_create_cq(struct ib_device *device,
ib_comp_handler comp_handler, ib_comp_handler comp_handler,
void (*event_handler)(struct ib_event *, void *), void (*event_handler)(struct ib_event *, void *),
void *cq_context, int cqe, int comp_vector) void *cq_context,
const struct ib_cq_init_attr *cq_attr)
{ {
struct ib_cq *cq; struct ib_cq *cq;
cq = device->create_cq(device, cqe, comp_vector, NULL, NULL); cq = device->create_cq(device, cq_attr, NULL, NULL);
if (!IS_ERR(cq)) { if (!IS_ERR(cq)) {
cq->device = device; cq->device = device;

View file

@ -63,13 +63,16 @@
#include "c2_provider.h" #include "c2_provider.h"
#include "c2_user.h" #include "c2_user.h"
static int c2_query_device(struct ib_device *ibdev, static int c2_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct c2_dev *c2dev = to_c2dev(ibdev); struct c2_dev *c2dev = to_c2dev(ibdev);
pr_debug("%s:%u\n", __func__, __LINE__); pr_debug("%s:%u\n", __func__, __LINE__);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
*props = c2dev->props; *props = c2dev->props;
return 0; return 0;
} }
@ -286,13 +289,18 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
return 0; return 0;
} }
static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vector, static struct ib_cq *c2_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct c2_cq *cq; struct c2_cq *cq;
int err; int err;
if (attr->flags)
return ERR_PTR(-EINVAL);
cq = kmalloc(sizeof(*cq), GFP_KERNEL); cq = kmalloc(sizeof(*cq), GFP_KERNEL);
if (!cq) { if (!cq) {
pr_debug("%s: Unable to allocate CQ\n", __func__); pr_debug("%s: Unable to allocate CQ\n", __func__);
@ -582,9 +590,13 @@ static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
static int c2_process_mad(struct ib_device *ibdev, static int c2_process_mad(struct ib_device *ibdev,
int mad_flags, int mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in_mad,
size_t in_mad_size,
struct ib_mad_hdr *out_mad,
size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
pr_debug("%s:%u\n", __func__, __LINE__); pr_debug("%s:%u\n", __func__, __LINE__);
return -ENOSYS; return -ENOSYS;
@ -757,6 +769,23 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
return netdev; return netdev;
} }
static int c2_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = c2_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
return 0;
}
int c2_register_device(struct c2_dev *dev) int c2_register_device(struct c2_dev *dev)
{ {
int ret = -ENOMEM; int ret = -ENOMEM;
@ -820,6 +849,7 @@ int c2_register_device(struct c2_dev *dev)
dev->ibdev.reg_phys_mr = c2_reg_phys_mr; dev->ibdev.reg_phys_mr = c2_reg_phys_mr;
dev->ibdev.reg_user_mr = c2_reg_user_mr; dev->ibdev.reg_user_mr = c2_reg_user_mr;
dev->ibdev.dereg_mr = c2_dereg_mr; dev->ibdev.dereg_mr = c2_dereg_mr;
dev->ibdev.get_port_immutable = c2_port_immutable;
dev->ibdev.alloc_fmr = NULL; dev->ibdev.alloc_fmr = NULL;
dev->ibdev.unmap_fmr = NULL; dev->ibdev.unmap_fmr = NULL;

View file

@ -85,9 +85,13 @@ static int iwch_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
static int iwch_process_mad(struct ib_device *ibdev, static int iwch_process_mad(struct ib_device *ibdev,
int mad_flags, int mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in_mad,
size_t in_mad_size,
struct ib_mad_hdr *out_mad,
size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
return -ENOSYS; return -ENOSYS;
} }
@ -138,10 +142,12 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
return 0; return 0;
} }
static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int vector, static struct ib_cq *iwch_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *ib_context, struct ib_ucontext *ib_context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct iwch_dev *rhp; struct iwch_dev *rhp;
struct iwch_cq *chp; struct iwch_cq *chp;
struct iwch_create_cq_resp uresp; struct iwch_create_cq_resp uresp;
@ -151,6 +157,9 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
size_t resplen; size_t resplen;
PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
if (attr->flags)
return ERR_PTR(-EINVAL);
rhp = to_iwch_dev(ibdev); rhp = to_iwch_dev(ibdev);
chp = kzalloc(sizeof(*chp), GFP_KERNEL); chp = kzalloc(sizeof(*chp), GFP_KERNEL);
if (!chp) if (!chp)
@ -1145,13 +1154,17 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev)
(fw_mic & 0xffff); (fw_mic & 0xffff);
} }
static int iwch_query_device(struct ib_device *ibdev, static int iwch_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct iwch_dev *dev; struct iwch_dev *dev;
PDBG("%s ibdev %p\n", __func__, ibdev); PDBG("%s ibdev %p\n", __func__, ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
dev = to_iwch_dev(ibdev); dev = to_iwch_dev(ibdev);
memset(props, 0, sizeof *props); memset(props, 0, sizeof *props);
memcpy(&props->sys_image_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6); memcpy(&props->sys_image_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
@ -1343,6 +1356,23 @@ static struct device_attribute *iwch_class_attributes[] = {
&dev_attr_board_id, &dev_attr_board_id,
}; };
static int iwch_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = iwch_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
return 0;
}
int iwch_register_device(struct iwch_dev *dev) int iwch_register_device(struct iwch_dev *dev)
{ {
int ret; int ret;
@ -1420,6 +1450,7 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.post_recv = iwch_post_receive; dev->ibdev.post_recv = iwch_post_receive;
dev->ibdev.get_protocol_stats = iwch_get_mib; dev->ibdev.get_protocol_stats = iwch_get_mib;
dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION; dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION;
dev->ibdev.get_port_immutable = iwch_port_immutable;
dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
if (!dev->ibdev.iwcm) if (!dev->ibdev.iwcm)

View file

@ -156,19 +156,17 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
goto err4; goto err4;
cq->gen = 1; cq->gen = 1;
cq->rdev = rdev;
if (user) {
u32 off = (cq->cqid << rdev->cqshift) & PAGE_MASK;
cq->ugts = (u64)rdev->bar2_pa + off;
} else if (is_t4(rdev->lldi.adapter_type)) {
cq->gts = rdev->lldi.gts_reg; cq->gts = rdev->lldi.gts_reg;
cq->qid_mask = -1U; cq->rdev = rdev;
} else {
u32 off = ((cq->cqid << rdev->cqshift) & PAGE_MASK) + 12;
cq->gts = rdev->bar2_kva + off; cq->bar2_va = c4iw_bar2_addrs(rdev, cq->cqid, T4_BAR2_QTYPE_INGRESS,
cq->qid_mask = rdev->qpmask; &cq->bar2_qid,
user ? &cq->bar2_pa : NULL);
if (user && !cq->bar2_va) {
pr_warn(MOD "%s: cqid %u not in BAR2 range.\n",
pci_name(rdev->lldi.pdev), cq->cqid);
ret = -EINVAL;
goto err4;
} }
return 0; return 0;
err4: err4:
@ -866,10 +864,13 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq)
return 0; return 0;
} }
struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
int vector, struct ib_ucontext *ib_context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *ib_context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
int vector = attr->comp_vector;
struct c4iw_dev *rhp; struct c4iw_dev *rhp;
struct c4iw_cq *chp; struct c4iw_cq *chp;
struct c4iw_create_cq_resp uresp; struct c4iw_create_cq_resp uresp;
@ -879,6 +880,8 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
struct c4iw_mm_entry *mm, *mm2; struct c4iw_mm_entry *mm, *mm2;
PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
if (attr->flags)
return ERR_PTR(-EINVAL);
rhp = to_c4iw_dev(ibdev); rhp = to_c4iw_dev(ibdev);
@ -971,7 +974,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
insert_mmap(ucontext, mm); insert_mmap(ucontext, mm);
mm2->key = uresp.gts_key; mm2->key = uresp.gts_key;
mm2->addr = chp->cq.ugts; mm2->addr = chp->cq.bar2_pa;
mm2->len = PAGE_SIZE; mm2->len = PAGE_SIZE;
insert_mmap(ucontext, mm2); insert_mmap(ucontext, mm2);
} }

View file

@ -795,13 +795,7 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
goto err1; goto err1;
} }
/*
* qpshift is the number of bits to shift the qpid left in order
* to get the correct address of the doorbell for that qp.
*/
rdev->qpshift = PAGE_SHIFT - ilog2(rdev->lldi.udb_density);
rdev->qpmask = rdev->lldi.udb_density - 1; rdev->qpmask = rdev->lldi.udb_density - 1;
rdev->cqshift = PAGE_SHIFT - ilog2(rdev->lldi.ucq_density);
rdev->cqmask = rdev->lldi.ucq_density - 1; rdev->cqmask = rdev->lldi.ucq_density - 1;
PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d " PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d "
"pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x " "pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x "
@ -815,14 +809,12 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
rdev->lldi.vr->qp.size, rdev->lldi.vr->qp.size,
rdev->lldi.vr->cq.start, rdev->lldi.vr->cq.start,
rdev->lldi.vr->cq.size); rdev->lldi.vr->cq.size);
PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu " PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p "
"qpmask 0x%x cqshift %lu cqmask 0x%x\n", "qpmask 0x%x cqmask 0x%x\n",
(unsigned)pci_resource_len(rdev->lldi.pdev, 2), (unsigned)pci_resource_len(rdev->lldi.pdev, 2),
(void *)pci_resource_start(rdev->lldi.pdev, 2), (void *)pci_resource_start(rdev->lldi.pdev, 2),
rdev->lldi.db_reg, rdev->lldi.db_reg, rdev->lldi.gts_reg,
rdev->lldi.gts_reg, rdev->qpmask, rdev->cqmask);
rdev->qpshift, rdev->qpmask,
rdev->cqshift, rdev->cqmask);
if (c4iw_num_stags(rdev) == 0) { if (c4iw_num_stags(rdev) == 0) {
err = -EINVAL; err = -EINVAL;

View file

@ -165,9 +165,7 @@ struct wr_log_entry {
struct c4iw_rdev { struct c4iw_rdev {
struct c4iw_resource resource; struct c4iw_resource resource;
unsigned long qpshift;
u32 qpmask; u32 qpmask;
unsigned long cqshift;
u32 cqmask; u32 cqmask;
struct c4iw_dev_ucontext uctx; struct c4iw_dev_ucontext uctx;
struct gen_pool *pbl_pool; struct gen_pool *pbl_pool;
@ -992,8 +990,8 @@ int c4iw_reregister_phys_mem(struct ib_mr *mr,
int acc, u64 *iova_start); int acc, u64 *iova_start);
int c4iw_dereg_mr(struct ib_mr *ib_mr); int c4iw_dereg_mr(struct ib_mr *ib_mr);
int c4iw_destroy_cq(struct ib_cq *ib_cq); int c4iw_destroy_cq(struct ib_cq *ib_cq);
struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
int vector, const struct ib_cq_init_attr *attr,
struct ib_ucontext *ib_context, struct ib_ucontext *ib_context,
struct ib_udata *udata); struct ib_udata *udata);
int c4iw_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); int c4iw_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata);
@ -1032,6 +1030,9 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe);
extern struct cxgb4_client t4c_client; extern struct cxgb4_client t4c_client;
extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS]; extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid,
enum cxgb4_bar2_qtype qtype,
unsigned int *pbar2_qid, u64 *pbar2_pa);
extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe); extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe);
extern int c4iw_wr_log; extern int c4iw_wr_log;
extern int db_fc_threshold; extern int db_fc_threshold;

View file

@ -80,9 +80,13 @@ static int c4iw_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
} }
static int c4iw_process_mad(struct ib_device *ibdev, int mad_flags, static int c4iw_process_mad(struct ib_device *ibdev, int mad_flags,
u8 port_num, struct ib_wc *in_wc, u8 port_num, const struct ib_wc *in_wc,
struct ib_grh *in_grh, struct ib_mad *in_mad, const struct ib_grh *in_grh,
struct ib_mad *out_mad) const struct ib_mad_hdr *in_mad,
size_t in_mad_size,
struct ib_mad_hdr *out_mad,
size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
return -ENOSYS; return -ENOSYS;
} }
@ -301,13 +305,17 @@ static int c4iw_query_gid(struct ib_device *ibdev, u8 port, int index,
return 0; return 0;
} }
static int c4iw_query_device(struct ib_device *ibdev, static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct c4iw_dev *dev; struct c4iw_dev *dev;
PDBG("%s ibdev %p\n", __func__, ibdev); PDBG("%s ibdev %p\n", __func__, ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
dev = to_c4iw_dev(ibdev); dev = to_c4iw_dev(ibdev);
memset(props, 0, sizeof *props); memset(props, 0, sizeof *props);
memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6); memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6);
@ -465,6 +473,23 @@ static struct device_attribute *c4iw_class_attributes[] = {
&dev_attr_board_id, &dev_attr_board_id,
}; };
static int c4iw_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = c4iw_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
return 0;
}
int c4iw_register_device(struct c4iw_dev *dev) int c4iw_register_device(struct c4iw_dev *dev)
{ {
int ret; int ret;
@ -542,6 +567,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.post_recv = c4iw_post_receive; dev->ibdev.post_recv = c4iw_post_receive;
dev->ibdev.get_protocol_stats = c4iw_get_mib; dev->ibdev.get_protocol_stats = c4iw_get_mib;
dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION; dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
dev->ibdev.get_port_immutable = c4iw_port_immutable;
dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
if (!dev->ibdev.iwcm) if (!dev->ibdev.iwcm)

View file

@ -165,6 +165,29 @@ static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
return 0; return 0;
} }
/*
* Determine the BAR2 virtual address and qid. If pbar2_pa is not NULL,
* then this is a user mapping so compute the page-aligned physical address
* for mapping.
*/
void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid,
enum cxgb4_bar2_qtype qtype,
unsigned int *pbar2_qid, u64 *pbar2_pa)
{
u64 bar2_qoffset;
int ret;
ret = cxgb4_bar2_sge_qregs(rdev->lldi.ports[0], qid, qtype,
pbar2_pa ? 1 : 0,
&bar2_qoffset, pbar2_qid);
if (ret)
return NULL;
if (pbar2_pa)
*pbar2_pa = (rdev->bar2_pa + bar2_qoffset) & PAGE_MASK;
return rdev->bar2_kva + bar2_qoffset;
}
static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
struct t4_cq *rcq, struct t4_cq *scq, struct t4_cq *rcq, struct t4_cq *scq,
struct c4iw_dev_ucontext *uctx) struct c4iw_dev_ucontext *uctx)
@ -236,25 +259,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr); dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr);
wq->db = rdev->lldi.db_reg; wq->db = rdev->lldi.db_reg;
wq->gts = rdev->lldi.gts_reg;
if (user || is_t5(rdev->lldi.adapter_type)) {
u32 off;
off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK; wq->sq.bar2_va = c4iw_bar2_addrs(rdev, wq->sq.qid, T4_BAR2_QTYPE_EGRESS,
if (user) { &wq->sq.bar2_qid,
wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off); user ? &wq->sq.bar2_pa : NULL);
} else { wq->rq.bar2_va = c4iw_bar2_addrs(rdev, wq->rq.qid, T4_BAR2_QTYPE_EGRESS,
off += 128 * (wq->sq.qid & rdev->qpmask) + 8; &wq->rq.bar2_qid,
wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off); user ? &wq->rq.bar2_pa : NULL);
}
off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK; /*
if (user) { * User mode must have bar2 access.
wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off); */
} else { if (user && (!wq->sq.bar2_va || !wq->rq.bar2_va)) {
off += 128 * (wq->rq.qid & rdev->qpmask) + 8; pr_warn(MOD "%s: sqid %u or rqid %u not in BAR2 range.\n",
wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off); pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid);
} goto free_dma;
} }
wq->rdev = rdev; wq->rdev = rdev;
wq->rq.msn = 1; wq->rq.msn = 1;
@ -336,10 +357,9 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
if (ret) if (ret)
goto free_dma; goto free_dma;
PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n", PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p sq_bar2_addr %p rq_bar2_addr %p\n",
__func__, wq->sq.qid, wq->rq.qid, wq->db, __func__, wq->sq.qid, wq->rq.qid, wq->db,
(__force unsigned long) wq->sq.udb, wq->sq.bar2_va, wq->rq.bar2_va);
(__force unsigned long) wq->rq.udb);
return 0; return 0;
free_dma: free_dma:
@ -1766,11 +1786,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize);
insert_mmap(ucontext, mm2); insert_mmap(ucontext, mm2);
mm3->key = uresp.sq_db_gts_key; mm3->key = uresp.sq_db_gts_key;
mm3->addr = (__force unsigned long)qhp->wq.sq.udb; mm3->addr = (__force unsigned long)qhp->wq.sq.bar2_pa;
mm3->len = PAGE_SIZE; mm3->len = PAGE_SIZE;
insert_mmap(ucontext, mm3); insert_mmap(ucontext, mm3);
mm4->key = uresp.rq_db_gts_key; mm4->key = uresp.rq_db_gts_key;
mm4->addr = (__force unsigned long)qhp->wq.rq.udb; mm4->addr = (__force unsigned long)qhp->wq.rq.bar2_pa;
mm4->len = PAGE_SIZE; mm4->len = PAGE_SIZE;
insert_mmap(ucontext, mm4); insert_mmap(ucontext, mm4);
if (mm5) { if (mm5) {

View file

@ -33,6 +33,7 @@
#include "t4_hw.h" #include "t4_hw.h"
#include "t4_regs.h" #include "t4_regs.h"
#include "t4_values.h"
#include "t4_msg.h" #include "t4_msg.h"
#include "t4fw_ri_api.h" #include "t4fw_ri_api.h"
@ -290,8 +291,10 @@ struct t4_sq {
unsigned long phys_addr; unsigned long phys_addr;
struct t4_swsqe *sw_sq; struct t4_swsqe *sw_sq;
struct t4_swsqe *oldest_read; struct t4_swsqe *oldest_read;
u64 __iomem *udb; void __iomem *bar2_va;
u64 bar2_pa;
size_t memsize; size_t memsize;
u32 bar2_qid;
u32 qid; u32 qid;
u16 in_use; u16 in_use;
u16 size; u16 size;
@ -314,8 +317,10 @@ struct t4_rq {
dma_addr_t dma_addr; dma_addr_t dma_addr;
DEFINE_DMA_UNMAP_ADDR(mapping); DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_swrqe *sw_rq; struct t4_swrqe *sw_rq;
u64 __iomem *udb; void __iomem *bar2_va;
u64 bar2_pa;
size_t memsize; size_t memsize;
u32 bar2_qid;
u32 qid; u32 qid;
u32 msn; u32 msn;
u32 rqt_hwaddr; u32 rqt_hwaddr;
@ -332,7 +337,6 @@ struct t4_wq {
struct t4_sq sq; struct t4_sq sq;
struct t4_rq rq; struct t4_rq rq;
void __iomem *db; void __iomem *db;
void __iomem *gts;
struct c4iw_rdev *rdev; struct c4iw_rdev *rdev;
int flushed; int flushed;
}; };
@ -457,15 +461,18 @@ static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5,
/* Flush host queue memory writes. */ /* Flush host queue memory writes. */
wmb(); wmb();
if (t5) { if (wq->sq.bar2_va) {
if (inc == 1 && wqe) { if (inc == 1 && wq->sq.bar2_qid == 0 && wqe) {
PDBG("%s: WC wq->sq.pidx = %d\n", PDBG("%s: WC wq->sq.pidx = %d\n",
__func__, wq->sq.pidx); __func__, wq->sq.pidx);
pio_copy(wq->sq.udb + 7, (void *)wqe); pio_copy((u64 __iomem *)
(wq->sq.bar2_va + SGE_UDB_WCDOORBELL),
(u64 *)wqe);
} else { } else {
PDBG("%s: DB wq->sq.pidx = %d\n", PDBG("%s: DB wq->sq.pidx = %d\n",
__func__, wq->sq.pidx); __func__, wq->sq.pidx);
writel(PIDX_T5_V(inc), wq->sq.udb); writel(PIDX_T5_V(inc) | QID_V(wq->sq.bar2_qid),
wq->sq.bar2_va + SGE_UDB_KDOORBELL);
} }
/* Flush user doorbell area writes. */ /* Flush user doorbell area writes. */
@ -481,15 +488,18 @@ static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5,
/* Flush host queue memory writes. */ /* Flush host queue memory writes. */
wmb(); wmb();
if (t5) { if (wq->rq.bar2_va) {
if (inc == 1 && wqe) { if (inc == 1 && wq->rq.bar2_qid == 0 && wqe) {
PDBG("%s: WC wq->rq.pidx = %d\n", PDBG("%s: WC wq->rq.pidx = %d\n",
__func__, wq->rq.pidx); __func__, wq->rq.pidx);
pio_copy(wq->rq.udb + 7, (void *)wqe); pio_copy((u64 __iomem *)
(wq->rq.bar2_va + SGE_UDB_WCDOORBELL),
(void *)wqe);
} else { } else {
PDBG("%s: DB wq->rq.pidx = %d\n", PDBG("%s: DB wq->rq.pidx = %d\n",
__func__, wq->rq.pidx); __func__, wq->rq.pidx);
writel(PIDX_T5_V(inc), wq->rq.udb); writel(PIDX_T5_V(inc) | QID_V(wq->rq.bar2_qid),
wq->rq.bar2_va + SGE_UDB_KDOORBELL);
} }
/* Flush user doorbell area writes. */ /* Flush user doorbell area writes. */
@ -534,8 +544,10 @@ struct t4_cq {
DEFINE_DMA_UNMAP_ADDR(mapping); DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_cqe *sw_queue; struct t4_cqe *sw_queue;
void __iomem *gts; void __iomem *gts;
void __iomem *bar2_va;
u64 bar2_pa;
u32 bar2_qid;
struct c4iw_rdev *rdev; struct c4iw_rdev *rdev;
u64 ugts;
size_t memsize; size_t memsize;
__be64 bits_type_ts; __be64 bits_type_ts;
u32 cqid; u32 cqid;
@ -552,6 +564,15 @@ struct t4_cq {
unsigned long flags; unsigned long flags;
}; };
static inline void write_gts(struct t4_cq *cq, u32 val)
{
if (cq->bar2_va)
writel(val | INGRESSQID_V(cq->bar2_qid),
cq->bar2_va + SGE_UDB_GTS);
else
writel(val | INGRESSQID_V(cq->cqid), cq->gts);
}
static inline int t4_clear_cq_armed(struct t4_cq *cq) static inline int t4_clear_cq_armed(struct t4_cq *cq)
{ {
return test_and_clear_bit(CQ_ARMED, &cq->flags); return test_and_clear_bit(CQ_ARMED, &cq->flags);
@ -563,14 +584,12 @@ static inline int t4_arm_cq(struct t4_cq *cq, int se)
set_bit(CQ_ARMED, &cq->flags); set_bit(CQ_ARMED, &cq->flags);
while (cq->cidx_inc > CIDXINC_M) { while (cq->cidx_inc > CIDXINC_M) {
val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7) | val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7);
INGRESSQID_V(cq->cqid & cq->qid_mask); write_gts(cq, val);
writel(val, cq->gts);
cq->cidx_inc -= CIDXINC_M; cq->cidx_inc -= CIDXINC_M;
} }
val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6) | val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6);
INGRESSQID_V(cq->cqid & cq->qid_mask); write_gts(cq, val);
writel(val, cq->gts);
cq->cidx_inc = 0; cq->cidx_inc = 0;
return 0; return 0;
} }
@ -601,9 +620,8 @@ static inline void t4_hwcq_consume(struct t4_cq *cq)
if (++cq->cidx_inc == (cq->size >> 4) || cq->cidx_inc == CIDXINC_M) { if (++cq->cidx_inc == (cq->size >> 4) || cq->cidx_inc == CIDXINC_M) {
u32 val; u32 val;
val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7) | val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7);
INGRESSQID_V(cq->cqid & cq->qid_mask); write_gts(cq, val);
writel(val, cq->gts);
cq->cidx_inc = 0; cq->cidx_inc = 0;
} }
if (++cq->cidx == cq->size) { if (++cq->cidx == cq->size) {

View file

@ -113,10 +113,12 @@ struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
return ret; return ret;
} }
struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, struct ib_cq *ehca_create_cq(struct ib_device *device,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int cqe = attr->cqe;
static const u32 additional_cqe = 20; static const u32 additional_cqe = 20;
struct ib_cq *cq; struct ib_cq *cq;
struct ehca_cq *my_cq; struct ehca_cq *my_cq;
@ -131,6 +133,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
int ipz_rc, i; int ipz_rc, i;
unsigned long flags; unsigned long flags;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);

View file

@ -50,7 +50,8 @@ static unsigned int limit_uint(unsigned int value)
return min_t(unsigned int, value, INT_MAX); return min_t(unsigned int, value, INT_MAX);
} }
int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_udata *uhw)
{ {
int i, ret = 0; int i, ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
@ -71,6 +72,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT, IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT,
}; };
if (uhw->inlen || uhw->outlen)
return -EINVAL;
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) { if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory."); ehca_err(&shca->ib_device, "Can't allocate rblock memory.");

View file

@ -44,11 +44,15 @@
#include "ehca_classes.h" #include "ehca_classes.h"
int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props); int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_udata *uhw);
int ehca_query_port(struct ib_device *ibdev, u8 port, int ehca_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props); struct ib_port_attr *props);
enum rdma_protocol_type
ehca_query_protocol(struct ib_device *device, u8 port_num);
int ehca_query_sma_attr(struct ehca_shca *shca, u8 port, int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
struct ehca_sma_attr *attr); struct ehca_sma_attr *attr);
@ -126,7 +130,8 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, struct ib_cq *ehca_create_cq(struct ib_device *device,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
@ -188,9 +193,10 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context);
int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad *out_mad); struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
void ehca_poll_eqs(unsigned long data); void ehca_poll_eqs(unsigned long data);

View file

@ -46,6 +46,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/memory.h> #include <linux/memory.h>
#include <rdma/ib_mad.h>
#include "ehca_classes.h" #include "ehca_classes.h"
#include "ehca_iverbs.h" #include "ehca_iverbs.h"
#include "ehca_mrmw.h" #include "ehca_mrmw.h"
@ -431,6 +432,24 @@ init_node_guid1:
return ret; return ret;
} }
static int ehca_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = ehca_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
static int ehca_init_device(struct ehca_shca *shca) static int ehca_init_device(struct ehca_shca *shca)
{ {
int ret; int ret;
@ -510,6 +529,7 @@ static int ehca_init_device(struct ehca_shca *shca)
shca->ib_device.process_mad = ehca_process_mad; shca->ib_device.process_mad = ehca_process_mad;
shca->ib_device.mmap = ehca_mmap; shca->ib_device.mmap = ehca_mmap;
shca->ib_device.dma_ops = &ehca_dma_mapping_ops; shca->ib_device.dma_ops = &ehca_dma_mapping_ops;
shca->ib_device.get_port_immutable = ehca_port_immutable;
if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) { if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
shca->ib_device.uverbs_cmd_mask |= shca->ib_device.uverbs_cmd_mask |=
@ -534,6 +554,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
struct ib_cq *ibcq; struct ib_cq *ibcq;
struct ib_qp *ibqp; struct ib_qp *ibqp;
struct ib_qp_init_attr qp_init_attr; struct ib_qp_init_attr qp_init_attr;
struct ib_cq_init_attr cq_attr = {};
int ret; int ret;
if (sport->ibcq_aqp1) { if (sport->ibcq_aqp1) {
@ -541,7 +562,9 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
return -EPERM; return -EPERM;
} }
ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), 10, 0); cq_attr.cqe = 10;
ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1),
&cq_attr);
if (IS_ERR(ibcq)) { if (IS_ERR(ibcq)) {
ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
return PTR_ERR(ibcq); return PTR_ERR(ibcq);

View file

@ -140,10 +140,10 @@ struct vertcfl {
} __attribute__ ((packed)); } __attribute__ ((packed));
static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad *in_mad, struct ib_mad *out_mad)
{ {
struct ib_perf *in_perf = (struct ib_perf *)in_mad; const struct ib_perf *in_perf = (const struct ib_perf *)in_mad;
struct ib_perf *out_perf = (struct ib_perf *)out_mad; struct ib_perf *out_perf = (struct ib_perf *)out_mad;
struct ib_class_port_info *poi = struct ib_class_port_info *poi =
(struct ib_class_port_info *)out_perf->data; (struct ib_class_port_info *)out_perf->data;
@ -187,8 +187,8 @@ static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
/* if request was globally routed, copy route info */ /* if request was globally routed, copy route info */
if (in_grh) { if (in_grh) {
struct vertcfl *vertcfl = const struct vertcfl *vertcfl =
(struct vertcfl *)&in_grh->version_tclass_flow; (const struct vertcfl *)&in_grh->version_tclass_flow;
memcpy(poi->redirect_gid, in_grh->dgid.raw, memcpy(poi->redirect_gid, in_grh->dgid.raw,
sizeof(poi->redirect_gid)); sizeof(poi->redirect_gid));
tcslfl->tc = vertcfl->tc; tcslfl->tc = vertcfl->tc;
@ -217,10 +217,17 @@ perf_reply:
} }
int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
int ret; int ret;
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc) if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
return IB_MAD_RESULT_FAILURE; return IB_MAD_RESULT_FAILURE;

View file

@ -188,7 +188,7 @@ static void send_complete(unsigned long data)
/** /**
* ipath_create_cq - create a completion queue * ipath_create_cq - create a completion queue
* @ibdev: the device this completion queue is attached to * @ibdev: the device this completion queue is attached to
* @entries: the minimum size of the completion queue * @attr: creation attributes
* @context: unused by the InfiniPath driver * @context: unused by the InfiniPath driver
* @udata: unused by the InfiniPath driver * @udata: unused by the InfiniPath driver
* *
@ -197,16 +197,21 @@ static void send_complete(unsigned long data)
* *
* Called by ib_create_cq() in the generic verbs code. * Called by ib_create_cq() in the generic verbs code.
*/ */
struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector, struct ib_cq *ipath_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
struct ipath_cq *cq; struct ipath_cq *cq;
struct ipath_cq_wc *wc; struct ipath_cq_wc *wc;
struct ib_cq *ret; struct ib_cq *ret;
u32 sz; u32 sz;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (entries < 1 || entries > ib_ipath_max_cqes) { if (entries < 1 || entries > ib_ipath_max_cqes) {
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
goto done; goto done;

View file

@ -1257,7 +1257,7 @@ static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp,
} }
static int process_subn(struct ib_device *ibdev, int mad_flags, static int process_subn(struct ib_device *ibdev, int mad_flags,
u8 port_num, struct ib_mad *in_mad, u8 port_num, const struct ib_mad *in_mad,
struct ib_mad *out_mad) struct ib_mad *out_mad)
{ {
struct ib_smp *smp = (struct ib_smp *)out_mad; struct ib_smp *smp = (struct ib_smp *)out_mad;
@ -1389,7 +1389,7 @@ bail:
} }
static int process_perf(struct ib_device *ibdev, u8 port_num, static int process_perf(struct ib_device *ibdev, u8 port_num,
struct ib_mad *in_mad, const struct ib_mad *in_mad,
struct ib_mad *out_mad) struct ib_mad *out_mad)
{ {
struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
@ -1490,10 +1490,17 @@ bail:
* This is called by the ib_mad module. * This is called by the ib_mad module.
*/ */
int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
int ret; int ret;
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
switch (in_mad->mad_hdr.mgmt_class) { switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:

View file

@ -1495,11 +1495,14 @@ bail:
return 0; return 0;
} }
static int ipath_query_device(struct ib_device *ibdev, static int ipath_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_ibdev *dev = to_idev(ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
memset(props, 0, sizeof(*props)); memset(props, 0, sizeof(*props));
props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
@ -1980,6 +1983,24 @@ static int disable_timer(struct ipath_devdata *dd)
return 0; return 0;
} }
static int ipath_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = ipath_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
/** /**
* ipath_register_ib_device - register our device with the infiniband core * ipath_register_ib_device - register our device with the infiniband core
* @dd: the device data structure * @dd: the device data structure
@ -2179,6 +2200,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
dev->process_mad = ipath_process_mad; dev->process_mad = ipath_process_mad;
dev->mmap = ipath_mmap; dev->mmap = ipath_mmap;
dev->dma_ops = &ipath_dma_mapping_ops; dev->dma_ops = &ipath_dma_mapping_ops;
dev->get_port_immutable = ipath_port_immutable;
snprintf(dev->node_desc, sizeof(dev->node_desc), snprintf(dev->node_desc, sizeof(dev->node_desc),
IPATH_IDSTR " %s", init_utsname()->nodename); IPATH_IDSTR " %s", init_utsname()->nodename);

View file

@ -701,9 +701,11 @@ static inline void ipath_schedule_send(struct ipath_qp *qp)
int ipath_process_mad(struct ib_device *ibdev, int ipath_process_mad(struct ib_device *ibdev,
int mad_flags, int mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad); const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
/* /*
* Compare the lower 24 bits of the two values. * Compare the lower 24 bits of the two values.
@ -807,7 +809,8 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector, struct ib_cq *ipath_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);

View file

@ -166,10 +166,14 @@ err_buf:
return err; return err;
} }
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, #define CQ_CREATE_FLAGS_SUPPORTED IB_CQ_FLAGS_TIMESTAMP_COMPLETION
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
int vector = attr->comp_vector;
struct mlx4_ib_dev *dev = to_mdev(ibdev); struct mlx4_ib_dev *dev = to_mdev(ibdev);
struct mlx4_ib_cq *cq; struct mlx4_ib_cq *cq;
struct mlx4_uar *uar; struct mlx4_uar *uar;
@ -178,6 +182,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
if (entries < 1 || entries > dev->dev->caps.max_cqes) if (entries < 1 || entries > dev->dev->caps.max_cqes)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (attr->flags & ~CQ_CREATE_FLAGS_SUPPORTED)
return ERR_PTR(-EINVAL);
cq = kmalloc(sizeof *cq, GFP_KERNEL); cq = kmalloc(sizeof *cq, GFP_KERNEL);
if (!cq) if (!cq)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -188,6 +195,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
spin_lock_init(&cq->lock); spin_lock_init(&cq->lock);
cq->resize_buf = NULL; cq->resize_buf = NULL;
cq->resize_umem = NULL; cq->resize_umem = NULL;
cq->create_flags = attr->flags;
INIT_LIST_HEAD(&cq->send_qp_list); INIT_LIST_HEAD(&cq->send_qp_list);
INIT_LIST_HEAD(&cq->recv_qp_list); INIT_LIST_HEAD(&cq->recv_qp_list);
@ -231,7 +239,8 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
vector = dev->eq_table[vector % ibdev->num_comp_vectors]; vector = dev->eq_table[vector % ibdev->num_comp_vectors];
err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
cq->db.dma, &cq->mcq, vector, 0, 0); cq->db.dma, &cq->mcq, vector, 0,
!!(cq->create_flags & IB_CQ_FLAGS_TIMESTAMP_COMPLETION));
if (err) if (err)
goto err_dbmap; goto err_dbmap;

View file

@ -111,8 +111,9 @@ __be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx)
} }
int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh, int port, const struct ib_wc *in_wc,
void *in_mad, void *response_mad) const struct ib_grh *in_grh,
const void *in_mad, void *response_mad)
{ {
struct mlx4_cmd_mailbox *inmailbox, *outmailbox; struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
void *inbox; void *inbox;
@ -220,7 +221,7 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl)
* Snoop SM MADs for port info, GUID info, and P_Key table sets, so we can * Snoop SM MADs for port info, GUID info, and P_Key table sets, so we can
* synthesize LID change, Client-Rereg, GID change, and P_Key change events. * synthesize LID change, Client-Rereg, GID change, and P_Key change events.
*/ */
static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, static void smp_snoop(struct ib_device *ibdev, u8 port_num, const struct ib_mad *mad,
u16 prev_lid) u16 prev_lid)
{ {
struct ib_port_info *pinfo; struct ib_port_info *pinfo;
@ -356,7 +357,7 @@ static void node_desc_override(struct ib_device *dev,
} }
} }
static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *mad) static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, const struct ib_mad *mad)
{ {
int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
struct ib_mad_send_buf *send_buf; struct ib_mad_send_buf *send_buf;
@ -366,7 +367,8 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma
if (agent) { if (agent) {
send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
IB_MGMT_MAD_DATA, GFP_ATOMIC); IB_MGMT_MAD_DATA, GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(send_buf)) if (IS_ERR(send_buf))
return; return;
/* /*
@ -722,8 +724,8 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
} }
static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad *in_mad, struct ib_mad *out_mad)
{ {
u16 slid, prev_lid = 0; u16 slid, prev_lid = 0;
int err; int err;
@ -825,8 +827,8 @@ static void edit_counter(struct mlx4_counter *cnt,
} }
static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad *in_mad, struct ib_mad *out_mad)
{ {
struct mlx4_cmd_mailbox *mailbox; struct mlx4_cmd_mailbox *mailbox;
struct mlx4_ib_dev *dev = to_mdev(ibdev); struct mlx4_ib_dev *dev = to_mdev(ibdev);
@ -866,9 +868,17 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
} }
int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
switch (rdma_port_get_link_layer(ibdev, port_num)) { switch (rdma_port_get_link_layer(ibdev, port_num)) {
case IB_LINK_LAYER_INFINIBAND: case IB_LINK_LAYER_INFINIBAND:
return ib_process_mad(ibdev, mad_flags, port_num, in_wc, return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
@ -1773,6 +1783,7 @@ static int create_pv_resources(struct ib_device *ibdev, int slave, int port,
int create_tun, struct mlx4_ib_demux_pv_ctx *ctx) int create_tun, struct mlx4_ib_demux_pv_ctx *ctx)
{ {
int ret, cq_size; int ret, cq_size;
struct ib_cq_init_attr cq_attr = {};
if (ctx->state != DEMUX_PV_STATE_DOWN) if (ctx->state != DEMUX_PV_STATE_DOWN)
return -EEXIST; return -EEXIST;
@ -1801,8 +1812,9 @@ static int create_pv_resources(struct ib_device *ibdev, int slave, int port,
if (ctx->has_smi) if (ctx->has_smi)
cq_size *= 2; cq_size *= 2;
cq_attr.cqe = cq_size;
ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler, ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler,
NULL, ctx, cq_size, 0); NULL, ctx, &cq_attr);
if (IS_ERR(ctx->cq)) { if (IS_ERR(ctx->cq)) {
ret = PTR_ERR(ctx->cq); ret = PTR_ERR(ctx->cq);
pr_err("Couldn't create tunnel CQ (%d)\n", ret); pr_err("Couldn't create tunnel CQ (%d)\n", ret);

View file

@ -132,14 +132,35 @@ static int num_ib_ports(struct mlx4_dev *dev)
} }
static int mlx4_ib_query_device(struct ib_device *ibdev, static int mlx4_ib_query_device(struct ib_device *ibdev,
struct ib_device_attr *props) struct ib_device_attr *props,
struct ib_udata *uhw)
{ {
struct mlx4_ib_dev *dev = to_mdev(ibdev); struct mlx4_ib_dev *dev = to_mdev(ibdev);
struct ib_smp *in_mad = NULL; struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL; struct ib_smp *out_mad = NULL;
int err = -ENOMEM; int err = -ENOMEM;
int have_ib_ports; int have_ib_ports;
struct mlx4_uverbs_ex_query_device cmd;
struct mlx4_uverbs_ex_query_device_resp resp = {.comp_mask = 0};
struct mlx4_clock_params clock_params;
if (uhw->inlen) {
if (uhw->inlen < sizeof(cmd))
return -EINVAL;
err = ib_copy_from_udata(&cmd, uhw, sizeof(cmd));
if (err)
return err;
if (cmd.comp_mask)
return -EINVAL;
if (cmd.reserved)
return -EINVAL;
}
resp.response_length = offsetof(typeof(resp), response_length) +
sizeof(resp.response_length);
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad) if (!in_mad || !out_mad)
@ -229,7 +250,24 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
props->max_mcast_grp; props->max_mcast_grp;
props->max_map_per_fmr = dev->dev->caps.max_fmr_maps; props->max_map_per_fmr = dev->dev->caps.max_fmr_maps;
props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL;
props->timestamp_mask = 0xFFFFFFFFFFFFULL;
err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
if (err)
goto out;
if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE;
resp.response_length += sizeof(resp.hca_core_clock_offset);
resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP;
}
if (uhw->outlen) {
err = ib_copy_to_udata(uhw, &resp, resp.response_length);
if (err)
goto out;
}
out: out:
kfree(in_mad); kfree(in_mad);
kfree(out_mad); kfree(out_mad);
@ -712,8 +750,24 @@ static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
dev->dev->caps.num_uars, dev->dev->caps.num_uars,
PAGE_SIZE, vma->vm_page_prot)) PAGE_SIZE, vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
} else } else if (vma->vm_pgoff == 3) {
struct mlx4_clock_params params;
int ret = mlx4_get_internal_clock_params(dev->dev, &params);
if (ret)
return ret;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (io_remap_pfn_range(vma, vma->vm_start,
(pci_resource_start(dev->dev->persist->pdev,
params.bar) +
params.offset)
>> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot))
return -EAGAIN;
} else {
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
@ -758,6 +812,7 @@ static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
struct ib_udata *udata) struct ib_udata *udata)
{ {
struct mlx4_ib_xrcd *xrcd; struct mlx4_ib_xrcd *xrcd;
struct ib_cq_init_attr cq_attr = {};
int err; int err;
if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
@ -777,7 +832,8 @@ static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
goto err2; goto err2;
} }
xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0); cq_attr.cqe = 1;
xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, &cq_attr);
if (IS_ERR(xrcd->cq)) { if (IS_ERR(xrcd->cq)) {
err = PTR_ERR(xrcd->cq); err = PTR_ERR(xrcd->cq);
goto err3; goto err3;
@ -1185,7 +1241,6 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
&mflow->reg_id[i].id); &mflow->reg_id[i].id);
if (err) if (err)
goto err_create_flow; goto err_create_flow;
i++;
if (is_bonded) { if (is_bonded) {
/* Application always sees one port so the mirror rule /* Application always sees one port so the mirror rule
* must be on port #2 * must be on port #2
@ -1200,6 +1255,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
j++; j++;
} }
i++;
} }
if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) { if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
@ -1207,7 +1263,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
&mflow->reg_id[i].id); &mflow->reg_id[i].id);
if (err) if (err)
goto err_create_flow; goto err_create_flow;
i++;
if (is_bonded) { if (is_bonded) {
flow_attr->port = 2; flow_attr->port = 2;
err = mlx4_ib_tunnel_steer_add(qp, flow_attr, err = mlx4_ib_tunnel_steer_add(qp, flow_attr,
@ -1218,6 +1274,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
j++; j++;
} }
/* function to create mirror rule */ /* function to create mirror rule */
i++;
} }
return &mflow->ibflow; return &mflow->ibflow;
@ -2114,6 +2171,29 @@ static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
kfree(ibdev->eq_table); kfree(ibdev->eq_table);
} }
static int mlx4_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = mlx4_ib_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
if (mlx4_ib_port_link_layer(ibdev, port_num) == IB_LINK_LAYER_INFINIBAND)
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
else
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
static void *mlx4_ib_add(struct mlx4_dev *dev) static void *mlx4_ib_add(struct mlx4_dev *dev)
{ {
struct mlx4_ib_dev *ibdev; struct mlx4_ib_dev *ibdev;
@ -2241,6 +2321,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach;
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad; ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
ibdev->ib_dev.get_port_immutable = mlx4_port_immutable;
if (!mlx4_is_slave(ibdev->dev)) { if (!mlx4_is_slave(ibdev->dev)) {
ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc;
@ -2278,6 +2359,10 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW); (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW);
} }
ibdev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) |
(1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ);
mlx4_ib_alloc_eqs(dev, ibdev); mlx4_ib_alloc_eqs(dev, ibdev);
spin_lock_init(&iboe->lock); spin_lock_init(&iboe->lock);

View file

@ -110,6 +110,7 @@ struct mlx4_ib_cq {
struct mutex resize_mutex; struct mutex resize_mutex;
struct ib_umem *umem; struct ib_umem *umem;
struct ib_umem *resize_umem; struct ib_umem *resize_umem;
int create_flags;
/* List of qps that it serves.*/ /* List of qps that it serves.*/
struct list_head send_qp_list; struct list_head send_qp_list;
struct list_head recv_qp_list; struct list_head recv_qp_list;
@ -555,6 +556,21 @@ struct mlx4_ib_qp_tunnel_init_attr {
u8 port; u8 port;
}; };
struct mlx4_uverbs_ex_query_device {
__u32 comp_mask;
__u32 reserved;
};
enum query_device_resp_mask {
QUERY_DEVICE_RESP_MASK_TIMESTAMP = 1UL << 0,
};
struct mlx4_uverbs_ex_query_device_resp {
__u32 comp_mask;
__u32 response_length;
__u64 hca_core_clock_offset;
};
static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
{ {
return container_of(ibdev, struct mlx4_ib_dev, ib_dev); return container_of(ibdev, struct mlx4_ib_dev, ib_dev);
@ -668,7 +684,8 @@ void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata); int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
int mlx4_ib_destroy_cq(struct ib_cq *cq); int mlx4_ib_destroy_cq(struct ib_cq *cq);
@ -706,11 +723,13 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
struct ib_recv_wr **bad_wr); struct ib_recv_wr **bad_wr);
int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh, int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
void *in_mad, void *response_mad); const void *in_mad, void *response_mad);
int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad); const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
int mlx4_ib_mad_init(struct mlx4_ib_dev *dev); int mlx4_ib_mad_init(struct mlx4_ib_dev *dev);
void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev); void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev);

View file

@ -736,10 +736,13 @@ static void destroy_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq)
mlx5_db_free(dev->mdev, &cq->db); mlx5_db_free(dev->mdev, &cq->db);
} }
struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
int vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
int vector = attr->comp_vector;
struct mlx5_create_cq_mbox_in *cqb = NULL; struct mlx5_create_cq_mbox_in *cqb = NULL;
struct mlx5_ib_dev *dev = to_mdev(ibdev); struct mlx5_ib_dev *dev = to_mdev(ibdev);
struct mlx5_ib_cq *cq; struct mlx5_ib_cq *cq;
@ -750,6 +753,9 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
int eqn; int eqn;
int err; int err;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (entries < 0) if (entries < 0)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);

View file

@ -41,8 +41,8 @@ enum {
}; };
int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh, u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
void *in_mad, void *response_mad) const void *in_mad, void *response_mad)
{ {
u8 op_modifier = 0; u8 op_modifier = 0;
@ -58,11 +58,18 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
} }
int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
u16 slid; u16 slid;
int err; int err;
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);

View file

@ -63,7 +63,8 @@ static char mlx5_version[] =
DRIVER_VERSION " (" DRIVER_RELDATE ")\n"; DRIVER_VERSION " (" DRIVER_RELDATE ")\n";
static int mlx5_ib_query_device(struct ib_device *ibdev, static int mlx5_ib_query_device(struct ib_device *ibdev,
struct ib_device_attr *props) struct ib_device_attr *props,
struct ib_udata *uhw)
{ {
struct mlx5_ib_dev *dev = to_mdev(ibdev); struct mlx5_ib_dev *dev = to_mdev(ibdev);
struct ib_smp *in_mad = NULL; struct ib_smp *in_mad = NULL;
@ -74,6 +75,9 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
int max_sq_sg; int max_sq_sg;
u64 flags; u64 flags;
if (uhw->inlen || uhw->outlen)
return -EINVAL;
gen = &dev->mdev->caps.gen; gen = &dev->mdev->caps.gen;
in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
@ -910,6 +914,7 @@ static int get_port_caps(struct mlx5_ib_dev *dev)
struct mlx5_general_caps *gen; struct mlx5_general_caps *gen;
int err = -ENOMEM; int err = -ENOMEM;
int port; int port;
struct ib_udata uhw = {.inlen = 0, .outlen = 0};
gen = &dev->mdev->caps.gen; gen = &dev->mdev->caps.gen;
pprops = kmalloc(sizeof(*pprops), GFP_KERNEL); pprops = kmalloc(sizeof(*pprops), GFP_KERNEL);
@ -920,7 +925,7 @@ static int get_port_caps(struct mlx5_ib_dev *dev)
if (!dprops) if (!dprops)
goto out; goto out;
err = mlx5_ib_query_device(&dev->ib_dev, dprops); err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw);
if (err) { if (err) {
mlx5_ib_warn(dev, "query_device failed %d\n", err); mlx5_ib_warn(dev, "query_device failed %d\n", err);
goto out; goto out;
@ -971,6 +976,7 @@ static int create_umr_res(struct mlx5_ib_dev *dev)
struct ib_cq *cq; struct ib_cq *cq;
struct ib_qp *qp; struct ib_qp *qp;
struct ib_mr *mr; struct ib_mr *mr;
struct ib_cq_init_attr cq_attr = {};
int ret; int ret;
attr = kzalloc(sizeof(*attr), GFP_KERNEL); attr = kzalloc(sizeof(*attr), GFP_KERNEL);
@ -994,8 +1000,9 @@ static int create_umr_res(struct mlx5_ib_dev *dev)
goto error_1; goto error_1;
} }
cq = ib_create_cq(&dev->ib_dev, mlx5_umr_cq_handler, NULL, NULL, 128, cq_attr.cqe = 128;
0); cq = ib_create_cq(&dev->ib_dev, mlx5_umr_cq_handler, NULL, NULL,
&cq_attr);
if (IS_ERR(cq)) { if (IS_ERR(cq)) {
mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
ret = PTR_ERR(cq); ret = PTR_ERR(cq);
@ -1087,6 +1094,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
{ {
struct ib_srq_init_attr attr; struct ib_srq_init_attr attr;
struct mlx5_ib_dev *dev; struct mlx5_ib_dev *dev;
struct ib_cq_init_attr cq_attr = {.cqe = 1};
int ret = 0; int ret = 0;
dev = container_of(devr, struct mlx5_ib_dev, devr); dev = container_of(devr, struct mlx5_ib_dev, devr);
@ -1100,7 +1108,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
devr->p0->uobject = NULL; devr->p0->uobject = NULL;
atomic_set(&devr->p0->usecnt, 0); atomic_set(&devr->p0->usecnt, 0);
devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, 1, 0, NULL, NULL); devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL, NULL);
if (IS_ERR(devr->c0)) { if (IS_ERR(devr->c0)) {
ret = PTR_ERR(devr->c0); ret = PTR_ERR(devr->c0);
goto error1; goto error1;
@ -1182,6 +1190,24 @@ static void destroy_dev_resources(struct mlx5_ib_resources *devr)
mlx5_ib_dealloc_pd(devr->p0); mlx5_ib_dealloc_pd(devr->p0);
} }
static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = mlx5_ib_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
static void *mlx5_ib_add(struct mlx5_core_dev *mdev) static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
{ {
struct mlx5_ib_dev *dev; struct mlx5_ib_dev *dev;
@ -1285,6 +1311,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list;
dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list;
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable;
mlx5_ib_internal_query_odp_caps(dev); mlx5_ib_internal_query_odp_caps(dev);

View file

@ -525,8 +525,8 @@ void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq)
void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index); void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh, u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
void *in_mad, void *response_mad); const void *in_mad, void *response_mad);
struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr, struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr,
struct mlx5_ib_ah *ah); struct mlx5_ib_ah *ah);
struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
@ -556,8 +556,9 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n); void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n);
int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index, int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index,
void *buffer, u32 length); void *buffer, u32 length);
struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
int vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
int mlx5_ib_destroy_cq(struct ib_cq *cq); int mlx5_ib_destroy_cq(struct ib_cq *cq);
int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
@ -586,8 +587,10 @@ int mlx5_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
int mlx5_ib_unmap_fmr(struct list_head *fmr_list); int mlx5_ib_unmap_fmr(struct list_head *fmr_list);
int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr); int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr);
int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad); const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);

View file

@ -1858,8 +1858,8 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn)
} }
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh, int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
void *in_mad, void *response_mad) const void *in_mad, void *response_mad)
{ {
struct mthca_mailbox *inmailbox, *outmailbox; struct mthca_mailbox *inmailbox, *outmailbox;
void *inbox; void *inbox;

View file

@ -312,8 +312,8 @@ int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
struct mthca_mailbox *mailbox); struct mthca_mailbox *mailbox);
int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn); int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn);
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh, int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
void *in_mad, void *response_mad); const void *in_mad, void *response_mad);
int mthca_READ_MGM(struct mthca_dev *dev, int index, int mthca_READ_MGM(struct mthca_dev *dev, int index,
struct mthca_mailbox *mailbox); struct mthca_mailbox *mailbox);
int mthca_WRITE_MGM(struct mthca_dev *dev, int index, int mthca_WRITE_MGM(struct mthca_dev *dev, int index,

View file

@ -576,10 +576,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_process_mad(struct ib_device *ibdev, int mthca_process_mad(struct ib_device *ibdev,
int mad_flags, int mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad *out_mad); struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
int mthca_create_agents(struct mthca_dev *dev); int mthca_create_agents(struct mthca_dev *dev);
void mthca_free_agents(struct mthca_dev *dev); void mthca_free_agents(struct mthca_dev *dev);

View file

@ -104,7 +104,7 @@ static void update_sm_ah(struct mthca_dev *dev,
*/ */
static void smp_snoop(struct ib_device *ibdev, static void smp_snoop(struct ib_device *ibdev,
u8 port_num, u8 port_num,
struct ib_mad *mad, const struct ib_mad *mad,
u16 prev_lid) u16 prev_lid)
{ {
struct ib_event event; struct ib_event event;
@ -160,7 +160,7 @@ static void node_desc_override(struct ib_device *dev,
static void forward_trap(struct mthca_dev *dev, static void forward_trap(struct mthca_dev *dev,
u8 port_num, u8 port_num,
struct ib_mad *mad) const struct ib_mad *mad)
{ {
int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
struct ib_mad_send_buf *send_buf; struct ib_mad_send_buf *send_buf;
@ -170,7 +170,8 @@ static void forward_trap(struct mthca_dev *dev,
if (agent) { if (agent) {
send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
IB_MGMT_MAD_DATA, GFP_ATOMIC); IB_MGMT_MAD_DATA, GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(send_buf)) if (IS_ERR(send_buf))
return; return;
/* /*
@ -195,15 +196,21 @@ static void forward_trap(struct mthca_dev *dev,
int mthca_process_mad(struct ib_device *ibdev, int mthca_process_mad(struct ib_device *ibdev,
int mad_flags, int mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad *out_mad) struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
int err; int err;
u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
u16 prev_lid = 0; u16 prev_lid = 0;
struct ib_port_attr pattr; struct ib_port_attr pattr;
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
/* Forward locally generated traps to the SM */ /* Forward locally generated traps to the SM */
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&

View file

@ -77,7 +77,6 @@ s64 mthca_make_profile(struct mthca_dev *dev,
u64 mem_base, mem_avail; u64 mem_base, mem_avail;
s64 total_size = 0; s64 total_size = 0;
struct mthca_resource *profile; struct mthca_resource *profile;
struct mthca_resource tmp;
int i, j; int i, j;
profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL); profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
@ -136,11 +135,8 @@ s64 mthca_make_profile(struct mthca_dev *dev,
*/ */
for (i = MTHCA_RES_NUM; i > 0; --i) for (i = MTHCA_RES_NUM; i > 0; --i)
for (j = 1; j < i; ++j) { for (j = 1; j < i; ++j) {
if (profile[j].size > profile[j - 1].size) { if (profile[j].size > profile[j - 1].size)
tmp = profile[j]; swap(profile[j], profile[j - 1]);
profile[j] = profile[j - 1];
profile[j - 1] = tmp;
}
} }
for (i = 0; i < MTHCA_RES_NUM; ++i) { for (i = 0; i < MTHCA_RES_NUM; ++i) {

View file

@ -57,14 +57,17 @@ static void init_query_mad(struct ib_smp *mad)
mad->method = IB_MGMT_METHOD_GET; mad->method = IB_MGMT_METHOD_GET;
} }
static int mthca_query_device(struct ib_device *ibdev, static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct ib_smp *in_mad = NULL; struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL; struct ib_smp *out_mad = NULL;
int err = -ENOMEM; int err = -ENOMEM;
struct mthca_dev *mdev = to_mdev(ibdev); struct mthca_dev *mdev = to_mdev(ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad) if (!in_mad || !out_mad)
@ -641,16 +644,20 @@ static int mthca_destroy_qp(struct ib_qp *qp)
return 0; return 0;
} }
static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, static struct ib_cq *mthca_create_cq(struct ib_device *ibdev,
int comp_vector, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct mthca_create_cq ucmd; struct mthca_create_cq ucmd;
struct mthca_cq *cq; struct mthca_cq *cq;
int nent; int nent;
int err; int err;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -1244,6 +1251,24 @@ out:
return err; return err;
} }
static int mthca_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = mthca_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
int mthca_register_device(struct mthca_dev *dev) int mthca_register_device(struct mthca_dev *dev)
{ {
int ret; int ret;
@ -1323,6 +1348,7 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr; dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr;
dev->ib_dev.reg_user_mr = mthca_reg_user_mr; dev->ib_dev.reg_user_mr = mthca_reg_user_mr;
dev->ib_dev.dereg_mr = mthca_dereg_mr; dev->ib_dev.dereg_mr = mthca_dereg_mr;
dev->ib_dev.get_port_immutable = mthca_port_immutable;
if (dev->mthca_flags & MTHCA_FLAG_FMR) { if (dev->mthca_flags & MTHCA_FLAG_FMR) {
dev->ib_dev.alloc_fmr = mthca_alloc_fmr; dev->ib_dev.alloc_fmr = mthca_alloc_fmr;

View file

@ -1616,6 +1616,8 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
&cm_node->loc_addr, cm_node->loc_port, &cm_node->loc_addr, cm_node->loc_port,
&cm_node->rem_addr, cm_node->rem_port); &cm_node->rem_addr, cm_node->rem_port);
cm_node->listener = listener; cm_node->listener = listener;
if (listener)
cm_node->tos = listener->tos;
cm_node->netdev = nesvnic->netdev; cm_node->netdev = nesvnic->netdev;
cm_node->cm_id = cm_info->cm_id; cm_node->cm_id = cm_info->cm_id;
memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
@ -2938,6 +2940,9 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT); nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT);
nesqp->nesqp_context->misc2 |= cpu_to_le32(
cm_node->tos << NES_QPCONTEXT_MISC2_TOS_SHIFT);
nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
@ -3612,6 +3617,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cm_node->ord_size = 1; cm_node->ord_size = 1;
cm_node->apbvt_set = apbvt_set; cm_node->apbvt_set = apbvt_set;
cm_node->tos = cm_id->tos;
nesqp->cm_node = cm_node; nesqp->cm_node = cm_node;
cm_node->nesqp = nesqp; cm_node->nesqp = nesqp;
nes_add_ref(&nesqp->ibqp); nes_add_ref(&nesqp->ibqp);
@ -3666,6 +3672,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
} }
cm_id->provider_data = cm_node; cm_id->provider_data = cm_node;
cm_node->tos = cm_id->tos;
if (!cm_node->reused_node) { if (!cm_node->reused_node) {
if (nes_create_mapinfo(&cm_info)) if (nes_create_mapinfo(&cm_info))

View file

@ -303,6 +303,7 @@ struct nes_cm_listener {
int backlog; int backlog;
enum nes_cm_listener_state listener_state; enum nes_cm_listener_state listener_state;
u32 reused_node; u32 reused_node;
u8 tos;
}; };
/* per connection node and node state information */ /* per connection node and node state information */
@ -352,6 +353,7 @@ struct nes_cm_node {
struct list_head reset_entry; struct list_head reset_entry;
struct nes_qp *nesqp; struct nes_qp *nesqp;
atomic_t passive_state; atomic_t passive_state;
u8 tos;
}; };
/* structure for client or CM to fill when making CM api calls. */ /* structure for client or CM to fill when making CM api calls. */

View file

@ -512,12 +512,16 @@ static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl)
/** /**
* nes_query_device * nes_query_device
*/ */
static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props) static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_udata *uhw)
{ {
struct nes_vnic *nesvnic = to_nesvnic(ibdev); struct nes_vnic *nesvnic = to_nesvnic(ibdev);
struct nes_device *nesdev = nesvnic->nesdev; struct nes_device *nesdev = nesvnic->nesdev;
struct nes_ib_device *nesibdev = nesvnic->nesibdev; struct nes_ib_device *nesibdev = nesvnic->nesibdev;
if (uhw->inlen || uhw->outlen)
return -EINVAL;
memset(props, 0, sizeof(*props)); memset(props, 0, sizeof(*props));
memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6); memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6);
@ -606,7 +610,6 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
return 0; return 0;
} }
/** /**
* nes_query_pkey * nes_query_pkey
*/ */
@ -1527,10 +1530,12 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
/** /**
* nes_create_cq * nes_create_cq
*/ */
static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, static struct ib_cq *nes_create_cq(struct ib_device *ibdev,
int comp_vector, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_udata *udata) struct ib_ucontext *context,
struct ib_udata *udata)
{ {
int entries = attr->cqe;
u64 u64temp; u64 u64temp;
struct nes_vnic *nesvnic = to_nesvnic(ibdev); struct nes_vnic *nesvnic = to_nesvnic(ibdev);
struct nes_device *nesdev = nesvnic->nesdev; struct nes_device *nesdev = nesvnic->nesdev;
@ -1550,6 +1555,9 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
unsigned long flags; unsigned long flags;
int ret; int ret;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (entries > nesadapter->max_cqe) if (entries > nesadapter->max_cqe)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -3222,8 +3230,10 @@ static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
* nes_process_mad * nes_process_mad
*/ */
static int nes_process_mad(struct ib_device *ibdev, int mad_flags, static int nes_process_mad(struct ib_device *ibdev, int mad_flags,
u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh, u8 port_num, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
nes_debug(NES_DBG_INIT, "\n"); nes_debug(NES_DBG_INIT, "\n");
return -ENOSYS; return -ENOSYS;
@ -3828,6 +3838,22 @@ static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_
return 0; return 0;
} }
static int nes_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = nes_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
return 0;
}
/** /**
* nes_init_ofa_device * nes_init_ofa_device
@ -3928,6 +3954,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
nesibdev->ibdev.iwcm->reject = nes_reject; nesibdev->ibdev.iwcm->reject = nes_reject;
nesibdev->ibdev.iwcm->create_listen = nes_create_listen; nesibdev->ibdev.iwcm->create_listen = nes_create_listen;
nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen; nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen;
nesibdev->ibdev.get_port_immutable = nes_port_immutable;
return nesibdev; return nesibdev;
} }

View file

@ -204,12 +204,19 @@ int ocrdma_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
int ocrdma_process_mad(struct ib_device *ibdev, int ocrdma_process_mad(struct ib_device *ibdev,
int process_mad_flags, int process_mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
int status; int status;
struct ocrdma_dev *dev; struct ocrdma_dev *dev;
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
switch (in_mad->mad_hdr.mgmt_class) { switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_PERF_MGMT: case IB_MGMT_CLASS_PERF_MGMT:

View file

@ -42,7 +42,9 @@ int ocrdma_modify_ah(struct ib_ah *, struct ib_ah_attr *);
int ocrdma_process_mad(struct ib_device *, int ocrdma_process_mad(struct ib_device *,
int process_mad_flags, int process_mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad); const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
#endif /* __OCRDMA_AH_H__ */ #endif /* __OCRDMA_AH_H__ */

View file

@ -30,6 +30,7 @@
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h> #include <rdma/ib_user_verbs.h>
#include <rdma/ib_addr.h> #include <rdma/ib_addr.h>
#include <rdma/ib_mad.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/addrconf.h> #include <net/addrconf.h>
@ -202,6 +203,24 @@ static enum rdma_link_layer ocrdma_link_layer(struct ib_device *device,
return IB_LINK_LAYER_ETHERNET; return IB_LINK_LAYER_ETHERNET;
} }
static int ocrdma_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = ocrdma_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
static int ocrdma_register_device(struct ocrdma_dev *dev) static int ocrdma_register_device(struct ocrdma_dev *dev)
{ {
strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX); strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX);
@ -286,6 +305,7 @@ static int ocrdma_register_device(struct ocrdma_dev *dev)
dev->ibdev.dma_device = &dev->nic_info.pdev->dev; dev->ibdev.dma_device = &dev->nic_info.pdev->dev;
dev->ibdev.process_mad = ocrdma_process_mad; dev->ibdev.process_mad = ocrdma_process_mad;
dev->ibdev.get_port_immutable = ocrdma_port_immutable;
if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) { if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) {
dev->ibdev.uverbs_cmd_mask |= dev->ibdev.uverbs_cmd_mask |=

View file

@ -61,10 +61,14 @@ int ocrdma_query_gid(struct ib_device *ibdev, u8 port,
return 0; return 0;
} }
int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr) int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
struct ib_udata *uhw)
{ {
struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
memset(attr, 0, sizeof *attr); memset(attr, 0, sizeof *attr);
memcpy(&attr->fw_ver, &dev->attr.fw_ver[0], memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver))); min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver)));
@ -375,7 +379,12 @@ static struct ocrdma_pd *_ocrdma_alloc_pd(struct ocrdma_dev *dev,
if (dev->pd_mgr->pd_prealloc_valid) { if (dev->pd_mgr->pd_prealloc_valid) {
status = ocrdma_get_pd_num(dev, pd); status = ocrdma_get_pd_num(dev, pd);
return (status == 0) ? pd : ERR_PTR(status); if (status == 0) {
return pd;
} else {
kfree(pd);
return ERR_PTR(status);
}
} }
retry: retry:
@ -679,7 +688,6 @@ err:
ocrdma_release_ucontext_pd(uctx); ocrdma_release_ucontext_pd(uctx);
} else { } else {
status = _ocrdma_dealloc_pd(dev, pd); status = _ocrdma_dealloc_pd(dev, pd);
kfree(pd);
} }
exit: exit:
return ERR_PTR(status); return ERR_PTR(status);
@ -1000,10 +1008,12 @@ err:
return status; return status;
} }
struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev,
const struct ib_cq_init_attr *attr,
struct ib_ucontext *ib_ctx, struct ib_ucontext *ib_ctx,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct ocrdma_cq *cq; struct ocrdma_cq *cq;
struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
struct ocrdma_ucontext *uctx = NULL; struct ocrdma_ucontext *uctx = NULL;
@ -1011,6 +1021,9 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector,
int status; int status;
struct ocrdma_create_cq_ureq ureq; struct ocrdma_create_cq_ureq ureq;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (udata) { if (udata) {
if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);

View file

@ -36,11 +36,15 @@ int ocrdma_post_recv(struct ib_qp *, struct ib_recv_wr *,
int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc); int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc);
int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags); int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags);
int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props); int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props,
struct ib_udata *uhw);
int ocrdma_query_port(struct ib_device *, u8 port, struct ib_port_attr *props); int ocrdma_query_port(struct ib_device *, u8 port, struct ib_port_attr *props);
int ocrdma_modify_port(struct ib_device *, u8 port, int mask, int ocrdma_modify_port(struct ib_device *, u8 port, int mask,
struct ib_port_modify *props); struct ib_port_modify *props);
enum rdma_protocol_type
ocrdma_query_protocol(struct ib_device *device, u8 port_num);
void ocrdma_get_guid(struct ocrdma_dev *, u8 *guid); void ocrdma_get_guid(struct ocrdma_dev *, u8 *guid);
int ocrdma_query_gid(struct ib_device *, u8 port, int ocrdma_query_gid(struct ib_device *, u8 port,
int index, union ib_gid *gid); int index, union ib_gid *gid);
@ -56,8 +60,10 @@ struct ib_pd *ocrdma_alloc_pd(struct ib_device *,
struct ib_ucontext *, struct ib_udata *); struct ib_ucontext *, struct ib_udata *);
int ocrdma_dealloc_pd(struct ib_pd *pd); int ocrdma_dealloc_pd(struct ib_pd *pd);
struct ib_cq *ocrdma_create_cq(struct ib_device *, int entries, int vector, struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev,
struct ib_ucontext *, struct ib_udata *); const struct ib_cq_init_attr *attr,
struct ib_ucontext *ib_ctx,
struct ib_udata *udata);
int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *); int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
int ocrdma_destroy_cq(struct ib_cq *); int ocrdma_destroy_cq(struct ib_cq *);

View file

@ -203,7 +203,7 @@ static void send_complete(struct kthread_work *work)
/** /**
* qib_create_cq - create a completion queue * qib_create_cq - create a completion queue
* @ibdev: the device this completion queue is attached to * @ibdev: the device this completion queue is attached to
* @entries: the minimum size of the completion queue * @attr: creation attributes
* @context: unused by the QLogic_IB driver * @context: unused by the QLogic_IB driver
* @udata: user data for libibverbs.so * @udata: user data for libibverbs.so
* *
@ -212,16 +212,21 @@ static void send_complete(struct kthread_work *work)
* *
* Called by ib_create_cq() in the generic verbs code. * Called by ib_create_cq() in the generic verbs code.
*/ */
struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *qib_create_cq(struct ib_device *ibdev,
int comp_vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
int entries = attr->cqe;
struct qib_ibdev *dev = to_idev(ibdev); struct qib_ibdev *dev = to_idev(ibdev);
struct qib_cq *cq; struct qib_cq *cq;
struct qib_cq_wc *wc; struct qib_cq_wc *wc;
struct ib_cq *ret; struct ib_cq *ret;
u32 sz; u32 sz;
if (attr->flags)
return ERR_PTR(-EINVAL);
if (entries < 1 || entries > ib_qib_max_cqes) { if (entries < 1 || entries > ib_qib_max_cqes) {
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
goto done; goto done;

View file

@ -5502,7 +5502,8 @@ static void try_7322_ipg(struct qib_pportdata *ppd)
goto retry; goto retry;
send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR,
IB_MGMT_MAD_DATA, GFP_ATOMIC); IB_MGMT_MAD_DATA, GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(send_buf)) if (IS_ERR(send_buf))
goto retry; goto retry;

View file

@ -83,7 +83,8 @@ static void qib_send_trap(struct qib_ibport *ibp, void *data, unsigned len)
return; return;
send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR,
IB_MGMT_MAD_DATA, GFP_ATOMIC); IB_MGMT_MAD_DATA, GFP_ATOMIC,
IB_MGMT_BASE_VERSION);
if (IS_ERR(send_buf)) if (IS_ERR(send_buf))
return; return;
@ -1854,7 +1855,7 @@ static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,
} }
static int process_subn(struct ib_device *ibdev, int mad_flags, static int process_subn(struct ib_device *ibdev, int mad_flags,
u8 port, struct ib_mad *in_mad, u8 port, const struct ib_mad *in_mad,
struct ib_mad *out_mad) struct ib_mad *out_mad)
{ {
struct ib_smp *smp = (struct ib_smp *)out_mad; struct ib_smp *smp = (struct ib_smp *)out_mad;
@ -2006,7 +2007,7 @@ bail:
} }
static int process_perf(struct ib_device *ibdev, u8 port, static int process_perf(struct ib_device *ibdev, u8 port,
struct ib_mad *in_mad, const struct ib_mad *in_mad,
struct ib_mad *out_mad) struct ib_mad *out_mad)
{ {
struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
@ -2299,7 +2300,7 @@ static int check_cc_key(struct qib_ibport *ibp,
} }
static int process_cc(struct ib_device *ibdev, int mad_flags, static int process_cc(struct ib_device *ibdev, int mad_flags,
u8 port, struct ib_mad *in_mad, u8 port, const struct ib_mad *in_mad,
struct ib_mad *out_mad) struct ib_mad *out_mad)
{ {
struct ib_cc_mad *ccp = (struct ib_cc_mad *)out_mad; struct ib_cc_mad *ccp = (struct ib_cc_mad *)out_mad;
@ -2400,12 +2401,19 @@ bail:
* This is called by the ib_mad module. * This is called by the ib_mad module.
*/ */
int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port, int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad) const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{ {
int ret; int ret;
struct qib_ibport *ibp = to_iport(ibdev, port); struct qib_ibport *ibp = to_iport(ibdev, port);
struct qib_pportdata *ppd = ppd_from_ibp(ibp); struct qib_pportdata *ppd = ppd_from_ibp(ibp);
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
BUG_ON(in_mad_size != sizeof(*in_mad) ||
*out_mad_size != sizeof(*out_mad));
switch (in_mad->mad_hdr.mgmt_class) { switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:

View file

@ -1550,12 +1550,14 @@ full:
} }
} }
static int qib_query_device(struct ib_device *ibdev, static int qib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
struct ib_device_attr *props) struct ib_udata *uhw)
{ {
struct qib_devdata *dd = dd_from_ibdev(ibdev); struct qib_devdata *dd = dd_from_ibdev(ibdev);
struct qib_ibdev *dev = to_idev(ibdev); struct qib_ibdev *dev = to_idev(ibdev);
if (uhw->inlen || uhw->outlen)
return -EINVAL;
memset(props, 0, sizeof(*props)); memset(props, 0, sizeof(*props));
props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
@ -2040,6 +2042,24 @@ static void init_ibport(struct qib_pportdata *ppd)
RCU_INIT_POINTER(ibp->qp1, NULL); RCU_INIT_POINTER(ibp->qp1, NULL);
} }
static int qib_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = qib_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
/** /**
* qib_register_ib_device - register our device with the infiniband core * qib_register_ib_device - register our device with the infiniband core
* @dd: the device data structure * @dd: the device data structure
@ -2227,6 +2247,7 @@ int qib_register_ib_device(struct qib_devdata *dd)
ibdev->process_mad = qib_process_mad; ibdev->process_mad = qib_process_mad;
ibdev->mmap = qib_mmap; ibdev->mmap = qib_mmap;
ibdev->dma_ops = &qib_dma_mapping_ops; ibdev->dma_ops = &qib_dma_mapping_ops;
ibdev->get_port_immutable = qib_port_immutable;
snprintf(ibdev->node_desc, sizeof(ibdev->node_desc), snprintf(ibdev->node_desc, sizeof(ibdev->node_desc),
"Intel Infiniband HCA %s", init_utsname()->nodename); "Intel Infiniband HCA %s", init_utsname()->nodename);

View file

@ -872,8 +872,10 @@ void qib_cap_mask_chg(struct qib_ibport *ibp);
void qib_sys_guid_chg(struct qib_ibport *ibp); void qib_sys_guid_chg(struct qib_ibport *ibp);
void qib_node_desc_chg(struct qib_ibport *ibp); void qib_node_desc_chg(struct qib_ibport *ibp);
int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad); const struct ib_mad_hdr *in, size_t in_mad_size,
struct ib_mad_hdr *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
int qib_create_agents(struct qib_ibdev *dev); int qib_create_agents(struct qib_ibdev *dev);
void qib_free_agents(struct qib_ibdev *dev); void qib_free_agents(struct qib_ibdev *dev);
@ -1007,8 +1009,9 @@ void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int sig);
int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *qib_create_cq(struct ib_device *ibdev,
int comp_vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
int qib_destroy_cq(struct ib_cq *ibcq); int qib_destroy_cq(struct ib_cq *ibcq);

View file

@ -300,6 +300,22 @@ static struct notifier_block usnic_ib_inetaddr_notifier = {
}; };
/* End of inet section*/ /* End of inet section*/
static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
int err;
err = usnic_ib_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
return 0;
}
/* Start of PF discovery section */ /* Start of PF discovery section */
static void *usnic_ib_device_add(struct pci_dev *dev) static void *usnic_ib_device_add(struct pci_dev *dev)
{ {
@ -383,6 +399,7 @@ static void *usnic_ib_device_add(struct pci_dev *dev)
us_ibdev->ib_dev.poll_cq = usnic_ib_poll_cq; us_ibdev->ib_dev.poll_cq = usnic_ib_poll_cq;
us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq; us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq;
us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr; us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr;
us_ibdev->ib_dev.get_port_immutable = usnic_port_immutable;
if (ib_register_device(&us_ibdev->ib_dev, NULL)) if (ib_register_device(&us_ibdev->ib_dev, NULL))

View file

@ -248,7 +248,8 @@ enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device,
} }
int usnic_ib_query_device(struct ib_device *ibdev, int usnic_ib_query_device(struct ib_device *ibdev,
struct ib_device_attr *props) struct ib_device_attr *props,
struct ib_udata *uhw)
{ {
struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
union ib_gid gid; union ib_gid gid;
@ -257,6 +258,9 @@ int usnic_ib_query_device(struct ib_device *ibdev,
int qp_per_vf; int qp_per_vf;
usnic_dbg("\n"); usnic_dbg("\n");
if (uhw->inlen || uhw->outlen)
return -EINVAL;
mutex_lock(&us_ibdev->usdev_lock); mutex_lock(&us_ibdev->usdev_lock);
us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd);
@ -570,13 +574,17 @@ int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
return status; return status;
} }
struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev,
int vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata) struct ib_udata *udata)
{ {
struct ib_cq *cq; struct ib_cq *cq;
usnic_dbg("\n"); usnic_dbg("\n");
if (attr->flags)
return ERR_PTR(-EINVAL);
cq = kzalloc(sizeof(*cq), GFP_KERNEL); cq = kzalloc(sizeof(*cq), GFP_KERNEL);
if (!cq) if (!cq)
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);

View file

@ -24,9 +24,12 @@
enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device, enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device,
u8 port_num); u8 port_num);
int usnic_ib_query_device(struct ib_device *ibdev, int usnic_ib_query_device(struct ib_device *ibdev,
struct ib_device_attr *props); struct ib_device_attr *props,
struct ib_udata *uhw);
int usnic_ib_query_port(struct ib_device *ibdev, u8 port, int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props); struct ib_port_attr *props);
enum rdma_protocol_type
usnic_ib_query_protocol(struct ib_device *device, u8 port_num);
int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, int qp_attr_mask,
struct ib_qp_init_attr *qp_init_attr); struct ib_qp_init_attr *qp_init_attr);
@ -44,8 +47,9 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
int usnic_ib_destroy_qp(struct ib_qp *qp); int usnic_ib_destroy_qp(struct ib_qp *qp);
int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata); int attr_mask, struct ib_udata *udata);
struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries, struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev,
int vector, struct ib_ucontext *context, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
int usnic_ib_destroy_cq(struct ib_cq *cq); int usnic_ib_destroy_cq(struct ib_cq *cq);
struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length, struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length,

View file

@ -472,11 +472,10 @@ struct usnic_uiom_pd *usnic_uiom_alloc_pd(void)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
pd->domain = domain = iommu_domain_alloc(&pci_bus_type); pd->domain = domain = iommu_domain_alloc(&pci_bus_type);
if (IS_ERR_OR_NULL(domain)) { if (!domain) {
usnic_err("Failed to allocate IOMMU domain with err %ld\n", usnic_err("Failed to allocate IOMMU domain");
PTR_ERR(pd->domain));
kfree(pd); kfree(pd);
return ERR_PTR(domain ? PTR_ERR(domain) : -ENOMEM); return ERR_PTR(-ENOMEM);
} }
iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL); iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL);

View file

@ -1128,7 +1128,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
{ {
struct ipoib_neigh_table *ntbl = &priv->ntbl; struct ipoib_neigh_table *ntbl = &priv->ntbl;
struct ipoib_neigh_hash *htbl; struct ipoib_neigh_hash *htbl;
struct ipoib_neigh **buckets; struct ipoib_neigh __rcu **buckets;
u32 size; u32 size;
clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
@ -1146,7 +1146,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
htbl->size = size; htbl->size = size;
htbl->mask = (size - 1); htbl->mask = (size - 1);
htbl->buckets = buckets; htbl->buckets = buckets;
ntbl->htbl = htbl; RCU_INIT_POINTER(ntbl->htbl, htbl);
htbl->ntbl = ntbl; htbl->ntbl = ntbl;
atomic_set(&ntbl->entries, 0); atomic_set(&ntbl->entries, 0);
@ -1685,9 +1685,7 @@ static void ipoib_add_one(struct ib_device *device)
struct net_device *dev; struct net_device *dev;
struct ipoib_dev_priv *priv; struct ipoib_dev_priv *priv;
int s, e, p; int s, e, p;
int count = 0;
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return;
dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
if (!dev_list) if (!dev_list)
@ -1704,15 +1702,21 @@ static void ipoib_add_one(struct ib_device *device)
} }
for (p = s; p <= e; ++p) { for (p = s; p <= e; ++p) {
if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND) if (!rdma_protocol_ib(device, p))
continue; continue;
dev = ipoib_add_port("ib%d", device, p); dev = ipoib_add_port("ib%d", device, p);
if (!IS_ERR(dev)) { if (!IS_ERR(dev)) {
priv = netdev_priv(dev); priv = netdev_priv(dev);
list_add_tail(&priv->list, dev_list); list_add_tail(&priv->list, dev_list);
count++;
} }
} }
if (!count) {
kfree(dev_list);
return;
}
ib_set_client_data(device, &ipoib_client, dev_list); ib_set_client_data(device, &ipoib_client, dev_list);
} }
@ -1721,9 +1725,6 @@ static void ipoib_remove_one(struct ib_device *device)
struct ipoib_dev_priv *priv, *tmp; struct ipoib_dev_priv *priv, *tmp;
struct list_head *dev_list; struct list_head *dev_list;
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return;
dev_list = ib_get_client_data(device, &ipoib_client); dev_list = ib_get_client_data(device, &ipoib_client);
if (!dev_list) if (!dev_list)
return; return;

View file

@ -141,6 +141,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
.sq_sig_type = IB_SIGNAL_ALL_WR, .sq_sig_type = IB_SIGNAL_ALL_WR,
.qp_type = IB_QPT_UD .qp_type = IB_QPT_UD
}; };
struct ib_cq_init_attr cq_attr = {};
int ret, size; int ret, size;
int i; int i;
@ -178,14 +179,17 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
} else } else
goto out_free_wq; goto out_free_wq;
priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0); cq_attr.cqe = size;
priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL,
dev, &cq_attr);
if (IS_ERR(priv->recv_cq)) { if (IS_ERR(priv->recv_cq)) {
printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name); printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
goto out_cm_dev_cleanup; goto out_cm_dev_cleanup;
} }
cq_attr.cqe = ipoib_sendq_size;
priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL, priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL,
dev, ipoib_sendq_size, 0); dev, &cq_attr);
if (IS_ERR(priv->send_cq)) { if (IS_ERR(priv->send_cq)) {
printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name); printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
goto out_free_recv_cq; goto out_free_recv_cq;

View file

@ -51,18 +51,21 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
static void iser_cq_event_callback(struct ib_event *cause, void *context) static void iser_cq_event_callback(struct ib_event *cause, void *context)
{ {
iser_err("got cq event %d \n", cause->event); iser_err("cq event %s (%d)\n",
ib_event_msg(cause->event), cause->event);
} }
static void iser_qp_event_callback(struct ib_event *cause, void *context) static void iser_qp_event_callback(struct ib_event *cause, void *context)
{ {
iser_err("got qp event %d\n",cause->event); iser_err("qp event %s (%d)\n",
ib_event_msg(cause->event), cause->event);
} }
static void iser_event_handler(struct ib_event_handler *handler, static void iser_event_handler(struct ib_event_handler *handler,
struct ib_event *event) struct ib_event *event)
{ {
iser_err("async event %d on device %s port %d\n", event->event, iser_err("async event %s (%d) on device %s port %d\n",
ib_event_msg(event->event), event->event,
event->device->name, event->element.port_num); event->device->name, event->element.port_num);
} }
@ -123,14 +126,17 @@ static int iser_create_device_ib_res(struct iser_device *device)
goto pd_err; goto pd_err;
for (i = 0; i < device->comps_used; i++) { for (i = 0; i < device->comps_used; i++) {
struct ib_cq_init_attr cq_attr = {};
struct iser_comp *comp = &device->comps[i]; struct iser_comp *comp = &device->comps[i];
comp->device = device; comp->device = device;
cq_attr.cqe = max_cqe;
cq_attr.comp_vector = i;
comp->cq = ib_create_cq(device->ib_device, comp->cq = ib_create_cq(device->ib_device,
iser_cq_callback, iser_cq_callback,
iser_cq_event_callback, iser_cq_event_callback,
(void *)comp, (void *)comp,
max_cqe, i); &cq_attr);
if (IS_ERR(comp->cq)) { if (IS_ERR(comp->cq)) {
comp->cq = NULL; comp->cq = NULL;
goto cq_err; goto cq_err;
@ -873,8 +879,9 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
int ret = 0; int ret = 0;
iser_conn = (struct iser_conn *)cma_id->context; iser_conn = (struct iser_conn *)cma_id->context;
iser_info("event %d status %d conn %p id %p\n", iser_info("%s (%d): status %d conn %p id %p\n",
event->event, event->status, cma_id->context, cma_id); rdma_event_msg(event->event), event->event,
event->status, cma_id->context, cma_id);
mutex_lock(&iser_conn->state_mutex); mutex_lock(&iser_conn->state_mutex);
switch (event->event) { switch (event->event) {
@ -913,7 +920,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
} }
break; break;
default: default:
iser_err("Unexpected RDMA CM event (%d)\n", event->event); iser_err("Unexpected RDMA CM event: %s (%d)\n",
rdma_event_msg(event->event), event->event);
break; break;
} }
mutex_unlock(&iser_conn->state_mutex); mutex_unlock(&iser_conn->state_mutex);
@ -1173,10 +1181,13 @@ static void iser_handle_wc(struct ib_wc *wc)
} }
} else { } else {
if (wc->status != IB_WC_WR_FLUSH_ERR) if (wc->status != IB_WC_WR_FLUSH_ERR)
iser_err("wr id %llx status %d vend_err %x\n", iser_err("%s (%d): wr id %llx vend_err %x\n",
wc->wr_id, wc->status, wc->vendor_err); ib_wc_status_msg(wc->status), wc->status,
wc->wr_id, wc->vendor_err);
else else
iser_dbg("flush error: wr id %llx\n", wc->wr_id); iser_dbg("%s (%d): wr id %llx\n",
ib_wc_status_msg(wc->status), wc->status,
wc->wr_id);
if (wc->wr_id == ISER_BEACON_WRID) if (wc->wr_id == ISER_BEACON_WRID)
/* all flush errors were consumed */ /* all flush errors were consumed */

View file

@ -80,7 +80,9 @@ isert_qp_event_callback(struct ib_event *e, void *context)
{ {
struct isert_conn *isert_conn = context; struct isert_conn *isert_conn = context;
isert_err("conn %p event: %d\n", isert_conn, e->event); isert_err("%s (%d): conn %p\n",
ib_event_msg(e->event), e->event, isert_conn);
switch (e->event) { switch (e->event) {
case IB_EVENT_COMM_EST: case IB_EVENT_COMM_EST:
rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST); rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST);
@ -318,15 +320,18 @@ isert_alloc_comps(struct isert_device *device,
max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe); max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe);
for (i = 0; i < device->comps_used; i++) { for (i = 0; i < device->comps_used; i++) {
struct ib_cq_init_attr cq_attr = {};
struct isert_comp *comp = &device->comps[i]; struct isert_comp *comp = &device->comps[i];
comp->device = device; comp->device = device;
INIT_WORK(&comp->work, isert_cq_work); INIT_WORK(&comp->work, isert_cq_work);
cq_attr.cqe = max_cqe;
cq_attr.comp_vector = i;
comp->cq = ib_create_cq(device->ib_device, comp->cq = ib_create_cq(device->ib_device,
isert_cq_callback, isert_cq_callback,
isert_cq_event_callback, isert_cq_event_callback,
(void *)comp, (void *)comp,
max_cqe, i); &cq_attr);
if (IS_ERR(comp->cq)) { if (IS_ERR(comp->cq)) {
isert_err("Unable to allocate cq\n"); isert_err("Unable to allocate cq\n");
ret = PTR_ERR(comp->cq); ret = PTR_ERR(comp->cq);
@ -900,7 +905,8 @@ static int
isert_np_cma_handler(struct isert_np *isert_np, isert_np_cma_handler(struct isert_np *isert_np,
enum rdma_cm_event_type event) enum rdma_cm_event_type event)
{ {
isert_dbg("isert np %p, handling event %d\n", isert_np, event); isert_dbg("%s (%d): isert np %p\n",
rdma_event_msg(event), event, isert_np);
switch (event) { switch (event) {
case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_DEVICE_REMOVAL:
@ -974,7 +980,8 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
{ {
int ret = 0; int ret = 0;
isert_info("event %d status %d id %p np %p\n", event->event, isert_info("%s (%d): status %d id %p np %p\n",
rdma_event_msg(event->event), event->event,
event->status, cma_id, cma_id->context); event->status, cma_id, cma_id->context);
switch (event->event) { switch (event->event) {
@ -2108,10 +2115,13 @@ isert_handle_wc(struct ib_wc *wc)
} }
} else { } else {
if (wc->status != IB_WC_WR_FLUSH_ERR) if (wc->status != IB_WC_WR_FLUSH_ERR)
isert_err("wr id %llx status %d vend_err %x\n", isert_err("%s (%d): wr id %llx vend_err %x\n",
wc->wr_id, wc->status, wc->vendor_err); ib_wc_status_msg(wc->status), wc->status,
wc->wr_id, wc->vendor_err);
else else
isert_dbg("flush error: wr id %llx\n", wc->wr_id); isert_dbg("%s (%d): wr id %llx\n",
ib_wc_status_msg(wc->status), wc->status,
wc->wr_id);
if (wc->wr_id != ISER_FASTREG_LI_WRID) if (wc->wr_id != ISER_FASTREG_LI_WRID)
isert_cq_comp_err(isert_conn, wc); isert_cq_comp_err(isert_conn, wc);

View file

@ -59,9 +59,10 @@
#define DRV_RELDATE "July 1, 2013" #define DRV_RELDATE "July 1, 2013"
MODULE_AUTHOR("Roland Dreier"); MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator");
"v" DRV_VERSION " (" DRV_RELDATE ")");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_INFO(release_date, DRV_RELDATE);
static unsigned int srp_sg_tablesize; static unsigned int srp_sg_tablesize;
static unsigned int cmd_sg_entries; static unsigned int cmd_sg_entries;
@ -253,7 +254,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
static void srp_qp_event(struct ib_event *event, void *context) static void srp_qp_event(struct ib_event *event, void *context)
{ {
pr_debug("QP event %d\n", event->event); pr_debug("QP event %s (%d)\n",
ib_event_msg(event->event), event->event);
} }
static int srp_init_qp(struct srp_target_port *target, static int srp_init_qp(struct srp_target_port *target,
@ -465,14 +467,13 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
*/ */
static void srp_destroy_qp(struct srp_rdma_ch *ch) static void srp_destroy_qp(struct srp_rdma_ch *ch)
{ {
struct srp_target_port *target = ch->target;
static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR }; static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID }; static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
struct ib_recv_wr *bad_wr; struct ib_recv_wr *bad_wr;
int ret; int ret;
/* Destroying a QP and reusing ch->done is only safe if not connected */ /* Destroying a QP and reusing ch->done is only safe if not connected */
WARN_ON_ONCE(target->connected); WARN_ON_ONCE(ch->connected);
ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE); ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE);
WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret); WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret);
@ -499,6 +500,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
struct ib_fmr_pool *fmr_pool = NULL; struct ib_fmr_pool *fmr_pool = NULL;
struct srp_fr_pool *fr_pool = NULL; struct srp_fr_pool *fr_pool = NULL;
const int m = 1 + dev->use_fast_reg; const int m = 1 + dev->use_fast_reg;
struct ib_cq_init_attr cq_attr = {};
int ret; int ret;
init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
@ -506,15 +508,19 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
return -ENOMEM; return -ENOMEM;
/* + 1 for SRP_LAST_WR_ID */ /* + 1 for SRP_LAST_WR_ID */
cq_attr.cqe = target->queue_size + 1;
cq_attr.comp_vector = ch->comp_vector;
recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch, recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch,
target->queue_size + 1, ch->comp_vector); &cq_attr);
if (IS_ERR(recv_cq)) { if (IS_ERR(recv_cq)) {
ret = PTR_ERR(recv_cq); ret = PTR_ERR(recv_cq);
goto err; goto err;
} }
cq_attr.cqe = m * target->queue_size;
cq_attr.comp_vector = ch->comp_vector;
send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch, send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch,
m * target->queue_size, ch->comp_vector); &cq_attr);
if (IS_ERR(send_cq)) { if (IS_ERR(send_cq)) {
ret = PTR_ERR(send_cq); ret = PTR_ERR(send_cq);
goto err_recv_cq; goto err_recv_cq;
@ -781,7 +787,7 @@ static int srp_send_req(struct srp_rdma_ch *ch, bool multich)
shost_printk(KERN_DEBUG, target->scsi_host, shost_printk(KERN_DEBUG, target->scsi_host,
PFX "Topspin/Cisco initiator port ID workaround " PFX "Topspin/Cisco initiator port ID workaround "
"activated for target GUID %016llx\n", "activated for target GUID %016llx\n",
(unsigned long long) be64_to_cpu(target->ioc_guid)); be64_to_cpu(target->ioc_guid));
memset(req->priv.initiator_port_id, 0, 8); memset(req->priv.initiator_port_id, 0, 8);
memcpy(req->priv.initiator_port_id + 8, memcpy(req->priv.initiator_port_id + 8,
&target->srp_host->srp_dev->dev->node_guid, 8); &target->srp_host->srp_dev->dev->node_guid, 8);
@ -811,37 +817,21 @@ static bool srp_queue_remove_work(struct srp_target_port *target)
return changed; return changed;
} }
static bool srp_change_conn_state(struct srp_target_port *target,
bool connected)
{
bool changed = false;
spin_lock_irq(&target->lock);
if (target->connected != connected) {
target->connected = connected;
changed = true;
}
spin_unlock_irq(&target->lock);
return changed;
}
static void srp_disconnect_target(struct srp_target_port *target) static void srp_disconnect_target(struct srp_target_port *target)
{ {
struct srp_rdma_ch *ch; struct srp_rdma_ch *ch;
int i; int i;
if (srp_change_conn_state(target, false)) {
/* XXX should send SRP_I_LOGOUT request */ /* XXX should send SRP_I_LOGOUT request */
for (i = 0; i < target->ch_count; i++) { for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i]; ch = &target->ch[i];
ch->connected = false;
if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) { if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
shost_printk(KERN_DEBUG, target->scsi_host, shost_printk(KERN_DEBUG, target->scsi_host,
PFX "Sending CM DREQ failed\n"); PFX "Sending CM DREQ failed\n");
} }
} }
}
} }
static void srp_free_req_data(struct srp_target_port *target, static void srp_free_req_data(struct srp_target_port *target,
@ -852,7 +842,7 @@ static void srp_free_req_data(struct srp_target_port *target,
struct srp_request *req; struct srp_request *req;
int i; int i;
if (!ch->target || !ch->req_ring) if (!ch->req_ring)
return; return;
for (i = 0; i < target->req_ring_size; ++i) { for (i = 0; i < target->req_ring_size; ++i) {
@ -986,14 +976,26 @@ static void srp_rport_delete(struct srp_rport *rport)
srp_queue_remove_work(target); srp_queue_remove_work(target);
} }
/**
* srp_connected_ch() - number of connected channels
* @target: SRP target port.
*/
static int srp_connected_ch(struct srp_target_port *target)
{
int i, c = 0;
for (i = 0; i < target->ch_count; i++)
c += target->ch[i].connected;
return c;
}
static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich) static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
{ {
struct srp_target_port *target = ch->target; struct srp_target_port *target = ch->target;
int ret; int ret;
WARN_ON_ONCE(!multich && target->connected); WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
target->qp_in_error = false;
ret = srp_lookup_path(ch); ret = srp_lookup_path(ch);
if (ret) if (ret)
@ -1016,7 +1018,7 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
*/ */
switch (ch->status) { switch (ch->status) {
case 0: case 0:
srp_change_conn_state(target, true); ch->connected = true;
return 0; return 0;
case SRP_PORT_REDIRECT: case SRP_PORT_REDIRECT:
@ -1214,14 +1216,10 @@ static int srp_rport_reconnect(struct srp_rport *rport)
*/ */
for (i = 0; i < target->ch_count; i++) { for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i]; ch = &target->ch[i];
if (!ch->target)
break;
ret += srp_new_cm_id(ch); ret += srp_new_cm_id(ch);
} }
for (i = 0; i < target->ch_count; i++) { for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i]; ch = &target->ch[i];
if (!ch->target)
break;
for (j = 0; j < target->req_ring_size; ++j) { for (j = 0; j < target->req_ring_size; ++j) {
struct srp_request *req = &ch->req_ring[j]; struct srp_request *req = &ch->req_ring[j];
@ -1230,8 +1228,6 @@ static int srp_rport_reconnect(struct srp_rport *rport)
} }
for (i = 0; i < target->ch_count; i++) { for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i]; ch = &target->ch[i];
if (!ch->target)
break;
/* /*
* Whether or not creating a new CM ID succeeded, create a new * Whether or not creating a new CM ID succeeded, create a new
* QP. This guarantees that all completion callback function * QP. This guarantees that all completion callback function
@ -1243,13 +1239,13 @@ static int srp_rport_reconnect(struct srp_rport *rport)
for (j = 0; j < target->queue_size; ++j) for (j = 0; j < target->queue_size; ++j)
list_add(&ch->tx_ring[j]->list, &ch->free_tx); list_add(&ch->tx_ring[j]->list, &ch->free_tx);
} }
target->qp_in_error = false;
for (i = 0; i < target->ch_count; i++) { for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i]; ch = &target->ch[i];
if (ret || !ch->target) { if (ret)
if (i > 1)
ret = 0;
break; break;
}
ret = srp_connect_ch(ch, multich); ret = srp_connect_ch(ch, multich);
multich = true; multich = true;
} }
@ -1842,7 +1838,7 @@ static void srp_process_aer_req(struct srp_rdma_ch *ch,
s32 delta = be32_to_cpu(req->req_lim_delta); s32 delta = be32_to_cpu(req->req_lim_delta);
shost_printk(KERN_ERR, target->scsi_host, PFX shost_printk(KERN_ERR, target->scsi_host, PFX
"ignoring AER for LUN %llu\n", be64_to_cpu(req->lun)); "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
if (srp_response_common(ch, delta, &rsp, sizeof(rsp))) if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
shost_printk(KERN_ERR, target->scsi_host, PFX shost_printk(KERN_ERR, target->scsi_host, PFX
@ -1929,20 +1925,21 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
return; return;
} }
if (target->connected && !target->qp_in_error) { if (ch->connected && !target->qp_in_error) {
if (wr_id & LOCAL_INV_WR_ID_MASK) { if (wr_id & LOCAL_INV_WR_ID_MASK) {
shost_printk(KERN_ERR, target->scsi_host, PFX shost_printk(KERN_ERR, target->scsi_host, PFX
"LOCAL_INV failed with status %d\n", "LOCAL_INV failed with status %s (%d)\n",
wc_status); ib_wc_status_msg(wc_status), wc_status);
} else if (wr_id & FAST_REG_WR_ID_MASK) { } else if (wr_id & FAST_REG_WR_ID_MASK) {
shost_printk(KERN_ERR, target->scsi_host, PFX shost_printk(KERN_ERR, target->scsi_host, PFX
"FAST_REG_MR failed status %d\n", "FAST_REG_MR failed status %s (%d)\n",
wc_status); ib_wc_status_msg(wc_status), wc_status);
} else { } else {
shost_printk(KERN_ERR, target->scsi_host, shost_printk(KERN_ERR, target->scsi_host,
PFX "failed %s status %d for iu %p\n", PFX "failed %s status %s (%d) for iu %p\n",
send_err ? "send" : "receive", send_err ? "send" : "receive",
wc_status, (void *)(uintptr_t)wr_id); ib_wc_status_msg(wc_status), wc_status,
(void *)(uintptr_t)wr_id);
} }
queue_work(system_long_wq, &target->tl_err_work); queue_work(system_long_wq, &target->tl_err_work);
} }
@ -2034,7 +2031,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
memset(cmd, 0, sizeof *cmd); memset(cmd, 0, sizeof *cmd);
cmd->opcode = SRP_CMD; cmd->opcode = SRP_CMD;
cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48); int_to_scsilun(scmnd->device->lun, &cmd->lun);
cmd->tag = tag; cmd->tag = tag;
memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len); memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
@ -2367,7 +2364,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
case IB_CM_DREQ_RECEIVED: case IB_CM_DREQ_RECEIVED:
shost_printk(KERN_WARNING, target->scsi_host, shost_printk(KERN_WARNING, target->scsi_host,
PFX "DREQ received - connection closed\n"); PFX "DREQ received - connection closed\n");
srp_change_conn_state(target, false); ch->connected = false;
if (ib_send_cm_drep(cm_id, NULL, 0)) if (ib_send_cm_drep(cm_id, NULL, 0))
shost_printk(KERN_ERR, target->scsi_host, shost_printk(KERN_ERR, target->scsi_host,
PFX "Sending CM DREP failed\n"); PFX "Sending CM DREP failed\n");
@ -2414,8 +2411,8 @@ srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
return scsi_change_queue_depth(sdev, qdepth); return scsi_change_queue_depth(sdev, qdepth);
} }
static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
unsigned int lun, u8 func) u8 func)
{ {
struct srp_target_port *target = ch->target; struct srp_target_port *target = ch->target;
struct srp_rport *rport = target->rport; struct srp_rport *rport = target->rport;
@ -2423,7 +2420,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
struct srp_iu *iu; struct srp_iu *iu;
struct srp_tsk_mgmt *tsk_mgmt; struct srp_tsk_mgmt *tsk_mgmt;
if (!target->connected || target->qp_in_error) if (!ch->connected || target->qp_in_error)
return -1; return -1;
init_completion(&ch->tsk_mgmt_done); init_completion(&ch->tsk_mgmt_done);
@ -2449,7 +2446,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
memset(tsk_mgmt, 0, sizeof *tsk_mgmt); memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
tsk_mgmt->opcode = SRP_TSK_MGMT; tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = cpu_to_be64((u64) lun << 48); int_to_scsilun(lun, &tsk_mgmt->lun);
tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT; tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT;
tsk_mgmt->tsk_mgmt_func = func; tsk_mgmt->tsk_mgmt_func = func;
tsk_mgmt->task_tag = req_tag; tsk_mgmt->task_tag = req_tag;
@ -2563,8 +2560,7 @@ static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
{ {
struct srp_target_port *target = host_to_target(class_to_shost(dev)); struct srp_target_port *target = host_to_target(class_to_shost(dev));
return sprintf(buf, "0x%016llx\n", return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
(unsigned long long) be64_to_cpu(target->id_ext));
} }
static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr, static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
@ -2572,8 +2568,7 @@ static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
{ {
struct srp_target_port *target = host_to_target(class_to_shost(dev)); struct srp_target_port *target = host_to_target(class_to_shost(dev));
return sprintf(buf, "0x%016llx\n", return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
(unsigned long long) be64_to_cpu(target->ioc_guid));
} }
static ssize_t show_service_id(struct device *dev, static ssize_t show_service_id(struct device *dev,
@ -2581,8 +2576,7 @@ static ssize_t show_service_id(struct device *dev,
{ {
struct srp_target_port *target = host_to_target(class_to_shost(dev)); struct srp_target_port *target = host_to_target(class_to_shost(dev));
return sprintf(buf, "0x%016llx\n", return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->service_id));
(unsigned long long) be64_to_cpu(target->service_id));
} }
static ssize_t show_pkey(struct device *dev, struct device_attribute *attr, static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
@ -2773,7 +2767,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
target->state = SRP_TARGET_SCANNING; target->state = SRP_TARGET_SCANNING;
sprintf(target->target_name, "SRP.T10:%016llX", sprintf(target->target_name, "SRP.T10:%016llX",
(unsigned long long) be64_to_cpu(target->id_ext)); be64_to_cpu(target->id_ext));
if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device)) if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device))
return -ENODEV; return -ENODEV;
@ -2797,7 +2791,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
scsi_scan_target(&target->scsi_host->shost_gendev, scsi_scan_target(&target->scsi_host->shost_gendev,
0, target->scsi_id, SCAN_WILD_CARD, 0); 0, target->scsi_id, SCAN_WILD_CARD, 0);
if (!target->connected || target->qp_in_error) { if (srp_connected_ch(target) < target->ch_count ||
target->qp_in_error) {
shost_printk(KERN_INFO, target->scsi_host, shost_printk(KERN_INFO, target->scsi_host,
PFX "SCSI scan failed - removing SCSI host\n"); PFX "SCSI scan failed - removing SCSI host\n");
srp_queue_remove_work(target); srp_queue_remove_work(target);
@ -3146,7 +3141,7 @@ static ssize_t srp_create_target(struct device *dev,
target_host->transportt = ib_srp_transport_template; target_host->transportt = ib_srp_transport_template;
target_host->max_channel = 0; target_host->max_channel = 0;
target_host->max_id = 1; target_host->max_id = 1;
target_host->max_lun = SRP_MAX_LUN; target_host->max_lun = -1LL;
target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
target = host_to_target(target_host); target = host_to_target(target_host);
@ -3172,11 +3167,11 @@ static ssize_t srp_create_target(struct device *dev,
ret = srp_parse_options(buf, target); ret = srp_parse_options(buf, target);
if (ret) if (ret)
goto err; goto out;
ret = scsi_init_shared_tag_map(target_host, target_host->can_queue); ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
if (ret) if (ret)
goto err; goto out;
target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE; target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
@ -3187,7 +3182,7 @@ static ssize_t srp_create_target(struct device *dev,
be64_to_cpu(target->ioc_guid), be64_to_cpu(target->ioc_guid),
be64_to_cpu(target->initiator_ext)); be64_to_cpu(target->initiator_ext));
ret = -EEXIST; ret = -EEXIST;
goto err; goto out;
} }
if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg && if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg &&
@ -3208,7 +3203,7 @@ static ssize_t srp_create_target(struct device *dev,
spin_lock_init(&target->lock); spin_lock_init(&target->lock);
ret = ib_query_gid(ibdev, host->port, 0, &target->sgid); ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
if (ret) if (ret)
goto err; goto out;
ret = -ENOMEM; ret = -ENOMEM;
target->ch_count = max_t(unsigned, num_online_nodes(), target->ch_count = max_t(unsigned, num_online_nodes(),
@ -3219,7 +3214,7 @@ static ssize_t srp_create_target(struct device *dev,
target->ch = kcalloc(target->ch_count, sizeof(*target->ch), target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
GFP_KERNEL); GFP_KERNEL);
if (!target->ch) if (!target->ch)
goto err; goto out;
node_idx = 0; node_idx = 0;
for_each_online_node(node) { for_each_online_node(node) {
@ -3315,9 +3310,6 @@ err_disconnect:
} }
kfree(target->ch); kfree(target->ch);
err:
scsi_host_put(target_host);
goto out; goto out;
} }

View file

@ -54,7 +54,6 @@ enum {
SRP_DLID_REDIRECT = 2, SRP_DLID_REDIRECT = 2,
SRP_STALE_CONN = 3, SRP_STALE_CONN = 3,
SRP_MAX_LUN = 512,
SRP_DEF_SG_TABLESIZE = 12, SRP_DEF_SG_TABLESIZE = 12,
SRP_DEFAULT_QUEUE_SIZE = 1 << 6, SRP_DEFAULT_QUEUE_SIZE = 1 << 6,
@ -170,6 +169,7 @@ struct srp_rdma_ch {
struct completion tsk_mgmt_done; struct completion tsk_mgmt_done;
u8 tsk_mgmt_status; u8 tsk_mgmt_status;
bool connected;
}; };
/** /**
@ -214,7 +214,6 @@ struct srp_target_port {
__be16 pkey; __be16 pkey;
u32 rq_tmo_jiffies; u32 rq_tmo_jiffies;
bool connected;
int zero_req_lim; int zero_req_lim;

View file

@ -476,7 +476,8 @@ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp, rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
mad_wc->wc->pkey_index, 0, mad_wc->wc->pkey_index, 0,
IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA, IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,
GFP_KERNEL); GFP_KERNEL,
IB_MGMT_BASE_VERSION);
if (IS_ERR(rsp)) if (IS_ERR(rsp))
goto err_rsp; goto err_rsp;
@ -2080,6 +2081,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
struct srpt_port *sport = ch->sport; struct srpt_port *sport = ch->sport;
struct srpt_device *sdev = sport->sdev; struct srpt_device *sdev = sport->sdev;
u32 srp_sq_size = sport->port_attrib.srp_sq_size; u32 srp_sq_size = sport->port_attrib.srp_sq_size;
struct ib_cq_init_attr cq_attr = {};
int ret; int ret;
WARN_ON(ch->rq_size < 1); WARN_ON(ch->rq_size < 1);
@ -2090,8 +2092,9 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
goto out; goto out;
retry: retry:
cq_attr.cqe = ch->rq_size + srp_sq_size;
ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
ch->rq_size + srp_sq_size, 0); &cq_attr);
if (IS_ERR(ch->cq)) { if (IS_ERR(ch->cq)) {
ret = PTR_ERR(ch->cq); ret = PTR_ERR(ch->cq);
pr_err("failed to create CQ cqe= %d ret= %d\n", pr_err("failed to create CQ cqe= %d ret= %d\n",

View file

@ -1185,6 +1185,7 @@ enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
int cxgb4_t4_bar2_sge_qregs(struct adapter *adapter, int cxgb4_t4_bar2_sge_qregs(struct adapter *adapter,
unsigned int qid, unsigned int qid,
enum t4_bar2_qtype qtype, enum t4_bar2_qtype qtype,
int user,
u64 *pbar2_qoffset, u64 *pbar2_qoffset,
unsigned int *pbar2_qid); unsigned int *pbar2_qid);

View file

@ -2145,6 +2145,7 @@ EXPORT_SYMBOL(cxgb4_read_sge_timestamp);
int cxgb4_bar2_sge_qregs(struct net_device *dev, int cxgb4_bar2_sge_qregs(struct net_device *dev,
unsigned int qid, unsigned int qid,
enum cxgb4_bar2_qtype qtype, enum cxgb4_bar2_qtype qtype,
int user,
u64 *pbar2_qoffset, u64 *pbar2_qoffset,
unsigned int *pbar2_qid) unsigned int *pbar2_qid)
{ {
@ -2153,6 +2154,7 @@ int cxgb4_bar2_sge_qregs(struct net_device *dev,
(qtype == CXGB4_BAR2_QTYPE_EGRESS (qtype == CXGB4_BAR2_QTYPE_EGRESS
? T4_BAR2_QTYPE_EGRESS ? T4_BAR2_QTYPE_EGRESS
: T4_BAR2_QTYPE_INGRESS), : T4_BAR2_QTYPE_INGRESS),
user,
pbar2_qoffset, pbar2_qoffset,
pbar2_qid); pbar2_qid);
} }
@ -2351,7 +2353,7 @@ static void process_db_drop(struct work_struct *work)
int ret; int ret;
ret = cxgb4_t4_bar2_sge_qregs(adap, qid, T4_BAR2_QTYPE_EGRESS, ret = cxgb4_t4_bar2_sge_qregs(adap, qid, T4_BAR2_QTYPE_EGRESS,
&bar2_qoffset, &bar2_qid); 0, &bar2_qoffset, &bar2_qid);
if (ret) if (ret)
dev_err(adap->pdev_dev, "doorbell drop recovery: " dev_err(adap->pdev_dev, "doorbell drop recovery: "
"qid=%d, pidx_inc=%d\n", qid, pidx_inc); "qid=%d, pidx_inc=%d\n", qid, pidx_inc);

View file

@ -306,6 +306,7 @@ enum cxgb4_bar2_qtype { CXGB4_BAR2_QTYPE_EGRESS, CXGB4_BAR2_QTYPE_INGRESS };
int cxgb4_bar2_sge_qregs(struct net_device *dev, int cxgb4_bar2_sge_qregs(struct net_device *dev,
unsigned int qid, unsigned int qid,
enum cxgb4_bar2_qtype qtype, enum cxgb4_bar2_qtype qtype,
int user,
u64 *pbar2_qoffset, u64 *pbar2_qoffset,
unsigned int *pbar2_qid); unsigned int *pbar2_qid);

View file

@ -2429,7 +2429,7 @@ static void __iomem *bar2_address(struct adapter *adapter,
u64 bar2_qoffset; u64 bar2_qoffset;
int ret; int ret;
ret = cxgb4_t4_bar2_sge_qregs(adapter, qid, qtype, ret = cxgb4_t4_bar2_sge_qregs(adapter, qid, qtype, 0,
&bar2_qoffset, pbar2_qid); &bar2_qoffset, pbar2_qid);
if (ret) if (ret)
return NULL; return NULL;

View file

@ -5102,6 +5102,7 @@ int t4_prep_adapter(struct adapter *adapter)
* @adapter: the adapter * @adapter: the adapter
* @qid: the Queue ID * @qid: the Queue ID
* @qtype: the Ingress or Egress type for @qid * @qtype: the Ingress or Egress type for @qid
* @user: true if this request is for a user mode queue
* @pbar2_qoffset: BAR2 Queue Offset * @pbar2_qoffset: BAR2 Queue Offset
* @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
* *
@ -5125,6 +5126,7 @@ int t4_prep_adapter(struct adapter *adapter)
int cxgb4_t4_bar2_sge_qregs(struct adapter *adapter, int cxgb4_t4_bar2_sge_qregs(struct adapter *adapter,
unsigned int qid, unsigned int qid,
enum t4_bar2_qtype qtype, enum t4_bar2_qtype qtype,
int user,
u64 *pbar2_qoffset, u64 *pbar2_qoffset,
unsigned int *pbar2_qid) unsigned int *pbar2_qid)
{ {
@ -5132,9 +5134,8 @@ int cxgb4_t4_bar2_sge_qregs(struct adapter *adapter,
u64 bar2_page_offset, bar2_qoffset; u64 bar2_page_offset, bar2_qoffset;
unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred; unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
/* T4 doesn't support BAR2 SGE Queue registers. /* T4 doesn't support BAR2 SGE Queue registers for kernel mode queues */
*/ if (!user && is_t4(adapter->params.chip))
if (is_t4(adapter->params.chip))
return -EINVAL; return -EINVAL;
/* Get our SGE Page Size parameters. /* Get our SGE Page Size parameters.

View file

@ -1674,6 +1674,25 @@ static int map_internal_clock(struct mlx4_dev *dev)
return 0; return 0;
} }
int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
struct mlx4_clock_params *params)
{
struct mlx4_priv *priv = mlx4_priv(dev);
if (mlx4_is_slave(dev))
return -ENOTSUPP;
if (!params)
return -EINVAL;
params->bar = priv->fw.clock_bar;
params->offset = priv->fw.clock_offset;
params->size = MLX4_CLOCK_SIZE;
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_get_internal_clock_params);
static void unmap_internal_clock(struct mlx4_dev *dev) static void unmap_internal_clock(struct mlx4_dev *dev)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);

View file

@ -36,7 +36,7 @@
#include <linux/mlx5/cmd.h> #include <linux/mlx5/cmd.h>
#include "mlx5_core.h" #include "mlx5_core.h"
int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb, int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
u16 opmod, u8 port) u16 opmod, u8 port)
{ {
struct mlx5_mad_ifc_mbox_in *in = NULL; struct mlx5_mad_ifc_mbox_in *in = NULL;

View file

@ -1053,7 +1053,7 @@ static int ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd,
memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
srp_cmd->opcode = SRP_CMD; srp_cmd->opcode = SRP_CMD;
memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
srp_cmd->lun = cpu_to_be64(((u64)lun) << 48); int_to_scsilun(lun, &srp_cmd->lun);
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
if (!firmware_has_feature(FW_FEATURE_CMO)) if (!firmware_has_feature(FW_FEATURE_CMO))
@ -1529,7 +1529,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
/* Set up an abort SRP command */ /* Set up an abort SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
tsk_mgmt->opcode = SRP_TSK_MGMT; tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = cpu_to_be64(((u64) lun) << 48); int_to_scsilun(lun, &tsk_mgmt->lun);
tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK; tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
tsk_mgmt->task_tag = (u64) found_evt; tsk_mgmt->task_tag = (u64) found_evt;
@ -1652,7 +1652,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* Set up a lun reset SRP command */ /* Set up a lun reset SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
tsk_mgmt->opcode = SRP_TSK_MGMT; tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = cpu_to_be64(((u64) lun) << 48); int_to_scsilun(lun, &tsk_mgmt->lun);
tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET; tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
evt->sync_srp = &srp_rsp; evt->sync_srp = &srp_rsp;

View file

@ -61,6 +61,11 @@ static inline struct Scsi_Host *rport_to_shost(struct srp_rport *r)
return dev_to_shost(r->dev.parent); return dev_to_shost(r->dev.parent);
} }
static inline struct srp_rport *shost_to_rport(struct Scsi_Host *shost)
{
return transport_class_to_srp_rport(&shost->shost_gendev);
}
/** /**
* srp_tmo_valid() - check timeout combination validity * srp_tmo_valid() - check timeout combination validity
* @reconnect_delay: Reconnect delay in seconds. * @reconnect_delay: Reconnect delay in seconds.
@ -396,6 +401,36 @@ static void srp_reconnect_work(struct work_struct *work)
} }
} }
/**
* scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
* @shost: SCSI host for which to count the number of scsi_request_fn() callers.
*
* To do: add support for scsi-mq in this function.
*/
static int scsi_request_fn_active(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
struct request_queue *q;
int request_fn_active = 0;
shost_for_each_device(sdev, shost) {
q = sdev->request_queue;
spin_lock_irq(q->queue_lock);
request_fn_active += q->request_fn_active;
spin_unlock_irq(q->queue_lock);
}
return request_fn_active;
}
/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */
static void srp_wait_for_queuecommand(struct Scsi_Host *shost)
{
while (scsi_request_fn_active(shost))
msleep(20);
}
static void __rport_fail_io_fast(struct srp_rport *rport) static void __rport_fail_io_fast(struct srp_rport *rport)
{ {
struct Scsi_Host *shost = rport_to_shost(rport); struct Scsi_Host *shost = rport_to_shost(rport);
@ -409,8 +444,10 @@ static void __rport_fail_io_fast(struct srp_rport *rport)
/* Involve the LLD if possible to terminate all I/O on the rport. */ /* Involve the LLD if possible to terminate all I/O on the rport. */
i = to_srp_internal(shost->transportt); i = to_srp_internal(shost->transportt);
if (i->f->terminate_rport_io) if (i->f->terminate_rport_io) {
srp_wait_for_queuecommand(shost);
i->f->terminate_rport_io(rport); i->f->terminate_rport_io(rport);
}
} }
/** /**
@ -503,27 +540,6 @@ void srp_start_tl_fail_timers(struct srp_rport *rport)
} }
EXPORT_SYMBOL(srp_start_tl_fail_timers); EXPORT_SYMBOL(srp_start_tl_fail_timers);
/**
* scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
* @shost: SCSI host for which to count the number of scsi_request_fn() callers.
*/
static int scsi_request_fn_active(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
struct request_queue *q;
int request_fn_active = 0;
shost_for_each_device(sdev, shost) {
q = sdev->request_queue;
spin_lock_irq(q->queue_lock);
request_fn_active += q->request_fn_active;
spin_unlock_irq(q->queue_lock);
}
return request_fn_active;
}
/** /**
* srp_reconnect_rport() - reconnect to an SRP target port * srp_reconnect_rport() - reconnect to an SRP target port
* @rport: SRP target port. * @rport: SRP target port.
@ -559,8 +575,7 @@ int srp_reconnect_rport(struct srp_rport *rport)
if (res) if (res)
goto out; goto out;
scsi_target_block(&shost->shost_gendev); scsi_target_block(&shost->shost_gendev);
while (scsi_request_fn_active(shost)) srp_wait_for_queuecommand(shost);
msleep(20);
res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
pr_debug("%s (state %d): transport.reconnect() returned %d\n", pr_debug("%s (state %d): transport.reconnect() returned %d\n",
dev_name(&shost->shost_gendev), rport->state, res); dev_name(&shost->shost_gendev), rport->state, res);
@ -618,9 +633,11 @@ static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd)
struct scsi_device *sdev = scmd->device; struct scsi_device *sdev = scmd->device;
struct Scsi_Host *shost = sdev->host; struct Scsi_Host *shost = sdev->host;
struct srp_internal *i = to_srp_internal(shost->transportt); struct srp_internal *i = to_srp_internal(shost->transportt);
struct srp_rport *rport = shost_to_rport(shost);
pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev)); pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev));
return i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? return rport->fast_io_fail_tmo < 0 && rport->dev_loss_tmo < 0 &&
i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ?
BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED;
} }

View file

@ -647,6 +647,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
kib_dev_t *dev; kib_dev_t *dev;
struct ib_qp_init_attr *init_qp_attr; struct ib_qp_init_attr *init_qp_attr;
struct kib_sched_info *sched; struct kib_sched_info *sched;
struct ib_cq_init_attr cq_attr = {};
kib_conn_t *conn; kib_conn_t *conn;
struct ib_cq *cq; struct ib_cq *cq;
unsigned long flags; unsigned long flags;
@ -742,10 +743,11 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
kiblnd_map_rx_descs(conn); kiblnd_map_rx_descs(conn);
cq_attr.cqe = IBLND_CQ_ENTRIES(version);
cq_attr.comp_vector = kiblnd_get_completion_vector(conn, cpt);
cq = ib_create_cq(cmid->device, cq = ib_create_cq(cmid->device,
kiblnd_cq_completion, kiblnd_cq_event, conn, kiblnd_cq_completion, kiblnd_cq_event, conn,
IBLND_CQ_ENTRIES(version), &cq_attr);
kiblnd_get_completion_vector(conn, cpt));
if (IS_ERR(cq)) { if (IS_ERR(cq)) {
CERROR("Can't create CQ: %ld, cqe: %d\n", CERROR("Can't create CQ: %ld, cqe: %d\n",
PTR_ERR(cq), IBLND_CQ_ENTRIES(version)); PTR_ERR(cq), IBLND_CQ_ENTRIES(version));

View file

@ -829,6 +829,12 @@ struct mlx4_dev {
struct mlx4_vf_dev *dev_vfs; struct mlx4_vf_dev *dev_vfs;
}; };
struct mlx4_clock_params {
u64 offset;
u8 bar;
u8 size;
};
struct mlx4_eqe { struct mlx4_eqe {
u8 reserved1; u8 reserved1;
u8 type; u8 type;
@ -1485,4 +1491,7 @@ int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev,
enum mlx4_access_reg_method method, enum mlx4_access_reg_method method,
struct mlx4_ptys_reg *ptys_reg); struct mlx4_ptys_reg *ptys_reg);
int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
struct mlx4_clock_params *params);
#endif /* MLX4_DEVICE_H */ #endif /* MLX4_DEVICE_H */

View file

@ -696,7 +696,7 @@ int mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
u32 *mkey); u32 *mkey);
int mlx5_core_alloc_pd(struct mlx5_core_dev *dev, u32 *pdn); int mlx5_core_alloc_pd(struct mlx5_core_dev *dev, u32 *pdn);
int mlx5_core_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn); int mlx5_core_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn);
int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb, int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
u16 opmod, u8 port); u16 opmod, u8 port);
void mlx5_pagealloc_init(struct mlx5_core_dev *dev); void mlx5_pagealloc_init(struct mlx5_core_dev *dev);
void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev); void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev);

View file

@ -111,8 +111,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
int rdma_addr_size(struct sockaddr *addr); int rdma_addr_size(struct sockaddr *addr);
int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id); int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id);
int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *smac, int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgid,
u16 *vlan_id); u8 *smac, u16 *vlan_id);
static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr) static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
{ {
@ -160,7 +160,7 @@ static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)
} }
/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */ /* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */
static inline void rdma_gid2ip(struct sockaddr *out, union ib_gid *gid) static inline void rdma_gid2ip(struct sockaddr *out, const union ib_gid *gid)
{ {
if (ipv6_addr_v4mapped((struct in6_addr *)gid)) { if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {
struct sockaddr_in *out_in = (struct sockaddr_in *)out; struct sockaddr_in *out_in = (struct sockaddr_in *)out;

View file

@ -65,7 +65,7 @@ int ib_get_cached_gid(struct ib_device *device,
* the local software cache. * the local software cache.
*/ */
int ib_find_cached_gid(struct ib_device *device, int ib_find_cached_gid(struct ib_device *device,
union ib_gid *gid, const union ib_gid *gid,
u8 *port_num, u8 *port_num,
u16 *index); u16 *index);

View file

@ -42,8 +42,11 @@
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <uapi/rdma/ib_user_mad.h> #include <uapi/rdma/ib_user_mad.h>
/* Management base version */ /* Management base versions */
#define IB_MGMT_BASE_VERSION 1 #define IB_MGMT_BASE_VERSION 1
#define OPA_MGMT_BASE_VERSION 0x80
#define OPA_SMP_CLASS_VERSION 0x80
/* Management classes */ /* Management classes */
#define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01 #define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01
@ -135,6 +138,10 @@ enum {
IB_MGMT_SA_DATA = 200, IB_MGMT_SA_DATA = 200,
IB_MGMT_DEVICE_HDR = 64, IB_MGMT_DEVICE_HDR = 64,
IB_MGMT_DEVICE_DATA = 192, IB_MGMT_DEVICE_DATA = 192,
IB_MGMT_MAD_SIZE = IB_MGMT_MAD_HDR + IB_MGMT_MAD_DATA,
OPA_MGMT_MAD_DATA = 2024,
OPA_MGMT_RMPP_DATA = 2012,
OPA_MGMT_MAD_SIZE = IB_MGMT_MAD_HDR + OPA_MGMT_MAD_DATA,
}; };
struct ib_mad_hdr { struct ib_mad_hdr {
@ -181,12 +188,23 @@ struct ib_mad {
u8 data[IB_MGMT_MAD_DATA]; u8 data[IB_MGMT_MAD_DATA];
}; };
struct opa_mad {
struct ib_mad_hdr mad_hdr;
u8 data[OPA_MGMT_MAD_DATA];
};
struct ib_rmpp_mad { struct ib_rmpp_mad {
struct ib_mad_hdr mad_hdr; struct ib_mad_hdr mad_hdr;
struct ib_rmpp_hdr rmpp_hdr; struct ib_rmpp_hdr rmpp_hdr;
u8 data[IB_MGMT_RMPP_DATA]; u8 data[IB_MGMT_RMPP_DATA];
}; };
struct opa_rmpp_mad {
struct ib_mad_hdr mad_hdr;
struct ib_rmpp_hdr rmpp_hdr;
u8 data[OPA_MGMT_RMPP_DATA];
};
struct ib_sa_mad { struct ib_sa_mad {
struct ib_mad_hdr mad_hdr; struct ib_mad_hdr mad_hdr;
struct ib_rmpp_hdr rmpp_hdr; struct ib_rmpp_hdr rmpp_hdr;
@ -235,7 +253,10 @@ struct ib_class_port_info {
* includes the common MAD, RMPP, and class specific headers. * includes the common MAD, RMPP, and class specific headers.
* @data_len: Indicates the total size of user-transferred data. * @data_len: Indicates the total size of user-transferred data.
* @seg_count: The number of RMPP segments allocated for this send. * @seg_count: The number of RMPP segments allocated for this send.
* @seg_size: Size of each RMPP segment. * @seg_size: Size of the data in each RMPP segment. This does not include
* class specific headers.
* @seg_rmpp_size: Size of each RMPP segment including the class specific
* headers.
* @timeout_ms: Time to wait for a response. * @timeout_ms: Time to wait for a response.
* @retries: Number of times to retry a request for a response. For MADs * @retries: Number of times to retry a request for a response. For MADs
* using RMPP, this applies per window. On completion, returns the number * using RMPP, this applies per window. On completion, returns the number
@ -255,6 +276,7 @@ struct ib_mad_send_buf {
int data_len; int data_len;
int seg_count; int seg_count;
int seg_size; int seg_size;
int seg_rmpp_size;
int timeout_ms; int timeout_ms;
int retries; int retries;
}; };
@ -263,7 +285,7 @@ struct ib_mad_send_buf {
* ib_response_mad - Returns if the specified MAD has been generated in * ib_response_mad - Returns if the specified MAD has been generated in
* response to a sent request or trap. * response to a sent request or trap.
*/ */
int ib_response_mad(struct ib_mad *mad); int ib_response_mad(const struct ib_mad_hdr *hdr);
/** /**
* ib_get_rmpp_resptime - Returns the RMPP response time. * ib_get_rmpp_resptime - Returns the RMPP response time.
@ -401,7 +423,10 @@ struct ib_mad_send_wc {
struct ib_mad_recv_buf { struct ib_mad_recv_buf {
struct list_head list; struct list_head list;
struct ib_grh *grh; struct ib_grh *grh;
union {
struct ib_mad *mad; struct ib_mad *mad;
struct opa_mad *opa_mad;
};
}; };
/** /**
@ -410,6 +435,7 @@ struct ib_mad_recv_buf {
* @recv_buf: Specifies the location of the received data buffer(s). * @recv_buf: Specifies the location of the received data buffer(s).
* @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers. * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
* @mad_len: The length of the received MAD, without duplicated headers. * @mad_len: The length of the received MAD, without duplicated headers.
* @mad_seg_size: The size of individual MAD segments
* *
* For received response, the wr_id contains a pointer to the ib_mad_send_buf * For received response, the wr_id contains a pointer to the ib_mad_send_buf
* for the corresponding send request. * for the corresponding send request.
@ -419,6 +445,7 @@ struct ib_mad_recv_wc {
struct ib_mad_recv_buf recv_buf; struct ib_mad_recv_buf recv_buf;
struct list_head rmpp_list; struct list_head rmpp_list;
int mad_len; int mad_len;
size_t mad_seg_size;
}; };
/** /**
@ -618,6 +645,7 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
* automatically adjust the allocated buffer size to account for any * automatically adjust the allocated buffer size to account for any
* additional padding that may be necessary. * additional padding that may be necessary.
* @gfp_mask: GFP mask used for the memory allocation. * @gfp_mask: GFP mask used for the memory allocation.
* @base_version: Base Version of this MAD
* *
* This routine allocates a MAD for sending. The returned MAD send buffer * This routine allocates a MAD for sending. The returned MAD send buffer
* will reference a data buffer usable for sending a MAD, along * will reference a data buffer usable for sending a MAD, along
@ -633,7 +661,8 @@ struct ib_mad_send_buf *ib_create_send_mad(struct ib_mad_agent *mad_agent,
u32 remote_qpn, u16 pkey_index, u32 remote_qpn, u16 pkey_index,
int rmpp_active, int rmpp_active,
int hdr_len, int data_len, int hdr_len, int data_len,
gfp_t gfp_mask); gfp_t gfp_mask,
u8 base_version);
/** /**
* ib_is_mad_class_rmpp - returns whether given management class * ib_is_mad_class_rmpp - returns whether given management class
@ -675,6 +704,6 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf);
* @agent: the agent in question * @agent: the agent in question
* @return: true if agent is performing rmpp, false otherwise. * @return: true if agent is performing rmpp, false otherwise.
*/ */
int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent); int ib_mad_kernel_rmpp_agent(const struct ib_mad_agent *agent);
#endif /* IB_MAD_H */ #endif /* IB_MAD_H */

View file

@ -81,6 +81,13 @@ enum rdma_transport_type {
RDMA_TRANSPORT_USNIC_UDP RDMA_TRANSPORT_USNIC_UDP
}; };
enum rdma_protocol_type {
RDMA_PROTOCOL_IB,
RDMA_PROTOCOL_IBOE,
RDMA_PROTOCOL_IWARP,
RDMA_PROTOCOL_USNIC_UDP
};
__attribute_const__ enum rdma_transport_type __attribute_const__ enum rdma_transport_type
rdma_node_get_transport(enum rdma_node_type node_type); rdma_node_get_transport(enum rdma_node_type node_type);
@ -166,6 +173,16 @@ struct ib_odp_caps {
} per_transport_caps; } per_transport_caps;
}; };
enum ib_cq_creation_flags {
IB_CQ_FLAGS_TIMESTAMP_COMPLETION = 1 << 0,
};
struct ib_cq_init_attr {
unsigned int cqe;
int comp_vector;
u32 flags;
};
struct ib_device_attr { struct ib_device_attr {
u64 fw_ver; u64 fw_ver;
__be64 sys_image_guid; __be64 sys_image_guid;
@ -210,6 +227,8 @@ struct ib_device_attr {
int sig_prot_cap; int sig_prot_cap;
int sig_guard_cap; int sig_guard_cap;
struct ib_odp_caps odp_caps; struct ib_odp_caps odp_caps;
uint64_t timestamp_mask;
uint64_t hca_core_clock; /* in KHZ */
}; };
enum ib_mtu { enum ib_mtu {
@ -346,6 +365,42 @@ union rdma_protocol_stats {
struct iw_protocol_stats iw; struct iw_protocol_stats iw;
}; };
/* Define bits for the various functionality this port needs to be supported by
* the core.
*/
/* Management 0x00000FFF */
#define RDMA_CORE_CAP_IB_MAD 0x00000001
#define RDMA_CORE_CAP_IB_SMI 0x00000002
#define RDMA_CORE_CAP_IB_CM 0x00000004
#define RDMA_CORE_CAP_IW_CM 0x00000008
#define RDMA_CORE_CAP_IB_SA 0x00000010
#define RDMA_CORE_CAP_OPA_MAD 0x00000020
/* Address format 0x000FF000 */
#define RDMA_CORE_CAP_AF_IB 0x00001000
#define RDMA_CORE_CAP_ETH_AH 0x00002000
/* Protocol 0xFFF00000 */
#define RDMA_CORE_CAP_PROT_IB 0x00100000
#define RDMA_CORE_CAP_PROT_ROCE 0x00200000
#define RDMA_CORE_CAP_PROT_IWARP 0x00400000
#define RDMA_CORE_PORT_IBA_IB (RDMA_CORE_CAP_PROT_IB \
| RDMA_CORE_CAP_IB_MAD \
| RDMA_CORE_CAP_IB_SMI \
| RDMA_CORE_CAP_IB_CM \
| RDMA_CORE_CAP_IB_SA \
| RDMA_CORE_CAP_AF_IB)
#define RDMA_CORE_PORT_IBA_ROCE (RDMA_CORE_CAP_PROT_ROCE \
| RDMA_CORE_CAP_IB_MAD \
| RDMA_CORE_CAP_IB_CM \
| RDMA_CORE_CAP_AF_IB \
| RDMA_CORE_CAP_ETH_AH)
#define RDMA_CORE_PORT_IWARP (RDMA_CORE_CAP_PROT_IWARP \
| RDMA_CORE_CAP_IW_CM)
#define RDMA_CORE_PORT_INTEL_OPA (RDMA_CORE_PORT_IBA_IB \
| RDMA_CORE_CAP_OPA_MAD)
struct ib_port_attr { struct ib_port_attr {
enum ib_port_state state; enum ib_port_state state;
enum ib_mtu max_mtu; enum ib_mtu max_mtu;
@ -412,6 +467,8 @@ enum ib_event_type {
IB_EVENT_GID_CHANGE, IB_EVENT_GID_CHANGE,
}; };
__attribute_const__ const char *ib_event_msg(enum ib_event_type event);
struct ib_event { struct ib_event {
struct ib_device *device; struct ib_device *device;
union { union {
@ -663,6 +720,8 @@ enum ib_wc_status {
IB_WC_GENERAL_ERR IB_WC_GENERAL_ERR
}; };
__attribute_const__ const char *ib_wc_status_msg(enum ib_wc_status status);
enum ib_wc_opcode { enum ib_wc_opcode {
IB_WC_SEND, IB_WC_SEND,
IB_WC_RDMA_WRITE, IB_WC_RDMA_WRITE,
@ -1407,7 +1466,7 @@ struct ib_flow {
struct ib_uobject *uobject; struct ib_uobject *uobject;
}; };
struct ib_mad; struct ib_mad_hdr;
struct ib_grh; struct ib_grh;
enum ib_process_mad_flags { enum ib_process_mad_flags {
@ -1474,6 +1533,13 @@ struct ib_dma_mapping_ops {
struct iw_cm_verbs; struct iw_cm_verbs;
struct ib_port_immutable {
int pkey_tbl_len;
int gid_tbl_len;
u32 core_cap_flags;
u32 max_mad_size;
};
struct ib_device { struct ib_device {
struct device *dma_device; struct device *dma_device;
@ -1487,8 +1553,10 @@ struct ib_device {
struct list_head client_data_list; struct list_head client_data_list;
struct ib_cache cache; struct ib_cache cache;
int *pkey_tbl_len; /**
int *gid_tbl_len; * port_immutable is indexed by port number
*/
struct ib_port_immutable *port_immutable;
int num_comp_vectors; int num_comp_vectors;
@ -1497,7 +1565,8 @@ struct ib_device {
int (*get_protocol_stats)(struct ib_device *device, int (*get_protocol_stats)(struct ib_device *device,
union rdma_protocol_stats *stats); union rdma_protocol_stats *stats);
int (*query_device)(struct ib_device *device, int (*query_device)(struct ib_device *device,
struct ib_device_attr *device_attr); struct ib_device_attr *device_attr,
struct ib_udata *udata);
int (*query_port)(struct ib_device *device, int (*query_port)(struct ib_device *device,
u8 port_num, u8 port_num,
struct ib_port_attr *port_attr); struct ib_port_attr *port_attr);
@ -1561,8 +1630,8 @@ struct ib_device {
int (*post_recv)(struct ib_qp *qp, int (*post_recv)(struct ib_qp *qp,
struct ib_recv_wr *recv_wr, struct ib_recv_wr *recv_wr,
struct ib_recv_wr **bad_recv_wr); struct ib_recv_wr **bad_recv_wr);
struct ib_cq * (*create_cq)(struct ib_device *device, int cqe, struct ib_cq * (*create_cq)(struct ib_device *device,
int comp_vector, const struct ib_cq_init_attr *attr,
struct ib_ucontext *context, struct ib_ucontext *context,
struct ib_udata *udata); struct ib_udata *udata);
int (*modify_cq)(struct ib_cq *cq, u16 cq_count, int (*modify_cq)(struct ib_cq *cq, u16 cq_count,
@ -1637,10 +1706,13 @@ struct ib_device {
int (*process_mad)(struct ib_device *device, int (*process_mad)(struct ib_device *device,
int process_mad_flags, int process_mad_flags,
u8 port_num, u8 port_num,
struct ib_wc *in_wc, const struct ib_wc *in_wc,
struct ib_grh *in_grh, const struct ib_grh *in_grh,
struct ib_mad *in_mad, const struct ib_mad_hdr *in_mad,
struct ib_mad *out_mad); size_t in_mad_size,
struct ib_mad_hdr *out_mad,
size_t *out_mad_size,
u16 *out_mad_pkey_index);
struct ib_xrcd * (*alloc_xrcd)(struct ib_device *device, struct ib_xrcd * (*alloc_xrcd)(struct ib_device *device,
struct ib_ucontext *ucontext, struct ib_ucontext *ucontext,
struct ib_udata *udata); struct ib_udata *udata);
@ -1675,6 +1747,14 @@ struct ib_device {
u32 local_dma_lkey; u32 local_dma_lkey;
u8 node_type; u8 node_type;
u8 phys_port_cnt; u8 phys_port_cnt;
/**
* The following mandatory functions are used only at device
* registration. Keep functions such as these at the end of this
* structure to avoid cache line misses when accessing struct ib_device
* in fast paths.
*/
int (*get_port_immutable)(struct ib_device *, u8, struct ib_port_immutable *);
}; };
struct ib_client { struct ib_client {
@ -1743,6 +1823,284 @@ int ib_query_port(struct ib_device *device,
enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device,
u8 port_num); u8 port_num);
/**
* rdma_start_port - Return the first valid port number for the device
* specified
*
* @device: Device to be checked
*
* Return start port number
*/
static inline u8 rdma_start_port(const struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
}
/**
* rdma_end_port - Return the last valid port number for the device
* specified
*
* @device: Device to be checked
*
* Return last port number
*/
static inline u8 rdma_end_port(const struct ib_device *device)
{
return (device->node_type == RDMA_NODE_IB_SWITCH) ?
0 : device->phys_port_cnt;
}
static inline bool rdma_protocol_ib(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IB;
}
static inline bool rdma_protocol_roce(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_ROCE;
}
static inline bool rdma_protocol_iwarp(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IWARP;
}
static inline bool rdma_ib_or_roce(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags &
(RDMA_CORE_CAP_PROT_IB | RDMA_CORE_CAP_PROT_ROCE);
}
/**
* rdma_cap_ib_mad - Check if the port of a device supports Infiniband
* Management Datagrams.
* @device: Device to check
* @port_num: Port number to check
*
* Management Datagrams (MAD) are a required part of the InfiniBand
* specification and are supported on all InfiniBand devices. A slightly
* extended version are also supported on OPA interfaces.
*
* Return: true if the port supports sending/receiving of MAD packets.
*/
static inline bool rdma_cap_ib_mad(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_MAD;
}
/**
* rdma_cap_opa_mad - Check if the port of device provides support for OPA
* Management Datagrams.
* @device: Device to check
* @port_num: Port number to check
*
* Intel OmniPath devices extend and/or replace the InfiniBand Management
* datagrams with their own versions. These OPA MADs share many but not all of
* the characteristics of InfiniBand MADs.
*
* OPA MADs differ in the following ways:
*
* 1) MADs are variable size up to 2K
* IBTA defined MADs remain fixed at 256 bytes
* 2) OPA SMPs must carry valid PKeys
* 3) OPA SMP packets are a different format
*
* Return: true if the port supports OPA MAD packet formats.
*/
static inline bool rdma_cap_opa_mad(struct ib_device *device, u8 port_num)
{
return (device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_OPA_MAD)
== RDMA_CORE_CAP_OPA_MAD;
}
/**
* rdma_cap_ib_smi - Check if the port of a device provides an Infiniband
* Subnet Management Agent (SMA) on the Subnet Management Interface (SMI).
* @device: Device to check
* @port_num: Port number to check
*
* Each InfiniBand node is required to provide a Subnet Management Agent
* that the subnet manager can access. Prior to the fabric being fully
* configured by the subnet manager, the SMA is accessed via a well known
* interface called the Subnet Management Interface (SMI). This interface
* uses directed route packets to communicate with the SM to get around the
* chicken and egg problem of the SM needing to know what's on the fabric
* in order to configure the fabric, and needing to configure the fabric in
* order to send packets to the devices on the fabric. These directed
* route packets do not need the fabric fully configured in order to reach
* their destination. The SMI is the only method allowed to send
* directed route packets on an InfiniBand fabric.
*
* Return: true if the port provides an SMI.
*/
static inline bool rdma_cap_ib_smi(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_SMI;
}
/**
* rdma_cap_ib_cm - Check if the port of device has the capability Infiniband
* Communication Manager.
* @device: Device to check
* @port_num: Port number to check
*
* The InfiniBand Communication Manager is one of many pre-defined General
* Service Agents (GSA) that are accessed via the General Service
* Interface (GSI). It's role is to facilitate establishment of connections
* between nodes as well as other management related tasks for established
* connections.
*
* Return: true if the port supports an IB CM (this does not guarantee that
* a CM is actually running however).
*/
static inline bool rdma_cap_ib_cm(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_CM;
}
/**
* rdma_cap_iw_cm - Check if the port of device has the capability IWARP
* Communication Manager.
* @device: Device to check
* @port_num: Port number to check
*
* Similar to above, but specific to iWARP connections which have a different
* managment protocol than InfiniBand.
*
* Return: true if the port supports an iWARP CM (this does not guarantee that
* a CM is actually running however).
*/
static inline bool rdma_cap_iw_cm(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IW_CM;
}
/**
* rdma_cap_ib_sa - Check if the port of device has the capability Infiniband
* Subnet Administration.
* @device: Device to check
* @port_num: Port number to check
*
* An InfiniBand Subnet Administration (SA) service is a pre-defined General
* Service Agent (GSA) provided by the Subnet Manager (SM). On InfiniBand
* fabrics, devices should resolve routes to other hosts by contacting the
* SA to query the proper route.
*
* Return: true if the port should act as a client to the fabric Subnet
* Administration interface. This does not imply that the SA service is
* running locally.
*/
static inline bool rdma_cap_ib_sa(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_SA;
}
/**
* rdma_cap_ib_mcast - Check if the port of device has the capability Infiniband
* Multicast.
* @device: Device to check
* @port_num: Port number to check
*
* InfiniBand multicast registration is more complex than normal IPv4 or
* IPv6 multicast registration. Each Host Channel Adapter must register
* with the Subnet Manager when it wishes to join a multicast group. It
* should do so only once regardless of how many queue pairs it subscribes
* to this group. And it should leave the group only after all queue pairs
* attached to the group have been detached.
*
* Return: true if the port must undertake the additional adminstrative
* overhead of registering/unregistering with the SM and tracking of the
* total number of queue pairs attached to the multicast group.
*/
static inline bool rdma_cap_ib_mcast(const struct ib_device *device, u8 port_num)
{
return rdma_cap_ib_sa(device, port_num);
}
/**
* rdma_cap_af_ib - Check if the port of device has the capability
* Native Infiniband Address.
* @device: Device to check
* @port_num: Port number to check
*
* InfiniBand addressing uses a port's GUID + Subnet Prefix to make a default
* GID. RoCE uses a different mechanism, but still generates a GID via
* a prescribed mechanism and port specific data.
*
* Return: true if the port uses a GID address to identify devices on the
* network.
*/
static inline bool rdma_cap_af_ib(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_AF_IB;
}
/**
* rdma_cap_eth_ah - Check if the port of device has the capability
* Ethernet Address Handle.
* @device: Device to check
* @port_num: Port number to check
*
* RoCE is InfiniBand over Ethernet, and it uses a well defined technique
* to fabricate GIDs over Ethernet/IP specific addresses native to the
* port. Normally, packet headers are generated by the sending host
* adapter, but when sending connectionless datagrams, we must manually
* inject the proper headers for the fabric we are communicating over.
*
* Return: true if we are running as a RoCE port and must force the
* addition of a Global Route Header built from our Ethernet Address
* Handle into our header list for connectionless packets.
*/
static inline bool rdma_cap_eth_ah(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_ETH_AH;
}
/**
* rdma_cap_read_multi_sge - Check if the port of device has the capability
* RDMA Read Multiple Scatter-Gather Entries.
* @device: Device to check
* @port_num: Port number to check
*
* iWARP has a restriction that RDMA READ requests may only have a single
* Scatter/Gather Entry (SGE) in the work request.
*
* NOTE: although the linux kernel currently assumes all devices are either
* single SGE RDMA READ devices or identical SGE maximums for RDMA READs and
* WRITEs, according to Tom Talpey, this is not accurate. There are some
* devices out there that support more than a single SGE on RDMA READ
* requests, but do not support the same number of SGEs as they do on
* RDMA WRITE requests. The linux kernel would need rearchitecting to
* support these imbalanced READ/WRITE SGEs allowed devices. So, for now,
* suffice with either the device supports the same READ/WRITE SGEs, or
* it only gets one READ sge.
*
* Return: true for any device that allows more than one SGE in RDMA READ
* requests.
*/
static inline bool rdma_cap_read_multi_sge(struct ib_device *device,
u8 port_num)
{
return !(device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IWARP);
}
/**
* rdma_max_mad_size - Return the max MAD size required by this RDMA Port.
*
* @device: Device
* @port_num: Port number
*
* This MAD size includes the MAD headers and MAD payload. No other headers
* are included.
*
* Return the max MAD size required by the Port. Will return 0 if the port
* does not support MADs
*/
static inline size_t rdma_max_mad_size(const struct ib_device *device, u8 port_num)
{
return device->port_immutable[port_num].max_mad_size;
}
int ib_query_gid(struct ib_device *device, int ib_query_gid(struct ib_device *device,
u8 port_num, int index, union ib_gid *gid); u8 port_num, int index, union ib_gid *gid);
@ -1799,8 +2157,9 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
* @ah_attr: Returned attributes that can be used when creating an address * @ah_attr: Returned attributes that can be used when creating an address
* handle for replying to the message. * handle for replying to the message.
*/ */
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
struct ib_grh *grh, struct ib_ah_attr *ah_attr); const struct ib_wc *wc, const struct ib_grh *grh,
struct ib_ah_attr *ah_attr);
/** /**
* ib_create_ah_from_wc - Creates an address handle associated with the * ib_create_ah_from_wc - Creates an address handle associated with the
@ -1814,8 +2173,8 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
* The address handle is used to reference a local or global destination * The address handle is used to reference a local or global destination
* in all UD QP post sends. * in all UD QP post sends.
*/ */
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
struct ib_grh *grh, u8 port_num); const struct ib_grh *grh, u8 port_num);
/** /**
* ib_modify_ah - Modifies the address vector associated with an address * ib_modify_ah - Modifies the address vector associated with an address
@ -2011,16 +2370,15 @@ static inline int ib_post_recv(struct ib_qp *qp,
* asynchronous event not associated with a completion occurs on the CQ. * asynchronous event not associated with a completion occurs on the CQ.
* @cq_context: Context associated with the CQ returned to the user via * @cq_context: Context associated with the CQ returned to the user via
* the associated completion and event handlers. * the associated completion and event handlers.
* @cqe: The minimum size of the CQ. * @cq_attr: The attributes the CQ should be created upon.
* @comp_vector - Completion vector used to signal completion events.
* Must be >= 0 and < context->num_comp_vectors.
* *
* Users can examine the cq structure to determine the actual CQ size. * Users can examine the cq structure to determine the actual CQ size.
*/ */
struct ib_cq *ib_create_cq(struct ib_device *device, struct ib_cq *ib_create_cq(struct ib_device *device,
ib_comp_handler comp_handler, ib_comp_handler comp_handler,
void (*event_handler)(struct ib_event *, void *), void (*event_handler)(struct ib_event *, void *),
void *cq_context, int cqe, int comp_vector); void *cq_context,
const struct ib_cq_init_attr *cq_attr);
/** /**
* ib_resize_cq - Modifies the capacity of the CQ. * ib_resize_cq - Modifies the capacity of the CQ.

View file

@ -91,6 +91,7 @@ struct iw_cm_id {
/* Used by provider to add and remove refs on IW cm_id */ /* Used by provider to add and remove refs on IW cm_id */
void (*add_ref)(struct iw_cm_id *); void (*add_ref)(struct iw_cm_id *);
void (*rem_ref)(struct iw_cm_id *); void (*rem_ref)(struct iw_cm_id *);
u8 tos;
}; };
struct iw_cm_conn_param { struct iw_cm_conn_param {

106
include/rdma/opa_smi.h Normal file
View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2014 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if !defined(OPA_SMI_H)
#define OPA_SMI_H
#include <rdma/ib_mad.h>
#include <rdma/ib_smi.h>
#define OPA_SMP_LID_DATA_SIZE 2016
#define OPA_SMP_DR_DATA_SIZE 1872
#define OPA_SMP_MAX_PATH_HOPS 64
#define OPA_SMI_CLASS_VERSION 0x80
#define OPA_LID_PERMISSIVE cpu_to_be32(0xFFFFFFFF)
struct opa_smp {
u8 base_version;
u8 mgmt_class;
u8 class_version;
u8 method;
__be16 status;
u8 hop_ptr;
u8 hop_cnt;
__be64 tid;
__be16 attr_id;
__be16 resv;
__be32 attr_mod;
__be64 mkey;
union {
struct {
uint8_t data[OPA_SMP_LID_DATA_SIZE];
} lid;
struct {
__be32 dr_slid;
__be32 dr_dlid;
u8 initial_path[OPA_SMP_MAX_PATH_HOPS];
u8 return_path[OPA_SMP_MAX_PATH_HOPS];
u8 reserved[8];
u8 data[OPA_SMP_DR_DATA_SIZE];
} dr;
} route;
} __packed;
static inline u8
opa_get_smp_direction(struct opa_smp *smp)
{
return ib_get_smp_direction((struct ib_smp *)smp);
}
static inline u8 *opa_get_smp_data(struct opa_smp *smp)
{
if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
return smp->route.dr.data;
return smp->route.lid.data;
}
static inline size_t opa_get_smp_data_size(struct opa_smp *smp)
{
if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
return sizeof(smp->route.dr.data);
return sizeof(smp->route.lid.data);
}
static inline size_t opa_get_smp_header_size(struct opa_smp *smp)
{
if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
return sizeof(*smp) - sizeof(smp->route.dr.data);
return sizeof(*smp) - sizeof(smp->route.lid.data);
}
#endif /* OPA_SMI_H */

View file

@ -62,6 +62,8 @@ enum rdma_cm_event_type {
RDMA_CM_EVENT_TIMEWAIT_EXIT RDMA_CM_EVENT_TIMEWAIT_EXIT
}; };
__attribute_const__ const char *rdma_event_msg(enum rdma_cm_event_type event);
enum rdma_port_space { enum rdma_port_space {
RDMA_PS_SDP = 0x0001, RDMA_PS_SDP = 0x0001,
RDMA_PS_IPOIB = 0x0002, RDMA_PS_IPOIB = 0x0002,

View file

@ -42,6 +42,7 @@
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <scsi/scsi.h>
enum { enum {
SRP_LOGIN_REQ = 0x00, SRP_LOGIN_REQ = 0x00,
@ -179,7 +180,7 @@ struct srp_tsk_mgmt {
u8 reserved1[6]; u8 reserved1[6];
u64 tag; u64 tag;
u8 reserved2[4]; u8 reserved2[4];
__be64 lun __attribute__((packed)); struct scsi_lun lun;
u8 reserved3[2]; u8 reserved3[2];
u8 tsk_mgmt_func; u8 tsk_mgmt_func;
u8 reserved4; u8 reserved4;
@ -200,7 +201,7 @@ struct srp_cmd {
u8 data_in_desc_cnt; u8 data_in_desc_cnt;
u64 tag; u64 tag;
u8 reserved2[4]; u8 reserved2[4];
__be64 lun __attribute__((packed)); struct scsi_lun lun;
u8 reserved3; u8 reserved3;
u8 task_attr; u8 task_attr;
u8 reserved4; u8 reserved4;
@ -265,7 +266,7 @@ struct srp_aer_req {
__be32 req_lim_delta; __be32 req_lim_delta;
u64 tag; u64 tag;
u32 reserved2; u32 reserved2;
__be64 lun; struct scsi_lun lun;
__be32 sense_data_len; __be32 sense_data_len;
u32 reserved3; u32 reserved3;
u8 sense_data[0]; u8 sense_data[0];

View file

@ -91,6 +91,7 @@ enum {
enum { enum {
IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE, IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE,
IB_USER_VERBS_EX_CMD_CREATE_CQ = IB_USER_VERBS_CMD_CREATE_CQ,
IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
IB_USER_VERBS_EX_CMD_DESTROY_FLOW, IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
}; };
@ -222,6 +223,8 @@ struct ib_uverbs_ex_query_device_resp {
__u32 comp_mask; __u32 comp_mask;
__u32 response_length; __u32 response_length;
struct ib_uverbs_odp_caps odp_caps; struct ib_uverbs_odp_caps odp_caps;
__u64 timestamp_mask;
__u64 hca_core_clock; /* in KHZ */
}; };
struct ib_uverbs_query_port { struct ib_uverbs_query_port {
@ -353,11 +356,27 @@ struct ib_uverbs_create_cq {
__u64 driver_data[0]; __u64 driver_data[0];
}; };
struct ib_uverbs_ex_create_cq {
__u64 user_handle;
__u32 cqe;
__u32 comp_vector;
__s32 comp_channel;
__u32 comp_mask;
__u32 flags;
__u32 reserved;
};
struct ib_uverbs_create_cq_resp { struct ib_uverbs_create_cq_resp {
__u32 cq_handle; __u32 cq_handle;
__u32 cqe; __u32 cqe;
}; };
struct ib_uverbs_ex_create_cq_resp {
struct ib_uverbs_create_cq_resp base;
__u32 comp_mask;
__u32 response_length;
};
struct ib_uverbs_resize_cq { struct ib_uverbs_resize_cq {
__u64 response; __u64 response;
__u32 cq_handle; __u32 cq_handle;

View file

@ -648,6 +648,7 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
struct rdma_conn_param conn_param; struct rdma_conn_param conn_param;
struct ib_qp_init_attr qp_attr; struct ib_qp_init_attr qp_attr;
struct ib_device_attr devattr; struct ib_device_attr devattr;
struct ib_cq_init_attr cq_attr = {};
/* Parse the transport specific mount options */ /* Parse the transport specific mount options */
err = parse_opts(args, &opts); err = parse_opts(args, &opts);
@ -705,9 +706,10 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
goto error; goto error;
/* Create the Completion Queue */ /* Create the Completion Queue */
cq_attr.cqe = opts.sq_depth + opts.rq_depth + 1;
rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler, rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler,
cq_event_handler, client, cq_event_handler, client,
opts.sq_depth + opts.rq_depth + 1, 0); &cq_attr);
if (IS_ERR(rdma->cq)) if (IS_ERR(rdma->cq))
goto error; goto error;
ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP);

View file

@ -40,15 +40,6 @@
#include "rds.h" #include "rds.h"
char *rds_str_array(char **array, size_t elements, size_t index)
{
if ((index < elements) && array[index])
return array[index];
else
return "unknown";
}
EXPORT_SYMBOL(rds_str_array);
/* this is just used for stats gathering :/ */ /* this is just used for stats gathering :/ */
static DEFINE_SPINLOCK(rds_sock_lock); static DEFINE_SPINLOCK(rds_sock_lock);
static unsigned long rds_sock_count; static unsigned long rds_sock_count;

Some files were not shown because too many files have changed in this diff Show more