aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c245
1 files changed, 141 insertions, 104 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 3db2c386546f..8a8df7552969 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -9,6 +9,9 @@
9 * Martin Schwidefsky (schwidefsky@de.ibm.com) 9 * Martin Schwidefsky (schwidefsky@de.ibm.com)
10 */ 10 */
11 11
12#define KMSG_COMPONENT "cio"
13#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
14
12#include <linux/module.h> 15#include <linux/module.h>
13#include <linux/init.h> 16#include <linux/init.h>
14#include <linux/slab.h> 17#include <linux/slab.h>
@@ -104,44 +107,6 @@ cio_get_options (struct subchannel *sch)
104 return flags; 107 return flags;
105} 108}
106 109
107/*
108 * Use tpi to get a pending interrupt, call the interrupt handler and
109 * return a pointer to the subchannel structure.
110 */
111static int
112cio_tpi(void)
113{
114 struct tpi_info *tpi_info;
115 struct subchannel *sch;
116 struct irb *irb;
117 int irq_context;
118
119 tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
120 if (tpi (NULL) != 1)
121 return 0;
122 irb = (struct irb *) __LC_IRB;
123 /* Store interrupt response block to lowcore. */
124 if (tsch (tpi_info->schid, irb) != 0)
125 /* Not status pending or not operational. */
126 return 1;
127 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
128 if (!sch)
129 return 1;
130 irq_context = in_interrupt();
131 if (!irq_context)
132 local_bh_disable();
133 irq_enter ();
134 spin_lock(sch->lock);
135 memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
136 if (sch->driver && sch->driver->irq)
137 sch->driver->irq(sch);
138 spin_unlock(sch->lock);
139 irq_exit ();
140 if (!irq_context)
141 _local_bh_enable();
142 return 1;
143}
144
145static int 110static int
146cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) 111cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
147{ 112{
@@ -152,11 +117,13 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
152 else 117 else
153 sch->lpm = 0; 118 sch->lpm = 0;
154 119
155 stsch (sch->schid, &sch->schib);
156
157 CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " 120 CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
158 "subchannel 0.%x.%04x!\n", sch->schid.ssid, 121 "subchannel 0.%x.%04x!\n", sch->schid.ssid,
159 sch->schid.sch_no); 122 sch->schid.sch_no);
123
124 if (cio_update_schib(sch))
125 return -ENODEV;
126
160 sprintf(dbf_text, "no%s", dev_name(&sch->dev)); 127 sprintf(dbf_text, "no%s", dev_name(&sch->dev));
161 CIO_TRACE_EVENT(0, dbf_text); 128 CIO_TRACE_EVENT(0, dbf_text);
162 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); 129 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -354,7 +321,8 @@ cio_cancel (struct subchannel *sch)
354 switch (ccode) { 321 switch (ccode) {
355 case 0: /* success */ 322 case 0: /* success */
356 /* Update information in scsw. */ 323 /* Update information in scsw. */
357 stsch (sch->schid, &sch->schib); 324 if (cio_update_schib(sch))
325 return -ENODEV;
358 return 0; 326 return 0;
359 case 1: /* status pending */ 327 case 1: /* status pending */
360 return -EBUSY; 328 return -EBUSY;
@@ -365,30 +333,70 @@ cio_cancel (struct subchannel *sch)
365 } 333 }
366} 334}
367 335
336
337static void cio_apply_config(struct subchannel *sch, struct schib *schib)
338{
339 schib->pmcw.intparm = sch->config.intparm;
340 schib->pmcw.mbi = sch->config.mbi;
341 schib->pmcw.isc = sch->config.isc;
342 schib->pmcw.ena = sch->config.ena;
343 schib->pmcw.mme = sch->config.mme;
344 schib->pmcw.mp = sch->config.mp;
345 schib->pmcw.csense = sch->config.csense;
346 schib->pmcw.mbfc = sch->config.mbfc;
347 if (sch->config.mbfc)
348 schib->mba = sch->config.mba;
349}
350
351static int cio_check_config(struct subchannel *sch, struct schib *schib)
352{
353 return (schib->pmcw.intparm == sch->config.intparm) &&
354 (schib->pmcw.mbi == sch->config.mbi) &&
355 (schib->pmcw.isc == sch->config.isc) &&
356 (schib->pmcw.ena == sch->config.ena) &&
357 (schib->pmcw.mme == sch->config.mme) &&
358 (schib->pmcw.mp == sch->config.mp) &&
359 (schib->pmcw.csense == sch->config.csense) &&
360 (schib->pmcw.mbfc == sch->config.mbfc) &&
361 (!sch->config.mbfc || (schib->mba == sch->config.mba));
362}
363
368/* 364/*
369 * Function: cio_modify 365 * cio_commit_config - apply configuration to the subchannel
370 * Issues a "Modify Subchannel" on the specified subchannel
371 */ 366 */
372int 367int cio_commit_config(struct subchannel *sch)
373cio_modify (struct subchannel *sch)
374{ 368{
375 int ccode, retry, ret; 369 struct schib schib;
370 int ccode, retry, ret = 0;
371
372 if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
373 return -ENODEV;
376 374
377 ret = 0;
378 for (retry = 0; retry < 5; retry++) { 375 for (retry = 0; retry < 5; retry++) {
379 ccode = msch_err (sch->schid, &sch->schib); 376 /* copy desired changes to local schib */
380 if (ccode < 0) /* -EIO if msch gets a program check. */ 377 cio_apply_config(sch, &schib);
378 ccode = msch_err(sch->schid, &schib);
379 if (ccode < 0) /* -EIO if msch gets a program check. */
381 return ccode; 380 return ccode;
382 switch (ccode) { 381 switch (ccode) {
383 case 0: /* successfull */ 382 case 0: /* successfull */
384 return 0; 383 if (stsch(sch->schid, &schib) ||
385 case 1: /* status pending */ 384 !css_sch_is_valid(&schib))
385 return -ENODEV;
386 if (cio_check_config(sch, &schib)) {
387 /* commit changes from local schib */
388 memcpy(&sch->schib, &schib, sizeof(schib));
389 return 0;
390 }
391 ret = -EAGAIN;
392 break;
393 case 1: /* status pending */
386 return -EBUSY; 394 return -EBUSY;
387 case 2: /* busy */ 395 case 2: /* busy */
388 udelay (100); /* allow for recovery */ 396 udelay(100); /* allow for recovery */
389 ret = -EBUSY; 397 ret = -EBUSY;
390 break; 398 break;
391 case 3: /* not operational */ 399 case 3: /* not operational */
392 return -ENODEV; 400 return -ENODEV;
393 } 401 }
394 } 402 }
@@ -396,6 +404,23 @@ cio_modify (struct subchannel *sch)
396} 404}
397 405
398/** 406/**
407 * cio_update_schib - Perform stsch and update schib if subchannel is valid.
408 * @sch: subchannel on which to perform stsch
409 * Return zero on success, -ENODEV otherwise.
410 */
411int cio_update_schib(struct subchannel *sch)
412{
413 struct schib schib;
414
415 if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
416 return -ENODEV;
417
418 memcpy(&sch->schib, &schib, sizeof(schib));
419 return 0;
420}
421EXPORT_SYMBOL_GPL(cio_update_schib);
422
423/**
399 * cio_enable_subchannel - enable a subchannel. 424 * cio_enable_subchannel - enable a subchannel.
400 * @sch: subchannel to be enabled 425 * @sch: subchannel to be enabled
401 * @intparm: interruption parameter to set 426 * @intparm: interruption parameter to set
@@ -403,7 +428,6 @@ cio_modify (struct subchannel *sch)
403int cio_enable_subchannel(struct subchannel *sch, u32 intparm) 428int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
404{ 429{
405 char dbf_txt[15]; 430 char dbf_txt[15];
406 int ccode;
407 int retry; 431 int retry;
408 int ret; 432 int ret;
409 433
@@ -412,33 +436,27 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
412 436
413 if (sch_is_pseudo_sch(sch)) 437 if (sch_is_pseudo_sch(sch))
414 return -EINVAL; 438 return -EINVAL;
415 ccode = stsch (sch->schid, &sch->schib); 439 if (cio_update_schib(sch))
416 if (ccode)
417 return -ENODEV; 440 return -ENODEV;
418 441
419 for (retry = 5, ret = 0; retry > 0; retry--) { 442 sch->config.ena = 1;
420 sch->schib.pmcw.ena = 1; 443 sch->config.isc = sch->isc;
421 sch->schib.pmcw.isc = sch->isc; 444 sch->config.intparm = intparm;
422 sch->schib.pmcw.intparm = intparm; 445
423 ret = cio_modify(sch); 446 for (retry = 0; retry < 3; retry++) {
424 if (ret == -ENODEV) 447 ret = cio_commit_config(sch);
425 break; 448 if (ret == -EIO) {
426 if (ret == -EIO)
427 /* 449 /*
428 * Got a program check in cio_modify. Try without 450 * Got a program check in msch. Try without
429 * the concurrent sense bit the next time. 451 * the concurrent sense bit the next time.
430 */ 452 */
431 sch->schib.pmcw.csense = 0; 453 sch->config.csense = 0;
432 if (ret == 0) { 454 } else if (ret == -EBUSY) {
433 stsch (sch->schid, &sch->schib);
434 if (sch->schib.pmcw.ena)
435 break;
436 }
437 if (ret == -EBUSY) {
438 struct irb irb; 455 struct irb irb;
439 if (tsch(sch->schid, &irb) != 0) 456 if (tsch(sch->schid, &irb) != 0)
440 break; 457 break;
441 } 458 } else
459 break;
442 } 460 }
443 sprintf (dbf_txt, "ret:%d", ret); 461 sprintf (dbf_txt, "ret:%d", ret);
444 CIO_TRACE_EVENT (2, dbf_txt); 462 CIO_TRACE_EVENT (2, dbf_txt);
@@ -453,8 +471,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
453int cio_disable_subchannel(struct subchannel *sch) 471int cio_disable_subchannel(struct subchannel *sch)
454{ 472{
455 char dbf_txt[15]; 473 char dbf_txt[15];
456 int ccode;
457 int retry;
458 int ret; 474 int ret;
459 475
460 CIO_TRACE_EVENT (2, "dissch"); 476 CIO_TRACE_EVENT (2, "dissch");
@@ -462,8 +478,7 @@ int cio_disable_subchannel(struct subchannel *sch)
462 478
463 if (sch_is_pseudo_sch(sch)) 479 if (sch_is_pseudo_sch(sch))
464 return 0; 480 return 0;
465 ccode = stsch (sch->schid, &sch->schib); 481 if (cio_update_schib(sch))
466 if (ccode == 3) /* Not operational. */
467 return -ENODEV; 482 return -ENODEV;
468 483
469 if (scsw_actl(&sch->schib.scsw) != 0) 484 if (scsw_actl(&sch->schib.scsw) != 0)
@@ -473,24 +488,9 @@ int cio_disable_subchannel(struct subchannel *sch)
473 */ 488 */
474 return -EBUSY; 489 return -EBUSY;
475 490
476 for (retry = 5, ret = 0; retry > 0; retry--) { 491 sch->config.ena = 0;
477 sch->schib.pmcw.ena = 0; 492 ret = cio_commit_config(sch);
478 ret = cio_modify(sch); 493
479 if (ret == -ENODEV)
480 break;
481 if (ret == -EBUSY)
482 /*
483 * The subchannel is busy or status pending.
484 * We'll disable when the next interrupt was delivered
485 * via the state machine.
486 */
487 break;
488 if (ret == 0) {
489 stsch (sch->schid, &sch->schib);
490 if (!sch->schib.pmcw.ena)
491 break;
492 }
493 }
494 sprintf (dbf_txt, "ret:%d", ret); 494 sprintf (dbf_txt, "ret:%d", ret);
495 CIO_TRACE_EVENT (2, dbf_txt); 495 CIO_TRACE_EVENT (2, dbf_txt);
496 return ret; 496 return ret;
@@ -687,6 +687,43 @@ static char console_sch_name[10] = "0.x.xxxx";
687static struct io_subchannel_private console_priv; 687static struct io_subchannel_private console_priv;
688static int console_subchannel_in_use; 688static int console_subchannel_in_use;
689 689
690/*
691 * Use tpi to get a pending interrupt, call the interrupt handler and
692 * return a pointer to the subchannel structure.
693 */
694static int cio_tpi(void)
695{
696 struct tpi_info *tpi_info;
697 struct subchannel *sch;
698 struct irb *irb;
699 int irq_context;
700
701 tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
702 if (tpi(NULL) != 1)
703 return 0;
704 irb = (struct irb *) __LC_IRB;
705 /* Store interrupt response block to lowcore. */
706 if (tsch(tpi_info->schid, irb) != 0)
707 /* Not status pending or not operational. */
708 return 1;
709 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
710 if (!sch)
711 return 1;
712 irq_context = in_interrupt();
713 if (!irq_context)
714 local_bh_disable();
715 irq_enter();
716 spin_lock(sch->lock);
717 memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
718 if (sch->driver && sch->driver->irq)
719 sch->driver->irq(sch);
720 spin_unlock(sch->lock);
721 irq_exit();
722 if (!irq_context)
723 _local_bh_enable();
724 return 1;
725}
726
690void *cio_get_console_priv(void) 727void *cio_get_console_priv(void)
691{ 728{
692 return &console_priv; 729 return &console_priv;
@@ -780,7 +817,7 @@ cio_probe_console(void)
780 sch_no = cio_get_console_sch_no(); 817 sch_no = cio_get_console_sch_no();
781 if (sch_no == -1) { 818 if (sch_no == -1) {
782 console_subchannel_in_use = 0; 819 console_subchannel_in_use = 0;
783 printk(KERN_WARNING "cio: No ccw console found!\n"); 820 pr_warning("No CCW console was found\n");
784 return ERR_PTR(-ENODEV); 821 return ERR_PTR(-ENODEV);
785 } 822 }
786 memset(&console_subchannel, 0, sizeof(struct subchannel)); 823 memset(&console_subchannel, 0, sizeof(struct subchannel));
@@ -796,10 +833,9 @@ cio_probe_console(void)
796 * enable console I/O-interrupt subclass 833 * enable console I/O-interrupt subclass
797 */ 834 */
798 isc_register(CONSOLE_ISC); 835 isc_register(CONSOLE_ISC);
799 console_subchannel.schib.pmcw.isc = CONSOLE_ISC; 836 console_subchannel.config.isc = CONSOLE_ISC;
800 console_subchannel.schib.pmcw.intparm = 837 console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel;
801 (u32)(addr_t)&console_subchannel; 838 ret = cio_commit_config(&console_subchannel);
802 ret = cio_modify(&console_subchannel);
803 if (ret) { 839 if (ret) {
804 isc_unregister(CONSOLE_ISC); 840 isc_unregister(CONSOLE_ISC);
805 console_subchannel_in_use = 0; 841 console_subchannel_in_use = 0;
@@ -811,8 +847,8 @@ cio_probe_console(void)
811void 847void
812cio_release_console(void) 848cio_release_console(void)
813{ 849{
814 console_subchannel.schib.pmcw.intparm = 0; 850 console_subchannel.config.intparm = 0;
815 cio_modify(&console_subchannel); 851 cio_commit_config(&console_subchannel);
816 isc_unregister(CONSOLE_ISC); 852 isc_unregister(CONSOLE_ISC);
817 console_subchannel_in_use = 0; 853 console_subchannel_in_use = 0;
818} 854}
@@ -852,7 +888,8 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
852 cc = msch(schid, schib); 888 cc = msch(schid, schib);
853 if (cc) 889 if (cc)
854 return (cc==3?-ENODEV:-EBUSY); 890 return (cc==3?-ENODEV:-EBUSY);
855 stsch(schid, schib); 891 if (stsch(schid, schib) || !css_sch_is_valid(schib))
892 return -ENODEV;
856 if (!schib->pmcw.ena) 893 if (!schib->pmcw.ena)
857 return 0; 894 return 0;
858 } 895 }