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; ...@@ -254,13 +254,13 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
/* /*
* Reboot, halt and power_off routines for non 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) static void do_machine_restart_nonsmp(char * __unused)
{ {
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0); cpcmd ("IPL", NULL, 0);
else else
do_reipl (0x10000 | S390_lowcore.ipl_device); reipl (0x10000 | S390_lowcore.ipl_device);
} }
static void do_machine_halt_nonsmp(void) static void do_machine_halt_nonsmp(void)
......
...@@ -64,7 +64,7 @@ EXPORT_SYMBOL(cpu_online_map); ...@@ -64,7 +64,7 @@ EXPORT_SYMBOL(cpu_online_map);
extern char vmhalt_cmd[]; extern char vmhalt_cmd[];
extern char vmpoff_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(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig);
...@@ -278,7 +278,7 @@ static void do_machine_restart(void * __unused) ...@@ -278,7 +278,7 @@ static void do_machine_restart(void * __unused)
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0); cpcmd ("IPL", NULL, 0);
else else
do_reipl (0x10000 | S390_lowcore.ipl_device); reipl (0x10000 | S390_lowcore.ipl_device);
} }
signal_processor(smp_processor_id(), sigp_stop); signal_processor(smp_processor_id(), sigp_stop);
} }
......
/* /*
* drivers/s390/cio/cio.c * drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls * 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, * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -783,3 +783,68 @@ cio_get_console_subchannel(void) ...@@ -783,3 +783,68 @@ cio_get_console_subchannel(void)
} }
#endif #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) ...@@ -440,12 +440,14 @@ ccw_device_nopath_notify(void *data)
if (!ret) { if (!ret) {
if (get_device(&sch->dev)) { if (get_device(&sch->dev)) {
/* Driver doesn't want to keep device. */ /* Driver doesn't want to keep device. */
cio_disable_subchannel(sch);
device_unregister(&sch->dev); device_unregister(&sch->dev);
sch->schib.pmcw.intparm = 0; sch->schib.pmcw.intparm = 0;
cio_modify(sch); cio_modify(sch);
put_device(&sch->dev); put_device(&sch->dev);
} }
} else { } else {
cio_disable_subchannel(sch);
ccw_device_set_timeout(cdev, 0); ccw_device_set_timeout(cdev, 0);
cdev->private->state = DEV_STATE_DISCONNECTED; cdev->private->state = DEV_STATE_DISCONNECTED;
wake_up(&cdev->private->wait_q); wake_up(&cdev->private->wait_q);
...@@ -787,6 +789,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -787,6 +789,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch; struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
ccw_device_set_timeout(cdev, 0);
/* OK, i/o is dead now. Call interrupt handler. */ /* OK, i/o is dead now. Call interrupt handler. */
cdev->private->state = DEV_STATE_ONLINE; cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler) if (cdev->handler)
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#include "ioasm.h" #include "ioasm.h"
#include "chsc.h" #include "chsc.h"
#define VERSION_QDIO_C "$Revision: 1.79 $" #define VERSION_QDIO_C "$Revision: 1.80 $"
/****************** MODULE PARAMETER VARIABLES ********************/ /****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
...@@ -461,12 +461,12 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) ...@@ -461,12 +461,12 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q)
switch(slsb[f_mod_no]) { 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: case SLSB_CU_OUTPUT_PRIMED:
QDIO_DBF_TEXT5(0,trace,"outpprim"); QDIO_DBF_TEXT5(0,trace,"outpprim");
break; break;
/* the hydra got it */ /* the adapter got it */
case SLSB_P_OUTPUT_EMPTY: case SLSB_P_OUTPUT_EMPTY:
atomic_dec(&q->number_of_buffers_used); atomic_dec(&q->number_of_buffers_used);
f++; f++;
...@@ -919,7 +919,7 @@ qdio_is_inbound_q_done(struct qdio_q *q) ...@@ -919,7 +919,7 @@ qdio_is_inbound_q_done(struct qdio_q *q)
no_used=atomic_read(&q->number_of_buffers_used); 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 * does a kind of PCI avoidance
*/ */
SYNC_MEMORY; SYNC_MEMORY;
...@@ -1069,7 +1069,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) ...@@ -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 * 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 * queues
*/ */
if (q->hydra_gives_outbound_pcis) { if (q->hydra_gives_outbound_pcis) {
...@@ -2027,7 +2027,7 @@ tiqdio_check_chsc_availability(void) ...@@ -2027,7 +2027,7 @@ tiqdio_check_chsc_availability(void)
goto exit; 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) hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
== 0x10000000); == 0x10000000);
sprintf(dbf_text,"hydrati%1x", hydra_thinints); 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