From d4a1bd480003f3e1a0590bc46fbcb24f05652ca7 Mon Sep 17 00:00:00 2001
From: tzh <tanzhtanzh@gmail.com>
Date: Thu, 15 Aug 2024 06:56:47 +0000
Subject: [PATCH] feat(wfit/bt): update aic8800 wifi/bt drive and hal

---
 longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c |  131 +++++++++++++++++++++++++++++--------------
 1 files changed, 88 insertions(+), 43 deletions(-)

diff --git a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c
old mode 100644
new mode 100755
index 141e59e..babf6dc
--- a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c
+++ b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c
@@ -80,37 +80,70 @@
 
 int aicbsp_set_subsys(int subsys, int state)
 {
-	static int cur_state;
-	static int aic_power_state;
+	static int pre_power_map;
+	int cur_power_map;
+	int pre_power_state;
+	int cur_power_state;
 
 	mutex_lock(&aicbsp_power_lock);
+	cur_power_map = pre_power_map;
 	if (state)
-		aic_power_state |= (1 << subsys);
+		cur_power_map |= (1 << subsys);
 	else
-		aic_power_state &= ~(1 << subsys);
+		cur_power_map &= ~(1 << subsys);
+
+	pre_power_state = pre_power_map > 0;
+	cur_power_state = cur_power_map > 0;
 
 	sdio_dbg("%s, subsys: %s, state to: %d\n", __func__, aicbsp_subsys_name(subsys), state);
 
-	if (cur_state != (aic_power_state > 0)) {
-		cur_state = (aic_power_state > 0);
-		sdio_dbg("%s, power state change to %d dure to %s\n", __func__, cur_state, aicbsp_subsys_name(subsys));
-		if (cur_state) {
-			aicbsp_platform_power_on();
-			aicbsp_sdio_init();
-			aicbsp_driver_fw_init(aicbsp_sdiodev);
+	if (cur_power_state != pre_power_state) {
+		sdio_dbg("%s, power state change to %d dure to %s\n", __func__, cur_power_state, aicbsp_subsys_name(subsys));
+		if (cur_power_state) {
+			if (aicbsp_platform_power_on() < 0)
+				goto err0;
+			if (aicbsp_sdio_init())
+				goto err1;
+			if (!aicbsp_sdiodev)
+				goto err2;
+			if (aicbsp_driver_fw_init(aicbsp_sdiodev))
+				goto err3;
 			aicbsp_sdio_release(aicbsp_sdiodev);
 		} else {
 			aicbsp_sdio_exit();
 			aicbsp_platform_power_off();
 		}
 	} else {
-		sdio_dbg("%s, power state no need to change\n", __func__);
+		sdio_dbg("%s, power state no need to change, current: %d\n", __func__, cur_power_state);
 	}
+	pre_power_map = cur_power_map;
 	mutex_unlock(&aicbsp_power_lock);
 
-	return cur_state > 0;
+	return cur_power_state;
+
+err3:
+	aicbsp_sdio_release(aicbsp_sdiodev);
+
+err2:
+	aicbsp_sdio_exit();
+
+err1:
+	aicbsp_platform_power_off();
+
+err0:
+	sdio_dbg("%s, fail to set %s power state to %d\n", __func__, aicbsp_subsys_name(subsys), state);
+	mutex_unlock(&aicbsp_power_lock);
+	return -1;
 }
 EXPORT_SYMBOL_GPL(aicbsp_set_subsys);
+
+void *aicbsp_get_drvdata(void *args)
+{
+	(void)args;
+	if (aicbsp_sdiodev)
+		return aicbsp_sdiodev->bus_if;
+	return dev_get_drvdata((const struct device *)args);
+}
 
 static int aicbsp_sdio_probe(struct sdio_func *func,
 	const struct sdio_device_id *id)
@@ -121,12 +154,12 @@
 	int err = -ENODEV;
 
 	sdio_dbg("%s:%d\n", __func__, func->num);
-	host = func->card->host;
 	if (func->num != 2) {
 		return err;
 	}
 
 	func = func->card->sdio_func[1 - 1]; //replace 2 with 1
+	host = func->card->host;
 	sdio_dbg("%s after replace:%d\n", __func__, func->num);
 
 	bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL);
@@ -155,6 +188,7 @@
 
 	if (aicwf_sdio_bus_init(sdiodev) == NULL) {
 		sdio_err("sdio bus init err\r\n");
+		err = -1;
 		goto fail;
 	}
 	host->caps |= MMC_CAP_NONREMOVABLE;
@@ -177,17 +211,20 @@
 	struct aic_sdio_dev *sdiodev = NULL;
 
 	sdio_dbg("%s\n", __func__);
-	host = func->card->host;
-	host->caps &= ~MMC_CAP_NONREMOVABLE;
-	bus_if = dev_get_drvdata(&func->dev);
+	bus_if = aicbsp_get_drvdata(&func->dev);
 	if (!bus_if) {
-		return;
+		sdio_dbg("%s: allready unregister\n", __func__);
+		goto done;
 	}
 
 	sdiodev = bus_if->bus_priv.sdio;
 	if (!sdiodev) {
-		return;
+		goto done;
 	}
+
+	func = sdiodev->func;
+	host = func->card->host;
+	host->caps &= ~MMC_CAP_NONREMOVABLE;
 
 	aicwf_sdio_release(sdiodev);
 	aicwf_sdio_func_deinit(sdiodev);
@@ -195,6 +232,9 @@
 	dev_set_drvdata(&sdiodev->func->dev, NULL);
 	kfree(sdiodev);
 	kfree(bus_if);
+
+done:
+	aicbsp_sdiodev = NULL;
 	sdio_dbg("%s done\n", __func__);
 }
 
@@ -276,6 +316,7 @@
 		return 0;
 	}
 
+	aicbsp_unreg_sdio_notify();
 	sunxi_wlan_set_power(0);
 	return -1;
 }
@@ -296,12 +337,12 @@
 }
 #endif
 
-void aicbsp_sdio_init(void)
+int aicbsp_sdio_init(void)
 {
-	if (sdio_register_driver(&aicbsp_sdio_driver)) {
-	} else {
-		//may add mmc_rescan here
-	}
+	if (sdio_register_driver(&aicbsp_sdio_driver))
+		return -1;
+
+	return 0;
 }
 
 void aicbsp_sdio_exit(void)
@@ -541,9 +582,9 @@
 
 static void aicwf_sdio_bus_stop(struct device *dev)
 {
-	struct aicwf_bus *bus_if = dev_get_drvdata(dev);
+	struct aicwf_bus *bus_if = aicbsp_get_drvdata(dev);
 	struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-	int ret;
+	int ret = 0;
 
 	aicwf_sdio_pwrctl_timer(sdiodev, 0);
 	sdio_dbg("%s\n", __func__);
@@ -553,18 +594,19 @@
 		sdiodev->pwrctl_tsk = NULL;
 	}
 
-	sdio_dbg("%s:pwrctl stopped\n", __func__);
-
 	bus_if->state = BUS_DOWN_ST;
-	ret = down_interruptible(&sdiodev->tx_priv->txctl_sema);
-	if (ret)
-	   sdio_err("down txctl_sema fail\n");
+	if (sdiodev->tx_priv) {
+		ret = down_interruptible(&sdiodev->tx_priv->txctl_sema);
+		if (ret)
+			sdio_err("down txctl_sema fail\n");
+	}
 
 	aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST);
-	if (!ret)
-		up(&sdiodev->tx_priv->txctl_sema);
-	aicwf_frame_queue_flush(&sdiodev->tx_priv->txq);
-	sdio_dbg("exit %s\n", __func__);
+	if (sdiodev->tx_priv) {
+		if (!ret)
+			up(&sdiodev->tx_priv->txctl_sema);
+		aicwf_frame_queue_flush(&sdiodev->tx_priv->txq);
+	}
 }
 
 struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev)
@@ -755,7 +797,7 @@
 
 	if (sdiodev->tx_priv->cmd_txstate) {
 		int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT);
-		ret = wait_event_interruptible_timeout(sdiodev->tx_priv->cmd_txdone_wait, \
+		ret = wait_event_timeout(sdiodev->tx_priv->cmd_txdone_wait, \
 											!(sdiodev->tx_priv->cmd_txstate), timeout);
 	}
 
@@ -1080,12 +1122,11 @@
 void aicwf_sdio_release(struct aic_sdio_dev *sdiodev)
 {
 	struct aicwf_bus *bus_if;
-	struct aicwf_rx_priv *rx_priv = NULL;
 	int ret = 0;
 
 	sdio_dbg("%s\n", __func__);
 
-	bus_if = dev_get_drvdata(sdiodev->dev);
+	bus_if = sdiodev->bus_if;
 	bus_if->state = BUS_DOWN_ST;
 
 	sdio_claim_host(sdiodev->func);
@@ -1097,13 +1138,17 @@
 	sdio_release_irq(sdiodev->func);
 	sdio_release_host(sdiodev->func);
 
-	aicwf_tx_deinit(sdiodev->tx_priv);
 	if (sdiodev->dev)
 		aicwf_bus_deinit(sdiodev->dev);
-	rx_priv = sdiodev->rx_priv;
-	if (rx_priv != NULL)
-		aicwf_rx_deinit(rx_priv);
-	sdio_dbg("exit cfg80211 deinit\n");
+
+	if (sdiodev->tx_priv)
+		aicwf_tx_deinit(sdiodev->tx_priv);
+
+	if (sdiodev->rx_priv)
+		aicwf_rx_deinit(sdiodev->rx_priv);
+
+	if (sdiodev->cmd_mgr.state == RWNX_CMD_MGR_STATE_INITED)
+		rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr);
 }
 
 int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev)

--
Gitblit v1.6.2