|
@@ -1530,11 +1530,16 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|
|
struct net_device *dev;
|
|
|
struct ccw_device *cdev0;
|
|
|
struct ccw_device *cdev1;
|
|
|
+ struct channel *readc;
|
|
|
+ struct channel *writec;
|
|
|
int ret;
|
|
|
+ int result;
|
|
|
|
|
|
priv = dev_get_drvdata(&cgdev->dev);
|
|
|
- if (!priv)
|
|
|
- return -ENODEV;
|
|
|
+ if (!priv) {
|
|
|
+ result = -ENODEV;
|
|
|
+ goto out_err_result;
|
|
|
+ }
|
|
|
|
|
|
cdev0 = cgdev->cdev[0];
|
|
|
cdev1 = cgdev->cdev[1];
|
|
@@ -1545,31 +1550,40 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|
|
snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
|
|
|
|
|
|
ret = add_channel(cdev0, type, priv);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ if (ret) {
|
|
|
+ result = ret;
|
|
|
+ goto out_err_result;
|
|
|
+ }
|
|
|
ret = add_channel(cdev1, type, priv);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ if (ret) {
|
|
|
+ result = ret;
|
|
|
+ goto out_remove_channel1;
|
|
|
+ }
|
|
|
|
|
|
ret = ccw_device_set_online(cdev0);
|
|
|
if (ret != 0) {
|
|
|
- /* may be ok to fail now - can be done later */
|
|
|
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
|
|
|
"%s(%s) set_online rc=%d",
|
|
|
CTCM_FUNTAIL, read_id, ret);
|
|
|
+ result = -EIO;
|
|
|
+ goto out_remove_channel2;
|
|
|
}
|
|
|
|
|
|
ret = ccw_device_set_online(cdev1);
|
|
|
if (ret != 0) {
|
|
|
- /* may be ok to fail now - can be done later */
|
|
|
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
|
|
|
"%s(%s) set_online rc=%d",
|
|
|
CTCM_FUNTAIL, write_id, ret);
|
|
|
+
|
|
|
+ result = -EIO;
|
|
|
+ goto out_ccw1;
|
|
|
}
|
|
|
|
|
|
dev = ctcm_init_netdevice(priv);
|
|
|
- if (dev == NULL)
|
|
|
- goto out;
|
|
|
+ if (dev == NULL) {
|
|
|
+ result = -ENODEV;
|
|
|
+ goto out_ccw2;
|
|
|
+ }
|
|
|
|
|
|
for (direction = READ; direction <= WRITE; direction++) {
|
|
|
priv->channel[direction] =
|
|
@@ -1587,12 +1601,14 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|
|
/* sysfs magic */
|
|
|
SET_NETDEV_DEV(dev, &cgdev->dev);
|
|
|
|
|
|
- if (register_netdev(dev))
|
|
|
- goto out_dev;
|
|
|
+ if (register_netdev(dev)) {
|
|
|
+ result = -ENODEV;
|
|
|
+ goto out_dev;
|
|
|
+ }
|
|
|
|
|
|
if (ctcm_add_attributes(&cgdev->dev)) {
|
|
|
- unregister_netdev(dev);
|
|
|
- goto out_dev;
|
|
|
+ result = -ENODEV;
|
|
|
+ goto out_unregister;
|
|
|
}
|
|
|
|
|
|
strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
|
|
@@ -1608,13 +1624,22 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|
|
priv->channel[WRITE]->id, priv->protocol);
|
|
|
|
|
|
return 0;
|
|
|
+out_unregister:
|
|
|
+ unregister_netdev(dev);
|
|
|
out_dev:
|
|
|
ctcm_free_netdevice(dev);
|
|
|
-out:
|
|
|
+out_ccw2:
|
|
|
ccw_device_set_offline(cgdev->cdev[1]);
|
|
|
+out_ccw1:
|
|
|
ccw_device_set_offline(cgdev->cdev[0]);
|
|
|
-
|
|
|
- return -ENODEV;
|
|
|
+out_remove_channel2:
|
|
|
+ readc = channel_get(type, read_id, READ);
|
|
|
+ channel_remove(readc);
|
|
|
+out_remove_channel1:
|
|
|
+ writec = channel_get(type, write_id, WRITE);
|
|
|
+ channel_remove(writec);
|
|
|
+out_err_result:
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|