Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa88861f authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Linus Torvalds
Browse files

[PATCH] s390: dasd reference counting



When using the dasd diag discipline, the base discipline module (eckd or fba)
can be unloaded, even though the dasd driver requires both discipline modules
(base and diag) to work correctly.

Implement reference counting for both base and diag discipline modules in
order to fix this.

Signed-off-by: default avatarPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 15c73691
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -156,7 +156,12 @@ dasd_state_known_to_new(struct dasd_device * device)
	/* disable extended error reporting for this device */
	dasd_disable_eer(device);
	/* Forget the discipline information. */
	if (device->discipline)
		module_put(device->discipline->owner);
	device->discipline = NULL;
	if (device->base_discipline)
		module_put(device->base_discipline->owner);
	device->base_discipline = NULL;
	device->state = DASD_STATE_NEW;

	dasd_free_queue(device);
@@ -1880,9 +1885,10 @@ dasd_generic_remove (struct ccw_device *cdev)
 */
int
dasd_generic_set_online (struct ccw_device *cdev,
			 struct dasd_discipline *discipline)
			 struct dasd_discipline *base_discipline)

{
	struct dasd_discipline *discipline;
	struct dasd_device *device;
	int rc;

@@ -1890,6 +1896,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
	if (IS_ERR(device))
		return PTR_ERR(device);

	discipline = base_discipline;
	if (device->features & DASD_FEATURE_USEDIAG) {
	  	if (!dasd_diag_discipline_pointer) {
		        printk (KERN_WARNING
@@ -1901,6 +1908,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
		}
		discipline = dasd_diag_discipline_pointer;
	}
	if (!try_module_get(base_discipline->owner)) {
		dasd_delete_device(device);
		return -EINVAL;
	}
	if (!try_module_get(discipline->owner)) {
		module_put(base_discipline->owner);
		dasd_delete_device(device);
		return -EINVAL;
	}
	device->base_discipline = base_discipline;
	device->discipline = discipline;

	rc = discipline->check_device(device);
@@ -1909,6 +1926,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
			"dasd_generic couldn't online device %s "
			"with discipline %s rc=%i\n",
			cdev->dev.bus_id, discipline->name, rc);
		module_put(discipline->owner);
		module_put(base_discipline->owner);
		dasd_delete_device(device);
		return rc;
	}
+1 −0
Original line number Diff line number Diff line
@@ -321,6 +321,7 @@ struct dasd_device {

	/* Device discipline stuff. */
	struct dasd_discipline *discipline;
	struct dasd_discipline *base_discipline;
	char *private;

	/* Device state and target state. */