Commit 1391c772 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: steal lock support.

cio: Add code to break a reservation of a device (steal lock).
parent 67408494
/* /*
* drivers/s390/cio/device.c * drivers/s390/cio/device.c
* bus driver for ccw devices * bus driver for ccw devices
* $Revision: 1.53 $ * $Revision: 1.54 $
* *
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -316,11 +316,63 @@ online_store (struct device *dev, const char *buf, size_t count) ...@@ -316,11 +316,63 @@ online_store (struct device *dev, const char *buf, size_t count)
return count; return count;
} }
static void ccw_device_unbox_recog(void *data);
static ssize_t
stlck_store(struct device *dev, const char *buf, size_t count)
{
struct ccw_device *cdev = to_ccwdev(dev);
int ret;
/* We don't care what was piped to the attribute 8) */
ret = ccw_device_stlck(cdev);
if (ret != 0) {
printk(KERN_WARNING
"Unconditional reserve failed on device %s, rc=%d\n",
dev->bus_id, ret);
return ret;
}
/*
* Device was successfully unboxed.
* Trigger removal of stlck attribute and device recognition.
*/
INIT_WORK(&cdev->private->kick_work,
ccw_device_unbox_recog, (void *) cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
return 0;
}
static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
static DEVICE_ATTR(online, 0644, online_show, online_store); static DEVICE_ATTR(online, 0644, online_show, online_store);
static DEVICE_ATTR(steal_lock, 0200, NULL, stlck_store);
/* A device has been unboxed. Start device recognition. */
static void
ccw_device_unbox_recog(void *data)
{
struct ccw_device *cdev;
cdev = (struct ccw_device *)data;
if (!cdev)
return;
/* Remove stlck attribute. */
device_remove_file(&cdev->dev, &dev_attr_steal_lock);
spin_lock_irq(cdev->ccwlock);
/* Device is no longer boxed. */
cdev->private->state = DEV_STATE_NOT_OPER;
/* Finally start device recognition. */
ccw_device_recognition(cdev);
spin_unlock_irq(cdev->ccwlock);
}
static inline int static inline int
subchannel_add_files (struct device *dev) subchannel_add_files (struct device *dev)
...@@ -348,6 +400,19 @@ device_add_files (struct device *dev) ...@@ -348,6 +400,19 @@ device_add_files (struct device *dev)
return ret; return ret;
} }
/*
* Add a "steal lock" attribute to boxed devices.
* 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).
*/
void
ccw_device_add_stlck(struct ccw_device *cdev)
{
device_create_file(&cdev->dev, &dev_attr_steal_lock);
}
/* this is a simple abstraction for device_register that sets the /* this is a simple abstraction for device_register that sets the
* correct bus type and adds the bus specific files */ * correct bus type and adds the bus specific files */
static int static int
......
...@@ -95,6 +95,9 @@ void ccw_device_disband_done(struct ccw_device *, int); ...@@ -95,6 +95,9 @@ void ccw_device_disband_done(struct ccw_device *, int);
void ccw_device_call_handler(struct ccw_device *); void ccw_device_call_handler(struct ccw_device *);
void ccw_device_add_stlck(struct ccw_device *);
int ccw_device_stlck(struct ccw_device *);
/* qdio needs this. */ /* qdio needs this. */
void ccw_device_set_timeout(struct ccw_device *, int); void ccw_device_set_timeout(struct ccw_device *, int);
#endif #endif
...@@ -132,6 +132,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) ...@@ -132,6 +132,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
CIO_DEBUG(KERN_WARNING, 2, CIO_DEBUG(KERN_WARNING, 2,
"SenseID : boxed device %04X on subchannel %04X\n", "SenseID : boxed device %04X on subchannel %04X\n",
sch->schib.pmcw.dev, sch->irq); sch->schib.pmcw.dev, sch->irq);
ccw_device_add_stlck(cdev);
break; break;
} }
io_subchannel_recog_done(cdev); io_subchannel_recog_done(cdev);
...@@ -588,6 +589,29 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -588,6 +589,29 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
ERR_PTR(-ETIMEDOUT)); ERR_PTR(-ETIMEDOUT));
} }
static void
ccw_device_stlck_done(struct ccw_device *cdev, enum dev_event dev_event)
{
struct irb *irb;
switch (dev_event) {
case DEV_EVENT_INTERRUPT:
irb = (struct irb *) __LC_IRB;
/* Check for unsolicited interrupt. */
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS))
goto out_wakeup;
ccw_device_accumulate_irb(cdev, irb);
/* We don't care about basic sense etc. */
break;
default: /* timeout */
break;
}
out_wakeup:
wake_up(&cdev->private->wait_q);
}
/* /*
* No operation action. This is used e.g. to ignore a timeout event in * No operation action. This is used e.g. to ignore a timeout event in
* state offline. * state offline.
...@@ -662,8 +686,8 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { ...@@ -662,8 +686,8 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
}, },
[DEV_STATE_BOXED] { [DEV_STATE_BOXED] {
[DEV_EVENT_NOTOPER] ccw_device_offline_notoper, [DEV_EVENT_NOTOPER] ccw_device_offline_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_bug, [DEV_EVENT_INTERRUPT] ccw_device_stlck_done,
[DEV_EVENT_TIMEOUT] ccw_device_nop, [DEV_EVENT_TIMEOUT] ccw_device_stlck_done,
[DEV_EVENT_VERIFY] ccw_device_nop, [DEV_EVENT_VERIFY] ccw_device_nop,
}, },
/* states to wait for i/o completion before doing something */ /* states to wait for i/o completion before doing something */
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
* Cornelia Huck (cohuck@de.ibm.com)
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -379,6 +380,52 @@ read_conf_data (struct ccw_device *cdev, void **buffer, int *length) ...@@ -379,6 +380,52 @@ read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
return ret; return ret;
} }
/*
* Try to issue an unconditional reserve on a boxed device.
*/
int
ccw_device_stlck(struct ccw_device *cdev)
{
char buf[32];
unsigned long flags;
struct subchannel *sch;
int ret;
if (!cdev)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
CIO_TRACE_EVENT(2, "stl lock");
CIO_TRACE_EVENT(2, cdev->dev.bus_id);
/* Setup ccw. This cmd code seems not to be in use elsewhere. */
cdev->private->iccws[0].cmd_code = CCW_CMD_STLCK;
cdev->private->iccws[0].cda = (__u32) __pa(buf);
cdev->private->iccws[0].count = 32;
cdev->private->iccws[0].flags = CCW_FLAG_SLI;
spin_lock_irqsave(&sch->lock, flags);
ret = cio_start(sch, cdev->private->iccws, 0xE2D3C3D2, 0);
spin_unlock_irqrestore(&sch->lock, flags);
if (ret)
return ret;
wait_event(cdev->private->wait_q, sch->schib.scsw.actl == 0);
spin_lock_irqsave(&sch->lock, flags);
if ((cdev->private->irb.scsw.dstat !=
(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
(cdev->private->irb.scsw.cstat != 0))
ret = -EIO;
/* Clear irb. */
memset(&cdev->private->irb, 0, sizeof(struct irb));
spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
// FIXME: these have to go: // FIXME: these have to go:
int int
......
...@@ -128,6 +128,7 @@ struct ccw1 { ...@@ -128,6 +128,7 @@ struct ccw1 {
#define CCW_CMD_NOOP 0x03 #define CCW_CMD_NOOP 0x03
#define CCW_CMD_BASIC_SENSE 0x04 #define CCW_CMD_BASIC_SENSE 0x04
#define CCW_CMD_TIC 0x08 #define CCW_CMD_TIC 0x08
#define CCW_CMD_STLCK 0x14
#define CCW_CMD_SENSE_PGID 0x34 #define CCW_CMD_SENSE_PGID 0x34
#define CCW_CMD_SUSPEND_RECONN 0x5B #define CCW_CMD_SUSPEND_RECONN 0x5B
#define CCW_CMD_RDC 0x64 #define CCW_CMD_RDC 0x64
......
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