Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/dwc2 Protect access of urb->hcpriv by adapt...
details: https://anonhg.NetBSD.org/src/rev/e80b150866c6
branches: trunk
changeset: 325647:e80b150866c6
user: skrll <skrll%NetBSD.org@localhost>
date: Thu Jan 02 15:54:10 2014 +0000
description:
Protect access of urb->hcpriv by adapting the following change from the
Raspberry PI dwc_otg driver.
https://github.com/raspberrypi/linux/commit/38753ce72d4f10d5d0f1ed27fa691a2ba8910941
dwc_otg: prevent OOPSes during device disconnects
The dwc_otg_urb_enqueue function is thread-unsafe. In particular the
access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and
friends does not occur within a critical section and so if a device
was unplugged during activity there was a high chance that the
usbcore hub_thread would try to disable the endpoint with partially-
formed entries in the URB queue. This would result in BUG() or null
pointer dereferences.
Fix so that access of urb->hcpriv, enqueuing to the hardware and
adding to usbcore endpoint URB lists is contained within a single
critical section.
diffstat:
sys/external/bsd/dwc2/dist/dwc2_hcd.c | 7 ++-----
sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c | 13 ++++---------
sys/external/bsd/dwc2/dwc2.c | 12 +++++++-----
3 files changed, 13 insertions(+), 19 deletions(-)
diffs (151 lines):
diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dist/dwc2_hcd.c
--- a/sys/external/bsd/dwc2/dist/dwc2_hcd.c Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dist/dwc2_hcd.c Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcd.c,v 1.9 2013/11/24 12:25:19 skrll Exp $ */
+/* $NetBSD: dwc2_hcd.c,v 1.10 2014/01/02 15:54:10 skrll Exp $ */
/*
* hcd.c - DesignWare HS OTG Controller host-mode routines
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.9 2013/11/24 12:25:19 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.10 2014/01/02 15:54:10 skrll Exp $");
#include <sys/types.h>
#include <sys/kmem.h>
@@ -367,7 +367,6 @@
{
struct dwc2_softc *sc = hsotg->hsotg_sc;
struct dwc2_qtd *qtd;
- unsigned long flags;
u32 intr_mask;
int retval;
int dev_speed;
@@ -421,11 +420,9 @@
*/
return 0;
- spin_lock_irqsave(&hsotg->lock, flags);
tr_type = dwc2_hcd_select_transactions(hsotg);
if (tr_type != DWC2_TRANSACTION_NONE)
dwc2_hcd_queue_transactions(hsotg, tr_type);
- spin_unlock_irqrestore(&hsotg->lock, flags);
}
return retval;
diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c
--- a/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcdqueue.c,v 1.6 2013/11/24 12:25:19 skrll Exp $ */
+/* $NetBSD: dwc2_hcdqueue.c,v 1.7 2014/01/02 15:54:10 skrll Exp $ */
/*
* hcd_queue.c - DesignWare HS OTG Controller host queuing routines
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.6 2013/11/24 12:25:19 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.7 2014/01/02 15:54:10 skrll Exp $");
#include <sys/types.h>
#include <sys/kmem.h>
@@ -787,12 +787,13 @@
* Finds the correct QH to place the QTD into. If it does not find a QH, it
* will create a new QH. If the QH to which the QTD is added is not currently
* scheduled, it is placed into the proper schedule based on its EP type.
+ *
+ * HCD lock must be held and interrupts must be disabled on entry
*/
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
struct dwc2_qh **qh, gfp_t mem_flags)
{
struct dwc2_hcd_urb *urb = qtd->urb;
- unsigned long flags;
int allocated = 0;
int retval;
@@ -807,15 +808,12 @@
allocated = 1;
}
- spin_lock_irqsave(&hsotg->lock, flags);
-
retval = dwc2_hcd_qh_add(hsotg, *qh);
if (retval)
goto fail;
qtd->qh = *qh;
list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
- spin_unlock_irqrestore(&hsotg->lock, flags);
return 0;
@@ -832,10 +830,7 @@
qtd_list_entry)
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
- spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_hcd_qh_free(hsotg, qh_tmp);
- } else {
- spin_unlock_irqrestore(&hsotg->lock, flags);
}
return retval;
diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dwc2.c
--- a/sys/external/bsd/dwc2/dwc2.c Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dwc2.c Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2.c,v 1.22 2013/12/31 09:10:43 skrll Exp $ */
+/* $NetBSD: dwc2.c,v 1.23 2014/01/02 15:54:10 skrll Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.22 2013/12/31 09:10:43 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.23 2014/01/02 15:54:10 skrll Exp $");
#include "opt_usb.h"
@@ -1298,7 +1298,6 @@
memset(dwc2_urb, 0, sizeof(*dwc2_urb) +
sizeof(dwc2_urb->iso_descs[0]) * DWC2_MAXISOCPACKETS);
- dwc2_urb->priv = xfer;
dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, addr, epnum, xfertype, dir,
mps);
@@ -1379,6 +1378,9 @@
}
/* might need to check cpu_intr_p */
+ mutex_spin_enter(&hsotg->lock);
+
+ dwc2_urb->priv = xfer;
retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &dpipe->priv, 0);
if (retval)
goto fail;
@@ -1389,14 +1391,14 @@
}
if (alloc_bandwidth) {
- mutex_spin_enter(&hsotg->lock);
dwc2_allocate_bus_bandwidth(hsotg,
dwc2_hcd_get_ep_bandwidth(hsotg, dpipe),
xfer);
- mutex_spin_exit(&hsotg->lock);
}
fail:
+ mutex_spin_exit(&hsotg->lock);
+
// mutex_exit(&sc->sc_lock);
switch (retval) {
Home |
Main Index |
Thread Index |
Old Index