aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif
diff options
context:
space:
mode:
authorSjur Braendeland <sjur.brandeland@stericsson.com>2010-04-28 04:54:37 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-28 15:55:13 -0400
commit8d545c8f958f5f433c50a00762ce1f231ed56eee (patch)
treef5688212d86c0bc6bf0ba8b02f57fca77de3145e /net/caif
parent5b2086567503f9b55136642031ec0067319f58e0 (diff)
caif: Disconnect without waiting for response
Changes: o Function cfcnfg_disconn_adapt_layer is changed to do asynchronous disconnect, not waiting for any response from the modem. Due to this the function cfcnfg_linkdestroy_rsp does nothing anymore. o Because disconnect may take down a connection before a connect response is received the function cfcnfg_linkup_rsp is checking if the client is still waiting for the response, if not a disconnect request is sent to the modem. o cfctrl is no longer keeping track of pending disconnect requests. o Added function cfctrl_cancel_req, which is used for deleting a pending connect request if disconnect is done before connect response is received. o Removed unused function cfctrl_insert_req2 o Added better handling of connect reject from modem. Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif')
-rw-r--r--net/caif/cfcnfg.c155
-rw-r--r--net/caif/cfctrl.c95
2 files changed, 107 insertions, 143 deletions
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index f94f3dfe85c1..471c62939fad 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -54,8 +54,7 @@ struct cfcnfg {
54static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, 54static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
55 enum cfctrl_srv serv, u8 phyid, 55 enum cfctrl_srv serv, u8 phyid,
56 struct cflayer *adapt_layer); 56 struct cflayer *adapt_layer);
57static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id, 57static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
58 struct cflayer *client_layer);
59static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, 58static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
60 struct cflayer *adapt_layer); 59 struct cflayer *adapt_layer);
61static void cfctrl_resp_func(void); 60static void cfctrl_resp_func(void);
@@ -175,73 +174,65 @@ int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
175 return 0; 174 return 0;
176} 175}
177 176
178/*
179 * NOTE: What happens on destroy failure:
180 * 1a) No response - Too early
181 * This will not happen because enumerate has already
182 * completed.
183 * 1b) No response - FATAL
184 * Not handled, but this should be a CAIF PROTOCOL ERROR
185 * Modem error, response is really expected - this
186 * case is not really handled.
187 * 2) O/E-bit indicate error
188 * Ignored - this link is destroyed anyway.
189 * 3) Not able to match on request
190 * Not handled, but this should be a CAIF PROTOCOL ERROR
191 * 4) Link-Error - (no response)
192 * Not handled, but this should be a CAIF PROTOCOL ERROR
193 */
194int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) 177int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
195{ 178{
196 u8 channel_id = 0; 179 u8 channel_id = 0;
197 int ret = 0; 180 int ret = 0;
181 struct cflayer *servl = NULL;
198 struct cfcnfg_phyinfo *phyinfo = NULL; 182 struct cfcnfg_phyinfo *phyinfo = NULL;
199 u8 phyid = 0; 183 u8 phyid = 0;
200
201 caif_assert(adap_layer != NULL); 184 caif_assert(adap_layer != NULL);
202 channel_id = adap_layer->id; 185 channel_id = adap_layer->id;
203 if (channel_id == 0) { 186 if (adap_layer->dn == NULL || channel_id == 0) {
204 pr_err("CAIF: %s():adap_layer->id is 0\n", __func__); 187 pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
205 ret = -ENOTCONN; 188 ret = -ENOTCONN;
206 goto end; 189 goto end;
207 } 190 }
208 191 servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
209 if (adap_layer->dn == NULL) { 192 if (servl == NULL)
210 pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__);
211 ret = -ENODEV;
212 goto end;
213 }
214
215 if (adap_layer->dn != NULL)
216 phyid = cfsrvl_getphyid(adap_layer->dn);
217
218 phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
219 if (phyinfo == NULL) {
220 pr_warning("CAIF: %s(): No interface to send disconnect to\n",
221 __func__);
222 ret = -ENODEV;
223 goto end; 193 goto end;
224 } 194 layer_set_up(servl, NULL);
225 195 ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
226 if (phyinfo->id != phyid 196 if (servl == NULL) {
227 || phyinfo->phy_layer->id != phyid 197 pr_err("CAIF: %s(): PROTOCOL ERROR "
228 || phyinfo->frm_layer->id != phyid) { 198 "- Error removing service_layer Channel_Id(%d)",
229 199 __func__, channel_id);
230 pr_err("CAIF: %s(): Inconsistency in phy registration\n",
231 __func__);
232 ret = -EINVAL; 200 ret = -EINVAL;
233 goto end; 201 goto end;
234 } 202 }
203 caif_assert(channel_id == servl->id);
204 if (adap_layer->dn != NULL) {
205 phyid = cfsrvl_getphyid(adap_layer->dn);
235 206
236 ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); 207 phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
237 208 if (phyinfo == NULL) {
238end: 209 pr_warning("CAIF: %s(): "
210 "No interface to send disconnect to\n",
211 __func__);
212 ret = -ENODEV;
213 goto end;
214 }
215 if (phyinfo->id != phyid ||
216 phyinfo->phy_layer->id != phyid ||
217 phyinfo->frm_layer->id != phyid) {
218 pr_err("CAIF: %s(): "
219 "Inconsistency in phy registration\n",
220 __func__);
221 ret = -EINVAL;
222 goto end;
223 }
224 }
239 if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && 225 if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 &&
240 phyinfo->phy_layer != NULL && 226 phyinfo->phy_layer != NULL &&
241 phyinfo->phy_layer->modemcmd != NULL) { 227 phyinfo->phy_layer->modemcmd != NULL) {
242 phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, 228 phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
243 _CAIF_MODEMCMD_PHYIF_USELESS); 229 _CAIF_MODEMCMD_PHYIF_USELESS);
244 } 230 }
231end:
232 cfsrvl_put(servl);
233 cfctrl_cancel_req(cnfg->ctrl, adap_layer);
234 if (adap_layer->ctrlcmd != NULL)
235 adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
245 return ret; 236 return ret;
246 237
247} 238}
@@ -254,69 +245,11 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
254} 245}
255EXPORT_SYMBOL(cfcnfg_release_adap_layer); 246EXPORT_SYMBOL(cfcnfg_release_adap_layer);
256 247
257static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id, 248static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
258 struct cflayer *client_layer)
259{ 249{
260 struct cfcnfg *cnfg = container_obj(layer);
261 struct cflayer *servl;
262
263 /*
264 * 1) Remove service from the MUX layer. The MUX must
265 * guarante that no more payload sent "upwards" (receive)
266 */
267 servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
268
269 if (servl == NULL) {
270 pr_err("CAIF: %s(): PROTOCOL ERROR "
271 "- Error removing service_layer Channel_Id(%d)",
272 __func__, channel_id);
273 return;
274 }
275 caif_assert(channel_id == servl->id);
276
277 if (servl != client_layer && servl->up != client_layer) {
278 pr_err("CAIF: %s(): Error removing service_layer "
279 "Channel_Id(%d) %p %p",
280 __func__, channel_id, (void *) servl,
281 (void *) client_layer);
282 return;
283 }
284
285 /*
286 * 2) DEINIT_RSP must guarantee that no more packets are transmitted
287 * from client (adap_layer) when it returns.
288 */
289
290 if (servl->ctrlcmd == NULL) {
291 pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__);
292 return;
293 }
294
295 servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0);
296
297 /* 3) It is now safe to destroy the service layer. */
298 cfservl_destroy(servl);
299} 250}
300 251
301/* 252int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
302 * NOTE: What happens on linksetup failure:
303 * 1a) No response - Too early
304 * This will not happen because enumerate is secured
305 * before using interface.
306 * 1b) No response - FATAL
307 * Not handled, but this should be a CAIF PROTOCOL ERROR
308 * Modem error, response is really expected - this case is
309 * not really handled.
310 * 2) O/E-bit indicate error
311 * Handled in cnfg_reject_rsp
312 * 3) Not able to match on request
313 * Not handled, but this should be a CAIF PROTOCOL ERROR
314 * 4) Link-Error - (no response)
315 * Not handled, but this should be a CAIF PROTOCOL ERROR
316 */
317
318int
319cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
320 struct cfctrl_link_param *param, 253 struct cfctrl_link_param *param,
321 struct cflayer *adap_layer) 254 struct cflayer *adap_layer)
322{ 255{
@@ -346,8 +279,7 @@ cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
346 param->phyid); 279 param->phyid);
347 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ 280 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
348 cfctrl_enum_req(cnfg->ctrl, param->phyid); 281 cfctrl_enum_req(cnfg->ctrl, param->phyid);
349 cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); 282 return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
350 return 0;
351} 283}
352EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); 284EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
353 285
@@ -367,8 +299,10 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
367 struct cflayer *servicel = NULL; 299 struct cflayer *servicel = NULL;
368 struct cfcnfg_phyinfo *phyinfo; 300 struct cfcnfg_phyinfo *phyinfo;
369 if (adapt_layer == NULL) { 301 if (adapt_layer == NULL) {
370 pr_err("CAIF: %s(): PROTOCOL ERROR " 302 pr_debug("CAIF: %s(): link setup response "
371 "- LinkUp Request/Response did not match\n", __func__); 303 "but no client exist, send linkdown back\n",
304 __func__);
305 cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
372 return; 306 return;
373 } 307 }
374 308
@@ -424,6 +358,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
424 cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); 358 cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
425 layer_set_up(servicel, adapt_layer); 359 layer_set_up(servicel, adapt_layer);
426 layer_set_dn(adapt_layer, servicel); 360 layer_set_dn(adapt_layer, servicel);
361 cfsrvl_get(servicel);
427 servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); 362 servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
428} 363}
429 364
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 11f80140f3cb..a521d32cfe56 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -32,6 +32,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
32 32
33struct cflayer *cfctrl_create(void) 33struct cflayer *cfctrl_create(void)
34{ 34{
35 struct dev_info dev_info;
35 struct cfctrl *this = 36 struct cfctrl *this =
36 kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); 37 kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
37 if (!this) { 38 if (!this) {
@@ -39,12 +40,13 @@ struct cflayer *cfctrl_create(void)
39 return NULL; 40 return NULL;
40 } 41 }
41 caif_assert(offsetof(struct cfctrl, serv.layer) == 0); 42 caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
43 memset(&dev_info, 0, sizeof(dev_info));
44 dev_info.id = 0xff;
42 memset(this, 0, sizeof(*this)); 45 memset(this, 0, sizeof(*this));
46 cfsrvl_init(&this->serv, 0, &dev_info);
43 spin_lock_init(&this->info_list_lock); 47 spin_lock_init(&this->info_list_lock);
44 atomic_set(&this->req_seq_no, 1); 48 atomic_set(&this->req_seq_no, 1);
45 atomic_set(&this->rsp_seq_no, 1); 49 atomic_set(&this->rsp_seq_no, 1);
46 this->serv.dev_info.id = 0xff;
47 this->serv.layer.id = 0;
48 this->serv.layer.receive = cfctrl_recv; 50 this->serv.layer.receive = cfctrl_recv;
49 sprintf(this->serv.layer.name, "ctrl"); 51 sprintf(this->serv.layer.name, "ctrl");
50 this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; 52 this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
@@ -127,20 +129,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl,
127 spin_unlock(&ctrl->info_list_lock); 129 spin_unlock(&ctrl->info_list_lock);
128} 130}
129 131
130static void cfctrl_insert_req2(struct cfctrl *ctrl, enum cfctrl_cmd cmd,
131 u8 linkid, struct cflayer *user_layer)
132{
133 struct cfctrl_request_info *req = kmalloc(sizeof(*req), GFP_KERNEL);
134 if (!req) {
135 pr_warning("CAIF: %s(): Out of memory\n", __func__);
136 return;
137 }
138 req->client_layer = user_layer;
139 req->cmd = cmd;
140 req->channel_id = linkid;
141 cfctrl_insert_req(ctrl, req);
142}
143
144/* Compare and remove request */ 132/* Compare and remove request */
145struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, 133struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
146 struct cfctrl_request_info *req) 134 struct cfctrl_request_info *req)
@@ -234,7 +222,7 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
234 } 222 }
235} 223}
236 224
237void cfctrl_linkup_request(struct cflayer *layer, 225int cfctrl_linkup_request(struct cflayer *layer,
238 struct cfctrl_link_param *param, 226 struct cfctrl_link_param *param,
239 struct cflayer *user_layer) 227 struct cflayer *user_layer)
240{ 228{
@@ -248,7 +236,7 @@ void cfctrl_linkup_request(struct cflayer *layer,
248 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); 236 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
249 if (!pkt) { 237 if (!pkt) {
250 pr_warning("CAIF: %s(): Out of memory\n", __func__); 238 pr_warning("CAIF: %s(): Out of memory\n", __func__);
251 return; 239 return -ENOMEM;
252 } 240 }
253 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); 241 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
254 cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); 242 cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype);
@@ -294,11 +282,12 @@ void cfctrl_linkup_request(struct cflayer *layer,
294 default: 282 default:
295 pr_warning("CAIF: %s():Request setup of bad link type = %d\n", 283 pr_warning("CAIF: %s():Request setup of bad link type = %d\n",
296 __func__, param->linktype); 284 __func__, param->linktype);
285 return -EINVAL;
297 } 286 }
298 req = kmalloc(sizeof(*req), GFP_KERNEL); 287 req = kmalloc(sizeof(*req), GFP_KERNEL);
299 if (!req) { 288 if (!req) {
300 pr_warning("CAIF: %s(): Out of memory\n", __func__); 289 pr_warning("CAIF: %s(): Out of memory\n", __func__);
301 return; 290 return -ENOMEM;
302 } 291 }
303 memset(req, 0, sizeof(*req)); 292 memset(req, 0, sizeof(*req));
304 req->client_layer = user_layer; 293 req->client_layer = user_layer;
@@ -306,6 +295,11 @@ void cfctrl_linkup_request(struct cflayer *layer,
306 req->param = *param; 295 req->param = *param;
307 cfctrl_insert_req(cfctrl, req); 296 cfctrl_insert_req(cfctrl, req);
308 init_info(cfpkt_info(pkt), cfctrl); 297 init_info(cfpkt_info(pkt), cfctrl);
298 /*
299 * NOTE:Always send linkup and linkdown request on the same
300 * device as the payload. Otherwise old queued up payload
301 * might arrive with the newly allocated channel ID.
302 */
309 cfpkt_info(pkt)->dev_info->id = param->phyid; 303 cfpkt_info(pkt)->dev_info->id = param->phyid;
310 ret = 304 ret =
311 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); 305 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
@@ -313,7 +307,9 @@ void cfctrl_linkup_request(struct cflayer *layer,
313 pr_err("CAIF: %s(): Could not transmit linksetup request\n", 307 pr_err("CAIF: %s(): Could not transmit linksetup request\n",
314 __func__); 308 __func__);
315 cfpkt_destroy(pkt); 309 cfpkt_destroy(pkt);
310 return -ENODEV;
316 } 311 }
312 return 0;
317} 313}
318 314
319int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, 315int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
@@ -326,7 +322,6 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
326 pr_warning("CAIF: %s(): Out of memory\n", __func__); 322 pr_warning("CAIF: %s(): Out of memory\n", __func__);
327 return -ENOMEM; 323 return -ENOMEM;
328 } 324 }
329 cfctrl_insert_req2(cfctrl, CFCTRL_CMD_LINK_DESTROY, channelid, client);
330 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); 325 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY);
331 cfpkt_addbdy(pkt, channelid); 326 cfpkt_addbdy(pkt, channelid);
332 init_info(cfpkt_info(pkt), cfctrl); 327 init_info(cfpkt_info(pkt), cfctrl);
@@ -392,6 +387,38 @@ void cfctrl_getstartreason_req(struct cflayer *layer)
392} 387}
393 388
394 389
390void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
391{
392 struct cfctrl_request_info *p, *req;
393 struct cfctrl *ctrl = container_obj(layr);
394 spin_lock(&ctrl->info_list_lock);
395
396 if (ctrl->first_req == NULL) {
397 spin_unlock(&ctrl->info_list_lock);
398 return;
399 }
400
401 if (ctrl->first_req->client_layer == adap_layer) {
402
403 req = ctrl->first_req;
404 ctrl->first_req = ctrl->first_req->next;
405 kfree(req);
406 }
407
408 p = ctrl->first_req;
409 while (p != NULL && p->next != NULL) {
410 if (p->next->client_layer == adap_layer) {
411
412 req = p->next;
413 p->next = p->next->next;
414 kfree(p->next);
415 }
416 p = p->next;
417 }
418
419 spin_unlock(&ctrl->info_list_lock);
420}
421
395static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) 422static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
396{ 423{
397 u8 cmdrsp; 424 u8 cmdrsp;
@@ -409,11 +436,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
409 cmd = cmdrsp & CFCTRL_CMD_MASK; 436 cmd = cmdrsp & CFCTRL_CMD_MASK;
410 if (cmd != CFCTRL_CMD_LINK_ERR 437 if (cmd != CFCTRL_CMD_LINK_ERR
411 && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { 438 && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
412 if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) { 439 if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE)
413 pr_info("CAIF: %s() CAIF Protocol error:" 440 cmdrsp |= CFCTRL_ERR_BIT;
414 "Response bit not set\n", __func__);
415 goto error;
416 }
417 } 441 }
418 442
419 switch (cmd) { 443 switch (cmd) {
@@ -451,12 +475,16 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
451 switch (serv) { 475 switch (serv) {
452 case CFCTRL_SRV_VEI: 476 case CFCTRL_SRV_VEI:
453 case CFCTRL_SRV_DBG: 477 case CFCTRL_SRV_DBG:
478 if (CFCTRL_ERR_BIT & cmdrsp)
479 break;
454 /* Link ID */ 480 /* Link ID */
455 cfpkt_extr_head(pkt, &linkid, 1); 481 cfpkt_extr_head(pkt, &linkid, 1);
456 break; 482 break;
457 case CFCTRL_SRV_VIDEO: 483 case CFCTRL_SRV_VIDEO:
458 cfpkt_extr_head(pkt, &tmp, 1); 484 cfpkt_extr_head(pkt, &tmp, 1);
459 linkparam.u.video.connid = tmp; 485 linkparam.u.video.connid = tmp;
486 if (CFCTRL_ERR_BIT & cmdrsp)
487 break;
460 /* Link ID */ 488 /* Link ID */
461 cfpkt_extr_head(pkt, &linkid, 1); 489 cfpkt_extr_head(pkt, &linkid, 1);
462 break; 490 break;
@@ -465,6 +493,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
465 cfpkt_extr_head(pkt, &tmp32, 4); 493 cfpkt_extr_head(pkt, &tmp32, 4);
466 linkparam.u.datagram.connid = 494 linkparam.u.datagram.connid =
467 le32_to_cpu(tmp32); 495 le32_to_cpu(tmp32);
496 if (CFCTRL_ERR_BIT & cmdrsp)
497 break;
468 /* Link ID */ 498 /* Link ID */
469 cfpkt_extr_head(pkt, &linkid, 1); 499 cfpkt_extr_head(pkt, &linkid, 1);
470 break; 500 break;
@@ -483,6 +513,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
483 *cp++ = tmp; 513 *cp++ = tmp;
484 *cp = '\0'; 514 *cp = '\0';
485 515
516 if (CFCTRL_ERR_BIT & cmdrsp)
517 break;
486 /* Link ID */ 518 /* Link ID */
487 cfpkt_extr_head(pkt, &linkid, 1); 519 cfpkt_extr_head(pkt, &linkid, 1);
488 520
@@ -519,6 +551,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
519 cfpkt_extr_head(pkt, &tmp, 1); 551 cfpkt_extr_head(pkt, &tmp, 1);
520 *cp++ = tmp; 552 *cp++ = tmp;
521 } 553 }
554 if (CFCTRL_ERR_BIT & cmdrsp)
555 break;
522 /* Link ID */ 556 /* Link ID */
523 cfpkt_extr_head(pkt, &linkid, 1); 557 cfpkt_extr_head(pkt, &linkid, 1);
524 /* Length */ 558 /* Length */
@@ -560,13 +594,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
560 break; 594 break;
561 case CFCTRL_CMD_LINK_DESTROY: 595 case CFCTRL_CMD_LINK_DESTROY:
562 cfpkt_extr_head(pkt, &linkid, 1); 596 cfpkt_extr_head(pkt, &linkid, 1);
563 rsp.cmd = cmd; 597 cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid);
564 rsp.channel_id = linkid;
565 req = cfctrl_remove_req(cfctrl, &rsp);
566 cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid,
567 req ? req->client_layer : NULL);
568 if (req != NULL)
569 kfree(req);
570 break; 598 break;
571 case CFCTRL_CMD_LINK_ERR: 599 case CFCTRL_CMD_LINK_ERR:
572 pr_err("CAIF: %s(): Frame Error Indication received\n", 600 pr_err("CAIF: %s(): Frame Error Indication received\n",
@@ -608,7 +636,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
608 case CAIF_CTRLCMD_FLOW_OFF_IND: 636 case CAIF_CTRLCMD_FLOW_OFF_IND:
609 spin_lock(&this->info_list_lock); 637 spin_lock(&this->info_list_lock);
610 if (this->first_req != NULL) { 638 if (this->first_req != NULL) {
611 pr_warning("CAIF: %s(): Received flow off in " 639 pr_debug("CAIF: %s(): Received flow off in "
612 "control layer", __func__); 640 "control layer", __func__);
613 } 641 }
614 spin_unlock(&this->info_list_lock); 642 spin_unlock(&this->info_list_lock);
@@ -633,6 +661,7 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
633 if (!ctrl->loop_linkused[linkid]) 661 if (!ctrl->loop_linkused[linkid])
634 goto found; 662 goto found;
635 spin_unlock(&ctrl->loop_linkid_lock); 663 spin_unlock(&ctrl->loop_linkid_lock);
664 pr_err("CAIF: %s(): Out of link-ids\n", __func__);
636 return -EINVAL; 665 return -EINVAL;
637found: 666found:
638 if (!ctrl->loop_linkused[linkid]) 667 if (!ctrl->loop_linkused[linkid])