X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fcio%2Fcio.c;h=b6e4d3402b36345b219d62618010ed382e47fd59;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=a16f061fdc693885010e0607f6a815be6bb641c0;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index a16f061fd..b6e4d3402 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.123 $ + * $Revision: 1.130 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -17,8 +17,8 @@ #include #include #include +#include -#include #include #include #include @@ -141,6 +141,7 @@ cio_tpi(void) sch = (struct subchannel *)(unsigned long)tpi_info->intparm; if (!sch) return 1; + local_bh_disable(); irq_enter (); spin_lock(&sch->lock); memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw)); @@ -148,6 +149,7 @@ cio_tpi(void) sch->driver->irq(&sch->dev); spin_unlock(&sch->lock); irq_exit (); + __local_bh_enable(); return 1; } @@ -173,9 +175,10 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) } int -cio_start (struct subchannel *sch, /* subchannel structure */ - struct ccw1 * cpa, /* logical channel prog addr */ - __u8 lpm) /* logical path mask */ +cio_start_key (struct subchannel *sch, /* subchannel structure */ + struct ccw1 * cpa, /* logical channel prog addr */ + __u8 lpm, /* logical path mask */ + __u8 key) /* storage key */ { char dbf_txt[15]; int ccode; @@ -198,12 +201,12 @@ cio_start (struct subchannel *sch, /* subchannel structure */ sch->orb.c64 = 1; sch->orb.i2k = 0; #endif + sch->orb.key = key >> 4; + /* issue "Start Subchannel" */ sch->orb.cpa = (__u32) __pa (cpa); - - /* - * Issue "Start subchannel" and process condition code - */ ccode = ssch (sch->irq, &sch->orb); + + /* process condition code */ sprintf (dbf_txt, "ccode:%d", ccode); CIO_TRACE_EVENT (4, dbf_txt); @@ -222,6 +225,12 @@ cio_start (struct subchannel *sch, /* subchannel structure */ } } +int +cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm) +{ + return cio_start_key(sch, cpa, lpm, default_storage_key); +} + /* * resume suspended I/O operation */ @@ -409,10 +418,10 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc) if (ccode) return -ENODEV; - sch->schib.pmcw.ena = 1; - sch->schib.pmcw.isc = isc; - sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; for (retry = 5, ret = 0; retry > 0; retry--) { + sch->schib.pmcw.ena = 1; + sch->schib.pmcw.isc = isc; + sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; ret = cio_modify(sch); if (ret == -ENODEV) break; @@ -463,9 +472,8 @@ cio_disable_subchannel (struct subchannel *sch) */ return -EBUSY; - - sch->schib.pmcw.ena = 0; for (retry = 5, ret = 0; retry > 0; retry--) { + sch->schib.pmcw.ena = 0; ret = cio_modify(sch); if (ret == -ENODEV) break; @@ -688,15 +696,15 @@ cio_console_irq(void) if (stsch(console_irq, &console_subchannel.schib) != 0 || !console_subchannel.schib.pmcw.dnv) return -1; - console_device = console_subchannel.schib.pmcw.dev; - } else if (console_device != -1) { + console_devno = console_subchannel.schib.pmcw.dev; + } else if (console_devno != -1) { /* At least the console device number is known. */ for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { if (stsch(irq, &console_subchannel.schib) != 0) break; if (console_subchannel.schib.pmcw.dnv && console_subchannel.schib.pmcw.dev == - console_device) { + console_devno) { console_irq = irq; break; } @@ -812,9 +820,10 @@ __clear_subchannel_easy(unsigned int schid) } extern void do_reipl(unsigned long devno); -/* Make sure all subchannels are quiet before we re-ipl an lpar. */ + +/* Clear all subchannels. */ void -reipl(unsigned long devno) +clear_all_subchannels(void) { unsigned int schid; @@ -822,7 +831,7 @@ reipl(unsigned long devno) for (schid=0;schid<=highest_subchannel;schid++) { struct schib schib; if (stsch(schid, &schib)) - goto out; + break; /* break out of the loop */ if (!schib.pmcw.ena) continue; switch(__disable_subchannel_easy(schid, &schib)) { @@ -831,11 +840,17 @@ reipl(unsigned long devno) break; default: /* -EBUSY */ if (__clear_subchannel_easy(schid)) - break; /* give up... */ + break; /* give up... jump out of switch */ stsch(schid, &schib); __disable_subchannel_easy(schid, &schib); } } -out: +} + +/* Make sure all subchannels are quiet before we re-ipl an lpar. */ +void +reipl(unsigned long devno) +{ + clear_all_subchannels(); do_reipl(devno); }