Commit 6161ae5f authored by Thomas Pugliese's avatar Thomas Pugliese Committed by Greg Kroah-Hartman

usb: wusbcore: do device lookup while holding the hc mutex

This patch modifies the device notification handler to not look up the
wusb_dev object before it calls the lower-level handler routines since
the wusbhc mutex is not held when calling those routines and the device
could go away in the meantime.  Instead, let the individual notification
handlers get the device ptr if they need to after they have taken the
mutex.
Signed-off-by: default avatarThomas Pugliese <thomas.pugliese@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f4042c06
......@@ -521,11 +521,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr)
*
* @wusbhc shall be referenced and unlocked
*/
static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr)
{
struct wusb_dev *wusb_dev;
mutex_lock(&wusbhc->mutex);
wusb_dev->entry_ts = jiffies;
__wusbhc_keep_alive(wusbhc);
wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
if (wusb_dev == NULL) {
dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n",
srcaddr);
} else {
wusb_dev->entry_ts = jiffies;
__wusbhc_keep_alive(wusbhc);
}
mutex_unlock(&wusbhc->mutex);
}
......@@ -579,14 +587,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
*
* @wusbhc shall be referenced and unlocked
*/
static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr)
{
struct device *dev = wusbhc->dev;
dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr);
struct wusb_dev *wusb_dev;
mutex_lock(&wusbhc->mutex);
__wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx));
wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
if (wusb_dev == NULL) {
dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n",
srcaddr);
} else {
dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n",
wusb_dev->addr);
__wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc,
wusb_dev->port_idx));
}
mutex_unlock(&wusbhc->mutex);
}
......@@ -608,30 +624,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
struct wusb_dn_hdr *dn_hdr, size_t size)
{
struct device *dev = wusbhc->dev;
struct wusb_dev *wusb_dev;
if (size < sizeof(struct wusb_dn_hdr)) {
dev_err(dev, "DN data shorter than DN header (%d < %d)\n",
(int)size, (int)sizeof(struct wusb_dn_hdr));
return;
}
wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) {
dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n",
dn_hdr->bType, srcaddr);
return;
}
switch (dn_hdr->bType) {
case WUSB_DN_CONNECT:
wusbhc_handle_dn_connect(wusbhc, dn_hdr, size);
break;
case WUSB_DN_ALIVE:
wusbhc_handle_dn_alive(wusbhc, wusb_dev);
wusbhc_handle_dn_alive(wusbhc, srcaddr);
break;
case WUSB_DN_DISCONNECT:
wusbhc_handle_dn_disconnect(wusbhc, wusb_dev);
wusbhc_handle_dn_disconnect(wusbhc, srcaddr);
break;
case WUSB_DN_MASAVAILCHANGED:
case WUSB_DN_RWAKE:
......
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