Date: Wed, 17 Dec 2008 04:35:31 GMT From: Weongyo Jeong <weongyo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 154848 for review Message-ID: <200812170435.mBH4ZVUH096207@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=154848 Change 154848 by weongyo@weongyo_ws on 2008/12/17 04:35:04 fix a page fault that it occured at ZD1211B USB adapter. Affected files ... .. //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#25 edit Differences ... ==== //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#25 (text+ko) ==== @@ -115,6 +115,8 @@ static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor( usb_config_descriptor_t *, uint8_t, uint8_t); +#define USBD_STATUS_IIN_ERROR 0x1 +static int usbd_iin_error; /* * We need to wrap these functions because these need `context switch' from * Windows to UNIX before it's called. @@ -931,8 +933,34 @@ usbd_private_handle priv; usbd_status status; { + int set = 0; + + /* + * We should handle the interrupt IN pipe specially. For a example, + * ZD1211B NDIS driver uses the interrupt IN pipe so we opens its pipe + * using usbd_open_pipe_intr(). In a case of we forcibly plug out + * the ZD1211B USB adapter then firstly usbd_open_pipe_intr() calls our + * callback function whose the value of the status is USBD_IOERROR. + * As a next return, sometimes it returns USBD_CANCELLED. The problem + * is that at this case when we get USBD_IOERROR status we try to free + * IRP related with the interrupt IN pipe. As next if we get + * USBD_CANCELLED, in the previous we tried to free again so it causes + * a page fault. I don't know why the USB framework reports errors + * twice. To solve this problem we only handle first error. + * + * XXX I don't want to use a global variable and don't like this like + * a hack but no way to pass `sc' safely because `priv' can be a pointer + * which already be freed. + */ + if (status == USBD_NORMAL_COMPLETION) + usbd_iin_error &= ~USBD_STATUS_IIN_ERROR; + if (status == USBD_IOERROR) { + usbd_iin_error |= USBD_STATUS_IIN_ERROR; + set = 1; + } - usbd_xferadd(xfer, priv, status, 0); + if ((!(usbd_iin_error & USBD_STATUS_IIN_ERROR)) || set == 1) + usbd_xferadd(xfer, priv, status, 0); } static void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812170435.mBH4ZVUH096207>