This is a rewamp of a patch to change the way GET_LOG is called within the libertas driver. Without this patch my UMID with a libertas_sdio card locks up solid when trying to associate with an access point. The only reference to the old patch I could find is this: http://lists.infradead.org/pipermail/libertas-dev/2009-June/002496.html but credit where credit is due since I didn't write the original patch. Signed-off-by: Jes Sorensen --- Index: linux-2.6.33.i686/drivers/net/wireless/libertas/cmd.c =================================================================== --- linux-2.6.33.i686.orig/drivers/net/wireless/libertas/cmd.c +++ linux-2.6.33.i686/drivers/net/wireless/libertas/cmd.c @@ -909,7 +909,7 @@ void lbs_set_mac_control(struct lbs_priv * @param cmd_action command action: GET or SET * @param wait_option wait option: wait response or not * @param cmd_oid cmd oid: treated as sub command - * @param pdata_buf A pointer to informaion buffer + * @param pdata_buf A pointer to information buffer * @return 0 or -1 */ int lbs_prepare_and_send_command(struct lbs_private *priv, @@ -1019,6 +1019,13 @@ int lbs_prepare_and_send_command(struct ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); break; + case CMD_802_11_GET_LOG: + cmdptr->command = cpu_to_le16(CMD_802_11_GET_LOG); + cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log)+ + sizeof(struct cmd_header)); + ret = 0; + break; + case CMD_802_11_BEACON_CTRL: ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); break; @@ -1026,6 +1033,7 @@ int lbs_prepare_and_send_command(struct cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); cmdptr->size = cpu_to_le16(sizeof(struct cmd_header)); break; + default: lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); ret = -1; Index: linux-2.6.33.i686/drivers/net/wireless/libertas/cmdresp.c =================================================================== --- linux-2.6.33.i686.orig/drivers/net/wireless/libertas/cmdresp.c +++ linux-2.6.33.i686/drivers/net/wireless/libertas/cmdresp.c @@ -116,6 +116,21 @@ static int lbs_ret_reg_access(struct lbs return ret; } + +static int lbs_ret_802_11_get_log(struct lbs_private * priv, + struct cmd_ds_command *resp) +{ + struct cmd_ds_802_11_get_log *log = &resp->params.log; + + lbs_deb_enter(LBS_DEB_CMD); + priv->wstats.discard.retries = get_unaligned_le32(&log->retry); + priv->wstats.discard.code = get_unaligned_le32(&log->wepundecryptable); + priv->wstats.discard.misc = get_unaligned_le32(&log->ackfailure); + lbs_deb_leave(LBS_DEB_CMD); + + return 0; +} + static inline int handle_cmd_response(struct lbs_private *priv, struct cmd_header *cmd_response) { @@ -173,7 +188,9 @@ static inline int handle_cmd_response(st case CMD_RET(CMD_802_11_BEACON_CTRL): ret = lbs_ret_802_11_bcn_ctrl(priv, resp); break; - + case CMD_RET(CMD_802_11_GET_LOG): + ret = lbs_ret_802_11_get_log(priv, resp); + break; default: lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n", le16_to_cpu(resp->command)); Index: linux-2.6.33.i686/drivers/net/wireless/libertas/host.h =================================================================== --- linux-2.6.33.i686.orig/drivers/net/wireless/libertas/host.h +++ linux-2.6.33.i686/drivers/net/wireless/libertas/host.h @@ -941,6 +941,7 @@ struct cmd_ds_command { /* command Body */ union { + struct cmd_ds_802_11_get_log log; struct cmd_ds_802_11_ps_mode psmode; struct cmd_ds_802_11_monitor_mode monitor; struct cmd_ds_802_11_rssi rssi; Index: linux-2.6.33.i686/drivers/net/wireless/libertas/wext.c =================================================================== --- linux-2.6.33.i686.orig/drivers/net/wireless/libertas/wext.c +++ linux-2.6.33.i686/drivers/net/wireless/libertas/wext.c @@ -855,7 +855,6 @@ static struct iw_statistics *lbs_get_wir int ret, stats_valid = 0; u8 rssi; u32 tx_retries; - struct cmd_ds_802_11_get_log log; lbs_deb_enter(LBS_DEB_WEXT); @@ -871,12 +870,11 @@ static struct iw_statistics *lbs_get_wir CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], priv->NF[TYPE_BEACON][TYPE_NOAVG]); - if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { + if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; - } else { + else priv->wstats.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); - } lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); @@ -897,15 +895,11 @@ static struct iw_statistics *lbs_get_wir quality = rssi_qual; /* Quality by TX errors */ - priv->wstats.discard.retries = dev->stats.tx_errors; - - memset(&log, 0, sizeof(log)); - log.hdr.size = cpu_to_le16(sizeof(log)); - ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); - if (ret) - goto out; + /* Previously this line was here, but the value was overwritten + * a few lines later. + * priv->wstats.discard.retries = priv->stats.tx_errors; */ - tx_retries = le32_to_cpu(log.retry); + tx_retries = priv->wstats.discard.retries; if (tx_retries > 75) tx_qual = (90 - tx_retries) * POOR / 15; @@ -915,15 +909,13 @@ static struct iw_statistics *lbs_get_wir tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; else if (tx_retries > 50) tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / - 15 + GOOD; + 15 + GOOD; else tx_qual = (50 - tx_retries) * - (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; + (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; quality = min(quality, tx_qual); - priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable); priv->wstats.discard.retries = tx_retries; - priv->wstats.discard.misc = le32_to_cpu(log.ackfailure); /* Calculate quality */ priv->wstats.qual.qual = min_t(u8, quality, 100); @@ -935,6 +927,11 @@ static struct iw_statistics *lbs_get_wir 0, 0, NULL); if (ret) lbs_pr_err("RSSI command failed\n"); + + ret = lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0, + 0, 0, NULL); + if (ret) + lbs_pr_err("GET_LOG command failed\n"); out: if (!stats_valid) { priv->wstats.miss.beacon = 0;