summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/rpm-smd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/rpm-smd.c')
-rw-r--r--drivers/soc/qcom/rpm-smd.c518
1 files changed, 409 insertions, 109 deletions
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index b1fa57da7241..fdff6f2140a3 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -25,6 +25,7 @@
#include <linux/irq.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/of_address.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/device.h>
@@ -88,6 +89,28 @@ static struct glink_apps_rpm_data *glink_data;
#define MAX_ERR_BUFFER_SIZE 128
#define MAX_WAIT_ON_ACK 24
#define INIT_ERROR 1
+#define V1_PROTOCOL_VERSION 0x31726576 /* rev1 */
+#define V0_PROTOCOL_VERSION 0 /* rev0 */
+#define RPM_MSG_TYPE_OFFSET 16
+#define RPM_MSG_TYPE_SIZE 8
+#define RPM_SET_TYPE_OFFSET 28
+#define RPM_SET_TYPE_SIZE 4
+#define RPM_REQ_LEN_OFFSET 0
+#define RPM_REQ_LEN_SIZE 16
+#define RPM_MSG_VERSION_OFFSET 24
+#define RPM_MSG_VERSION_SIZE 8
+#define RPM_MSG_VERSION 1
+#define RPM_MSG_SET_OFFSET 28
+#define RPM_MSG_SET_SIZE 4
+#define RPM_RSC_ID_OFFSET 16
+#define RPM_RSC_ID_SIZE 12
+#define RPM_DATA_LEN_OFFSET 0
+#define RPM_DATA_LEN_SIZE 16
+#define RPM_HDR_SIZE ((rpm_msg_fmt_ver == RPM_MSG_V0_FMT) ?\
+ sizeof(struct rpm_v0_hdr) : sizeof(struct rpm_v1_hdr))
+#define GET_FIELD(offset, size) (((1U << (offset + size)) - 1) - \
+ ((1U << offset) - 1))
+#define CLEAR_FIELD(offset, size) (~GET_FIELD(offset, size))
static ATOMIC_NOTIFIER_HEAD(msm_rpm_sleep_notifier);
static bool standalone;
@@ -111,17 +134,29 @@ enum {
MSM_RPM_MSG_TYPE_NR,
};
-static const uint32_t msm_rpm_request_service[MSM_RPM_MSG_TYPE_NR] = {
+static const uint32_t msm_rpm_request_service_v1[MSM_RPM_MSG_TYPE_NR] = {
0x716572, /* 'req\0' */
};
-/*the order of fields matter and reflect the order expected by the RPM*/
-struct rpm_request_header {
+enum {
+ RPM_V1_REQUEST_SERVICE,
+ RPM_V1_SYSTEMDB_SERVICE,
+ RPM_V1_COMMAND_SERVICE,
+ RPM_V1_ACK_SERVICE,
+ RPM_V1_NACK_SERVICE,
+} msm_rpm_request_service_v2;
+
+struct rpm_v0_hdr {
uint32_t service_type;
uint32_t request_len;
};
-struct rpm_message_header {
+struct rpm_v1_hdr {
+ uint32_t request_hdr;
+};
+
+struct rpm_message_header_v0 {
+ struct rpm_v0_hdr hdr;
uint32_t msg_id;
enum msm_rpm_set set;
uint32_t resource_type;
@@ -129,6 +164,26 @@ struct rpm_message_header {
uint32_t data_len;
};
+struct rpm_message_header_v1 {
+ struct rpm_v1_hdr hdr;
+ uint32_t msg_id;
+ uint32_t resource_type;
+ uint32_t request_details;
+};
+
+struct msm_rpm_ack_msg_v0 {
+ uint32_t req;
+ uint32_t req_len;
+ uint32_t rsc_id;
+ uint32_t msg_len;
+ uint32_t id_ack;
+};
+
+struct msm_rpm_ack_msg_v1 {
+ uint32_t request_hdr;
+ uint32_t id_ack;
+};
+
struct kvp {
unsigned int k;
unsigned int s;
@@ -147,49 +202,252 @@ struct slp_buf {
char *buf;
bool valid;
};
+
+enum rpm_msg_fmts {
+ RPM_MSG_V0_FMT,
+ RPM_MSG_V1_FMT
+};
+
+static uint32_t rpm_msg_fmt_ver;
+module_param_named(
+ rpm_msg_fmt_ver, rpm_msg_fmt_ver, uint, S_IRUGO
+);
+
static struct rb_root tr_root = RB_ROOT;
static int (*msm_rpm_send_buffer)(char *buf, uint32_t size, bool noirq);
static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq);
static int msm_rpm_glink_send_buffer(char *buf, uint32_t size, bool noirq);
static uint32_t msm_rpm_get_next_msg_id(void);
-static inline unsigned int get_rsc_type(char *buf)
+static inline uint32_t get_offset_value(uint32_t val, uint32_t offset,
+ uint32_t size)
{
- struct rpm_message_header *h;
- h = (struct rpm_message_header *)
- (buf + sizeof(struct rpm_request_header));
- return h->resource_type;
+ return (((val) & GET_FIELD(offset, size))
+ >> offset);
}
-static inline unsigned int get_rsc_id(char *buf)
+static inline void change_offset_value(uint32_t *val, uint32_t offset,
+ uint32_t size, int32_t val1)
{
- struct rpm_message_header *h;
- h = (struct rpm_message_header *)
- (buf + sizeof(struct rpm_request_header));
- return h->resource_id;
+ uint32_t member = *val;
+ uint32_t offset_val = get_offset_value(member, offset, size);
+ uint32_t mask = (1 << size) - 1;
+
+ offset_val += val1;
+ *val &= CLEAR_FIELD(offset, size);
+ *val |= ((offset_val & mask) << offset);
}
-#define get_data_len(buf) \
- (((struct rpm_message_header *) \
- (buf + sizeof(struct rpm_request_header)))->data_len)
+static inline void set_offset_value(uint32_t *val, uint32_t offset,
+ uint32_t size, uint32_t val1)
+{
+ uint32_t mask = (1 << size) - 1;
-#define get_req_len(buf) \
- (((struct rpm_request_header *)(buf))->request_len)
+ *val &= CLEAR_FIELD(offset, size);
+ *val |= ((val1 & mask) << offset);
+}
+static uint32_t get_msg_id(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->msg_id;
-#define get_msg_id(buf) \
- (((struct rpm_message_header *) \
- (buf + sizeof(struct rpm_request_header)))->msg_id)
+ return ((struct rpm_message_header_v1 *)buf)->msg_id;
+}
+
+static uint32_t get_ack_msg_id(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct msm_rpm_ack_msg_v0 *)buf)->id_ack;
+
+ return ((struct msm_rpm_ack_msg_v1 *)buf)->id_ack;
+
+}
+
+static uint32_t get_rsc_type(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->resource_type;
+
+ return ((struct rpm_message_header_v1 *)buf)->resource_type;
+
+}
+
+static uint32_t get_set_type(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->set;
+
+ return get_offset_value(((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_SET_TYPE_OFFSET,
+ RPM_SET_TYPE_SIZE);
+}
+
+static uint32_t get_data_len(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->data_len;
+
+ return get_offset_value(((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_DATA_LEN_OFFSET,
+ RPM_DATA_LEN_SIZE);
+}
+
+static uint32_t get_rsc_id(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->resource_id;
+
+ return get_offset_value(((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_RSC_ID_OFFSET,
+ RPM_RSC_ID_SIZE);
+}
+
+static uint32_t get_ack_req_len(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct msm_rpm_ack_msg_v0 *)buf)->req_len;
+
+ return get_offset_value(((struct msm_rpm_ack_msg_v1 *)buf)->
+ request_hdr, RPM_REQ_LEN_OFFSET,
+ RPM_REQ_LEN_SIZE);
+}
+
+static uint32_t get_ack_msg_type(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct msm_rpm_ack_msg_v0 *)buf)->req;
+
+ return get_offset_value(((struct msm_rpm_ack_msg_v1 *)buf)->
+ request_hdr, RPM_MSG_TYPE_OFFSET,
+ RPM_MSG_TYPE_SIZE);
+}
+
+static uint32_t get_req_len(char *buf)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return ((struct rpm_message_header_v0 *)buf)->hdr.request_len;
+
+ return get_offset_value(((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_REQ_LEN_OFFSET,
+ RPM_REQ_LEN_SIZE);
+}
+
+static void set_msg_ver(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver) {
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_MSG_VERSION_OFFSET,
+ RPM_MSG_VERSION_SIZE, val);
+ } else {
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_MSG_VERSION_OFFSET,
+ RPM_MSG_VERSION_SIZE, 0);
+ }
+}
+
+static void set_req_len(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) {
+ ((struct rpm_message_header_v0 *)buf)->hdr.request_len = val;
+ } else {
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_REQ_LEN_OFFSET,
+ RPM_REQ_LEN_SIZE, val);
+ }
+}
+
+static void change_req_len(char *buf, int32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) {
+ ((struct rpm_message_header_v0 *)buf)->hdr.request_len += val;
+ } else {
+ change_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_REQ_LEN_OFFSET,
+ RPM_REQ_LEN_SIZE, val);
+ }
+}
+
+static void set_msg_type(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) {
+ ((struct rpm_message_header_v0 *)buf)->hdr.service_type =
+ msm_rpm_request_service_v1[val];
+ } else {
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ hdr.request_hdr, RPM_MSG_TYPE_OFFSET,
+ RPM_MSG_TYPE_SIZE, RPM_V1_REQUEST_SERVICE);
+ }
+}
+
+static void set_rsc_id(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->resource_id = val;
+ else
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_RSC_ID_OFFSET,
+ RPM_RSC_ID_SIZE, val);
+}
+
+static void set_data_len(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->data_len = val;
+ else
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_DATA_LEN_OFFSET,
+ RPM_DATA_LEN_SIZE, val);
+}
+static void change_data_len(char *buf, int32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->data_len += val;
+ else
+ change_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_DATA_LEN_OFFSET,
+ RPM_DATA_LEN_SIZE, val);
+}
+
+static void set_set_type(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->set = val;
+ else
+ set_offset_value(&((struct rpm_message_header_v1 *)buf)->
+ request_details, RPM_SET_TYPE_OFFSET,
+ RPM_SET_TYPE_SIZE, val);
+}
+static void set_msg_id(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->msg_id = val;
+ else
+ ((struct rpm_message_header_v1 *)buf)->msg_id = val;
+
+}
+
+static void set_rsc_type(char *buf, uint32_t val)
+{
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ ((struct rpm_message_header_v0 *)buf)->resource_type = val;
+ else
+ ((struct rpm_message_header_v1 *)buf)->resource_type = val;
+}
static inline int get_buf_len(char *buf)
{
- return get_req_len(buf) + sizeof(struct rpm_request_header);
+ return get_req_len(buf) + RPM_HDR_SIZE;
}
static inline struct kvp *get_first_kvp(char *buf)
{
- return (struct kvp *)(buf + sizeof(struct rpm_request_header)
- + sizeof(struct rpm_message_header));
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ return (struct kvp *)(buf +
+ sizeof(struct rpm_message_header_v0));
+ else
+ return (struct kvp *)(buf +
+ sizeof(struct rpm_message_header_v1));
}
static inline struct kvp *get_next_kvp(struct kvp *k)
@@ -203,7 +461,7 @@ static inline void *get_data(struct kvp *k)
}
-static void delete_kvp(char *msg, struct kvp *d)
+static void delete_kvp(char *buf, struct kvp *d)
{
struct kvp *n;
int dec;
@@ -211,12 +469,13 @@ static void delete_kvp(char *msg, struct kvp *d)
n = get_next_kvp(d);
dec = (void *)n - (void *)d;
- size = get_data_len(msg) - ((void *)n - (void *)get_first_kvp(msg));
+ size = get_data_len(buf) -
+ ((void *)n - (void *)get_first_kvp(buf));
memcpy((void *)d, (void *)n, size);
- get_data_len(msg) -= dec;
- get_req_len(msg) -= dec;
+ change_data_len(buf, -dec);
+ change_req_len(buf, -dec);
}
static inline void update_kvp_data(struct kvp *dest, struct kvp *src)
@@ -226,20 +485,23 @@ static inline void update_kvp_data(struct kvp *dest, struct kvp *src)
static void add_kvp(char *buf, struct kvp *n)
{
- uint32_t inc = sizeof(*n) + n->s;
- BUG_ON((get_req_len(buf) + inc) > MAX_SLEEP_BUFFER);
+ int32_t inc = sizeof(*n) + n->s;
+
+ if (get_req_len(buf) + inc > MAX_SLEEP_BUFFER) {
+ WARN_ON(get_req_len(buf) + inc > MAX_SLEEP_BUFFER);
+ return;
+ }
memcpy(buf + get_buf_len(buf), n, inc);
- get_data_len(buf) += inc;
- get_req_len(buf) += inc;
+ change_data_len(buf, inc);
+ change_req_len(buf, inc);
}
static struct slp_buf *tr_search(struct rb_root *root, char *slp)
{
unsigned int type = get_rsc_type(slp);
unsigned int id = get_rsc_id(slp);
-
struct rb_node *node = root->rb_node;
while (node) {
@@ -265,7 +527,6 @@ static int tr_insert(struct rb_root *root, struct slp_buf *slp)
{
unsigned int type = get_rsc_type(slp->buf);
unsigned int id = get_rsc_id(slp->buf);
-
struct rb_node **node = &(root->rb_node), *parent = NULL;
while (*node) {
@@ -295,7 +556,8 @@ static int tr_insert(struct rb_root *root, struct slp_buf *slp)
#define for_each_kvp(buf, k) \
for (k = (struct kvp *)get_first_kvp(buf); \
- ((void *)k - (void *)get_first_kvp(buf)) < get_data_len(buf);\
+ ((void *)k - (void *)get_first_kvp(buf)) < \
+ get_data_len(buf);\
k = get_next_kvp(k))
@@ -333,8 +595,7 @@ static void tr_update(struct slp_buf *s, char *buf)
static atomic_t msm_rpm_msg_id = ATOMIC_INIT(0);
struct msm_rpm_request {
- struct rpm_request_header req_hdr;
- struct rpm_message_header msg_hdr;
+ uint8_t *client_buf;
struct msm_rpm_kvp_data *kvp;
uint32_t num_elements;
uint32_t write_idx;
@@ -357,13 +618,7 @@ struct msm_rpm_wait_data {
};
DEFINE_SPINLOCK(msm_rpm_list_lock);
-struct msm_rpm_ack_msg {
- uint32_t req;
- uint32_t req_len;
- uint32_t rsc_id;
- uint32_t msg_len;
- uint32_t id_ack;
-};
+
LIST_HEAD(msm_rpm_ack_list);
@@ -371,26 +626,37 @@ static struct tasklet_struct data_tasklet;
static inline uint32_t msm_rpm_get_msg_id_from_ack(uint8_t *buf)
{
- return ((struct msm_rpm_ack_msg *)buf)->id_ack;
+ return get_ack_msg_id(buf);
}
static inline int msm_rpm_get_error_from_ack(uint8_t *buf)
{
uint8_t *tmp;
- uint32_t req_len = ((struct msm_rpm_ack_msg *)buf)->req_len;
-
- struct msm_rpm_ack_msg *tmp_buf = (struct msm_rpm_ack_msg *)buf;
+ uint32_t req_len = get_ack_req_len(buf);
+ uint32_t msg_type = get_ack_msg_type(buf);
int rc = -ENODEV;
+ uint32_t err;
+ uint32_t ack_msg_size = rpm_msg_fmt_ver ?
+ sizeof(struct msm_rpm_ack_msg_v1) :
+ sizeof(struct msm_rpm_ack_msg_v0);
+
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT &&
+ msg_type == RPM_V1_ACK_SERVICE) {
+ return 0;
+ } else if (rpm_msg_fmt_ver && msg_type == RPM_V1_NACK_SERVICE) {
+ err = *(uint32_t *)(buf + sizeof(struct msm_rpm_ack_msg_v1));
+ return err;
+ }
- req_len -= sizeof(struct msm_rpm_ack_msg);
+ req_len -= ack_msg_size;
req_len += 2 * sizeof(uint32_t);
if (!req_len)
return 0;
pr_err("%s:rpm returned error or nack req_len: %d id_ack: %d\n",
- __func__, tmp_buf->req_len, tmp_buf->id_ack);
+ __func__, req_len, get_ack_msg_id(buf));
- tmp = buf + sizeof(struct msm_rpm_ack_msg);
+ tmp = buf + ack_msg_size;
if (memcmp(tmp, ERR, sizeof(uint32_t))) {
pr_err("%s rpm returned error\n", __func__);
@@ -440,9 +706,9 @@ int msm_rpm_smd_buffer_request(struct msm_rpm_request *cdata,
/* handle unsent requests */
tr_update(slp, buf);
}
- trace_rpm_smd_sleep_set(cdata->msg_hdr.msg_id,
- cdata->msg_hdr.resource_type,
- cdata->msg_hdr.resource_id);
+ trace_rpm_smd_sleep_set(get_msg_id(cdata->client_buf),
+ get_rsc_type(cdata->client_buf),
+ get_req_len(cdata->client_buf));
spin_unlock_irqrestore(&slp_buffer_lock, flags);
@@ -454,8 +720,9 @@ static void msm_rpm_print_sleep_buffer(struct slp_buf *s)
int pos;
int buflen = DEBUG_PRINT_BUFFER_SIZE;
char ch[5] = {0};
- u32 type;
struct kvp *e;
+ uint32_t type;
+ unsigned int id;
if (!s)
return;
@@ -464,13 +731,15 @@ static void msm_rpm_print_sleep_buffer(struct slp_buf *s)
return;
type = get_rsc_type(s->buf);
+ id = get_rsc_id(s->buf);
+
memcpy(ch, &type, sizeof(u32));
pos = scnprintf(buf, buflen,
"Sleep request type = 0x%08x(%s)",
- get_rsc_type(s->buf), ch);
+ type, ch);
pos += scnprintf(buf + pos, buflen - pos, " id = 0%x",
- get_rsc_id(s->buf));
+ id);
for_each_kvp(s->buf, e) {
uint32_t i;
char *data = get_data(e);
@@ -544,6 +813,8 @@ static int msm_rpm_flush_requests(bool print)
for (t = rb_first(&tr_root); t; t = rb_next(t)) {
struct slp_buf *s = rb_entry(t, struct slp_buf, node);
+ unsigned int type = get_rsc_type(s->buf);
+ unsigned int id = get_rsc_id(s->buf);
if (!s->valid)
continue;
@@ -551,7 +822,7 @@ static int msm_rpm_flush_requests(bool print)
if (print)
msm_rpm_print_sleep_buffer(s);
- get_msg_id(s->buf) = msm_rpm_get_next_msg_id();
+ set_msg_id(s->buf, msm_rpm_get_next_msg_id());
if (!glink_enabled)
ret = msm_rpm_send_smd_buffer(s->buf,
@@ -561,9 +832,7 @@ static int msm_rpm_flush_requests(bool print)
get_buf_len(s->buf), true);
WARN_ON(ret != get_buf_len(s->buf));
- trace_rpm_smd_send_sleep_set(get_msg_id(s->buf),
- get_rsc_type(s->buf),
- get_rsc_id(s->buf));
+ trace_rpm_smd_send_sleep_set(get_msg_id(s->buf), type, id);
s->valid = false;
count++;
@@ -587,13 +856,13 @@ static int msm_rpm_flush_requests(bool print)
return 0;
}
-static void msm_rpm_notify_sleep_chain(struct rpm_message_header *hdr,
+static void msm_rpm_notify_sleep_chain(char *buf,
struct msm_rpm_kvp_data *kvp)
{
struct msm_rpm_notifier_data notif;
- notif.rsc_type = hdr->resource_type;
- notif.rsc_id = hdr->resource_id;
+ notif.rsc_type = get_rsc_type(buf);
+ notif.rsc_id = get_req_len(buf);
notif.key = kvp->key;
notif.size = kvp->nbytes;
notif.value = kvp->value;
@@ -618,7 +887,7 @@ static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle,
return -EINVAL;
data_size = ALIGN(size, SZ_4);
- msg_size = data_size + sizeof(struct rpm_request_header);
+ msg_size = data_size + 8;
for (i = 0; i < handle->write_idx; i++) {
if (handle->kvp[i].key != key)
@@ -657,9 +926,10 @@ static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle,
}
if (!handle->kvp[i].valid)
- handle->msg_hdr.data_len += msg_size;
+ change_data_len(handle->client_buf, msg_size);
else
- handle->msg_hdr.data_len += (data_size - handle->kvp[i].nbytes);
+ change_data_len(handle->client_buf,
+ (data_size - handle->kvp[i].nbytes));
handle->kvp[i].nbytes = data_size;
handle->kvp[i].key = key;
@@ -675,6 +945,7 @@ static struct msm_rpm_request *msm_rpm_create_request_common(
int num_elements, bool noirq)
{
struct msm_rpm_request *cdata;
+ uint32_t buf_size;
if (probe_status)
return ERR_PTR(probe_status);
@@ -687,10 +958,19 @@ static struct msm_rpm_request *msm_rpm_create_request_common(
goto cdata_alloc_fail;
}
- cdata->msg_hdr.set = set;
- cdata->msg_hdr.resource_type = rsc_type;
- cdata->msg_hdr.resource_id = rsc_id;
- cdata->msg_hdr.data_len = 0;
+ if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT)
+ buf_size = sizeof(struct rpm_message_header_v0);
+ else
+ buf_size = sizeof(struct rpm_message_header_v1);
+
+ cdata->client_buf = kzalloc(buf_size, GFP_FLAG(noirq));
+
+ if (!cdata->client_buf)
+ goto cdata_alloc_fail;
+
+ set_set_type(cdata->client_buf, set);
+ set_rsc_type(cdata->client_buf, rsc_type);
+ set_rsc_id(cdata->client_buf, rsc_id);
cdata->num_elements = num_elements;
cdata->write_idx = 0;
@@ -730,6 +1010,7 @@ void msm_rpm_free_request(struct msm_rpm_request *handle)
for (i = 0; i < handle->num_elements; i++)
kfree(handle->kvp[i].value);
kfree(handle->kvp);
+ kfree(handle->client_buf);
kfree(handle->buf);
kfree(handle);
}
@@ -973,6 +1254,7 @@ static void msm_rpm_log_request(struct msm_rpm_request *cdata)
int j, prev_valid;
int valid_count = 0;
int pos = 0;
+ uint32_t res_type, rsc_id;
name[4] = 0;
@@ -983,18 +1265,20 @@ static void msm_rpm_log_request(struct msm_rpm_request *cdata)
pos += scnprintf(buf + pos, buflen - pos, "%sRPM req: ", KERN_INFO);
if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_SHOW_MSG_ID)
pos += scnprintf(buf + pos, buflen - pos, "msg_id=%u, ",
- cdata->msg_hdr.msg_id);
+ get_msg_id(cdata->client_buf));
pos += scnprintf(buf + pos, buflen - pos, "s=%s",
- (cdata->msg_hdr.set == MSM_RPM_CTX_ACTIVE_SET ? "act" : "slp"));
+ (get_set_type(cdata->client_buf) ==
+ MSM_RPM_CTX_ACTIVE_SET ? "act" : "slp"));
+ res_type = get_rsc_type(cdata->client_buf);
+ rsc_id = get_rsc_id(cdata->client_buf);
if ((msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY)
&& (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_RAW)) {
/* Both pretty and raw formatting */
- memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ memcpy(name, &res_type, sizeof(uint32_t));
pos += scnprintf(buf + pos, buflen - pos,
", rsc_type=0x%08X (%s), rsc_id=%u; ",
- cdata->msg_hdr.resource_type, name,
- cdata->msg_hdr.resource_id);
+ res_type, name, rsc_id);
for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
if (!cdata->kvp[i].valid)
@@ -1034,9 +1318,9 @@ static void msm_rpm_log_request(struct msm_rpm_request *cdata)
}
} else if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY) {
/* Pretty formatting only */
- memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ memcpy(name, &res_type, sizeof(uint32_t));
pos += scnprintf(buf + pos, buflen - pos, " %s %u; ", name,
- cdata->msg_hdr.resource_id);
+ rsc_id);
for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
if (!cdata->kvp[i].valid)
@@ -1065,9 +1349,7 @@ static void msm_rpm_log_request(struct msm_rpm_request *cdata)
} else {
/* Raw formatting only */
pos += scnprintf(buf + pos, buflen - pos,
- ", rsc_type=0x%08X, rsc_id=%u; ",
- cdata->msg_hdr.resource_type,
- cdata->msg_hdr.resource_id);
+ ", rsc_type=0x%08X, rsc_id=%u; ", res_type, rsc_id);
for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
if (!cdata->kvp[i].valid)
@@ -1169,21 +1451,25 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata,
int ret;
uint32_t i;
uint32_t msg_size;
- int req_hdr_sz, msg_hdr_sz;
+ int msg_hdr_sz, req_hdr_sz;
+ uint32_t data_len = get_data_len(cdata->client_buf);
+ uint32_t set = get_set_type(cdata->client_buf);
+ uint32_t msg_id;
if (probe_status)
return probe_status;
- if (!cdata->msg_hdr.data_len)
+ if (!data_len)
return 1;
- req_hdr_sz = sizeof(cdata->req_hdr);
- msg_hdr_sz = sizeof(cdata->msg_hdr);
+ msg_hdr_sz = rpm_msg_fmt_ver ? sizeof(struct rpm_message_header_v1) :
+ sizeof(struct rpm_message_header_v0);
- cdata->req_hdr.service_type = msm_rpm_request_service[msg_type];
+ req_hdr_sz = RPM_HDR_SIZE;
+ set_msg_type(cdata->client_buf, msg_type);
- cdata->req_hdr.request_len = cdata->msg_hdr.data_len + msg_hdr_sz;
- msg_size = cdata->req_hdr.request_len + req_hdr_sz;
+ set_req_len(cdata->client_buf, data_len + msg_hdr_sz - req_hdr_sz);
+ msg_size = get_req_len(cdata->client_buf) + req_hdr_sz;
/* populate data_len */
if (msg_size > cdata->numbytes) {
@@ -1199,8 +1485,7 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata,
tmpbuff = cdata->buf;
- tmpbuff += req_hdr_sz + msg_hdr_sz;
-
+ tmpbuff += msg_hdr_sz;
for (i = 0; (i < cdata->write_idx); i++) {
/* Sanity check */
BUG_ON((tmpbuff - cdata->buf) > cdata->numbytes);
@@ -1217,22 +1502,23 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata,
memcpy(tmpbuff, cdata->kvp[i].value, cdata->kvp[i].nbytes);
tmpbuff += cdata->kvp[i].nbytes;
- if (cdata->msg_hdr.set == MSM_RPM_CTX_SLEEP_SET)
- msm_rpm_notify_sleep_chain(&cdata->msg_hdr,
+ if (set == MSM_RPM_CTX_SLEEP_SET)
+ msm_rpm_notify_sleep_chain(cdata->client_buf,
&cdata->kvp[i]);
}
- memcpy(cdata->buf, &cdata->req_hdr, req_hdr_sz + msg_hdr_sz);
-
- if ((cdata->msg_hdr.set == MSM_RPM_CTX_SLEEP_SET) &&
+ memcpy(cdata->buf, cdata->client_buf, msg_hdr_sz);
+ if ((set == MSM_RPM_CTX_SLEEP_SET) &&
!msm_rpm_smd_buffer_request(cdata, msg_size,
GFP_FLAG(noirq)))
return 1;
- cdata->msg_hdr.msg_id = msm_rpm_get_next_msg_id();
-
- memcpy(cdata->buf + req_hdr_sz, &cdata->msg_hdr, msg_hdr_sz);
+ msg_id = msm_rpm_get_next_msg_id();
+ /* Set the version bit for new protocol */
+ set_msg_ver(cdata->buf, rpm_msg_fmt_ver);
+ set_msg_id(cdata->buf, msg_id);
+ set_msg_id(cdata->client_buf, msg_id);
if (msm_rpm_debug_mask
& (MSM_RPM_LOG_REQUEST_PRETTY | MSM_RPM_LOG_REQUEST_RAW))
@@ -1242,30 +1528,30 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata,
for (i = 0; (i < cdata->write_idx); i++)
cdata->kvp[i].valid = false;
- cdata->msg_hdr.data_len = 0;
- ret = cdata->msg_hdr.msg_id;
+ set_data_len(cdata->client_buf, 0);
+ ret = msg_id;
return ret;
}
if (!noack)
- msm_rpm_add_wait_list(cdata->msg_hdr.msg_id);
+ msm_rpm_add_wait_list(msg_id);
ret = msm_rpm_send_buffer(&cdata->buf[0], msg_size, noirq);
if (ret == msg_size) {
for (i = 0; (i < cdata->write_idx); i++)
cdata->kvp[i].valid = false;
- cdata->msg_hdr.data_len = 0;
- ret = cdata->msg_hdr.msg_id;
- trace_rpm_smd_send_active_set(cdata->msg_hdr.msg_id,
- cdata->msg_hdr.resource_type,
- cdata->msg_hdr.resource_id);
+ set_data_len(cdata->client_buf, 0);
+ ret = msg_id;
+ trace_rpm_smd_send_active_set(msg_id,
+ get_rsc_type(cdata->client_buf),
+ get_rsc_id(cdata->client_buf));
} else if (ret < msg_size) {
struct msm_rpm_wait_data *rc;
ret = 0;
pr_err("Failed to write data msg_size:%d ret:%d msg_id:%d\n",
- msg_size, ret, cdata->msg_hdr.msg_id);
- rc = msm_rpm_get_entry_from_msg_id(cdata->msg_hdr.msg_id);
+ msg_size, ret, msg_id);
+ rc = msm_rpm_get_entry_from_msg_id(msg_id);
if (rc)
msm_rpm_free_list_entry(rc);
}
@@ -1801,6 +2087,8 @@ static int msm_rpm_dev_probe(struct platform_device *pdev)
{
char *key = NULL;
int ret = 0;
+ void __iomem *reg_base;
+ uint32_t version = V0_PROTOCOL_VERSION; /* set to default v0 format */
/*
* Check for standalone support
@@ -1812,6 +2100,18 @@ static int msm_rpm_dev_probe(struct platform_device *pdev)
goto skip_init;
}
+ reg_base = of_iomap(pdev->dev.of_node, 0);
+
+ if (reg_base) {
+ version = readq_relaxed(reg_base);
+ iounmap(reg_base);
+ }
+
+ if (version == V1_PROTOCOL_VERSION)
+ rpm_msg_fmt_ver = RPM_MSG_V1_FMT;
+
+ pr_debug("RPM-SMD running version %d/n", rpm_msg_fmt_ver);
+
ret = msm_rpm_dev_glink_probe(pdev);
if (!ret) {
pr_info("APSS-RPM communication over GLINK\n");