static int hcd_alloc_coherent(struct usb_bus *bus, gfp_t mem_flags, dma_addr_t *dma_handle, void **vaddr_handle, size_t size, enum dma_data_direction dir) { unsigned char *vaddr; vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), mem_flags, dma_handle); if (!vaddr) return -ENOMEM; /* * Store the virtual address of the buffer at the end * of the allocated dma buffer. The size of the buffer * may be uneven so use unaligned functions instead * of just rounding up. It makes sense to optimize for * memory footprint over access speed since the amount * of memory available for dma may be limited. */ put_unaligned((unsigned long)*vaddr_handle, (unsigned long *)(vaddr + size)); if (dir == DMA_TO_DEVICE) memcpy(vaddr, *vaddr_handle, size); *vaddr_handle = vaddr; return 0; }
/** * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP * @dev: device the buffer will be used with * @size: requested buffer size * @mem_flags: affect whether allocation may block * @dma: used to return DMA address of buffer * * Return value is either null (indicating no buffer could be allocated), or * the cpu-space pointer to a buffer that may be used to perform DMA to the * specified device. Such cpu-space buffers are returned along with the DMA * address (through the pointer provided). * * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU * hardware during URB completion/resubmit. The implementation varies between * platforms, depending on details of how DMA will work to this device. * Using these buffers also eliminates cacheline sharing problems on * architectures where CPU caches are not DMA-coherent. On systems without * bus-snooping caches, these buffers are uncached. * * When the buffer is no longer used, free it with usb_buffer_free(). */ void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma) { if (!dev || !dev->bus) return NULL; return hcd_buffer_alloc(dev->bus, size, mem_flags, dma); }
void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma) { if (!dev || !dev->bus) return NULL; #ifdef RA2070_PRE_ALLOC //if( ( 0xf004 == size || 0xf04 == size || 0x6000 == size ) && ( 4 == dev->devnum ) ) if( 0x32004 == size || 0xf04 == size || 0x6000 == size ) { void* buf = ra2070_dma[ra2070_i].buf; *dma = ra2070_dma[ra2070_i].dma; printk("usb_buffer_alloc : dev->bus = 0x%x,size=0x%x,dma=0x%x,ra2070_i=%d,devpath=%s,devnum=%d\r\n" ,dev->bus,size,dma,ra2070_i,dev->devpath,dev->devnum); ra2070_i++; return buf; } #endif return hcd_buffer_alloc(dev->bus, size, mem_flags, dma); }