diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 13:20:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 13:20:04 -0500 |
commit | ff47d8c05019d6e7753cef270d6399cb5a33be57 (patch) | |
tree | 78eec48c53554902062f9a06b57a700d7671330e /drivers | |
parent | 3051bf36c25d5153051704291782f8d44e744d36 (diff) | |
parent | d24b98e3a9c66b16ed029e1b2bcdf3c90e9d82d9 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
- New entropy generation for the pseudo random number generator.
- Early boot printk output via sclp to help debug crashes on boot. This
needs to be enabled with a kernel parameter.
- Add proper no-execute support with a bit in the page table entry.
- Bug fixes and cleanups.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (65 commits)
s390/syscall: fix single stepped system calls
s390/zcrypt: make ap_bus explicitly non-modular
s390/zcrypt: Removed unneeded debug feature directory creation.
s390: add missing "do {} while (0)" loop constructs to multiline macros
s390/mm: add cond_resched call to kernel page table dumper
s390: get rid of MACHINE_HAS_PFMF and MACHINE_HAS_HPAGE
s390/mm: make memory_block_size_bytes available for !MEMORY_HOTPLUG
s390: replace ACCESS_ONCE with READ_ONCE
s390: Audit and remove any remaining unnecessary uses of module.h
s390: mm: Audit and remove any unnecessary uses of module.h
s390: kernel: Audit and remove any unnecessary uses of module.h
s390/kdump: Use "LINUX" ELF note name instead of "CORE"
s390: add no-execute support
s390: report new vector facilities
s390: use correct input data address for setup_randomness
s390/sclp: get rid of common response code handling
s390/sclp: don't add new lines to each printed string
s390/sclp: make early sclp code readable
s390/sclp: disable early sclp code as soon as the base sclp driver is active
s390/sclp: move early printk code to drivers
...
Diffstat (limited to 'drivers')
28 files changed, 697 insertions, 534 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0e3fdfdbd098..6fb3fd5efc11 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1712,8 +1712,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1712 | /* check for for attention message */ | 1712 | /* check for for attention message */ |
1713 | if (scsw_dstat(&irb->scsw) & DEV_STAT_ATTENTION) { | 1713 | if (scsw_dstat(&irb->scsw) & DEV_STAT_ATTENTION) { |
1714 | device = dasd_device_from_cdev_locked(cdev); | 1714 | device = dasd_device_from_cdev_locked(cdev); |
1715 | device->discipline->check_attention(device, irb->esw.esw1.lpum); | 1715 | if (!IS_ERR(device)) { |
1716 | dasd_put_device(device); | 1716 | device->discipline->check_attention(device, |
1717 | irb->esw.esw1.lpum); | ||
1718 | dasd_put_device(device); | ||
1719 | } | ||
1717 | } | 1720 | } |
1718 | 1721 | ||
1719 | if (!cqr) | 1722 | if (!cqr) |
@@ -3598,10 +3601,11 @@ int dasd_generic_set_offline(struct ccw_device *cdev) | |||
3598 | * empty | 3601 | * empty |
3599 | */ | 3602 | */ |
3600 | /* sync blockdev and partitions */ | 3603 | /* sync blockdev and partitions */ |
3601 | rc = fsync_bdev(device->block->bdev); | 3604 | if (device->block) { |
3602 | if (rc != 0) | 3605 | rc = fsync_bdev(device->block->bdev); |
3603 | goto interrupted; | 3606 | if (rc != 0) |
3604 | 3607 | goto interrupted; | |
3608 | } | ||
3605 | /* schedule device tasklet and wait for completion */ | 3609 | /* schedule device tasklet and wait for completion */ |
3606 | dasd_schedule_device_bh(device); | 3610 | dasd_schedule_device_bh(device); |
3607 | rc = wait_event_interruptible(shutdown_waitq, | 3611 | rc = wait_event_interruptible(shutdown_waitq, |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index dd46e96a3034..1164b51d09f3 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -26,6 +26,7 @@ | |||
26 | /* This is ugly... */ | 26 | /* This is ugly... */ |
27 | #define PRINTK_HEADER "dasd_devmap:" | 27 | #define PRINTK_HEADER "dasd_devmap:" |
28 | #define DASD_BUS_ID_SIZE 20 | 28 | #define DASD_BUS_ID_SIZE 20 |
29 | #define DASD_MAX_PARAMS 256 | ||
29 | 30 | ||
30 | #include "dasd_int.h" | 31 | #include "dasd_int.h" |
31 | 32 | ||
@@ -76,7 +77,7 @@ EXPORT_SYMBOL_GPL(dasd_nofcx); | |||
76 | * it is named 'dasd' to directly be filled by insmod with the comma separated | 77 | * it is named 'dasd' to directly be filled by insmod with the comma separated |
77 | * strings when running as a module. | 78 | * strings when running as a module. |
78 | */ | 79 | */ |
79 | static char *dasd[256]; | 80 | static char *dasd[DASD_MAX_PARAMS]; |
80 | module_param_array(dasd, charp, NULL, S_IRUGO); | 81 | module_param_array(dasd, charp, NULL, S_IRUGO); |
81 | 82 | ||
82 | /* | 83 | /* |
@@ -104,18 +105,19 @@ dasd_hash_busid(const char *bus_id) | |||
104 | } | 105 | } |
105 | 106 | ||
106 | #ifndef MODULE | 107 | #ifndef MODULE |
107 | /* | 108 | static int __init dasd_call_setup(char *opt) |
108 | * The parameter parsing functions for builtin-drivers are called | ||
109 | * before kmalloc works. Store the pointers to the parameters strings | ||
110 | * into dasd[] for later processing. | ||
111 | */ | ||
112 | static int __init | ||
113 | dasd_call_setup(char *str) | ||
114 | { | 109 | { |
115 | static int count = 0; | 110 | static int i __initdata; |
111 | char *tmp; | ||
112 | |||
113 | while (i < DASD_MAX_PARAMS) { | ||
114 | tmp = strsep(&opt, ","); | ||
115 | if (!tmp) | ||
116 | break; | ||
117 | |||
118 | dasd[i++] = tmp; | ||
119 | } | ||
116 | 120 | ||
117 | if (count < 256) | ||
118 | dasd[count++] = str; | ||
119 | return 1; | 121 | return 1; |
120 | } | 122 | } |
121 | 123 | ||
@@ -127,14 +129,13 @@ __setup ("dasd=", dasd_call_setup); | |||
127 | /* | 129 | /* |
128 | * Read a device busid/devno from a string. | 130 | * Read a device busid/devno from a string. |
129 | */ | 131 | */ |
130 | static int | 132 | static int __init dasd_busid(char *str, int *id0, int *id1, int *devno) |
131 | |||
132 | dasd_busid(char **str, int *id0, int *id1, int *devno) | ||
133 | { | 133 | { |
134 | int val, old_style; | 134 | unsigned int val; |
135 | char *tok; | ||
135 | 136 | ||
136 | /* Interpret ipldev busid */ | 137 | /* Interpret ipldev busid */ |
137 | if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) { | 138 | if (strncmp(DASD_IPLDEV, str, strlen(DASD_IPLDEV)) == 0) { |
138 | if (ipl_info.type != IPL_TYPE_CCW) { | 139 | if (ipl_info.type != IPL_TYPE_CCW) { |
139 | pr_err("The IPL device is not a CCW device\n"); | 140 | pr_err("The IPL device is not a CCW device\n"); |
140 | return -EINVAL; | 141 | return -EINVAL; |
@@ -142,63 +143,50 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) | |||
142 | *id0 = 0; | 143 | *id0 = 0; |
143 | *id1 = ipl_info.data.ccw.dev_id.ssid; | 144 | *id1 = ipl_info.data.ccw.dev_id.ssid; |
144 | *devno = ipl_info.data.ccw.dev_id.devno; | 145 | *devno = ipl_info.data.ccw.dev_id.devno; |
145 | *str += strlen(DASD_IPLDEV); | ||
146 | 146 | ||
147 | return 0; | 147 | return 0; |
148 | } | 148 | } |
149 | /* check for leading '0x' */ | 149 | |
150 | old_style = 0; | 150 | /* Old style 0xXXXX or XXXX */ |
151 | if ((*str)[0] == '0' && (*str)[1] == 'x') { | 151 | if (!kstrtouint(str, 16, &val)) { |
152 | *str += 2; | ||
153 | old_style = 1; | ||
154 | } | ||
155 | if (!isxdigit((*str)[0])) /* We require at least one hex digit */ | ||
156 | return -EINVAL; | ||
157 | val = simple_strtoul(*str, str, 16); | ||
158 | if (old_style || (*str)[0] != '.') { | ||
159 | *id0 = *id1 = 0; | 152 | *id0 = *id1 = 0; |
160 | if (val < 0 || val > 0xffff) | 153 | if (val < 0 || val > 0xffff) |
161 | return -EINVAL; | 154 | return -EINVAL; |
162 | *devno = val; | 155 | *devno = val; |
163 | return 0; | 156 | return 0; |
164 | } | 157 | } |
158 | |||
165 | /* New style x.y.z busid */ | 159 | /* New style x.y.z busid */ |
166 | if (val < 0 || val > 0xff) | 160 | tok = strsep(&str, "."); |
161 | if (kstrtouint(tok, 16, &val) || val > 0xff) | ||
167 | return -EINVAL; | 162 | return -EINVAL; |
168 | *id0 = val; | 163 | *id0 = val; |
169 | (*str)++; | 164 | |
170 | if (!isxdigit((*str)[0])) /* We require at least one hex digit */ | 165 | tok = strsep(&str, "."); |
171 | return -EINVAL; | 166 | if (kstrtouint(tok, 16, &val) || val > 0xff) |
172 | val = simple_strtoul(*str, str, 16); | ||
173 | if (val < 0 || val > 0xff || (*str)++[0] != '.') | ||
174 | return -EINVAL; | 167 | return -EINVAL; |
175 | *id1 = val; | 168 | *id1 = val; |
176 | if (!isxdigit((*str)[0])) /* We require at least one hex digit */ | 169 | |
177 | return -EINVAL; | 170 | tok = strsep(&str, "."); |
178 | val = simple_strtoul(*str, str, 16); | 171 | if (kstrtouint(tok, 16, &val) || val > 0xffff) |
179 | if (val < 0 || val > 0xffff) | ||
180 | return -EINVAL; | 172 | return -EINVAL; |
181 | *devno = val; | 173 | *devno = val; |
174 | |||
182 | return 0; | 175 | return 0; |
183 | } | 176 | } |
184 | 177 | ||
185 | /* | 178 | /* |
186 | * Read colon separated list of dasd features. Currently there is | 179 | * Read colon separated list of dasd features. |
187 | * only one: "ro" for read-only devices. The default feature set | ||
188 | * is empty (value 0). | ||
189 | */ | 180 | */ |
190 | static int | 181 | static int __init dasd_feature_list(char *str) |
191 | dasd_feature_list(char *str, char **endp) | ||
192 | { | 182 | { |
193 | int features, len, rc; | 183 | int features, len, rc; |
194 | 184 | ||
185 | features = 0; | ||
195 | rc = 0; | 186 | rc = 0; |
196 | if (*str != '(') { | 187 | |
197 | *endp = str; | 188 | if (!str) |
198 | return DASD_FEATURE_DEFAULT; | 189 | return DASD_FEATURE_DEFAULT; |
199 | } | ||
200 | str++; | ||
201 | features = 0; | ||
202 | 190 | ||
203 | while (1) { | 191 | while (1) { |
204 | for (len = 0; | 192 | for (len = 0; |
@@ -223,15 +211,8 @@ dasd_feature_list(char *str, char **endp) | |||
223 | break; | 211 | break; |
224 | str++; | 212 | str++; |
225 | } | 213 | } |
226 | if (*str != ')') { | 214 | |
227 | pr_warn("A closing parenthesis ')' is missing in the dasd= parameter\n"); | 215 | return rc ? : features; |
228 | rc = -EINVAL; | ||
229 | } else | ||
230 | str++; | ||
231 | *endp = str; | ||
232 | if (rc != 0) | ||
233 | return rc; | ||
234 | return features; | ||
235 | } | 216 | } |
236 | 217 | ||
237 | /* | 218 | /* |
@@ -240,48 +221,38 @@ dasd_feature_list(char *str, char **endp) | |||
240 | * action and return a pointer to the residual string. If the first element | 221 | * action and return a pointer to the residual string. If the first element |
241 | * could not be matched to any keyword then return an error code. | 222 | * could not be matched to any keyword then return an error code. |
242 | */ | 223 | */ |
243 | static char * | 224 | static int __init dasd_parse_keyword(char *keyword) |
244 | dasd_parse_keyword( char *parsestring ) { | 225 | { |
245 | 226 | int length = strlen(keyword); | |
246 | char *nextcomma, *residual_str; | ||
247 | int length; | ||
248 | 227 | ||
249 | nextcomma = strchr(parsestring,','); | 228 | if (strncmp("autodetect", keyword, length) == 0) { |
250 | if (nextcomma) { | ||
251 | length = nextcomma - parsestring; | ||
252 | residual_str = nextcomma + 1; | ||
253 | } else { | ||
254 | length = strlen(parsestring); | ||
255 | residual_str = parsestring + length; | ||
256 | } | ||
257 | if (strncmp("autodetect", parsestring, length) == 0) { | ||
258 | dasd_autodetect = 1; | 229 | dasd_autodetect = 1; |
259 | pr_info("The autodetection mode has been activated\n"); | 230 | pr_info("The autodetection mode has been activated\n"); |
260 | return residual_str; | 231 | return 0; |
261 | } | 232 | } |
262 | if (strncmp("probeonly", parsestring, length) == 0) { | 233 | if (strncmp("probeonly", keyword, length) == 0) { |
263 | dasd_probeonly = 1; | 234 | dasd_probeonly = 1; |
264 | pr_info("The probeonly mode has been activated\n"); | 235 | pr_info("The probeonly mode has been activated\n"); |
265 | return residual_str; | 236 | return 0; |
266 | } | 237 | } |
267 | if (strncmp("nopav", parsestring, length) == 0) { | 238 | if (strncmp("nopav", keyword, length) == 0) { |
268 | if (MACHINE_IS_VM) | 239 | if (MACHINE_IS_VM) |
269 | pr_info("'nopav' is not supported on z/VM\n"); | 240 | pr_info("'nopav' is not supported on z/VM\n"); |
270 | else { | 241 | else { |
271 | dasd_nopav = 1; | 242 | dasd_nopav = 1; |
272 | pr_info("PAV support has be deactivated\n"); | 243 | pr_info("PAV support has be deactivated\n"); |
273 | } | 244 | } |
274 | return residual_str; | 245 | return 0; |
275 | } | 246 | } |
276 | if (strncmp("nofcx", parsestring, length) == 0) { | 247 | if (strncmp("nofcx", keyword, length) == 0) { |
277 | dasd_nofcx = 1; | 248 | dasd_nofcx = 1; |
278 | pr_info("High Performance FICON support has been " | 249 | pr_info("High Performance FICON support has been " |
279 | "deactivated\n"); | 250 | "deactivated\n"); |
280 | return residual_str; | 251 | return 0; |
281 | } | 252 | } |
282 | if (strncmp("fixedbuffers", parsestring, length) == 0) { | 253 | if (strncmp("fixedbuffers", keyword, length) == 0) { |
283 | if (dasd_page_cache) | 254 | if (dasd_page_cache) |
284 | return residual_str; | 255 | return 0; |
285 | dasd_page_cache = | 256 | dasd_page_cache = |
286 | kmem_cache_create("dasd_page_cache", PAGE_SIZE, | 257 | kmem_cache_create("dasd_page_cache", PAGE_SIZE, |
287 | PAGE_SIZE, SLAB_CACHE_DMA, | 258 | PAGE_SIZE, SLAB_CACHE_DMA, |
@@ -292,107 +263,126 @@ dasd_parse_keyword( char *parsestring ) { | |||
292 | else | 263 | else |
293 | DBF_EVENT(DBF_INFO, "%s", | 264 | DBF_EVENT(DBF_INFO, "%s", |
294 | "turning on fixed buffer mode"); | 265 | "turning on fixed buffer mode"); |
295 | return residual_str; | 266 | return 0; |
296 | } | 267 | } |
297 | return ERR_PTR(-EINVAL); | 268 | |
269 | return -EINVAL; | ||
298 | } | 270 | } |
299 | 271 | ||
300 | /* | 272 | /* |
301 | * Try to interprete the first element on the comma separated parse string | 273 | * Split a string of a device range into its pieces and return the from, to, and |
302 | * as a device number or a range of devices. If the interpretation is | 274 | * feature parts separately. |
303 | * successful, create the matching dasd_devmap entries and return a pointer | 275 | * e.g.: |
304 | * to the residual string. | 276 | * 0.0.1234-0.0.5678(ro:erplog) -> from: 0.0.1234 to: 0.0.5678 features: ro:erplog |
305 | * If interpretation fails or in case of an error, return an error code. | 277 | * 0.0.8765(raw) -> from: 0.0.8765 to: null features: raw |
278 | * 0x4321 -> from: 0x4321 to: null features: null | ||
306 | */ | 279 | */ |
307 | static char * | 280 | static int __init dasd_evaluate_range_param(char *range, char **from_str, |
308 | dasd_parse_range( char *parsestring ) { | 281 | char **to_str, char **features_str) |
282 | { | ||
283 | int rc = 0; | ||
284 | |||
285 | /* Do we have a range or a single device? */ | ||
286 | if (strchr(range, '-')) { | ||
287 | *from_str = strsep(&range, "-"); | ||
288 | *to_str = strsep(&range, "("); | ||
289 | *features_str = strsep(&range, ")"); | ||
290 | } else { | ||
291 | *from_str = strsep(&range, "("); | ||
292 | *features_str = strsep(&range, ")"); | ||
293 | } | ||
309 | 294 | ||
295 | if (*features_str && !range) { | ||
296 | pr_warn("A closing parenthesis ')' is missing in the dasd= parameter\n"); | ||
297 | rc = -EINVAL; | ||
298 | } | ||
299 | |||
300 | return rc; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Try to interprete the range string as a device number or a range of devices. | ||
305 | * If the interpretation is successful, create the matching dasd_devmap entries. | ||
306 | * If interpretation fails or in case of an error, return an error code. | ||
307 | */ | ||
308 | static int __init dasd_parse_range(const char *range) | ||
309 | { | ||
310 | struct dasd_devmap *devmap; | 310 | struct dasd_devmap *devmap; |
311 | int from, from_id0, from_id1; | 311 | int from, from_id0, from_id1; |
312 | int to, to_id0, to_id1; | 312 | int to, to_id0, to_id1; |
313 | int features, rc; | 313 | int features; |
314 | char bus_id[DASD_BUS_ID_SIZE+1], *str; | 314 | char bus_id[DASD_BUS_ID_SIZE + 1]; |
315 | 315 | char *features_str = NULL; | |
316 | str = parsestring; | 316 | char *from_str = NULL; |
317 | rc = dasd_busid(&str, &from_id0, &from_id1, &from); | 317 | char *to_str = NULL; |
318 | if (rc == 0) { | 318 | size_t len = strlen(range) + 1; |
319 | to = from; | 319 | char tmp[len]; |
320 | to_id0 = from_id0; | 320 | |
321 | to_id1 = from_id1; | 321 | strlcpy(tmp, range, len); |
322 | if (*str == '-') { | 322 | |
323 | str++; | 323 | if (dasd_evaluate_range_param(tmp, &from_str, &to_str, &features_str)) |
324 | rc = dasd_busid(&str, &to_id0, &to_id1, &to); | 324 | goto out_err; |
325 | |||
326 | if (dasd_busid(from_str, &from_id0, &from_id1, &from)) | ||
327 | goto out_err; | ||
328 | |||
329 | to = from; | ||
330 | to_id0 = from_id0; | ||
331 | to_id1 = from_id1; | ||
332 | if (to_str) { | ||
333 | if (dasd_busid(to_str, &to_id0, &to_id1, &to)) | ||
334 | goto out_err; | ||
335 | if (from_id0 != to_id0 || from_id1 != to_id1 || from > to) { | ||
336 | pr_err("%s is not a valid device range\n", range); | ||
337 | goto out_err; | ||
325 | } | 338 | } |
326 | } | 339 | } |
327 | if (rc == 0 && | 340 | |
328 | (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) | 341 | features = dasd_feature_list(features_str); |
329 | rc = -EINVAL; | ||
330 | if (rc) { | ||
331 | pr_err("%s is not a valid device range\n", parsestring); | ||
332 | return ERR_PTR(rc); | ||
333 | } | ||
334 | features = dasd_feature_list(str, &str); | ||
335 | if (features < 0) | 342 | if (features < 0) |
336 | return ERR_PTR(-EINVAL); | 343 | goto out_err; |
337 | /* each device in dasd= parameter should be set initially online */ | 344 | /* each device in dasd= parameter should be set initially online */ |
338 | features |= DASD_FEATURE_INITIAL_ONLINE; | 345 | features |= DASD_FEATURE_INITIAL_ONLINE; |
339 | while (from <= to) { | 346 | while (from <= to) { |
340 | sprintf(bus_id, "%01x.%01x.%04x", | 347 | sprintf(bus_id, "%01x.%01x.%04x", from_id0, from_id1, from++); |
341 | from_id0, from_id1, from++); | ||
342 | devmap = dasd_add_busid(bus_id, features); | 348 | devmap = dasd_add_busid(bus_id, features); |
343 | if (IS_ERR(devmap)) | 349 | if (IS_ERR(devmap)) |
344 | return (char *)devmap; | 350 | return PTR_ERR(devmap); |
345 | } | 351 | } |
346 | if (*str == ',') | ||
347 | return str + 1; | ||
348 | if (*str == '\0') | ||
349 | return str; | ||
350 | pr_warn("The dasd= parameter value %s has an invalid ending\n", str); | ||
351 | return ERR_PTR(-EINVAL); | ||
352 | } | ||
353 | 352 | ||
354 | static char * | 353 | return 0; |
355 | dasd_parse_next_element( char *parsestring ) { | 354 | |
356 | char * residual_str; | 355 | out_err: |
357 | residual_str = dasd_parse_keyword(parsestring); | 356 | return -EINVAL; |
358 | if (!IS_ERR(residual_str)) | ||
359 | return residual_str; | ||
360 | residual_str = dasd_parse_range(parsestring); | ||
361 | return residual_str; | ||
362 | } | 357 | } |
363 | 358 | ||
364 | /* | 359 | /* |
365 | * Parse parameters stored in dasd[] | 360 | * Parse parameters stored in dasd[] |
366 | * The 'dasd=...' parameter allows to specify a comma separated list of | 361 | * The 'dasd=...' parameter allows to specify a comma separated list of |
367 | * keywords and device ranges. When the dasd driver is build into the kernel, | 362 | * keywords and device ranges. The parameters in that list will be stored as |
368 | * the complete list will be stored as one element of the dasd[] array. | 363 | * separate elementes in dasd[]. |
369 | * When the dasd driver is build as a module, then the list is broken into | ||
370 | * it's elements and each dasd[] entry contains one element. | ||
371 | */ | 364 | */ |
372 | int | 365 | int __init dasd_parse(void) |
373 | dasd_parse(void) | ||
374 | { | 366 | { |
375 | int rc, i; | 367 | int rc, i; |
376 | char *parsestring; | 368 | char *cur; |
377 | 369 | ||
378 | rc = 0; | 370 | rc = 0; |
379 | for (i = 0; i < 256; i++) { | 371 | for (i = 0; i < DASD_MAX_PARAMS; i++) { |
380 | if (dasd[i] == NULL) | 372 | cur = dasd[i]; |
373 | if (!cur) | ||
381 | break; | 374 | break; |
382 | parsestring = dasd[i]; | 375 | if (*cur == '\0') |
383 | /* loop over the comma separated list in the parsestring */ | 376 | continue; |
384 | while (*parsestring) { | 377 | |
385 | parsestring = dasd_parse_next_element(parsestring); | 378 | rc = dasd_parse_keyword(cur); |
386 | if(IS_ERR(parsestring)) { | 379 | if (rc) |
387 | rc = PTR_ERR(parsestring); | 380 | rc = dasd_parse_range(cur); |
388 | break; | 381 | |
389 | } | 382 | if (rc) |
390 | } | ||
391 | if (rc) { | ||
392 | DBF_EVENT(DBF_ALERT, "%s", "invalid range found"); | ||
393 | break; | 383 | break; |
394 | } | ||
395 | } | 384 | } |
385 | |||
396 | return rc; | 386 | return rc; |
397 | } | 387 | } |
398 | 388 | ||
@@ -1528,14 +1518,12 @@ dasd_path_threshold_store(struct device *dev, struct device_attribute *attr, | |||
1528 | if (IS_ERR(device)) | 1518 | if (IS_ERR(device)) |
1529 | return -ENODEV; | 1519 | return -ENODEV; |
1530 | 1520 | ||
1531 | if ((kstrtoul(buf, 10, &val) != 0) || | 1521 | if (kstrtoul(buf, 10, &val) != 0 || val > DASD_THRHLD_MAX) { |
1532 | (val > DASD_THRHLD_MAX) || val == 0) { | ||
1533 | dasd_put_device(device); | 1522 | dasd_put_device(device); |
1534 | return -EINVAL; | 1523 | return -EINVAL; |
1535 | } | 1524 | } |
1536 | spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags); | 1525 | spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags); |
1537 | if (val) | 1526 | device->path_thrhld = val; |
1538 | device->path_thrhld = val; | ||
1539 | spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags); | 1527 | spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags); |
1540 | dasd_put_device(device); | 1528 | dasd_put_device(device); |
1541 | return count; | 1529 | return count; |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ade04216c970..0f1713727d4c 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -2543,8 +2543,8 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
2543 | DASD_ECKD_CCW_WRITE_CKD_MT; | 2543 | DASD_ECKD_CCW_WRITE_CKD_MT; |
2544 | ccw->flags = CCW_FLAG_SLI; | 2544 | ccw->flags = CCW_FLAG_SLI; |
2545 | ccw->count = 8; | 2545 | ccw->count = 8; |
2546 | ccw->cda = (__u32)(addr_t) ect; | 2546 | ccw->cda = (__u32)(addr_t) ect; |
2547 | ccw++; | 2547 | ccw++; |
2548 | } | 2548 | } |
2549 | } | 2549 | } |
2550 | } | 2550 | } |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 24be210c10e5..518dba2732d5 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -805,7 +805,7 @@ struct dasd_device *dasd_device_from_devindex(int); | |||
805 | void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *); | 805 | void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *); |
806 | struct dasd_device *dasd_device_from_gendisk(struct gendisk *); | 806 | struct dasd_device *dasd_device_from_gendisk(struct gendisk *); |
807 | 807 | ||
808 | int dasd_parse(void); | 808 | int dasd_parse(void) __init; |
809 | int dasd_busid_known(const char *); | 809 | int dasd_busid_known(const char *); |
810 | 810 | ||
811 | /* externals in dasd_gendisk.c */ | 811 | /* externals in dasd_gendisk.c */ |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 9d66b4fb174b..415d10a67b7a 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -892,7 +892,7 @@ dcssblk_direct_access (struct block_device *bdev, sector_t secnum, | |||
892 | dev_info = bdev->bd_disk->private_data; | 892 | dev_info = bdev->bd_disk->private_data; |
893 | if (!dev_info) | 893 | if (!dev_info) |
894 | return -ENODEV; | 894 | return -ENODEV; |
895 | dev_sz = dev_info->end - dev_info->start; | 895 | dev_sz = dev_info->end - dev_info->start + 1; |
896 | offset = secnum * 512; | 896 | offset = secnum * 512; |
897 | *kaddr = (void *) dev_info->start + offset; | 897 | *kaddr = (void *) dev_info->start + offset; |
898 | *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), PFN_DEV); | 898 | *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), PFN_DEV); |
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 41e28b23b26a..0c443e26835d 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -2,9 +2,23 @@ | |||
2 | # S/390 character devices | 2 | # S/390 character devices |
3 | # | 3 | # |
4 | 4 | ||
5 | ifdef CONFIG_FUNCTION_TRACER | ||
6 | # Do not trace early setup code | ||
7 | CFLAGS_REMOVE_sclp_early_core.o = $(CC_FLAGS_FTRACE) | ||
8 | endif | ||
9 | |||
10 | GCOV_PROFILE_sclp_early_core.o := n | ||
11 | KCOV_INSTRUMENT_sclp_early_core.o := n | ||
12 | UBSAN_SANITIZE_sclp_early_core.o := n | ||
13 | |||
14 | ifneq ($(CC_FLAGS_MARCH),-march=z900) | ||
15 | CFLAGS_REMOVE_sclp_early_core.o += $(CC_FLAGS_MARCH) | ||
16 | CFLAGS_sclp_early_core.o += -march=z900 | ||
17 | endif | ||
18 | |||
5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ | 19 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \ | 20 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \ |
7 | sclp_early.o | 21 | sclp_early.o sclp_early_core.o |
8 | 22 | ||
9 | obj-$(CONFIG_TN3270) += raw3270.o | 23 | obj-$(CONFIG_TN3270) += raw3270.o |
10 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 24 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 285b4006f44b..8522cfce5b4e 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | static struct raw3270_fn con3270_fn; | 32 | static struct raw3270_fn con3270_fn; |
33 | 33 | ||
34 | static bool auto_update = 1; | 34 | static bool auto_update = true; |
35 | module_param(auto_update, bool, 0); | 35 | module_param(auto_update, bool, 0); |
36 | 36 | ||
37 | /* | 37 | /* |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index a2da898ce90f..710f2292911d 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -82,7 +82,7 @@ static LIST_HEAD(raw3270_devices); | |||
82 | static int raw3270_registered; | 82 | static int raw3270_registered; |
83 | 83 | ||
84 | /* Module parameters */ | 84 | /* Module parameters */ |
85 | static bool tubxcorrect = 0; | 85 | static bool tubxcorrect; |
86 | module_param(tubxcorrect, bool, 0); | 86 | module_param(tubxcorrect, bool, 0); |
87 | 87 | ||
88 | /* | 88 | /* |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 272898225dbb..9c471ea1b99c 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -94,13 +94,6 @@ static struct timer_list sclp_request_timer; | |||
94 | /* Timer for queued requests. */ | 94 | /* Timer for queued requests. */ |
95 | static struct timer_list sclp_queue_timer; | 95 | static struct timer_list sclp_queue_timer; |
96 | 96 | ||
97 | /* Internal state: is the driver initialized? */ | ||
98 | static volatile enum sclp_init_state_t { | ||
99 | sclp_init_state_uninitialized, | ||
100 | sclp_init_state_initializing, | ||
101 | sclp_init_state_initialized | ||
102 | } sclp_init_state = sclp_init_state_uninitialized; | ||
103 | |||
104 | /* Internal state: is a request active at the sclp? */ | 97 | /* Internal state: is a request active at the sclp? */ |
105 | static volatile enum sclp_running_state_t { | 98 | static volatile enum sclp_running_state_t { |
106 | sclp_running_state_idle, | 99 | sclp_running_state_idle, |
@@ -147,31 +140,6 @@ static void __sclp_make_read_req(void); | |||
147 | static int sclp_init_mask(int calculate); | 140 | static int sclp_init_mask(int calculate); |
148 | static int sclp_init(void); | 141 | static int sclp_init(void); |
149 | 142 | ||
150 | /* Perform service call. Return 0 on success, non-zero otherwise. */ | ||
151 | int | ||
152 | sclp_service_call(sclp_cmdw_t command, void *sccb) | ||
153 | { | ||
154 | int cc = 4; /* Initialize for program check handling */ | ||
155 | |||
156 | asm volatile( | ||
157 | "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ | ||
158 | "1: ipm %0\n" | ||
159 | " srl %0,28\n" | ||
160 | "2:\n" | ||
161 | EX_TABLE(0b, 2b) | ||
162 | EX_TABLE(1b, 2b) | ||
163 | : "+&d" (cc) : "d" (command), "a" (__pa(sccb)) | ||
164 | : "cc", "memory"); | ||
165 | if (cc == 4) | ||
166 | return -EINVAL; | ||
167 | if (cc == 3) | ||
168 | return -EIO; | ||
169 | if (cc == 2) | ||
170 | return -EBUSY; | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | |||
175 | static void | 143 | static void |
176 | __sclp_queue_read_req(void) | 144 | __sclp_queue_read_req(void) |
177 | { | 145 | { |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index e1fc7eb043d6..53b5d1b9761a 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -204,19 +204,57 @@ void sclp_unregister(struct sclp_register *reg); | |||
204 | int sclp_remove_processed(struct sccb_header *sccb); | 204 | int sclp_remove_processed(struct sccb_header *sccb); |
205 | int sclp_deactivate(void); | 205 | int sclp_deactivate(void); |
206 | int sclp_reactivate(void); | 206 | int sclp_reactivate(void); |
207 | int sclp_service_call(sclp_cmdw_t command, void *sccb); | ||
208 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); | 207 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); |
209 | int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout); | 208 | int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout); |
210 | 209 | ||
211 | int sclp_sdias_init(void); | 210 | int sclp_sdias_init(void); |
212 | void sclp_sdias_exit(void); | 211 | void sclp_sdias_exit(void); |
213 | 212 | ||
213 | enum { | ||
214 | sclp_init_state_uninitialized, | ||
215 | sclp_init_state_initializing, | ||
216 | sclp_init_state_initialized | ||
217 | }; | ||
218 | |||
219 | extern int sclp_init_state; | ||
214 | extern int sclp_console_pages; | 220 | extern int sclp_console_pages; |
215 | extern int sclp_console_drop; | 221 | extern int sclp_console_drop; |
216 | extern unsigned long sclp_console_full; | 222 | extern unsigned long sclp_console_full; |
217 | 223 | ||
224 | extern char sclp_early_sccb[PAGE_SIZE]; | ||
225 | |||
226 | void sclp_early_wait_irq(void); | ||
227 | int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb); | ||
228 | unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb); | ||
229 | int sclp_early_set_event_mask(struct init_sccb *sccb, | ||
230 | unsigned long receive_mask, | ||
231 | unsigned long send_mask); | ||
232 | |||
218 | /* useful inlines */ | 233 | /* useful inlines */ |
219 | 234 | ||
235 | /* Perform service call. Return 0 on success, non-zero otherwise. */ | ||
236 | static inline int sclp_service_call(sclp_cmdw_t command, void *sccb) | ||
237 | { | ||
238 | int cc = 4; /* Initialize for program check handling */ | ||
239 | |||
240 | asm volatile( | ||
241 | "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ | ||
242 | "1: ipm %0\n" | ||
243 | " srl %0,28\n" | ||
244 | "2:\n" | ||
245 | EX_TABLE(0b, 2b) | ||
246 | EX_TABLE(1b, 2b) | ||
247 | : "+&d" (cc) : "d" (command), "a" ((unsigned long)sccb) | ||
248 | : "cc", "memory"); | ||
249 | if (cc == 4) | ||
250 | return -EINVAL; | ||
251 | if (cc == 3) | ||
252 | return -EIO; | ||
253 | if (cc == 2) | ||
254 | return -EBUSY; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
220 | /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ | 258 | /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ |
221 | /* translate single character from ASCII to EBCDIC */ | 259 | /* translate single character from ASCII to EBCDIC */ |
222 | static inline unsigned char | 260 | static inline unsigned char |
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index f8e46c22e641..519ec1787117 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c | |||
@@ -55,46 +55,23 @@ struct read_info_sccb { | |||
55 | u8 _pad_128[4096 - 128]; /* 128-4095 */ | 55 | u8 _pad_128[4096 - 128]; /* 128-4095 */ |
56 | } __packed __aligned(PAGE_SIZE); | 56 | } __packed __aligned(PAGE_SIZE); |
57 | 57 | ||
58 | static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; | ||
59 | static struct sclp_ipl_info sclp_ipl_info; | 58 | static struct sclp_ipl_info sclp_ipl_info; |
60 | 59 | ||
61 | struct sclp_info sclp; | 60 | struct sclp_info sclp; |
62 | EXPORT_SYMBOL(sclp); | 61 | EXPORT_SYMBOL(sclp); |
63 | 62 | ||
64 | static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | 63 | static int __init sclp_early_read_info(struct read_info_sccb *sccb) |
65 | { | 64 | { |
66 | int rc; | 65 | int i; |
67 | |||
68 | __ctl_set_bit(0, 9); | ||
69 | rc = sclp_service_call(cmd, sccb); | ||
70 | if (rc) | ||
71 | goto out; | ||
72 | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | | ||
73 | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); | ||
74 | local_irq_disable(); | ||
75 | out: | ||
76 | /* Contents of the sccb might have changed. */ | ||
77 | barrier(); | ||
78 | __ctl_clear_bit(0, 9); | ||
79 | return rc; | ||
80 | } | ||
81 | |||
82 | static int __init sclp_read_info_early(struct read_info_sccb *sccb) | ||
83 | { | ||
84 | int rc, i; | ||
85 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | 66 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, |
86 | SCLP_CMDW_READ_SCP_INFO}; | 67 | SCLP_CMDW_READ_SCP_INFO}; |
87 | 68 | ||
88 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | 69 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
89 | do { | 70 | memset(sccb, 0, sizeof(*sccb)); |
90 | memset(sccb, 0, sizeof(*sccb)); | 71 | sccb->header.length = sizeof(*sccb); |
91 | sccb->header.length = sizeof(*sccb); | 72 | sccb->header.function_code = 0x80; |
92 | sccb->header.function_code = 0x80; | 73 | sccb->header.control_mask[2] = 0x80; |
93 | sccb->header.control_mask[2] = 0x80; | 74 | if (sclp_early_cmd(commands[i], sccb)) |
94 | rc = sclp_cmd_sync_early(commands[i], sccb); | ||
95 | } while (rc == -EBUSY); | ||
96 | |||
97 | if (rc) | ||
98 | break; | 75 | break; |
99 | if (sccb->header.response_code == 0x10) | 76 | if (sccb->header.response_code == 0x10) |
100 | return 0; | 77 | return 0; |
@@ -104,12 +81,12 @@ static int __init sclp_read_info_early(struct read_info_sccb *sccb) | |||
104 | return -EIO; | 81 | return -EIO; |
105 | } | 82 | } |
106 | 83 | ||
107 | static void __init sclp_facilities_detect(struct read_info_sccb *sccb) | 84 | static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb) |
108 | { | 85 | { |
109 | struct sclp_core_entry *cpue; | 86 | struct sclp_core_entry *cpue; |
110 | u16 boot_cpu_address, cpu; | 87 | u16 boot_cpu_address, cpu; |
111 | 88 | ||
112 | if (sclp_read_info_early(sccb)) | 89 | if (sclp_early_read_info(sccb)) |
113 | return; | 90 | return; |
114 | 91 | ||
115 | sclp.facilities = sccb->facilities; | 92 | sclp.facilities = sccb->facilities; |
@@ -172,141 +149,96 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb) | |||
172 | } | 149 | } |
173 | 150 | ||
174 | /* | 151 | /* |
175 | * This function will be called after sclp_facilities_detect(), which gets | 152 | * This function will be called after sclp_early_facilities_detect(), which gets |
176 | * called from early.c code. The sclp_facilities_detect() function retrieves | 153 | * called from early.c code. The sclp_early_facilities_detect() function retrieves |
177 | * and saves the IPL information. | 154 | * and saves the IPL information. |
178 | */ | 155 | */ |
179 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | 156 | void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info) |
180 | { | 157 | { |
181 | *info = sclp_ipl_info; | 158 | *info = sclp_ipl_info; |
182 | } | 159 | } |
183 | 160 | ||
184 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | 161 | static struct sclp_core_info sclp_early_core_info __initdata; |
185 | { | 162 | static int sclp_early_core_info_valid __initdata; |
186 | int rc; | ||
187 | |||
188 | do { | ||
189 | rc = sclp_cmd_sync_early(cmd, sccb); | ||
190 | } while (rc == -EBUSY); | ||
191 | |||
192 | if (rc) | ||
193 | return -EIO; | ||
194 | if (((struct sccb_header *) sccb)->response_code != 0x0020) | ||
195 | return -EIO; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static void __init sccb_init_eq_size(struct sdias_sccb *sccb) | ||
200 | { | ||
201 | memset(sccb, 0, sizeof(*sccb)); | ||
202 | |||
203 | sccb->hdr.length = sizeof(*sccb); | ||
204 | sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf); | ||
205 | sccb->evbuf.hdr.type = EVTYP_SDIAS; | ||
206 | sccb->evbuf.event_qual = SDIAS_EQ_SIZE; | ||
207 | sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP; | ||
208 | sccb->evbuf.event_id = 4712; | ||
209 | sccb->evbuf.dbs = 1; | ||
210 | } | ||
211 | 163 | ||
212 | static int __init sclp_set_event_mask(struct init_sccb *sccb, | 164 | static void __init sclp_early_init_core_info(struct read_cpu_info_sccb *sccb) |
213 | unsigned long receive_mask, | ||
214 | unsigned long send_mask) | ||
215 | { | 165 | { |
216 | memset(sccb, 0, sizeof(*sccb)); | ||
217 | sccb->header.length = sizeof(*sccb); | ||
218 | sccb->mask_length = sizeof(sccb_mask_t); | ||
219 | sccb->receive_mask = receive_mask; | ||
220 | sccb->send_mask = send_mask; | ||
221 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
222 | } | ||
223 | |||
224 | static struct sclp_core_info sclp_core_info_early __initdata; | ||
225 | static int sclp_core_info_early_valid __initdata; | ||
226 | |||
227 | static void __init sclp_init_core_info_early(struct read_cpu_info_sccb *sccb) | ||
228 | { | ||
229 | int rc; | ||
230 | |||
231 | if (!SCLP_HAS_CPU_INFO) | 166 | if (!SCLP_HAS_CPU_INFO) |
232 | return; | 167 | return; |
233 | memset(sccb, 0, sizeof(*sccb)); | 168 | memset(sccb, 0, sizeof(*sccb)); |
234 | sccb->header.length = sizeof(*sccb); | 169 | sccb->header.length = sizeof(*sccb); |
235 | do { | 170 | if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) |
236 | rc = sclp_cmd_sync_early(SCLP_CMDW_READ_CPU_INFO, sccb); | ||
237 | } while (rc == -EBUSY); | ||
238 | if (rc) | ||
239 | return; | 171 | return; |
240 | if (sccb->header.response_code != 0x0010) | 172 | if (sccb->header.response_code != 0x0010) |
241 | return; | 173 | return; |
242 | sclp_fill_core_info(&sclp_core_info_early, sccb); | 174 | sclp_fill_core_info(&sclp_early_core_info, sccb); |
243 | sclp_core_info_early_valid = 1; | 175 | sclp_early_core_info_valid = 1; |
244 | } | 176 | } |
245 | 177 | ||
246 | int __init _sclp_get_core_info_early(struct sclp_core_info *info) | 178 | int __init sclp_early_get_core_info(struct sclp_core_info *info) |
247 | { | 179 | { |
248 | if (!sclp_core_info_early_valid) | 180 | if (!sclp_early_core_info_valid) |
249 | return -EIO; | 181 | return -EIO; |
250 | *info = sclp_core_info_early; | 182 | *info = sclp_early_core_info; |
251 | return 0; | 183 | return 0; |
252 | } | 184 | } |
253 | 185 | ||
254 | static long __init sclp_hsa_size_init(struct sdias_sccb *sccb) | 186 | static long __init sclp_early_hsa_size_init(struct sdias_sccb *sccb) |
255 | { | 187 | { |
256 | sccb_init_eq_size(sccb); | 188 | memset(sccb, 0, sizeof(*sccb)); |
257 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | 189 | sccb->hdr.length = sizeof(*sccb); |
190 | sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf); | ||
191 | sccb->evbuf.hdr.type = EVTYP_SDIAS; | ||
192 | sccb->evbuf.event_qual = SDIAS_EQ_SIZE; | ||
193 | sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP; | ||
194 | sccb->evbuf.event_id = 4712; | ||
195 | sccb->evbuf.dbs = 1; | ||
196 | if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | ||
197 | return -EIO; | ||
198 | if (sccb->hdr.response_code != 0x20) | ||
258 | return -EIO; | 199 | return -EIO; |
259 | if (sccb->evbuf.blk_cnt == 0) | 200 | if (sccb->evbuf.blk_cnt == 0) |
260 | return 0; | 201 | return 0; |
261 | return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE; | 202 | return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE; |
262 | } | 203 | } |
263 | 204 | ||
264 | static long __init sclp_hsa_copy_wait(struct sccb_header *sccb) | 205 | static long __init sclp_early_hsa_copy_wait(struct sdias_sccb *sccb) |
265 | { | 206 | { |
266 | memset(sccb, 0, PAGE_SIZE); | 207 | memset(sccb, 0, PAGE_SIZE); |
267 | sccb->length = PAGE_SIZE; | 208 | sccb->hdr.length = PAGE_SIZE; |
268 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) | 209 | if (sclp_early_cmd(SCLP_CMDW_READ_EVENT_DATA, sccb)) |
269 | return -EIO; | 210 | return -EIO; |
270 | if (((struct sdias_sccb *) sccb)->evbuf.blk_cnt == 0) | 211 | if ((sccb->hdr.response_code != 0x20) && (sccb->hdr.response_code != 0x220)) |
212 | return -EIO; | ||
213 | if (sccb->evbuf.blk_cnt == 0) | ||
271 | return 0; | 214 | return 0; |
272 | return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE; | 215 | return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE; |
273 | } | 216 | } |
274 | 217 | ||
275 | static void __init sclp_hsa_size_detect(void *sccb) | 218 | static void __init sclp_early_hsa_size_detect(void *sccb) |
276 | { | 219 | { |
277 | long size; | 220 | unsigned long flags; |
221 | long size = -EIO; | ||
278 | 222 | ||
279 | /* First try synchronous interface (LPAR) */ | 223 | raw_local_irq_save(flags); |
280 | if (sclp_set_event_mask(sccb, 0, 0x40000010)) | 224 | if (sclp_early_set_event_mask(sccb, EVTYP_SDIAS_MASK, EVTYP_SDIAS_MASK)) |
281 | return; | ||
282 | size = sclp_hsa_size_init(sccb); | ||
283 | if (size < 0) | ||
284 | return; | ||
285 | if (size != 0) | ||
286 | goto out; | 225 | goto out; |
287 | /* Then try asynchronous interface (z/VM) */ | 226 | size = sclp_early_hsa_size_init(sccb); |
288 | if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010)) | 227 | /* First check for synchronous response (LPAR) */ |
289 | return; | 228 | if (size) |
290 | size = sclp_hsa_size_init(sccb); | 229 | goto out_mask; |
291 | if (size < 0) | 230 | if (!(S390_lowcore.ext_params & 1)) |
292 | return; | 231 | sclp_early_wait_irq(); |
293 | size = sclp_hsa_copy_wait(sccb); | 232 | size = sclp_early_hsa_copy_wait(sccb); |
294 | if (size < 0) | 233 | out_mask: |
295 | return; | 234 | sclp_early_set_event_mask(sccb, 0, 0); |
296 | out: | 235 | out: |
297 | sclp.hsa_size = size; | 236 | raw_local_irq_restore(flags); |
298 | } | 237 | if (size > 0) |
299 | 238 | sclp.hsa_size = size; | |
300 | static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb) | ||
301 | { | ||
302 | if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK)) | ||
303 | return 0; | ||
304 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
305 | return 0; | ||
306 | return 1; | ||
307 | } | 239 | } |
308 | 240 | ||
309 | static void __init sclp_console_detect(struct init_sccb *sccb) | 241 | static void __init sclp_early_console_detect(struct init_sccb *sccb) |
310 | { | 242 | { |
311 | if (sccb->header.response_code != 0x20) | 243 | if (sccb->header.response_code != 0x20) |
312 | return; | 244 | return; |
@@ -314,21 +246,22 @@ static void __init sclp_console_detect(struct init_sccb *sccb) | |||
314 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | 246 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) |
315 | sclp.has_vt220 = 1; | 247 | sclp.has_vt220 = 1; |
316 | 248 | ||
317 | if (sclp_con_check_linemode(sccb)) | 249 | if (sclp_early_con_check_linemode(sccb)) |
318 | sclp.has_linemode = 1; | 250 | sclp.has_linemode = 1; |
319 | } | 251 | } |
320 | 252 | ||
321 | void __init sclp_early_detect(void) | 253 | void __init sclp_early_detect(void) |
322 | { | 254 | { |
323 | void *sccb = &sccb_early; | 255 | void *sccb = &sclp_early_sccb; |
324 | 256 | ||
325 | sclp_facilities_detect(sccb); | 257 | sclp_early_facilities_detect(sccb); |
326 | sclp_init_core_info_early(sccb); | 258 | sclp_early_init_core_info(sccb); |
327 | sclp_hsa_size_detect(sccb); | 259 | sclp_early_hsa_size_detect(sccb); |
328 | 260 | ||
329 | /* Turn off SCLP event notifications. Also save remote masks in the | 261 | /* |
262 | * Turn off SCLP event notifications. Also save remote masks in the | ||
330 | * sccb. These are sufficient to detect sclp console capabilities. | 263 | * sccb. These are sufficient to detect sclp console capabilities. |
331 | */ | 264 | */ |
332 | sclp_set_event_mask(sccb, 0, 0); | 265 | sclp_early_set_event_mask(sccb, 0, 0); |
333 | sclp_console_detect(sccb); | 266 | sclp_early_console_detect(sccb); |
334 | } | 267 | } |
diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c new file mode 100644 index 000000000000..5029cc87e80f --- /dev/null +++ b/drivers/s390/char/sclp_early_core.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2015 | ||
3 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <asm/processor.h> | ||
8 | #include <asm/lowcore.h> | ||
9 | #include <asm/ebcdic.h> | ||
10 | #include <asm/irq.h> | ||
11 | #include "sclp.h" | ||
12 | #include "sclp_rw.h" | ||
13 | |||
14 | char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(data); | ||
15 | int sclp_init_state __section(data) = sclp_init_state_uninitialized; | ||
16 | |||
17 | void sclp_early_wait_irq(void) | ||
18 | { | ||
19 | unsigned long psw_mask, addr; | ||
20 | psw_t psw_ext_save, psw_wait; | ||
21 | union ctlreg0 cr0, cr0_new; | ||
22 | |||
23 | __ctl_store(cr0.val, 0, 0); | ||
24 | cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; | ||
25 | cr0_new.lap = 0; | ||
26 | cr0_new.sssm = 1; | ||
27 | __ctl_load(cr0_new.val, 0, 0); | ||
28 | |||
29 | psw_ext_save = S390_lowcore.external_new_psw; | ||
30 | psw_mask = __extract_psw(); | ||
31 | S390_lowcore.external_new_psw.mask = psw_mask; | ||
32 | psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT; | ||
33 | S390_lowcore.ext_int_code = 0; | ||
34 | |||
35 | do { | ||
36 | asm volatile( | ||
37 | " larl %[addr],0f\n" | ||
38 | " stg %[addr],%[psw_wait_addr]\n" | ||
39 | " stg %[addr],%[psw_ext_addr]\n" | ||
40 | " lpswe %[psw_wait]\n" | ||
41 | "0:\n" | ||
42 | : [addr] "=&d" (addr), | ||
43 | [psw_wait_addr] "=Q" (psw_wait.addr), | ||
44 | [psw_ext_addr] "=Q" (S390_lowcore.external_new_psw.addr) | ||
45 | : [psw_wait] "Q" (psw_wait) | ||
46 | : "cc", "memory"); | ||
47 | } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG); | ||
48 | |||
49 | S390_lowcore.external_new_psw = psw_ext_save; | ||
50 | __ctl_load(cr0.val, 0, 0); | ||
51 | } | ||
52 | |||
53 | int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb) | ||
54 | { | ||
55 | unsigned long flags; | ||
56 | int rc; | ||
57 | |||
58 | raw_local_irq_save(flags); | ||
59 | rc = sclp_service_call(cmd, sccb); | ||
60 | if (rc) | ||
61 | goto out; | ||
62 | sclp_early_wait_irq(); | ||
63 | out: | ||
64 | raw_local_irq_restore(flags); | ||
65 | return rc; | ||
66 | } | ||
67 | |||
68 | struct write_sccb { | ||
69 | struct sccb_header header; | ||
70 | struct msg_buf msg; | ||
71 | } __packed; | ||
72 | |||
73 | /* Output multi-line text using SCLP Message interface. */ | ||
74 | static void sclp_early_print_lm(const char *str, unsigned int len) | ||
75 | { | ||
76 | unsigned char *ptr, *end, ch; | ||
77 | unsigned int count, offset; | ||
78 | struct write_sccb *sccb; | ||
79 | struct msg_buf *msg; | ||
80 | struct mdb *mdb; | ||
81 | struct mto *mto; | ||
82 | struct go *go; | ||
83 | |||
84 | sccb = (struct write_sccb *) &sclp_early_sccb; | ||
85 | end = (unsigned char *) sccb + sizeof(sclp_early_sccb) - 1; | ||
86 | memset(sccb, 0, sizeof(*sccb)); | ||
87 | ptr = (unsigned char *) &sccb->msg.mdb.mto; | ||
88 | offset = 0; | ||
89 | do { | ||
90 | for (count = sizeof(*mto); offset < len; count++) { | ||
91 | ch = str[offset++]; | ||
92 | if ((ch == 0x0a) || (ptr + count > end)) | ||
93 | break; | ||
94 | ptr[count] = _ascebc[ch]; | ||
95 | } | ||
96 | mto = (struct mto *) ptr; | ||
97 | memset(mto, 0, sizeof(*mto)); | ||
98 | mto->length = count; | ||
99 | mto->type = 4; | ||
100 | mto->line_type_flags = LNTPFLGS_ENDTEXT; | ||
101 | ptr += count; | ||
102 | } while ((offset < len) && (ptr + sizeof(*mto) <= end)); | ||
103 | len = ptr - (unsigned char *) sccb; | ||
104 | sccb->header.length = len - offsetof(struct write_sccb, header); | ||
105 | msg = &sccb->msg; | ||
106 | msg->header.type = EVTYP_MSG; | ||
107 | msg->header.length = len - offsetof(struct write_sccb, msg.header); | ||
108 | mdb = &msg->mdb; | ||
109 | mdb->header.type = 1; | ||
110 | mdb->header.tag = 0xD4C4C240; | ||
111 | mdb->header.revision_code = 1; | ||
112 | mdb->header.length = len - offsetof(struct write_sccb, msg.mdb.header); | ||
113 | go = &mdb->go; | ||
114 | go->length = sizeof(*go); | ||
115 | go->type = 1; | ||
116 | sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb); | ||
117 | } | ||
118 | |||
119 | struct vt220_sccb { | ||
120 | struct sccb_header header; | ||
121 | struct { | ||
122 | struct evbuf_header header; | ||
123 | char data[]; | ||
124 | } msg; | ||
125 | } __packed; | ||
126 | |||
127 | /* Output multi-line text using SCLP VT220 interface. */ | ||
128 | static void sclp_early_print_vt220(const char *str, unsigned int len) | ||
129 | { | ||
130 | struct vt220_sccb *sccb; | ||
131 | |||
132 | sccb = (struct vt220_sccb *) &sclp_early_sccb; | ||
133 | if (sizeof(*sccb) + len >= sizeof(sclp_early_sccb)) | ||
134 | len = sizeof(sclp_early_sccb) - sizeof(*sccb); | ||
135 | memset(sccb, 0, sizeof(*sccb)); | ||
136 | memcpy(&sccb->msg.data, str, len); | ||
137 | sccb->header.length = sizeof(*sccb) + len; | ||
138 | sccb->msg.header.length = sizeof(sccb->msg) + len; | ||
139 | sccb->msg.header.type = EVTYP_VT220MSG; | ||
140 | sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb); | ||
141 | } | ||
142 | |||
143 | int sclp_early_set_event_mask(struct init_sccb *sccb, | ||
144 | unsigned long receive_mask, | ||
145 | unsigned long send_mask) | ||
146 | { | ||
147 | memset(sccb, 0, sizeof(*sccb)); | ||
148 | sccb->header.length = sizeof(*sccb); | ||
149 | sccb->mask_length = sizeof(sccb_mask_t); | ||
150 | sccb->receive_mask = receive_mask; | ||
151 | sccb->send_mask = send_mask; | ||
152 | if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb)) | ||
153 | return -EIO; | ||
154 | if (sccb->header.response_code != 0x20) | ||
155 | return -EIO; | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb) | ||
160 | { | ||
161 | if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK)) | ||
162 | return 0; | ||
163 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
164 | return 0; | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220) | ||
169 | { | ||
170 | unsigned long receive_mask, send_mask; | ||
171 | struct init_sccb *sccb; | ||
172 | int rc; | ||
173 | |||
174 | *have_linemode = *have_vt220 = 0; | ||
175 | sccb = (struct init_sccb *) &sclp_early_sccb; | ||
176 | receive_mask = disable ? 0 : EVTYP_OPCMD_MASK; | ||
177 | send_mask = disable ? 0 : EVTYP_VT220MSG_MASK | EVTYP_MSG_MASK; | ||
178 | rc = sclp_early_set_event_mask(sccb, receive_mask, send_mask); | ||
179 | if (rc) | ||
180 | return rc; | ||
181 | *have_linemode = sclp_early_con_check_linemode(sccb); | ||
182 | *have_vt220 = sccb->send_mask & EVTYP_VT220MSG_MASK; | ||
183 | return rc; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Output one or more lines of text on the SCLP console (VT220 and / | ||
188 | * or line-mode). | ||
189 | */ | ||
190 | void __sclp_early_printk(const char *str, unsigned int len) | ||
191 | { | ||
192 | int have_linemode, have_vt220; | ||
193 | |||
194 | if (sclp_init_state != sclp_init_state_uninitialized) | ||
195 | return; | ||
196 | if (sclp_early_setup(0, &have_linemode, &have_vt220) != 0) | ||
197 | return; | ||
198 | if (have_linemode) | ||
199 | sclp_early_print_lm(str, len); | ||
200 | if (have_vt220) | ||
201 | sclp_early_print_vt220(str, len); | ||
202 | sclp_early_setup(1, &have_linemode, &have_vt220); | ||
203 | } | ||
204 | |||
205 | void sclp_early_printk(const char *str) | ||
206 | { | ||
207 | __sclp_early_printk(str, strlen(str)); | ||
208 | } | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index d3b51edb056e..aaed778f67c4 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/debugfs.h> | 18 | #include <linux/debugfs.h> |
20 | #include <linux/memblock.h> | 19 | #include <linux/memblock.h> |
21 | 20 | ||
@@ -273,7 +272,7 @@ static int __init zcore_reipl_init(void) | |||
273 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); | 272 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); |
274 | else | 273 | else |
275 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); | 274 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); |
276 | if (rc || csum_partial(ipl_block, ipl_block->hdr.len, 0) != | 275 | if (rc || (__force u32)csum_partial(ipl_block, ipl_block->hdr.len, 0) != |
277 | ipib_info.checksum) { | 276 | ipib_info.checksum) { |
278 | TRACE("Checksum does not match\n"); | 277 | TRACE("Checksum does not match\n"); |
279 | free_page((unsigned long) ipl_block); | 278 | free_page((unsigned long) ipl_block); |
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 876c7e6e3a99..7e0d4f724dda 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -444,6 +444,7 @@ int chp_update_desc(struct channel_path *chp) | |||
444 | */ | 444 | */ |
445 | int chp_new(struct chp_id chpid) | 445 | int chp_new(struct chp_id chpid) |
446 | { | 446 | { |
447 | struct channel_subsystem *css = css_by_id(chpid.cssid); | ||
447 | struct channel_path *chp; | 448 | struct channel_path *chp; |
448 | int ret; | 449 | int ret; |
449 | 450 | ||
@@ -456,7 +457,7 @@ int chp_new(struct chp_id chpid) | |||
456 | /* fill in status, etc. */ | 457 | /* fill in status, etc. */ |
457 | chp->chpid = chpid; | 458 | chp->chpid = chpid; |
458 | chp->state = 1; | 459 | chp->state = 1; |
459 | chp->dev.parent = &channel_subsystems[chpid.cssid]->device; | 460 | chp->dev.parent = &css->device; |
460 | chp->dev.groups = chp_attr_groups; | 461 | chp->dev.groups = chp_attr_groups; |
461 | chp->dev.release = chp_release; | 462 | chp->dev.release = chp_release; |
462 | mutex_init(&chp->lock); | 463 | mutex_init(&chp->lock); |
@@ -479,17 +480,17 @@ int chp_new(struct chp_id chpid) | |||
479 | put_device(&chp->dev); | 480 | put_device(&chp->dev); |
480 | goto out; | 481 | goto out; |
481 | } | 482 | } |
482 | mutex_lock(&channel_subsystems[chpid.cssid]->mutex); | 483 | mutex_lock(&css->mutex); |
483 | if (channel_subsystems[chpid.cssid]->cm_enabled) { | 484 | if (css->cm_enabled) { |
484 | ret = chp_add_cmg_attr(chp); | 485 | ret = chp_add_cmg_attr(chp); |
485 | if (ret) { | 486 | if (ret) { |
486 | device_unregister(&chp->dev); | 487 | device_unregister(&chp->dev); |
487 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); | 488 | mutex_unlock(&css->mutex); |
488 | goto out; | 489 | goto out; |
489 | } | 490 | } |
490 | } | 491 | } |
491 | channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; | 492 | css->chps[chpid.id] = chp; |
492 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); | 493 | mutex_unlock(&css->mutex); |
493 | goto out; | 494 | goto out; |
494 | out_free: | 495 | out_free: |
495 | kfree(chp); | 496 | kfree(chp); |
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h index bb5a68226cda..0d8437b7ea72 100644 --- a/drivers/s390/cio/chp.h +++ b/drivers/s390/cio/chp.h | |||
@@ -54,7 +54,7 @@ struct channel_path { | |||
54 | /* Return channel_path struct for given chpid. */ | 54 | /* Return channel_path struct for given chpid. */ |
55 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) | 55 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) |
56 | { | 56 | { |
57 | return channel_subsystems[chpid.cssid]->chps[chpid.id]; | 57 | return css_by_id(chpid.cssid)->chps[chpid.id]; |
58 | } | 58 | } |
59 | 59 | ||
60 | int chp_get_status(struct chp_id chpid); | 60 | int chp_get_status(struct chp_id chpid); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 11674698b36d..7b0b295b2313 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -1131,6 +1131,52 @@ int chsc_enable_facility(int operation_code) | |||
1131 | return ret; | 1131 | return ret; |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | int __init chsc_get_cssid(int idx) | ||
1135 | { | ||
1136 | struct { | ||
1137 | struct chsc_header request; | ||
1138 | u8 atype; | ||
1139 | u32 : 24; | ||
1140 | u32 reserved1[6]; | ||
1141 | struct chsc_header response; | ||
1142 | u32 reserved2[3]; | ||
1143 | struct { | ||
1144 | u8 cssid; | ||
1145 | u32 : 24; | ||
1146 | } list[0]; | ||
1147 | } __packed *sdcal_area; | ||
1148 | int ret; | ||
1149 | |||
1150 | spin_lock_irq(&chsc_page_lock); | ||
1151 | memset(chsc_page, 0, PAGE_SIZE); | ||
1152 | sdcal_area = chsc_page; | ||
1153 | sdcal_area->request.length = 0x0020; | ||
1154 | sdcal_area->request.code = 0x0034; | ||
1155 | sdcal_area->atype = 4; | ||
1156 | |||
1157 | ret = chsc(sdcal_area); | ||
1158 | if (ret) { | ||
1159 | ret = (ret == 3) ? -ENODEV : -EBUSY; | ||
1160 | goto exit; | ||
1161 | } | ||
1162 | |||
1163 | ret = chsc_error_from_response(sdcal_area->response.code); | ||
1164 | if (ret) { | ||
1165 | CIO_CRW_EVENT(2, "chsc: sdcal failed (rc=%04x)\n", | ||
1166 | sdcal_area->response.code); | ||
1167 | goto exit; | ||
1168 | } | ||
1169 | |||
1170 | if ((addr_t) &sdcal_area->list[idx] < | ||
1171 | (addr_t) &sdcal_area->response + sdcal_area->response.length) | ||
1172 | ret = sdcal_area->list[idx].cssid; | ||
1173 | else | ||
1174 | ret = -ENODEV; | ||
1175 | exit: | ||
1176 | spin_unlock_irq(&chsc_page_lock); | ||
1177 | return ret; | ||
1178 | } | ||
1179 | |||
1134 | struct css_general_char css_general_characteristics; | 1180 | struct css_general_char css_general_characteristics; |
1135 | struct css_chsc_char css_chsc_characteristics; | 1181 | struct css_chsc_char css_chsc_characteristics; |
1136 | 1182 | ||
@@ -1216,7 +1262,7 @@ int chsc_sstpi(void *page, void *result, size_t size) | |||
1216 | struct chsc_header request; | 1262 | struct chsc_header request; |
1217 | unsigned int rsvd0[3]; | 1263 | unsigned int rsvd0[3]; |
1218 | struct chsc_header response; | 1264 | struct chsc_header response; |
1219 | char data[size]; | 1265 | char data[]; |
1220 | } __attribute__ ((packed)) *rr; | 1266 | } __attribute__ ((packed)) *rr; |
1221 | int rc; | 1267 | int rc; |
1222 | 1268 | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 67c87b6e63ec..321a3f765810 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -242,6 +242,8 @@ int chsc_pnso_brinfo(struct subchannel_id schid, | |||
242 | struct chsc_brinfo_resume_token resume_token, | 242 | struct chsc_brinfo_resume_token resume_token, |
243 | int cnc); | 243 | int cnc); |
244 | 244 | ||
245 | int __init chsc_get_cssid(int idx); | ||
246 | |||
245 | #ifdef CONFIG_SCM_BUS | 247 | #ifdef CONFIG_SCM_BUS |
246 | int scm_update_information(void); | 248 | int scm_update_information(void); |
247 | int scm_process_availability_information(void); | 249 | int scm_process_availability_information(void); |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 6b6386e9a500..220491d27ef4 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -1085,15 +1085,9 @@ static ssize_t cmb_show_avg_utilization(struct device *dev, | |||
1085 | data.function_pending_time + | 1085 | data.function_pending_time + |
1086 | data.device_disconnect_time; | 1086 | data.device_disconnect_time; |
1087 | 1087 | ||
1088 | /* shift to avoid long long division */ | ||
1089 | while (-1ul < (data.elapsed_time | utilization)) { | ||
1090 | utilization >>= 8; | ||
1091 | data.elapsed_time >>= 8; | ||
1092 | } | ||
1093 | |||
1094 | /* calculate value in 0.1 percent units */ | 1088 | /* calculate value in 0.1 percent units */ |
1095 | t = (unsigned long) data.elapsed_time / 1000; | 1089 | t = data.elapsed_time / 1000; |
1096 | u = (unsigned long) utilization / t; | 1090 | u = utilization / t; |
1097 | 1091 | ||
1098 | return sprintf(buf, "%02ld.%01ld%%\n", u/ 10, u - (u/ 10) * 10); | 1092 | return sprintf(buf, "%02ld.%01ld%%\n", u/ 10, u - (u/ 10) * 10); |
1099 | } | 1093 | } |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index bc099b61394d..e2aa944eb566 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -36,7 +36,8 @@ | |||
36 | int css_init_done = 0; | 36 | int css_init_done = 0; |
37 | int max_ssid; | 37 | int max_ssid; |
38 | 38 | ||
39 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; | 39 | #define MAX_CSS_IDX 0 |
40 | struct channel_subsystem *channel_subsystems[MAX_CSS_IDX + 1]; | ||
40 | static struct bus_type css_bus_type; | 41 | static struct bus_type css_bus_type; |
41 | 42 | ||
42 | int | 43 | int |
@@ -702,7 +703,8 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
702 | 703 | ||
703 | if (css_general_characteristics.mcss) { | 704 | if (css_general_characteristics.mcss) { |
704 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; | 705 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
705 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 706 | css->global_pgid.pgid_high.ext_cssid.cssid = |
707 | (css->cssid < 0) ? 0 : css->cssid; | ||
706 | } else { | 708 | } else { |
707 | css->global_pgid.pgid_high.cpu_addr = stap(); | 709 | css->global_pgid.pgid_high.cpu_addr = stap(); |
708 | } | 710 | } |
@@ -712,43 +714,44 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
712 | css->global_pgid.tod_high = tod_high; | 714 | css->global_pgid.tod_high = tod_high; |
713 | } | 715 | } |
714 | 716 | ||
715 | static void | 717 | static void channel_subsystem_release(struct device *dev) |
716 | channel_subsystem_release(struct device *dev) | ||
717 | { | 718 | { |
718 | struct channel_subsystem *css; | 719 | struct channel_subsystem *css = to_css(dev); |
719 | 720 | ||
720 | css = to_css(dev); | ||
721 | mutex_destroy(&css->mutex); | 721 | mutex_destroy(&css->mutex); |
722 | if (css->pseudo_subchannel) { | ||
723 | /* Implies that it has been generated but never registered. */ | ||
724 | css_subchannel_release(&css->pseudo_subchannel->dev); | ||
725 | css->pseudo_subchannel = NULL; | ||
726 | } | ||
727 | kfree(css); | 722 | kfree(css); |
728 | } | 723 | } |
729 | 724 | ||
730 | static ssize_t | 725 | static ssize_t real_cssid_show(struct device *dev, struct device_attribute *a, |
731 | css_cm_enable_show(struct device *dev, struct device_attribute *attr, | 726 | char *buf) |
732 | char *buf) | 727 | { |
728 | struct channel_subsystem *css = to_css(dev); | ||
729 | |||
730 | if (css->cssid < 0) | ||
731 | return -EINVAL; | ||
732 | |||
733 | return sprintf(buf, "%x\n", css->cssid); | ||
734 | } | ||
735 | static DEVICE_ATTR_RO(real_cssid); | ||
736 | |||
737 | static ssize_t cm_enable_show(struct device *dev, struct device_attribute *a, | ||
738 | char *buf) | ||
733 | { | 739 | { |
734 | struct channel_subsystem *css = to_css(dev); | 740 | struct channel_subsystem *css = to_css(dev); |
735 | int ret; | 741 | int ret; |
736 | 742 | ||
737 | if (!css) | ||
738 | return 0; | ||
739 | mutex_lock(&css->mutex); | 743 | mutex_lock(&css->mutex); |
740 | ret = sprintf(buf, "%x\n", css->cm_enabled); | 744 | ret = sprintf(buf, "%x\n", css->cm_enabled); |
741 | mutex_unlock(&css->mutex); | 745 | mutex_unlock(&css->mutex); |
742 | return ret; | 746 | return ret; |
743 | } | 747 | } |
744 | 748 | ||
745 | static ssize_t | 749 | static ssize_t cm_enable_store(struct device *dev, struct device_attribute *a, |
746 | css_cm_enable_store(struct device *dev, struct device_attribute *attr, | 750 | const char *buf, size_t count) |
747 | const char *buf, size_t count) | ||
748 | { | 751 | { |
749 | struct channel_subsystem *css = to_css(dev); | 752 | struct channel_subsystem *css = to_css(dev); |
750 | int ret; | ||
751 | unsigned long val; | 753 | unsigned long val; |
754 | int ret; | ||
752 | 755 | ||
753 | ret = kstrtoul(buf, 16, &val); | 756 | ret = kstrtoul(buf, 16, &val); |
754 | if (ret) | 757 | if (ret) |
@@ -767,51 +770,104 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr, | |||
767 | mutex_unlock(&css->mutex); | 770 | mutex_unlock(&css->mutex); |
768 | return ret < 0 ? ret : count; | 771 | return ret < 0 ? ret : count; |
769 | } | 772 | } |
773 | static DEVICE_ATTR_RW(cm_enable); | ||
774 | |||
775 | static umode_t cm_enable_mode(struct kobject *kobj, struct attribute *attr, | ||
776 | int index) | ||
777 | { | ||
778 | return css_chsc_characteristics.secm ? attr->mode : 0; | ||
779 | } | ||
780 | |||
781 | static struct attribute *cssdev_attrs[] = { | ||
782 | &dev_attr_real_cssid.attr, | ||
783 | NULL, | ||
784 | }; | ||
785 | |||
786 | static struct attribute_group cssdev_attr_group = { | ||
787 | .attrs = cssdev_attrs, | ||
788 | }; | ||
789 | |||
790 | static struct attribute *cssdev_cm_attrs[] = { | ||
791 | &dev_attr_cm_enable.attr, | ||
792 | NULL, | ||
793 | }; | ||
794 | |||
795 | static struct attribute_group cssdev_cm_attr_group = { | ||
796 | .attrs = cssdev_cm_attrs, | ||
797 | .is_visible = cm_enable_mode, | ||
798 | }; | ||
770 | 799 | ||
771 | static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); | 800 | static const struct attribute_group *cssdev_attr_groups[] = { |
801 | &cssdev_attr_group, | ||
802 | &cssdev_cm_attr_group, | ||
803 | NULL, | ||
804 | }; | ||
772 | 805 | ||
773 | static int __init setup_css(int nr) | 806 | static int __init setup_css(int nr) |
774 | { | 807 | { |
775 | u32 tod_high; | ||
776 | int ret; | ||
777 | struct channel_subsystem *css; | 808 | struct channel_subsystem *css; |
809 | int ret; | ||
778 | 810 | ||
779 | css = channel_subsystems[nr]; | 811 | css = kzalloc(sizeof(*css), GFP_KERNEL); |
780 | memset(css, 0, sizeof(struct channel_subsystem)); | 812 | if (!css) |
781 | css->pseudo_subchannel = | ||
782 | kzalloc(sizeof(*css->pseudo_subchannel), GFP_KERNEL); | ||
783 | if (!css->pseudo_subchannel) | ||
784 | return -ENOMEM; | 813 | return -ENOMEM; |
814 | |||
815 | channel_subsystems[nr] = css; | ||
816 | dev_set_name(&css->device, "css%x", nr); | ||
817 | css->device.groups = cssdev_attr_groups; | ||
818 | css->device.release = channel_subsystem_release; | ||
819 | |||
820 | mutex_init(&css->mutex); | ||
821 | css->cssid = chsc_get_cssid(nr); | ||
822 | css_generate_pgid(css, (u32) (get_tod_clock() >> 32)); | ||
823 | |||
824 | ret = device_register(&css->device); | ||
825 | if (ret) { | ||
826 | put_device(&css->device); | ||
827 | goto out_err; | ||
828 | } | ||
829 | |||
830 | css->pseudo_subchannel = kzalloc(sizeof(*css->pseudo_subchannel), | ||
831 | GFP_KERNEL); | ||
832 | if (!css->pseudo_subchannel) { | ||
833 | device_unregister(&css->device); | ||
834 | ret = -ENOMEM; | ||
835 | goto out_err; | ||
836 | } | ||
837 | |||
785 | css->pseudo_subchannel->dev.parent = &css->device; | 838 | css->pseudo_subchannel->dev.parent = &css->device; |
786 | css->pseudo_subchannel->dev.release = css_subchannel_release; | 839 | css->pseudo_subchannel->dev.release = css_subchannel_release; |
787 | dev_set_name(&css->pseudo_subchannel->dev, "defunct"); | ||
788 | mutex_init(&css->pseudo_subchannel->reg_mutex); | 840 | mutex_init(&css->pseudo_subchannel->reg_mutex); |
789 | ret = css_sch_create_locks(css->pseudo_subchannel); | 841 | ret = css_sch_create_locks(css->pseudo_subchannel); |
790 | if (ret) { | 842 | if (ret) { |
791 | kfree(css->pseudo_subchannel); | 843 | kfree(css->pseudo_subchannel); |
792 | return ret; | 844 | device_unregister(&css->device); |
845 | goto out_err; | ||
793 | } | 846 | } |
794 | mutex_init(&css->mutex); | 847 | |
795 | css->valid = 1; | 848 | dev_set_name(&css->pseudo_subchannel->dev, "defunct"); |
796 | css->cssid = nr; | 849 | ret = device_register(&css->pseudo_subchannel->dev); |
797 | dev_set_name(&css->device, "css%x", nr); | 850 | if (ret) { |
798 | css->device.release = channel_subsystem_release; | 851 | put_device(&css->pseudo_subchannel->dev); |
799 | tod_high = (u32) (get_tod_clock() >> 32); | 852 | device_unregister(&css->device); |
800 | css_generate_pgid(css, tod_high); | 853 | goto out_err; |
801 | return 0; | 854 | } |
855 | |||
856 | return ret; | ||
857 | out_err: | ||
858 | channel_subsystems[nr] = NULL; | ||
859 | return ret; | ||
802 | } | 860 | } |
803 | 861 | ||
804 | static int css_reboot_event(struct notifier_block *this, | 862 | static int css_reboot_event(struct notifier_block *this, |
805 | unsigned long event, | 863 | unsigned long event, |
806 | void *ptr) | 864 | void *ptr) |
807 | { | 865 | { |
808 | int ret, i; | 866 | struct channel_subsystem *css; |
867 | int ret; | ||
809 | 868 | ||
810 | ret = NOTIFY_DONE; | 869 | ret = NOTIFY_DONE; |
811 | for (i = 0; i <= __MAX_CSSID; i++) { | 870 | for_each_css(css) { |
812 | struct channel_subsystem *css; | ||
813 | |||
814 | css = channel_subsystems[i]; | ||
815 | mutex_lock(&css->mutex); | 871 | mutex_lock(&css->mutex); |
816 | if (css->cm_enabled) | 872 | if (css->cm_enabled) |
817 | if (chsc_secm(css, 0)) | 873 | if (chsc_secm(css, 0)) |
@@ -835,16 +891,14 @@ static struct notifier_block css_reboot_notifier = { | |||
835 | static int css_power_event(struct notifier_block *this, unsigned long event, | 891 | static int css_power_event(struct notifier_block *this, unsigned long event, |
836 | void *ptr) | 892 | void *ptr) |
837 | { | 893 | { |
838 | int ret, i; | 894 | struct channel_subsystem *css; |
895 | int ret; | ||
839 | 896 | ||
840 | switch (event) { | 897 | switch (event) { |
841 | case PM_HIBERNATION_PREPARE: | 898 | case PM_HIBERNATION_PREPARE: |
842 | case PM_SUSPEND_PREPARE: | 899 | case PM_SUSPEND_PREPARE: |
843 | ret = NOTIFY_DONE; | 900 | ret = NOTIFY_DONE; |
844 | for (i = 0; i <= __MAX_CSSID; i++) { | 901 | for_each_css(css) { |
845 | struct channel_subsystem *css; | ||
846 | |||
847 | css = channel_subsystems[i]; | ||
848 | mutex_lock(&css->mutex); | 902 | mutex_lock(&css->mutex); |
849 | if (!css->cm_enabled) { | 903 | if (!css->cm_enabled) { |
850 | mutex_unlock(&css->mutex); | 904 | mutex_unlock(&css->mutex); |
@@ -858,10 +912,7 @@ static int css_power_event(struct notifier_block *this, unsigned long event, | |||
858 | case PM_POST_HIBERNATION: | 912 | case PM_POST_HIBERNATION: |
859 | case PM_POST_SUSPEND: | 913 | case PM_POST_SUSPEND: |
860 | ret = NOTIFY_DONE; | 914 | ret = NOTIFY_DONE; |
861 | for (i = 0; i <= __MAX_CSSID; i++) { | 915 | for_each_css(css) { |
862 | struct channel_subsystem *css; | ||
863 | |||
864 | css = channel_subsystems[i]; | ||
865 | mutex_lock(&css->mutex); | 916 | mutex_lock(&css->mutex); |
866 | if (!css->cm_enabled) { | 917 | if (!css->cm_enabled) { |
867 | mutex_unlock(&css->mutex); | 918 | mutex_unlock(&css->mutex); |
@@ -916,36 +967,10 @@ static int __init css_bus_init(void) | |||
916 | goto out; | 967 | goto out; |
917 | 968 | ||
918 | /* Setup css structure. */ | 969 | /* Setup css structure. */ |
919 | for (i = 0; i <= __MAX_CSSID; i++) { | 970 | for (i = 0; i <= MAX_CSS_IDX; i++) { |
920 | struct channel_subsystem *css; | ||
921 | |||
922 | css = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); | ||
923 | if (!css) { | ||
924 | ret = -ENOMEM; | ||
925 | goto out_unregister; | ||
926 | } | ||
927 | channel_subsystems[i] = css; | ||
928 | ret = setup_css(i); | 971 | ret = setup_css(i); |
929 | if (ret) { | 972 | if (ret) |
930 | kfree(channel_subsystems[i]); | ||
931 | goto out_unregister; | ||
932 | } | ||
933 | ret = device_register(&css->device); | ||
934 | if (ret) { | ||
935 | put_device(&css->device); | ||
936 | goto out_unregister; | 973 | goto out_unregister; |
937 | } | ||
938 | if (css_chsc_characteristics.secm) { | ||
939 | ret = device_create_file(&css->device, | ||
940 | &dev_attr_cm_enable); | ||
941 | if (ret) | ||
942 | goto out_device; | ||
943 | } | ||
944 | ret = device_register(&css->pseudo_subchannel->dev); | ||
945 | if (ret) { | ||
946 | put_device(&css->pseudo_subchannel->dev); | ||
947 | goto out_file; | ||
948 | } | ||
949 | } | 974 | } |
950 | ret = register_reboot_notifier(&css_reboot_notifier); | 975 | ret = register_reboot_notifier(&css_reboot_notifier); |
951 | if (ret) | 976 | if (ret) |
@@ -961,23 +986,10 @@ static int __init css_bus_init(void) | |||
961 | isc_register(IO_SCH_ISC); | 986 | isc_register(IO_SCH_ISC); |
962 | 987 | ||
963 | return 0; | 988 | return 0; |
964 | out_file: | ||
965 | if (css_chsc_characteristics.secm) | ||
966 | device_remove_file(&channel_subsystems[i]->device, | ||
967 | &dev_attr_cm_enable); | ||
968 | out_device: | ||
969 | device_unregister(&channel_subsystems[i]->device); | ||
970 | out_unregister: | 989 | out_unregister: |
971 | while (i > 0) { | 990 | while (i-- > 0) { |
972 | struct channel_subsystem *css; | 991 | struct channel_subsystem *css = channel_subsystems[i]; |
973 | |||
974 | i--; | ||
975 | css = channel_subsystems[i]; | ||
976 | device_unregister(&css->pseudo_subchannel->dev); | 992 | device_unregister(&css->pseudo_subchannel->dev); |
977 | css->pseudo_subchannel = NULL; | ||
978 | if (css_chsc_characteristics.secm) | ||
979 | device_remove_file(&css->device, | ||
980 | &dev_attr_cm_enable); | ||
981 | device_unregister(&css->device); | 993 | device_unregister(&css->device); |
982 | } | 994 | } |
983 | bus_unregister(&css_bus_type); | 995 | bus_unregister(&css_bus_type); |
@@ -993,14 +1005,9 @@ out: | |||
993 | static void __init css_bus_cleanup(void) | 1005 | static void __init css_bus_cleanup(void) |
994 | { | 1006 | { |
995 | struct channel_subsystem *css; | 1007 | struct channel_subsystem *css; |
996 | int i; | ||
997 | 1008 | ||
998 | for (i = 0; i <= __MAX_CSSID; i++) { | 1009 | for_each_css(css) { |
999 | css = channel_subsystems[i]; | ||
1000 | device_unregister(&css->pseudo_subchannel->dev); | 1010 | device_unregister(&css->pseudo_subchannel->dev); |
1001 | css->pseudo_subchannel = NULL; | ||
1002 | if (css_chsc_characteristics.secm) | ||
1003 | device_remove_file(&css->device, &dev_attr_cm_enable); | ||
1004 | device_unregister(&css->device); | 1011 | device_unregister(&css->device); |
1005 | } | 1012 | } |
1006 | bus_unregister(&css_bus_type); | 1013 | bus_unregister(&css_bus_type); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 2c9107e20251..c9f3fb39ebeb 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -113,8 +113,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); | |||
113 | void css_update_ssd_info(struct subchannel *sch); | 113 | void css_update_ssd_info(struct subchannel *sch); |
114 | 114 | ||
115 | struct channel_subsystem { | 115 | struct channel_subsystem { |
116 | u8 cssid; | 116 | int cssid; |
117 | int valid; | ||
118 | struct channel_path *chps[__MAX_CHPID + 1]; | 117 | struct channel_path *chps[__MAX_CHPID + 1]; |
119 | struct device device; | 118 | struct device device; |
120 | struct pgid global_pgid; | 119 | struct pgid global_pgid; |
@@ -130,6 +129,16 @@ struct channel_subsystem { | |||
130 | 129 | ||
131 | extern struct channel_subsystem *channel_subsystems[]; | 130 | extern struct channel_subsystem *channel_subsystems[]; |
132 | 131 | ||
132 | /* Dummy helper which needs to change once we support more than one css. */ | ||
133 | static inline struct channel_subsystem *css_by_id(u8 cssid) | ||
134 | { | ||
135 | return channel_subsystems[0]; | ||
136 | } | ||
137 | |||
138 | /* Dummy iterator which needs to change once we support more than one css. */ | ||
139 | #define for_each_css(css) \ | ||
140 | for ((css) = channel_subsystems[0]; (css); (css) = NULL) | ||
141 | |||
133 | /* Helper functions to build lists for the slow path. */ | 142 | /* Helper functions to build lists for the slow path. */ |
134 | void css_schedule_eval(struct subchannel_id schid); | 143 | void css_schedule_eval(struct subchannel_id schid); |
135 | void css_schedule_eval_all(void); | 144 | void css_schedule_eval_all(void); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 71bf9bded485..a4ad39ba3873 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -457,7 +457,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
457 | { | 457 | { |
458 | int new; | 458 | int new; |
459 | 459 | ||
460 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %02x", count); | 460 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim:%1d %02x", q->nr, count); |
461 | 461 | ||
462 | /* for QEBSM the ACK was already set by EQBS */ | 462 | /* for QEBSM the ACK was already set by EQBS */ |
463 | if (is_qebsm(q)) { | 463 | if (is_qebsm(q)) { |
@@ -544,7 +544,8 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
544 | case SLSB_P_INPUT_ACK: | 544 | case SLSB_P_INPUT_ACK: |
545 | if (q->irq_ptr->perf_stat_enabled) | 545 | if (q->irq_ptr->perf_stat_enabled) |
546 | q->q_stats.nr_sbal_nop++; | 546 | q->q_stats.nr_sbal_nop++; |
547 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop"); | 547 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop:%1d %#02x", |
548 | q->nr, q->first_to_check); | ||
548 | break; | 549 | break; |
549 | default: | 550 | default: |
550 | WARN_ON_ONCE(1); | 551 | WARN_ON_ONCE(1); |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 5d06253c2a7a..8ad98a902a91 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -147,11 +147,11 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq) | |||
147 | struct qdio_q *q; | 147 | struct qdio_q *q; |
148 | int i; | 148 | int i; |
149 | 149 | ||
150 | for_each_input_queue(irq, q, i) { | 150 | if (!references_shared_dsci(irq) && |
151 | if (!references_shared_dsci(irq) && | 151 | has_multiple_inq_on_dsci(irq)) |
152 | has_multiple_inq_on_dsci(irq)) | 152 | xchg(irq->dsci, 0); |
153 | xchg(q->irq_ptr->dsci, 0); | ||
154 | 153 | ||
154 | for_each_input_queue(irq, q, i) { | ||
155 | if (q->u.in.queue_start_poll) { | 155 | if (q->u.in.queue_start_poll) { |
156 | /* skip if polling is enabled or already in work */ | 156 | /* skip if polling is enabled or already in work */ |
157 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | 157 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, |
@@ -161,11 +161,11 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | /* avoid dsci clear here, done after processing */ | 163 | /* avoid dsci clear here, done after processing */ |
164 | q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr, | 164 | q->u.in.queue_start_poll(irq->cdev, q->nr, |
165 | q->irq_ptr->int_parm); | 165 | irq->int_parm); |
166 | } else { | 166 | } else { |
167 | if (!shared_ind(q->irq_ptr)) | 167 | if (!shared_ind(irq)) |
168 | xchg(q->irq_ptr->dsci, 0); | 168 | xchg(irq->dsci, 0); |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * Call inbound processing but not directly | 171 | * Call inbound processing but not directly |
@@ -178,8 +178,7 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq) | |||
178 | 178 | ||
179 | /** | 179 | /** |
180 | * tiqdio_thinint_handler - thin interrupt handler for qdio | 180 | * tiqdio_thinint_handler - thin interrupt handler for qdio |
181 | * @alsi: pointer to adapter local summary indicator | 181 | * @airq: pointer to adapter interrupt descriptor |
182 | * @data: NULL | ||
183 | */ | 182 | */ |
184 | static void tiqdio_thinint_handler(struct airq_struct *airq) | 183 | static void tiqdio_thinint_handler(struct airq_struct *airq) |
185 | { | 184 | { |
diff --git a/drivers/s390/crypto/ap_asm.h b/drivers/s390/crypto/ap_asm.h index 7a630047c372..287b4ad0999e 100644 --- a/drivers/s390/crypto/ap_asm.h +++ b/drivers/s390/crypto/ap_asm.h | |||
@@ -129,7 +129,6 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid, | |||
129 | unsigned long long psmid, | 129 | unsigned long long psmid, |
130 | void *msg, size_t length) | 130 | void *msg, size_t length) |
131 | { | 131 | { |
132 | struct msgblock { char _[length]; }; | ||
133 | register unsigned long reg0 asm ("0") = qid | 0x40000000UL; | 132 | register unsigned long reg0 asm ("0") = qid | 0x40000000UL; |
134 | register struct ap_queue_status reg1 asm ("1"); | 133 | register struct ap_queue_status reg1 asm ("1"); |
135 | register unsigned long reg2 asm ("2") = (unsigned long) msg; | 134 | register unsigned long reg2 asm ("2") = (unsigned long) msg; |
@@ -141,8 +140,8 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid, | |||
141 | "0: .long 0xb2ad0042\n" /* NQAP */ | 140 | "0: .long 0xb2ad0042\n" /* NQAP */ |
142 | " brc 2,0b" | 141 | " brc 2,0b" |
143 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) | 142 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) |
144 | : "d" (reg4), "d" (reg5), "m" (*(struct msgblock *) msg) | 143 | : "d" (reg4), "d" (reg5) |
145 | : "cc"); | 144 | : "cc", "memory"); |
146 | return reg1; | 145 | return reg1; |
147 | } | 146 | } |
148 | 147 | ||
@@ -168,7 +167,6 @@ static inline struct ap_queue_status ap_dqap(ap_qid_t qid, | |||
168 | unsigned long long *psmid, | 167 | unsigned long long *psmid, |
169 | void *msg, size_t length) | 168 | void *msg, size_t length) |
170 | { | 169 | { |
171 | struct msgblock { char _[length]; }; | ||
172 | register unsigned long reg0 asm("0") = qid | 0x80000000UL; | 170 | register unsigned long reg0 asm("0") = qid | 0x80000000UL; |
173 | register struct ap_queue_status reg1 asm ("1"); | 171 | register struct ap_queue_status reg1 asm ("1"); |
174 | register unsigned long reg2 asm("2") = 0UL; | 172 | register unsigned long reg2 asm("2") = 0UL; |
@@ -182,8 +180,8 @@ static inline struct ap_queue_status ap_dqap(ap_qid_t qid, | |||
182 | "0: .long 0xb2ae0064\n" /* DQAP */ | 180 | "0: .long 0xb2ae0064\n" /* DQAP */ |
183 | " brc 6,0b\n" | 181 | " brc 6,0b\n" |
184 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), | 182 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), |
185 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), | 183 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7) |
186 | "=m" (*(struct msgblock *) msg) : : "cc"); | 184 | : : "cc", "memory"); |
187 | *psmid = (((unsigned long long) reg6) << 32) + reg7; | 185 | *psmid = (((unsigned long long) reg6) << 32) + reg7; |
188 | return reg1; | 186 | return reg1; |
189 | } | 187 | } |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 5fa699192864..56db76c05775 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
28 | 28 | ||
29 | #include <linux/kernel_stat.h> | 29 | #include <linux/kernel_stat.h> |
30 | #include <linux/module.h> | 30 | #include <linux/moduleparam.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
@@ -54,16 +54,7 @@ | |||
54 | #include "ap_debug.h" | 54 | #include "ap_debug.h" |
55 | 55 | ||
56 | /* | 56 | /* |
57 | * Module description. | 57 | * Module parameters; note though this file itself isn't modular. |
58 | */ | ||
59 | MODULE_AUTHOR("IBM Corporation"); | ||
60 | MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ | ||
61 | "Copyright IBM Corp. 2006, 2012"); | ||
62 | MODULE_LICENSE("GPL"); | ||
63 | MODULE_ALIAS_CRYPTO("z90crypt"); | ||
64 | |||
65 | /* | ||
66 | * Module parameter | ||
67 | */ | 58 | */ |
68 | int ap_domain_index = -1; /* Adjunct Processor Domain Index */ | 59 | int ap_domain_index = -1; /* Adjunct Processor Domain Index */ |
69 | static DEFINE_SPINLOCK(ap_domain_lock); | 60 | static DEFINE_SPINLOCK(ap_domain_lock); |
@@ -86,7 +77,6 @@ static bool initialised; | |||
86 | /* | 77 | /* |
87 | * AP bus related debug feature things. | 78 | * AP bus related debug feature things. |
88 | */ | 79 | */ |
89 | static struct dentry *ap_dbf_root; | ||
90 | debug_info_t *ap_dbf_info; | 80 | debug_info_t *ap_dbf_info; |
91 | 81 | ||
92 | /* | 82 | /* |
@@ -1148,7 +1138,6 @@ static struct reset_call ap_reset_call = { | |||
1148 | 1138 | ||
1149 | int __init ap_debug_init(void) | 1139 | int __init ap_debug_init(void) |
1150 | { | 1140 | { |
1151 | ap_dbf_root = debugfs_create_dir("ap", NULL); | ||
1152 | ap_dbf_info = debug_register("ap", 1, 1, | 1141 | ap_dbf_info = debug_register("ap", 1, 1, |
1153 | DBF_MAX_SPRINTF_ARGS * sizeof(long)); | 1142 | DBF_MAX_SPRINTF_ARGS * sizeof(long)); |
1154 | debug_register_view(ap_dbf_info, &debug_sprintf_view); | 1143 | debug_register_view(ap_dbf_info, &debug_sprintf_view); |
@@ -1159,7 +1148,6 @@ int __init ap_debug_init(void) | |||
1159 | 1148 | ||
1160 | void ap_debug_exit(void) | 1149 | void ap_debug_exit(void) |
1161 | { | 1150 | { |
1162 | debugfs_remove(ap_dbf_root); | ||
1163 | debug_unregister(ap_dbf_info); | 1151 | debug_unregister(ap_dbf_info); |
1164 | } | 1152 | } |
1165 | 1153 | ||
@@ -1270,43 +1258,4 @@ out_free: | |||
1270 | kfree(ap_configuration); | 1258 | kfree(ap_configuration); |
1271 | return rc; | 1259 | return rc; |
1272 | } | 1260 | } |
1273 | 1261 | device_initcall(ap_module_init); | |
1274 | /** | ||
1275 | * ap_modules_exit(): The module termination code | ||
1276 | * | ||
1277 | * Terminates the module. | ||
1278 | */ | ||
1279 | void ap_module_exit(void) | ||
1280 | { | ||
1281 | int i; | ||
1282 | |||
1283 | initialised = false; | ||
1284 | ap_reset_domain(); | ||
1285 | ap_poll_thread_stop(); | ||
1286 | del_timer_sync(&ap_config_timer); | ||
1287 | hrtimer_cancel(&ap_poll_timer); | ||
1288 | tasklet_kill(&ap_tasklet); | ||
1289 | |||
1290 | /* first remove queue devices */ | ||
1291 | bus_for_each_dev(&ap_bus_type, NULL, NULL, | ||
1292 | __ap_queue_devices_unregister); | ||
1293 | /* now remove the card devices */ | ||
1294 | bus_for_each_dev(&ap_bus_type, NULL, NULL, | ||
1295 | __ap_card_devices_unregister); | ||
1296 | |||
1297 | /* remove bus attributes */ | ||
1298 | for (i = 0; ap_bus_attrs[i]; i++) | ||
1299 | bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); | ||
1300 | unregister_pm_notifier(&ap_power_notifier); | ||
1301 | root_device_unregister(ap_root_device); | ||
1302 | bus_unregister(&ap_bus_type); | ||
1303 | kfree(ap_configuration); | ||
1304 | unregister_reset_call(&ap_reset_call); | ||
1305 | if (ap_using_interrupts()) | ||
1306 | unregister_adapter_interrupt(&ap_airq); | ||
1307 | |||
1308 | ap_debug_exit(); | ||
1309 | } | ||
1310 | |||
1311 | module_init(ap_module_init); | ||
1312 | module_exit(ap_module_exit); | ||
diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c index 0110d44172a3..1cd9128593e4 100644 --- a/drivers/s390/crypto/ap_card.c +++ b/drivers/s390/crypto/ap_card.c | |||
@@ -137,7 +137,7 @@ static const struct attribute_group *ap_card_dev_attr_groups[] = { | |||
137 | NULL | 137 | NULL |
138 | }; | 138 | }; |
139 | 139 | ||
140 | struct device_type ap_card_type = { | 140 | static struct device_type ap_card_type = { |
141 | .name = "ap_card", | 141 | .name = "ap_card", |
142 | .groups = ap_card_dev_attr_groups, | 142 | .groups = ap_card_dev_attr_groups, |
143 | }; | 143 | }; |
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index b58a917dc510..7be67fa9f224 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c | |||
@@ -564,7 +564,7 @@ static const struct attribute_group *ap_queue_dev_attr_groups[] = { | |||
564 | NULL | 564 | NULL |
565 | }; | 565 | }; |
566 | 566 | ||
567 | struct device_type ap_queue_type = { | 567 | static struct device_type ap_queue_type = { |
568 | .name = "ap_queue", | 568 | .name = "ap_queue", |
569 | .groups = ap_queue_dev_attr_groups, | 569 | .groups = ap_queue_dev_attr_groups, |
570 | }; | 570 | }; |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 51eece9af577..144a17941e6f 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -81,7 +81,6 @@ EXPORT_SYMBOL(zcrypt_rescan_req); | |||
81 | static LIST_HEAD(zcrypt_ops_list); | 81 | static LIST_HEAD(zcrypt_ops_list); |
82 | 82 | ||
83 | /* Zcrypt related debug feature stuff. */ | 83 | /* Zcrypt related debug feature stuff. */ |
84 | static struct dentry *zcrypt_dbf_root; | ||
85 | debug_info_t *zcrypt_dbf_info; | 84 | debug_info_t *zcrypt_dbf_info; |
86 | 85 | ||
87 | /** | 86 | /** |
@@ -201,7 +200,7 @@ static inline bool zcrypt_card_compare(struct zcrypt_card *zc, | |||
201 | unsigned weight, unsigned pref_weight) | 200 | unsigned weight, unsigned pref_weight) |
202 | { | 201 | { |
203 | if (!pref_zc) | 202 | if (!pref_zc) |
204 | return 0; | 203 | return false; |
205 | weight += atomic_read(&zc->load); | 204 | weight += atomic_read(&zc->load); |
206 | pref_weight += atomic_read(&pref_zc->load); | 205 | pref_weight += atomic_read(&pref_zc->load); |
207 | if (weight == pref_weight) | 206 | if (weight == pref_weight) |
@@ -215,7 +214,7 @@ static inline bool zcrypt_queue_compare(struct zcrypt_queue *zq, | |||
215 | unsigned weight, unsigned pref_weight) | 214 | unsigned weight, unsigned pref_weight) |
216 | { | 215 | { |
217 | if (!pref_zq) | 216 | if (!pref_zq) |
218 | return 0; | 217 | return false; |
219 | weight += atomic_read(&zq->load); | 218 | weight += atomic_read(&zq->load); |
220 | pref_weight += atomic_read(&pref_zq->load); | 219 | pref_weight += atomic_read(&pref_zq->load); |
221 | if (weight == pref_weight) | 220 | if (weight == pref_weight) |
@@ -668,6 +667,7 @@ static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES]) | |||
668 | 667 | ||
669 | memset(qdepth, 0, sizeof(char) * AP_DEVICES); | 668 | memset(qdepth, 0, sizeof(char) * AP_DEVICES); |
670 | spin_lock(&zcrypt_list_lock); | 669 | spin_lock(&zcrypt_list_lock); |
670 | local_bh_disable(); | ||
671 | for_each_zcrypt_card(zc) { | 671 | for_each_zcrypt_card(zc) { |
672 | for_each_zcrypt_queue(zq, zc) { | 672 | for_each_zcrypt_queue(zq, zc) { |
673 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) | 673 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) |
@@ -679,6 +679,7 @@ static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES]) | |||
679 | spin_unlock(&zq->queue->lock); | 679 | spin_unlock(&zq->queue->lock); |
680 | } | 680 | } |
681 | } | 681 | } |
682 | local_bh_enable(); | ||
682 | spin_unlock(&zcrypt_list_lock); | 683 | spin_unlock(&zcrypt_list_lock); |
683 | } | 684 | } |
684 | 685 | ||
@@ -689,6 +690,7 @@ static void zcrypt_perdev_reqcnt(int reqcnt[AP_DEVICES]) | |||
689 | 690 | ||
690 | memset(reqcnt, 0, sizeof(int) * AP_DEVICES); | 691 | memset(reqcnt, 0, sizeof(int) * AP_DEVICES); |
691 | spin_lock(&zcrypt_list_lock); | 692 | spin_lock(&zcrypt_list_lock); |
693 | local_bh_disable(); | ||
692 | for_each_zcrypt_card(zc) { | 694 | for_each_zcrypt_card(zc) { |
693 | for_each_zcrypt_queue(zq, zc) { | 695 | for_each_zcrypt_queue(zq, zc) { |
694 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) | 696 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) |
@@ -699,6 +701,7 @@ static void zcrypt_perdev_reqcnt(int reqcnt[AP_DEVICES]) | |||
699 | spin_unlock(&zq->queue->lock); | 701 | spin_unlock(&zq->queue->lock); |
700 | } | 702 | } |
701 | } | 703 | } |
704 | local_bh_enable(); | ||
702 | spin_unlock(&zcrypt_list_lock); | 705 | spin_unlock(&zcrypt_list_lock); |
703 | } | 706 | } |
704 | 707 | ||
@@ -710,6 +713,7 @@ static int zcrypt_pendingq_count(void) | |||
710 | 713 | ||
711 | pendingq_count = 0; | 714 | pendingq_count = 0; |
712 | spin_lock(&zcrypt_list_lock); | 715 | spin_lock(&zcrypt_list_lock); |
716 | local_bh_disable(); | ||
713 | for_each_zcrypt_card(zc) { | 717 | for_each_zcrypt_card(zc) { |
714 | for_each_zcrypt_queue(zq, zc) { | 718 | for_each_zcrypt_queue(zq, zc) { |
715 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) | 719 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) |
@@ -719,6 +723,7 @@ static int zcrypt_pendingq_count(void) | |||
719 | spin_unlock(&zq->queue->lock); | 723 | spin_unlock(&zq->queue->lock); |
720 | } | 724 | } |
721 | } | 725 | } |
726 | local_bh_enable(); | ||
722 | spin_unlock(&zcrypt_list_lock); | 727 | spin_unlock(&zcrypt_list_lock); |
723 | return pendingq_count; | 728 | return pendingq_count; |
724 | } | 729 | } |
@@ -731,6 +736,7 @@ static int zcrypt_requestq_count(void) | |||
731 | 736 | ||
732 | requestq_count = 0; | 737 | requestq_count = 0; |
733 | spin_lock(&zcrypt_list_lock); | 738 | spin_lock(&zcrypt_list_lock); |
739 | local_bh_disable(); | ||
734 | for_each_zcrypt_card(zc) { | 740 | for_each_zcrypt_card(zc) { |
735 | for_each_zcrypt_queue(zq, zc) { | 741 | for_each_zcrypt_queue(zq, zc) { |
736 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) | 742 | if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) |
@@ -740,6 +746,7 @@ static int zcrypt_requestq_count(void) | |||
740 | spin_unlock(&zq->queue->lock); | 746 | spin_unlock(&zq->queue->lock); |
741 | } | 747 | } |
742 | } | 748 | } |
749 | local_bh_enable(); | ||
743 | spin_unlock(&zcrypt_list_lock); | 750 | spin_unlock(&zcrypt_list_lock); |
744 | return requestq_count; | 751 | return requestq_count; |
745 | } | 752 | } |
@@ -1419,7 +1426,6 @@ void zcrypt_rng_device_remove(void) | |||
1419 | 1426 | ||
1420 | int __init zcrypt_debug_init(void) | 1427 | int __init zcrypt_debug_init(void) |
1421 | { | 1428 | { |
1422 | zcrypt_dbf_root = debugfs_create_dir("zcrypt", NULL); | ||
1423 | zcrypt_dbf_info = debug_register("zcrypt", 1, 1, | 1429 | zcrypt_dbf_info = debug_register("zcrypt", 1, 1, |
1424 | DBF_MAX_SPRINTF_ARGS * sizeof(long)); | 1430 | DBF_MAX_SPRINTF_ARGS * sizeof(long)); |
1425 | debug_register_view(zcrypt_dbf_info, &debug_sprintf_view); | 1431 | debug_register_view(zcrypt_dbf_info, &debug_sprintf_view); |
@@ -1430,7 +1436,6 @@ int __init zcrypt_debug_init(void) | |||
1430 | 1436 | ||
1431 | void zcrypt_debug_exit(void) | 1437 | void zcrypt_debug_exit(void) |
1432 | { | 1438 | { |
1433 | debugfs_remove(zcrypt_dbf_root); | ||
1434 | debug_unregister(zcrypt_dbf_info); | 1439 | debug_unregister(zcrypt_dbf_info); |
1435 | } | 1440 | } |
1436 | 1441 | ||
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 070c4da95f48..648373cde4a1 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c | |||
@@ -661,7 +661,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
661 | ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw); | 661 | ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw); |
662 | if (ret) | 662 | if (ret) |
663 | /* no error, just fall back to legacy interrupts */ | 663 | /* no error, just fall back to legacy interrupts */ |
664 | vcdev->is_thinint = 0; | 664 | vcdev->is_thinint = false; |
665 | } | 665 | } |
666 | if (!vcdev->is_thinint) { | 666 | if (!vcdev->is_thinint) { |
667 | /* Register queue indicators with host. */ | 667 | /* Register queue indicators with host. */ |