2 * DHD Protocol Module for CDC and BDC.
4 * Copyright (C) 1999-2011, Broadcom Corporation
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
24 * $Id: dhd_cdc.c,v 1.51.6.28.4.1 2011-02-01 19:36:23 $
26 * BDC is like CDC, except it includes a header for data packets to convey
27 * packet priority over the bus, and flags (e.g. to indicate checksum status
28 * for dongle offload.)
36 #include <bcmendian.h>
38 #include <dngl_stats.h>
40 #include <dhd_proto.h>
46 /* Packet alignment for most efficient SDIO (can change based on platform) */
48 #define DHD_SDALIGN 32
50 #if !ISPOWEROF2(DHD_SDALIGN)
51 #error DHD_SDALIGN is not a power of 2!
54 #define RETRIES 2 /* # of retries to retrieve matching ioctl response */
55 #define BUS_HEADER_LEN (16+DHD_SDALIGN) /* Must be at least SDPCM_RESERVE
56 * defined in dhd_sdio.c (amount of header tha might be added)
57 * plus any space that might be needed for alignment padding.
59 #define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
60 * round off at the end of buffer
63 typedef struct dhd_prot {
67 uint8 bus_header[BUS_HEADER_LEN];
69 unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
73 dhdcdc_msg(dhd_pub_t *dhd)
76 dhd_prot_t *prot = dhd->prot;
77 int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
79 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
81 DHD_OS_WAKE_LOCK(dhd);
83 /* NOTE : cdc->msg.len holds the desired length of the buffer to be
84 * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
85 * is actually sent to the dongle
87 if (len > CDC_MAX_MSG_SIZE)
88 len = CDC_MAX_MSG_SIZE;
91 err = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
93 DHD_OS_WAKE_UNLOCK(dhd);
98 dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
101 int cdc_len = len+sizeof(cdc_ioctl_t);
102 dhd_prot_t *prot = dhd->prot;
104 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
107 ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
110 } while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
116 dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
118 dhd_prot_t *prot = dhd->prot;
119 cdc_ioctl_t *msg = &prot->msg;
121 int ret = 0, retries = 0;
122 uint32 id, flags = 0;
124 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
125 DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
128 /* Respond "bcmerror" and "bcmerrorstr" with local cache */
129 if (cmd == WLC_GET_VAR && buf)
131 if (!strcmp((char *)buf, "bcmerrorstr"))
133 strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
136 else if (!strcmp((char *)buf, "bcmerror"))
138 *(int *)buf = dhd->dongle_error;
143 memset(msg, 0, sizeof(cdc_ioctl_t));
146 /* 11bit gSPI bus allows 2048bytes of max-data. We restrict 'len'
147 * value which is 8Kbytes for various 'get' commands to 2000. 48 bytes are
148 * left for sw headers and misc.
150 len = (len > 2000) ? 2000 : len;
152 msg->cmd = htol32(cmd);
153 msg->len = htol32(len);
154 msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
155 CDC_SET_IF_IDX(msg, ifidx);
156 /* add additional action bits */
157 action &= WL_IOCTL_ACTION_MASK;
158 msg->flags |= (action << CDCF_IOC_ACTION_SHIFT);
159 msg->flags = htol32(msg->flags);
162 memcpy((void *)(&msg[1]), buf, len);
164 if ((ret = dhdcdc_msg(dhd)) < 0) {
165 DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
170 /* wait for interrupt and get first fragment */
171 if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
174 flags = ltoh32(msg->flags);
175 id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
177 if ((id < prot->reqid) && (++retries < RETRIES))
179 if (id != prot->reqid) {
180 DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
181 dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
186 /* Check info buffer */
187 info = (void*)&msg[1];
189 /* Copy info buffer */
194 memcpy(buf, info, len);
197 /* Check the ERROR flag */
198 if (flags & CDCF_IOC_ERROR)
200 ret = ltoh32(msg->status);
201 /* Cache error from dongle */
202 dhd->dongle_error = ret;
210 dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
212 dhd_prot_t *prot = dhd->prot;
213 cdc_ioctl_t *msg = &prot->msg;
217 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
218 DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
220 memset(msg, 0, sizeof(cdc_ioctl_t));
222 msg->cmd = htol32(cmd);
223 msg->len = htol32(len);
224 msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
225 CDC_SET_IF_IDX(msg, ifidx);
226 /* add additional action bits */
227 action &= WL_IOCTL_ACTION_MASK;
228 msg->flags |= (action << CDCF_IOC_ACTION_SHIFT) | CDCF_IOC_SET;
229 msg->flags = htol32(msg->flags);
232 memcpy((void *)(&msg[1]), buf, len);
234 if ((ret = dhdcdc_msg(dhd)) < 0) {
235 DHD_ERROR(("dhdcdc_set_ioctl: dhdcdc_msg failed w/status %d\n", ret));
239 if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
242 flags = ltoh32(msg->flags);
243 id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
245 if (id != prot->reqid) {
246 DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
247 dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
252 /* Check the ERROR flag */
253 if (flags & CDCF_IOC_ERROR)
255 ret = ltoh32(msg->status);
256 /* Cache error from dongle */
257 dhd->dongle_error = ret;
266 dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
268 dhd_prot_t *prot = dhd->prot;
272 if (dhd->busstate == DHD_BUS_DOWN) {
273 DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
277 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
279 ASSERT(len <= WLC_IOCTL_MAXLEN);
281 if (len > WLC_IOCTL_MAXLEN)
284 if (prot->pending == TRUE) {
285 DHD_ERROR(("CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
286 ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
287 (unsigned long)prot->lastcmd));
288 if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) {
289 DHD_TRACE(("iovar cmd=%s\n", (char*)buf));
294 prot->pending = TRUE;
295 prot->lastcmd = ioc->cmd;
297 if (action & WL_IOCTL_ACTION_SET)
298 ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
300 ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
302 ioc->used = ret - sizeof(cdc_ioctl_t);
305 /* Too many programs assume ioctl() returns 0 on success */
309 cdc_ioctl_t *msg = &prot->msg;
310 ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */
313 /* Intercept the wme_dp ioctl here */
314 if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
317 slen = strlen("wme_dp") + 1;
318 if (len >= (int)(slen + sizeof(int)))
319 bcopy(((char *)buf + slen), &val, sizeof(int));
320 dhd->wme_dp = (uint8) ltoh32(val);
323 prot->pending = FALSE;
330 dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
331 void *params, int plen, void *arg, int len, bool set)
333 return BCME_UNSUPPORTED;
338 dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
340 bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
344 dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf)
347 struct bdc_header *h;
350 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
353 /* Push BDC header used to convey priority for buses that don't */
355 PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN);
357 h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf);
359 h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
360 if (PKTSUMNEEDED(pktbuf))
361 h->flags |= BDC_FLAG_SUM_NEEDED;
364 h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK);
368 BDC_SET_IF_IDX(h, ifidx);
372 dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf)
375 struct bdc_header *h;
378 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
381 /* Pop BDC header used to convey priority for buses that don't */
383 if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) {
384 DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
385 PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN));
389 h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf);
391 if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) {
392 DHD_ERROR(("%s: rx data ifnum out of range (%d)\n",
393 __FUNCTION__, *ifidx));
397 if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) {
398 DHD_ERROR(("%s: non-BDC packet received, flags = 0x%x\n",
399 dhd_ifname(dhd, *ifidx), h->flags));
400 if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1)
406 if (h->flags & BDC_FLAG_SUM_GOOD) {
407 DHD_INFO(("%s: BDC packet received with good rx-csum, flags 0x%x\n",
408 dhd_ifname(dhd, *ifidx), h->flags));
409 PKTSETSUMGOOD(pktbuf, TRUE);
412 PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK));
413 PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
416 if (PKTLEN(dhd->osh, pktbuf) < (uint32) (h->dataOffset << 2)) {
417 DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
418 PKTLEN(dhd->osh, pktbuf), (h->dataOffset * 4)));
422 PKTPULL(dhd->osh, pktbuf, (h->dataOffset << 2));
427 dhd_prot_attach(dhd_pub_t *dhd)
431 #ifndef DHD_USE_STATIC_BUF
432 if (!(cdc = (dhd_prot_t *)MALLOC(dhd->osh, sizeof(dhd_prot_t)))) {
433 DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
437 if (!(cdc = (dhd_prot_t *)dhd_os_prealloc(DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) {
438 DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
441 #endif /* DHD_USE_STATIC_BUF */
442 memset(cdc, 0, sizeof(dhd_prot_t));
444 /* ensure that the msg buf directly follows the cdc msg struct */
445 if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) {
446 DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
452 dhd->hdrlen += BDC_HEADER_LEN;
454 dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
458 #ifndef DHD_USE_STATIC_BUF
460 MFREE(dhd->osh, cdc, sizeof(dhd_prot_t));
465 /* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
467 dhd_prot_detach(dhd_pub_t *dhd)
469 #ifndef DHD_USE_STATIC_BUF
470 MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t));
476 dhd_prot_dstats(dhd_pub_t *dhd)
478 /* No stats from dongle added yet, copy bus stats */
479 dhd->dstats.tx_packets = dhd->tx_packets;
480 dhd->dstats.tx_errors = dhd->tx_errors;
481 dhd->dstats.rx_packets = dhd->rx_packets;
482 dhd->dstats.rx_errors = dhd->rx_errors;
483 dhd->dstats.rx_dropped = dhd->rx_dropped;
484 dhd->dstats.multicast = dhd->rx_multicast;
488 int dhd_set_suspend(int value, dhd_pub_t *dhd)
490 int power_mode = PM_MAX;
491 wl_pkt_filter_enable_t enable_parm;
496 #endif /* CUSTOMER_HW2 */
500 if (dhd && dhd->up) {
502 dhd_wl_ioctl_cmd(dhd, WLC_SET_PM,
503 (char *)&power_mode, sizeof(power_mode), TRUE, 0);
504 /* Enable packet filter, only allow unicast packet to send up */
505 enable_parm.id = htod32(100);
506 enable_parm.enable = htod32(1);
507 bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
508 sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
509 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
510 /* set bcn_li_dtim */
511 bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
512 4, iovbuf, sizeof(iovbuf));
513 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
515 /* Disable build-in roaming to allowed ext supplicant to take of romaing */
516 bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
517 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
518 #endif /* CUSTOMER_HW2 */
520 power_mode = PM_FAST;
521 dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
522 sizeof(power_mode), TRUE, 0);
523 /* disable pkt filter */
524 enable_parm.id = htod32(100);
525 enable_parm.enable = htod32(0);
526 bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
527 sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
528 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
529 /* set bcn_li_dtim */
531 bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
532 4, iovbuf, sizeof(iovbuf));
533 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
536 bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
537 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
538 #endif /* CUSTOMER_HW2 */
545 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
547 extern void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode);
548 extern void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable);
549 extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
550 extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
553 dhd_preinit_ioctls(dhd_pub_t *dhd)
556 char eventmask[WL_EVENTING_MASK_LEN];
557 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
559 int power_mode = PM_FAST;
560 int dongle_align = DHD_SDALIGN;
564 int scan_assoc_time = 40;
565 int scan_unassoc_time = 80;
567 #ifdef GET_CUSTOM_MAC_ENABLE
568 struct ether_addr ea_addr;
569 #endif /* GET_CUSTOM_MAC_ENABLE */
570 #ifdef USE_WIFI_DIRECT
576 /* query for 'ver' to get version info from firmware */
578 if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) {
579 DHD_ERROR(("%s: can't get F/W version , error=%d\n", __FUNCTION__, ret));
582 /* Print fw version info */
583 DHD_ERROR(("Firmware version = %s\n", buf));
585 /* Get the device MAC address */
586 strcpy(iovbuf, "cur_etheraddr");
587 if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
588 DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
591 memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
593 /* Set Country code */
594 if (dhd->country_code[0] != 0) {
595 if (dhd_wl_ioctl_cmd(dhd, WLC_SET_COUNTRY,
596 dhd->country_code, sizeof(dhd->country_code), TRUE, 0) < 0) {
597 DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
601 /* Set PowerSave mode */
602 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
604 /* Match Host and Dongle rx alignment */
605 bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
606 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
608 /* disable glom option per default */
609 bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
610 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
612 /* Setup timeout if Beacons are lost and roam is off to report link down */
613 bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
614 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
616 /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
617 bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
618 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
620 #ifdef USE_WIFI_DIRECT
621 /* Enable APSTA mode */
622 bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
623 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
629 ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
634 /* Setup event_msgs */
635 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
636 dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
639 bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
641 /* Setup event_msgs */
642 setbit(eventmask, WLC_E_SET_SSID);
643 setbit(eventmask, WLC_E_PRUNE);
644 setbit(eventmask, WLC_E_AUTH);
645 setbit(eventmask, WLC_E_REASSOC);
646 setbit(eventmask, WLC_E_REASSOC_IND);
647 setbit(eventmask, WLC_E_DEAUTH_IND);
648 setbit(eventmask, WLC_E_DISASSOC_IND);
649 setbit(eventmask, WLC_E_DISASSOC);
650 setbit(eventmask, WLC_E_JOIN);
651 setbit(eventmask, WLC_E_ASSOC_IND);
652 setbit(eventmask, WLC_E_PSK_SUP);
653 setbit(eventmask, WLC_E_LINK);
654 setbit(eventmask, WLC_E_NDIS_LINK);
655 setbit(eventmask, WLC_E_MIC_ERROR);
656 setbit(eventmask, WLC_E_PMKID_CACHE);
657 setbit(eventmask, WLC_E_TXFAIL);
658 setbit(eventmask, WLC_E_JOIN_START);
659 setbit(eventmask, WLC_E_SCAN_COMPLETE);
661 setbit(eventmask, WLC_E_HTSFSYNC);
664 setbit(eventmask, WLC_E_PFN_NET_FOUND);
665 setbit(eventmask, WLC_E_PFN_NET_LOST);
667 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
668 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
671 dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, sizeof(scan_assoc_time), TRUE, 0);
672 dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, sizeof(scan_unassoc_time), TRUE, 0);
674 #ifdef ARP_OFFLOAD_SUPPORT
675 /* Set and enable ARP offload feature */
677 dhd_arp_offload_set(dhd, dhd_arp_mode);
678 dhd_arp_offload_enable(dhd, dhd_arp_enable);
679 #endif /* ARP_OFFLOAD_SUPPORT */
681 #ifdef PKT_FILTER_SUPPORT
684 /* Set up pkt filter */
685 if (dhd_pkt_filter_enable) {
686 for (i = 0; i < dhd->pktfilter_count; i++) {
687 dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
688 dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
689 dhd_pkt_filter_init, dhd_master_mode);
693 #endif /* PKT_FILTER_SUPPORT */
698 #ifdef ENABLE_DEEP_SLEEP
699 static dhd_pub_t *dhdpub = NULL;
700 extern void dhd_os_deepsleep_block(void); /* dhd_linux.c */
701 extern void dhd_os_deepsleep_unblock(void); /* dhd_linux.c */
702 extern void dhd_os_deepsleep_wait(void); /* dhd_linux.c */
704 #define MAX_TRY_CNT 5
706 int dhd_deepsleep(int flag)
713 DHD_ERROR(("[WIFI] %s: Enter.. Flag-> %d \n", __FUNCTION__, flag));
716 case 1 : /* Deepsleep on */
717 dhd_os_deepsleep_wait();
718 printk(KERN_INFO "[WIFI] Deep Sleep ON\n");
722 bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
723 dhd_wl_ioctl_cmd(dhdpub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
725 /* Enable Deepsleep*/
727 bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
728 dhd_wl_ioctl_cmd(dhdpub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
731 case 0: /* Deepsleep Off */
732 printk(KERN_INFO "[WIFI] Deep Sleep OFF\n");
733 dhd_os_deepsleep_block();
734 /* Disable Deepsleep */
735 for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) {
737 bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
738 /* Waiting to settle down after resume. */
740 dhd_wl_ioctl_cmd(dhdpub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
741 memset(iovbuf,0,sizeof(iovbuf));
742 strcpy(iovbuf, "deepsleep");
743 ret = dhd_wl_ioctl_cmd(dhdpub, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
745 DHD_ERROR(("the error of dhd deepsleep status ret value : %d\n",ret));
747 int status = *(int *)iovbuf;
749 DHD_ERROR(("deepsleep mode is 0, ok , count : %d\n",cnt));
757 memset(iovbuf,0,sizeof(iovbuf));
758 bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
759 dhd_wl_ioctl_cmd(dhdpub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
760 dhd_os_deepsleep_unblock();
764 printk("Faulty Input Arg to %s",__FUNCTION__);
769 #endif /* ENABLE_DEEP_SLEEP */
772 dhd_prot_init(dhd_pub_t *dhd)
775 wlc_rev_info_t revinfo;
777 #ifdef ENABLE_DEEP_SLEEP
781 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
783 /* Get the device MAC address */
784 strcpy(buf, "cur_etheraddr");
785 ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0);
788 memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
790 /* Get the device rev info */
791 memset(&revinfo, 0, sizeof(revinfo));
792 ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
797 ret = dhd_preinit_ioctls(dhd);
799 /* Always assumes wl for now */
809 dhd_prot_stop(dhd_pub_t *dhd)
811 /* Nothing to do for CDC */