Commit 3b1e2468 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: common i/o layer.

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

Common i/o layer changes:
 - Quiesce active subchannels for lpar reipl.
 - Delete timer after reception of interrupt for kill on timeout.
 - Cleanup some comments in qdio.
parent a23d3734
......@@ -254,13 +254,13 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
/*
* Reboot, halt and power_off routines for non SMP.
*/
extern void do_reipl(unsigned long devno);
extern void reipl(unsigned long devno);
static void do_machine_restart_nonsmp(char * __unused)
{
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0);
else
do_reipl (0x10000 | S390_lowcore.ipl_device);
reipl (0x10000 | S390_lowcore.ipl_device);
}
static void do_machine_halt_nonsmp(void)
......
......@@ -64,7 +64,7 @@ EXPORT_SYMBOL(cpu_online_map);
extern char vmhalt_cmd[];
extern char vmpoff_cmd[];
extern void do_reipl(unsigned long devno);
extern void reipl(unsigned long devno);
static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig);
......@@ -278,7 +278,7 @@ static void do_machine_restart(void * __unused)
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0);
else
do_reipl (0x10000 | S390_lowcore.ipl_device);
reipl (0x10000 | S390_lowcore.ipl_device);
}
signal_processor(smp_processor_id(), sigp_stop);
}
......
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
* $Revision: 1.117 $
* $Revision: 1.121 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -783,3 +783,68 @@ cio_get_console_subchannel(void)
}
#endif
static inline int
__disable_subchannel_easy(unsigned int schid, struct schib *schib)
{
int retry, cc;
cc = 0;
for (retry=0;retry<3;retry++) {
schib->pmcw.ena = 0;
cc = msch(schid, schib);
if (cc)
return (cc==3?-ENODEV:-EBUSY);
stsch(schid, schib);
if (!schib->pmcw.ena)
return 0;
}
return -EBUSY; /* uhm... */
}
static inline int
__clear_subchannel_easy(unsigned int schid)
{
int retry;
if (csch(schid))
return -ENODEV;
for (retry=0;retry<20;retry++) {
struct tpi_info ti;
if (tpi(&ti)) {
tsch(schid, (struct irb *)__LC_IRB);
return 0;
}
udelay(100);
}
return -EBUSY;
}
extern void do_reipl(unsigned long devno);
/* Make sure all subchannels are quiet before we re-ipl an lpar. */
void
reipl(unsigned long devno)
{
unsigned int schid;
local_irq_disable();
for (schid=0;schid<=highest_subchannel;schid++) {
struct schib schib;
if (stsch(schid, &schib))
goto out;
if (!schib.pmcw.ena)
continue;
switch(__disable_subchannel_easy(schid, &schib)) {
case 0:
case -ENODEV:
break;
default: /* -EBUSY */
if (__clear_subchannel_easy(schid))
break; /* give up... */
stsch(schid, &schib);
__disable_subchannel_easy(schid, &schib);
}
}
out:
do_reipl(devno);
}
......@@ -440,12 +440,14 @@ ccw_device_nopath_notify(void *data)
if (!ret) {
if (get_device(&sch->dev)) {
/* Driver doesn't want to keep device. */
cio_disable_subchannel(sch);
device_unregister(&sch->dev);
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
put_device(&sch->dev);
}
} else {
cio_disable_subchannel(sch);
ccw_device_set_timeout(cdev, 0);
cdev->private->state = DEV_STATE_DISCONNECTED;
wake_up(&cdev->private->wait_q);
......@@ -787,6 +789,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
ccw_device_set_timeout(cdev, 0);
/* OK, i/o is dead now. Call interrupt handler. */
cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler)
......
......@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
#define VERSION_QDIO_C "$Revision: 1.79 $"
#define VERSION_QDIO_C "$Revision: 1.80 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
......@@ -461,12 +461,12 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q)
switch(slsb[f_mod_no]) {
/* the hydra has not fetched the output yet */
/* the adapter has not fetched the output yet */
case SLSB_CU_OUTPUT_PRIMED:
QDIO_DBF_TEXT5(0,trace,"outpprim");
break;
/* the hydra got it */
/* the adapter got it */
case SLSB_P_OUTPUT_EMPTY:
atomic_dec(&q->number_of_buffers_used);
f++;
......@@ -919,7 +919,7 @@ qdio_is_inbound_q_done(struct qdio_q *q)
no_used=atomic_read(&q->number_of_buffers_used);
/*
* we need that one for synchronization with Hydra, as Hydra
* we need that one for synchronization with the adapter, as it
* does a kind of PCI avoidance
*/
SYNC_MEMORY;
......@@ -1069,7 +1069,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
}
/*
* maybe we have to do work on our outbound queues... at least
* we have to check Hydra outbound-int-capable thinint-capable
* we have to check the outbound-int-capable thinint-capable
* queues
*/
if (q->hydra_gives_outbound_pcis) {
......@@ -2027,7 +2027,7 @@ tiqdio_check_chsc_availability(void)
goto exit;
}
/* Check for hydra thin interrupts (bit 67). */
/* Check for OSA/FCP thin interrupts (bit 67). */
hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
== 0x10000000);
sprintf(dbf_text,"hydrati%1x", hydra_thinints);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment