Bug? 2.6.29-rc1 on cat /proc/net/wireless
John W. Linville
linville at tuxdriver.com
Mon Jan 12 10:12:44 EST 2009
I guess this looks OK -- any comments from the libertas guys?
Do you get the same BUG w/o Colin's patch? Did you try any other
bisection?
Thanks,
John
On Mon, Jan 12, 2009 at 03:00:06PM +0000, Jonathan Cameron wrote:
> Jonathan Cameron wrote:
> > Sorry all if this has already been fixed, but with 2.6.29-rc1 +
> > Colin McCabe's alignment fix of the other day (can't see the
> > relevance but that's what I'm running) just got the following
> > with an sdio connected 8686. I'll try tracking this one down
> > tomorrow if I don't hear anything.
> >
> > cat /proc/net/wireless
> > BUG: scheduling while atomic: cat/1272/0x00000002
> > Modules linked in: max1363 ring_sw iio_trig_periodic_rtc industrialio rtc_pxa27x rtc_core libertas_sdio libertas lib80211 pxamci mmc_core
> > [<c00227c8>] (dump_stack+0x0/0x14) from [<c00318f4>] (__schedule_bug+0x4c/0x58)
> > [<c00318a8>] (__schedule_bug+0x0/0x58) from [<c020c61c>] (__sched_text_start+0x64/0x308)
> > r4:c1116000
> > [<c020c5b8>] (__sched_text_start+0x0/0x308) from [<bf025b3c>] (__lbs_cmd+0xd8/0x154 [libertas])
> > [<bf025a64>] (__lbs_cmd+0x0/0x154 [libertas]) from [<bf021eec>] (lbs_get_wireless_stats+0xec/0x26c [libertas])
> > [<bf021e00>] (lbs_get_wireless_stats+0x0/0x26c [libertas]) from [<c020a0b4>] (get_wireless_stats+0x30/0x3c)
> > [<c020a084>] (get_wireless_stats+0x0/0x3c) from [<c020a24c>] (wireless_seq_show+0x38/0x110)
> > [<c020a214>] (wireless_seq_show+0x0/0x110) from [<c00a668c>] (seq_read+0x2ac/0x404)
> > r5:c1117ee8 r4:c1194000
> > [<c00a63e0>] (seq_read+0x0/0x404) from [<c00c6ec4>] (proc_reg_read+0xac/0xc0)
> > [<c00c6e18>] (proc_reg_read+0x0/0xc0) from [<c008d2f0>] (vfs_read+0xc8/0x14c)
> > [<c008d228>] (vfs_read+0x0/0x14c) from [<c008d620>] (sys_read+0x4c/0x74)
> > r7:00000000 r6:c1117f78 r5:c1387c80 r4:c1387ca0
> > [<c008d5d4>] (sys_read+0x0/0x74) from [<c001ef00>] (ret_fast_syscall+0x0/0x2c)
> > r8:c001f0a4 r7:00000003 r6:00000003 r5:bea33c64 r4:00001000
> > Inter-| sta-| Quality | Discarded packets | Missed | WE
> > face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
> > eth0: 0002 95. -36. -81. 0 363 0 1179 236246 0
> >
> A bit of googling suggests this has been a much discussed problem in other drivers.
>
> How about the following patch as a work around? Bit messy at the mo, but I want
> to check people are happy with basic form before cleaning up (and confirming
> everything relevant has been set!)
>
> Basically does the same as various other wireless drivers and actually gives you
> the values from the last time it was queried rather than current.
>
> --
>
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index b1326e6..e51e1c5 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -1345,7 +1345,7 @@ void lbs_set_mac_control(struct lbs_private *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,
> @@ -1487,6 +1487,13 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
> 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) +
> + S_DS_GEN);
> + ret = 0;
> + break;
> +
> case CMD_GET_TSF:
> cmdptr->command = cpu_to_le16(CMD_GET_TSF);
> cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
> @@ -1496,6 +1503,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
> case CMD_802_11_BEACON_CTRL:
> ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
> break;
> +
> default:
> lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
> ret = -1;
> diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
> index 14f54ad..af18b5d 100644
> --- a/drivers/net/wireless/libertas/cmdresp.c
> +++ b/drivers/net/wireless/libertas/cmdresp.c
> @@ -200,7 +200,21 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
> get_unaligned_le16(&bcn_ctrl->beacon_period);
> }
>
> + lbs_deb_leave(LBS_DEB_CMD);
> + return 0;
> +}
> +
> +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;
> }
>
> @@ -284,7 +298,9 @@ static inline int handle_cmd_response(struct lbs_private *priv,
> 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",
> get_unaligned_le16(&resp->command));
> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> index c6d5771..00423f7 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -736,6 +736,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_associate associate;
> struct cmd_ds_802_11_authenticate auth;
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index e1700a1..8c7201f 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -789,7 +789,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> int stats_valid = 0;
> u8 rssi;
> u32 tx_retries;
> - struct cmd_ds_802_11_get_log log;
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> @@ -805,12 +804,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> 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);
> @@ -831,13 +829,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> quality = rssi_qual;
>
> /* Quality by TX errors */
> - priv->wstats.discard.retries = priv->stats.tx_errors;
> + /* Previously this line was here, but the value was overwritten
> + * a few lines later.
> + * priv->wstats.discard.retries = priv->stats.tx_errors; */
>
> - memset(&log, 0, sizeof(log));
> - log.hdr.size = cpu_to_le16(sizeof(log));
> - lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
> -
> - tx_retries = get_unaligned_le32(&log.retry);
> + tx_retries = priv->wstats.discard.retries;
>
> if (tx_retries > 75)
> tx_qual = (90 - tx_retries) * POOR / 15;
> @@ -847,16 +843,12 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> 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 = get_unaligned_le32(&log.wepundecryptable);
> - priv->wstats.discard.retries = tx_retries;
> - priv->wstats.discard.misc = get_unaligned_le32(&log.ackfailure);
> -
> /* Calculate quality */
> priv->wstats.qual.qual = min_t(u8, quality, 100);
> priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
> @@ -865,6 +857,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> /* update stats asynchronously for future calls */
> lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
> 0, 0, NULL);
> +
> + lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
> + 0, 0, NULL);
> out:
> if (!stats_valid) {
> priv->wstats.miss.beacon = 0;
>
--
John W. Linville Linux should be at the core
linville at tuxdriver.com of your literate lifestyle.
More information about the libertas-dev
mailing list