Search Linux Wireless

Re: Re: [PATCH v4 1/3] mwifiex: refactor device dump code to make it generic for usb interface

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

 



Hi Brian,

> -----Original Message-----
> From: Brian Norris [mailto:briannorris@xxxxxxxxxxxx]
> Sent: 2017年12月6日 2:26
> To: Xinming Hu <huxm@xxxxxxxxxxx>
> Cc: Linux Wireless <linux-wireless@xxxxxxxxxxxxxxx>; Kalle Valo
> <kvalo@xxxxxxxxxxxxxx>; Dmitry Torokhov <dtor@xxxxxxxxxx>;
> rajatja@xxxxxxxxxx; Zhiyuan Yang <yangzy@xxxxxxxxxxx>; Tim Song
> <songtao@xxxxxxxxxxx>; Cathy Luo <cluo@xxxxxxxxxxx>; James Cao
> <jcao@xxxxxxxxxxx>; Ganapathi Bhat <gbhat@xxxxxxxxxxx>; Ellie Reeves
> <ellierevves@xxxxxxxxx>
> Subject: [EXT] Re: [PATCH v4 1/3] mwifiex: refactor device dump code to make it
> generic for usb interface
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi,
> 
> On Mon, Dec 04, 2017 at 08:18:42PM +0800, Xinming Hu wrote:
> > This patch refactor current device dump code to make it generic for
> > subsequent implementation on usb interface.
> 
> I still think you're making the spaghetti worse. I only have a few specific
> suggestions for improving your spaghetti code at the moment, but I'm still sure
> you could do better.
> 

Ok, Thanks.

> > Signed-off-by: Xinming Hu <huxm@xxxxxxxxxxx>
> > Signed-off-by: Cathy Luo <cluo@xxxxxxxxxxx>
> > Signed-off-by: Ganapathi Bhat <gbhat@xxxxxxxxxxx>
> > ---
> > v2: Addressed below review comments from Brian Norris
> >     a) use new API timer_setup/from_timer.
> >     b) reset devdump_len during initization
> > v4: Same as v2,v3
> > ---
> >  drivers/net/wireless/marvell/mwifiex/init.c |  1 +
> > drivers/net/wireless/marvell/mwifiex/main.c | 87
> > +++++++++++++++--------------
> > drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
> > drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
> > drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
> >  5 files changed, 72 insertions(+), 54 deletions(-)
> >
> > diff --git a/drivers/net/wireless/marvell/mwifiex/init.c
> > b/drivers/net/wireless/marvell/mwifiex/init.c
> > index e1aa860..b0d3d68 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/init.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> > @@ -314,6 +314,7 @@ static void mwifiex_init_adapter(struct
> mwifiex_adapter *adapter)
> >  	adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
> >  	adapter->active_scan_triggered = false;
> >  	timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
> > +	adapter->devdump_len = 0;
> >  }
> >
> >  /*
> > diff --git a/drivers/net/wireless/marvell/mwifiex/main.c
> > b/drivers/net/wireless/marvell/mwifiex/main.c
> > index a96bd7e..f7d0299 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/main.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> > @@ -1051,9 +1051,23 @@ void mwifiex_multi_chan_resync(struct
> > mwifiex_adapter *adapter)  }
> > EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
> >
> > -int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void
> > **drv_info)
> > +void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
> >  {
> > -	void *p;
> > +	/* Dump all the memory data into single file, a userspace script will
> > +	 * be used to split all the memory data to multiple files
> > +	 */
> > +	mwifiex_dbg(adapter, MSG,
> > +		    "== mwifiex dump information to /sys/class/devcoredump
> start\n");
> > +	dev_coredumpv(adapter->dev, adapter->devdump_data,
> adapter->devdump_len,
> > +		      GFP_KERNEL);
> 
> Seems like you should reset adapter->devdump_data and ->devdump_len here,
> so you don't accidentally reuse it? (You're expecting
> dev_coredumpv() to free the buffer, no?)
> 

Oh, yes, I was expect dev_coredumpv to free the buffer, the dev_coredump framework will free dump data after 5 minutes.
What's more, If there is new coredump in 5 minutes, the new dump data will be discard and free.
Consider below sequence happens in command timeout context:
Mwifiex_cmd_tmo_func
(1)  -->   firmware dump 1 -->    devcoredump 1
(2)  -->  card_reset --> init software
				Command timeout happens again	in 5 minutes -->  firmware dump 2  -->   devcoredump 2

Here, if we free adapter-> devdump_data, and  then user cat devcoredump1, will crash the kernel


I think, here, Regards "reset adapter->devdump_data", you mean adapter->devdump_data = NULL, But not free it, right ?

> > +	mwifiex_dbg(adapter, MSG,
> > +		    "== mwifiex dump information to /sys/class/devcoredump
> end\n");
> > +} EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
> > +
> > +void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) {
> > +	char *p;
> >  	char drv_version[64];
> >  	struct usb_card_rec *cardp;
> >  	struct sdio_mmc_card *sdio_card;
> > @@ -1061,17 +1075,12 @@ int mwifiex_drv_info_dump(struct
> mwifiex_adapter *adapter, void **drv_info)
> >  	int i, idx;
> >  	struct netdev_queue *txq;
> >  	struct mwifiex_debug_info *debug_info;
> > -	void *drv_info_dump;
> >
> >  	mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
> >
> > -	/* memory allocate here should be free in mwifiex_upload_device_dump*/
> > -	drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
> > -
> > -	if (!drv_info_dump)
> > -		return 0;
> > -
> > -	p = (char *)(drv_info_dump);
> > +	p = adapter->devdump_data;
> > +	strcpy(p, "========Start dump driverinfo========\n");
> > +	p += strlen("========Start dump driverinfo========\n");
> >  	p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
> >
> >  	mwifiex_drv_get_driver_version(adapter, drv_version, @@ -1155,21
> > +1164,18 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter,
> void **drv_info)
> >  		kfree(debug_info);
> >  	}
> >
> > +	strcpy(p, "\n========End dump========\n");
> > +	p += strlen("\n========End dump========\n");
> >  	mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
> > -	*drv_info = drv_info_dump;
> > -	return p - drv_info_dump;
> > +	adapter->devdump_len = p - (char *)adapter->devdump_data;
> >  }
> >  EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
> >
> > -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void
> *drv_info,
> > -				int drv_info_size)
> > +void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter)
> >  {
> > -	u8 idx, *dump_data, *fw_dump_ptr;
> > -	u32 dump_len;
> > -
> > -	dump_len = (strlen("========Start dump driverinfo========\n") +
> > -		       drv_info_size +
> > -		       strlen("\n========End dump========\n"));
> > +	u8 idx;
> > +	char *fw_dump_ptr;
> > +	u32 dump_len = 0;
> >
> >  	for (idx = 0; idx < adapter->num_mem_types; idx++) {
> >  		struct memory_type_mapping *entry = @@ -1184,24 +1190,24 @@
> void
> > mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void
> *drv_info,
> >  		}
> >  	}
> >
> > -	dump_data = vzalloc(dump_len + 1);
> > -	if (!dump_data)
> > -		goto done;
> > -
> > -	fw_dump_ptr = dump_data;
> > +	if (dump_len + 1 + adapter->devdump_len > MWIFIEX_FW_DUMP_SIZE) {
> > +		/* Realloc in case buffer overflow */
> > +		fw_dump_ptr = vzalloc(dump_len + 1 + adapter->devdump_len);
> > +		mwifiex_dbg(adapter, MSG, "Realloc device dump data.\n");
> > +		if (!fw_dump_ptr) {
> > +			vfree(adapter->devdump_data);
> > +			mwifiex_dbg(adapter, ERROR,
> > +				    "vzalloc devdump data failure!\n");
> > +			return;
> > +		}
> >
> > -	/* Dump all the memory data into single file, a userspace script will
> > -	 * be used to split all the memory data to multiple files
> > -	 */
> > -	mwifiex_dbg(adapter, MSG,
> > -		    "== mwifiex dump information to /sys/class/devcoredump
> start");
> > +		memmove(fw_dump_ptr, adapter->devdump_data,
> > +			adapter->devdump_len);
> > +		vfree(adapter->devdump_data);
> > +		adapter->devdump_data = fw_dump_ptr;
> > +	}
> >
> > -	strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
> > -	fw_dump_ptr += strlen("========Start dump driverinfo========\n");
> > -	memcpy(fw_dump_ptr, drv_info, drv_info_size);
> > -	fw_dump_ptr += drv_info_size;
> > -	strcpy(fw_dump_ptr, "\n========End dump========\n");
> > -	fw_dump_ptr += strlen("\n========End dump========\n");
> > +	fw_dump_ptr = (char *)adapter->devdump_data +
> adapter->devdump_len;
> >
> >  	for (idx = 0; idx < adapter->num_mem_types; idx++) {
> >  		struct memory_type_mapping *entry = @@ -1228,11 +1234,8 @@
> void
> > mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void
> *drv_info,
> >  	/* device dump data will be free in device coredump release function
> >  	 * after 5 min
> >  	 */
> 
> ^^ This comment is a bit out of place now. The data is not dumped until we call
> mwifiex_upload_device_dump(), and so we don't guarantee anyone will
> actually free it for us until then
> 

Okay.

> > -	dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
> > -	mwifiex_dbg(adapter, MSG,
> > -		    "== mwifiex dump information to /sys/class/devcoredump end");
> > +	adapter->devdump_len = fw_dump_ptr - (char *)adapter->devdump_data;
> >
> > -done:
> >  	for (idx = 0; idx < adapter->num_mem_types; idx++) {
> >  		struct memory_type_mapping *entry =
> >  			&adapter->mem_type_mapping_tbl[idx];
> > @@ -1241,10 +1244,8 @@ void mwifiex_upload_device_dump(struct
> mwifiex_adapter *adapter, void *drv_info,
> >  		entry->mem_ptr = NULL;
> >  		entry->mem_size = 0;
> >  	}
> > -
> > -	vfree(drv_info);
> >  }
> > -EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
> > +EXPORT_SYMBOL_GPL(mwifiex_prepare_fw_dump_info);
> >
> >  /*
> >   * CFG802.11 network device handler for statistics retrieval.
> > diff --git a/drivers/net/wireless/marvell/mwifiex/main.h
> > b/drivers/net/wireless/marvell/mwifiex/main.h
> > index 154c079..8b6241a 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/main.h
> > +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> > @@ -94,6 +94,8 @@ enum {
> >
> >  #define MAX_EVENT_SIZE                  2048
> >
> > +#define MWIFIEX_FW_DUMP_SIZE       (2 * 1024 * 1024)
> > +
> >  #define ARP_FILTER_MAX_BUF_SIZE         68
> >
> >  #define MWIFIEX_KEY_BUFFER_SIZE			16
> > @@ -1032,6 +1034,9 @@ struct mwifiex_adapter {
> >  	bool wake_by_wifi;
> >  	/* Aggregation parameters*/
> >  	struct bus_aggr_params bus_aggr;
> > +	/* Device dump data/length */
> > +	void *devdump_data;
> > +	int devdump_len;
> >  };
> >
> >  void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); @@
> > -1656,9 +1661,9 @@ void mwifiex_hist_data_add(struct mwifiex_private
> > *priv,
> >  u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
> >  			    u8 rx_rate, u8 ht_info);
> >
> > -int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void
> > **drv_info); -void mwifiex_upload_device_dump(struct mwifiex_adapter
> *adapter, void *drv_info,
> > -				int drv_info_size);
> > +void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); void
> > +mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter); void
> > +mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
> >  void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);  void
> > mwifiex_queue_main_work(struct mwifiex_adapter *adapter);  int
> > mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
> > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > index cd31494..f666cb2 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > @@ -2769,12 +2769,17 @@ static void mwifiex_pcie_fw_dump(struct
> > mwifiex_adapter *adapter)
> >
> >  static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter
> > *adapter)  {
> > -	int drv_info_size;
> > -	void *drv_info;
> > +	adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
> 
> I'm still not sure why you need 3 different callers to allocate the same size
> buffer. It seems like this should all be done in the core.
> 

I had thought of put memory allocation and drv_info_dump into 1 function , and let it called in device_dump.
But it looks quite strange.
Consider the different implementation on usb, let these sub functions works in a loose coupling way seems better to reuse than a "core" architecture.

Please let us know if you have more suggestions to enhance this part

Thanks & Regards,
Simon

> Brian
> 
> > +	if (!adapter->devdump_data) {
> > +		mwifiex_dbg(adapter, ERROR,
> > +			    "vzalloc devdump data failure!\n");
> > +		return;
> > +	}
> >
> > -	drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
> > +	mwifiex_drv_info_dump(adapter);
> >  	mwifiex_pcie_fw_dump(adapter);
> > -	mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
> > +	mwifiex_prepare_fw_dump_info(adapter);
> > +	mwifiex_upload_device_dump(adapter);
> >  }
> >
> >  static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter
> > *adapter) diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > index fd5183c..a828801 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> > @@ -2505,15 +2505,21 @@ static void
> > mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)  static
> > void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)  {
> >  	struct sdio_mmc_card *card = adapter->card;
> > -	int drv_info_size;
> > -	void *drv_info;
> >
> > -	drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
> > +	adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
> > +	if (!adapter->devdump_data) {
> > +		mwifiex_dbg(adapter, ERROR,
> > +			    "vzalloc devdump data failure!\n");
> > +		return;
> > +	}
> > +
> > +	mwifiex_drv_info_dump(adapter);
> >  	if (card->fw_dump_enh)
> >  		mwifiex_sdio_generic_fw_dump(adapter);
> >  	else
> >  		mwifiex_sdio_fw_dump(adapter);
> > -	mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
> > +	mwifiex_prepare_fw_dump_info(adapter);
> > +	mwifiex_upload_device_dump(adapter);
> >  }
> >
> >  static void mwifiex_sdio_work(struct work_struct *work)
> > --
> > 1.9.1
> >




[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