Commit 5fe4dffb authored by Kalle Valo's avatar Kalle Valo

ath6kl: power down hardware when interface is down

The benefit from this is that user space can control hardware's power state
by putting interface up and down. This is handy if firmware gets to some
weird state.

The downside will be that putting interface up takes a bit longer,
I was measuring ~500 ms during interface up.
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 32a07e44
......@@ -670,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
return ret;
}
void ath6kl_bmi_reset(struct ath6kl *ar)
{
ar->bmi.done_sent = false;
}
int ath6kl_bmi_init(struct ath6kl *ar)
{
ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
......
......@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info {
int ath6kl_bmi_init(struct ath6kl *ar);
void ath6kl_bmi_cleanup(struct ath6kl *ar);
void ath6kl_bmi_reset(struct ath6kl *ar);
int ath6kl_bmi_done(struct ath6kl *ar);
int ath6kl_bmi_get_target_info(struct ath6kl *ar,
struct ath6kl_bmi_target_info *targ_info);
......
......@@ -447,6 +447,7 @@ enum ath6kl_dev_state {
DESTROY_IN_PROGRESS,
SKIP_SCAN,
ROAM_TBL_PEND,
FIRST_BOOT,
};
struct ath6kl {
......@@ -662,4 +663,7 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
void ath6kl_core_free(struct ath6kl *ar);
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
int ath6kl_init_hw_start(struct ath6kl *ar);
int ath6kl_init_hw_stop(struct ath6kl *ar);
#endif /* CORE_H */
......@@ -2622,6 +2622,9 @@ int ath6kl_htc_start(struct htc_target *target)
struct htc_packet *packet;
int status;
memset(&target->dev->irq_proc_reg, 0,
sizeof(target->dev->irq_proc_reg));
/* Disable interrupts at the chip level */
ath6kl_hif_disable_intrs(target->dev);
......
......@@ -1421,11 +1421,13 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
return 0;
}
static int ath6kl_hw_start(struct ath6kl *ar)
int ath6kl_init_hw_start(struct ath6kl *ar)
{
long timeleft;
int ret, i;
ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
ret = ath6kl_hif_power_on(ar);
if (ret)
return ret;
......@@ -1517,6 +1519,25 @@ static int ath6kl_hw_start(struct ath6kl *ar)
return ret;
}
int ath6kl_init_hw_stop(struct ath6kl *ar)
{
int ret;
ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
ath6kl_htc_stop(ar->htc_target);
ath6kl_hif_stop(ar);
ath6kl_bmi_reset(ar);
ret = ath6kl_hif_power_off(ar);
if (ret)
ath6kl_warn("failed to power off hif: %d\n", ret);
return 0;
}
int ath6kl_core_init(struct ath6kl *ar)
{
struct ath6kl_bmi_target_info targ_info;
......@@ -1629,9 +1650,11 @@ int ath6kl_core_init(struct ath6kl *ar)
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME;
ret = ath6kl_hw_start(ar);
set_bit(FIRST_BOOT, &ar->flag);
ret = ath6kl_init_hw_start(ar);
if (ret) {
ath6kl_err("Failed to boot hardware: %d\n", ret);
ath6kl_err("Failed to start hardware: %d\n", ret);
goto err_rxbuf_cleanup;
}
......@@ -1641,6 +1664,12 @@ int ath6kl_core_init(struct ath6kl *ar)
*/
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
ret = ath6kl_init_hw_stop(ar);
if (ret) {
ath6kl_err("Failed to stop hardware: %d\n", ret);
goto err_htc_cleanup;
}
return ret;
err_rxbuf_cleanup:
......
......@@ -673,10 +673,12 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
set_bit(WMI_READY, &ar->flag);
wake_up(&ar->event_wq);
ath6kl_info("hw %s fw %s%s\n",
get_hw_id_string(ar->wiphy->hw_version),
ar->wiphy->fw_version,
test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
ath6kl_info("hw %s fw %s%s\n",
get_hw_id_string(ar->wiphy->hw_version),
ar->wiphy->fw_version,
test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
}
}
void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
......@@ -1112,6 +1114,12 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
static int ath6kl_open(struct net_device *dev)
{
struct ath6kl_vif *vif = netdev_priv(dev);
int ret;
/* FIXME: how to handle multi vif support? */
ret = ath6kl_init_hw_start(vif->ar);
if (ret)
return ret;
set_bit(WLAN_ENABLED, &vif->flags);
......@@ -1128,6 +1136,7 @@ static int ath6kl_close(struct net_device *dev)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
int ret;
netif_stop_queue(dev);
......@@ -1143,6 +1152,11 @@ static int ath6kl_close(struct net_device *dev)
ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
/* FIXME: how to handle multi vif support? */
ret = ath6kl_init_hw_stop(ar);
if (ret)
return ret;
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment