Commit 03cd7b46 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: common i/o layer.

 - Remove initialization of device.name.
 - Don't do put_device after failed get_device in get_ccwdev_by_busid.
 - Fix read_dev_chars and read_conf_data.
 - Call interrupt function of ccw device if path verification has been started.
 - Replace atomic_return_add by atomic_add_return in qdio.
 - Use wait_event instead of homegrown wait loop.
 - Fix reestablish queue problem.
 - Add ungroup attribute to ccw_group devices and add links from each
   ccw device of a group to the group device.
 - Use BUS_ID_SIZE instead of DEVICE_ID_SIZE.
 - Delay path verification if a basic sense is required.
 - Move qdio shutdown code from qdio_free to qdio_shutdown.
parent 7d853ae3
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
* $Revision: 1.7 $
* $Revision: 1.15 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
* Cornelia Huck (cohuck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/errno.h>
......@@ -14,6 +15,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/dcache.h>
#include <asm/semaphore.h>
#include <asm/ccwdev.h>
......@@ -56,6 +58,45 @@ static struct bus_type ccwgroup_bus_type = {
.hotplug = ccwgroup_hotplug,
};
static inline void
__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
{
int i;
char str[8];
for (i = 0; i < gdev->count; i++) {
sprintf(str, "cdev%d", i);
sysfs_remove_link(&gdev->dev.kobj, str);
/* Hack: Make sure we act on still valid subdirs. */
if (atomic_read(&gdev->cdev[i]->dev.kobj.dentry->d_count))
sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
"group_device");
}
}
/*
* Provide an 'ungroup' attribute so the user can remove group devices no
* longer needed or accidentially created. Saves memory :)
*/
static ssize_t
ccwgroup_ungroup_store(struct device *dev, const char *buf, size_t count)
{
struct ccwgroup_device *gdev;
gdev = to_ccwgroupdev(dev);
if (gdev->state != CCWGROUP_OFFLINE)
return -EINVAL;
__ccwgroup_remove_symlinks(gdev);
device_unregister(dev);
return count;
}
static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store);
static void
ccwgroup_release (struct device *dev)
{
......@@ -69,6 +110,40 @@ ccwgroup_release (struct device *dev)
kfree(gdev);
}
static inline int
__ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
{
char str[8];
int i, rc;
for (i = 0; i < gdev->count; i++) {
rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, &gdev->dev.kobj,
"group_device");
if (rc) {
for (--i; i >= 0; i--)
sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
"group_device");
return rc;
}
}
for (i = 0; i < gdev->count; i++) {
sprintf(str, "cdev%d", i);
rc = sysfs_create_link(&gdev->dev.kobj, &gdev->cdev[i]->dev.kobj,
str);
if (rc) {
for (--i; i >= 0; i--) {
sprintf(str, "cdev%d", i);
sysfs_remove_link(&gdev->dev.kobj, str);
}
for (i = 0; i < gdev->count; i++)
sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
"group_device");
return rc;
}
}
return 0;
}
/*
* try to add a new ccwgroup device for one driver
* argc and argv[] are a list of bus_id's of devices
......@@ -82,6 +157,7 @@ ccwgroup_create(struct device *root,
{
struct ccwgroup_device *gdev;
int i;
int rc;
if (argc > 256) /* disallow dumb users */
return -EINVAL;
......@@ -90,6 +166,8 @@ ccwgroup_create(struct device *root,
if (!gdev)
return -ENOMEM;
memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0]));
for (i = 0; i < argc; i++) {
gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
......@@ -97,9 +175,11 @@ ccwgroup_create(struct device *root,
* order to be grouped */
if (!gdev->cdev[i]
|| gdev->cdev[i]->id.driver_info !=
gdev->cdev[0]->id.driver_info)
gdev->cdev[0]->id.driver_info) {
rc = -EINVAL;
goto error;
}
}
*gdev = (struct ccwgroup_device) {
.creator_id = creator_id,
......@@ -114,9 +194,24 @@ ccwgroup_create(struct device *root,
snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
gdev->cdev[0]->dev.bus_id);
/* TODO: make symlinks for sysfs */
return device_register(&gdev->dev);
rc = device_register(&gdev->dev);
if (rc)
goto error;
rc = device_create_file(&gdev->dev, &dev_attr_ungroup);
if (rc) {
device_unregister(&gdev->dev);
goto error;
}
rc = __ccwgroup_create_symlinks(gdev);
if (!rc)
return 0;
device_remove_file(&gdev->dev, &dev_attr_ungroup);
device_unregister(&gdev->dev);
error:
for (i = 0; i < argc; i++)
if (gdev->cdev[i])
......@@ -124,7 +219,7 @@ ccwgroup_create(struct device *root,
kfree(gdev);
return -EINVAL;
return rc;
}
static int __init
......@@ -213,7 +308,7 @@ ccwgroup_online_show (struct device *dev, char *buf)
online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE);
return sprintf(buf, online ? "yes\n" : "no\n");
return sprintf(buf, online ? "1\n" : "0\n");
}
static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
......@@ -286,9 +381,59 @@ ccwgroup_probe_ccwdev(struct ccw_device *cdev)
return 0;
}
static inline struct ccwgroup_device *
__ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
{
struct ccwgroup_device *gdev;
struct list_head *entry;
struct device *dev;
int i, found;
/*
* Find groupdevice cdev belongs to.
* Unfortunately, we can't use bus_for_each_dev() because of the
* semaphore (and return value of fn() is int).
*/
if (!get_bus(&ccwgroup_bus_type))
return NULL;
gdev = NULL;
down_read(&ccwgroup_bus_type.subsys.rwsem);
list_for_each(entry, &ccwgroup_bus_type.devices.list) {
dev = get_device(container_of(entry, struct device, bus_list));
found = 0;
if (!dev)
continue;
gdev = to_ccwgroupdev(dev);
for (i = 0; i < gdev->count && (!found); i++) {
if (gdev->cdev[i] == cdev)
found = 1;
}
if (found)
break;
put_device(dev);
gdev = NULL;
}
up_read(&ccwgroup_bus_type.subsys.rwsem);
put_bus(&ccwgroup_bus_type);
return gdev;
}
int
ccwgroup_remove_ccwdev(struct ccw_device *cdev)
{
struct ccwgroup_device *gdev;
/* If one of its devices is gone, the whole group is done for. */
gdev = __ccwgroup_get_gdev_by_cdev(cdev);
if (gdev) {
ccwgroup_set_offline(gdev);
__ccwgroup_remove_symlinks(gdev);
device_unregister(&gdev->dev);
put_device(&gdev->dev);
}
return 0;
}
......
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
* $Revision: 1.74 $
* $Revision: 1.77 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -865,9 +865,7 @@ new_channel_path(int chpid, int status)
chp->state = status;
chp->dev.parent = &css_bus_device;
snprintf(chp->dev.name, DEVICE_NAME_SIZE,
"channel path %x", chpid);
snprintf(chp->dev.bus_id, DEVICE_ID_SIZE, "chp%x", chpid);
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
/* make it known to the system */
ret = device_register(&chp->dev);
......
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
* $Revision: 1.100 $
* $Revision: 1.105 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -277,11 +277,6 @@ cio_halt(struct subchannel *sch)
if (!sch)
return -ENODEV;
/*
* we ignore the halt_io() request if ending_status was received but
* a SENSE operation is waiting for completion.
*/
sprintf (dbf_txt, "haltIO%x", sch->irq);
CIO_TRACE_EVENT (2, dbf_txt);
......@@ -316,10 +311,6 @@ cio_clear(struct subchannel *sch)
if (!sch)
return -ENODEV;
/*
* we ignore the clear_io() request if ending_status was received but
* a SENSE operation is waiting for completion.
*/
sprintf (dbf_txt, "clearIO%x", sch->irq);
CIO_TRACE_EVENT (2, dbf_txt);
......@@ -380,7 +371,7 @@ cio_cancel (struct subchannel *sch)
}
/*
* Function: cio_cancel
* Function: cio_modify
* Issues a "Modify Subchannel" on the specified subchannel
*/
static int
......@@ -469,11 +460,6 @@ cio_disable_subchannel (struct subchannel *sch)
sprintf (dbf_txt, "dissch%x", sch->irq);
CIO_TRACE_EVENT (2, dbf_txt);
/*
* If device isn't operational we have to perform delayed
* disabling when the next interrupt occurs - unless the
* irq is re-requested prior to the interrupt to occur.
*/
ccode = stsch (sch->irq, &sch->schib);
if (ccode == 3) /* Not operational. */
return -ENODEV;
......
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
* $Revision: 1.43 $
* $Revision: 1.49 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -27,7 +27,6 @@ unsigned int highest_subchannel;
int css_init_done = 0;
struct device css_bus_device = {
.name = "Channel Subsystem 0",
.bus_id = "css0",
};
......@@ -79,17 +78,6 @@ css_free_subchannel(int irq)
static int
css_register_subchannel(struct subchannel *sch)
{
static const char *subchannel_types[] = {
"I/O Subchannel",
"CHSC Subchannel",
"Message Subchannel",
"ADM Subchannel",
"undefined subchannel type 4",
"undefined subchannel type 5",
"undefined subchannel type 6",
"undefined subchannel type 7",
"undefined subchannel type 8",
};
int ret;
/* Initialize the subchannel structure */
......@@ -97,8 +85,7 @@ css_register_subchannel(struct subchannel *sch)
sch->dev.bus = &css_bus_type;
/* Set a name for the subchannel */
strlcpy (sch->dev.name, subchannel_types[sch->st], DEVICE_NAME_SIZE);
snprintf (sch->dev.bus_id, DEVICE_ID_SIZE, "0:%04x", sch->irq);
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", sch->irq);
/* make it known to the system */
ret = device_register(&sch->dev);
......
......@@ -78,6 +78,7 @@ struct ccw_device_private {
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 */
unsigned int doverify:1; /* delayed path verification */
} __attribute__((packed)) flags;
unsigned long intparm; /* user interruption parameter */
struct qdio_irq *qdio_data;
......
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
* $Revision: 1.60 $
* $Revision: 1.70 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -229,7 +229,7 @@ online_show (struct device *dev, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
return sprintf(buf, cdev->online ? "yes\n" : "no\n");
return sprintf(buf, cdev->online ? "1\n" : "0\n");
}
void
......@@ -537,8 +537,7 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
init_timer(&cdev->private->timer);
/* Set an initial name for the device. */
snprintf (cdev->dev.name, DEVICE_NAME_SIZE,"ccw device");
snprintf (cdev->dev.bus_id, DEVICE_ID_SIZE, "0:%04x",
snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
sch->schib.pmcw.dev);
/* Increase counter of devices currently in recognition. */
......@@ -679,6 +678,7 @@ ccw_device_probe_console(void)
console_cdev_in_use = 0;
return ERR_PTR(ret);
}
console_cdev.online = 1;
return &console_cdev;
}
#endif
......@@ -702,10 +702,12 @@ get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
list_for_each_entry(d, &drv->devices, driver_list) {
dev = get_device(d);
if (dev && !strncmp(bus_id, dev->bus_id, DEVICE_ID_SIZE))
if (dev && !strncmp(bus_id, dev->bus_id, BUS_ID_SIZE))
break;
else
else if (dev) {
put_device(dev);
dev = NULL;
}
}
up_read(&drv->bus->subsys.rwsem);
put_driver(drv);
......
......@@ -15,8 +15,6 @@ enum dev_state {
DEV_STATE_DISBAND_PGID,
DEV_STATE_BOXED,
/* states to wait for i/o completion before doing something */
DEV_STATE_ONLINE_VERIFY,
DEV_STATE_W4SENSE_VERIFY,
DEV_STATE_CLEAR_VERIFY,
DEV_STATE_TIMEOUT_KILL,
/* last element! */
......@@ -95,7 +93,7 @@ void ccw_device_disband_start(struct ccw_device *);
void ccw_device_disband_irq(struct ccw_device *, enum dev_event);
void ccw_device_disband_done(struct ccw_device *, int);
void ccw_device_call_handler(struct ccw_device *);
int ccw_device_call_handler(struct ccw_device *);
void ccw_device_add_stlck(void *);
int ccw_device_stlck(struct ccw_device *);
......
......@@ -269,6 +269,7 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
void
ccw_device_verify_done(struct ccw_device *cdev, int err)
{
cdev->private->flags.doverify = 0;
switch (err) {
case 0:
ccw_device_done(cdev, DEV_STATE_ONLINE);
......@@ -419,13 +420,21 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
{
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
if (!cdev->private->options.pgroup)
return;
if (cdev->private->state == DEV_STATE_W4SENSE) {
cdev->private->state = DEV_STATE_W4SENSE_VERIFY;
cdev->private->flags.doverify = 1;
return;
}
if (sch->schib.scsw.actl != 0) {
cdev->private->state = DEV_STATE_ONLINE_VERIFY;
sch = to_subchannel(cdev->dev.parent);
if (sch->schib.scsw.actl != 0 ||
(cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
/*
* No final status yet or final status not yet delivered
* to the device driver. Can't do path verfication now,
* delay until final status was delivered.
*/
cdev->private->flags.doverify = 1;
return;
}
/* Device is idle, we can do the path verification. */
......@@ -453,19 +462,14 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
ccw_device_accumulate_irb(cdev, irb);
if (cdev->private->flags.dosense) {
if (ccw_device_do_sense(cdev, irb) == 0) {
/* Check if we have to trigger path verification. */
if (irb->esw.esw0.erw.pvrf)
cdev->private->state = DEV_STATE_W4SENSE_VERIFY;
else
cdev->private->state = DEV_STATE_W4SENSE;
}
return;
}
if (irb->esw.esw0.erw.pvrf)
/* Try to start path verification. */
/* Call the handler. */
if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify)
/* Start delayed path verification. */
ccw_device_online_verify(cdev, 0);
/* No basic sense required, call the handler. */
ccw_device_call_handler(cdev);
}
/*
......@@ -485,32 +489,6 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
ERR_PTR(-ETIMEDOUT));
}
static void
ccw_device_irq_verify(struct ccw_device *cdev, enum dev_event dev_event)
{
struct irb *irb;
irb = (struct irb *) __LC_IRB;
/* Check for unsolicited interrupt. */
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
if (cdev->handler)
cdev->handler (cdev, 0, irb);
return;
}
/* Accumulate status and find out if a basic sense is needed. */
ccw_device_accumulate_irb(cdev, irb);
if (cdev->private->flags.dosense) {
if (ccw_device_do_sense(cdev, irb) == 0)
cdev->private->state = DEV_STATE_W4SENSE_VERIFY;
return;
}
/* Try to start delayed device verification. */
ccw_device_online_verify(cdev, 0);
/* No basic sense required, call the handler. */
ccw_device_call_handler(cdev);
}
/*
* Got an interrupt for a basic sense.
*/
......@@ -530,46 +508,15 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
/* Add basic sense info to irb. */
ccw_device_accumulate_basic_sense(cdev, irb);
if (cdev->private->flags.dosense) {
/* Check if we have to trigger path verification. */
if (irb->esw.esw0.erw.pvrf)
cdev->private->state = DEV_STATE_W4SENSE_VERIFY;
/* Another basic sense is needed. */
ccw_device_do_sense(cdev, irb);
return;
}
cdev->private->state = DEV_STATE_ONLINE;
if (irb->esw.esw0.erw.pvrf)
/* Try to start path verification. */
ccw_device_online_verify(cdev, 0);
/* Call the handler. */
ccw_device_call_handler(cdev);
}
static void
ccw_device_w4sense_verify(struct ccw_device *cdev, enum dev_event dev_event)
{
struct irb *irb;
irb = (struct irb *) __LC_IRB;
/* Check for unsolicited interrupt. */
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
if (cdev->handler)
cdev->handler (cdev, 0, irb);
return;
}
/* Add basic sense info to irb. */
ccw_device_accumulate_basic_sense(cdev, irb);
if (cdev->private->flags.dosense) {
/* Another basic sense is needed. */
ccw_device_do_sense(cdev, irb);
return;
}
cdev->private->state = DEV_STATE_ONLINE_VERIFY;
/* Start delayed device verification. */
if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify)
/* Start delayed path verification. */
ccw_device_online_verify(cdev, 0);
/* Call the handler. */
ccw_device_call_handler(cdev);
}
static void
......@@ -718,18 +665,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_VERIFY] ccw_device_nop,
},
/* states to wait for i/o completion before doing something */
[DEV_STATE_ONLINE_VERIFY] {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_irq_verify,
[DEV_EVENT_TIMEOUT] ccw_device_nop,
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_W4SENSE_VERIFY] {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_w4sense_verify,
[DEV_EVENT_TIMEOUT] ccw_device_nop,
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_CLEAR_VERIFY] {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_clear_verify,
......
......@@ -342,3 +342,4 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
}
}
EXPORT_SYMBOL(diag210);
This diff is collapsed.
......@@ -67,7 +67,8 @@ ccw_device_path_notoper(struct ccw_device *cdev)
sch->schib.pmcw.pnom);
sch->lpm &= ~sch->schib.pmcw.pnom;
dev_fsm_event(cdev, DEV_EVENT_VERIFY);
if (cdev->private->options.pgroup)
cdev->private->flags.doverify = 1;
}
/*
......@@ -92,6 +93,21 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
memcpy (&cdev->private->irb.ecw, irb->ecw, sizeof (irb->ecw));
}
/*
* Check if extended status word is valid.
*/
static inline int
ccw_device_accumulate_esw_valid(struct irb *irb)
{
if (irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
return 0;
if (irb->scsw.stctl ==
(SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
!(irb->scsw.actl & SCSW_ACTL_SUSPENDED))
return 0;
return 1;
}
/*
* Copy valid bits from the extended status word to device irb.
*/
......@@ -101,12 +117,7 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
struct irb *cdev_irb;
struct sublog *cdev_sublog, *sublog;
/* Check if extended status word is valid. */
if (irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
return;
if (irb->scsw.stctl ==
(SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
!(irb->scsw.actl & SCSW_ACTL_SUSPENDED))
if (!ccw_device_accumulate_esw_valid(irb))
return;
cdev_irb = &cdev->private->irb;
......@@ -169,6 +180,8 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
cdev_irb->esw.esw0.erw.auth = irb->esw.esw0.erw.auth;
/* Copy path verification required flag. */
cdev_irb->esw.esw0.erw.pvrf = irb->esw.esw0.erw.pvrf;
if (irb->esw.esw0.erw.pvrf && cdev->private->options.pgroup)
cdev->private->flags.doverify = 1;
/* Copy concurrent sense bit. */
cdev_irb->esw.esw0.erw.cons = irb->esw.esw0.erw.cons;
if (irb->esw.esw0.erw.cons)
......@@ -339,6 +352,10 @@ ccw_device_accumulate_basic_sense(struct ccw_device *cdev, struct irb *irb)
cdev->private->irb.esw.esw0.erw.cons = 1;
cdev->private->flags.dosense = 0;
}
/* Check if path verification is required. */
if (ccw_device_accumulate_esw_valid(irb) &&
irb->esw.esw0.erw.pvrf && cdev->private->options.pgroup)
cdev->private->flags.doverify = 1;
}
/*
......
This diff is collapsed.
#ifndef _CIO_QDIO_H
#define _CIO_QDIO_H
#define VERSION_CIO_QDIO_H "$Revision: 1.18 $"
#define VERSION_CIO_QDIO_H "$Revision: 1.20 $"
//#define QDIO_DBF_LIKE_HELL
......@@ -56,7 +56,6 @@
#define QDIO_STATS_CLASSES 2
#define QDIO_STATS_COUNT_NEEDED 2*/
#define QDIO_NO_USE_COUNT_TIME 10
#define QDIO_NO_USE_COUNT_TIMEOUT 1000 /* wait for 1 sec on each q before
exiting without having use_count
of the queue to 0 */
......@@ -577,9 +576,6 @@ struct qdio_q {
volatile struct qdio_q *list_next;
volatile struct qdio_q *list_prev;
struct slib *slib; /* a page is allocated under this pointer,
sl points into this page, offset PAGE_SIZE/2
(after slib) */
struct sl *sl;
volatile struct sbal *sbal[QDIO_MAX_BUFFERS_PER_Q];
......@@ -605,6 +601,11 @@ struct qdio_q {
__u64 last_transfer_time;
} timing;
unsigned int queue_type;
/* leave this member at the end. won't be cleared in qdio_fill_qs */
struct slib *slib; /* a page is allocated under this pointer,
sl points into this page, offset PAGE_SIZE/2
(after slib) */
} __attribute__ ((aligned(256)));
struct qdio_irq {
......@@ -619,20 +620,14 @@ struct qdio_irq {
unsigned int sync_done_on_outb_pcis;
enum qdio_irq_states state;
struct semaphore setting_up_sema;
unsigned int no_input_qs;
unsigned int no_output_qs;
unsigned char qdioac;
struct qdio_q *input_qs[QDIO_MAX_QUEUES_PER_IRQ];
struct qdio_q *output_qs[QDIO_MAX_QUEUES_PER_IRQ];
struct ccw1 ccw;
struct qdr *qdr;
struct ciw equeue;
struct ciw aqueue;
......@@ -641,5 +636,10 @@ struct qdio_irq {
void (*original_int_handler) (struct ccw_device *,
unsigned long, struct irb *);
/* leave these four members together at the end. won't be cleared in qdio_fill_irq */
struct qdr *qdr;
struct qdio_q *input_qs[QDIO_MAX_QUEUES_PER_IRQ];
struct qdio_q *output_qs[QDIO_MAX_QUEUES_PER_IRQ];
struct semaphore setting_up_sema;
};
#endif
/*
* $Id: cu3088.c,v 1.26 2003/01/17 13:46:13 cohuck Exp $
* $Id: cu3088.c,v 1.30 2003/08/28 11:14:11 cohuck Exp $
*
* CTC / LCS ccw_device driver
*
......@@ -56,7 +56,6 @@ static struct ccw_device_id cu3088_ids[] = {
static struct ccw_driver cu3088_driver;
struct device cu3088_root_dev = {
.name = "CU3088 Devices",
.bus_id = "cu3088",
};
......@@ -64,7 +63,7 @@ static ssize_t
group_write(struct device_driver *drv, const char *buf, size_t count)
{
const char *start, *end;
char bus_ids[2][BUS_ID_SIZE+1], *argv[2];
char bus_ids[2][BUS_ID_SIZE], *argv[2];
int i;
int ret;
struct ccwgroup_driver *cdrv;
......@@ -79,7 +78,7 @@ group_write(struct device_driver *drv, const char *buf, size_t count)
if (!(end = strchr(start, delim[i])))
return count;
len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start)+1;
len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
strlcpy (bus_ids[i], start, len);
argv[i] = bus_ids[i];
start = end + 1;
......
......@@ -76,7 +76,7 @@ typedef void qdio_handler_t(struct ccw_device *,unsigned int,unsigned int,
#define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01
#define QDIO_FLAG_CLEANUP_USING_HALT 0x02
struct qdio_initialize{
struct qdio_initialize {
struct ccw_device *cdev;
unsigned char q_format;
unsigned char adapter_name[8];
......@@ -99,9 +99,10 @@ struct qdio_initialize{
void **input_sbal_addr_array; /* addr of n*128 void ptrs */
void **output_sbal_addr_array; /* addr of n*128 void ptrs */
};
extern int qdio_initialize(struct qdio_initialize *init_data);
extern int qdio_allocate(struct qdio_initialize *init_data);
extern int qdio_establish(struct ccw_device *);
extern int qdio_establish(struct qdio_initialize *init_data);
extern int qdio_activate(struct ccw_device *,int flags);
......
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