History

dmaengine: idxd: setup event log configuration

Add setup of event log feature for supported device. Event log addresses error reporting that was lacking in gen 1 DSA devices where a second error event does not get reported when a first event is pending software handling. The event log allows a circular buffer that the device can push error events to. It is up to the user to create a large enough event log ring in order to capture the expected events. The evl size can be set in the device sysfs attribute. By default 64 entries are supported as minimal when event log is enabled.

Dave Jiang committed 3 years ago

Commit 244da661 parent 16490916 files · +181 −4Browse files

Unified · Split

6 files
  1. drivers/dma/idxd/device.c +88 −1
  2. drivers/dma/idxd/idxd.h +19 −0
  3. drivers/dma/idxd/init.c +1 −0
  4. drivers/dma/idxd/registers.h +70 −2
  5. drivers/dma/idxd/sysfs.c +2 −1
  6. include/uapi/linux/idxd.h +1 −0
drivers/dma/idxd/device.c+88−1
@@ -752,6 +752,83 @@ void idxd_device_clear_state(struct idxd_device *idxd) · 751 unmodified lines
752 spin_unlock(&idxd->dev_lock);752 spin_unlock(&idxd->dev_lock);
753}753}
754 754
755static int idxd_device_evl_setup(struct idxd_device *idxd)
756{
757 union gencfg_reg gencfg;
758 union evlcfg_reg evlcfg;
759 union genctrl_reg genctrl;
760 struct device *dev = &idxd->pdev->dev;
761 void *addr;
762 dma_addr_t dma_addr;
763 int size;
764 struct idxd_evl *evl = idxd->evl;
765
766 if (!evl)
767 return 0;
768
769 size = evl_size(idxd);
770 /*
771 * Address needs to be page aligned. However, dma_alloc_coherent() provides
772 * at minimal page size aligned address. No manual alignment required.
773 */
774 addr = dma_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
775 if (!addr)
776 return -ENOMEM;
777
778 memset(addr, 0, size);
779
780 spin_lock(&evl->lock);
781 evl->log = addr;
782 evl->dma = dma_addr;
783 evl->log_size = size;
784
785 memset(&evlcfg, 0, sizeof(evlcfg));
786 evlcfg.bits[0] = dma_addr & GENMASK(63, 12);
787 evlcfg.size = evl->size;
788
789 iowrite64(evlcfg.bits[0], idxd->reg_base + IDXD_EVLCFG_OFFSET);
790 iowrite64(evlcfg.bits[1], idxd->reg_base + IDXD_EVLCFG_OFFSET + 8);
791
792 genctrl.bits = ioread32(idxd->reg_base + IDXD_GENCTRL_OFFSET);
793 genctrl.evl_int_en = 1;
794 iowrite32(genctrl.bits, idxd->reg_base + IDXD_GENCTRL_OFFSET);
795
796 gencfg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
797 gencfg.evl_en = 1;
798 iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
799
800 spin_unlock(&evl->lock);
801 return 0;
802}
803
804static void idxd_device_evl_free(struct idxd_device *idxd)
805{
806 union gencfg_reg gencfg;
807 union genctrl_reg genctrl;
808 struct device *dev = &idxd->pdev->dev;
809 struct idxd_evl *evl = idxd->evl;
810
811 gencfg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
812 if (!gencfg.evl_en)
813 return;
814
815 spin_lock(&evl->lock);
816 gencfg.evl_en = 0;
817 iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
818
819 genctrl.bits = ioread32(idxd->reg_base + IDXD_GENCTRL_OFFSET);
820 genctrl.evl_int_en = 0;
821 iowrite32(genctrl.bits, idxd->reg_base + IDXD_GENCTRL_OFFSET);
822
823 iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET);
824 iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET + 8);
825
826 dma_free_coherent(dev, evl->log_size, evl->log, evl->dma);
827 evl->log = NULL;
828 evl->size = IDXD_EVL_SIZE_MIN;
829 spin_unlock(&evl->lock);
830}
831
755static void idxd_group_config_write(struct idxd_group *group)832static void idxd_group_config_write(struct idxd_group *group)
756{833{
757 struct idxd_device *idxd = group->idxd;834 struct idxd_device *idxd = group->idxd;
@@ -1451,15 +1528,24 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev) · 693 unmodified lines
1451 if (rc < 0)1528 if (rc < 0)
1452 return -ENXIO;1529 return -ENXIO;
1453 1530
1531 rc = idxd_device_evl_setup(idxd);
1532 if (rc < 0) {
1533 idxd->cmd_status = IDXD_SCMD_DEV_EVL_ERR;
1534 return rc;
1535 }
1536
1454 /* Start device */1537 /* Start device */
1455 rc = idxd_device_enable(idxd);1538 rc = idxd_device_enable(idxd);
1456 if (rc < 0)1539 if (rc < 0) {
1540 idxd_device_evl_free(idxd);
1457 return rc;1541 return rc;
1542 }
1458 1543
1459 /* Setup DMA device without channels */1544 /* Setup DMA device without channels */
1460 rc = idxd_register_dma_device(idxd);1545 rc = idxd_register_dma_device(idxd);
1461 if (rc < 0) {1546 if (rc < 0) {
1462 idxd_device_disable(idxd);1547 idxd_device_disable(idxd);
1548 idxd_device_evl_free(idxd);
1463 idxd->cmd_status = IDXD_SCMD_DEV_DMA_ERR;1549 idxd->cmd_status = IDXD_SCMD_DEV_DMA_ERR;
1464 return rc;1550 return rc;
1465 }1551 }
@@ -1488,6 +1574,7 @@ void idxd_device_drv_remove(struct idxd_dev *idxd_dev) · 22 unmodified lines
1488 idxd_device_disable(idxd);1574 idxd_device_disable(idxd);
1489 if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))1575 if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1490 idxd_device_reset(idxd);1576 idxd_device_reset(idxd);
1577 idxd_device_evl_free(idxd);
1491}1578}
1492 1579
1493static enum idxd_dev_type dev_types[] = {1580static enum idxd_dev_type dev_types[] = {
drivers/dma/idxd/idxd.h+19−0
@@ -262,7 +262,15 @@ struct idxd_driver_data { · 261 unmodified lines
262};262};
263 263
264struct idxd_evl {264struct idxd_evl {
265 /* Lock to protect event log access. */
266 spinlock_t lock;
267 void *log;
268 dma_addr_t dma;
269 /* Total size of event log = number of entries * entry size. */
270 unsigned int log_size;
271 /* The number of entries in the event log. */
265 u16 size;272 u16 size;
273 u16 head;
266};274};
267 275
268struct idxd_device {276struct idxd_device {
@@ -324,6 +332,17 @@ struct idxd_device { · 55 unmodified lines
324 struct idxd_evl *evl;332 struct idxd_evl *evl;
325};333};
326 334
335static inline unsigned int evl_ent_size(struct idxd_device *idxd)
336{
337 return idxd->hw.gen_cap.evl_support ?
338 (32 * (1 << idxd->hw.gen_cap.evl_support)) : 0;
339}
340
341static inline unsigned int evl_size(struct idxd_device *idxd)
342{
343 return idxd->evl->size * evl_ent_size(idxd);
344}
345
327/* IDXD software descriptor */346/* IDXD software descriptor */
328struct idxd_desc {347struct idxd_desc {
329 union {348 union {
drivers/dma/idxd/init.c+1−0
@@ -343,6 +343,7 @@ static int idxd_init_evl(struct idxd_device *idxd) · 342 unmodified lines
343 if (!evl)343 if (!evl)
344 return -ENOMEM;344 return -ENOMEM;
345 345
346 spin_lock_init(&evl->lock);
346 evl->size = IDXD_EVL_SIZE_MIN;347 evl->size = IDXD_EVL_SIZE_MIN;
347 idxd->evl = evl;348 idxd->evl = evl;
348 return 0;349 return 0;
drivers/dma/idxd/registers.h+70−2
@@ -3,6 +3,8 @@ · 2 unmodified lines
3#ifndef _IDXD_REGISTERS_H_3#ifndef _IDXD_REGISTERS_H_
4#define _IDXD_REGISTERS_H_4#define _IDXD_REGISTERS_H_
5 5
6#include <uapi/linux/idxd.h>
7
6/* PCI Config */8/* PCI Config */
7#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b259#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25
8#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe10#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe
@@ -119,7 +121,8 @@ union gencfg_reg { · 110 unmodified lines
119 u32 rdbuf_limit:8;121 u32 rdbuf_limit:8;
120 u32 rsvd:4;122 u32 rsvd:4;
121 u32 user_int_en:1;123 u32 user_int_en:1;
122 u32 rsvd2:19;124 u32 evl_en:1;
125 u32 rsvd2:18;
123 };126 };
124 u32 bits;127 u32 bits;
125} __packed;128} __packed;
@@ -129,7 +132,8 @@ union genctrl_reg { · 3 unmodified lines
129 struct {132 struct {
130 u32 softerr_int_en:1;133 u32 softerr_int_en:1;
131 u32 halt_int_en:1;134 u32 halt_int_en:1;
132 u32 rsvd:30;135 u32 evl_int_en:1;
136 u32 rsvd:29;
133 };137 };
134 u32 bits;138 u32 bits;
135} __packed;139} __packed;
@@ -299,6 +303,21 @@ union iaa_cap_reg { · 163 unmodified lines
299 303
300#define IDXD_IAACAP_OFFSET 0x180304#define IDXD_IAACAP_OFFSET 0x180
301 305
306#define IDXD_EVLCFG_OFFSET 0xe0
307union evlcfg_reg {
308 struct {
309 u64 pasid_en:1;
310 u64 priv:1;
311 u64 rsvd:10;
312 u64 base_addr:52;
313
314 u64 size:16;
315 u64 pasid:20;
316 u64 rsvd2:28;
317 };
318 u64 bits[2];
319} __packed;
320
302#define IDXD_EVL_SIZE_MIN 0x0040321#define IDXD_EVL_SIZE_MIN 0x0040
303#define IDXD_EVL_SIZE_MAX 0xffff322#define IDXD_EVL_SIZE_MAX 0xffff
304 323
@@ -539,4 +558,53 @@ union filter_cfg { · 234 unmodified lines
539 u64 val;558 u64 val;
540} __packed;559} __packed;
541 560
561struct __evl_entry {
562 u64 rsvd:2;
563 u64 desc_valid:1;
564 u64 wq_idx_valid:1;
565 u64 batch:1;
566 u64 fault_rw:1;
567 u64 priv:1;
568 u64 err_info_valid:1;
569 u64 error:8;
570 u64 wq_idx:8;
571 u64 batch_id:8;
572 u64 operation:8;
573 u64 pasid:20;
574 u64 rsvd2:4;
575
576 u16 batch_idx;
577 u16 rsvd3;
578 union {
579 /* Invalid Flags 0x11 */
580 u32 invalid_flags;
581 /* Invalid Int Handle 0x19 */
582 /* Page fault 0x1a */
583 /* Page fault 0x06, 0x1f, only operand_id */
584 /* Page fault before drain or in batch, 0x26, 0x27 */
585 struct {
586 u16 int_handle;
587 u16 rci:1;
588 u16 ims:1;
589 u16 rcr:1;
590 u16 first_err_in_batch:1;
591 u16 rsvd4_2:9;
592 u16 operand_id:3;
593 };
594 };
595 u64 fault_addr;
596 u64 rsvd5;
597} __packed;
598
599struct dsa_evl_entry {
600 struct __evl_entry e;
601 struct dsa_completion_record cr;
602} __packed;
603
604struct iax_evl_entry {
605 struct __evl_entry e;
606 u64 rsvd[4];
607 struct iax_completion_record cr;
608} __packed;
609
542#endif610#endif
drivers/dma/idxd/sysfs.c+2−1
@@ -1605,7 +1605,8 @@ static ssize_t event_log_size_store(struct device *dev, · 1604 unmodified lines
1605 if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))1605 if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1606 return -EPERM;1606 return -EPERM;
1607 1607
1608 if (val < IDXD_EVL_SIZE_MIN || val > IDXD_EVL_SIZE_MAX)1608 if (val < IDXD_EVL_SIZE_MIN || val > IDXD_EVL_SIZE_MAX ||
1609 (val * evl_ent_size(idxd) > ULONG_MAX - idxd->evl->dma))
1609 return -EINVAL;1610 return -EINVAL;
1610 1611
1611 idxd->evl->size = val;1612 idxd->evl->size = val;
include/uapi/linux/idxd.h+1−0
@@ -30,6 +30,7 @@ enum idxd_scmd_stat { · 29 unmodified lines
30 IDXD_SCMD_WQ_NO_PRIV = 0x800f0000,30 IDXD_SCMD_WQ_NO_PRIV = 0x800f0000,
31 IDXD_SCMD_WQ_IRQ_ERR = 0x80100000,31 IDXD_SCMD_WQ_IRQ_ERR = 0x80100000,
32 IDXD_SCMD_WQ_USER_NO_IOMMU = 0x80110000,32 IDXD_SCMD_WQ_USER_NO_IOMMU = 0x80110000,
33 IDXD_SCMD_DEV_EVL_ERR = 0x80120000,
33};34};
34 35
35#define IDXD_SCMD_SOFTERR_MASK 0x8000000036#define IDXD_SCMD_SOFTERR_MASK 0x80000000

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t