PERFORCE change 153880 for review

Weongyo Jeong weongyo at FreeBSD.org
Mon Dec 1 03:21:10 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=153880

Change 153880 by weongyo at weongyo_ws on 2008/12/01 11:20:36

	- fix a panic when IRP cancel is invoked after detaching.
	- after returning IRP cancel routine there's no any guarantee that
	  IRP structure is maintained at memory so we shouldn't pass IRP
	  pointer.

Affected files ...

.. //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#16 edit
.. //depot/projects/ndisusb/sys/compat/ndis/usbd_var.h#4 edit

Differences ...

==== //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#16 (text+ko) ====

@@ -48,7 +48,7 @@
 #include <sys/socket.h>
 #include <machine/bus.h>
 #include <sys/bus.h>
-
+#include <sys/ktr.h>
 #include <sys/queue.h>
 
 #include <net/if.h>
@@ -603,22 +603,17 @@
 	void			*priv;
 {
 	struct ndisusb_cancel *nc = priv;
-	irp *ip = nc->ip;
-	device_t dev = IRP_NDIS_DEV(ip);
-	struct ndis_softc *sc = device_get_softc(dev);
-	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct ndis_softc *sc = device_get_softc(nc->dev);
 	usbd_status status;
-	usbd_xfer_handle xfer;
 
-	usb_rem_task(uaa->device, &nc->task);
-	free(priv, M_USBDEV);
+	if (sc->ndisusb_status & NDISUSB_STATUS_DETACH)
+		goto exit;
 
-	xfer = IRP_NDISUSB_XFER(ip);
-	IRP_NDISUSB_XFER(ip) = NULL;
-
 	status = usbd_abort_pipe(sc->ndisusb_ep[NDISUSB_ENDPT_IIN]);
 	if (status != USBD_NORMAL_COMPLETION)
-		device_printf(dev, "IIN can't be canceld");
+		device_printf(nc->dev, "IIN can't be canceld");
+exit:
+	free(nc, M_USBDEV);
 }
 
 static int32_t
@@ -638,8 +633,11 @@
 		return (-1);
 	}
 
-	nc->ip = ip;
+	nc->dev = dev;
+	nc->xfer = IRP_NDISUSB_XFER(ip);
 	usb_init_task(&nc->task, usbd_irpcancel_iin_cb, nc);
+
+	IRP_NDISUSB_XFER(ip) = NULL;
 	usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER);
 
 	IoReleaseCancelSpinLock(ip->irp_cancelirql);
@@ -797,21 +795,18 @@
 	void			*priv;
 {
 	struct ndisusb_cancel *nc = priv;
-	irp *ip = nc->ip;
-	device_t dev = IRP_NDIS_DEV(ip);
-	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct ndis_softc *sc = device_get_softc(nc->dev);
 	usbd_status status;
-	usbd_xfer_handle xfer;
+	usbd_xfer_handle xfer = nc->xfer;
 
-	usb_rem_task(uaa->device, &nc->task);
-	free(priv, M_USBDEV);
+	if (sc->ndisusb_status & NDISUSB_STATUS_DETACH)
+		goto exit;
 
-	xfer = IRP_NDISUSB_XFER(ip);
-	IRP_NDISUSB_XFER(ip) = NULL;
-
 	status = usbd_abort_pipe(xfer->pipe);
 	if (status != USBD_NORMAL_COMPLETION)
-		device_printf(dev, "can't be canceld");
+		device_printf(nc->dev, "can't be canceld");
+exit:
+	free(nc, M_USBDEV);
 }
 
 static int32_t
@@ -847,8 +842,11 @@
 		return (-1);
 	}
 
-	nc->ip = ip;
+	nc->dev = dev;
+	nc->xfer = IRP_NDISUSB_XFER(ip);
 	usb_init_task(&nc->task, usbd_irpcancel_cb, nc);
+
+	IRP_NDISUSB_XFER(ip) = NULL;
 	usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER);
 
 	IoReleaseCancelSpinLock(ip->irp_cancelirql);

==== //depot/projects/ndisusb/sys/compat/ndis/usbd_var.h#4 (text+ko) ====

@@ -189,8 +189,9 @@
 
 /* used for IRP cancel.  */
 struct ndisusb_cancel {
+	device_t		dev;
+	usbd_xfer_handle	xfer;
 	struct usb_task		task;
-	irp			*ip;
 };
 
 extern image_patch_table usbd_functbl[];


More information about the p4-projects mailing list