0001
0002
0003
0004
0005
0006
0007 #define KMSG_COMPONENT "sclp_cmd"
0008 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0009
0010 #include <linux/completion.h>
0011 #include <linux/export.h>
0012 #include <linux/mutex.h>
0013 #include <linux/errno.h>
0014 #include <linux/slab.h>
0015 #include <linux/init.h>
0016 #include <linux/err.h>
0017
0018 #include <asm/sclp.h>
0019
0020 #include "sclp.h"
0021
0022 #define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
0023 #define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
0024
0025 #define SCLP_ATYPE_PCI 2
0026
0027 #define SCLP_ERRNOTIFY_AQ_RESET 0
0028 #define SCLP_ERRNOTIFY_AQ_REPAIR 1
0029 #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
0030
0031 static DEFINE_MUTEX(sclp_pci_mutex);
0032 static struct sclp_register sclp_pci_event = {
0033 .send_mask = EVTYP_ERRNOTIFY_MASK,
0034 };
0035
0036 struct err_notify_evbuf {
0037 struct evbuf_header header;
0038 u8 action;
0039 u8 atype;
0040 u32 fh;
0041 u32 fid;
0042 u8 data[];
0043 } __packed;
0044
0045 struct err_notify_sccb {
0046 struct sccb_header header;
0047 struct err_notify_evbuf evbuf;
0048 } __packed;
0049
0050 struct pci_cfg_sccb {
0051 struct sccb_header header;
0052 u8 atype;
0053 u8 reserved1;
0054 u16 reserved2;
0055 u32 aid;
0056 } __packed;
0057
0058 static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
0059 {
0060 struct pci_cfg_sccb *sccb;
0061 int rc;
0062
0063 if (!SCLP_HAS_PCI_RECONFIG)
0064 return -EOPNOTSUPP;
0065
0066 sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0067 if (!sccb)
0068 return -ENOMEM;
0069
0070 sccb->header.length = PAGE_SIZE;
0071 sccb->atype = SCLP_ATYPE_PCI;
0072 sccb->aid = fid;
0073 rc = sclp_sync_request(cmd, sccb);
0074 if (rc)
0075 goto out;
0076 switch (sccb->header.response_code) {
0077 case 0x0020:
0078 case 0x0120:
0079 break;
0080 default:
0081 pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n",
0082 cmd, sccb->header.response_code);
0083 rc = -EIO;
0084 break;
0085 }
0086 out:
0087 free_page((unsigned long) sccb);
0088 return rc;
0089 }
0090
0091 int sclp_pci_configure(u32 fid)
0092 {
0093 return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid);
0094 }
0095 EXPORT_SYMBOL(sclp_pci_configure);
0096
0097 int sclp_pci_deconfigure(u32 fid)
0098 {
0099 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
0100 }
0101 EXPORT_SYMBOL(sclp_pci_deconfigure);
0102
0103 static void sclp_pci_callback(struct sclp_req *req, void *data)
0104 {
0105 struct completion *completion = data;
0106
0107 complete(completion);
0108 }
0109
0110 static int sclp_pci_check_report(struct zpci_report_error_header *report)
0111 {
0112 if (report->version != 1)
0113 return -EINVAL;
0114
0115 switch (report->action) {
0116 case SCLP_ERRNOTIFY_AQ_RESET:
0117 case SCLP_ERRNOTIFY_AQ_REPAIR:
0118 case SCLP_ERRNOTIFY_AQ_INFO_LOG:
0119 break;
0120 default:
0121 return -EINVAL;
0122 }
0123
0124 if (report->length > (PAGE_SIZE - sizeof(struct err_notify_sccb)))
0125 return -EINVAL;
0126
0127 return 0;
0128 }
0129
0130 int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid)
0131 {
0132 DECLARE_COMPLETION_ONSTACK(completion);
0133 struct err_notify_sccb *sccb;
0134 struct sclp_req req;
0135 int ret;
0136
0137 ret = sclp_pci_check_report(report);
0138 if (ret)
0139 return ret;
0140
0141 mutex_lock(&sclp_pci_mutex);
0142 ret = sclp_register(&sclp_pci_event);
0143 if (ret)
0144 goto out_unlock;
0145
0146 if (!(sclp_pci_event.sclp_receive_mask & EVTYP_ERRNOTIFY_MASK)) {
0147 ret = -EOPNOTSUPP;
0148 goto out_unregister;
0149 }
0150
0151 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0152 if (!sccb) {
0153 ret = -ENOMEM;
0154 goto out_unregister;
0155 }
0156
0157 memset(&req, 0, sizeof(req));
0158 req.callback_data = &completion;
0159 req.callback = sclp_pci_callback;
0160 req.command = SCLP_CMDW_WRITE_EVENT_DATA;
0161 req.status = SCLP_REQ_FILLED;
0162 req.sccb = sccb;
0163
0164 sccb->evbuf.header.length = sizeof(sccb->evbuf) + report->length;
0165 sccb->evbuf.header.type = EVTYP_ERRNOTIFY;
0166 sccb->header.length = sizeof(sccb->header) + sccb->evbuf.header.length;
0167
0168 sccb->evbuf.action = report->action;
0169 sccb->evbuf.atype = SCLP_ATYPE_PCI;
0170 sccb->evbuf.fh = fh;
0171 sccb->evbuf.fid = fid;
0172
0173 memcpy(sccb->evbuf.data, report->data, report->length);
0174
0175 ret = sclp_add_request(&req);
0176 if (ret)
0177 goto out_free_req;
0178
0179 wait_for_completion(&completion);
0180 if (req.status != SCLP_REQ_DONE) {
0181 pr_warn("request failed (status=0x%02x)\n",
0182 req.status);
0183 ret = -EIO;
0184 goto out_free_req;
0185 }
0186
0187 if (sccb->header.response_code != 0x0020) {
0188 pr_warn("request failed with response code 0x%x\n",
0189 sccb->header.response_code);
0190 ret = -EIO;
0191 }
0192
0193 out_free_req:
0194 free_page((unsigned long) sccb);
0195 out_unregister:
0196 sclp_unregister(&sclp_pci_event);
0197 out_unlock:
0198 mutex_unlock(&sclp_pci_mutex);
0199 return ret;
0200 }