PageRenderTime 40ms CodeModel.GetById 20ms app.highlight 16ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/arm/mach-fsm/smd_rpcrouter_xdr.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase
C | 419 lines | 308 code | 87 blank | 24 comment | 41 complexity | 92fd812bac62b5f38017c5ce008f0ad3 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2 *
  3 * This program is free software; you can redistribute it and/or modify
  4 * it under the terms of the GNU General Public License version 2 and
  5 * only version 2 as published by the Free Software Foundation.
  6 *
  7 * This program is distributed in the hope that it will be useful,
  8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 10 * GNU General Public License for more details.
 11 *
 12 * You should have received a copy of the GNU General Public License
 13 * along with this program; if not, write to the Free Software
 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 15 * 02110-1301, USA.
 16 *
 17 */
 18
 19/*
 20 * SMD RPCROUTER XDR module.
 21 */
 22
 23#include <linux/types.h>
 24#include <linux/string.h>
 25#include <linux/kernel.h>
 26#include <linux/delay.h>
 27#include <linux/sched.h>
 28
 29#include <mach/msm_rpcrouter.h>
 30
 31int xdr_send_uint32(struct msm_rpc_xdr *xdr, const uint32_t *value)
 32{
 33	if ((xdr->out_index + sizeof(uint32_t)) > xdr->out_size) {
 34		pr_err("%s: xdr out buffer full\n", __func__);
 35		return -1;
 36	}
 37
 38	*(uint32_t *)(xdr->out_buf + xdr->out_index) = cpu_to_be32(*value);
 39	xdr->out_index += sizeof(uint32_t);
 40	return 0;
 41}
 42
 43int xdr_send_int8(struct msm_rpc_xdr *xdr, const int8_t *value)
 44{
 45	return xdr_send_uint32(xdr, (uint32_t *)value);
 46}
 47
 48int xdr_send_uint8(struct msm_rpc_xdr *xdr, const uint8_t *value)
 49{
 50	return xdr_send_uint32(xdr, (uint32_t *)value);
 51}
 52
 53int xdr_send_int16(struct msm_rpc_xdr *xdr, const int16_t *value)
 54{
 55	return xdr_send_uint32(xdr, (uint32_t *)value);
 56}
 57
 58int xdr_send_uint16(struct msm_rpc_xdr *xdr, const uint16_t *value)
 59{
 60	return xdr_send_uint32(xdr, (uint32_t *)value);
 61}
 62
 63int xdr_send_int32(struct msm_rpc_xdr *xdr, const int32_t *value)
 64{
 65	return xdr_send_uint32(xdr, (uint32_t *)value);
 66}
 67
 68int xdr_send_bytes(struct msm_rpc_xdr *xdr, const void **data,
 69		   uint32_t *size)
 70{
 71	void *buf = xdr->out_buf + xdr->out_index;
 72	uint32_t temp;
 73
 74	if (!size || !data || !*data)
 75		return -1;
 76
 77	temp = *size;
 78	if (temp & 0x3)
 79		temp += 4 - (temp & 0x3);
 80
 81	temp += sizeof(uint32_t);
 82	if ((xdr->out_index + temp) > xdr->out_size) {
 83		pr_err("%s: xdr out buffer full\n", __func__);
 84		return -1;
 85	}
 86
 87	*((uint32_t *)buf) = cpu_to_be32(*size);
 88	buf += sizeof(uint32_t);
 89	memcpy(buf, *data, *size);
 90	buf += *size;
 91	if (*size & 0x3) {
 92		memset(buf, 0, 4 - (*size & 0x3));
 93		buf += 4 - (*size & 0x3);
 94	}
 95
 96	xdr->out_index = buf - xdr->out_buf;
 97	return 0;
 98}
 99
100int xdr_recv_uint32(struct msm_rpc_xdr *xdr, uint32_t *value)
101{
102	if ((xdr->in_index + sizeof(uint32_t)) > xdr->in_size) {
103		pr_err("%s: xdr in buffer full\n", __func__);
104		return -1;
105	}
106
107	*value = be32_to_cpu(*(uint32_t *)(xdr->in_buf + xdr->in_index));
108	xdr->in_index += sizeof(uint32_t);
109	return 0;
110}
111
112int xdr_recv_int8(struct msm_rpc_xdr *xdr, int8_t *value)
113{
114	return xdr_recv_uint32(xdr, (uint32_t *)value);
115}
116
117int xdr_recv_uint8(struct msm_rpc_xdr *xdr, uint8_t *value)
118{
119	return xdr_recv_uint32(xdr, (uint32_t *)value);
120}
121
122int xdr_recv_int16(struct msm_rpc_xdr *xdr, int16_t *value)
123{
124	return xdr_recv_uint32(xdr, (uint32_t *)value);
125}
126
127int xdr_recv_uint16(struct msm_rpc_xdr *xdr, uint16_t *value)
128{
129	return xdr_recv_uint32(xdr, (uint32_t *)value);
130}
131
132int xdr_recv_int32(struct msm_rpc_xdr *xdr, int32_t *value)
133{
134	return xdr_recv_uint32(xdr, (uint32_t *)value);
135}
136
137int xdr_recv_bytes(struct msm_rpc_xdr *xdr, void **data,
138		   uint32_t *size)
139{
140	void *buf = xdr->in_buf + xdr->in_index;
141	uint32_t temp;
142
143	if (!size || !data)
144		return -1;
145
146	*size = be32_to_cpu(*(uint32_t *)buf);
147	buf += sizeof(uint32_t);
148
149	temp = *size;
150	if (temp & 0x3)
151		temp += 4 - (temp & 0x3);
152
153	temp += sizeof(uint32_t);
154	if ((xdr->in_index + temp) > xdr->in_size) {
155		pr_err("%s: xdr in buffer full\n", __func__);
156		return -1;
157	}
158
159	if (*size) {
160		*data = kmalloc(*size, GFP_KERNEL);
161		if (!*data)
162			return -1;
163
164		memcpy(*data, buf, *size);
165
166		buf += *size;
167		if (*size & 0x3)
168			buf += 4 - (*size & 0x3);
169	} else
170		*data = NULL;
171
172	xdr->in_index = buf - xdr->in_buf;
173	return 0;
174}
175
176int xdr_send_pointer(struct msm_rpc_xdr *xdr, void **obj,
177		     uint32_t obj_size, void *xdr_op)
178{
179	uint32_t ptr_valid, rc;
180
181	ptr_valid = (*obj != NULL);
182
183	rc = xdr_send_uint32(xdr, &ptr_valid);
184	if (rc)
185		return rc;
186
187	if (!ptr_valid)
188		return 0;
189
190	return ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)(xdr, *obj);
191}
192
193int xdr_recv_pointer(struct msm_rpc_xdr *xdr, void **obj,
194		     uint32_t obj_size, void *xdr_op)
195{
196	uint32_t rc, ptr_valid = 0;
197
198	rc = xdr_recv_uint32(xdr, &ptr_valid);
199	if (rc)
200		return rc;
201
202	if (!ptr_valid) {
203		*obj = NULL;
204		return 0;
205	}
206
207	*obj = kmalloc(obj_size, GFP_KERNEL);
208	if (!*obj)
209		return -1;
210
211	rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)(xdr, *obj);
212	if (rc)
213		kfree(*obj);
214
215	return rc;
216}
217
218int xdr_send_array(struct msm_rpc_xdr *xdr, void **addr, uint32_t *size,
219		   uint32_t maxsize, uint32_t elm_size, void *xdr_op)
220{
221	int i, rc;
222	void *tmp_addr = *addr;
223
224	if (!size || !tmp_addr || (*size > maxsize) || !xdr_op)
225		return -1;
226
227	rc = xdr_send_uint32(xdr, size);
228	if (rc)
229		return rc;
230
231	for (i = 0; i < *size; i++) {
232		rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)
233			(xdr, tmp_addr);
234		if (rc)
235			return rc;
236
237		tmp_addr += elm_size;
238	}
239
240	return 0;
241}
242
243int xdr_recv_array(struct msm_rpc_xdr *xdr, void **addr, uint32_t *size,
244		   uint32_t maxsize, uint32_t elm_size, void *xdr_op)
245{
246	int i, rc;
247	void *tmp_addr;
248
249	if (!size || !xdr_op)
250		return -1;
251
252	rc = xdr_recv_uint32(xdr, size);
253	if (rc)
254		return rc;
255
256	if (*size > maxsize)
257		return -1;
258
259	tmp_addr = kmalloc((*size * elm_size), GFP_KERNEL);
260	if (!tmp_addr)
261		return -1;
262
263	*addr = tmp_addr;
264	for (i = 0; i < *size; i++) {
265		rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)
266			(xdr, tmp_addr);
267		if (rc) {
268			kfree(*addr);
269			*addr = NULL;
270			return rc;
271		}
272
273		tmp_addr += elm_size;
274	}
275
276	return 0;
277}
278
279int xdr_recv_req(struct msm_rpc_xdr *xdr, struct rpc_request_hdr *req)
280{
281	int rc = 0;
282	if (!req)
283		return -1;
284
285	rc |= xdr_recv_uint32(xdr, &req->xid);           /* xid */
286	rc |= xdr_recv_uint32(xdr, &req->type);          /* type */
287	rc |= xdr_recv_uint32(xdr, &req->rpc_vers);      /* rpc_vers */
288	rc |= xdr_recv_uint32(xdr, &req->prog);          /* prog */
289	rc |= xdr_recv_uint32(xdr, &req->vers);          /* vers */
290	rc |= xdr_recv_uint32(xdr, &req->procedure);     /* procedure */
291	rc |= xdr_recv_uint32(xdr, &req->cred_flavor);   /* cred_flavor */
292	rc |= xdr_recv_uint32(xdr, &req->cred_length);   /* cred_length */
293	rc |= xdr_recv_uint32(xdr, &req->verf_flavor);   /* verf_flavor */
294	rc |= xdr_recv_uint32(xdr, &req->verf_length);   /* verf_length */
295
296	return rc;
297}
298
299int xdr_recv_reply(struct msm_rpc_xdr *xdr, struct rpc_reply_hdr *reply)
300{
301	int rc = 0;
302
303	if (!reply)
304		return -1;
305
306	rc |= xdr_recv_uint32(xdr, &reply->xid);           /* xid */
307	rc |= xdr_recv_uint32(xdr, &reply->type);          /* type */
308	rc |= xdr_recv_uint32(xdr, &reply->reply_stat);    /* reply_stat */
309
310	/* acc_hdr */
311	if (reply->reply_stat == RPCMSG_REPLYSTAT_ACCEPTED) {
312		rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.verf_flavor);
313		rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.verf_length);
314		rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.accept_stat);
315	}
316
317	return rc;
318}
319
320int xdr_start_request(struct msm_rpc_xdr *xdr, uint32_t prog,
321		      uint32_t ver, uint32_t proc)
322{
323	mutex_lock(&xdr->out_lock);
324
325	/* TODO: replace below function with its implementation */
326	msm_rpc_setup_req((struct rpc_request_hdr *)xdr->out_buf,
327			  prog, ver, proc);
328
329	xdr->out_index = sizeof(struct rpc_request_hdr);
330	return 0;
331}
332
333int xdr_start_accepted_reply(struct msm_rpc_xdr *xdr, uint32_t accept_status)
334{
335	struct rpc_reply_hdr *reply;
336
337	mutex_lock(&xdr->out_lock);
338
339	/* TODO: err if xdr is not cb xdr */
340	reply = (struct rpc_reply_hdr *)xdr->out_buf;
341
342	/* TODO: use xdr functions instead */
343	reply->xid = ((struct rpc_request_hdr *)(xdr->in_buf))->xid;
344	reply->type = cpu_to_be32(1); /* reply */
345	reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
346
347	reply->data.acc_hdr.accept_stat = cpu_to_be32(accept_status);
348	reply->data.acc_hdr.verf_flavor = 0;
349	reply->data.acc_hdr.verf_length = 0;
350
351	xdr->out_index = sizeof(*reply);
352	return 0;
353}
354
355int xdr_send_msg(struct msm_rpc_xdr *xdr)
356{
357	int rc = 0;
358
359	rc = msm_rpc_write(xdr->ept, xdr->out_buf,
360			   xdr->out_index);
361	if (rc > 0)
362		rc = 0;
363
364	mutex_unlock(&xdr->out_lock);
365	return rc;
366}
367
368void xdr_init(struct msm_rpc_xdr *xdr)
369{
370	mutex_init(&xdr->out_lock);
371	init_waitqueue_head(&xdr->in_buf_wait_q);
372
373	xdr->in_buf = NULL;
374	xdr->in_size = 0;
375	xdr->in_index = 0;
376
377	xdr->out_buf = NULL;
378	xdr->out_size = 0;
379	xdr->out_index = 0;
380}
381
382void xdr_init_input(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
383{
384	wait_event(xdr->in_buf_wait_q, !(xdr->in_buf));
385
386	xdr->in_buf = buf;
387	xdr->in_size = size;
388	xdr->in_index = 0;
389}
390
391void xdr_init_output(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
392{
393	xdr->out_buf = buf;
394	xdr->out_size = size;
395	xdr->out_index = 0;
396}
397
398void xdr_clean_input(struct msm_rpc_xdr *xdr)
399{
400	kfree(xdr->in_buf);
401	xdr->in_size = 0;
402	xdr->in_index = 0;
403	xdr->in_buf = NULL;
404
405	wake_up(&xdr->in_buf_wait_q);
406}
407
408void xdr_clean_output(struct msm_rpc_xdr *xdr)
409{
410	kfree(xdr->out_buf);
411	xdr->out_buf = NULL;
412	xdr->out_size = 0;
413	xdr->out_index = 0;
414}
415
416uint32_t xdr_read_avail(struct msm_rpc_xdr *xdr)
417{
418	return xdr->in_size;
419}