Merge "cnss2: Add fallback support for device specific path loading"
diff --git a/arch/arm64/configs/vendor/kona-perf_defconfig b/arch/arm64/configs/vendor/kona-perf_defconfig
index 74b58921..5713457 100644
--- a/arch/arm64/configs/vendor/kona-perf_defconfig
+++ b/arch/arm64/configs/vendor/kona-perf_defconfig
@@ -330,7 +330,6 @@
CONFIG_CNSS2_QMI=y
CONFIG_CNSS_ASYNC=y
CONFIG_BUS_AUTO_SUSPEND=y
-CONFIG_CNSS_QCA6390=y
CONFIG_CNSS_GENL=y
CONFIG_NVM=y
CONFIG_NVM_PBLK=y
diff --git a/arch/arm64/configs/vendor/kona_defconfig b/arch/arm64/configs/vendor/kona_defconfig
index 46b77b9..5033e4a 100644
--- a/arch/arm64/configs/vendor/kona_defconfig
+++ b/arch/arm64/configs/vendor/kona_defconfig
@@ -344,7 +344,6 @@
CONFIG_CNSS2_QMI=y
CONFIG_CNSS_ASYNC=y
CONFIG_BUS_AUTO_SUSPEND=y
-CONFIG_CNSS_QCA6390=y
CONFIG_CNSS_GENL=y
CONFIG_NVM=y
CONFIG_NVM_PBLK=y
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index 94e0a4d..87d2d8b 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -95,6 +95,23 @@
}
}
+void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
+ char *prefix_name, char *name)
+{
+ if (!plat_priv)
+ return;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_add_fw_prefix_name(plat_priv->bus_priv,
+ prefix_name, name);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return;
+ }
+}
+
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 1e7cc0f..686b12d 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -24,6 +24,8 @@
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
int cnss_bus_init(struct cnss_plat_data *plat_priv);
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
+void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
+ char *prefix_name, char *name);
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index cd0abc1..6757ea9 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -2205,6 +2205,12 @@
plat_priv->set_wlaon_pwr_ctrl);
}
+static bool cnss_use_fw_path_with_prefix(struct cnss_plat_data *plat_priv)
+{
+ return of_property_read_bool(plat_priv->plat_dev->dev.of_node,
+ "qcom,converged-dt");
+}
+
static const struct platform_device_id cnss_platform_id_table[] = {
{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
@@ -2270,6 +2276,8 @@
plat_priv->device_id = device_id->driver_data;
plat_priv->bus_type = cnss_get_bus_type(plat_priv->device_id);
plat_priv->use_nv_mac = cnss_use_nv_mac(plat_priv);
+ plat_priv->use_fw_path_with_prefix =
+ cnss_use_fw_path_with_prefix(plat_priv);
cnss_set_plat_priv(plat_dev, plat_priv);
platform_set_drvdata(plat_dev, plat_priv);
INIT_LIST_HEAD(&plat_priv->vreg_list);
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 9d0c51a..5dfd4a4 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -25,6 +25,7 @@
#define TIME_CLOCK_FREQ_HZ 19200000
#define CNSS_RAMDUMP_MAGIC 0x574C414E
#define CNSS_RAMDUMP_VERSION 0
+#define MAX_FIRMWARE_NAME_LEN 20
#define CNSS_EVENT_SYNC BIT(0)
#define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
@@ -369,7 +370,9 @@
u8 *diag_reg_read_buf;
u8 cal_done;
u8 powered_on;
- char firmware_name[13];
+ u8 use_fw_path_with_prefix;
+ char firmware_name[MAX_FIRMWARE_NAME_LEN];
+ char fw_fallback_name[MAX_FIRMWARE_NAME_LEN];
struct completion rddm_complete;
struct completion recovery_complete;
struct cnss_control_params ctrl_params;
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index f2f8560..cc94890 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -38,7 +38,8 @@
#define MHI_NODE_NAME "qcom,mhi"
#define MHI_MSI_NAME "MHI"
-#define MAX_M3_FILE_NAME_LENGTH 13
+#define QCA6390_PATH_PREFIX "qca6390/"
+#define QCA6490_PATH_PREFIX "qca6490/"
#define DEFAULT_M3_FILE_NAME "m3.bin"
#define DEFAULT_FW_FILE_NAME "amss.bin"
#define FW_V2_FILE_NAME "amss20.bin"
@@ -3113,12 +3114,13 @@
{
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem;
- char filename[MAX_M3_FILE_NAME_LENGTH];
+ char filename[MAX_FIRMWARE_NAME_LEN];
const struct firmware *fw_entry;
int ret = 0;
if (!m3_mem->va && !m3_mem->size) {
- snprintf(filename, sizeof(filename), DEFAULT_M3_FILE_NAME);
+ cnss_pci_add_fw_prefix_name(pci_priv, filename,
+ DEFAULT_M3_FILE_NAME);
ret = request_firmware(&fw_entry, filename,
&pci_priv->pci_dev->dev);
@@ -4038,6 +4040,99 @@
cnss_pci_pm_runtime_put_noidle(pci_priv);
}
+void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
+ char *prefix_name, char *name)
+{
+ struct cnss_plat_data *plat_priv;
+
+ if (!pci_priv)
+ return;
+
+ plat_priv = pci_priv->plat_priv;
+
+ if (!plat_priv->use_fw_path_with_prefix) {
+ scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN, "%s", name);
+ return;
+ }
+
+ switch (pci_priv->device_id) {
+ case QCA6390_DEVICE_ID:
+ scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
+ QCA6390_PATH_PREFIX "%s", name);
+ break;
+ case QCA6490_DEVICE_ID:
+ scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
+ QCA6490_PATH_PREFIX "%s", name);
+ break;
+ default:
+ scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN, "%s", name);
+ break;
+ }
+
+ cnss_pr_dbg("FW name added with prefix: %s\n", prefix_name);
+}
+
+static int cnss_pci_update_fw_name(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+ struct mhi_controller *mhi_ctrl = pci_priv->mhi_ctrl;
+
+ plat_priv->device_version.family_number = mhi_ctrl->family_number;
+ plat_priv->device_version.device_number = mhi_ctrl->device_number;
+ plat_priv->device_version.major_version = mhi_ctrl->major_version;
+ plat_priv->device_version.minor_version = mhi_ctrl->minor_version;
+
+ cnss_pr_dbg("Get device version info, family number: 0x%x, device number: 0x%x, major version: 0x%x, minor version: 0x%x\n",
+ plat_priv->device_version.family_number,
+ plat_priv->device_version.device_number,
+ plat_priv->device_version.major_version,
+ plat_priv->device_version.minor_version);
+
+ switch (pci_priv->device_id) {
+ case QCA6390_DEVICE_ID:
+ if (plat_priv->device_version.major_version < FW_V2_NUMBER) {
+ cnss_pr_dbg("Device ID:version (0x%lx:%d) is not supported\n",
+ pci_priv->device_id,
+ plat_priv->device_version.major_version);
+ return -EINVAL;
+ }
+ cnss_pci_add_fw_prefix_name(pci_priv, plat_priv->firmware_name,
+ FW_V2_FILE_NAME);
+ snprintf(plat_priv->fw_fallback_name, MAX_FIRMWARE_NAME_LEN,
+ FW_V2_FILE_NAME);
+ break;
+ case QCA6490_DEVICE_ID:
+ switch (plat_priv->device_version.major_version) {
+ case FW_V2_NUMBER:
+ cnss_pci_add_fw_prefix_name(pci_priv,
+ plat_priv->firmware_name,
+ FW_V2_FILE_NAME);
+ snprintf(plat_priv->fw_fallback_name,
+ MAX_FIRMWARE_NAME_LEN, FW_V2_FILE_NAME);
+ break;
+ default:
+ cnss_pci_add_fw_prefix_name(pci_priv,
+ plat_priv->firmware_name,
+ DEFAULT_FW_FILE_NAME);
+ snprintf(plat_priv->fw_fallback_name,
+ MAX_FIRMWARE_NAME_LEN, DEFAULT_FW_FILE_NAME);
+ break;
+ }
+ break;
+ default:
+ cnss_pci_add_fw_prefix_name(pci_priv, plat_priv->firmware_name,
+ DEFAULT_FW_FILE_NAME);
+ snprintf(plat_priv->fw_fallback_name, MAX_FIRMWARE_NAME_LEN,
+ DEFAULT_FW_FILE_NAME);
+ break;
+ }
+
+ cnss_pr_dbg("FW name is %s, FW fallback name is %s\n",
+ mhi_ctrl->fw_image, mhi_ctrl->fw_image_fallback);
+
+ return 0;
+}
+
static char *cnss_mhi_notify_status_to_str(enum MHI_CB status)
{
switch (status) {
@@ -4051,6 +4146,8 @@
return "FATAL_ERROR";
case MHI_CB_EE_MISSION_MODE:
return "MISSION_MODE";
+ case MHI_CB_FW_FALLBACK_IMG:
+ return "FW_FALLBACK";
default:
return "UNKNOWN";
}
@@ -4123,6 +4220,10 @@
cnss_pci_update_status(pci_priv, CNSS_FW_DOWN);
cnss_reason = CNSS_REASON_RDDM;
break;
+ case MHI_CB_FW_FALLBACK_IMG:
+ plat_priv->use_fw_path_with_prefix = false;
+ cnss_pci_update_fw_name(pci_priv);
+ return;
default:
cnss_pr_err("Unsupported MHI status cb reason: %d\n", reason);
return;
@@ -4160,55 +4261,6 @@
return 0;
}
-static int cnss_pci_update_fw_name(struct cnss_pci_data *pci_priv)
-{
- struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
- struct mhi_controller *mhi_ctrl = pci_priv->mhi_ctrl;
-
- plat_priv->device_version.family_number = mhi_ctrl->family_number;
- plat_priv->device_version.device_number = mhi_ctrl->device_number;
- plat_priv->device_version.major_version = mhi_ctrl->major_version;
- plat_priv->device_version.minor_version = mhi_ctrl->minor_version;
-
- cnss_pr_dbg("Get device version info, family number: 0x%x, device number: 0x%x, major version: 0x%x, minor version: 0x%x\n",
- plat_priv->device_version.family_number,
- plat_priv->device_version.device_number,
- plat_priv->device_version.major_version,
- plat_priv->device_version.minor_version);
-
- switch (pci_priv->device_id) {
- case QCA6390_DEVICE_ID:
- if (plat_priv->device_version.major_version < FW_V2_NUMBER) {
- cnss_pr_dbg("Device ID:version (0x%lx:%d) is not supported\n",
- pci_priv->device_id,
- plat_priv->device_version.major_version);
- return -EINVAL;
- }
- scnprintf(plat_priv->firmware_name,
- sizeof(plat_priv->firmware_name), FW_V2_FILE_NAME);
- mhi_ctrl->fw_image = plat_priv->firmware_name;
- break;
- case QCA6490_DEVICE_ID:
- switch (plat_priv->device_version.major_version) {
- case FW_V2_NUMBER:
- scnprintf(plat_priv->firmware_name,
- sizeof(plat_priv->firmware_name),
- FW_V2_FILE_NAME);
- break;
- default:
- break;
- }
-
- break;
- default:
- break;
- }
-
- cnss_pr_dbg("Firmware name is %s\n", mhi_ctrl->fw_image);
-
- return 0;
-}
-
static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
{
int ret = 0;
@@ -4233,6 +4285,7 @@
mhi_ctrl->slot = PCI_SLOT(pci_dev->devfn);
mhi_ctrl->fw_image = plat_priv->firmware_name;
+ mhi_ctrl->fw_image_fallback = plat_priv->fw_fallback_name;
mhi_ctrl->regs = pci_priv->bar;
cnss_pr_dbg("BAR starts at %pa\n",
@@ -4363,8 +4416,6 @@
cnss_set_pci_priv(pci_dev, pci_priv);
plat_priv->device_id = pci_dev->device;
plat_priv->bus_priv = pci_priv;
- snprintf(plat_priv->firmware_name, sizeof(plat_priv->firmware_name),
- DEFAULT_FW_FILE_NAME);
mutex_init(&pci_priv->bus_lock);
ret = of_reserved_mem_device_init(dev);
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 2984273..a05ad7c 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -167,6 +167,8 @@
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
int cnss_pci_init(struct cnss_plat_data *plat_priv);
void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
+void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
+ char *prefix_name, char *name);
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index e1153ed..e7dc9ff 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -12,7 +12,6 @@
#define WLFW_SERVICE_INS_ID_V01 1
#define WLFW_CLIENT_ID 0x4b4e454c
-#define MAX_BDF_FILE_NAME 13
#define BDF_FILE_NAME_PREFIX "bdwlan"
#define ELF_BDF_FILE_NAME "bdwlan.elf"
#define ELF_BDF_FILE_NAME_PREFIX "bdwlan.e"
@@ -459,42 +458,43 @@
u32 bdf_type, char *filename,
u32 filename_len)
{
+ char filename_tmp[MAX_FIRMWARE_NAME_LEN];
int ret = 0;
switch (bdf_type) {
case CNSS_BDF_ELF:
if (plat_priv->board_info.board_id == 0xFF)
- snprintf(filename, filename_len, ELF_BDF_FILE_NAME);
+ snprintf(filename_tmp, filename_len, ELF_BDF_FILE_NAME);
else if (plat_priv->board_info.board_id < 0xFF)
- snprintf(filename, filename_len,
+ snprintf(filename_tmp, filename_len,
ELF_BDF_FILE_NAME_PREFIX "%02x",
plat_priv->board_info.board_id);
else
- snprintf(filename, filename_len,
+ snprintf(filename_tmp, filename_len,
BDF_FILE_NAME_PREFIX "%02x.e%02x",
plat_priv->board_info.board_id >> 8 & 0xFF,
plat_priv->board_info.board_id & 0xFF);
break;
case CNSS_BDF_BIN:
if (plat_priv->board_info.board_id == 0xFF)
- snprintf(filename, filename_len, BIN_BDF_FILE_NAME);
+ snprintf(filename_tmp, filename_len, BIN_BDF_FILE_NAME);
else if (plat_priv->board_info.board_id < 0xFF)
- snprintf(filename, filename_len,
+ snprintf(filename_tmp, filename_len,
BIN_BDF_FILE_NAME_PREFIX "%02x",
plat_priv->board_info.board_id);
else
- snprintf(filename, filename_len,
+ snprintf(filename_tmp, filename_len,
BDF_FILE_NAME_PREFIX "%02x.b%02x",
plat_priv->board_info.board_id >> 8 & 0xFF,
plat_priv->board_info.board_id & 0xFF);
break;
case CNSS_BDF_REGDB:
- snprintf(filename, filename_len, REGDB_FILE_NAME);
+ snprintf(filename_tmp, filename_len, REGDB_FILE_NAME);
break;
case CNSS_BDF_DUMMY:
cnss_pr_dbg("CNSS_BDF_DUMMY is set, sending dummy BDF\n");
- snprintf(filename, filename_len, DUMMY_BDF_FILE_NAME);
- ret = MAX_BDF_FILE_NAME;
+ snprintf(filename_tmp, filename_len, DUMMY_BDF_FILE_NAME);
+ ret = MAX_FIRMWARE_NAME_LEN;
break;
default:
cnss_pr_err("Invalid BDF type: %d\n",
@@ -502,6 +502,10 @@
ret = -EINVAL;
break;
}
+
+ if (ret >= 0)
+ cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp);
+
return ret;
}
@@ -511,7 +515,7 @@
struct wlfw_bdf_download_req_msg_v01 *req;
struct wlfw_bdf_download_resp_msg_v01 *resp;
struct qmi_txn txn;
- char filename[MAX_BDF_FILE_NAME];
+ char filename[MAX_FIRMWARE_NAME_LEN];
const struct firmware *fw_entry = NULL;
const u8 *temp;
unsigned int remaining;
@@ -534,7 +538,7 @@
filename, sizeof(filename));
if (ret > 0) {
temp = DUMMY_BDF_FILE_NAME;
- remaining = MAX_BDF_FILE_NAME;
+ remaining = MAX_FIRMWARE_NAME_LEN;
goto bypass_bdf;
} else if (ret < 0) {
goto err_req_fw;