PERFORCE change 158418 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Feb 27 16:52:08 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=158418
Change 158418 by hselasky at 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.
*/
More information about the p4-projects
mailing list