--- c38fefc2287bd5a7b61199bed25850ba7fe0fc84 +++ bff7c330352797477888bd6da8e5535c2cf8777e @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2009-2011, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -132,9 +132,9 @@ struct audlpa_event { union msm_audio_event_payload payload; }; -struct audlpa_pmem_region { +struct audlpa_ion_region { struct list_head list; - struct file *file; + struct ion_handle *handle; int fd; void *vaddr; unsigned long paddr; @@ -166,7 +166,7 @@ static int auddec_dsp_config(struct audi static void audio_dsp_event(void *private, unsigned id, uint16_t *msg); static void audlpa_post_event(struct audio *audio, int type, union msm_audio_event_payload payload); -static unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr, +static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr, unsigned long len, int ref_up); static void audlpa_async_send_data(struct audio *audio, unsigned needed, uint32_t *payload); @@ -753,7 +753,7 @@ static long audlpa_process_event_req(str if (drv_evt->event_type == AUDIO_EVENT_WRITE_DONE || drv_evt->event_type == AUDIO_EVENT_READ_DONE) { mutex_lock(&audio->lock); - audlpa_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr, + audlpa_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr, drv_evt->payload.aio_buf.buf_len, 0); mutex_unlock(&audio->lock); } @@ -763,94 +763,118 @@ static long audlpa_process_event_req(str return rc; } -static int audlpa_pmem_check(struct audio *audio, +static int audlpa_ion_check(struct audio *audio, void *vaddr, unsigned long len) { - struct audlpa_pmem_region *region_elt; - struct audlpa_pmem_region t = { .vaddr = vaddr, .len = len }; + struct audlpa_ion_region *region_elt; + struct audlpa_ion_region t = {.vaddr = vaddr, .len = len }; - list_for_each_entry(region_elt, &audio->pmem_region_queue, list) { + list_for_each_entry(region_elt, &audio->ion_region_queue, list) { if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) || OVERLAPS(region_elt, &t)) { - MM_ERR("region (vaddr %p len %ld)" + MM_ERR("[%p]:region (vaddr %p len %ld)" " clashes with registered region" " (vaddr %p paddr %p len %ld)\n", - vaddr, len, + audio, vaddr, len, region_elt->vaddr, - (void *)region_elt->paddr, - region_elt->len); + (void *)region_elt->paddr, region_elt->len); return -EINVAL; } } return 0; } - -static int audlpa_pmem_add(struct audio *audio, - struct msm_audio_pmem_info *info) +static int audlpa_ion_add(struct audio *audio, + struct msm_audio_ion_info *info) { - unsigned long paddr, kvaddr, len; - struct file *file; - struct audlpa_pmem_region *region; + ion_phys_addr_t paddr; + size_t len; + unsigned long kvaddr; + struct audlpa_ion_region *region; int rc = -EINVAL; + struct ion_handle *handle; + unsigned long ionflag; - MM_DBG("\n"); /* Macro prints the file name and function */ + MM_ERR("\n"); /* Macro prints the file name and function */ region = kmalloc(sizeof(*region), GFP_KERNEL); if (!region) { rc = -ENOMEM; goto end; } - - if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) { - kfree(region); - goto end; + handle = ion_import_fd(audio->client, info->fd); + if (IS_ERR_OR_NULL(handle)) { + pr_err("%s: could not get handle of the given fd\n", __func__); + goto import_error; } - - rc = audlpa_pmem_check(audio, info->vaddr, len); + rc = ion_handle_get_flags(audio->client, handle, &ionflag); + if (rc) { + pr_err("%s: could not get flags for the handle\n", __func__); + goto flag_error; + } + kvaddr = (unsigned long)ion_map_kernel(audio->client, handle, ionflag); + if (IS_ERR_OR_NULL((void *)kvaddr)) { + pr_err("%s: could not get virtual address\n", __func__); + goto map_error; + } + rc = ion_phys(audio->client, handle, &paddr, &len); + if (rc) { + pr_err("%s: could not get physical address\n", __func__); + goto ion_error; + } + rc = audlpa_ion_check(audio, info->vaddr, len); if (rc < 0) { - put_pmem_file(file); - kfree(region); - goto end; + MM_ERR("audpcm_ion_check failed\n"); + goto ion_error; } - + region->handle = handle; region->vaddr = info->vaddr; region->fd = info->fd; region->paddr = paddr; region->kvaddr = kvaddr; region->len = len; - region->file = file; region->ref_cnt = 0; - MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr, - region->vaddr, region->len); - list_add_tail(®ion->list, &audio->pmem_region_queue); + MM_DBG("[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n", + audio, region->paddr, region->vaddr, + region->len, region->kvaddr); + list_add_tail(®ion->list, &audio->ion_region_queue); + + return rc; + +ion_error: + ion_unmap_kernel(audio->client, handle); +map_error: +flag_error: + ion_free(audio->client, handle); +import_error: + kfree(region); end: return rc; } -static int audlpa_pmem_remove(struct audio *audio, - struct msm_audio_pmem_info *info) +static int audlpa_ion_remove(struct audio *audio, + struct msm_audio_ion_info *info) { - struct audlpa_pmem_region *region; + struct audlpa_ion_region *region; struct list_head *ptr, *next; int rc = -EINVAL; - MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr); + list_for_each_safe(ptr, next, &audio->ion_region_queue) { + region = list_entry(ptr, struct audlpa_ion_region, list); - list_for_each_safe(ptr, next, &audio->pmem_region_queue) { - region = list_entry(ptr, struct audlpa_pmem_region, list); - - if ((region->fd == info->fd) && + if (region != NULL && (region->fd == info->fd) && (region->vaddr == info->vaddr)) { if (region->ref_cnt) { - MM_DBG("region %p in use ref_cnt %d\n", - region, region->ref_cnt); + MM_DBG("%s[%p]:region %p in use ref_cnt %d\n", + __func__, audio, region, + region->ref_cnt); break; } MM_DBG("remove region fd %d vaddr %p\n", info->fd, info->vaddr); list_del(®ion->list); - put_pmem_file(region->file); + ion_unmap_kernel(audio->client, region->handle); + ion_free(audio->client, region->handle); kfree(region); rc = 0; break; @@ -860,23 +884,20 @@ static int audlpa_pmem_remove(struct aud return rc; } -static int audlpa_pmem_lookup_vaddr(struct audio *audio, void *addr, - unsigned long len, struct audlpa_pmem_region **region) +static int audlpa_ion_lookup_vaddr(struct audio *audio, void *addr, + unsigned long len, struct audlpa_ion_region **region) { - struct audlpa_pmem_region *region_elt; - + struct audlpa_ion_region *region_elt; int match_count = 0; - *region = NULL; /* returns physical address or zero */ - list_for_each_entry(region_elt, &audio->pmem_region_queue, - list) { + list_for_each_entry(region_elt, &audio->ion_region_queue, list) { if (addr >= region_elt->vaddr && addr < region_elt->vaddr + region_elt->len && addr + len <= region_elt->vaddr + region_elt->len) { /* offset since we could pass vaddr inside a registerd - * pmem buffer + * ion buffer */ match_count++; @@ -886,13 +907,16 @@ static int audlpa_pmem_lookup_vaddr(stru } if (match_count > 1) { - MM_ERR("multiple hits for vaddr %p, len %ld\n", addr, len); - list_for_each_entry(region_elt, - &audio->pmem_region_queue, list) { + MM_ERR("%s[%p]:multiple hits for vaddr %p, len %ld\n", + __func__, audio, addr, len); + list_for_each_entry(region_elt, &audio->ion_region_queue, + list) { if (addr >= region_elt->vaddr && addr < region_elt->vaddr + region_elt->len && addr + len <= region_elt->vaddr + region_elt->len) - MM_ERR("\t%p, %ld --> %p\n", region_elt->vaddr, + MM_ERR("\t%s[%p]:%p, %ld --> %p\n", + __func__, audio, + region_elt->vaddr, region_elt->len, (void *)region_elt->paddr); } @@ -900,17 +924,17 @@ static int audlpa_pmem_lookup_vaddr(stru return *region ? 0 : -1; } - -unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr, +static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr, unsigned long len, int ref_up) { - struct audlpa_pmem_region *region; + struct audlpa_ion_region *region; unsigned long paddr; int ret; - ret = audlpa_pmem_lookup_vaddr(audio, addr, len, ®ion); + ret = audlpa_ion_lookup_vaddr(audio, addr, len, ®ion); if (ret) { - MM_ERR("lookup (%p, %ld) failed\n", addr, len); + MM_ERR("%s[%p]:lookup (%p, %ld) failed\n", + __func__, audio, addr, len); return 0; } if (ref_up) @@ -944,7 +968,7 @@ static int audlpa_aio_buf_add(struct aud buf_node->buf.buf_addr, buf_node->buf.buf_len, buf_node->buf.data_len); - buf_node->paddr = audlpa_pmem_fixup( + buf_node->paddr = audlpa_ion_fixup( audio, buf_node->buf.buf_addr, buf_node->buf.buf_len, 1); @@ -1232,25 +1256,26 @@ static long audio_ioctl(struct file *fil audio->drv_status &= ~ADRV_STATUS_PAUSE; break; - case AUDIO_REGISTER_PMEM: { - struct msm_audio_pmem_info info; - MM_DBG("AUDIO_REGISTER_PMEM\n"); - if (copy_from_user(&info, (void *) arg, sizeof(info))) + case AUDIO_REGISTER_ION: { + struct msm_audio_ion_info info; + MM_DBG("AUDIO_REGISTER_ION\n"); + if (copy_from_user(&info, (void *) arg, sizeof(info))) rc = -EFAULT; else - rc = audlpa_pmem_add(audio, &info); + rc = audlpa_ion_add(audio, &info); break; } - case AUDIO_DEREGISTER_PMEM: { - struct msm_audio_pmem_info info; - MM_DBG("AUDIO_DEREGISTER_PMEM\n"); - if (copy_from_user(&info, (void *) arg, sizeof(info))) + case AUDIO_DEREGISTER_ION: { + struct msm_audio_ion_info info; + MM_DBG("AUDIO_DEREGISTER_ION\n"); + if (copy_from_user(&info, (void *) arg, sizeof(info))) rc = -EFAULT; else - rc = audlpa_pmem_remove(audio, &info); + rc = audlpa_ion_remove(audio, &info); break; } + case AUDIO_ASYNC_WRITE: if (audio->drv_status & ADRV_STATUS_FSYNC) rc = -EBUSY; @@ -1336,15 +1361,16 @@ int audlpa_fsync(struct file *file, int return audlpa_async_fsync(audio); } -static void audlpa_reset_pmem_region(struct audio *audio) +static void audpcm_reset_ion_region(struct audio *audio) { - struct audlpa_pmem_region *region; + struct audlpa_ion_region *region; struct list_head *ptr, *next; - list_for_each_safe(ptr, next, &audio->pmem_region_queue) { - region = list_entry(ptr, struct audlpa_pmem_region, list); + list_for_each_safe(ptr, next, &audio->ion_region_queue) { + region = list_entry(ptr, struct audlpa_ion_region, list); list_del(®ion->list); - put_pmem_file(region->file); + ion_unmap_kernel(audio->client, region->handle); + ion_free(audio->client, region->handle); kfree(region); } @@ -1362,7 +1388,7 @@ static int audio_release(struct inode *i auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id); audio_disable(audio); audlpa_async_flush(audio); - audlpa_reset_pmem_region(audio); + audpcm_reset_ion_region(audio); msm_adsp_put(audio->audplay); audpp_adec_free(audio->dec_id); @@ -1373,13 +1399,12 @@ static int audio_release(struct inode *i audio->event_abort = 1; wake_up(&audio->event_wait); audlpa_reset_event_queue(audio); - iounmap(audio->data); - pmem_kfree(audio->phys); mutex_unlock(&audio->lock); #ifdef CONFIG_DEBUG_FS if (audio->dentry) debugfs_remove(audio->dentry); #endif + ion_client_destroy(audio->client); kfree(audio); return 0; } @@ -1550,7 +1575,7 @@ static int audio_open(struct inode *inod spin_lock_init(&audio->dsp_lock); init_waitqueue_head(&audio->write_wait); INIT_LIST_HEAD(&audio->out_queue); - INIT_LIST_HEAD(&audio->pmem_region_queue); + INIT_LIST_HEAD(&audio->ion_region_queue); INIT_LIST_HEAD(&audio->free_event_queue); INIT_LIST_HEAD(&audio->event_queue); init_waitqueue_head(&audio->wait); @@ -1611,13 +1636,19 @@ static int audio_open(struct inode *inod break; } } + + audio->client = msm_ion_client_create(UINT_MAX, "Audio_LPA_Client"); + if (IS_ERR_OR_NULL(audio->client)) { + pr_err("Unable to create ION client\n"); + goto err; + } + MM_DBG("Ion client created\n"); + done: return rc; event_err: msm_adsp_put(audio->audplay); err: - iounmap(audio->data); - pmem_kfree(audio->phys); audpp_adec_free(audio->dec_id); MM_INFO("audio instance 0x%08x freeing\n", (int)audio); kfree(audio);