Merge remote-tracking branch 'origin/upstream/android-common-3.10' into linux-linaro-lsk-v3.10-android+android-common-3.10

Conflicts:
	kernel/printk.c
This commit is contained in:
黄涛 2013-11-21 13:28:24 +08:00
commit 68a6548244
11 changed files with 142 additions and 80 deletions

View File

@ -690,6 +690,14 @@ config EARLY_PRINTK
kernel low-level debugging functions. Add earlyprintk to your
kernel parameters to enable this console.
config EARLY_PRINTK_DIRECT
bool "Early printk direct"
depends on DEBUG_LL
help
Say Y here if you want to have an early console using the
kernel low-level debugging functions and EARLY_PRINTK is
not early enough.
config OC_ETM
bool "On-chip ETM and ETB"
depends on ARM_AMBA

View File

@ -35,6 +35,12 @@ struct compat_ion_custom_data {
compat_ulong_t arg;
};
#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
struct compat_ion_allocation_data)
#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \
struct compat_ion_custom_data)
static int compat_get_ion_allocation_data(
struct compat_ion_allocation_data __user *data32,
struct ion_allocation_data __user *data)
@ -105,7 +111,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -ENOTTY;
switch (cmd) {
case ION_IOC_ALLOC:
case COMPAT_ION_IOC_ALLOC:
{
struct compat_ion_allocation_data __user *data32;
struct ion_allocation_data __user *data;
@ -119,13 +125,12 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
err = compat_get_ion_allocation_data(data32, data);
if (err)
return err;
ret = filp->f_op->unlocked_ioctl(filp, cmd,
ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
(unsigned long)data);
err = compat_put_ion_allocation_data(data32, data);
return ret ? ret : err;
}
case ION_IOC_FREE:
case COMPAT_ION_IOC_FREE:
{
struct compat_ion_allocation_data __user *data32;
struct ion_allocation_data __user *data;
@ -140,10 +145,10 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (err)
return err;
return filp->f_op->unlocked_ioctl(filp, cmd,
return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
(unsigned long)data);
}
case ION_IOC_CUSTOM: {
case COMPAT_ION_IOC_CUSTOM: {
struct compat_ion_custom_data __user *data32;
struct ion_custom_data __user *data;
int err;
@ -157,7 +162,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (err)
return err;
return filp->f_op->unlocked_ioctl(filp, cmd,
return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
(unsigned long)data);
}
case ION_IOC_SHARE:

View File

@ -224,7 +224,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
for (j = 0; j < sg_dma_len(sg) / PAGE_SIZE; j++)
for (j = 0; j < sg->length / PAGE_SIZE; j++)
buffer->pages[k++] = page++;
}
@ -383,7 +383,14 @@ static void ion_handle_get(struct ion_handle *handle)
static int ion_handle_put(struct ion_handle *handle)
{
return kref_put(&handle->ref, ion_handle_destroy);
struct ion_client *client = handle->client;
int ret;
mutex_lock(&client->lock);
ret = kref_put(&handle->ref, ion_handle_destroy);
mutex_unlock(&client->lock);
return ret;
}
static struct ion_handle *ion_handle_lookup(struct ion_client *client,
@ -403,14 +410,24 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client,
return ERR_PTR(-EINVAL);
}
static struct ion_handle *ion_uhandle_get(struct ion_client *client, int id)
static struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
int id)
{
return idr_find(&client->idr, id);
struct ion_handle *handle;
mutex_lock(&client->lock);
handle = idr_find(&client->idr, id);
if (handle)
ion_handle_get(handle);
mutex_unlock(&client->lock);
return handle ? handle : ERR_PTR(-EINVAL);
}
static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle)
{
return (ion_uhandle_get(client, handle->id) == handle);
WARN_ON(!mutex_is_locked(&client->lock));
return (idr_find(&client->idr, handle->id) == handle);
}
static int ion_handle_add(struct ion_client *client, struct ion_handle *handle)
@ -468,11 +485,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
* request of the caller allocate from it. Repeat until allocate has
* succeeded or all heaps have been tried
*/
if (WARN_ON(!len))
return ERR_PTR(-EINVAL);
len = PAGE_ALIGN(len);
if (!len)
return ERR_PTR(-EINVAL);
down_read(&dev->lock);
plist_for_each_entry(heap, &dev->heaps, node) {
/* if the caller didn't specify this heap id */
@ -503,11 +520,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
mutex_lock(&client->lock);
ret = ion_handle_add(client, handle);
mutex_unlock(&client->lock);
if (ret) {
ion_handle_put(handle);
handle = ERR_PTR(ret);
}
mutex_unlock(&client->lock);
return handle;
}
@ -527,8 +544,8 @@ void ion_free(struct ion_client *client, struct ion_handle *handle)
mutex_unlock(&client->lock);
return;
}
ion_handle_put(handle);
mutex_unlock(&client->lock);
ion_handle_put(handle);
}
EXPORT_SYMBOL(ion_free);
@ -823,6 +840,22 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
{
}
void ion_pages_sync_for_device(struct device *dev, struct page *page,
size_t size, enum dma_data_direction dir)
{
struct scatterlist sg;
sg_init_table(&sg, 1);
sg_set_page(&sg, page, size, 0);
/*
* This is not correct - sg_dma_address needs a dma_addr_t that is valid
* for the the targeted device, but this works on the currently targeted
* hardware.
*/
sg_dma_address(&sg) = page_to_phys(page);
dma_sync_sg_for_device(dev, &sg, 1, dir);
}
struct ion_vma_list {
struct list_head list;
struct vm_area_struct *vma;
@ -847,7 +880,9 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
struct page *page = buffer->pages[i];
if (ion_buffer_page_is_dirty(page))
__dma_page_cpu_to_dev(page, 0, PAGE_SIZE, dir);
ion_pages_sync_for_device(dev, ion_buffer_page(page),
PAGE_SIZE, dir);
ion_buffer_page_clean(buffer->pages + i);
}
list_for_each_entry(vma_list, &buffer->vmas, list) {
@ -1021,14 +1056,15 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
mutex_lock(&client->lock);
valid_handle = ion_handle_validate(client, handle);
mutex_unlock(&client->lock);
if (!valid_handle) {
WARN(1, "%s: invalid handle passed to share.\n", __func__);
mutex_unlock(&client->lock);
return ERR_PTR(-EINVAL);
}
buffer = handle->buffer;
ion_buffer_get(buffer);
mutex_unlock(&client->lock);
dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR);
if (IS_ERR(dmabuf)) {
ion_buffer_put(buffer);
@ -1081,18 +1117,24 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
handle = ion_handle_lookup(client, buffer);
if (!IS_ERR(handle)) {
ion_handle_get(handle);
mutex_unlock(&client->lock);
goto end;
}
mutex_unlock(&client->lock);
handle = ion_handle_create(client, buffer);
if (IS_ERR(handle))
goto end;
mutex_lock(&client->lock);
ret = ion_handle_add(client, handle);
mutex_unlock(&client->lock);
if (ret) {
ion_handle_put(handle);
handle = ERR_PTR(ret);
}
end:
mutex_unlock(&client->lock);
dma_buf_put(dmabuf);
return handle;
}
@ -1156,12 +1198,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (copy_from_user(&data, (void __user *)arg,
sizeof(struct ion_handle_data)))
return -EFAULT;
mutex_lock(&client->lock);
handle = ion_uhandle_get(client, data.handle);
mutex_unlock(&client->lock);
if (!handle)
return -EINVAL;
handle = ion_handle_get_by_id(client, data.handle);
if (IS_ERR(handle))
return PTR_ERR(handle);
ion_free(client, handle);
ion_handle_put(handle);
break;
}
case ION_IOC_SHARE:
@ -1172,8 +1213,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
return -EFAULT;
handle = ion_uhandle_get(client, data.handle);
handle = ion_handle_get_by_id(client, data.handle);
if (IS_ERR(handle))
return PTR_ERR(handle);
data.fd = ion_share_dma_buf_fd(client, handle);
ion_handle_put(handle);
if (copy_to_user((void __user *)arg, &data, sizeof(data)))
return -EFAULT;
if (data.fd < 0)

View File

@ -84,7 +84,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap,
sg = table->sgl;
for (i -= 1; i >= 0; i--) {
gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
sg_dma_len(sg));
sg->length);
sg = sg_next(sg);
}
sg_free_table(table);
@ -106,13 +106,13 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
ion_heap_buffer_zero(buffer);
if (ion_buffer_cached(buffer))
dma_sync_sg_for_device(NULL, table->sgl, table->nents,
DMA_BIDIRECTIONAL);
for_each_sg(table->sgl, sg, table->nents, i) {
if (ion_buffer_cached(buffer))
arm_dma_ops.sync_single_for_device(NULL,
pfn_to_dma(NULL, page_to_pfn(sg_page(sg))),
sg_dma_len(sg), DMA_BIDIRECTIONAL);
gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
sg_dma_len(sg));
sg->length);
}
chunk_heap->allocated -= allocated_size;
sg_free_table(table);
@ -148,7 +148,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL);
int i, ret;
chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL);
if (!chunk_heap)
return ERR_PTR(-ENOMEM);
@ -181,9 +180,9 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
}
free_vm_area(vm_struct);
arm_dma_ops.sync_single_for_device(NULL,
pfn_to_dma(NULL, page_to_pfn(phys_to_page(heap_data->base))),
heap_data->size, DMA_BIDIRECTIONAL);
ion_pages_sync_for_device(NULL, pfn_to_page(PFN_DOWN(heap_data->base)),
heap_data->size, DMA_BIDIRECTIONAL);
gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1);
chunk_heap->heap.ops = &chunk_heap_ops;
chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;

View File

@ -46,7 +46,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap,
pgprot = pgprot_writecombine(PAGE_KERNEL);
for_each_sg(table->sgl, sg, table->nents, i) {
int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE;
int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE;
struct page *page = sg_page(sg);
BUG_ON(i >= npages);
for (j = 0; j < npages_this_entry; j++) {
@ -80,14 +80,14 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
unsigned long remainder = vma->vm_end - addr;
unsigned long len = sg_dma_len(sg);
unsigned long len = sg->length;
if (offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
if (offset >= sg->length) {
offset -= sg->length;
continue;
} else if (offset) {
page += offset / PAGE_SIZE;
len = sg_dma_len(sg) - offset;
len = sg->length - offset;
offset = 0;
}
len = min(len, remainder);
@ -119,7 +119,7 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer)
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
unsigned long len = sg_dma_len(sg);
unsigned long len = sg->length;
for (j = 0; j < len / PAGE_SIZE; j++) {
struct page *sub_page = page + j;

View File

@ -34,13 +34,8 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
if (!page)
return NULL;
/* this is only being used to flush the page for dma,
this api is not really suitable for calling from a driver
but no better way to flush a page for dma exist at this time */
arm_dma_ops.sync_single_for_device(NULL,
pfn_to_dma(NULL, page_to_pfn(page)),
PAGE_SIZE << pool->order,
DMA_BIDIRECTIONAL);
ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order,
DMA_BIDIRECTIONAL);
return page;
}

View File

@ -17,6 +17,7 @@
#ifndef _ION_PRIV_H
#define _ION_PRIV_H
#include <linux/dma-direction.h>
#include <linux/kref.h>
#include <linux/mm_types.h>
#include <linux/mutex.h>
@ -357,4 +358,15 @@ void ion_page_pool_free(struct ion_page_pool *, struct page *);
int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
int nr_to_scan);
/**
* ion_pages_sync_for_device - cache flush pages for use with the specified
* device
* @dev: the device the pages will be used with
* @page: the first page to be flushed
* @size: size in bytes of region to be flushed
* @dir: direction of dma transfer
*/
void ion_pages_sync_for_device(struct device *dev, struct page *page,
size_t size, enum dma_data_direction dir);
#endif /* _ION_PRIV_H */

View File

@ -77,9 +77,8 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
page = ion_heap_alloc_pages(buffer, gfp_flags, order);
if (!page)
return 0;
arm_dma_ops.sync_single_for_device(NULL,
pfn_to_dma(NULL, page_to_pfn(page)),
PAGE_SIZE << order, DMA_BIDIRECTIONAL);
ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order,
DMA_BIDIRECTIONAL);
}
if (!page)
return 0;
@ -210,7 +209,7 @@ void ion_system_heap_free(struct ion_buffer *buffer)
for_each_sg(table->sgl, sg, table->nents, i)
free_buffer_page(sys_heap, buffer, sg_page(sg),
get_order(sg_dma_len(sg)));
get_order(sg->length));
sg_free_table(table);
kfree(table);
}

View File

@ -37,6 +37,8 @@
#define ADF_SHORT_FENCE_TIMEOUT (1 * MSEC_PER_SEC)
#define ADF_LONG_FENCE_TIMEOUT (10 * MSEC_PER_SEC)
static DEFINE_IDR(adf_devices);
static void adf_fence_wait(struct adf_device *dev, struct sync_fence *fence)
{
/* sync_fence_wait() dumps debug information on timeout. Experience
@ -455,23 +457,20 @@ static int adf_obj_init(struct adf_obj *obj, enum adf_obj_type type,
struct idr *idr, struct adf_device *parent,
const struct adf_obj_ops *ops, const char *fmt, va_list args)
{
int ret;
if (ops && ops->supports_event && !ops->set_event) {
pr_err("%s: %s implements supports_event but not set_event\n",
__func__, adf_obj_type_str(type));
return -EINVAL;
}
if (idr) {
int ret = idr_alloc(idr, obj, 0, 0, GFP_KERNEL);
if (ret < 0) {
pr_err("%s: allocating object id failed: %d\n",
__func__, ret);
return ret;
}
obj->id = ret;
} else {
obj->id = -1;
ret = idr_alloc(idr, obj, 0, 0, GFP_KERNEL);
if (ret < 0) {
pr_err("%s: allocating object id failed: %d\n", __func__, ret);
return ret;
}
obj->id = ret;
vscnprintf(obj->name, sizeof(obj->name), fmt, args);
@ -498,8 +497,7 @@ static void adf_obj_destroy(struct adf_obj *obj, struct idr *idr)
}
mutex_destroy(&obj->event_lock);
if (idr)
idr_remove(idr, obj->id);
idr_remove(idr, obj->id);
}
/**
@ -543,8 +541,8 @@ int adf_device_init(struct adf_device *dev, struct device *parent,
memset(dev, 0, sizeof(*dev));
va_start(args, fmt);
ret = adf_obj_init(&dev->base, ADF_OBJ_DEVICE, NULL, dev, &ops->base,
fmt, args);
ret = adf_obj_init(&dev->base, ADF_OBJ_DEVICE, &adf_devices, dev,
&ops->base, fmt, args);
va_end(args);
if (ret < 0)
return ret;
@ -612,7 +610,7 @@ void adf_device_destroy(struct adf_device *dev)
}
mutex_destroy(&dev->post_lock);
mutex_destroy(&dev->client_lock);
adf_obj_destroy(&dev->base, NULL);
adf_obj_destroy(&dev->base, &adf_devices);
}
EXPORT_SYMBOL(adf_device_destroy);

View File

@ -105,11 +105,6 @@ static struct device_attribute adf_interface_attrs[] = {
__ATTR_RO(vsync_timestamp),
};
static char *adf_devnode(struct device *dev, umode_t *mode)
{
return kasprintf(GFP_KERNEL, "adf/%s", dev_name(dev));
}
int adf_obj_sysfs_init(struct adf_obj *obj, struct device *parent)
{
int ret = idr_alloc(&adf_minors, obj, 0, 0, GFP_KERNEL);
@ -142,7 +137,7 @@ static char *adf_device_devnode(struct device *dev, umode_t *mode,
kuid_t *uid, kgid_t *gid)
{
struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
return kasprintf(GFP_KERNEL, "adf/%s/device", obj->name);
return kasprintf(GFP_KERNEL, "adf%d", obj->id);
}
static char *adf_interface_devnode(struct device *dev, umode_t *mode,
@ -151,8 +146,8 @@ static char *adf_interface_devnode(struct device *dev, umode_t *mode,
struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
struct adf_interface *intf = adf_obj_to_interface(obj);
struct adf_device *parent = adf_interface_parent(intf);
return kasprintf(GFP_KERNEL, "adf/%s/interface%d",
parent->base.name, intf->base.id);
return kasprintf(GFP_KERNEL, "adf-interface%d.%d",
parent->base.id, intf->base.id);
}
static char *adf_overlay_engine_devnode(struct device *dev, umode_t *mode,
@ -161,8 +156,8 @@ static char *adf_overlay_engine_devnode(struct device *dev, umode_t *mode,
struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
struct adf_overlay_engine *eng = adf_obj_to_overlay_engine(obj);
struct adf_device *parent = adf_overlay_engine_parent(eng);
return kasprintf(GFP_KERNEL, "adf/%s/overlay-engine%d",
parent->base.name, eng->base.id);
return kasprintf(GFP_KERNEL, "adf-overlay-engine%d.%d",
parent->base.id, eng->base.id);
}
static void adf_noop_release(struct device *dev)
@ -285,7 +280,6 @@ int adf_sysfs_init(void)
goto err_chrdev;
}
class->devnode = adf_devnode;
adf_class = class;
adf_major = ret;
return 0;

View File

@ -51,6 +51,10 @@
#define CREATE_TRACE_POINTS
#include <trace/events/printk.h>
#ifdef CONFIG_EARLY_PRINTK_DIRECT
extern void printascii(char *);
#endif
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
@ -1578,6 +1582,10 @@ asmlinkage int vprintk_emit(int facility, int level,
}
}
#ifdef CONFIG_EARLY_PRINTK_DIRECT
printascii(text);
#endif
if (level == -1)
level = default_message_loglevel;