Skip to content

Commit

Permalink
caif: Disconnect without waiting for response
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sjur Braendeland authored and David S. Miller committed Apr 28, 2010
1 parent 5b20865 commit 8d545c8
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 146 deletions.
7 changes: 4 additions & 3 deletions include/net/caif/cfctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ struct cfctrl_rsp {
void (*linksetup_rsp)(struct cflayer *layer, u8 linkid,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid,
struct cflayer *client_layer);
void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid);
void (*linkerror_ind)(void);
void (*enum_rsp)(void);
void (*sleep_rsp)(void);
Expand Down Expand Up @@ -117,7 +116,7 @@ struct cfctrl {
};

void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid);
void cfctrl_linkup_request(struct cflayer *cfctrl,
int cfctrl_linkup_request(struct cflayer *cfctrl,
struct cfctrl_link_param *param,
struct cflayer *user_layer);
int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid,
Expand All @@ -135,4 +134,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl,
struct cfctrl_request_info *req);
struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
struct cfctrl_request_info *req);
void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer);

#endif /* CFCTRL_H_ */
155 changes: 45 additions & 110 deletions net/caif/cfcnfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ struct cfcnfg {
static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *client_layer);
static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *adapt_layer);
static void cfctrl_resp_func(void);
Expand Down Expand Up @@ -175,73 +174,65 @@ int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
return 0;
}

/*
* NOTE: What happens on destroy failure:
* 1a) No response - Too early
* This will not happen because enumerate has already
* completed.
* 1b) No response - FATAL
* Not handled, but this should be a CAIF PROTOCOL ERROR
* Modem error, response is really expected - this
* case is not really handled.
* 2) O/E-bit indicate error
* Ignored - this link is destroyed anyway.
* 3) Not able to match on request
* Not handled, but this should be a CAIF PROTOCOL ERROR
* 4) Link-Error - (no response)
* Not handled, but this should be a CAIF PROTOCOL ERROR
*/
int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
{
u8 channel_id = 0;
int ret = 0;
struct cflayer *servl = NULL;
struct cfcnfg_phyinfo *phyinfo = NULL;
u8 phyid = 0;

caif_assert(adap_layer != NULL);
channel_id = adap_layer->id;
if (channel_id == 0) {
if (adap_layer->dn == NULL || channel_id == 0) {
pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
ret = -ENOTCONN;
goto end;
}

if (adap_layer->dn == NULL) {
pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__);
ret = -ENODEV;
goto end;
}

if (adap_layer->dn != NULL)
phyid = cfsrvl_getphyid(adap_layer->dn);

phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
if (phyinfo == NULL) {
pr_warning("CAIF: %s(): No interface to send disconnect to\n",
__func__);
ret = -ENODEV;
servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
if (servl == NULL)
goto end;
}

if (phyinfo->id != phyid
|| phyinfo->phy_layer->id != phyid
|| phyinfo->frm_layer->id != phyid) {

pr_err("CAIF: %s(): Inconsistency in phy registration\n",
__func__);
layer_set_up(servl, NULL);
ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
if (servl == NULL) {
pr_err("CAIF: %s(): PROTOCOL ERROR "
"- Error removing service_layer Channel_Id(%d)",
__func__, channel_id);
ret = -EINVAL;
goto end;
}
caif_assert(channel_id == servl->id);
if (adap_layer->dn != NULL) {
phyid = cfsrvl_getphyid(adap_layer->dn);

ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);

end:
phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
if (phyinfo == NULL) {
pr_warning("CAIF: %s(): "
"No interface to send disconnect to\n",
__func__);
ret = -ENODEV;
goto end;
}
if (phyinfo->id != phyid ||
phyinfo->phy_layer->id != phyid ||
phyinfo->frm_layer->id != phyid) {
pr_err("CAIF: %s(): "
"Inconsistency in phy registration\n",
__func__);
ret = -EINVAL;
goto end;
}
}
if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 &&
phyinfo->phy_layer != NULL &&
phyinfo->phy_layer->modemcmd != NULL) {
phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
_CAIF_MODEMCMD_PHYIF_USELESS);
}
end:
cfsrvl_put(servl);
cfctrl_cancel_req(cnfg->ctrl, adap_layer);
if (adap_layer->ctrlcmd != NULL)
adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
return ret;

}
Expand All @@ -254,69 +245,11 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
}
EXPORT_SYMBOL(cfcnfg_release_adap_layer);

static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *client_layer)
static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
{
struct cfcnfg *cnfg = container_obj(layer);
struct cflayer *servl;

/*
* 1) Remove service from the MUX layer. The MUX must
* guarante that no more payload sent "upwards" (receive)
*/
servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);

if (servl == NULL) {
pr_err("CAIF: %s(): PROTOCOL ERROR "
"- Error removing service_layer Channel_Id(%d)",
__func__, channel_id);
return;
}
caif_assert(channel_id == servl->id);

if (servl != client_layer && servl->up != client_layer) {
pr_err("CAIF: %s(): Error removing service_layer "
"Channel_Id(%d) %p %p",
__func__, channel_id, (void *) servl,
(void *) client_layer);
return;
}

/*
* 2) DEINIT_RSP must guarantee that no more packets are transmitted
* from client (adap_layer) when it returns.
*/

if (servl->ctrlcmd == NULL) {
pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__);
return;
}

servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0);

/* 3) It is now safe to destroy the service layer. */
cfservl_destroy(servl);
}

/*
* NOTE: What happens on linksetup failure:
* 1a) No response - Too early
* This will not happen because enumerate is secured
* before using interface.
* 1b) No response - FATAL
* Not handled, but this should be a CAIF PROTOCOL ERROR
* Modem error, response is really expected - this case is
* not really handled.
* 2) O/E-bit indicate error
* Handled in cnfg_reject_rsp
* 3) Not able to match on request
* Not handled, but this should be a CAIF PROTOCOL ERROR
* 4) Link-Error - (no response)
* Not handled, but this should be a CAIF PROTOCOL ERROR
*/

int
cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
struct cfctrl_link_param *param,
struct cflayer *adap_layer)
{
Expand Down Expand Up @@ -346,8 +279,7 @@ cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
param->phyid);
/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
cfctrl_enum_req(cnfg->ctrl, param->phyid);
cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
return 0;
return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
}
EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);

Expand All @@ -367,8 +299,10 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
struct cflayer *servicel = NULL;
struct cfcnfg_phyinfo *phyinfo;
if (adapt_layer == NULL) {
pr_err("CAIF: %s(): PROTOCOL ERROR "
"- LinkUp Request/Response did not match\n", __func__);
pr_debug("CAIF: %s(): link setup response "
"but no client exist, send linkdown back\n",
__func__);
cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
return;
}

Expand Down Expand Up @@ -424,6 +358,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
layer_set_up(servicel, adapt_layer);
layer_set_dn(adapt_layer, servicel);
cfsrvl_get(servicel);
servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
}

Expand Down
Loading

0 comments on commit 8d545c8

Please sign in to comment.