- Make ccwgroup online attribute consistent with ccw online attribute.
- Add link incident record handling to channel subsystem code.
- Do path grouping only if the device driver explicitly requests it.
- Fix multicast or broadcast flood ping hand on HiperSockets.
diffstat:
drivers/s390/block/dasd_eckd.c | 8 ++-
drivers/s390/block/dasd_fba.c | 10 +++
drivers/s390/char/tape_core.c | 6 +-
drivers/s390/cio/ccwgroup.c | 10 ++-
drivers/s390/cio/chsc.c | 54 +++++++++++++++-----
drivers/s390/cio/css.h | 2
drivers/s390/cio/device.c | 35 +++++++------
drivers/s390/cio/device.h | 2
drivers/s390/cio/device_fsm.c | 109 ++++++++++++++++++++++++-----------------
drivers/s390/cio/device_ops.c | 1
drivers/s390/cio/device_pgid.c | 6 --
drivers/s390/cio/qdio.h | 12 +++-
include/asm-s390/ccwdev.h | 2
13 files changed, 169 insertions(+), 88 deletions(-)
diff -urN linux-2.5/drivers/s390/block/dasd_eckd.c linux-2.5-s390/drivers/s390/block/dasd_eckd.c
--- linux-2.5/drivers/s390/block/dasd_eckd.c Sun Jun 22 20:32:28 2003
+++ linux-2.5-s390/drivers/s390/block/dasd_eckd.c Fri Jun 27 16:04:38 2003
@@ -80,7 +80,13 @@
static int
dasd_eckd_probe (struct ccw_device *cdev)
{
- return dasd_generic_probe (cdev, &dasd_eckd_discipline);
+ int ret;
+
+ ret = dasd_generic_probe (cdev, &dasd_eckd_discipline);
+ if (ret)
+ return ret;
+ ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+ return 0;
}
static int
diff -urN linux-2.5/drivers/s390/block/dasd_fba.c linux-2.5-s390/drivers/s390/block/dasd_fba.c
--- linux-2.5/drivers/s390/block/dasd_fba.c Sun Jun 22 20:32:58 2003
+++ linux-2.5-s390/drivers/s390/block/dasd_fba.c Fri Jun 27 16:04:38 2003
@@ -4,7 +4,7 @@
* Bugreports.to..: <[email protected]>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.29 $
+ * $Revision: 1.30 $
*/
#include <linux/config.h>
@@ -57,7 +57,13 @@
static int
dasd_fba_probe(struct ccw_device *cdev)
{
- return dasd_generic_probe (cdev, &dasd_fba_discipline);
+ int ret;
+
+ ret = dasd_generic_probe (cdev, &dasd_fba_discipline);
+ if (ret)
+ return ret;
+ ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+ return 0;
}
static int
diff -urN linux-2.5/drivers/s390/char/tape_core.c linux-2.5-s390/drivers/s390/char/tape_core.c
--- linux-2.5/drivers/s390/char/tape_core.c Sun Jun 22 20:32:37 2003
+++ linux-2.5-s390/drivers/s390/char/tape_core.c Fri Jun 27 16:04:38 2003
@@ -372,6 +372,8 @@
device->cdev = cdev;
cdev->handler = tape_do_irq;
+ ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+
return 0;
}
@@ -903,7 +905,7 @@
{
tape_dbf_area = debug_register ( "tape", 1, 2, 3*sizeof(long));
debug_register_view(tape_dbf_area, &debug_sprintf_view);
- DBF_EVENT(3, "tape init: ($Revision: 1.25 $)\n");
+ DBF_EVENT(3, "tape init: ($Revision: 1.26 $)\n");
tape_proc_init();
tapechar_init ();
tapeblock_init ();
@@ -928,7 +930,7 @@
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu ([email protected],[email protected])");
MODULE_DESCRIPTION("Linux on zSeries channel attached "
- "tape device driver ($Revision: 1.25 $)");
+ "tape device driver ($Revision: 1.26 $)");
module_init(tape_init);
module_exit(tape_exit);
diff -urN linux-2.5/drivers/s390/cio/ccwgroup.c linux-2.5-s390/drivers/s390/cio/ccwgroup.c
--- linux-2.5/drivers/s390/cio/ccwgroup.c Sun Jun 22 20:32:55 2003
+++ linux-2.5-s390/drivers/s390/cio/ccwgroup.c Fri Jun 27 16:04:38 2003
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -196,10 +196,12 @@
value = simple_strtoul(buf, 0, 0);
- if (value)
+ if (value == 1)
ccwgroup_set_online(gdev);
- else
+ else if (value == 0)
ccwgroup_set_offline(gdev);
+ else
+ return -EINVAL;
return count;
}
@@ -211,7 +213,7 @@
online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE);
- return sprintf(buf, online ? "1\n" : "0\n");
+ return sprintf(buf, online ? "yes\n" : "no\n");
}
static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
diff -urN linux-2.5/drivers/s390/cio/chsc.c linux-2.5-s390/drivers/s390/cio/chsc.c
--- linux-2.5/drivers/s390/cio/chsc.c Sun Jun 22 20:32:55 2003
+++ linux-2.5-s390/drivers/s390/cio/chsc.c Fri Jun 27 16:04:38 2003
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.69 $
+ * $Revision: 1.73 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -322,10 +322,6 @@
sprintf(dbf_txt, "chpr%x", chpid);
CIO_TRACE_EVENT(2, dbf_txt);
- /*
- * TODO: the chpid may be not the chpid with the link incident,
- * but the chpid the report came in through. How to handle???
- */
clear_bit(chpid, chpids);
if (!test_and_clear_bit(chpid, chpids_known))
return; /* we didn't know the chpid anyway */
@@ -469,9 +465,40 @@
free_page((unsigned long)page);
}
+static int
+__get_chpid_from_lir(void *data)
+{
+ struct lir {
+ u8 iq;
+ u8 ic;
+ u16 sci;
+ /* incident-node descriptor */
+ u32 indesc[28];
+ /* attached-node descriptor */
+ u32 andesc[28];
+ /* incident-specific information */
+ u32 isinfo[28];
+ } *lir;
+
+ lir = (struct lir*) data;
+ if (!(lir->iq&0x80))
+ /* NULL link incident record */
+ return -EINVAL;
+ if (!(lir->indesc[0]&0xc0000000))
+ /* node descriptor not valid */
+ return -EINVAL;
+ if (!(lir->indesc[0]&0x10000000))
+ /* don't handle device-type nodes - FIXME */
+ return -EINVAL;
+ /* Byte 3 contains the chpid. Could also be CTCA, but we don't care */
+
+ return (u16) (lir->indesc[0]&0x000000ff);
+}
+
static void
do_process_crw(void *ignore)
{
+ int chpid;
struct {
struct chsc_header request;
u32 reserved1;
@@ -487,10 +514,8 @@
u16 rsid; /* reporting source id */
u32 reserved5;
u32 reserved6;
- u32 ccdf; /* content-code dependent field */
- u32 reserved7;
- u32 reserved8;
- u32 reserved9;
+ u32 ccdf[96]; /* content-code dependent field */
+ /* ccdf has to be big enough for a link-incident record */
} *sei_area;
/*
@@ -560,9 +585,14 @@
case 1: /* link incident*/
CIO_CRW_EVENT(4, "chsc_process_crw: "
"channel subsystem reports link incident,"
- " source is chpid %x\n", sei_area->rsid);
-
- s390_set_chpid_offline(sei_area->rsid);
+ " reporting source is chpid %x\n",
+ sei_area->rsid);
+ chpid = __get_chpid_from_lir(sei_area->ccdf);
+ if (chpid < 0)
+ CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n",
+ __FUNCTION__);
+ else
+ s390_set_chpid_offline(chpid);
break;
case 2: /* i/o resource accessibiliy */
diff -urN linux-2.5/drivers/s390/cio/css.h linux-2.5-s390/drivers/s390/cio/css.h
--- linux-2.5/drivers/s390/cio/css.h Sun Jun 22 20:33:37 2003
+++ linux-2.5-s390/drivers/s390/cio/css.h Fri Jun 27 16:04:38 2003
@@ -72,9 +72,9 @@
struct {
unsigned int fast:1; /* post with "channel end" */
unsigned int repall:1; /* report every interrupt status */
+ unsigned int pgroup:1; /* do path grouping */
} __attribute__ ((packed)) options;
struct {
- unsigned int pgid_supp:1; /* "path group ID" supported */
unsigned int pgid_single:1; /* use single path for Set PGID */
unsigned int esid:1; /* Ext. SenseID supported by HW */
unsigned int dosense:1; /* delayed SENSE required */
diff -urN linux-2.5/drivers/s390/cio/device.c linux-2.5-s390/drivers/s390/cio/device.c
--- linux-2.5/drivers/s390/cio/device.c Sun Jun 22 20:33:04 2003
+++ linux-2.5-s390/drivers/s390/cio/device.c Fri Jun 27 16:04:38 2003
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.54 $
+ * $Revision: 1.57 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -298,20 +298,19 @@
online_store (struct device *dev, const char *buf, size_t count)
{
struct ccw_device *cdev = to_ccwdev(dev);
- unsigned int value;
+ int i;
+ char *tmp;
if (!cdev->drv)
return count;
- sscanf(buf, "%u", &value);
-
- if (value) {
- if (cdev->drv->set_online)
- ccw_device_set_online(cdev);
- } else {
- if (cdev->drv->set_offline)
- ccw_device_set_offline(cdev);
- }
+ i = simple_strtoul(buf, &tmp, 16);
+ if (i == 0 && cdev->drv->set_online)
+ ccw_device_set_online(cdev);
+ else if (i == 1 && cdev->drv->set_offline)
+ ccw_device_set_offline(cdev);
+ else
+ return -EINVAL;
return count;
}
@@ -405,11 +404,14 @@
* This allows to trigger an unconditional reserve ccw to eckd dasds
* (if the device is something else, there should be no problems more than
* a command reject; we don't have any means of finding out the device's
- * type if it was boxed at ipl/attach).
+ * type if it was boxed at ipl/attach for older devices and under VM).
*/
void
-ccw_device_add_stlck(struct ccw_device *cdev)
+ccw_device_add_stlck(void *data)
{
+ struct ccw_device *cdev;
+
+ cdev = (struct ccw_device *)data;
device_create_file(&cdev->dev, &dev_attr_steal_lock);
}
@@ -470,6 +472,8 @@
if (ret)
printk(KERN_WARNING "%s: could not add attributes to %04x\n",
__func__, sch->irq);
+ if (cdev->private->state == DEV_STATE_BOXED)
+ device_create_file(&cdev->dev, &dev_attr_steal_lock);
out:
put_device(&sch->dev);
}
@@ -493,6 +497,8 @@
if (cdev->dev.release)
cdev->dev.release(&cdev->dev);
break;
+ case DEV_STATE_BOXED:
+ /* Device did not respond in time. */
case DEV_STATE_OFFLINE:
/*
* We can't register the device in interrupt context so
@@ -502,9 +508,6 @@
io_subchannel_register, (void *) cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
break;
- case DEV_STATE_BOXED:
- /* Device did not respond in time. */
- break;
}
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
diff -urN linux-2.5/drivers/s390/cio/device.h linux-2.5-s390/drivers/s390/cio/device.h
--- linux-2.5/drivers/s390/cio/device.h Sun Jun 22 20:33:07 2003
+++ linux-2.5-s390/drivers/s390/cio/device.h Fri Jun 27 16:04:38 2003
@@ -95,7 +95,7 @@
void ccw_device_call_handler(struct ccw_device *);
-void ccw_device_add_stlck(struct ccw_device *);
+void ccw_device_add_stlck(void *);
int ccw_device_stlck(struct ccw_device *);
/* qdio needs this. */
diff -urN linux-2.5/drivers/s390/cio/device_fsm.c linux-2.5-s390/drivers/s390/cio/device_fsm.c
--- linux-2.5/drivers/s390/cio/device_fsm.c Sun Jun 22 20:32:46 2003
+++ linux-2.5-s390/drivers/s390/cio/device_fsm.c Fri Jun 27 16:04:38 2003
@@ -132,11 +132,11 @@
CIO_DEBUG(KERN_WARNING, 2,
"SenseID : boxed device %04X on subchannel %04X\n",
sch->schib.pmcw.dev, sch->irq);
- ccw_device_add_stlck(cdev);
break;
}
io_subchannel_recog_done(cdev);
- wake_up(&cdev->private->wait_q);
+ if (state != DEV_STATE_NOT_OPER)
+ wake_up(&cdev->private->wait_q);
}
/*
@@ -159,22 +159,65 @@
}
/*
+ * Finished with online/offline processing.
+ */
+static void
+ccw_device_done(struct ccw_device *cdev, int state)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
+
+ if (state != DEV_STATE_ONLINE)
+ cio_disable_subchannel(sch);
+
+ /* Reset device status. */
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+
+ cdev->private->state = state;
+
+
+ if (state == DEV_STATE_BOXED) {
+ CIO_DEBUG(KERN_WARNING, 2,
+ "Boxed device %04X on subchannel %04X\n",
+ sch->schib.pmcw.dev, sch->irq);
+ INIT_WORK(&cdev->private->kick_work,
+ ccw_device_add_stlck, (void *) cdev);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
+
+ wake_up(&cdev->private->wait_q);
+
+ if (state != DEV_STATE_ONLINE)
+ put_device (&cdev->dev);
+}
+
+/*
* Function called from device_pgid.c after sense path ground has completed.
*/
void
ccw_device_sense_pgid_done(struct ccw_device *cdev, int err)
{
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
switch (err) {
case 0:
- cdev->private->state = DEV_STATE_SENSE_ID;
- ccw_device_sense_id_start(cdev);
+ /* Start Path Group verification. */
+ sch->vpm = 0; /* Start with no path groups set. */
+ cdev->private->state = DEV_STATE_VERIFY;
+ ccw_device_verify_start(cdev);
break;
case -ETIME: /* Sense path group id stopped by timeout. */
case -EUSERS: /* device is reserved for someone else. */
- ccw_device_recog_done(cdev, DEV_STATE_BOXED);
+ ccw_device_done(cdev, DEV_STATE_BOXED);
+ break;
+ case -EOPNOTSUPP: /* path grouping not supported, just set online. */
+ cdev->private->options.pgroup = 0;
+ ccw_device_done(cdev, DEV_STATE_ONLINE);
break;
default:
- ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER);
+ ccw_device_done(cdev, DEV_STATE_NOT_OPER);
break;
}
}
@@ -198,11 +241,15 @@
ccw_device_set_timeout(cdev, 60*HZ);
/*
- * First thing we should do is a sensePGID in order to find out how
- * we can proceed with the recognition process.
+ * We used to start here with a sense pgid to find out whether a device
+ * is locked by someone else. Unfortunately, the sense pgid command
+ * code has other meanings on devices predating the path grouping
+ * algorithm, so we start with sense id and box the device after an
+ * timeout (or if sense pgid during path verification detects the device
+ * is locked, as may happen on newer devices).
*/
- cdev->private->state = DEV_STATE_SENSE_PGID;
- ccw_device_sense_pgid_start(cdev);
+ cdev->private->state = DEV_STATE_SENSE_ID;
+ ccw_device_sense_id_start(cdev);
return 0;
}
@@ -218,29 +265,6 @@
ccw_device_set_timeout(cdev, 3*HZ);
}
-/*
- * Finished with online/offline processing.
- */
-static void
-ccw_device_done(struct ccw_device *cdev, int state)
-{
- struct subchannel *sch;
-
- sch = to_subchannel(cdev->dev.parent);
-
- if (state != DEV_STATE_ONLINE)
- cio_disable_subchannel(sch);
-
- /* Reset device status. */
- memset(&cdev->private->irb, 0, sizeof(struct irb));
-
- cdev->private->state = state;
-
- wake_up(&cdev->private->wait_q);
-
- if (state != DEV_STATE_ONLINE)
- put_device (&cdev->dev);
-}
void
ccw_device_verify_done(struct ccw_device *cdev, int err)
@@ -276,16 +300,15 @@
dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
return -ENODEV;
}
- /* Is Set Path Group supported? */
- if (!cdev->private->flags.pgid_supp) {
+ /* Do we want to do path grouping? */
+ if (!cdev->private->options.pgroup) {
/* No, set state online immediately. */
ccw_device_done(cdev, DEV_STATE_ONLINE);
return 0;
}
- /* Start Path Group verification. */
- sch->vpm = 0; /* Start with no path groups set. */
- cdev->private->state = DEV_STATE_VERIFY;
- ccw_device_verify_start(cdev);
+ /* Do a SensePGID first. */
+ cdev->private->state = DEV_STATE_SENSE_PGID;
+ ccw_device_sense_pgid_start(cdev);
return 0;
}
@@ -321,8 +344,8 @@
}
if (sch->schib.scsw.actl != 0)
return -EBUSY;
- /* Is Set Path Group supported? */
- if (!cdev->private->flags.pgid_supp) {
+ /* Are we doing path grouping? */
+ if (!cdev->private->options.pgroup) {
/* No, set state offline immediately. */
ccw_device_done(cdev, DEV_STATE_OFFLINE);
return 0;
@@ -643,9 +666,9 @@
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_SENSE_PGID] {
- [DEV_EVENT_NOTOPER] ccw_device_recog_notoper,
+ [DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_sense_pgid_irq,
- [DEV_EVENT_TIMEOUT] ccw_device_recog_timeout,
+ [DEV_EVENT_TIMEOUT] ccw_device_onoff_timeout,
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_SENSE_ID] {
diff -urN linux-2.5/drivers/s390/cio/device_ops.c linux-2.5-s390/drivers/s390/cio/device_ops.c
--- linux-2.5/drivers/s390/cio/device_ops.c Sun Jun 22 20:33:04 2003
+++ linux-2.5-s390/drivers/s390/cio/device_ops.c Fri Jun 27 16:04:38 2003
@@ -37,6 +37,7 @@
return -EINVAL;
cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
+ cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
return 0;
}
diff -urN linux-2.5/drivers/s390/cio/device_pgid.c linux-2.5-s390/drivers/s390/cio/device_pgid.c
--- linux-2.5/drivers/s390/cio/device_pgid.c Sun Jun 22 20:32:55 2003
+++ linux-2.5-s390/drivers/s390/cio/device_pgid.c Fri Jun 27 16:04:38 2003
@@ -84,7 +84,6 @@
cdev->private->state = DEV_STATE_SENSE_PGID;
cdev->private->imask = 0x80;
cdev->private->iretry = 5;
- cdev->private->flags.pgid_supp = 0;
memset (&cdev->private->pgid, 0, sizeof (struct pgid));
ret = __ccw_device_sense_pgid_start(cdev);
if (ret)
@@ -165,14 +164,13 @@
switch (__ccw_device_check_sense_pgid(cdev)) {
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
case 0: /* Sense Path Group ID successful. */
- cdev->private->flags.pgid_supp = 1;
opm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom;
for (i=0;i<8;i++) {
if (opm == (0x80 << i)) {
/* Don't group single path devices. */
- cdev->private->flags.pgid_supp = 0;
+ cdev->private->options.pgroup = 0;
break;
}
}
@@ -181,7 +179,7 @@
sizeof(struct pgid));
/* fall through. */
case -EOPNOTSUPP: /* Sense Path Group ID not supported */
- ccw_device_sense_pgid_done(cdev, 0);
+ ccw_device_sense_pgid_done(cdev, -EOPNOTSUPP);
break;
case -ETIME: /* Sense path group id stopped by timeout. */
ccw_device_sense_pgid_done(cdev, -ETIME);
diff -urN linux-2.5/drivers/s390/cio/qdio.h linux-2.5-s390/drivers/s390/cio/qdio.h
--- linux-2.5/drivers/s390/cio/qdio.h Sun Jun 22 20:32:36 2003
+++ linux-2.5-s390/drivers/s390/cio/qdio.h Fri Jun 27 16:04:38 2003
@@ -1,7 +1,7 @@
#ifndef _CIO_QDIO_H
#define _CIO_QDIO_H
-#define VERSION_CIO_QDIO_H "$Revision: 1.16 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.17 $"
//#define QDIO_DBF_LIKE_HELL
@@ -21,7 +21,15 @@
#define QDIO_TIMER_POLL_VALUE 1
#define IQDIO_TIMER_POLL_VALUE 1
-#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3)
+/*
+ * unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as
+ * we never know, whether we'll get initiative again, e.g. to give the
+ * transmit skb's back to the stack, however the stack may be waiting for
+ * them... therefore we define 4 as threshold to start polling (which
+ * will stop as soon as the asynchronous queue catches up)
+ * btw, this only applies to the asynchronous HiperSockets queue
+ */
+#define IQDIO_FILL_LEVEL_TO_POLL 4
#define IQDIO_THININT_ISC 3
#define IQDIO_DELAY_TARGET 0
diff -urN linux-2.5/include/asm-s390/ccwdev.h linux-2.5-s390/include/asm-s390/ccwdev.h
--- linux-2.5/include/asm-s390/ccwdev.h Sun Jun 22 20:33:15 2003
+++ linux-2.5-s390/include/asm-s390/ccwdev.h Fri Jun 27 16:04:38 2003
@@ -115,6 +115,8 @@
#define CCWDEV_EARLY_NOTIFICATION 0x0001
/* Report all interrupt conditions. */
#define CCWDEV_REPORT_ALL 0x0002
+/* Try to perform path grouping. */
+#define CCWDEV_DO_PATHGROUP 0x0004
/*
* ccw_device_start()