diff options
author | Daniel Axtens <dja@axtens.net> | 2015-08-14 03:41:25 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-08-14 07:32:07 -0400 |
commit | 13e68d8bd05c998cae452a4f3400af1e8edd852e (patch) | |
tree | d17ff97c9f46a663b5cb4916fc333703b2cdfea4 /drivers/misc/cxl | |
parent | 4e1efb403c1c016ae831bd9988a7d2e5e0af41a0 (diff) |
cxl: Allow the kernel to trust that an image won't change on PERST.
Provide a kernel API and a sysfs entry which allow a user to specify
that when a card is PERSTed, it's image will stay the same, allowing
it to participate in EEH.
cxl_reset is used to reflash the card. In that case, we cannot safely
assert that the image will not change. Therefore, disallow cxl_reset
if the flag is set.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/misc/cxl')
-rw-r--r-- | drivers/misc/cxl/api.c | 7 | ||||
-rw-r--r-- | drivers/misc/cxl/cxl.h | 1 | ||||
-rw-r--r-- | drivers/misc/cxl/pci.c | 7 | ||||
-rw-r--r-- | drivers/misc/cxl/sysfs.c | 26 |
4 files changed, 41 insertions, 0 deletions
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 729e0851167d..6a768a9ad22f 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c | |||
@@ -327,3 +327,10 @@ int cxl_afu_reset(struct cxl_context *ctx) | |||
327 | return cxl_afu_check_and_enable(afu); | 327 | return cxl_afu_check_and_enable(afu); |
328 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(cxl_afu_reset); | 329 | EXPORT_SYMBOL_GPL(cxl_afu_reset); |
330 | |||
331 | void cxl_perst_reloads_same_image(struct cxl_afu *afu, | ||
332 | bool perst_reloads_same_image) | ||
333 | { | ||
334 | afu->adapter->perst_same_image = perst_reloads_same_image; | ||
335 | } | ||
336 | EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image); | ||
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index d540542f9931..cda02412b01e 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h | |||
@@ -493,6 +493,7 @@ struct cxl { | |||
493 | bool user_image_loaded; | 493 | bool user_image_loaded; |
494 | bool perst_loads_image; | 494 | bool perst_loads_image; |
495 | bool perst_select_user; | 495 | bool perst_select_user; |
496 | bool perst_same_image; | ||
496 | }; | 497 | }; |
497 | 498 | ||
498 | int cxl_alloc_one_irq(struct cxl *adapter); | 499 | int cxl_alloc_one_irq(struct cxl *adapter); |
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 2b61cb1ee62c..bfbd6478c0c5 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -878,6 +878,12 @@ int cxl_reset(struct cxl *adapter) | |||
878 | int i; | 878 | int i; |
879 | u32 val; | 879 | u32 val; |
880 | 880 | ||
881 | if (adapter->perst_same_image) { | ||
882 | dev_warn(&dev->dev, | ||
883 | "cxl: refusing to reset/reflash when perst_reloads_same_image is set.\n"); | ||
884 | return -EINVAL; | ||
885 | } | ||
886 | |||
881 | dev_info(&dev->dev, "CXL reset\n"); | 887 | dev_info(&dev->dev, "CXL reset\n"); |
882 | 888 | ||
883 | /* pcie_warm_reset requests a fundamental pci reset which includes a | 889 | /* pcie_warm_reset requests a fundamental pci reset which includes a |
@@ -1151,6 +1157,7 @@ static struct cxl *cxl_init_adapter(struct pci_dev *dev) | |||
1151 | * configure/reconfigure | 1157 | * configure/reconfigure |
1152 | */ | 1158 | */ |
1153 | adapter->perst_loads_image = true; | 1159 | adapter->perst_loads_image = true; |
1160 | adapter->perst_same_image = false; | ||
1154 | 1161 | ||
1155 | rc = cxl_configure_adapter(adapter, dev); | 1162 | rc = cxl_configure_adapter(adapter, dev); |
1156 | if (rc) { | 1163 | if (rc) { |
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 31f38bc71a3d..6619cf1f6e1f 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c | |||
@@ -112,12 +112,38 @@ static ssize_t load_image_on_perst_store(struct device *device, | |||
112 | return count; | 112 | return count; |
113 | } | 113 | } |
114 | 114 | ||
115 | static ssize_t perst_reloads_same_image_show(struct device *device, | ||
116 | struct device_attribute *attr, | ||
117 | char *buf) | ||
118 | { | ||
119 | struct cxl *adapter = to_cxl_adapter(device); | ||
120 | |||
121 | return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->perst_same_image); | ||
122 | } | ||
123 | |||
124 | static ssize_t perst_reloads_same_image_store(struct device *device, | ||
125 | struct device_attribute *attr, | ||
126 | const char *buf, size_t count) | ||
127 | { | ||
128 | struct cxl *adapter = to_cxl_adapter(device); | ||
129 | int rc; | ||
130 | int val; | ||
131 | |||
132 | rc = sscanf(buf, "%i", &val); | ||
133 | if ((rc != 1) || !(val == 1 || val == 0)) | ||
134 | return -EINVAL; | ||
135 | |||
136 | adapter->perst_same_image = (val == 1 ? true : false); | ||
137 | return count; | ||
138 | } | ||
139 | |||
115 | static struct device_attribute adapter_attrs[] = { | 140 | static struct device_attribute adapter_attrs[] = { |
116 | __ATTR_RO(caia_version), | 141 | __ATTR_RO(caia_version), |
117 | __ATTR_RO(psl_revision), | 142 | __ATTR_RO(psl_revision), |
118 | __ATTR_RO(base_image), | 143 | __ATTR_RO(base_image), |
119 | __ATTR_RO(image_loaded), | 144 | __ATTR_RO(image_loaded), |
120 | __ATTR_RW(load_image_on_perst), | 145 | __ATTR_RW(load_image_on_perst), |
146 | __ATTR_RW(perst_reloads_same_image), | ||
121 | __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), | 147 | __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), |
122 | }; | 148 | }; |
123 | 149 | ||