aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/usbnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/usbnet.c')
-rw-r--r--drivers/net/usb/usbnet.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index edb81ed06950..c04110ba677f 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1616,6 +1616,202 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
1616EXPORT_SYMBOL(usbnet_device_suggests_idle); 1616EXPORT_SYMBOL(usbnet_device_suggests_idle);
1617 1617
1618/*-------------------------------------------------------------------------*/ 1618/*-------------------------------------------------------------------------*/
1619static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1620 u16 value, u16 index, void *data, u16 size)
1621{
1622 void *buf = NULL;
1623 int err = -ENOMEM;
1624
1625 netdev_dbg(dev->net, "usbnet_read_cmd cmd=0x%02x reqtype=%02x"
1626 " value=0x%04x index=0x%04x size=%d\n",
1627 cmd, reqtype, value, index, size);
1628
1629 if (data) {
1630 buf = kmalloc(size, GFP_KERNEL);
1631 if (!buf)
1632 goto out;
1633 }
1634
1635 err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
1636 cmd, reqtype, value, index, buf, size,
1637 USB_CTRL_GET_TIMEOUT);
1638 if (err > 0 && err <= size)
1639 memcpy(data, buf, err);
1640 kfree(buf);
1641out:
1642 return err;
1643}
1644
1645static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1646 u16 value, u16 index, const void *data,
1647 u16 size)
1648{
1649 void *buf = NULL;
1650 int err = -ENOMEM;
1651
1652 netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
1653 " value=0x%04x index=0x%04x size=%d\n",
1654 cmd, reqtype, value, index, size);
1655
1656 if (data) {
1657 buf = kmemdup(data, size, GFP_KERNEL);
1658 if (!buf)
1659 goto out;
1660 }
1661
1662 err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
1663 cmd, reqtype, value, index, buf, size,
1664 USB_CTRL_SET_TIMEOUT);
1665 kfree(buf);
1666
1667out:
1668 return err;
1669}
1670
1671/*
1672 * The function can't be called inside suspend/resume callback,
1673 * otherwise deadlock will be caused.
1674 */
1675int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1676 u16 value, u16 index, void *data, u16 size)
1677{
1678 int ret;
1679
1680 if (usb_autopm_get_interface(dev->intf) < 0)
1681 return -ENODEV;
1682 ret = __usbnet_read_cmd(dev, cmd, reqtype, value, index,
1683 data, size);
1684 usb_autopm_put_interface(dev->intf);
1685 return ret;
1686}
1687EXPORT_SYMBOL_GPL(usbnet_read_cmd);
1688
1689/*
1690 * The function can't be called inside suspend/resume callback,
1691 * otherwise deadlock will be caused.
1692 */
1693int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1694 u16 value, u16 index, const void *data, u16 size)
1695{
1696 int ret;
1697
1698 if (usb_autopm_get_interface(dev->intf) < 0)
1699 return -ENODEV;
1700 ret = __usbnet_write_cmd(dev, cmd, reqtype, value, index,
1701 data, size);
1702 usb_autopm_put_interface(dev->intf);
1703 return ret;
1704}
1705EXPORT_SYMBOL_GPL(usbnet_write_cmd);
1706
1707/*
1708 * The function can be called inside suspend/resume callback safely
1709 * and should only be called by suspend/resume callback generally.
1710 */
1711int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
1712 u16 value, u16 index, void *data, u16 size)
1713{
1714 return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
1715 data, size);
1716}
1717EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
1718
1719/*
1720 * The function can be called inside suspend/resume callback safely
1721 * and should only be called by suspend/resume callback generally.
1722 */
1723int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
1724 u16 value, u16 index, const void *data,
1725 u16 size)
1726{
1727 return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
1728 data, size);
1729}
1730EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
1731
1732static void usbnet_async_cmd_cb(struct urb *urb)
1733{
1734 struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
1735 int status = urb->status;
1736
1737 if (status < 0)
1738 dev_dbg(&urb->dev->dev, "%s failed with %d",
1739 __func__, status);
1740
1741 kfree(req);
1742 usb_free_urb(urb);
1743}
1744
1745/*
1746 * The caller must make sure that device can't be put into suspend
1747 * state until the control URB completes.
1748 */
1749int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
1750 u16 value, u16 index, const void *data, u16 size)
1751{
1752 struct usb_ctrlrequest *req = NULL;
1753 struct urb *urb;
1754 int err = -ENOMEM;
1755 void *buf = NULL;
1756
1757 netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
1758 " value=0x%04x index=0x%04x size=%d\n",
1759 cmd, reqtype, value, index, size);
1760
1761 urb = usb_alloc_urb(0, GFP_ATOMIC);
1762 if (!urb) {
1763 netdev_err(dev->net, "Error allocating URB in"
1764 " %s!\n", __func__);
1765 goto fail;
1766 }
1767
1768 if (data) {
1769 buf = kmemdup(data, size, GFP_ATOMIC);
1770 if (!buf) {
1771 netdev_err(dev->net, "Error allocating buffer"
1772 " in %s!\n", __func__);
1773 goto fail_free;
1774 }
1775 }
1776
1777 req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
1778 if (!req) {
1779 netdev_err(dev->net, "Failed to allocate memory for %s\n",
1780 __func__);
1781 goto fail_free_buf;
1782 }
1783
1784 req->bRequestType = reqtype;
1785 req->bRequest = cmd;
1786 req->wValue = cpu_to_le16(value);
1787 req->wIndex = cpu_to_le16(index);
1788 req->wLength = cpu_to_le16(size);
1789
1790 usb_fill_control_urb(urb, dev->udev,
1791 usb_sndctrlpipe(dev->udev, 0),
1792 (void *)req, buf, size,
1793 usbnet_async_cmd_cb, req);
1794 urb->transfer_flags |= URB_FREE_BUFFER;
1795
1796 err = usb_submit_urb(urb, GFP_ATOMIC);
1797 if (err < 0) {
1798 netdev_err(dev->net, "Error submitting the control"
1799 " message: status=%d\n", err);
1800 goto fail_free;
1801 }
1802 return 0;
1803
1804fail_free_buf:
1805 kfree(buf);
1806fail_free:
1807 kfree(req);
1808 usb_free_urb(urb);
1809fail:
1810 return err;
1811
1812}
1813EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
1814/*-------------------------------------------------------------------------*/
1619 1815
1620static int __init usbnet_init(void) 1816static int __init usbnet_init(void)
1621{ 1817{