fix get_active_super()/umount() race
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / net / caif / cfrfml.c
blobcd2830fec9351322156e941c9d7043418ea549a4
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 */
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>
14 #define container_obj(layr) container_of(layr, struct cfsrvl, layer)
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
24 static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt);
25 static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt);
26 static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl);
28 struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info)
30 struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
31 if (!rfm) {
32 pr_warning("CAIF: %s(): Out of memory\n", __func__);
33 return NULL;
35 caif_assert(offsetof(struct cfsrvl, layer) == 0);
36 memset(rfm, 0, sizeof(struct cfsrvl));
37 cfsrvl_init(rfm, channel_id, dev_info);
38 rfm->layer.modemcmd = cfservl_modemcmd;
39 rfm->layer.receive = cfrfml_receive;
40 rfm->layer.transmit = cfrfml_transmit;
41 snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id);
42 return &rfm->layer;
45 static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
47 return -EPROTO;
50 static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt)
52 u8 tmp;
53 bool segmented;
54 int ret;
55 caif_assert(layr->up != NULL);
56 caif_assert(layr->receive != NULL);
59 * RFM is taking care of segmentation and stripping of
60 * segmentation bit.
62 if (cfpkt_extr_head(pkt, &tmp, 1) < 0) {
63 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
64 cfpkt_destroy(pkt);
65 return -EPROTO;
67 segmented = tmp & RFM_SEGMENTATION_BIT;
68 caif_assert(!segmented);
70 ret = layr->up->receive(layr->up, pkt);
71 return ret;
74 static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
76 u8 tmp = 0;
77 int ret;
78 struct cfsrvl *service = container_obj(layr);
80 caif_assert(layr->dn != NULL);
81 caif_assert(layr->dn->transmit != NULL);
83 if (!cfsrvl_ready(service, &ret))
84 return ret;
86 if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
87 pr_err("CAIF: %s():Packet too large - size=%d\n",
88 __func__, cfpkt_getlen(pkt));
89 return -EOVERFLOW;
91 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
92 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
93 return -EPROTO;
96 /* Add info for MUX-layer to route the packet out. */
97 cfpkt_info(pkt)->channel_id = service->layer.id;
99 * To optimize alignment, we add up the size of CAIF header before
100 * payload.
102 cfpkt_info(pkt)->hdr_len = 1;
103 cfpkt_info(pkt)->dev_info = &service->dev_info;
104 ret = layr->dn->transmit(layr->dn, pkt);
105 if (ret < 0)
106 cfpkt_extr_head(pkt, &tmp, 1);
107 return ret;