caif: Bugfix not all services uses flow-ctrl.
[deliverable/linux.git] / net / caif / cfrfml.c
CommitLineData
b482cd20
SB
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/spinlock.h>
9#include <linux/slab.h>
10#include <net/caif/caif_layer.h>
11#include <net/caif/cfsrvl.h>
12#include <net/caif/cfpkt.h>
13
14#define container_obj(layr) container_of(layr, struct cfsrvl, layer)
15
16#define RFM_SEGMENTATION_BIT 0x01
17#define RFM_PAYLOAD 0x00
18#define RFM_CMD_BIT 0x80
19#define RFM_FLOW_OFF 0x81
20#define RFM_FLOW_ON 0x80
21#define RFM_SET_PIN 0x82
22#define RFM_CTRL_PKT_SIZE 1
23
24static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt);
25static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt);
b482cd20
SB
26
27struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info)
28{
29 struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
b1c74247 30
b482cd20
SB
31 if (!rfm) {
32 pr_warning("CAIF: %s(): Out of memory\n", __func__);
33 return NULL;
34 }
b1c74247 35
b482cd20 36 caif_assert(offsetof(struct cfsrvl, layer) == 0);
b1c74247 37
b482cd20 38 memset(rfm, 0, sizeof(struct cfsrvl));
b1c74247 39 cfsrvl_init(rfm, channel_id, dev_info, false);
b482cd20
SB
40 rfm->layer.receive = cfrfml_receive;
41 rfm->layer.transmit = cfrfml_transmit;
42 snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id);
43 return &rfm->layer;
44}
45
b482cd20
SB
46static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt)
47{
48 u8 tmp;
49 bool segmented;
50 int ret;
51 caif_assert(layr->up != NULL);
52 caif_assert(layr->receive != NULL);
53
54 /*
55 * RFM is taking care of segmentation and stripping of
56 * segmentation bit.
57 */
58 if (cfpkt_extr_head(pkt, &tmp, 1) < 0) {
59 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
60 cfpkt_destroy(pkt);
61 return -EPROTO;
62 }
63 segmented = tmp & RFM_SEGMENTATION_BIT;
64 caif_assert(!segmented);
65
66 ret = layr->up->receive(layr->up, pkt);
67 return ret;
68}
69
70static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
71{
72 u8 tmp = 0;
73 int ret;
74 struct cfsrvl *service = container_obj(layr);
75
76 caif_assert(layr->dn != NULL);
77 caif_assert(layr->dn->transmit != NULL);
78
79 if (!cfsrvl_ready(service, &ret))
80 return ret;
81
aea34e7a 82 if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
b482cd20
SB
83 pr_err("CAIF: %s():Packet too large - size=%d\n",
84 __func__, cfpkt_getlen(pkt));
85 return -EOVERFLOW;
86 }
87 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
88 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
89 return -EPROTO;
90 }
91
92 /* Add info for MUX-layer to route the packet out. */
93 cfpkt_info(pkt)->channel_id = service->layer.id;
94 /*
95 * To optimize alignment, we add up the size of CAIF header before
96 * payload.
97 */
98 cfpkt_info(pkt)->hdr_len = 1;
99 cfpkt_info(pkt)->dev_info = &service->dev_info;
100 ret = layr->dn->transmit(layr->dn, pkt);
101 if (ret < 0)
102 cfpkt_extr_head(pkt, &tmp, 1);
103 return ret;
104}
This page took 0.059781 seconds and 5 git commands to generate.