cregit-Linux how code gets into the kernel

Release 4.11 drivers/usb/core/buffer.c

Directory: drivers/usb/core
/*
 * DMA memory management for framework level HCD code (hc_driver)
 *
 * This implementation plugs in through generic "usb_bus" level methods,
 * and should work with all USB controllers, regardless of bus type.
 *
 * Released under the GPLv2 only.
 * SPDX-License-Identifier: GPL-2.0
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>


/*
 * DMA-Coherent Buffers
 */

/* FIXME tune these based on pool statistics ... */

static size_t pool_max[HCD_BUFFER_POOLS] = {
	32, 128, 512, 2048,
};


void __init usb_init_pool_max(void) { /* * The pool_max values must never be smaller than * ARCH_KMALLOC_MINALIGN. */ if (ARCH_KMALLOC_MINALIGN <= 32) ; /* Original value is okay */ else if (ARCH_KMALLOC_MINALIGN <= 64) pool_max[0] = 64; else if (ARCH_KMALLOC_MINALIGN <= 128) pool_max[0] = 0; /* Don't use this pool */ else BUILD_BUG(); /* We don't allow this */ }

Contributors

PersonTokensPropCommitsCommitProp
Sebastian Andrzej Siewior51100.00%1100.00%
Total51100.00%1100.00%

/* SETUP primitives */ /** * hcd_buffer_create - initialize buffer pools * @hcd: the bus whose buffer pools are to be initialized * Context: !in_interrupt() * * Call this as part of initializing a host controller that uses the dma * memory allocators. It initializes some pools of dma-coherent memory that * will be shared by all drivers using that controller. * * Call hcd_buffer_destroy() to clean up after using those pools. * * Return: 0 if successful. A negative errno value otherwise. */
int hcd_buffer_create(struct usb_hcd *hcd) { char name[16]; int i, size; if (!IS_ENABLED(CONFIG_HAS_DMA) || (!hcd->self.controller->dma_mask && !(hcd->driver->flags & HCD_LOCAL_MEM))) return 0; for (i = 0; i < HCD_BUFFER_POOLS; i++) { size = pool_max[i]; if (!size) continue; snprintf(name, sizeof(name), "buffer-%d", size); hcd->pool[i] = dma_pool_create(name, hcd->self.controller, size, size, 0); if (!hcd->pool[i]) { hcd_buffer_destroy(hcd); return -ENOMEM; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Brownell10069.44%114.29%
Chris Humbert149.72%114.29%
Magnus Damm117.64%114.29%
Geert Uytterhoeven85.56%114.29%
Greg Kroah-Hartman53.47%114.29%
Deepak Saxena42.78%114.29%
Nizam Haider21.39%114.29%
Total144100.00%7100.00%

/** * hcd_buffer_destroy - deallocate buffer pools * @hcd: the bus whose buffer pools are to be destroyed * Context: !in_interrupt() * * This frees the buffer pools created by hcd_buffer_create(). */
void hcd_buffer_destroy(struct usb_hcd *hcd) { int i; if (!IS_ENABLED(CONFIG_HAS_DMA)) return; for (i = 0; i < HCD_BUFFER_POOLS; i++) { struct dma_pool *pool = hcd->pool[i]; if (pool) { dma_pool_destroy(pool); hcd->pool[i] = NULL; } } }

Contributors

PersonTokensPropCommitsCommitProp
David Brownell5782.61%125.00%
Geert Uytterhoeven913.04%125.00%
Deepak Saxena22.90%125.00%
Mika Kukkonen11.45%125.00%
Total69100.00%4100.00%

/* sometimes alloc/free could use kmalloc with GFP_DMA, for * better sharing and to leverage mm/slab.c intelligence. */
void *hcd_buffer_alloc( struct usb_bus *bus, size_t size, gfp_t mem_flags, dma_addr_t *dma ) { struct usb_hcd *hcd = bus_to_hcd(bus); int i; if (size == 0) return NULL; /* some USB hosts just use PIO */ if (!IS_ENABLED(CONFIG_HAS_DMA) || (!bus->controller->dma_mask && !(hcd->driver->flags & HCD_LOCAL_MEM))) { *dma = ~(dma_addr_t) 0; return kmalloc(size, mem_flags); } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max[i]) return dma_pool_alloc(hcd->pool[i], mem_flags, dma); } return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags); }

Contributors

PersonTokensPropCommitsCommitProp
David Brownell10773.29%222.22%
Magnus Damm117.53%111.11%
Chunfeng Yun96.16%111.11%
Geert Uytterhoeven85.48%111.11%
Deepak Saxena64.11%111.11%
Alan Stern32.05%111.11%
Johannes Berg10.68%111.11%
Al Viro10.68%111.11%
Total146100.00%9100.00%


void hcd_buffer_free( struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma ) { struct usb_hcd *hcd = bus_to_hcd(bus); int i; if (!addr) return; if (!IS_ENABLED(CONFIG_HAS_DMA) || (!bus->controller->dma_mask && !(hcd->driver->flags & HCD_LOCAL_MEM))) { kfree(addr); return; } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max[i]) { dma_pool_free(hcd->pool[i], addr, dma); return; } } dma_free_coherent(hcd->self.controller, size, addr, dma); }

Contributors

PersonTokensPropCommitsCommitProp
David Brownell10479.39%342.86%
Magnus Damm118.40%114.29%
Geert Uytterhoeven86.11%114.29%
Deepak Saxena53.82%114.29%
Alan Stern32.29%114.29%
Total131100.00%7100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
David Brownell40367.73%522.73%
Sebastian Andrzej Siewior538.91%14.55%
Geert Uytterhoeven335.55%14.55%
Magnus Damm335.55%14.55%
Deepak Saxena294.87%14.55%
Chris Humbert142.35%14.55%
Chunfeng Yun91.51%14.55%
Greg Kroah-Hartman61.01%29.09%
Alan Stern61.01%14.55%
Nizam Haider20.34%14.55%
Al Viro10.17%14.55%
Mika Kukkonen10.17%14.55%
Eric Lescouet10.17%14.55%
Christoph Lameter10.17%14.55%
Yacine Belkadi10.17%14.55%
Tobias Ollmann10.17%14.55%
Johannes Berg10.17%14.55%
Total595100.00%22100.00%
Directory: drivers/usb/core
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.