Skip to content

Commit

Permalink
net: split out ndo_siowandev ioctl
Browse files Browse the repository at this point in the history
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: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Arnd Bergmann authored and David S. Miller committed Jul 27, 2021
1 parent a760537 commit ad7eab2
Show file tree
Hide file tree
Showing 28 changed files with 211 additions and 258 deletions.
7 changes: 7 additions & 0 deletions Documentation/networking/netdevices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 9 additions & 14 deletions drivers/char/pcmcia/synclink_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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,
};

Expand Down
19 changes: 8 additions & 11 deletions drivers/net/wan/c101.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wan/cosa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down
92 changes: 42 additions & 50 deletions drivers/net/wan/farsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -1784,24 +1784,23 @@ 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)
return -EINVAL;

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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -2020,55 +2019,48 @@ 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;

if (!capable(CAP_NET_ADMIN))
return -EPERM;

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

case IF_IFACE_SYNC_SERIAL:
case IF_IFACE_V35:
case IF_IFACE_V24:
case IF_IFACE_X21:
case IF_IFACE_X21D:
case IF_IFACE_T1:
case IF_IFACE_E1:
return fst_set_iface(card, port, ifr);

case IF_PROTO_RAW:
port->mode = FST_RAW;
return 0;
switch (ifs->type) {
case IF_GET_IFACE:
return fst_get_iface(card, port, ifs);

case IF_GET_PROTO:
if (port->mode == FST_RAW) {
ifr->ifr_settings.type = IF_PROTO_RAW;
return 0;
}
return hdlc_ioctl(dev, ifr, cmd);
case IF_IFACE_SYNC_SERIAL:
case IF_IFACE_V35:
case IF_IFACE_V24:
case IF_IFACE_X21:
case IF_IFACE_X21D:
case IF_IFACE_T1:
case IF_IFACE_E1:
return fst_set_iface(card, port, 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);
case IF_PROTO_RAW:
port->mode = FST_RAW;
return 0;

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

default:
/* Not one of ours. Pass through to HDLC package */
return hdlc_ioctl(dev, ifr, cmd);
port->mode = FST_GEN_HDLC;
dbg(DBG_IOCTL, "Passing this type to hdlc %x\n",
ifs->type);
return hdlc_ioctl(dev, ifs);
}
}

Expand Down Expand Up @@ -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,
};
Expand Down
19 changes: 8 additions & 11 deletions drivers/net/wan/fsl_ucc_hdlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,31 +674,28 @@ static irqreturn_t ucc_hdlc_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}

static int uhdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int uhdlc_ioctl(struct net_device *dev, struct if_settings *ifs)
{
const size_t size = sizeof(te1_settings);
te1_settings line;
struct ucc_hdlc_private *priv = netdev_priv(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_E1;
if (ifr->ifr_settings.size < size) {
ifr->ifr_settings.size = size; /* data size wanted */
ifs->type = IF_IFACE_E1;
if (ifs->size < size) {
ifs->size = size; /* data size wanted */
return -ENOBUFS;
}
memset(&line, 0, sizeof(line));
line.clock_type = priv->clocking;

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

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

Expand Down Expand Up @@ -1053,7 +1050,7 @@ static const struct net_device_ops uhdlc_ops = {
.ndo_open = uhdlc_open,
.ndo_stop = uhdlc_close,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = uhdlc_ioctl,
.ndo_siocwandev = uhdlc_ioctl,
.ndo_tx_timeout = uhdlc_tx_timeout,
};

Expand Down
9 changes: 3 additions & 6 deletions drivers/net/wan/hdlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,24 +196,21 @@ void hdlc_close(struct net_device *dev)
}
EXPORT_SYMBOL(hdlc_close);

int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
int hdlc_ioctl(struct net_device *dev, struct if_settings *ifs)
{
struct hdlc_proto *proto = first_proto;
int result;

if (cmd != SIOCWANDEV)
return -EINVAL;

if (dev_to_hdlc(dev)->proto) {
result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr);
result = dev_to_hdlc(dev)->proto->ioctl(dev, ifs);
if (result != -EINVAL)
return result;
}

/* Not handled by currently attached protocol (if any) */

while (proto) {
result = proto->ioctl(dev, ifr);
result = proto->ioctl(dev, ifs);
if (result != -EINVAL)
return result;
proto = proto->next;
Expand Down
Loading

0 comments on commit ad7eab2

Please sign in to comment.