diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-22 13:18:51 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-23 02:11:47 +0200 |
commit | 54e90fb5ca8050156d3e748ddc690ed6ea9d71ac (patch) | |
tree | 63a4d1a736a7c44cc88b69e41dec9c4885ef2f74 /net/caif/cfcnfg.c | |
parent | caif: Bugfix add check NULL pointer before calling functions. (diff) | |
download | linux-54e90fb5ca8050156d3e748ddc690ed6ea9d71ac.tar.xz linux-54e90fb5ca8050156d3e748ddc690ed6ea9d71ac.zip |
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.c | 44 |
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) int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) { - u8 channel_id = 0; - int ret = 0; - struct cflayer *servl = NULL; + u8 channel_id; struct cfcnfg *cfg = get_cfcnfg(net); caif_assert(adap_layer != NULL); - - channel_id = adap_layer->id; - if (adap_layer->dn == NULL || channel_id == 0) { - pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n"); - ret = -ENOTCONN; - goto end; - } - - servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); - if (servl == NULL) { - pr_err("PROTOCOL ERROR - " - "Error removing service_layer Channel_Id(%d)", - channel_id); - ret = -EINVAL; - goto end; - } - - ret = cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); - -end: cfctrl_cancel_req(cfg->ctrl, adap_layer); + channel_id = adap_layer->id; + if (channel_id != 0) { + struct cflayer *servl; + servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); + if (servl != NULL) + layer_set_up(servl, NULL); + } else + pr_debug("nothing to disconnect\n"); + cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); /* Do RCU sync before initiating cleanup */ synchronize_rcu(); if (adap_layer->ctrlcmd != NULL) adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); - return ret; + return 0; } EXPORT_SYMBOL(caif_disconnect_client); @@ -400,6 +387,14 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, struct cfcnfg_phyinfo *phyinfo; struct net_device *netdev; + if (channel_id == 0) { + pr_warn("received channel_id zero\n"); + if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) + adapt_layer->ctrlcmd(adapt_layer, + CAIF_CTRLCMD_INIT_FAIL_RSP, 0); + return; + } + rcu_read_lock(); if (adapt_layer == NULL) { @@ -523,7 +518,6 @@ got_phyid: phyinfo->use_stx = stx; phyinfo->use_fcs = fcs; - phy_layer->type = phy_type; frml = cffrml_create(phyid, fcs); if (!frml) { |