Search Linux Wireless

RE: [PATCH v2 01/12] mwifiex: check tx_hw_pending before downloading sleep confirm

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

> -----Original Message-----
> From: Brian Norris [mailto:briannorris@xxxxxxxxxxxx]
> Sent: 2016年11月4日 0:12
> To: Xinming Hu
> Cc: Linux Wireless; Kalle Valo; Dmitry Torokhov; Amitkumar Karwar; Cathy Luo;
> Shengzhen Li; Xinming Hu; Wei-Ning Huang
> Subject: Re: [PATCH v2 01/12] mwifiex: check tx_hw_pending before
> downloading sleep confirm
> 
> + Wei-Ning
> 
> On Tue, Nov 01, 2016 at 08:08:17PM +0800, Xinming Hu wrote:
> > From: Shengzhen Li <szli@xxxxxxxxxxx>
> >
> > We may get SLEEP event from firmware even if TXDone interrupt for last
> > Tx packet is still pending. In this case, we may end up accessing PCIe
> > memory for handling TXDone after power save handshake is completed.
> > This causes kernel crash with external abort.
> >
> > This patch will only allow downloading sleep confirm when no tx done
> > interrupt is pending in the hardware.
> >
> > ---
> > v2: address format issues(Brain)
> > ---
> 
> Nit: typically, it's best if the changelog is placed after the Sign-offs, so that the
> first "---" line denotes the beginning of text that can be discarded. (Typically
> the changelog doesn't go into the final git commit, and it also happens that
> git-am discards everything between the first "---" line and the actual patch
> content.)
> 

Ok, we will address this in updated version.

> > Signed-off-by: Cathy Luo <cluo@xxxxxxxxxxx>
> > Signed-off-by: Shengzhen Li <szli@xxxxxxxxxxx>
> > Signed-off-by: Xinming Hu <huxm@xxxxxxxxxxx>
> > Signed-off-by: Amitkumar Karwar <akarwar@xxxxxxxxxxx>
> > ---
> >  drivers/net/wireless/marvell/mwifiex/cmdevt.c | 5 +++--
> >  drivers/net/wireless/marvell/mwifiex/init.c   | 1 +
> >  drivers/net/wireless/marvell/mwifiex/main.h   | 1 +
> >  drivers/net/wireless/marvell/mwifiex/pcie.c   | 5 +++++
> >  4 files changed, 10 insertions(+), 2 deletions(-)
> 
> Overall, I think this change is good, and it tests out fine for me so far. Do we
> have the same problem for other interfaces too? e.g., SDIO?
> It seems to me that the root problem is generic (i.e., don't try to SLEEP while
> processing TX traffic) but the symptom just happened to be fatal on a
> particular PCIe controller.
> 

For SDIO interface, command 53 write return indicate tx complete on the bus, no any pending packets in hardware then.
So, SDIO interface don't have the same issue as PCIE. 

> Brian
> 
> > diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> > b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> > index 5347728..25a7475 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> > @@ -1118,13 +1118,14 @@ mwifiex_cancel_pending_ioctl(struct
> > mwifiex_adapter *adapter)  void  mwifiex_check_ps_cond(struct
> > mwifiex_adapter *adapter)  {
> > -	if (!adapter->cmd_sent &&
> > +	if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) &&
> >  	    !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
> >  		mwifiex_dnld_sleep_confirm_cmd(adapter);
> >  	else
> >  		mwifiex_dbg(adapter, CMD,
> > -			    "cmd: Delay Sleep Confirm (%s%s%s)\n",
> > +			    "cmd: Delay Sleep Confirm (%s%s%s%s)\n",
> >  			    (adapter->cmd_sent) ? "D" : "",
> > +			    atomic_read(&adapter->tx_hw_pending) ? "T" : "",
> >  			    (adapter->curr_cmd) ? "C" : "",
> >  			    (IS_CARD_RX_RCVD(adapter)) ? "R" : "");  } diff --git
> > a/drivers/net/wireless/marvell/mwifiex/init.c
> > b/drivers/net/wireless/marvell/mwifiex/init.c
> > index 82839d9..b36cb3f 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/init.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> > @@ -270,6 +270,7 @@ static void mwifiex_init_adapter(struct
> mwifiex_adapter *adapter)
> >  	adapter->adhoc_11n_enabled = false;
> >
> >  	mwifiex_wmm_init(adapter);
> > +	atomic_set(&adapter->tx_hw_pending, 0);
> >
> >  	sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
> >  					adapter->sleep_cfm->data;
> > diff --git a/drivers/net/wireless/marvell/mwifiex/main.h
> > b/drivers/net/wireless/marvell/mwifiex/main.h
> > index d61fe3a..7f67f23 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/main.h
> > +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> > @@ -857,6 +857,7 @@ struct mwifiex_adapter {
> >  	atomic_t rx_pending;
> >  	atomic_t tx_pending;
> >  	atomic_t cmd_pending;
> > +	atomic_t tx_hw_pending;
> >  	struct workqueue_struct *workqueue;
> >  	struct work_struct main_work;
> >  	struct workqueue_struct *rx_workqueue; diff --git
> > a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > index 063c707..4aa5d91 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > @@ -516,6 +516,7 @@ static int mwifiex_pcie_enable_host_int(struct
> mwifiex_adapter *adapter)
> >  		}
> >  	}
> >
> > +	atomic_set(&adapter->tx_hw_pending, 0);
> >  	return 0;
> >  }
> >
> > @@ -689,6 +690,7 @@ static void mwifiex_cleanup_txq_ring(struct
> mwifiex_adapter *adapter)
> >  		card->tx_buf_list[i] = NULL;
> >  	}
> >
> > +	atomic_set(&adapter->tx_hw_pending, 0);
> >  	return;
> >  }
> >
> > @@ -1126,6 +1128,7 @@ static int mwifiex_pcie_send_data_complete(struct
> mwifiex_adapter *adapter)
> >  							    -1);
> >  			else
> >  				mwifiex_write_data_complete(adapter, skb, 0, 0);
> > +			atomic_dec(&adapter->tx_hw_pending);
> >  		}
> >
> >  		card->tx_buf_list[wrdoneidx] = NULL; @@ -1218,6 +1221,7 @@
> > mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff
> *skb,
> >  		wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
> >  		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
> >  		card->tx_buf_list[wrindx] = skb;
> > +		atomic_inc(&adapter->tx_hw_pending);
> >
> >  		if (reg->pfu_enabled) {
> >  			desc2 = card->txbd_ring[wrindx];
> > @@ -1295,6 +1299,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter
> > *adapter, struct sk_buff *skb,
> >  done_unmap:
> >  	mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
> >  	card->tx_buf_list[wrindx] = NULL;
> > +	atomic_dec(&adapter->tx_hw_pending);
> >  	if (reg->pfu_enabled)
> >  		memset(desc2, 0, sizeof(*desc2));
> >  	else
> > --
> > 1.8.1.4
> >




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux