Commit 0547fad2 authored by Ming Lei's avatar Ming Lei Committed by David S. Miller

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: default avatarMing Lei <ming.lei@canonical.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ef468d23
...@@ -1611,7 +1611,7 @@ void usbnet_device_suggests_idle(struct usbnet *dev) ...@@ -1611,7 +1611,7 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
EXPORT_SYMBOL(usbnet_device_suggests_idle); EXPORT_SYMBOL(usbnet_device_suggests_idle);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size) u16 value, u16 index, void *data, u16 size)
{ {
void *buf = NULL; void *buf = NULL;
...@@ -1636,10 +1636,10 @@ int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, ...@@ -1636,10 +1636,10 @@ int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
out: out:
return err; return err;
} }
EXPORT_SYMBOL_GPL(usbnet_read_cmd);
int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size) u16 value, u16 index, const void *data,
u16 size)
{ {
void *buf = NULL; void *buf = NULL;
int err = -ENOMEM; int err = -ENOMEM;
...@@ -1662,8 +1662,56 @@ int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, ...@@ -1662,8 +1662,56 @@ int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
out: out:
return err; return err;
} }
/*
* The function can't be called inside suspend/resume callback,
* otherwise deadlock will be caused.
*/
int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size)
{
return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
data, size);
}
EXPORT_SYMBOL_GPL(usbnet_read_cmd);
/*
* The function can't be called inside suspend/resume callback,
* otherwise deadlock will be caused.
*/
int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size)
{
return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
data, size);
}
EXPORT_SYMBOL_GPL(usbnet_write_cmd); EXPORT_SYMBOL_GPL(usbnet_write_cmd);
/*
* The function can be called inside suspend/resume callback safely
* and should only be called by suspend/resume callback generally.
*/
int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size)
{
return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
data, size);
}
EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
/*
* The function can be called inside suspend/resume callback safely
* and should only be called by suspend/resume callback generally.
*/
int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data,
u16 size)
{
return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
data, size);
}
EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
static void usbnet_async_cmd_cb(struct urb *urb) static void usbnet_async_cmd_cb(struct urb *urb)
{ {
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
...@@ -1677,6 +1725,10 @@ static void usbnet_async_cmd_cb(struct urb *urb) ...@@ -1677,6 +1725,10 @@ static void usbnet_async_cmd_cb(struct urb *urb)
usb_free_urb(urb); usb_free_urb(urb);
} }
/*
* The caller must make sure that device can't be put into suspend
* state until the control URB completes.
*/
int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype, int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size) u16 value, u16 index, const void *data, u16 size)
{ {
......
...@@ -167,6 +167,10 @@ extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, ...@@ -167,6 +167,10 @@ extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size); u16 value, u16 index, void *data, u16 size);
extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size); u16 value, u16 index, const void *data, u16 size);
extern int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size);
extern int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size);
extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype, extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size); u16 value, u16 index, const void *data, u16 size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment