aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2012-11-05 23:53:04 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-07 03:53:38 -0500
commit0547fad2dd7ccaaf3c914ba49073fa37e4e241eb (patch)
tree5434c18a01f9c4591c74e0bda596f1d4b29ddd6b
parentef468d234753aff7afa96075d3be135b0df1ded0 (diff)
usbnet: introduce usbnet_{read|write}_cmd_nopm
This patch introduces the below two helpers to prepare for solving the usbnet runtime PM problem, which may cause some network utilities (ifconfig, ethtool,...) touch a suspended device. usbnet_read_cmd_nopm() usbnet_write_cmd_nopm() The above two helpers should be called by usbnet resume/suspend callback to avoid deadlock. Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/usb/usbnet.c62
-rw-r--r--include/linux/usb/usbnet.h4
2 files changed, 61 insertions, 5 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 447d20d22b7..0ac1ff3571c 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1611,8 +1611,8 @@ 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, 1614static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1615 u16 value, u16 index, void *data, u16 size) 1615 u16 value, u16 index, void *data, u16 size)
1616{ 1616{
1617 void *buf = NULL; 1617 void *buf = NULL;
1618 int err = -ENOMEM; 1618 int err = -ENOMEM;
@@ -1636,10 +1636,10 @@ int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1636out: 1636out:
1637 return err; 1637 return err;
1638} 1638}
1639EXPORT_SYMBOL_GPL(usbnet_read_cmd);
1640 1639
1641int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, 1640static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1642 u16 value, u16 index, const void *data, u16 size) 1641 u16 value, u16 index, const void *data,
1642 u16 size)
1643{ 1643{
1644 void *buf = NULL; 1644 void *buf = NULL;
1645 int err = -ENOMEM; 1645 int err = -ENOMEM;
@@ -1662,8 +1662,56 @@ int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1662out: 1662out:
1663 return err; 1663 return err;
1664} 1664}
1665
1666/*
1667 * The function can't be called inside suspend/resume callback,
1668 * otherwise deadlock will be caused.
1669 */
1670int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1671 u16 value, u16 index, void *data, u16 size)
1672{
1673 return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
1674 data, size);
1675}
1676EXPORT_SYMBOL_GPL(usbnet_read_cmd);
1677
1678/*
1679 * The function can't be called inside suspend/resume callback,
1680 * otherwise deadlock will be caused.
1681 */
1682int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
1683 u16 value, u16 index, const void *data, u16 size)
1684{
1685 return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
1686 data, size);
1687}
1665EXPORT_SYMBOL_GPL(usbnet_write_cmd); 1688EXPORT_SYMBOL_GPL(usbnet_write_cmd);
1666 1689
1690/*
1691 * The function can be called inside suspend/resume callback safely
1692 * and should only be called by suspend/resume callback generally.
1693 */
1694int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
1695 u16 value, u16 index, void *data, u16 size)
1696{
1697 return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
1698 data, size);
1699}
1700EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
1701
1702/*
1703 * The function can be called inside suspend/resume callback safely
1704 * and should only be called by suspend/resume callback generally.
1705 */
1706int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
1707 u16 value, u16 index, const void *data,
1708 u16 size)
1709{
1710 return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
1711 data, size);
1712}
1713EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
1714
1667static void usbnet_async_cmd_cb(struct urb *urb) 1715static void usbnet_async_cmd_cb(struct urb *urb)
1668{ 1716{
1669 struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; 1717 struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
@@ -1677,6 +1725,10 @@ static void usbnet_async_cmd_cb(struct urb *urb)
1677 usb_free_urb(urb); 1725 usb_free_urb(urb);
1678} 1726}
1679 1727
1728/*
1729 * The caller must make sure that device can't be put into suspend
1730 * state until the control URB completes.
1731 */
1680int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype, 1732int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
1681 u16 value, u16 index, const void *data, u16 size) 1733 u16 value, u16 index, const void *data, u16 size)
1682{ 1734{
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 4410e4166c6..9bbeabf66c5 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -167,6 +167,10 @@ extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
167 u16 value, u16 index, void *data, u16 size); 167 u16 value, u16 index, void *data, u16 size);
168extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, 168extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
169 u16 value, u16 index, const void *data, u16 size); 169 u16 value, u16 index, const void *data, u16 size);
170extern int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
171 u16 value, u16 index, void *data, u16 size);
172extern int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
173 u16 value, u16 index, const void *data, u16 size);
170extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype, 174extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
171 u16 value, u16 index, const void *data, u16 size); 175 u16 value, u16 index, const void *data, u16 size);
172 176