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_RESET 0
28 #define SCLP_ERRNOTIFY_AQ_REPAIR 1
29 #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
31 static DEFINE_MUTEX(sclp_pci_mutex
);
32 static struct sclp_register sclp_pci_event
= {
33 .send_mask
= EVTYP_ERRNOTIFY_MASK
,
36 struct err_notify_evbuf
{
37 struct evbuf_header header
;
45 struct err_notify_sccb
{
46 struct sccb_header header
;
47 struct err_notify_evbuf evbuf
;
51 struct sccb_header header
;
52 u8 atype
; /* adapter type */
55 u32 aid
; /* adapter identifier */
58 static int do_pci_configure(sclp_cmdw_t cmd
, u32 fid
)
60 struct pci_cfg_sccb
*sccb
;
63 if (!SCLP_HAS_PCI_RECONFIG
)
66 sccb
= (struct pci_cfg_sccb
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
70 sccb
->header
.length
= PAGE_SIZE
;
71 sccb
->atype
= SCLP_ATYPE_PCI
;
73 rc
= sclp_sync_request(cmd
, sccb
);
76 switch (sccb
->header
.response_code
) {
81 pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n",
82 cmd
, sccb
->header
.response_code
);
87 free_page((unsigned long) sccb
);
91 int sclp_pci_configure(u32 fid
)
93 return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI
, fid
);
95 EXPORT_SYMBOL(sclp_pci_configure
);
97 int sclp_pci_deconfigure(u32 fid
)
99 return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI
, fid
);
101 EXPORT_SYMBOL(sclp_pci_deconfigure
);
103 static void sclp_pci_callback(struct sclp_req
*req
, void *data
)
105 struct completion
*completion
= data
;
107 complete(completion
);
110 static int sclp_pci_check_report(struct zpci_report_error_header
*report
)
112 if (report
->version
!= 1)
115 switch (report
->action
) {
116 case SCLP_ERRNOTIFY_AQ_RESET
:
117 case SCLP_ERRNOTIFY_AQ_REPAIR
:
118 case SCLP_ERRNOTIFY_AQ_INFO_LOG
:
124 if (report
->length
> (PAGE_SIZE
- sizeof(struct err_notify_sccb
)))
130 int sclp_pci_report(struct zpci_report_error_header
*report
, u32 fh
, u32 fid
)
132 DECLARE_COMPLETION_ONSTACK(completion
);
133 struct err_notify_sccb
*sccb
;
137 ret
= sclp_pci_check_report(report
);
141 mutex_lock(&sclp_pci_mutex
);
142 ret
= sclp_register(&sclp_pci_event
);
146 if (!(sclp_pci_event
.sclp_receive_mask
& EVTYP_ERRNOTIFY_MASK
)) {
151 sccb
= (void *) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
157 memset(&req
, 0, sizeof(req
));
158 req
.callback_data
= &completion
;
159 req
.callback
= sclp_pci_callback
;
160 req
.command
= SCLP_CMDW_WRITE_EVENT_DATA
;
161 req
.status
= SCLP_REQ_FILLED
;
164 sccb
->evbuf
.header
.length
= sizeof(sccb
->evbuf
) + report
->length
;
165 sccb
->evbuf
.header
.type
= EVTYP_ERRNOTIFY
;
166 sccb
->header
.length
= sizeof(sccb
->header
) + sccb
->evbuf
.header
.length
;
168 sccb
->evbuf
.action
= report
->action
;
169 sccb
->evbuf
.atype
= SCLP_ATYPE_PCI
;
171 sccb
->evbuf
.fid
= fid
;
173 memcpy(sccb
->evbuf
.data
, report
->data
, report
->length
);
175 ret
= sclp_add_request(&req
);
179 wait_for_completion(&completion
);
180 if (req
.status
!= SCLP_REQ_DONE
) {
181 pr_warn("request failed (status=0x%02x)\n",
187 if (sccb
->header
.response_code
!= 0x0020) {
188 pr_warn("request failed with response code 0x%x\n",
189 sccb
->header
.response_code
);
194 free_page((unsigned long) sccb
);
196 sclp_unregister(&sclp_pci_event
);
198 mutex_unlock(&sclp_pci_mutex
);