1 // SPDX-License-Identifier: GPL-2.0
3 * PCI I/O adapter configuration related functions.
5 * Copyright IBM Corp. 2016
7 #define KMSG_COMPONENT "sclp_cmd"
8 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10 #include <linux/completion.h>
11 #include <linux/export.h>
12 #include <linux/mutex.h>
13 #include <linux/errno.h>
14 #include <linux/slab.h>
15 #include <linux/init.h>
16 #include <linux/err.h>
22 #define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
23 #define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
25 #define SCLP_ATYPE_PCI 2
27 #define SCLP_ERRNOTIFY_AQ_REPAIR 1
28 #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
30 static DEFINE_MUTEX(sclp_pci_mutex
);
31 static struct sclp_register sclp_pci_event
= {
32 .send_mask
= EVTYP_ERRNOTIFY_MASK
,
35 struct err_notify_evbuf
{
36 struct evbuf_header header
;
44 struct err_notify_sccb
{
45 struct sccb_header header
;
46 struct err_notify_evbuf evbuf
;
50 struct sccb_header header
;
51 u8 atype
; /* adapter type */
54 u32 aid
; /* adapter identifier */
57 static int do_pci_configure(sclp_cmdw_t cmd
, u32 fid
)
59 struct pci_cfg_sccb
*sccb
;
62 if (!SCLP_HAS_PCI_RECONFIG
)
65 sccb
= (struct pci_cfg_sccb
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
69 sccb
->header
.length
= PAGE_SIZE
;
70 sccb
->atype
= SCLP_ATYPE_PCI
;
72 rc
= sclp_sync_request(cmd
, sccb
);
75 switch (sccb
->header
.response_code
) {
80 pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n",
81 cmd
, sccb
->header
.response_code
);
86 free_page((unsigned long) sccb
);
90 int sclp_pci_configure(u32 fid
)
92 return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI
, fid
);
94 EXPORT_SYMBOL(sclp_pci_configure
);
96 int sclp_pci_deconfigure(u32 fid
)
98 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI
, fid
);
100 EXPORT_SYMBOL(sclp_pci_deconfigure
);
102 static void sclp_pci_callback(struct sclp_req
*req
, void *data
)
104 struct completion
*completion
= data
;
106 complete(completion
);
109 static int sclp_pci_check_report(struct zpci_report_error_header
*report
)
111 if (report
->version
!= 1)
114 if (report
->action
!= SCLP_ERRNOTIFY_AQ_REPAIR
&&
115 report
->action
!= SCLP_ERRNOTIFY_AQ_INFO_LOG
)
118 if (report
->length
> (PAGE_SIZE
- sizeof(struct err_notify_sccb
)))
124 int sclp_pci_report(struct zpci_report_error_header
*report
, u32 fh
, u32 fid
)
126 DECLARE_COMPLETION_ONSTACK(completion
);
127 struct err_notify_sccb
*sccb
;
131 ret
= sclp_pci_check_report(report
);
135 mutex_lock(&sclp_pci_mutex
);
136 ret
= sclp_register(&sclp_pci_event
);
140 if (!(sclp_pci_event
.sclp_receive_mask
& EVTYP_ERRNOTIFY_MASK
)) {
145 sccb
= (void *) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
151 memset(&req
, 0, sizeof(req
));
152 req
.callback_data
= &completion
;
153 req
.callback
= sclp_pci_callback
;
154 req
.command
= SCLP_CMDW_WRITE_EVENT_DATA
;
155 req
.status
= SCLP_REQ_FILLED
;
158 sccb
->evbuf
.header
.length
= sizeof(sccb
->evbuf
) + report
->length
;
159 sccb
->evbuf
.header
.type
= EVTYP_ERRNOTIFY
;
160 sccb
->header
.length
= sizeof(sccb
->header
) + sccb
->evbuf
.header
.length
;
162 sccb
->evbuf
.action
= report
->action
;
163 sccb
->evbuf
.atype
= SCLP_ATYPE_PCI
;
165 sccb
->evbuf
.fid
= fid
;
167 memcpy(sccb
->evbuf
.data
, report
->data
, report
->length
);
169 ret
= sclp_add_request(&req
);
173 wait_for_completion(&completion
);
174 if (req
.status
!= SCLP_REQ_DONE
) {
175 pr_warn("request failed (status=0x%02x)\n",
181 if (sccb
->header
.response_code
!= 0x0020) {
182 pr_warn("request failed with response code 0x%x\n",
183 sccb
->header
.response_code
);
188 free_page((unsigned long) sccb
);
190 sclp_unregister(&sclp_pci_event
);
192 mutex_unlock(&sclp_pci_mutex
);