2 * drivers/s390/char/sclp_chp.c
4 * Copyright IBM Corp. 2007
5 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
8 #include <linux/types.h>
10 #include <linux/errno.h>
11 #include <linux/completion.h>
13 #include <asm/chpid.h>
17 #define TAG "sclp_chp: "
19 #define SCLP_CMDW_CONFIGURE_CHANNEL_PATH 0x000f0001
20 #define SCLP_CMDW_DECONFIGURE_CHANNEL_PATH 0x000e0001
21 #define SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION 0x00030001
23 static inline sclp_cmdw_t
get_configure_cmdw(struct chp_id chpid
)
25 return SCLP_CMDW_CONFIGURE_CHANNEL_PATH
| chpid
.id
<< 8;
28 static inline sclp_cmdw_t
get_deconfigure_cmdw(struct chp_id chpid
)
30 return SCLP_CMDW_DECONFIGURE_CHANNEL_PATH
| chpid
.id
<< 8;
33 static void chp_callback(struct sclp_req
*req
, void *data
)
35 struct completion
*completion
= data
;
41 struct sccb_header header
;
45 } __attribute__((packed
));
48 struct chp_cfg_sccb sccb
;
50 struct completion completion
;
51 } __attribute__((packed
));
53 static int do_configure(sclp_cmdw_t cmd
)
55 struct chp_cfg_data
*data
;
58 if (!SCLP_HAS_CHP_RECONFIG
)
61 data
= (struct chp_cfg_data
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
64 data
->sccb
.header
.length
= sizeof(struct chp_cfg_sccb
);
65 data
->req
.command
= cmd
;
66 data
->req
.sccb
= &(data
->sccb
);
67 data
->req
.status
= SCLP_REQ_FILLED
;
68 data
->req
.callback
= chp_callback
;
69 data
->req
.callback_data
= &(data
->completion
);
70 init_completion(&data
->completion
);
72 /* Perform sclp request. */
73 rc
= sclp_add_request(&(data
->req
));
76 wait_for_completion(&data
->completion
);
79 if (data
->req
.status
!= SCLP_REQ_DONE
) {
80 printk(KERN_WARNING TAG
"configure channel-path request failed "
81 "(status=0x%02x)\n", data
->req
.status
);
85 switch (data
->sccb
.header
.response_code
) {
92 printk(KERN_WARNING TAG
"configure channel-path failed "
93 "(cmd=0x%08x, response=0x%04x)\n", cmd
,
94 data
->sccb
.header
.response_code
);
99 free_page((unsigned long) data
);
105 * sclp_chp_configure - perform configure channel-path sclp command
106 * @chpid: channel-path ID
108 * Perform configure channel-path command sclp command for specified chpid.
109 * Return 0 after command successfully finished, non-zero otherwise.
111 int sclp_chp_configure(struct chp_id chpid
)
113 return do_configure(get_configure_cmdw(chpid
));
117 * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
118 * @chpid: channel-path ID
120 * Perform deconfigure channel-path command sclp command for specified chpid
121 * and wait for completion. On success return 0. Return non-zero otherwise.
123 int sclp_chp_deconfigure(struct chp_id chpid
)
125 return do_configure(get_deconfigure_cmdw(chpid
));
128 struct chp_info_sccb
{
129 struct sccb_header header
;
130 u8 recognized
[SCLP_CHP_INFO_MASK_SIZE
];
131 u8 standby
[SCLP_CHP_INFO_MASK_SIZE
];
132 u8 configured
[SCLP_CHP_INFO_MASK_SIZE
];
136 } __attribute__((packed
));
138 struct chp_info_data
{
139 struct chp_info_sccb sccb
;
141 struct completion completion
;
142 } __attribute__((packed
));
145 * sclp_chp_read_info - perform read channel-path information sclp command
146 * @info: resulting channel-path information data
148 * Perform read channel-path information sclp command and wait for completion.
149 * On success, store channel-path information in @info and return 0. Return
150 * non-zero otherwise.
152 int sclp_chp_read_info(struct sclp_chp_info
*info
)
154 struct chp_info_data
*data
;
157 if (!SCLP_HAS_CHP_INFO
)
160 data
= (struct chp_info_data
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
163 data
->sccb
.header
.length
= sizeof(struct chp_info_sccb
);
164 data
->req
.command
= SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION
;
165 data
->req
.sccb
= &(data
->sccb
);
166 data
->req
.status
= SCLP_REQ_FILLED
;
167 data
->req
.callback
= chp_callback
;
168 data
->req
.callback_data
= &(data
->completion
);
169 init_completion(&data
->completion
);
171 /* Perform sclp request. */
172 rc
= sclp_add_request(&(data
->req
));
175 wait_for_completion(&data
->completion
);
177 /* Check response .*/
178 if (data
->req
.status
!= SCLP_REQ_DONE
) {
179 printk(KERN_WARNING TAG
"read channel-path info request failed "
180 "(status=0x%02x)\n", data
->req
.status
);
184 if (data
->sccb
.header
.response_code
!= 0x0010) {
185 printk(KERN_WARNING TAG
"read channel-path info failed "
186 "(response=0x%04x)\n", data
->sccb
.header
.response_code
);
190 memcpy(info
->recognized
, data
->sccb
.recognized
,
191 SCLP_CHP_INFO_MASK_SIZE
);
192 memcpy(info
->standby
, data
->sccb
.standby
,
193 SCLP_CHP_INFO_MASK_SIZE
);
194 memcpy(info
->configured
, data
->sccb
.configured
,
195 SCLP_CHP_INFO_MASK_SIZE
);
197 free_page((unsigned long) data
);