18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file is part of wl12xx
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009-2010 Nokia Corporation
68c2ecf20Sopenharmony_ci * Copyright (C) 2011 Texas Instruments Inc.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "../wlcore/cmd.h"
108c2ecf20Sopenharmony_ci#include "../wlcore/debug.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include "wl12xx.h"
138c2ecf20Sopenharmony_ci#include "cmd.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciint wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
188c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
198c2ecf20Sopenharmony_ci	struct wl12xx_conf_rf *rf = &priv->conf.rf;
208c2ecf20Sopenharmony_ci	int ret;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	if (!wl->nvs)
238c2ecf20Sopenharmony_ci		return -ENODEV;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
268c2ecf20Sopenharmony_ci	if (!ext_radio_parms)
278c2ecf20Sopenharmony_ci		return -ENOMEM;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
328c2ecf20Sopenharmony_ci	       rf->tx_per_channel_power_compensation_2,
338c2ecf20Sopenharmony_ci	       CONF_TX_PWR_COMPENSATION_LEN_2);
348c2ecf20Sopenharmony_ci	memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
358c2ecf20Sopenharmony_ci	       rf->tx_per_channel_power_compensation_5,
368c2ecf20Sopenharmony_ci	       CONF_TX_PWR_COMPENSATION_LEN_5);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
398c2ecf20Sopenharmony_ci		    ext_radio_parms, sizeof(*ext_radio_parms));
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
428c2ecf20Sopenharmony_ci	if (ret < 0)
438c2ecf20Sopenharmony_ci		wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	kfree(ext_radio_parms);
468c2ecf20Sopenharmony_ci	return ret;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciint wl1271_cmd_general_parms(struct wl1271 *wl)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	struct wl1271_general_parms_cmd *gen_parms;
528c2ecf20Sopenharmony_ci	struct wl1271_ini_general_params *gp =
538c2ecf20Sopenharmony_ci		&((struct wl1271_nvs_file *)wl->nvs)->general_params;
548c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
558c2ecf20Sopenharmony_ci	bool answer = false;
568c2ecf20Sopenharmony_ci	int ret;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (!wl->nvs)
598c2ecf20Sopenharmony_ci		return -ENODEV;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
628c2ecf20Sopenharmony_ci		wl1271_warning("FEM index from INI out of bounds");
638c2ecf20Sopenharmony_ci		return -EINVAL;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
678c2ecf20Sopenharmony_ci	if (!gen_parms)
688c2ecf20Sopenharmony_ci		return -ENOMEM;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	memcpy(&gen_parms->general_params, gp, sizeof(*gp));
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* If we started in PLT FEM_DETECT mode, force auto detect */
758c2ecf20Sopenharmony_ci	if (wl->plt_mode == PLT_FEM_DETECT)
768c2ecf20Sopenharmony_ci		gen_parms->general_params.tx_bip_fem_auto_detect = true;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (gen_parms->general_params.tx_bip_fem_auto_detect)
798c2ecf20Sopenharmony_ci		answer = true;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/* Override the REF CLK from the NVS with the one from platform data */
828c2ecf20Sopenharmony_ci	gen_parms->general_params.ref_clock = priv->ref_clock;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
858c2ecf20Sopenharmony_ci	if (ret < 0) {
868c2ecf20Sopenharmony_ci		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
878c2ecf20Sopenharmony_ci		goto out;
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	gp->tx_bip_fem_manufacturer =
918c2ecf20Sopenharmony_ci		gen_parms->general_params.tx_bip_fem_manufacturer;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
948c2ecf20Sopenharmony_ci		wl1271_warning("FEM index from FW out of bounds");
958c2ecf20Sopenharmony_ci		ret = -EINVAL;
968c2ecf20Sopenharmony_ci		goto out;
978c2ecf20Sopenharmony_ci	}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* If we are in calibrator based fem auto detect - save fem nr */
1008c2ecf20Sopenharmony_ci	if (wl->plt_mode == PLT_FEM_DETECT)
1018c2ecf20Sopenharmony_ci		wl->fem_manuf = gp->tx_bip_fem_manufacturer;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
1048c2ecf20Sopenharmony_ci		answer == false ?
1058c2ecf20Sopenharmony_ci			"manual" :
1068c2ecf20Sopenharmony_ci		wl->plt_mode == PLT_FEM_DETECT ?
1078c2ecf20Sopenharmony_ci			"calibrator_fem_detect" :
1088c2ecf20Sopenharmony_ci			"auto",
1098c2ecf20Sopenharmony_ci		gp->tx_bip_fem_manufacturer);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ciout:
1128c2ecf20Sopenharmony_ci	kfree(gen_parms);
1138c2ecf20Sopenharmony_ci	return ret;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciint wl128x_cmd_general_parms(struct wl1271 *wl)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct wl128x_general_parms_cmd *gen_parms;
1198c2ecf20Sopenharmony_ci	struct wl128x_ini_general_params *gp =
1208c2ecf20Sopenharmony_ci		&((struct wl128x_nvs_file *)wl->nvs)->general_params;
1218c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
1228c2ecf20Sopenharmony_ci	bool answer = false;
1238c2ecf20Sopenharmony_ci	int ret;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (!wl->nvs)
1268c2ecf20Sopenharmony_ci		return -ENODEV;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
1298c2ecf20Sopenharmony_ci		wl1271_warning("FEM index from ini out of bounds");
1308c2ecf20Sopenharmony_ci		return -EINVAL;
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
1348c2ecf20Sopenharmony_ci	if (!gen_parms)
1358c2ecf20Sopenharmony_ci		return -ENOMEM;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	memcpy(&gen_parms->general_params, gp, sizeof(*gp));
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	/* If we started in PLT FEM_DETECT mode, force auto detect */
1428c2ecf20Sopenharmony_ci	if (wl->plt_mode == PLT_FEM_DETECT)
1438c2ecf20Sopenharmony_ci		gen_parms->general_params.tx_bip_fem_auto_detect = true;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	if (gen_parms->general_params.tx_bip_fem_auto_detect)
1468c2ecf20Sopenharmony_ci		answer = true;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	/* Replace REF and TCXO CLKs with the ones from platform data */
1498c2ecf20Sopenharmony_ci	gen_parms->general_params.ref_clock = priv->ref_clock;
1508c2ecf20Sopenharmony_ci	gen_parms->general_params.tcxo_ref_clock = priv->tcxo_clock;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
1538c2ecf20Sopenharmony_ci	if (ret < 0) {
1548c2ecf20Sopenharmony_ci		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
1558c2ecf20Sopenharmony_ci		goto out;
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	gp->tx_bip_fem_manufacturer =
1598c2ecf20Sopenharmony_ci		gen_parms->general_params.tx_bip_fem_manufacturer;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
1628c2ecf20Sopenharmony_ci		wl1271_warning("FEM index from FW out of bounds");
1638c2ecf20Sopenharmony_ci		ret = -EINVAL;
1648c2ecf20Sopenharmony_ci		goto out;
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	/* If we are in calibrator based fem auto detect - save fem nr */
1688c2ecf20Sopenharmony_ci	if (wl->plt_mode == PLT_FEM_DETECT)
1698c2ecf20Sopenharmony_ci		wl->fem_manuf = gp->tx_bip_fem_manufacturer;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
1728c2ecf20Sopenharmony_ci		answer == false ?
1738c2ecf20Sopenharmony_ci			"manual" :
1748c2ecf20Sopenharmony_ci		wl->plt_mode == PLT_FEM_DETECT ?
1758c2ecf20Sopenharmony_ci			"calibrator_fem_detect" :
1768c2ecf20Sopenharmony_ci			"auto",
1778c2ecf20Sopenharmony_ci		gp->tx_bip_fem_manufacturer);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ciout:
1808c2ecf20Sopenharmony_ci	kfree(gen_parms);
1818c2ecf20Sopenharmony_ci	return ret;
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciint wl1271_cmd_radio_parms(struct wl1271 *wl)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
1878c2ecf20Sopenharmony_ci	struct wl1271_radio_parms_cmd *radio_parms;
1888c2ecf20Sopenharmony_ci	struct wl1271_ini_general_params *gp = &nvs->general_params;
1898c2ecf20Sopenharmony_ci	int ret, fem_idx;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (!wl->nvs)
1928c2ecf20Sopenharmony_ci		return -ENODEV;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
1958c2ecf20Sopenharmony_ci	if (!radio_parms)
1968c2ecf20Sopenharmony_ci		return -ENOMEM;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	/* 2.4GHz parameters */
2038c2ecf20Sopenharmony_ci	memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
2048c2ecf20Sopenharmony_ci	       sizeof(struct wl1271_ini_band_params_2));
2058c2ecf20Sopenharmony_ci	memcpy(&radio_parms->dyn_params_2,
2068c2ecf20Sopenharmony_ci	       &nvs->dyn_radio_params_2[fem_idx].params,
2078c2ecf20Sopenharmony_ci	       sizeof(struct wl1271_ini_fem_params_2));
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/* 5GHz parameters */
2108c2ecf20Sopenharmony_ci	memcpy(&radio_parms->static_params_5,
2118c2ecf20Sopenharmony_ci	       &nvs->stat_radio_params_5,
2128c2ecf20Sopenharmony_ci	       sizeof(struct wl1271_ini_band_params_5));
2138c2ecf20Sopenharmony_ci	memcpy(&radio_parms->dyn_params_5,
2148c2ecf20Sopenharmony_ci	       &nvs->dyn_radio_params_5[fem_idx].params,
2158c2ecf20Sopenharmony_ci	       sizeof(struct wl1271_ini_fem_params_5));
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
2188c2ecf20Sopenharmony_ci		    radio_parms, sizeof(*radio_parms));
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
2218c2ecf20Sopenharmony_ci	if (ret < 0)
2228c2ecf20Sopenharmony_ci		wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	kfree(radio_parms);
2258c2ecf20Sopenharmony_ci	return ret;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ciint wl128x_cmd_radio_parms(struct wl1271 *wl)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
2318c2ecf20Sopenharmony_ci	struct wl128x_radio_parms_cmd *radio_parms;
2328c2ecf20Sopenharmony_ci	struct wl128x_ini_general_params *gp = &nvs->general_params;
2338c2ecf20Sopenharmony_ci	int ret, fem_idx;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (!wl->nvs)
2368c2ecf20Sopenharmony_ci		return -ENODEV;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
2398c2ecf20Sopenharmony_ci	if (!radio_parms)
2408c2ecf20Sopenharmony_ci		return -ENOMEM;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	/* 2.4GHz parameters */
2478c2ecf20Sopenharmony_ci	memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
2488c2ecf20Sopenharmony_ci	       sizeof(struct wl128x_ini_band_params_2));
2498c2ecf20Sopenharmony_ci	memcpy(&radio_parms->dyn_params_2,
2508c2ecf20Sopenharmony_ci	       &nvs->dyn_radio_params_2[fem_idx].params,
2518c2ecf20Sopenharmony_ci	       sizeof(struct wl128x_ini_fem_params_2));
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* 5GHz parameters */
2548c2ecf20Sopenharmony_ci	memcpy(&radio_parms->static_params_5,
2558c2ecf20Sopenharmony_ci	       &nvs->stat_radio_params_5,
2568c2ecf20Sopenharmony_ci	       sizeof(struct wl128x_ini_band_params_5));
2578c2ecf20Sopenharmony_ci	memcpy(&radio_parms->dyn_params_5,
2588c2ecf20Sopenharmony_ci	       &nvs->dyn_radio_params_5[fem_idx].params,
2598c2ecf20Sopenharmony_ci	       sizeof(struct wl128x_ini_fem_params_5));
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
2648c2ecf20Sopenharmony_ci		    radio_parms, sizeof(*radio_parms));
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
2678c2ecf20Sopenharmony_ci	if (ret < 0)
2688c2ecf20Sopenharmony_ci		wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	kfree(radio_parms);
2718c2ecf20Sopenharmony_ci	return ret;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ciint wl12xx_cmd_channel_switch(struct wl1271 *wl,
2758c2ecf20Sopenharmony_ci			      struct wl12xx_vif *wlvif,
2768c2ecf20Sopenharmony_ci			      struct ieee80211_channel_switch *ch_switch)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct wl12xx_cmd_channel_switch *cmd;
2798c2ecf20Sopenharmony_ci	int ret;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_ACX, "cmd channel switch");
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2848c2ecf20Sopenharmony_ci	if (!cmd) {
2858c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2868c2ecf20Sopenharmony_ci		goto out;
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	cmd->role_id = wlvif->role_id;
2908c2ecf20Sopenharmony_ci	cmd->channel = ch_switch->chandef.chan->hw_value;
2918c2ecf20Sopenharmony_ci	cmd->switch_time = ch_switch->count;
2928c2ecf20Sopenharmony_ci	cmd->stop_tx = ch_switch->block_tx;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* FIXME: control from mac80211 in the future */
2958c2ecf20Sopenharmony_ci	/* Enable TX on the target channel */
2968c2ecf20Sopenharmony_ci	cmd->post_switch_tx_disable = 0;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
2998c2ecf20Sopenharmony_ci	if (ret < 0) {
3008c2ecf20Sopenharmony_ci		wl1271_error("failed to send channel switch command");
3018c2ecf20Sopenharmony_ci		goto out_free;
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ciout_free:
3058c2ecf20Sopenharmony_ci	kfree(cmd);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ciout:
3088c2ecf20Sopenharmony_ci	return ret;
3098c2ecf20Sopenharmony_ci}
310