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