Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] s390: multiple subchannel sets support

Add support for multiple subchannel sets. Works with arbitrary devices in
subchannel set 1 and is transparent to device drivers. Although currently
only two subchannel sets are available, this will work with the architectured
maximum number of subchannel sets as well.

Signed-off-by: Cornelia Huck <cohuck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Cornelia Huck and committed by
Linus Torvalds
fb6958a5 678a395b

+354 -165
+50 -36
drivers/s390/cio/blacklist.c
··· 1 1 /* 2 2 * drivers/s390/cio/blacklist.c 3 3 * S/390 common I/O routines -- blacklisting of specific devices 4 - * $Revision: 1.35 $ 4 + * $Revision: 1.39 $ 5 5 * 6 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 7 7 * IBM Corporation ··· 35 35 * These can be single devices or ranges of devices 36 36 */ 37 37 38 - /* 65536 bits to indicate if a devno is blacklisted or not */ 38 + /* 65536 bits for each set to indicate if a devno is blacklisted or not */ 39 39 #define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ 40 40 (8*sizeof(long))) 41 - static unsigned long bl_dev[__BL_DEV_WORDS]; 41 + static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS]; 42 42 typedef enum {add, free} range_action; 43 43 44 44 /* ··· 46 46 * (Un-)blacklist the devices from-to 47 47 */ 48 48 static inline void 49 - blacklist_range (range_action action, unsigned int from, unsigned int to) 49 + blacklist_range (range_action action, unsigned int from, unsigned int to, 50 + unsigned int ssid) 50 51 { 51 52 if (!to) 52 53 to = from; 53 54 54 - if (from > to || to > __MAX_SUBCHANNEL) { 55 + if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) { 55 56 printk (KERN_WARNING "Invalid blacklist range " 56 - "0x%04x to 0x%04x, skipping\n", from, to); 57 + "0.%x.%04x to 0.%x.%04x, skipping\n", 58 + ssid, from, ssid, to); 57 59 return; 58 60 } 59 61 for (; from <= to; from++) { 60 62 if (action == add) 61 - set_bit (from, bl_dev); 63 + set_bit (from, bl_dev[ssid]); 62 64 else 63 - clear_bit (from, bl_dev); 65 + clear_bit (from, bl_dev[ssid]); 64 66 } 65 67 } 66 68 ··· 72 70 * Shamelessly grabbed from dasd_devmap.c. 73 71 */ 74 72 static inline int 75 - blacklist_busid(char **str, int *id0, int *id1, int *devno) 73 + blacklist_busid(char **str, int *id0, int *ssid, int *devno) 76 74 { 77 75 int val, old_style; 78 76 char *sav; ··· 89 87 goto confused; 90 88 val = simple_strtoul(*str, str, 16); 91 89 if (old_style || (*str)[0] != '.') { 92 - *id0 = *id1 = 0; 90 + *id0 = *ssid = 0; 93 91 if (val < 0 || val > 0xffff) 94 92 goto confused; 95 93 *devno = val; ··· 108 106 val = simple_strtoul(*str, str, 16); 109 107 if (val < 0 || val > 0xff || (*str)++[0] != '.') 110 108 goto confused; 111 - *id1 = val; 109 + *ssid = val; 112 110 if (!isxdigit((*str)[0])) /* We require at least one hex digit */ 113 111 goto confused; 114 112 val = simple_strtoul(*str, str, 16); ··· 128 126 static inline int 129 127 blacklist_parse_parameters (char *str, range_action action) 130 128 { 131 - unsigned int from, to, from_id0, to_id0, from_id1, to_id1; 129 + unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid; 132 130 133 131 while (*str != 0 && *str != '\n') { 134 132 range_action ra = action; ··· 145 143 */ 146 144 if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 || 147 145 strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) { 148 - from = 0; 149 - to = __MAX_SUBCHANNEL; 146 + int j; 147 + 150 148 str += 3; 149 + for (j=0; j <= __MAX_SSID; j++) 150 + blacklist_range(ra, 0, __MAX_SUBCHANNEL, j); 151 151 } else { 152 152 int rc; 153 153 154 154 rc = blacklist_busid(&str, &from_id0, 155 - &from_id1, &from); 155 + &from_ssid, &from); 156 156 if (rc) 157 157 continue; 158 158 to = from; 159 159 to_id0 = from_id0; 160 - to_id1 = from_id1; 160 + to_ssid = from_ssid; 161 161 if (*str == '-') { 162 162 str++; 163 163 rc = blacklist_busid(&str, &to_id0, 164 - &to_id1, &to); 164 + &to_ssid, &to); 165 165 if (rc) 166 166 continue; 167 167 } ··· 173 169 strsep(&str, ",\n")); 174 170 continue; 175 171 } 176 - if ((from_id0 != to_id0) || (from_id1 != to_id1)) { 172 + if ((from_id0 != to_id0) || 173 + (from_ssid != to_ssid)) { 177 174 printk(KERN_WARNING "invalid cio_ignore range " 178 175 "%x.%x.%04x-%x.%x.%04x\n", 179 - from_id0, from_id1, from, 180 - to_id0, to_id1, to); 176 + from_id0, from_ssid, from, 177 + to_id0, to_ssid, to); 181 178 continue; 182 179 } 180 + pr_debug("blacklist_setup: adding range " 181 + "from %x.%x.%04x to %x.%x.%04x\n", 182 + from_id0, from_ssid, from, to_id0, to_ssid, to); 183 + blacklist_range (ra, from, to, to_ssid); 183 184 } 184 - /* FIXME: ignoring id0 and id1 here. */ 185 - pr_debug("blacklist_setup: adding range " 186 - "from 0.0.%04x to 0.0.%04x\n", from, to); 187 - blacklist_range (ra, from, to); 188 185 } 189 186 return 1; 190 187 } ··· 219 214 * Used by validate_subchannel() 220 215 */ 221 216 int 222 - is_blacklisted (int devno) 217 + is_blacklisted (int ssid, int devno) 223 218 { 224 - return test_bit (devno, bl_dev); 219 + return test_bit (devno, bl_dev[ssid]); 225 220 } 226 221 227 222 #ifdef CONFIG_PROC_FS ··· 288 283 /* Iterator struct for all devices. */ 289 284 struct ccwdev_iter { 290 285 int devno; 286 + int ssid; 291 287 int in_range; 292 288 }; 293 289 ··· 297 291 { 298 292 struct ccwdev_iter *iter; 299 293 300 - if (*offset > __MAX_SUBCHANNEL) 294 + if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) 301 295 return NULL; 302 296 iter = kmalloc(sizeof(struct ccwdev_iter), GFP_KERNEL); 303 297 if (!iter) 304 298 return ERR_PTR(-ENOMEM); 305 299 memset(iter, 0, sizeof(struct ccwdev_iter)); 306 - iter->devno = *offset; 300 + iter->ssid = *offset / (__MAX_SUBCHANNEL + 1); 301 + iter->devno = *offset % (__MAX_SUBCHANNEL + 1); 307 302 return iter; 308 303 } 309 304 ··· 320 313 { 321 314 struct ccwdev_iter *iter; 322 315 323 - if (*offset > __MAX_SUBCHANNEL) 316 + if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) 324 317 return NULL; 325 318 iter = (struct ccwdev_iter *)it; 326 - iter->devno++; 319 + if (iter->devno == __MAX_SUBCHANNEL) { 320 + iter->devno = 0; 321 + iter->ssid++; 322 + if (iter->ssid > __MAX_SSID) 323 + return NULL; 324 + } else 325 + iter->devno++; 327 326 (*offset)++; 328 327 return iter; 329 328 } ··· 340 327 struct ccwdev_iter *iter; 341 328 342 329 iter = (struct ccwdev_iter *)it; 343 - if (!is_blacklisted(iter->devno)) 330 + if (!is_blacklisted(iter->ssid, iter->devno)) 344 331 /* Not blacklisted, nothing to output. */ 345 332 return 0; 346 333 if (!iter->in_range) { 347 334 /* First device in range. */ 348 335 if ((iter->devno == __MAX_SUBCHANNEL) || 349 - !is_blacklisted(iter->devno + 1)) 336 + !is_blacklisted(iter->ssid, iter->devno + 1)) 350 337 /* Singular device. */ 351 - return seq_printf(s, "0.0.%04x\n", iter->devno); 338 + return seq_printf(s, "0.%x.%04x\n", 339 + iter->ssid, iter->devno); 352 340 iter->in_range = 1; 353 - return seq_printf(s, "0.0.%04x-", iter->devno); 341 + return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno); 354 342 } 355 343 if ((iter->devno == __MAX_SUBCHANNEL) || 356 - !is_blacklisted(iter->devno + 1)) { 344 + !is_blacklisted(iter->ssid, iter->devno + 1)) { 357 345 /* Last device in range. */ 358 346 iter->in_range = 0; 359 - return seq_printf(s, "0.0.%04x\n", iter->devno); 347 + return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno); 360 348 } 361 349 return 0; 362 350 }
+1 -1
drivers/s390/cio/blacklist.h
··· 1 1 #ifndef S390_BLACKLIST_H 2 2 #define S390_BLACKLIST_H 3 3 4 - extern int is_blacklisted (int devno); 4 + extern int is_blacklisted (int ssid, int devno); 5 5 6 6 #endif
+60 -8
drivers/s390/cio/chsc.c
··· 1 1 /* 2 2 * drivers/s390/cio/chsc.c 3 3 * S/390 common I/O routines -- channel subsystem call 4 - * $Revision: 1.120 $ 4 + * $Revision: 1.126 $ 5 5 * 6 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 7 7 * IBM Corporation ··· 75 75 76 76 struct { 77 77 struct chsc_header request; 78 - u16 reserved1; 78 + u16 reserved1a:10; 79 + u16 ssid:2; 80 + u16 reserved1b:4; 79 81 u16 f_sch; /* first subchannel */ 80 82 u16 reserved2; 81 83 u16 l_sch; /* last subchannel */ ··· 104 102 .code = 0x0004, 105 103 }; 106 104 105 + ssd_area->ssid = sch->schid.ssid; 107 106 ssd_area->f_sch = sch->schid.sch_no; 108 107 ssd_area->l_sch = sch->schid.sch_no; 109 108 ··· 148 145 */ 149 146 if (ssd_area->st > 3) { /* uhm, that looks strange... */ 150 147 CIO_CRW_EVENT(0, "Strange subchannel type %d" 151 - " for sch %04x\n", ssd_area->st, 152 - sch->schid.sch_no); 148 + " for sch 0.%x.%04x\n", ssd_area->st, 149 + sch->schid.ssid, sch->schid.sch_no); 153 150 /* 154 151 * There may have been a new subchannel type defined in the 155 152 * time since this code was written; since we don't know which ··· 158 155 return 0; 159 156 } else { 160 157 const char *type[4] = {"I/O", "chsc", "message", "ADM"}; 161 - CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n", 162 - sch->schid.sch_no, type[ssd_area->st]); 158 + CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n", 159 + sch->schid.ssid, sch->schid.sch_no, 160 + type[ssd_area->st]); 163 161 164 162 sch->ssd_info.valid = 1; 165 163 sch->ssd_info.type = ssd_area->st; ··· 368 364 * that beast may be on we'll have to do a stsch 369 365 * on all devices, grr... 370 366 */ 371 - if (stsch(schid, &schib)) 367 + if (stsch_err(schid, &schib)) 372 368 /* We're through */ 373 369 return need_rescan ? -EAGAIN : -ENXIO; 374 370 ··· 822 818 put_device(&sch->dev); 823 819 return 0; 824 820 } 825 - if (stsch(schid, &schib)) 821 + if (stsch_err(schid, &schib)) 826 822 /* We're through */ 827 823 return -ENXIO; 828 824 /* Put it on the slow path. */ ··· 1080 1076 printk(KERN_WARNING"Can't allocate page for processing of " \ 1081 1077 "chsc machine checks!\n"); 1082 1078 return (sei_page ? 0 : -ENOMEM); 1079 + } 1080 + 1081 + int __init 1082 + chsc_enable_facility(int operation_code) 1083 + { 1084 + int ret; 1085 + struct { 1086 + struct chsc_header request; 1087 + u8 reserved1:4; 1088 + u8 format:4; 1089 + u8 reserved2; 1090 + u16 operation_code; 1091 + u32 reserved3; 1092 + u32 reserved4; 1093 + u32 operation_data_area[252]; 1094 + struct chsc_header response; 1095 + u32 reserved5:4; 1096 + u32 format2:4; 1097 + u32 reserved6:24; 1098 + } *sda_area; 1099 + 1100 + sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); 1101 + if (!sda_area) 1102 + return -ENOMEM; 1103 + sda_area->request = (struct chsc_header) { 1104 + .length = 0x0400, 1105 + .code = 0x0031, 1106 + }; 1107 + sda_area->operation_code = operation_code; 1108 + 1109 + ret = chsc(sda_area); 1110 + if (ret > 0) { 1111 + ret = (ret == 3) ? -ENODEV : -EBUSY; 1112 + goto out; 1113 + } 1114 + switch (sda_area->response.code) { 1115 + case 0x0003: /* invalid request block */ 1116 + case 0x0007: 1117 + ret = -EINVAL; 1118 + break; 1119 + case 0x0004: /* command not provided */ 1120 + case 0x0101: /* facility not provided */ 1121 + ret = -EOPNOTSUPP; 1122 + break; 1123 + } 1124 + out: 1125 + free_page((unsigned long)sda_area); 1126 + return ret; 1083 1127 } 1084 1128 1085 1129 subsys_initcall(chsc_alloc_sei_area);
+4
drivers/s390/cio/chsc.h
··· 5 5 #define CHSC_SEI_ACC_LINKADDR 2 6 6 #define CHSC_SEI_ACC_FULLLINKADDR 3 7 7 8 + #define CHSC_SDA_OC_MSS 0x2 9 + 8 10 struct chsc_header { 9 11 u16 length; 10 12 u16 code; ··· 65 63 extern int css_characteristics_avail; 66 64 67 65 extern void *chsc_get_chp_desc(struct subchannel*, int); 66 + 67 + extern int chsc_enable_facility(int); 68 68 69 69 #define to_channelpath(dev) container_of(dev, struct channel_path, dev) 70 70
+21 -14
drivers/s390/cio/cio.c
··· 1 1 /* 2 2 * drivers/s390/cio/cio.c 3 3 * S/390 common I/O routines -- low level i/o calls 4 - * $Revision: 1.135 $ 4 + * $Revision: 1.138 $ 5 5 * 6 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 7 7 * IBM Corporation ··· 166 166 stsch (sch->schid, &sch->schib); 167 167 168 168 CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " 169 - "subchannel %04x!\n", sch->schid.sch_no); 169 + "subchannel 0.%x.%04x!\n", sch->schid.ssid, 170 + sch->schid.sch_no); 170 171 sprintf(dbf_text, "no%s", sch->dev.bus_id); 171 172 CIO_TRACE_EVENT(0, dbf_text); 172 173 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); ··· 523 522 spin_lock_init(&sch->lock); 524 523 525 524 /* Set a name for the subchannel */ 526 - snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", schid.sch_no); 525 + snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, 526 + schid.sch_no); 527 527 528 528 /* 529 529 * The first subchannel that is not-operational (ccode==3) 530 530 * indicates that there aren't any more devices available. 531 + * If stsch gets an exception, it means the current subchannel set 532 + * is not valid. 531 533 */ 532 - ccode = stsch (schid, &sch->schib); 534 + ccode = stsch_err (schid, &sch->schib); 533 535 if (ccode) 534 - return -ENXIO; 536 + return (ccode == 3) ? -ENXIO : ccode; 535 537 536 538 sch->schid = schid; 537 539 /* Copy subchannel type from path management control word. */ ··· 545 541 */ 546 542 if (sch->st != 0) { 547 543 CIO_DEBUG(KERN_INFO, 0, 548 - "Subchannel %04X reports " 544 + "Subchannel 0.%x.%04x reports " 549 545 "non-I/O subchannel type %04X\n", 550 - sch->schid.sch_no, sch->st); 546 + sch->schid.ssid, sch->schid.sch_no, sch->st); 551 547 /* We stop here for non-io subchannels. */ 552 548 return sch->st; 553 549 } ··· 558 554 return -ENODEV; 559 555 560 556 /* Devno is valid. */ 561 - if (is_blacklisted (sch->schib.pmcw.dev)) { 557 + if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { 562 558 /* 563 559 * This device must not be known to Linux. So we simply 564 560 * say that there is no device and return ENODEV. 565 561 */ 566 562 CIO_MSG_EVENT(0, "Blacklisted device detected " 567 - "at devno %04X\n", sch->schib.pmcw.dev); 563 + "at devno %04X, subchannel set %x\n", 564 + sch->schib.pmcw.dev, sch->schid.ssid); 568 565 return -ENODEV; 569 566 } 570 567 sch->opm = 0xff; 571 - chsc_validate_chpids(sch); 568 + if (!cio_is_console(sch->schid)) 569 + chsc_validate_chpids(sch); 572 570 sch->lpm = sch->schib.pmcw.pim & 573 571 sch->schib.pmcw.pam & 574 572 sch->schib.pmcw.pom & 575 573 sch->opm; 576 574 577 575 CIO_DEBUG(KERN_INFO, 0, 578 - "Detected device %04X on subchannel %04X" 576 + "Detected device %04x on subchannel 0.%x.%04X" 579 577 " - PIM = %02X, PAM = %02X, POM = %02X\n", 580 - sch->schib.pmcw.dev, sch->schid.sch_no, sch->schib.pmcw.pim, 578 + sch->schib.pmcw.dev, sch->schid.ssid, 579 + sch->schid.sch_no, sch->schib.pmcw.pim, 581 580 sch->schib.pmcw.pam, sch->schib.pmcw.pom); 582 581 583 582 /* ··· 700 693 static int 701 694 cio_test_for_console(struct subchannel_id schid, void *data) 702 695 { 703 - if (stsch(schid, &console_subchannel.schib) != 0) 696 + if (stsch_err(schid, &console_subchannel.schib) != 0) 704 697 return -ENXIO; 705 698 if (console_subchannel.schib.pmcw.dnv && 706 699 console_subchannel.schib.pmcw.dev == ··· 848 841 { 849 842 struct schib schib; 850 843 851 - if (stsch(schid, &schib)) 844 + if (stsch_err(schid, &schib)) 852 845 return -ENXIO; 853 846 if (!schib.pmcw.ena) 854 847 return 0;
+32 -12
drivers/s390/cio/css.c
··· 1 1 /* 2 2 * drivers/s390/cio/css.c 3 3 * driver for channel subsystem 4 - * $Revision: 1.85 $ 4 + * $Revision: 1.93 $ 5 5 * 6 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 7 7 * IBM Corporation ··· 23 23 24 24 int need_rescan = 0; 25 25 int css_init_done = 0; 26 + static int max_ssid = 0; 26 27 27 28 struct channel_subsystem *css[__MAX_CSSID + 1]; 28 29 ··· 38 37 init_subchannel_id(&schid); 39 38 ret = -ENODEV; 40 39 do { 41 - ret = fn(schid, data); 42 - if (ret) 43 - break; 44 - } while (schid.sch_no++ < __MAX_SUBCHANNEL); 40 + do { 41 + ret = fn(schid, data); 42 + if (ret) 43 + break; 44 + } while (schid.sch_no++ < __MAX_SUBCHANNEL); 45 + schid.sch_no = 0; 46 + } while (schid.ssid++ < max_ssid); 45 47 return ret; 46 48 } 47 49 ··· 209 205 return -EAGAIN; /* Will be done on the slow path. */ 210 206 } 211 207 event = css_get_subchannel_status(sch, schid); 212 - CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n", 213 - schid.sch_no, event, 208 + CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n", 209 + schid.ssid, schid.sch_no, event, 214 210 sch?(disc?"disconnected":"normal"):"unknown", 215 211 slow?"slow":"fast"); 216 212 switch (event) { ··· 356 352 * Called from the machine check handler for subchannel report words. 357 353 */ 358 354 int 359 - css_process_crw(int irq) 355 + css_process_crw(int rsid1, int rsid2) 360 356 { 361 357 int ret; 362 358 struct subchannel_id mchk_schid; 363 359 364 - CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq); 360 + CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n", 361 + rsid1, rsid2); 365 362 366 363 if (need_rescan) 367 364 /* We need to iterate all subchannels anyway. */ 368 365 return -EAGAIN; 369 366 370 367 init_subchannel_id(&mchk_schid); 371 - mchk_schid.sch_no = irq; 368 + mchk_schid.sch_no = rsid1; 369 + if (rsid2 != 0) 370 + mchk_schid.ssid = (rsid2 >> 8) & 3; 371 + 372 372 /* 373 373 * Since we are always presented with IPI in the CRW, we have to 374 374 * use stsch() to find out if the subchannel in question has come ··· 473 465 if ((ret = bus_register(&css_bus_type))) 474 466 goto out; 475 467 468 + /* Try to enable MSS. */ 469 + ret = chsc_enable_facility(CHSC_SDA_OC_MSS); 470 + switch (ret) { 471 + case 0: /* Success. */ 472 + max_ssid = __MAX_SSID; 473 + break; 474 + case -ENOMEM: 475 + goto out_bus; 476 + default: 477 + max_ssid = 0; 478 + } 476 479 /* Setup css structure. */ 477 480 for (i = 0; i <= __MAX_CSSID; i++) { 478 481 css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); 479 482 if (!css[i]) { 480 483 ret = -ENOMEM; 481 - goto out_bus; 484 + goto out_unregister; 482 485 } 483 486 setup_css(i); 484 487 ret = device_register(&css[i]->device); ··· 504 485 return 0; 505 486 out_free: 506 487 kfree(css[i]); 507 - out_bus: 488 + out_unregister: 508 489 while (i > 0) { 509 490 i--; 510 491 device_unregister(&css[i]->device); 511 492 } 493 + out_bus: 512 494 bus_unregister(&css_bus_type); 513 495 out: 514 496 return ret;
+2
drivers/s390/cio/css.h
··· 77 77 unsigned long registered; 78 78 __u16 devno; /* device number */ 79 79 __u16 sch_no; /* subchannel number */ 80 + __u8 ssid; /* subchannel set id */ 80 81 __u8 imask; /* lpm mask for SNID/SID/SPGID */ 81 82 int iretry; /* retry counter SNID/SID/SPGID */ 82 83 struct { ··· 136 135 extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); 137 136 138 137 #define __MAX_SUBCHANNEL 65535 138 + #define __MAX_SSID 3 139 139 #define __MAX_CHPID 255 140 140 #define __MAX_CSSID 0 141 141
+14 -8
drivers/s390/cio/device.c
··· 535 535 } 536 536 537 537 struct match_data { 538 - unsigned int devno; 538 + unsigned int devno; 539 + unsigned int ssid; 539 540 struct ccw_device * sibling; 540 541 }; 541 542 ··· 549 548 cdev = to_ccwdev(dev); 550 549 if ((cdev->private->state == DEV_STATE_DISCONNECTED) && 551 550 (cdev->private->devno == d->devno) && 551 + (cdev->private->ssid == d->ssid) && 552 552 (cdev != d->sibling)) { 553 553 cdev->private->state = DEV_STATE_NOT_OPER; 554 554 return 1; ··· 558 556 } 559 557 560 558 static struct ccw_device * 561 - get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) 559 + get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid, 560 + struct ccw_device *sibling) 562 561 { 563 562 struct device *dev; 564 563 struct match_data data = { 565 - .devno = devno, 564 + .devno = devno, 565 + .ssid = ssid, 566 566 .sibling = sibling, 567 567 }; 568 568 ··· 620 616 621 617 need_rename = 1; 622 618 other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev, 623 - cdev); 619 + sch->schid.ssid, cdev); 624 620 if (other_cdev) { 625 621 struct subchannel *other_sch; 626 622 ··· 643 639 if (test_and_clear_bit(1, &cdev->private->registered)) 644 640 device_del(&cdev->dev); 645 641 if (need_rename) 646 - snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", 647 - sch->schib.pmcw.dev); 642 + snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", 643 + sch->schid.ssid, sch->schib.pmcw.dev); 648 644 PREPARE_WORK(&cdev->private->kick_work, 649 645 ccw_device_add_changed, (void *)cdev); 650 646 queue_work(ccw_device_work, &cdev->private->kick_work); ··· 773 769 sch->dev.driver_data = cdev; 774 770 sch->driver = &io_subchannel_driver; 775 771 cdev->ccwlock = &sch->lock; 772 + 776 773 /* Init private data. */ 777 774 priv = cdev->private; 778 775 priv->devno = sch->schib.pmcw.dev; 776 + priv->ssid = sch->schid.ssid; 779 777 priv->sch_no = sch->schid.sch_no; 780 778 priv->state = DEV_STATE_NOT_OPER; 781 779 INIT_LIST_HEAD(&priv->cmb_list); ··· 785 779 init_timer(&priv->timer); 786 780 787 781 /* Set an initial name for the device. */ 788 - snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", 789 - sch->schib.pmcw.dev); 782 + snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", 783 + sch->schid.ssid, sch->schib.pmcw.dev); 790 784 791 785 /* Increase counter of devices currently in recognition. */ 792 786 atomic_inc(&ccw_device_init_count);
+9 -6
drivers/s390/cio/device_fsm.c
··· 257 257 switch (state) { 258 258 case DEV_STATE_NOT_OPER: 259 259 CIO_DEBUG(KERN_WARNING, 2, 260 - "SenseID : unknown device %04x on subchannel %04x\n", 261 - cdev->private->devno, sch->schid.sch_no); 260 + "SenseID : unknown device %04x on subchannel " 261 + "0.%x.%04x\n", cdev->private->devno, 262 + sch->schid.ssid, sch->schid.sch_no); 262 263 break; 263 264 case DEV_STATE_OFFLINE: 264 265 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { ··· 283 282 return; 284 283 } 285 284 /* Issue device info message. */ 286 - CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: " 285 + CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: " 287 286 "CU Type/Mod = %04X/%02X, Dev Type/Mod = " 288 - "%04X/%02X\n", cdev->private->devno, 287 + "%04X/%02X\n", 288 + cdev->private->ssid, cdev->private->devno, 289 289 cdev->id.cu_type, cdev->id.cu_model, 290 290 cdev->id.dev_type, cdev->id.dev_model); 291 291 break; 292 292 case DEV_STATE_BOXED: 293 293 CIO_DEBUG(KERN_WARNING, 2, 294 - "SenseID : boxed device %04x on subchannel %04x\n", 295 - cdev->private->devno, sch->schid.sch_no); 294 + "SenseID : boxed device %04x on subchannel " 295 + "0.%x.%04x\n", cdev->private->devno, 296 + sch->schid.ssid, sch->schid.sch_no); 296 297 break; 297 298 } 298 299 cdev->private->state = state;
+12 -10
drivers/s390/cio/device_id.c
··· 256 256 * sense id information. So, for intervention required, 257 257 * we use the "whack it until it talks" strategy... 258 258 */ 259 - CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x " 260 - "reports cmd reject\n", 261 - cdev->private->devno, sch->schid.sch_no); 259 + CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel " 260 + "0.%x.%04x reports cmd reject\n", 261 + cdev->private->devno, sch->schid.ssid, 262 + sch->schid.sch_no); 262 263 return -EOPNOTSUPP; 263 264 } 264 265 if (irb->esw.esw0.erw.cons) { 265 - CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, " 266 + CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, " 266 267 "lpum %02X, cnt %02d, sns :" 267 268 " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 268 - cdev->private->devno, 269 + cdev->private->ssid, cdev->private->devno, 269 270 irb->esw.esw0.sublog.lpum, 270 271 irb->esw.esw0.erw.scnt, 271 272 irb->ecw[0], irb->ecw[1], ··· 278 277 if (irb->scsw.cc == 3) { 279 278 if ((sch->orb.lpm & 280 279 sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) 281 - CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on" 282 - " subchannel %04x is 'not operational'\n", 283 - sch->orb.lpm, cdev->private->devno, 280 + CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x " 281 + "on subchannel 0.%x.%04x is " 282 + "'not operational'\n", sch->orb.lpm, 283 + cdev->private->devno, sch->schid.ssid, 284 284 sch->schid.sch_no); 285 285 return -EACCES; 286 286 } 287 287 /* Hmm, whatever happened, try again. */ 288 288 CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on " 289 - "subchannel %04x returns status %02X%02X\n", 290 - cdev->private->devno, sch->schid.sch_no, 289 + "subchannel 0.%x.%04x returns status %02X%02X\n", 290 + cdev->private->devno, sch->schid.ssid, sch->schid.sch_no, 291 291 irb->scsw.dstat, irb->scsw.cstat); 292 292 return -EAGAIN; 293 293 }
+22 -18
drivers/s390/cio/device_pgid.c
··· 57 57 if (ret != -EACCES) 58 58 return ret; 59 59 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " 60 - "%04x, lpm %02X, became 'not " 60 + "0.%x.%04x, lpm %02X, became 'not " 61 61 "operational'\n", 62 - cdev->private->devno, sch->schid.sch_no, 63 - cdev->private->imask); 62 + cdev->private->devno, sch->schid.ssid, 63 + sch->schid.sch_no, cdev->private->imask); 64 64 65 65 } 66 66 cdev->private->imask >>= 1; ··· 106 106 return -EOPNOTSUPP; 107 107 } 108 108 if (irb->esw.esw0.erw.cons) { 109 - CIO_MSG_EVENT(2, "SNID - device %04x, unit check, " 109 + CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, " 110 110 "lpum %02X, cnt %02d, sns : " 111 111 "%02X%02X%02X%02X %02X%02X%02X%02X ...\n", 112 - cdev->private->devno, 112 + cdev->private->ssid, cdev->private->devno, 113 113 irb->esw.esw0.sublog.lpum, 114 114 irb->esw.esw0.erw.scnt, 115 115 irb->ecw[0], irb->ecw[1], ··· 119 119 return -EAGAIN; 120 120 } 121 121 if (irb->scsw.cc == 3) { 122 - CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " 123 - "%04x, lpm %02X, became 'not operational'\n", 124 - cdev->private->devno, sch->schid.sch_no, 125 - sch->orb.lpm); 122 + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x," 123 + " lpm %02X, became 'not operational'\n", 124 + cdev->private->devno, sch->schid.ssid, 125 + sch->schid.sch_no, sch->orb.lpm); 126 126 return -EACCES; 127 127 } 128 128 if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) { 129 - CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x " 129 + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x " 130 130 "is reserved by someone else\n", 131 - cdev->private->devno, sch->schid.sch_no); 131 + cdev->private->devno, sch->schid.ssid, 132 + sch->schid.sch_no); 132 133 return -EUSERS; 133 134 } 134 135 return 0; ··· 238 237 sch->lpm &= ~cdev->private->imask; 239 238 sch->vpm &= ~cdev->private->imask; 240 239 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " 241 - "%04x, lpm %02X, became 'not operational'\n", 242 - cdev->private->devno, sch->schid.sch_no, cdev->private->imask); 240 + "0.%x.%04x, lpm %02X, became 'not operational'\n", 241 + cdev->private->devno, sch->schid.ssid, 242 + sch->schid.sch_no, cdev->private->imask); 243 243 return ret; 244 244 } 245 245 ··· 262 260 if (irb->ecw[0] & SNS0_CMD_REJECT) 263 261 return -EOPNOTSUPP; 264 262 /* Hmm, whatever happened, try again. */ 265 - CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, " 263 + CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, " 264 + "cnt %02d, " 266 265 "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 266 + cdev->private->ssid, 267 267 cdev->private->devno, irb->esw.esw0.erw.scnt, 268 268 irb->ecw[0], irb->ecw[1], 269 269 irb->ecw[2], irb->ecw[3], ··· 274 270 return -EAGAIN; 275 271 } 276 272 if (irb->scsw.cc == 3) { 277 - CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " 278 - "%04x, lpm %02X, became 'not operational'\n", 279 - cdev->private->devno, sch->schid.sch_no, 280 - cdev->private->imask); 273 + CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x," 274 + " lpm %02X, became 'not operational'\n", 275 + cdev->private->devno, sch->schid.ssid, 276 + sch->schid.sch_no, cdev->private->imask); 281 277 return -EACCES; 282 278 } 283 279 return 0;
+6 -4
drivers/s390/cio/device_status.c
··· 36 36 37 37 CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check " 38 38 "received" 39 - " ... device %04X on subchannel %04X, dev_stat " 39 + " ... device %04x on subchannel 0.%x.%04x, dev_stat " 40 40 ": %02X sch_stat : %02X\n", 41 - cdev->private->devno, cdev->private->sch_no, 41 + cdev->private->devno, cdev->private->ssid, 42 + cdev->private->sch_no, 42 43 irb->scsw.dstat, irb->scsw.cstat); 43 44 44 45 if (irb->scsw.cc != 3) { ··· 62 61 sch = to_subchannel(cdev->dev.parent); 63 62 stsch (sch->schid, &sch->schib); 64 63 65 - CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are " 66 - "not operational \n", __FUNCTION__, sch->schid.sch_no, 64 + CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are " 65 + "not operational \n", __FUNCTION__, 66 + sch->schid.ssid, sch->schid.sch_no, 67 67 sch->schib.pmcw.pnom); 68 68 69 69 sch->lpm &= ~sch->schib.pmcw.pnom;
+29
drivers/s390/cio/ioasm.h
··· 38 38 return ccode; 39 39 } 40 40 41 + static inline int stsch_err(struct subchannel_id schid, 42 + volatile struct schib *addr) 43 + { 44 + int ccode; 45 + 46 + __asm__ __volatile__( 47 + " lhi %0,%3\n" 48 + " lr 1,%1\n" 49 + " stsch 0(%2)\n" 50 + "0: ipm %0\n" 51 + " srl %0,28\n" 52 + "1:\n" 53 + #ifdef CONFIG_ARCH_S390X 54 + ".section __ex_table,\"a\"\n" 55 + " .align 8\n" 56 + " .quad 0b,1b\n" 57 + ".previous" 58 + #else 59 + ".section __ex_table,\"a\"\n" 60 + " .align 4\n" 61 + " .long 0b,1b\n" 62 + ".previous" 63 + #endif 64 + : "=&d" (ccode) 65 + : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr) 66 + : "cc", "1" ); 67 + return ccode; 68 + } 69 + 41 70 static inline int msch(struct subchannel_id schid, 42 71 volatile struct schib *addr) 43 72 {
+48 -33
drivers/s390/cio/qdio.c
··· 56 56 #include "ioasm.h" 57 57 #include "chsc.h" 58 58 59 - #define VERSION_QDIO_C "$Revision: 1.113 $" 59 + #define VERSION_QDIO_C "$Revision: 1.114 $" 60 60 61 61 /****************** MODULE PARAMETER VARIABLES ********************/ 62 62 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); ··· 2066 2066 2067 2067 switch (irq_ptr->state) { 2068 2068 case QDIO_IRQ_STATE_INACTIVE: 2069 - QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n", 2070 - irq_ptr->schid.sch_no); 2069 + QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n", 2070 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2071 2071 QDIO_DBF_TEXT2(1,setup,"eq:timeo"); 2072 2072 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2073 2073 break; 2074 2074 case QDIO_IRQ_STATE_CLEANUP: 2075 - QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n", 2076 - irq_ptr->schid.sch_no); 2075 + QDIO_PRINT_INFO("Did not get interrupt on cleanup, " 2076 + "irq=0.%x.%x.\n", 2077 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2077 2078 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2078 2079 break; 2079 2080 case QDIO_IRQ_STATE_ESTABLISHED: 2080 2081 case QDIO_IRQ_STATE_ACTIVE: 2081 2082 /* I/O has been terminated by common I/O layer. */ 2082 - QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n", 2083 - irq_ptr->schid.sch_no); 2083 + QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n", 2084 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2084 2085 QDIO_DBF_TEXT2(1, trace, "cio:term"); 2085 2086 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); 2086 2087 if (get_device(&cdev->dev)) { ··· 2274 2273 unsigned char qdioac; 2275 2274 struct { 2276 2275 struct chsc_header request; 2277 - u16 reserved1; 2276 + u16 reserved1:10; 2277 + u16 ssid:2; 2278 + u16 fmt:4; 2278 2279 u16 first_sch; 2279 2280 u16 reserved2; 2280 2281 u16 last_sch; ··· 2321 2318 }; 2322 2319 ssqd_area->first_sch = irq_ptr->schid.sch_no; 2323 2320 ssqd_area->last_sch = irq_ptr->schid.sch_no; 2321 + ssqd_area->ssid = irq_ptr->schid.ssid; 2324 2322 result = chsc(ssqd_area); 2325 2323 2326 2324 if (result) { 2327 2325 QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ 2328 - "SIGAs for sch x%x.\n", 2329 - result, irq_ptr->schid.sch_no); 2326 + "SIGAs for sch 0.%x.%x.\n", result, 2327 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2330 2328 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2331 2329 CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2332 2330 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ ··· 2337 2333 2338 2334 if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { 2339 2335 QDIO_PRINT_WARN("response upon checking SIGA needs " \ 2340 - "is 0x%x. Using all SIGAs for sch x%x.\n", 2341 - ssqd_area->response.code, irq_ptr->schid.sch_no); 2336 + "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n", 2337 + ssqd_area->response.code, 2338 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2342 2339 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2343 2340 CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2344 2341 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ ··· 2349 2344 if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || 2350 2345 !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || 2351 2346 (ssqd_area->sch != irq_ptr->schid.sch_no)) { 2352 - QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ 2353 - "using all SIGAs.\n",irq_ptr->schid.sch_no); 2347 + QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \ 2348 + "using all SIGAs.\n", 2349 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2354 2350 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | 2355 2351 CHSC_FLAG_SIGA_OUTPUT_NECESSARY | 2356 2352 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ ··· 2459 2453 scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2460 2454 if (!scssc_area) { 2461 2455 QDIO_PRINT_WARN("No memory for setting indicators on " \ 2462 - "subchannel x%x.\n", irq_ptr->schid.sch_no); 2456 + "subchannel 0.%x.%x.\n", 2457 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2463 2458 return -ENOMEM; 2464 2459 } 2465 2460 scssc_area->request = (struct chsc_header) { ··· 2486 2479 2487 2480 result = chsc(scssc_area); 2488 2481 if (result) { 2489 - QDIO_PRINT_WARN("could not set indicators on irq x%x, " \ 2490 - "cc=%i.\n",irq_ptr->schid.sch_no,result); 2482 + QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \ 2483 + "cc=%i.\n", 2484 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result); 2491 2485 result = -EIO; 2492 2486 goto out; 2493 2487 } ··· 2544 2536 scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2545 2537 if (!scsscf_area) { 2546 2538 QDIO_PRINT_WARN("No memory for setting delay target on " \ 2547 - "subchannel x%x.\n", irq_ptr->schid.sch_no); 2539 + "subchannel 0.%x.%x.\n", 2540 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2548 2541 return -ENOMEM; 2549 2542 } 2550 2543 scsscf_area->request = (struct chsc_header) { ··· 2557 2548 2558 2549 result=chsc(scsscf_area); 2559 2550 if (result) { 2560 - QDIO_PRINT_WARN("could not set delay target on irq x%x, " \ 2561 - "cc=%i. Continuing.\n",irq_ptr->schid.sch_no, 2551 + QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \ 2552 + "cc=%i. Continuing.\n", 2553 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 2562 2554 result); 2563 2555 result = -EIO; 2564 2556 goto out; ··· 2880 2870 QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int)); 2881 2871 QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int)); 2882 2872 QDIO_PRINT_ERR("received check condition on establish " \ 2883 - "queues on irq 0x%x (cs=x%x, ds=x%x).\n", 2884 - irq_ptr->schid.sch_no,cstat,dstat); 2873 + "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n", 2874 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 2875 + cstat,dstat); 2885 2876 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR); 2886 2877 } 2887 2878 ··· 2890 2879 QDIO_DBF_TEXT2(1,setup,"eq:no de"); 2891 2880 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); 2892 2881 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); 2893 - QDIO_PRINT_ERR("establish queues on irq %04x: didn't get " 2882 + QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get " 2894 2883 "device end: dstat=%02x, cstat=%02x\n", 2895 - irq_ptr->schid.sch_no, dstat, cstat); 2884 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 2885 + dstat, cstat); 2896 2886 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2897 2887 return 1; 2898 2888 } ··· 2902 2890 QDIO_DBF_TEXT2(1,setup,"eq:badio"); 2903 2891 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); 2904 2892 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); 2905 - QDIO_PRINT_ERR("establish queues on irq %04x: got " 2893 + QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got " 2906 2894 "the following devstat: dstat=%02x, " 2907 - "cstat=%02x\n", 2895 + "cstat=%02x\n", irq_ptr->schid.ssid, 2908 2896 irq_ptr->schid.sch_no, dstat, cstat); 2909 2897 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2910 2898 return 1; ··· 3053 3041 QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); 3054 3042 if (!irq_ptr->dev_st_chg_ind) { 3055 3043 QDIO_PRINT_WARN("no indicator location available " \ 3056 - "for irq 0x%x\n",irq_ptr->schid.sch_no); 3044 + "for irq 0.%x.%x\n", 3045 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 3057 3046 qdio_release_irq_memory(irq_ptr); 3058 3047 return -ENOBUFS; 3059 3048 } ··· 3211 3198 sprintf(dbf_text,"eq:io%4x",result); 3212 3199 QDIO_DBF_TEXT2(1,setup,dbf_text); 3213 3200 } 3214 - QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \ 3215 - "returned %i, next try returned %i\n", 3216 - irq_ptr->schid.sch_no,result,result2); 3201 + QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \ 3202 + "returned %i, next try returned %i\n", 3203 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 3204 + result, result2); 3217 3205 result=result2; 3218 3206 if (result) 3219 3207 ccw_device_set_timeout(cdev, 0); ··· 3312 3298 sprintf(dbf_text,"aq:io%4x",result); 3313 3299 QDIO_DBF_TEXT2(1,setup,dbf_text); 3314 3300 } 3315 - QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \ 3316 - "returned %i, next try returned %i\n", 3317 - irq_ptr->schid.sch_no,result,result2); 3301 + QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \ 3302 + "returned %i, next try returned %i\n", 3303 + irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 3304 + result, result2); 3318 3305 result=result2; 3319 3306 } 3320 3307
+2 -1
drivers/s390/cio/schid.h
··· 2 2 #define S390_SCHID_H 3 3 4 4 struct subchannel_id { 5 - __u32 reserved:15; 5 + __u32 reserved:13; 6 + __u32 ssid:2; 6 7 __u32 one:1; 7 8 __u32 sch_no:16; 8 9 } __attribute__ ((packed,aligned(4)));
+42 -14
drivers/s390/s390mach.c
··· 23 23 24 24 static struct semaphore m_sem; 25 25 26 - extern int css_process_crw(int); 26 + extern int css_process_crw(int, int); 27 27 extern int chsc_process_crw(void); 28 28 extern int chp_process_crw(int, int); 29 29 extern void css_reiterate_subchannels(void); ··· 49 49 static int 50 50 s390_collect_crw_info(void *param) 51 51 { 52 - struct crw crw; 52 + struct crw crw[2]; 53 53 int ccode, ret, slow; 54 54 struct semaphore *sem; 55 + unsigned int chain; 55 56 56 57 sem = (struct semaphore *)param; 57 58 /* Set a nice name. */ ··· 60 59 repeat: 61 60 down_interruptible(sem); 62 61 slow = 0; 62 + chain = 0; 63 63 while (1) { 64 - ccode = stcrw(&crw); 64 + if (unlikely(chain > 1)) { 65 + struct crw tmp_crw; 66 + 67 + printk(KERN_WARNING"%s: Code does not support more " 68 + "than two chained crws; please report to " 69 + "linux390@de.ibm.com!\n", __FUNCTION__); 70 + ccode = stcrw(&tmp_crw); 71 + printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " 72 + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 73 + __FUNCTION__, tmp_crw.slct, tmp_crw.oflw, 74 + tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, 75 + tmp_crw.erc, tmp_crw.rsid); 76 + printk(KERN_WARNING"%s: This was crw number %x in the " 77 + "chain\n", __FUNCTION__, chain); 78 + if (ccode != 0) 79 + break; 80 + chain = tmp_crw.chn ? chain + 1 : 0; 81 + continue; 82 + } 83 + ccode = stcrw(&crw[chain]); 65 84 if (ccode != 0) 66 85 break; 67 86 DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " 68 87 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 69 - crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc, 70 - crw.erc, crw.rsid); 88 + crw[chain].slct, crw[chain].oflw, crw[chain].chn, 89 + crw[chain].rsc, crw[chain].anc, crw[chain].erc, 90 + crw[chain].rsid); 71 91 /* Check for overflows. */ 72 - if (crw.oflw) { 92 + if (crw[chain].oflw) { 73 93 pr_debug("%s: crw overflow detected!\n", __FUNCTION__); 74 94 css_reiterate_subchannels(); 95 + chain = 0; 75 96 slow = 1; 76 97 continue; 77 98 } 78 - switch (crw.rsc) { 99 + switch (crw[chain].rsc) { 79 100 case CRW_RSC_SCH: 80 - pr_debug("source is subchannel %04X\n", crw.rsid); 81 - ret = css_process_crw (crw.rsid); 101 + if (crw[0].chn && !chain) 102 + break; 103 + pr_debug("source is subchannel %04X\n", crw[0].rsid); 104 + ret = css_process_crw (crw[0].rsid, 105 + chain ? crw[1].rsid : 0); 82 106 if (ret == -EAGAIN) 83 107 slow = 1; 84 108 break; ··· 111 85 pr_debug("source is monitoring facility\n"); 112 86 break; 113 87 case CRW_RSC_CPATH: 114 - pr_debug("source is channel path %02X\n", crw.rsid); 115 - switch (crw.erc) { 88 + pr_debug("source is channel path %02X\n", crw[0].rsid); 89 + switch (crw[0].erc) { 116 90 case CRW_ERC_IPARM: /* Path has come. */ 117 - ret = chp_process_crw(crw.rsid, 1); 91 + ret = chp_process_crw(crw[0].rsid, 1); 118 92 break; 119 93 case CRW_ERC_PERRI: /* Path has gone. */ 120 94 case CRW_ERC_PERRN: 121 - ret = chp_process_crw(crw.rsid, 0); 95 + ret = chp_process_crw(crw[0].rsid, 0); 122 96 break; 123 97 default: 124 98 pr_debug("Don't know how to handle erc=%x\n", 125 - crw.erc); 99 + crw[0].erc); 126 100 ret = 0; 127 101 } 128 102 if (ret == -EAGAIN) ··· 141 115 pr_debug("unknown source\n"); 142 116 break; 143 117 } 118 + /* chain is always 0 or 1 here. */ 119 + chain = crw[chain].chn ? chain + 1 : 0; 144 120 } 145 121 if (slow) 146 122 queue_work(slow_path_wq, &slow_path_work);