Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/rdma/rdma

Pull rdma updates from Jason Gunthorpe:
 "Usual collection of small improvements and fixes:

   - Bug fixes and minor improvments in efa, irdma, mlx4, mlx5, rxe,
     hf1, qib, ocrdma

   - bnxt_re support for MSN, which is a new retransmit logic

   - Initial mana support for RC qps

   - Use after free bug and cleanups in iwcm

   - Reduce resource usage in mlx5 when RDMA verbs features are not used

   - New verb to drain shared recieve queues, similar to normal recieve
     queues. This is necessary to allow ULPs a clean shutdown. Used in
     the iscsi rdma target

   - mlx5 support for more than 16 bits of doorbell indexes

   - Doorbell moderation support for bnxt_re

   - IB multi-plane support for mlx5

   - New EFA adaptor PCI IDs

   - RDMA_NAME_ASSIGN_TYPE_USER to hint to userspace that it shouldn't
     rename the device

   - A collection of hns bugs

   - Fix long standing bug in bnxt_re with incorrect endian handling of
     immediate data"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (65 commits)
  IB/hfi1: Constify struct flag_table
  RDMA/mana_ib: Set correct device into ib
  bnxt_re: Fix imm_data endianness
  RDMA: Fix netdev tracker in ib_device_set_netdev
  RDMA/hns: Fix mbx timing out before CMD execution is completed
  RDMA/hns: Fix insufficient extend DB for VFs.
  RDMA/hns: Fix undifined behavior caused by invalid max_sge
  RDMA/hns: Fix shift-out-bounds when max_inline_data is 0
  RDMA/hns: Fix missing pagesize and alignment check in FRMR
  RDMA/hns: Fix unmatch exception handling when init eq table fails
  RDMA/hns: Fix soft lockup under heavy CEQE load
  RDMA/hns: Check atomic wr length
  RDMA/ocrdma: Don't inline statistics functions
  RDMA/core: Introduce "name_assign_type" for an IB device
  RDMA/qib: Fix truncation compilation warnings in qib_verbs.c
  RDMA/qib: Fix truncation compilation warnings in qib_init.c
  RDMA/efa: Add EFA 0xefa3 PCI ID
  RDMA/mlx5: Support per-plane port IB counters by querying PPCNT register
  net/mlx5: mlx5_ifc update for accessing ppcnt register of plane ports
  RDMA/mlx5: Add plane index support when querying PTYS registers
  ...
  • Loading branch information
torvalds committed Jul 19, 2024
2 parents ef7c8f2 + 887cd30 commit 3d51520
Show file tree
Hide file tree
Showing 106 changed files with 1,785 additions and 414 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -11207,7 +11207,7 @@ F: include/linux/net/intel/iidc.h

INTEL ETHERNET PROTOCOL DRIVER FOR RDMA
M: Mustafa Ismail <[email protected]>
M: Shiraz Saleem <shiraz.saleem@intel.com>
M: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
L: [email protected]
S: Supported
F: drivers/infiniband/hw/irdma/
Expand Down
32 changes: 22 additions & 10 deletions drivers/infiniband/core/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,16 @@ __ib_get_agent_port(const struct ib_device *device, int port_num)
struct ib_agent_port_private *entry;

list_for_each_entry(entry, &ib_agent_port_list, port_list) {
if (entry->agent[1]->device == device &&
/* Need to check both agent[0] and agent[1], as an agent port
* may only have one of them
*/
if (entry->agent[0] &&
entry->agent[0]->device == device &&
entry->agent[0]->port_num == port_num)
return entry;

if (entry->agent[1] &&
entry->agent[1]->device == device &&
entry->agent[1]->port_num == port_num)
return entry;
}
Expand Down Expand Up @@ -172,14 +181,16 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
}
}

/* Obtain send only MAD agent for GSI QP */
port_priv->agent[1] = ib_register_mad_agent(device, port_num,
IB_QPT_GSI, NULL, 0,
&agent_send_handler,
NULL, NULL, 0);
if (IS_ERR(port_priv->agent[1])) {
ret = PTR_ERR(port_priv->agent[1]);
goto error3;
if (rdma_cap_ib_cm(device, port_num)) {
/* Obtain send only MAD agent for GSI QP */
port_priv->agent[1] = ib_register_mad_agent(device, port_num,
IB_QPT_GSI, NULL, 0,
&agent_send_handler,
NULL, NULL, 0);
if (IS_ERR(port_priv->agent[1])) {
ret = PTR_ERR(port_priv->agent[1]);
goto error3;
}
}

spin_lock_irqsave(&ib_agent_port_list_lock, flags);
Expand Down Expand Up @@ -212,7 +223,8 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
list_del(&port_priv->port_list);
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);

ib_unregister_mad_agent(port_priv->agent[1]);
if (port_priv->agent[1])
ib_unregister_mad_agent(port_priv->agent[1]);
if (port_priv->agent[0])
ib_unregister_mad_agent(port_priv->agent[0]);

Expand Down
14 changes: 5 additions & 9 deletions drivers/infiniband/core/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,6 @@ static struct ib_gid_table *alloc_gid_table(int sz)
static void release_gid_table(struct ib_device *device,
struct ib_gid_table *table)
{
bool leak = false;
int i;

if (!table)
Expand All @@ -803,15 +802,12 @@ static void release_gid_table(struct ib_device *device,
for (i = 0; i < table->sz; i++) {
if (is_gid_entry_free(table->data_vec[i]))
continue;
if (kref_read(&table->data_vec[i]->kref) > 1) {
dev_err(&device->dev,
"GID entry ref leak for index %d ref=%u\n", i,
kref_read(&table->data_vec[i]->kref));
leak = true;
}

WARN_ONCE(true,
"GID entry ref leak for dev %s index %d ref=%u\n",
dev_name(&device->dev), i,
kref_read(&table->data_vec[i]->kref));
}
if (leak)
return;

mutex_destroy(&table->lock);
kfree(table->data_vec);
Expand Down
83 changes: 74 additions & 9 deletions drivers/infiniband/core/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ static void ib_device_release(struct device *device)
rcu_head);
}

mutex_destroy(&dev->subdev_lock);
mutex_destroy(&dev->unregistration_lock);
mutex_destroy(&dev->compat_devs_mutex);

Expand Down Expand Up @@ -641,6 +642,11 @@ struct ib_device *_ib_alloc_device(size_t size)
BIT_ULL(IB_USER_VERBS_CMD_REG_MR) |
BIT_ULL(IB_USER_VERBS_CMD_REREG_MR) |
BIT_ULL(IB_USER_VERBS_CMD_RESIZE_CQ);

mutex_init(&device->subdev_lock);
INIT_LIST_HEAD(&device->subdev_list_head);
INIT_LIST_HEAD(&device->subdev_list);

return device;
}
EXPORT_SYMBOL(_ib_alloc_device);
Expand Down Expand Up @@ -1461,6 +1467,18 @@ EXPORT_SYMBOL(ib_register_device);
/* Callers must hold a get on the device. */
static void __ib_unregister_device(struct ib_device *ib_dev)
{
struct ib_device *sub, *tmp;

mutex_lock(&ib_dev->subdev_lock);
list_for_each_entry_safe_reverse(sub, tmp,
&ib_dev->subdev_list_head,
subdev_list) {
list_del(&sub->subdev_list);
ib_dev->ops.del_sub_dev(sub);
ib_device_put(ib_dev);
}
mutex_unlock(&ib_dev->subdev_lock);

/*
* We have a registration lock so that all the calls to unregister are
* fully fenced, once any unregister returns the device is truely
Expand Down Expand Up @@ -2146,6 +2164,9 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
unsigned long flags;
int ret;

if (!rdma_is_port_valid(ib_dev, port))
return -EINVAL;

/*
* Drivers wish to call this before ib_register_driver, so we have to
* setup the port data early.
Expand All @@ -2154,9 +2175,6 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
if (ret)
return ret;

if (!rdma_is_port_valid(ib_dev, port))
return -EINVAL;

pdata = &ib_dev->port_data[port];
spin_lock_irqsave(&pdata->netdev_lock, flags);
old_ndev = rcu_dereference_protected(
Expand All @@ -2166,16 +2184,12 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
return 0;
}

if (old_ndev)
netdev_tracker_free(ndev, &pdata->netdev_tracker);
if (ndev)
netdev_hold(ndev, &pdata->netdev_tracker, GFP_ATOMIC);
rcu_assign_pointer(pdata->netdev, ndev);
netdev_put(old_ndev, &pdata->netdev_tracker);
netdev_hold(ndev, &pdata->netdev_tracker, GFP_ATOMIC);
spin_unlock_irqrestore(&pdata->netdev_lock, flags);

add_ndev_hash(pdata);
__dev_put(old_ndev);

return 0;
}
EXPORT_SYMBOL(ib_device_set_netdev);
Expand Down Expand Up @@ -2597,6 +2611,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
ops->uverbs_no_driver_id_binding;

SET_DEVICE_OP(dev_ops, add_gid);
SET_DEVICE_OP(dev_ops, add_sub_dev);
SET_DEVICE_OP(dev_ops, advise_mr);
SET_DEVICE_OP(dev_ops, alloc_dm);
SET_DEVICE_OP(dev_ops, alloc_hw_device_stats);
Expand Down Expand Up @@ -2631,6 +2646,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
SET_DEVICE_OP(dev_ops, dealloc_ucontext);
SET_DEVICE_OP(dev_ops, dealloc_xrcd);
SET_DEVICE_OP(dev_ops, del_gid);
SET_DEVICE_OP(dev_ops, del_sub_dev);
SET_DEVICE_OP(dev_ops, dereg_mr);
SET_DEVICE_OP(dev_ops, destroy_ah);
SET_DEVICE_OP(dev_ops, destroy_counters);
Expand Down Expand Up @@ -2727,6 +2743,55 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
}
EXPORT_SYMBOL(ib_set_device_ops);

int ib_add_sub_device(struct ib_device *parent,
enum rdma_nl_dev_type type,
const char *name)
{
struct ib_device *sub;
int ret = 0;

if (!parent->ops.add_sub_dev || !parent->ops.del_sub_dev)
return -EOPNOTSUPP;

if (!ib_device_try_get(parent))
return -EINVAL;

sub = parent->ops.add_sub_dev(parent, type, name);
if (IS_ERR(sub)) {
ib_device_put(parent);
return PTR_ERR(sub);
}

sub->type = type;
sub->parent = parent;

mutex_lock(&parent->subdev_lock);
list_add_tail(&parent->subdev_list_head, &sub->subdev_list);
mutex_unlock(&parent->subdev_lock);

return ret;
}
EXPORT_SYMBOL(ib_add_sub_device);

int ib_del_sub_device_and_put(struct ib_device *sub)
{
struct ib_device *parent = sub->parent;

if (!parent)
return -EOPNOTSUPP;

mutex_lock(&parent->subdev_lock);
list_del(&sub->subdev_list);
mutex_unlock(&parent->subdev_lock);

ib_device_put(sub);
parent->ops.del_sub_dev(sub);
ib_device_put(parent);

return 0;
}
EXPORT_SYMBOL(ib_del_sub_device_and_put);

#ifdef CONFIG_INFINIBAND_VIRT_DMA
int ib_dma_virt_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents)
{
Expand Down
41 changes: 18 additions & 23 deletions drivers/infiniband/core/iwcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ static struct iwcm_work *get_work(struct iwcm_id_private *cm_id_priv)

if (list_empty(&cm_id_priv->work_free_list))
return NULL;
work = list_entry(cm_id_priv->work_free_list.next, struct iwcm_work,
free_list);
work = list_first_entry(&cm_id_priv->work_free_list, struct iwcm_work,
free_list);
list_del_init(&work->free_list);
return work;
}
Expand Down Expand Up @@ -206,17 +206,17 @@ static void free_cm_id(struct iwcm_id_private *cm_id_priv)

/*
* Release a reference on cm_id. If the last reference is being
* released, free the cm_id and return 1.
* released, free the cm_id and return 'true'.
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
static bool iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
if (refcount_dec_and_test(&cm_id_priv->refcount)) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
free_cm_id(cm_id_priv);
return 1;
return true;
}

return 0;
return false;
}

static void add_ref(struct iw_cm_id *cm_id)
Expand Down Expand Up @@ -368,8 +368,10 @@ EXPORT_SYMBOL(iw_cm_disconnect);
*
* Clean up all resources associated with the connection and release
* the initial reference taken by iw_create_cm_id.
*
* Returns true if and only if the last cm_id_priv reference has been dropped.
*/
static void destroy_cm_id(struct iw_cm_id *cm_id)
static bool destroy_cm_id(struct iw_cm_id *cm_id)
{
struct iwcm_id_private *cm_id_priv;
struct ib_qp *qp;
Expand Down Expand Up @@ -439,7 +441,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
}

(void)iwcm_deref_id(cm_id_priv);
return iwcm_deref_id(cm_id_priv);
}

/*
Expand All @@ -450,7 +452,8 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
*/
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
{
destroy_cm_id(cm_id);
if (!destroy_cm_id(cm_id))
flush_workqueue(iwcm_wq);
}
EXPORT_SYMBOL(iw_destroy_cm_id);

Expand Down Expand Up @@ -1017,30 +1020,25 @@ static void cm_work_handler(struct work_struct *_work)
struct iw_cm_event levent;
struct iwcm_id_private *cm_id_priv = work->cm_id;
unsigned long flags;
int empty;
int ret = 0;

spin_lock_irqsave(&cm_id_priv->lock, flags);
empty = list_empty(&cm_id_priv->work_list);
while (!empty) {
work = list_entry(cm_id_priv->work_list.next,
struct iwcm_work, list);
while (!list_empty(&cm_id_priv->work_list)) {
work = list_first_entry(&cm_id_priv->work_list,
struct iwcm_work, list);
list_del_init(&work->list);
empty = list_empty(&cm_id_priv->work_list);
levent = work->event;
put_work(work);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);

if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
ret = process_event(cm_id_priv, &levent);
if (ret)
destroy_cm_id(&cm_id_priv->id);
WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
} else
pr_debug("dropping event %d\n", levent.event);
if (iwcm_deref_id(cm_id_priv))
return;
if (empty)
return;
spin_lock_irqsave(&cm_id_priv->lock, flags);
}
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
Expand Down Expand Up @@ -1093,11 +1091,8 @@ static int cm_event_handler(struct iw_cm_id *cm_id,
}

refcount_inc(&cm_id_priv->refcount);
if (list_empty(&cm_id_priv->work_list)) {
list_add_tail(&work->list, &cm_id_priv->work_list);
queue_work(iwcm_wq, &work->work);
} else
list_add_tail(&work->list, &cm_id_priv->work_list);
list_add_tail(&work->list, &cm_id_priv->work_list);
queue_work(iwcm_wq, &work->work);
out:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
return ret;
Expand Down
9 changes: 6 additions & 3 deletions drivers/infiniband/core/mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -2983,9 +2983,12 @@ static int ib_mad_port_open(struct ib_device *device,
if (ret)
goto error6;
}
ret = create_mad_qp(&port_priv->qp_info[1], IB_QPT_GSI);
if (ret)
goto error7;

if (rdma_cap_ib_cm(device, port_num)) {
ret = create_mad_qp(&port_priv->qp_info[1], IB_QPT_GSI);
if (ret)
goto error7;
}

snprintf(name, sizeof(name), "ib_mad%u", port_num);
port_priv->wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
Expand Down
Loading

0 comments on commit 3d51520

Please sign in to comment.