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) ...@@ -113,6 +113,7 @@ tape_34xx_work_handler(void *data)
switch(p->op) { switch(p->op) {
case TO_MSEN: case TO_MSEN:
tape_34xx_medium_sense(p->device); tape_34xx_medium_sense(p->device);
break;
default: default:
DBF_EVENT(3, "T34XX: internal error: unknown work\n"); DBF_EVENT(3, "T34XX: internal error: unknown work\n");
} }
...@@ -1342,7 +1343,7 @@ tape_34xx_init (void) ...@@ -1342,7 +1343,7 @@ tape_34xx_init (void)
{ {
int rc; 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. */ /* Register driver for 3480/3490 tapes. */
rc = ccw_driver_register(&tape_34xx_driver); rc = ccw_driver_register(&tape_34xx_driver);
if (rc) if (rc)
...@@ -1361,7 +1362,7 @@ tape_34xx_exit(void) ...@@ -1361,7 +1362,7 @@ tape_34xx_exit(void)
MODULE_DEVICE_TABLE(ccw, tape_34xx_ids); MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH"); MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape " MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
"device driver ($Revision: 1.19 $)"); "device driver ($Revision: 1.20 $)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(tape_34xx_init); module_init(tape_34xx_init);
......
/* /*
* (C) Copyright IBM Corp. 2004 * (C) Copyright IBM Corp. 2004
* tape_class.c ($Revision: 1.6 $) * tape_class.c ($Revision: 1.8 $)
* *
* Tape class device support * Tape class device support
* *
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
MODULE_DESCRIPTION( MODULE_DESCRIPTION(
"(C) Copyright IBM Corp. 2004 All Rights Reserved.\n" "(C) Copyright IBM Corp. 2004 All Rights Reserved.\n"
"tape_class.c ($Revision: 1.6 $)" "tape_class.c ($Revision: 1.8 $)"
); );
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -85,7 +85,7 @@ struct tape_class_device *register_tape_dev( ...@@ -85,7 +85,7 @@ struct tape_class_device *register_tape_dev(
return tcd; return tcd;
fail_with_cdev: fail_with_cdev:
cdev_del(&tcd->char_device); cdev_del(tcd->char_device);
fail_with_tcd: fail_with_tcd:
kfree(tcd); kfree(tcd);
......
...@@ -377,6 +377,16 @@ tape_generic_online(struct tape_device *device, ...@@ -377,6 +377,16 @@ tape_generic_online(struct tape_device *device,
return rc; 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. * Set device offline.
* *
...@@ -399,12 +409,13 @@ tape_generic_offline(struct tape_device *device) ...@@ -399,12 +409,13 @@ tape_generic_offline(struct tape_device *device)
switch (device->tape_state) { switch (device->tape_state) {
case TS_INIT: case TS_INIT:
case TS_NOT_OPER: case TS_NOT_OPER:
spin_unlock_irq(get_ccwdev_lock(device->cdev));
break; break;
case TS_UNUSED: case TS_UNUSED:
tapeblock_cleanup_device(device); tape_state_set(device, TS_INIT);
tapechar_cleanup_device(device); spin_unlock_irq(get_ccwdev_lock(device->cdev));
device->discipline->cleanup_device(device); tape_cleanup_device(device);
tape_remove_minor(device); break;
default: default:
DBF_EVENT(3, "(%08x): Set offline failed " DBF_EVENT(3, "(%08x): Set offline failed "
"- drive in use.\n", "- drive in use.\n",
...@@ -415,9 +426,6 @@ tape_generic_offline(struct tape_device *device) ...@@ -415,9 +426,6 @@ tape_generic_offline(struct tape_device *device)
spin_unlock_irq(get_ccwdev_lock(device->cdev)); spin_unlock_irq(get_ccwdev_lock(device->cdev));
return -EBUSY; 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); DBF_LH(3, "(%08x): Drive set offline.\n", device->cdev_id);
return 0; return 0;
...@@ -543,26 +551,12 @@ tape_generic_probe(struct ccw_device *cdev) ...@@ -543,26 +551,12 @@ tape_generic_probe(struct ccw_device *cdev)
return 0; return 0;
} }
/* static inline void
* Driverfs tape remove function. __tape_discard_requests(struct tape_device *device)
*
* 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;
struct tape_request * request; struct tape_request * request;
struct list_head * l, *n; 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) { list_for_each_safe(l, n, &device->req_queue) {
request = list_entry(l, struct tape_request, list); request = list_entry(l, struct tape_request, list);
if (request->status == TAPE_REQUEST_IN_IO) if (request->status == TAPE_REQUEST_IN_IO)
...@@ -575,28 +569,66 @@ tape_generic_remove(struct ccw_device *cdev) ...@@ -575,28 +569,66 @@ tape_generic_remove(struct ccw_device *cdev)
if (request->callback != NULL) if (request->callback != NULL)
request->callback(request, request->callback_data); 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) { spin_lock_irq(get_ccwdev_lock(device->cdev));
DBF_EVENT(3, "(%08x): Drive in use vanished!\n", switch (device->tape_state) {
device->cdev_id); case TS_INIT:
PRINT_WARN("(%s): Drive in use vanished - expect trouble!\n", tape_state_set(device, TS_NOT_OPER);
device->cdev->dev.bus_id); case TS_NOT_OPER:
PRINT_WARN("State was %i\n", device->tape_state); /*
device->tape_state = TS_NOT_OPER; * Nothing to do.
tapeblock_cleanup_device(device); */
tapechar_cleanup_device(device); spin_unlock_irq(get_ccwdev_lock(device->cdev));
device->discipline->cleanup_device(device); break;
tape_remove_minor(device); 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) { if (cdev->dev.driver_data != NULL) {
sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group);
cdev->dev.driver_data = tape_put_device(cdev->dev.driver_data); cdev->dev.driver_data = tape_put_device(cdev->dev.driver_data);
} }
} }
/* /*
...@@ -1149,7 +1181,7 @@ tape_init (void) ...@@ -1149,7 +1181,7 @@ tape_init (void)
#ifdef DBF_LIKE_HELL #ifdef DBF_LIKE_HELL
debug_set_level(tape_dbf_area, 6); debug_set_level(tape_dbf_area, 6);
#endif #endif
DBF_EVENT(3, "tape init: ($Revision: 1.48 $)\n"); DBF_EVENT(3, "tape init: ($Revision: 1.49 $)\n");
tape_proc_init(); tape_proc_init();
tapechar_init (); tapechar_init ();
tapeblock_init (); tapeblock_init ();
...@@ -1174,7 +1206,7 @@ tape_exit(void) ...@@ -1174,7 +1206,7 @@ tape_exit(void)
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
MODULE_DESCRIPTION("Linux on zSeries channel attached " MODULE_DESCRIPTION("Linux on zSeries channel attached "
"tape device driver ($Revision: 1.48 $)"); "tape device driver ($Revision: 1.49 $)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(tape_init); 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