mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma updates from Jason Gunthorpe:
"A quiet cycle after the larger 5.8 effort. Substantially cleanup and
driver work with a few smaller features this time.
- Driver updates for hfi1, rxe, mlx5, hns, qedr, usnic, bnxt_re
- Removal of dead or redundant code across the drivers
- RAW resource tracker dumps to include a device specific data blob
for device objects to aide device debugging
- Further advance the IOCTL interface, remove the ability to turn it
off. Add QUERY_CONTEXT, QUERY_MR, and QUERY_PD commands
- Remove stubs related to devices with no pkey table
- A shared CQ scheme to allow multiple ULPs to share the CQ rings of
a device to give higher performance
- Several more static checker, syzkaller and rare crashers fixed"
* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (121 commits)
RDMA/mlx5: Fix flow destination setting for RDMA TX flow table
RDMA/rxe: Remove pkey table
RDMA/umem: Add a schedule point in ib_umem_get()
RDMA/hns: Fix the unneeded process when getting a general type of CQE error
RDMA/hns: Fix error during modify qp RTS2RTS
RDMA/hns: Delete unnecessary memset when allocating VF resource
RDMA/hns: Remove redundant parameters in set_rc_wqe()
RDMA/hns: Remove support for HIP08_A
RDMA/hns: Refactor hns_roce_v2_set_hem()
RDMA/hns: Remove redundant hardware opcode definitions
RDMA/netlink: Remove CAP_NET_RAW check when dump a raw QP
RDMA/include: Replace license text with SPDX tags
RDMA/rtrs: remove WQ_MEM_RECLAIM for rtrs_wq
RDMA/rtrs-clt: add an additional random 8 seconds before reconnecting
RDMA/cma: Execute rdma_cm destruction from a handler properly
RDMA/cma: Remove unneeded locking for req paths
RDMA/cma: Using the standard locking pattern when delivering the removal event
RDMA/cma: Simplify DEVICE_REMOVAL for internal_id
RDMA/efa: Add EFA 0xefa1 PCI ID
RDMA/efa: User/kernel compatibility handshake mechanism
...
This commit is contained in:
@@ -3621,6 +3621,7 @@ M: Selvin Xavier <selvin.xavier@broadcom.com>
|
||||
M: Devesh Sharma <devesh.sharma@broadcom.com>
|
||||
M: Somnath Kotur <somnath.kotur@broadcom.com>
|
||||
M: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
|
||||
M: Naresh Kumar PBS <nareshkumar.pbs@broadcom.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.broadcom.com
|
||||
|
||||
@@ -37,14 +37,6 @@ config INFINIBAND_USER_ACCESS
|
||||
libibverbs, libibcm and a hardware driver library from
|
||||
rdma-core <https://github.com/linux-rdma/rdma-core>.
|
||||
|
||||
config INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI
|
||||
bool "Allow experimental legacy verbs in new ioctl uAPI (EXPERIMENTAL)"
|
||||
depends on INFINIBAND_USER_ACCESS
|
||||
help
|
||||
IOCTL based uAPI support for Infiniband is enabled by default for
|
||||
new verbs only. This allows userspace to invoke the IOCTL based uAPI
|
||||
for current legacy verbs too.
|
||||
|
||||
config INFINIBAND_USER_MEM
|
||||
bool
|
||||
depends on INFINIBAND_USER_ACCESS != n
|
||||
|
||||
@@ -1054,7 +1054,7 @@ int ib_get_cached_pkey(struct ib_device *device,
|
||||
|
||||
cache = device->port_data[port_num].cache.pkey;
|
||||
|
||||
if (index < 0 || index >= cache->table_len)
|
||||
if (!cache || index < 0 || index >= cache->table_len)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
*pkey = cache->table[index];
|
||||
@@ -1099,6 +1099,10 @@ int ib_find_cached_pkey(struct ib_device *device,
|
||||
read_lock_irqsave(&device->cache_lock, flags);
|
||||
|
||||
cache = device->port_data[port_num].cache.pkey;
|
||||
if (!cache) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*index = -1;
|
||||
|
||||
@@ -1117,6 +1121,7 @@ int ib_find_cached_pkey(struct ib_device *device,
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
err:
|
||||
read_unlock_irqrestore(&device->cache_lock, flags);
|
||||
|
||||
return ret;
|
||||
@@ -1139,6 +1144,10 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
|
||||
read_lock_irqsave(&device->cache_lock, flags);
|
||||
|
||||
cache = device->port_data[port_num].cache.pkey;
|
||||
if (!cache) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*index = -1;
|
||||
|
||||
@@ -1149,6 +1158,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
read_unlock_irqrestore(&device->cache_lock, flags);
|
||||
|
||||
return ret;
|
||||
@@ -1425,24 +1435,27 @@ ib_cache_update(struct ib_device *device, u8 port, bool enforce_security)
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_cache = kmalloc(struct_size(pkey_cache, table,
|
||||
tprops->pkey_tbl_len),
|
||||
GFP_KERNEL);
|
||||
if (!pkey_cache) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_cache->table_len = tprops->pkey_tbl_len;
|
||||
|
||||
for (i = 0; i < pkey_cache->table_len; ++i) {
|
||||
ret = ib_query_pkey(device, port, i, pkey_cache->table + i);
|
||||
if (ret) {
|
||||
dev_warn(&device->dev,
|
||||
"ib_query_pkey failed (%d) for index %d\n",
|
||||
ret, i);
|
||||
if (tprops->pkey_tbl_len) {
|
||||
pkey_cache = kmalloc(struct_size(pkey_cache, table,
|
||||
tprops->pkey_tbl_len),
|
||||
GFP_KERNEL);
|
||||
if (!pkey_cache) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_cache->table_len = tprops->pkey_tbl_len;
|
||||
|
||||
for (i = 0; i < pkey_cache->table_len; ++i) {
|
||||
ret = ib_query_pkey(device, port, i,
|
||||
pkey_cache->table + i);
|
||||
if (ret) {
|
||||
dev_warn(&device->dev,
|
||||
"ib_query_pkey failed (%d) for index %d\n",
|
||||
ret, i);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_lock_irq(&device->cache_lock);
|
||||
|
||||
@@ -428,19 +428,6 @@ static int cma_comp_exch(struct rdma_id_private *id_priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum rdma_cm_state cma_exch(struct rdma_id_private *id_priv,
|
||||
enum rdma_cm_state exch)
|
||||
{
|
||||
unsigned long flags;
|
||||
enum rdma_cm_state old;
|
||||
|
||||
spin_lock_irqsave(&id_priv->lock, flags);
|
||||
old = id_priv->state;
|
||||
id_priv->state = exch;
|
||||
spin_unlock_irqrestore(&id_priv->lock, flags);
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline u8 cma_get_ip_ver(const struct cma_hdr *hdr)
|
||||
{
|
||||
return hdr->ip_version >> 4;
|
||||
@@ -1829,23 +1816,11 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
|
||||
}
|
||||
}
|
||||
|
||||
void rdma_destroy_id(struct rdma_cm_id *id)
|
||||
static void _destroy_id(struct rdma_id_private *id_priv,
|
||||
enum rdma_cm_state state)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
enum rdma_cm_state state;
|
||||
|
||||
id_priv = container_of(id, struct rdma_id_private, id);
|
||||
trace_cm_id_destroy(id_priv);
|
||||
state = cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
cma_cancel_operation(id_priv, state);
|
||||
|
||||
/*
|
||||
* Wait for any active callback to finish. New callbacks will find
|
||||
* the id_priv state set to destroying and abort.
|
||||
*/
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
|
||||
rdma_restrack_del(&id_priv->res);
|
||||
if (id_priv->cma_dev) {
|
||||
if (rdma_cap_ib_cm(id_priv->id.device, 1)) {
|
||||
@@ -1874,6 +1849,42 @@ void rdma_destroy_id(struct rdma_cm_id *id)
|
||||
put_net(id_priv->id.route.addr.dev_addr.net);
|
||||
kfree(id_priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* destroy an ID from within the handler_mutex. This ensures that no other
|
||||
* handlers can start running concurrently.
|
||||
*/
|
||||
static void destroy_id_handler_unlock(struct rdma_id_private *id_priv)
|
||||
__releases(&idprv->handler_mutex)
|
||||
{
|
||||
enum rdma_cm_state state;
|
||||
unsigned long flags;
|
||||
|
||||
trace_cm_id_destroy(id_priv);
|
||||
|
||||
/*
|
||||
* Setting the state to destroyed under the handler mutex provides a
|
||||
* fence against calling handler callbacks. If this is invoked due to
|
||||
* the failure of a handler callback then it guarentees that no future
|
||||
* handlers will be called.
|
||||
*/
|
||||
lockdep_assert_held(&id_priv->handler_mutex);
|
||||
spin_lock_irqsave(&id_priv->lock, flags);
|
||||
state = id_priv->state;
|
||||
id_priv->state = RDMA_CM_DESTROYING;
|
||||
spin_unlock_irqrestore(&id_priv->lock, flags);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
_destroy_id(id_priv, state);
|
||||
}
|
||||
|
||||
void rdma_destroy_id(struct rdma_cm_id *id)
|
||||
{
|
||||
struct rdma_id_private *id_priv =
|
||||
container_of(id, struct rdma_id_private, id);
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_destroy_id);
|
||||
|
||||
static int cma_rep_recv(struct rdma_id_private *id_priv)
|
||||
@@ -1925,6 +1936,8 @@ static int cma_cm_event_handler(struct rdma_id_private *id_priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&id_priv->handler_mutex);
|
||||
|
||||
trace_cm_event_handler(id_priv, event);
|
||||
ret = id_priv->id.event_handler(&id_priv->id, event);
|
||||
trace_cm_event_done(id_priv, event, ret);
|
||||
@@ -1936,7 +1949,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id,
|
||||
{
|
||||
struct rdma_id_private *id_priv = cm_id->context;
|
||||
struct rdma_cm_event event = {};
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
|
||||
@@ -2005,14 +2018,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id,
|
||||
if (ret) {
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
id_priv->cm_id.ib = NULL;
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rdma_id_private *
|
||||
@@ -2174,7 +2185,7 @@ static int cma_ib_req_handler(struct ib_cm_id *cm_id,
|
||||
mutex_lock(&listen_id->handler_mutex);
|
||||
if (listen_id->state != RDMA_CM_LISTEN) {
|
||||
ret = -ECONNABORTED;
|
||||
goto err1;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
offset = cma_user_data_offset(listen_id);
|
||||
@@ -2191,55 +2202,38 @@ static int cma_ib_req_handler(struct ib_cm_id *cm_id,
|
||||
}
|
||||
if (!conn_id) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
|
||||
ret = cma_ib_acquire_dev(conn_id, listen_id, &req);
|
||||
if (ret)
|
||||
goto err2;
|
||||
if (ret) {
|
||||
destroy_id_handler_unlock(conn_id);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
conn_id->cm_id.ib = cm_id;
|
||||
cm_id->context = conn_id;
|
||||
cm_id->cm_handler = cma_ib_handler;
|
||||
|
||||
/*
|
||||
* Protect against the user destroying conn_id from another thread
|
||||
* until we're done accessing it.
|
||||
*/
|
||||
cma_id_get(conn_id);
|
||||
ret = cma_cm_event_handler(conn_id, &event);
|
||||
if (ret)
|
||||
goto err3;
|
||||
/*
|
||||
* Acquire mutex to prevent user executing rdma_destroy_id()
|
||||
* while we're accessing the cm_id.
|
||||
*/
|
||||
mutex_lock(&lock);
|
||||
if (ret) {
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
conn_id->cm_id.ib = NULL;
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
destroy_id_handler_unlock(conn_id);
|
||||
goto net_dev_put;
|
||||
}
|
||||
|
||||
if (cma_comp(conn_id, RDMA_CM_CONNECT) &&
|
||||
(conn_id->id.qp_type != IB_QPT_UD)) {
|
||||
trace_cm_send_mra(cm_id->context);
|
||||
ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
|
||||
}
|
||||
mutex_unlock(&lock);
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
cma_id_put(conn_id);
|
||||
if (net_dev)
|
||||
dev_put(net_dev);
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
cma_id_put(conn_id);
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
conn_id->cm_id.ib = NULL;
|
||||
err2:
|
||||
cma_exch(conn_id, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
err1:
|
||||
err_unlock:
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
if (conn_id)
|
||||
rdma_destroy_id(&conn_id->id);
|
||||
|
||||
net_dev_put:
|
||||
if (net_dev)
|
||||
@@ -2339,9 +2333,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
|
||||
if (ret) {
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
id_priv->cm_id.iw = NULL;
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2388,16 +2380,16 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
|
||||
|
||||
ret = rdma_translate_ip(laddr, &conn_id->id.route.addr.dev_addr);
|
||||
if (ret) {
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
rdma_destroy_id(new_cm_id);
|
||||
goto out;
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
destroy_id_handler_unlock(conn_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cma_iw_acquire_dev(conn_id, listen_id);
|
||||
if (ret) {
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
rdma_destroy_id(new_cm_id);
|
||||
goto out;
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
destroy_id_handler_unlock(conn_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
conn_id->cm_id.iw = cm_id;
|
||||
@@ -2407,25 +2399,16 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
|
||||
memcpy(cma_src_addr(conn_id), laddr, rdma_addr_size(laddr));
|
||||
memcpy(cma_dst_addr(conn_id), raddr, rdma_addr_size(raddr));
|
||||
|
||||
/*
|
||||
* Protect against the user destroying conn_id from another thread
|
||||
* until we're done accessing it.
|
||||
*/
|
||||
cma_id_get(conn_id);
|
||||
ret = cma_cm_event_handler(conn_id, &event);
|
||||
if (ret) {
|
||||
/* User wants to destroy the CM ID */
|
||||
conn_id->cm_id.iw = NULL;
|
||||
cma_exch(conn_id, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
cma_id_put(conn_id);
|
||||
rdma_destroy_id(&conn_id->id);
|
||||
destroy_id_handler_unlock(conn_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&conn_id->handler_mutex);
|
||||
cma_id_put(conn_id);
|
||||
|
||||
out:
|
||||
mutex_unlock(&listen_id->handler_mutex);
|
||||
@@ -2482,6 +2465,10 @@ static int cma_listen_handler(struct rdma_cm_id *id,
|
||||
{
|
||||
struct rdma_id_private *id_priv = id->context;
|
||||
|
||||
/* Listening IDs are always destroyed on removal */
|
||||
if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
|
||||
return -1;
|
||||
|
||||
id->context = id_priv->id.context;
|
||||
id->event_handler = id_priv->id.event_handler;
|
||||
trace_cm_event_handler(id_priv, event);
|
||||
@@ -2657,21 +2644,21 @@ static void cma_work_handler(struct work_struct *_work)
|
||||
{
|
||||
struct cma_work *work = container_of(_work, struct cma_work, work);
|
||||
struct rdma_id_private *id_priv = work->id;
|
||||
int destroy = 0;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
|
||||
if (cma_cm_event_handler(id_priv, &work->event)) {
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
destroy = 1;
|
||||
cma_id_put(id_priv);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
goto out_free;
|
||||
}
|
||||
out:
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
cma_id_put(id_priv);
|
||||
if (destroy)
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
out_free:
|
||||
kfree(work);
|
||||
}
|
||||
|
||||
@@ -2679,23 +2666,22 @@ static void cma_ndev_work_handler(struct work_struct *_work)
|
||||
{
|
||||
struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
|
||||
struct rdma_id_private *id_priv = work->id;
|
||||
int destroy = 0;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if (id_priv->state == RDMA_CM_DESTROYING ||
|
||||
id_priv->state == RDMA_CM_DEVICE_REMOVAL)
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
|
||||
if (cma_cm_event_handler(id_priv, &work->event)) {
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
destroy = 1;
|
||||
cma_id_put(id_priv);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out:
|
||||
out_unlock:
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
cma_id_put(id_priv);
|
||||
if (destroy)
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
out_free:
|
||||
kfree(work);
|
||||
}
|
||||
|
||||
@@ -3171,9 +3157,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
|
||||
event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
|
||||
|
||||
if (cma_cm_event_handler(id_priv, &event)) {
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
return;
|
||||
}
|
||||
out:
|
||||
@@ -3790,7 +3774,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
|
||||
struct rdma_cm_event event = {};
|
||||
const struct ib_cm_sidr_rep_event_param *rep =
|
||||
&ib_event->param.sidr_rep_rcvd;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if (id_priv->state != RDMA_CM_CONNECT)
|
||||
@@ -3840,14 +3824,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
|
||||
if (ret) {
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
id_priv->cm_id.ib = NULL;
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
|
||||
@@ -4372,9 +4354,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
|
||||
|
||||
rdma_destroy_ah_attr(&event.param.ud.ah_attr);
|
||||
if (ret) {
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
destroy_id_handler_unlock(id_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4789,50 +4769,59 @@ free_cma_dev:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
|
||||
static void cma_send_device_removal_put(struct rdma_id_private *id_priv)
|
||||
{
|
||||
struct rdma_cm_event event = {};
|
||||
struct rdma_cm_event event = { .event = RDMA_CM_EVENT_DEVICE_REMOVAL };
|
||||
enum rdma_cm_state state;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* Record that we want to remove the device */
|
||||
state = cma_exch(id_priv, RDMA_CM_DEVICE_REMOVAL);
|
||||
if (state == RDMA_CM_DESTROYING)
|
||||
return 0;
|
||||
|
||||
cma_cancel_operation(id_priv, state);
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
/* Record that we want to remove the device */
|
||||
spin_lock_irqsave(&id_priv->lock, flags);
|
||||
state = id_priv->state;
|
||||
if (state == RDMA_CM_DESTROYING || state == RDMA_CM_DEVICE_REMOVAL) {
|
||||
spin_unlock_irqrestore(&id_priv->lock, flags);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
cma_id_put(id_priv);
|
||||
return;
|
||||
}
|
||||
id_priv->state = RDMA_CM_DEVICE_REMOVAL;
|
||||
spin_unlock_irqrestore(&id_priv->lock, flags);
|
||||
|
||||
/* Check for destruction from another callback. */
|
||||
if (!cma_comp(id_priv, RDMA_CM_DEVICE_REMOVAL))
|
||||
goto out;
|
||||
|
||||
event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
|
||||
ret = cma_cm_event_handler(id_priv, &event);
|
||||
out:
|
||||
if (cma_cm_event_handler(id_priv, &event)) {
|
||||
/*
|
||||
* At this point the ULP promises it won't call
|
||||
* rdma_destroy_id() concurrently
|
||||
*/
|
||||
cma_id_put(id_priv);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
trace_cm_id_destroy(id_priv);
|
||||
_destroy_id(id_priv, state);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If this races with destroy then the thread that first assigns state
|
||||
* to a destroying does the cancel.
|
||||
*/
|
||||
cma_cancel_operation(id_priv, state);
|
||||
cma_id_put(id_priv);
|
||||
}
|
||||
|
||||
static void cma_process_remove(struct cma_device *cma_dev)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&lock);
|
||||
while (!list_empty(&cma_dev->id_list)) {
|
||||
id_priv = list_entry(cma_dev->id_list.next,
|
||||
struct rdma_id_private, list);
|
||||
struct rdma_id_private *id_priv = list_first_entry(
|
||||
&cma_dev->id_list, struct rdma_id_private, list);
|
||||
|
||||
list_del(&id_priv->listen_list);
|
||||
list_del_init(&id_priv->list);
|
||||
cma_id_get(id_priv);
|
||||
mutex_unlock(&lock);
|
||||
|
||||
ret = id_priv->internal_id ? 1 : cma_remove_id_dev(id_priv);
|
||||
cma_id_put(id_priv);
|
||||
if (ret)
|
||||
rdma_destroy_id(&id_priv->id);
|
||||
cma_send_device_removal_put(id_priv);
|
||||
|
||||
mutex_lock(&lock);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "core_priv.h"
|
||||
#include "restrack.h"
|
||||
|
||||
#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE)
|
||||
#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE | RDMA_COUNTER_MASK_PID)
|
||||
|
||||
static int __counter_set_mode(struct rdma_counter_mode *curr,
|
||||
enum rdma_nl_counter_mode new_mode,
|
||||
@@ -149,23 +149,13 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
|
||||
struct auto_mode_param *param = &counter->mode.param;
|
||||
bool match = true;
|
||||
|
||||
/*
|
||||
* Ensure that counter belongs to the right PID. This operation can
|
||||
* race with user space which kills the process and leaves QP and
|
||||
* counters orphans.
|
||||
*
|
||||
* It is not a big deal because exitted task will leave both QP and
|
||||
* counter in the same bucket of zombie process. Just ensure that
|
||||
* process is still alive before procedding.
|
||||
*
|
||||
*/
|
||||
if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task) ||
|
||||
!task_pid_nr(qp->res.task))
|
||||
return false;
|
||||
|
||||
if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
|
||||
match &= (param->qp_type == qp->qp_type);
|
||||
|
||||
if (auto_mask & RDMA_COUNTER_MASK_PID)
|
||||
match &= (task_pid_nr(counter->res.task) ==
|
||||
task_pid_nr(qp->res.task));
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -288,7 +278,7 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)
|
||||
struct rdma_counter *counter;
|
||||
int ret;
|
||||
|
||||
if (!qp->res.valid)
|
||||
if (!qp->res.valid || rdma_is_kernel_res(&qp->res))
|
||||
return 0;
|
||||
|
||||
if (!rdma_is_port_valid(dev, port))
|
||||
@@ -483,7 +473,7 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (counter->res.task != qp->res.task) {
|
||||
if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res)) {
|
||||
ret = -EINVAL;
|
||||
goto err_task;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,6 @@ static void ib_device_check_mandatory(struct ib_device *device)
|
||||
} mandatory_table[] = {
|
||||
IB_MANDATORY_FUNC(query_device),
|
||||
IB_MANDATORY_FUNC(query_port),
|
||||
IB_MANDATORY_FUNC(query_pkey),
|
||||
IB_MANDATORY_FUNC(alloc_pd),
|
||||
IB_MANDATORY_FUNC(dealloc_pd),
|
||||
IB_MANDATORY_FUNC(create_qp),
|
||||
@@ -1343,6 +1342,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prevent_dealloc_device(struct ib_device *ib_dev)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_register_device - Register an IB device with IB core
|
||||
* @device: Device to register
|
||||
@@ -1413,11 +1416,11 @@ int ib_register_device(struct ib_device *device, const char *name)
|
||||
* possibility for a parallel unregistration along with this
|
||||
* error flow. Since we have a refcount here we know any
|
||||
* parallel flow is stopped in disable_device and will see the
|
||||
* NULL pointers, causing the responsibility to
|
||||
* special dealloc_driver pointer, causing the responsibility to
|
||||
* ib_dealloc_device() to revert back to this thread.
|
||||
*/
|
||||
dealloc_fn = device->ops.dealloc_driver;
|
||||
device->ops.dealloc_driver = NULL;
|
||||
device->ops.dealloc_driver = prevent_dealloc_device;
|
||||
ib_device_put(device);
|
||||
__ib_unregister_device(device);
|
||||
device->ops.dealloc_driver = dealloc_fn;
|
||||
@@ -1466,7 +1469,8 @@ static void __ib_unregister_device(struct ib_device *ib_dev)
|
||||
* Drivers using the new flow may not call ib_dealloc_device except
|
||||
* in error unwind prior to registration success.
|
||||
*/
|
||||
if (ib_dev->ops.dealloc_driver) {
|
||||
if (ib_dev->ops.dealloc_driver &&
|
||||
ib_dev->ops.dealloc_driver != prevent_dealloc_device) {
|
||||
WARN_ON(kref_read(&ib_dev->dev.kobj.kref) <= 1);
|
||||
ib_dealloc_device(ib_dev);
|
||||
}
|
||||
@@ -2361,6 +2365,9 @@ int ib_query_pkey(struct ib_device *device,
|
||||
if (!rdma_is_port_valid(device, port_num))
|
||||
return -EINVAL;
|
||||
|
||||
if (!device->ops.query_pkey)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return device->ops.query_pkey(device, port_num, index, pkey);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_query_pkey);
|
||||
@@ -2621,8 +2628,14 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
|
||||
SET_DEVICE_OP(dev_ops, drain_rq);
|
||||
SET_DEVICE_OP(dev_ops, drain_sq);
|
||||
SET_DEVICE_OP(dev_ops, enable_driver);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_stat_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_cm_id_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_cq_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_cq_entry_raw);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_mr_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_mr_entry_raw);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_qp_entry);
|
||||
SET_DEVICE_OP(dev_ops, fill_res_qp_entry_raw);
|
||||
SET_DEVICE_OP(dev_ops, fill_stat_mr_entry);
|
||||
SET_DEVICE_OP(dev_ops, get_dev_fw_str);
|
||||
SET_DEVICE_OP(dev_ops, get_dma_mr);
|
||||
SET_DEVICE_OP(dev_ops, get_hw_stats);
|
||||
@@ -2667,6 +2680,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
|
||||
SET_DEVICE_OP(dev_ops, query_port);
|
||||
SET_DEVICE_OP(dev_ops, query_qp);
|
||||
SET_DEVICE_OP(dev_ops, query_srq);
|
||||
SET_DEVICE_OP(dev_ops, query_ucontext);
|
||||
SET_DEVICE_OP(dev_ops, rdma_netdev_get_params);
|
||||
SET_DEVICE_OP(dev_ops, read_counters);
|
||||
SET_DEVICE_OP(dev_ops, reg_dm_mr);
|
||||
@@ -2679,10 +2693,12 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
|
||||
SET_DEVICE_OP(dev_ops, set_vf_link_state);
|
||||
|
||||
SET_OBJ_SIZE(dev_ops, ib_ah);
|
||||
SET_OBJ_SIZE(dev_ops, ib_counters);
|
||||
SET_OBJ_SIZE(dev_ops, ib_cq);
|
||||
SET_OBJ_SIZE(dev_ops, ib_pd);
|
||||
SET_OBJ_SIZE(dev_ops, ib_srq);
|
||||
SET_OBJ_SIZE(dev_ops, ib_ucontext);
|
||||
SET_OBJ_SIZE(dev_ops, ib_xrcd);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_set_device_ops);
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
|
||||
INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends);
|
||||
INIT_LIST_HEAD(&mad_agent_priv->local_list);
|
||||
INIT_WORK(&mad_agent_priv->local_work, local_completions);
|
||||
atomic_set(&mad_agent_priv->refcount, 1);
|
||||
refcount_set(&mad_agent_priv->refcount, 1);
|
||||
init_completion(&mad_agent_priv->comp);
|
||||
|
||||
ret2 = ib_mad_agent_security_setup(&mad_agent_priv->agent, qp_type);
|
||||
@@ -484,7 +484,7 @@ EXPORT_SYMBOL(ib_register_mad_agent);
|
||||
|
||||
static inline void deref_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
|
||||
{
|
||||
if (atomic_dec_and_test(&mad_agent_priv->refcount))
|
||||
if (refcount_dec_and_test(&mad_agent_priv->refcount))
|
||||
complete(&mad_agent_priv->comp);
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
|
||||
* Reference MAD agent until receive
|
||||
* side of local completion handled
|
||||
*/
|
||||
atomic_inc(&mad_agent_priv->refcount);
|
||||
refcount_inc(&mad_agent_priv->refcount);
|
||||
} else
|
||||
kfree(mad_priv);
|
||||
break;
|
||||
@@ -758,7 +758,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
|
||||
local->return_wc_byte_len = mad_size;
|
||||
}
|
||||
/* Reference MAD agent until send side of local completion handled */
|
||||
atomic_inc(&mad_agent_priv->refcount);
|
||||
refcount_inc(&mad_agent_priv->refcount);
|
||||
/* Queue local completion to local list */
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
list_add_tail(&local->completion_list, &mad_agent_priv->local_list);
|
||||
@@ -916,7 +916,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
|
||||
}
|
||||
|
||||
mad_send_wr->send_buf.mad_agent = mad_agent;
|
||||
atomic_inc(&mad_agent_priv->refcount);
|
||||
refcount_inc(&mad_agent_priv->refcount);
|
||||
return &mad_send_wr->send_buf;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_send_mad);
|
||||
@@ -1131,7 +1131,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
|
||||
mad_send_wr->status = IB_WC_SUCCESS;
|
||||
|
||||
/* Reference MAD agent until send completes */
|
||||
atomic_inc(&mad_agent_priv->refcount);
|
||||
refcount_inc(&mad_agent_priv->refcount);
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
list_add_tail(&mad_send_wr->agent_list,
|
||||
&mad_agent_priv->send_list);
|
||||
@@ -1148,7 +1148,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
list_del(&mad_send_wr->agent_list);
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1554,7 +1554,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
|
||||
hi_tid = be64_to_cpu(mad_hdr->tid) >> 32;
|
||||
rcu_read_lock();
|
||||
mad_agent = xa_load(&ib_mad_clients, hi_tid);
|
||||
if (mad_agent && !atomic_inc_not_zero(&mad_agent->refcount))
|
||||
if (mad_agent && !refcount_inc_not_zero(&mad_agent->refcount))
|
||||
mad_agent = NULL;
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
@@ -1606,7 +1606,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
|
||||
}
|
||||
}
|
||||
if (mad_agent)
|
||||
atomic_inc(&mad_agent->refcount);
|
||||
refcount_inc(&mad_agent->refcount);
|
||||
out:
|
||||
spin_unlock_irqrestore(&port_priv->reg_lock, flags);
|
||||
}
|
||||
@@ -1831,7 +1831,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
|
||||
mad_agent_priv->agent.recv_handler(
|
||||
&mad_agent_priv->agent, NULL,
|
||||
mad_recv_wc);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
} else {
|
||||
/* not user rmpp, revert to normal behavior and
|
||||
* drop the mad */
|
||||
@@ -1848,7 +1848,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
|
||||
&mad_agent_priv->agent,
|
||||
&mad_send_wr->send_buf,
|
||||
mad_recv_wc);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
|
||||
mad_send_wc.status = IB_WC_SUCCESS;
|
||||
mad_send_wc.vendor_err = 0;
|
||||
@@ -2438,7 +2438,7 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
|
||||
list_del(&mad_send_wr->agent_list);
|
||||
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
|
||||
&mad_send_wc);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2572,7 +2572,7 @@ static void local_completions(struct work_struct *work)
|
||||
&local->mad_send_wr->send_buf,
|
||||
&local->mad_priv->header.recv_wc);
|
||||
spin_lock_irqsave(&recv_mad_agent->lock, flags);
|
||||
atomic_dec(&recv_mad_agent->refcount);
|
||||
deref_mad_agent(recv_mad_agent);
|
||||
spin_unlock_irqrestore(&recv_mad_agent->lock, flags);
|
||||
}
|
||||
|
||||
@@ -2585,7 +2585,7 @@ local_send_completion:
|
||||
&mad_send_wc);
|
||||
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
if (free_mad)
|
||||
kfree(local->mad_priv);
|
||||
kfree(local);
|
||||
@@ -2671,7 +2671,7 @@ static void timeout_sends(struct work_struct *work)
|
||||
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
|
||||
&mad_send_wc);
|
||||
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
|
||||
@@ -103,7 +103,7 @@ struct ib_mad_agent_private {
|
||||
struct work_struct local_work;
|
||||
struct list_head rmpp_list;
|
||||
|
||||
atomic_t refcount;
|
||||
refcount_t refcount;
|
||||
union {
|
||||
struct completion comp;
|
||||
struct rcu_head rcu;
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
enum rmpp_state {
|
||||
RMPP_STATE_ACTIVE,
|
||||
RMPP_STATE_TIMEOUT,
|
||||
RMPP_STATE_COMPLETE,
|
||||
RMPP_STATE_CANCELING
|
||||
RMPP_STATE_COMPLETE
|
||||
};
|
||||
|
||||
struct mad_rmpp_recv {
|
||||
@@ -52,7 +51,7 @@ struct mad_rmpp_recv {
|
||||
struct completion comp;
|
||||
enum rmpp_state state;
|
||||
spinlock_t lock;
|
||||
atomic_t refcount;
|
||||
refcount_t refcount;
|
||||
|
||||
struct ib_ah *ah;
|
||||
struct ib_mad_recv_wc *rmpp_wc;
|
||||
@@ -73,7 +72,7 @@ struct mad_rmpp_recv {
|
||||
|
||||
static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
if (atomic_dec_and_test(&rmpp_recv->refcount))
|
||||
if (refcount_dec_and_test(&rmpp_recv->refcount))
|
||||
complete(&rmpp_recv->comp);
|
||||
}
|
||||
|
||||
@@ -91,23 +90,19 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) {
|
||||
if (rmpp_recv->state != RMPP_STATE_COMPLETE)
|
||||
ib_free_recv_mad(rmpp_recv->rmpp_wc);
|
||||
rmpp_recv->state = RMPP_STATE_CANCELING;
|
||||
}
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
|
||||
list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) {
|
||||
cancel_delayed_work(&rmpp_recv->timeout_work);
|
||||
cancel_delayed_work(&rmpp_recv->cleanup_work);
|
||||
}
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
|
||||
flush_workqueue(agent->qp_info->port_priv->wq);
|
||||
|
||||
list_for_each_entry_safe(rmpp_recv, temp_rmpp_recv,
|
||||
&agent->rmpp_list, list) {
|
||||
list_del(&rmpp_recv->list);
|
||||
if (rmpp_recv->state != RMPP_STATE_COMPLETE)
|
||||
ib_free_recv_mad(rmpp_recv->rmpp_wc);
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
}
|
||||
}
|
||||
@@ -272,10 +267,6 @@ static void recv_cleanup_handler(struct work_struct *work)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->agent->lock, flags);
|
||||
if (rmpp_recv->state == RMPP_STATE_CANCELING) {
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
return;
|
||||
}
|
||||
list_del(&rmpp_recv->list);
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
@@ -305,7 +296,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler);
|
||||
spin_lock_init(&rmpp_recv->lock);
|
||||
rmpp_recv->state = RMPP_STATE_ACTIVE;
|
||||
atomic_set(&rmpp_recv->refcount, 1);
|
||||
refcount_set(&rmpp_recv->refcount, 1);
|
||||
|
||||
rmpp_recv->rmpp_wc = mad_recv_wc;
|
||||
rmpp_recv->cur_seg_buf = &mad_recv_wc->recv_buf;
|
||||
@@ -357,7 +348,7 @@ acquire_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
rmpp_recv = find_rmpp_recv(agent, mad_recv_wc);
|
||||
if (rmpp_recv)
|
||||
atomic_inc(&rmpp_recv->refcount);
|
||||
refcount_inc(&rmpp_recv->refcount);
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
return rmpp_recv;
|
||||
}
|
||||
@@ -553,7 +544,7 @@ start_rmpp(struct ib_mad_agent_private *agent,
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
return continue_rmpp(agent, mad_recv_wc);
|
||||
}
|
||||
atomic_inc(&rmpp_recv->refcount);
|
||||
refcount_inc(&rmpp_recv->refcount);
|
||||
|
||||
if (get_last_flag(&mad_recv_wc->recv_buf)) {
|
||||
rmpp_recv->state = RMPP_STATE_COMPLETE;
|
||||
|
||||
@@ -114,6 +114,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
|
||||
[RDMA_NLDEV_ATTR_RES_PS] = { .type = NLA_U32 },
|
||||
[RDMA_NLDEV_ATTR_RES_QP] = { .type = NLA_NESTED },
|
||||
[RDMA_NLDEV_ATTR_RES_QP_ENTRY] = { .type = NLA_NESTED },
|
||||
[RDMA_NLDEV_ATTR_RES_RAW] = { .type = NLA_BINARY },
|
||||
[RDMA_NLDEV_ATTR_RES_RKEY] = { .type = NLA_U32 },
|
||||
[RDMA_NLDEV_ATTR_RES_RQPN] = { .type = NLA_U32 },
|
||||
[RDMA_NLDEV_ATTR_RES_RQ_PSN] = { .type = NLA_U32 },
|
||||
@@ -446,27 +447,11 @@ static int fill_res_name_pid(struct sk_buff *msg,
|
||||
return err ? -EMSGSIZE : 0;
|
||||
}
|
||||
|
||||
static bool fill_res_entry(struct ib_device *dev, struct sk_buff *msg,
|
||||
struct rdma_restrack_entry *res)
|
||||
static int fill_res_qp_entry_query(struct sk_buff *msg,
|
||||
struct rdma_restrack_entry *res,
|
||||
struct ib_device *dev,
|
||||
struct ib_qp *qp)
|
||||
{
|
||||
if (!dev->ops.fill_res_entry)
|
||||
return false;
|
||||
return dev->ops.fill_res_entry(msg, res);
|
||||
}
|
||||
|
||||
static bool fill_stat_entry(struct ib_device *dev, struct sk_buff *msg,
|
||||
struct rdma_restrack_entry *res)
|
||||
{
|
||||
if (!dev->ops.fill_stat_entry)
|
||||
return false;
|
||||
return dev->ops.fill_stat_entry(msg, res);
|
||||
}
|
||||
|
||||
static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_qp *qp = container_of(res, struct ib_qp, res);
|
||||
struct ib_device *dev = qp->device;
|
||||
struct ib_qp_init_attr qp_init_attr;
|
||||
struct ib_qp_attr qp_attr;
|
||||
int ret;
|
||||
@@ -475,16 +460,6 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (port && port != qp_attr.port_num)
|
||||
return -EAGAIN;
|
||||
|
||||
/* In create_qp() port is not set yet */
|
||||
if (qp_attr.port_num &&
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp_attr.port_num))
|
||||
goto err;
|
||||
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num))
|
||||
goto err;
|
||||
if (qp->qp_type == IB_QPT_RC || qp->qp_type == IB_QPT_UC) {
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RQPN,
|
||||
qp_attr.dest_qp_num))
|
||||
@@ -508,21 +483,55 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_STATE, qp_attr.qp_state))
|
||||
goto err;
|
||||
|
||||
if (!rdma_is_kernel_res(res) &&
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, qp->pd->res.id))
|
||||
goto err;
|
||||
|
||||
if (fill_res_name_pid(msg, res))
|
||||
goto err;
|
||||
|
||||
if (fill_res_entry(dev, msg, res))
|
||||
goto err;
|
||||
|
||||
if (dev->ops.fill_res_qp_entry)
|
||||
return dev->ops.fill_res_qp_entry(msg, qp);
|
||||
return 0;
|
||||
|
||||
err: return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_qp *qp = container_of(res, struct ib_qp, res);
|
||||
struct ib_device *dev = qp->device;
|
||||
int ret;
|
||||
|
||||
if (port && port != qp->port)
|
||||
return -EAGAIN;
|
||||
|
||||
/* In create_qp() port is not set yet */
|
||||
if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port))
|
||||
return -EINVAL;
|
||||
|
||||
ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num);
|
||||
if (ret)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (!rdma_is_kernel_res(res) &&
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, qp->pd->res.id))
|
||||
return -EMSGSIZE;
|
||||
|
||||
ret = fill_res_name_pid(msg, res);
|
||||
if (ret)
|
||||
return -EMSGSIZE;
|
||||
|
||||
return fill_res_qp_entry_query(msg, res, dev, qp);
|
||||
}
|
||||
|
||||
static int fill_res_qp_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_qp *qp = container_of(res, struct ib_qp, res);
|
||||
struct ib_device *dev = qp->device;
|
||||
|
||||
if (port && port != qp->port)
|
||||
return -EAGAIN;
|
||||
if (!dev->ops.fill_res_qp_entry_raw)
|
||||
return -EINVAL;
|
||||
return dev->ops.fill_res_qp_entry_raw(msg, qp);
|
||||
}
|
||||
|
||||
static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
@@ -568,9 +577,8 @@ static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
if (fill_res_name_pid(msg, res))
|
||||
goto err;
|
||||
|
||||
if (fill_res_entry(dev, msg, res))
|
||||
goto err;
|
||||
|
||||
if (dev->ops.fill_res_cm_id_entry)
|
||||
return dev->ops.fill_res_cm_id_entry(msg, cm_id);
|
||||
return 0;
|
||||
|
||||
err: return -EMSGSIZE;
|
||||
@@ -583,35 +591,42 @@ static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct ib_device *dev = cq->device;
|
||||
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQE, cq->cqe))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
|
||||
atomic_read(&cq->usecnt), RDMA_NLDEV_ATTR_PAD))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
/* Poll context is only valid for kernel CQs */
|
||||
if (rdma_is_kernel_res(res) &&
|
||||
nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_POLL_CTX, cq->poll_ctx))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, (cq->dim != NULL)))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQN, res->id))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
if (!rdma_is_kernel_res(res) &&
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,
|
||||
cq->uobject->uevent.uobject.context->res.id))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (fill_res_name_pid(msg, res))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (fill_res_entry(dev, msg, res))
|
||||
goto err;
|
||||
return (dev->ops.fill_res_cq_entry) ?
|
||||
dev->ops.fill_res_cq_entry(msg, cq) : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static int fill_res_cq_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_cq *cq = container_of(res, struct ib_cq, res);
|
||||
struct ib_device *dev = cq->device;
|
||||
|
||||
err: return -EMSGSIZE;
|
||||
if (!dev->ops.fill_res_cq_entry_raw)
|
||||
return -EINVAL;
|
||||
return dev->ops.fill_res_cq_entry_raw(msg, cq);
|
||||
}
|
||||
|
||||
static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
@@ -622,38 +637,45 @@ static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
|
||||
if (has_cap_net_admin) {
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_MRLEN, mr->length,
|
||||
RDMA_NLDEV_ATTR_PAD))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (!rdma_is_kernel_res(res) &&
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, mr->pd->res.id))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (fill_res_name_pid(msg, res))
|
||||
goto err;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (fill_res_entry(dev, msg, res))
|
||||
goto err;
|
||||
return (dev->ops.fill_res_mr_entry) ?
|
||||
dev->ops.fill_res_mr_entry(msg, mr) :
|
||||
0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static int fill_res_mr_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_mr *mr = container_of(res, struct ib_mr, res);
|
||||
struct ib_device *dev = mr->pd->device;
|
||||
|
||||
err: return -EMSGSIZE;
|
||||
if (!dev->ops.fill_res_mr_entry_raw)
|
||||
return -EINVAL;
|
||||
return dev->ops.fill_res_mr_entry_raw(msg, mr);
|
||||
}
|
||||
|
||||
static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
struct rdma_restrack_entry *res, uint32_t port)
|
||||
{
|
||||
struct ib_pd *pd = container_of(res, struct ib_pd, res);
|
||||
struct ib_device *dev = pd->device;
|
||||
|
||||
if (has_cap_net_admin) {
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY,
|
||||
@@ -676,13 +698,7 @@ static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
pd->uobject->context->res.id))
|
||||
goto err;
|
||||
|
||||
if (fill_res_name_pid(msg, res))
|
||||
goto err;
|
||||
|
||||
if (fill_res_entry(dev, msg, res))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
return fill_res_name_pid(msg, res);
|
||||
|
||||
err: return -EMSGSIZE;
|
||||
}
|
||||
@@ -695,11 +711,16 @@ static int fill_stat_counter_mode(struct sk_buff *msg,
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, m->mode))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (m->mode == RDMA_COUNTER_MODE_AUTO)
|
||||
if (m->mode == RDMA_COUNTER_MODE_AUTO) {
|
||||
if ((m->mask & RDMA_COUNTER_MASK_QP_TYPE) &&
|
||||
nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, m->param.qp_type))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if ((m->mask & RDMA_COUNTER_MASK_PID) &&
|
||||
fill_res_name_pid(msg, &counter->res))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -738,9 +759,6 @@ static int fill_stat_counter_qps(struct sk_buff *msg,
|
||||
xa_lock(&rt->xa);
|
||||
xa_for_each(&rt->xa, id, res) {
|
||||
qp = container_of(res, struct ib_qp, res);
|
||||
if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
|
||||
continue;
|
||||
|
||||
if (!qp->counter || (qp->counter->id != counter->id))
|
||||
continue;
|
||||
|
||||
@@ -793,9 +811,8 @@ static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
|
||||
goto err;
|
||||
|
||||
if (fill_stat_entry(dev, msg, res))
|
||||
goto err;
|
||||
|
||||
if (dev->ops.fill_stat_mr_entry)
|
||||
return dev->ops.fill_stat_mr_entry(msg, mr);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -840,7 +857,6 @@ static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin,
|
||||
|
||||
if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, counter->port) ||
|
||||
nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, counter->id) ||
|
||||
fill_res_name_pid(msg, &counter->res) ||
|
||||
fill_stat_counter_mode(msg, counter) ||
|
||||
fill_stat_counter_qps(msg, counter) ||
|
||||
fill_stat_counter_hwcounters(msg, counter))
|
||||
@@ -1177,7 +1193,6 @@ static int nldev_res_get_dumpit(struct sk_buff *skb,
|
||||
|
||||
struct nldev_fill_res_entry {
|
||||
enum rdma_nldev_attr nldev_attr;
|
||||
enum rdma_nldev_command nldev_cmd;
|
||||
u8 flags;
|
||||
u32 entry;
|
||||
u32 id;
|
||||
@@ -1189,40 +1204,34 @@ enum nldev_res_flags {
|
||||
|
||||
static const struct nldev_fill_res_entry fill_entries[RDMA_RESTRACK_MAX] = {
|
||||
[RDMA_RESTRACK_QP] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_RES_QP_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_RES_QP,
|
||||
.entry = RDMA_NLDEV_ATTR_RES_QP_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_RES_LQPN,
|
||||
},
|
||||
[RDMA_RESTRACK_CM_ID] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_RES_CM_ID_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_RES_CM_ID,
|
||||
.entry = RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_RES_CM_IDN,
|
||||
},
|
||||
[RDMA_RESTRACK_CQ] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_RES_CQ_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_RES_CQ,
|
||||
.flags = NLDEV_PER_DEV,
|
||||
.entry = RDMA_NLDEV_ATTR_RES_CQ_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_RES_CQN,
|
||||
},
|
||||
[RDMA_RESTRACK_MR] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_RES_MR_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_RES_MR,
|
||||
.flags = NLDEV_PER_DEV,
|
||||
.entry = RDMA_NLDEV_ATTR_RES_MR_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_RES_MRN,
|
||||
},
|
||||
[RDMA_RESTRACK_PD] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_RES_PD_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_RES_PD,
|
||||
.flags = NLDEV_PER_DEV,
|
||||
.entry = RDMA_NLDEV_ATTR_RES_PD_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_RES_PDN,
|
||||
},
|
||||
[RDMA_RESTRACK_COUNTER] = {
|
||||
.nldev_cmd = RDMA_NLDEV_CMD_STAT_GET,
|
||||
.nldev_attr = RDMA_NLDEV_ATTR_STAT_COUNTER,
|
||||
.entry = RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY,
|
||||
.id = RDMA_NLDEV_ATTR_STAT_COUNTER_ID,
|
||||
@@ -1281,7 +1290,8 @@ static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
|
||||
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd),
|
||||
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
|
||||
RDMA_NL_GET_OP(nlh->nlmsg_type)),
|
||||
0, 0);
|
||||
|
||||
if (fill_nldev_handle(msg, device)) {
|
||||
@@ -1359,7 +1369,8 @@ static int res_get_common_dumpit(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
|
||||
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd),
|
||||
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
|
||||
RDMA_NL_GET_OP(cb->nlh->nlmsg_type)),
|
||||
0, NLM_F_MULTI);
|
||||
|
||||
if (fill_nldev_handle(skb, device)) {
|
||||
@@ -1441,26 +1452,29 @@ err_index:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define RES_GET_FUNCS(name, type) \
|
||||
static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \
|
||||
#define RES_GET_FUNCS(name, type) \
|
||||
static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \
|
||||
struct netlink_callback *cb) \
|
||||
{ \
|
||||
return res_get_common_dumpit(skb, cb, type, \
|
||||
fill_res_##name##_entry); \
|
||||
} \
|
||||
static int nldev_res_get_##name##_doit(struct sk_buff *skb, \
|
||||
struct nlmsghdr *nlh, \
|
||||
{ \
|
||||
return res_get_common_dumpit(skb, cb, type, \
|
||||
fill_res_##name##_entry); \
|
||||
} \
|
||||
static int nldev_res_get_##name##_doit(struct sk_buff *skb, \
|
||||
struct nlmsghdr *nlh, \
|
||||
struct netlink_ext_ack *extack) \
|
||||
{ \
|
||||
return res_get_common_doit(skb, nlh, extack, type, \
|
||||
fill_res_##name##_entry); \
|
||||
{ \
|
||||
return res_get_common_doit(skb, nlh, extack, type, \
|
||||
fill_res_##name##_entry); \
|
||||
}
|
||||
|
||||
RES_GET_FUNCS(qp, RDMA_RESTRACK_QP);
|
||||
RES_GET_FUNCS(qp_raw, RDMA_RESTRACK_QP);
|
||||
RES_GET_FUNCS(cm_id, RDMA_RESTRACK_CM_ID);
|
||||
RES_GET_FUNCS(cq, RDMA_RESTRACK_CQ);
|
||||
RES_GET_FUNCS(cq_raw, RDMA_RESTRACK_CQ);
|
||||
RES_GET_FUNCS(pd, RDMA_RESTRACK_PD);
|
||||
RES_GET_FUNCS(mr, RDMA_RESTRACK_MR);
|
||||
RES_GET_FUNCS(mr_raw, RDMA_RESTRACK_MR);
|
||||
RES_GET_FUNCS(counter, RDMA_RESTRACK_COUNTER);
|
||||
|
||||
static LIST_HEAD(link_ops);
|
||||
@@ -2145,6 +2159,21 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
|
||||
.doit = nldev_stat_del_doit,
|
||||
.flags = RDMA_NL_ADMIN_PERM,
|
||||
},
|
||||
[RDMA_NLDEV_CMD_RES_QP_GET_RAW] = {
|
||||
.doit = nldev_res_get_qp_raw_doit,
|
||||
.dump = nldev_res_get_qp_raw_dumpit,
|
||||
.flags = RDMA_NL_ADMIN_PERM,
|
||||
},
|
||||
[RDMA_NLDEV_CMD_RES_CQ_GET_RAW] = {
|
||||
.doit = nldev_res_get_cq_raw_doit,
|
||||
.dump = nldev_res_get_cq_raw_dumpit,
|
||||
.flags = RDMA_NL_ADMIN_PERM,
|
||||
},
|
||||
[RDMA_NLDEV_CMD_RES_MR_GET_RAW] = {
|
||||
.doit = nldev_res_get_mr_raw_doit,
|
||||
.dump = nldev_res_get_mr_raw_dumpit,
|
||||
.flags = RDMA_NL_ADMIN_PERM,
|
||||
},
|
||||
};
|
||||
|
||||
void __init nldev_init(void)
|
||||
|
||||
@@ -58,7 +58,7 @@ struct ib_port {
|
||||
struct ib_device *ibdev;
|
||||
struct gid_attr_group *gid_attr_group;
|
||||
struct attribute_group gid_group;
|
||||
struct attribute_group pkey_group;
|
||||
struct attribute_group *pkey_group;
|
||||
struct attribute_group *pma_table;
|
||||
struct attribute_group *hw_stats_ag;
|
||||
struct rdma_hw_stats *hw_stats;
|
||||
@@ -681,11 +681,16 @@ static void ib_port_release(struct kobject *kobj)
|
||||
kfree(p->gid_group.attrs);
|
||||
}
|
||||
|
||||
if (p->pkey_group.attrs) {
|
||||
for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
|
||||
kfree(a);
|
||||
if (p->pkey_group) {
|
||||
if (p->pkey_group->attrs) {
|
||||
for (i = 0; (a = p->pkey_group->attrs[i]); ++i)
|
||||
kfree(a);
|
||||
|
||||
kfree(p->pkey_group.attrs);
|
||||
kfree(p->pkey_group->attrs);
|
||||
}
|
||||
|
||||
kfree(p->pkey_group);
|
||||
p->pkey_group = NULL;
|
||||
}
|
||||
|
||||
kfree(p);
|
||||
@@ -1118,17 +1123,26 @@ static int add_port(struct ib_core_device *coredev, int port_num)
|
||||
if (ret)
|
||||
goto err_free_gid_type;
|
||||
|
||||
p->pkey_group.name = "pkeys";
|
||||
p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
|
||||
attr.pkey_tbl_len);
|
||||
if (!p->pkey_group.attrs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_remove_gid_type;
|
||||
if (attr.pkey_tbl_len) {
|
||||
p->pkey_group = kzalloc(sizeof(*p->pkey_group), GFP_KERNEL);
|
||||
if (!p->pkey_group) {
|
||||
ret = -ENOMEM;
|
||||
goto err_remove_gid_type;
|
||||
}
|
||||
|
||||
p->pkey_group->name = "pkeys";
|
||||
p->pkey_group->attrs = alloc_group_attrs(show_port_pkey,
|
||||
attr.pkey_tbl_len);
|
||||
if (!p->pkey_group->attrs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pkey_group;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&p->kobj, p->pkey_group);
|
||||
if (ret)
|
||||
goto err_free_pkey;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&p->kobj, &p->pkey_group);
|
||||
if (ret)
|
||||
goto err_free_pkey;
|
||||
|
||||
if (device->ops.init_port && is_full_dev) {
|
||||
ret = device->ops.init_port(device, port_num, &p->kobj);
|
||||
@@ -1150,14 +1164,20 @@ static int add_port(struct ib_core_device *coredev, int port_num)
|
||||
return 0;
|
||||
|
||||
err_remove_pkey:
|
||||
sysfs_remove_group(&p->kobj, &p->pkey_group);
|
||||
if (p->pkey_group)
|
||||
sysfs_remove_group(&p->kobj, p->pkey_group);
|
||||
|
||||
err_free_pkey:
|
||||
for (i = 0; i < attr.pkey_tbl_len; ++i)
|
||||
kfree(p->pkey_group.attrs[i]);
|
||||
if (p->pkey_group) {
|
||||
for (i = 0; i < attr.pkey_tbl_len; ++i)
|
||||
kfree(p->pkey_group->attrs[i]);
|
||||
|
||||
kfree(p->pkey_group.attrs);
|
||||
p->pkey_group.attrs = NULL;
|
||||
kfree(p->pkey_group->attrs);
|
||||
p->pkey_group->attrs = NULL;
|
||||
}
|
||||
|
||||
err_free_pkey_group:
|
||||
kfree(p->pkey_group);
|
||||
|
||||
err_remove_gid_type:
|
||||
sysfs_remove_group(&p->gid_attr_group->kobj,
|
||||
@@ -1317,7 +1337,8 @@ void ib_free_port_attrs(struct ib_core_device *coredev)
|
||||
|
||||
if (port->pma_table)
|
||||
sysfs_remove_group(p, port->pma_table);
|
||||
sysfs_remove_group(p, &port->pkey_group);
|
||||
if (port->pkey_group)
|
||||
sysfs_remove_group(p, port->pkey_group);
|
||||
sysfs_remove_group(p, &port->gid_group);
|
||||
sysfs_remove_group(&port->gid_attr_group->kobj,
|
||||
&port->gid_attr_group->ndev);
|
||||
|
||||
@@ -9,6 +9,4 @@
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
#include <trace/events/rdma_core.h>
|
||||
|
||||
@@ -261,6 +261,7 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
|
||||
sg = umem->sg_head.sgl;
|
||||
|
||||
while (npages) {
|
||||
cond_resched();
|
||||
ret = pin_user_pages_fast(cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE /
|
||||
|
||||
@@ -152,6 +152,7 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_implicit);
|
||||
* ib_alloc_implicit_odp_umem()
|
||||
* @addr: The starting userspace VA
|
||||
* @size: The length of the userspace VA
|
||||
* @ops: MMU interval ops, currently only @invalidate
|
||||
*/
|
||||
struct ib_umem_odp *
|
||||
ib_umem_odp_alloc_child(struct ib_umem_odp *root, unsigned long addr,
|
||||
@@ -213,6 +214,7 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_child);
|
||||
* @addr: userspace virtual address to start at
|
||||
* @size: length of region to pin
|
||||
* @access: IB_ACCESS_xxx flags for memory being pinned
|
||||
* @ops: MMU interval ops, currently only @invalidate
|
||||
*
|
||||
* The driver should use when the access flags indicate ODP memory. It avoids
|
||||
* pinning, instead, stores the mm for future page fault handling in
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -790,6 +790,7 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
|
||||
}
|
||||
return uverbs_copy_to(bundle, idx, from, size);
|
||||
}
|
||||
EXPORT_SYMBOL(uverbs_copy_to_struct_or_zero);
|
||||
|
||||
/* Once called an abort will call through to the type's destroy_hw() */
|
||||
void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *bundle,
|
||||
|
||||
@@ -601,6 +601,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
|
||||
memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
|
||||
bundle.ufile = file;
|
||||
bundle.context = NULL; /* only valid if bundle has uobject */
|
||||
bundle.uobject = NULL;
|
||||
if (!method_elm->is_ex) {
|
||||
size_t in_len = hdr.in_words * 4 - sizeof(hdr);
|
||||
size_t out_len = hdr.out_words * 4;
|
||||
@@ -664,6 +665,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
|
||||
}
|
||||
|
||||
ret = method_elm->handler(&bundle);
|
||||
if (bundle.uobject)
|
||||
uverbs_finalize_object(bundle.uobject, UVERBS_ACCESS_NEW, true,
|
||||
!ret, &bundle);
|
||||
out_unlock:
|
||||
srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
|
||||
return (ret) ? : count;
|
||||
|
||||
@@ -46,7 +46,9 @@ static int uverbs_free_counters(struct ib_uobject *uobject,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return counters->device->ops.destroy_counters(counters);
|
||||
counters->device->ops.destroy_counters(counters);
|
||||
kfree(counters);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
|
||||
@@ -66,20 +68,19 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
|
||||
if (!ib_dev->ops.create_counters)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
counters = ib_dev->ops.create_counters(ib_dev, attrs);
|
||||
if (IS_ERR(counters)) {
|
||||
ret = PTR_ERR(counters);
|
||||
goto err_create_counters;
|
||||
}
|
||||
counters = rdma_zalloc_drv_obj(ib_dev, ib_counters);
|
||||
if (!counters)
|
||||
return -ENOMEM;
|
||||
|
||||
counters->device = ib_dev;
|
||||
counters->uobject = uobj;
|
||||
uobj->object = counters;
|
||||
atomic_set(&counters->usecnt, 0);
|
||||
|
||||
return 0;
|
||||
ret = ib_dev->ops.create_counters(counters, attrs);
|
||||
if (ret)
|
||||
kfree(counters);
|
||||
|
||||
err_create_counters:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -207,11 +207,8 @@ DECLARE_UVERBS_NAMED_METHOD(
|
||||
DECLARE_UVERBS_NAMED_OBJECT(
|
||||
UVERBS_OBJECT_CQ,
|
||||
UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), uverbs_free_cq),
|
||||
|
||||
#if IS_ENABLED(CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI)
|
||||
&UVERBS_METHOD(UVERBS_METHOD_CQ_CREATE),
|
||||
&UVERBS_METHOD(UVERBS_METHOD_CQ_DESTROY)
|
||||
#endif
|
||||
);
|
||||
|
||||
const struct uapi_definition uverbs_def_obj_cq[] = {
|
||||
|
||||
@@ -38,7 +38,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)(
|
||||
attrs->ucore.outlen < method_elm->resp_size)
|
||||
return -ENOSPC;
|
||||
|
||||
return method_elm->handler(attrs);
|
||||
attrs->uobject = NULL;
|
||||
rc = method_elm->handler(attrs);
|
||||
if (attrs->uobject)
|
||||
uverbs_finalize_object(attrs->uobject, UVERBS_ACCESS_NEW, true,
|
||||
!rc, attrs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
|
||||
@@ -229,6 +234,37 @@ static int UVERBS_HANDLER(UVERBS_METHOD_GET_CONTEXT)(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT)(
|
||||
struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
u64 core_support = IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS;
|
||||
struct ib_ucontext *ucontext;
|
||||
struct ib_device *ib_dev;
|
||||
u32 num_comp;
|
||||
int ret;
|
||||
|
||||
ucontext = ib_uverbs_get_ucontext(attrs);
|
||||
if (IS_ERR(ucontext))
|
||||
return PTR_ERR(ucontext);
|
||||
ib_dev = ucontext->device;
|
||||
|
||||
if (!ib_dev->ops.query_ucontext)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
num_comp = attrs->ufile->device->num_comp_vectors;
|
||||
ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS,
|
||||
&num_comp, sizeof(num_comp));
|
||||
if (IS_UVERBS_COPY_ERR(ret))
|
||||
return ret;
|
||||
|
||||
ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT,
|
||||
&core_support, sizeof(core_support));
|
||||
if (IS_UVERBS_COPY_ERR(ret))
|
||||
return ret;
|
||||
|
||||
return ucontext->device->ops.query_ucontext(ucontext, attrs);
|
||||
}
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
UVERBS_METHOD_GET_CONTEXT,
|
||||
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
|
||||
@@ -237,6 +273,13 @@ DECLARE_UVERBS_NAMED_METHOD(
|
||||
UVERBS_ATTR_TYPE(u64), UA_OPTIONAL),
|
||||
UVERBS_ATTR_UHW());
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
UVERBS_METHOD_QUERY_CONTEXT,
|
||||
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS,
|
||||
UVERBS_ATTR_TYPE(u32), UA_OPTIONAL),
|
||||
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT,
|
||||
UVERBS_ATTR_TYPE(u64), UA_OPTIONAL));
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
UVERBS_METHOD_INFO_HANDLES,
|
||||
/* Also includes any device specific object ids */
|
||||
@@ -260,7 +303,8 @@ DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
|
||||
&UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT),
|
||||
&UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),
|
||||
&UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES),
|
||||
&UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT));
|
||||
&UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT),
|
||||
&UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT));
|
||||
|
||||
const struct uapi_definition uverbs_def_obj_device[] = {
|
||||
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user