aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/cfcnfg.c
diff options
context:
space:
mode:
authorsjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com>2011-05-22 07:18:51 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-22 20:11:47 -0400
commit54e90fb5ca8050156d3e748ddc690ed6ea9d71ac (patch)
tree63a4d1a736a7c44cc88b69e41dec9c4885ef2f74 /net/caif/cfcnfg.c
parent0e5a117441ce245b87949cc7713627a293f37227 (diff)
caif: Fixes freeze on Link layer removal.
CAIF Socket layer - caif_socket.c: - Plug mem-leak at reconnect. - Always call disconnect to cleanup CAIF stack. - Disconnect will always report success. CAIF configuration layer - cfcnfg.c - Disconnect must dismantle the caif stack correctly - Protect against faulty removals (check on id zero) CAIF mux layer - cfmuxl.c - When inserting new service layer in the MUX remove any old entries with the same ID. - When removing CAIF Link layer, remove the associated service layers before notifying service layers. Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif/cfcnfg.c')
-rw-r--r--net/caif/cfcnfg.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 351c2ca7e7b9..52fe33bee029 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -182,39 +182,26 @@ static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
182 182
183int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) 183int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
184{ 184{
185 u8 channel_id = 0; 185 u8 channel_id;
186 int ret = 0;
187 struct cflayer *servl = NULL;
188 struct cfcnfg *cfg = get_cfcnfg(net); 186 struct cfcnfg *cfg = get_cfcnfg(net);
189 187
190 caif_assert(adap_layer != NULL); 188 caif_assert(adap_layer != NULL);
191
192 channel_id = adap_layer->id;
193 if (adap_layer->dn == NULL || channel_id == 0) {
194 pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n");
195 ret = -ENOTCONN;
196 goto end;
197 }
198
199 servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
200 if (servl == NULL) {
201 pr_err("PROTOCOL ERROR - "
202 "Error removing service_layer Channel_Id(%d)",
203 channel_id);
204 ret = -EINVAL;
205 goto end;
206 }
207
208 ret = cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
209
210end:
211 cfctrl_cancel_req(cfg->ctrl, adap_layer); 189 cfctrl_cancel_req(cfg->ctrl, adap_layer);
190 channel_id = adap_layer->id;
191 if (channel_id != 0) {
192 struct cflayer *servl;
193 servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
194 if (servl != NULL)
195 layer_set_up(servl, NULL);
196 } else
197 pr_debug("nothing to disconnect\n");
198 cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
212 199
213 /* Do RCU sync before initiating cleanup */ 200 /* Do RCU sync before initiating cleanup */
214 synchronize_rcu(); 201 synchronize_rcu();
215 if (adap_layer->ctrlcmd != NULL) 202 if (adap_layer->ctrlcmd != NULL)
216 adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); 203 adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
217 return ret; 204 return 0;
218 205
219} 206}
220EXPORT_SYMBOL(caif_disconnect_client); 207EXPORT_SYMBOL(caif_disconnect_client);
@@ -400,6 +387,14 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
400 struct cfcnfg_phyinfo *phyinfo; 387 struct cfcnfg_phyinfo *phyinfo;
401 struct net_device *netdev; 388 struct net_device *netdev;
402 389
390 if (channel_id == 0) {
391 pr_warn("received channel_id zero\n");
392 if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
393 adapt_layer->ctrlcmd(adapt_layer,
394 CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
395 return;
396 }
397
403 rcu_read_lock(); 398 rcu_read_lock();
404 399
405 if (adapt_layer == NULL) { 400 if (adapt_layer == NULL) {
@@ -523,7 +518,6 @@ got_phyid:
523 phyinfo->use_stx = stx; 518 phyinfo->use_stx = stx;
524 phyinfo->use_fcs = fcs; 519 phyinfo->use_fcs = fcs;
525 520
526 phy_layer->type = phy_type;
527 frml = cffrml_create(phyid, fcs); 521 frml = cffrml_create(phyid, fcs);
528 522
529 if (!frml) { 523 if (!frml) {