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
;
59 data
= (struct chp_cfg_data
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
62 data
->sccb
.header
.length
= sizeof(struct chp_cfg_sccb
);
63 data
->req
.command
= cmd
;
64 data
->req
.sccb
= &(data
->sccb
);
65 data
->req
.status
= SCLP_REQ_FILLED
;
66 data
->req
.callback
= chp_callback
;
67 data
->req
.callback_data
= &(data
->completion
);
68 init_completion(&data
->completion
);
70 /* Perform sclp request. */
71 rc
= sclp_add_request(&(data
->req
));
74 wait_for_completion(&data
->completion
);
77 if (data
->req
.status
!= SCLP_REQ_DONE
) {
78 printk(KERN_WARNING TAG
"configure channel-path request failed "
79 "(status=0x%02x)\n", data
->req
.status
);
83 switch (data
->sccb
.header
.response_code
) {
90 printk(KERN_WARNING TAG
"configure channel-path failed "
91 "(cmd=0x%08x, response=0x%04x)\n", cmd
,
92 data
->sccb
.header
.response_code
);
97 free_page((unsigned long) data
);
103 * sclp_chp_configure - perform configure channel-path sclp command
104 * @chpid: channel-path ID
106 * Perform configure channel-path command sclp command for specified chpid.
107 * Return 0 after command successfully finished, non-zero otherwise.
109 int sclp_chp_configure(struct chp_id chpid
)
111 return do_configure(get_configure_cmdw(chpid
));
115 * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
116 * @chpid: channel-path ID
118 * Perform deconfigure channel-path command sclp command for specified chpid
119 * and wait for completion. On success return 0. Return non-zero otherwise.
121 int sclp_chp_deconfigure(struct chp_id chpid
)
123 return do_configure(get_deconfigure_cmdw(chpid
));
126 struct chp_info_sccb
{
127 struct sccb_header header
;
128 u8 recognized
[SCLP_CHP_INFO_MASK_SIZE
];
129 u8 standby
[SCLP_CHP_INFO_MASK_SIZE
];
130 u8 configured
[SCLP_CHP_INFO_MASK_SIZE
];
134 } __attribute__((packed
));
136 struct chp_info_data
{
137 struct chp_info_sccb sccb
;
139 struct completion completion
;
140 } __attribute__((packed
));
143 * sclp_chp_read_info - perform read channel-path information sclp command
144 * @info: resulting channel-path information data
146 * Perform read channel-path information sclp command and wait for completion.
147 * On success, store channel-path information in @info and return 0. Return
148 * non-zero otherwise.
150 int sclp_chp_read_info(struct sclp_chp_info
*info
)
152 struct chp_info_data
*data
;
156 data
= (struct chp_info_data
*) get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
159 data
->sccb
.header
.length
= sizeof(struct chp_info_sccb
);
160 data
->req
.command
= SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION
;
161 data
->req
.sccb
= &(data
->sccb
);
162 data
->req
.status
= SCLP_REQ_FILLED
;
163 data
->req
.callback
= chp_callback
;
164 data
->req
.callback_data
= &(data
->completion
);
165 init_completion(&data
->completion
);
167 /* Perform sclp request. */
168 rc
= sclp_add_request(&(data
->req
));
171 wait_for_completion(&data
->completion
);
173 /* Check response .*/
174 if (data
->req
.status
!= SCLP_REQ_DONE
) {
175 printk(KERN_WARNING TAG
"read channel-path info request failed "
176 "(status=0x%02x)\n", data
->req
.status
);
180 if (data
->sccb
.header
.response_code
!= 0x0010) {
181 printk(KERN_WARNING TAG
"read channel-path info failed "
182 "(response=0x%04x)\n", data
->sccb
.header
.response_code
);
186 memcpy(info
->recognized
, data
->sccb
.recognized
,
187 SCLP_CHP_INFO_MASK_SIZE
);
188 memcpy(info
->standby
, data
->sccb
.standby
,
189 SCLP_CHP_INFO_MASK_SIZE
);
190 memcpy(info
->configured
, data
->sccb
.configured
,
191 SCLP_CHP_INFO_MASK_SIZE
);
193 free_page((unsigned long) data
);