aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2015-11-27 05:18:02 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-04-15 12:16:38 -0400
commit12283a4035691697977083a5ac1e00ad5cfa6a3d (patch)
tree1e1fd34032cda6850e378cfa019e0ddfcf04b929
parent68dd13d6d58c145bbf6d295b8c430b4d38c943d9 (diff)
s390/sclp: add error notification command
Add SCLP event 24 "Adapter-error notification". Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/sclp.h13
-rw-r--r--drivers/s390/char/sclp.h2
-rw-r--r--drivers/s390/char/sclp_pci.c120
3 files changed, 133 insertions, 2 deletions
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index bab456be9a4f..bd7893d274fa 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -72,6 +72,18 @@ struct sclp_info {
72}; 72};
73extern struct sclp_info sclp; 73extern struct sclp_info sclp;
74 74
75struct zpci_report_error_header {
76 u8 version; /* Interface version byte */
77 u8 action; /* Action qualifier byte
78 * 1: Deconfigure and repair action requested
79 * (OpenCrypto Problem Call Home)
80 * 2: Informational Report
81 * (OpenCrypto Successful Diagnostics Execution)
82 */
83 u16 length; /* Length of Subsequent Data (up to 4K – SCLP header */
84 u8 data[0]; /* Subsequent Data passed verbatim to SCLP ET 24 */
85} __packed;
86
75int sclp_get_core_info(struct sclp_core_info *info); 87int sclp_get_core_info(struct sclp_core_info *info);
76int sclp_core_configure(u8 core); 88int sclp_core_configure(u8 core);
77int sclp_core_deconfigure(u8 core); 89int sclp_core_deconfigure(u8 core);
@@ -83,6 +95,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
83void sclp_get_ipl_info(struct sclp_ipl_info *info); 95void sclp_get_ipl_info(struct sclp_ipl_info *info);
84int sclp_pci_configure(u32 fid); 96int sclp_pci_configure(u32 fid);
85int sclp_pci_deconfigure(u32 fid); 97int sclp_pci_deconfigure(u32 fid);
98int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid);
86int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count); 99int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
87int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count); 100int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
88void sclp_early_detect(void); 101void sclp_early_detect(void);
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 026e38990952..6079efa95eaa 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -22,6 +22,7 @@
22#define EVTYP_DIAG_TEST 0x07 22#define EVTYP_DIAG_TEST 0x07
23#define EVTYP_STATECHANGE 0x08 23#define EVTYP_STATECHANGE 0x08
24#define EVTYP_PMSGCMD 0x09 24#define EVTYP_PMSGCMD 0x09
25#define EVTYP_ERRNOTIFY 0x18
25#define EVTYP_CNTLPROGOPCMD 0x20 26#define EVTYP_CNTLPROGOPCMD 0x20
26#define EVTYP_CNTLPROGIDENT 0x0B 27#define EVTYP_CNTLPROGIDENT 0x0B
27#define EVTYP_SIGQUIESCE 0x1D 28#define EVTYP_SIGQUIESCE 0x1D
@@ -36,6 +37,7 @@
36#define EVTYP_DIAG_TEST_MASK 0x02000000 37#define EVTYP_DIAG_TEST_MASK 0x02000000
37#define EVTYP_STATECHANGE_MASK 0x01000000 38#define EVTYP_STATECHANGE_MASK 0x01000000
38#define EVTYP_PMSGCMD_MASK 0x00800000 39#define EVTYP_PMSGCMD_MASK 0x00800000
40#define EVTYP_ERRNOTIFY_MASK 0x00000100
39#define EVTYP_CTLPROGOPCMD_MASK 0x00000001 41#define EVTYP_CTLPROGOPCMD_MASK 0x00000001
40#define EVTYP_CTLPROGIDENT_MASK 0x00200000 42#define EVTYP_CTLPROGIDENT_MASK 0x00200000
41#define EVTYP_SIGQUIESCE_MASK 0x00000008 43#define EVTYP_SIGQUIESCE_MASK 0x00000008
diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
index 943e92539e65..0c8973c45b48 100644
--- a/drivers/s390/char/sclp_pci.c
+++ b/drivers/s390/char/sclp_pci.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/completion.h> 9#include <linux/completion.h>
10#include <linux/export.h> 10#include <linux/export.h>
11#include <linux/mutex.h>
11#include <linux/errno.h> 12#include <linux/errno.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/init.h> 14#include <linux/init.h>
@@ -20,7 +21,29 @@
20#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 21#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
21#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 22#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
22 23
23#define SCLP_RECONFIG_PCI_ATPYE 2 24#define SCLP_ATYPE_PCI 2
25
26#define SCLP_ERRNOTIFY_AQ_REPAIR 1
27#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
28
29static DEFINE_MUTEX(sclp_pci_mutex);
30static struct sclp_register sclp_pci_event = {
31 .send_mask = EVTYP_ERRNOTIFY_MASK,
32};
33
34struct err_notify_evbuf {
35 struct evbuf_header header;
36 u8 action;
37 u8 atype;
38 u32 fh;
39 u32 fid;
40 u8 data[0];
41} __packed;
42
43struct err_notify_sccb {
44 struct sccb_header header;
45 struct err_notify_evbuf evbuf;
46} __packed;
24 47
25struct pci_cfg_sccb { 48struct pci_cfg_sccb {
26 struct sccb_header header; 49 struct sccb_header header;
@@ -43,7 +66,7 @@ static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
43 return -ENOMEM; 66 return -ENOMEM;
44 67
45 sccb->header.length = PAGE_SIZE; 68 sccb->header.length = PAGE_SIZE;
46 sccb->atype = SCLP_RECONFIG_PCI_ATPYE; 69 sccb->atype = SCLP_ATYPE_PCI;
47 sccb->aid = fid; 70 sccb->aid = fid;
48 rc = sclp_sync_request(cmd, sccb); 71 rc = sclp_sync_request(cmd, sccb);
49 if (rc) 72 if (rc)
@@ -74,3 +97,96 @@ int sclp_pci_deconfigure(u32 fid)
74 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid); 97 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
75} 98}
76EXPORT_SYMBOL(sclp_pci_deconfigure); 99EXPORT_SYMBOL(sclp_pci_deconfigure);
100
101static void sclp_pci_callback(struct sclp_req *req, void *data)
102{
103 struct completion *completion = data;
104
105 complete(completion);
106}
107
108static int sclp_pci_check_report(struct zpci_report_error_header *report)
109{
110 if (report->version != 1)
111 return -EINVAL;
112
113 if (report->action != SCLP_ERRNOTIFY_AQ_REPAIR &&
114 report->action != SCLP_ERRNOTIFY_AQ_INFO_LOG)
115 return -EINVAL;
116
117 if (report->length > (PAGE_SIZE - sizeof(struct err_notify_sccb)))
118 return -EINVAL;
119
120 return 0;
121}
122
123int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid)
124{
125 DECLARE_COMPLETION_ONSTACK(completion);
126 struct err_notify_sccb *sccb;
127 struct sclp_req req = {0};
128 int ret;
129
130 ret = sclp_pci_check_report(report);
131 if (ret)
132 return ret;
133
134 mutex_lock(&sclp_pci_mutex);
135 ret = sclp_register(&sclp_pci_event);
136 if (ret)
137 goto out_unlock;
138
139 if (!(sclp_pci_event.sclp_receive_mask & EVTYP_ERRNOTIFY_MASK)) {
140 ret = -EOPNOTSUPP;
141 goto out_unregister;
142 }
143
144 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
145 if (!sccb) {
146 ret = -ENOMEM;
147 goto out_unregister;
148 }
149
150 req.callback_data = &completion;
151 req.callback = sclp_pci_callback;
152 req.command = SCLP_CMDW_WRITE_EVENT_DATA;
153 req.status = SCLP_REQ_FILLED;
154 req.sccb = sccb;
155
156 sccb->evbuf.header.length = sizeof(sccb->evbuf) + report->length;
157 sccb->evbuf.header.type = EVTYP_ERRNOTIFY;
158 sccb->header.length = sizeof(sccb->header) + sccb->evbuf.header.length;
159
160 sccb->evbuf.action = report->action;
161 sccb->evbuf.atype = SCLP_ATYPE_PCI;
162 sccb->evbuf.fh = fh;
163 sccb->evbuf.fid = fid;
164
165 memcpy(sccb->evbuf.data, report->data, report->length);
166
167 ret = sclp_add_request(&req);
168 if (ret)
169 goto out_free_req;
170
171 wait_for_completion(&completion);
172 if (req.status != SCLP_REQ_DONE) {
173 pr_warn("request failed (status=0x%02x)\n",
174 req.status);
175 ret = -EIO;
176 goto out_free_req;
177 }
178
179 if (sccb->header.response_code != 0x0020) {
180 pr_warn("request failed with response code 0x%x\n",
181 sccb->header.response_code);
182 ret = -EIO;
183 }
184
185out_free_req:
186 free_page((unsigned long) sccb);
187out_unregister:
188 sclp_unregister(&sclp_pci_event);
189out_unlock:
190 mutex_unlock(&sclp_pci_mutex);
191 return ret;
192}