2013-03-09 10:01:32

by Kalle Valo

[permalink] [raw]
Subject: [PATCH v2 0/3] ath6kl: fix usb warm reboot and cleanups

While looking at the usb warm reboot I had to some cleanup, especially with error
handling.

v2:

o don't remove reset from ath6kl_stop_txrx()
o line wrap commit logs

---

Kalle Valo (3):
ath6kl: cleanup ath6kl_reset_device()
ath6kl: fix usb related error handling and warnings
ath6kl: cold reset target after host warm boot


drivers/net/wireless/ath/ath6kl/core.h | 2 --
drivers/net/wireless/ath/ath6kl/htc_pipe.c | 12 +++++-----
drivers/net/wireless/ath/ath6kl/init.c | 33 +++++++++++++++++++++------
drivers/net/wireless/ath/ath6kl/main.c | 33 ---------------------------
drivers/net/wireless/ath/ath6kl/target.h | 2 +-
drivers/net/wireless/ath/ath6kl/usb.c | 34 ++++++++++++++++++----------
6 files changed, 55 insertions(+), 61 deletions(-)



2013-03-11 10:26:09

by Julien Massot

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] ath6kl: cold reset target after host warm boot

Hi Kalle,

> Julien reported that ar6004 usb device fails to initialise
> after host has been rebooted and power is still on for the ar6004 device. He
> found out that doing a cold reset fixes the issue.
>
> I wasn't sure what would be the best way to detect if target needs a reset so I
> settled on checking a timeout from htc_wait_recv_ctrl_message().
>
> Reported-by: Julien Massot <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>
> ---

This patch fix the issue, now my adapter works after a soft reboot.
The log are also better: (here is what happen on soft reboot)

[ 17.328029] ath6kl: htc pipe control receive timeout!
[ 17.328033] ath6kl: htc wait target timed out, resetting device
[ 17.332178] ath6kl: Failed to start hardware: -110
[ 17.332208] ath6kl: Failed to init ath6kl core: -110
[ 17.332270] ath6kl_usb: probe of 2-1:1.0 failed with error -110
[ 17.332306] usbcore: registered new interface driver ath6kl_usb
[ 19.040315] ath6kl: ar6004 hw 1.3 usb fw 3.5.0.2356\x01 api 3

Thanks!

Tested-by: Julien Massot <[email protected]>

Julien

2013-03-11 11:11:14

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] ath6kl: cold reset target after host warm boot

Julien Massot <[email protected]> writes:

>> Julien reported that ar6004 usb device fails to initialise
>> after host has been rebooted and power is still on for the ar6004 device. He
>> found out that doing a cold reset fixes the issue.
>>
>> I wasn't sure what would be the best way to detect if target needs a reset so I
>> settled on checking a timeout from htc_wait_recv_ctrl_message().
>>
>> Reported-by: Julien Massot <[email protected]>
>> Signed-off-by: Kalle Valo <[email protected]>
>> ---
>
> This patch fix the issue, now my adapter works after a soft reboot.
> The log are also better: (here is what happen on soft reboot)
>
> [ 17.328029] ath6kl: htc pipe control receive timeout!
> [ 17.328033] ath6kl: htc wait target timed out, resetting device
> [ 17.332178] ath6kl: Failed to start hardware: -110
> [ 17.332208] ath6kl: Failed to init ath6kl core: -110
> [ 17.332270] ath6kl_usb: probe of 2-1:1.0 failed with error -110
> [ 17.332306] usbcore: registered new interface driver ath6kl_usb
> [ 19.040315] ath6kl: ar6004 hw 1.3 usb fw 3.5.0.2356\x01 api 3

Oh, I also need to fix that \x01 in the firmware version, the null
termination is incorrect. But this is a separate issue.

> Tested-by: Julien Massot <[email protected]>

Thank you. I add that to the patch.

--
Kalle Valo

2013-03-09 10:01:53

by Kalle Valo

[permalink] [raw]
Subject: [PATCH v2 3/3] ath6kl: cold reset target after host warm boot

Julien reported that ar6004 usb device fails to initialise
after host has been rebooted and power is still on for the ar6004 device. He
found out that doing a cold reset fixes the issue.

I wasn't sure what would be the best way to detect if target needs a reset so I
settled on checking a timeout from htc_wait_recv_ctrl_message().

Reported-by: Julien Massot <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/ath/ath6kl/htc_pipe.c | 2 +-
drivers/net/wireless/ath/ath6kl/init.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index c02d9d3..67aa924 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -1168,7 +1168,7 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)

if (count <= 0) {
ath6kl_warn("htc pipe control receive timeout!\n");
- return -ECOMM;
+ return -ETIMEDOUT;
}

return 0;
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 8b01ec3..4ad45bb 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1658,7 +1658,18 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar)
* size.
*/
ret = ath6kl_htc_wait_target(ar->htc_target);
- if (ret) {
+
+ if (ret == -ETIMEDOUT) {
+ /*
+ * Most likely USB target is in odd state after reboot and
+ * needs a reset. A cold reset makes the whole device
+ * disappear from USB bus and initialisation starts from
+ * beginning.
+ */
+ ath6kl_warn("htc wait target timed out, resetting device\n");
+ ath6kl_init_hw_reset(ar);
+ goto err_power_off;
+ } else if (ret) {
ath6kl_err("htc wait target failed: %d\n", ret);
goto err_power_off;
}


2013-03-09 10:01:46

by Kalle Valo

[permalink] [raw]
Subject: [PATCH v2 2/3] ath6kl: fix usb related error handling and warnings

It was annoying to debug usb warm reboot initialisation problems as many usb
related functions just ignored errors and it wasn't obvious from the kernel
logs what was failing. Fix all that so that error messages are printed and
errors are handled properly.

Signed-off-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/ath/ath6kl/htc_pipe.c | 10 ++++----
drivers/net/wireless/ath/ath6kl/init.c | 10 +++++---
drivers/net/wireless/ath/ath6kl/usb.c | 34 ++++++++++++++++++----------
3 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 9adb567..c02d9d3 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -1167,7 +1167,7 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
}

if (count <= 0) {
- ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__);
+ ath6kl_warn("htc pipe control receive timeout!\n");
return -ECOMM;
}

@@ -1581,16 +1581,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target)
return status;

if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) {
- ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n",
- target->pipe.ctrl_response_len);
+ ath6kl_warn("invalid htc pipe ready msg len: %d\n",
+ target->pipe.ctrl_response_len);
return -ECOMM;
}

ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf;

if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) {
- ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n",
- ready_msg->ver2_0_info.msg_id);
+ ath6kl_warn("invalid htc pipe ready msg: 0x%x\n",
+ ready_msg->ver2_0_info.msg_id);
return -ECOMM;
}

diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index ae1e477..8b01ec3 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1657,13 +1657,15 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar)
* driver layer has to init BMI in order to set the host block
* size.
*/
- if (ath6kl_htc_wait_target(ar->htc_target)) {
- ret = -EIO;
+ ret = ath6kl_htc_wait_target(ar->htc_target);
+ if (ret) {
+ ath6kl_err("htc wait target failed: %d\n", ret);
goto err_power_off;
}

- if (ath6kl_init_service_ep(ar)) {
- ret = -EIO;
+ ret = ath6kl_init_service_ep(ar);
+ if (ret) {
+ ath6kl_err("Endpoint service initilisation failed: %d\n", ret);
goto err_cleanup_scatter;
}

diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 5fcd342..63948f6 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -872,8 +872,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb,
size, 1000);

if (ret < 0) {
- ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
- __func__, ret);
+ ath6kl_warn("Failed to submit usb control message: %d\n", ret);
+ kfree(buf);
+ return ret;
}

kfree(buf);
@@ -903,8 +904,9 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb,
size, 2 * HZ);

if (ret < 0) {
- ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
- __func__, ret);
+ ath6kl_warn("Failed to read usb control message: %d\n", ret);
+ kfree(buf);
+ return ret;
}

memcpy((u8 *) data, buf, size);
@@ -961,8 +963,10 @@ static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
ATH6KL_USB_CONTROL_REQ_DIAG_RESP,
ar_usb->diag_resp_buffer, &resp_len);

- if (ret)
+ if (ret) {
+ ath6kl_warn("diag read32 failed: %d\n", ret);
return ret;
+ }

resp = (struct ath6kl_usb_ctrl_diag_resp_read *)
ar_usb->diag_resp_buffer;
@@ -976,6 +980,7 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
{
struct ath6kl_usb *ar_usb = ar->hif_priv;
struct ath6kl_usb_ctrl_diag_cmd_write *cmd;
+ int ret;

cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer;

@@ -984,12 +989,17 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
cmd->address = cpu_to_le32(address);
cmd->value = data;

- return ath6kl_usb_ctrl_msg_exchange(ar_usb,
- ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
- (u8 *) cmd,
- sizeof(*cmd),
- 0, NULL, NULL);
+ ret = ath6kl_usb_ctrl_msg_exchange(ar_usb,
+ ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
+ (u8 *) cmd,
+ sizeof(*cmd),
+ 0, NULL, NULL);
+ if (ret) {
+ ath6kl_warn("diag_write32 failed: %d\n", ret);
+ return ret;
+ }

+ return 0;
}

static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
@@ -1001,7 +1011,7 @@ static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
ret = ath6kl_usb_submit_ctrl_in(ar_usb,
ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP,
0, 0, buf, len);
- if (ret != 0) {
+ if (ret) {
ath6kl_err("Unable to read the bmi data from the device: %d\n",
ret);
return ret;
@@ -1019,7 +1029,7 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
ret = ath6kl_usb_submit_ctrl_out(ar_usb,
ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD,
0, 0, buf, len);
- if (ret != 0) {
+ if (ret) {
ath6kl_err("unable to send the bmi data to the device: %d\n",
ret);
return ret;


2013-03-12 16:26:37

by Mohammed Shafi Shajakhan

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] ath6kl: cold reset target after host warm boot

On 03/11/2013 04:41 PM, Kalle Valo wrote:
> Julien Massot <[email protected]> writes:
>
>>> Julien reported that ar6004 usb device fails to initialise
>>> after host has been rebooted and power is still on for the ar6004 device. He
>>> found out that doing a cold reset fixes the issue.
>>>
>>> I wasn't sure what would be the best way to detect if target needs a reset so I
>>> settled on checking a timeout from htc_wait_recv_ctrl_message().
>>>
>>> Reported-by: Julien Massot <[email protected]>
>>> Signed-off-by: Kalle Valo <[email protected]>
>>> ---
>>
>> This patch fix the issue, now my adapter works after a soft reboot.
>> The log are also better: (here is what happen on soft reboot)
>>
>> [ 17.328029] ath6kl: htc pipe control receive timeout!
>> [ 17.328033] ath6kl: htc wait target timed out, resetting device
>> [ 17.332178] ath6kl: Failed to start hardware: -110
>> [ 17.332208] ath6kl: Failed to init ath6kl core: -110
>> [ 17.332270] ath6kl_usb: probe of 2-1:1.0 failed with error -110
>> [ 17.332306] usbcore: registered new interface driver ath6kl_usb
>> [ 19.040315] ath6kl: ar6004 hw 1.3 usb fw 3.5.0.2356\x01 api 3
>
> Oh, I also need to fix that \x01 in the firmware version, the null
> termination is incorrect. But this is a separate issue.
>
>> Tested-by: Julien Massot <[email protected]>
>
> Thank you. I add that to the patch.
>
Kalle,

attached the internally suggested patch with CL explanation, not rebased.

During host crashes or some unexpected reasons causing driver reload
without unload first, the target firmware will fail to upload again
since it never power down or reset by host. We check the host app area
to check target status and reset target if needed.


--
thanks,
shafi


Attachments:
0001-ath6kl-Reset-target-if-the-firmware-is-already-uploa.patch (2.50 kB)

2013-03-18 11:40:22

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ath6kl: fix usb warm reboot and cleanups

Kalle Valo <[email protected]> writes:

> While looking at the usb warm reboot I had to some cleanup, especially with error
> handling.
>
> v2:
>
> o don't remove reset from ath6kl_stop_txrx()
> o line wrap commit logs
>
> ---
>
> Kalle Valo (3):
> ath6kl: cleanup ath6kl_reset_device()
> ath6kl: fix usb related error handling and warnings
> ath6kl: cold reset target after host warm boot

All three patches applied.

--
Kalle Valo

2013-03-09 10:01:39

by Kalle Valo

[permalink] [raw]
Subject: [PATCH v2 1/3] ath6kl: cleanup ath6kl_reset_device()

Move it to init.c, make it static, remove all useless checks and force it to
always do cold reset.

Signed-off-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/ath/ath6kl/core.h | 2 --
drivers/net/wireless/ath/ath6kl/init.c | 12 ++++++++---
drivers/net/wireless/ath/ath6kl/main.c | 33 ------------------------------
drivers/net/wireless/ath/ath6kl/target.h | 2 +-
4 files changed, 10 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 1c9ed40..26b0f92 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -935,8 +935,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
u8 win_sz);
void ath6kl_wakeup_event(void *dev);

-void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
- bool wait_fot_compltn, bool cold_reset);
void ath6kl_init_control_info(struct ath6kl_vif *vif);
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 3e45adc..ae1e477 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1619,6 +1619,14 @@ static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len)
buf[len] = '\0';
}

+static int ath6kl_init_hw_reset(struct ath6kl *ar)
+{
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device");
+
+ return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS,
+ cpu_to_le32(RESET_CONTROL_COLD_RST));
+}
+
static int __ath6kl_init_hw_start(struct ath6kl *ar)
{
long timeleft;
@@ -1836,9 +1844,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
* Try to reset the device if we can. The driver may have been
* configure NOT to reset the target during a debug session.
*/
- ath6kl_dbg(ATH6KL_DBG_TRC,
- "attempting to reset target on instance destroy\n");
- ath6kl_reset_device(ar, ar->target_type, true, true);
+ ath6kl_init_hw_reset(ar);

up(&ar->sem);
}
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index bd50b6b..bad62b3 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -345,39 +345,6 @@ out:
return ret;
}

-/* FIXME: move to a better place, target.h? */
-#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
-#define AR6004_RESET_CONTROL_ADDRESS 0x00004000
-
-void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
- bool wait_fot_compltn, bool cold_reset)
-{
- int status = 0;
- u32 address;
- __le32 data;
-
- if (target_type != TARGET_TYPE_AR6003 &&
- target_type != TARGET_TYPE_AR6004)
- return;
-
- data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
- cpu_to_le32(RESET_CONTROL_MBOX_RST);
-
- switch (target_type) {
- case TARGET_TYPE_AR6003:
- address = AR6003_RESET_CONTROL_ADDRESS;
- break;
- case TARGET_TYPE_AR6004:
- address = AR6004_RESET_CONTROL_ADDRESS;
- break;
- }
-
- status = ath6kl_diag_write32(ar, address, data);
-
- if (status)
- ath6kl_err("failed to reset target\n");
-}
-
static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif)
{
u8 index;
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
index a98c12b..a580a62 100644
--- a/drivers/net/wireless/ath/ath6kl/target.h
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -25,7 +25,7 @@
#define AR6004_BOARD_DATA_SZ 6144
#define AR6004_BOARD_EXT_DATA_SZ 0

-#define RESET_CONTROL_ADDRESS 0x00000000
+#define RESET_CONTROL_ADDRESS 0x00004000
#define RESET_CONTROL_COLD_RST 0x00000100
#define RESET_CONTROL_MBOX_RST 0x00000004