2017-05-09 13:31:27

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 00/11] Firmware loading changes

This patch series includes firmware loading enhancements for
Redpine 9113 chipset. The older method is not being used by any
Redpine chipset. There is no firmware image submitted to upstream
yet. We will submit 9113's firmware image once these changes are
accepted.

This patch series is based on original work submitted by Prameela
earlier. We have done some cleanup work and prepared smaller
incremental patches. We will start maintaining changelog for further
revisions.

Prameela Rani Garnepudi (11):
rsi: Rename file rsi_91x_pkt.c to rsi_91x_hal.c
rsi: Changes to sdio reads and writes
rsi: Changes in USB read and write operations
rsi: use macros in USB specific code
rsi: Remove unnecessary buffer allocation
rsi: Handle usb multi-byte write failure case properly
rsi: Add usb multi-byte read operation
rsi: Add host interface operations as separate structure.
rsi: Add new host interface operations
rsi: Add new firmware loading method
rsi: Remove old firmware loading method

drivers/net/wireless/rsi/Makefile | 2 +-
drivers/net/wireless/rsi/rsi_91x_hal.c | 740 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_pkt.c | 215 --------
drivers/net/wireless/rsi/rsi_91x_sdio.c | 211 +++++++-
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 190 +------
drivers/net/wireless/rsi/rsi_91x_usb.c | 182 +++++--
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 125 -----
drivers/net/wireless/rsi/rsi_common.h | 3 +-
drivers/net/wireless/rsi/rsi_hal.h | 90 ++++
drivers/net/wireless/rsi/rsi_main.h | 36 +-
drivers/net/wireless/rsi/rsi_sdio.h | 6 +-
drivers/net/wireless/rsi/rsi_usb.h | 3 -
12 files changed, 1215 insertions(+), 588 deletions(-)
create mode 100644 drivers/net/wireless/rsi/rsi_91x_hal.c
delete mode 100644 drivers/net/wireless/rsi/rsi_91x_pkt.c
create mode 100644 drivers/net/wireless/rsi/rsi_hal.h

--
2.7.4


2017-05-12 08:46:02

by Kalle Valo

[permalink] [raw]
Subject: Re: [v2 10/11] rsi: Add new firmware loading method

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> The older firmware loading method has been deprecated and not in use
> for any chipets. New method is introduced which works based on soft
> boot loader. In this method, complete RAM image and FLASH image are
> present in the flash. Before loading the functional firmware, host
> issues boot loader commands to verify whether firmware to load is
> different from the current functional firmware. If not, firmware
> upgrade progresses and boot loader will switch to the new functional
> firmware.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

Please document in the commit log the new firmware filenames used by
this patch.

--
Kalle Valo

2017-05-09 13:32:06

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 08/11] rsi: Add host interface operations as separate structure.

From: Prameela Rani Garnepudi <[email protected]>

Host interface operations are currently function pointers in rsi_hw
structure. As more host interface operations are going to be introduced,
separate structure is added for these for convenience.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 16 +++++++---------
drivers/net/wireless/rsi/rsi_91x_sdio.c | 11 +++++++++--
drivers/net/wireless/rsi/rsi_91x_usb.c | 9 ++++++++-
drivers/net/wireless/rsi/rsi_main.h | 18 ++++++++++++++++--
4 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 02920c9..8fbf904 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -100,9 +100,8 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
(skb->priority & 0xf) |
(tx_params->sta_id << 8));

- status = adapter->host_intf_write_pkt(common->priv,
- skb->data,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
+ skb->len);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
__func__);
@@ -148,9 +147,9 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
}
skb_push(skb, extnd_size);
skb->data[extnd_size + 4] = extnd_size;
- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)skb->data,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+ (u8 *)skb->data,
+ skb->len);
if (status) {
rsi_dbg(ERR_ZONE,
"%s: Failed to write the packet\n", __func__);
@@ -203,9 +202,8 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,

msg[7] |= cpu_to_le16(vap_id << 8);

- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)msg,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv, (u8 *)msg,
+ skb->len);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 39d94b3..bdbec8b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -676,8 +676,6 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
}
sdio_release_host(pfunction);

- adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt;
- adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt;
adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;

@@ -691,6 +689,13 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
return status;
}

+static struct rsi_host_intf_ops sdio_host_intf_ops = {
+ .write_pkt = rsi_sdio_host_intf_write_pkt,
+ .read_pkt = rsi_sdio_host_intf_read_pkt,
+ .read_reg_multiple = rsi_sdio_read_register_multiple,
+ .write_reg_multiple = rsi_sdio_write_register_multiple,
+};
+
/**
* rsi_probe() - This function is called by kernel when the driver provided
* Vendor and device IDs are matched. All the initialization
@@ -713,6 +718,8 @@ static int rsi_probe(struct sdio_func *pfunction,
__func__);
return 1;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_SDIO;
+ adapter->host_intf_ops = &sdio_host_intf_ops;

if (rsi_init_sdio_interface(adapter, pfunction)) {
rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index fc52311..8b81a73 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -382,6 +382,12 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
len);
}

+static struct rsi_host_intf_ops usb_host_intf_ops = {
+ .write_pkt = rsi_usb_host_intf_write_pkt,
+ .read_reg_multiple = rsi_usb_read_register_multiple,
+ .write_reg_multiple = rsi_usb_write_register_multiple,
+};
+
/**
* rsi_deinit_usb_interface() - This function deinitializes the usb interface.
* @adapter: Pointer to the adapter structure.
@@ -447,9 +453,10 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,

/* Initializing function callbacks */
adapter->rx_urb_submit = rsi_rx_urb_submit;
- adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt;
adapter->check_hw_queue_status = rsi_usb_check_queue_status;
adapter->determine_event_timeout = rsi_usb_event_timeout;
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
+ adapter->host_intf_ops = &usb_host_intf_ops;

rsi_init_event(&rsi_dev->rx_thread.event);
status = rsi_create_kthread(common, &rsi_dev->rx_thread,
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 1d5904b..7fdeda7 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -209,6 +209,11 @@ struct rsi_common {
u8 ant_in_use;
};

+enum host_intf {
+ RSI_HOST_INTF_SDIO = 0,
+ RSI_HOST_INTF_USB
+};
+
struct rsi_hw {
struct rsi_common *priv;
struct ieee80211_hw *hw;
@@ -219,16 +224,25 @@ struct rsi_hw {
struct device *device;
u8 sc_nvifs;

+ enum host_intf rsi_host_intf;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
u8 dfs_region;
void *rsi_dev;
- int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
- int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ struct rsi_host_intf_ops *host_intf_ops;
int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
int (*rx_urb_submit)(struct rsi_hw *adapter);
int (*determine_event_timeout)(struct rsi_hw *adapter);
};
+
+struct rsi_host_intf_ops {
+ int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+ int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+};
#endif
--
2.7.4

2017-05-11 18:35:15

by Kalle Valo

[permalink] [raw]
Subject: Re: [v2 07/11] rsi: Add usb multi-byte read operation

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> USB multibyte read will be used in the new firmware loading method
> for RS9113 chipset.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> +static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
> + u8 *data, u16 count)
> +{
> + struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
> + u8 *buf;
> + u16 transfer;
> + int status;
> +
> + if (!addr)
> + return -EINVAL;
> +
> + buf = kzalloc(4096, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + while (count) {
> + transfer = min_t(u16, count, 4096);

A minor thing, no need to resend just because of this. But a define for
4096 would be nice.

--
Kalle Valo

2017-05-16 10:08:19

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v2 07/11] rsi: Add usb multi-byte read operation

On Fri, May 12, 2017 at 12:05 AM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> USB multibyte read will be used in the new firmware loading method
>> for RS9113 chipset.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> +static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
>> + u8 *data, u16 count)
>> +{
>> + struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
>> + u8 *buf;
>> + u16 transfer;
>> + int status;
>> +
>> + if (!addr)
>> + return -EINVAL;
>> +
>> + buf = kzalloc(4096, GFP_KERNEL);
>> + if (!buf)
>> + return -ENOMEM;
>> +
>> + while (count) {
>> + transfer = min_t(u16, count, 4096);
>
> A minor thing, no need to resend just because of this. But a define for
> 4096 would be nice.
>

I have defined a macro for 4096 in v3 series.

Regards,
Amitkumar Karwar

2017-05-09 13:32:17

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 11/11] rsi: Remove old firmware loading method

From: Prameela Rani Garnepudi <[email protected]>

The older firmware loading method is not usable by any Redpine chipset.
Hence removing that part of the code.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 187 ----------------------------
drivers/net/wireless/rsi/rsi_91x_usb.c | 6 +-
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 126 -------------------
drivers/net/wireless/rsi/rsi_common.h | 3 +-
drivers/net/wireless/rsi/rsi_sdio.h | 1 -
drivers/net/wireless/rsi/rsi_usb.h | 3 -
6 files changed, 3 insertions(+), 323 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 225042f..df2a63b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -60,171 +60,6 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
}

/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the
- * TA file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u16 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 indx, ii;
- u16 block_size = dev->tx_blk_size;
- u32 lsb_address;
- __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
- TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
- u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG,
- TA_TH0_PC_REG, TA_RELEASE_THREAD_REG };
- u32 base_address;
- u16 msb_address;
-
- base_address = TA_LOAD_ADDRESS;
- msb_address = base_address >> 16;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -1;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- if ((base_address >> 16) != msb_address) {
- msb_address += 1;
- if (rsi_sdio_master_access_msword(adapter,
- msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- }
- }
-
- if (len % block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load f/w\n", __func__);
- return -1;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded TA instructions\n", __func__);
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
-
- for (ii = 0; ii < ARRAY_SIZE(data); ii++) {
- /* Bringing TA out of reset */
- if (rsi_sdio_write_register_multiple(adapter,
- (address[ii] |
- RSI_SD_REQUEST_MASTER),
- (u8 *)&data[ii],
- 4)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to hold TA threads\n", __func__);
- return -1;
- }
- }
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 len;
- u16 num_blocks;
- const u8 *fw;
- const struct firmware *fw_entry = NULL;
- u16 block_size = dev->tx_blk_size;
- int status = 0;
- u32 base_address;
- u16 msb_address;
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
- base_address = TA_LOAD_ADDRESS;
- msb_address = (base_address >> 16);
-
- if (rsi_sdio_master_access_msword(adapter, msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n", __func__);
- return -1;
- }
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
* rsi_process_pkt() - This Function reads rx_blocks register and figures out
* the size of the rx pkt.
* @common: Pointer to the driver private structure.
@@ -471,28 +306,6 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
}

/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_sdio_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -1;
-
- if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- rsi_dbg(INIT_ZONE,
- "%s: Setting ms word to 0x41050000\n", __func__);
-
- return 0;
-}
-
-/**
* rsi_sdio_read_buffer_status_register() - This function is used to the read
* buffer status register and set
* relevant fields in
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 10dc724..c55586c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -317,10 +317,8 @@ static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
*
* Return: status: 0 on success, a negative error code on failure.
*/
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
- u32 addr,
- u8 *data,
- u16 count)
+static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u8 *buf;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index 1c3e654..d3e0a07 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -19,67 +19,6 @@
#include "rsi_usb.h"

/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the TA
- * file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u16 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- u32 indx, ii;
- u16 block_size = dev->tx_blk_size;
- u32 lsb_address;
- u32 base_address;
-
- base_address = TA_LOAD_ADDRESS;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- }
-
- if (len % block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded %s instructions\n", __func__,
- FIRMWARE_RSI9113);
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
* rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
* the USB device.
* @common: Pointer to the driver private structure.
@@ -119,68 +58,3 @@ void rsi_usb_rx_thread(struct rsi_common *common)
complete_and_exit(&dev->rx_thread.completion, 0);
}

-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- const struct firmware *fw_entry = NULL;
- u16 block_size = dev->tx_blk_size;
- const u8 *fw;
- u16 num_blocks;
- u32 len;
- int status = 0;
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_usb_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -EIO;
-
- return 0;
- }
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index d3fbe33..4434969 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -20,8 +20,7 @@
#include <linux/kthread.h>

#define EVENT_WAIT_FOREVER 0
-#define TA_LOAD_ADDRESS 0x00
-#define FIRMWARE_RSI9113 "rsi_91x.fw"
+#define FIRMWARE_RSI9113 "rs9113_wlan_qspi.rps"
#define QUEUE_NOT_FULL 1
#define QUEUE_FULL 0

diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index 7ae6d51..9fb73f6 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -116,7 +116,6 @@ struct rsi_91x_sdiodev {

void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
-int rsi_sdio_device_init(struct rsi_common *common);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index 52379c6..c53975d 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -61,8 +61,5 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
return EVENT_WAIT_FOREVER;
}

-int rsi_usb_device_init(struct rsi_common *common);
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u16 count);
void rsi_usb_rx_thread(struct rsi_common *common);
#endif
--
2.7.4

2017-05-12 08:46:57

by Kalle Valo

[permalink] [raw]
Subject: Re: [v2 11/11] rsi: Remove old firmware loading method

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> The older firmware loading method is not usable by any Redpine chipset.
> Hence removing that part of the code.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

Please document in the commit log the firmware files which are not used
anymore.

--
Kalle Valo

2017-05-09 13:31:46

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 02/11] rsi: Changes to sdio reads and writes

From: Prameela Rani Garnepudi <[email protected]>

SDIO read or write maximum size is limited to 2^16. This is done to make
the host interface operations common for SDIO and USB.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 10 +++++-----
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 8 ++++----
drivers/net/wireless/rsi/rsi_sdio.h | 4 ++--
3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 8428858..39d94b3 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -487,8 +487,8 @@ void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
*/
static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
u32 addr,
- u32 count,
- u8 *data)
+ u8 *data,
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -518,7 +518,7 @@ static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
u8 *data,
- u32 count)
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -614,8 +614,8 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,

status = rsi_sdio_read_register_multiple(adapter,
length,
- length, /*num of bytes*/
- (u8 *)pkt);
+ (u8 *)pkt,
+ length); /*num of bytes*/

if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 40d7231..7c9cf01 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -75,13 +75,13 @@ static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
static int rsi_copy_to_card(struct rsi_common *common,
const u8 *fw,
u32 len,
- u32 num_blocks)
+ u16 num_blocks)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
u32 lsb_address;
__le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
@@ -171,10 +171,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
u32 len;
- u32 num_blocks;
+ u16 num_blocks;
const u8 *fw;
const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
int status = 0;
u32 base_address;
u16 msb_address;
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index c7e8f2b..a82bc4c 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -110,7 +110,7 @@ struct rsi_91x_sdiodev {
u8 sdio_clock_speed;
u32 cardcapability;
u8 prev_desc[16];
- u32 tx_blk_size;
+ u16 tx_blk_size;
u8 write_fail;
};

@@ -122,7 +122,7 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
+ u8 *data, u16 count);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
--
2.7.4

2017-05-12 08:28:18

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [v2 05/11] rsi: Remove unnecessary buffer allocation

On 5/11/2017 8:28 PM, Kalle Valo wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> In functions usb read register and usb write register, dynamic allocation
>> of 4 bytes is used. This is removed as it is unncessary for local variable
>> and for such small data.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>> ---
>> drivers/net/wireless/rsi/rsi_91x_usb.c | 18 ++++--------------
>> 1 file changed, 4 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
>> index 73b01a8..8eb7407 100644
>> --- a/drivers/net/wireless/rsi/rsi_91x_usb.c
>> +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
>> @@ -157,12 +157,8 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
>> u16 *value,
>> u16 len)
>> {
>> - u8 *buf;
>> - int status = -ENOMEM;
>> -
>> - buf = kmalloc(0x04, GFP_KERNEL);
>> - if (!buf)
>> - return status;
>> + u8 buf[4];
>> + int status;
>>
>> status = usb_control_msg(usbdev,
>> usb_rcvctrlpipe(usbdev, 0),
>
> Recently I got a patch to orinoco_usb which did exactly the opposite
> (unless I'm missing something):
>
> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git/commit/?id=2f6ae79cb04bb7f9b4be3f1c32b6fda35bf976bc
>
> The documentation for usb_control_msg() does not mention anything if
> it's possible to use stack memory, but AFAIU it's not possible to use
> stack memory with DMA. Can anyone clarify?

After private message I sent to Kalle here my public response :-p
According to Greg this has been a USB core requirement for a long, long
time (see below).

Regards,
Arend

[1] http://marc.info/?l=linux-kernel&m=149391173014176&w=2

-------- Forwarded Message --------
Subject: Re: [PATCH] i2c: i2c-tiny-usb: fix buffer not being DMA capable
Date: Thu, 4 May 2017 08:27:09 -0700
From: Greg KH <[email protected]>
To: Sebastian Reichel <[email protected]>
CC: Sebastian Reichel <[email protected]>, Till Harbaum <[email protected]>,
Wolfram Sang <[email protected]>, [email protected],
[email protected], # Kernel 4 . 9+ <[email protected]>

On Thu, May 04, 2017 at 02:56:32PM +0200, Sebastian Reichel wrote:
> The i2c-tiny-usb driver generates the following trace and fails to
> read or write data on a v4.9 or newer kernels. This patch avoids the
> problem by allocating a DMA capable buffer for data transfer.

[snip]

This has been a USB core requirement since the 2.2 days, it's only since
4.9 that most people have started to notice this. So backporting it to
anything that it can go to is best to have happen :)

> Signed-off-by: Sebastian Reichel <[email protected]>
> ---
> drivers/i2c/busses/i2c-tiny-usb.c | 19 +++++++++++++++----
> 1 file changed, 15 insertions(+), 4 deletions(-)

2017-05-16 10:06:57

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v2 05/11] rsi: Remove unnecessary buffer allocation

On Fri, May 12, 2017 at 1:58 PM, Arend van Spriel
<[email protected]> wrote:
> On 5/11/2017 8:28 PM, Kalle Valo wrote:
>>
>> Amitkumar Karwar <[email protected]> writes:
>>
>>> From: Prameela Rani Garnepudi <[email protected]>
>>>
>>> In functions usb read register and usb write register, dynamic allocation
>>> of 4 bytes is used. This is removed as it is unncessary for local
>>> variable
>>> and for such small data.
>>>
>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>>> ---
>>> drivers/net/wireless/rsi/rsi_91x_usb.c | 18 ++++--------------
>>> 1 file changed, 4 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c
>>> b/drivers/net/wireless/rsi/rsi_91x_usb.c
>>> index 73b01a8..8eb7407 100644
>>> --- a/drivers/net/wireless/rsi/rsi_91x_usb.c
>>> +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
>>> @@ -157,12 +157,8 @@ static int rsi_usb_reg_read(struct usb_device
>>> *usbdev,
>>> u16 *value,
>>> u16 len)
>>> {
>>> - u8 *buf;
>>> - int status = -ENOMEM;
>>> -
>>> - buf = kmalloc(0x04, GFP_KERNEL);
>>> - if (!buf)
>>> - return status;
>>> + u8 buf[4];
>>> + int status;
>>> status = usb_control_msg(usbdev,
>>> usb_rcvctrlpipe(usbdev, 0),
>>
>>
>> Recently I got a patch to orinoco_usb which did exactly the opposite
>> (unless I'm missing something):
>>
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git/commit/?id=2f6ae79cb04bb7f9b4be3f1c32b6fda35bf976bc
>>
>> The documentation for usb_control_msg() does not mention anything if
>> it's possible to use stack memory, but AFAIU it's not possible to use
>> stack memory with DMA. Can anyone clarify?
>
>
> After private message I sent to Kalle here my public response :-p
> According to Greg this has been a USB core requirement for a long, long time
> (see below).
>

Thanks Arend.
I have dropped this patch in V3 series.

Regards,
Amitkumar Karwar

2017-05-09 13:31:42

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 01/11] rsi: Rename file rsi_91x_pkt.c to rsi_91x_hal.c

From: Prameela Rani Garnepudi <[email protected]>

The file rsi_91x_hal.c is going to contain device specific code i.e new
firmware loading method for RS9113 chipset. As the file rsi_91x_pkt.c
contains code to prepare device specific descriptors for transmit packet,
this file is renamed to rsi_91x_hal.c which is more relevant as per it's
functionality.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/Makefile | 2 +-
drivers/net/wireless/rsi/{rsi_91x_pkt.c => rsi_91x_hal.c} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename drivers/net/wireless/rsi/{rsi_91x_pkt.c => rsi_91x_hal.c} (100%)

diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile
index 25828b6..a475c81 100644
--- a/drivers/net/wireless/rsi/Makefile
+++ b/drivers/net/wireless/rsi/Makefile
@@ -2,7 +2,7 @@ rsi_91x-y += rsi_91x_main.o
rsi_91x-y += rsi_91x_core.o
rsi_91x-y += rsi_91x_mac80211.o
rsi_91x-y += rsi_91x_mgmt.o
-rsi_91x-y += rsi_91x_pkt.o
+rsi_91x-y += rsi_91x_hal.o
rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o

rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
similarity index 100%
rename from drivers/net/wireless/rsi/rsi_91x_pkt.c
rename to drivers/net/wireless/rsi/rsi_91x_hal.c
--
2.7.4

2017-05-09 13:32:13

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 07/11] rsi: Add usb multi-byte read operation

From: Prameela Rani Garnepudi <[email protected]>

USB multibyte read will be used in the new firmware loading method
for RS9113 chipset.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 40 ++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 634f726..fc52311 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -266,6 +266,46 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
return status;
}

+static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ u8 *buf;
+ u16 transfer;
+ int status;
+
+ if (!addr)
+ return -EINVAL;
+
+ buf = kzalloc(4096, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ while (count) {
+ transfer = min_t(u16, count, 4096);
+ status = usb_control_msg(dev->usbdev,
+ usb_rcvctrlpipe(dev->usbdev, 0),
+ USB_VENDOR_REGISTER_READ,
+ RSI_USB_REQ_IN,
+ ((addr & 0xffff0000) >> 16),
+ (addr & 0xffff), (void *)buf,
+ transfer, USB_CTRL_GET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Reg read failed with error code :%d\n",
+ status);
+ kfree(buf);
+ return status;
+ }
+ memcpy(data, buf, transfer);
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+ kfree(buf);
+ return 0;
+}
+
/**
* rsi_usb_write_register_multiple() - This function writes multiple bytes of
* information to multiple registers.
--
2.7.4

2017-05-09 13:31:49

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 03/11] rsi: Changes in USB read and write operations

From: Prameela Rani Garnepudi <[email protected]>

USB read and write registers maximum size is limited 2^16. More than
this size is not used in the driver.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 6 +++---
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 9 +++++----
drivers/net/wireless/rsi/rsi_usb.h | 2 +-
3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index cc8deec..dfb8a75 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -286,11 +286,11 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
u8 *data,
- u32 count)
+ u16 count)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u8 *buf;
- u8 transfer;
+ u16 transfer;
int status = 0;

buf = kzalloc(4096, GFP_KERNEL);
@@ -298,7 +298,7 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
return -ENOMEM;

while (count) {
- transfer = (u8)(min_t(u32, count, 4096));
+ transfer = min_t(u16, count, 4096);
memcpy(buf, data, transfer);
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index de49008..1c3e654 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -33,12 +33,12 @@
static int rsi_copy_to_card(struct rsi_common *common,
const u8 *fw,
u32 len,
- u32 num_blocks)
+ u16 num_blocks)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
u32 lsb_address;
u32 base_address;

@@ -134,9 +134,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
struct rsi_hw *adapter = common->priv;
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
const u8 *fw;
- u32 num_blocks, len;
+ u16 num_blocks;
+ u32 len;
int status = 0;

status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index ebea0c4..52379c6 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -63,6 +63,6 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)

int rsi_usb_device_init(struct rsi_common *common);
int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
+ u8 *data, u16 count);
void rsi_usb_rx_thread(struct rsi_common *common);
#endif
--
2.7.4

2017-05-09 13:32:10

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 09/11] rsi: Add new host interface operations

From: Prameela Rani Garnepudi <[email protected]>

Host interface opearation master_reg_read, master_reg_write and
load_data_master_write are added. These functions are needed for the
new firmware loading method. As part of this, the function
master_access_msword is moved from rsi_91x_sdio_ops.c to rsi_91x_sdio.c.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 179 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 3 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 65 ++++++++++
drivers/net/wireless/rsi/rsi_main.h | 8 ++
drivers/net/wireless/rsi/rsi_sdio.h | 1 +
5 files changed, 254 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index bdbec8b..b397e2c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -552,6 +552,182 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
return status;
}

+static int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz,
+ u16 block_size,
+ u8 *ta_firmware)
+{
+ u32 num_blocks, offset, i;
+ u16 msb_address, lsb_address;
+ u8 temp_buf[block_size];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ msb_address = base_address >> 16;
+
+ rsi_dbg(INFO_ZONE, "ins_size: %d, num_blocks: %d\n",
+ instructions_sz, num_blocks);
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter, msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return status;
+ }
+
+ for (offset = 0, i = 0; i < num_blocks; i++, offset += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset, block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf, block_size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+
+ if ((base_address >> 16) != msb_address) {
+ msb_address += 1;
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter,
+ msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word reg\n",
+ __func__);
+ return status;
+ }
+ }
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset,
+ instructions_sz % block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ offset | RSI_SD_REQUEST_MASTER);
+ }
+ return 0;
+}
+
+#define FLASH_SIZE_ADDR 0x04000016
+static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size)
+{
+ u32 addr_on_bus, *data;
+ u32 align[2] = {};
+ u16 ms_addr;
+ int status;
+
+ data = PTR_ALIGN(&align[0], 8);
+
+ ms_addr = (addr >> 16);
+ status = rsi_sdio_master_access_msword(adapter, ms_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ addr &= 0xFFFF;
+
+ addr_on_bus = (addr & 0xFF000000);
+ if ((addr_on_bus == (FLASH_SIZE_ADDR & 0xFF000000)) ||
+ (addr_on_bus == 0x0))
+ addr_on_bus = (addr & ~(0x3));
+ else
+ addr_on_bus = addr;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_read_register_multiple
+ (adapter,
+ (addr_on_bus | RSI_SD_REQUEST_MASTER),
+ (u8 *)data, 4);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+ return status;
+ }
+ if (size == 2) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else
+ *read_buf = (*data >> 16);
+ *read_buf = (*read_buf & 0xFFFF);
+ } else if (size == 1) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else if ((addr & 0x3) == 1)
+ *read_buf = (*data >> 8);
+ else if ((addr & 0x3) == 2)
+ *read_buf = (*data >> 16);
+ else
+ *read_buf = (*data >> 24);
+ *read_buf = (*read_buf & 0xFF);
+ } else {
+ *read_buf = *data;
+ }
+
+ return 0;
+}
+
+static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+ unsigned long addr,
+ unsigned long data, u16 size)
+{
+ unsigned long data1[2], *data_aligned;
+ int status;
+
+ data_aligned = PTR_ALIGN(&data1[0], 8);
+
+ if (size == 2) {
+ *data_aligned = ((data << 16) | (data & 0xFFFF));
+ } else if (size == 1) {
+ u32 temp_data = data & 0xFF;
+
+ *data_aligned = ((temp_data << 24) | (temp_data << 16) |
+ (temp_data << 8) | temp_data);
+ } else {
+ *data_aligned = data;
+ }
+ size = 4;
+
+ status = rsi_sdio_master_access_msword(adapter, (addr >> 16));
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -EIO;
+ }
+ addr = addr & 0xFFFF;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ (addr | RSI_SD_REQUEST_MASTER),
+ (u8 *)data_aligned, size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to do AHB reg write\n", __func__);
+ return status;
+ }
+ return 0;
+}
+
/**
* rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.
* @adapter: Pointer to the adapter structure.
@@ -694,6 +870,9 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = {
.read_pkt = rsi_sdio_host_intf_read_pkt,
.read_reg_multiple = rsi_sdio_read_register_multiple,
.write_reg_multiple = rsi_sdio_write_register_multiple,
+ .master_reg_read = rsi_sdio_master_reg_read,
+ .master_reg_write = rsi_sdio_master_reg_write,
+ .load_data_master_write = rsi_sdio_load_data_master_write,
};

/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 7c9cf01..225042f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -27,8 +27,7 @@
*
* Return: status: 0 on success, -1 on failure.
*/
-static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
- u16 ms_word)
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
{
u8 byte;
u8 function = 0;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 8b81a73..7156fcb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -382,10 +382,75 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
len);
}

+static int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg,
+ u32 *value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_read(usbdev, reg, (u16 *)value, len);
+}
+
+static int rsi_usb_master_reg_write(struct rsi_hw *adapter,
+ unsigned long reg,
+ unsigned long value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_write(usbdev, reg, value, len);
+}
+
+static int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz, u16 block_size,
+ u8 *ta_firmware)
+{
+ u16 num_blocks;
+ u32 cur_indx, i;
+ u8 temp_buf[256];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+ for (cur_indx = 0, i = 0; i < num_blocks; i++, cur_indx += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx, block_size);
+ status = rsi_usb_write_register_multiple(adapter, base_address,
+ (u8 *)(temp_buf),
+ block_size);
+ if (status < 0)
+ return status;
+
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx,
+ instructions_sz % block_size);
+ status = rsi_usb_write_register_multiple
+ (adapter, base_address,
+ (u8 *)temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ cur_indx);
+ }
+ return 0;
+}
+
static struct rsi_host_intf_ops usb_host_intf_ops = {
.write_pkt = rsi_usb_host_intf_write_pkt,
.read_reg_multiple = rsi_usb_read_register_multiple,
.write_reg_multiple = rsi_usb_write_register_multiple,
+ .master_reg_read = rsi_usb_master_reg_read,
+ .master_reg_write = rsi_usb_master_reg_write,
+ .load_data_master_write = rsi_usb_load_data_master_write,
};

/**
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 7fdeda7..2ac5bcf 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -244,5 +244,13 @@ struct rsi_host_intf_ops {
u8 *data, u16 count);
int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
+ int (*master_reg_read)(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size);
+ int (*master_reg_write)(struct rsi_hw *adapter,
+ unsigned long addr, unsigned long data,
+ u16 size);
+ int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
+ u32 instructions_size, u16 block_size,
+ u8 *fw);
};
#endif
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index a82bc4c..7ae6d51 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -123,6 +123,7 @@ int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
--
2.7.4

2017-05-09 13:31:52

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 04/11] rsi: use macros in USB specific code

From: Prameela Rani Garnepudi <[email protected]>

For USB vendor read and write operations new macros added to avoid
redundant usage of long or'ed macros. Also for timeouts standard USB
macros are used.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index dfb8a75..73b01a8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -141,6 +141,9 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
return 0;
}

+#define RSI_USB_REQ_OUT (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE)
+#define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE)
+
/* rsi_usb_reg_read() - This function reads data from given register address.
* @usbdev: Pointer to the usb_device structure.
* @reg: Address of the register to be read.
@@ -164,11 +167,11 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_rcvctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_READ,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_IN,
((reg & 0xffff0000) >> 16), (reg & 0xffff),
(void *)buf,
len,
- HZ * 5);
+ USB_CTRL_GET_TIMEOUT);

*value = (buf[0] | (buf[1] << 8));
if (status < 0) {
@@ -211,12 +214,12 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_sndctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((reg & 0xffff0000) >> 16),
(reg & 0xffff),
(void *)usb_reg_buf,
len,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"%s: Reg write failed with error code :%d\n",
@@ -303,12 +306,12 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((addr & 0xffff0000) >> 16),
(addr & 0xffff),
(void *)buf,
transfer,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"Reg write failed with error code :%d\n",
--
2.7.4

2017-05-09 13:32:18

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 10/11] rsi: Add new firmware loading method

From: Prameela Rani Garnepudi <[email protected]>

The older firmware loading method has been deprecated and not in use
for any chipets. New method is introduced which works based on soft
boot loader. In this method, complete RAM image and FLASH image are
present in the flash. Before loading the functional firmware, host
issues boot loader commands to verify whether firmware to load is
different from the current functional firmware. If not, firmware
upgrade progresses and boot loader will switch to the new functional
firmware.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 527 ++++++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_sdio.c | 11 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 16 +-
drivers/net/wireless/rsi/rsi_hal.h | 90 ++++++
drivers/net/wireless/rsi/rsi_main.h | 10 +
5 files changed, 644 insertions(+), 10 deletions(-)
create mode 100644 drivers/net/wireless/rsi/rsi_hal.h

diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 8fbf904..d49dbaa 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -14,7 +14,16 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

+#include <linux/firmware.h>
#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+#include "rsi_sdio.h"
+
+/* FLASH Firmware */
+static struct ta_metadata metadata_flash_content[] = {
+ {"flash_content", 0x00010000},
+ {"rs9113_wlan_qspi.rps", 0x00010000},
+};

/**
* rsi_send_data_pkt() - This function sends the recieved data packet from
@@ -211,3 +220,521 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
rsi_indicate_tx_status(common->priv, skb, status);
return status;
}
+
+static void bl_cmd_timeout(unsigned long priv)
+{
+ struct rsi_hw *adapter = (struct rsi_hw *)priv;
+
+ adapter->blcmd_timer_expired = true;
+ del_timer(&adapter->bl_cmd_timer);
+}
+
+static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout)
+{
+ init_timer(&adapter->bl_cmd_timer);
+ adapter->bl_cmd_timer.data = (unsigned long)adapter;
+ adapter->bl_cmd_timer.function = (void *)&bl_cmd_timeout;
+ adapter->bl_cmd_timer.expires = (msecs_to_jiffies(timeout) + jiffies);
+
+ adapter->blcmd_timer_expired = false;
+ add_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_stop_cmd_timer(struct rsi_hw *adapter)
+{
+ adapter->blcmd_timer_expired = false;
+ if (timer_pending(&adapter->bl_cmd_timer))
+ del_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp,
+ u16 *cmd_resp)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 regin_val = 0, regout_val = 0;
+ u32 regin_input = 0;
+ u8 output = 0;
+ int status;
+
+ regin_input = (REGIN_INPUT | adapter->priv->coex_mode);
+
+ while (!adapter->blcmd_timer_expired) {
+ regin_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGIN,
+ &regin_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regin_val >> 12) != REGIN_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading timed out..\n",
+ __func__, cmd);
+ return -ETIMEDOUT;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "Issuing write to Regin val:%0x sending cmd:%0x\n",
+ regin_val, (cmd | regin_input << 8));
+ status = hif_ops->master_reg_write(adapter, SWBL_REGIN,
+ (cmd | regin_input << 8), 2);
+ if (status < 0)
+ return status;
+ mdelay(1);
+
+ if (cmd == LOAD_HOSTED_FW || cmd == JUMP_TO_ZERO_PC) {
+ /* JUMP_TO_ZERO_PC doesn't expect
+ * any response. So return from here
+ */
+ return 0;
+ }
+
+ while (!adapter->blcmd_timer_expired) {
+ regout_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ &regout_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading timed out..\n",
+ __func__, cmd);
+ return status;
+ }
+
+ *cmd_resp = ((u16 *)&regout_val)[0] & 0xffff;
+
+ output = ((u8 *)&regout_val)[0] & 0xff;
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (cmd | REGOUT_INVALID << 8), 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT writing failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+
+ if (output != exp_resp) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Recvd resp %x for cmd %0x\n",
+ __func__, output, cmd);
+ return -EINVAL;
+ }
+ rsi_dbg(INFO_ZONE,
+ "%s: Recvd Expected resp %x for cmd %0x\n",
+ __func__, output, cmd);
+
+ return 0;
+}
+
+static int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
+{
+ u16 regout_val = 0;
+ u32 timeout;
+ int status;
+
+ if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
+ timeout = BL_BURN_TIMEOUT;
+ else
+ timeout = BL_CMD_TIMEOUT;
+
+ bl_start_cmd_timer(adapter, timeout);
+ status = bl_write_cmd(adapter, cmd, exp_resp, &regout_val);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %s (%0x) writing failed..\n",
+ __func__, str, cmd);
+ return status;
+ }
+ bl_stop_cmd_timer(adapter);
+ return 0;
+}
+
+#define CHECK_SUM_OFFSET 20
+#define LEN_OFFSET 8
+#define ADDR_OFFSET 16
+static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ struct bl_header bl_hdr;
+ u32 write_addr, write_len;
+ int status;
+
+ bl_hdr.flags = 0;
+ bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
+ bl_hdr.check_sum = cpu_to_le32(
+ *(u32 *)&flash_content[CHECK_SUM_OFFSET]);
+ bl_hdr.flash_start_address = cpu_to_le32(
+ *(u32 *)&flash_content[ADDR_OFFSET]);
+ bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
+ write_len = sizeof(struct bl_header);
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+ write_addr = PING_BUFFER_ADDRESS;
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ } else {
+ write_addr = PING_BUFFER_ADDRESS >> 16;
+ status = hif_ops->master_access_msword(adapter, write_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ write_addr = RSI_SD_REQUEST_MASTER |
+ (PING_BUFFER_ADDRESS & 0xFFFF);
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ }
+ return 0;
+}
+
+static u32 read_flash_capacity(struct rsi_hw *adapter)
+{
+ u32 flash_sz = 0;
+
+ if ((adapter->host_intf_ops->master_reg_read(adapter, FLASH_SIZE_ADDR,
+ &flash_sz, 2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash size reading failed..\n",
+ __func__);
+ return 0;
+ }
+ rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+
+ return (flash_sz * 1024); /* Return size in kbytes */
+}
+
+static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 block_size = adapter->block_size;
+ u32 cmd_addr;
+ u16 cmd_resp, cmd_req;
+ u8 *str;
+ int status;
+
+ if (cmd == PING_WRITE) {
+ cmd_addr = PING_BUFFER_ADDRESS;
+ cmd_resp = PONG_AVAIL;
+ cmd_req = PING_VALID;
+ str = "PING_VALID";
+ } else {
+ cmd_addr = PONG_BUFFER_ADDRESS;
+ cmd_resp = PING_AVAIL;
+ cmd_req = PONG_VALID;
+ str = "PONG_VALID";
+ }
+
+ status = hif_ops->load_data_master_write(adapter, cmd_addr, size,
+ block_size, addr);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+ __func__, *addr);
+ return status;
+ }
+
+ status = bl_cmd(adapter, cmd_req, cmd_resp, str);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ return 0;
+}
+
+static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ u8 cmd, *temp_flash_content;
+ u32 temp_content_size, num_flash, index;
+ u32 flash_start_address;
+ int status;
+
+ temp_flash_content = flash_content;
+
+ if (content_size > MAX_FLASH_FILE_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content size is more than 400K %u\n",
+ __func__, MAX_FLASH_FILE_SIZE);
+ return -EINVAL;
+ }
+
+ flash_start_address = *(u32 *)&flash_content[FLASH_START_ADDRESS];
+ rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+
+ if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Fw image Flash Start Address is less than 64K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (flash_start_address % FLASH_SECTOR_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Start Address is not multiple of 4K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((flash_start_address + content_size) > adapter->flash_capacity) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content will cross max flash size\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ temp_content_size = content_size;
+ num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
+
+ rsi_dbg(INFO_ZONE, "content_size: %d, num_flash: %d\n",
+ content_size, num_flash);
+
+ for (index = 0; index <= num_flash; index++) {
+ rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+ if (index != num_flash) {
+ content_size = FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE, "QSPI content_size:%d\n",
+ content_size);
+ } else {
+ content_size =
+ temp_content_size % FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE,
+ "Writing last sector content_size:%d\n",
+ content_size);
+ if (!content_size) {
+ rsi_dbg(INFO_ZONE, "instruction size zero\n");
+ break;
+ }
+ }
+
+ if (index % 2)
+ cmd = PING_WRITE;
+ else
+ cmd = PONG_WRITE;
+
+ status = ping_pong_write(adapter, cmd, flash_content,
+ content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to load %d block\n",
+ __func__, index);
+ return status;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Successfully loaded %d instructions\n",
+ __func__, index);
+ flash_content += content_size;
+ }
+
+ status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
+ "EOF_REACHED");
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+ return 0;
+}
+
+static int rsi_load_firmware(struct rsi_hw *adapter)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ const struct firmware *fw_entry = NULL;
+ u32 regout_val = 0, content_size;
+ u16 tmp_regout_val = 0;
+ u8 *flash_content = NULL;
+ struct ta_metadata *metadata_p;
+ int status;
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+
+ while (!adapter->blcmd_timer_expired) {
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ &regout_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: REGOUT read failed\n", __func__);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+ rsi_dbg(ERR_ZONE,
+ "%s: Soft boot loader not present\n", __func__);
+ return -ETIMEDOUT;
+ }
+ bl_stop_cmd_timer(adapter);
+
+ rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+ (regout_val & 0xff));
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (REGOUT_INVALID | REGOUT_INVALID << 8),
+ 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+ return status;
+ }
+ mdelay(1);
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_CMD");
+ if (status < 0)
+ return status;
+
+ adapter->flash_capacity = read_flash_capacity(adapter);
+ if (adapter->flash_capacity <= 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to read flash size from EEPROM\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
+
+ rsi_dbg(INIT_ZONE, "%s: Loading file %s\n", __func__, metadata_p->name);
+ adapter->fw_file_name = metadata_p->name;
+
+ status = request_firmware(&fw_entry, metadata_p->name, adapter->device);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ __func__, metadata_p->name);
+ return status;
+ }
+ flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!flash_content) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+ status = -EIO;
+ goto fail;
+ }
+ content_size = fw_entry->size;
+ rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+
+ status = bl_write_header(adapter, flash_content, content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: RPS Image header loading failed\n",
+ __func__);
+ goto fail;
+ }
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+ status = bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ rsi_dbg(ERR_ZONE,
+ "%s: CHECK_CRC Command writing failed..\n",
+ __func__);
+ if ((tmp_regout_val & 0xff) == CMD_FAIL) {
+ rsi_dbg(ERR_ZONE,
+ "CRC Fail.. Proceeding to Upgrade mode\n");
+ goto fw_upgrade;
+ }
+ }
+ bl_stop_cmd_timer(adapter);
+
+ status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, "POLLING_MODE");
+ if (status)
+ goto fail;
+
+load_image_cmd:
+ status = bl_cmd(adapter, LOAD_HOSTED_FW, LOADING_INITIATED,
+ "LOAD_HOSTED_FW");
+ if (status)
+ goto fail;
+ rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+ goto success;
+
+fw_upgrade:
+ status = bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE");
+ if (status)
+ goto fail;
+
+ rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+
+ status = auto_fw_upgrade(adapter, flash_content, content_size);
+ if (status == 0) {
+ rsi_dbg(ERR_ZONE, "Firmware upgradation Done\n");
+ goto load_image_cmd;
+ }
+ rsi_dbg(ERR_ZONE, "Firmware upgrade failed\n");
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_MODE");
+ if (status)
+ goto fail;
+
+success:
+ rsi_dbg(ERR_ZONE, "***** Firmware Loading successful *****\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return 0;
+
+fail:
+ rsi_dbg(ERR_ZONE, "##### Firmware loading failed #####\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return status;
+}
+
+int rsi_hal_device_init(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+
+ common->coex_mode = 1;
+ adapter->device_model = RSI_DEV_9113;
+
+ switch (adapter->device_model) {
+ case RSI_DEV_9113:
+ if (rsi_load_firmware(adapter)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load TA instructions\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_hal_device_init);
+
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index b397e2c..2ef844a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include "rsi_sdio.h"
#include "rsi_common.h"
+#include "rsi_hal.h"

/**
* rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
@@ -365,6 +366,7 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)

status = sdio_set_block_size(dev->pfunction, length);
dev->pfunction->max_blksize = 256;
+ adapter->block_size = dev->pfunction->max_blksize;

rsi_dbg(INFO_ZONE,
"%s: Operational blk length is %d\n", __func__, length);
@@ -868,6 +870,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
static struct rsi_host_intf_ops sdio_host_intf_ops = {
.write_pkt = rsi_sdio_host_intf_write_pkt,
.read_pkt = rsi_sdio_host_intf_read_pkt,
+ .master_access_msword = rsi_sdio_master_access_msword,
.read_reg_multiple = rsi_sdio_read_register_multiple,
.write_reg_multiple = rsi_sdio_write_register_multiple,
.master_reg_read = rsi_sdio_master_reg_read,
@@ -906,13 +909,19 @@ static int rsi_probe(struct sdio_func *pfunction,
goto fail;
}

- if (rsi_sdio_device_init(adapter->priv)) {
+ if (rsi_hal_device_init(adapter)) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
sdio_claim_host(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
goto fail;
}
+ rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
+
+ if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return -EIO;
+ }

sdio_claim_host(pfunction);
if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 7156fcb..10dc724 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -17,6 +17,7 @@

#include <linux/module.h>
#include "rsi_usb.h"
+#include "rsi_hal.h"

/**
* rsi_usb_card_write() - This function writes to the USB Card.
@@ -515,6 +516,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
}
rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
rsi_dev->tx_blk_size = 252;
+ adapter->block_size = rsi_dev->tx_blk_size;

/* Initializing function callbacks */
adapter->rx_urb_submit = rsi_rx_urb_submit;
@@ -573,6 +575,7 @@ static int rsi_probe(struct usb_interface *pfunction,
__func__);
return -ENOMEM;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;

status = rsi_init_usb_interface(adapter, pfunction);
if (status) {
@@ -586,25 +589,20 @@ static int rsi_probe(struct usb_interface *pfunction,
dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;

status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
- if (status)
+ if (status < 0)
goto err1;
else
fw_status &= 1;

if (!fw_status) {
- status = rsi_usb_device_init(adapter->priv);
+ rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+ status = rsi_hal_device_init(adapter);
if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
__func__);
goto err1;
}
-
- status = rsi_usb_reg_write(dev->usbdev,
- USB_INTERNAL_REG_1,
- RSI_USB_READY_MAGIC_NUM, 1);
- if (status)
- goto err1;
- rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
+ rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
}

status = rsi_rx_urb_submit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
new file mode 100644
index 0000000..e1c26e5
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HAL_H__
+#define __RSI_HAL_H__
+
+#define FLASH_WRITE_CHUNK_SIZE (4 * 1024)
+#define FLASH_SECTOR_SIZE (4 * 1024)
+
+#define FLASH_SIZE_ADDR 0x04000016
+#define PING_BUFFER_ADDRESS 0x19000
+#define PONG_BUFFER_ADDRESS 0x1a000
+#define SWBL_REGIN 0x41050034
+#define SWBL_REGOUT 0x4105003c
+#define PING_WRITE 0x1
+#define PONG_WRITE 0x2
+
+#define BL_CMD_TIMEOUT 2000
+#define BL_BURN_TIMEOUT (50 * 1000)
+
+#define MASTER_READ_MODE 1
+#define EEPROM_READ_MODE 2
+
+#define REGIN_VALID 0xA
+#define REGIN_INPUT 0xA0
+#define REGOUT_VALID 0xAB
+#define REGOUT_INVALID (~0xAB)
+#define CMD_PASS 0xAA
+#define CMD_FAIL 0xCC
+#define INVALID_ADDR 0x4C
+
+#define LOAD_HOSTED_FW 'A'
+#define BURN_HOSTED_FW 'B'
+#define PING_VALID 'I'
+#define PONG_VALID 'O'
+#define PING_AVAIL 'I'
+#define PONG_AVAIL 'O'
+#define EOF_REACHED 'E'
+#define CHECK_CRC 'K'
+#define POLLING_MODE 'P'
+#define CONFIG_AUTO_READ_MODE 'R'
+#define JUMP_TO_ZERO_PC 'J'
+#define FW_LOADING_SUCCESSFUL 'S'
+#define LOADING_INITIATED '1'
+
+/* Boot loader commands */
+#define SEND_RPS_FILE '2'
+
+#define FW_IMAGE_MIN_ADDRESS (68 * 1024)
+#define FLASH_MAX_ADDRESS (4 * 1024 * 1024) //4MB
+#define MAX_FLASH_FILE_SIZE (400 * 1024) //400K
+#define FLASH_START_ADDRESS 16
+#define CALIB_VALUES_START_ADDR 16
+#define EEPROM_DATA_SIZE 4096
+#define BL_HEADER 32
+
+#define WLAN_CARD_READY_IND 0x0
+#define COMMON_HAL_CARD_READY_IND 0x0
+
+#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+
+struct bl_header {
+ __le32 flags;
+ __le32 image_no;
+ __le32 check_sum;
+ __le32 flash_start_address;
+ __le32 flash_len;
+} __packed;
+
+struct ta_metadata {
+ char *name;
+ unsigned int address;
+};
+
+int rsi_hal_device_init(struct rsi_hw *adapter);
+
+#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 2ac5bcf..ea4fc22 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -82,6 +82,8 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
((_q) == VI_Q) ? IEEE80211_AC_VI : \
IEEE80211_AC_VO)

+#define RSI_DEV_9113 1
+
struct version_info {
u16 major;
u16 minor;
@@ -204,6 +206,7 @@ struct rsi_common {
struct cqm_info cqm_info;

bool hw_data_qs_blocked;
+ u8 coex_mode;

int tx_power;
u8 ant_in_use;
@@ -216,6 +219,7 @@ enum host_intf {

struct rsi_hw {
struct rsi_common *priv;
+ u8 device_model;
struct ieee80211_hw *hw;
struct ieee80211_vif *vifs[RSI_MAX_VIFS];
struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
@@ -225,10 +229,15 @@ struct rsi_hw {
u8 sc_nvifs;

enum host_intf rsi_host_intf;
+ u16 block_size;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
+ char *fw_file_name;
+ struct timer_list bl_cmd_timer;
+ bool blcmd_timer_expired;
+ u32 flash_capacity;
u8 dfs_region;
void *rsi_dev;
struct rsi_host_intf_ops *host_intf_ops;
@@ -240,6 +249,7 @@ struct rsi_hw {
struct rsi_host_intf_ops {
int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*master_access_msword)(struct rsi_hw *adapter, u16 ms_word);
int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
--
2.7.4

2017-05-11 18:28:43

by Kalle Valo

[permalink] [raw]
Subject: Re: [v2 05/11] rsi: Remove unnecessary buffer allocation

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> In functions usb read register and usb write register, dynamic allocation
> of 4 bytes is used. This is removed as it is unncessary for local variable
> and for such small data.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> drivers/net/wireless/rsi/rsi_91x_usb.c | 18 ++++--------------
> 1 file changed, 4 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
> index 73b01a8..8eb7407 100644
> --- a/drivers/net/wireless/rsi/rsi_91x_usb.c
> +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
> @@ -157,12 +157,8 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
> u16 *value,
> u16 len)
> {
> - u8 *buf;
> - int status = -ENOMEM;
> -
> - buf = kmalloc(0x04, GFP_KERNEL);
> - if (!buf)
> - return status;
> + u8 buf[4];
> + int status;
>
> status = usb_control_msg(usbdev,
> usb_rcvctrlpipe(usbdev, 0),

Recently I got a patch to orinoco_usb which did exactly the opposite
(unless I'm missing something):

https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git/commit/?id=2f6ae79cb04bb7f9b4be3f1c32b6fda35bf976bc

The documentation for usb_control_msg() does not mention anything if
it's possible to use stack memory, but AFAIU it's not possible to use
stack memory with DMA. Can anyone clarify?

--
Kalle Valo

2017-05-09 13:32:04

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 06/11] rsi: Handle usb multi-byte write failure case properly

From: Prameela Rani Garnepudi <[email protected]>

In function usb_write_register_multiple, if any intermediate block transfer
is failed, further operations should be terminated. 'else' is removed, as
there is no significance for it after return.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 8eb7407..634f726 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -306,11 +306,12 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
rsi_dbg(ERR_ZONE,
"Reg write failed with error code :%d\n",
status);
- } else {
- count -= transfer;
- data += transfer;
- addr += transfer;
+ kfree(buf);
+ return status;
}
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
}

kfree(buf);
--
2.7.4

2017-05-09 13:32:00

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 05/11] rsi: Remove unnecessary buffer allocation

From: Prameela Rani Garnepudi <[email protected]>

In functions usb read register and usb write register, dynamic allocation
of 4 bytes is used. This is removed as it is unncessary for local variable
and for such small data.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 73b01a8..8eb7407 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -157,12 +157,8 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
u16 *value,
u16 len)
{
- u8 *buf;
- int status = -ENOMEM;
-
- buf = kmalloc(0x04, GFP_KERNEL);
- if (!buf)
- return status;
+ u8 buf[4];
+ int status;

status = usb_control_msg(usbdev,
usb_rcvctrlpipe(usbdev, 0),
@@ -179,7 +175,6 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
"%s: Reg read failed with error code :%d\n",
__func__, status);
}
- kfree(buf);

return status;
}
@@ -199,12 +194,8 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
u16 value,
u16 len)
{
- u8 *usb_reg_buf;
- int status = -ENOMEM;
-
- usb_reg_buf = kmalloc(0x04, GFP_KERNEL);
- if (!usb_reg_buf)
- return status;
+ u8 usb_reg_buf[4];
+ int status;

usb_reg_buf[0] = (value & 0x00ff);
usb_reg_buf[1] = (value & 0xff00) >> 8;
@@ -225,7 +216,6 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
"%s: Reg write failed with error code :%d\n",
__func__, status);
}
- kfree(usb_reg_buf);

return status;
}
--
2.7.4

2017-05-16 10:09:29

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v2 10/11] rsi: Add new firmware loading method

On Fri, May 12, 2017 at 2:15 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> The older firmware loading method has been deprecated and not in use
>> for any chipets. New method is introduced which works based on soft
>> boot loader. In this method, complete RAM image and FLASH image are
>> present in the flash. Before loading the functional firmware, host
>> issues boot loader commands to verify whether firmware to load is
>> different from the current functional firmware. If not, firmware
>> upgrade progresses and boot loader will switch to the new functional
>> firmware.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> Please document in the commit log the new firmware filenames used by
> this patch.
>

Sure. This has been taken care in updated version.

Regards,
Amitkumar