diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-22 07:18:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-22 20:11:47 -0400 |
commit | 54e90fb5ca8050156d3e748ddc690ed6ea9d71ac (patch) | |
tree | 63a4d1a736a7c44cc88b69e41dec9c4885ef2f74 /net/caif/cfcnfg.c | |
parent | 0e5a117441ce245b87949cc7713627a293f37227 (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.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) | |||
182 | 182 | ||
183 | int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) | 183 | int 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 | |||
210 | end: | ||
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 | } |
220 | EXPORT_SYMBOL(caif_disconnect_client); | 207 | EXPORT_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) { |