Author: hselasky
Date: Mon Jun  8 09:27:48 2020
New Revision: 361911
URL: https://svnweb.freebsd.org/changeset/base/361911

Log:
  MFC r361581:
  Implement helper function, usbd_get_max_frame_length(), which allows kernel
  device drivers to correctly predict the default USB transfer frame length.
  
  Sponsored by: Mellanox Technologies

Modified:
  stable/11/sys/dev/usb/usb_transfer.c
  stable/11/sys/dev/usb/usbdi.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/usb/usb_transfer.c
==============================================================================
--- stable/11/sys/dev/usb/usb_transfer.c        Mon Jun  8 09:26:46 2020        
(r361910)
+++ stable/11/sys/dev/usb/usb_transfer.c        Mon Jun  8 09:27:48 2020        
(r361911)
@@ -373,6 +373,81 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params
 #endif
 
 /*------------------------------------------------------------------------*
+ *     usbd_get_max_frame_length
+ *
+ * This function returns the maximum single frame length as computed by
+ * usbd_transfer_setup(). It is useful when computing buffer sizes for
+ * devices having multiple alternate settings. The SuperSpeed endpoint
+ * companion pointer is allowed to be NULL.
+ *------------------------------------------------------------------------*/
+uint32_t
+usbd_get_max_frame_length(const struct usb_endpoint_descriptor *edesc,
+    const struct usb_endpoint_ss_comp_descriptor *ecomp,
+    enum usb_dev_speed speed)
+{
+       uint32_t max_packet_size;
+       uint32_t max_packet_count;
+       uint8_t type;
+
+       max_packet_size = UGETW(edesc->wMaxPacketSize);
+       max_packet_count = 1;
+       type = (edesc->bmAttributes & UE_XFERTYPE);
+
+       switch (speed) {
+       case USB_SPEED_HIGH:
+               switch (type) {
+               case UE_ISOCHRONOUS:
+               case UE_INTERRUPT:
+                       max_packet_count +=
+                           (max_packet_size >> 11) & 3;
+
+                       /* check for invalid max packet count */
+                       if (max_packet_count > 3)
+                               max_packet_count = 3;
+                       break;
+               default:
+                       break;
+               }
+               max_packet_size &= 0x7FF;
+               break;
+       case USB_SPEED_SUPER:
+               max_packet_count += (max_packet_size >> 11) & 3;
+
+               if (ecomp != NULL)
+                       max_packet_count += ecomp->bMaxBurst;
+
+               if ((max_packet_count == 0) || 
+                   (max_packet_count > 16))
+                       max_packet_count = 16;
+
+               switch (type) {
+               case UE_CONTROL:
+                       max_packet_count = 1;
+                       break;
+               case UE_ISOCHRONOUS:
+                       if (ecomp != NULL) {
+                               uint8_t mult;
+
+                               mult = UE_GET_SS_ISO_MULT(
+                                   ecomp->bmAttributes) + 1;
+                               if (mult > 3)
+                                       mult = 3;
+
+                               max_packet_count *= mult;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               max_packet_size &= 0x7FF;
+               break;
+       default:
+               break;
+       }
+       return (max_packet_size * max_packet_count);
+}
+
+/*------------------------------------------------------------------------*
  *     usbd_transfer_setup_sub - transfer setup subroutine
  *
  * This function must be called from the "xfer_setup" callback of the

Modified: stable/11/sys/dev/usb/usbdi.h
==============================================================================
--- stable/11/sys/dev/usb/usbdi.h       Mon Jun  8 09:26:46 2020        
(r361910)
+++ stable/11/sys/dev/usb/usbdi.h       Mon Jun  8 09:27:48 2020        
(r361911)
@@ -552,6 +552,9 @@ uint8_t     usbd_get_interface_altindex(struct usb_interfa
 usb_error_t usbd_set_alt_interface_index(struct usb_device *udev,
            uint8_t iface_index, uint8_t alt_index);
 uint32_t usbd_get_isoc_fps(struct usb_device *udev);
+uint32_t usbd_get_max_frame_length(const struct usb_endpoint_descriptor *,
+    const struct usb_endpoint_ss_comp_descriptor *,
+    enum usb_dev_speed);
 usb_error_t usbd_transfer_setup(struct usb_device *udev,
            const uint8_t *ifaces, struct usb_xfer **pxfer,
            const struct usb_config *setup_start, uint16_t n_setup,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to