[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <877guzl3qz.fsf@nemi.mork.no>
Date: Fri, 22 Jun 2012 18:18:12 +0200
From: Bjørn Mork <bjorn@...k.no>
To: Ming Lei <tom.leiming@...il.com>
Cc: netdev@...r.kernel.org, linux-usb@...r.kernel.org,
Marius Bjørnstad Kotsbak
<marius.kotsbak@...il.com>
Subject: Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
Ming Lei <tom.leiming@...il.com> writes:
> Looks I understand the problem incorrectly, your problem is
> that qmi_wwan_cdc_wdm_manage_power is called from
> wdm_open, not from usbnet_open. It is a problem crossing
> 2 class drivers.
That's correct. Trying to use two drivers at once will necessarily lead
to the situation where one drivers shutdown is called from the other
drivers shutdown. And the fact that one of the drivers is a usbnet
minidriver complicates this a bit.
But I believe most of it should be OK now. I tried my best to let the
two drivers share as little as possible. The only shared state is in
the power management code, which have to access the active/idle state of
both drivers.
>>> diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
>>> index e92c057..2eb9e1e 100644
>>> --- a/drivers/net/usb/usbnet.c
>>> +++ b/drivers/net/usb/usbnet.c
>>> @@ -1286,7 +1286,6 @@ void usbnet_disconnect (struct usb_interface *intf)
>>> struct net_device *net;
>>>
>>> dev = usb_get_intfdata(intf);
>>> - usb_set_intfdata(intf, NULL);
>>> if (!dev)
>>> return;
>>
>> I believe that call is there to prevent disconnect from running twice
>> for the common two-interface CDC ethernet model, like e.g. cdc_ether.
>
> No, intfdata is per interface, and .unbind will clear it for each interface.
Yes, intfdata is per interface, but in the case of cdc_ether (and
probably other similar minidrivers) there are two interfaces pointing to
the *same* usbnet private data.
What about the situation where disconnect is called simultaneously for
both interfaces? Or can't that happen? If it can, then we'll do
driver->disconnect(intf1) driver->disconnect(intf2)
dev = usb_get_intfdata(intf1) dev = usb_get_intfdata(intf2)
dev->driver_info->unbind() dev->driver_info->unbind()
net = dev->net net = dev->net
free_netdev(net) free_netdev(dev->net)
where "dev" and "net" will be pointing to the same private data and
netdevice.
I assume that is what the code above is trying to protect against. But
I could be wrong. That has happened before, believe it or not :-)
Bjørn
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists