Author: hselasky
Date: Fri May  3 11:10:04 2013
New Revision: 250207
URL: http://svnweb.freebsd.org/changeset/base/250207

Log:
  - Add more defines to limit USB memory usage and number of allocations
  in reduced memory systems.
  
  - Split allocation and freeing of the configuration descriptor into a separate
  function, so that the configuration descriptor can be made fixed size
  to save memory allocations. This applies for both device and host mode.

Modified:
  head/sys/dev/usb/template/usb_template.c
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_device.h
  head/sys/dev/usb/usb_dynamic.c
  head/sys/dev/usb/usb_freebsd.h
  head/sys/dev/usb/usb_freebsd_loader.h
  head/sys/dev/usb/usb_generic.c
  head/sys/dev/usb/usb_hub.c
  head/sys/dev/usb/usb_hub.h
  head/sys/dev/usb/usb_request.c
  head/sys/dev/usb/usb_request.h

Modified: head/sys/dev/usb/template/usb_template.c
==============================================================================
--- head/sys/dev/usb/template/usb_template.c    Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/template/usb_template.c    Fri May  3 11:10:04 2013        
(r250207)
@@ -69,6 +69,7 @@
 
 #include <dev/usb/usb_controller.h>
 #include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_request.h>
 #include <dev/usb/template/usb_template.h>
 #endif                 /* USB_GLOBAL_INCLUDE_FILE */
 
@@ -1267,7 +1268,7 @@ usb_temp_setup(struct usb_device *udev,
                goto done;
        }
        /* allocate zeroed memory */
-       uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO);
+       uts->buf = usbd_alloc_config_desc(udev, uts->size);
        /*
         * Allow malloc() to return NULL regardless of M_WAITOK flag.
         * This helps when porting the software to non-FreeBSD
@@ -1336,12 +1337,8 @@ done:
 void
 usb_temp_unsetup(struct usb_device *udev)
 {
-       if (udev->usb_template_ptr) {
-
-               free(udev->usb_template_ptr, M_USB);
-
-               udev->usb_template_ptr = NULL;
-       }
+       usbd_free_config_desc(udev, udev->usb_template_ptr);
+       udev->usb_template_ptr = NULL;
 }
 
 static usb_error_t

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c       Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_device.c       Fri May  3 11:10:04 2013        
(r250207)
@@ -493,7 +493,7 @@ usb_unconfigure(struct usb_device *udev,
        /* free "cdesc" after "ifaces" and "endpoints", if any */
        if (udev->cdesc != NULL) {
                if (udev->flags.usb_mode != USB_MODE_DEVICE)
-                       free(udev->cdesc, M_USB);
+                       usbd_free_config_desc(udev, udev->cdesc);
                udev->cdesc = NULL;
        }
        /* set unconfigured state */
@@ -552,7 +552,7 @@ usbd_set_config_index(struct usb_device 
        } else {
                /* normal request */
                err = usbd_req_get_config_desc_full(udev,
-                   NULL, &cdp, M_USB, index);
+                   NULL, &cdp, index);
        }
        if (err) {
                goto done;

Modified: head/sys/dev/usb/usb_device.h
==============================================================================
--- head/sys/dev/usb/usb_device.h       Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_device.h       Fri May  3 11:10:04 2013        
(r250207)
@@ -267,6 +267,10 @@ struct usb_device {
        uint32_t clear_stall_errors;    /* number of clear-stall failures */
 
        union usb_device_scratch scratch;
+
+#if (USB_HAVE_FIXED_CONFIG != 0)
+       uint32_t config_data[(USB_CONFIG_MAX + 3) / 4];
+#endif
 };
 
 /* globals */

Modified: head/sys/dev/usb/usb_dynamic.c
==============================================================================
--- head/sys/dev/usb/usb_dynamic.c      Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_dynamic.c      Fri May  3 11:10:04 2013        
(r250207)
@@ -53,6 +53,7 @@
 #include <dev/usb/usb_process.h>
 #include <dev/usb/usb_device.h>
 #include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_request.h>
 #endif                 /* USB_GLOBAL_INCLUDE_FILE */
 
 /* function prototypes */
@@ -98,12 +99,8 @@ usb_temp_get_desc_w(struct usb_device *u
 static void
 usb_temp_unsetup_w(struct usb_device *udev)
 {
-       if (udev->usb_template_ptr) {
-
-               free(udev->usb_template_ptr, M_USB);
-
-               udev->usb_template_ptr = NULL;
-       }
+       usbd_free_config_desc(udev, udev->usb_template_ptr);
+       udev->usb_template_ptr = NULL;
 }
 
 void

Modified: head/sys/dev/usb/usb_freebsd.h
==============================================================================
--- head/sys/dev/usb/usb_freebsd.h      Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_freebsd.h      Fri May  3 11:10:04 2013        
(r250207)
@@ -47,6 +47,8 @@
 #define        USB_HAVE_PER_BUS_PROCESS 1
 #define        USB_HAVE_FIXED_ENDPOINT 0
 #define        USB_HAVE_FIXED_IFACE 0
+#define        USB_HAVE_FIXED_CONFIG 0
+#define        USB_HAVE_FIXED_PORT 0
 
 #define        USB_TD_GET_PROC(td) (td)->td_proc
 #define        USB_PROC_GET_GID(td) (td)->p_pgid
@@ -68,6 +70,7 @@
 #define        USB_FIFO_MAX 128                /* units */
 #define        USB_MAX_EP_STREAMS 8            /* units */
 #define        USB_MAX_EP_UNITS 32             /* units */
+#define        USB_MAX_PORTS 255               /* units */
 
 #define        USB_MAX_FS_ISOC_FRAMES_PER_XFER (120)   /* units */
 #define        USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */

Modified: head/sys/dev/usb/usb_freebsd_loader.h
==============================================================================
--- head/sys/dev/usb/usb_freebsd_loader.h       Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_freebsd_loader.h       Fri May  3 11:10:04 2013        
(r250207)
@@ -47,6 +47,8 @@
 #define        USB_HAVE_PER_BUS_PROCESS 0
 #define        USB_HAVE_FIXED_ENDPOINT 0
 #define        USB_HAVE_FIXED_IFACE 0
+#define        USB_HAVE_FIXED_CONFIG 0
+#define        USB_HAVE_FIXED_PORT 0
 
 #define        USB_TD_GET_PROC(td) (td)->td_proc
 #define        USB_PROC_GET_GID(td) (td)->p_pgid
@@ -68,6 +70,7 @@
 #define        USB_FIFO_MAX 128                /* units */
 #define        USB_MAX_EP_UNITS 32             /* units */
 #define        USB_MAX_EP_STREAMS 8            /* units */
+#define        USB_MAX_PORTS 255               /* units */
 
 #define        USB_MAX_FS_ISOC_FRAMES_PER_XFER (120)   /* units */
 #define        USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */

Modified: head/sys/dev/usb/usb_generic.c
==============================================================================
--- head/sys/dev/usb/usb_generic.c      Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_generic.c      Fri May  3 11:10:04 2013        
(r250207)
@@ -688,18 +688,21 @@ ugen_get_cdesc(struct usb_fifo *f, struc
        if ((ugd->ugd_config_index == USB_UNCONFIG_INDEX) ||
            (ugd->ugd_config_index == udev->curr_config_index)) {
                cdesc = usbd_get_config_descriptor(udev);
-               if (cdesc == NULL) {
+               if (cdesc == NULL)
                        return (ENXIO);
-               }
                free_data = 0;
 
        } else {
+#if (USB_HAVE_FIXED_CONFIG == 0)
                if (usbd_req_get_config_desc_full(udev,
-                   NULL, &cdesc, M_USBDEV,
-                   ugd->ugd_config_index)) {
+                   NULL, &cdesc, ugd->ugd_config_index)) {
                        return (ENXIO);
                }
                free_data = 1;
+#else
+               /* configuration descriptor data is shared */
+               return (EINVAL);
+#endif
        }
 
        len = UGETW(cdesc->wTotalLength);
@@ -713,9 +716,9 @@ ugen_get_cdesc(struct usb_fifo *f, struc
 
        error = copyout(cdesc, ugd->ugd_data, len);
 
-       if (free_data) {
-               free(cdesc, M_USBDEV);
-       }
+       if (free_data)
+               usbd_free_config_desc(udev, cdesc);
+
        return (error);
 }
 

Modified: head/sys/dev/usb/usb_hub.c
==============================================================================
--- head/sys/dev/usb/usb_hub.c  Fri May  3 10:37:59 2013        (r250206)
+++ head/sys/dev/usb/usb_hub.c  Fri May  3 11:10:04 2013        (r250207)
@@ -100,6 +100,9 @@ struct uhub_current_state {
 
 struct uhub_softc {
        struct uhub_current_state sc_st;/* current state */
+#if (USB_HAVE_FIXED_PORT != 0)
+       struct usb_hub sc_hub;
+#endif
        device_t sc_dev;                /* base device */
        struct mtx sc_mtx;              /* our mutex */
        struct usb_device *sc_udev;     /* USB device */
@@ -922,8 +925,8 @@ uhub_attach(device_t dev)
        struct usb_hub_descriptor hubdesc20;
        struct usb_hub_ss_descriptor hubdesc30;
        uint16_t pwrdly;
+       uint16_t nports;
        uint8_t x;
-       uint8_t nports;
        uint8_t portno;
        uint8_t removable;
        uint8_t iface_index;
@@ -1067,12 +1070,19 @@ uhub_attach(device_t dev)
                DPRINTFN(0, "portless HUB\n");
                goto error;
        }
+       if (nports > USB_MAX_PORTS) {
+               DPRINTF("Port limit exceeded\n");
+               goto error;
+       }
+#if (USB_HAVE_FIXED_PORT == 0)
        hub = malloc(sizeof(hub[0]) + (sizeof(hub->ports[0]) * nports),
            M_USBDEV, M_WAITOK | M_ZERO);
 
-       if (hub == NULL) {
+       if (hub == NULL)
                goto error;
-       }
+#else
+       hub = &sc->sc_hub;
+#endif
        udev->hub = hub;
 
        /* initialize HUB structure */
@@ -1197,10 +1207,10 @@ uhub_attach(device_t dev)
 error:
        usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
 
-       if (udev->hub) {
-               free(udev->hub, M_USBDEV);
-               udev->hub = NULL;
-       }
+#if (USB_HAVE_FIXED_PORT == 0)
+       free(udev->hub, M_USBDEV);
+#endif
+       udev->hub = NULL;
 
        mtx_destroy(&sc->sc_mtx);
 
@@ -1240,7 +1250,9 @@ uhub_detach(device_t dev)
                usb_free_device(child, 0);
        }
 
+#if (USB_HAVE_FIXED_PORT == 0)
        free(hub, M_USBDEV);
+#endif
        sc->sc_udev->hub = NULL;
 
        mtx_destroy(&sc->sc_mtx);

Modified: head/sys/dev/usb/usb_hub.h
==============================================================================
--- head/sys/dev/usb/usb_hub.h  Fri May  3 10:37:59 2013        (r250206)
+++ head/sys/dev/usb/usb_hub.h  Fri May  3 11:10:04 2013        (r250207)
@@ -48,7 +48,11 @@ struct usb_hub {
        uint16_t portpower;             /* mA per USB port */
        uint8_t isoc_last_time;
        uint8_t nports;
+#if (USB_HAVE_FIXED_PORT == 0)
        struct usb_port ports[0];
+#else
+       struct usb_port ports[USB_MAX_PORTS];
+#endif
 };
 
 /* function prototypes */

Modified: head/sys/dev/usb/usb_request.c
==============================================================================
--- head/sys/dev/usb/usb_request.c      Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_request.c      Fri May  3 11:10:04 2013        
(r250207)
@@ -1260,10 +1260,49 @@ done:
 }
 
 /*------------------------------------------------------------------------*
+ *     usbd_alloc_config_desc
+ *
+ * This function is used to allocate a zeroed configuration
+ * descriptor.
+ *
+ * Returns:
+ * NULL: Failure
+ * Else: Success
+ *------------------------------------------------------------------------*/
+void *
+usbd_alloc_config_desc(struct usb_device *udev, uint32_t size)
+{
+       if (size > USB_CONFIG_MAX) {
+               DPRINTF("Configuration descriptor too big\n");
+               return (NULL);
+       }
+#if (USB_HAVE_FIXED_CONFIG == 0)
+       return (malloc(size, M_USBDEV, M_ZERO | M_WAITOK));
+#else
+       memset(udev->config_data, 0, sizeof(udev->config_data));
+       return (udev->config_data);
+#endif
+}
+
+/*------------------------------------------------------------------------*
+ *     usbd_alloc_config_desc
+ *
+ * This function is used to free a configuration descriptor.
+ *------------------------------------------------------------------------*/
+void
+usbd_free_config_desc(struct usb_device *udev, void *ptr)
+{
+#if (USB_HAVE_FIXED_CONFIG == 0)
+       free(ptr, M_USBDEV);
+#endif
+}
+
+/*------------------------------------------------------------------------*
  *     usbd_req_get_config_desc_full
  *
  * This function gets the complete USB configuration descriptor and
- * ensures that "wTotalLength" is correct.
+ * ensures that "wTotalLength" is correct. The returned configuration
+ * descriptor is freed by calling "usbd_free_config_desc()".
  *
  * Returns:
  *    0: Success
@@ -1271,8 +1310,7 @@ done:
  *------------------------------------------------------------------------*/
 usb_error_t
 usbd_req_get_config_desc_full(struct usb_device *udev, struct mtx *mtx,
-    struct usb_config_descriptor **ppcd, struct malloc_type *mtype,
-    uint8_t index)
+    struct usb_config_descriptor **ppcd, uint8_t index)
 {
        struct usb_config_descriptor cd;
        struct usb_config_descriptor *cdesc;
@@ -1296,13 +1334,13 @@ usbd_req_get_config_desc_full(struct usb
                DPRINTF("Configuration descriptor was truncated\n");
                len = USB_CONFIG_MAX;
        }
-       cdesc = malloc(len, mtype, M_WAITOK);
+       cdesc = usbd_alloc_config_desc(udev, len);
        if (cdesc == NULL)
                return (USB_ERR_NOMEM);
        err = usbd_req_get_desc(udev, mtx, NULL, cdesc, len, len, 0,
            UDESC_CONFIG, index, 3);
        if (err) {
-               free(cdesc, mtype);
+               usbd_free_config_desc(udev, cdesc);
                return (err);
        }
        /* make sure that the device is not fooling us: */

Modified: head/sys/dev/usb/usb_request.h
==============================================================================
--- head/sys/dev/usb/usb_request.h      Fri May  3 10:37:59 2013        
(r250206)
+++ head/sys/dev/usb/usb_request.h      Fri May  3 11:10:04 2013        
(r250207)
@@ -44,7 +44,7 @@ usb_error_t usbd_req_get_config_desc(str
                    struct usb_config_descriptor *d, uint8_t conf_index);
 usb_error_t usbd_req_get_config_desc_full(struct usb_device *udev,
                    struct mtx *mtx, struct usb_config_descriptor **ppcd,
-                   struct malloc_type *mtype, uint8_t conf_index);
+                   uint8_t conf_index);
 usb_error_t usbd_req_get_desc(struct usb_device *udev, struct mtx *mtx,
                    uint16_t *actlen, void *desc, uint16_t min_len,
                    uint16_t max_len, uint16_t id, uint8_t type,
@@ -94,4 +94,7 @@ usb_error_t usbd_req_set_port_link_state
 usb_error_t usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx,
                    uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe);
 
+void * usbd_alloc_config_desc(struct usb_device *, uint32_t);
+void   usbd_free_config_desc(struct usb_device *, void *);
+
 #endif                                 /* _USB_REQUEST_H_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to