diff options
| -rw-r--r-- | Documentation/ABI/testing/sysfs-class-cxl | 37 | ||||
| -rw-r--r-- | drivers/misc/cxl/cxl.h | 13 | ||||
| -rw-r--r-- | drivers/misc/cxl/pci.c | 23 | ||||
| -rw-r--r-- | drivers/misc/cxl/sysfs.c | 179 |
4 files changed, 242 insertions, 10 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 9ea01068a16c..3680364b4048 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl | |||
| @@ -81,6 +81,43 @@ Description: read only | |||
| 81 | this this kernel supports. | 81 | this this kernel supports. |
| 82 | 82 | ||
| 83 | 83 | ||
| 84 | AFU configuration records (eg. /sys/class/cxl/afu0.0/cr0): | ||
| 85 | |||
| 86 | An AFU may optionally export one or more PCIe like configuration records, known | ||
| 87 | as AFU configuration records, which will show up here (if present). | ||
| 88 | |||
| 89 | What: /sys/class/cxl/<afu>/cr<config num>/vendor | ||
| 90 | Date: February 2015 | ||
| 91 | Contact: linuxppc-dev@lists.ozlabs.org | ||
| 92 | Description: read only | ||
| 93 | Hexadecimal value of the vendor ID found in this AFU | ||
| 94 | configuration record. | ||
| 95 | |||
| 96 | What: /sys/class/cxl/<afu>/cr<config num>/device | ||
| 97 | Date: February 2015 | ||
| 98 | Contact: linuxppc-dev@lists.ozlabs.org | ||
| 99 | Description: read only | ||
| 100 | Hexadecimal value of the device ID found in this AFU | ||
| 101 | configuration record. | ||
| 102 | |||
| 103 | What: /sys/class/cxl/<afu>/cr<config num>/vendor | ||
| 104 | Date: February 2015 | ||
| 105 | Contact: linuxppc-dev@lists.ozlabs.org | ||
| 106 | Description: read only | ||
| 107 | Hexadecimal value of the class code found in this AFU | ||
| 108 | configuration record. | ||
| 109 | |||
| 110 | What: /sys/class/cxl/<afu>/cr<config num>/config | ||
| 111 | Date: February 2015 | ||
| 112 | Contact: linuxppc-dev@lists.ozlabs.org | ||
| 113 | Description: read only | ||
| 114 | This binary file provides raw access to the AFU configuration | ||
| 115 | record. The format is expected to match the either the standard | ||
| 116 | or extended configuration space defined by the PCIe | ||
| 117 | specification. | ||
| 118 | |||
| 119 | |||
| 120 | |||
| 84 | Master contexts (eg. /sys/class/cxl/afu0.0m) | 121 | Master contexts (eg. /sys/class/cxl/afu0.0m) |
| 85 | 122 | ||
| 86 | What: /sys/class/cxl/<afu>m/mmio_size | 123 | What: /sys/class/cxl/<afu>m/mmio_size |
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 6a6a487464c5..a1cee4767ec6 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h | |||
| @@ -382,6 +382,10 @@ struct cxl_afu { | |||
| 382 | int slice; | 382 | int slice; |
| 383 | int modes_supported; | 383 | int modes_supported; |
| 384 | int current_mode; | 384 | int current_mode; |
| 385 | int crs_num; | ||
| 386 | u64 crs_len; | ||
| 387 | u64 crs_offset; | ||
| 388 | struct list_head crs; | ||
| 385 | enum prefault_modes prefault_mode; | 389 | enum prefault_modes prefault_mode; |
| 386 | bool psa; | 390 | bool psa; |
| 387 | bool pp_psa; | 391 | bool pp_psa; |
| @@ -551,6 +555,15 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu *afu, cxl_p2n_reg_t reg | |||
| 551 | #define cxl_p2n_read(afu, reg) \ | 555 | #define cxl_p2n_read(afu, reg) \ |
| 552 | in_be64(_cxl_p2n_addr(afu, reg)) | 556 | in_be64(_cxl_p2n_addr(afu, reg)) |
| 553 | 557 | ||
| 558 | |||
| 559 | #define cxl_afu_cr_read64(afu, cr, off) \ | ||
| 560 | in_le64((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * (afu)->crs_len) + (off)) | ||
| 561 | #define cxl_afu_cr_read32(afu, cr, off) \ | ||
| 562 | in_le32((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * (afu)->crs_len) + (off)) | ||
| 563 | u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off); | ||
| 564 | u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off); | ||
| 565 | |||
| 566 | |||
| 554 | struct cxl_calls { | 567 | struct cxl_calls { |
| 555 | void (*cxl_slbia)(struct mm_struct *mm); | 568 | void (*cxl_slbia)(struct mm_struct *mm); |
| 556 | struct module *owner; | 569 | struct module *owner; |
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index cb250673b5c6..2b2e1b80d759 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
| @@ -114,6 +114,24 @@ | |||
| 114 | #define AFUD_EB_LEN(val) EXTRACT_PPC_BITS(val, 8, 63) | 114 | #define AFUD_EB_LEN(val) EXTRACT_PPC_BITS(val, 8, 63) |
| 115 | #define AFUD_READ_EB_OFF(afu) AFUD_READ(afu, 0x48) | 115 | #define AFUD_READ_EB_OFF(afu) AFUD_READ(afu, 0x48) |
| 116 | 116 | ||
| 117 | u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off) | ||
| 118 | { | ||
| 119 | u64 aligned_off = off & ~0x3L; | ||
| 120 | u32 val; | ||
| 121 | |||
| 122 | val = cxl_afu_cr_read32(afu, cr, aligned_off); | ||
| 123 | return (val >> ((off & 0x2) * 8)) & 0xffff; | ||
| 124 | } | ||
| 125 | |||
| 126 | u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off) | ||
| 127 | { | ||
| 128 | u64 aligned_off = off & ~0x3L; | ||
| 129 | u32 val; | ||
| 130 | |||
| 131 | val = cxl_afu_cr_read32(afu, cr, aligned_off); | ||
| 132 | return (val >> ((off & 0x3) * 8)) & 0xff; | ||
| 133 | } | ||
| 134 | |||
| 117 | static DEFINE_PCI_DEVICE_TABLE(cxl_pci_tbl) = { | 135 | static DEFINE_PCI_DEVICE_TABLE(cxl_pci_tbl) = { |
| 118 | { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), }, | 136 | { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), }, |
| 119 | { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), }, | 137 | { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), }, |
| @@ -556,6 +574,7 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu) | |||
| 556 | val = AFUD_READ_INFO(afu); | 574 | val = AFUD_READ_INFO(afu); |
| 557 | afu->pp_irqs = AFUD_NUM_INTS_PER_PROC(val); | 575 | afu->pp_irqs = AFUD_NUM_INTS_PER_PROC(val); |
| 558 | afu->max_procs_virtualised = AFUD_NUM_PROCS(val); | 576 | afu->max_procs_virtualised = AFUD_NUM_PROCS(val); |
| 577 | afu->crs_num = AFUD_NUM_CRS(val); | ||
| 559 | 578 | ||
| 560 | if (AFUD_AFU_DIRECTED(val)) | 579 | if (AFUD_AFU_DIRECTED(val)) |
| 561 | afu->modes_supported |= CXL_MODE_DIRECTED; | 580 | afu->modes_supported |= CXL_MODE_DIRECTED; |
| @@ -570,6 +589,10 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu) | |||
| 570 | if ((afu->pp_psa = AFUD_PPPSA_PP(val))) | 589 | if ((afu->pp_psa = AFUD_PPPSA_PP(val))) |
| 571 | afu->pp_offset = AFUD_READ_PPPSA_OFF(afu); | 590 | afu->pp_offset = AFUD_READ_PPPSA_OFF(afu); |
| 572 | 591 | ||
| 592 | val = AFUD_READ_CR(afu); | ||
| 593 | afu->crs_len = AFUD_CR_LEN(val) * 256; | ||
| 594 | afu->crs_offset = AFUD_READ_CR_OFF(afu); | ||
| 595 | |||
| 573 | return 0; | 596 | return 0; |
| 574 | } | 597 | } |
| 575 | 598 | ||
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index adf1f6d84913..d0c38c7bc0c4 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
| 12 | #include <linux/sysfs.h> | 12 | #include <linux/sysfs.h> |
| 13 | #include <linux/pci_regs.h> | ||
| 13 | 14 | ||
| 14 | #include "cxl.h" | 15 | #include "cxl.h" |
| 15 | 16 | ||
| @@ -367,8 +368,6 @@ static struct device_attribute afu_attrs[] = { | |||
| 367 | __ATTR(reset, S_IWUSR, NULL, reset_store_afu), | 368 | __ATTR(reset, S_IWUSR, NULL, reset_store_afu), |
| 368 | }; | 369 | }; |
| 369 | 370 | ||
| 370 | |||
| 371 | |||
| 372 | int cxl_sysfs_adapter_add(struct cxl *adapter) | 371 | int cxl_sysfs_adapter_add(struct cxl *adapter) |
| 373 | { | 372 | { |
| 374 | int i, rc; | 373 | int i, rc; |
| @@ -391,31 +390,191 @@ void cxl_sysfs_adapter_remove(struct cxl *adapter) | |||
| 391 | device_remove_file(&adapter->dev, &adapter_attrs[i]); | 390 | device_remove_file(&adapter->dev, &adapter_attrs[i]); |
| 392 | } | 391 | } |
| 393 | 392 | ||
| 393 | struct afu_config_record { | ||
| 394 | struct kobject kobj; | ||
| 395 | struct bin_attribute config_attr; | ||
| 396 | struct list_head list; | ||
| 397 | int cr; | ||
| 398 | u16 device; | ||
| 399 | u16 vendor; | ||
| 400 | u32 class; | ||
| 401 | }; | ||
| 402 | |||
| 403 | #define to_cr(obj) container_of(obj, struct afu_config_record, kobj) | ||
| 404 | |||
| 405 | static ssize_t vendor_show(struct kobject *kobj, | ||
| 406 | struct kobj_attribute *attr, char *buf) | ||
| 407 | { | ||
| 408 | struct afu_config_record *cr = to_cr(kobj); | ||
| 409 | |||
| 410 | return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->vendor); | ||
| 411 | } | ||
| 412 | |||
| 413 | static ssize_t device_show(struct kobject *kobj, | ||
| 414 | struct kobj_attribute *attr, char *buf) | ||
| 415 | { | ||
| 416 | struct afu_config_record *cr = to_cr(kobj); | ||
| 417 | |||
| 418 | return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->device); | ||
| 419 | } | ||
| 420 | |||
| 421 | static ssize_t class_show(struct kobject *kobj, | ||
| 422 | struct kobj_attribute *attr, char *buf) | ||
| 423 | { | ||
| 424 | struct afu_config_record *cr = to_cr(kobj); | ||
| 425 | |||
