aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-12-25 07:39:09 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 07:39:08 -0500
commit90ed2b692fa75272d7395c4e4c2de4423d52f506 (patch)
tree62b2d1a0595b73718dd0d39d331a4c3c9fa91f81 /drivers/s390
parent5fb6b8544d9ccd2ed478af777f9e99e342eb8886 (diff)
[S390] cio: Dont fail probe for I/O subchannels.
If we fail the probe for an I/O subchannel, we won't be able to unregister it again since there are no sch_event() callbacks for unbound subchannels. Just succeed the probe in any case and schedule unregistering the subchannel. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/cio.h1
-rw-r--r--drivers/s390/cio/device.c43
2 files changed, 32 insertions, 12 deletions
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 0fb24784e925..5db887e8f032 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -82,6 +82,7 @@ struct subchannel {
82 struct device dev; /* entry in device tree */ 82 struct device dev; /* entry in device tree */
83 struct css_driver *driver; 83 struct css_driver *driver;
84 void *private; /* private per subchannel type data */ 84 void *private; /* private per subchannel type data */
85 struct work_struct work;
85} __attribute__ ((aligned(8))); 86} __attribute__ ((aligned(8)));
86 87
87#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */ 88#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 91acea10840d..2d31f06a913e 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1196,6 +1196,30 @@ static void io_subchannel_init_fields(struct subchannel *sch)
1196 sch->schib.mba = 0; 1196 sch->schib.mba = 0;
1197} 1197}
1198 1198
1199static void io_subchannel_do_unreg(struct work_struct *work)
1200{
1201 struct subchannel *sch;
1202
1203 sch = container_of(work, struct subchannel, work);
1204 css_sch_device_unregister(sch);
1205 /* Reset intparm to zeroes. */
1206 sch->schib.pmcw.intparm = 0;
1207 cio_modify(sch);
1208 put_device(&sch->dev);
1209}
1210
1211/* Schedule unregister if we have no cdev. */
1212static void io_subchannel_schedule_removal(struct subchannel *sch)
1213{
1214 get_device(&sch->dev);
1215 INIT_WORK(&sch->work, io_subchannel_do_unreg);
1216 queue_work(slow_path_wq, &sch->work);
1217}
1218
1219/*
1220 * Note: We always return 0 so that we bind to the device even on error.
1221 * This is needed so that our remove function is called on unregister.
1222 */
1199static int io_subchannel_probe(struct subchannel *sch) 1223static int io_subchannel_probe(struct subchannel *sch)
1200{ 1224{
1201 struct ccw_device *cdev; 1225 struct ccw_device *cdev;
@@ -1238,14 +1262,12 @@ static int io_subchannel_probe(struct subchannel *sch)
1238 rc = sysfs_create_group(&sch->dev.kobj, 1262 rc = sysfs_create_group(&sch->dev.kobj,
1239 &io_subchannel_attr_group); 1263 &io_subchannel_attr_group);
1240 if (rc) 1264 if (rc)
1241 return rc; 1265 goto out_schedule;
1242 /* Allocate I/O subchannel private data. */ 1266 /* Allocate I/O subchannel private data. */
1243 sch->private = kzalloc(sizeof(struct io_subchannel_private), 1267 sch->private = kzalloc(sizeof(struct io_subchannel_private),
1244 GFP_KERNEL | GFP_DMA); 1268 GFP_KERNEL | GFP_DMA);
1245 if (!sch->private) { 1269 if (!sch->private)
1246 rc = -ENOMEM;
1247 goto out_err; 1270 goto out_err;
1248 }
1249 /* 1271 /*
1250 * First check if a fitting device may be found amongst the 1272 * First check if a fitting device may be found amongst the
1251 * disconnected devices or in the orphanage. 1273 * disconnected devices or in the orphanage.
@@ -1269,24 +1291,21 @@ static int io_subchannel_probe(struct subchannel *sch)
1269 return 0; 1291 return 0;
1270 } 1292 }
1271 cdev = io_subchannel_create_ccwdev(sch); 1293 cdev = io_subchannel_create_ccwdev(sch);
1272 if (IS_ERR(cdev)) { 1294 if (IS_ERR(cdev))
1273 rc = PTR_ERR(cdev);
1274 goto out_err; 1295 goto out_err;
1275 }
1276 rc = io_subchannel_recog(cdev, sch); 1296 rc = io_subchannel_recog(cdev, sch);
1277 if (rc) { 1297 if (rc) {
1278 spin_lock_irqsave(sch->lock, flags); 1298 spin_lock_irqsave(sch->lock, flags);
1279 sch_set_cdev(sch, NULL); 1299 io_subchannel_recog_done(cdev);
1280 spin_unlock_irqrestore(sch->lock, flags); 1300 spin_unlock_irqrestore(sch->lock, flags);
1281 if (cdev->dev.release)
1282 cdev->dev.release(&cdev->dev);
1283 goto out_err;
1284 } 1301 }
1285 return 0; 1302 return 0;
1286out_err: 1303out_err:
1287 kfree(sch->private); 1304 kfree(sch->private);
1288 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); 1305 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
1289 return rc; 1306out_schedule:
1307 io_subchannel_schedule_removal(sch);
1308 return 0;
1290} 1309}
1291 1310
1292static int 1311static int