Blame view
net/caif/cfsrvl.c
5.59 KB
b482cd205
|
1 2 3 4 5 |
/* * Copyright (C) ST-Ericsson AB 2010 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com * License terms: GNU General Public License (GPL) version 2 */ |
b31fa5bad
|
6 |
#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ |
b482cd205
|
7 8 9 10 |
#include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/slab.h> |
43e369210
|
11 |
#include <linux/module.h> |
b482cd205
|
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <net/caif/caif_layer.h> #include <net/caif/cfsrvl.h> #include <net/caif/cfpkt.h> #define SRVL_CTRL_PKT_SIZE 1 #define SRVL_FLOW_OFF 0x81 #define SRVL_FLOW_ON 0x80 #define SRVL_SET_PIN 0x82 #define SRVL_CTRL_PKT_SIZE 1 #define container_obj(layr) container_of(layr, struct cfsrvl, layer) static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, int phyid) { struct cfsrvl *service = container_obj(layr); |
b1c74247b
|
28 |
|
43e369210
|
29 30 |
if (layr->up == NULL || layr->up->ctrlcmd == NULL) return; |
b1c74247b
|
31 |
|
b482cd205
|
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
switch (ctrl) { case CAIF_CTRLCMD_INIT_RSP: service->open = true; layr->up->ctrlcmd(layr->up, ctrl, phyid); break; case CAIF_CTRLCMD_DEINIT_RSP: case CAIF_CTRLCMD_INIT_FAIL_RSP: service->open = false; layr->up->ctrlcmd(layr->up, ctrl, phyid); break; case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: if (phyid != service->dev_info.id) break; if (service->modem_flow_on) layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_FLOW_OFF_IND, phyid); service->phy_flow_on = false; break; case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: if (phyid != service->dev_info.id) return; if (service->modem_flow_on) { layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_FLOW_ON_IND, phyid); } service->phy_flow_on = true; break; case CAIF_CTRLCMD_FLOW_OFF_IND: if (service->phy_flow_on) { layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_FLOW_OFF_IND, phyid); } service->modem_flow_on = false; break; case CAIF_CTRLCMD_FLOW_ON_IND: if (service->phy_flow_on) { layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_FLOW_ON_IND, phyid); } service->modem_flow_on = true; break; case _CAIF_CTRLCMD_PHYIF_DOWN_IND: /* In case interface is down, let's fake a remove shutdown */ layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid); break; case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: layr->up->ctrlcmd(layr->up, ctrl, phyid); break; default: |
b31fa5bad
|
83 84 |
pr_warn("Unexpected ctrl in cfsrvl (%d) ", ctrl); |
b482cd205
|
85 86 87 88 89 90 91 92 93 94 |
/* We have both modem and phy flow on, send flow on */ layr->up->ctrlcmd(layr->up, ctrl, phyid); service->phy_flow_on = true; break; } } static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) { struct cfsrvl *service = container_obj(layr); |
b1c74247b
|
95 |
|
b482cd205
|
96 97 98 |
caif_assert(layr != NULL); caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); |
b1c74247b
|
99 100 101 |
if (!service->supports_flowctrl) return 0; |
b482cd205
|
102 103 104 105 106 107 108 109 |
switch (ctrl) { case CAIF_MODEMCMD_FLOW_ON_REQ: { struct cfpkt *pkt; struct caif_payload_info *info; u8 flow_on = SRVL_FLOW_ON; pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); if (!pkt) { |
b31fa5bad
|
110 111 |
pr_warn("Out of memory "); |
b482cd205
|
112 113 114 115 |
return -ENOMEM; } if (cfpkt_add_head(pkt, &flow_on, 1) < 0) { |
b31fa5bad
|
116 117 |
pr_err("Packet is erroneous! "); |
b482cd205
|
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
cfpkt_destroy(pkt); return -EPROTO; } info = cfpkt_info(pkt); info->channel_id = service->layer.id; info->hdr_len = 1; info->dev_info = &service->dev_info; return layr->dn->transmit(layr->dn, pkt); } case CAIF_MODEMCMD_FLOW_OFF_REQ: { struct cfpkt *pkt; struct caif_payload_info *info; u8 flow_off = SRVL_FLOW_OFF; pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); |
638e628a6
|
133 |
if (!pkt) { |
b31fa5bad
|
134 135 |
pr_warn("Out of memory "); |
638e628a6
|
136 137 |
return -ENOMEM; } |
b482cd205
|
138 |
if (cfpkt_add_head(pkt, &flow_off, 1) < 0) { |
b31fa5bad
|
139 140 |
pr_err("Packet is erroneous! "); |
b482cd205
|
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
cfpkt_destroy(pkt); return -EPROTO; } info = cfpkt_info(pkt); info->channel_id = service->layer.id; info->hdr_len = 1; info->dev_info = &service->dev_info; return layr->dn->transmit(layr->dn, pkt); } default: break; } return -EINVAL; } |
43e369210
|
155 |
static void cfsrvl_release(struct cflayer *layer) |
a7da1f55a
|
156 |
{ |
43e369210
|
157 |
struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); |
a7da1f55a
|
158 159 |
kfree(service); } |
b482cd205
|
160 |
void cfsrvl_init(struct cfsrvl *service, |
b1c74247b
|
161 162 163 164 |
u8 channel_id, struct dev_info *dev_info, bool supports_flowctrl ) |
b482cd205
|
165 166 167 168 169 170 171 172 173 |
{ caif_assert(offsetof(struct cfsrvl, layer) == 0); service->open = false; service->modem_flow_on = true; service->phy_flow_on = true; service->layer.id = channel_id; service->layer.ctrlcmd = cfservl_ctrlcmd; service->layer.modemcmd = cfservl_modemcmd; service->dev_info = *dev_info; |
b1c74247b
|
174 |
service->supports_flowctrl = supports_flowctrl; |
a7da1f55a
|
175 |
service->release = cfsrvl_release; |
5b2086567
|
176 |
} |
b482cd205
|
177 178 179 180 181 182 183 184 185 186 187 188 |
bool cfsrvl_ready(struct cfsrvl *service, int *err) { if (service->open && service->modem_flow_on && service->phy_flow_on) return true; if (!service->open) { *err = -ENOTCONN; return false; } caif_assert(!(service->modem_flow_on && service->phy_flow_on)); *err = -EAGAIN; return false; } |
43e369210
|
189 |
|
b482cd205
|
190 191 192 193 194 195 196 197 198 199 200 |
u8 cfsrvl_getphyid(struct cflayer *layer) { struct cfsrvl *servl = container_obj(layer); return servl->dev_info.id; } bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) { struct cfsrvl *servl = container_obj(layer); return servl->dev_info.id == phyid; } |
43e369210
|
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
void caif_free_client(struct cflayer *adap_layer) { struct cfsrvl *servl; if (adap_layer == NULL || adap_layer->dn == NULL) return; servl = container_obj(adap_layer->dn); servl->release(&servl->layer); } EXPORT_SYMBOL(caif_free_client); void caif_client_register_refcnt(struct cflayer *adapt_layer, void (*hold)(struct cflayer *lyr), void (*put)(struct cflayer *lyr)) { struct cfsrvl *service; service = container_of(adapt_layer->dn, struct cfsrvl, layer); WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); service->hold = hold; service->put = put; } EXPORT_SYMBOL(caif_client_register_refcnt); |