Merge "crypto: msm: Add support for FIPS complience"
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index 6146454..6b3e945 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -41,6 +41,7 @@
compatible = "qcom,android-usb";
reg = <0xfc42b0c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,android-usb-uicc-nluns = /bits/ 8 <1>;
};
qcom,msm-imem@fc42b000 {
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index fd4221f..91844c3 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -41,6 +41,7 @@
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,android-usb-uicc-nluns = /bits/ 8 <1>;
};
qcom,msm-imem@fe805000 {
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 3e00a46..7a08ca6 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -27,6 +27,7 @@
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,android-usb-uicc-nluns = /bits/ 8 <1>;
};
qcom,msm-imem@fe805000 {
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 414a4df..913d798 100755
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -396,6 +396,7 @@
CONFIG_USB_EHCI_MSM=y
CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
+CONFIG_USB_MON=y
CONFIG_USB_CCID_BRIDGE=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 3b2f2b5..d588fc6 100755
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -420,6 +420,7 @@
CONFIG_USB_EHCI_MSM=y
CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
+CONFIG_USB_MON=y
CONFIG_USB_CCID_BRIDGE=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index 8cb3cf3..fc57bd6 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -1808,12 +1808,12 @@
static void bke_switch(
void __iomem *baddr, uint32_t mas_index, bool req, int mode)
{
- uint32_t reg_val, val;
+ uint32_t reg_val, val, cur_val;
val = req << M_BKE_EN_EN_SHFT;
- reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index)) &
- M_BKE_EN_RMSK;
- if (val == reg_val)
+ reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index));
+ cur_val = reg_val & M_BKE_EN_RMSK;
+ if (val == cur_val)
return;
if (!req && mode == BIMC_QOS_MODE_FIXED)
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index df7760a..f19ad59 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -29,7 +29,7 @@
bool smmu_enabled;
bool audioheap_enabled;
struct iommu_group *group;
- u32 domain_id;
+ int32_t domain_id;
struct iommu_domain *domain;
};
diff --git a/arch/arm/mach-msm/qdsp6v2/voice_svc.c b/arch/arm/mach-msm/qdsp6v2/voice_svc.c
old mode 100644
new mode 100755
index 92b3003..5bf86dc
--- a/arch/arm/mach-msm/qdsp6v2/voice_svc.c
+++ b/arch/arm/mach-msm/qdsp6v2/voice_svc.c
@@ -56,8 +56,15 @@
static struct voice_svc_device *voice_svc_dev;
static struct class *voice_svc_class;
+static bool reg_dummy_sess;
+static void *dummy_q6_mvm;
+static void *dummy_q6_cvs;
dev_t device_num;
+static int voice_svc_dummy_reg(void);
+static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data,
+ void *priv);
+
static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv)
{
struct voice_svc_prvt *prtd;
@@ -127,6 +134,12 @@
return 0;
}
+static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data, void *priv)
+{
+ /* Do Nothing */
+ return 0;
+}
+
static void voice_svc_update_hdr(struct voice_svc_cmd_request* apr_req_data,
struct apr_data *aprdata,
struct voice_svc_prvt *prtd)
@@ -223,6 +236,13 @@
goto done;
}
+ if (src_port == (APR_MAX_PORTS - 1)) {
+ pr_err("%s: SRC port reserved for dummy session\n", __func__);
+ pr_err("%s: Unable to register %s\n", __func__, svc);
+ ret = -EINVAL;
+ goto done;
+ }
+
*handle = apr_register("ADSP",
svc, qdsp_apr_callback,
((src_port) << 8 | 0x0001),
@@ -449,6 +469,37 @@
return ret;
}
+static int voice_svc_dummy_reg()
+{
+ uint32_t src_port = APR_MAX_PORTS - 1;
+
+ pr_debug("%s\n", __func__);
+ dummy_q6_mvm = apr_register("ADSP", "MVM",
+ qdsp_dummy_apr_callback,
+ src_port,
+ NULL);
+ if (dummy_q6_mvm == NULL) {
+ pr_err("%s: Unable to register dummy MVM\n", __func__);
+ goto err;
+ }
+
+ dummy_q6_cvs = apr_register("ADSP", "CVS",
+ qdsp_dummy_apr_callback,
+ src_port,
+ NULL);
+ if (dummy_q6_cvs == NULL) {
+ pr_err("%s: Unable to register dummy CVS\n", __func__);
+ goto err;
+ }
+ return 0;
+err:
+ if (dummy_q6_mvm != NULL) {
+ apr_deregister(dummy_q6_mvm);
+ dummy_q6_mvm = NULL;
+ }
+ return -EINVAL;
+}
+
static int voice_svc_open(struct inode *inode, struct file *file)
{
struct voice_svc_prvt *prtd = NULL;
@@ -472,6 +523,16 @@
file->private_data = (void*)prtd;
+ /* Current APR implementation doesn't support session based
+ * multiple service registrations. The apr_deregister()
+ * function sets the destination and client IDs to zero, if
+ * deregister is called for a single service instance.
+ * To avoid this, register for additional services.
+ */
+ if (!reg_dummy_sess) {
+ voice_svc_dummy_reg();
+ reg_dummy_sess = 1;
+ }
return 0;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index eb8a75b..831f033 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1483,7 +1483,9 @@
*(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
*(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
*(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
- encode_rsp_and_send(99);
+ *(uint16_t *)(driver->apps_rsp_buf + 100) = MSG_SSID_23;
+ *(uint16_t *)(driver->apps_rsp_buf + 102) = MSG_SSID_23_LAST;
+ encode_rsp_and_send(103);
return 0;
}
/* Check for Apps Only Respond to Get Subsys Build mask */
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 309816d..9839279 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -2114,6 +2114,75 @@
return 0;
};
+static int qcedev_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct qcedev_control *podev;
+ int ret;
+ podev = platform_get_drvdata(pdev);
+
+ if (!podev || !podev->platform_support.bus_scale_table)
+ return 0;
+
+ mutex_lock(&qcedev_sent_bw_req);
+ if (podev->high_bw_req_count) {
+ ret = msm_bus_scale_client_update_request(
+ podev->bus_scale_handle, 0);
+ if (ret) {
+ pr_err("%s Unable to set to low bandwidth\n",
+ __func__);
+ goto suspend_exit;
+ }
+ ret = qce_disable_clk(podev->qce);
+ if (ret) {
+ pr_err("%s Unable disable clk\n", __func__);
+ ret = msm_bus_scale_client_update_request(
+ podev->bus_scale_handle, 1);
+ if (ret)
+ pr_err("%s Unable to set to high bandwidth\n",
+ __func__);
+ goto suspend_exit;
+ }
+ }
+
+suspend_exit:
+ mutex_unlock(&qcedev_sent_bw_req);
+ return 0;
+}
+
+static int qcedev_resume(struct platform_device *pdev)
+{
+ struct qcedev_control *podev;
+ int ret;
+ podev = platform_get_drvdata(pdev);
+
+ if (!podev || !podev->platform_support.bus_scale_table)
+ return 0;
+
+ mutex_lock(&qcedev_sent_bw_req);
+ if (podev->high_bw_req_count) {
+ ret = qce_enable_clk(podev->qce);
+ if (ret) {
+ pr_err("%s Unable enable clk\n", __func__);
+ goto resume_exit;
+ }
+ ret = msm_bus_scale_client_update_request(
+ podev->bus_scale_handle, 1);
+ if (ret) {
+ pr_err("%s Unable to set to high bandwidth\n",
+ __func__);
+ ret = qce_disable_clk(podev->qce);
+ if (ret)
+ pr_err("%s Unable enable clk\n",
+ __func__);
+ goto resume_exit;
+ }
+ }
+
+resume_exit:
+ mutex_unlock(&qcedev_sent_bw_req);
+ return 0;
+}
+
static struct of_device_id qcedev_match[] = {
{ .compatible = "qcom,qcedev",
},
@@ -2123,6 +2192,8 @@
static struct platform_driver qcedev_plat_driver = {
.probe = qcedev_probe,
.remove = qcedev_remove,
+ .suspend = qcedev_suspend,
+ .resume = qcedev_resume,
.driver = {
.name = "qce",
.owner = THIS_MODULE,
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index aa2551a..0b193a0 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -2,7 +2,7 @@
* drivers/gpu/ion/ion_heap.c
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 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
@@ -26,6 +26,7 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
#include "ion_priv.h"
void *ion_heap_map_kernel(struct ion_heap *heap,
@@ -107,16 +108,15 @@
* chunks to minimize the number of memsets and vmaps/vunmaps.
*
* Note that the `pages' array should be composed of all 4K pages.
+ *
+ * NOTE: This function does not guarantee synchronization of the caches
+ * and thus caller is responsible for handling any cache maintenance
+ * operations needed.
*/
int ion_heap_pages_zero(struct page **pages, int num_pages)
{
- int i, j, k, npages_to_vmap;
+ int i, j, npages_to_vmap;
void *ptr = NULL;
- /*
- * It's cheaper just to use writecombine memory and skip the
- * cache vs. using a cache memory and trying to flush it afterwards
- */
- pgprot_t pgprot = pgprot_writecombine(pgprot_kernel);
/*
* As an optimization, we manually zero out all of the pages
@@ -132,7 +132,7 @@
for (j = 0; j < MAX_VMAP_RETRIES && npages_to_vmap;
++j) {
ptr = vmap(&pages[i], npages_to_vmap,
- VM_IOREMAP, pgprot);
+ VM_IOREMAP, PAGE_KERNEL);
if (ptr)
break;
else
@@ -141,21 +141,6 @@
if (!ptr)
return -ENOMEM;
- /*
- * We have to invalidate the cache here because there
- * might be dirty lines to these physical pages (which
- * we don't care about) that could get written out at
- * any moment.
- */
- for (k = 0; k < npages_to_vmap; k++) {
- void *p = kmap_atomic(pages[i + k]);
- phys_addr_t phys = page_to_phys(
- pages[i + k]);
-
- dmac_inv_range(p, p + PAGE_SIZE);
- outer_inv_range(phys, phys + PAGE_SIZE);
- kunmap_atomic(p);
- }
memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
vunmap(ptr);
}
@@ -163,11 +148,12 @@
return 0;
}
-static int ion_heap_alloc_pages_mem(int page_tbl_size,
- struct pages_mem *pages_mem)
+int ion_heap_alloc_pages_mem(struct pages_mem *pages_mem)
{
struct page **pages;
+ unsigned int page_tbl_size;
pages_mem->free_fn = kfree;
+ page_tbl_size = sizeof(struct page *) * (pages_mem->size >> PAGE_SHIFT);
if (page_tbl_size > SZ_8K) {
/*
* Do fallback to ensure we have a balance between
@@ -191,7 +177,7 @@
return 0;
}
-static void ion_heap_free_pages_mem(struct pages_mem *pages_mem)
+void ion_heap_free_pages_mem(struct pages_mem *pages_mem)
{
pages_mem->free_fn(pages_mem->pages);
}
@@ -201,15 +187,17 @@
int i, ret;
struct pages_mem pages_mem;
int npages = 1 << order;
- int page_tbl_size = sizeof(struct page *) * npages;
+ pages_mem.size = npages * PAGE_SIZE;
- if (ion_heap_alloc_pages_mem(page_tbl_size, &pages_mem))
+ if (ion_heap_alloc_pages_mem(&pages_mem))
return -ENOMEM;
for (i = 0; i < (1 << order); ++i)
pages_mem.pages[i] = page + i;
ret = ion_heap_pages_zero(pages_mem.pages, npages);
+ dma_sync_single_for_device(NULL, page_to_phys(page), pages_mem.size,
+ DMA_BIDIRECTIONAL);
ion_heap_free_pages_mem(&pages_mem);
return ret;
}
@@ -218,16 +206,12 @@
{
struct sg_table *table = buffer->sg_table;
struct scatterlist *sg;
- int i, j, ret = 0, npages = 0, page_tbl_size = 0;
+ int i, j, ret = 0, npages = 0;
struct pages_mem pages_mem;
- for_each_sg(table->sgl, sg, table->nents, i) {
- unsigned long len = sg_dma_len(sg);
- int nrpages = len >> PAGE_SHIFT;
- page_tbl_size += sizeof(struct page *) * nrpages;
- }
+ pages_mem.size = PAGE_ALIGN(buffer->size);
- if (ion_heap_alloc_pages_mem(page_tbl_size, &pages_mem))
+ if (ion_heap_alloc_pages_mem(&pages_mem))
return -ENOMEM;
for_each_sg(table->sgl, sg, table->nents, i) {
@@ -239,6 +223,8 @@
}
ret = ion_heap_pages_zero(pages_mem.pages, npages);
+ dma_sync_sg_for_device(NULL, table->sgl, table->nents,
+ DMA_BIDIRECTIONAL);
ion_heap_free_pages_mem(&pages_mem);
return ret;
}
diff --git a/drivers/gpu/ion/ion_page_pool.c b/drivers/gpu/ion/ion_page_pool.c
index cc2a36d..a1845de 100644
--- a/drivers/gpu/ion/ion_page_pool.c
+++ b/drivers/gpu/ion/ion_page_pool.c
@@ -32,7 +32,6 @@
static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
{
struct page *page;
- struct scatterlist sg;
page = alloc_pages(pool->gfp_mask & ~__GFP_ZERO, pool->order);
@@ -43,11 +42,6 @@
if (ion_heap_high_order_page_zero(page, pool->order))
goto error_free_pages;
- sg_init_table(&sg, 1);
- sg_set_page(&sg, page, PAGE_SIZE << pool->order, 0);
- sg_dma_address(&sg) = sg_phys(&sg);
- dma_sync_sg_for_device(NULL, &sg, 1, DMA_BIDIRECTIONAL);
-
return page;
error_free_pages:
__free_pages(page, pool->order);
@@ -104,22 +98,25 @@
return page;
}
-void *ion_page_pool_alloc(struct ion_page_pool *pool)
+void *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool)
{
struct page *page = NULL;
BUG_ON(!pool);
- mutex_lock(&pool->mutex);
- if (pool->high_count)
- page = ion_page_pool_remove(pool, true);
- else if (pool->low_count)
- page = ion_page_pool_remove(pool, false);
- mutex_unlock(&pool->mutex);
+ *from_pool = true;
- if (!page)
+ if (mutex_trylock(&pool->mutex)) {
+ if (pool->high_count)
+ page = ion_page_pool_remove(pool, true);
+ else if (pool->low_count)
+ page = ion_page_pool_remove(pool, false);
+ mutex_unlock(&pool->mutex);
+ }
+ if (!page) {
page = ion_page_pool_alloc_pages(pool);
-
+ *from_pool = false;
+ }
return page;
}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index c57efc1..1f78cb1 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -2,7 +2,7 @@
* drivers/gpu/ion/ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 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
@@ -223,6 +223,7 @@
struct pages_mem {
struct page **pages;
+ u32 size;
void (*free_fn) (const void *);
};
@@ -237,6 +238,8 @@
int ion_heap_pages_zero(struct page **pages, int num_pages);
int ion_heap_buffer_zero(struct ion_buffer *buffer);
int ion_heap_high_order_page_zero(struct page *page, int order);
+int ion_heap_alloc_pages_mem(struct pages_mem *pages_mem);
+void ion_heap_free_pages_mem(struct pages_mem *pages_mem);
/**
* ion_heap_init_deferred_free -- initialize deferred free functionality
@@ -374,7 +377,7 @@
struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order);
void ion_page_pool_destroy(struct ion_page_pool *);
-void *ion_page_pool_alloc(struct ion_page_pool *);
+void *ion_page_pool_alloc(struct ion_page_pool *, bool *from_pool);
void ion_page_pool_free(struct ion_page_pool *, struct page *);
/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index cfdd5f4..b7ad01f 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -29,10 +29,10 @@
#include <linux/dma-mapping.h>
#include <trace/events/kmem.h>
-static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO |
+static unsigned int high_order_gfp_flags = (GFP_HIGHUSER |
__GFP_NOWARN | __GFP_NORETRY |
__GFP_NO_KSWAPD) & ~__GFP_WAIT;
-static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO |
+static unsigned int low_order_gfp_flags = (GFP_HIGHUSER |
__GFP_NOWARN);
static const unsigned int orders[] = {9, 8, 4, 0};
static const int num_orders = ARRAY_SIZE(orders);
@@ -59,13 +59,15 @@
struct page_info {
struct page *page;
+ bool from_pool;
unsigned int order;
struct list_head list;
};
static struct page *alloc_buffer_page(struct ion_system_heap *heap,
struct ion_buffer *buffer,
- unsigned long order)
+ unsigned long order,
+ bool *from_pool)
{
bool cached = ion_buffer_cached(buffer);
bool split_pages = ion_buffer_fault_user_mappings(buffer);
@@ -76,7 +78,7 @@
pool = heap->uncached_pools[order_to_index(order)];
else
pool = heap->cached_pools[order_to_index(order)];
- page = ion_page_pool_alloc(pool);
+ page = ion_page_pool_alloc(pool, from_pool);
if (!page)
return 0;
@@ -119,14 +121,14 @@
struct page *page;
struct page_info *info;
int i;
-
+ bool from_pool;
for (i = 0; i < num_orders; i++) {
if (size < order_to_size(orders[i]))
continue;
if (max_order < orders[i])
continue;
- page = alloc_buffer_page(heap, buffer, orders[i]);
+ page = alloc_buffer_page(heap, buffer, orders[i], &from_pool);
if (!page)
continue;
@@ -134,11 +136,39 @@
if (info) {
info->page = page;
info->order = orders[i];
+ info->from_pool = from_pool;
}
return info;
}
return NULL;
}
+static unsigned int process_info(struct page_info *info,
+ struct scatterlist *sg,
+ struct scatterlist *sg_sync,
+ struct pages_mem *data, unsigned int i)
+{
+ struct page *page = info->page;
+ unsigned int j;
+
+ if (sg_sync) {
+ sg_set_page(sg_sync, page, (1 << info->order) * PAGE_SIZE, 0);
+ sg_dma_address(sg_sync) = page_to_phys(page);
+ }
+ sg_set_page(sg, page, (1 << info->order) * 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);
+ if (data) {
+ for (j = 0; j < (1 << info->order); ++j)
+ data->pages[i++] = nth_page(page, j);
+ }
+ list_del(&info->list);
+ kfree(info);
+ return i;
+}
static int ion_system_heap_allocate(struct ion_heap *heap,
struct ion_buffer *buffer,
@@ -149,29 +179,51 @@
struct ion_system_heap,
heap);
struct sg_table *table;
+ struct sg_table table_sync;
struct scatterlist *sg;
+ struct scatterlist *sg_sync;
int ret;
struct list_head pages;
+ struct list_head pages_from_pool;
struct page_info *info, *tmp_info;
int i = 0;
+ unsigned int nents_sync = 0;
unsigned long size_remaining = PAGE_ALIGN(size);
unsigned int max_order = orders[0];
+ struct pages_mem data;
+ unsigned int sz;
bool split_pages = ion_buffer_fault_user_mappings(buffer);
+ data.size = 0;
INIT_LIST_HEAD(&pages);
+ INIT_LIST_HEAD(&pages_from_pool);
while (size_remaining > 0) {
info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order);
if (!info)
goto err;
- list_add_tail(&info->list, &pages);
- size_remaining -= (1 << info->order) * PAGE_SIZE;
+
+ sz = (1 << info->order) * PAGE_SIZE;
+
+ if (info->from_pool) {
+ list_add_tail(&info->list, &pages_from_pool);
+ } else {
+ list_add_tail(&info->list, &pages);
+ data.size += sz;
+ ++nents_sync;
+ }
+ size_remaining -= sz;
max_order = info->order;
i++;
}
+ ret = ion_heap_alloc_pages_mem(&data);
+
+ if (ret)
+ goto err;
+
table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!table)
- goto err;
+ goto err_free_data_pages;
if (split_pages)
ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE,
@@ -182,32 +234,91 @@
if (ret)
goto err1;
- sg = table->sgl;
- list_for_each_entry_safe(info, tmp_info, &pages, list) {
- struct page *page = info->page;
- if (split_pages) {
- for (i = 0; i < (1 << info->order); i++) {
- sg_set_page(sg, page + i, PAGE_SIZE, 0);
- sg = sg_next(sg);
- }
- } else {
- sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE,
- 0);
- sg = sg_next(sg);
- }
- list_del(&info->list);
- kfree(info);
+ if (nents_sync) {
+ ret = sg_alloc_table(&table_sync, nents_sync, GFP_KERNEL);
+ if (ret)
+ goto err_free_sg;
}
+ i = 0;
+ sg = table->sgl;
+ sg_sync = table_sync.sgl;
+
+ /*
+ * We now have two separate lists. One list contains pages from the
+ * pool and the other pages from buddy. We want to merge these
+ * together while preserving the ordering of the pages (higher order
+ * first).
+ */
+ do {
+ if (!list_empty(&pages))
+ info = list_first_entry(&pages, struct page_info, list);
+ else
+ info = NULL;
+ if (!list_empty(&pages_from_pool))
+ tmp_info = list_first_entry(&pages_from_pool,
+ struct page_info, list);
+ else
+ tmp_info = NULL;
+
+ if (info && tmp_info) {
+ if (info->order >= tmp_info->order) {
+ i = process_info(info, sg, sg_sync, &data, i);
+ sg_sync = sg_next(sg_sync);
+ } else {
+ i = process_info(tmp_info, sg, 0, 0, i);
+ }
+ } else if (info) {
+ i = process_info(info, sg, sg_sync, &data, i);
+ sg_sync = sg_next(sg_sync);
+ } else if (tmp_info) {
+ i = process_info(tmp_info, sg, 0, 0, i);
+ } else {
+ BUG();
+ }
+ sg = sg_next(sg);
+
+ } while (sg);
+
+ ret = ion_heap_pages_zero(data.pages, data.size >> PAGE_SHIFT);
+ if (ret) {
+ pr_err("Unable to zero pages\n");
+ goto err_free_sg2;
+ }
+
+ if (nents_sync)
+ dma_sync_sg_for_device(NULL, table_sync.sgl, table_sync.nents,
+ DMA_BIDIRECTIONAL);
+
buffer->priv_virt = table;
+ if (nents_sync)
+ sg_free_table(&table_sync);
+ ion_heap_free_pages_mem(&data);
return 0;
+err_free_sg2:
+ /* We failed to zero buffers. Bypass pool */
+ buffer->flags |= ION_FLAG_FREED_FROM_SHRINKER;
+
+ for_each_sg(table->sgl, sg, table->nents, i)
+ free_buffer_page(sys_heap, buffer, sg_page(sg),
+ get_order(sg->length));
+ if (nents_sync)
+ sg_free_table(&table_sync);
+err_free_sg:
+ sg_free_table(table);
err1:
kfree(table);
+err_free_data_pages:
+ ion_heap_free_pages_mem(&data);
err:
list_for_each_entry_safe(info, tmp_info, &pages, list) {
free_buffer_page(sys_heap, buffer, info->page, info->order);
kfree(info);
}
+ list_for_each_entry_safe(info, tmp_info, &pages_from_pool, list) {
+ free_buffer_page(sys_heap, buffer, info->page, info->order);
+ kfree(info);
+ }
return -ENOMEM;
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d163317..4fbbda4 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3444,13 +3444,17 @@
struct adreno_busy_data busy_data;
memset(stats, 0, sizeof(*stats));
+
/*
- * Get the busy cycles counted since the counter was last reset.
* If we're not currently active, there shouldn't have been
* any cycles since the last time this function was called.
*/
- if (device->state == KGSL_STATE_ACTIVE)
- adreno_dev->gpudev->busy_cycles(adreno_dev, &busy_data);
+
+ if (device->state != KGSL_STATE_ACTIVE)
+ return;
+
+ /* Get the busy cycles counted since the counter was last reset */
+ adreno_dev->gpudev->busy_cycles(adreno_dev, &busy_data);
stats->busy_time = adreno_ticks_to_us(busy_data.gpu_busy,
kgsl_pwrctrl_active_freq(pwr));
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 353b55f..c92b29d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -352,6 +352,10 @@
msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x34);
msm_camera_io_w(vfe_dev->stats_data.stats_mask,
vfe_dev->vfe_base + 0x44);
+ msm_camera_io_w(1, vfe_dev->vfe_base + 0x24);
+ msm_camera_io_w(0, vfe_dev->vfe_base + 0x30);
+ msm_camera_io_w_mb(0, vfe_dev->vfe_base + 0x34);
+ msm_camera_io_w(1, vfe_dev->vfe_base + 0x24);
}
static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index d3a848a..b4196e9 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -56,6 +56,16 @@
#define MSM_CPP_NOMINAL_CLOCK 266670000
#define MSM_CPP_TURBO_CLOCK 320000000
+#define CPP_FW_VERSION_1_2_0 0x10020000
+#define CPP_FW_VERSION_1_4_0 0x10040000
+#define CPP_FW_VERSION_1_6_0 0x10060000
+#define CPP_FW_VERSION_1_8_0 0x10080000
+
+/* stripe information offsets in frame command */
+#define STRIPE_BASE_FW_1_2_0 130
+#define STRIPE_BASE_FW_1_4_0 140
+#define STRIPE_BASE_FW_1_6_0 464
+
struct msm_cpp_timer_data_t {
struct cpp_device *cpp_dev;
struct msm_cpp_frame_info_t *processed_frame;
@@ -918,7 +928,8 @@
msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_CMD);
msm_cpp_poll(cpp_dev->base, 0x2);
msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_FW_VER);
- pr_info("CPP FW Version: 0x%x\n", msm_cpp_read(cpp_dev->base));
+ cpp_dev->fw_version = msm_cpp_read(cpp_dev->base);
+ pr_info("CPP FW Version: 0x%08x\n", cpp_dev->fw_version);
msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_TRAILER);
/*Disable MC clock*/
@@ -1284,12 +1295,9 @@
unsigned long in_phyaddr, out_phyaddr0, out_phyaddr1;
uint16_t num_stripes = 0;
struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info;
- struct msm_cpp_frame_info_t *u_frame_info =
- (struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
int32_t status = 0;
- uint8_t fw_version_1_2_x = 0;
int in_fd;
-
+ int32_t stripe_base = 0;
int i = 0;
if (!new_frame) {
pr_err("Insufficient memory. return\n");
@@ -1330,7 +1338,16 @@
}
new_frame->cpp_cmd_msg = cpp_frame_msg;
-
+ if (cpp_frame_msg == NULL ||
+ (new_frame->msg_len < MSM_CPP_MIN_FRAME_LENGTH)) {
+ pr_err("%s %d Length is not correct or frame message is missing\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (cpp_frame_msg[new_frame->msg_len - 1] != MSM_CPP_MSG_ID_TRAILER) {
+ pr_err("%s %d Invalid frame message\n", __func__, __LINE__);
+ return -EINVAL;
+ }
in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
&new_frame->input_buffer_info,
((new_frame->input_buffer_info.identity >> 16) & 0xFFFF),
@@ -1404,22 +1421,36 @@
((cpp_frame_msg[12] >> 10) & 0x3FF) +
(cpp_frame_msg[12] & 0x3FF);
- fw_version_1_2_x = 0;
- if ((cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_0) ||
- (cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_1) ||
- (cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_2_0_0))
- fw_version_1_2_x = 2;
+ if ((cpp_dev->fw_version & 0xffff0000) ==
+ CPP_FW_VERSION_1_2_0) {
+ stripe_base = STRIPE_BASE_FW_1_2_0;
+ } else if ((cpp_dev->fw_version & 0xffff0000) ==
+ CPP_FW_VERSION_1_4_0) {
+ stripe_base = STRIPE_BASE_FW_1_4_0;
+ } else if ((cpp_dev->fw_version & 0xffff0000) ==
+ CPP_FW_VERSION_1_6_0) {
+ stripe_base = STRIPE_BASE_FW_1_6_0;
+ } else {
+ pr_err("invalid fw version %08x", cpp_dev->fw_version);
+ }
+
+ if ((stripe_base + num_stripes*27 + 1) != new_frame->msg_len) {
+ pr_err("Invalid frame message\n");
+ rc = -EINVAL;
+ goto ERROR3;
+ }
+
for (i = 0; i < num_stripes; i++) {
- cpp_frame_msg[(133 + fw_version_1_2_x) + i * 27] +=
+ cpp_frame_msg[stripe_base + 5 + i*27] +=
(uint32_t) in_phyaddr;
- cpp_frame_msg[(139 + fw_version_1_2_x) + i * 27] +=
+ cpp_frame_msg[stripe_base + 11 + i * 27] +=
(uint32_t) out_phyaddr0;
- cpp_frame_msg[(140 + fw_version_1_2_x) + i * 27] +=
+ cpp_frame_msg[stripe_base + 12 + i * 27] +=
(uint32_t) out_phyaddr1;
- cpp_frame_msg[(141 + fw_version_1_2_x) + i * 27] +=
+ cpp_frame_msg[stripe_base + 13 + i * 27] +=
(uint32_t) out_phyaddr0;
- cpp_frame_msg[(142 + fw_version_1_2_x) + i * 27] +=
+ cpp_frame_msg[stripe_base + 14 + i * 27] +=
(uint32_t) out_phyaddr1;
}
@@ -1441,7 +1472,7 @@
ioctl_ptr->trans_code = rc;
status = rc;
- rc = (copy_to_user((void __user *)u_frame_info->status, &status,
+ rc = (copy_to_user((void __user *)new_frame->status, &status,
sizeof(int32_t)) ? -EFAULT : 0);
if (rc) {
ERR_COPY_FROM_USER();
@@ -1457,12 +1488,12 @@
ERROR2:
kfree(cpp_frame_msg);
ERROR1:
- kfree(new_frame);
ioctl_ptr->trans_code = rc;
status = rc;
- if (copy_to_user((void __user *)u_frame_info->status, &status,
+ if (copy_to_user((void __user *)new_frame->status, &status,
sizeof(int32_t)))
pr_err("error cannot copy error\n");
+ kfree(new_frame);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index bd73ab2..af1af2d 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -189,6 +189,7 @@
char *fw_name_bin;
struct workqueue_struct *timer_wq;
struct msm_cpp_work_t *work;
+ uint32_t fw_version;
uint8_t stream_cnt;
uint8_t timeout_trial_cnt;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index cce6525..7fb312a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -135,66 +135,57 @@
{
int32_t rc = -EFAULT;
int32_t i = 0;
+ enum msm_camera_i2c_reg_addr_type save_addr_type;
CDBG("Enter\n");
+ save_addr_type = a_ctrl->i2c_client.addr_type;
for (i = 0; i < size; i++) {
+
+ switch (settings[i].addr_type) {
+ case MSM_ACTUATOR_BYTE_ADDR:
+ a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ break;
+ case MSM_ACTUATOR_WORD_ADDR:
+ a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR;
+ break;
+ default:
+ pr_err("Unsupport addr type: %d\n",
+ settings[i].addr_type);
+ break;
+ }
+
switch (settings[i].i2c_operation) {
- case MSM_ACT_WRITE: {
- switch (settings[i].data_type) {
- case MSM_ACTUATOR_BYTE_DATA:
- rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write(
- &a_ctrl->i2c_client,
- settings[i].reg_addr,
- settings[i].reg_data,
- MSM_CAMERA_I2C_BYTE_DATA);
- break;
- case MSM_ACTUATOR_WORD_DATA:
- rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write(
- &a_ctrl->i2c_client,
- settings[i].reg_addr,
- settings[i].reg_data,
- MSM_CAMERA_I2C_WORD_DATA);
- break;
- default:
- pr_err("Unsupport data type: %d\n",
- settings[i].i2c_operation);
- break;
- }
+ case MSM_ACT_WRITE:
+ rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write(
+ &a_ctrl->i2c_client,
+ settings[i].reg_addr,
+ settings[i].reg_data,
+ settings[i].data_type);
break;
- }
- case MSM_ACT_POLL: {
- switch (settings[i].data_type) {
- case MSM_ACTUATOR_BYTE_DATA:
- rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
- &a_ctrl->i2c_client,
- settings[i].reg_addr,
- settings[i].reg_data,
- MSM_CAMERA_I2C_BYTE_DATA);
- break;
- case MSM_ACTUATOR_WORD_DATA:
- rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
- &a_ctrl->i2c_client,
- settings[i].reg_addr,
- settings[i].reg_data,
- MSM_CAMERA_I2C_WORD_DATA);
- break;
- default:
- pr_err("Unsupport data type: %d\n",
- settings[i].i2c_operation);
- break;
- }
+ case MSM_ACT_POLL:
+ rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
+ &a_ctrl->i2c_client,
+ settings[i].reg_addr,
+ settings[i].reg_data,
+ settings[i].data_type);
break;
- }
- }
+ default:
+ pr_err("Unsupport i2c_operation: %d\n",
+ settings[i].i2c_operation);
+ break;
if (0 != settings[i].delay)
msleep(settings[i].delay);
if (rc < 0)
break;
+ }
}
a_ctrl->curr_step_pos = 0;
+ /* recover register addr_type after the init
+ settings are written */
+ a_ctrl->i2c_client.addr_type = save_addr_type;
CDBG("Exit\n");
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
index 6067f26..44c134e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
@@ -27,6 +27,8 @@
#define TRUE 1
#define FALSE 0
+#define CCI_NUM_CLK_MAX 16
+
enum cci_i2c_queue_t {
QUEUE_0,
QUEUE_1,
@@ -128,7 +130,7 @@
uint8_t ref_count;
enum msm_cci_state_t cci_state;
- struct clk *cci_clk[5];
+ struct clk *cci_clk[CCI_NUM_CLK_MAX];
struct msm_camera_cci_i2c_queue_info
cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES];
struct msm_camera_cci_master_info cci_master_info[NUM_MASTERS];
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
index fd4db79..0a17d93 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
@@ -20,6 +20,8 @@
#include <media/msm_cam_sensor.h>
#include "msm_sd.h"
+#define CSID_NUM_CLK_MAX 16
+
enum msm_csid_state_t {
CSID_POWER_UP,
CSID_POWER_DOWN,
@@ -38,7 +40,7 @@
uint32_t hw_version;
enum msm_csid_state_t csid_state;
- struct clk *csid_clk[11];
+ struct clk *csid_clk[CSID_NUM_CLK_MAX];
};
#define VIDIOC_MSM_CSID_RELEASE \
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
index a11b958..35b9ca1 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
@@ -21,6 +21,7 @@
#include "msm_sd.h"
#define MAX_CSIPHY 3
+#define CSIPHY_NUM_CLK_MAX 16
enum msm_csiphy_state_t {
CSIPHY_POWER_UP,
@@ -41,8 +42,7 @@
struct mutex mutex;
uint32_t hw_version;
enum msm_csiphy_state_t csiphy_state;
-
- struct clk *csiphy_clk[4];
+ struct clk *csiphy_clk[CSIPHY_NUM_CLK_MAX];
uint8_t ref_count;
uint16_t lane_mask[MAX_CSIPHY];
};
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index a563f68..0e38b18 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1447,7 +1447,6 @@
hfi->ltrcount = hal->ltrcount;
hfi->trustmode = hal->trustmode;
pkt->size += sizeof(u32) + sizeof(struct hfi_ltrmode);
- pr_err("SET LTR\n");
break;
}
case HAL_CONFIG_VENC_USELTRFRAME:
@@ -1461,7 +1460,6 @@
hfi->refltr = hal->refltr;
hfi->useconstrnt = hal->useconstrnt;
pkt->size += sizeof(u32) + sizeof(struct hfi_ltruse);
- pr_err("USE LTR\n");
break;
}
case HAL_CONFIG_VENC_MARKLTRFRAME:
@@ -1473,7 +1471,6 @@
hfi = (struct hfi_ltrmark *) &pkt->rg_property_data[1];
hfi->markframe = hal->markframe;
pkt->size += sizeof(u32) + sizeof(struct hfi_ltrmark);
- pr_err("MARK LTR\n");
break;
}
case HAL_PARAM_VENC_HIER_P_MAX_ENH_LAYERS:
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index c638415..aaed0e9 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -543,6 +543,35 @@
{}
};
+static int msm_vidc_pm_suspend(struct device *pdev)
+{
+ struct msm_vidc_core *core;
+
+ if (!pdev) {
+ dprintk(VIDC_ERR, "%s invalid device\n", __func__);
+ return -EINVAL;
+ }
+
+ core = (struct msm_vidc_core *)pdev->platform_data;
+ if (!core) {
+ dprintk(VIDC_ERR, "%s invalid core\n", __func__);
+ return -EINVAL;
+ }
+ dprintk(VIDC_INFO, "%s\n", __func__);
+
+ return msm_vidc_suspend(core->id);
+}
+
+static int msm_vidc_pm_resume(struct device *dev)
+{
+ dprintk(VIDC_INFO, "%s\n", __func__);
+ return 0;
+}
+
+static const struct dev_pm_ops msm_vidc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)
+};
+
MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
static struct platform_driver msm_vidc_driver = {
@@ -552,6 +581,7 @@
.name = "msm_vidc_v4l2",
.owner = THIS_MODULE,
.of_match_table = msm_vidc_dt_match,
+ .pm = &msm_vidc_pm_ops,
},
};
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index f84a806..bff86a6 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -22,7 +22,7 @@
#define MSM_VDEC_DVC_NAME "msm_vdec_8974"
#define MIN_NUM_OUTPUT_BUFFERS 4
#define MAX_NUM_OUTPUT_BUFFERS VIDEO_MAX_FRAME
-#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8080
+#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8010
#define TZ_DYNAMIC_BUFFER_FEATURE_ID 12
#define TZ_FEATURE_VERSION(major, minor, patch) \
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index bcd13b8..701a8cc 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -723,7 +723,7 @@
{
.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME,
.name = "H264 Use LTR",
- .type = V4L2_CTRL_TYPE_BUTTON,
+ .type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
.maximum = (MAX_LTR_FRAME_COUNT - 1),
.default_value = 0,
@@ -753,7 +753,7 @@
{
.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME,
.name = "H264 Mark LTR",
- .type = V4L2_CTRL_TYPE_BUTTON,
+ .type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
.maximum = (MAX_LTR_FRAME_COUNT - 1),
.default_value = 0,
@@ -2179,7 +2179,7 @@
}
case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
property_id = HAL_CONFIG_VENC_USELTRFRAME;
- useltr.refltr = ctrl->val;
+ useltr.refltr = (1 << ctrl->val);
useltr.useconstrnt = false;
useltr.frames = 0;
pdata = &useltr;
@@ -2302,7 +2302,6 @@
rc = call_hfi_op(hdev, session_set_property,
(void *)inst->session, property_id, pdata);
}
- pr_err("Returning from %s\n", __func__);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index cfc2eb8..c5d038f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1404,3 +1404,8 @@
return 0;
}
+
+int msm_vidc_suspend(int core_id)
+{
+ return msm_comm_suspend(core_id);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 9f0dac4..8176b06 100755
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2112,6 +2112,33 @@
return rc;
}
+int msm_comm_suspend(int core_id)
+{
+ struct hfi_device *hdev;
+ struct msm_vidc_core *core;
+ int rc = 0;
+
+ core = get_vidc_core(core_id);
+ if (!core) {
+ dprintk(VIDC_ERR,
+ "%s: Failed to find core for core_id = %d\n",
+ __func__, core_id);
+ return -EINVAL;
+ }
+
+ hdev = (struct hfi_device *)core->device;
+ if (!hdev) {
+ dprintk(VIDC_ERR, "%s Invalid device handle\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = call_hfi_op(hdev, suspend, hdev->hfi_device_data);
+ if (rc)
+ dprintk(VIDC_WARN, "Failed to suspend\n");
+
+ return rc;
+}
+
static int get_flipped_state(int present_state,
int desired_state)
{
@@ -3137,6 +3164,40 @@
mutex_unlock(&inst->lock);
}
+void msm_comm_flush_pending_dynamic_buffers(struct msm_vidc_inst *inst)
+{
+ struct buffer_info *binfo = NULL;
+ struct list_head *list = NULL;
+
+ if (!inst)
+ return;
+
+ if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
+ return;
+
+ if (list_empty(&inst->pendingq) || list_empty(&inst->registered_bufs))
+ return;
+
+ list = &inst->registered_bufs;
+
+ /*
+ * Dynamic Buffer mode - Since pendingq is not empty
+ * no output buffers have been sent to firmware yet.
+ * Hence remove reference to all pendingq o/p buffers
+ * before flushing them.
+ */
+
+ list_for_each_entry(binfo, list, list) {
+ if (binfo && binfo->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ dprintk(VIDC_DBG,
+ "%s: binfo = %p device_addr = 0x%pa\n",
+ __func__, binfo, &binfo->device_addr[0]);
+ buf_ref_put(inst, binfo);
+ }
+ }
+}
+
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
{
int rc = 0;
@@ -3202,6 +3263,8 @@
} else {
if (!list_empty(&inst->pendingq)) {
+ msm_comm_flush_pending_dynamic_buffers(inst);
+
/*If flush is called after queueing buffers but before
* streamon driver should flush the pending queue*/
list_for_each_safe(ptr, next, &inst->pendingq) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index da71424..f4e2cd5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -40,6 +40,7 @@
int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst);
int msm_comm_release_output_buffers(struct msm_vidc_inst *inst);
int msm_comm_force_cleanup(struct msm_vidc_inst *inst);
+int msm_comm_suspend(int core_id);
enum hal_extradata_id msm_comm_get_hal_extradata_index(
enum v4l2_mpeg_vidc_extradata index);
int msm_comm_get_domain_partition(struct msm_vidc_inst *inst, u32 flags,
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 448fe3b..a46dc95 100755
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -3518,6 +3518,25 @@
return rc;
}
+static int venus_hfi_suspend(void *dev)
+{
+ int rc = 0;
+ struct venus_hfi_device *device = (struct venus_hfi_device *) dev;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s invalid device\n", __func__);
+ return -EINVAL;
+ }
+ dprintk(VIDC_INFO, "%s\n", __func__);
+
+ if (device->power_enabled) {
+ venus_hfi_try_clk_gating(device);
+ rc = flush_delayed_work(&venus_hfi_pm_work);
+ dprintk(VIDC_INFO, "%s flush delayed work %d\n", __func__, rc);
+ }
+ return 0;
+}
+
static int venus_hfi_load_fw(void *dev)
{
int rc = 0;
@@ -3910,6 +3929,7 @@
hdev->get_stride_scanline = venus_hfi_get_stride_scanline;
hdev->get_core_capabilities = venus_hfi_get_core_capabilities;
hdev->power_enable = venus_hfi_power_enable;
+ hdev->suspend = venus_hfi_suspend;
}
int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 38c5bdb..8484bb2 100755
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1171,6 +1171,7 @@
int (*session_clean)(void *sess);
int (*get_core_capabilities)(void);
int (*power_enable)(void *dev);
+ int (*suspend)(void *dev);
};
typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7c20d1e..9d294f0 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -116,6 +116,7 @@
struct list_head list;
u32 app_id;
u32 ref_cnt;
+ char app_name[MAX_APP_NAME_SIZE];
};
struct qseecom_registered_kclient_list {
@@ -185,6 +186,7 @@
uint32_t user_virt_sb_base;
size_t sb_length;
struct ion_handle *ihandle; /* Retrieve phy addr */
+ char app_name[MAX_APP_NAME_SIZE];
};
struct qseecom_listener_handle {
@@ -999,7 +1001,9 @@
}
entry->app_id = app_id;
entry->ref_cnt = 1;
-
+ memset((void *)entry->app_name, 0, MAX_APP_NAME_SIZE);
+ memcpy((void *)entry->app_name,
+ (void *)load_img_req.img_name, MAX_APP_NAME_SIZE);
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
@@ -1013,6 +1017,9 @@
(char *)(load_img_req.img_name));
}
data->client.app_id = app_id;
+ memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
+ memcpy((void *)data->client.app_name,
+ (void *)load_img_req.img_name, MAX_APP_NAME_SIZE);
load_img_req.app_id = app_id;
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
pr_err("copy_to_user failed\n");
@@ -1061,53 +1068,55 @@
bool app_crash)
{
unsigned long flags;
+ unsigned long flags1;
int ret = 0;
struct qseecom_command_scm_resp resp;
- struct qseecom_registered_app_list *ptr_app;
+ struct qseecom_registered_app_list *ptr_app = NULL;
bool unload = false;
bool found_app = false;
+ bool found_dead_app = false;
+
+ if (!memcmp(data->client.app_name, "keymaste", strlen("keymaste"))) {
+ pr_warn("Do not unload keymaster app from tz\n");
+ return 0;
+ }
if (data->client.app_id > 0) {
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
list) {
if (ptr_app->app_id == data->client.app_id) {
- found_app = true;
- if (app_crash) {
- ptr_app->ref_cnt = 0;
- unload = true;
+ if (!memcmp((void *)ptr_app->app_name,
+ (void *)data->client.app_name,
+ strlen(data->client.app_name))) {
+ found_app = true;
+ if (app_crash || ptr_app->ref_cnt == 1)
+ unload = true;
break;
} else {
- if (ptr_app->ref_cnt == 1) {
- unload = true;
- break;
- } else {
- ptr_app->ref_cnt--;
- pr_debug("Can't unload app(%d) inuse\n",
- ptr_app->app_id);
- break;
- }
+ found_dead_app = true;
+ break;
}
}
}
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
flags);
- if (found_app == false) {
- pr_err("Cannot find app with id = %d\n",
- data->client.app_id);
+ if (found_app == false && found_dead_app == false) {
+ pr_err("Cannot find app with id = %d (%s)\n",
+ data->client.app_id,
+ (char *)data->client.app_name);
return -EINVAL;
}
}
+ if (found_dead_app) {
+ pr_warn("cleanup app_id %d(%s)\n", data->client.app_id,
+ (char *)data->client.app_name);
+ __qseecom_cleanup_app(data);
+ }
+
if (unload) {
struct qseecom_unload_app_ireq req;
-
- __qseecom_cleanup_app(data);
- spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
- list_del(&ptr_app->list);
- kzfree(ptr_app);
- spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
- flags);
/* Populate the structure for sending scm call to load image */
req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND;
req.app_id = data->client.app_id;
@@ -1123,6 +1132,15 @@
} else {
pr_warn("App id %d now unloaded\n", req.app_id);
}
+ if (resp.result == QSEOS_RESULT_FAILURE) {
+ pr_err("app (%d) unload_failed!!\n",
+ data->client.app_id);
+ return -EFAULT;
+ }
+ if (resp.result == QSEOS_RESULT_SUCCESS)
+ pr_info("App (%d) is unloaded!!\n",
+ data->client.app_id);
+ __qseecom_cleanup_app(data);
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
ret = __qseecom_process_incomplete_cmd(data, &resp);
if (ret) {
@@ -1132,6 +1150,29 @@
}
}
}
+
+ if (found_app) {
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
+ if (app_crash) {
+ ptr_app->ref_cnt = 0;
+ pr_debug("app_crash: ref_count = 0\n");
+ } else {
+ if (ptr_app->ref_cnt == 1) {
+ ptr_app->ref_cnt = 0;
+ pr_info("ref_count set to 0\n");
+ } else {
+ ptr_app->ref_cnt--;
+ pr_info("Can't unload app(%d) inuse\n",
+ ptr_app->app_id);
+ }
+ }
+ if (unload) {
+ list_del(&ptr_app->list);
+ kzfree(ptr_app);
+ }
+ spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+ flags1);
+ }
qseecom_unmap_ion_allocated_memory(data);
data->released = true;
return ret;
@@ -1326,6 +1367,9 @@
u32 reqd_len_sb_in = 0;
struct qseecom_client_send_data_ireq send_data_req;
struct qseecom_command_scm_resp resp;
+ unsigned long flags;
+ struct qseecom_registered_app_list *ptr_app;
+ bool found_app = false;
if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
pr_err("cmd buffer or response buffer is null\n");
@@ -1367,6 +1411,26 @@
return -ENOMEM;
}
+ /* find app_id & img_name from list */
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+ list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
+ list) {
+ if ((ptr_app->app_id == data->client.app_id) &&
+ (!memcmp((void *)ptr_app->app_name,
+ (void *)data->client.app_name,
+ strlen(data->client.app_name)))) {
+ found_app = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
+
+ if (!found_app) {
+ pr_err("app_id %d (%s) is not found\n", data->client.app_id,
+ (char *)data->client.app_name);
+ return -EINVAL;
+ }
+
send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
send_data_req.app_id = data->client.app_id;
send_data_req.req_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
@@ -2841,7 +2905,9 @@
&qseecom.registered_app_list_lock, flags);
data->client.app_id = ret;
query_req.app_id = ret;
-
+ memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
+ memcpy((void *)data->client.app_name,
+ (void *)query_req.app_name, MAX_APP_NAME_SIZE);
if (copy_to_user(argp, &query_req, sizeof(query_req))) {
pr_err("copy_to_user failed\n");
return -EFAULT;
@@ -3516,7 +3582,6 @@
ret = -EINVAL;
break;
}
- data->type = QSEECOM_CLIENT_APP;
pr_debug("SET_MEM_PARAM: qseecom addr = 0x%x\n", (u32)data);
ret = qseecom_set_client_mem_param(data, argp);
if (ret)
@@ -3850,6 +3915,7 @@
data->abort = 0;
data->type = QSEECOM_GENERIC;
data->released = false;
+ memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
data->mode = INACTIVE;
init_waitqueue_head(&data->abort_wq);
atomic_set(&data->ioctl_count, 0);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index d06ec85..2d260be 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -207,7 +207,7 @@
/* max 20mhz channel count */
#define WCNSS_MAX_CH_NUM 45
-#define WCNSS_MAX_PIL_RETRY 3
+#define WCNSS_MAX_PIL_RETRY 2
#define VALID_VERSION(version) \
((strncmp(version, "INVALID", WCNSS_VERSION_LEN)) ? 1 : 0)
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 588afc6..80b0892 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -136,12 +136,6 @@
(value |= (BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
} while (0)
-#define QPNP_DISABLE_LUT_V1(value, id) \
-do { \
- (id < 8) ? (value &= ~BIT(id)) : \
- (value &= (~BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
-} while (0)
-
/* LPG Control for RAMP_STEP_DURATION_LSB */
#define QPNP_RAMP_STEP_DURATION_LSB_MASK 0xFF
@@ -1018,7 +1012,6 @@
QPNP_ENABLE_LUT_V1(value1, pwm->pwm_config.channel_id);
value2 = QPNP_ENABLE_LPG_MODE;
} else {
- QPNP_DISABLE_LUT_V1(value1, pwm->pwm_config.channel_id);
value2 = QPNP_DISABLE_LPG_MODE;
}
mask1 = value1;
@@ -1038,8 +1031,10 @@
if (rc)
return rc;
- return qpnp_lpg_save_and_write(value1, mask1, reg1,
+ if (state == QPNP_LUT_ENABLE || chip->revision == QPNP_LPG_REVISION_0)
+ rc = qpnp_lpg_save_and_write(value1, mask1, reg1,
addr1, 1, chip);
+ return rc;
}
static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_config *pwm_conf)
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 94d48e6..7963ed4 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -2465,11 +2465,6 @@
int rc;
u8 chgr_sts, bat_if_sts;
- if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
- qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
- return POWER_SUPPLY_STATUS_FULL;
- }
-
rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
if (rc) {
pr_err("failed to read interrupt sts %d\n", rc);
@@ -2487,10 +2482,14 @@
if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
return POWER_SUPPLY_STATUS_CHARGING;
- /* report full if state of charge is 100 and a charger is connected */
+ /*
+ * Report full if state of charge is 100 or chg_done is true
+ * when a charger is connected and boost is disabled
+ */
if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
- qpnp_chg_is_dc_chg_plugged_in(chip))
- && get_batt_capacity(chip) == 100) {
+ qpnp_chg_is_dc_chg_plugged_in(chip)) &&
+ (chip->chg_done || get_batt_capacity(chip) == 100)
+ && qpnp_chg_is_boost_en_set(chip) == 0) {
return POWER_SUPPLY_STATUS_FULL;
}
@@ -3242,10 +3241,10 @@
qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
{
struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+ int usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
int rc;
- if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
- (chip->flags & BOOST_FLASH_WA)) {
+ if (usb_present && (chip->flags & BOOST_FLASH_WA)) {
if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
pr_debug("EXT OVP IC ISNS disabled\n");
@@ -3273,10 +3272,24 @@
}
}
- return qpnp_chg_masked_write(chip,
+ rc = qpnp_chg_masked_write(chip,
chip->boost_base + BOOST_ENABLE_CONTROL,
BOOST_PWR_EN,
BOOST_PWR_EN, 1);
+ if (rc) {
+ pr_err("failed to enable boost rc = %d\n", rc);
+ return rc;
+ }
+ /*
+ * update battery status when charger is connected and state is full
+ */
+ if (usb_present && (chip->chg_done
+ || (get_batt_capacity(chip) == 100)
+ || (get_prop_batt_status(chip) ==
+ POWER_SUPPLY_STATUS_FULL)))
+ power_supply_changed(&chip->batt_psy);
+
+ return rc;
}
/* Boost regulator operations */
@@ -3369,6 +3382,20 @@
qpnp_chg_usb_suspend_enable(chip, 0);
}
+ /*
+ * When a charger is connected,if state of charge is not full
+ * resumeing charging else update battery status
+ */
+ if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
+ if (get_batt_capacity(chip) < 100 || !chip->chg_done) {
+ chip->chg_done = false;
+ chip->resuming_charging = true;
+ qpnp_chg_set_appropriate_vbatdet(chip);
+ } else if (chip->chg_done) {
+ power_supply_changed(&chip->batt_psy);
+ }
+ }
+
if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
pr_debug("EXT OVP IC ISNS enable\n");
gpio_direction_output(chip->ext_ovp_isns_gpio, 1);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 5686107..b570937 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -3102,6 +3102,7 @@
spin_lock_init(&dd->queue_lock);
mutex_init(&dd->core_lock);
+ init_waitqueue_head(&dd->continue_suspend);
if (!devm_request_mem_region(&pdev->dev, dd->mem_phys_addr,
dd->mem_size, SPI_DRV_NAME)) {
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 6be6599..84288a7 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1539,6 +1539,7 @@
if (msm_uport->clk_state != MSM_HS_CLK_ON) {
MSM_HS_WARN("%s: Failed.Clocks are OFF\n", __func__);
+ return;
}
if ((msm_uport->tx.tx_ready_int_en == 0) &&
(msm_uport->tx.dma_in_flight == 0))
@@ -2132,6 +2133,8 @@
case MSM_HS_CLK_ON:
break;
case MSM_HS_CLK_PORT_OFF:
+ MSM_HS_ERR("%s:Clock ON failed;UART Port is Closed\n",
+ __func__);
break;
}
@@ -2852,6 +2855,11 @@
msm_uport = devm_kzalloc(&pdev->dev, sizeof(struct msm_hs_port),
GFP_KERNEL);
+ if (!msm_uport) {
+ MSM_HS_ERR("Memory allocation failed\n");
+ return -ENOMEM;
+ }
+
msm_uport->uport.type = PORT_UNKNOWN;
uport = &msm_uport->uport;
uport->dev = &pdev->dev;
@@ -3018,15 +3026,16 @@
msm_hs_write(uport, UART_DM_MR2, data);
mb();
- msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
hrtimer_init(&msm_uport->clk_off_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
msm_uport->clk_off_timer.function = msm_hs_clk_off_retry;
msm_uport->clk_off_delay = ktime_set(0, 1000000); /* 1ms */
ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_clock.attr);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ MSM_HS_ERR("Probe Failed as sysfs failed\n");
goto err_clock;
+ }
msm_serial_debugfs_init(msm_uport, pdev->id);
@@ -3036,6 +3045,7 @@
ret = uart_add_one_port(&msm_hs_driver, uport);
if (!ret) {
msm_hs_clock_unvote(msm_uport);
+ msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
return ret;
}
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 05292f9..669fca9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -235,15 +235,6 @@
sdev->use_rpm_auto = 1;
sdev->autosuspend_delay = us->sdev_autosuspend_delay;
}
-
- /*
- * This quirk enables sending consecutive TEST_UNIT_READY
- * commands in WRITE(10) command processing context. Increase
- * the timeout to 60 seconds.
- */
- if (us->fflags & US_FL_TUR_AFTER_WRITE)
- blk_queue_rq_timeout(sdev->request_queue, (60 * HZ));
-
} else {
/* Non-disk-type devices don't need to blacklist any pages
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index a710d9f..c70109e 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -859,42 +859,6 @@
srb->result = DID_ERROR << 16;
last_sector_hacks(us, srb);
-
- /*
- * TMC UICC cards expect 5 TEST_UNIT_READY commands after
- * writing some data. The card performs the flash related
- * house keeping operations after receiving these commands.
- * Send 5 TEST_UNIT_READY commands for every 8 WRITE_10
- * commands.
- */
- if (unlikely((us->fflags & US_FL_TUR_AFTER_WRITE) &&
- srb->cmnd[0] == WRITE_10)) {
- int i;
- int temp_result;
- struct scsi_eh_save ses;
- unsigned char cmd[] = {
- TEST_UNIT_READY, 0, 0, 0, 0, 0,
- };
-
- us->tur_count[srb->device->lun]++;
-
- if (++us->tur_count[srb->device->lun] == 8) {
-
- us->tur_count[srb->device->lun] = 0;
-
- scsi_eh_prep_cmnd(srb, &ses, cmd, 6, 0);
- for (i = 0; i < 5; i++) {
- temp_result = us->transport(us->srb, us);
- if (temp_result != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("TUR failed %d %d\n",
- i, temp_result);
- break;
- }
- }
- scsi_eh_restore_cmnd(srb, &ses);
- }
- }
-
return;
/* Error and abort processing: try to resynchronize with the device
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 901f6fb..856ad92 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2018,12 +2018,6 @@
"Digital MP3 Audio Player",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
-/* Reported by Pavankumar Kondeti <pkondeti@codeaurora.org> */
-UNUSUAL_DEV(0x0925, 0x9011, 0x0100, 0x0100,
- "TMC",
- "USB DISK",
- USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_TUR_AFTER_WRITE),
-
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index b079984..db75080 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -162,8 +162,6 @@
int use_last_sector_hacks;
int last_sector_retries;
int sdev_autosuspend_delay;
- /* consecutive TEST_UNIT_READY commands during write */
- int tur_count[16];
};
/* Convert between us_data and the corresponding Scsi_Host */
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index f12d03a..4fc3909 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -133,8 +133,8 @@
pdata->panel_info.panel_power_on = 0;
if (!pdata->panel_info.dynamic_switch_pending) {
if (pdata->panel_info.type == MIPI_CMD_PANEL)
- mdss_dsi_panel_reset(pdata, 0);
- dsi_ctrl_gpio_free(ctrl_pdata);
+ dsi_ctrl_gpio_free(ctrl_pdata);
+ mdss_dsi_panel_reset(pdata, 0);
}
}
return rc;
@@ -296,7 +296,7 @@
if (!dev || !mp) {
pr_err("%s: invalid input\n", __func__);
rc = -EINVAL;
- goto error;
+ return rc;
}
np = dev->of_node;
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 37134b4..d4d913f 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -2373,7 +2373,7 @@
if (!mdp3_res || !mdp3_res->pan_cfg.init_done)
rc = -EPROBE_DEFER;
- if (mdp3_res->pan_cfg.lk_cfg)
+ else if (mdp3_res->pan_cfg.lk_cfg)
rc = 1;
else
rc = 0;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index f448c46..cd0af6d 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -49,7 +49,7 @@
if (!count)
return;
- while (count--) {
+ while (count-- && (bufq->pop_idx >= 0)) {
struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
mdp3_put_img(data, MDP3_CLIENT_DMA_P);
@@ -986,7 +986,7 @@
{
struct mdp3_session_data *mdp3_session;
struct mdp3_img_data *data;
- struct mdss_panel_info *panel_info = mfd->panel_info;
+ struct mdss_panel_info *panel_info;
int rc = 0;
bool reset_done = false;
struct mdss_panel_data *panel;
@@ -994,6 +994,7 @@
if (!mfd || !mfd->mdp.private1)
return -EINVAL;
+ panel_info = mfd->panel_info;
mdp3_session = mfd->mdp.private1;
if (!mdp3_session || !mdp3_session->dma)
return -EINVAL;
@@ -1050,7 +1051,8 @@
if (mdp3_bufq_count(&mdp3_session->bufq_out) > 1) {
mdp3_release_splash_memory(mfd);
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
- mdp3_put_img(data, MDP3_CLIENT_DMA_P);
+ if (data)
+ mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
if (mdp3_session->first_commit) {
@@ -1076,13 +1078,14 @@
struct mdp3_session_data *mdp3_session;
u32 offset;
int bpp;
- struct mdss_panel_info *panel_info = mfd->panel_info;
+ struct mdss_panel_info *panel_info;
int rc;
pr_debug("mdp3_ctrl_pan_display\n");
if (!mfd || !mfd->mdp.private1)
return;
+ panel_info = mfd->panel_info;
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
if (!mdp3_session || !mdp3_session->dma)
return;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 993645a..50e4a01 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -131,7 +131,7 @@
if (!dev || !mp) {
pr_err("%s: invalid input\n", __func__);
rc = -EINVAL;
- goto error;
+ return rc;
}
of_node = dev->of_node;
@@ -1080,6 +1080,7 @@
case MDSS_EVENT_REGISTER_RECOVERY_HANDLER:
rc = mdss_dsi_register_recovery_handler(ctrl_pdata,
(struct mdss_panel_recovery *)arg);
+ break;
case MDSS_EVENT_DSI_DYNAMIC_SWITCH:
rc = mdss_dsi_update_panel_config(ctrl_pdata,
(int)(unsigned long) arg);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index d8cd22e..d8a713e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1534,9 +1534,11 @@
(struct mdss_dsi_ctrl_pdata *)ptr;
struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- if (!ctrl->ctrl_base)
+ if (!ctrl->ctrl_base) {
pr_err("%s:%d DSI base adr no Initialized",
- __func__, __LINE__);
+ __func__, __LINE__);
+ return IRQ_HANDLED;
+ }
isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 1ac37dc..4fa995f 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -924,13 +924,14 @@
else if (!strcmp(pdest, "display_2"))
pinfo->pdest = DISPLAY_2;
else {
- pr_debug("%s: pdest not specified. Set Default\n",
- __func__);
+ pr_debug("%s: incorrect pdest. Set Default\n",
+ __func__);
pinfo->pdest = DISPLAY_1;
}
} else {
- pr_err("%s: pdest not specified\n", __func__);
- return -EINVAL;
+ pr_debug("%s: pdest not specified. Set Default\n",
+ __func__);
+ pinfo->pdest = DISPLAY_1;
}
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
pinfo->lcdc.h_front_porch = (!rc ? tmp : 6);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 511fa00..84ee426 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -661,13 +661,13 @@
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+
mdss_fb_remove_sysfs(mfd);
pm_runtime_disable(mfd->fbi->dev);
- if (!mfd)
- return -ENODEV;
-
if (mfd->key != MFD_KEY)
return -EINVAL;
@@ -2653,7 +2653,8 @@
pr_info("adding framebuffer device %s\n", dev_name(&pdev->dev));
fb_pdev = of_platform_device_create(node, NULL,
&mdss_pdev->dev);
- fb_pdev->dev.platform_data = pdata;
+ if (fb_pdev)
+ fb_pdev->dev.platform_data = pdata;
}
if (master_panel && mdp_instance->panel_register_done)
@@ -2682,7 +2683,7 @@
struct fb_info *info;
struct msm_fb_data_type *mfd;
- if (fb_num > MAX_FBI_LIST)
+ if (fb_num >= MAX_FBI_LIST)
return -EINVAL;
info = fbi_list[fb_num];
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 2b409f5..1bf389a 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -3340,7 +3340,7 @@
switch (module_type) {
case HDMI_TX_HPD_PM:
- mp->num_clk = 3;
+ mp->num_clk = 4;
mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
mp->num_clk, GFP_KERNEL);
if (!mp->clk_config) {
@@ -3366,10 +3366,14 @@
snprintf(mp->clk_config[2].clk_name, 32, "%s", "mdp_core_clk");
mp->clk_config[2].type = DSS_CLK_AHB;
mp->clk_config[2].rate = 0;
+
+ snprintf(mp->clk_config[3].clk_name, 32, "%s", "alt_iface_clk");
+ mp->clk_config[3].type = DSS_CLK_AHB;
+ mp->clk_config[3].rate = 0;
break;
case HDMI_TX_CORE_PM:
- mp->num_clk = 2;
+ mp->num_clk = 1;
mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
mp->num_clk, GFP_KERNEL);
if (!mp->clk_config) {
@@ -3382,10 +3386,6 @@
mp->clk_config[0].type = DSS_CLK_PCLK;
/* This rate will be overwritten when core is powered on */
mp->clk_config[0].rate = 148500000;
-
- snprintf(mp->clk_config[1].clk_name, 32, "%s", "alt_iface_clk");
- mp->clk_config[1].type = DSS_CLK_AHB;
- mp->clk_config[1].rate = 0;
break;
case HDMI_TX_DDC_PM:
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index e619e6b..6808313 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -405,14 +405,6 @@
return;
}
- mutex_lock(&ctx->clk_mtx);
- if (ctx->clk_enabled) {
- mutex_unlock(&ctx->clk_mtx);
- pr_warn("Cannot enter ulps mode if DSI clocks are on\n");
- return;
- }
- mutex_unlock(&ctx->clk_mtx);
-
if (!ctx->panel_on) {
pr_err("Panel is off. skipping ULPS configuration\n");
return;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index f371f9c..41a7d9d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -56,6 +56,7 @@
static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd);
static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd);
+static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val);
static int mdss_mdp_overlay_sd_ctrl(struct msm_fb_data_type *mfd,
unsigned int enable)
@@ -1995,6 +1996,8 @@
mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+ if (!mixer)
+ return -ENODEV;
if ((img->width > MDSS_MDP_CURSOR_WIDTH) ||
(img->height > MDSS_MDP_CURSOR_HEIGHT) ||
@@ -2788,6 +2791,20 @@
mdss_mdp_overlay_kickoff(mfd, NULL);
}
+ /*
+ * If retire fences are still active wait for a vsync time
+ * for retire fence to be updated.
+ * As a last resort signal the timeline if vsync doesn't arrive.
+ */
+ if (mdp5_data->retire_cnt) {
+ u32 fps = mdss_panel_get_framerate(mfd->panel_info);
+ u32 vsync_time = 1000 / (fps ? : DEFAULT_FRAME_RATE);
+
+ msleep(vsync_time);
+
+ __vsync_retire_signal(mfd, mdp5_data->retire_cnt);
+ }
+
rc = mdss_mdp_ctl_stop(mdp5_data->ctl);
if (rc == 0) {
__mdss_mdp_overlay_free_list_purge(mfd);
@@ -2966,7 +2983,6 @@
{
struct mdss_overlay_private *mdp5_data =
container_of(work, typeof(*mdp5_data), retire_work);
- struct msm_sync_pt_data *sync_pt_data;
if (!mdp5_data->ctl || !mdp5_data->ctl->mfd)
return;
@@ -2974,12 +2990,18 @@
if (!mdp5_data->ctl->remove_vsync_handler)
return;
- sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data;
- mutex_lock(&sync_pt_data->sync_mutex);
- if (mdp5_data->retire_cnt > 0) {
- sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1);
+ __vsync_retire_signal(mdp5_data->ctl->mfd, 1);
+}
- mdp5_data->retire_cnt--;
+static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+
+ mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
+ if (mdp5_data->retire_cnt > 0) {
+ sw_sync_timeline_inc(mdp5_data->vsync_timeline, val);
+
+ mdp5_data->retire_cnt -= min(val, mdp5_data->retire_cnt);
if (mdp5_data->retire_cnt == 0) {
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl,
@@ -2987,7 +3009,7 @@
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
}
}
- mutex_unlock(&sync_pt_data->sync_mutex);
+ mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
}
static struct sync_fence *
@@ -3013,7 +3035,7 @@
return ERR_PTR(-EPERM);
}
- if (mdp5_data->retire_cnt == 0) {
+ if (!mdp5_data->vsync_retire_handler.enabled) {
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
rc = ctl->add_vsync_handler(ctl,
&mdp5_data->vsync_retire_handler);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 70544c0..ccd60a6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -276,7 +276,7 @@
if (pipe->mixer && pipe->mixer->rotator_mode) {
rot_mode = 1;
- } else if (ps.num_planes == 1) {
+ } else if (pipe->mixer && (ps.num_planes == 1)) {
ps.ystride[0] = MAX_BPP *
max(pipe->mixer->width, width);
} else if (mdata->has_decimation) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 7159a0a..ebda2ee 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1174,15 +1174,17 @@
struct pp_hist_col_info *hist_info;
char __iomem *ctl_base;
- if (!pipe && pipe->pp_res.hist.col_en) {
- done_bit = 3 << (pipe->num * 4);
- hist_info = &pipe->pp_res.hist;
- ctl_base = pipe->base +
- MDSS_MDP_REG_VIG_HIST_CTL_BASE;
- pp_histogram_disable(hist_info, done_bit, ctl_base);
+ if (pipe) {
+ if (pipe->pp_res.hist.col_en) {
+ done_bit = 3 << (pipe->num * 4);
+ hist_info = &pipe->pp_res.hist;
+ ctl_base = pipe->base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ pp_histogram_disable(hist_info, done_bit, ctl_base);
+ }
+ memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params));
+ memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res));
}
- memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params));
- memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res));
}
int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op)
@@ -1251,10 +1253,10 @@
struct pp_sts_type *pp_sts;
struct mdss_mdp_ctl *ctl;
char __iomem *addr;
- dspp_num = mixer->num;
if (!mixer || !mixer->ctl)
return -EINVAL;
+ dspp_num = mixer->num;
ctl = mixer->ctl;
/* no corresponding dspp */
@@ -1815,7 +1817,7 @@
}
}
}
- if (mdata) {
+ if (mdata && mdata->vig_pipes) {
vig = mdata->vig_pipes;
for (i = 0; i < mdata->nvig_pipes; i++) {
mutex_init(&vig[i].pp_res.hist.hist_mutex);
@@ -1844,6 +1846,7 @@
mutex_unlock(&mdss_pp_mutex);
return ret;
}
+
void mdss_mdp_pp_term(struct device *dev)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -3763,8 +3766,7 @@
hist_info = &pipe->pp_res.hist;
}
/* Histogram Done Interrupt */
- if (hist_info && (isr_blk & 0x1) &&
- (hist_info->col_en)) {
+ if (hist_info && (isr_blk & 0x1) && (hist_info->col_en)) {
spin_lock(&hist_info->hist_lock);
hist_info->col_state = HIST_READY;
spin_unlock(&hist_info->hist_lock);
@@ -3774,8 +3776,7 @@
}
}
/* Histogram Reset Done Interrupt */
- if ((isr_blk & 0x2) &&
- (hist_info->col_en)) {
+ if (hist_info && (isr_blk & 0x2) && (hist_info->col_en)) {
spin_lock(&hist_info->hist_lock);
hist_info->col_state = HIST_IDLE;
spin_unlock(&hist_info->hist_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 9336582..01745fd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -498,24 +498,28 @@
data->srcp_file = NULL;
} else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
pr_debug("ion hdl=%p buf=0x%x\n", data->srcp_ihdl, data->addr);
-
- if (is_mdss_iommu_attached()) {
- int domain;
- if (data->flags & MDP_SECURE_OVERLAY_SESSION)
- domain = MDSS_IOMMU_DOMAIN_SECURE;
- else
- domain = MDSS_IOMMU_DOMAIN_UNSECURE;
- ion_unmap_iommu(iclient, data->srcp_ihdl,
+ if (!iclient) {
+ pr_err("invalid ion client\n");
+ return -ENOMEM;
+ } else {
+ if (is_mdss_iommu_attached()) {
+ int domain;
+ if (data->flags & MDP_SECURE_OVERLAY_SESSION)
+ domain = MDSS_IOMMU_DOMAIN_SECURE;
+ else
+ domain = MDSS_IOMMU_DOMAIN_UNSECURE;
+ ion_unmap_iommu(iclient, data->srcp_ihdl,
mdss_get_iommu_domain(domain), 0);
- if (domain == MDSS_IOMMU_DOMAIN_SECURE) {
- msm_ion_unsecure_buffer(iclient,
- data->srcp_ihdl);
+ if (domain == MDSS_IOMMU_DOMAIN_SECURE) {
+ msm_ion_unsecure_buffer(iclient,
+ data->srcp_ihdl);
+ }
}
+ ion_free(iclient, data->srcp_ihdl);
+ data->srcp_ihdl = NULL;
}
- ion_free(iclient, data->srcp_ihdl);
- data->srcp_ihdl = NULL;
} else {
return -ENOMEM;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 6086e28..3b30b2b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -343,12 +343,12 @@
static int mdss_mdp_wb_register_node(struct mdss_mdp_wb *wb,
struct mdss_mdp_wb_data *node)
{
- node->state = REGISTERED;
- list_add_tail(&node->registered_entry, &wb->register_queue);
if (!node) {
pr_err("Invalid wb node\n");
return -EINVAL;
}
+ node->state = REGISTERED;
+ list_add_tail(&node->registered_entry, &wb->register_queue);
return 0;
}
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 584ffe7..671fb50 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -217,7 +217,7 @@
}
/* find the mnd settings from mnd_table entry */
- for (; mnd_entry != mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
+ for (; mnd_entry < mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
if (((mnd_entry->lanes) == lanes) &&
((mnd_entry->bpp) == bpp))
break;
diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c
index b701eaa..51942d5 100644
--- a/fs/proc/consoles.c
+++ b/fs/proc/consoles.c
@@ -29,7 +29,6 @@
char flags[ARRAY_SIZE(con_flags) + 1];
struct console *con = v;
unsigned int a;
- int len;
dev_t dev = 0;
if (con->device) {
@@ -47,11 +46,10 @@
con_flags[a].name : ' ';
flags[a] = 0;
- seq_printf(m, "%s%d%n", con->name, con->index, &len);
- len = 21 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c%c%c%c (%s)", len, ' ', con->read ? 'R' : '-',
+ seq_setwidth(m, 21 - 1);
+ seq_printf(m, "%s%d", con->name, con->index);
+ seq_pad(m, ' ');
+ seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-',
con->write ? 'W' : '-', con->unblank ? 'U' : '-',
flags);
if (dev)
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index b1822dd..501ae3a 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -39,7 +39,7 @@
unsigned long ino = 0;
struct file *file;
dev_t dev = 0;
- int flags, len;
+ int flags;
flags = region->vm_flags;
file = region->vm_file;
@@ -50,8 +50,9 @@
ino = inode->i_ino;
}
+ seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
seq_printf(m,
- "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
+ "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
region->vm_start,
region->vm_end,
flags & VM_READ ? 'r' : '-',
@@ -59,13 +60,10 @@
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
((loff_t)region->vm_pgoff) << PAGE_SHIFT,
- MAJOR(dev), MINOR(dev), ino, &len);
+ MAJOR(dev), MINOR(dev), ino);
if (file) {
- len = 25 + sizeof(void *) * 6 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c", len, ' ');
+ seq_pad(m, ' ');
seq_path(m, &file->f_path, "");
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 1030a71..2fb663a 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -82,14 +82,6 @@
return mm->total_vm;
}
-static void pad_len_spaces(struct seq_file *m, int len)
-{
- len = 25 + sizeof(void*) * 6 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c", len, ' ');
-}
-
static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
{
if (vma && vma != priv->tail_vma) {
@@ -221,7 +213,6 @@
unsigned long long pgoff = 0;
unsigned long start, end;
dev_t dev = 0;
- int len;
const char *name = NULL;
if (file) {
@@ -239,7 +230,8 @@
if (stack_guard_page_end(vma, end))
end -= PAGE_SIZE;
- seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
+ seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
+ seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
start,
end,
flags & VM_READ ? 'r' : '-',
@@ -247,14 +239,14 @@
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? 's' : 'p',
pgoff,
- MAJOR(dev), MINOR(dev), ino, &len);
+ MAJOR(dev), MINOR(dev), ino);
/*
* Print the dentry name for named mappings, and a
* special [heap] marker for the heap:
*/
if (file) {
- pad_len_spaces(m, len);
+ seq_pad(m, ' ');
seq_path(m, &file->f_path, "\n");
goto done;
}
@@ -286,7 +278,7 @@
name = "[stack]";
} else {
/* Thread stack in /proc/PID/maps */
- pad_len_spaces(m, len);
+ seq_pad(m, ' ');
seq_printf(m, "[stack:%d]", tid);
}
}
@@ -294,7 +286,7 @@
done:
if (name) {
- pad_len_spaces(m, len);
+ seq_pad(m, ' ');
seq_puts(m, name);
}
seq_putc(m, '\n');
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 74fe164..1d2b545 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -123,14 +123,6 @@
return size;
}
-static void pad_len_spaces(struct seq_file *m, int len)
-{
- len = 25 + sizeof(void*) * 6 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c", len, ' ');
-}
-
/*
* display a single VMA to a sequenced file
*/
@@ -142,7 +134,7 @@
unsigned long ino = 0;
struct file *file;
dev_t dev = 0;
- int flags, len;
+ int flags;
unsigned long long pgoff = 0;
flags = vma->vm_flags;
@@ -155,8 +147,9 @@
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
}
+ seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
seq_printf(m,
- "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
+ "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
vma->vm_start,
vma->vm_end,
flags & VM_READ ? 'r' : '-',
@@ -164,16 +157,16 @@
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
pgoff,
- MAJOR(dev), MINOR(dev), ino, &len);
+ MAJOR(dev), MINOR(dev), ino);
if (file) {
- pad_len_spaces(m, len);
+ seq_pad(m, ' ');
seq_path(m, &file->f_path, "");
} else if (mm) {
pid_t tid = vm_is_stack(priv->task, vma, is_pid);
if (tid != 0) {
- pad_len_spaces(m, len);
+ seq_pad(m, ' ');
/*
* Thread stack in /proc/PID/task/TID/maps or
* the main process stack.
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 0cbd049..74717b4 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -732,6 +732,21 @@
}
EXPORT_SYMBOL(seq_write);
+/**
+ * seq_pad - write padding spaces to buffer
+ * @m: seq_file identifying the buffer to which data should be written
+ * @c: the byte to append after padding if non-zero
+ */
+void seq_pad(struct seq_file *m, char c)
+{
+ int size = m->pad_until - m->count;
+ if (size > 0)
+ seq_printf(m, "%*s", size, "");
+ if (c)
+ seq_putc(m, c);
+}
+EXPORT_SYMBOL(seq_pad);
+
struct list_head *seq_list_start(struct list_head *head, loff_t pos)
{
struct list_head *lh;
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 1e15415..c1c440f 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -124,11 +124,11 @@
/* This needs to be modified manually now, when we add
a new RANGE of SSIDs to the msg_mask_tbl */
-#define MSG_MASK_TBL_CNT 24
-#define EVENT_LAST_ID 0x09F6
+#define MSG_MASK_TBL_CNT 25
+#define EVENT_LAST_ID 0x0A22
#define MSG_SSID_0 0
-#define MSG_SSID_0_LAST 101
+#define MSG_SSID_0_LAST 105
#define MSG_SSID_1 500
#define MSG_SSID_1_LAST 506
#define MSG_SSID_2 1000
@@ -142,7 +142,7 @@
#define MSG_SSID_6 4500
#define MSG_SSID_6_LAST 4526
#define MSG_SSID_7 4600
-#define MSG_SSID_7_LAST 4614
+#define MSG_SSID_7_LAST 4615
#define MSG_SSID_8 5000
#define MSG_SSID_8_LAST 5031
#define MSG_SSID_9 5500
@@ -173,8 +173,10 @@
#define MSG_SSID_21_LAST 10300
#define MSG_SSID_22 10350
#define MSG_SSID_22_LAST 10377
-#define MSG_SSID_23 0xC000
-#define MSG_SSID_23_LAST 0xC063
+#define MSG_SSID_23 10400
+#define MSG_SSID_23_LAST 10414
+#define MSG_SSID_24 0xC000
+#define MSG_SSID_24_LAST 0xC063
struct diagpkt_delay_params {
void *rsp_ptr;
@@ -302,7 +304,11 @@
MSG_LVL_HIGH,
MSG_LVL_LOW,
MSG_LVL_HIGH,
- MSG_LVL_HIGH
+ MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL,
+ MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR,
+ MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR,
+ MSG_LVL_MED|MSG_LVL_HIGH,
+ MSG_LVL_MED|MSG_LVL_HIGH
};
static const uint32_t msg_bld_masks_1[] = {
@@ -417,7 +423,8 @@
MSG_LVL_MED,
MSG_LVL_LOW,
MSG_LVL_LOW,
- MSG_LVL_LOW
+ MSG_LVL_LOW,
+ MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL
};
static const uint32_t msg_bld_masks_8[] = {
@@ -742,10 +749,28 @@
MSG_LVL_LOW
};
+static const uint32_t msg_bld_masks_23[] = {
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW
+};
+
/* LOG CODES */
static const uint32_t log_code_last_tbl[] = {
0x0, /* EQUIP ID 0 */
- 0x184A, /* EQUIP ID 1 */
+ 0x1871, /* EQUIP ID 1 */
0x0, /* EQUIP ID 2 */
0x0, /* EQUIP ID 3 */
0x4910, /* EQUIP ID 4 */
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 20fb776..3ba696b 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -190,6 +190,7 @@
extern void rcu_idle_exit(void);
extern void rcu_irq_enter(void);
extern void rcu_irq_exit(void);
+extern void exit_rcu(void);
/**
* RCU_NONIDLE - Indicate idle-loop code that needs RCU readers
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e93df77..4e56a9c 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -91,23 +91,20 @@
{
}
-static inline void exit_rcu(void)
+static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{
-}
-
-static inline int rcu_needs_cpu(int cpu)
-{
+ *delta_jiffies = ULONG_MAX;
return 0;
}
#else /* #ifdef CONFIG_TINY_RCU */
void rcu_preempt_note_context_switch(void);
-extern void exit_rcu(void);
int rcu_preempt_needs_cpu(void);
-static inline int rcu_needs_cpu(int cpu)
+static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{
+ *delta_jiffies = ULONG_MAX;
return rcu_preempt_needs_cpu();
}
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index e8ee5dd..624e6e9 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -32,7 +32,7 @@
extern void rcu_init(void);
extern void rcu_note_context_switch(int cpu);
-extern int rcu_needs_cpu(int cpu);
+extern int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
extern void rcu_cpu_stall_reset(void);
/*
@@ -45,18 +45,6 @@
rcu_note_context_switch(cpu);
}
-#ifdef CONFIG_TREE_PREEMPT_RCU
-
-extern void exit_rcu(void);
-
-#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-
-static inline void exit_rcu(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
-
extern void synchronize_rcu_bh(void);
extern void synchronize_sched_expedited(void);
extern void synchronize_rcu_expedited(void);
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index fc61854..e156ce1 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -19,6 +19,7 @@
size_t size;
size_t from;
size_t count;
+ size_t pad_until;
loff_t index;
loff_t read_pos;
u64 version;
@@ -75,6 +76,20 @@
}
}
+/**
+ * seq_setwidth - set padding width
+ * @m: the seq_file handle
+ * @size: the max number of bytes to pad.
+ *
+ * Call seq_setwidth() for setting max width, then call seq_printf() etc. and
+ * finally call seq_pad() to pad the remaining bytes.
+ */
+static inline void seq_setwidth(struct seq_file *m, size_t size)
+{
+ m->pad_until = m->count + size;
+}
+void seq_pad(struct seq_file *m, char c);
+
char *mangle_path(char *s, const char *p, const char *esc);
int seq_open(struct file *, const struct seq_operations *);
ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index ff30988..17df360 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -64,9 +64,7 @@
US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \
/* cannot handle READ_CAPACITY_16 */ \
US_FLAG(INITIAL_READ10, 0x00100000) \
- /* Initial READ(10) (and others) must be retried */ \
- US_FLAG(TUR_AFTER_WRITE, 0x00200000) \
- /* 5 TEST_UNIT_READY after 8 WRITE(10) */ \
+ /* Initial READ(10) (and others) must be retried */
#define US_FLAG(name, value) US_FL_##name = value ,
enum { US_DO_ALL_FLAGS };
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index d583601..15edaf9 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -53,6 +53,11 @@
#define MAX_AF_ITERATIONS 3
#define MAX_NUMBER_OF_STEPS 47
+typedef enum sensor_stats_type {
+ YRGB,
+ YYYY,
+} sensor_stats_type_t;
+
enum flash_type {
LED_FLASH = 1,
STROBE_FLASH,
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index bbde6ef..e48c7da 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -55,6 +55,7 @@
void *msm_vidc_open(int core_id, int session_type);
int msm_vidc_close(void *instance);
+int msm_vidc_suspend(int core_id);
int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f);
int msm_vidc_s_fmt(void *instance, struct v4l2_format *f);
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 59dcca9..f5a53a8 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -13,7 +13,8 @@
#define MAX_NUM_CPP_STRIPS 8
#define MSM_CPP_MAX_NUM_PLANES 3
-#define MSM_CPP_MAX_FRAME_LENGTH 1024
+#define MSM_CPP_MIN_FRAME_LENGTH 13
+#define MSM_CPP_MAX_FRAME_LENGTH 2048
#define MSM_CPP_MAX_FW_NAME_LEN 32
#define MAX_FREQ_TBL 10
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 07199e0..ec3038b 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -165,6 +165,7 @@
/* Relative or absolute TS */
atomic_t time_flag;
atomic_t nowait_cmd_cnt;
+ atomic_t mem_state;
void *priv;
uint32_t io_mode;
uint64_t time_stamp;
@@ -176,6 +177,7 @@
struct audio_port_data port[2];
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
+ wait_queue_head_t mem_wait;
int perf_mode;
int stream_id;
/* audio cache operations fptr*/
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 3370997..d274734 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -289,9 +289,12 @@
* "In holdoff": Nothing to do, holding off after unsuccessful attempt.
* "Begin holdoff": Attempt failed, don't retry until next jiffy.
* "Dyntick with callbacks": Entering dyntick-idle despite callbacks.
+ * "Dyntick with lazy callbacks": Entering dyntick-idle w/lazy callbacks.
* "More callbacks": Still more callbacks, try again to clear them out.
* "Callbacks drained": All callbacks processed, off to dyntick idle!
* "Timer": Timer fired to cause CPU to continue processing callbacks.
+ * "Demigrate": Timer fired on wrong CPU, woke up correct CPU.
+ * "Cleanup after idle": Idle exited, timer canceled.
*/
TRACE_EVENT(rcu_prep_idle,
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2db91f9..745a600 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -648,10 +648,12 @@
void set_cpu_online(unsigned int cpu, bool online)
{
- if (online)
+ if (online) {
cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
- else
+ cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
+ } else {
cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
+ }
}
void set_cpu_active(unsigned int cpu, bool active)
diff --git a/kernel/futex.c b/kernel/futex.c
index e2b0fb9..9536918 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1256,6 +1256,13 @@
if (requeue_pi) {
/*
+ * Requeue PI only works on two distinct uaddrs. This
+ * check is only valid for private futexes. See below.
+ */
+ if (uaddr1 == uaddr2)
+ return -EINVAL;
+
+ /*
* requeue_pi requires a pi_state, try to allocate it now
* without any locks in case it fails.
*/
@@ -1293,6 +1300,15 @@
if (unlikely(ret != 0))
goto out_put_key1;
+ /*
+ * The check above which compares uaddrs is not sufficient for
+ * shared futexes. We need to compare the keys:
+ */
+ if (requeue_pi && match_futex(&key1, &key2)) {
+ ret = -EINVAL;
+ goto out_put_keys;
+ }
+
hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
@@ -2308,6 +2324,15 @@
if (ret)
goto out_key2;
+ /*
+ * The check above which compares uaddrs is not sufficient for
+ * shared futexes. We need to compare the keys:
+ */
+ if (match_futex(&q.key, &key2)) {
+ ret = -EINVAL;
+ goto out_put_keys;
+ }
+
/* Queue the futex_q, drop the hb lock, wait for wakeup. */
futex_wait_queue_me(hb, &q, to);
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 5746f18..c1a835c 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -53,6 +53,33 @@
#include "rcu.h"
module_param(rcu_expedited, int, 0);
+#ifdef CONFIG_PREEMPT_RCU
+
+/*
+ * Check for a task exiting while in a preemptible-RCU read-side
+ * critical section, clean up if so. No need to issue warnings,
+ * as debug_check_no_locks_held() already does this if lockdep
+ * is enabled.
+ */
+void exit_rcu(void)
+{
+ struct task_struct *t = current;
+
+ if (likely(list_empty(¤t->rcu_node_entry)))
+ return;
+ t->rcu_read_lock_nesting = 1;
+ barrier();
+ t->rcu_read_unlock_special = RCU_READ_UNLOCK_BLOCKED;
+ __rcu_read_unlock();
+}
+
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+void exit_rcu(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key rcu_lock_key;
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 5a0f324..977250f 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -854,22 +854,6 @@
return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
}
-/*
- * Check for a task exiting while in a preemptible -RCU read-side
- * critical section, clean up if so. No need to issue warnings,
- * as debug_check_no_locks_held() already does this if lockdep
- * is enabled.
- */
-void exit_rcu(void)
-{
- struct task_struct *t = current;
-
- if (t->rcu_read_lock_nesting == 0)
- return;
- t->rcu_read_lock_nesting = 1;
- __rcu_read_unlock();
-}
-
#else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
#ifdef CONFIG_RCU_TRACE
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index e269782..aaf798b 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -75,6 +75,8 @@
.gpnum = -300, \
.completed = -300, \
.onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.onofflock), \
+ .orphan_nxttail = &structname##_state.orphan_nxtlist, \
+ .orphan_donetail = &structname##_state.orphan_donelist, \
.fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.fqslock), \
.n_force_qs = 0, \
.n_force_qs_ngp = 0, \
@@ -145,6 +147,13 @@
unsigned long rcutorture_testseq;
unsigned long rcutorture_vernum;
+/* State information for rcu_barrier() and friends. */
+
+static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
+static atomic_t rcu_barrier_cpu_count;
+static DEFINE_MUTEX(rcu_barrier_mutex);
+static struct completion rcu_barrier_completion;
+
/*
* Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
* permit this function to be invoked without holding the root rcu_node
@@ -1313,95 +1322,133 @@
#ifdef CONFIG_HOTPLUG_CPU
/*
- * Move a dying CPU's RCU callbacks to online CPU's callback list.
- * Also record a quiescent state for this CPU for the current grace period.
- * Synchronization and interrupt disabling are not required because
- * this function executes in stop_machine() context. Therefore, cleanup
- * operations that might block must be done later from the CPU_DEAD
- * notifier.
- *
- * Note that the outgoing CPU's bit has already been cleared in the
- * cpu_online_mask. This allows us to randomly pick a callback
- * destination from the bits set in that mask.
+ * Send the specified CPU's RCU callbacks to the orphanage. The
+ * specified CPU must be offline, and the caller must hold the
+ * ->onofflock.
*/
-static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
+static void
+rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
+ struct rcu_node *rnp, struct rcu_data *rdp)
{
int i;
- unsigned long mask;
- int receive_cpu = cpumask_any(cpu_online_mask);
- struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
- struct rcu_data *receive_rdp = per_cpu_ptr(rsp->rda, receive_cpu);
- RCU_TRACE(struct rcu_node *rnp = rdp->mynode); /* For dying CPU. */
- /* First, adjust the counts. */
+ /*
+ * Orphan the callbacks. First adjust the counts. This is safe
+ * because ->onofflock excludes _rcu_barrier()'s adoption of
+ * the callbacks, thus no memory barrier is required.
+ */
if (rdp->nxtlist != NULL) {
- receive_rdp->qlen_lazy += rdp->qlen_lazy;
- receive_rdp->qlen += rdp->qlen;
+ rsp->qlen_lazy += rdp->qlen_lazy;
+ rsp->qlen += rdp->qlen;
+ rdp->n_cbs_orphaned += rdp->qlen;
rdp->qlen_lazy = 0;
rdp->qlen = 0;
}
/*
- * Next, move ready-to-invoke callbacks to be invoked on some
- * other CPU. These will not be required to pass through another
- * grace period: They are done, regardless of CPU.
+ * Next, move those callbacks still needing a grace period to
+ * the orphanage, where some other CPU will pick them up.
+ * Some of the callbacks might have gone partway through a grace
+ * period, but that is too bad. They get to start over because we
+ * cannot assume that grace periods are synchronized across CPUs.
+ * We don't bother updating the ->nxttail[] array yet, instead
+ * we just reset the whole thing later on.
*/
- if (rdp->nxtlist != NULL &&
- rdp->nxttail[RCU_DONE_TAIL] != &rdp->nxtlist) {
- struct rcu_head *oldhead;
- struct rcu_head **oldtail;
- struct rcu_head **newtail;
-
- oldhead = rdp->nxtlist;
- oldtail = receive_rdp->nxttail[RCU_DONE_TAIL];
- rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL];
- *rdp->nxttail[RCU_DONE_TAIL] = *oldtail;
- *receive_rdp->nxttail[RCU_DONE_TAIL] = oldhead;
- newtail = rdp->nxttail[RCU_DONE_TAIL];
- for (i = RCU_DONE_TAIL; i < RCU_NEXT_SIZE; i++) {
- if (receive_rdp->nxttail[i] == oldtail)
- receive_rdp->nxttail[i] = newtail;
- if (rdp->nxttail[i] == newtail)
- rdp->nxttail[i] = &rdp->nxtlist;
- }
+ if (*rdp->nxttail[RCU_DONE_TAIL] != NULL) {
+ *rsp->orphan_nxttail = *rdp->nxttail[RCU_DONE_TAIL];
+ rsp->orphan_nxttail = rdp->nxttail[RCU_NEXT_TAIL];
+ *rdp->nxttail[RCU_DONE_TAIL] = NULL;
}
/*
- * Finally, put the rest of the callbacks at the end of the list.
- * The ones that made it partway through get to start over: We
- * cannot assume that grace periods are synchronized across CPUs.
- * (We could splice RCU_WAIT_TAIL into RCU_NEXT_READY_TAIL, but
- * this does not seem compelling. Not yet, anyway.)
+ * Then move the ready-to-invoke callbacks to the orphanage,
+ * where some other CPU will pick them up. These will not be
+ * required to pass though another grace period: They are done.
*/
if (rdp->nxtlist != NULL) {
- *receive_rdp->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist;
- receive_rdp->nxttail[RCU_NEXT_TAIL] =
- rdp->nxttail[RCU_NEXT_TAIL];
- receive_rdp->n_cbs_adopted += rdp->qlen;
- rdp->n_cbs_orphaned += rdp->qlen;
-
- rdp->nxtlist = NULL;
- for (i = 0; i < RCU_NEXT_SIZE; i++)
- rdp->nxttail[i] = &rdp->nxtlist;
+ *rsp->orphan_donetail = rdp->nxtlist;
+ rsp->orphan_donetail = rdp->nxttail[RCU_DONE_TAIL];
}
+ /* Finally, initialize the rcu_data structure's list to empty. */
+ rdp->nxtlist = NULL;
+ for (i = 0; i < RCU_NEXT_SIZE; i++)
+ rdp->nxttail[i] = &rdp->nxtlist;
+}
+
+/*
+ * Adopt the RCU callbacks from the specified rcu_state structure's
+ * orphanage. The caller must hold the ->onofflock.
+ */
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+ int i;
+ struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
+
/*
- * Record a quiescent state for the dying CPU. This is safe
- * only because we have already cleared out the callbacks.
- * (Otherwise, the RCU core might try to schedule the invocation
- * of callbacks on this now-offline CPU, which would be bad.)
+ * If there is an rcu_barrier() operation in progress, then
+ * only the task doing that operation is permitted to adopt
+ * callbacks. To do otherwise breaks rcu_barrier() and friends
+ * by causing them to fail to wait for the callbacks in the
+ * orphanage.
*/
- mask = rdp->grpmask; /* rnp->grplo is constant. */
+ if (rsp->rcu_barrier_in_progress &&
+ rsp->rcu_barrier_in_progress != current)
+ return;
+
+ /* Do the accounting first. */
+ rdp->qlen_lazy += rsp->qlen_lazy;
+ rdp->qlen += rsp->qlen;
+ rdp->n_cbs_adopted += rsp->qlen;
+ rsp->qlen_lazy = 0;
+ rsp->qlen = 0;
+
+ /*
+ * We do not need a memory barrier here because the only way we
+ * can get here if there is an rcu_barrier() in flight is if
+ * we are the task doing the rcu_barrier().
+ */
+
+ /* First adopt the ready-to-invoke callbacks. */
+ if (rsp->orphan_donelist != NULL) {
+ *rsp->orphan_donetail = *rdp->nxttail[RCU_DONE_TAIL];
+ *rdp->nxttail[RCU_DONE_TAIL] = rsp->orphan_donelist;
+ for (i = RCU_NEXT_SIZE - 1; i >= RCU_DONE_TAIL; i--)
+ if (rdp->nxttail[i] == rdp->nxttail[RCU_DONE_TAIL])
+ rdp->nxttail[i] = rsp->orphan_donetail;
+ rsp->orphan_donelist = NULL;
+ rsp->orphan_donetail = &rsp->orphan_donelist;
+ }
+
+ /* And then adopt the callbacks that still need a grace period. */
+ if (rsp->orphan_nxtlist != NULL) {
+ *rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxtlist;
+ rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxttail;
+ rsp->orphan_nxtlist = NULL;
+ rsp->orphan_nxttail = &rsp->orphan_nxtlist;
+ }
+}
+
+/*
+ * Trace the fact that this CPU is going offline.
+ */
+static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
+{
+ RCU_TRACE(unsigned long mask);
+ RCU_TRACE(struct rcu_data *rdp = this_cpu_ptr(rsp->rda));
+ RCU_TRACE(struct rcu_node *rnp = rdp->mynode);
+
+ RCU_TRACE(mask = rdp->grpmask);
trace_rcu_grace_period(rsp->name,
rnp->gpnum + 1 - !!(rnp->qsmask & mask),
"cpuofl");
- rcu_report_qs_rdp(smp_processor_id(), rsp, rdp, rsp->gpnum);
- /* Note that rcu_report_qs_rdp() might call trace_rcu_grace_period(). */
}
/*
* The CPU has been completely removed, and some other CPU is reporting
- * this fact from process context. Do the remainder of the cleanup.
+ * this fact from process context. Do the remainder of the cleanup,
+ * including orphaning the outgoing CPU's RCU callbacks, and also
+ * adopting them, if there is no _rcu_barrier() instance running.
* There can only be one CPU hotplug operation at a time, so no other
* CPU can be attempting to update rcu_cpu_kthread_task.
*/
@@ -1411,17 +1458,21 @@
unsigned long mask;
int need_report = 0;
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
- struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rnp. */
+ struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
/* Adjust any no-longer-needed kthreads. */
rcu_stop_cpu_kthread(cpu);
rcu_node_kthread_setaffinity(rnp, -1);
- /* Remove the dying CPU from the bitmasks in the rcu_node hierarchy. */
+ /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
/* Exclude any attempts to start a new grace period. */
raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
+ rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
+ rcu_adopt_orphan_cbs(rsp);
+
/* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */
mask = rdp->grpmask; /* rnp->grplo is constant. */
do {
@@ -1458,6 +1509,10 @@
#else /* #ifdef CONFIG_HOTPLUG_CPU */
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+}
+
static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
{
}
@@ -1476,7 +1531,7 @@
{
unsigned long flags;
struct rcu_head *next, *list, **tail;
- int bl, count, count_lazy;
+ int bl, count, count_lazy, i;
/* If no callbacks are ready, just return.*/
if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
@@ -1499,9 +1554,9 @@
rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL];
*rdp->nxttail[RCU_DONE_TAIL] = NULL;
tail = rdp->nxttail[RCU_DONE_TAIL];
- for (count = RCU_NEXT_SIZE - 1; count >= 0; count--)
- if (rdp->nxttail[count] == rdp->nxttail[RCU_DONE_TAIL])
- rdp->nxttail[count] = &rdp->nxtlist;
+ for (i = RCU_NEXT_SIZE - 1; i >= 0; i--)
+ if (rdp->nxttail[i] == rdp->nxttail[RCU_DONE_TAIL])
+ rdp->nxttail[i] = &rdp->nxtlist;
local_irq_restore(flags);
/* Invoke callbacks. */
@@ -1526,18 +1581,19 @@
rcu_is_callbacks_kthread());
/* Update count, and requeue any remaining callbacks. */
- rdp->qlen_lazy -= count_lazy;
- rdp->qlen -= count;
- rdp->n_cbs_invoked += count;
if (list != NULL) {
*tail = rdp->nxtlist;
rdp->nxtlist = list;
- for (count = 0; count < RCU_NEXT_SIZE; count++)
- if (&rdp->nxtlist == rdp->nxttail[count])
- rdp->nxttail[count] = tail;
+ for (i = 0; i < RCU_NEXT_SIZE; i++)
+ if (&rdp->nxtlist == rdp->nxttail[i])
+ rdp->nxttail[i] = tail;
else
break;
}
+ smp_mb(); /* List handling before counting for rcu_barrier(). */
+ rdp->qlen_lazy -= count_lazy;
+ rdp->qlen -= count;
+ rdp->n_cbs_invoked += count;
/* Reinstate batch limit if we have worked down the excess. */
if (rdp->blimit == LONG_MAX && rdp->qlen <= qlowmark)
@@ -1825,11 +1881,14 @@
rdp = this_cpu_ptr(rsp->rda);
/* Add the callback to our list. */
- *rdp->nxttail[RCU_NEXT_TAIL] = head;
- rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
rdp->qlen++;
if (lazy)
rdp->qlen_lazy++;
+ else
+ rcu_idle_count_callbacks_posted();
+ smp_mb(); /* Count before adding callback for rcu_barrier(). */
+ *rdp->nxttail[RCU_NEXT_TAIL] = head;
+ rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
if (__is_kfree_rcu_offset((unsigned long)func))
trace_rcu_kfree_callback(rsp->name, head, (unsigned long)func,
@@ -2174,11 +2233,10 @@
rcu_preempt_cpu_has_callbacks(cpu);
}
-static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
-static DEFINE_MUTEX(rcu_barrier_mutex);
-static struct completion rcu_barrier_completion;
-
+/*
+ * RCU callback function for _rcu_barrier(). If we are last, wake
+ * up the task executing _rcu_barrier().
+ */
static void rcu_barrier_callback(struct rcu_head *notused)
{
if (atomic_dec_and_test(&rcu_barrier_cpu_count))
@@ -2208,27 +2266,94 @@
void (*call_rcu_func)(struct rcu_head *head,
void (*func)(struct rcu_head *head)))
{
- BUG_ON(in_interrupt());
+ int cpu;
+ unsigned long flags;
+ struct rcu_data *rdp;
+ struct rcu_head rh;
+
+ init_rcu_head_on_stack(&rh);
+
/* Take mutex to serialize concurrent rcu_barrier() requests. */
mutex_lock(&rcu_barrier_mutex);
- init_completion(&rcu_barrier_completion);
+
+ smp_mb(); /* Prevent any prior operations from leaking in. */
+
/*
- * Initialize rcu_barrier_cpu_count to 1, then invoke
- * rcu_barrier_func() on each CPU, so that each CPU also has
- * incremented rcu_barrier_cpu_count. Only then is it safe to
- * decrement rcu_barrier_cpu_count -- otherwise the first CPU
- * might complete its grace period before all of the other CPUs
- * did their increment, causing this function to return too
- * early. Note that on_each_cpu() disables irqs, which prevents
- * any CPUs from coming online or going offline until each online
- * CPU has queued its RCU-barrier callback.
+ * Initialize the count to one rather than to zero in order to
+ * avoid a too-soon return to zero in case of a short grace period
+ * (or preemption of this task). Also flag this task as doing
+ * an rcu_barrier(). This will prevent anyone else from adopting
+ * orphaned callbacks, which could cause otherwise failure if a
+ * CPU went offline and quickly came back online. To see this,
+ * consider the following sequence of events:
+ *
+ * 1. We cause CPU 0 to post an rcu_barrier_callback() callback.
+ * 2. CPU 1 goes offline, orphaning its callbacks.
+ * 3. CPU 0 adopts CPU 1's orphaned callbacks.
+ * 4. CPU 1 comes back online.
+ * 5. We cause CPU 1 to post an rcu_barrier_callback() callback.
+ * 6. Both rcu_barrier_callback() callbacks are invoked, awakening
+ * us -- but before CPU 1's orphaned callbacks are invoked!!!
*/
+ init_completion(&rcu_barrier_completion);
atomic_set(&rcu_barrier_cpu_count, 1);
- on_each_cpu(rcu_barrier_func, (void *)call_rcu_func, 1);
+ raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ rsp->rcu_barrier_in_progress = current;
+ raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+
+ /*
+ * Force every CPU with callbacks to register a new callback
+ * that will tell us when all the preceding callbacks have
+ * been invoked. If an offline CPU has callbacks, wait for
+ * it to either come back online or to finish orphaning those
+ * callbacks.
+ */
+ for_each_possible_cpu(cpu) {
+ preempt_disable();
+ rdp = per_cpu_ptr(rsp->rda, cpu);
+ if (cpu_is_offline(cpu)) {
+ preempt_enable();
+ while (cpu_is_offline(cpu) && ACCESS_ONCE(rdp->qlen))
+ schedule_timeout_interruptible(1);
+ } else if (ACCESS_ONCE(rdp->qlen)) {
+ smp_call_function_single(cpu, rcu_barrier_func,
+ (void *)call_rcu_func, 1);
+ preempt_enable();
+ } else {
+ preempt_enable();
+ }
+ }
+
+ /*
+ * Now that all online CPUs have rcu_barrier_callback() callbacks
+ * posted, we can adopt all of the orphaned callbacks and place
+ * an rcu_barrier_callback() callback after them. When that is done,
+ * we are guaranteed to have an rcu_barrier_callback() callback
+ * following every callback that could possibly have been
+ * registered before _rcu_barrier() was called.
+ */
+ raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ rcu_adopt_orphan_cbs(rsp);
+ rsp->rcu_barrier_in_progress = NULL;
+ raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+ atomic_inc(&rcu_barrier_cpu_count);
+ smp_mb__after_atomic_inc(); /* Ensure atomic_inc() before callback. */
+ call_rcu_func(&rh, rcu_barrier_callback);
+
+ /*
+ * Now that we have an rcu_barrier_callback() callback on each
+ * CPU, and thus each counted, remove the initial count.
+ */
if (atomic_dec_and_test(&rcu_barrier_cpu_count))
complete(&rcu_barrier_completion);
+
+ /* Wait for all rcu_barrier_callback() callbacks to be invoked. */
wait_for_completion(&rcu_barrier_completion);
+
+ /* Other rcu_barrier() invocations can now safely proceed. */
mutex_unlock(&rcu_barrier_mutex);
+
+ destroy_rcu_head_on_stack(&rh);
}
/**
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index cdd1be0..aa5676b 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -88,6 +88,20 @@
/* Process level is worth LLONG_MAX/2. */
int dynticks_nmi_nesting; /* Track NMI nesting level. */
atomic_t dynticks; /* Even value for idle, else odd. */
+#ifdef CONFIG_RCU_FAST_NO_HZ
+ int dyntick_drain; /* Prepare-for-idle state variable. */
+ unsigned long dyntick_holdoff;
+ /* No retries for the jiffy of failure. */
+ struct timer_list idle_gp_timer;
+ /* Wake up CPU sleeping with callbacks. */
+ unsigned long idle_gp_timer_expires;
+ /* When to wake up CPU (for repost). */
+ bool idle_first_pass; /* First pass of attempt to go idle? */
+ unsigned long nonlazy_posted;
+ /* # times non-lazy CBs posted to CPU. */
+ unsigned long nonlazy_posted_snap;
+ /* idle-period nonlazy_posted snapshot. */
+#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
};
/* RCU's kthread states for tracing. */
@@ -371,6 +385,17 @@
raw_spinlock_t onofflock; /* exclude on/offline and */
/* starting new GP. */
+ struct rcu_head *orphan_nxtlist; /* Orphaned callbacks that */
+ /* need a grace period. */
+ struct rcu_head **orphan_nxttail; /* Tail of above. */
+ struct rcu_head *orphan_donelist; /* Orphaned callbacks that */
+ /* are ready to invoke. */
+ struct rcu_head **orphan_donetail; /* Tail of above. */
+ long qlen_lazy; /* Number of lazy callbacks. */
+ long qlen; /* Total number of callbacks. */
+ struct task_struct *rcu_barrier_in_progress;
+ /* Task doing rcu_barrier(), */
+ /* or NULL if no barrier. */
raw_spinlock_t fqslock; /* Only one task forcing */
/* quiescent states. */
unsigned long jiffies_force_qs; /* Time at which to invoke */
@@ -471,6 +496,7 @@
static void rcu_prepare_for_idle_init(int cpu);
static void rcu_cleanup_after_idle(int cpu);
static void rcu_prepare_for_idle(int cpu);
+static void rcu_idle_count_callbacks_posted(void);
static void print_cpu_stall_info_begin(void);
static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
static void print_cpu_stall_info_end(void);
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index beafb9c..9e501bd 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -972,22 +972,6 @@
rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
}
-/*
- * Check for a task exiting while in a preemptible-RCU read-side
- * critical section, clean up if so. No need to issue warnings,
- * as debug_check_no_locks_held() already does this if lockdep
- * is enabled.
- */
-void exit_rcu(void)
-{
- struct task_struct *t = current;
-
- if (t->rcu_read_lock_nesting == 0)
- return;
- t->rcu_read_lock_nesting = 1;
- __rcu_read_unlock();
-}
-
#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
static struct rcu_state *rcu_state = &rcu_sched_state;
@@ -1913,8 +1897,9 @@
* Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs
* any flavor of RCU.
*/
-int rcu_needs_cpu(int cpu)
+int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{
+ *delta_jiffies = ULONG_MAX;
return rcu_cpu_has_callbacks(cpu);
}
@@ -1941,6 +1926,14 @@
{
}
+/*
+ * Don't bother keeping a running count of the number of RCU callbacks
+ * posted because CONFIG_RCU_FAST_NO_HZ=n.
+ */
+static void rcu_idle_count_callbacks_posted(void)
+{
+}
+
#else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */
/*
@@ -1981,30 +1974,6 @@
#define RCU_IDLE_GP_DELAY 6 /* Roughly one grace period. */
#define RCU_IDLE_LAZY_GP_DELAY (6 * HZ) /* Roughly six seconds. */
-static DEFINE_PER_CPU(int, rcu_dyntick_drain);
-static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff);
-static DEFINE_PER_CPU(struct hrtimer, rcu_idle_gp_timer);
-static ktime_t rcu_idle_gp_wait; /* If some non-lazy callbacks. */
-static ktime_t rcu_idle_lazy_gp_wait; /* If only lazy callbacks. */
-
-/*
- * Allow the CPU to enter dyntick-idle mode if either: (1) There are no
- * callbacks on this CPU, (2) this CPU has not yet attempted to enter
- * dyntick-idle mode, or (3) this CPU is in the process of attempting to
- * enter dyntick-idle mode. Otherwise, if we have recently tried and failed
- * to enter dyntick-idle mode, we refuse to try to enter it. After all,
- * it is better to incur scheduling-clock interrupts than to spin
- * continuously for the same time duration!
- */
-int rcu_needs_cpu(int cpu)
-{
- /* If no callbacks, RCU doesn't need the CPU. */
- if (!rcu_cpu_has_callbacks(cpu))
- return 0;
- /* Otherwise, RCU needs the CPU only if it recently tried and failed. */
- return per_cpu(rcu_dyntick_holdoff, cpu) == jiffies;
-}
-
/*
* Does the specified flavor of RCU have non-lazy callbacks pending on
* the specified CPU? Both RCU flavor and CPU are specified by the
@@ -2048,16 +2017,75 @@
}
/*
+ * Allow the CPU to enter dyntick-idle mode if either: (1) There are no
+ * callbacks on this CPU, (2) this CPU has not yet attempted to enter
+ * dyntick-idle mode, or (3) this CPU is in the process of attempting to
+ * enter dyntick-idle mode. Otherwise, if we have recently tried and failed
+ * to enter dyntick-idle mode, we refuse to try to enter it. After all,
+ * it is better to incur scheduling-clock interrupts than to spin
+ * continuously for the same time duration!
+ *
+ * The delta_jiffies argument is used to store the time when RCU is
+ * going to need the CPU again if it still has callbacks. The reason
+ * for this is that rcu_prepare_for_idle() might need to post a timer,
+ * but if so, it will do so after tick_nohz_stop_sched_tick() has set
+ * the wakeup time for this CPU. This means that RCU's timer can be
+ * delayed until the wakeup time, which defeats the purpose of posting
+ * a timer.
+ */
+int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+{
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
+ /* Flag a new idle sojourn to the idle-entry state machine. */
+ rdtp->idle_first_pass = 1;
+ /* If no callbacks, RCU doesn't need the CPU. */
+ if (!rcu_cpu_has_callbacks(cpu)) {
+ *delta_jiffies = ULONG_MAX;
+ return 0;
+ }
+ if (rdtp->dyntick_holdoff == jiffies) {
+ /* RCU recently tried and failed, so don't try again. */
+ *delta_jiffies = 1;
+ return 1;
+ }
+ /* Set up for the possibility that RCU will post a timer. */
+ if (rcu_cpu_has_nonlazy_callbacks(cpu))
+ *delta_jiffies = RCU_IDLE_GP_DELAY;
+ else
+ *delta_jiffies = RCU_IDLE_LAZY_GP_DELAY;
+ return 0;
+}
+
+/*
+ * Handler for smp_call_function_single(). The only point of this
+ * handler is to wake the CPU up, so the handler does only tracing.
+ */
+void rcu_idle_demigrate(void *unused)
+{
+ trace_rcu_prep_idle("Demigrate");
+}
+
+/*
* Timer handler used to force CPU to start pushing its remaining RCU
* callbacks in the case where it entered dyntick-idle mode with callbacks
* pending. The hander doesn't really need to do anything because the
* real work is done upon re-entry to idle, or by the next scheduling-clock
* interrupt should idle not be re-entered.
+ *
+ * One special case: the timer gets migrated without awakening the CPU
+ * on which the timer was scheduled on. In this case, we must wake up
+ * that CPU. We do so with smp_call_function_single().
*/
-static enum hrtimer_restart rcu_idle_gp_timer_func(struct hrtimer *hrtp)
+static void rcu_idle_gp_timer_func(unsigned long cpu_in)
{
+ int cpu = (int)cpu_in;
+
trace_rcu_prep_idle("Timer");
- return HRTIMER_NORESTART;
+ if (cpu != smp_processor_id())
+ smp_call_function_single(cpu, rcu_idle_demigrate, NULL, 0);
+ else
+ WARN_ON_ONCE(1); /* Getting here can hang the system... */
}
/*
@@ -2065,29 +2093,25 @@
*/
static void rcu_prepare_for_idle_init(int cpu)
{
- static int firsttime = 1;
- struct hrtimer *hrtp = &per_cpu(rcu_idle_gp_timer, cpu);
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
- hrtimer_init(hrtp, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtp->function = rcu_idle_gp_timer_func;
- if (firsttime) {
- unsigned int upj = jiffies_to_usecs(RCU_IDLE_GP_DELAY);
-
- rcu_idle_gp_wait = ns_to_ktime(upj * (u64)1000);
- upj = jiffies_to_usecs(RCU_IDLE_LAZY_GP_DELAY);
- rcu_idle_lazy_gp_wait = ns_to_ktime(upj * (u64)1000);
- firsttime = 0;
- }
+ rdtp->dyntick_holdoff = jiffies - 1;
+ setup_timer(&rdtp->idle_gp_timer, rcu_idle_gp_timer_func, cpu);
+ rdtp->idle_gp_timer_expires = jiffies - 1;
+ rdtp->idle_first_pass = 1;
}
/*
* Clean up for exit from idle. Because we are exiting from idle, there
- * is no longer any point to rcu_idle_gp_timer, so cancel it. This will
+ * is no longer any point to ->idle_gp_timer, so cancel it. This will
* do nothing if this timer is not active, so just cancel it unconditionally.
*/
static void rcu_cleanup_after_idle(int cpu)
{
- hrtimer_cancel(&per_cpu(rcu_idle_gp_timer, cpu));
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
+ del_timer(&rdtp->idle_gp_timer);
+ trace_rcu_prep_idle("Cleanup after idle");
}
/*
@@ -2105,19 +2129,41 @@
* Because it is not legal to invoke rcu_process_callbacks() with irqs
* disabled, we do one pass of force_quiescent_state(), then do a
* invoke_rcu_core() to cause rcu_process_callbacks() to be invoked
- * later. The per-cpu rcu_dyntick_drain variable controls the sequencing.
+ * later. The ->dyntick_drain field controls the sequencing.
*
* The caller must have disabled interrupts.
*/
static void rcu_prepare_for_idle(int cpu)
{
+ struct timer_list *tp;
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
+ /*
+ * If this is an idle re-entry, for example, due to use of
+ * RCU_NONIDLE() or the new idle-loop tracing API within the idle
+ * loop, then don't take any state-machine actions, unless the
+ * momentary exit from idle queued additional non-lazy callbacks.
+ * Instead, repost the ->idle_gp_timer if this CPU has callbacks
+ * pending.
+ */
+ if (!rdtp->idle_first_pass &&
+ (rdtp->nonlazy_posted == rdtp->nonlazy_posted_snap)) {
+ if (rcu_cpu_has_callbacks(cpu)) {
+ tp = &rdtp->idle_gp_timer;
+ mod_timer_pinned(tp, rdtp->idle_gp_timer_expires);
+ }
+ return;
+ }
+ rdtp->idle_first_pass = 0;
+ rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted - 1;
+
/*
* If there are no callbacks on this CPU, enter dyntick-idle mode.
* Also reset state to avoid prejudicing later attempts.
*/
if (!rcu_cpu_has_callbacks(cpu)) {
- per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1;
- per_cpu(rcu_dyntick_drain, cpu) = 0;
+ rdtp->dyntick_holdoff = jiffies - 1;
+ rdtp->dyntick_drain = 0;
trace_rcu_prep_idle("No callbacks");
return;
}
@@ -2126,32 +2172,37 @@
* If in holdoff mode, just return. We will presumably have
* refrained from disabling the scheduling-clock tick.
*/
- if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies) {
+ if (rdtp->dyntick_holdoff == jiffies) {
trace_rcu_prep_idle("In holdoff");
return;
}
- /* Check and update the rcu_dyntick_drain sequencing. */
- if (per_cpu(rcu_dyntick_drain, cpu) <= 0) {
+ /* Check and update the ->dyntick_drain sequencing. */
+ if (rdtp->dyntick_drain <= 0) {
/* First time through, initialize the counter. */
- per_cpu(rcu_dyntick_drain, cpu) = RCU_IDLE_FLUSHES;
- } else if (per_cpu(rcu_dyntick_drain, cpu) <= RCU_IDLE_OPT_FLUSHES &&
+ rdtp->dyntick_drain = RCU_IDLE_FLUSHES;
+ } else if (rdtp->dyntick_drain <= RCU_IDLE_OPT_FLUSHES &&
!rcu_pending(cpu) &&
!local_softirq_pending()) {
/* Can we go dyntick-idle despite still having callbacks? */
- trace_rcu_prep_idle("Dyntick with callbacks");
- per_cpu(rcu_dyntick_drain, cpu) = 0;
- per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
- if (rcu_cpu_has_nonlazy_callbacks(cpu))
- hrtimer_start(&per_cpu(rcu_idle_gp_timer, cpu),
- rcu_idle_gp_wait, HRTIMER_MODE_REL);
- else
- hrtimer_start(&per_cpu(rcu_idle_gp_timer, cpu),
- rcu_idle_lazy_gp_wait, HRTIMER_MODE_REL);
+ rdtp->dyntick_drain = 0;
+ rdtp->dyntick_holdoff = jiffies;
+ if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
+ trace_rcu_prep_idle("Dyntick with callbacks");
+ rdtp->idle_gp_timer_expires =
+ jiffies + RCU_IDLE_GP_DELAY;
+ } else {
+ rdtp->idle_gp_timer_expires =
+ jiffies + RCU_IDLE_LAZY_GP_DELAY;
+ trace_rcu_prep_idle("Dyntick with lazy callbacks");
+ }
+ tp = &rdtp->idle_gp_timer;
+ mod_timer_pinned(tp, rdtp->idle_gp_timer_expires);
+ rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
return; /* Nothing more to do immediately. */
- } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) {
+ } else if (--(rdtp->dyntick_drain) <= 0) {
/* We have hit the limit, so time to give up. */
- per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
+ rdtp->dyntick_holdoff = jiffies;
trace_rcu_prep_idle("Begin holdoff");
invoke_rcu_core(); /* Force the CPU out of dyntick-idle. */
return;
@@ -2187,6 +2238,19 @@
trace_rcu_prep_idle("Callbacks drained");
}
+/*
+ * Keep a running count of the number of non-lazy callbacks posted
+ * on this CPU. This running counter (which is never decremented) allows
+ * rcu_prepare_for_idle() to detect when something out of the idle loop
+ * posts a callback, even if an equal number of callbacks are invoked.
+ * Of course, callbacks should only be posted from within a trace event
+ * designed to be called from idle or from within RCU_NONIDLE().
+ */
+static void rcu_idle_count_callbacks_posted(void)
+{
+ __this_cpu_add(rcu_dynticks.nonlazy_posted, 1);
+}
+
#endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */
#ifdef CONFIG_RCU_CPU_STALL_INFO
@@ -2195,14 +2259,13 @@
static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
{
- struct hrtimer *hrtp = &per_cpu(rcu_idle_gp_timer, cpu);
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+ struct timer_list *tltp = &rdtp->idle_gp_timer;
- sprintf(cp, "drain=%d %c timer=%lld",
- per_cpu(rcu_dyntick_drain, cpu),
- per_cpu(rcu_dyntick_holdoff, cpu) == jiffies ? 'H' : '.',
- hrtimer_active(hrtp)
- ? ktime_to_us(hrtimer_get_remaining(hrtp))
- : -1);
+ sprintf(cp, "drain=%d %c timer=%lu",
+ rdtp->dyntick_drain,
+ rdtp->dyntick_holdoff == jiffies ? 'H' : '.',
+ timer_pending(tltp) ? tltp->expires - jiffies : -1);
}
#else /* #ifdef CONFIG_RCU_FAST_NO_HZ */
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index ed459ed..d4bc16d 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -271,13 +271,13 @@
gpnum = rsp->gpnum;
seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x "
- "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n",
+ "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
rsp->completed, gpnum, rsp->fqs_state,
(long)(rsp->jiffies_force_qs - jiffies),
(int)(jiffies & 0xffff),
rsp->n_force_qs, rsp->n_force_qs_ngp,
rsp->n_force_qs - rsp->n_force_qs_ngp,
- rsp->n_force_qs_lh);
+ rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen);
for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
if (rnp->level != level) {
seq_puts(m, "\n");
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 56b2b86..faeb4b7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5507,7 +5507,6 @@
unsigned long action, void *hcpu)
{
switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_STARTING:
case CPU_DOWN_FAILED:
set_cpu_active((long)hcpu, true);
return NOTIFY_OK;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index c6cd85b..0f30374 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -280,6 +280,7 @@
static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
{
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
+ unsigned long rcu_delta_jiffies;
ktime_t last_update, expires, now;
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
u64 time_delta;
@@ -328,7 +329,7 @@
time_delta = timekeeping_max_deferment();
} while (read_seqretry(&xtime_lock, seq));
- if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
+ if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) ||
arch_needs_cpu(cpu)) {
next_jiffies = last_jiffies + 1;
delta_jiffies = 1;
@@ -336,6 +337,10 @@
/* Get the next timer wheel timer */
next_jiffies = get_next_timer_interrupt(last_jiffies);
delta_jiffies = next_jiffies - last_jiffies;
+ if (rcu_delta_jiffies < delta_jiffies) {
+ next_jiffies = last_jiffies + rcu_delta_jiffies;
+ delta_jiffies = rcu_delta_jiffies;
+ }
}
/*
* Do not stop the tick, if we are only one off
diff --git a/kernel/timer.c b/kernel/timer.c
index cf7217a..a851025 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -862,7 +862,13 @@
*
* mod_timer_pinned() is a way to update the expire field of an
* active timer (if the timer is inactive it will be activated)
- * and not allow the timer to be migrated to a different CPU.
+ * and to ensure that the timer is scheduled on the current CPU.
+ *
+ * Note that this does not prevent the timer from being migrated
+ * when the current CPU goes offline. If this is a problem for
+ * you, use CPU-hotplug notifiers to handle it correctly, for
+ * example, cancelling the timer when the corresponding CPU goes
+ * offline.
*
* mod_timer_pinned(timer, expires) is equivalent to:
*
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 08b5ae7..0b3c622 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1287,18 +1287,16 @@
break;
case FORMAT_TYPE_NRCHARS: {
- u8 qualifier = spec.qualifier;
+ /*
+ * Since %n poses a greater security risk than
+ * utility, ignore %n and skip its argument.
+ */
+ void *skip_arg;
- if (qualifier == 'l') {
- long *ip = va_arg(args, long *);
- *ip = (str - buf);
- } else if (_tolower(qualifier) == 'z') {
- size_t *ip = va_arg(args, size_t *);
- *ip = (str - buf);
- } else {
- int *ip = va_arg(args, int *);
- *ip = (str - buf);
- }
+ WARN_ONCE(1, "Please remove ignored %%n in '%s'\n",
+ old_fmt);
+
+ skip_arg = va_arg(args, void *);
break;
}
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 6d6d7d2..452fa86 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -691,11 +691,13 @@
static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
{
- struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+ struct ethtool_wolinfo wol;
if (!dev->ethtool_ops->get_wol)
return -EOPNOTSUPP;
+ memset(&wol, 0, sizeof(struct ethtool_wolinfo));
+ wol.cmd = ETHTOOL_GWOL;
dev->ethtool_ops->get_wol(dev, &wol);
if (copy_to_user(useraddr, &wol, sizeof(wol)))
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index cada6a7..348df4d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2550,16 +2550,17 @@
list_for_each_entry_rcu(fa, &li->falh, fa_list) {
const struct fib_info *fi = fa->fa_info;
unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
- int len;
if (fa->fa_type == RTN_BROADCAST
|| fa->fa_type == RTN_MULTICAST)
continue;
+ seq_setwidth(seq, 127);
+
if (fi)
seq_printf(seq,
"%s\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u%n",
+ "%d\t%08X\t%d\t%u\t%u",
fi->fib_dev ? fi->fib_dev->name : "*",
prefix,
fi->fib_nh->nh_gw, flags, 0, 0,
@@ -2568,15 +2569,15 @@
(fi->fib_advmss ?
fi->fib_advmss + 40 : 0),
fi->fib_window,
- fi->fib_rtt >> 3, &len);
+ fi->fib_rtt >> 3);
else
seq_printf(seq,
"*\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u%n",
+ "%d\t%08X\t%d\t%u\t%u",
prefix, 0, flags, 0, 0, 0,
- mask, 0, 0, 0, &len);
+ mask, 0, 0, 0);
- seq_printf(seq, "%*s\n", 127 - len, "");
+ seq_pad(seq, '\n');
}
}
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 8e64f2f..5f2ee64 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -1078,7 +1078,7 @@
}
static void ping_format_sock(struct sock *sp, struct seq_file *f,
- int bucket, int *len)
+ int bucket)
{
struct inet_sock *inet = inet_sk(sp);
__be32 dest = inet->inet_daddr;
@@ -1087,29 +1087,28 @@
__u16 srcp = ntohs(inet->inet_sport);
seq_printf(f, "%5d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- atomic_read(&sp->sk_drops), len);
+ atomic_read(&sp->sk_drops));
}
static int ping_seq_show(struct seq_file *seq, void *v)
{
+ seq_setwidth(seq, 127);
if (v == SEQ_START_TOKEN)
- seq_printf(seq, "%-127s\n",
- " sl local_address rem_address st tx_queue "
+ seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode ref pointer drops");
else {
struct ping_iter_state *state = seq->private;
- int len;
- ping_format_sock(v, seq, state->bucket, &len);
- seq_printf(seq, "%*s\n", 127 - len, "");
+ ping_format_sock(v, seq, state->bucket);
}
+ seq_pad(seq, '\n');
return 0;
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0cb86ce..54225b1 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2398,13 +2398,13 @@
EXPORT_SYMBOL(tcp_proc_unregister);
static void get_openreq4(const struct sock *sk, const struct request_sock *req,
- struct seq_file *f, int i, int uid, int *len)
+ struct seq_file *f, int i, int uid)
{
const struct inet_request_sock *ireq = inet_rsk(req);
int ttd = req->expires - jiffies;
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK%n",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK",
i,
ireq->loc_addr,
ntohs(inet_sk(sk)->inet_sport),
@@ -2419,11 +2419,10 @@
0, /* non standard timer */
0, /* open_requests have no inode */
atomic_read(&sk->sk_refcnt),
- req,
- len);
+ req);
}
-static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
+static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
{
int timer_active;
unsigned long timer_expires;
@@ -2459,7 +2458,7 @@
rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
- "%08X %5d %8d %lu %d %pK %lu %lu %u %u %d%n",
+ "%08X %5d %8d %lu %d %pK %lu %lu %u %u %d",
i, src, srcp, dest, destp, sk->sk_state,
tp->write_seq - tp->snd_una,
rx_queue,
@@ -2474,12 +2473,12 @@
jiffies_to_clock_t(icsk->icsk_ack.ato),
(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
tp->snd_cwnd,
- tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh,
- len);
+ tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh);
+
}
static void get_timewait4_sock(const struct inet_timewait_sock *tw,
- struct seq_file *f, int i, int *len)
+ struct seq_file *f, int i)
{
__be32 dest, src;
__u16 destp, srcp;
@@ -2494,10 +2493,10 @@
srcp = ntohs(tw->tw_sport);
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK%n",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
- atomic_read(&tw->tw_refcnt), tw, len);
+ atomic_read(&tw->tw_refcnt), tw);
}
#define TMPSZ 150
@@ -2505,11 +2504,10 @@
static int tcp4_seq_show(struct seq_file *seq, void *v)
{
struct tcp_iter_state *st;
- int len;
+ seq_setwidth(seq, TMPSZ - 1);
if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "%-*s\n", TMPSZ - 1,
- " sl local_address rem_address st tx_queue "
+ seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode");
goto out;
@@ -2519,17 +2517,17 @@
switch (st->state) {
case TCP_SEQ_STATE_LISTENING:
case TCP_SEQ_STATE_ESTABLISHED:
- get_tcp4_sock(v, seq, st->num, &len);
+ get_tcp4_sock(v, seq, st->num);
break;
case TCP_SEQ_STATE_OPENREQ:
- get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len);
+ get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid);
break;
case TCP_SEQ_STATE_TIME_WAIT:
- get_timewait4_sock(v, seq, st->num, &len);
+ get_timewait4_sock(v, seq, st->num);
break;
}
- seq_printf(seq, "%*s\n", TMPSZ - 1 - len, "");
out:
+ seq_pad(seq, '\n');
return 0;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index fe14105..7c9e1ab 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2080,7 +2080,7 @@
/* ------------------------------------------------------------------------ */
static void udp4_format_sock(struct sock *sp, struct seq_file *f,
- int bucket, int *len)
+ int bucket)
{
struct inet_sock *inet = inet_sk(sp);
__be32 dest = inet->inet_daddr;
@@ -2089,29 +2089,28 @@
__u16 srcp = ntohs(inet->inet_sport);
seq_printf(f, "%5d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- atomic_read(&sp->sk_drops), len);
+ atomic_read(&sp->sk_drops));
}
int udp4_seq_show(struct seq_file *seq, void *v)
{
+ seq_setwidth(seq, 127);
if (v == SEQ_START_TOKEN)
- seq_printf(seq, "%-127s\n",
- " sl local_address rem_address st tx_queue "
+ seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode ref pointer drops");
else {
struct udp_iter_state *state = seq->private;
- int len;
- udp4_format_sock(v, seq, state->bucket, &len);
- seq_printf(seq, "%*s\n", 127 - len, "");
+ udp4_format_sock(v, seq, state->bucket);
}
+ seq_pad(seq, '\n');
return 0;
}
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 4c7eff3..0e3c6ec 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -598,25 +598,24 @@
static int pn_sock_seq_show(struct seq_file *seq, void *v)
{
- int len;
-
+ seq_setwidth(seq, 127);
if (v == SEQ_START_TOKEN)
- seq_printf(seq, "%s%n", "pt loc rem rs st tx_queue rx_queue "
- " uid inode ref pointer drops", &len);
+ seq_puts(seq, "pt loc rem rs st tx_queue rx_queue "
+ " uid inode ref pointer drops");
else {
struct sock *sk = v;
struct pn_sock *pn = pn_sk(sk);
seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu "
- "%d %pK %d%n",
+ "%d %pK %d",
sk->sk_protocol, pn->sobject, pn->dobject,
pn->resource, sk->sk_state,
sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
sock_i_uid(sk), sock_i_ino(sk),
atomic_read(&sk->sk_refcnt), sk,
- atomic_read(&sk->sk_drops), &len);
+ atomic_read(&sk->sk_drops));
}
- seq_printf(seq, "%*s\n", 127 - len, "");
+ seq_pad(seq, '\n');
return 0;
}
@@ -787,19 +786,19 @@
static int pn_res_seq_show(struct seq_file *seq, void *v)
{
- int len;
-
+ seq_setwidth(seq, 63);
if (v == SEQ_START_TOKEN)
- seq_printf(seq, "%s%n", "rs uid inode", &len);
+ seq_puts(seq, "rs uid inode");
else {
struct sock **psk = v;
struct sock *sk = *psk;
- seq_printf(seq, "%02X %5d %lu%n",
- (int) (psk - pnres.sk), sock_i_uid(sk),
- sock_i_ino(sk), &len);
+ seq_printf(seq, "%02X %5d %lu",
+ (int) (psk - pnres.sk),
+ from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
+ sock_i_ino(sk));
}
- seq_printf(seq, "%*s\n", 63 - len, "");
+ seq_pad(seq, '\n');
return 0;
}
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index 8ef8e7d..d1e259c 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -85,12 +85,13 @@
*/
static int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
{
- int i, len;
+ int i;
i = (int)*(loff_t *)v;
- seq_printf(seq, "%s: %d%n", sctp_dbg_objcnt[i].label,
- atomic_read(sctp_dbg_objcnt[i].counter), &len);
- seq_printf(seq, "%*s\n", 127 - len, "");
+ seq_setwidth(seq, 127);
+ seq_printf(seq, "%s: %d", sctp_dbg_objcnt[i].label,
+ atomic_read(sctp_dbg_objcnt[i].counter));
+ seq_pad(seq, '\n');
return 0;
}
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 6a77ffc..91591c7 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -7,6 +7,8 @@
(2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
# Channel 36 - 48
(5170 - 5250 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
+ (5250 - 5330 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
+ (5490 - 5710 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
# NB: 5260 MHz - 5700 MHz requies DFS
# Channel 149 - 165
(5735 - 5835 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index 675e378..c4c219c 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -657,14 +657,38 @@
}
EXPORT_SYMBOL(wcd9xxx_restore_registers);
+static void wcd9xxx_dynamic_bypass_buck_ctrl_lo(struct snd_soc_codec *cdc,
+ bool enable)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_BUCK_MODE_3, (0x1 << 3), (enable << 3)},
+ {WCD9XXX_A_BUCK_MODE_5, enable ? 0xFF : 0x02, 0x02},
+ {WCD9XXX_A_BUCK_MODE_5, 0x1, 0x01}
+ };
+
+ if (!enable) {
+ snd_soc_update_bits(cdc, WCD9XXX_A_BUCK_MODE_1,
+ (0x1 << 3), 0x00);
+ snd_soc_update_bits(cdc, WCD9XXX_A_BUCK_MODE_4,
+ 0xFF, BUCK_VREF_2V);
+ }
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(cdc, reg_set[i].reg, reg_set[i].mask,
+ reg_set[i].val);
+
+ /* 50us sleep is reqd. as per the class H HW design sequence */
+ usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US+10);
+}
+
static void wcd9xxx_dynamic_bypass_buck_ctrl(struct snd_soc_codec *cdc,
bool enable)
{
int i;
const struct wcd9xxx_reg_mask_val reg_set[] = {
{WCD9XXX_A_BUCK_MODE_3, (0x1 << 3), (enable << 3)},
- {WCD9XXX_A_BUCK_MODE_5, (0x1 << 1), (enable << 1)},
- {WCD9XXX_A_BUCK_MODE_5, 0x1, enable}
+ {WCD9XXX_A_BUCK_MODE_5, (0x1 << 1), ((!enable) << 1)},
+ {WCD9XXX_A_BUCK_MODE_5, 0x1, !enable}
};
if (!enable) {
snd_soc_update_bits(cdc, WCD9XXX_A_BUCK_MODE_1,
@@ -929,7 +953,7 @@
if (is_enable) {
if ((clsh_d->state == WCD9XXX_CLSH_STATE_LO) ||
(req_state == WCD9XXX_CLSH_STATE_LO)) {
- wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
+ wcd9xxx_dynamic_bypass_buck_ctrl_lo(codec, false);
wcd9xxx_enable_buck(codec, clsh_d, true);
wcd9xxx_set_fclk_get_ncp(codec, clsh_d,
NCP_FCLK_LEVEL_8);
@@ -951,7 +975,7 @@
case WCD9XXX_CLSH_STATE_LO:
snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
0x20, 0x00);
- wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
+ wcd9xxx_dynamic_bypass_buck_ctrl_lo(codec, true);
break;
case WCD9XXX_CLSH_STATE_HPHL:
wcd9xxx_clsh_comp_req(codec, clsh_d,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 9bd1652..a49866c 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -845,9 +845,9 @@
if (mbhc->micbias_enable && mbhc->micbias_enable_cb) {
pr_debug("%s: Disabling micbias\n", __func__);
+ mbhc->micbias_enable = false;
mbhc->micbias_enable_cb(mbhc->codec, false,
mbhc->mbhc_cfg->micbias);
- mbhc->micbias_enable = false;
}
mbhc->zl = mbhc->zr = 0;
pr_debug("%s: Reporting removal %d(%x)\n", __func__,
@@ -872,9 +872,9 @@
if (mbhc->micbias_enable && mbhc->micbias_enable_cb &&
mbhc->hph_status == SND_JACK_HEADSET) {
pr_debug("%s: Disabling micbias\n", __func__);
+ mbhc->micbias_enable = false;
mbhc->micbias_enable_cb(mbhc->codec, false,
mbhc->mbhc_cfg->micbias);
- mbhc->micbias_enable = false;
}
pr_debug("%s: Reporting removal (%x)\n",
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 774a33c..fc82215 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -2580,7 +2580,7 @@
goto afe_error;
}
- if (param[1] < 0 || param[1] > 100) {
+ if (param[1] > 100) {
pr_err("%s: Error, volume shoud be 0 to 100 percentage param = %lu\n",
__func__, param[1]);
rc = -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 4b9d079..9a3cb87 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -445,7 +445,7 @@
q6asm_add_hdr_custom_topology(ac, &asm_top.hdr,
APR_PKT_SIZE(APR_HDR_SIZE,
sizeof(asm_top)), TRUE);
- atomic_set(&ac->cmd_state, 1);
+ atomic_set(&ac->mem_state, 1);
asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES;
asm_top.payload_addr_lsw = cal_block.cal_paddr;
asm_top.payload_addr_msw = 0;
@@ -463,8 +463,8 @@
goto err_unmap;
}
- result = wait_event_timeout(ac->cmd_wait,
- (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ result = wait_event_timeout(ac->mem_wait,
+ (atomic_read(&ac->mem_state) == 0), 5*HZ);
if (!result) {
pr_err("%s: Set topologies failed after timedout payload = 0x%x\n",
__func__, cal_block.cal_paddr);
@@ -884,6 +884,7 @@
init_waitqueue_head(&ac->cmd_wait);
init_waitqueue_head(&ac->time_wait);
+ init_waitqueue_head(&ac->mem_wait);
atomic_set(&ac->time_flag, 1);
INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
@@ -895,6 +896,7 @@
}
atomic_set(&ac->cmd_state, 0);
atomic_set(&ac->nowait_cmd_cnt, 0);
+ atomic_set(&ac->mem_state, 0);
send_asm_custom_topology(ac);
@@ -1185,10 +1187,8 @@
atomic_set(&ac->unmap_cb_success, 1);
}
- if (atomic_read(&ac->cmd_state)) {
- atomic_set(&ac->cmd_state, 0);
- wake_up(&ac->cmd_wait);
- }
+ if (atomic_cmpxchg(&ac->mem_state, 1, 0))
+ wake_up(&ac->mem_wait);
pr_debug("%s:Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]);
break;
@@ -1208,10 +1208,9 @@
pr_debug("%s:PL#0[0x%x]PL#1 [0x%x] dir=%x s_id=%x\n",
__func__, payload[0], payload[1], dir, sid);
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
- if (atomic_read(&ac->cmd_state)) {
+ if (atomic_cmpxchg(&ac->mem_state, 1, 0)) {
ac->port[dir].tmp_hdl = payload[0];
- atomic_set(&ac->cmd_state, 0);
- wake_up(&ac->cmd_wait);
+ wake_up(&ac->mem_wait);
}
spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
break;
@@ -1220,10 +1219,8 @@
pr_debug("%s:PL#0[0x%x]PL#1 [0x%x]\n",
__func__, payload[0], payload[1]);
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
- if (atomic_read(&ac->cmd_state)) {
- atomic_set(&ac->cmd_state, 0);
- wake_up(&ac->cmd_wait);
- }
+ if (atomic_cmpxchg(&ac->mem_state, 1, 0))
+ wake_up(&ac->mem_wait);
spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
break;
@@ -1343,7 +1340,6 @@
case ASM_STREAM_CMD_OPEN_LOOPBACK_V2:
case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
- case ASM_CMD_ADD_TOPOLOGIES:
case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
@@ -1357,6 +1353,17 @@
ac->cb(data->opcode, data->token,
(uint32_t *)data->payload, ac->priv);
break;
+ case ASM_CMD_ADD_TOPOLOGIES:
+ pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
+ __func__, payload[0], payload[1]);
+ if (atomic_read(&ac->mem_state) && wakeup_flag) {
+ atomic_set(&ac->mem_state, 0);
+ wake_up(&ac->mem_wait);
+ }
+ if (ac->cb)
+ ac->cb(data->opcode, data->token,
+ (uint32_t *)data->payload, ac->priv);
+ break;
case ASM_STREAM_CMD_GET_PP_PARAMS_V2:
pr_debug("%s: ASM_STREAM_CMD_GET_PP_PARAMS_V2\n",
__func__);
@@ -3130,7 +3137,7 @@
mmap_region_cmd;
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size,
TRUE, ((ac->session << 8) | dir));
- atomic_set(&ac->cmd_state, 1);
+ atomic_set(&ac->mem_state, 1);
mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mmap_regions->num_regions = bufcnt & 0x00ff;
@@ -3157,8 +3164,8 @@
goto fail_cmd;
}
- rc = wait_event_timeout(ac->cmd_wait,
- (atomic_read(&ac->cmd_state) == 0 &&
+ rc = wait_event_timeout(ac->mem_wait,
+ (atomic_read(&ac->mem_state) == 0 &&
ac->port[dir].tmp_hdl), 5*HZ);
if (!rc) {
pr_err("timeout. waited for memory_map\n");
@@ -3194,7 +3201,7 @@
q6asm_add_mmaphdr(ac, &mem_unmap.hdr,
sizeof(struct avs_cmd_shared_mem_unmap_regions),
TRUE, ((ac->session << 8) | dir));
- atomic_set(&ac->cmd_state, 1);
+ atomic_set(&ac->mem_state, 1);
mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
mem_unmap.mem_map_handle = 0;
list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
@@ -3222,8 +3229,8 @@
goto fail_cmd;
}
- rc = wait_event_timeout(ac->cmd_wait,
- (atomic_read(&ac->cmd_state) == 0), 5 * HZ);
+ rc = wait_event_timeout(ac->mem_wait,
+ (atomic_read(&ac->mem_state) == 0), 5 * HZ);
if (!rc) {
pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
__func__, mem_unmap.mem_map_handle);
@@ -3305,7 +3312,7 @@
mmap_region_cmd;
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, TRUE,
((ac->session << 8) | dir));
- atomic_set(&ac->cmd_state, 1);
+ atomic_set(&ac->mem_state, 1);
pr_debug("mmap_region=0x%p token=0x%x\n",
mmap_regions, ((ac->session << 8) | dir));
@@ -3338,8 +3345,8 @@
goto fail_cmd;
}
- rc = wait_event_timeout(ac->cmd_wait,
- (atomic_read(&ac->cmd_state) == 0)
+ rc = wait_event_timeout(ac->mem_wait,
+ (atomic_read(&ac->mem_state) == 0)
, 5*HZ);
if (!rc) {
pr_err("timeout. waited for memory_map\n");
@@ -3387,7 +3394,7 @@
cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
q6asm_add_mmaphdr(ac, &mem_unmap.hdr, cmd_size,
TRUE, ((ac->session << 8) | dir));
- atomic_set(&ac->cmd_state, 1);
+ atomic_set(&ac->mem_state, 1);
port = &ac->port[dir];
buf_add = (uint32_t)port->buf->phys;
mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
@@ -3417,8 +3424,8 @@
goto fail_cmd;
}
- rc = wait_event_timeout(ac->cmd_wait,
- (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ rc = wait_event_timeout(ac->mem_wait,
+ (atomic_read(&ac->mem_state) == 0), 5*HZ);
if (!rc) {
pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
__func__, mem_unmap.mem_map_handle);
@@ -4650,6 +4657,7 @@
common_client.port[1].buf = &common_buf[1];
init_waitqueue_head(&common_client.cmd_wait);
init_waitqueue_head(&common_client.time_wait);
+ init_waitqueue_head(&common_client.mem_wait);
atomic_set(&common_client.time_flag, 1);
INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
@@ -4660,6 +4668,7 @@
}
atomic_set(&common_client.cmd_state, 0);
atomic_set(&common_client.nowait_cmd_cnt, 0);
+ atomic_set(&common_client.mem_state, 0);
config_debug_fs_init();