Skip to content

Commit 1649091

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: add event log size sysfs attribute
Add support for changing of the event log size. Event log is a feature added to DSA 2.0 hardware to improve error reporting. It supersedes the SWERROR register on DSA 1.0 hardware and hope to prevent loss of reported errors. The error log size determines how many error entries supported for the device. It can be configured by the user via sysfs attribute. Tested-by: Tony Zhu <tony.zhu@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Co-developed-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Link: https://lore.kernel.org/r/20230407203143.2189681-3-fenghua.yu@intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 0c40bfb commit 1649091

5 files changed

Lines changed: 94 additions & 1 deletion

File tree

Documentation/ABI/stable/sysfs-driver-dma-idxd

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ Description: IAA (IAX) capability mask. Exported to user space for application
144144
consumption. This attribute should only be visible on IAA devices
145145
that are version 2 or later.
146146

147+
What: /sys/bus/dsa/devices/dsa<m>/event_log_size
148+
Date: Sept 14, 2022
149+
KernelVersion: 6.4.0
150+
Contact: dmaengine@vger.kernel.org
151+
Description: The event log size to be configured. Default is 64 entries and
152+
occupies 4k size if the evl entry is 64 bytes. It's visible
153+
only on platforms that support the capability.
154+
147155
What: /sys/bus/dsa/devices/wq<m>.<n>/block_on_fault
148156
Date: Oct 27, 2020
149157
KernelVersion: 5.11.0

drivers/dma/idxd/idxd.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ struct idxd_driver_data {
261261
int align;
262262
};
263263

264+
struct idxd_evl {
265+
u16 size;
266+
};
267+
264268
struct idxd_device {
265269
struct idxd_dev idxd_dev;
266270
struct idxd_driver_data *data;
@@ -317,6 +321,7 @@ struct idxd_device {
317321
struct idxd_pmu *idxd_pmu;
318322

319323
unsigned long *opcap_bmap;
324+
struct idxd_evl *evl;
320325
};
321326

322327
/* IDXD software descriptor */

drivers/dma/idxd/init.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,23 @@ static void idxd_cleanup_internals(struct idxd_device *idxd)
331331
destroy_workqueue(idxd->wq);
332332
}
333333

334+
static int idxd_init_evl(struct idxd_device *idxd)
335+
{
336+
struct device *dev = &idxd->pdev->dev;
337+
struct idxd_evl *evl;
338+
339+
if (idxd->hw.gen_cap.evl_support == 0)
340+
return 0;
341+
342+
evl = kzalloc_node(sizeof(*evl), GFP_KERNEL, dev_to_node(dev));
343+
if (!evl)
344+
return -ENOMEM;
345+
346+
evl->size = IDXD_EVL_SIZE_MIN;
347+
idxd->evl = evl;
348+
return 0;
349+
}
350+
334351
static int idxd_setup_internals(struct idxd_device *idxd)
335352
{
336353
struct device *dev = &idxd->pdev->dev;
@@ -356,8 +373,14 @@ static int idxd_setup_internals(struct idxd_device *idxd)
356373
goto err_wkq_create;
357374
}
358375

376+
rc = idxd_init_evl(idxd);
377+
if (rc < 0)
378+
goto err_evl;
379+
359380
return 0;
360381

382+
err_evl:
383+
destroy_workqueue(idxd->wq);
361384
err_wkq_create:
362385
for (i = 0; i < idxd->max_groups; i++)
363386
put_device(group_confdev(idxd->groups[i]));

drivers/dma/idxd/registers.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ union gen_cap_reg {
3131
u64 rsvd:3;
3232
u64 dest_readback:1;
3333
u64 drain_readback:1;
34-
u64 rsvd2:6;
34+
u64 rsvd2:3;
35+
u64 evl_support:2;
36+
u64 rsvd4:1;
3537
u64 max_xfer_shift:5;
3638
u64 max_batch_shift:4;
3739
u64 max_ims_mult:6;
@@ -297,6 +299,9 @@ union iaa_cap_reg {
297299

298300
#define IDXD_IAACAP_OFFSET 0x180
299301

302+
#define IDXD_EVL_SIZE_MIN 0x0040
303+
#define IDXD_EVL_SIZE_MAX 0xffff
304+
300305
union msix_perm {
301306
struct {
302307
u32 rsvd:2;

drivers/dma/idxd/sysfs.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,46 @@ static ssize_t iaa_cap_show(struct device *dev,
15731573
}
15741574
static DEVICE_ATTR_RO(iaa_cap);
15751575

1576+
static ssize_t event_log_size_show(struct device *dev,
1577+
struct device_attribute *attr, char *buf)
1578+
{
1579+
struct idxd_device *idxd = confdev_to_idxd(dev);
1580+
1581+
if (!idxd->evl)
1582+
return -EOPNOTSUPP;
1583+
1584+
return sysfs_emit(buf, "%u\n", idxd->evl->size);
1585+
}
1586+
1587+
static ssize_t event_log_size_store(struct device *dev,
1588+
struct device_attribute *attr,
1589+
const char *buf, size_t count)
1590+
{
1591+
struct idxd_device *idxd = confdev_to_idxd(dev);
1592+
unsigned long val;
1593+
int rc;
1594+
1595+
if (!idxd->evl)
1596+
return -EOPNOTSUPP;
1597+
1598+
rc = kstrtoul(buf, 10, &val);
1599+
if (rc < 0)
1600+
return -EINVAL;
1601+
1602+
if (idxd->state == IDXD_DEV_ENABLED)
1603+
return -EPERM;
1604+
1605+
if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1606+
return -EPERM;
1607+
1608+
if (val < IDXD_EVL_SIZE_MIN || val > IDXD_EVL_SIZE_MAX)
1609+
return -EINVAL;
1610+
1611+
idxd->evl->size = val;
1612+
return count;
1613+
}
1614+
static DEVICE_ATTR_RW(event_log_size);
1615+
15761616
static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr,
15771617
struct idxd_device *idxd)
15781618
{
@@ -1603,6 +1643,13 @@ static bool idxd_device_attr_iaa_cap_invisible(struct attribute *attr,
16031643
idxd->hw.version < DEVICE_VERSION_2);
16041644
}
16051645

1646+
static bool idxd_device_attr_event_log_size_invisible(struct attribute *attr,
1647+
struct idxd_device *idxd)
1648+
{
1649+
return (attr == &dev_attr_event_log_size.attr &&
1650+
!idxd->hw.gen_cap.evl_support);
1651+
}
1652+
16061653
static umode_t idxd_device_attr_visible(struct kobject *kobj,
16071654
struct attribute *attr, int n)
16081655
{
@@ -1618,6 +1665,9 @@ static umode_t idxd_device_attr_visible(struct kobject *kobj,
16181665
if (idxd_device_attr_iaa_cap_invisible(attr, idxd))
16191666
return 0;
16201667

1668+
if (idxd_device_attr_event_log_size_invisible(attr, idxd))
1669+
return 0;
1670+
16211671
return attr->mode;
16221672
}
16231673

@@ -1644,6 +1694,7 @@ static struct attribute *idxd_device_attributes[] = {
16441694
&dev_attr_cdev_major.attr,
16451695
&dev_attr_cmd_status.attr,
16461696
&dev_attr_iaa_cap.attr,
1697+
&dev_attr_event_log_size.attr,
16471698
NULL,
16481699
};
16491700

@@ -1665,6 +1716,7 @@ static void idxd_conf_device_release(struct device *dev)
16651716
bitmap_free(idxd->wq_enable_map);
16661717
kfree(idxd->wqs);
16671718
kfree(idxd->engines);
1719+
kfree(idxd->evl);
16681720
ida_free(&idxd_ida, idxd->id);
16691721
bitmap_free(idxd->opcap_bmap);
16701722
kfree(idxd);

0 commit comments

Comments
 (0)