Commit 2152527f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: tape driver fixes

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

Tape driver changes:
 - Add missing break in tape_34xx_work_handler to avoid misleading message.
 - Cleanup offline/remove code.
parent 6a562864
......@@ -113,6 +113,7 @@ tape_34xx_work_handler(void *data)
switch(p->op) {
case TO_MSEN:
tape_34xx_medium_sense(p->device);
break;
default:
DBF_EVENT(3, "T34XX: internal error: unknown work\n");
}
......@@ -1342,7 +1343,7 @@ tape_34xx_init (void)
{
int rc;
DBF_EVENT(3, "34xx init: $Revision: 1.19 $\n");
DBF_EVENT(3, "34xx init: $Revision: 1.20 $\n");
/* Register driver for 3480/3490 tapes. */
rc = ccw_driver_register(&tape_34xx_driver);
if (rc)
......@@ -1361,7 +1362,7 @@ tape_34xx_exit(void)
MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
"device driver ($Revision: 1.19 $)");
"device driver ($Revision: 1.20 $)");
MODULE_LICENSE("GPL");
module_init(tape_34xx_init);
......
/*
* (C) Copyright IBM Corp. 2004
* tape_class.c ($Revision: 1.6 $)
* tape_class.c ($Revision: 1.8 $)
*
* Tape class device support
*
......@@ -12,7 +12,7 @@
MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
MODULE_DESCRIPTION(
"(C) Copyright IBM Corp. 2004 All Rights Reserved.\n"
"tape_class.c ($Revision: 1.6 $)"
"tape_class.c ($Revision: 1.8 $)"
);
MODULE_LICENSE("GPL");
......@@ -85,7 +85,7 @@ struct tape_class_device *register_tape_dev(
return tcd;
fail_with_cdev:
cdev_del(&tcd->char_device);
cdev_del(tcd->char_device);
fail_with_tcd:
kfree(tcd);
......
......@@ -377,6 +377,16 @@ tape_generic_online(struct tape_device *device,
return rc;
}
static inline void
tape_cleanup_device(struct tape_device *device)
{
tapeblock_cleanup_device(device);
tapechar_cleanup_device(device);
device->discipline->cleanup_device(device);
tape_remove_minor(device);
tape_med_state_set(device, MS_UNKNOWN);
}
/*
* Set device offline.
*
......@@ -399,12 +409,13 @@ tape_generic_offline(struct tape_device *device)
switch (device->tape_state) {
case TS_INIT:
case TS_NOT_OPER:
spin_unlock_irq(get_ccwdev_lock(device->cdev));
break;
case TS_UNUSED:
tapeblock_cleanup_device(device);
tapechar_cleanup_device(device);
device->discipline->cleanup_device(device);
tape_remove_minor(device);
tape_state_set(device, TS_INIT);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
tape_cleanup_device(device);
break;
default:
DBF_EVENT(3, "(%08x): Set offline failed "
"- drive in use.\n",
......@@ -415,9 +426,6 @@ tape_generic_offline(struct tape_device *device)
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return -EBUSY;
}
spin_unlock_irq(get_ccwdev_lock(device->cdev));
tape_med_state_set(device, MS_UNKNOWN);
DBF_LH(3, "(%08x): Drive set offline.\n", device->cdev_id);
return 0;
......@@ -543,26 +551,12 @@ tape_generic_probe(struct ccw_device *cdev)
return 0;
}
/*
* Driverfs tape remove function.
*
* This function is called whenever the common I/O layer detects the device
* gone. This can happen at any time and we cannot refuse.
*/
void
tape_generic_remove(struct ccw_device *cdev)
static inline void
__tape_discard_requests(struct tape_device *device)
{
struct tape_device * device;
struct tape_request * request;
struct list_head * l, *n;
device = cdev->dev.driver_data;
DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev);
/*
* No more requests may be processed. So just post them as i/o errors.
*/
spin_lock_irq(get_ccwdev_lock(device->cdev));
list_for_each_safe(l, n, &device->req_queue) {
request = list_entry(l, struct tape_request, list);
if (request->status == TAPE_REQUEST_IN_IO)
......@@ -575,28 +569,66 @@ tape_generic_remove(struct ccw_device *cdev)
if (request->callback != NULL)
request->callback(request, request->callback_data);
}
}
/*
* Driverfs tape remove function.
*
* This function is called whenever the common I/O layer detects the device
* gone. This can happen at any time and we cannot refuse.
*/
void
tape_generic_remove(struct ccw_device *cdev)
{
struct tape_device * device;
device = cdev->dev.driver_data;
if (!device) {
PRINT_ERR("No device pointer in tape_generic_remove!\n");
return;
}
DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev);
if (device->tape_state != TS_UNUSED && device->tape_state != TS_INIT) {
DBF_EVENT(3, "(%08x): Drive in use vanished!\n",
device->cdev_id);
PRINT_WARN("(%s): Drive in use vanished - expect trouble!\n",
device->cdev->dev.bus_id);
PRINT_WARN("State was %i\n", device->tape_state);
device->tape_state = TS_NOT_OPER;
tapeblock_cleanup_device(device);
tapechar_cleanup_device(device);
device->discipline->cleanup_device(device);
tape_remove_minor(device);
spin_lock_irq(get_ccwdev_lock(device->cdev));
switch (device->tape_state) {
case TS_INIT:
tape_state_set(device, TS_NOT_OPER);
case TS_NOT_OPER:
/*
* Nothing to do.
*/
spin_unlock_irq(get_ccwdev_lock(device->cdev));
break;
case TS_UNUSED:
/*
* Need only to release the device.
*/
tape_state_set(device, TS_NOT_OPER);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
tape_cleanup_device(device);
break;
default:
/*
* There may be requests on the queue. We will not get
* an interrupt for a request that was running. So we
* just post them all as I/O errors.
*/
DBF_EVENT(3, "(%08x): Drive in use vanished!\n",
device->cdev_id);
PRINT_WARN("(%s): Drive in use vanished - "
"expect trouble!\n",
device->cdev->dev.bus_id);
PRINT_WARN("State was %i\n", device->tape_state);
tape_state_set(device, TS_NOT_OPER);
__tape_discard_requests(device);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
tape_cleanup_device(device);
}
device->tape_state = TS_NOT_OPER;
tape_med_state_set(device, MS_UNKNOWN);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (cdev->dev.driver_data != NULL) {
sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group);
cdev->dev.driver_data = tape_put_device(cdev->dev.driver_data);
}
}
/*
......@@ -1149,7 +1181,7 @@ tape_init (void)
#ifdef DBF_LIKE_HELL
debug_set_level(tape_dbf_area, 6);
#endif
DBF_EVENT(3, "tape init: ($Revision: 1.48 $)\n");
DBF_EVENT(3, "tape init: ($Revision: 1.49 $)\n");
tape_proc_init();
tapechar_init ();
tapeblock_init ();
......@@ -1174,7 +1206,7 @@ tape_exit(void)
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
MODULE_DESCRIPTION("Linux on zSeries channel attached "
"tape device driver ($Revision: 1.48 $)");
"tape device driver ($Revision: 1.49 $)");
MODULE_LICENSE("GPL");
module_init(tape_init);
......
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