wl1251: add wl1251 prefix to all 1251 files

Now that all 1271 files are split, we can add wl1251_ prefix to the files.

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index f94970c..d5595a8 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,4 +1,5 @@
-wl1251-objs		= main.o spi.o event.o wl1251_tx.o rx.o \
-			  ps.o cmd.o acx.o boot.o init.o wl1251_ops.o  \
-			  debugfs.o
+wl1251-objs		= wl1251_main.o wl1251_spi.o wl1251_event.o \
+			  wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
+			  wl1251_acx.o wl1251_boot.o wl1251_init.o \
+			  wl1251_ops.o wl1251_debugfs.o
 obj-$(CONFIG_WL1251)	+= wl1251.o
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
similarity index 99%
rename from drivers/net/wireless/wl12xx/acx.c
rename to drivers/net/wireless/wl12xx/wl1251_acx.c
index 328f88a..cecc1fa 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -1,4 +1,4 @@
-#include "acx.h"
+#include "wl1251_acx.h"
 
 #include <linux/module.h>
 #include <linux/crc7.h>
@@ -7,8 +7,8 @@
 #include "wl12xx.h"
 #include "wl12xx_80211.h"
 #include "reg.h"
-#include "spi.h"
-#include "ps.h"
+#include "wl1251_spi.h"
+#include "wl1251_ps.h"
 
 int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
 			   u8 mgt_rate, u8 mgt_mod)
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
similarity index 99%
rename from drivers/net/wireless/wl12xx/acx.h
rename to drivers/net/wireless/wl12xx/wl1251_acx.h
index 92e7248..203f11f 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -26,7 +26,7 @@
 #define __WL12XX_ACX_H__
 
 #include "wl12xx.h"
-#include "cmd.h"
+#include "wl1251_cmd.h"
 
 /* Target's information element */
 struct acx_header {
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
similarity index 98%
rename from drivers/net/wireless/wl12xx/boot.c
rename to drivers/net/wireless/wl12xx/wl1251_boot.c
index a6a2649..c52a208 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -24,9 +24,9 @@
 #include <linux/gpio.h>
 
 #include "reg.h"
-#include "boot.h"
-#include "spi.h"
-#include "event.h"
+#include "wl1251_boot.h"
+#include "wl1251_spi.h"
+#include "wl1251_event.h"
 
 static void wl12xx_boot_enable_interrupts(struct wl12xx *wl)
 {
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/boot.h
rename to drivers/net/wireless/wl12xx/wl1251_boot.h
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
similarity index 98%
rename from drivers/net/wireless/wl12xx/cmd.c
rename to drivers/net/wireless/wl12xx/wl1251_cmd.c
index cad258d..d0c2df6 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -1,4 +1,4 @@
-#include "cmd.h"
+#include "wl1251_cmd.h"
 
 #include <linux/module.h>
 #include <linux/crc7.h>
@@ -7,9 +7,9 @@
 #include "wl12xx.h"
 #include "wl12xx_80211.h"
 #include "reg.h"
-#include "spi.h"
-#include "ps.h"
-#include "acx.h"
+#include "wl1251_spi.h"
+#include "wl1251_ps.h"
+#include "wl1251_acx.h"
 
 /**
  * send command to firmware
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/cmd.h
rename to drivers/net/wireless/wl12xx/wl1251_cmd.h
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
similarity index 99%
rename from drivers/net/wireless/wl12xx/debugfs.c
rename to drivers/net/wireless/wl12xx/wl1251_debugfs.c
index 94ad994..a63bc78 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
@@ -21,13 +21,13 @@
  *
  */
 
-#include "debugfs.h"
+#include "wl1251_debugfs.h"
 
 #include <linux/skbuff.h>
 
 #include "wl12xx.h"
-#include "acx.h"
-#include "ps.h"
+#include "wl1251_acx.h"
+#include "wl1251_ps.h"
 
 /* ms */
 #define WL12XX_DEBUGFS_STATS_LIFETIME 1000
diff --git a/drivers/net/wireless/wl12xx/debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/debugfs.h
rename to drivers/net/wireless/wl12xx/wl1251_debugfs.h
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
similarity index 97%
rename from drivers/net/wireless/wl12xx/event.c
rename to drivers/net/wireless/wl12xx/wl1251_event.c
index 99529ca..50b5e43 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/wl1251_event.c
@@ -24,9 +24,9 @@
 
 #include "wl12xx.h"
 #include "reg.h"
-#include "spi.h"
-#include "event.h"
-#include "ps.h"
+#include "wl1251_spi.h"
+#include "wl1251_event.h"
+#include "wl1251_ps.h"
 
 static int wl12xx_event_scan_complete(struct wl12xx *wl,
 				      struct event_mailbox *mbox)
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/wl1251_event.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/event.h
rename to drivers/net/wireless/wl12xx/wl1251_event.h
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/wl1251_init.c
similarity index 97%
rename from drivers/net/wireless/wl12xx/init.c
rename to drivers/net/wireless/wl12xx/wl1251_init.c
index 2a573a6..0929461a 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/wl1251_init.c
@@ -24,10 +24,10 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#include "init.h"
+#include "wl1251_init.h"
 #include "wl12xx_80211.h"
-#include "acx.h"
-#include "cmd.h"
+#include "wl1251_acx.h"
+#include "wl1251_cmd.h"
 
 int wl12xx_hw_init_hwenc_config(struct wl12xx *wl)
 {
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/wl1251_init.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/init.h
rename to drivers/net/wireless/wl12xx/wl1251_init.h
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
similarity index 99%
rename from drivers/net/wireless/wl12xx/main.c
rename to drivers/net/wireless/wl12xx/wl1251_main.c
index dd75d3d..16cd46c 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -35,13 +35,13 @@
 #include "wl12xx_80211.h"
 #include "reg.h"
 #include "wl1251_ops.h"
-#include "spi.h"
-#include "event.h"
+#include "wl1251_spi.h"
+#include "wl1251_event.h"
 #include "wl1251_tx.h"
-#include "rx.h"
-#include "ps.h"
-#include "init.h"
-#include "debugfs.h"
+#include "wl1251_rx.h"
+#include "wl1251_ps.h"
+#include "wl1251_init.h"
+#include "wl1251_debugfs.h"
 
 static void wl12xx_disable_interrupts(struct wl12xx *wl)
 {
diff --git a/drivers/net/wireless/wl12xx/wl1251_netlink.c b/drivers/net/wireless/wl12xx/wl1251_netlink.c
new file mode 100644
index 0000000..1bc049f
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_netlink.c
@@ -0,0 +1,679 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include "wl1251_netlink.h"
+
+#include <linux/mutex.h>
+#include <linux/socket.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+#include <net/genetlink.h>
+#include <net/wireless.h>
+#include <net/mac80211.h>
+
+#include "wl12xx.h"
+#include "wl1251_spi.h"
+#include "wl1251_acx.h"
+
+/* FIXME: this should be changed as soon as user space catches up */
+#define WL12XX_NL_NAME "wl1251"
+#define WL12XX_NL_VERSION 1
+
+#define WL12XX_MAX_TEST_LENGTH 1024
+#define WL12XX_MAX_NVS_LENGTH 1024
+
+enum wl12xx_nl_commands {
+	WL12XX_NL_CMD_UNSPEC,
+	WL12XX_NL_CMD_TEST,
+	WL12XX_NL_CMD_INTERROGATE,
+	WL12XX_NL_CMD_CONFIGURE,
+	WL12XX_NL_CMD_PHY_REG_READ,
+	WL12XX_NL_CMD_NVS_PUSH,
+	WL12XX_NL_CMD_REG_WRITE,
+	WL12XX_NL_CMD_REG_READ,
+	WL12XX_NL_CMD_SET_PLT_MODE,
+
+	__WL12XX_NL_CMD_AFTER_LAST
+};
+#define WL12XX_NL_CMD_MAX (__WL12XX_NL_CMD_AFTER_LAST - 1)
+
+enum wl12xx_nl_attrs {
+	WL12XX_NL_ATTR_UNSPEC,
+	WL12XX_NL_ATTR_IFNAME,
+	WL12XX_NL_ATTR_CMD_TEST_PARAM,
+	WL12XX_NL_ATTR_CMD_TEST_ANSWER,
+	WL12XX_NL_ATTR_CMD_IE,
+	WL12XX_NL_ATTR_CMD_IE_LEN,
+	WL12XX_NL_ATTR_CMD_IE_BUFFER,
+	WL12XX_NL_ATTR_CMD_IE_ANSWER,
+	WL12XX_NL_ATTR_REG_ADDR,
+	WL12XX_NL_ATTR_REG_VAL,
+	WL12XX_NL_ATTR_NVS_BUFFER,
+	WL12XX_NL_ATTR_NVS_LEN,
+	WL12XX_NL_ATTR_PLT_MODE,
+
+	__WL12XX_NL_ATTR_AFTER_LAST
+};
+#define WL12XX_NL_ATTR_MAX (__WL12XX_NL_ATTR_AFTER_LAST - 1)
+
+static struct genl_family wl12xx_nl_family = {
+	.id = GENL_ID_GENERATE,
+	.name = WL12XX_NL_NAME,
+	.hdrsize = 0,
+	.version = WL12XX_NL_VERSION,
+	.maxattr = WL12XX_NL_ATTR_MAX,
+};
+
+static struct net_device *ifname_to_netdev(struct net *net,
+					   struct genl_info *info)
+{
+	char *ifname;
+
+	if (!info->attrs[WL12XX_NL_ATTR_IFNAME])
+		return NULL;
+
+	ifname = nla_data(info->attrs[WL12XX_NL_ATTR_IFNAME]);
+
+	wl12xx_debug(DEBUG_NETLINK, "Looking for %s", ifname);
+
+	return dev_get_by_name(net, ifname);
+}
+
+static struct wl12xx *ifname_to_wl12xx(struct net *net, struct genl_info *info)
+{
+	struct net_device *netdev;
+	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
+	struct ieee80211_hw *hw;
+
+	netdev = ifname_to_netdev(net, info);
+	if (netdev == NULL) {
+		wl12xx_error("Wrong interface");
+		return NULL;
+	}
+
+	wdev = netdev->ieee80211_ptr;
+	if (wdev == NULL) {
+		wl12xx_error("ieee80211_ptr is NULL");
+		return NULL;
+	}
+
+	wiphy = wdev->wiphy;
+	if (wiphy == NULL) {
+		wl12xx_error("wiphy is NULL");
+		return NULL;
+	}
+
+	hw = wiphy_priv(wiphy);
+	if (hw == NULL) {
+		wl12xx_error("hw is NULL");
+		return NULL;
+	}
+
+	dev_put(netdev);
+
+	return hw->priv;
+}
+
+static int wl12xx_nl_test_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	struct wl12xx_command *cmd;
+	char *buf;
+	int buf_len, ret, cmd_len;
+	u8 answer;
+
+	if (!info->attrs[WL12XX_NL_ATTR_CMD_TEST_PARAM])
+		return -EINVAL;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		return -EINVAL;
+	}
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	buf = nla_data(info->attrs[WL12XX_NL_ATTR_CMD_TEST_PARAM]);
+	buf_len = nla_len(info->attrs[WL12XX_NL_ATTR_CMD_TEST_PARAM]);
+	answer = nla_get_u8(info->attrs[WL12XX_NL_ATTR_CMD_TEST_ANSWER]);
+
+	cmd->header.id = CMD_TEST;
+	memcpy(cmd->parameters, buf, buf_len);
+	cmd_len = sizeof(struct wl12xx_cmd_header) + buf_len;
+
+	mutex_lock(&wl->mutex);
+	ret = wl12xx_cmd_test(wl, cmd, cmd_len, answer);
+	mutex_unlock(&wl->mutex);
+
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto out;
+	}
+
+	if (answer) {
+		struct sk_buff *msg;
+		void *hdr;
+
+		msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+		if (!msg) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+				  &wl12xx_nl_family, 0, WL12XX_NL_CMD_TEST);
+		if (IS_ERR(hdr)) {
+			ret = PTR_ERR(hdr);
+			goto nla_put_failure;
+		}
+
+		NLA_PUT_STRING(msg, WL12XX_NL_ATTR_IFNAME,
+			       nla_data(info->attrs[WL12XX_NL_ATTR_IFNAME]));
+		NLA_PUT(msg, WL12XX_NL_ATTR_CMD_TEST_ANSWER,
+			sizeof(*cmd), cmd);
+
+		ret = genlmsg_end(msg, hdr);
+		if (ret < 0) {
+			wl12xx_error("%s() failed", __func__);
+			goto nla_put_failure;
+		}
+
+		wl12xx_debug(DEBUG_NETLINK, "TEST cmd sent, answer");
+		ret = genlmsg_reply(msg, info);
+		goto out;
+
+ nla_put_failure:
+		nlmsg_free(msg);
+	} else
+		wl12xx_debug(DEBUG_NETLINK, "TEST cmd sent");
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
+static int wl12xx_nl_interrogate(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	struct sk_buff *msg;
+	int ret = -ENOBUFS, cmd_ie, cmd_ie_len;
+	struct wl12xx_command *cmd;
+	void *hdr;
+
+	if (!info->attrs[WL12XX_NL_ATTR_CMD_IE])
+		return -EINVAL;
+
+	if (!info->attrs[WL12XX_NL_ATTR_CMD_IE_LEN])
+		return -EINVAL;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		ret = -EINVAL;
+		goto nla_put_failure;
+	}
+
+	/* acx id */
+	cmd_ie = nla_get_u32(info->attrs[WL12XX_NL_ATTR_CMD_IE]);
+
+	/* maximum length of acx, including all headers */
+	cmd_ie_len = nla_get_u32(info->attrs[WL12XX_NL_ATTR_CMD_IE_LEN]);
+
+	wl12xx_debug(DEBUG_NETLINK, "Getting IE 0x%x (len %d)",
+		     cmd_ie, cmd_ie_len);
+
+	mutex_lock(&wl->mutex);
+	ret = wl12xx_cmd_interrogate(wl, cmd_ie, cmd, cmd_ie_len);
+	mutex_unlock(&wl->mutex);
+
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+			  &wl12xx_nl_family, 0, WL12XX_NL_CMD_INTERROGATE);
+	if (IS_ERR(hdr)) {
+		ret = PTR_ERR(hdr);
+		goto nla_put_failure;
+	}
+
+	NLA_PUT_STRING(msg, WL12XX_NL_ATTR_IFNAME,
+		       nla_data(info->attrs[WL12XX_NL_ATTR_IFNAME]));
+	NLA_PUT(msg, WL12XX_NL_ATTR_CMD_IE_ANSWER, cmd_ie_len, cmd);
+
+	ret = genlmsg_end(msg, hdr);
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+	kfree(cmd);
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	kfree(cmd);
+	nlmsg_free(msg);
+
+	return ret;
+}
+
+static int wl12xx_nl_configure(struct sk_buff *skb, struct genl_info *info)
+{
+	int ret = 0, cmd_ie_len, acx_len;
+	struct acx_header *acx = NULL;
+	struct sk_buff *msg;
+	struct wl12xx *wl;
+	void *cmd_ie;
+	u16 *id;
+
+	if (!info->attrs[WL12XX_NL_ATTR_CMD_IE_BUFFER])
+		return -EINVAL;
+
+	if (!info->attrs[WL12XX_NL_ATTR_CMD_IE_LEN])
+		return -EINVAL;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		ret = -EINVAL;
+		goto nla_put_failure;
+	}
+
+	/* contains the acx header but not the cmd header */
+	cmd_ie = nla_data(info->attrs[WL12XX_NL_ATTR_CMD_IE_BUFFER]);
+
+	cmd_ie_len = nla_get_u32(info->attrs[WL12XX_NL_ATTR_CMD_IE_LEN]);
+
+	/* acx id is in the first two bytes */
+	id = cmd_ie;
+
+	/* need to add acx_header before cmd_ie, so create a new command */
+	acx_len = sizeof(struct acx_header) + cmd_ie_len;
+	acx = kzalloc(acx_len, GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto nla_put_failure;
+	}
+
+	/* copy the acx header and the payload */
+	memcpy(&acx->id, cmd_ie, cmd_ie_len);
+
+	mutex_lock(&wl->mutex);
+	ret = wl12xx_cmd_configure(wl, *id, acx, acx_len);
+	mutex_unlock(&wl->mutex);
+
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+	wl12xx_debug(DEBUG_NETLINK, "CONFIGURE cmd sent");
+
+ nla_put_failure:
+	kfree(acx);
+	nlmsg_free(msg);
+
+	return ret;
+}
+
+static int wl12xx_nl_phy_reg_read(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	struct sk_buff *msg;
+	u32 reg_addr, *reg_value = NULL;
+	int ret = 0;
+	void *hdr;
+
+	if (!info->attrs[WL12XX_NL_ATTR_REG_ADDR])
+		return -EINVAL;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		ret = -EINVAL;
+		goto nla_put_failure;
+	}
+
+	reg_value = kmalloc(sizeof(*reg_value), GFP_KERNEL);
+	if (!reg_value) {
+		ret = -ENOMEM;
+		goto nla_put_failure;
+	}
+
+	reg_addr = nla_get_u32(info->attrs[WL12XX_NL_ATTR_REG_ADDR]);
+
+	wl12xx_debug(DEBUG_NETLINK, "Reading PHY reg 0x%x", reg_addr);
+
+	mutex_lock(&wl->mutex);
+	ret = wl12xx_cmd_read_memory(wl, reg_addr, reg_value,
+				     sizeof(*reg_value));
+	mutex_unlock(&wl->mutex);
+
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+
+	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+			  &wl12xx_nl_family, 0, WL12XX_NL_CMD_PHY_REG_READ);
+	if (IS_ERR(hdr)) {
+		ret = PTR_ERR(hdr);
+		goto nla_put_failure;
+	}
+
+	NLA_PUT_STRING(msg, WL12XX_NL_ATTR_IFNAME,
+		       nla_data(info->attrs[WL12XX_NL_ATTR_IFNAME]));
+
+	NLA_PUT_U32(msg, WL12XX_NL_ATTR_REG_VAL, *reg_value);
+
+	ret = genlmsg_end(msg, hdr);
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+	kfree(reg_value);
+
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	nlmsg_free(msg);
+	kfree(reg_value);
+
+	return ret;
+}
+
+static int wl12xx_nl_nvs_push(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	int ret = 0;
+
+	if (!info->attrs[WL12XX_NL_ATTR_NVS_BUFFER])
+		return -EINVAL;
+
+	if (!info->attrs[WL12XX_NL_ATTR_NVS_LEN])
+		return -EINVAL;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		return -EINVAL;
+	}
+
+	mutex_lock(&wl->mutex);
+	wl->nvs_len = nla_get_u32(info->attrs[WL12XX_NL_ATTR_NVS_LEN]);
+	if (wl->nvs_len % 4) {
+		wl12xx_error("NVS size is not multiple of 32: %d", wl->nvs_len);
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	/* If we already have an NVS, we should free it */
+	kfree(wl->nvs);
+
+	wl->nvs = kzalloc(wl->nvs_len, GFP_KERNEL);
+	if (wl->nvs == NULL) {
+		wl12xx_error("Can't allocate NVS");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(wl->nvs,
+	       nla_data(info->attrs[WL12XX_NL_ATTR_NVS_BUFFER]),
+	       wl->nvs_len);
+
+	wl12xx_debug(DEBUG_NETLINK, "got NVS from userspace, %d bytes",
+		     wl->nvs_len);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static int wl12xx_nl_reg_read(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	u32 addr, val;
+	int ret = 0;
+	struct sk_buff *msg;
+	void *hdr;
+
+	if (!info->attrs[WL12XX_NL_ATTR_REG_ADDR])
+		return -EINVAL;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		return -EINVAL;
+	}
+
+	addr = nla_get_u32(info->attrs[WL12XX_NL_ATTR_REG_ADDR]);
+
+	mutex_lock(&wl->mutex);
+	val = wl12xx_reg_read32(wl, addr);
+	mutex_unlock(&wl->mutex);
+
+	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+			  &wl12xx_nl_family, 0, WL12XX_NL_CMD_PHY_REG_READ);
+	if (IS_ERR(hdr)) {
+		ret = PTR_ERR(hdr);
+		goto nla_put_failure;
+	}
+
+	NLA_PUT_STRING(msg, WL12XX_NL_ATTR_IFNAME,
+		       nla_data(info->attrs[WL12XX_NL_ATTR_IFNAME]));
+
+	NLA_PUT_U32(msg, WL12XX_NL_ATTR_REG_VAL, val);
+
+	ret = genlmsg_end(msg, hdr);
+	if (ret < 0) {
+		wl12xx_error("%s() failed", __func__);
+		goto nla_put_failure;
+	}
+
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	nlmsg_free(msg);
+
+	return ret;
+}
+
+static int wl12xx_nl_reg_write(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	u32 addr, val;
+
+	if (!info->attrs[WL12XX_NL_ATTR_REG_ADDR])
+		return -EINVAL;
+
+	if (!info->attrs[WL12XX_NL_ATTR_REG_VAL])
+		return -EINVAL;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		return -EINVAL;
+	}
+
+	addr = nla_get_u32(info->attrs[WL12XX_NL_ATTR_REG_ADDR]);
+	val = nla_get_u32(info->attrs[WL12XX_NL_ATTR_REG_VAL]);
+
+	mutex_lock(&wl->mutex);
+	wl12xx_reg_write32(wl, addr, val);
+	mutex_unlock(&wl->mutex);
+
+	return 0;
+}
+
+static int wl12xx_nl_set_plt_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wl12xx *wl;
+	u32 val;
+	int ret;
+
+	if (!info->attrs[WL12XX_NL_ATTR_PLT_MODE])
+		return -EINVAL;
+
+	wl = ifname_to_wl12xx(&init_net, info);
+	if (wl == NULL) {
+		wl12xx_error("wl12xx not found");
+		return -EINVAL;
+	}
+
+	val = nla_get_u32(info->attrs[WL12XX_NL_ATTR_PLT_MODE]);
+
+	switch (val) {
+	case 0:
+		ret = wl12xx_plt_stop(wl);
+		break;
+	case 1:
+		ret = wl12xx_plt_start(wl);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static struct nla_policy wl12xx_nl_policy[WL12XX_NL_ATTR_MAX + 1] = {
+	[WL12XX_NL_ATTR_IFNAME] =            { .type = NLA_NUL_STRING,
+					       .len = IFNAMSIZ-1 },
+	[WL12XX_NL_ATTR_CMD_TEST_PARAM] =    { .type = NLA_BINARY,
+					       .len = WL12XX_MAX_TEST_LENGTH },
+	[WL12XX_NL_ATTR_CMD_TEST_ANSWER] =   { .type = NLA_U8 },
+	[WL12XX_NL_ATTR_CMD_IE] =            { .type = NLA_U32 },
+	[WL12XX_NL_ATTR_CMD_IE_LEN] =        { .type = NLA_U32 },
+	[WL12XX_NL_ATTR_CMD_IE_BUFFER] =     { .type = NLA_BINARY,
+					       .len = WL12XX_MAX_TEST_LENGTH },
+	[WL12XX_NL_ATTR_CMD_IE_ANSWER] =     { .type = NLA_BINARY,
+					       .len = WL12XX_MAX_TEST_LENGTH },
+	[WL12XX_NL_ATTR_REG_ADDR] =          { .type = NLA_U32 },
+	[WL12XX_NL_ATTR_REG_VAL] =           { .type = NLA_U32 },
+	[WL12XX_NL_ATTR_NVS_BUFFER] =        { .type = NLA_BINARY,
+					       .len = WL12XX_MAX_NVS_LENGTH },
+	[WL12XX_NL_ATTR_NVS_LEN] =           { .type = NLA_U32 },
+	[WL12XX_NL_ATTR_PLT_MODE] =          { .type = NLA_U32 },
+};
+
+static struct genl_ops wl12xx_nl_ops[] = {
+	{
+		.cmd = WL12XX_NL_CMD_TEST,
+		.doit = wl12xx_nl_test_cmd,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_INTERROGATE,
+		.doit = wl12xx_nl_interrogate,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_CONFIGURE,
+		.doit = wl12xx_nl_configure,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_PHY_REG_READ,
+		.doit = wl12xx_nl_phy_reg_read,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_NVS_PUSH,
+		.doit = wl12xx_nl_nvs_push,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_REG_WRITE,
+		.doit = wl12xx_nl_reg_write,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_REG_READ,
+		.doit = wl12xx_nl_reg_read,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = WL12XX_NL_CMD_SET_PLT_MODE,
+		.doit = wl12xx_nl_set_plt_mode,
+		.policy = wl12xx_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+};
+
+int wl12xx_nl_register(void)
+{
+	int err, i;
+
+	err = genl_register_family(&wl12xx_nl_family);
+	if (err)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(wl12xx_nl_ops); i++) {
+		err = genl_register_ops(&wl12xx_nl_family, &wl12xx_nl_ops[i]);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+ err_out:
+	genl_unregister_family(&wl12xx_nl_family);
+	return err;
+}
+
+void wl12xx_nl_unregister(void)
+{
+	genl_unregister_family(&wl12xx_nl_family);
+}
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/wl1251_netlink.h
similarity index 66%
copy from drivers/net/wireless/wl12xx/ps.h
copy to drivers/net/wireless/wl12xx/wl1251_netlink.h
index ad61b4a..acfbd02 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/wl1251_netlink.h
@@ -1,11 +1,7 @@
-#ifndef __WL12XX_PS_H__
-#define __WL12XX_PS_H__
-
 /*
  * This file is part of wl12xx
  *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2009 Nokia Corporation
  *
  * Contact: Kalle Valo <kalle.valo@nokia.com>
  *
@@ -25,12 +21,10 @@
  *
  */
 
-#include "wl12xx.h"
-#include "acx.h"
+#ifndef __WL12XX_NETLINK_H__
+#define __WL12XX_NETLINK_H__
 
-int wl12xx_ps_set_mode(struct wl12xx *wl, enum wl12xx_cmd_ps_mode mode);
-void wl12xx_ps_elp_sleep(struct wl12xx *wl);
-int wl12xx_ps_elp_wakeup(struct wl12xx *wl);
+int wl12xx_nl_register(void);
+void wl12xx_nl_unregister(void);
 
-
-#endif /* __WL12XX_PS_H__ */
+#endif /* __WL12XX_NETLINK_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c
index 126537f..cdfd2c2 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ops.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ops.c
@@ -26,14 +26,14 @@
 
 #include "wl1251_ops.h"
 #include "reg.h"
-#include "spi.h"
-#include "boot.h"
-#include "event.h"
-#include "acx.h"
+#include "wl1251_spi.h"
+#include "wl1251_boot.h"
+#include "wl1251_event.h"
+#include "wl1251_acx.h"
 #include "wl1251_tx.h"
-#include "rx.h"
-#include "ps.h"
-#include "init.h"
+#include "wl1251_rx.h"
+#include "wl1251_ps.h"
+#include "wl1251_init.h"
 
 static struct wl12xx_partition_set wl1251_part_table[PART_TABLE_LEN] = {
 	[PART_DOWN] = {
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.h b/drivers/net/wireless/wl12xx/wl1251_ops.h
index 74acf8e..7a78cc9 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ops.h
+++ b/drivers/net/wireless/wl12xx/wl1251_ops.h
@@ -27,7 +27,7 @@
 #include <linux/bitops.h>
 
 #include "wl12xx.h"
-#include "acx.h"
+#include "wl1251_acx.h"
 
 #define WL1251_FW_NAME "wl1251-fw.bin"
 #define WL1251_NVS_NAME "wl1251-nvs.bin"
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
similarity index 98%
rename from drivers/net/wireless/wl12xx/ps.c
rename to drivers/net/wireless/wl12xx/wl1251_ps.c
index f28f194..83baaa2 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -22,8 +22,8 @@
  */
 
 #include "reg.h"
-#include "ps.h"
-#include "spi.h"
+#include "wl1251_ps.h"
+#include "wl1251_spi.h"
 
 #define WL12XX_WAKEUP_TIMEOUT 2000
 
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h
similarity index 97%
rename from drivers/net/wireless/wl12xx/ps.h
rename to drivers/net/wireless/wl12xx/wl1251_ps.h
index ad61b4a..db9f7ed 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.h
@@ -26,7 +26,7 @@
  */
 
 #include "wl12xx.h"
-#include "acx.h"
+#include "wl1251_acx.h"
 
 int wl12xx_ps_set_mode(struct wl12xx *wl, enum wl12xx_cmd_ps_mode mode);
 void wl12xx_ps_elp_sleep(struct wl12xx *wl);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
similarity index 98%
rename from drivers/net/wireless/wl12xx/rx.c
rename to drivers/net/wireless/wl12xx/wl1251_rx.c
index 7ac26ef..d73e014 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -27,8 +27,9 @@
 
 #include "wl12xx.h"
 #include "reg.h"
-#include "spi.h"
-#include "rx.h"
+#include "wl1251_spi.h"
+#include "wl1251_rx.h"
+#include "wl1251_acx.h"
 
 static void wl12xx_rx_header(struct wl12xx *wl,
 			     struct wl12xx_rx_descriptor *desc)
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/rx.h
rename to drivers/net/wireless/wl12xx/wl1251_rx.h
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
similarity index 99%
rename from drivers/net/wireless/wl12xx/spi.c
rename to drivers/net/wireless/wl12xx/wl1251_spi.c
index 9c9943f..d7eee8c 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -28,8 +28,7 @@
 #include "wl12xx.h"
 #include "wl12xx_80211.h"
 #include "reg.h"
-#include "spi.h"
-#include "ps.h"
+#include "wl1251_spi.h"
 
 static int wl12xx_translate_reg_addr(struct wl12xx *wl, int addr)
 {
diff --git a/drivers/net/wireless/wl12xx/spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
similarity index 98%
rename from drivers/net/wireless/wl12xx/spi.h
rename to drivers/net/wireless/wl12xx/wl1251_spi.h
index e48a552..82b009c 100644
--- a/drivers/net/wireless/wl12xx/spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -25,8 +25,8 @@
 #ifndef __WL12XX_SPI_H__
 #define __WL12XX_SPI_H__
 
-#include "cmd.h"
-#include "acx.h"
+#include "wl1251_cmd.h"
+#include "wl1251_acx.h"
 #include "reg.h"
 
 #define HW_ACCESS_MEMORY_MAX_RANGE		0x1FFC0
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index 10023fc..c57330e 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -27,9 +27,9 @@
 
 #include "wl12xx.h"
 #include "reg.h"
-#include "spi.h"
+#include "wl1251_spi.h"
 #include "wl1251_tx.h"
-#include "ps.h"
+#include "wl1251_ps.h"
 
 static bool wl1251_tx_double_buffer_busy(struct wl12xx *wl, u32 data_out_count)
 {