Samsung VZW MB1 update
/drivers/net/wireless/bcmdhd/wl_android.c
blob:bb402b2ac1962ae4a41b730e13af558fab54ba80 -> blob:1161b7d58e546a80600b0229124e371d3007617b
--- drivers/net/wireless/bcmdhd/wl_android.c
+++ drivers/net/wireless/bcmdhd/wl_android.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_android.c 354184 2012-08-30 08:08:08Z $
+ * $Id: wl_android.c 372067 2012-11-30 08:03:06Z $
*/
#include <linux/module.h>
@@ -77,8 +77,10 @@
#if !defined WL_ENABLE_P2P_IF
#define CMD_P2P_GET_NOA "P2P_GET_NOA"
#endif
+#define CMD_P2P_SD_OFFLOAD "P2P_SD_"
#define CMD_P2P_SET_PS "P2P_SET_PS"
#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
+#define CMD_SETROAMMODE "SETROAMMODE"
#if defined(SUPPORT_HIDDEN_AP)
/* Hostapd private command */
@@ -199,6 +201,45 @@ typedef struct android_wifi_priv_cmd {
int total_len;
} android_wifi_priv_cmd;
+#ifdef WL_GENL
+static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info);
+static int wl_genl_init(void);
+static int wl_genl_deinit(void);
+
+extern struct net init_net;
+/* attribute policy: defines which attribute has which type (e.g int, char * etc)
+ * possible values defined in net/netlink.h
+ */
+static struct nla_policy wl_genl_policy[BCM_GENL_ATTR_MAX + 1] = {
+ [BCM_GENL_ATTR_MSG] = { .type = NLA_NUL_STRING },
+};
+
+#define WL_GENL_VER 1
+/* family definition */
+static struct genl_family wl_genl_family = {
+ .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
+ .hdrsize = 0,
+ .name = "bcm-genl", /* Netlink I/F for Android */
+ .version = WL_GENL_VER, /* Version Number */
+ .maxattr = BCM_GENL_ATTR_MAX,
+};
+
+/* commands: mapping between the command enumeration and the actual function */
+struct genl_ops wl_genl_ops = {
+ .cmd = BCM_GENL_CMD_MSG,
+ .flags = 0,
+ .policy = wl_genl_policy,
+ .doit = wl_genl_handle_msg,
+ .dumpit = NULL,
+};
+
+static struct genl_multicast_group wl_genl_mcast = {
+ .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
+ .name = "bcm-genl-mcast",
+};
+
+#endif /* WL_GENL */
+
/**
* Extern function declarations (TODO: move them to dhd_linux.h)
*/
@@ -223,9 +264,16 @@ int wl_cfg80211_get_p2p_noa(struct net_d
int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
{ return 0; }
#endif /* WL_CFG80211 */
+
+extern int dhd_os_check_wakelock(void *dhdp);
extern int dhd_os_check_if_up(void *dhdp);
extern void *bcmsdh_get_drvdata(void);
+#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB)
+extern int dhd_wlfc_init(dhd_pub_t *dhd);
+extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
+#endif
+
#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT)
/* wl_roam.c */
extern int get_roamscan_mode(struct net_device *dev, int *mode);
@@ -998,7 +1046,7 @@ int wl_android_set_okc_mode(struct net_d
}
#endif /* WES_SUPPORT */
-#ifdef PNO_SUPPORT
+#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN)
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
{
wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
@@ -1105,7 +1153,7 @@ static int wl_android_set_pno_setup(stru
exit_proc:
return res;
}
-#endif /* PNO_SUPPORT */
+#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */
static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
{
@@ -1239,6 +1287,9 @@ int wl_android_wifi_on(struct net_device
if (dhd_dev_init_ioctl(dev) < 0)
ret = -EFAULT;
}
+#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB)
+ dhd_wlfc_init(bcmsdh_get_drvdata());
+#endif
g_wifi_on = TRUE;
}
@@ -1260,6 +1311,9 @@ int wl_android_wifi_off(struct net_devic
dhd_net_if_lock(dev);
if (g_wifi_on) {
+#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB)
+ dhd_wlfc_deinit(bcmsdh_get_drvdata());
+#endif
ret = dhd_dev_reset(dev, TRUE);
sdioh_stop(NULL);
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
@@ -1411,7 +1465,7 @@ wl_android_sta_diassoc(struct net_device
bcm_ether_atoe(straddr, &scbval.ea);
DHD_INFO(("%s: deauth STA: "MACDBG "\n", __FUNCTION__,
- STR_TO_MACD(scbval.ea.octet)));
+ MAC2STRDBG(scbval.ea.octet)));
wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
sizeof(scb_val_t), true);
@@ -1515,6 +1569,28 @@ wl_android_set_ampdu_mpdu(struct net_dev
}
#endif /* SUPPORT_AMPDU_MPDU_CMD */
+int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ int mode = 0;
+
+ if (sscanf(command, "%*s %d", &mode) != 1) {
+ DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
+ return -1;
+ }
+
+ error = wldev_iovar_setint(dev, "roam_off", mode);
+ if (error) {
+ DHD_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
+ __FUNCTION__, mode, error));
+ return -1;
+ }
+ else
+ DHD_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
+ __FUNCTION__, mode, error));
+ return 0;
+}
+
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
#define PRIVATE_COMMAND_MAX_LEN 8192
@@ -1633,7 +1709,16 @@ int wl_android_priv_cmd(struct net_devic
}
else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
+#ifdef WL_HOST_BAND_MGMT
+ if (wl_cfg80211_set_band(net, band) < 0) {
+ bytes_written = -1;
+ goto exit;
+ }
+ if (band == WLC_BAND_AUTO)
+ bytes_written = wldev_set_band(net, band);
+#else
bytes_written = wldev_set_band(net, band);
+#endif /* WL_HOST_BAND_MGMT */
}
else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
@@ -1684,7 +1769,6 @@ int wl_android_priv_cmd(struct net_devic
strlen(CMD_COUNTRYREV_SET)) == 0) {
bytes_written = wl_android_set_country_rev(net, command,
priv_cmd.total_len);
- wl_update_wiphybands(NULL);
} else if (strnicmp(command, CMD_COUNTRYREV_GET,
strlen(CMD_COUNTRYREV_GET)) == 0) {
bytes_written = wl_android_get_country_rev(net, command,
@@ -1749,7 +1833,7 @@ int wl_android_priv_cmd(struct net_devic
bytes_written = wl_android_set_okc_mode(net, command, priv_cmd.total_len);
}
#endif /* WES_SUPPORT */
-#ifdef PNO_SUPPORT
+#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN)
else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
bytes_written = dhd_dev_pno_reset(net);
}
@@ -1760,7 +1844,7 @@ int wl_android_priv_cmd(struct net_devic
uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
}
-#endif
+#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */
else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
}
@@ -1849,6 +1933,8 @@ int wl_android_priv_cmd(struct net_devic
else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0)
bytes_written = wl_android_ch_res_rl(net, false);
#endif /* CUSTOMER_HW4 */
+ else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
+ bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
else {
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
snprintf(command, 3, "OK");
@@ -1897,6 +1983,11 @@ int wl_android_init(void)
bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
}
#endif /* CUSTOMER_HW2 || CUSTOMER_HW4 */
+
+#ifdef WL_GENL
+ wl_genl_init();
+#endif
+
return ret;
}
@@ -1904,6 +1995,10 @@ int wl_android_exit(void)
{
int ret = 0;
+#ifdef WL_GENL
+ wl_genl_deinit();
+#endif /* WL_GENL */
+
return ret;
}
@@ -1915,6 +2010,145 @@ void wl_android_post_init(void)
g_wifi_on = 0;
}
}
+
+#ifdef WL_GENL
+/* Generic Netlink Initializaiton */
+static int wl_genl_init(void)
+{
+ int ret;
+
+ WL_DBG(("GEN Netlink Init\n\n"));
+
+ /* register new family */
+ ret = genl_register_family(&wl_genl_family);
+ if (ret != 0)
+ goto failure;
+
+ /* register functions (commands) of the new family */
+ ret = genl_register_ops(&wl_genl_family, &wl_genl_ops);
+ if (ret != 0) {
+ WL_ERR(("register ops failed: %i\n", ret));
+ genl_unregister_family(&wl_genl_family);
+ goto failure;
+ }
+
+ ret = genl_register_mc_group(&wl_genl_family, &wl_genl_mcast);
+ if (ret != 0) {
+ WL_ERR(("register mc_group failed: %i\n", ret));
+ genl_unregister_ops(&wl_genl_family, &wl_genl_ops);
+ genl_unregister_family(&wl_genl_family);
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+ WL_ERR(("Registering Netlink failed!!\n"));
+ return -1;
+}
+
+/* Generic netlink deinit */
+static int wl_genl_deinit(void)
+{
+ if (genl_unregister_ops(&wl_genl_family, &wl_genl_ops) < 0)
+ WL_ERR(("Unregister wl_genl_ops failed\n"));
+
+ if (genl_unregister_family(&wl_genl_family) < 0)
+ WL_ERR(("Unregister wl_genl_ops failed\n"));
+
+ return 0;
+}
+
+s32
+wl_genl_send_msg(
+ struct net_device *ndev,
+ int pid,
+ u8 *string,
+ u8 len,
+ int mcast)
+{
+ int ret = 0;
+ struct sk_buff *skb;
+ void *msg;
+
+ WL_DBG(("Enter \n"));
+ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (skb == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG);
+ if (msg == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Add a BCM_GENL_MSG attribute. Since it is specified as a string.
+ * make sure it is null terminated
+ */
+ ret = nla_put_string(skb, BCM_GENL_ATTR_MSG, string);
+ if (ret != 0) {
+ WL_ERR(("nla_put_string failed\n"));
+ goto out;
+ }
+
+ if (mcast) {
+ /* finalize the message */
+ genlmsg_end(skb, msg);
+ /* NETLINK_CB(skb).dst_group = 1; */
+ if (genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC) < 0)
+ WL_ERR(("genlmsg_multicast failed\n"));
+ } else {
+ NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */
+
+ /* finalize the message */
+ genlmsg_end(skb, msg);
+
+ /* send the message back */
+ if (genlmsg_unicast(&init_net, skb, pid) < 0)
+ WL_ERR(("genlmsg_unicast failed\n"));
+ }
+
+ return 0;
+out:
+ nlmsg_free(skb);
+ return ret;
+}
+
+static s32
+wl_genl_handle_msg(
+ struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct nlattr *na;
+ u8 *data = NULL;
+
+ WL_DBG(("Enter \n"));
+
+ if (info == NULL) {
+ return -EINVAL;
+ }
+
+ na = info->attrs[BCM_GENL_ATTR_MSG];
+ if (!na) {
+ WL_ERR(("nlattribute NULL\n"));
+ return -EINVAL;
+ }
+
+ data = (char *)nla_data(na);
+ if (!data) {
+ WL_ERR(("Invalid data\n"));
+ return -EINVAL;
+ } else {
+ /* Handle the data */
+ WL_DBG(("%s: Data received from pid (%d) \n", __func__, info->snd_pid));
+ }
+
+ return 0;
+}
+#endif /* WL_GENL */
+
/**
* Functions for Android WiFi card detection
*/
@@ -2109,7 +2343,6 @@ static int wifi_add_dev(void)
{
int ret = 0;
DHD_TRACE(("## Calling platform_driver_register\n"));
-
ret = platform_driver_register(&wifi_device);
if (ret)
return ret;