Skip to content

Commit

Permalink
net: qmi_wwan: call subdriver with control intf only
Browse files Browse the repository at this point in the history
This fixes a hang on suspend due to calling wdm_suspend on
the unregistered data interface. The hang should have been
a NULL pointer reference had it not been for a logic error
in the cdc_wdm code.

  commit 230718b net: qmi_wwan: bind to both control and data interface

changed qmi_wwan to use cdc_wdm as a subdriver for devices with
a two-interface QMI/wwan function.  The commit failed to update
qmi_wwan_suspend and qmi_wwan_resume, which were written to handle
either a single combined interface function, or no subdriver at all.

The result was that we called into the subdriver both when the
control interface was suspended and when the data interface was
suspended.  Calling the subdriver suspend function with an
unregistered interface is not supported and will make the
subdriver bug out.

Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Bjørn Mork authored and David S. Miller committed Sep 13, 2012
1 parent ba1bf47 commit 8624dd2
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions drivers/net/usb/qmi_wwan.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
if (ret < 0)
goto err;

if (info->subdriver && info->subdriver->suspend)
if (intf == info->control && info->subdriver && info->subdriver->suspend)
ret = info->subdriver->suspend(intf, message);
if (ret < 0)
usbnet_resume(intf);
Expand All @@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf)
struct usbnet *dev = usb_get_intfdata(intf);
struct qmi_wwan_state *info = (void *)&dev->data;
int ret = 0;
bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume);

if (info->subdriver && info->subdriver->resume)
if (callsub)
ret = info->subdriver->resume(intf);
if (ret < 0)
goto err;
ret = usbnet_resume(intf);
if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend)
if (ret < 0 && callsub && info->subdriver->suspend)
info->subdriver->suspend(intf, PMSG_SUSPEND);
err:
return ret;
Expand Down

0 comments on commit 8624dd2

Please sign in to comment.