Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Feb 2009 00:51:57 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 158418 for review
Message-ID:  <200902280051.n1S0pvQ0091790@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=158418

Change 158418 by hselasky@hselasky_laptop001 on 2009/02/28 00:51:00

	
	USB NDIS: Fix the last bits and pieces.
	- mostly fix locking issues
	- add support for pipe abortion
	- remove IFF_NEEDSGIANT

Affected files ...

.. //depot/projects/usb/src/sys/compat/ndis/kern_windrv.c#6 edit
.. //depot/projects/usb/src/sys/compat/ndis/subr_usbd.c#7 edit
.. //depot/projects/usb/src/sys/compat/ndis/usbd_var.h#4 edit
.. //depot/projects/usb/src/sys/dev/if_ndis/if_ndis.c#18 edit
.. //depot/projects/usb/src/sys/dev/if_ndis/if_ndis_usb.c#13 edit
.. //depot/projects/usb/src/sys/dev/if_ndis/if_ndisvar.h#9 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.h#2 edit

Differences ...

==== //depot/projects/usb/src/sys/compat/ndis/kern_windrv.c#6 (text+ko) ====

@@ -56,6 +56,9 @@
 #include <machine/segments.h>
 #endif
 
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_hub.h>
+
 #include <compat/ndis/pe_var.h>
 #include <compat/ndis/cfg_var.h>
 #include <compat/ndis/resource_var.h>
@@ -431,6 +434,9 @@
 	STAILQ_INSERT_HEAD(&drvdb_head, new, link);
 	mtx_unlock(&drvdb_mtx); 
 
+	/* Make sure all driver-less USB devices get explored again! */
+	usb2_needs_explore_all();
+
 	return (0);
 }
 

==== //depot/projects/usb/src/sys/compat/ndis/subr_usbd.c#7 (text+ko) ====

@@ -96,10 +96,11 @@
 static int32_t usbd_func_getdesc(irp *ip);
 static usb2_error_t usbd_get_desc_ndis(struct usb2_device *udev, struct mtx *mtx, uint16_t id, uint16_t maxlen, uint8_t type, uint8_t index, uint8_t retries, void *desc, uint16_t *actlen);
 static int32_t usbd_func_selconf(irp *ip);
+static int32_t usbd_func_pipe_abort(irp *ip);
 static int32_t usbd_func_vendorclass(irp *ip);
 static void usbd_irpcancel(device_object *dobj, irp *ip);
 static int32_t ndis_setup_endpoint(struct ndis_softc *sc, uint8_t iface_index, struct usb2_endpoint_descriptor *edesc, uint32_t bufsize);
-static void ndis_xfer_complete(struct ndisusb_ep *nuep, int32_t status);
+static void ndis_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *nuep, int32_t status);
 static int32_t usbd_func_bulkintr(irp *ip);
 static union usbd_urb *USBD_CreateConfigurationRequest(struct usb2_config_descriptor *conf, uint16_t *len);
 static union usbd_urb *USBD_CreateConfigurationRequestEx(struct usb2_config_descriptor *conf, struct usbd_interface_list_entry *list);
@@ -415,6 +416,10 @@
 		status = usbd_func_selconf(ip);
 		USBD_URB_STATUS(urb) = status;
 		break;
+	case URB_FUNCTION_ABORT_PIPE:
+		status = usbd_func_pipe_abort(ip);
+		USBD_URB_STATUS(urb) = status;
+		break;
 	case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
 		status = usbd_func_getdesc(ip);
 		USBD_URB_STATUS(urb) = status;
@@ -425,7 +430,6 @@
 		USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED;
 		break;
 	}
-
 	return (status);
 }
 
@@ -469,7 +473,7 @@
 		/* Success */
 		status = USB_ERR_NORMAL_COMPLETION;
 	} else {
-		status = usbd_get_desc_ndis(sc->ndisusb_dev, &sc->ndis_mtx,
+		status = usbd_get_desc_ndis(sc->ndisusb_dev, NULL,
 		    ctldesc->ucd_langid, ctldesc->ucd_trans_buflen,
 		    ctldesc->ucd_desctype, ctldesc->ucd_idx, 3,
 		    ctldesc->ucd_trans_buf, &actlen);
@@ -532,13 +536,9 @@
 	intf = &selconf->usc_intf;
 	for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) {
 
-		mtx_unlock(&sc->ndis_mtx);
-
 		err = usb2_set_alt_interface_index(sc->ndisusb_dev,
 		    intf->uii_intfnum, intf->uii_altset);
 
-		mtx_lock(&sc->ndis_mtx);
-
 		if (err != USB_ERR_NORMAL_COMPLETION) {
 			device_printf(dev,
 			    "setting alternate interface failed: %s\n",
@@ -585,6 +585,47 @@
 }
 
 static int32_t
+usbd_func_pipe_abort(irp *ip)
+{
+	device_t dev = IRP_NDIS_DEV(ip);
+	struct ndis_softc *sc;
+	struct usb2_endpoint_descriptor *edesc;
+	struct usbd_urb_pipe_abort *upa;
+	struct usbd_urb_bulk_or_intr_transfer *ubi;
+	union usbd_urb *urb;
+	static struct ndisusb_ep *nuep;
+
+	sc = device_get_softc(dev);
+	urb = usbd_geturb(ip);
+
+	upa = &urb->uu_pipe_abort;
+	edesc = upa->upa_handle;
+	if (edesc == NULL) {
+		device_printf(dev, "pipe handle is NULL\n");
+		return USBD_STATUS_REQUEST_FAILED;
+	}
+
+	nuep = usbd_get_ndisusb_ep(sc, edesc->bEndpointAddress);
+	if (nuep == NULL) {
+		device_printf(dev, "endpoint does not exist\n");
+		return USBD_STATUS_REQUEST_FAILED;
+	}
+
+	NDIS_LOCK(sc);
+
+	usb2_transfer_stop(nuep->urb_xfer[0]);
+
+	while ((ubi = usbd_first_ubi(nuep))) {
+		ndis_xfer_complete(sc, nuep, USBD_STATUS_CANCELED);
+	}
+
+	usb2_transfer_start(nuep->urb_xfer[0]);
+
+	NDIS_UNLOCK(sc);
+	return USBD_STATUS_SUCCESS;
+}
+
+static int32_t
 usbd_func_vendorclass(irp *ip)
 {
 	device_t dev = IRP_NDIS_DEV(ip);
@@ -639,7 +680,7 @@
 	USETW(req.wLength, vcreq->uvc_trans_buflen);
 
 	err = usb2_do_request(sc->ndisusb_dev, 
-	    &sc->ndis_mtx, &req, vcreq->uvc_trans_buf);
+	    NULL, &req, vcreq->uvc_trans_buf);
 
 	return usbd_usb2urb(err);
 }
@@ -647,13 +688,23 @@
 static void
 usbd_irpcancel(device_object *dobj, irp *ip)
 {
+	device_t dev = IRP_NDIS_DEV(ip);
+	struct ndis_softc *sc = device_get_softc(dev);
 	struct ndisusb_ep *nuep;
 	union usbd_urb *urb;
 	struct usbd_urb_bulk_or_intr_transfer *ubi;
+	struct usbd_urb_bulk_or_intr_transfer *ubi_first;
+
+	/* XXX we have a LOR here ! --hps */
+	IoReleaseCancelSpinLock(ip->irp_cancelirql);
 
+	NDIS_LOCK(sc);
+	IoAcquireCancelSpinLock(&ip->irp_cancelirql);
+
 	if (IRP_NDISUSB_EP(ip) == NULL) {
 		ip->irp_cancel = TRUE;
 		IoReleaseCancelSpinLock(ip->irp_cancelirql);
+		NDIS_UNLOCK(sc);
 		return;
 	}
 
@@ -663,13 +714,14 @@
 	urb = usbd_geturb(ip);
 	ubi = &urb->uu_bulkintr;
 
+	/* get current UBI */
+	ubi_first = usbd_first_ubi(nuep);
+
 	/* remove UBI from queue */
 	usbd_remove_ubi(nuep, ubi);
 
 	/* check if the currently executing transfer is being cancelled */
-	if (nuep->irp_curr == ip) {
-		nuep->irp_curr = NULL;
-
+	if (ubi == ubi_first) {
 		/*
 		 * Make sure that the current USB transfer proxy is
 		 * cancelled and then restarted.
@@ -680,6 +732,7 @@
 
 	ip->irp_cancel = TRUE;
 	IoReleaseCancelSpinLock(ip->irp_cancelirql);
+	NDIS_UNLOCK(sc);
 }
 
 static int32_t
@@ -718,13 +771,9 @@
 	cfg[0].mh.flags.proxy_buffer = 1;
 	cfg[0].mh.flags.short_xfer_ok = 1;
 
-	mtx_unlock(&sc->ndis_mtx);
-
 	err = usb2_transfer_setup(sc->ndisusb_dev, &iface_index,
 	    nuep->urb_xfer, cfg, 1, sc, &sc->ndis_mtx);
 
-	mtx_lock(&sc->ndis_mtx);
-
 	if (err)
 		return (usbd_usb2urb(err));
 
@@ -760,14 +809,19 @@
 }
 
 static void
-ndis_xfer_complete(struct ndisusb_ep *nuep, int32_t status)
+ndis_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *nuep, int32_t status)
 {
-	irp *ip = nuep->irp_curr;
+	irp *ip;
 	struct usbd_urb_bulk_or_intr_transfer *ubi;
 	union usbd_urb *urb;
 
+	ubi = usbd_first_ubi(nuep);
+	if (ubi == NULL)
+		return;	/* cancelled */
+
+	ip = ubi->ubi_hca.reserved8[2];
 	if (ip == NULL)
-		return;	/* cancelled */
+		return; /* cancelled */
 
 	if (status != USBD_STATUS_SUCCESS)
 		nuep->urb_actlen = 0;
@@ -790,7 +844,11 @@
 
 	ip->irp_iostat.isb_status = usbd_urb2nt(USBD_URB_STATUS(urb));
 
+	NDIS_UNLOCK(sc);
+
 	IoCompleteRequest(ip, IO_NO_INCREMENT);
+
+	NDIS_LOCK(sc);
 }
 
 /*------------------------------------------------------------------------*
@@ -810,6 +868,7 @@
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
+
 		if (nuep->urb_rx_data) {
 			/* copy in data with regard to the URB */
 			usb2_copy_out(xfer->frbuffers, 0,
@@ -825,15 +884,15 @@
 			nuep->urb_len = 0;
 			/* check if short transfer is ok */
 			if (nuep->urb_short_flag)
-				ndis_xfer_complete(nuep, USBD_STATUS_ERROR_SHORT_TRANSFER);
+				ndis_xfer_complete(sc, nuep, USBD_STATUS_ERROR_SHORT_TRANSFER);
 			else
-				ndis_xfer_complete(nuep, USBD_STATUS_SUCCESS);
+				ndis_xfer_complete(sc, nuep, USBD_STATUS_SUCCESS);
 		} else {
 			/* check remainder */
 			if (nuep->urb_len > 0)
 				goto setup_bulk;
 
-			ndis_xfer_complete(nuep, USBD_STATUS_SUCCESS);
+			ndis_xfer_complete(sc, nuep, USBD_STATUS_SUCCESS);
 		}
 
 	case USB_ST_SETUP:
@@ -851,6 +910,10 @@
 		nuep->urb_len = ubi->ubi_trans_buflen;
 		nuep->urb_data = ubi->ubi_trans_buf;
 		nuep->urb_actlen = 0;
+		if (ubi->ubi_trans_flags & USBD_SHORT_TRANSFER_OK)
+			nuep->urb_short_flag = 0;
+		else
+			nuep->urb_short_flag = 1;
 
 setup_bulk:
 		if (max_bulk > nuep->urb_len)
@@ -874,12 +937,11 @@
 		break;
 
 	default:
-		ndis_xfer_complete(nuep, usbd_usb2urb(xfer->error));
-
 		if (xfer->error != USB_ERR_CANCELLED) {
 			xfer->flags.stall_pipe = 1;
 			device_printf(sc->ndis_dev, "USB error (%s)\n",
 			    usb2_errstr(xfer->error));
+			ndis_xfer_complete(sc, nuep, usbd_usb2urb(xfer->error));
 			goto tr_setup;
 		}
 		break;
@@ -916,6 +978,8 @@
 		return (USBD_STATUS_REQUEST_FAILED);
 	}
 
+	NDIS_LOCK(sc);
+
 	/* final UBI transfer setup */
 
 	IoAcquireCancelSpinLock(&ip->irp_cancelirql);
@@ -931,9 +995,14 @@
 	/* enqueue the URB */
 	usbd_enqueue_ubi(nuep, ubi);
 
+	/* store reference to IRP */
+	ubi->ubi_hca.reserved8[2] = ip;
+
 	/* start USB transfer, if any */
 	usb2_transfer_start(nuep->urb_xfer[0]);
 
+	NDIS_UNLOCK(sc);
+
 	/* return pending status code */
 	return (USBD_STATUS_PENDING);
 }
@@ -1095,4 +1164,4 @@
 	{ NULL, NULL, NULL }
 };
 
-MODULE_DEPEND(ndis, usb2_core, 1, 1, 1);
+MODULE_DEPEND(ndis, usb, 1, 1, 1);

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

@@ -44,7 +44,9 @@
 #define	IOCTL_INTERNAL_USB_SUBMIT_URB			0x00220003
 
 #define	URB_FUNCTION_SELECT_CONFIGURATION		0x0000
+#define	URB_FUNCTION_ABORT_PIPE				0x0002
 #define	URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER		0x0009
+#define	URB_FUNCTION_ISOCH_TRANSFER			0x000A
 #define	URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE		0x000B
 #define	URB_FUNCTION_VENDOR_DEVICE			0x0017
 #define	URB_FUNCTION_VENDOR_INTERFACE			0x0018
@@ -136,6 +138,12 @@
         struct usbd_interface_information usc_intf;
 };
 
+struct usbd_urb_pipe_abort {
+	struct usbd_urb_header	upa_hdr;
+	struct usb2_endpoint_descriptor *upa_handle;
+	uint32_t upa_reserved;
+};
+
 struct usbd_hcd_area {
 	void			*reserved8[8];
 };
@@ -192,10 +200,11 @@
 
 union usbd_urb {
 	struct usbd_urb_header			uu_hdr;
-        struct usbd_urb_select_configuration	uu_selconf;
-        struct usbd_urb_bulk_or_intr_transfer	uu_bulkintr;
-        struct usbd_urb_control_descriptor_request	uu_ctldesc;
-        struct usbd_urb_vendor_or_class_request	uu_vcreq;
+	struct usbd_urb_select_configuration	uu_selconf;
+	struct usbd_urb_pipe_abort		uu_pipe_abort;
+	struct usbd_urb_bulk_or_intr_transfer	uu_bulkintr;
+	struct usbd_urb_control_descriptor_request	uu_ctldesc;
+	struct usbd_urb_vendor_or_class_request	uu_vcreq;
 };
 
 #define	USBD_URB_STATUS(urb)	((urb)->uu_hdr.uuh_status)

==== //depot/projects/usb/src/sys/dev/if_ndis/if_ndis.c#18 (text+ko) ====

@@ -713,8 +713,6 @@
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_mtu = ETHERMTU;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	if (sc->ndis_iftype == PNPBus)
-		ifp->if_flags |= IFF_NEEDSGIANT;
 	ifp->if_ioctl = ndis_ioctl;
 	ifp->if_start = ndis_start;
 	ifp->if_init = ndis_init;

==== //depot/projects/usb/src/sys/dev/if_ndis/if_ndis_usb.c#13 (text+ko) ====

@@ -69,7 +69,6 @@
 
 MODULE_DEPEND(ndis, usb, 1, 1, 1);
 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
-MODULE_DEPEND(ndis, if_ndis, 1, 1, 1);
 
 static device_probe_t ndisusb_probe;
 static device_attach_t ndisusb_attach;

==== //depot/projects/usb/src/sys/dev/if_ndis/if_ndisvar.h#9 (text+ko) ====

@@ -123,7 +123,6 @@
 struct ndisusb_ep {
 	struct usbd_urb_bulk_or_intr_transfer *ubi_first;
 	struct usbd_urb_bulk_or_intr_transfer **ubi_last;
-	irp *irp_curr;
 	struct usb2_xfer *urb_xfer[1];
 	uint8_t *urb_data;
 	uint32_t urb_len;

==== //depot/projects/usb/src/sys/dev/usb/usb_hub.h#2 (text+ko) ====

@@ -27,6 +27,11 @@
 #ifndef _USB2_HUB_H_
 #define	_USB2_HUB_H_
 
+#include <dev/usb/usb_defs.h>
+
+struct usb2_bus;
+struct usb2_device;
+
 /*
  * The following structure defines an USB port.
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902280051.n1S0pvQ0091790>