Skip to content

Commit

Permalink
usbnet: introduce usbnet_{read|write}_cmd_nopm
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ming Lei authored and David S. Miller committed Nov 7, 2012
1 parent ef468d2 commit 0547fad
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
62 changes: 57 additions & 5 deletions drivers/net/usb/usbnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1611,8 +1611,8 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
EXPORT_SYMBOL(usbnet_device_suggests_idle);

/*-------------------------------------------------------------------------*/
int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size)
static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size)
{
void *buf = NULL;
int err = -ENOMEM;
Expand All @@ -1636,10 +1636,10 @@ int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
out:
return err;
}
EXPORT_SYMBOL_GPL(usbnet_read_cmd);

int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data, u16 size)
static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data,
u16 size)
{
void *buf = NULL;
int err = -ENOMEM;
Expand All @@ -1662,8 +1662,56 @@ int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
out:
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);

/*
* 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)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
Expand All @@ -1677,6 +1725,10 @@ static void usbnet_async_cmd_cb(struct 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,
u16 value, u16 index, const void *data, u16 size)
{
Expand Down
4 changes: 4 additions & 0 deletions include/linux/usb/usbnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size);
extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
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,
u16 value, u16 index, const void *data, u16 size);

Expand Down

0 comments on commit 0547fad

Please sign in to comment.