summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcmdhd/dhd_linux.c
diff options
context:
space:
mode:
authorLin Ma <linm@broadcom.com>2011-07-18 11:42:36 -0700
committerDmitry Shmidt <dimitrysh@google.com>2011-07-21 17:13:52 -0700
commit2f66cb426e32ac6c731e4eda09aded204a800d64 (patch)
tree35cc7eeb8ec6f72697259048e85e6b21c25dce9d /drivers/net/wireless/bcmdhd/dhd_linux.c
parentb06f3b5edb8f9256f0435f13a439074291cd9055 (diff)
Update to 5.90.125.40
Add monitor interface support and fix cfg80211 management frame isses Add support for hostapd Use private command to get p2p device address Change-Id: Ie490e38f1af9f259ff4a96b2f7d367119c65c377 Signed-off-by: Howard M. Harte <hharte@broadcom.com> Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers/net/wireless/bcmdhd/dhd_linux.c')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c68
1 files changed, 49 insertions, 19 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index e952ee1ccc2..ff9f9fa9c21 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -91,6 +91,7 @@ static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
#if defined(SOFTAP)
extern bool ap_cfg_running;
+extern bool ap_fw_loaded;
#endif
/* enable HOSTIP cache update from the host side when an eth0:N is up */
@@ -442,6 +443,12 @@ static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf);
static void dhd_dump_htsfhisto(histo_t *his, char *s);
#endif /* WLMEDIA_HTSF */
+extern s32 wl_cfg80211_ifdel_ops(struct net_device *net);
+
+/* Monitor interface */
+extern int dhd_monitor_init(void *dhd_pub);
+extern int dhd_monitor_uninit(void);
+
#if defined(CONFIG_WIRELESS_EXT)
struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
@@ -491,6 +498,7 @@ extern int register_pm_notifier(struct notifier_block *nb);
extern int unregister_pm_notifier(struct notifier_block *nb);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
/* && defined(DHD_GPL) */
+
static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
{
#ifdef PKT_FILTER_SUPPORT
@@ -972,7 +980,7 @@ dhd_op_if(dhd_if_t *ifp)
ret = -EOPNOTSUPP;
} else {
#if defined(SOFTAP)
- if (ap_cfg_running && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
+ if (ap_fw_loaded && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
/* semaphore that the soft AP CODE waits on */
flags = dhd_os_spin_lock(&dhd->pub);
@@ -992,6 +1000,9 @@ dhd_op_if(dhd_if_t *ifp)
case WLC_E_IF_DEL:
if (ifp->net != NULL) {
DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", __FUNCTION__));
+#ifdef WL_CFG80211
+ wl_cfg80211_ifdel_ops(ifp->net);
+#endif
netif_stop_queue(ifp->net);
unregister_netdev(ifp->net);
ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */
@@ -1234,7 +1245,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
return ret;
}
-static int
+int
dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
{
int ret;
@@ -1462,7 +1473,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
}
}
-
ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
ifp = dhd->iflist[ifidx];
@@ -1473,6 +1483,14 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
dhdp->dstats.rx_bytes += skb->len;
dhdp->rx_packets++; /* Local count */
+ /* Dropping packets before registering net device to avoid kernel panic */
+ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
+ DHD_ERROR(("%s: net device is NOT registered yet. drop [%s] packet\n",
+ __FUNCTION__, (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) ? "event" : "data"));
+ PKTFREE(dhdp->osh, pktbuf, TRUE);
+ continue;
+ }
+
if (in_interrupt()) {
netif_rx(skb);
} else {
@@ -2363,7 +2381,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
/* updates firmware nvram path if it was provided as module parameters */
if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
strcpy(fw_path, firmware_path);
@@ -2469,6 +2486,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
DHD_ERROR(("wl_cfg80211_attach failed\n"));
goto fail;
}
+
+ dhd_monitor_init(&dhd->pub);
dhd_state |= DHD_ATTACH_STATE_CFG80211;
#endif
#if defined(CONFIG_WIRELESS_EXT)
@@ -2563,7 +2582,6 @@ fail:
dhd_free(&dhd->pub);
}
-
return NULL;
}
@@ -2665,7 +2683,11 @@ dhd_bus_start(dhd_pub_t *dhdp)
setbit(dhdp->eventmask, WLC_E_TXFAIL);
setbit(dhdp->eventmask, WLC_E_JOIN_START);
setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
-
+ setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_RX);
+ setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_COMPLETE);
+#if defined(WLP2P)
+ setbit(dhdp->eventmask, WLC_E_P2P_PROBREQ_MSG);
+#endif /* WLP2P */
#ifdef PNO_SUPPORT
setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
#endif /* PNO_SUPPORT */
@@ -2694,10 +2716,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
dhd_write_macaddr(dhd->pub.mac.octet);
#endif
-#if defined(CONFIG_SYSCTL) && defined(WL_CFG80211)
- wl_cfg80211_sysctl_export_devaddr(&dhd->pub);
-#endif
-
return 0;
}
@@ -2724,6 +2742,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, in
return ret;
}
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
static struct net_device_ops dhd_ops_pri = {
.ndo_open = dhd_open,
@@ -2848,6 +2867,8 @@ static int dhd_device_event(struct notifier_block *this,
__FUNCTION__));
aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
}
+ else
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
#endif
break;
@@ -2923,12 +2944,18 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
* We have to use the primary MAC for virtual interfaces
*/
memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
- if (ifidx == 1) {
- DHD_TRACE(("%s ACCESS POINT MAC: \n", __FUNCTION__));
- /* ACCESSPOINT INTERFACE CASE */
- temp_addr[0] |= 0x02; /* set bit 2 , - Locally Administered address */
+ /*
+ * Android sets the locally administered bit to indicate that this is a
+ * portable hotspot. This will not work in simultaneous AP/STA mode,
+ * nor with P2P. Need to set the Donlge's MAC address, and then use that.
+ */
+ if (ifidx > 0) {
+ DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n",
+ __func__, net->name));
+ temp_addr[0] |= 0x02;
}
}
+
net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
net->ethtool_ops = &dhd_ethtool_ops;
@@ -2951,11 +2978,11 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
DHD_ERROR(("couldn't register the net device, err %d\n", err));
goto fail;
}
-
- printf("%s: Driver up: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ printf("Broadcom Dongle Host Driver: register interface [%s]"
+ " MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
net->name,
- dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
- dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
+ net->dev_addr[0], net->dev_addr[1], net->dev_addr[2],
+ net->dev_addr[3], net->dev_addr[4], net->dev_addr[5]);
#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211)
wl_iw_iscan_set_scan_broadcast_prep(net, 1);
@@ -3106,8 +3133,10 @@ void dhd_detach(dhd_pub_t *dhdp)
}
#ifdef WL_CFG80211
- if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
wl_cfg80211_detach();
+ dhd_monitor_uninit();
+ }
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@@ -3120,6 +3149,7 @@ void dhd_detach(dhd_pub_t *dhdp)
wake_lock_destroy(&dhd->wl_rxwake);
#endif
}
+
}