Search Linux Wireless

RE: Re: [PATCH v3 4/4] mwifiex: pcie: extract wifi part from combo firmware during function level reset

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

 



Hi Brain,

> -----Original Message-----
> From: Brian Norris [mailto:briannorris@xxxxxxxxxxxx]
> Sent: 2017年4月11日 9:37
> To: Xinming Hu
> Cc: Linux Wireless; Kalle Valo; Dmitry Torokhov; rajatja@xxxxxxxxxx;
> Amitkumar Karwar; Cathy Luo; Xinming Hu; Ganapathi Bhat
> Subject: [EXT] Re: [PATCH v3 4/4] mwifiex: pcie: extract wifi part from combo
> firmware during function level reset
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi,
> 
> On Mon, Apr 10, 2017 at 09:09:34AM +0000, Xinming Hu wrote:
> > From: Xinming Hu <huxm@xxxxxxxxxxx>
> >
> > A seperate wifi-only firmware was download during pcie function level reset.
> > It is in fact the tail part of wifi/bt combo firmware. Per Brian's and
> > Dmitry's suggestion, this patch extract the wifi part from combo firmware.
> >
> > After that, we can discard the redudant image in linux-firmware repo.
> >
> > Signed-off-by: Xinming Hu <huxm@xxxxxxxxxxx>
> > Signed-off-by: Ganapathi Bhat <gbhat@xxxxxxxxxxx>
> > Signed-off-by: Cathy Luo <cluo@xxxxxxxxxxx>
> > ---
> > v2: extract wifi part from combo firmware(Dimtry and Brain)
> >     add more description(Kalle)
> > v3: same as v2
> > ---
> >  drivers/net/wireless/marvell/mwifiex/fw.h   | 18 +++++++
> >  drivers/net/wireless/marvell/mwifiex/pcie.c | 83
> > ++++++++++++++++++++++++++---
> > drivers/net/wireless/marvell/mwifiex/pcie.h |  2 +
> >  3 files changed, 96 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h
> > b/drivers/net/wireless/marvell/mwifiex/fw.h
> > index 0b68374..6cf9ab9 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/fw.h
> > +++ b/drivers/net/wireless/marvell/mwifiex/fw.h
> > @@ -43,6 +43,24 @@ struct tx_packet_hdr {
> >  	struct rfc_1042_hdr rfc1042_hdr;
> >  } __packed;
> >
> > +struct mwifiex_fw_header {
> > +	__le32 dnld_cmd;
> > +	__le32 base_addr;
> > +	__le32 data_length;
> > +	__le32 crc;
> > +} __packed;
> > +
> > +struct mwifiex_fw_data {
> > +	struct mwifiex_fw_header header;
> > +	__le32 seq_num;
> > +	u8 data[1];
> > +} __packed;
> > +
> > +#define MWIFIEX_FW_DNLD_CMD_1 0x1
> > +#define MWIFIEX_FW_DNLD_CMD_5 0x5
> > +#define MWIFIEX_FW_DNLD_CMD_6 0x6
> > +#define MWIFIEX_FW_DNLD_CMD_7 0x7
> > +
> >  #define B_SUPPORTED_RATES               5
> >  #define G_SUPPORTED_RATES               9
> >  #define BG_SUPPORTED_RATES              13
> > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > index a07cb0a..ebf00d9 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > @@ -1956,6 +1956,63 @@ static int mwifiex_pcie_event_complete(struct
> mwifiex_adapter *adapter,
> >  	return ret;
> >  }
> >
> > +/* Extract wifi part from wifi-bt combo firmware image.
> > + */
> > +
> > +static int mwifiex_extract_wifi_fw(struct mwifiex_adapter *adapter,
> > +				   u8 *firmware, u32 firmware_len) {
> 
> Can you make 'firmware' const? Also, to help below, it might work better as
> 'const void *'.
> 

OK, Thanks for the review.

> > +	struct mwifiex_fw_data fwdata;
> > +	u32 offset = 0, data_len, dnld_cmd;
> > +	int ret = 0;
> > +	bool cmd7_before = false;
> > +
> > +	while (1) {
> > +		if (offset + sizeof(fwdata.header) >= firmware_len) {
> > +			mwifiex_dbg(adapter, ERROR,
> > +				    "extract wifi-only firmware failure!");
> > +			ret = -1;
> > +			goto done;
> > +		}
> > +
> > +		memcpy(&fwdata.header, firmware + offset,
> > +		       sizeof(fwdata.header));
> 
> Do you actually need to copy this? Can't you just keep a pointer to the location?
> e.g.
> 
> 	const struct mwifiex_fw_data *fwdata;
> ...
> 	fwdata = firmware + offset;
> 

Ok.

> > +		dnld_cmd = le32_to_cpu(fwdata.header.dnld_cmd);
> > +		data_len = le32_to_cpu(fwdata.header.data_length);
> > +
> > +		switch (dnld_cmd) {
> > +		case MWIFIEX_FW_DNLD_CMD_1:
> > +			if (!cmd7_before) {
> > +				mwifiex_dbg(adapter, ERROR,
> > +					    "no cmd7 before cmd1!");
> > +				ret = -1;
> > +				goto done;
> > +			}
> > +			offset += data_len + sizeof(fwdata.header);
> 
> Technically, we need an overflow check to make sure that 'data_len'
> isn't some bogus value that overflows 'offset'.
> 

There is the sanity check for the offset after bypass CMD1/5/7 in the start of while-loop, enhanced in v4 as,
if (offset >= firmware_len)

> > +			break;
> > +		case MWIFIEX_FW_DNLD_CMD_5:
> > +			offset += data_len + sizeof(fwdata.header);
> 
> Same here.
> 
> > +			break;
> > +		case MWIFIEX_FW_DNLD_CMD_6:
> 
> Can we have a comment, either here or above this function, to describe what
> this sequence is? Or particularly, what is this terminating condition? "CMD_6"
> doesn't really tell me that this is the start of the Wifi blob.
> 
> > +			offset += data_len + sizeof(fwdata.header);
> 

The sequence have been added to function comments in v4.

> You don't check for overflow here. Check this before returning this (either here,
> or in the 'done' label).
> 

Yes, add sanity check for the offset in end of CMD6.

> > +			ret = offset;
> > +			goto done;
> > +		case MWIFIEX_FW_DNLD_CMD_7:
> > +			if (!cmd7_before)
> 
> ^^ This 'if' isn't really needed.

Done.

> 
> > +				cmd7_before = true;
> > +			offset += sizeof(fwdata.header);
> > +			break;
> > +		default:
> > +			mwifiex_dbg(adapter, ERROR, "unknown dnld_cmd %d\n",
> > +				    dnld_cmd);
> > +			ret = -1;
> > +			goto done;
> > +		}
> > +	}
> > +
> > +done:
> > +	return ret;
> > +}
> > +
> >  /*
> >   * This function downloads the firmware to the card.
> >   *
> > @@ -1971,7 +2028,7 @@ static int mwifiex_prog_fw_w_helper(struct
> mwifiex_adapter *adapter,
> >  	u32 firmware_len = fw->fw_len;
> >  	u32 offset = 0;
> >  	struct sk_buff *skb;
> > -	u32 txlen, tx_blocks = 0, tries, len;
> > +	u32 txlen, tx_blocks = 0, tries, len, val;
> >  	u32 block_retry_cnt = 0;
> >  	struct pcie_service_card *card = adapter->card;
> >  	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -1998,6
> > +2055,24 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter
> *adapter,
> >  		goto done;
> >  	}
> >
> > +	ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_13_REG, &val);
> > +	if (ret) {
> > +		mwifiex_dbg(adapter, FATAL, "Failed to read scratch register 13\n");
> > +		goto done;
> > +	}
> > +
> > +	/* PCIE FLR case: extract wifi part from combo firmware*/
> > +	if (val == MWIFIEX_PCIE_FLR_HAPPENS) {
> > +		ret = mwifiex_extract_wifi_fw(adapter, firmware, firmware_len);
> > +		if (ret < 0) {
> > +			mwifiex_dbg(adapter, ERROR, "Failed to extract wifi fw\n");
> > +			goto done;
> > +		}
> > +		offset = ret;
> > +		mwifiex_dbg(adapter, MSG,
> > +			    "info: dnld wifi firmware from %d bytes\n", offset);
> > +	}
> > +
> >  	/* Perform firmware data transfer */
> >  	do {
> >  		u32 ireg_intr = 0;
> > @@ -3060,12 +3135,6 @@ static void mwifiex_pcie_up_dev(struct
> mwifiex_adapter *adapter)
> >  	struct pci_dev *pdev = card->dev;
> >  	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
> >
> > -	/* Bluetooth is not on pcie interface. Download Wifi only firmware
> > -	 * during pcie FLR, so that bluetooth part of firmware which is
> > -	 * already running doesn't get affected.
> > -	 */
> > -	strcpy(adapter->fw_name, PCIE8997_DEFAULT_WIFIFW_NAME);
> 
> Now that there's no users, delete PCIE8997_DEFAULT_WIFIFW_NAME from
> pcie.h.

Removed in V4.

> 
> Brian
> 
> > -
> >  	/* tx_buf_size might be changed to 3584 by firmware during
> >  	 * data transfer, we should reset it to default size.
> >  	 */
> > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h
> > b/drivers/net/wireless/marvell/mwifiex/pcie.h
> > index 7e2450c..54aecda 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.h
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
> > @@ -120,6 +120,8 @@
> >  #define MWIFIEX_SLEEP_COOKIE_SIZE			4
> >  #define MWIFIEX_MAX_DELAY_COUNT				100
> >
> > +#define MWIFIEX_PCIE_FLR_HAPPENS 0xFEDCBABA
> > +
> >  struct mwifiex_pcie_card_reg {
> >  	u16 cmd_addr_lo;
> >  	u16 cmd_addr_hi;
> > --
> > 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