Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Mar 2008 17:37:45 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 137011 for review
Message-ID:  <200803061737.m26Hbjr2026841@repoman.freebsd.org>

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

Change 137011 by hselasky@hselasky_laptop001 on 2008/03/06 17:36:50

	
	Update "usbd_fs_isoc_schedule_alloc". Be more proactive
	against isochronous schedule overflow situations. When 
	the schedule is full we simply stop activating the USB
	transfer descriptors.
	
	NOTE: There sneaked in a one-line style change in the patch
	to usb_subr.h which does not affect anything.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ehci.c#74 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#100 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#100 edit

Differences ...

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

@@ -2424,6 +2424,7 @@
 #endif
 	uint8_t sa;
 	uint8_t sb;
+	uint8_t error;
 	ehci_sitd_t *td;
 	ehci_sitd_t *td_last = NULL;
 	ehci_sitd_t **pp_last;
@@ -2521,7 +2522,7 @@
 		 * We currently don't care if the ISOCHRONOUS schedule is
 		 * full!
 		 */
-		sa = usbd_fs_isoc_schedule_alloc(fss, *plen);
+		error = usbd_fs_isoc_schedule_alloc(fss, &sa, *plen);
 
 		if (*plen) {
 			/*
@@ -2587,6 +2588,15 @@
 			    (EHCI_SITD_ACTIVE |
 			    EHCI_SITD_SET_LEN(*plen));
 		}
+		if (error) {
+			/*
+			 * The FULL speed schedule is FULL! Pretend that the
+			 * transaction has been executed. The IOC bit should
+			 * be active even if the ACTIVE bit is zero.
+			 */
+			td->sitd_status &=
+			    ~htole32(EHCI_SITD_ACTIVE);
+		}
 		usbd_pc_cpu_flush(td->page_cache);
 
 #ifdef USB_DEBUG

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

@@ -787,14 +787,19 @@
 /*------------------------------------------------------------------------*
  *	usbd_fs_isoc_schedule_alloc
  *
- * This function will allocate bandwidth for the isochronous FULL
- * speed schedule.
+ * This function will allocate bandwidth for an isochronous FULL speed
+ * transaction in the FULL speed schedule. The microframe slot where
+ * the transaction should be started is stored in the byte pointed to
+ * by "pstart". The "len" argument specifies the length of the
+ * transaction in bytes.
  *
  * Returns:
- *   Microframe slot where the transaction will start.
+ *    0: Success
+ * Else: Error
  *------------------------------------------------------------------------*/
 uint8_t
-usbd_fs_isoc_schedule_alloc(struct usbd_fs_isoc_schedule *fss, uint16_t len)
+usbd_fs_isoc_schedule_alloc(struct usbd_fs_isoc_schedule *fss,
+    uint8_t *pstart, uint16_t len)
 {
 	uint8_t slot = fss->frame_slot;
 
@@ -806,7 +811,8 @@
 	len /= 6;
 
 	if (len > fss->total_bytes) {
-		len = fss->total_bytes;
+		*pstart = 0;		/* set some dummy value */
+		return (1);		/* error */
 	}
 	if (len > 0) {
 
@@ -820,7 +826,8 @@
 
 		fss->frame_bytes -= len;
 	}
-	return (slot);
+	*pstart = slot;
+	return (0);			/* success */
 }
 
 /*------------------------------------------------------------------------*

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

@@ -570,7 +570,7 @@
 	uint16_t langid;		/* language for strings */
 
 	uint8_t	address;		/* device addess */
-	uint8_t device_index;		/* device index in "bus->devices" */
+	uint8_t	device_index;		/* device index in "bus->devices" */
 	uint8_t	curr_config_no;		/* current configuration # */
 	uint8_t	depth;			/* distance from root HUB */
 	uint8_t	speed;			/* low/full/high speed */
@@ -996,7 +996,7 @@
 uint8_t	usbd_intr_schedule_adjust(struct usbd_device *udev, int16_t len, uint8_t slot);
 void	usbd_fs_isoc_schedule_init_all(struct usbd_fs_isoc_schedule *fss);
 uint16_t usbd_fs_isoc_schedule_isoc_time_expand(struct usbd_device *udev, struct usbd_fs_isoc_schedule **pp_start, struct usbd_fs_isoc_schedule **pp_end, uint16_t isoc_time);
-uint8_t	usbd_fs_isoc_schedule_alloc(struct usbd_fs_isoc_schedule *fss, uint16_t len);
+uint8_t	usbd_fs_isoc_schedule_alloc(struct usbd_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
 usbd_status_t usbd_set_config_no(struct usbd_device *udev, uint8_t no, uint8_t msg);
 usbd_status_t usbd_set_config_index(struct usbd_device *udev, uint8_t index, uint8_t msg);
 usbd_status_t usbd_set_alt_interface_index(struct usbd_device *udev, uint8_t iface_index, uint8_t alt_index);



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