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>
This commit is contained in:
parent
68dd13d6d5
commit
12283a4035
|
@ -72,6 +72,18 @@ struct sclp_info {
|
|||
};
|
||||
extern struct sclp_info sclp;
|
||||
|
||||
struct zpci_report_error_header {
|
||||
u8 version; /* Interface version byte */
|
||||
u8 action; /* Action qualifier byte
|
||||
* 1: Deconfigure and repair action requested
|
||||
* (OpenCrypto Problem Call Home)
|
||||
* 2: Informational Report
|
||||
* (OpenCrypto Successful Diagnostics Execution)
|
||||
*/
|
||||
u16 length; /* Length of Subsequent Data (up to 4K – SCLP header */
|
||||
u8 data[0]; /* Subsequent Data passed verbatim to SCLP ET 24 */
|
||||
} __packed;
|
||||
|
||||
int sclp_get_core_info(struct sclp_core_info *info);
|
||||
int sclp_core_configure(u8 core);
|
||||
int sclp_core_deconfigure(u8 core);
|
||||
|
@ -83,6 +95,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
|
|||
void sclp_get_ipl_info(struct sclp_ipl_info *info);
|
||||
int sclp_pci_configure(u32 fid);
|
||||
int sclp_pci_deconfigure(u32 fid);
|
||||
int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid);
|
||||
int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
|
||||
int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
|
||||
void sclp_early_detect(void);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define EVTYP_DIAG_TEST 0x07
|
||||
#define EVTYP_STATECHANGE 0x08
|
||||
#define EVTYP_PMSGCMD 0x09
|
||||
#define EVTYP_ERRNOTIFY 0x18
|
||||
#define EVTYP_CNTLPROGOPCMD 0x20
|
||||
#define EVTYP_CNTLPROGIDENT 0x0B
|
||||
#define EVTYP_SIGQUIESCE 0x1D
|
||||
|
@ -36,6 +37,7 @@
|
|||
#define EVTYP_DIAG_TEST_MASK 0x02000000
|
||||
#define EVTYP_STATECHANGE_MASK 0x01000000
|
||||
#define EVTYP_PMSGCMD_MASK 0x00800000
|
||||
#define EVTYP_ERRNOTIFY_MASK 0x00000100
|
||||
#define EVTYP_CTLPROGOPCMD_MASK 0x00000001
|
||||
#define EVTYP_CTLPROGIDENT_MASK 0x00200000
|
||||
#define EVTYP_SIGQUIESCE_MASK 0x00000008
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -20,7 +21,29 @@
|
|||
#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
|
||||
#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
|
||||
|
||||
#define SCLP_RECONFIG_PCI_ATPYE 2
|
||||
#define SCLP_ATYPE_PCI 2
|
||||
|
||||
#define SCLP_ERRNOTIFY_AQ_REPAIR 1
|
||||
#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
|
||||
|
||||
static DEFINE_MUTEX(sclp_pci_mutex);
|
||||
static struct sclp_register sclp_pci_event = {
|
||||
.send_mask = EVTYP_ERRNOTIFY_MASK,
|
||||
};
|
||||
|
||||
struct err_notify_evbuf {
|
||||
struct evbuf_header header;
|
||||
u8 action;
|
||||
u8 atype;
|
||||
u32 fh;
|
||||
u32 fid;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct err_notify_sccb {
|
||||
struct sccb_header header;
|
||||
struct err_notify_evbuf evbuf;
|
||||
} __packed;
|
||||
|
||||
struct pci_cfg_sccb {
|
||||
struct sccb_header header;
|
||||
|
@ -43,7 +66,7 @@ static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
|
|||
return -ENOMEM;
|
||||
|
||||
sccb->header.length = PAGE_SIZE;
|
||||
sccb->atype = SCLP_RECONFIG_PCI_ATPYE;
|
||||
sccb->atype = SCLP_ATYPE_PCI;
|
||||
sccb->aid = fid;
|
||||
rc = sclp_sync_request(cmd, sccb);
|
||||
if (rc)
|
||||
|
@ -74,3 +97,96 @@ int sclp_pci_deconfigure(u32 fid)
|
|||
return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
|
||||
}
|
||||
EXPORT_SYMBOL(sclp_pci_deconfigure);
|
||||
|
||||
static void sclp_pci_callback(struct sclp_req *req, void *data)
|
||||
{
|
||||
struct completion *completion = data;
|
||||
|
||||
complete(completion);
|
||||
}
|
||||
|
||||
static int sclp_pci_check_report(struct zpci_report_error_header *report)
|
||||
{
|
||||
if (report->version != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (report->action != SCLP_ERRNOTIFY_AQ_REPAIR &&
|
||||
report->action != SCLP_ERRNOTIFY_AQ_INFO_LOG)
|
||||
return -EINVAL;
|
||||
|
||||
if (report->length > (PAGE_SIZE - sizeof(struct err_notify_sccb)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
struct err_notify_sccb *sccb;
|
||||
struct sclp_req req = {0};
|
||||
int ret;
|
||||
|
||||
ret = sclp_pci_check_report(report);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&sclp_pci_mutex);
|
||||
ret = sclp_register(&sclp_pci_event);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (!(sclp_pci_event.sclp_receive_mask & EVTYP_ERRNOTIFY_MASK)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sccb) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
req.callback_data = &completion;
|
||||
req.callback = sclp_pci_callback;
|
||||
req.command = SCLP_CMDW_WRITE_EVENT_DATA;
|
||||
req.status = SCLP_REQ_FILLED;
|
||||
req.sccb = sccb;
|
||||
|
||||
sccb->evbuf.header.length = sizeof(sccb->evbuf) + report->length;
|
||||
sccb->evbuf.header.type = EVTYP_ERRNOTIFY;
|
||||
sccb->header.length = sizeof(sccb->header) + sccb->evbuf.header.length;
|
||||
|
||||
sccb->evbuf.action = report->action;
|
||||
sccb->evbuf.atype = SCLP_ATYPE_PCI;
|
||||
sccb->evbuf.fh = fh;
|
||||
sccb->evbuf.fid = fid;
|
||||
|
||||
memcpy(sccb->evbuf.data, report->data, report->length);
|
||||
|
||||
ret = sclp_add_request(&req);
|
||||
if (ret)
|
||||
goto out_free_req;
|
||||
|
||||
wait_for_completion(&completion);
|
||||
if (req.status != SCLP_REQ_DONE) {
|
||||
pr_warn("request failed (status=0x%02x)\n",
|
||||
req.status);
|
||||
ret = -EIO;
|
||||
goto out_free_req;
|
||||
}
|
||||
|
||||
if (sccb->header.response_code != 0x0020) {
|
||||
pr_warn("request failed with response code 0x%x\n",
|
||||
sccb->header.response_code);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
out_free_req:
|
||||
free_page((unsigned long) sccb);
|
||||
out_unregister:
|
||||
sclp_unregister(&sclp_pci_event);
|
||||
out_unlock:
|
||||
mutex_unlock(&sclp_pci_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue