aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2006-02-20 21:28:13 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-20 23:00:12 -0500
commitaa88861fc3184a7d830954661dd281de4ae8d2ba (patch)
treeac1ff810dd3b8426c727aba3ea57bb6381978f7d /drivers/s390
parent15c73691780252a5571bfa7902b4dc227ec66c84 (diff)
[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: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c21
-rw-r--r--drivers/s390/block/dasd_int.h1
2 files changed, 21 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 08c88fcd8963..06bb992a4c6c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -156,7 +156,12 @@ dasd_state_known_to_new(struct dasd_device * device)
156 /* disable extended error reporting for this device */ 156 /* disable extended error reporting for this device */
157 dasd_disable_eer(device); 157 dasd_disable_eer(device);
158 /* Forget the discipline information. */ 158 /* Forget the discipline information. */
159 if (device->discipline)
160 module_put(device->discipline->owner);
159 device->discipline = NULL; 161 device->discipline = NULL;
162 if (device->base_discipline)
163 module_put(device->base_discipline->owner);
164 device->base_discipline = NULL;
160 device->state = DASD_STATE_NEW; 165 device->state = DASD_STATE_NEW;
161 166
162 dasd_free_queue(device); 167 dasd_free_queue(device);
@@ -1880,9 +1885,10 @@ dasd_generic_remove (struct ccw_device *cdev)
1880 */ 1885 */
1881int 1886int
1882dasd_generic_set_online (struct ccw_device *cdev, 1887dasd_generic_set_online (struct ccw_device *cdev,
1883 struct dasd_discipline *discipline) 1888 struct dasd_discipline *base_discipline)
1884 1889
1885{ 1890{
1891 struct dasd_discipline *discipline;
1886 struct dasd_device *device; 1892 struct dasd_device *device;
1887 int rc; 1893 int rc;
1888 1894
@@ -1890,6 +1896,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
1890 if (IS_ERR(device)) 1896 if (IS_ERR(device))
1891 return PTR_ERR(device); 1897 return PTR_ERR(device);
1892 1898
1899 discipline = base_discipline;
1893 if (device->features & DASD_FEATURE_USEDIAG) { 1900 if (device->features & DASD_FEATURE_USEDIAG) {
1894 if (!dasd_diag_discipline_pointer) { 1901 if (!dasd_diag_discipline_pointer) {
1895 printk (KERN_WARNING 1902 printk (KERN_WARNING
@@ -1901,6 +1908,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
1901 } 1908 }
1902 discipline = dasd_diag_discipline_pointer; 1909 discipline = dasd_diag_discipline_pointer;
1903 } 1910 }
1911 if (!try_module_get(base_discipline->owner)) {
1912 dasd_delete_device(device);
1913 return -EINVAL;
1914 }
1915 if (!try_module_get(discipline->owner)) {
1916 module_put(base_discipline->owner);
1917 dasd_delete_device(device);
1918 return -EINVAL;
1919 }
1920 device->base_discipline = base_discipline;
1904 device->discipline = discipline; 1921 device->discipline = discipline;
1905 1922
1906 rc = discipline->check_device(device); 1923 rc = discipline->check_device(device);
@@ -1909,6 +1926,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
1909 "dasd_generic couldn't online device %s " 1926 "dasd_generic couldn't online device %s "
1910 "with discipline %s rc=%i\n", 1927 "with discipline %s rc=%i\n",
1911 cdev->dev.bus_id, discipline->name, rc); 1928 cdev->dev.bus_id, discipline->name, rc);
1929 module_put(discipline->owner);
1930 module_put(base_discipline->owner);
1912 dasd_delete_device(device); 1931 dasd_delete_device(device);
1913 return rc; 1932 return rc;
1914 } 1933 }
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1b08fa13fd2..5efac1b97ece 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -321,6 +321,7 @@ struct dasd_device {
321 321
322 /* Device discipline stuff. */ 322 /* Device discipline stuff. */
323 struct dasd_discipline *discipline; 323 struct dasd_discipline *discipline;
324 struct dasd_discipline *base_discipline;
324 char *private; 325 char *private;
325 326
326 /* Device state and target state. */ 327 /* Device state and target state. */