aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
authorCornelia Huck <cohuck@de.ibm.com>2006-01-06 03:19:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:51 -0500
commita8237fc4108060402d904bea5e1062e22e731969 (patch)
treefc19e33ea8bbe664c33fba6c78b34e497f2cc478 /drivers/s390/cio/cio.c
parent8129ee164267dc030b8e1d541ee3643c0b9f2fa1 (diff)
[PATCH] s390: introduce struct subchannel_id
This patch introduces a struct subchannel_id containing the subchannel number (formerly referred to as "irq") and switches code formerly relying on the subchannel number over to it. While we're touching inline assemblies anyway, make sure they have correct memory constraints. 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>
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c84
1 files changed, 45 insertions, 39 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 185bc73c3ecd..396bada65f86 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -135,7 +135,7 @@ cio_tpi(void)
135 return 0; 135 return 0;
136 irb = (struct irb *) __LC_IRB; 136 irb = (struct irb *) __LC_IRB;
137 /* Store interrupt response block to lowcore. */ 137 /* Store interrupt response block to lowcore. */
138 if (tsch (tpi_info->irq, irb) != 0) 138 if (tsch (tpi_info->schid, irb) != 0)
139 /* Not status pending or not operational. */ 139 /* Not status pending or not operational. */
140 return 1; 140 return 1;
141 sch = (struct subchannel *)(unsigned long)tpi_info->intparm; 141 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -163,10 +163,10 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
163 else 163 else
164 sch->lpm = 0; 164 sch->lpm = 0;
165 165
166 stsch (sch->irq, &sch->schib); 166 stsch (sch->schid, &sch->schib);
167 167
168 CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " 168 CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
169 "subchannel %04x!\n", sch->irq); 169 "subchannel %04x!\n", sch->schid.sch_no);
170 sprintf(dbf_text, "no%s", sch->dev.bus_id); 170 sprintf(dbf_text, "no%s", sch->dev.bus_id);
171 CIO_TRACE_EVENT(0, dbf_text); 171 CIO_TRACE_EVENT(0, dbf_text);
172 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); 172 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -204,7 +204,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
204 sch->orb.key = key >> 4; 204 sch->orb.key = key >> 4;
205 /* issue "Start Subchannel" */ 205 /* issue "Start Subchannel" */
206 sch->orb.cpa = (__u32) __pa (cpa); 206 sch->orb.cpa = (__u32) __pa (cpa);
207 ccode = ssch (sch->irq, &sch->orb); 207 ccode = ssch (sch->schid, &sch->orb);
208 208
209 /* process condition code */ 209 /* process condition code */
210 sprintf (dbf_txt, "ccode:%d", ccode); 210 sprintf (dbf_txt, "ccode:%d", ccode);
@@ -243,7 +243,7 @@ cio_resume (struct subchannel *sch)
243 CIO_TRACE_EVENT (4, "resIO"); 243 CIO_TRACE_EVENT (4, "resIO");
244 CIO_TRACE_EVENT (4, sch->dev.bus_id); 244 CIO_TRACE_EVENT (4, sch->dev.bus_id);
245 245
246 ccode = rsch (sch->irq); 246 ccode = rsch (sch->schid);
247 247
248 sprintf (dbf_txt, "ccode:%d", ccode); 248 sprintf (dbf_txt, "ccode:%d", ccode);
249 CIO_TRACE_EVENT (4, dbf_txt); 249 CIO_TRACE_EVENT (4, dbf_txt);
@@ -283,7 +283,7 @@ cio_halt(struct subchannel *sch)
283 /* 283 /*
284 * Issue "Halt subchannel" and process condition code 284 * Issue "Halt subchannel" and process condition code
285 */ 285 */
286 ccode = hsch (sch->irq); 286 ccode = hsch (sch->schid);
287 287
288 sprintf (dbf_txt, "ccode:%d", ccode); 288 sprintf (dbf_txt, "ccode:%d", ccode);
289 CIO_TRACE_EVENT (2, dbf_txt); 289 CIO_TRACE_EVENT (2, dbf_txt);
@@ -318,7 +318,7 @@ cio_clear(struct subchannel *sch)
318 /* 318 /*
319 * Issue "Clear subchannel" and process condition code 319 * Issue "Clear subchannel" and process condition code
320 */ 320 */
321 ccode = csch (sch->irq); 321 ccode = csch (sch->schid);
322 322
323 sprintf (dbf_txt, "ccode:%d", ccode); 323 sprintf (dbf_txt, "ccode:%d", ccode);
324 CIO_TRACE_EVENT (2, dbf_txt); 324 CIO_TRACE_EVENT (2, dbf_txt);
@@ -351,7 +351,7 @@ cio_cancel (struct subchannel *sch)
351 CIO_TRACE_EVENT (2, "cancelIO"); 351 CIO_TRACE_EVENT (2, "cancelIO");
352 CIO_TRACE_EVENT (2, sch->dev.bus_id); 352 CIO_TRACE_EVENT (2, sch->dev.bus_id);
353 353
354 ccode = xsch (sch->irq); 354 ccode = xsch (sch->schid);
355 355
356 sprintf (dbf_txt, "ccode:%d", ccode); 356 sprintf (dbf_txt, "ccode:%d", ccode);
357 CIO_TRACE_EVENT (2, dbf_txt); 357 CIO_TRACE_EVENT (2, dbf_txt);
@@ -359,7 +359,7 @@ cio_cancel (struct subchannel *sch)
359 switch (ccode) { 359 switch (ccode) {
360 case 0: /* success */ 360 case 0: /* success */
361 /* Update information in scsw. */ 361 /* Update information in scsw. */
362 stsch (sch->irq, &sch->schib); 362 stsch (sch->schid, &sch->schib);
363 return 0; 363 return 0;
364 case 1: /* status pending */ 364 case 1: /* status pending */
365 return -EBUSY; 365 return -EBUSY;
@@ -381,7 +381,7 @@ cio_modify (struct subchannel *sch)
381 381
382 ret = 0; 382 ret = 0;
383 for (retry = 0; retry < 5; retry++) { 383 for (retry = 0; retry < 5; retry++) {
384 ccode = msch_err (sch->irq, &sch->schib); 384 ccode = msch_err (sch->schid, &sch->schib);
385 if (ccode < 0) /* -EIO if msch gets a program check. */ 385 if (ccode < 0) /* -EIO if msch gets a program check. */
386 return ccode; 386 return ccode;
387 switch (ccode) { 387 switch (ccode) {
@@ -414,7 +414,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
414 CIO_TRACE_EVENT (2, "ensch"); 414 CIO_TRACE_EVENT (2, "ensch");
415 CIO_TRACE_EVENT (2, sch->dev.bus_id); 415 CIO_TRACE_EVENT (2, sch->dev.bus_id);
416 416
417 ccode = stsch (sch->irq, &sch->schib); 417 ccode = stsch (sch->schid, &sch->schib);
418 if (ccode) 418 if (ccode)
419 return -ENODEV; 419 return -ENODEV;
420 420
@@ -432,13 +432,13 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
432 */ 432 */
433 sch->schib.pmcw.csense = 0; 433 sch->schib.pmcw.csense = 0;
434 if (ret == 0) { 434 if (ret == 0) {
435 stsch (sch->irq, &sch->schib); 435 stsch (sch->schid, &sch->schib);
436 if (sch->schib.pmcw.ena) 436 if (sch->schib.pmcw.ena)
437 break; 437 break;
438 } 438 }
439 if (ret == -EBUSY) { 439 if (ret == -EBUSY) {
440 struct irb irb; 440 struct irb irb;
441 if (tsch(sch->irq, &irb) != 0) 441 if (tsch(sch->schid, &irb) != 0)
442 break; 442 break;
443 } 443 }
444 } 444 }
@@ -461,7 +461,7 @@ cio_disable_subchannel (struct subchannel *sch)
461 CIO_TRACE_EVENT (2, "dissch"); 461 CIO_TRACE_EVENT (2, "dissch");
462 CIO_TRACE_EVENT (2, sch->dev.bus_id); 462 CIO_TRACE_EVENT (2, sch->dev.bus_id);
463 463
464 ccode = stsch (sch->irq, &sch->schib); 464 ccode = stsch (sch->schid, &sch->schib);
465 if (ccode == 3) /* Not operational. */ 465 if (ccode == 3) /* Not operational. */
466 return -ENODEV; 466 return -ENODEV;
467 467
@@ -485,7 +485,7 @@ cio_disable_subchannel (struct subchannel *sch)
485 */ 485 */
486 break; 486 break;
487 if (ret == 0) { 487 if (ret == 0) {
488 stsch (sch->irq, &sch->schib); 488 stsch (sch->schid, &sch->schib);
489 if (!sch->schib.pmcw.ena) 489 if (!sch->schib.pmcw.ena)
490 break; 490 break;
491 } 491 }
@@ -508,12 +508,12 @@ cio_disable_subchannel (struct subchannel *sch)
508 * -ENODEV for subchannels with invalid device number or blacklisted devices 508 * -ENODEV for subchannels with invalid device number or blacklisted devices
509 */ 509 */
510int 510int
511cio_validate_subchannel (struct subchannel *sch, unsigned int irq) 511cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
512{ 512{
513 char dbf_txt[15]; 513 char dbf_txt[15];
514 int ccode; 514 int ccode;
515 515
516 sprintf (dbf_txt, "valsch%x", irq); 516 sprintf (dbf_txt, "valsch%x", schid.sch_no);
517 CIO_TRACE_EVENT (4, dbf_txt); 517 CIO_TRACE_EVENT (4, dbf_txt);
518 518
519 /* Nuke all fields. */ 519 /* Nuke all fields. */
@@ -522,17 +522,17 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
522 spin_lock_init(&sch->lock); 522 spin_lock_init(&sch->lock);
523 523
524 /* Set a name for the subchannel */ 524 /* Set a name for the subchannel */
525 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", irq); 525 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", schid.sch_no);
526 526
527 /* 527 /*
528 * The first subchannel that is not-operational (ccode==3) 528 * The first subchannel that is not-operational (ccode==3)
529 * indicates that there aren't any more devices available. 529 * indicates that there aren't any more devices available.
530 */ 530 */
531 sch->irq = irq; 531 ccode = stsch (schid, &sch->schib);
532 ccode = stsch (irq, &sch->schib);
533 if (ccode) 532 if (ccode)
534 return -ENXIO; 533 return -ENXIO;
535 534
535 sch->schid = schid;
536 /* Copy subchannel type from path management control word. */ 536 /* Copy subchannel type from path management control word. */
537 sch->st = sch->schib.pmcw.st; 537 sch->st = sch->schib.pmcw.st;
538 538
@@ -543,7 +543,7 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
543 CIO_DEBUG(KERN_INFO, 0, 543 CIO_DEBUG(KERN_INFO, 0,
544 "Subchannel %04X reports " 544 "Subchannel %04X reports "
545 "non-I/O subchannel type %04X\n", 545 "non-I/O subchannel type %04X\n",
546 sch->irq, sch->st); 546 sch->schid.sch_no, sch->st);
547 /* We stop here for non-io subchannels. */ 547 /* We stop here for non-io subchannels. */
548 return sch->st; 548 return sch->st;
549 } 549 }
@@ -573,7 +573,7 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
573 CIO_DEBUG(KERN_INFO, 0, 573 CIO_DEBUG(KERN_INFO, 0,
574 "Detected device %04X on subchannel %04X" 574 "Detected device %04X on subchannel %04X"
575 " - PIM = %02X, PAM = %02X, POM = %02X\n", 575 " - PIM = %02X, PAM = %02X, POM = %02X\n",
576 sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim, 576 sch->schib.pmcw.dev, sch->schid.sch_no, sch->schib.pmcw.pim,
577 sch->schib.pmcw.pam, sch->schib.pmcw.pom); 577 sch->schib.pmcw.pam, sch->schib.pmcw.pom);
578 578
579 /* 579 /*
@@ -632,7 +632,7 @@ do_IRQ (struct pt_regs *regs)
632 if (sch) 632 if (sch)
633 spin_lock(&sch->lock); 633 spin_lock(&sch->lock);
634 /* Store interrupt response block to lowcore. */ 634 /* Store interrupt response block to lowcore. */
635 if (tsch (tpi_info->irq, irb) == 0 && sch) { 635 if (tsch (tpi_info->schid, irb) == 0 && sch) {
636 /* Keep subchannel information word up to date. */ 636 /* Keep subchannel information word up to date. */
637 memcpy (&sch->schib.scsw, &irb->scsw, 637 memcpy (&sch->schib.scsw, &irb->scsw,
638 sizeof (irb->scsw)); 638 sizeof (irb->scsw));
@@ -693,26 +693,28 @@ wait_cons_dev (void)
693static int 693static int
694cio_console_irq(void) 694cio_console_irq(void)
695{ 695{
696 int irq; 696 struct subchannel_id schid;
697 697
698 init_subchannel_id(&schid);
698 if (console_irq != -1) { 699 if (console_irq != -1) {
699 /* VM provided us with the irq number of the console. */ 700 /* VM provided us with the irq number of the console. */
700 if (stsch(console_irq, &console_subchannel.schib) != 0 || 701 schid.sch_no = console_irq;
702 if (stsch(schid, &console_subchannel.schib) != 0 ||
701 !console_subchannel.schib.pmcw.dnv) 703 !console_subchannel.schib.pmcw.dnv)
702 return -1; 704 return -1;
703 console_devno = console_subchannel.schib.pmcw.dev; 705 console_devno = console_subchannel.schib.pmcw.dev;
704 } else if (console_devno != -1) { 706 } else if (console_devno != -1) {
705 /* At least the console device number is known. */ 707 /* At least the console device number is known. */
706 for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { 708 do {
707 if (stsch(irq, &console_subchannel.schib) != 0) 709 if (stsch(schid, &console_subchannel.schib) != 0)
708 break; 710 break;
709 if (console_subchannel.schib.pmcw.dnv && 711 if (console_subchannel.schib.pmcw.dnv &&
710 console_subchannel.schib.pmcw.dev == 712 console_subchannel.schib.pmcw.dev ==
711 console_devno) { 713 console_devno) {
712 console_irq = irq; 714 console_irq = schid.sch_no;
713 break; 715 break;
714 } 716 }
715 } 717 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
716 if (console_irq == -1) 718 if (console_irq == -1)
717 return -1; 719 return -1;
718 } else { 720 } else {
@@ -729,6 +731,7 @@ struct subchannel *
729cio_probe_console(void) 731cio_probe_console(void)
730{ 732{
731 int irq, ret; 733 int irq, ret;
734 struct subchannel_id schid;
732 735
733 if (xchg(&console_subchannel_in_use, 1) != 0) 736 if (xchg(&console_subchannel_in_use, 1) != 0)
734 return ERR_PTR(-EBUSY); 737 return ERR_PTR(-EBUSY);
@@ -738,7 +741,9 @@ cio_probe_console(void)
738 return ERR_PTR(-ENODEV); 741 return ERR_PTR(-ENODEV);
739 } 742 }
740 memset(&console_subchannel, 0, sizeof(struct subchannel)); 743 memset(&console_subchannel, 0, sizeof(struct subchannel));
741 ret = cio_validate_subchannel(&console_subchannel, irq); 744 init_subchannel_id(&schid);
745 schid.sch_no = irq;
746 ret = cio_validate_subchannel(&console_subchannel, schid);
742 if (ret) { 747 if (ret) {
743 console_subchannel_in_use = 0; 748 console_subchannel_in_use = 0;
744 return ERR_PTR(-ENODEV); 749 return ERR_PTR(-ENODEV);
@@ -770,11 +775,11 @@ cio_release_console(void)
770 775
771/* Bah... hack to catch console special sausages. */ 776/* Bah... hack to catch console special sausages. */
772int 777int
773cio_is_console(int irq) 778cio_is_console(struct subchannel_id schid)
774{ 779{
775 if (!console_subchannel_in_use) 780 if (!console_subchannel_in_use)
776 return 0; 781 return 0;
777 return (irq == console_subchannel.irq); 782 return schid_equal(&schid, &console_subchannel.schid);
778} 783}
779 784
780struct subchannel * 785struct subchannel *
@@ -787,7 +792,7 @@ cio_get_console_subchannel(void)
787 792
788#endif 793#endif
789static inline int 794static inline int
790__disable_subchannel_easy(unsigned int schid, struct schib *schib) 795__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
791{ 796{
792 int retry, cc; 797 int retry, cc;
793 798
@@ -805,7 +810,7 @@ __disable_subchannel_easy(unsigned int schid, struct schib *schib)
805} 810}
806 811
807static inline int 812static inline int
808__clear_subchannel_easy(unsigned int schid) 813__clear_subchannel_easy(struct subchannel_id schid)
809{ 814{
810 int retry; 815 int retry;
811 816
@@ -815,8 +820,8 @@ __clear_subchannel_easy(unsigned int schid)
815 struct tpi_info ti; 820 struct tpi_info ti;
816 821
817 if (tpi(&ti)) { 822 if (tpi(&ti)) {
818 tsch(ti.irq, (struct irb *)__LC_IRB); 823 tsch(ti.schid, (struct irb *)__LC_IRB);
819 if (ti.irq == schid) 824 if (schid_equal(&ti.schid, &schid))
820 return 0; 825 return 0;
821 } 826 }
822 udelay(100); 827 udelay(100);
@@ -830,10 +835,11 @@ extern void do_reipl(unsigned long devno);
830void 835void
831clear_all_subchannels(void) 836clear_all_subchannels(void)
832{ 837{
833 unsigned int schid; 838 struct subchannel_id schid;
834 839
835 local_irq_disable(); 840 local_irq_disable();
836 for (schid=0;schid<=highest_subchannel;schid++) { 841 init_subchannel_id(&schid);
842 do {
837 struct schib schib; 843 struct schib schib;
838 if (stsch(schid, &schib)) 844 if (stsch(schid, &schib))
839 break; /* break out of the loop */ 845 break; /* break out of the loop */
@@ -849,7 +855,7 @@ clear_all_subchannels(void)
849 stsch(schid, &schib); 855 stsch(schid, &schib);
850 __disable_subchannel_easy(schid, &schib); 856 __disable_subchannel_easy(schid, &schib);
851 } 857 }
852 } 858 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
853} 859}
854 860
855/* Make sure all subchannels are quiet before we re-ipl an lpar. */ 861/* Make sure all subchannels are quiet before we re-ipl an lpar. */