- 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.
This commit is contained in:
Hans Petter Selasky 2013-05-03 11:10:04 +00:00
parent 5d0b98f2c3
commit 2c79a775ed
11 changed files with 99 additions and 35 deletions

View File

@ -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 @@ usb_temp_setup(struct usb_device *udev,
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

View File

@ -493,7 +493,7 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
/* 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 *udev, uint8_t index)
} else {
/* normal request */
err = usbd_req_get_config_desc_full(udev,
NULL, &cdp, M_USB, index);
NULL, &cdp, index);
}
if (err) {
goto done;

View File

@ -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 */

View File

@ -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 *udev, struct usb_device_request *req, con
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

View File

@ -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 */

View File

@ -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 */

View File

@ -688,18 +688,21 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
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, struct usb_gen_descriptor *ugd)
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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -1259,11 +1259,50 @@ usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
return (err);
}
/*------------------------------------------------------------------------*
* 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 @@ usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
*------------------------------------------------------------------------*/
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_device *udev, struct mtx *mtx,
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: */

View File

@ -44,7 +44,7 @@ usb_error_t usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
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(struct usb_device *udev,
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_ */