diff mbox

[1/2] mwifiex: add hostcmd wext ioctl support

Message ID 1467298875-3581-2-git-send-email-akarwar@marvell.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show

Commit Message

Amitkumar Karwar June 30, 2016, 3:01 p.m. UTC
From: Xinming Hu <huxm@marvell.com>

This patch adds ndo_ioctl support to mwifiex netdev handlers.
This will be used to download hostcmds to firmware from userspace.
This is needed for manufacturing mode support in mwifiex. ndo_ioctl
is allowed only when mfg mode is enabled via module load parameters.

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/cmdevt.c | 59 +++++++++++++++++++++++++++
 drivers/net/wireless/marvell/mwifiex/main.c   | 38 +++++++++++++++++
 drivers/net/wireless/marvell/mwifiex/main.h   |  9 +++-
 3 files changed, 105 insertions(+), 1 deletion(-)

Comments

kernel test robot June 30, 2016, 5:49 p.m. UTC | #1
Hi,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.7-rc5 next-20160630]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Amitkumar-Karwar/mwifiex-add-hostcmd-wext-ioctl-support/20160630-231444
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: arm-at91_dt_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   drivers/net/wireless/marvell/mwifiex/main.c: In function 'mwifiex_do_ioctl':
   drivers/net/wireless/marvell/mwifiex/main.c:1220:20: error: 'struct mwifiex_adapter' has no member named 'mfg_mode'
     if (!priv->adapter->mfg_mode)
                       ^
   drivers/net/wireless/marvell/mwifiex/main.c: At top level:
>> drivers/net/wireless/marvell/mwifiex/main.c:1260:2: error: unknown field 'num_private_args' specified in initializer
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
     ^
   In file included from drivers/net/wireless/marvell/mwifiex/main.h:23:0,
                    from drivers/net/wireless/marvell/mwifiex/main.c:20:
>> include/linux/kernel.h:54:25: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                            ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1260:22: note: in expansion of macro 'ARRAY_SIZE'
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
                         ^
   include/linux/kernel.h:54:25: note: (near initialization for 'mwifiex_iwpriv_handler_def.standard')
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                            ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1260:22: note: in expansion of macro 'ARRAY_SIZE'
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
                         ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1261:2: error: unknown field 'private_args' specified in initializer
     .private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
     ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1261:18: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
     .private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
                     ^
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: note: (near initialization for 'mwifiex_iwpriv_handler_def.num_standard')
>> drivers/net/wireless/marvell/mwifiex/main.c:1261:18: error: initializer element is not computable at load time
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: note: (near initialization for 'mwifiex_iwpriv_handler_def.num_standard')

vim +/num_private_args +1260 drivers/net/wireless/marvell/mwifiex/main.c

  1214	static int mwifiex_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  1215	{
  1216		struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
  1217		struct iwreq *wrq = (struct iwreq *)req;
  1218		int ret;
  1219	
> 1220		if (!priv->adapter->mfg_mode)
  1221			return -EINVAL;
  1222	
  1223		dev_dbg(priv->adapter->dev, "ioctl cmd = 0x%x\n", cmd);
  1224	
  1225		switch (cmd) {
  1226		case MWIFIEX_HOSTCMD_IOCTL:
  1227			ret = mwifiex_process_host_command(priv, wrq);
  1228			break;
  1229		default:
  1230			ret = -EINVAL;
  1231			break;
  1232		}
  1233	
  1234		return ret;
  1235	}
  1236	
  1237	/* Network device handlers */
  1238	static const struct net_device_ops mwifiex_netdev_ops = {
  1239		.ndo_open = mwifiex_open,
  1240		.ndo_stop = mwifiex_close,
  1241		.ndo_start_xmit = mwifiex_hard_start_xmit,
  1242		.ndo_set_mac_address = mwifiex_set_mac_address,
  1243		.ndo_do_ioctl = mwifiex_do_ioctl,
  1244		.ndo_validate_addr = eth_validate_addr,
  1245		.ndo_tx_timeout = mwifiex_tx_timeout,
  1246		.ndo_get_stats = mwifiex_get_stats,
  1247		.ndo_set_rx_mode = mwifiex_set_multicast_list,
  1248		.ndo_select_queue = mwifiex_netdev_select_wmm_queue,
  1249		};
  1250	
  1251	static const struct iw_priv_args mwifiex_iwpriv_args[] = {
  1252		{       MWIFIEX_HOSTCMD_IOCTL,
  1253			IW_PRIV_TYPE_BYTE | 2047,
  1254			IW_PRIV_TYPE_BYTE | 2047,
  1255			"hostcmd"
  1256		},
  1257	};
  1258	
  1259	static struct iw_handler_def mwifiex_iwpriv_handler_def = {
> 1260		.num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
> 1261		.private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
  1262	};
  1263	
  1264	/*

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot June 30, 2016, 6 p.m. UTC | #2
Hi,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.7-rc5 next-20160630]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Amitkumar-Karwar/mwifiex-add-hostcmd-wext-ioctl-support/20160630-231444
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: arm-exynos_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/net/wireless/marvell/mwifiex/main.c: In function 'mwifiex_do_ioctl':
   drivers/net/wireless/marvell/mwifiex/main.c:1220:20: error: 'struct mwifiex_adapter' has no member named 'mfg_mode'
     if (!priv->adapter->mfg_mode)
                       ^
   drivers/net/wireless/marvell/mwifiex/main.c: At top level:
   drivers/net/wireless/marvell/mwifiex/main.c:1260:2: error: unknown field 'num_private_args' specified in initializer
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
     ^
   In file included from drivers/net/wireless/marvell/mwifiex/main.h:23:0,
                    from drivers/net/wireless/marvell/mwifiex/main.c:20:
   include/linux/kernel.h:54:25: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                            ^
   drivers/net/wireless/marvell/mwifiex/main.c:1260:22: note: in expansion of macro 'ARRAY_SIZE'
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
                         ^
   include/linux/kernel.h:54:25: note: (near initialization for 'mwifiex_iwpriv_handler_def.standard')
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                            ^
   drivers/net/wireless/marvell/mwifiex/main.c:1260:22: note: in expansion of macro 'ARRAY_SIZE'
     .num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
                         ^
   drivers/net/wireless/marvell/mwifiex/main.c:1261:2: error: unknown field 'private_args' specified in initializer
     .private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
     ^
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
     .private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
                     ^
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: note: (near initialization for 'mwifiex_iwpriv_handler_def.num_standard')
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: error: initializer element is not computable at load time
   drivers/net/wireless/marvell/mwifiex/main.c:1261:18: note: (near initialization for 'mwifiex_iwpriv_handler_def.num_standard')
   drivers/net/wireless/marvell/mwifiex/main.c: In function 'mwifiex_init_priv_params':
>> drivers/net/wireless/marvell/mwifiex/main.c:1289:5: error: 'struct net_device' has no member named 'wireless_handlers'
     dev->wireless_handlers = &mwifiex_iwpriv_handler_def;
        ^

vim +1289 drivers/net/wireless/marvell/mwifiex/main.c

  1255			"hostcmd"
  1256		},
  1257	};
  1258	
  1259	static struct iw_handler_def mwifiex_iwpriv_handler_def = {
  1260		.num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
> 1261		.private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
  1262	};
  1263	
  1264	/*
  1265	 * This function initializes the private structure parameters.
  1266	 *
  1267	 * The following wait queues are initialized -
  1268	 *      - IOCTL wait queue
  1269	 *      - Command wait queue
  1270	 *      - Statistics wait queue
  1271	 *
  1272	 * ...and the following default parameters are set -
  1273	 *      - Current key index     : Set to 0
  1274	 *      - Rate index            : Set to auto
  1275	 *      - Media connected       : Set to disconnected
  1276	 *      - Adhoc link sensed     : Set to false
  1277	 *      - Nick name             : Set to null
  1278	 *      - Number of Tx timeout  : Set to 0
  1279	 *      - Device address        : Set to current address
  1280	 *      - Rx histogram statistc : Set to 0
  1281	 *
  1282	 * In addition, the CFG80211 work queue is also created.
  1283	 */
  1284	void mwifiex_init_priv_params(struct mwifiex_private *priv,
  1285				      struct net_device *dev)
  1286	{
  1287		dev->netdev_ops = &mwifiex_netdev_ops;
  1288		dev->destructor = free_netdev;
> 1289		dev->wireless_handlers = &mwifiex_iwpriv_handler_def;
  1290		/* Initialize private structure */
  1291		priv->current_key_index = 0;
  1292		priv->media_connected = false;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index c29f26d..fcfe556 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -818,6 +818,8 @@  int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 			hostcmd = adapter->curr_cmd->data_buf;
 			hostcmd->len = size;
 			memcpy(hostcmd->cmd, resp, size);
+			adapter->hostcmd_resp_data.len = size;
+			memcpy(adapter->hostcmd_resp_data.cmd, resp, size);
 		}
 	}
 	orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -1200,6 +1202,63 @@  mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
 				   false);
 }
 EXPORT_SYMBOL_GPL(mwifiex_process_hs_config);
+/* This function get hostcmd data from userspace and construct a cmd
+   * to be download to FW.
+  */
+int mwifiex_process_host_command(struct mwifiex_private *priv,
+				 struct iwreq *wrq)
+{
+	struct mwifiex_ds_misc_cmd *hostcmd_buf;
+	struct host_cmd_ds_command *cmd;
+	struct mwifiex_adapter *adapter = priv->adapter;
+	int ret;
+
+	hostcmd_buf = kzalloc(sizeof(*hostcmd_buf), GFP_KERNEL);
+	if (!hostcmd_buf)
+		return -ENOMEM;
+
+	cmd = (void *)hostcmd_buf->cmd;
+
+	if (copy_from_user(cmd, wrq->u.data.pointer,
+			   sizeof(cmd->command) + sizeof(cmd->size))) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	hostcmd_buf->len = le16_to_cpu(cmd->size);
+	if (hostcmd_buf->len > MWIFIEX_SIZE_OF_CMD_BUFFER) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (copy_from_user(cmd, wrq->u.data.pointer, hostcmd_buf->len)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd_buf, true)) {
+		dev_err(priv->adapter->dev, "Failed to process hostcmd\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (adapter->hostcmd_resp_data.len > hostcmd_buf->len) {
+		ret = -EFBIG;
+		goto done;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, adapter->hostcmd_resp_data.cmd,
+			 adapter->hostcmd_resp_data.len)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = adapter->hostcmd_resp_data.len;
+
+	ret = 0;
+done:
+	kfree(hostcmd_buf);
+	return ret;
+}
 
 /*
  * This function handles the command response of a sleep confirm command.
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 0e280f8..8b06d1d 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1211,17 +1211,54 @@  mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
 	return mwifiex_1d_to_wmm_queue[skb->priority];
 }
 
+static int mwifiex_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	struct iwreq *wrq = (struct iwreq *)req;
+	int ret;
+
+	if (!priv->adapter->mfg_mode)
+		return -EINVAL;
+
+	dev_dbg(priv->adapter->dev, "ioctl cmd = 0x%x\n", cmd);
+
+	switch (cmd) {
+	case MWIFIEX_HOSTCMD_IOCTL:
+		ret = mwifiex_process_host_command(priv, wrq);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 /* Network device handlers */
 static const struct net_device_ops mwifiex_netdev_ops = {
 	.ndo_open = mwifiex_open,
 	.ndo_stop = mwifiex_close,
 	.ndo_start_xmit = mwifiex_hard_start_xmit,
 	.ndo_set_mac_address = mwifiex_set_mac_address,
+	.ndo_do_ioctl = mwifiex_do_ioctl,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_tx_timeout = mwifiex_tx_timeout,
 	.ndo_get_stats = mwifiex_get_stats,
 	.ndo_set_rx_mode = mwifiex_set_multicast_list,
 	.ndo_select_queue = mwifiex_netdev_select_wmm_queue,
+	};
+
+static const struct iw_priv_args mwifiex_iwpriv_args[] = {
+	{       MWIFIEX_HOSTCMD_IOCTL,
+		IW_PRIV_TYPE_BYTE | 2047,
+		IW_PRIV_TYPE_BYTE | 2047,
+		"hostcmd"
+	},
+};
+
+static struct iw_handler_def mwifiex_iwpriv_handler_def = {
+	.num_private_args = ARRAY_SIZE(mwifiex_iwpriv_args),
+	.private_args = (struct iw_priv_args *)mwifiex_iwpriv_args,
 };
 
 /*
@@ -1249,6 +1286,7 @@  void mwifiex_init_priv_params(struct mwifiex_private *priv,
 {
 	dev->netdev_ops = &mwifiex_netdev_ops;
 	dev->destructor = free_netdev;
+	dev->wireless_handlers = &mwifiex_iwpriv_handler_def;
 	/* Initialize private structure */
 	priv->current_key_index = 0;
 	priv->media_connected = false;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 9f6bb40..23532cf 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -48,6 +48,8 @@ 
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/of_irq.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
 
 #include "decl.h"
 #include "ioctl.h"
@@ -157,6 +159,9 @@  enum {
 /* Threshold for tx_timeout_cnt before we trigger a card reset */
 #define TX_TIMEOUT_THRESHOLD	6
 
+/* IOCTL number used for hostcmd process*/
+#define MWIFIEX_HOSTCMD_IOCTL (SIOCIWFIRSTPRIV + 17)
+
 #define MWIFIEX_DRV_INFO_SIZE_MAX 0x40000
 
 /* Address alignment */
@@ -892,6 +897,7 @@  struct mwifiex_adapter {
 	u8 event_received;
 	u8 data_received;
 	u16 seq_num;
+	struct mwifiex_ds_misc_cmd hostcmd_resp_data;
 	struct cmd_ctrl_node *cmd_pool;
 	struct cmd_ctrl_node *curr_cmd;
 	/* spin lock for command */
@@ -1553,7 +1559,8 @@  bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
 u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
 				 u32 pri_chan, u8 chan_bw);
 int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);
-
+int mwifiex_process_host_command(struct mwifiex_private *priv,
+				 struct iwreq *wrq);
 int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb);
 void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv);
 void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,