All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Norris <briannorris@chromium.org>
To: Xinming Hu <huxinming820@gmail.com>
Cc: Linux Wireless <linux-wireless@vger.kernel.org>,
	Kalle Valo <kvalo@qca.qualcomm.com>,
	Dmitry Torokhov <dtor@google.com>,
	rajatja@google.com, Amitkumar Karwar <akarwar@marvell.com>,
	Cathy Luo <cluo@marvell.com>, Xinming Hu <huxm@marvell.com>,
	Ganapathi Bhat <gbhat@marvell.com>
Subject: Re: [PATCH v3 4/4] mwifiex: pcie: extract wifi part from combo firmware during function level reset
Date: Mon, 10 Apr 2017 18:37:25 -0700	[thread overview]
Message-ID: <20170411013724.GA135531@google.com> (raw)
In-Reply-To: <1491815374-6555-4-git-send-email-huxinming820@gmail.com>

Hi,

On Mon, Apr 10, 2017 at 09:09:34AM +0000, Xinming Hu wrote:
> From: Xinming Hu <huxm@marvell.com>
> 
> 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@marvell.com>
> Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> Signed-off-by: Cathy Luo <cluo@marvell.com>
> ---
> 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 *'.

> +	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;

> +		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'.

> +			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);

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

> +			ret = offset;
> +			goto done;
> +		case MWIFIEX_FW_DNLD_CMD_7:
> +			if (!cmd7_before)

^^ This 'if' isn't really needed.

> +				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.

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
> 

  reply	other threads:[~2017-04-11  1:37 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-10  9:09 [PATCH v3 1/4] mwifiex: remove unnecessary wakeup interrupt number sanity check Xinming Hu
2017-04-10  9:09 ` [PATCH v3 2/4] mwifiex: fall back mwifiex_dbg to pr_info when adapter->dev not set Xinming Hu
2017-04-10  9:09 ` [PATCH v3 3/4] mwifiex: pcie: correct scratch register name Xinming Hu
2017-04-10  9:09 ` [PATCH v3 4/4] mwifiex: pcie: extract wifi part from combo firmware during function level reset Xinming Hu
2017-04-11  1:37   ` Brian Norris [this message]
2017-04-13  6:47     ` Xinming Hu
2017-04-13 17:49       ` Brian Norris
2017-04-14  3:28         ` Xinming Hu
2017-04-14 16:55           ` Brian Norris
2017-04-15  8:55             ` Xinming Hu
2017-04-12 17:32   ` Brian Norris

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170411013724.GA135531@google.com \
    --to=briannorris@chromium.org \
    --cc=akarwar@marvell.com \
    --cc=cluo@marvell.com \
    --cc=dtor@google.com \
    --cc=gbhat@marvell.com \
    --cc=huxinming820@gmail.com \
    --cc=huxm@marvell.com \
    --cc=kvalo@qca.qualcomm.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=rajatja@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.