aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/cfcnfg.c
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/cfcnfg.c
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/cfcnfg.c')
-rw-r--r--net/caif/cfcnfg.c155
1 files changed, 45 insertions, 110 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