Skip to content

Commit 877bd86

Browse files
Ming Leidavem330
authored andcommitted
usbnet: introduce usbnet 3 command helpers
This patch introduces the below 3 usb command helpers: usbnet_read_cmd / usbnet_write_cmd / usbnet_write_cmd_async so that each low level driver doesn't need to implement them by itself, and the dma buffer allocation for usb transfer and runtime PM things can be handled just in one place. Acked-by: Oliver Neukum <[email protected]> Signed-off-by: Ming Lei <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 02c38d0 commit 877bd86

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

drivers/net/usb/usbnet.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,138 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
16101610
}
16111611
EXPORT_SYMBOL(usbnet_device_suggests_idle);
16121612

1613+
/*-------------------------------------------------------------------------*/
1614+
int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1615+
u16 value, u16 index, void *data, u16 size)
1616+
{
1617+
void *buf = NULL;
1618+
int err = -ENOMEM;
1619+
1620+
netdev_dbg(dev->net, "usbnet_read_cmd cmd=0x%02x reqtype=%02x"
1621+
" value=0x%04x index=0x%04x size=%d\n",
1622+
cmd, reqtype, value, index, size);
1623+
1624+
if (data) {
1625+
buf = kmalloc(size, GFP_KERNEL);
1626+
if (!buf)
1627+
goto out;
1628+
}
1629+
1630+
err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
1631+
cmd, reqtype, value, index, buf, size,
1632+
USB_CTRL_GET_TIMEOUT);
1633+
if (err > 0 && err <= size)
1634+
memcpy(data, buf, err);
1635+
kfree(buf);
1636+
out:
1637+
return err;
1638+
}
1639+
EXPORT_SYMBOL_GPL(usbnet_read_cmd);
1640+
1641+
int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1642+
u16 value, u16 index, const void *data, u16 size)
1643+
{
1644+
void *buf = NULL;
1645+
int err = -ENOMEM;
1646+
1647+
netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
1648+
" value=0x%04x index=0x%04x size=%d\n",
1649+
cmd, reqtype, value, index, size);
1650+
1651+
if (data) {
1652+
buf = kmemdup(data, size, GFP_KERNEL);
1653+
if (!buf)
1654+
goto out;
1655+
}
1656+
1657+
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
1658+
cmd, reqtype, value, index, buf, size,
1659+
USB_CTRL_SET_TIMEOUT);
1660+
kfree(buf);
1661+
1662+
out:
1663+
return err;
1664+
}
1665+
EXPORT_SYMBOL_GPL(usbnet_write_cmd);
1666+
1667+
static void usbnet_async_cmd_cb(struct urb *urb)
1668+
{
1669+
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
1670+
int status = urb->status;
1671+
1672+
if (status < 0)
1673+
dev_dbg(&urb->dev->dev, "%s failed with %d",
1674+
__func__, status);
1675+
1676+
kfree(req);
1677+
usb_free_urb(urb);
1678+
}
1679+
1680+
int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
1681+
u16 value, u16 index, const void *data, u16 size)
1682+
{
1683+
struct usb_ctrlrequest *req = NULL;
1684+
struct urb *urb;
1685+
int err = -ENOMEM;
1686+
void *buf = NULL;
1687+
1688+
netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
1689+
" value=0x%04x index=0x%04x size=%d\n",
1690+
cmd, reqtype, value, index, size);
1691+
1692+
urb = usb_alloc_urb(0, GFP_ATOMIC);
1693+
if (!urb) {
1694+
netdev_err(dev->net, "Error allocating URB in"
1695+
" %s!\n", __func__);
1696+
goto fail;
1697+
}
1698+
1699+
if (data) {
1700+
buf = kmemdup(data, size, GFP_ATOMIC);
1701+
if (!buf) {
1702+
netdev_err(dev->net, "Error allocating buffer"
1703+
" in %s!\n", __func__);
1704+
goto fail_free;
1705+
}
1706+
}
1707+
1708+
req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
1709+
if (!req) {
1710+
netdev_err(dev->net, "Failed to allocate memory for %s\n",
1711+
__func__);
1712+
goto fail_free_buf;
1713+
}
1714+
1715+
req->bRequestType = reqtype;
1716+
req->bRequest = cmd;
1717+
req->wValue = cpu_to_le16(value);
1718+
req->wIndex = cpu_to_le16(index);
1719+
req->wLength = cpu_to_le16(size);
1720+
1721+
usb_fill_control_urb(urb, dev->udev,
1722+
usb_sndctrlpipe(dev->udev, 0),
1723+
(void *)req, buf, size,
1724+
usbnet_async_cmd_cb, req);
1725+
urb->transfer_flags |= URB_FREE_BUFFER;
1726+
1727+
err = usb_submit_urb(urb, GFP_ATOMIC);
1728+
if (err < 0) {
1729+
netdev_err(dev->net, "Error submitting the control"
1730+
" message: status=%d\n", err);
1731+
goto fail_free;
1732+
}
1733+
return 0;
1734+
1735+
fail_free_buf:
1736+
kfree(buf);
1737+
fail_free:
1738+
kfree(req);
1739+
usb_free_urb(urb);
1740+
fail:
1741+
return err;
1742+
1743+
}
1744+
EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
16131745
/*-------------------------------------------------------------------------*/
16141746

16151747
static int __init usbnet_init(void)

include/linux/usb/usbnet.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ extern int usbnet_resume(struct usb_interface *);
163163
extern void usbnet_disconnect(struct usb_interface *);
164164
extern void usbnet_device_suggests_idle(struct usbnet *dev);
165165

166+
extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
167+
u16 value, u16 index, void *data, u16 size);
168+
extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
169+
u16 value, u16 index, const void *data, u16 size);
170+
extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
171+
u16 value, u16 index, const void *data, u16 size);
166172

167173
/* Drivers that reuse some of the standard USB CDC infrastructure
168174
* (notably, using multiple interfaces according to the CDC

0 commit comments

Comments
 (0)