Merge "msm: rpc: Fix uninitialized union in rpc router code"
diff --git a/Documentation/devicetree/bindings/qdsp/msm-adsp-sensors.txt b/Documentation/devicetree/bindings/qdsp/msm-adsp-sensors.txt
index ff0b1ef..4f1c10b 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-adsp-sensors.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-adsp-sensors.txt
@@ -3,17 +3,9 @@
Required properties:
- compatible: "qcom,msm-adsp-sensors"
- - qcom,src-id: Master port id
- - qcom,dst-id: Slave port id
- - qcom,ab: Arbitrated bandwidth in bytes/s
- - qcom,ib: Instantaneous bandwidth in bytes/s
Example:
qcom,msm-adsp-sensors {
compatible = "qcom,msm-adsp-sensors";
- qcom,src-id = <11>;
- qcom,dst-id = <604>;
- qcom,ab = <209715200>;
- qcom,ib = <471859200>;
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 8495276..f20c959 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -659,10 +659,6 @@
qcom,msm-adsp-sensors {
compatible = "qcom,msm-adsp-sensors";
- qcom,src-id = <11>;
- qcom,dst-id = <604>;
- qcom,ab = <32505856>;
- qcom,ib = <32505856>;
};
qcom,wdt@f9017000 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index eb77618..5faa75c 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -1910,10 +1910,6 @@
qcom,msm-adsp-sensors {
compatible = "qcom,msm-adsp-sensors";
- qcom,src-id = <11>;
- qcom,dst-id = <604>;
- qcom,ab = <32505856>;
- qcom,ib = <32505856>;
};
qcom,mss@fc880000 {
diff --git a/arch/arm/mach-msm/include/mach/sensors_adsp.h b/arch/arm/mach-msm/include/mach/sensors_adsp.h
deleted file mode 100644
index 3c65e37..0000000
--- a/arch/arm/mach-msm/include/mach/sensors_adsp.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (c) 2012, 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef SENSORS_ADSP_H
-#define SENSORS_ADSP_H
-
-#include <linux/types.h>
-
-/** Maximum number of segments that may be mapped from DDR to OCMEM */
-#define SNS_OCMEM_MAX_NUM_SEG_V01 16
-
-/** Maximum size of the ocmem_vectors structure */
-#define SNS_OCMEM_MAX_VECTORS_SIZE_V01 512
-
-/* Sensor OCMEM message id */
-
-#define SNS_OCMEM_CANCEL_REQ_V01 0x0000
-#define SNS_OCMEM_CANCEL_RESP_V01 0x0000
-#define SNS_OCMEM_VERSION_REQ_V01 0x0001
-#define SNS_OCMEM_VERSION_RESP_V01 0x0001
-#define SNS_OCMEM_PHYS_ADDR_REQ_V01 0x0002
-#define SNS_OCMEM_PHYS_ADDR_RESP_V01 0x0002
-#define SNS_OCMEM_HAS_CLIENT_IND_V01 0x0002
-#define SNS_OCMEM_BW_VOTE_REQ_V01 0x0003
-#define SNS_OCMEM_BW_VOTE_RESP_V01 0x0003
-#define SNS_OCMEM_BW_VOTE_IND_V01 0x0003
-
-enum {
- SNS_OCMEM_MODULE_KERNEL = 0,
- SNS_OCMEM_MODULE_ADSP
-};
-
-/**
- * Defines the types of response messages
- */
-enum {
- SNS_OCMEM_MSG_TYPE_REQ = 0, /* Request */
- SNS_OCMEM_MSG_TYPE_RESP, /* Response to a request */
- SNS_OCMEM_MSG_TYPE_IND /* Asynchronous indication */
-};
-
-/**
- * The message header. Used in both incoming and outgoing messages
- */
-struct sns_ocmem_hdr_s {
- int32_t msg_id ; /* Message ID, as defined in the IDL */
- uint16_t msg_size; /* Size of message, in bytes */
- uint8_t dst_module; /* Destination module */
- uint8_t src_module; /* Source module */
- uint8_t msg_type; /* The message type */
-} __packed;
-
-struct sns_ocmem_common_resp_s_v01 {
- /* This shall be the first element of every response message */
- uint8_t sns_result_t;
- /**< 0 == SUCCESS; 1 == FAILURE
- A result of FAILURE indicates that that any data contained in the
- response should not be used other than sns_err_t, to determine the
- type of error */
- uint8_t sns_err_t;
- /**< See sns_ocmem_error_e in ocmem_sensors.h */
-};
-
-/* This structure represents a single memory region that must be
-mapped from DDR to OCMEM */
-struct sns_mem_segment_s_v01 {
-
- uint64_t start_address; /* Physical start address of segment */
- uint32_t size; /* Size (in bytes) of this segment */
- uint16_t type; /* 1 == Read only; 2 == Read/Write Data */
-} __packed;
-
-struct sns_ocmem_phys_addr_resp_msg_v01 {
- struct sns_ocmem_common_resp_s_v01 resp; /* response */
- uint32_t segments_len; /* number of elements in segments */
- /* Segments mapped from DDR to OCMEM */
- struct sns_mem_segment_s_v01 segments[SNS_OCMEM_MAX_NUM_SEG_V01];
- uint8_t segments_valid; /* true if segments is being passed */
-} __packed ;
-
-struct sns_ocmem_has_client_ind_msg_v01 {
- uint16_t num_clients; /* Number of active clients on the ADSP */
-} __packed;
-
-struct sns_ocmem_bw_vote_req_msg_v01 {
- uint8_t is_map; /* True if mapping; false if unmapping */
- uint8_t vectors_valid; /* True if vectors is being passed */
- uint32_t vectors_len; /* Number of elements in vectors */
- uint8_t vectors[SNS_OCMEM_MAX_VECTORS_SIZE_V01]; /* vectors */
-} __packed;
-
-struct sns_ocmem_bw_vote_resp_msg_v01 {
- struct sns_ocmem_common_resp_s_v01 resp;
-};
-
-struct sns_ocmem_bw_vote_ind_msg_v01 {
- /* If the ADSP just voted for, or took away its vote for
- OCMEM bandwidth */
- uint8_t is_vote_on;
-} __packed;
-
-#endif /* SENSORS_ADSP_H */
diff --git a/arch/arm/mach-msm/sensors_adsp.c b/arch/arm/mach-msm/sensors_adsp.c
index ad19e16..80fe32f 100644
--- a/arch/arm/mach-msm/sensors_adsp.c
+++ b/arch/arm/mach-msm/sensors_adsp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 2015 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
@@ -10,1019 +10,30 @@
* GNU General Public License for more details.
*/
-#include <linux/workqueue.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/notifier.h>
-#include <linux/slab.h>
+#include <linux/msm_dsps.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/ctype.h>
#include <linux/of_device.h>
-#include <linux/msm_dsps.h>
-#include <linux/uaccess.h>
-#include <asm/mach-types.h>
#include <asm/arch_timer.h>
-#include <mach/subsystem_restart.h>
-#include <mach/ocmem.h>
-#include <mach/msm_smd.h>
-#include <mach/sensors_adsp.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
+#include <linux/uaccess.h>
#define CLASS_NAME "ssc"
#define DRV_NAME "sensors"
-#define DRV_VERSION "1.00"
+#define DRV_VERSION "2.00"
-#define SNS_OCMEM_SMD_CHANNEL "SENSOR"
-#define SNS_OCMEM_CLIENT_ID OCMEM_SENSORS
-#define SNS_OCMEM_SIZE SZ_256K
-#define SMD_BUF_SIZE 1024
-#define SNS_TIMEOUT_MS 1000
-
-#define SNS_OCMEM_ALLOC_GROW 0x00000001
-#define SNS_OCMEM_ALLOC_SHRINK 0x00000002
-#define SNS_OCMEM_MAP_DONE 0x00000004
-#define SNS_OCMEM_MAP_FAIL 0x00000008
-#define SNS_OCMEM_UNMAP_DONE 0x00000010
-#define SNS_OCMEM_UNMAP_FAIL 0x00000020
-
-#define DSPS_HAS_CLIENT 0x00000100
-#define DSPS_HAS_NO_CLIENT 0x00000200
-#define DSPS_BW_VOTE_ON 0x00000400
-#define DSPS_BW_VOTE_OFF 0x00000800
-#define DSPS_PHYS_ADDR_SET 0x00001000
-
-/*
- * Structure contains all state used by the sensors driver
- */
struct sns_adsp_control_s {
- wait_queue_head_t sns_wait;
- spinlock_t sns_lock;
- struct workqueue_struct *sns_workqueue;
- struct work_struct sns_work;
- struct workqueue_struct *smd_wq;
- struct work_struct smd_read_work;
- smd_channel_t *smd_ch;
- uint32_t sns_ocmem_status;
- uint32_t mem_segments_size;
- struct sns_mem_segment_s_v01 mem_segments[SNS_OCMEM_MAX_NUM_SEG_V01];
- struct ocmem_buf *buf;
- struct ocmem_map_list map_list;
- struct ocmem_notifier *ocmem_handle;
- bool ocmem_enabled;
- struct notifier_block ocmem_nb;
- uint32_t sns_ocmem_bus_client;
- struct platform_device *pdev;
- void *pil;
struct class *dev_class;
dev_t dev_num;
struct device *dev;
struct cdev *cdev;
};
-
static struct sns_adsp_control_s sns_ctl;
/*
- * All asynchronous responses from the OCMEM driver are received
- * by this function
- */
-int sns_ocmem_drv_cb(struct notifier_block *self,
- unsigned long action,
- void *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
-
- pr_debug("%s: Received OCMEM callback: action=%li\n",
- __func__, action);
-
- switch (action) {
- case OCMEM_MAP_DONE:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_MAP_DONE;
- sns_ctl.sns_ocmem_status &= (~OCMEM_MAP_FAIL &
- ~SNS_OCMEM_UNMAP_DONE &
- ~SNS_OCMEM_UNMAP_FAIL);
- break;
- case OCMEM_MAP_FAIL:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_MAP_FAIL;
- sns_ctl.sns_ocmem_status &= (~OCMEM_MAP_DONE &
- ~SNS_OCMEM_UNMAP_DONE &
- ~SNS_OCMEM_UNMAP_FAIL);
- break;
- case OCMEM_UNMAP_DONE:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_UNMAP_DONE;
- sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_FAIL &
- ~SNS_OCMEM_MAP_DONE &
- ~OCMEM_MAP_FAIL);
- break;
- case OCMEM_UNMAP_FAIL:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_UNMAP_FAIL;
- sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_DONE &
- ~SNS_OCMEM_MAP_DONE &
- ~OCMEM_MAP_FAIL);
- break;
- case OCMEM_ALLOC_GROW:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_ALLOC_GROW;
- sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_SHRINK;
- break;
- case OCMEM_ALLOC_SHRINK:
- sns_ctl.sns_ocmem_status |= SNS_OCMEM_ALLOC_SHRINK;
- sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_GROW;
- break;
- default:
- pr_err("%s: Unknown action received in OCMEM callback %lu\n",
- __func__, action);
- break;
- }
-
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
- wake_up(&sns_ctl.sns_wait);
-
- return 0;
-}
-
-/*
- * Processes messages received through SMD from the ADSP
- *
- * @param hdr The message header
- * @param msg Message pointer
- *
- */
-void sns_ocmem_smd_process(struct sns_ocmem_hdr_s *hdr, void *msg)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
-
- pr_debug("%s: Received message from ADSP; id: %i type: %i (%08x)\n",
- __func__, hdr->msg_id, hdr->msg_type,
- sns_ctl.sns_ocmem_status);
-
- if (hdr->msg_id == SNS_OCMEM_PHYS_ADDR_RESP_V01 &&
- hdr->msg_type == SNS_OCMEM_MSG_TYPE_RESP) {
- struct sns_ocmem_phys_addr_resp_msg_v01 *msg_ptr =
- (struct sns_ocmem_phys_addr_resp_msg_v01 *)msg;
- pr_debug("%s: Received SNS_OCMEM_PHYS_ADDR_RESP_V01\n",
- __func__);
- pr_debug("%s: segments_valid=%d, segments_len=%d\n", __func__,
- msg_ptr->segments_valid, msg_ptr->segments_len);
-
- if (msg_ptr->segments_valid) {
- sns_ctl.mem_segments_size = msg_ptr->segments_len;
- memcpy(sns_ctl.mem_segments, msg_ptr->segments,
- sizeof(struct sns_mem_segment_s_v01) *
- msg_ptr->segments_len);
-
- sns_ctl.sns_ocmem_status |= DSPS_PHYS_ADDR_SET;
- } else {
- pr_err("%s: Received invalid segment list\n", __func__);
- }
- } else if (hdr->msg_id == SNS_OCMEM_HAS_CLIENT_IND_V01 &&
- hdr->msg_type == SNS_OCMEM_MSG_TYPE_IND) {
- struct sns_ocmem_has_client_ind_msg_v01 *msg_ptr =
- (struct sns_ocmem_has_client_ind_msg_v01 *)msg;
-
- pr_debug("%s: Received SNS_OCMEM_HAS_CLIENT_IND_V01\n",
- __func__);
- pr_debug("%s: ADSP has %i client(s)\n", __func__,
- msg_ptr->num_clients);
- if (msg_ptr->num_clients > 0) {
- sns_ctl.sns_ocmem_status |= DSPS_HAS_CLIENT;
- sns_ctl.sns_ocmem_status &= ~DSPS_HAS_NO_CLIENT;
- } else {
- sns_ctl.sns_ocmem_status |= DSPS_HAS_NO_CLIENT;
- sns_ctl.sns_ocmem_status &= ~DSPS_HAS_CLIENT;
- }
- } else if (hdr->msg_id == SNS_OCMEM_BW_VOTE_RESP_V01 &&
- hdr->msg_type == SNS_OCMEM_MSG_TYPE_RESP) {
- /* no need to handle this response msg, just return */
- pr_debug("%s: Received SNS_OCMEM_BW_VOTE_RESP_V01\n", __func__);
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
- return;
- } else if (hdr->msg_id == SNS_OCMEM_BW_VOTE_IND_V01 &&
- hdr->msg_type == SNS_OCMEM_MSG_TYPE_IND) {
- struct sns_ocmem_bw_vote_ind_msg_v01 *msg_ptr =
- (struct sns_ocmem_bw_vote_ind_msg_v01 *)msg;
- pr_debug("%s: Received BW_VOTE_IND_V01, is_vote_on=%d\n",
- __func__, msg_ptr->is_vote_on);
-
- if (msg_ptr->is_vote_on) {
- sns_ctl.sns_ocmem_status |= DSPS_BW_VOTE_ON;
- sns_ctl.sns_ocmem_status &= ~DSPS_BW_VOTE_OFF;
- } else {
- sns_ctl.sns_ocmem_status |= DSPS_BW_VOTE_OFF;
- sns_ctl.sns_ocmem_status &= ~DSPS_BW_VOTE_ON;
- }
- } else {
- pr_err("%s: Unknown message type received. id: %i; type: %i\n",
- __func__, hdr->msg_id, hdr->msg_type);
- }
-
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
-
- wake_up(&sns_ctl.sns_wait);
-}
-
-static void sns_ocmem_smd_read(struct work_struct *ws)
-{
- struct smd_channel *ch = sns_ctl.smd_ch;
- unsigned char *buf = NULL;
- int sz, len;
-
- for (;;) {
- sz = smd_cur_packet_size(ch);
- BUG_ON(sz > SMD_BUF_SIZE);
- len = smd_read_avail(ch);
- pr_debug("%s: sz=%d, len=%d\n", __func__, sz, len);
- if (len == 0 || len < sz)
- break;
- buf = kzalloc(SMD_BUF_SIZE, GFP_KERNEL);
- if (buf == NULL) {
- pr_err("%s: malloc failed", __func__);
- break;
- }
-
- if (smd_read(ch, buf, sz) != sz) {
- pr_err("%s: not enough data?!\n", __func__);
- kfree(buf);
- continue;
- }
-
- sns_ocmem_smd_process((struct sns_ocmem_hdr_s *)buf,
- (void *)((char *)buf +
- sizeof(struct sns_ocmem_hdr_s)));
-
- kfree(buf);
-
- }
-}
-
-/*
- * All SMD notifications and messages from Sensors on ADSP are
- * received by this function
- *
- */
-void sns_ocmem_smd_notify_data(void *data, unsigned int event)
-{
- if (event == SMD_EVENT_DATA) {
- int sz;
- pr_debug("%s: Received SMD event Data\n", __func__);
- sz = smd_cur_packet_size(sns_ctl.smd_ch);
- if ((sz > 0) && (sz <= smd_read_avail(sns_ctl.smd_ch)))
- queue_work(sns_ctl.smd_wq, &sns_ctl.smd_read_work);
- } else if (event == SMD_EVENT_OPEN) {
- pr_debug("%s: Received SMD event Open\n", __func__);
- } else if (event == SMD_EVENT_CLOSE) {
- pr_debug("%s: Received SMD event Close\n", __func__);
- }
-}
-
-static bool sns_ocmem_is_status_set(uint32_t sns_ocmem_status)
-{
- unsigned long flags;
- bool is_set;
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
- is_set = sns_ctl.sns_ocmem_status & sns_ocmem_status;
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
- return is_set;
-}
-
-/*
- * Wait for a response from ADSP or OCMEM Driver, timeout if necessary
- *
- * @param sns_ocmem_status Status flags to wait for.
- * @param timeout_sec Seconds to wait before timeout
- * @param timeout_nsec Nanoseconds to wait. Total timeout = nsec + sec
- *
- * @return 0 If any status flag is set at any time prior to a timeout.
- * 0 if success or timedout ; <0 for failures
- */
-static int sns_ocmem_wait(uint32_t sns_ocmem_status,
- uint32_t timeout_ms)
-{
- int err;
- if (timeout_ms) {
- err = wait_event_interruptible_timeout(sns_ctl.sns_wait,
- sns_ocmem_is_status_set(sns_ocmem_status),
- msecs_to_jiffies(timeout_ms));
-
- if (err == 0)
- pr_err("%s: interruptible_timeout timeout err=%i\n",
- __func__, err);
- else if (err < 0)
- pr_err("%s: interruptible_timeout failed err=%i\n",
- __func__, err);
- } else { /* no timeout */
- err = wait_event_interruptible(sns_ctl.sns_wait,
- sns_ocmem_is_status_set(sns_ocmem_status));
- if (err < 0)
- pr_err("%s: wait_event_interruptible failed err=%i\n",
- __func__, err);
- }
-
- return err;
-}
-
-/*
- * Sends a message to the ADSP via SMD.
- *
- * @param hdr Specifies message type and other meta data
- * @param msg_ptr Pointer to the message contents.
- * Must be freed within this function if no error is returned.
- *
- * @return 0 upon success; < 0 upon error
- */
-static int
-sns_ocmem_send_msg(struct sns_ocmem_hdr_s *hdr, void const *msg_ptr)
-{
- int rv = 0;
- int err = 0;
- void *temp = NULL;
- int size = sizeof(struct sns_ocmem_hdr_s) + hdr->msg_size;
-
- temp = kzalloc(sizeof(struct sns_ocmem_hdr_s) + hdr->msg_size,
- GFP_KERNEL);
- if (temp == NULL) {
- pr_err("%s: allocation failure\n", __func__);
- rv = -ENOMEM;
- goto out;
- }
-
- hdr->dst_module = SNS_OCMEM_MODULE_ADSP;
- hdr->src_module = SNS_OCMEM_MODULE_KERNEL;
-
- memcpy(temp, hdr, sizeof(struct sns_ocmem_hdr_s));
- memcpy((char *)temp + sizeof(struct sns_ocmem_hdr_s),
- msg_ptr, hdr->msg_size);
- pr_debug("%s: send msg type: %i size: %i id: %i dst: %i src: %i\n",
- __func__, hdr->msg_type, hdr->msg_size,
- hdr->msg_id, hdr->dst_module, hdr->src_module);
-
- if (hdr == NULL) {
- pr_err("%s: NULL message header\n", __func__);
- rv = -EINVAL;
- } else {
- if (sns_ctl.smd_ch == NULL) {
- pr_err("%s: null smd_ch\n", __func__);
- rv = -EINVAL;
- }
- err = smd_write(sns_ctl.smd_ch, temp, size);
- if (err < 0) {
- pr_err("%s: smd_write failed %i\n", __func__, err);
- rv = -ECOMM;
- } else {
- pr_debug("%s smd_write successful ret=%d\n",
- __func__, err);
- }
- }
-
- kfree(temp);
-
-out:
- return rv;
-}
-
-/*
- * Load ADSP Firmware.
- */
-
-static int sns_load_adsp(void)
-{
- sns_ctl.pil = subsystem_get("adsp");
- if (IS_ERR(sns_ctl.pil)) {
- pr_err("%s: fail to load ADSP firmware\n", __func__);
- return -ENODEV;
- }
-
- pr_debug("%s: Q6/ADSP image is loaded\n", __func__);
-
- return 0;
-}
-
-static int sns_ocmem_platform_data_populate(struct platform_device *pdev)
-{
- int ret;
- struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
- struct msm_bus_vectors *sns_ocmem_bus_vectors = NULL;
- struct msm_bus_paths *ocmem_sns_bus_paths = NULL;
- u32 val;
-
- if (!pdev->dev.of_node) {
- pr_err("%s: device tree information missing\n", __func__);
- return -ENODEV;
- }
-
- sns_ocmem_bus_vectors = kzalloc(sizeof(struct msm_bus_vectors),
- GFP_KERNEL);
- if (!sns_ocmem_bus_vectors) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- return -ENOMEM;
- }
-
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,src-id", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,src-id missing in DT node\n",
- __func__);
- goto fail1;
- }
- sns_ocmem_bus_vectors->src = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,dst-id", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,dst-id missing in DT node\n",
- __func__);
- goto fail1;
- }
- sns_ocmem_bus_vectors->dst = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,ab", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,ab missing in DT node\n",
- __func__);
- goto fail1;
- }
- sns_ocmem_bus_vectors->ab = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,ib", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,ib missing in DT node\n",
- __func__);
- goto fail1;
- }
- sns_ocmem_bus_vectors->ib = val;
- ocmem_sns_bus_paths = kzalloc(sizeof(struct msm_bus_paths),
- GFP_KERNEL);
-
- if (!ocmem_sns_bus_paths) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- goto fail1;
- }
- ocmem_sns_bus_paths->num_paths = 1;
- ocmem_sns_bus_paths->vectors = sns_ocmem_bus_vectors;
-
- sns_ocmem_bus_scale_pdata =
- kzalloc(sizeof(struct msm_bus_scale_pdata), GFP_KERNEL);
- if (!sns_ocmem_bus_scale_pdata) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- goto fail2;
- }
-
- sns_ocmem_bus_scale_pdata->usecase = ocmem_sns_bus_paths;
- sns_ocmem_bus_scale_pdata->num_usecases = 1;
- sns_ocmem_bus_scale_pdata->name = "sensors-ocmem";
-
- dev_set_drvdata(&pdev->dev, sns_ocmem_bus_scale_pdata);
- return ret;
-
-fail2:
- kfree(ocmem_sns_bus_paths);
-fail1:
- kfree(sns_ocmem_bus_vectors);
- return ret;
-}
-
-
-/*
- * Initialize all sensors ocmem driver data fields and register with the
- * ocmem driver.
- *
- * @return 0 upon success; < 0 upon error
- */
-static int sns_ocmem_init(void)
-{
- int i, err, ret;
- struct sns_ocmem_hdr_s addr_req_hdr;
- struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
-
- /* register from OCMEM callack */
- sns_ctl.ocmem_handle =
- ocmem_notifier_register(SNS_OCMEM_CLIENT_ID,
- &sns_ctl.ocmem_nb);
- if (sns_ctl.ocmem_handle == NULL) {
- pr_err("OCMEM notifier registration failed\n");
- return -EFAULT;
- }
-
- /* populate platform data */
- ret = sns_ocmem_platform_data_populate(sns_ctl.pdev);
- if (ret) {
- dev_err(&sns_ctl.pdev->dev,
- "%s: failed to populate platform data, rc = %d\n",
- __func__, ret);
- return -ENODEV;
- }
- sns_ocmem_bus_scale_pdata = dev_get_drvdata(&sns_ctl.pdev->dev);
-
- sns_ctl.sns_ocmem_bus_client =
- msm_bus_scale_register_client(sns_ocmem_bus_scale_pdata);
-
- if (!sns_ctl.sns_ocmem_bus_client) {
- pr_err("%s: msm_bus_scale_register_client() failed\n",
- __func__);
- return -EFAULT;
- }
-
- /* load ADSP first */
- if (sns_load_adsp() != 0) {
- pr_err("%s: sns_load_adsp failed\n", __func__);
- return -EFAULT;
- }
-
- /*
- * wait before open SMD channel from kernel to ensure
- * channel has been openned already from ADSP side
- */
- msleep(1000);
-
- err = smd_named_open_on_edge(SNS_OCMEM_SMD_CHANNEL,
- SMD_APPS_QDSP,
- &sns_ctl.smd_ch,
- NULL,
- sns_ocmem_smd_notify_data);
- if (err != 0) {
- pr_err("%s: smd_named_open_on_edge failed %i\n", __func__, err);
- return -EFAULT;
- }
-
- pr_debug("%s: SMD channel openned successfuly!\n", __func__);
- /* wait for the channel ready before writing data */
- msleep(1000);
- addr_req_hdr.msg_id = SNS_OCMEM_PHYS_ADDR_REQ_V01;
- addr_req_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
- addr_req_hdr.msg_size = 0;
-
- err = sns_ocmem_send_msg(&addr_req_hdr, NULL);
- if (err != 0) {
- pr_err("%s: sns_ocmem_send_msg failed %i\n", __func__, err);
- return -ECOMM;
- }
-
- err = sns_ocmem_wait(DSPS_PHYS_ADDR_SET, 0);
- if (err != 0) {
- pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
- return -EFAULT;
- }
-
- sns_ctl.map_list.num_chunks = sns_ctl.mem_segments_size;
- for (i = 0; i < sns_ctl.mem_segments_size; i++) {
- sns_ctl.map_list.chunks[i].ro =
- sns_ctl.mem_segments[i].type == 1 ? true : false;
- sns_ctl.map_list.chunks[i].ddr_paddr =
- sns_ctl.mem_segments[i].start_address;
- sns_ctl.map_list.chunks[i].size =
- sns_ctl.mem_segments[i].size;
-
- pr_debug("%s: chunks[%d]: ro=%d, ddr_paddr=0x%lx, size=%li",
- __func__, i,
- sns_ctl.map_list.chunks[i].ro,
- sns_ctl.map_list.chunks[i].ddr_paddr,
- sns_ctl.map_list.chunks[i].size);
- }
-
- return 0;
-}
-
-/*
- * Unmaps memory in ocmem back to DDR, indicates to the ADSP its completion,
- * and waits for it to finish removing its bandwidth vote.
- */
-static void sns_ocmem_unmap(void)
-{
- unsigned long flags;
- int err = 0;
-
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf, OCMEM_ON);
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
- sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_FAIL &
- ~SNS_OCMEM_UNMAP_DONE);
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
-
- err = ocmem_unmap(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf,
- &sns_ctl.map_list);
-
- if (err != 0) {
- pr_err("ocmem_unmap failed %i\n", err);
- } else {
- err = sns_ocmem_wait(SNS_OCMEM_UNMAP_DONE |
- SNS_OCMEM_UNMAP_FAIL, 0);
-
- if (err == 0) {
- if (sns_ocmem_is_status_set(SNS_OCMEM_UNMAP_DONE))
- pr_debug("%s: OCMEM_UNMAP_DONE\n", __func__);
- else if (sns_ocmem_is_status_set(
- SNS_OCMEM_UNMAP_FAIL)) {
- pr_err("%s: OCMEM_UNMAP_FAIL\n", __func__);
- BUG_ON(true);
- } else
- pr_err("%s: status flag not set\n", __func__);
- } else {
- pr_err("%s: sns_ocmem_wait failed %i\n",
- __func__, err);
- }
- }
-
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf, OCMEM_OFF);
-}
-
-/*
- * Waits for allocation to succeed. This may take considerable time if the device
- * is presently in a high-power use case.
- *
- * @return 0 on success; < 0 upon error
- */
-static int sns_ocmem_wait_for_alloc(void)
-{
- int err = 0;
-
- err = sns_ocmem_wait(SNS_OCMEM_ALLOC_GROW |
- DSPS_HAS_NO_CLIENT, 0);
-
- if (err == 0) {
- if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
- pr_debug("%s: Lost client while waiting for GROW\n",
- __func__);
- ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
- sns_ctl.buf = NULL;
- return -EPIPE;
- }
- } else {
- pr_err("sns_ocmem_wait failed %i\n", err);
- return -EFAULT;
- }
-
- return 0;
-}
-
-/*
- * Kicks-off the mapping of memory from DDR to ocmem. Waits for the process
- * to complete, then indicates so to the ADSP.
- *
- * @return 0: Success; < 0: Other error
- */
-static int sns_ocmem_map(void)
-{
- int err = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
- sns_ctl.sns_ocmem_status &=
- (~SNS_OCMEM_MAP_FAIL & ~SNS_OCMEM_MAP_DONE);
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
-
- /* vote for ocmem bus bandwidth */
- err = msm_bus_scale_client_update_request(
- sns_ctl.sns_ocmem_bus_client,
- 0);
- if (err)
- pr_err("%s: failed to vote for bus bandwidth\n", __func__);
-
- err = ocmem_map(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf,
- &sns_ctl.map_list);
-
- if (err != 0) {
- pr_debug("ocmem_map failed %i\n", err);
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf, OCMEM_OFF);
- ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
- sns_ctl.buf = NULL;
- } else {
- err = sns_ocmem_wait(SNS_OCMEM_ALLOC_SHRINK |
- DSPS_HAS_NO_CLIENT |
- SNS_OCMEM_MAP_DONE |
- SNS_OCMEM_MAP_FAIL, 0);
-
- if (err == 0) {
- if (sns_ocmem_is_status_set(SNS_OCMEM_MAP_DONE))
- pr_debug("%s: OCMEM mapping DONE\n", __func__);
- else if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
- pr_debug("%s: Lost client while waiting for MAP\n",
- __func__);
- sns_ocmem_unmap();
- ocmem_free(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf);
- sns_ctl.buf = NULL;
- err = -EPIPE;
- } else if (sns_ocmem_is_status_set(
- SNS_OCMEM_ALLOC_SHRINK)) {
- pr_debug("%s: SHRINK while wait for MAP\n",
- __func__);
- sns_ocmem_unmap();
- err = ocmem_shrink(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf, 0);
- BUG_ON(err != 0);
- err = -EFAULT;
- } else if (sns_ocmem_is_status_set(
- SNS_OCMEM_MAP_FAIL)) {
- pr_err("%s: OCMEM mapping fails\n", __func__);
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf,
- OCMEM_OFF);
- ocmem_free(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf);
- sns_ctl.buf = NULL;
- } else
- pr_err("%s: status flag not set\n", __func__);
- } else {
- pr_err("sns_ocmem_wait failed %i\n", err);
- }
- }
-
- return err;
-}
-
-/*
- * Allocates memory in ocmem and maps to it from DDR.
- *
- * @return 0 upon success; <0 upon failure;
- */
-static int sns_ocmem_alloc(void)
-{
- int err = 0;
- unsigned long flags;
-
- if (sns_ctl.buf == NULL) {
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
- sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_GROW &
- ~SNS_OCMEM_ALLOC_SHRINK;
- spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
- sns_ctl.buf = ocmem_allocate_nb(SNS_OCMEM_CLIENT_ID,
- SNS_OCMEM_SIZE);
-
- if (sns_ctl.buf == NULL) {
- pr_err("ocmem_allocate_nb returned NULL\n");
- sns_ctl.ocmem_enabled = false;
- err = -EFAULT;
- } else if (sns_ctl.buf->len != 0 &&
- SNS_OCMEM_SIZE > sns_ctl.buf->len) {
- pr_err("ocmem_allocate_nb: invalid len %li, Req: %i)\n",
- sns_ctl.buf->len, SNS_OCMEM_SIZE);
- sns_ctl.ocmem_enabled = false;
- err = -EFAULT;
- }
- }
-
- pr_debug("%s OCMEM buf=%lx, buffer len=%li\n", __func__,
- sns_ctl.buf->addr, sns_ctl.buf->len);
-
- while (sns_ctl.ocmem_enabled) {
- if (sns_ctl.buf->len == 0) {
- pr_debug("%s: Waiting for memory allocation\n",
- __func__);
- err = sns_ocmem_wait_for_alloc();
- if (err == -EPIPE) {
- pr_debug("%s:Lost client while wait for alloc\n",
- __func__);
- break;
- } else if (err != 0) {
- pr_err("sns_ocmem_wait_for_alloc failed %i\n",
- err);
- break;
- }
- }
-
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf,
- OCMEM_ON);
-
- err = sns_ocmem_map();
-
- if (err == -EPIPE) {
- pr_debug("%s: Lost client while waiting for mapping\n",
- __func__);
- break;
- } else if (err < 0) {
- pr_debug("%s: Mapping failed, will try again\n",
- __func__);
- break;
- } else if (err == 0) {
- pr_debug("%s: Mapping finished\n", __func__);
- break;
- }
- }
-
- return err;
-}
-
-/*
- * Indicate to the ADSP that unmapping has completed, and wait for the response
- * that its bandwidth vote has been removed.
- *
- * @return 0 Upon success; < 0 upon error
- */
-static int sns_ocmem_unmap_send(void)
-{
- int err;
- struct sns_ocmem_hdr_s msg_hdr;
- struct sns_ocmem_bw_vote_req_msg_v01 msg;
-
- memset(&msg, 0, sizeof(struct sns_ocmem_bw_vote_req_msg_v01));
-
- msg_hdr.msg_id = SNS_OCMEM_BW_VOTE_REQ_V01;
- msg_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
- msg_hdr.msg_size = sizeof(struct sns_ocmem_bw_vote_req_msg_v01);
- msg.is_map = 0;
- msg.vectors_valid = 0;
- msg.vectors_len = 0;
-
- pr_debug("%s: send bw_vote OFF\n", __func__);
- err = sns_ocmem_send_msg(&msg_hdr, &msg);
- if (err != 0) {
- pr_err("%s: sns_ocmem_send_msg failed %i\n",
- __func__, err);
- } else {
- err = sns_ocmem_wait(DSPS_BW_VOTE_OFF, 0);
- if (err != 0)
- pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
- }
-
- return err;
-}
-
-/*
- * Indicate to the ADSP that mapping has completed, and wait for the response
- * that its bandwidth vote has been made.
- *
- * @return 0 Upon success; < 0 upon error
- */
-static int sns_ocmem_map_send(void)
-{
- int err;
- struct sns_ocmem_hdr_s msg_hdr;
- struct sns_ocmem_bw_vote_req_msg_v01 msg;
- struct ocmem_vectors *vectors;
-
- memset(&msg, 0, sizeof(struct sns_ocmem_bw_vote_req_msg_v01));
-
- msg_hdr.msg_id = SNS_OCMEM_BW_VOTE_REQ_V01;
- msg_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
- msg_hdr.msg_size = sizeof(struct sns_ocmem_bw_vote_req_msg_v01);
- msg.is_map = 1;
-
- vectors = ocmem_get_vectors(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
- if ((vectors != NULL)) {
- memcpy(&msg.vectors, vectors, sizeof(*vectors));
- /* TODO: set vectors_len */
- msg.vectors_valid = true;
- msg.vectors_len = 0;
- }
-
- pr_debug("%s: send bw_vote ON\n", __func__);
- err = sns_ocmem_send_msg(&msg_hdr, &msg);
- if (err != 0) {
- pr_err("%s: sns_ocmem_send_msg failed %i\n", __func__, err);
- } else {
- err = sns_ocmem_wait(DSPS_BW_VOTE_ON |
- SNS_OCMEM_ALLOC_SHRINK, 0);
- if (err != 0)
- pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
- }
-
- return err;
-}
-
-/*
- * Perform the encessary operations to clean-up OCMEM after being notified that
- * there is no longer a client; if sensors was evicted; or if some error
- * has occurred.
- *
- * @param[i] do_free Whether the memory should be freed (true) or if shrink
- * should be called instead (false).
- */
-static void sns_ocmem_evicted(bool do_free)
-{
- int err = 0;
-
- sns_ocmem_unmap();
- if (do_free) {
- ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
- sns_ctl.buf = NULL;
- } else {
- err = ocmem_shrink(SNS_OCMEM_CLIENT_ID, sns_ctl.buf, 0);
- BUG_ON(err != 0);
- }
-
- err = sns_ocmem_unmap_send();
- if (err != 0)
- pr_err("sns_ocmem_unmap_send failed %i\n", err);
-}
-
-/*
- * After mapping has completed and the ADSP has reacted appropriately, wait
- * for a shrink command or word from the ADSP that it no longer has a client.
- *
- * @return 0 If no clients; < 0 upon error;
- */
-static int sns_ocmem_map_done(void)
-{
- int err = 0;
- unsigned long flags;
-
- err = sns_ocmem_map_send();
- if (err != 0) {
- pr_err("sns_ocmem_map_send failed %i\n", err);
- sns_ocmem_evicted(true);
- } else {
- ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
- sns_ctl.buf, OCMEM_OFF);
-
- pr_debug("%s: Waiting for shrink or 'no client' updates\n",
- __func__);
- err = sns_ocmem_wait(DSPS_HAS_NO_CLIENT |
- SNS_OCMEM_ALLOC_SHRINK, 0);
- if (err == 0) {
- if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
- pr_debug("%s: No longer have a client\n",
- __func__);
- sns_ocmem_evicted(true);
- } else if (sns_ocmem_is_status_set(
- SNS_OCMEM_ALLOC_SHRINK)) {
- pr_debug("%s: Received SHRINK\n", __func__);
- sns_ocmem_evicted(false);
-
- spin_lock_irqsave(&sns_ctl.sns_lock, flags);
- sns_ctl.sns_ocmem_status &=
- ~SNS_OCMEM_ALLOC_SHRINK;
- spin_unlock_irqrestore(&sns_ctl.sns_lock,
- flags);
- err = -EFAULT;
- }
- } else {
- pr_err("sns_ocmem_wait failed %i\n", err);
- }
- }
-
- return err;
-}
-
-/*
- * Main function.
- * Initializes sensors ocmem feature, and waits for an ADSP client.
- */
-static void sns_ocmem_main(struct work_struct *work)
-{
- int err = 0;
- pr_debug("%s\n", __func__);
-
- err = sns_ocmem_init();
- if (err != 0) {
- pr_err("%s: sns_ocmem_init failed %i\n", __func__, err);
- return;
- }
-
- while (true) {
- pr_debug("%s: Waiting for sensor client\n", __func__);
- if (sns_ocmem_is_status_set(DSPS_HAS_CLIENT) ||
- !sns_ocmem_wait(DSPS_HAS_CLIENT, 0)) {
- pr_debug("%s: DSPS_HAS_CLIENT\n", __func__);
-
- err = sns_ocmem_alloc();
- if (err != 0) {
- pr_err("sns_ocmem_alloc failed %i\n", err);
- return;
- } else {
- err = sns_ocmem_map_done();
- if (err != 0) {
- pr_err("sns_ocmem_map_done failed %i",
- err);
- return;
- }
- }
- }
- }
-
- ocmem_notifier_unregister(sns_ctl.ocmem_handle,
- &sns_ctl.ocmem_nb);
-}
-
-static int sensors_adsp_open(struct inode *ip, struct file *fp)
-{
- int ret = 0;
- return ret;
-}
-
-static int sensors_adsp_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-/*
* Read QTimer clock ticks and scale down to 32KHz clock as used
* in DSPS
*/
@@ -1044,9 +55,16 @@
return (u32)val;
}
-/*
- * IO Control - handle commands from client.
- */
+static int sensors_adsp_open(struct inode *ip, struct file *fp)
+{
+ return 0;
+}
+
+static int sensors_adsp_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
static long sensors_adsp_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -1067,19 +85,17 @@
return ret;
}
-/*
- * platform driver
- */
const struct file_operations sensors_adsp_fops = {
.owner = THIS_MODULE,
.open = sensors_adsp_open,
.release = sensors_adsp_release,
- .unlocked_ioctl = sensors_adsp_ioctl,
+ .unlocked_ioctl = sensors_adsp_ioctl
};
static int sensors_adsp_probe(struct platform_device *pdev)
{
int ret = 0;
+
sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME);
if (sns_ctl.dev_class == NULL) {
pr_err("%s: class_create fail.\n", __func__);
@@ -1114,38 +130,6 @@
goto cdev_add_err;
}
- sns_ctl.sns_workqueue =
- alloc_workqueue("sns_ocmem", WQ_NON_REENTRANT, 0);
- if (!sns_ctl.sns_workqueue) {
- pr_err("%s: Failed to create work queue\n",
- __func__);
- goto cdev_add_err;
- }
-
- sns_ctl.smd_wq =
- alloc_workqueue("smd_wq", WQ_NON_REENTRANT, 0);
- if (!sns_ctl.smd_wq) {
- pr_err("%s: Failed to create work queue\n",
- __func__);
- goto cdev_add_err;
- }
-
- init_waitqueue_head(&sns_ctl.sns_wait);
- spin_lock_init(&sns_ctl.sns_lock);
-
- sns_ctl.ocmem_handle = NULL;
- sns_ctl.buf = NULL;
- sns_ctl.sns_ocmem_status = 0;
- sns_ctl.ocmem_enabled = true;
- sns_ctl.ocmem_nb.notifier_call = sns_ocmem_drv_cb;
- sns_ctl.smd_ch = NULL;
- sns_ctl.pdev = pdev;
-
- INIT_WORK(&sns_ctl.sns_work, sns_ocmem_main);
- INIT_WORK(&sns_ctl.smd_read_work, sns_ocmem_smd_read);
-
- queue_work(sns_ctl.sns_workqueue, &sns_ctl.sns_work);
-
return 0;
cdev_add_err:
@@ -1162,20 +146,6 @@
static int sensors_adsp_remove(struct platform_device *pdev)
{
- struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
-
- sns_ocmem_bus_scale_pdata = (struct msm_bus_scale_pdata *)
- dev_get_drvdata(&pdev->dev);
-
- kfree(sns_ocmem_bus_scale_pdata->usecase->vectors);
- kfree(sns_ocmem_bus_scale_pdata->usecase);
- kfree(sns_ocmem_bus_scale_pdata);
-
- ocmem_notifier_unregister(sns_ctl.ocmem_handle,
- &sns_ctl.ocmem_nb);
- destroy_workqueue(sns_ctl.sns_workqueue);
- destroy_workqueue(sns_ctl.smd_wq);
-
cdev_del(sns_ctl.cdev);
kfree(sns_ctl.cdev);
sns_ctl.cdev = NULL;
@@ -1187,12 +157,10 @@
}
static const struct of_device_id msm_adsp_sensors_dt_match[] = {
- {.compatible = "qcom,msm-adsp-sensors"},
- {}
+ {.compatible = "qcom,msm-adsp-sensors"}
};
MODULE_DEVICE_TABLE(of, msm_adsp_sensors_dt_match);
-
static struct platform_driver sensors_adsp_driver = {
.driver = {
.name = "sensors-adsp",
@@ -1203,16 +171,12 @@
.remove = sensors_adsp_remove,
};
-/*
- * Module Init.
- */
-static int sensors_adsp_init(void)
+static int __init sensors_adsp_init(void)
{
int rc;
+
pr_debug("%s driver version %s.\n", DRV_NAME, DRV_VERSION);
-
rc = platform_driver_register(&sensors_adsp_driver);
-
if (rc) {
pr_err("%s: Failed to register sensors adsp driver\n",
__func__);
@@ -1222,16 +186,12 @@
return 0;
}
-/*
- * Module Exit.
- */
-static void sensors_adsp_exit(void)
+static void __exit sensors_adsp_exit(void)
{
platform_driver_unregister(&sensors_adsp_driver);
}
module_init(sensors_adsp_init);
module_exit(sensors_adsp_exit);
-
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Sensors ADSP driver");
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 28b066b..b25e033 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -1289,9 +1289,11 @@
* registered on the Apps Processor
*/
if (entry.cmd_code_lo == MODE_CMD &&
- entry.cmd_code_hi == MODE_CMD)
+ entry.cmd_code_hi == MODE_CMD &&
+ header->subsys_id == RESET_ID) {
if (entry.client_id != APPS_DATA)
continue;
+ }
ret = diag_send_dci_pkt(entry, buf, len,
req_entry->tag);
found = 1;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b29d81c..2ed6479 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -2086,15 +2086,20 @@
WCD9XXX_CLSH_STATE_LO,
WCD9XXX_CLSH_REQ_ENABLE,
WCD9XXX_CLSH_EVENT_POST_PA);
- dev_dbg(codec->dev, "%s: sleeping 3 ms after %s PA turn on\n",
+ dev_dbg(codec->dev, "%s: sleeping 5 ms after %s PA turn on\n",
__func__, w->name);
- usleep_range(3000, 3010);
+ /* Wait for CnP time after PA enable */
+ usleep_range(5000, 5100);
break;
case SND_SOC_DAPM_POST_PMD:
wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
WCD9XXX_CLSH_STATE_LO,
WCD9XXX_CLSH_REQ_DISABLE,
WCD9XXX_CLSH_EVENT_POST_PA);
+ dev_dbg(codec->dev, "%s: sleeping 5 ms after %s PA turn on\n",
+ __func__, w->name);
+ /* Wait for CnP time after PA disable */
+ usleep_range(5000, 5100);
break;
}
return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
index 5e4d9d3..2fc4949 100644
--- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -621,6 +621,11 @@
}
for (j = 0; j < eq->config.num_bands; j++) {
idx = *values++;
+ if (idx >= MAX_EQ_BANDS) {
+ pr_err("EQ_CONFIG:invalid band index\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
eq->per_band_cfg[idx].band_idx = idx;
eq->per_band_cfg[idx].filter_type = *values++;
eq->per_band_cfg[idx].freq_millihertz =