Skip to content

Commit

Permalink
Merge tag 'aux-sysfs-irqs' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/mellanox/linux

Saeed Mahameed says:

====================
aux-sysfs-irqs

Shay Says:
==========
Introduce auxiliary bus IRQs sysfs

Today, PCI PFs and VFs, which are anchored on the PCI bus, display their
IRQ information in the <pci_device>/msi_irqs/<irq_num> sysfs files.  PCI
subfunctions (SFs) are similar to PFs and VFs and these SFs are anchored
on the auxiliary bus. However, these PCI SFs lack such IRQ information
on the auxiliary bus, leaving users without visibility into which IRQs
are used by the SFs. This absence makes it impossible to debug
situations and to understand the source of interrupts/SFs for
performance tuning and debug.

Additionally, the SFs are multifunctional devices supporting RDMA,
network devices, clocks, and more, similar to their peer PCI PFs and
VFs. Therefore, it is desirable to have SFs' IRQ information available
at the bus/device level.

To overcome the above limitations, this short series extends the
auxiliary bus to display IRQ information in sysfs, similar to that of
PFs and VFs.

It adds an 'irqs' directory under the auxiliary device and includes an
<irq_num> sysfs file within it.

For example:
$ ls /sys/bus/auxiliary/devices/mlx5_core.sf.1/irqs/
50  51  52  53  54  55  56  57  58

Patch summary:
patch-1 adds auxiliary bus to support irqs used by auxiliary device
patch-2 mlx5 driver using exposing irqs for PCI SF devices via auxiliary
        bus
==========

* tag 'aux-sysfs-irqs' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux:
  net/mlx5: Expose SFs IRQs
  driver core: auxiliary bus: show auxiliary device IRQs
  RDMA/mlx5: Add Qcounters req_transport_retries_exceeded/req_rnr_retries_exceeded
  net/mlx5: Reimplement write combining test
====================

Link: https://patch.msgid.link/20240711213140.256997-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Jul 15, 2024
2 parents e7afb95 + 0477d51 commit dd3cd3c
Show file tree
Hide file tree
Showing 20 changed files with 651 additions and 246 deletions.
9 changes: 9 additions & 0 deletions Documentation/ABI/testing/sysfs-bus-auxiliary
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
What: /sys/bus/auxiliary/devices/.../irqs/
Date: April, 2024
Contact: Shay Drory <shayd@nvidia.com>
Description:
The /sys/devices/.../irqs directory contains a variable set of
files, with each file is named as irq number similar to PCI PF
or VF's irq number located in msi_irqs directory.
These irq files are added and removed dynamically when an IRQ
is requested and freed respectively for the PCI SF.
1 change: 1 addition & 0 deletions drivers/base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
ifeq ($(CONFIG_SYSFS),y)
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_AUXILIARY_BUS) += auxiliary_sysfs.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
obj-$(CONFIG_REGMAP) += regmap/
Expand Down
1 change: 1 addition & 0 deletions drivers/base/auxiliary.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ int auxiliary_device_init(struct auxiliary_device *auxdev)

dev->bus = &auxiliary_bus_type;
device_initialize(&auxdev->dev);
mutex_init(&auxdev->sysfs.lock);
return 0;
}
EXPORT_SYMBOL_GPL(auxiliary_device_init);
Expand Down
113 changes: 113 additions & 0 deletions drivers/base/auxiliary_sysfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
*/

#include <linux/auxiliary_bus.h>
#include <linux/slab.h>

#define AUXILIARY_MAX_IRQ_NAME 11

struct auxiliary_irq_info {
struct device_attribute sysfs_attr;
char name[AUXILIARY_MAX_IRQ_NAME];
};

static struct attribute *auxiliary_irq_attrs[] = {
NULL
};

static const struct attribute_group auxiliary_irqs_group = {
.name = "irqs",
.attrs = auxiliary_irq_attrs,
};

static int auxiliary_irq_dir_prepare(struct auxiliary_device *auxdev)
{
int ret = 0;

guard(mutex)(&auxdev->sysfs.lock);
if (auxdev->sysfs.irq_dir_exists)
return 0;

ret = devm_device_add_group(&auxdev->dev, &auxiliary_irqs_group);
if (ret)
return ret;

auxdev->sysfs.irq_dir_exists = true;
xa_init(&auxdev->sysfs.irqs);
return 0;
}

/**
* auxiliary_device_sysfs_irq_add - add a sysfs entry for the given IRQ
* @auxdev: auxiliary bus device to add the sysfs entry.
* @irq: The associated interrupt number.
*
* This function should be called after auxiliary device have successfully
* received the irq.
* The driver is responsible to add a unique irq for the auxiliary device. The
* driver can invoke this function from multiple thread context safely for
* unique irqs of the auxiliary devices. The driver must not invoke this API
* multiple times if the irq is already added previously.
*
* Return: zero on success or an error code on failure.
*/
int auxiliary_device_sysfs_irq_add(struct auxiliary_device *auxdev, int irq)
{
struct auxiliary_irq_info *info __free(kfree) = NULL;
struct device *dev = &auxdev->dev;
int ret;

ret = auxiliary_irq_dir_prepare(auxdev);
if (ret)
return ret;

info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;

sysfs_attr_init(&info->sysfs_attr.attr);
snprintf(info->name, AUXILIARY_MAX_IRQ_NAME, "%d", irq);

ret = xa_insert(&auxdev->sysfs.irqs, irq, info, GFP_KERNEL);
if (ret)
return ret;

info->sysfs_attr.attr.name = info->name;
ret = sysfs_add_file_to_group(&dev->kobj, &info->sysfs_attr.attr,
auxiliary_irqs_group.name);
if (ret)
goto sysfs_add_err;

xa_store(&auxdev->sysfs.irqs, irq, no_free_ptr(info), GFP_KERNEL);
return 0;

sysfs_add_err:
xa_erase(&auxdev->sysfs.irqs, irq);
return ret;
}
EXPORT_SYMBOL_GPL(auxiliary_device_sysfs_irq_add);

/**
* auxiliary_device_sysfs_irq_remove - remove a sysfs entry for the given IRQ
* @auxdev: auxiliary bus device to add the sysfs entry.
* @irq: the IRQ to remove.
*
* This function should be called to remove an IRQ sysfs entry.
* The driver must invoke this API when IRQ is released by the device.
*/
void auxiliary_device_sysfs_irq_remove(struct auxiliary_device *auxdev, int irq)
{
struct auxiliary_irq_info *info __free(kfree) = xa_load(&auxdev->sysfs.irqs, irq);
struct device *dev = &auxdev->dev;

if (!info) {
dev_err(&auxdev->dev, "IRQ %d doesn't exist\n", irq);
return;
}
sysfs_remove_file_from_group(&dev->kobj, &info->sysfs_attr.attr,
auxiliary_irqs_group.name);
xa_erase(&auxdev->sysfs.irqs, irq);
}
EXPORT_SYMBOL_GPL(auxiliary_device_sysfs_irq_remove);
4 changes: 4 additions & 0 deletions drivers/infiniband/hw/mlx5/counters.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ static const struct mlx5_ib_counter extended_err_cnts[] = {
INIT_Q_COUNTER(resp_remote_access_errors),
INIT_Q_COUNTER(resp_cqe_flush_error),
INIT_Q_COUNTER(req_cqe_flush_error),
INIT_Q_COUNTER(req_transport_retries_exceeded),
INIT_Q_COUNTER(req_rnr_retries_exceeded),
};

static const struct mlx5_ib_counter roce_accl_cnts[] = {
Expand All @@ -102,6 +104,8 @@ static const struct mlx5_ib_counter vport_extended_err_cnts[] = {
INIT_VPORT_Q_COUNTER(resp_remote_access_errors),
INIT_VPORT_Q_COUNTER(resp_cqe_flush_error),
INIT_VPORT_Q_COUNTER(req_cqe_flush_error),
INIT_VPORT_Q_COUNTER(req_transport_retries_exceeded),
INIT_VPORT_Q_COUNTER(req_rnr_retries_exceeded),
};

static const struct mlx5_ib_counter vport_roce_accl_cnts[] = {
Expand Down
19 changes: 3 additions & 16 deletions drivers/infiniband/hw/mlx5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,7 @@ static int set_ucontext_resp(struct ib_ucontext *uctx,
}

resp->qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
if (dev->wc_support)
if (mlx5_wc_support_get(dev->mdev))
resp->bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev,
log_bf_reg_size);
resp->cache_line_size = cache_line_size();
Expand Down Expand Up @@ -2337,7 +2337,7 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
switch (command) {
case MLX5_IB_MMAP_WC_PAGE:
case MLX5_IB_MMAP_ALLOC_WC:
if (!dev->wc_support)
if (!mlx5_wc_support_get(dev->mdev))
return -EPERM;
fallthrough;
case MLX5_IB_MMAP_NC_PAGE:
Expand Down Expand Up @@ -3612,7 +3612,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_UAR_OBJ_ALLOC)(
alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC)
return -EOPNOTSUPP;

if (!to_mdev(c->ibucontext.device)->wc_support &&
if (!mlx5_wc_support_get(to_mdev(c->ibucontext.device)->mdev) &&
alloc_type == MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF)
return -EOPNOTSUPP;

Expand Down Expand Up @@ -3766,18 +3766,6 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
return err;
}

static int mlx5_ib_enable_driver(struct ib_device *dev)
{
struct mlx5_ib_dev *mdev = to_mdev(dev);
int ret;

ret = mlx5_ib_test_wc(mdev);
mlx5_ib_dbg(mdev, "Write-Combining %s",
mdev->wc_support ? "supported" : "not supported");

return ret;
}

static const struct ib_device_ops mlx5_ib_dev_ops = {
.owner = THIS_MODULE,
.driver_id = RDMA_DRIVER_MLX5,
Expand Down Expand Up @@ -3808,7 +3796,6 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
.drain_rq = mlx5_ib_drain_rq,
.drain_sq = mlx5_ib_drain_sq,
.device_group = &mlx5_attr_group,
.enable_driver = mlx5_ib_enable_driver,
.get_dev_fw_str = get_dev_fw_str,
.get_dma_mr = mlx5_ib_get_dma_mr,
.get_link_layer = mlx5_ib_port_link_layer,
Expand Down
Loading

0 comments on commit dd3cd3c

Please sign in to comment.