static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) { struct tegra_drm *tegra = drm->dev_private; int err; if (tegra->domain) { err = tegra_bo_get_pages(drm, bo); if (err < 0) return err; err = tegra_bo_iommu_map(tegra, bo); if (err < 0) { tegra_bo_free(drm, bo); return err; } } else { size_t size = bo->gem.size; bo->vaddr = dma_alloc_wc(drm->dev, size, &bo->paddr, GFP_KERNEL | __GFP_NOWARN); if (!bo->vaddr) { dev_err(drm->dev, "failed to allocate buffer of size %zu\n", size); return -ENOMEM; } } return 0; }
/** * drm_gem_cma_create - allocate an object with the given size * @drm: DRM device * @size: size of the object to allocate * * This function creates a CMA GEM object and allocates a contiguous chunk of * memory as backing store. The backing memory has the writecombine attribute * set. * * Returns: * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative * error code on failure. */ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, size_t size) { struct drm_gem_cma_object *cma_obj; int ret; size = round_up(size, PAGE_SIZE); cma_obj = __drm_gem_cma_create(drm, size); if (IS_ERR(cma_obj)) return cma_obj; cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); if (!cma_obj->vaddr) { dev_err(drm->dev, "failed to allocate buffer with size %zu\n", size); ret = -ENOMEM; goto error; } return cma_obj; error: drm->driver->gem_free_object(&cma_obj->base); return ERR_PTR(ret); }
/** * vsp1_dl_body_pool_create - Create a pool of bodies from a single allocation * @vsp1: The VSP1 device * @num_bodies: The number of bodies to allocate * @num_entries: The maximum number of entries that a body can contain * @extra_size: Extra allocation provided for the bodies * * Allocate a pool of display list bodies each with enough memory to contain the * requested number of entries plus the @extra_size. * * Return a pointer to a pool on success or NULL if memory can't be allocated. */ struct vsp1_dl_body_pool * vsp1_dl_body_pool_create(struct vsp1_device *vsp1, unsigned int num_bodies, unsigned int num_entries, size_t extra_size) { struct vsp1_dl_body_pool *pool; size_t dlb_size; unsigned int i; pool = kzalloc(sizeof(*pool), GFP_KERNEL); if (!pool) return NULL; pool->vsp1 = vsp1; /* * TODO: 'extra_size' is only used by vsp1_dlm_create(), to allocate * extra memory for the display list header. We need only one header per * display list, not per display list body, thus this allocation is * extraneous and should be reworked in the future. */ dlb_size = num_entries * sizeof(struct vsp1_dl_entry) + extra_size; pool->size = dlb_size * num_bodies; pool->bodies = kcalloc(num_bodies, sizeof(*pool->bodies), GFP_KERNEL); if (!pool->bodies) { kfree(pool); return NULL; } pool->mem = dma_alloc_wc(vsp1->bus_master, pool->size, &pool->dma, GFP_KERNEL); if (!pool->mem) { kfree(pool->bodies); kfree(pool); return NULL; } spin_lock_init(&pool->lock); INIT_LIST_HEAD(&pool->free); for (i = 0; i < num_bodies; ++i) { struct vsp1_dl_body *dlb = &pool->bodies[i]; dlb->pool = pool; dlb->max_entries = num_entries; dlb->dma = pool->dma + i * dlb_size; dlb->entries = pool->mem + i * dlb_size; list_add_tail(&dlb->free, &pool->free); } return pool; }
/* * Initialize a display list body object and allocate DMA memory for the body * data. The display list body object is expected to have been initialized to * 0 when allocated. */ static int vsp1_dl_body_init(struct vsp1_device *vsp1, struct vsp1_dl_body *dlb, unsigned int num_entries, size_t extra_size) { size_t size = num_entries * sizeof(*dlb->entries) + extra_size; dlb->vsp1 = vsp1; dlb->size = size; dlb->entries = dma_alloc_wc(vsp1->dev, dlb->size, &dlb->dma, GFP_KERNEL); if (!dlb->entries) return -ENOMEM; return 0; }
static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { struct snd_pcm_substream *substream = pcm->streams[stream].substream; struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size = omap_pcm_hardware.buffer_bytes_max; buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.dev = pcm->card->dev; buf->private_data = NULL; buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL); if (!buf->area) return -ENOMEM; buf->bytes = size; return 0; }
static int lpc32xx_clcd_setup(struct clcd_fb *fb) { dma_addr_t dma; fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, PANEL_SIZE, &dma, GFP_KERNEL); if (!fb->fb.screen_base) { printk(KERN_ERR "CLCD: unable to map framebuffer\n"); return -ENOMEM; } fb->fb.fix.smem_start = dma; fb->fb.fix.smem_len = PANEL_SIZE; fb->panel = &conn_lcd_panel; return 0; }
/* * Init push buffer resources */ static int host1x_pushbuffer_init(struct push_buffer *pb) { struct host1x_cdma *cdma = pb_to_cdma(pb); struct host1x *host1x = cdma_to_host1x(cdma); struct iova *alloc; u32 size; int err; pb->mapped = NULL; pb->phys = 0; pb->size = HOST1X_PUSHBUFFER_SLOTS * 8; size = pb->size + 4; /* initialize buffer pointers */ pb->fence = pb->size - 8; pb->pos = 0; if (host1x->domain) { unsigned long shift; size = iova_align(&host1x->iova, size); pb->mapped = dma_alloc_wc(host1x->dev, size, &pb->phys, GFP_KERNEL); if (!pb->mapped) return -ENOMEM; shift = iova_shift(&host1x->iova); alloc = alloc_iova(&host1x->iova, size >> shift, host1x->iova_end >> shift, true); if (!alloc) { err = -ENOMEM; goto iommu_free_mem; } pb->dma = iova_dma_addr(&host1x->iova, alloc); err = iommu_map(host1x->domain, pb->dma, pb->phys, size, IOMMU_READ); if (err) goto iommu_free_iova; } else {
static void sti_hqvdp_init(struct sti_hqvdp *hqvdp) { int size; dma_addr_t dma_addr; hqvdp->vtg_nb.notifier_call = sti_hqvdp_vtg_cb; /* Allocate memory for the VDP commands */ size = NB_VDP_CMD * sizeof(struct sti_hqvdp_cmd); hqvdp->hqvdp_cmd = dma_alloc_wc(hqvdp->dev, size, &dma_addr, GFP_KERNEL | GFP_DMA); if (!hqvdp->hqvdp_cmd) { DRM_ERROR("Failed to allocate memory for VDP cmd\n"); return; } hqvdp->hqvdp_cmd_paddr = (u32)dma_addr; memset(hqvdp->hqvdp_cmd, 0, size); }
/* * Alloc the SDRAM region of NUC900 for the frame buffer. * The buffer should be a non-cached, non-buffered, memory region * to allow palette and pixel writes without flushing the cache. */ static int nuc900fb_map_video_memory(struct fb_info *info) { struct nuc900fb_info *fbi = info->par; dma_addr_t map_dma; unsigned long map_size = PAGE_ALIGN(info->fix.smem_len); dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n", fbi, map_size); info->screen_base = dma_alloc_wc(fbi->dev, map_size, &map_dma, GFP_KERNEL); if (!info->screen_base) return -ENOMEM; memset(info->screen_base, 0x00, map_size); info->fix.smem_start = map_dma; return 0; }