Commit ad7eab2a authored by Arnd Bergmann's avatar Arnd Bergmann Committed by David S. Miller
Browse files

net: split out ndo_siowandev ioctl



In order to further reduce the scope of ndo_do_ioctl(), move
out the SIOCWANDEV handling into a new network device operation
function.

Adjust the prototype to only pass the if_settings sub-structure
in place of the ifreq, and remove the redundant 'cmd' argument
in the process.

Cc: Krzysztof Halasa <khc@pm.waw.pl>
Cc: "Jan \"Yenya\" Kasprzak" <kas@fi.muni.cz>
Cc: Kevin Curtis <kevin.curtis@farsite.co.uk>
Cc: Zhao Qiang <qiang.zhao@nxp.com>
Cc: Martin Schiller <ms@dev.tdt.de>
Cc: Jiri Slaby <jirislaby@kernel.org>
Cc: linux-x25@vger.kernel.org
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a7605370
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -222,6 +222,13 @@ ndo_do_ioctl:
	Synchronization: rtnl_lock() semaphore.
	Context: process

ndo_siocwandev:
	Synchronization: rtnl_lock() semaphore.
	Context: process

	Used by the drivers/net/wan framework to handle
	the SIOCWANDEV ioctl with the if_settings structure.

ndo_siocdevprivate:
	Synchronization: rtnl_lock() semaphore.
	Context: process
+9 −14
Original line number Diff line number Diff line
@@ -4050,16 +4050,15 @@ static int hdlcdev_close(struct net_device *dev)
 * called by network layer to process IOCTL call to network device
 *
 * dev  pointer to network device structure
 * ifr  pointer to network interface request structure
 * cmd  IOCTL command code
 * ifs  pointer to network interface settings structure
 *
 * returns 0 if success, otherwise error code
 */
static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int hdlcdev_wan_ioctl(struct net_device *dev, struct if_settings *ifs)
{
	const size_t size = sizeof(sync_serial_settings);
	sync_serial_settings new_line;
	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
	sync_serial_settings __user *line = ifs->ifs_ifsu.sync;
	MGSLPC_INFO *info = dev_to_port(dev);
	unsigned int flags;

@@ -4070,17 +4069,14 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	if (info->port.count)
		return -EBUSY;

	if (cmd != SIOCWANDEV)
		return hdlc_ioctl(dev, ifr, cmd);

	memset(&new_line, 0, size);

	switch(ifr->ifr_settings.type) {
	switch (ifs->type) {
	case IF_GET_IFACE: /* return current sync_serial_settings */

		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
		if (ifr->ifr_settings.size < size) {
			ifr->ifr_settings.size = size; /* data size wanted */
		ifs->type = IF_IFACE_SYNC_SERIAL;
		if (ifs->size < size) {
			ifs->size = size; /* data size wanted */
			return -ENOBUFS;
		}

@@ -4148,9 +4144,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
			tty_kref_put(tty);
		}
		return 0;

	default:
		return hdlc_ioctl(dev, ifr, cmd);
		return hdlc_ioctl(dev, ifs);
	}
}

@@ -4225,7 +4220,7 @@ static const struct net_device_ops hdlcdev_ops = {
	.ndo_open       = hdlcdev_open,
	.ndo_stop       = hdlcdev_close,
	.ndo_start_xmit = hdlc_start_xmit,
	.ndo_do_ioctl   = hdlcdev_ioctl,
	.ndo_siocwandev = hdlcdev_wan_ioctl,
	.ndo_tx_timeout = hdlcdev_tx_timeout,
};

+8 −11
Original line number Diff line number Diff line
@@ -228,21 +228,18 @@ static int c101_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
	return -EOPNOTSUPP;
}

static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int c101_ioctl(struct net_device *dev, struct if_settings *ifs)
{
	const size_t size = sizeof(sync_serial_settings);
	sync_serial_settings new_line;
	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
	sync_serial_settings __user *line = ifs->ifs_ifsu.sync;
	port_t *port = dev_to_port(dev);

	if (cmd != SIOCWANDEV)
		return hdlc_ioctl(dev, ifr, cmd);

	switch (ifr->ifr_settings.type) {
	switch (ifs->type) {
	case IF_GET_IFACE:
		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
		if (ifr->ifr_settings.size < size) {
			ifr->ifr_settings.size = size; /* data size wanted */
		ifs->type = IF_IFACE_SYNC_SERIAL;
		if (ifs->size < size) {
			ifs->size = size; /* data size wanted */
			return -ENOBUFS;
		}
		if (copy_to_user(line, &port->settings, size))
@@ -270,7 +267,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
		return 0;

	default:
		return hdlc_ioctl(dev, ifr, cmd);
		return hdlc_ioctl(dev, ifs);
	}
}

@@ -295,7 +292,7 @@ static const struct net_device_ops c101_ops = {
	.ndo_open       = c101_open,
	.ndo_stop       = c101_close,
	.ndo_start_xmit = hdlc_start_xmit,
	.ndo_do_ioctl   = c101_ioctl,
	.ndo_siocwandev = c101_ioctl,
	.ndo_siocdevprivate = c101_siocdevprivate,
};

+1 −1
Original line number Diff line number Diff line
@@ -414,7 +414,7 @@ static const struct net_device_ops cosa_ops = {
	.ndo_open       = cosa_net_open,
	.ndo_stop       = cosa_net_close,
	.ndo_start_xmit = hdlc_start_xmit,
	.ndo_do_ioctl   = hdlc_ioctl,
	.ndo_siocwandev = hdlc_ioctl,
	.ndo_tx_timeout = cosa_net_timeout,
};

+42 −50
Original line number Diff line number Diff line
@@ -1784,16 +1784,15 @@ gather_conf_info(struct fst_card_info *card, struct fst_port_info *port,

static int
fst_set_iface(struct fst_card_info *card, struct fst_port_info *port,
	      struct ifreq *ifr)
	      struct if_settings *ifs)
{
	sync_serial_settings sync;
	int i;

	if (ifr->ifr_settings.size != sizeof(sync))
	if (ifs->size != sizeof(sync))
		return -ENOMEM;

	if (copy_from_user
	    (&sync, ifr->ifr_settings.ifs_ifsu.sync, sizeof(sync)))
	if (copy_from_user(&sync, ifs->ifs_ifsu.sync, sizeof(sync)))
		return -EFAULT;

	if (sync.loopback)
@@ -1801,7 +1800,7 @@ fst_set_iface(struct fst_card_info *card, struct fst_port_info *port,

	i = port->index;

	switch (ifr->ifr_settings.type) {
	switch (ifs->type) {
	case IF_IFACE_V35:
		FST_WRW(card, portConfig[i].lineInterface, V35);
		port->hwif = V35;
@@ -1857,7 +1856,7 @@ fst_set_iface(struct fst_card_info *card, struct fst_port_info *port,

static int
fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
	      struct ifreq *ifr)
	      struct if_settings *ifs)
{
	sync_serial_settings sync;
	int i;
@@ -1868,29 +1867,29 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
	 */
	switch (port->hwif) {
	case E1:
		ifr->ifr_settings.type = IF_IFACE_E1;
		ifs->type = IF_IFACE_E1;
		break;
	case T1:
		ifr->ifr_settings.type = IF_IFACE_T1;
		ifs->type = IF_IFACE_T1;
		break;
	case V35:
		ifr->ifr_settings.type = IF_IFACE_V35;
		ifs->type = IF_IFACE_V35;
		break;
	case V24:
		ifr->ifr_settings.type = IF_IFACE_V24;
		ifs->type = IF_IFACE_V24;
		break;
	case X21D:
		ifr->ifr_settings.type = IF_IFACE_X21D;
		ifs->type = IF_IFACE_X21D;
		break;
	case X21:
	default:
		ifr->ifr_settings.type = IF_IFACE_X21;
		ifs->type = IF_IFACE_X21;
		break;
	}
	if (ifr->ifr_settings.size == 0)
	if (!ifs->size)
		return 0;	/* only type requested */

	if (ifr->ifr_settings.size < sizeof(sync))
	if (ifs->size < sizeof(sync))
		return -ENOMEM;

	i = port->index;
@@ -1901,10 +1900,10 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
	    INTCLK ? CLOCK_INT : CLOCK_EXT;
	sync.loopback = 0;

	if (copy_to_user(ifr->ifr_settings.ifs_ifsu.sync, &sync, sizeof(sync)))
	if (copy_to_user(ifs->ifs_ifsu.sync, &sync, sizeof(sync)))
		return -EFAULT;

	ifr->ifr_settings.size = sizeof(sync);
	ifs->size = sizeof(sync);
	return 0;
}

@@ -2020,12 +2019,12 @@ fst_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data,
}

static int
fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
fst_ioctl(struct net_device *dev, struct if_settings *ifs)
{
	struct fst_card_info *card;
	struct fst_port_info *port;

	dbg(DBG_IOCTL, "ioctl: %x, %x\n", cmd, ifr->ifr_settings.type);
	dbg(DBG_IOCTL, "SIOCDEVPRIVATE, %x\n", ifs->type);

	port = dev_to_port(dev);
	card = port->card;
@@ -2033,11 +2032,9 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	switch (cmd) {
	case SIOCWANDEV:
		switch (ifr->ifr_settings.type) {
	switch (ifs->type) {
	case IF_GET_IFACE:
			return fst_get_iface(card, port, ifr);
		return fst_get_iface(card, port, ifs);

	case IF_IFACE_SYNC_SERIAL:
	case IF_IFACE_V35:
@@ -2046,7 +2043,7 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	case IF_IFACE_X21D:
	case IF_IFACE_T1:
	case IF_IFACE_E1:
			return fst_set_iface(card, port, ifr);
		return fst_set_iface(card, port, ifs);

	case IF_PROTO_RAW:
		port->mode = FST_RAW;
@@ -2054,21 +2051,16 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

	case IF_GET_PROTO:
		if (port->mode == FST_RAW) {
				ifr->ifr_settings.type = IF_PROTO_RAW;
			ifs->type = IF_PROTO_RAW;
			return 0;
		}
			return hdlc_ioctl(dev, ifr, cmd);
		return hdlc_ioctl(dev, ifs);

	default:
		port->mode = FST_GEN_HDLC;
		dbg(DBG_IOCTL, "Passing this type to hdlc %x\n",
			    ifr->ifr_settings.type);
			return hdlc_ioctl(dev, ifr, cmd);
		}

	default:
		/* Not one of ours. Pass through to HDLC package */
		return hdlc_ioctl(dev, ifr, cmd);
		    ifs->type);
		return hdlc_ioctl(dev, ifs);
	}
}

@@ -2328,7 +2320,7 @@ static const struct net_device_ops fst_ops = {
	.ndo_open       = fst_open,
	.ndo_stop       = fst_close,
	.ndo_start_xmit = hdlc_start_xmit,
	.ndo_do_ioctl	= fst_ioctl,
	.ndo_siocwandev	= fst_ioctl,
	.ndo_siocdevprivate = fst_siocdevprivate,
	.ndo_tx_timeout = fst_tx_timeout,
};
Loading