aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2012-10-24 15:46:54 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-26 03:36:50 -0400
commit877bd862f32b815d54ab5fc10a4fd903d7bf3012 (patch)
tree83242b70bcf295b189ac4afa5ba115755bc9a66a /drivers/net
parent02c38d0a0b7b973911e66d38e369d0fcfce2c186 (diff)
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 <oneukum@suse.de> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/usb/usbnet.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f9819d10b1f9..447d20d22b7c 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1611,6 +1611,138 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
1611EXPORT_SYMBOL(usbnet_device_suggests_idle); 1611EXPORT_SYMBOL(usbnet_device_suggests_idle);
1612 1612
1613/*-------------------------------------------------------------------------*/ 1613/*-------------------------------------------------------------------------*/
1614int 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);
1636out:
1637 return err;
1638}
1639EXPORT_SYMBOL_GPL(usbnet_read_cmd);
1640
1641int 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
1662out:
1663 return err;
1664}
1665EXPORT_SYMBOL_GPL(usbnet_write_cmd);
1666
1667static 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
1680int 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
1735fail_free_buf:
1736 kfree(buf);
1737fail_free:
1738 kfree(req);
1739 usb_free_urb(urb);
1740fail:
1741 return err;
1742
1743}
1744EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
1745/*-------------------------------------------------------------------------*/
1614 1746
1615static int __init usbnet_init(void) 1747static int __init usbnet_init(void)
1616{ 1748{