mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
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: Thomas Pugliese <thomas.pugliese@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
f4042c068a
commit
6161ae5f1f
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user