Commit 8fdd4019 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull rdma updates from Jason Gunthorpe:
 "A very quiet cycle with few notable changes. Mostly the usual list of
  one or two patches to drivers changing something that isn't quite rc
  worthy. The subsystem seems to be seeing a larger number of rework and
  cleanup style patches right now, I feel that several vendors are
  prepping their drivers for new silicon.

  Summary:

   - Driver updates and cleanup for qedr, bnxt_re, hns, siw, mlx5, mlx4,
     rxe, i40iw

   - Larger series doing cleanup and rework for hns and hfi1.

   - Some general reworking of the CM code to make it a little more
     understandable

   - Unify the different code paths connected to the uverbs FD scheme

   - New UAPI ioctls conversions for get context and get async fd

   - Trace points for CQ and CM portions of the RDMA stack

   - mlx5 driver support for virtio-net formatted rings as RDMA raw
     ethernet QPs

   - verbs support for setting the PCI-E relaxed ordering bit on DMA
     traffic connected to a MR

   - A couple of bug fixes that came too late to make rc7"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (108 commits)
  RDMA/core: Make the entire API tree static
  RDMA/efa: Mask access flags with the correct optional range
  RDMA/cma: Fix unbalanced cm_id reference count during address resolve
  RDMA/umem: Fix ib_umem_find_best_pgsz()
  IB/mlx4: Fix leak in id_map_find_del
  IB/opa_vnic: Spelling correction of 'erorr' to 'error'
  IB/hfi1: Fix logical condition in msix_request_irq
  RDMA/cm: Remove CM message structs
  RDMA/cm: Use IBA functions for complex structure members
  RDMA/cm: Use IBA functions for simple structure members
  RDMA/cm: Use IBA functions for swapping get/set acessors
  RDMA/cm: Use IBA functions for simple get/set acessors
  RDMA/cm: Add SET/GET implementations to hide IBA wire format
  RDMA/cm: Add accessors for CM_REQ transport_type
  IB/mlx5: Return the administrative GUID if exists
  RDMA/core: Ensure that rdma_user_mmap_entry_remove() is a fence
  IB/mlx4: Fix memory leak in add_gid error flow
  IB/mlx5: Expose RoCE accelerator counters
  RDMA/mlx5: Set relaxed ordering when requested
  RDMA/core: Add the core support field to METHOD_GET_CONTEXT
  ...
parents 68b62e5d 8889f6fa
...@@ -11,7 +11,8 @@ ib_core-y := packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \ ...@@ -11,7 +11,8 @@ ib_core-y := packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
device.o fmr_pool.o cache.o netlink.o \ device.o fmr_pool.o cache.o netlink.o \
roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \ roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
multicast.o mad.o smi.o agent.o mad_rmpp.o \ multicast.o mad.o smi.o agent.o mad_rmpp.o \
nldev.o restrack.o counters.o ib_core_uverbs.o nldev.o restrack.o counters.o ib_core_uverbs.o \
trace.o
ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
...@@ -20,7 +21,8 @@ ib_cm-y := cm.o ...@@ -20,7 +21,8 @@ ib_cm-y := cm.o
iw_cm-y := iwcm.o iwpm_util.o iwpm_msg.o iw_cm-y := iwcm.o iwpm_util.o iwpm_msg.o
rdma_cm-y := cma.o CFLAGS_cma_trace.o += -I$(src)
rdma_cm-y := cma.o cma_trace.o
rdma_cm-$(CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS) += cma_configfs.o rdma_cm-$(CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS) += cma_configfs.o
...@@ -33,6 +35,7 @@ ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \ ...@@ -33,6 +35,7 @@ ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
uverbs_std_types_cq.o \ uverbs_std_types_cq.o \
uverbs_std_types_flow_action.o uverbs_std_types_dm.o \ uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
uverbs_std_types_mr.o uverbs_std_types_counters.o \ uverbs_std_types_mr.o uverbs_std_types_counters.o \
uverbs_uapi.o uverbs_std_types_device.o uverbs_uapi.o uverbs_std_types_device.o \
uverbs_std_types_async_fd.o
ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o
...@@ -139,7 +139,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb, ...@@ -139,7 +139,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
if (ib_nl_is_good_ip_resp(nlh)) if (ib_nl_is_good_ip_resp(nlh))
ib_nl_process_good_ip_rsep(nlh); ib_nl_process_good_ip_rsep(nlh);
return skb->len; return 0;
} }
static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr, static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr,
......
...@@ -51,9 +51,8 @@ struct ib_pkey_cache { ...@@ -51,9 +51,8 @@ struct ib_pkey_cache {
struct ib_update_work { struct ib_update_work {
struct work_struct work; struct work_struct work;
struct ib_device *device; struct ib_event event;
u8 port_num; bool enforce_security;
bool enforce_security;
}; };
union ib_gid zgid; union ib_gid zgid;
...@@ -130,7 +129,7 @@ static void dispatch_gid_change_event(struct ib_device *ib_dev, u8 port) ...@@ -130,7 +129,7 @@ static void dispatch_gid_change_event(struct ib_device *ib_dev, u8 port)
event.element.port_num = port; event.element.port_num = port;
event.event = IB_EVENT_GID_CHANGE; event.event = IB_EVENT_GID_CHANGE;
ib_dispatch_event(&event); ib_dispatch_event_clients(&event);
} }
static const char * const gid_type_str[] = { static const char * const gid_type_str[] = {
...@@ -1034,7 +1033,7 @@ int ib_get_cached_pkey(struct ib_device *device, ...@@ -1034,7 +1033,7 @@ int ib_get_cached_pkey(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
cache = device->port_data[port_num].cache.pkey; cache = device->port_data[port_num].cache.pkey;
...@@ -1043,7 +1042,7 @@ int ib_get_cached_pkey(struct ib_device *device, ...@@ -1043,7 +1042,7 @@ int ib_get_cached_pkey(struct ib_device *device,
else else
*pkey = cache->table[index]; *pkey = cache->table[index];
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return ret; return ret;
} }
...@@ -1058,9 +1057,9 @@ int ib_get_cached_subnet_prefix(struct ib_device *device, ...@@ -1058,9 +1057,9 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
*sn_pfx = device->port_data[port_num].cache.subnet_prefix; *sn_pfx = device->port_data[port_num].cache.subnet_prefix;
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return 0; return 0;
} }
...@@ -1080,7 +1079,7 @@ int ib_find_cached_pkey(struct ib_device *device, ...@@ -1080,7 +1079,7 @@ int ib_find_cached_pkey(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
cache = device->port_data[port_num].cache.pkey; cache = device->port_data[port_num].cache.pkey;
...@@ -1101,7 +1100,7 @@ int ib_find_cached_pkey(struct ib_device *device, ...@@ -1101,7 +1100,7 @@ int ib_find_cached_pkey(struct ib_device *device,
ret = 0; ret = 0;
} }
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return ret; return ret;
} }
...@@ -1120,7 +1119,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device, ...@@ -1120,7 +1119,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
cache = device->port_data[port_num].cache.pkey; cache = device->port_data[port_num].cache.pkey;
...@@ -1133,7 +1132,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device, ...@@ -1133,7 +1132,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
break; break;
} }
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return ret; return ret;
} }
...@@ -1149,9 +1148,9 @@ int ib_get_cached_lmc(struct ib_device *device, ...@@ -1149,9 +1148,9 @@ int ib_get_cached_lmc(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
*lmc = device->port_data[port_num].cache.lmc; *lmc = device->port_data[port_num].cache.lmc;
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return ret; return ret;
} }
...@@ -1167,9 +1166,9 @@ int ib_get_cached_port_state(struct ib_device *device, ...@@ -1167,9 +1166,9 @@ int ib_get_cached_port_state(struct ib_device *device,
if (!rdma_is_port_valid(device, port_num)) if (!rdma_is_port_valid(device, port_num))
return -EINVAL; return -EINVAL;
read_lock_irqsave(&device->cache.lock, flags); read_lock_irqsave(&device->cache_lock, flags);
*port_state = device->port_data[port_num].cache.port_state; *port_state = device->port_data[port_num].cache.port_state;
read_unlock_irqrestore(&device->cache.lock, flags); read_unlock_irqrestore(&device->cache_lock, flags);
return ret; return ret;
} }
...@@ -1381,9 +1380,8 @@ static int config_non_roce_gid_cache(struct ib_device *device, ...@@ -1381,9 +1380,8 @@ static int config_non_roce_gid_cache(struct ib_device *device,
return ret; return ret;
} }
static void ib_cache_update(struct ib_device *device, static int
u8 port, ib_cache_update(struct ib_device *device, u8 port, bool enforce_security)
bool enforce_security)
{ {
struct ib_port_attr *tprops = NULL; struct ib_port_attr *tprops = NULL;
struct ib_pkey_cache *pkey_cache = NULL, *old_pkey_cache; struct ib_pkey_cache *pkey_cache = NULL, *old_pkey_cache;
...@@ -1391,11 +1389,11 @@ static void ib_cache_update(struct ib_device *device, ...@@ -1391,11 +1389,11 @@ static void ib_cache_update(struct ib_device *device,
int ret; int ret;
if (!rdma_is_port_valid(device, port)) if (!rdma_is_port_valid(device, port))
return; return -EINVAL;
tprops = kmalloc(sizeof *tprops, GFP_KERNEL); tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
if (!tprops) if (!tprops)
return; return -ENOMEM;
ret = ib_query_port(device, port, tprops); ret = ib_query_port(device, port, tprops);
if (ret) { if (ret) {
...@@ -1413,8 +1411,10 @@ static void ib_cache_update(struct ib_device *device, ...@@ -1413,8 +1411,10 @@ static void ib_cache_update(struct ib_device *device,
pkey_cache = kmalloc(struct_size(pkey_cache, table, pkey_cache = kmalloc(struct_size(pkey_cache, table,
tprops->pkey_tbl_len), tprops->pkey_tbl_len),
GFP_KERNEL); GFP_KERNEL);
if (!pkey_cache) if (!pkey_cache) {
ret = -ENOMEM;
goto err; goto err;
}
pkey_cache->table_len = tprops->pkey_tbl_len; pkey_cache->table_len = tprops->pkey_tbl_len;
...@@ -1428,7 +1428,7 @@ static void ib_cache_update(struct ib_device *device, ...@@ -1428,7 +1428,7 @@ 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->port_data[port].cache.pkey; old_pkey_cache = device->port_data[port].cache.pkey;
...@@ -1437,7 +1437,7 @@ static void ib_cache_update(struct ib_device *device, ...@@ -1437,7 +1437,7 @@ static void ib_cache_update(struct ib_device *device,
device->port_data[port].cache.port_state = tprops->state; device->port_data[port].cache.port_state = tprops->state;
device->port_data[port].cache.subnet_prefix = tprops->subnet_prefix; device->port_data[port].cache.subnet_prefix = tprops->subnet_prefix;
write_unlock_irq(&device->cache.lock); write_unlock_irq(&device->cache_lock);
if (enforce_security) if (enforce_security)
ib_security_cache_change(device, ib_security_cache_change(device,
...@@ -1446,57 +1446,91 @@ static void ib_cache_update(struct ib_device *device, ...@@ -1446,57 +1446,91 @@ static void ib_cache_update(struct ib_device *device,
kfree(old_pkey_cache); kfree(old_pkey_cache);
kfree(tprops); kfree(tprops);
return; return 0;
err: err:
kfree(pkey_cache); kfree(pkey_cache);
kfree(tprops); kfree(tprops);
return ret;
}
static void ib_cache_event_task(struct work_struct *_work)
{
struct ib_update_work *work =
container_of(_work, struct ib_update_work, work);
int ret;
/* Before distributing the cache update event, first sync
* the cache.
*/
ret = ib_cache_update(work->event.device, work->event.element.port_num,
work->enforce_security);
/* GID event is notified already for individual GID entries by
* dispatch_gid_change_event(). Hence, notifiy for rest of the
* events.
*/
if (!ret && work->event.event != IB_EVENT_GID_CHANGE)
ib_dispatch_event_clients(&work->event);
kfree(work);
} }
static void ib_cache_task(struct work_struct *_work) static void ib_generic_event_task(struct work_struct *_work)
{ {
struct ib_update_work *work = struct ib_update_work *work =
container_of(_work, struct ib_update_work, work); container_of(_work, struct ib_update_work, work);
ib_cache_update(work->device, ib_dispatch_event_clients(&work->event);
work->port_num,
work->enforce_security);
kfree(work); kfree(work);
} }
static void ib_cache_event(struct ib_event_handler *handler, static bool is_cache_update_event(const struct ib_event *event)
struct ib_event *event) {
return (event->event == IB_EVENT_PORT_ERR ||
event->event == IB_EVENT_PORT_ACTIVE ||
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_CLIENT_REREGISTER ||
event->event == IB_EVENT_GID_CHANGE);
}
/**
* ib_dispatch_event - Dispatch an asynchronous event
* @event:Event to dispatch
*
* Low-level drivers must call ib_dispatch_event() to dispatch the
* event to all registered event handlers when an asynchronous event
* occurs.
*/
void ib_dispatch_event(const struct ib_event *event)
{ {
struct ib_update_work *work; struct ib_update_work *work;
if (event->event == IB_EVENT_PORT_ERR || work = kzalloc(sizeof(*work), GFP_ATOMIC);
event->event == IB_EVENT_PORT_ACTIVE || if (!work)
event->event == IB_EVENT_LID_CHANGE || return;
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_CLIENT_REREGISTER || if (is_cache_update_event(event))
event->event == IB_EVENT_GID_CHANGE) { INIT_WORK(&work->work, ib_cache_event_task);
work = kmalloc(sizeof *work, GFP_ATOMIC); else
if (work) { INIT_WORK(&work->work, ib_generic_event_task);
INIT_WORK(&work->work, ib_cache_task);
work->device = event->device; work->event = *event;
work->port_num = event->element.port_num; if (event->event == IB_EVENT_PKEY_CHANGE ||
if (event->event == IB_EVENT_PKEY_CHANGE || event->event == IB_EVENT_GID_CHANGE)
event->event == IB_EVENT_GID_CHANGE) work->enforce_security = true;
work->enforce_security = true;
else queue_work(ib_wq, &work->work);
work->enforce_security = false;
queue_work(ib_wq, &work->work);
}
}
} }
EXPORT_SYMBOL(ib_dispatch_event);
int ib_cache_setup_one(struct ib_device *device) int ib_cache_setup_one(struct ib_device *device)
{ {
unsigned int p; unsigned int p;
int err; int err;
rwlock_init(&device->cache.lock); rwlock_init(&device->cache_lock);
err = gid_table_setup_one(device); err = gid_table_setup_one(device);
if (err) if (err)
...@@ -1505,9 +1539,6 @@ int ib_cache_setup_one(struct ib_device *device) ...@@ -1505,9 +1539,6 @@ int ib_cache_setup_one(struct ib_device *device)
rdma_for_each_port (device, p) rdma_for_each_port (device, p)
ib_cache_update(device, p, true); ib_cache_update(device, p, true);
INIT_IB_EVENT_HANDLER(&device->cache.event_handler,
device, ib_cache_event);
ib_register_event_handler(&device->cache.event_handler);
return 0; return 0;
} }
...@@ -1529,14 +1560,12 @@ void ib_cache_release_one(struct ib_device *device) ...@@ -1529,14 +1560,12 @@ void ib_cache_release_one(struct ib_device *device)
void ib_cache_cleanup_one(struct ib_device *device) void ib_cache_cleanup_one(struct ib_device *device)
{ {
/* The cleanup function unregisters the event handler, /* The cleanup function waits for all in-progress workqueue
* waits for all in-progress workqueue elements and cleans * elements and cleans up the GID cache. This function should be
* up the GID cache. This function should be called after * called after the device was removed from the devices list and
* the device was removed from the devices list and all * all clients were removed, so the cache exists but is
* clients were removed, so the cache exists but is
* non-functional and shouldn't be updated anymore. * non-functional and shouldn't be updated anymore.
*/ */
ib_unregister_event_handler(&device->cache.event_handler);
flush_workqueue(ib_wq); flush_workqueue(ib_wq);
gid_table_cleanup_one(device); gid_table_cleanup_one(device);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* Trace points for the RDMA Connection Manager.
*
* Author: Chuck Lever <chuck.lever@oracle.com>
*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*/
#define CREATE_TRACE_POINTS
#include <rdma/rdma_cm.h>
#include <rdma/ib_cm.h>
#include "cma_priv.h"
#include "cma_trace.h"
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Trace point definitions for the RDMA Connect Manager.
*
* Author: Chuck Lever <chuck.lever@oracle.com>
*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM rdma_cma
#if !defined(_TRACE_RDMA_CMA_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_RDMA_CMA_H
#include <linux/tracepoint.h>
#include <trace/events/rdma.h>
/*
* enum ib_cm_event_type, from include/rdma/ib_cm.h
*/
#define IB_CM_EVENT_LIST \
ib_cm_event(REQ_ERROR) \
ib_cm_event(REQ_RECEIVED) \
ib_cm_event(REP_ERROR) \
ib_cm_event(REP_RECEIVED) \
ib_cm_event(RTU_RECEIVED) \
ib_cm_event(USER_ESTABLISHED) \
ib_cm_event(DREQ_ERROR) \
ib_cm_event(DREQ_RECEIVED) \
ib_cm_event(DREP_RECEIVED) \
ib_cm_event(TIMEWAIT_EXIT) \
ib_cm_event(MRA_RECEIVED) \
ib_cm_event(REJ_RECEIVED) \
ib_cm_event(LAP_ERROR) \
ib_cm_event(LAP_RECEIVED) \
ib_cm_event(APR_RECEIVED) \
ib_cm_event(SIDR_REQ_ERROR) \
ib_cm_event(SIDR_REQ_RECEIVED) \
ib_cm_event_end(SIDR_REP_RECEIVED)
#undef ib_cm_event
#undef ib_cm_event_end
#define ib_cm_event(x) TRACE_DEFINE_ENUM(IB_CM_##x);
#define ib_cm_event_end(x) TRACE_DEFINE_ENUM(IB_CM_##x);
IB_CM_EVENT_LIST
#undef ib_cm_event
#undef ib_cm_event_end
#define ib_cm_event(x) { IB_CM_##x, #x },
#define ib_cm_event_end(x) { IB_CM_##x, #x }
#define rdma_show_ib_cm_event(x) \
__print_symbolic(x, IB_CM_EVENT_LIST)
DECLARE_EVENT_CLASS(cma_fsm_class,
TP_PROTO(
const struct rdma_id_private *id_priv
),
TP_ARGS(id_priv),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, tos)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->tos = id_priv->tos;
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr, __entry->tos
)
);
#define DEFINE_CMA_FSM_EVENT(name) \
DEFINE_EVENT(cma_fsm_class, cm_##name, \
TP_PROTO( \
const struct rdma_id_private *id_priv \
), \
TP_ARGS(id_priv))
DEFINE_CMA_FSM_EVENT(send_rtu);
DEFINE_CMA_FSM_EVENT(send_rej);
DEFINE_CMA_FSM_EVENT(send_mra);
DEFINE_CMA_FSM_EVENT(send_sidr_req);
DEFINE_CMA_FSM_EVENT(send_sidr_rep);
DEFINE_CMA_FSM_EVENT(disconnect);
DEFINE_CMA_FSM_EVENT(sent_drep);
DEFINE_CMA_FSM_EVENT(sent_dreq);
DEFINE_CMA_FSM_EVENT(id_destroy);
TRACE_EVENT(cm_id_create,
TP_PROTO(
const struct rdma_id_private *id_priv
),
TP_ARGS(id_priv),
TP_STRUCT__entry(
__field(u32, cm_id)
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
),
TP_printk("cm.id=%u",
__entry->cm_id
)
);
DECLARE_EVENT_CLASS(cma_qp_class,
TP_PROTO(
const struct rdma_id_private *id_priv
),
TP_ARGS(id_priv),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, tos)
__field(u32, qp_num)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->tos = id_priv->tos;
__entry->qp_num = id_priv->qp_num;
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u qp_num=%u",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr, __entry->tos,
__entry->qp_num
)
);
#define DEFINE_CMA_QP_EVENT(name) \
DEFINE_EVENT(cma_qp_class, cm_##name, \
TP_PROTO( \
const struct rdma_id_private *id_priv \
), \
TP_ARGS(id_priv))
DEFINE_CMA_QP_EVENT(send_req);
DEFINE_CMA_QP_EVENT(send_rep);
DEFINE_CMA_QP_EVENT(qp_destroy);
/*
* enum ib_wp_type, from include/rdma/ib_verbs.h
*/
#define IB_QP_TYPE_LIST \
ib_qp_type(SMI) \
ib_qp_type(GSI) \
ib_qp_type(RC) \
ib_qp_type(UC) \
ib_qp_type(UD) \
ib_qp_type(RAW_IPV6) \
ib_qp_type(RAW_ETHERTYPE) \
ib_qp_type(RAW_PACKET) \
ib_qp_type(XRC_INI) \
ib_qp_type_end(XRC_TGT)
#undef ib_qp_type
#undef ib_qp_type_end
#define ib_qp_type(x) TRACE_DEFINE_ENUM(IB_QPT_##x);
#define ib_qp_type_end(x) TRACE_DEFINE_ENUM(IB_QPT_##x);
IB_QP_TYPE_LIST
#undef ib_qp_type
#undef ib_qp_type_end
#define ib_qp_type(x) { IB_QPT_##x, #x },
#define ib_qp_type_end(x) { IB_QPT_##x, #x }
#define rdma_show_qp_type(x) \
__print_symbolic(x, IB_QP_TYPE_LIST)
TRACE_EVENT(cm_qp_create,
TP_PROTO(
const struct rdma_id_private *id_priv,
const struct ib_pd *pd,
const struct ib_qp_init_attr *qp_init_attr,
int rc
),
TP_ARGS(id_priv, pd, qp_init_attr, rc),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, pd_id)
__field(u32, tos)
__field(u32, qp_num)
__field(u32, send_wr)
__field(u32, recv_wr)
__field(int, rc)
__field(unsigned long, qp_type)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->pd_id = pd->res.id;
__entry->tos = id_priv->tos;
__entry->send_wr = qp_init_attr->cap.max_send_wr;
__entry->recv_wr = qp_init_attr->cap.max_recv_wr;
__entry->rc = rc;
if (!rc) {
__entry->qp_num = id_priv->qp_num;
__entry->qp_type = id_priv->id.qp_type;
} else {
__entry->qp_num = 0;
__entry->qp_type = 0;
}
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u pd.id=%u qp_type=%s"
" send_wr=%u recv_wr=%u qp_num=%u rc=%d",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr,
__entry->tos, __entry->pd_id,
rdma_show_qp_type(__entry->qp_type), __entry->send_wr,
__entry->recv_wr, __entry->qp_num, __entry->rc
)
);
TRACE_EVENT(cm_req_handler,
TP_PROTO(
const struct rdma_id_private *id_priv,
int event
),
TP_ARGS(id_priv, event),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, tos)
__field(unsigned long, event)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->tos = id_priv->tos;
__entry->event = event;
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u %s (%lu)",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr, __entry->tos,
rdma_show_ib_cm_event(__entry->event), __entry->event
)
);
TRACE_EVENT(cm_event_handler,
TP_PROTO(
const struct rdma_id_private *id_priv,
const struct rdma_cm_event *event
),
TP_ARGS(id_priv, event),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, tos)
__field(unsigned long, event)
__field(int, status)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->tos = id_priv->tos;
__entry->event = event->event;
__entry->status = event->status;
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u %s (%lu/%d)",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr, __entry->tos,
rdma_show_cm_event(__entry->event), __entry->event,
__entry->status
)
);
TRACE_EVENT(cm_event_done,
TP_PROTO(
const struct rdma_id_private *id_priv,
const struct rdma_cm_event *event,
int result
),
TP_ARGS(id_priv, event, result),
TP_STRUCT__entry(
__field(u32, cm_id)
__field(u32, tos)
__field(unsigned long, event)
__field(int, result)
__array(unsigned char, srcaddr, sizeof(struct sockaddr_in6))
__array(unsigned char, dstaddr, sizeof(struct sockaddr_in6))
),
TP_fast_assign(
__entry->cm_id = id_priv->res.id;
__entry->tos = id_priv->tos;
__entry->event = event->event;
__entry->result = result;
memcpy(__entry->srcaddr, &id_priv->id.route.addr.src_addr,
sizeof(struct sockaddr_in6));
memcpy(__entry->dstaddr, &id_priv->id.route.addr.dst_addr,
sizeof(struct sockaddr_in6));
),
TP_printk("cm.id=%u src=%pISpc dst=%pISpc tos=%u %s consumer returns %d",
__entry->cm_id, __entry->srcaddr, __entry->dstaddr, __entry->tos,
rdma_show_cm_event(__entry->event), __entry->result
)
);
DECLARE_EVENT_CLASS(cma_client_class,
TP_PROTO(
const struct ib_device *device
),
TP_ARGS(device),
TP_STRUCT__entry(
__string(name, device->name)
),
TP_fast_assign(
__assign_str(name, device->name);
),
TP_printk("device name=%s",
__get_str(name)
)
);
#define DEFINE_CMA_CLIENT_EVENT(name) \
DEFINE_EVENT(cma_client_class, cm_##name, \
TP_PROTO( \
const struct ib_device *device \
), \
TP_ARGS(device))
DEFINE_CMA_CLIENT_EVENT(add_one);
DEFINE_CMA_CLIENT_EVENT(remove_one);
#endif /* _TRACE_RDMA_CMA_H */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE cma_trace
#include <trace/define_trace.h>
...@@ -149,6 +149,7 @@ unsigned long roce_gid_type_mask_support(struct ib_device *ib_dev, u8 port); ...@@ -149,6 +149,7 @@ unsigned long roce_gid_type_mask_support(struct ib_device *ib_dev, u8 port);
int ib_cache_setup_one(struct ib_device *device); int ib_cache_setup_one(struct ib_device *device);
void ib_cache_cleanup_one(struct ib_device *device); void ib_cache_cleanup_one(struct ib_device *device);
void ib_cache_release_one(struct ib_device *device); void ib_cache_release_one(struct ib_device *device);
void ib_dispatch_event_clients(struct ib_event *event);
#ifdef CONFIG_CGROUP_RDMA #ifdef CONFIG_CGROUP_RDMA
void ib_device_register_rdmacg(struct ib_device *device); void ib_device_register_rdmacg(struct ib_device *device);
...@@ -320,7 +321,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, ...@@ -320,7 +321,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
struct ib_pd *pd, struct ib_pd *pd,
struct ib_qp_init_attr *attr, struct ib_qp_init_attr *attr,
struct ib_udata *udata, struct ib_udata *udata,
struct ib_uobject *uobj) struct ib_uqp_object *uobj)
{ {
enum ib_qp_type qp_type = attr->qp_type; enum ib_qp_type qp_type = attr->qp_type;
struct ib_qp *qp; struct ib_qp *qp;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <trace/events/rdma_core.h>
/* # of WCs to poll for with a single call to ib_poll_cq */ /* # of WCs to poll for with a single call to ib_poll_cq */
#define IB_POLL_BATCH 16 #define IB_POLL_BATCH 16
#define IB_POLL_BATCH_DIRECT 8 #define IB_POLL_BATCH_DIRECT 8
...@@ -41,6 +43,7 @@ static void ib_cq_rdma_dim_work(struct work_struct *w) ...@@ -41,6 +43,7 @@ static void ib_cq_rdma_dim_work(struct work_struct *w)
dim->state = DIM_START_MEASURE; dim->state = DIM_START_MEASURE;
trace_cq_modify(cq, comps, usec);
cq->device->ops.modify_cq(cq, comps, usec); cq->device->ops.modify_cq(cq, comps, usec);
} }
...@@ -65,18 +68,29 @@ static void rdma_dim_init(struct ib_cq *cq) ...@@ -65,18 +68,29 @@ static void rdma_dim_init(struct ib_cq *cq)
INIT_WORK(&dim->work, ib_cq_rdma_dim_work); INIT_WORK(&dim->work, ib_cq_rdma_dim_work);
} }
static int __poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
{
int rc;
rc = ib_poll_cq(cq, num_entries, wc);
trace_cq_poll(cq, num_entries, rc);
return rc;
}
static int __ib_process_cq(struct ib_cq *cq, int budget, struct ib_wc *wcs, static int __ib_process_cq(struct ib_cq *cq, int budget, struct ib_wc *wcs,
int batch) int batch)
{ {
int i, n, completed = 0; int i, n, completed = 0;
trace_cq_process(cq);
/* /*
* budget might be (-1) if the caller does not * budget might be (-1) if the caller does not
* want to bound this call, thus we need unsigned * want to bound this call, thus we need unsigned
* minimum here. * minimum here.
*/ */
while ((n = ib_poll_cq(cq, min_t(u32, batch, while ((n = __poll_cq(cq, min_t(u32, batch,
budget - completed), wcs)) > 0) { budget - completed), wcs)) > 0) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct ib_wc *wc = &wcs[i]; struct ib_wc *wc = &wcs[i];
...@@ -131,8 +145,10 @@ static int ib_poll_handler(struct irq_poll *iop, int budget) ...@@ -131,8 +145,10 @@ static int ib_poll_handler(struct irq_poll *iop, int budget)
completed = __ib_process_cq(cq, budget, cq->wc, IB_POLL_BATCH); completed = __ib_process_cq(cq, budget, cq->wc, IB_POLL_BATCH);
if (completed < budget) { if (completed < budget) {
irq_poll_complete(&cq->iop); irq_poll_complete(&cq->iop);
if (ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0) if (ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0) {
trace_cq_reschedule(cq);
irq_poll_sched(&cq->iop); irq_poll_sched(&cq->iop);
}
} }
if (dim) if (dim)
...@@ -143,6 +159,7 @@ static int ib_poll_handler(struct irq_poll *iop, int budget) ...@@ -143,6 +159,7 @@ static int ib_poll_handler(struct irq_poll *iop, int budget)
static void ib_cq_completion_softirq(struct ib_cq *cq, void *private) static void ib_cq_completion_softirq(struct ib_cq *cq, void *private)
{ {
trace_cq_schedule(cq);
irq_poll_sched(&cq->iop); irq_poll_sched(&cq->iop);
} }
...@@ -162,6 +179,7 @@ static void ib_cq_poll_work(struct work_struct *work) ...@@ -162,6 +179,7 @@ static void ib_cq_poll_work(struct work_struct *work)
static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private) static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private)
{ {
trace_cq_schedule(cq);
queue_work(cq->comp_wq, &cq->work); queue_work(cq->comp_wq, &cq->work);
} }
...@@ -239,6 +257,7 @@ struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private, ...@@ -239,6 +257,7 @@ struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private,
goto out_destroy_cq; goto out_destroy_cq;
} }
trace_cq_alloc(cq, nr_cqe, comp_vector, poll_ctx);
return cq; return cq;
out_destroy_cq: out_destroy_cq:
...@@ -248,6 +267,7 @@ struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private, ...@@ -248,6 +267,7 @@ struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private,
kfree(cq->wc); kfree(cq->wc);
out_free_cq: out_free_cq:
kfree(cq); kfree(cq);
trace_cq_alloc_error(nr_cqe, comp_vector, poll_ctx, ret);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
EXPORT_SYMBOL(__ib_alloc_cq_user); EXPORT_SYMBOL(__ib_alloc_cq_user);
...@@ -304,6 +324,7 @@ void ib_free_cq_user(struct ib_cq *cq, struct ib_udata *udata) ...@@ -304,6 +324,7 @@ void ib_free_cq_user(struct ib_cq *cq, struct ib_udata *udata)
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
trace_cq_free(cq);
rdma_restrack_del(&cq->res); rdma_restrack_del(&cq->res);
cq->device->ops.destroy_cq(cq, udata); cq->device->ops.destroy_cq(cq, udata);
if (cq->dim) if (cq->dim)
......
...@@ -587,7 +587,8 @@ struct ib_device *_ib_alloc_device(size_t size) ...@@ -587,7 +587,8 @@ struct ib_device *_ib_alloc_device(size_t size)
rdma_init_coredev(&device->coredev, device, &init_net); rdma_init_coredev(&device->coredev, device, &init_net);
INIT_LIST_HEAD(&device->event_handler_list); INIT_LIST_HEAD(&device->event_handler_list);
spin_lock_init(&device->event_handler_lock); spin_lock_init(&device->qp_open_list_lock);
init_rwsem(&device->event_handler_rwsem);
mutex_init(&device->unregistration_lock); mutex_init(&device->unregistration_lock);
/* /*
* client_data needs to be alloc because we don't want our mark to be * client_data needs to be alloc because we don't want our mark to be
...@@ -1931,17 +1932,15 @@ EXPORT_SYMBOL(ib_set_client_data); ...@@ -1931,17 +1932,15 @@ EXPORT_SYMBOL(ib_set_client_data);
* *
* ib_register_event_handler() registers an event handler that will be * ib_register_event_handler() registers an event handler that will be
* called back when asynchronous IB events occur (as defined in * called back when asynchronous IB events occur (as defined in
* chapter 11 of the InfiniBand Architecture Specification). This * chapter 11 of the InfiniBand Architecture Specification). This
* callback may occur in interrupt context. * callback occurs in workqueue context.
*/ */
void ib_register_event_handler(struct ib_event_handler *event_handler) void ib_register_event_handler(struct ib_event_handler *event_handler)
{ {
unsigned long flags; down_write(&event_handler->device->event_handler_rwsem);
spin_lock_irqsave(&event_handler->device->event_handler_lock, flags);
list_add_tail(&event_handler->list, list_add_tail(&event_handler->list,
&event_handler->device->event_handler_list); &event_handler->device->event_handler_list);
spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags); up_write(&event_handler->device->event_handler_rwsem);
} }
EXPORT_SYMBOL(ib_register_event_handler); EXPORT_SYMBOL(ib_register_event_handler);
...@@ -1954,35 +1953,23 @@ EXPORT_SYMBOL(ib_register_event_handler); ...@@ -1954,35 +1953,23 @@ EXPORT_SYMBOL(ib_register_event_handler);
*/ */
void ib_unregister_event_handler(struct ib_event_handler *event_handler) void ib_unregister_event_handler(struct ib_event_handler *event_handler)
{ {
unsigned long flags; down_write(&event_handler->device->event_handler_rwsem);
spin_lock_irqsave(&event_handler->device->event_handler_lock, flags);
list_del(&event_handler->list); list_del(&event_handler->list);
spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags); up_write(&event_handler->device->event_handler_rwsem);
} }
EXPORT_SYMBOL(ib_unregister_event_handler); EXPORT_SYMBOL(ib_unregister_event_handler);
/** void ib_dispatch_event_clients(struct ib_event *event)
* ib_dispatch_event - Dispatch an asynchronous event
* @event:Event to dispatch
*
* Low-level drivers must call ib_dispatch_event() to dispatch the
* event to all registered event handlers when an asynchronous event
* occurs.
*/
void ib_dispatch_event(struct ib_event *event)
{ {
unsigned long flags;
struct ib_event_handler *handler; struct ib_event_handler *handler;
spin_lock_irqsave(&event->device->event_handler_lock, flags); down_read(&event->device->event_handler_rwsem);
list_for_each_entry(handler, &event->device->event_handler_list, list) list_for_each_entry(handler, &event->device->event_handler_list, list)
handler->handler(handler, event); handler->handler(handler, event);
spin_unlock_irqrestore(&event->device->event_handler_lock, flags); up_read(&event->device->event_handler_rwsem);
} }
EXPORT_SYMBOL(ib_dispatch_event);
static int iw_query_port(struct ib_device *device, static int iw_query_port(struct ib_device *device,
u8 port_num, u8 port_num,
...@@ -1990,7 +1977,6 @@ static int iw_query_port(struct ib_device *device, ...@@ -1990,7 +1977,6 @@ static int iw_query_port(struct ib_device *device,
{ {
struct in_device *inetdev; struct in_device *inetdev;
struct net_device *netdev; struct net_device *netdev;
int err;
memset(port_attr, 0, sizeof(*port_attr)); memset(port_attr, 0, sizeof(*port_attr));
...@@ -2021,11 +2007,7 @@ static int iw_query_port(struct ib_device *device, ...@@ -2021,11 +2007,7 @@ static int iw_query_port(struct ib_device *device,
} }
dev_put(netdev); dev_put(netdev);
err = device->ops.query_port(device, port_num, port_attr); return device->ops.query_port(device, port_num, port_attr);
if (err)
return err;
return 0;
} }
static int __ib_query_port(struct ib_device *device, static int __ib_query_port(struct ib_device *device,
......
...@@ -232,7 +232,9 @@ void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry) ...@@ -232,7 +232,9 @@ void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry)
if (!entry) if (!entry)
return; return;
xa_lock(&entry->ucontext->mmap_xa);
entry->driver_removed = true; entry->driver_removed = true;
xa_unlock(&entry->ucontext->mmap_xa);
kref_put(&entry->ref, rdma_user_mmap_entry_free); kref_put(&entry->ref, rdma_user_mmap_entry_free);
} }
EXPORT_SYMBOL(rdma_user_mmap_entry_remove); EXPORT_SYMBOL(rdma_user_mmap_entry_remove);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "core_priv.h" #include "core_priv.h"
#include "cma_priv.h" #include "cma_priv.h"
#include "restrack.h" #include "restrack.h"
#include "uverbs.h"
typedef int (*res_fill_func_t)(struct sk_buff*, bool, typedef int (*res_fill_func_t)(struct sk_buff*, bool,
struct rdma_restrack_entry*, uint32_t); struct rdma_restrack_entry*, uint32_t);
...@@ -599,7 +600,7 @@ static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin, ...@@ -599,7 +600,7 @@ static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin,
goto err; goto err;
if (!rdma_is_kernel_res(res) && if (!rdma_is_kernel_res(res) &&
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN, nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,
cq->uobject->context->res.id)) cq->uobject->uevent.uobject.context->res.id))
goto err; goto err;
if (fill_res_name_pid(msg, res)) if (fill_res_name_pid(msg, res))
......
This diff is collapsed.
...@@ -50,29 +50,6 @@ void uverbs_destroy_ufile_hw(struct ib_uverbs_file *ufile, ...@@ -50,29 +50,6 @@ void uverbs_destroy_ufile_hw(struct ib_uverbs_file *ufile,
int uobj_destroy(struct ib_uobject *uobj, struct uverbs_attr_bundle *attrs); int uobj_destroy(struct ib_uobject *uobj, struct uverbs_attr_bundle *attrs);
/*
* uverbs_uobject_get is called in order to increase the reference count on
* an uobject. This is useful when a handler wants to keep the uobject's memory
* alive, regardless if this uobject is still alive in the context's objects
* repository. Objects are put via uverbs_uobject_put.
*/
void uverbs_uobject_get(struct ib_uobject *uobject);
/*
* In order to indicate we no longer needs this uobject, uverbs_uobject_put
* is called. When the reference count is decreased, the uobject is freed.
* For example, this is used when attaching a completion channel to a CQ.
*/
void uverbs_uobject_put(struct ib_uobject *uobject);
/* Indicate this fd is no longer used by this consumer, but its memory isn't
* necessarily released yet. When the last reference is put, we release the
* memory. After this call is executed, calling uverbs_uobject_get isn't
* allowed.
* This must be called from the release file_operations of the file!
*/
void uverbs_close_fd(struct file *f);
/* /*
* Get an ib_uobject that corresponds to the given id from ufile, assuming * Get an ib_uobject that corresponds to the given id from ufile, assuming
* the object is from the given type. Lock it to the required access when * the object is from the given type. Lock it to the required access when
...@@ -86,24 +63,9 @@ struct ib_uobject * ...@@ -86,24 +63,9 @@ struct ib_uobject *
uverbs_get_uobject_from_file(u16 object_id, enum uverbs_obj_access access, uverbs_get_uobject_from_file(u16 object_id, enum uverbs_obj_access access,
s64 id, struct uverbs_attr_bundle *attrs); s64 id, struct uverbs_attr_bundle *attrs);
/* void uverbs_finalize_object(struct ib_uobject *uobj,
* Note that certain finalize stages could return a status: enum uverbs_obj_access access, bool commit,
* (a) alloc_commit could return a failure if the object is committed at the struct uverbs_attr_bundle *attrs);
* same time when the context is destroyed.
* (b) remove_commit could fail if the object wasn't destroyed successfully.
* Since multiple objects could be finalized in one transaction, it is very NOT
* recommended to have several finalize actions which have side effects.
* For example, it's NOT recommended to have a certain action which has both
* a commit action and a destroy action or two destroy objects in the same
* action. The rule of thumb is to have one destroy or commit action with
* multiple lookups.
* The first non zero return value of finalize_object is returned from this
* function. For example, this could happen when we couldn't destroy an
* object.
*/
int uverbs_finalize_object(struct ib_uobject *uobj,
enum uverbs_obj_access access, bool commit,
struct uverbs_attr_bundle *attrs);
int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx); int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
...@@ -189,6 +151,7 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm, ...@@ -189,6 +151,7 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
unsigned int num_attrs); unsigned int num_attrs);
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile); void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);
extern const struct uapi_definition uverbs_def_obj_async_fd[];
extern const struct uapi_definition uverbs_def_obj_counters[]; extern const struct uapi_definition uverbs_def_obj_counters[];
extern const struct uapi_definition uverbs_def_obj_cq[]; extern const struct uapi_definition uverbs_def_obj_cq[];
extern const struct uapi_definition uverbs_def_obj_device[]; extern const struct uapi_definition uverbs_def_obj_device[];
......
...@@ -1068,7 +1068,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb, ...@@ -1068,7 +1068,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
} }
settimeout_out: settimeout_out:
return skb->len; return 0;
} }
static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh) static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh)
...@@ -1139,7 +1139,7 @@ int ib_nl_handle_resolve_resp(struct sk_buff *skb, ...@@ -1139,7 +1139,7 @@ int ib_nl_handle_resolve_resp(struct sk_buff *skb,
} }
resp_out: resp_out:
return skb->len; return 0;
} }
static void free_sm_ah(struct kref *kref) static void free_sm_ah(struct kref *kref)
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Trace points for core RDMA functions.
*
* Author: Chuck Lever <chuck.lever@oracle.com>
*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*/
#define CREATE_TRACE_POINTS
#include <rdma/ib_verbs.h>
#include <trace/events/rdma_core.h>
...@@ -166,10 +166,13 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, ...@@ -166,10 +166,13 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
* for any address. * for any address.
*/ */
mask |= (sg_dma_address(sg) + pgoff) ^ va; mask |= (sg_dma_address(sg) + pgoff) ^ va;
if (i && i != (umem->nmap - 1))
/* restrict by length as well for interior SGEs */
mask |= sg_dma_len(sg);
va += sg_dma_len(sg) - pgoff; va += sg_dma_len(sg) - pgoff;
/* Except for the last entry, the ending iova alignment sets
* the maximum possible page size as the low bits of the iova
* must be zero when starting the next chunk.
*/
if (i != (umem->nmap - 1))
mask |= va;
pgoff = 0; pgoff = 0;
} }
best_pg_bit = rdma_find_pg_bit(mask, pgsz_bitmap); best_pg_bit = rdma_find_pg_bit(mask, pgsz_bitmap);
......
...@@ -227,21 +227,10 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device, ...@@ -227,21 +227,10 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device,
umem_odp->notifier.ops = ops; umem_odp->notifier.ops = ops;
umem_odp->page_shift = PAGE_SHIFT; umem_odp->page_shift = PAGE_SHIFT;
if (access & IB_ACCESS_HUGETLB) { #ifdef CONFIG_HUGETLB_PAGE
struct vm_area_struct *vma; if (access & IB_ACCESS_HUGETLB)
struct hstate *h; umem_odp->page_shift = HPAGE_SHIFT;
#endif
down_read(&mm->mmap_sem);
vma = find_vma(mm, ib_umem_start(umem_odp));
if (!vma || !is_vm_hugetlb_page(vma)) {
up_read(&mm->mmap_sem);
ret = -EINVAL;
goto err_free;
}
h = hstate_vma(vma);
umem_odp->page_shift = huge_page_shift(h);
up_read(&mm->mmap_sem);
}
umem_odp->tgid = get_task_pid(current->group_leader, PIDTYPE_PID); umem_odp->tgid = get_task_pid(current->group_leader, PIDTYPE_PID);
ret = ib_init_umem_odp(umem_odp, ops); ret = ib_init_umem_odp(umem_odp, ops);
...@@ -251,7 +240,6 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device, ...@@ -251,7 +240,6 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device,
err_put_pid: err_put_pid:
put_pid(umem_odp->tgid); put_pid(umem_odp->tgid);
err_free:
kfree(umem_odp); kfree(umem_odp);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -424,7 +412,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt, ...@@ -424,7 +412,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt,
while (bcnt > 0) { while (bcnt > 0) {
const size_t gup_num_pages = min_t(size_t, const size_t gup_num_pages = min_t(size_t,
(bcnt + BIT(page_shift) - 1) >> page_shift, ALIGN(bcnt, PAGE_SIZE) / PAGE_SIZE,
PAGE_SIZE / sizeof(struct page *)); PAGE_SIZE / sizeof(struct page *));
down_read(&owning_mm->mmap_sem); down_read(&owning_mm->mmap_sem);
......
...@@ -111,7 +111,6 @@ struct ib_uverbs_device { ...@@ -111,7 +111,6 @@ struct ib_uverbs_device {
struct srcu_struct disassociate_srcu; struct srcu_struct disassociate_srcu;
struct mutex lists_mutex; /* protect lists */ struct mutex lists_mutex; /* protect lists */
struct list_head uverbs_file_list; struct list_head uverbs_file_list;
struct list_head uverbs_events_file_list;
struct uverbs_api *uapi; struct uverbs_api *uapi;
}; };
...@@ -124,10 +123,9 @@ struct ib_uverbs_event_queue { ...@@ -124,10 +123,9 @@ struct ib_uverbs_event_queue {
}; };
struct ib_uverbs_async_event_file { struct ib_uverbs_async_event_file {
struct ib_uobject uobj;
struct ib_uverbs_event_queue ev_queue; struct ib_uverbs_event_queue ev_queue;
struct ib_uverbs_file *uverbs_file; struct ib_event_handler event_handler;
struct kref ref;
struct list_head list;
}; };
struct ib_uverbs_completion_event_file { struct ib_uverbs_completion_event_file {
...@@ -144,8 +142,7 @@ struct ib_uverbs_file { ...@@ -144,8 +142,7 @@ struct ib_uverbs_file {
* ucontext_lock held * ucontext_lock held
*/ */
struct ib_ucontext *ucontext; struct ib_ucontext *ucontext;
struct ib_event_handler event_handler; struct ib_uverbs_async_event_file *async_file;
struct ib_uverbs_async_event_file *async_file;
struct list_head list; struct list_head list;
/* /*
...@@ -183,6 +180,7 @@ struct ib_uverbs_mcast_entry { ...@@ -183,6 +180,7 @@ struct ib_uverbs_mcast_entry {
struct ib_uevent_object { struct ib_uevent_object {
struct ib_uobject uobject; struct ib_uobject uobject;
/* List member for ib_uverbs_async_event_file list */
struct list_head event_list; struct list_head event_list;
u32 events_reported; u32 events_reported;
}; };
...@@ -210,25 +208,24 @@ struct ib_uwq_object { ...@@ -210,25 +208,24 @@ struct ib_uwq_object {
}; };
struct ib_ucq_object { struct ib_ucq_object {
struct ib_uobject uobject; struct ib_uevent_object uevent;
struct list_head comp_list; struct list_head comp_list;
struct list_head async_list;
u32 comp_events_reported; u32 comp_events_reported;
u32 async_events_reported;
}; };
extern const struct file_operations uverbs_event_fops; extern const struct file_operations uverbs_event_fops;
extern const struct file_operations uverbs_async_event_fops;
void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue); void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);
struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file, void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file);
struct ib_device *ib_dev); void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue);
void ib_uverbs_free_async_event_file(struct ib_uverbs_file *uverbs_file);
void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res); void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);
void ib_uverbs_release_ucq(struct ib_uverbs_file *file, int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs);
struct ib_uverbs_completion_event_file *ev_file, int ib_init_ucontext(struct uverbs_attr_bundle *attrs);
void ib_uverbs_release_ucq(struct ib_uverbs_completion_event_file *ev_file,
struct ib_ucq_object *uobj); struct ib_ucq_object *uobj);
void ib_uverbs_release_uevent(struct ib_uverbs_file *file, void ib_uverbs_release_uevent(struct ib_uevent_object *uobj);
struct ib_uevent_object *uobj);
void ib_uverbs_release_file(struct kref *ref); void ib_uverbs_release_file(struct kref *ref);
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
...@@ -236,8 +233,6 @@ void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); ...@@ -236,8 +233,6 @@ void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd, int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,
enum rdma_remove_reason why, enum rdma_remove_reason why,
struct uverbs_attr_bundle *attrs); struct uverbs_attr_bundle *attrs);
...@@ -276,23 +271,6 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type, ...@@ -276,23 +271,6 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
size_t kern_filter_sz, size_t kern_filter_sz,
union ib_flow_spec *ib_spec); union ib_flow_spec *ib_spec);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_DEVICE);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_PD);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_MR);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_COMP_CHANNEL);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_CQ);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_QP);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_AH);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_MW);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_SRQ);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_FLOW);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_WQ);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_XRCD);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_FLOW_ACTION);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_DM);
extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_COUNTERS);
/* /*
* ib_uverbs_query_port_resp.port_cap_flags started out as just a copy of the * ib_uverbs_query_port_resp.port_cap_flags started out as just a copy of the
* PortInfo CapabilityMask, but was extended with unique bits. * PortInfo CapabilityMask, but was extended with unique bits.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -677,7 +677,7 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev) ...@@ -677,7 +677,7 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
bnxt_qplib_get_guid(rdev->netdev->dev_addr, (u8 *)&ibdev->node_guid); bnxt_qplib_get_guid(rdev->netdev->dev_addr, (u8 *)&ibdev->node_guid);
ibdev->num_comp_vectors = 1; ibdev->num_comp_vectors = rdev->num_msix - 1;
ibdev->dev.parent = &rdev->en_dev->pdev->dev; ibdev->dev.parent = &rdev->en_dev->pdev->dev;
ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY; ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment