static int ctcm_new_device()

in net/ctcm_main.c [1482:1596]


static int ctcm_new_device(struct ccwgroup_device *cgdev)
{
	char read_id[CTCM_ID_SIZE];
	char write_id[CTCM_ID_SIZE];
	int direction;
	enum ctcm_channel_types type;
	struct ctcm_priv *priv;
	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) {
		result = -ENODEV;
		goto out_err_result;
	}

	cdev0 = cgdev->cdev[0];
	cdev1 = cgdev->cdev[1];

	type = get_channel_type(&cdev0->id);

	snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
	snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));

	ret = add_channel(cdev0, type, priv);
	if (ret) {
		result = ret;
		goto out_err_result;
	}
	ret = add_channel(cdev1, type, priv);
	if (ret) {
		result = ret;
		goto out_remove_channel1;
	}

	ret = ccw_device_set_online(cdev0);
	if (ret != 0) {
		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) {
		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) {
		result = -ENODEV;
		goto out_ccw2;
	}

	for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
		priv->channel[direction] =
			channel_get(type, direction == CTCM_READ ?
				read_id : write_id, direction);
		if (priv->channel[direction] == NULL) {
			if (direction == CTCM_WRITE)
				channel_free(priv->channel[CTCM_READ]);
			result = -ENODEV;
			goto out_dev;
		}
		priv->channel[direction]->netdev = dev;
		priv->channel[direction]->protocol = priv->protocol;
		priv->channel[direction]->max_bufsize = priv->buffer_size;
	}
	/* sysfs magic */
	SET_NETDEV_DEV(dev, &cgdev->dev);

	if (register_netdev(dev)) {
		result = -ENODEV;
		goto out_dev;
	}

	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));

	dev_info(&dev->dev,
		"setup OK : r/w = %s/%s, protocol : %d\n",
			priv->channel[CTCM_READ]->id,
			priv->channel[CTCM_WRITE]->id, priv->protocol);

	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
		"setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
			priv->channel[CTCM_READ]->id,
			priv->channel[CTCM_WRITE]->id, priv->protocol);

	return 0;
out_dev:
	ctcm_free_netdevice(dev);
out_ccw2:
	ccw_device_set_offline(cgdev->cdev[1]);
out_ccw1:
	ccw_device_set_offline(cgdev->cdev[0]);
out_remove_channel2:
	readc = channel_get(type, read_id, CTCM_READ);
	channel_remove(readc);
out_remove_channel1:
	writec = channel_get(type, write_id, CTCM_WRITE);
	channel_remove(writec);
out_err_result:
	return result;
}