#include <asm/reset.h>
#include <asm/ipl.h>
#include <asm/chpid.h>
-#include "airq.h"
+#include <asm/airq.h>
+#include <asm/cpu.h>
#include "cio.h"
#include "css.h"
#include "chsc.h"
#include "ioasm.h"
+#include "io_sch.h"
#include "blacklist.h"
#include "cio_debug.h"
#include "chp.h"
*/
static int __init cio_debug_init(void)
{
- cio_debug_msg_id = debug_register("cio_msg", 16, 4, 16 * sizeof(long));
+ cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long));
if (!cio_debug_msg_id)
goto out_unregister;
debug_register_view(cio_debug_msg_id, &debug_sprintf_view);
debug_set_level(cio_debug_msg_id, 2);
- cio_debug_trace_id = debug_register("cio_trace", 16, 4, 16);
+ cio_debug_trace_id = debug_register("cio_trace", 16, 1, 16);
if (!cio_debug_trace_id)
goto out_unregister;
debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view);
debug_set_level(cio_debug_trace_id, 2);
- cio_debug_crw_id = debug_register("cio_crw", 16, 4, 16 * sizeof(long));
+ cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long));
if (!cio_debug_crw_id)
goto out_unregister;
debug_register_view(cio_debug_crw_id, &debug_sprintf_view);
{
char dbf_txt[15];
int ccode;
+ struct orb *orb;
- CIO_TRACE_EVENT (4, "stIO");
- CIO_TRACE_EVENT (4, sch->dev.bus_id);
+ CIO_TRACE_EVENT(4, "stIO");
+ CIO_TRACE_EVENT(4, sch->dev.bus_id);
+ orb = &to_io_private(sch)->orb;
/* sch is always under 2G. */
- sch->orb.intparm = (__u32)(unsigned long)sch;
- sch->orb.fmt = 1;
+ orb->intparm = (u32)(addr_t)sch;
+ orb->fmt = 1;
- sch->orb.pfch = sch->options.prefetch == 0;
- sch->orb.spnd = sch->options.suspend;
- sch->orb.ssic = sch->options.suspend && sch->options.inter;
- sch->orb.lpm = (lpm != 0) ? lpm : sch->lpm;
+ orb->pfch = sch->options.prefetch == 0;
+ orb->spnd = sch->options.suspend;
+ orb->ssic = sch->options.suspend && sch->options.inter;
+ orb->lpm = (lpm != 0) ? lpm : sch->lpm;
#ifdef CONFIG_64BIT
/*
* for 64 bit we always support 64 bit IDAWs with 4k page size only
*/
- sch->orb.c64 = 1;
- sch->orb.i2k = 0;
+ orb->c64 = 1;
+ orb->i2k = 0;
#endif
- sch->orb.key = key >> 4;
+ orb->key = key >> 4;
/* issue "Start Subchannel" */
- sch->orb.cpa = (__u32) __pa (cpa);
- ccode = ssch (sch->schid, &sch->orb);
+ orb->cpa = (__u32) __pa(cpa);
+ ccode = ssch(sch->schid, orb);
/* process condition code */
- sprintf (dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT (4, dbf_txt);
+ sprintf(dbf_txt, "ccode:%d", ccode);
+ CIO_TRACE_EVENT(4, dbf_txt);
switch (ccode) {
case 0:
/*
* Enable subchannel.
*/
-int
-cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
+int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
{
char dbf_txt[15];
int ccode;
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;
+ sch->schib.pmcw.isc = sch->isc;
+ sch->schib.pmcw.intparm = intparm;
ret = cio_modify(sch);
if (ret == -ENODEV)
break;
}
/* Initialization for io subchannels. */
- if (!sch->schib.pmcw.dnv) {
- /* io subchannel but device number is invalid. */
+ if (!css_sch_is_valid(&sch->schib)) {
err = -ENODEV;
goto out;
}
+
/* Devno is valid. */
if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
/*
else
sch->opm = chp_get_sch_opm(sch);
sch->lpm = sch->schib.pmcw.pam & sch->opm;
+ sch->isc = 3;
CIO_DEBUG(KERN_INFO, 0,
"Detected device %04x on subchannel 0.%x.%04X"
/*
* We now have to initially ...
- * ... set "interruption subclass"
* ... enable "concurrent sense"
* ... enable "multipath mode" if more than one
* CHPID is available. This is done regardless
* whether multiple paths are available for us.
*/
- sch->schib.pmcw.isc = 3; /* could be smth. else */
sch->schib.pmcw.csense = 1; /* concurrent sense */
sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0)
old_regs = set_irq_regs(regs);
irq_enter();
- asm volatile ("mc 0,0");
- if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
- /**
- * Make sure that the i/o interrupt did not "overtake"
- * the last HZ timer interrupt.
- */
- account_ticks(S390_lowcore.int_clock);
+ s390_idle_check();
+ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+ /* Serve timer interrupts first. */
+ clock_comparator_work();
/*
* Get interrupt information from lowcore
*/
continue;
}
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
- if (sch)
- spin_lock(sch->lock);
+ if (!sch) {
+ /* Clear pending interrupt condition. */
+ tsch(tpi_info->schid, irb);
+ continue;
+ }
+ spin_lock(sch->lock);
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->schid, irb) == 0 && sch) {
+ if (tsch(tpi_info->schid, irb) == 0) {
/* Keep subchannel information word up to date. */
memcpy (&sch->schib.scsw, &irb->scsw,
sizeof (irb->scsw));
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
}
- if (sch)
- spin_unlock(sch->lock);
+ spin_unlock(sch->lock);
/*
* Are more interrupts pending?
* If so, the tpi instruction will update the lowcore
#ifdef CONFIG_CCW_CONSOLE
static struct subchannel console_subchannel;
+static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
+void *cio_get_console_priv(void)
+{
+ return &console_priv;
+}
+
/*
* busy wait for the next interrupt on the console
*/
-void
-wait_cons_dev (void)
+void wait_cons_dev(void)
+ __releases(console_subchannel.lock)
+ __acquires(console_subchannel.lock)
{
unsigned long cr6 __attribute__ ((aligned (8)));
unsigned long save_cr6 __attribute__ ((aligned (8)));
{
if (stsch_err(schid, &console_subchannel.schib) != 0)
return -ENXIO;
- if (console_subchannel.schib.pmcw.dnv &&
- console_subchannel.schib.pmcw.dev ==
- console_devno) {
+ if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
+ console_subchannel.schib.pmcw.dnv &&
+ (console_subchannel.schib.pmcw.dev == console_devno)) {
console_irq = schid.sch_no;
return 1; /* found */
}
/* VM provided us with the irq number of the console. */
schid.sch_no = console_irq;
if (stsch(schid, &console_subchannel.schib) != 0 ||
+ (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
!console_subchannel.schib.pmcw.dnv)
return -1;
console_devno = console_subchannel.schib.pmcw.dev;
* enable console I/O-interrupt subclass 7
*/
ctl_set_bit(6, 24);
+ console_subchannel.isc = 7;
console_subchannel.schib.pmcw.isc = 7;
console_subchannel.schib.pmcw.intparm =
- (__u32)(unsigned long)&console_subchannel;
+ (u32)(addr_t)&console_subchannel;
ret = cio_modify(&console_subchannel);
if (ret) {
console_subchannel_in_use = 0;
if (stsch_reset(schid, &schib))
return -ENXIO;
- if (schib.pmcw.dnv &&
+ if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
(schib.pmcw.dev == match_id->devid.devno) &&
(schid.ssid == match_id->devid.ssid)) {
match_id->schid = schid;
return -ENODEV;
if (stsch(schid, &schib))
return -ENODEV;
+ if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
+ return -ENODEV;
if (!schib.pmcw.dnv)
return -ENODEV;
iplinfo->devno = schib.pmcw.dev;