mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 22:52:35 +02:00
net: wireless: bcmdhd: Update to version 5.90.125.78
- Add BT-Coex support to cfg80211 - Add private event logic to cfg80211 when FW hangs - Reduce passive dwell time to 130 ms - Fix proptx initialize fail issue - Implement codes for WPS2.0 using cfg80211 - Clean any left virtual interfaces in primary dhd_stop context - Skip waiting for rtnl_lock in cfg80211 callback if already taken - Skip writing to file FW trap info Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
parent
95cf7a199c
commit
4bc71443e4
|
|
@ -202,7 +202,7 @@ typedef struct dhd_pub {
|
|||
void* wlfc_state;
|
||||
#endif
|
||||
bool dongle_isolation;
|
||||
|
||||
int hang_was_sent;
|
||||
#ifdef WLMEDIA_HTSF
|
||||
uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
|
||||
#endif
|
||||
|
|
@ -389,7 +389,7 @@ extern void dhd_os_sdlock_rxq(dhd_pub_t * pub);
|
|||
extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
|
||||
extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
|
||||
extern void dhd_customer_gpio_wlan_ctrl(int onoff);
|
||||
extern int dhd_custom_get_mac_address(unsigned char *buf);
|
||||
extern int dhd_custom_get_mac_address(unsigned char *buf);
|
||||
extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
|
||||
extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
|
||||
extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@
|
|||
* round off at the end of buffer
|
||||
*/
|
||||
|
||||
#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */
|
||||
|
||||
#ifdef PROP_TXSTATUS
|
||||
typedef struct dhd_wlfc_commit_info {
|
||||
uint8 needs_hdr;
|
||||
uint8 ac_fifo_credit_spent;
|
||||
ewlfc_packet_state_t pkt_type;
|
||||
wlfc_mac_descriptor_t* mac_entry;
|
||||
void* p;
|
||||
} dhd_wlfc_commit_info_t;
|
||||
#endif /* PROP_TXSTATUS */
|
||||
typedef struct dhd_prot {
|
||||
uint16 reqid;
|
||||
uint8 pending;
|
||||
|
|
@ -152,7 +163,8 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uin
|
|||
memcpy(prot->buf, buf, len);
|
||||
|
||||
if ((ret = dhdcdc_msg(dhd)) < 0) {
|
||||
DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
|
||||
if (!dhd->hang_was_sent)
|
||||
DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -206,6 +218,17 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8
|
|||
|
||||
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
|
||||
DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
|
||||
if (dhd->busstate == DHD_BUS_DOWN) {
|
||||
DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* don't talk to the dongle if fw is about to be reloaded */
|
||||
if (dhd->hang_was_sent) {
|
||||
DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
|
||||
__FUNCTION__));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memset(msg, 0, sizeof(cdc_ioctl_t));
|
||||
|
||||
|
|
@ -629,8 +652,8 @@ dhd_wlfc_hanger_get_free_slot(void* hanger)
|
|||
if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE)
|
||||
return (uint16)i;
|
||||
}
|
||||
h->failed_slotfind++;
|
||||
}
|
||||
h->failed_slotfind++;
|
||||
return WLFC_HANGER_MAXITEMS;
|
||||
}
|
||||
|
||||
|
|
@ -1286,6 +1309,30 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t*
|
|||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map, int borrower_ac)
|
||||
{
|
||||
int lender_ac;
|
||||
int rc = BCME_ERROR;
|
||||
|
||||
if (ctx == NULL || available_credit_map == 0) {
|
||||
WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__));
|
||||
return BCME_BADARG;
|
||||
}
|
||||
|
||||
/* Borrow from lowest priority available AC (including BC/MC credits) */
|
||||
for (lender_ac = 0; lender_ac <= AC_COUNT; lender_ac++) {
|
||||
if ((available_credit_map && (1 << lender_ac)) &&
|
||||
(ctx->FIFO_credit[lender_ac] > 0)) {
|
||||
ctx->credits_borrowed[borrower_ac][lender_ac]++;
|
||||
ctx->FIFO_credit[lender_ac]--;
|
||||
rc = BCME_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
int
|
||||
dhd_wlfc_interface_entry_update(void* state,
|
||||
ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea)
|
||||
|
|
@ -1313,6 +1360,7 @@ dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits)
|
|||
/* credit for bc/mc packets */
|
||||
ctx->FIFO_credit[4] = credits[4];
|
||||
/* credit for ATIM FIFO is not used yet. */
|
||||
ctx->FIFO_credit[5] = 0;
|
||||
return BCME_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1344,18 +1392,69 @@ dhd_wlfc_enque_sendq(void* state, int prec, void* p)
|
|||
return BCME_OK;
|
||||
}
|
||||
|
||||
int
|
||||
_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac,
|
||||
dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx)
|
||||
{
|
||||
uint32 hslot;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
if ac_fifo_credit_spent = 0
|
||||
|
||||
This packet will not count against the FIFO credit.
|
||||
To ensure the txstatus corresponding to this packet
|
||||
does not provide an implied credit (default behavior)
|
||||
mark the packet accordingly.
|
||||
|
||||
if ac_fifo_credit_spent = 1
|
||||
|
||||
This is a normal packet and it counts against the FIFO
|
||||
credit count.
|
||||
*/
|
||||
DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent);
|
||||
rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p,
|
||||
commit_info->needs_hdr, &hslot);
|
||||
|
||||
if (rc == BCME_OK)
|
||||
rc = fcommit(commit_ctx, commit_info->p);
|
||||
else
|
||||
ctx->stats.generic_error++;
|
||||
|
||||
if (rc == BCME_OK) {
|
||||
ctx->stats.pkt2bus++;
|
||||
if (commit_info->ac_fifo_credit_spent) {
|
||||
ctx->stats.sendq_pkts[ac]++;
|
||||
WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
bus commit has failed, rollback.
|
||||
- remove wl-header for a delayed packet
|
||||
- save wl-header header for suppressed packets
|
||||
*/
|
||||
rc = _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p,
|
||||
(commit_info->pkt_type), hslot);
|
||||
if (rc != BCME_OK)
|
||||
ctx->stats.rollback_failed++;
|
||||
|
||||
rc = BCME_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
int
|
||||
dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx)
|
||||
{
|
||||
int ac;
|
||||
int credit;
|
||||
uint8 ac_fifo_credit_spent;
|
||||
uint8 needs_hdr;
|
||||
uint32 hslot;
|
||||
void* p;
|
||||
int rc;
|
||||
dhd_wlfc_commit_info_t commit_info;
|
||||
athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
|
||||
wlfc_mac_descriptor_t* mac_entry;
|
||||
int credit_count = 0;
|
||||
int bus_retry_count = 0;
|
||||
uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */
|
||||
|
||||
if ((state == NULL) ||
|
||||
(fcommit == NULL)) {
|
||||
|
|
@ -1363,8 +1462,12 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx)
|
|||
return BCME_BADARG;
|
||||
}
|
||||
|
||||
/*
|
||||
memset(&commit_info, 0, sizeof(commit_info));
|
||||
|
||||
/*
|
||||
Commit packets for regular AC traffic. Higher priority first.
|
||||
First, use up FIFO credits available to each AC. Based on distribution
|
||||
and credits left, borrow from other ACs as applicable
|
||||
|
||||
-NOTE:
|
||||
If the bus between the host and firmware is overwhelmed by the
|
||||
|
|
@ -1373,96 +1476,189 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx)
|
|||
have to employ weighted round-robin or ucode scheme to avoid
|
||||
low priority packet starvation.
|
||||
*/
|
||||
|
||||
for (ac = AC_COUNT; ac >= 0; ac--) {
|
||||
|
||||
int initial_credit_count = ctx->FIFO_credit[ac];
|
||||
|
||||
for (credit = 0; credit < ctx->FIFO_credit[ac];) {
|
||||
p = _dhd_wlfc_deque_delayedq(ctx, ac, &ac_fifo_credit_spent, &needs_hdr,
|
||||
&mac_entry);
|
||||
if (p == NULL)
|
||||
commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
|
||||
&(commit_info.ac_fifo_credit_spent),
|
||||
&(commit_info.needs_hdr),
|
||||
&(commit_info.mac_entry));
|
||||
|
||||
if (commit_info.p == NULL)
|
||||
break;
|
||||
/*
|
||||
if ac_fifo_credit_spent = 0
|
||||
|
||||
This packet will not count against the FIFO credit.
|
||||
To ensure the txstatus corresponding to this packet
|
||||
does not provide an implied credit (default behavior)
|
||||
mark the packet accordingly.
|
||||
commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
|
||||
eWLFC_PKTTYPE_SUPPRESSED;
|
||||
|
||||
if ac_fifo_credit_spent = 1
|
||||
|
||||
This is a normal packet and it counts against the FIFO
|
||||
credit count.
|
||||
*/
|
||||
DHD_PKTTAG_SETCREDITCHECK(PKTTAG(p), ac_fifo_credit_spent);
|
||||
rc = _dhd_wlfc_pretx_pktprocess(ctx, mac_entry, p, needs_hdr, &hslot);
|
||||
|
||||
if (rc == BCME_OK)
|
||||
rc = fcommit(commit_ctx, p);
|
||||
else
|
||||
ctx->stats.generic_error++;
|
||||
rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
|
||||
fcommit, commit_ctx);
|
||||
|
||||
/* Bus commits may fail (e.g. flow control); abort after retries */
|
||||
if (rc == BCME_OK) {
|
||||
ctx->stats.pkt2bus++;
|
||||
if (ac_fifo_credit_spent) {
|
||||
ctx->stats.sendq_pkts[ac]++;
|
||||
WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac);
|
||||
/*
|
||||
1 FIFO credit has been spent by sending this packet
|
||||
to the device.
|
||||
*/
|
||||
if (commit_info.ac_fifo_credit_spent) {
|
||||
credit++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* bus commit has failed, rollback. */
|
||||
rc = _dhd_wlfc_rollback_packet_toq(ctx,
|
||||
p,
|
||||
/*
|
||||
- remove wl-header for a delayed packet
|
||||
- save wl-header header for suppressed packets
|
||||
*/
|
||||
(needs_hdr ? eWLFC_PKTTYPE_DELAYED :
|
||||
eWLFC_PKTTYPE_SUPPRESSED),
|
||||
hslot);
|
||||
if (rc != BCME_OK)
|
||||
ctx->stats.rollback_failed++;
|
||||
bus_retry_count++;
|
||||
if (bus_retry_count >= BUS_RETRIES) {
|
||||
DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n"));
|
||||
ctx->FIFO_credit[ac] -= credit;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->FIFO_credit[ac] -= credit;
|
||||
/* packets from SENDQ are fresh and they'd need header */
|
||||
needs_hdr = 1;
|
||||
|
||||
/* packets from SENDQ are fresh and they'd need header and have no MAC entry */
|
||||
commit_info.needs_hdr = 1;
|
||||
commit_info.mac_entry = NULL;
|
||||
commit_info.pkt_type = eWLFC_PKTTYPE_NEW;
|
||||
|
||||
for (credit = 0; credit < ctx->FIFO_credit[ac];) {
|
||||
p = _dhd_wlfc_deque_sendq(ctx, ac, &ac_fifo_credit_spent);
|
||||
if (p == NULL)
|
||||
commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac,
|
||||
&(commit_info.ac_fifo_credit_spent));
|
||||
if (commit_info.p == NULL)
|
||||
break;
|
||||
|
||||
DHD_PKTTAG_SETCREDITCHECK(PKTTAG(p), ac_fifo_credit_spent);
|
||||
rc = _dhd_wlfc_pretx_pktprocess(ctx, NULL, p, needs_hdr, &hslot);
|
||||
if (rc == BCME_OK)
|
||||
rc = fcommit(commit_ctx, p);
|
||||
else
|
||||
ctx->stats.generic_error++;
|
||||
rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
|
||||
fcommit, commit_ctx);
|
||||
|
||||
/* Bus commits may fail (e.g. flow control); abort after retries */
|
||||
if (rc == BCME_OK) {
|
||||
ctx->stats.pkt2bus++;
|
||||
if (ac_fifo_credit_spent) {
|
||||
WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac);
|
||||
ctx->stats.sendq_pkts[ac]++;
|
||||
if (commit_info.ac_fifo_credit_spent) {
|
||||
credit++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* bus commit has failed, rollback. */
|
||||
rc = _dhd_wlfc_rollback_packet_toq(ctx,
|
||||
p,
|
||||
/* remove wl-header while rolling back */
|
||||
eWLFC_PKTTYPE_NEW,
|
||||
hslot);
|
||||
if (rc != BCME_OK)
|
||||
ctx->stats.rollback_failed++;
|
||||
bus_retry_count++;
|
||||
if (bus_retry_count >= BUS_RETRIES) {
|
||||
DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n"));
|
||||
ctx->FIFO_credit[ac] -= credit;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->FIFO_credit[ac] -= credit;
|
||||
|
||||
/* If no credits were used, the queue is idle and can be re-used
|
||||
Note that resv credits cannot be borrowed
|
||||
*/
|
||||
if (initial_credit_count == ctx->FIFO_credit[ac]) {
|
||||
ac_available |= (1 << ac);
|
||||
credit_count += ctx->FIFO_credit[ac];
|
||||
}
|
||||
}
|
||||
|
||||
/* We borrow only for AC_BE and only if no other traffic seen for DEFER_PERIOD
|
||||
|
||||
Note that (ac_available & WLFC_AC_BE_TRAFFIC_ONLY) is done to:
|
||||
a) ignore BC/MC for deferring borrow
|
||||
b) ignore AC_BE being available along with other ACs
|
||||
(this should happen only for pure BC/MC traffic)
|
||||
|
||||
i.e. AC_VI, AC_VO, AC_BK all MUST be available (i.e. no traffic) and
|
||||
we do not care if AC_BE and BC/MC are available or not
|
||||
*/
|
||||
if ((ac_available & WLFC_AC_BE_TRAFFIC_ONLY) == WLFC_AC_BE_TRAFFIC_ONLY) {
|
||||
|
||||
if (ctx->allow_credit_borrow) {
|
||||
ac = 1; /* Set ac to AC_BE and borrow credits */
|
||||
}
|
||||
else {
|
||||
int delta;
|
||||
int curr_t = OSL_SYSUPTIME();
|
||||
|
||||
if (curr_t > ctx->borrow_defer_timestamp)
|
||||
delta = curr_t - ctx->borrow_defer_timestamp;
|
||||
else
|
||||
delta = 0xffffffff + curr_t - ctx->borrow_defer_timestamp;
|
||||
|
||||
if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) {
|
||||
/* Reset borrow but defer to next iteration (defensive borrowing) */
|
||||
ctx->allow_credit_borrow = TRUE;
|
||||
ctx->borrow_defer_timestamp = 0;
|
||||
}
|
||||
return BCME_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If we have multiple AC traffic, turn off borrowing, mark time and bail out */
|
||||
ctx->allow_credit_borrow = FALSE;
|
||||
ctx->borrow_defer_timestamp = OSL_SYSUPTIME();
|
||||
return BCME_OK;
|
||||
}
|
||||
|
||||
/* At this point, borrow all credits only for "ac" (which should be set above to AC_BE)
|
||||
Generically use "ac" only in case we extend to all ACs in future
|
||||
*/
|
||||
for (; (credit_count > 0);) {
|
||||
|
||||
commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
|
||||
&(commit_info.ac_fifo_credit_spent),
|
||||
&(commit_info.needs_hdr),
|
||||
&(commit_info.mac_entry));
|
||||
if (commit_info.p == NULL)
|
||||
break;
|
||||
|
||||
commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
|
||||
eWLFC_PKTTYPE_SUPPRESSED;
|
||||
|
||||
rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
|
||||
fcommit, commit_ctx);
|
||||
|
||||
/* Bus commits may fail (e.g. flow control); abort after retries */
|
||||
if (rc == BCME_OK) {
|
||||
if (commit_info.ac_fifo_credit_spent) {
|
||||
(void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac);
|
||||
credit_count--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bus_retry_count++;
|
||||
if (bus_retry_count >= BUS_RETRIES) {
|
||||
DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n"));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* packets from SENDQ are fresh and they'd need header and have no MAC entry */
|
||||
commit_info.needs_hdr = 1;
|
||||
commit_info.mac_entry = NULL;
|
||||
commit_info.pkt_type = eWLFC_PKTTYPE_NEW;
|
||||
|
||||
for (; (credit_count > 0);) {
|
||||
|
||||
commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac,
|
||||
&(commit_info.ac_fifo_credit_spent));
|
||||
if (commit_info.p == NULL)
|
||||
break;
|
||||
|
||||
rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
|
||||
fcommit, commit_ctx);
|
||||
|
||||
/* Bus commits may fail (e.g. flow control); abort after retries */
|
||||
if (rc == BCME_OK) {
|
||||
if (commit_info.ac_fifo_credit_spent) {
|
||||
(void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac);
|
||||
credit_count--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bus_retry_count++;
|
||||
if (bus_retry_count >= BUS_RETRIES) {
|
||||
DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n"));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BCME_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1489,6 +1685,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success)
|
|||
athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)
|
||||
dhd->wlfc_state;
|
||||
void* p;
|
||||
int fifo_id;
|
||||
|
||||
if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) {
|
||||
#ifdef PROP_TXSTATUS_DEBUG
|
||||
|
|
@ -1506,11 +1703,29 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success)
|
|||
|
||||
/* indicate failure and free the packet */
|
||||
dhd_txcomplete(dhd, txp, FALSE);
|
||||
PKTFREE(wlfc->osh, txp, TRUE);
|
||||
|
||||
/* return the credit, if necessary */
|
||||
if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp)))
|
||||
wlfc->FIFO_credit[DHD_PKTTAG_FIFO(PKTTAG(txp))]++;
|
||||
if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp))) {
|
||||
int lender, credit_returned = 0; /* Note that borrower is fifo_id */
|
||||
|
||||
fifo_id = DHD_PKTTAG_FIFO(PKTTAG(txp));
|
||||
|
||||
/* Return credits to highest priority lender first */
|
||||
for (lender = AC_COUNT; lender >= 0; lender--) {
|
||||
if (wlfc->credits_borrowed[fifo_id][lender] > 0) {
|
||||
wlfc->FIFO_credit[lender]++;
|
||||
wlfc->credits_borrowed[fifo_id][lender]--;
|
||||
credit_returned = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!credit_returned) {
|
||||
wlfc->FIFO_credit[fifo_id]++;
|
||||
}
|
||||
}
|
||||
|
||||
PKTFREE(wlfc->osh, txp, TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1593,7 +1808,21 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info)
|
|||
/* pick up the implicit credit from this packet */
|
||||
if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) {
|
||||
if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) {
|
||||
wlfc->FIFO_credit[fifo_id]++;
|
||||
int lender, credit_returned = 0; /* Note that borrower is fifo_id */
|
||||
|
||||
/* Return credits to highest priority lender first */
|
||||
for (lender = AC_COUNT; lender >= 0; lender--) {
|
||||
if (wlfc->credits_borrowed[fifo_id][lender] > 0) {
|
||||
wlfc->FIFO_credit[lender]++;
|
||||
wlfc->credits_borrowed[fifo_id][lender]--;
|
||||
credit_returned = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!credit_returned) {
|
||||
wlfc->FIFO_credit[fifo_id]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1644,8 +1873,33 @@ dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits)
|
|||
#endif
|
||||
/* update FIFO credits */
|
||||
if (wlfc->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT)
|
||||
wlfc->FIFO_credit[i] += credits[i];
|
||||
{
|
||||
int lender; /* Note that borrower is i */
|
||||
|
||||
/* Return credits to highest priority lender first */
|
||||
for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) {
|
||||
if (wlfc->credits_borrowed[i][lender] > 0) {
|
||||
if (credits[i] >= wlfc->credits_borrowed[i][lender]) {
|
||||
credits[i] -= wlfc->credits_borrowed[i][lender];
|
||||
wlfc->FIFO_credit[lender] +=
|
||||
wlfc->credits_borrowed[i][lender];
|
||||
wlfc->credits_borrowed[i][lender] = 0;
|
||||
}
|
||||
else {
|
||||
wlfc->credits_borrowed[i][lender] -= credits[i];
|
||||
wlfc->FIFO_credit[lender] += credits[i];
|
||||
credits[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have more credits left over, these must belong to the AC */
|
||||
if (credits[i] > 0) {
|
||||
wlfc->FIFO_credit[i] += credits[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BCME_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1986,6 +2240,9 @@ dhd_wlfc_enable(dhd_pub_t *dhd)
|
|||
|
||||
wlfc->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT;
|
||||
|
||||
wlfc->allow_credit_borrow = TRUE;
|
||||
wlfc->borrow_defer_timestamp = 0;
|
||||
|
||||
return BCME_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2165,7 +2422,7 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf)
|
|||
dhd_wlfc_parse_header_info(dhd, pktbuf, (h->dataOffset << 2));
|
||||
((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++;
|
||||
dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata,
|
||||
dhd->bus);
|
||||
(void *)dhd->bus);
|
||||
dhd_os_wlfc_unblock(dhd);
|
||||
}
|
||||
#endif /* PROP_TXSTATUS */
|
||||
|
|
@ -2232,7 +2489,6 @@ dhd_prot_dstats(dhd_pub_t *dhd)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dhd_prot_init(dhd_pub_t *dhd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1970,7 +1970,7 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
|
|||
pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
|
||||
pfn_element.wsec = htod32(0);
|
||||
pfn_element.infra = htod32(1);
|
||||
|
||||
pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
|
||||
memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len);
|
||||
pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,11 @@ MODULE_LICENSE("GPL v2");
|
|||
|
||||
#include <dhd_bus.h>
|
||||
|
||||
#ifndef PROP_TXSTATUS
|
||||
#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen)
|
||||
#else
|
||||
#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
|
||||
const char *
|
||||
|
|
@ -218,7 +222,7 @@ typedef struct dhd_info {
|
|||
struct semaphore proto_sem;
|
||||
#ifdef PROP_TXSTATUS
|
||||
spinlock_t wlfc_spinlock;
|
||||
#endif
|
||||
#endif /* PROP_TXSTATUS */
|
||||
#ifdef WLMEDIA_HTSF
|
||||
htsf_t htsf;
|
||||
#endif
|
||||
|
|
@ -258,8 +262,6 @@ typedef struct dhd_info {
|
|||
int wakelock_counter;
|
||||
int wakelock_timeout_enable;
|
||||
|
||||
int hang_was_sent;
|
||||
|
||||
/* Thread to issue ioctl for multicast */
|
||||
bool set_macaddress;
|
||||
struct ether_addr macvalue;
|
||||
|
|
@ -498,7 +500,6 @@ static struct notifier_block dhd_sleep_pm_notifier = {
|
|||
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)
|
||||
{
|
||||
|
|
@ -976,10 +977,8 @@ dhd_op_if(dhd_if_t *ifp)
|
|||
dhd_net_attach)) {
|
||||
ifp->state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((err = dhd_net_attach(&dhd->pub, ifp->idx)) != 0) {
|
||||
DHD_ERROR(("%s: dhd_net_attach failed, err %d\n",
|
||||
__FUNCTION__, err));
|
||||
|
|
@ -1037,7 +1036,7 @@ dhd_op_if(dhd_if_t *ifp)
|
|||
ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */
|
||||
dhd_os_spin_unlock(&dhd->pub, flags);
|
||||
#endif /* SOFTAP */
|
||||
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
|
||||
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1413,6 +1412,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
pnext = PKTNEXT(dhdp->osh, pktbuf);
|
||||
PKTSETNEXT(wl->sh.osh, pktbuf, NULL);
|
||||
|
||||
|
|
@ -2078,6 +2078,14 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* send to dongle only if we are not waiting for reload already */
|
||||
if (dhd->pub.hang_was_sent) {
|
||||
DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
|
||||
__FUNCTION__));
|
||||
bcmerror = BCME_DONGLE_DOWN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check for local dhd ioctl and handle it */
|
||||
if (driver == DHD_IOCTL_MAGIC) {
|
||||
bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen);
|
||||
|
|
@ -2184,6 +2192,41 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
|
|||
return OSL_ERROR(bcmerror);
|
||||
}
|
||||
|
||||
static int
|
||||
dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
|
||||
{
|
||||
int i = 1; /* Leave ifidx 0 [Primary Interface] */
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
int rollback_lock = FALSE;
|
||||
#endif
|
||||
|
||||
DHD_TRACE(("%s: Enter \n", __func__));
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
/* release lock for unregister_netdev */
|
||||
if (rtnl_is_locked()) {
|
||||
rtnl_unlock();
|
||||
rollback_lock = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 1; i < DHD_MAX_IFS; i++) {
|
||||
if (dhd->iflist[i]) {
|
||||
DHD_TRACE(("Deleting IF: %d \n", i));
|
||||
dhd->iflist[i]->state = WLC_E_IF_DEL;
|
||||
dhd->iflist[i]->idx = i;
|
||||
dhd_op_if(dhd->iflist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
if (rollback_lock)
|
||||
rtnl_lock();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dhd_stop(struct net_device *net)
|
||||
{
|
||||
|
|
@ -2197,8 +2240,17 @@ dhd_stop(struct net_device *net)
|
|||
ifidx = dhd_net2idx(dhd, net);
|
||||
|
||||
#ifdef WL_CFG80211
|
||||
if (ifidx == 0)
|
||||
if (ifidx == 0) {
|
||||
wl_cfg80211_down();
|
||||
|
||||
/** For CFG80211: Clean up all the left over virtual interfaces
|
||||
* when the primary Interface is brought down. [ifconfig wlan0 down]
|
||||
*/
|
||||
if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) &&
|
||||
(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
|
||||
dhd_cleanup_virt_ifaces(dhd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PROP_TXSTATUS
|
||||
|
|
@ -2238,6 +2290,7 @@ dhd_open(struct net_device *net)
|
|||
strcpy(fw_path, firmware_path);
|
||||
firmware_path[0] = '\0';
|
||||
}
|
||||
|
||||
#if !defined(WL_CFG80211)
|
||||
/** Force start if ifconfig_up gets called before START command
|
||||
* We keep WEXT's wl_control_wl_start to provide backward compatibility
|
||||
|
|
@ -2262,7 +2315,9 @@ dhd_open(struct net_device *net)
|
|||
if (ifidx == 0) {
|
||||
atomic_set(&dhd->pend_8021x_cnt, 0);
|
||||
#if defined(WL_CFG80211)
|
||||
DHD_ERROR(("\n%s\n", dhd_version));
|
||||
wl_android_wifi_on(net);
|
||||
dhd->pub.hang_was_sent = 0;
|
||||
#endif
|
||||
|
||||
if (dhd->pub.busstate != DHD_BUS_DATA) {
|
||||
|
|
@ -2610,7 +2665,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
|
||||
ASSERT(dhd);
|
||||
|
||||
DHD_TRACE(("%s: \n", __FUNCTION__));
|
||||
DHD_TRACE(("Enter %s:\n", __FUNCTION__));
|
||||
|
||||
dhd_os_sdlock(dhdp);
|
||||
|
||||
|
|
@ -2706,6 +2761,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
|||
#endif
|
||||
int scan_assoc_time = 40;
|
||||
int scan_unassoc_time = 40;
|
||||
int scan_passive_time = 130;
|
||||
char buf[WLC_IOCTL_SMLEN];
|
||||
char *ptr;
|
||||
uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
|
||||
|
|
@ -2946,14 +3002,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
|||
sizeof(scan_assoc_time), TRUE, 0);
|
||||
dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
|
||||
sizeof(scan_unassoc_time), TRUE, 0);
|
||||
dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time,
|
||||
sizeof(scan_passive_time), TRUE, 0);
|
||||
|
||||
#ifdef ARP_OFFLOAD_SUPPORT
|
||||
/* Set and enable ARP offload feature for STA only */
|
||||
if (arpoe
|
||||
#if defined(SOFTAP)
|
||||
&& (!ap_fw_loaded)
|
||||
#endif /* (OEM_ANDROID) && defined(SOFTAP) */
|
||||
) {
|
||||
if (arpoe && !ap_fw_loaded) {
|
||||
#else
|
||||
if (arpoe) {
|
||||
#endif
|
||||
dhd_arp_offload_set(dhd, dhd_arp_mode);
|
||||
dhd_arp_offload_enable(dhd, arpoe);
|
||||
} else {
|
||||
|
|
@ -2970,7 +3028,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
|||
dhd->pktfilter[1] = NULL;
|
||||
dhd->pktfilter[2] = NULL;
|
||||
dhd->pktfilter[3] = NULL;
|
||||
|
||||
#if defined(SOFTAP)
|
||||
if (ap_fw_loaded) {
|
||||
int i;
|
||||
|
|
@ -2979,13 +3036,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
|||
0, dhd_master_mode);
|
||||
}
|
||||
}
|
||||
#endif /* (SOFTAP) */
|
||||
#endif /* defined(SOFTAP) */
|
||||
#endif /* PKT_FILTER_SUPPORT */
|
||||
|
||||
/* Force STA UP */
|
||||
ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0)
|
||||
DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret));
|
||||
|
||||
|
||||
done:
|
||||
|
|
@ -3065,7 +3121,8 @@ int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx)
|
|||
|
||||
#ifdef ARP_OFFLOAD_SUPPORT
|
||||
/* add or remove AOE host ip(s) (up to 8 IPs on the interface) */
|
||||
void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
|
||||
void
|
||||
aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
|
||||
{
|
||||
u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */
|
||||
int i;
|
||||
|
|
@ -3088,14 +3145,11 @@ void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
|
|||
}
|
||||
|
||||
for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
|
||||
|
||||
if (add && (ipv4_buf[i] == 0)) {
|
||||
|
||||
ipv4_buf[i] = ipa;
|
||||
ipv4_buf[i] = ipa;
|
||||
add = FALSE; /* added ipa to local table */
|
||||
DHD_ARPOE(("%s: Saved new IP in temp arp_hostip[%d]\n",
|
||||
__FUNCTION__, i));
|
||||
|
||||
} else if (ipv4_buf[i] == ipa) {
|
||||
ipv4_buf[i] = 0;
|
||||
DHD_ARPOE(("%s: removed IP:%x from temp table %d\n",
|
||||
|
|
@ -3160,14 +3214,14 @@ static int dhd_device_event(struct notifier_block *this,
|
|||
#ifdef AOE_IP_ALIAS_SUPPORT
|
||||
if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) {
|
||||
DHD_ARPOE(("%s: primary interface is down, AOE clr all\n",
|
||||
__FUNCTION__));
|
||||
__FUNCTION__));
|
||||
dhd_aoe_hostip_clr(&dhd->pub);
|
||||
dhd_aoe_arp_clr(&dhd->pub);
|
||||
} else
|
||||
aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE);
|
||||
#else
|
||||
dhd_aoe_hostip_clr(&dhd->pub);
|
||||
dhd_aoe_arp_clr(&dhd->pub);
|
||||
dhd_aoe_hostip_clr(&dhd->pub);
|
||||
dhd_aoe_arp_clr(&dhd->pub);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
|
@ -3221,9 +3275,9 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
|
|||
net->netdev_ops = &dhd_ops_pri;
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* We have to use the primary MAC for virtual interfaces
|
||||
*/
|
||||
/*
|
||||
* We have to use the primary MAC for virtual interfaces
|
||||
*/
|
||||
memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
|
||||
/*
|
||||
* Android sets the locally administered bit to indicate that this is a
|
||||
|
|
@ -3362,15 +3416,10 @@ void dhd_detach(dhd_pub_t *dhdp)
|
|||
|
||||
/* delete all interfaces, start with virtual */
|
||||
if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) {
|
||||
int i = 1;
|
||||
dhd_if_t *ifp;
|
||||
|
||||
for (i = 1; i < DHD_MAX_IFS; i++)
|
||||
if (dhd->iflist[i]) {
|
||||
dhd->iflist[i]->state = WLC_E_IF_DEL;
|
||||
dhd->iflist[i]->idx = i;
|
||||
dhd_op_if(dhd->iflist[i]);
|
||||
}
|
||||
/* Cleanup all virtual Interfaces */
|
||||
dhd_cleanup_virt_ifaces(dhd);
|
||||
|
||||
/* delete primary interface 0 */
|
||||
ifp = dhd->iflist[0];
|
||||
|
|
@ -3428,8 +3477,8 @@ void dhd_detach(dhd_pub_t *dhdp)
|
|||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
|
||||
unregister_pm_notifier(&dhd_sleep_pm_notifier);
|
||||
#endif
|
||||
unregister_pm_notifier(&dhd_sleep_pm_notifier);
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
|
||||
|
||||
if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) {
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
|
|
@ -3437,7 +3486,6 @@ void dhd_detach(dhd_pub_t *dhdp)
|
|||
wake_lock_destroy(&dhd->wl_rxwake);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3509,7 +3557,6 @@ dhd_module_init(void)
|
|||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
|
||||
error = dhd_bus_register();
|
||||
|
||||
|
||||
if (!error)
|
||||
printf("\n%s\n", dhd_version);
|
||||
else {
|
||||
|
|
@ -4156,10 +4203,13 @@ int net_os_send_hang_message(struct net_device *dev)
|
|||
int ret = 0;
|
||||
|
||||
if (dhd) {
|
||||
if (!dhd->hang_was_sent) {
|
||||
dhd->hang_was_sent = 1;
|
||||
if (!dhd->pub.hang_was_sent) {
|
||||
dhd->pub.hang_was_sent = 1;
|
||||
#if defined(CONFIG_WIRELESS_EXT)
|
||||
ret = wl_iw_send_priv_event(dev, "HANG");
|
||||
#endif
|
||||
#if defined(WL_CFG80211)
|
||||
ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <typedefs.h>
|
||||
#include <linuxver.h>
|
||||
|
||||
int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success);
|
|||
|
||||
#ifdef DHD_DEBUG
|
||||
/* Device console log buffer state */
|
||||
#define CONSOLE_LINE_MAX 192
|
||||
#define CONSOLE_BUFFER_MAX 2024
|
||||
typedef struct dhd_console {
|
||||
uint count; /* Poll interval msec counter */
|
||||
uint log_addr; /* Log struct address (fixed) */
|
||||
|
|
@ -429,7 +431,7 @@ do { \
|
|||
* Mode 0: Dongle writes the software host mailbox and host is interrupted.
|
||||
* Mode 1: (sdiod core rev >= 4)
|
||||
* Device sets a new bit in the intstatus whenever there is a packet
|
||||
* available in fifo. Host can't clear this specific status bit until all the
|
||||
* available in fifo. Host can't clear this specific status bit until all the
|
||||
* packets are read from the FIFO. No need to ack dongle intstatus.
|
||||
* Mode 2: (sdiod core rev >= 4)
|
||||
* Device sets a bit in the intstatus, and host acks this by writing
|
||||
|
|
@ -463,9 +465,9 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint8 count);
|
|||
|
||||
#ifdef DHD_DEBUG
|
||||
static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size);
|
||||
static int dhdsdio_mem_dump(dhd_bus_t *bus);
|
||||
static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
|
||||
#endif /* DHD_DEBUG */
|
||||
|
||||
static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
|
||||
|
||||
static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
|
||||
|
|
@ -1374,7 +1376,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
|
|||
DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
|
||||
ret = 0;
|
||||
} else {
|
||||
DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
|
||||
if (!bus->dhd->hang_was_sent)
|
||||
DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
|
||||
ret = -1;
|
||||
bus->ctrl_frame_stat = FALSE;
|
||||
goto done;
|
||||
|
|
@ -1528,9 +1531,9 @@ enum {
|
|||
IOV_SD1IDLE,
|
||||
IOV_SLEEP,
|
||||
IOV_DONGLEISOLATION,
|
||||
IOV_VARS
|
||||
IOV_VARS,
|
||||
#ifdef SOFTAP
|
||||
, IOV_FWPATH
|
||||
IOV_FWPATH
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -1836,6 +1839,7 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
|
|||
|
||||
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
|
||||
return BCME_OK;
|
||||
|
||||
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
|
||||
DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
|
||||
"is different than sdpcm_shared version %d in dongle\n",
|
||||
|
|
@ -1847,7 +1851,6 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
|
|||
return BCME_OK;
|
||||
}
|
||||
|
||||
#define CONSOLE_LINE_MAX 192
|
||||
|
||||
static int
|
||||
dhdsdio_readconsole(dhd_bus_t *bus)
|
||||
|
|
@ -1925,11 +1928,16 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
|
|||
int bcmerror = 0;
|
||||
uint msize = 512;
|
||||
char *mbuffer = NULL;
|
||||
char *console_buffer = NULL;
|
||||
uint maxstrlen = 256;
|
||||
char *str = NULL;
|
||||
trap_t tr;
|
||||
sdpcm_shared_t sdpcm_shared;
|
||||
struct bcmstrbuf strbuf;
|
||||
uint32 console_ptr, console_size, console_index;
|
||||
uint8 line[CONSOLE_LINE_MAX], ch;
|
||||
uint32 n, i, addr;
|
||||
int rv;
|
||||
|
||||
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
|
||||
|
||||
|
|
@ -2013,86 +2021,76 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
|
|||
bcm_bprintf(&strbuf,
|
||||
"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
|
||||
"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
|
||||
"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
|
||||
"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
|
||||
ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
|
||||
ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
|
||||
ltoh32(sdpcm_shared.trap_addr),
|
||||
ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3),
|
||||
ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
|
||||
|
||||
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log);
|
||||
if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
|
||||
goto printbuf;
|
||||
|
||||
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.buf_size);
|
||||
if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_size, sizeof(console_size))) < 0)
|
||||
goto printbuf;
|
||||
|
||||
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.idx);
|
||||
if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_index, sizeof(console_index))) < 0)
|
||||
goto printbuf;
|
||||
|
||||
console_ptr = ltoh32(console_ptr);
|
||||
console_size = ltoh32(console_size);
|
||||
console_index = ltoh32(console_index);
|
||||
|
||||
if (console_size > CONSOLE_BUFFER_MAX || !(console_buffer = MALLOC(bus->dhd->osh, console_size)))
|
||||
goto printbuf;
|
||||
|
||||
if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr, (uint8 *)console_buffer, console_size)) < 0)
|
||||
goto printbuf;
|
||||
|
||||
for ( i = 0, n = 0; i < console_size; i += n + 1 ) {
|
||||
for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
|
||||
ch = console_buffer[ (console_index + i + n) % console_size];
|
||||
if (ch == '\n')
|
||||
break;
|
||||
line[n] = ch;
|
||||
}
|
||||
|
||||
|
||||
if (n > 0) {
|
||||
if (line[n - 1] == '\r')
|
||||
n--;
|
||||
line[n] = 0;
|
||||
/* Don't use DHD_ERROR macro since we print a lot of information quickly */
|
||||
/* The macro will truncate a lot of the printfs */
|
||||
|
||||
if (dhd_msg_level & DHD_ERROR_VAL)
|
||||
printf("CONSOLE: %s\n", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printbuf:
|
||||
if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
|
||||
DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
|
||||
}
|
||||
|
||||
#ifdef DHD_DEBUG
|
||||
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
|
||||
/* Mem dump to a file on device */
|
||||
dhdsdio_mem_dump(bus);
|
||||
}
|
||||
#endif /* DHD_DEBUG */
|
||||
|
||||
done:
|
||||
if (mbuffer)
|
||||
MFREE(bus->dhd->osh, mbuffer, msize);
|
||||
if (str)
|
||||
MFREE(bus->dhd->osh, str, maxstrlen);
|
||||
if (console_buffer)
|
||||
MFREE(bus->dhd->osh, console_buffer, console_size);
|
||||
|
||||
return bcmerror;
|
||||
}
|
||||
#endif /* #ifdef DHD_DEBUG */
|
||||
|
||||
static int
|
||||
dhdsdio_mem_dump(dhd_bus_t *bus)
|
||||
{
|
||||
int ret = 0;
|
||||
int size; /* Full mem size */
|
||||
int start = 0; /* Start address */
|
||||
int read_size = 0; /* Read size of each iteration */
|
||||
uint8 *buf = NULL, *databuf = NULL;
|
||||
|
||||
/* Get full mem size */
|
||||
size = bus->ramsize;
|
||||
buf = MALLOC(bus->dhd->osh, size);
|
||||
if (!buf) {
|
||||
printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read mem content */
|
||||
printf("Dump dongle memory");
|
||||
databuf = buf;
|
||||
while (size)
|
||||
{
|
||||
read_size = MIN(MEMBLOCK, size);
|
||||
if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
|
||||
{
|
||||
printf("%s: Error membytes %d\n", __FUNCTION__, ret);
|
||||
if (buf) {
|
||||
MFREE(bus->dhd->osh, buf, size);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
printf(".");
|
||||
|
||||
/* Decrement size and increment start address */
|
||||
size -= read_size;
|
||||
start += read_size;
|
||||
databuf += read_size;
|
||||
}
|
||||
printf("Done\n");
|
||||
|
||||
/* free buf before return !!! */
|
||||
if (write_to_file(bus->dhd, buf, bus->ramsize))
|
||||
{
|
||||
printf("%s: Error writing to files\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* buf free handled in write_to_file, not here */
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(DHD_DEBUG) */
|
||||
|
||||
int
|
||||
dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
|
||||
|
|
@ -3040,6 +3038,7 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
|
|||
dhd_os_sdunlock(bus->dhd);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
|
||||
{
|
||||
|
|
@ -4352,6 +4351,13 @@ dhdsdio_hostmail(dhd_bus_t *bus)
|
|||
bus->flowcontrol = fcbits;
|
||||
}
|
||||
|
||||
#ifdef DHD_DEBUG
|
||||
/* At least print a message if FW halted */
|
||||
if (hmb_data & HMB_DATA_FWHALT) {
|
||||
DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED\n"));
|
||||
dhdsdio_checkdied(bus, NULL, 0);
|
||||
}
|
||||
#endif /* DHD_DEBUG */
|
||||
|
||||
/* Shouldn't be any others */
|
||||
if (hmb_data & ~(HMB_DATA_DEVREADY |
|
||||
|
|
@ -5176,6 +5182,9 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
|
|||
#ifdef GET_CUSTOM_MAC_ENABLE
|
||||
struct ether_addr ea_addr;
|
||||
#endif /* GET_CUSTOM_MAC_ENABLE */
|
||||
#ifdef PROP_TXSTATUS
|
||||
uint up = 0;
|
||||
#endif
|
||||
|
||||
/* Init global variables at run-time, not as part of the declaration.
|
||||
* This is required to support init/de-init of the driver. Initialization
|
||||
|
|
@ -5342,6 +5351,10 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef PROP_TXSTATUS
|
||||
if (dhd_download_fw_on_driverload)
|
||||
dhd_wl_ioctl_cmd(bus->dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
|
||||
#endif
|
||||
return bus;
|
||||
|
||||
fail:
|
||||
|
|
@ -5916,7 +5929,7 @@ dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
|
|||
return bcmerror;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
EXAMPLE: nvram_array
|
||||
nvram_arry format:
|
||||
name=value
|
||||
|
|
@ -6190,16 +6203,16 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
|
|||
dhd_enable_oob_intr(bus, TRUE);
|
||||
#endif /* defined(OOB_INTR_ONLY) */
|
||||
|
||||
bus->dhd->dongle_reset = FALSE;
|
||||
bus->dhd->up = TRUE;
|
||||
bus->dhd->dongle_reset = FALSE;
|
||||
bus->dhd->up = TRUE;
|
||||
|
||||
#if !defined(IGNORE_ETH0_DOWN)
|
||||
/* Restore flow control */
|
||||
dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
|
||||
/* Restore flow control */
|
||||
dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
|
||||
#endif
|
||||
dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
|
||||
dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
|
||||
|
||||
DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
|
||||
DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
|
||||
} else {
|
||||
dhd_bus_stop(bus, FALSE);
|
||||
dhdsdio_release_dongle(bus, bus->dhd->osh,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,14 @@ typedef struct athost_wl_stat_counters {
|
|||
#define WLFC_FCMODE_IMPLIED_CREDIT 1
|
||||
#define WLFC_FCMODE_EXPLICIT_CREDIT 2
|
||||
|
||||
#define WLFC_BORROW_DEFER_PERIOD_MS 100
|
||||
|
||||
/* Mask to represent available ACs (note: BC/MC is ignored */
|
||||
#define WLFC_AC_MASK 0xF
|
||||
|
||||
/* Mask to check for only on-going AC_BE traffic */
|
||||
#define WLFC_AC_BE_TRAFFIC_ONLY 0xD
|
||||
|
||||
typedef struct athost_wl_status_info {
|
||||
uint8 last_seqid_to_wlc;
|
||||
|
||||
|
|
@ -213,7 +221,11 @@ typedef struct athost_wl_status_info {
|
|||
athost_wl_stat_counters_t stats;
|
||||
|
||||
/* the additional ones are for bc/mc and ATIM FIFO */
|
||||
int FIFO_credit[AC_COUNT + 2];
|
||||
int FIFO_credit[AC_COUNT + 2];
|
||||
|
||||
/* Credit borrow counts for each FIFO from each of the other FIFOs */
|
||||
int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2];
|
||||
|
||||
struct pktq SENDQ;
|
||||
|
||||
/* packet hanger and MAC->handle lookup table */
|
||||
|
|
@ -228,7 +240,7 @@ typedef struct athost_wl_status_info {
|
|||
wlfc_mac_descriptor_t other;
|
||||
} destination_entries;
|
||||
/* token position for different priority packets */
|
||||
uint8 token_pos[AC_COUNT];
|
||||
uint8 token_pos[AC_COUNT+1];
|
||||
/* ON/OFF state for flow control to the host network interface */
|
||||
uint8 hostif_flow_state[WLFC_MAX_IFNUM];
|
||||
uint8 host_ifidx;
|
||||
|
|
@ -243,6 +255,12 @@ typedef struct athost_wl_status_info {
|
|||
2 - Use explicit credit
|
||||
*/
|
||||
uint8 proptxstatus_mode;
|
||||
|
||||
/* To borrow credits */
|
||||
uint8 allow_credit_borrow;
|
||||
|
||||
/* Timestamp to compute how long to defer borrowing for */
|
||||
uint32 borrow_defer_timestamp;
|
||||
} athost_wl_status_info_t;
|
||||
|
||||
#endif /* __wlfc_host_driver_definitions_h__ */
|
||||
|
|
|
|||
|
|
@ -33,17 +33,17 @@
|
|||
|
||||
#define EPI_RC_NUMBER 125
|
||||
|
||||
#define EPI_INCREMENTAL_NUMBER 74
|
||||
#define EPI_INCREMENTAL_NUMBER 78
|
||||
|
||||
#define EPI_BUILD_NUMBER 0
|
||||
|
||||
#define EPI_VERSION 5, 90, 125, 74
|
||||
#define EPI_VERSION 5, 90, 125, 78
|
||||
|
||||
#define EPI_VERSION_NUM 0x055a7d4a
|
||||
#define EPI_VERSION_NUM 0x055a7d4e
|
||||
|
||||
#define EPI_VERSION_DEV 5.90.125
|
||||
|
||||
|
||||
#define EPI_VERSION_STR "5.90.125.74"
|
||||
#define EPI_VERSION_STR "5.90.125.78"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -48,23 +48,25 @@
|
|||
#define BCM_MEM_FILENAME_LEN 24
|
||||
|
||||
#ifdef DHD_USE_STATIC_BUF
|
||||
#define MAX_STATIC_BUF_NUM 16
|
||||
#define STATIC_BUF_SIZE (PAGE_SIZE*2)
|
||||
#define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE)
|
||||
#define STATIC_BUF_MAX_NUM 16
|
||||
#define STATIC_BUF_SIZE (PAGE_SIZE * 2)
|
||||
#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
|
||||
|
||||
typedef struct bcm_static_buf {
|
||||
struct semaphore static_sem;
|
||||
unsigned char *buf_ptr;
|
||||
unsigned char buf_use[MAX_STATIC_BUF_NUM];
|
||||
unsigned char buf_use[STATIC_BUF_MAX_NUM];
|
||||
} bcm_static_buf_t;
|
||||
|
||||
static bcm_static_buf_t *bcm_static_buf = 0;
|
||||
|
||||
#define MAX_STATIC_PKT_NUM 8
|
||||
#define STATIC_PKT_MAX_NUM 8
|
||||
|
||||
typedef struct bcm_static_pkt {
|
||||
struct sk_buff *skb_4k[MAX_STATIC_PKT_NUM];
|
||||
struct sk_buff *skb_8k[MAX_STATIC_PKT_NUM];
|
||||
struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM];
|
||||
struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM];
|
||||
struct semaphore osl_pkt_sem;
|
||||
unsigned char pkt_use[MAX_STATIC_PKT_NUM*2];
|
||||
unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2];
|
||||
} bcm_static_pkt_t;
|
||||
static bcm_static_pkt_t *bcm_static_skb = 0;
|
||||
#endif
|
||||
|
|
@ -228,8 +230,8 @@ osl_attach(void *pdev, uint bustype, bool pkttag)
|
|||
bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
|
||||
skb_buff_ptr = dhd_os_prealloc(osh, 4, 0);
|
||||
|
||||
bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16);
|
||||
for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++)
|
||||
bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16);
|
||||
for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++)
|
||||
bcm_static_skb->pkt_use[i] = 0;
|
||||
|
||||
sema_init(&bcm_static_skb->osl_pkt_sem, 1);
|
||||
|
|
@ -548,84 +550,69 @@ osl_pktget_static(osl_t *osh, uint len)
|
|||
struct sk_buff *skb;
|
||||
|
||||
|
||||
if (len > (PAGE_SIZE*2))
|
||||
{
|
||||
if (len > (PAGE_SIZE * 2)) {
|
||||
printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len);
|
||||
printk("Do we really need this big skb??\n");
|
||||
return osl_pktget(osh, len);
|
||||
}
|
||||
|
||||
|
||||
down(&bcm_static_skb->osl_pkt_sem);
|
||||
if (len <= PAGE_SIZE)
|
||||
{
|
||||
|
||||
for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
|
||||
{
|
||||
if (len <= PAGE_SIZE) {
|
||||
for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
|
||||
if (bcm_static_skb->pkt_use[i] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != MAX_STATIC_PKT_NUM)
|
||||
{
|
||||
if (i != STATIC_PKT_MAX_NUM) {
|
||||
bcm_static_skb->pkt_use[i] = 1;
|
||||
up(&bcm_static_skb->osl_pkt_sem);
|
||||
|
||||
skb = bcm_static_skb->skb_4k[i];
|
||||
skb->tail = skb->data + len;
|
||||
skb->len = len;
|
||||
|
||||
return skb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
|
||||
{
|
||||
if (bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] == 0)
|
||||
for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
|
||||
if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != MAX_STATIC_PKT_NUM)
|
||||
{
|
||||
bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] = 1;
|
||||
if (i != STATIC_PKT_MAX_NUM) {
|
||||
bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1;
|
||||
up(&bcm_static_skb->osl_pkt_sem);
|
||||
skb = bcm_static_skb->skb_8k[i];
|
||||
skb->tail = skb->data + len;
|
||||
skb->len = len;
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
up(&bcm_static_skb->osl_pkt_sem);
|
||||
printk("all static pkt in use!\n");
|
||||
printk("%s: all static pkt in use!\n", __FUNCTION__);
|
||||
return osl_pktget(osh, len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
osl_pktfree_static(osl_t *osh, void *p, bool send)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
|
||||
{
|
||||
if (p == bcm_static_skb->skb_4k[i])
|
||||
{
|
||||
for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
|
||||
if (p == bcm_static_skb->skb_4k[i]) {
|
||||
down(&bcm_static_skb->osl_pkt_sem);
|
||||
bcm_static_skb->pkt_use[i] = 0;
|
||||
up(&bcm_static_skb->osl_pkt_sem);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
|
||||
{
|
||||
if (p == bcm_static_skb->skb_8k[i])
|
||||
{
|
||||
for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
|
||||
if (p == bcm_static_skb->skb_8k[i]) {
|
||||
down(&bcm_static_skb->osl_pkt_sem);
|
||||
bcm_static_skb->pkt_use[i + MAX_STATIC_PKT_NUM] = 0;
|
||||
bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0;
|
||||
up(&bcm_static_skb->osl_pkt_sem);
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ uint dhd_dev_reset(struct net_device *dev, uint8 flag);
|
|||
void dhd_dev_init_ioctl(struct net_device *dev);
|
||||
#ifdef WL_CFG80211
|
||||
int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
|
||||
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command);
|
||||
#else
|
||||
int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) { return 0; }
|
||||
#endif
|
||||
|
|
@ -454,6 +455,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
|||
net_os_set_packet_filter(net, 0); /* DHCP starts */
|
||||
else
|
||||
net_os_set_packet_filter(net, 1); /* DHCP ends */
|
||||
#ifdef WL_CFG80211
|
||||
bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
|
||||
#endif
|
||||
}
|
||||
else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
|
||||
bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,32 @@ static ctl_table wl_sysctl_table[] = {
|
|||
static struct ctl_table_header *wl_sysctl_hdr;
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
#define COEX_DHCP
|
||||
|
||||
#if defined(COEX_DHCP)
|
||||
#define BT_DHCP_eSCO_FIX /* use New SCO/eSCO smart YG
|
||||
* suppression
|
||||
*/
|
||||
#define BT_DHCP_USE_FLAGS /* this flag boost wifi pkt priority
|
||||
* to max, caution: -not fair to sco
|
||||
*/
|
||||
#define BT_DHCP_OPPR_WIN_TIME 2500 /* T1 start SCO/ESCo priority
|
||||
* suppression
|
||||
*/
|
||||
#define BT_DHCP_FLAG_FORCE_TIME 5500 /* T2 turn off SCO/SCO supperesion
|
||||
* is (timeout)
|
||||
*/
|
||||
enum wl_cfg80211_btcoex_status {
|
||||
BT_DHCP_IDLE,
|
||||
BT_DHCP_START,
|
||||
BT_DHCP_OPPR_WIN,
|
||||
BT_DHCP_FLAG_FORCE_TIMEOUT
|
||||
};
|
||||
|
||||
static int wl_cfg80211_btcoex_init(struct wl_priv *wl);
|
||||
static void wl_cfg80211_btcoex_deinit(struct wl_priv *wl);
|
||||
#endif
|
||||
|
||||
/* This is to override regulatory domains defined in cfg80211 module (reg.c)
|
||||
* By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
|
||||
* and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
|
||||
|
|
@ -909,7 +935,6 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
|
|||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
|
||||
static s32
|
||||
wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
|
||||
{
|
||||
|
|
@ -944,7 +969,6 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
|
|||
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
|
||||
(wl->scan_request == false),
|
||||
msecs_to_jiffies(MAX_WAIT_TIME));
|
||||
|
||||
if (timeout > 0 && (!wl->scan_request)) {
|
||||
WL_DBG(("IFDEL Operations Done"));
|
||||
} else {
|
||||
|
|
@ -1063,6 +1087,7 @@ s32
|
|||
wl_cfg80211_ifdel_ops(struct net_device *net)
|
||||
{
|
||||
struct wl_priv *wl = wlcfg_drv_priv;
|
||||
int rollback_lock = FALSE;
|
||||
|
||||
if (!net || !net->name) {
|
||||
WL_DBG(("net is NULL\n"));
|
||||
|
|
@ -1073,10 +1098,15 @@ wl_cfg80211_ifdel_ops(struct net_device *net)
|
|||
|
||||
/* Abort any pending scan requests */
|
||||
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
|
||||
rtnl_lock();
|
||||
if (!rtnl_is_locked()) {
|
||||
rtnl_lock();
|
||||
rollback_lock = TRUE;
|
||||
}
|
||||
WL_INFO(("ESCAN COMPLETED\n"));
|
||||
wl_notify_escan_complete(wl, true);
|
||||
rtnl_unlock();
|
||||
|
||||
if (rollback_lock)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/* Wake up any waiting thread */
|
||||
|
|
@ -1093,7 +1123,6 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
|
|||
|
||||
if (wl->p2p->vif_created) {
|
||||
s32 index = 0;
|
||||
|
||||
WL_DBG(("IF_DEL event called from dongle, net %x, vif name: %s\n",
|
||||
(unsigned int)net, wl->p2p->vir_ifname));
|
||||
|
||||
|
|
@ -1459,6 +1488,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
struct wl_priv *wl = wiphy_priv(wiphy);
|
||||
struct cfg80211_ssid *ssids;
|
||||
struct wl_scan_req *sr = wl_to_sr(wl);
|
||||
wpa_ie_fixed_t *wps_ie;
|
||||
s32 passive_scan;
|
||||
bool iscan_req;
|
||||
bool escan_req;
|
||||
|
|
@ -1466,7 +1496,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
bool p2p_ssid;
|
||||
s32 err = 0;
|
||||
s32 i;
|
||||
|
||||
u32 wpsie_len = 0;
|
||||
u8 wpsie[IE_MAX_LEN];
|
||||
if (unlikely(wl_get_drv_status(wl, SCANNING))) {
|
||||
WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
|
||||
return -EAGAIN;
|
||||
|
|
@ -1531,6 +1562,26 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!wl->p2p_supported || !p2p_scan(wl)) {
|
||||
if (ndev == wl_to_prmry_ndev(wl)) {
|
||||
/* find the WPSIE */
|
||||
memset(wpsie, 0, sizeof(wpsie));
|
||||
if ((wps_ie = wl_cfgp2p_find_wpsie(
|
||||
(u8 *)request->ie,
|
||||
request->ie_len)) != NULL) {
|
||||
wpsie_len =
|
||||
wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
|
||||
memcpy(wpsie, wps_ie, wpsie_len);
|
||||
} else {
|
||||
wpsie_len = 0;
|
||||
}
|
||||
err = wl_cfgp2p_set_management_ie(wl, ndev, -1,
|
||||
VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len);
|
||||
if (unlikely(err)) {
|
||||
goto scan_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* scan in ibss */
|
||||
|
|
@ -1615,6 +1666,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
WL_DBG(("Enter \n"));
|
||||
CHECK_SYS_UP(wl);
|
||||
|
||||
err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
|
||||
if (unlikely(err)) {
|
||||
WL_ERR(("scan error (%d)\n", err));
|
||||
|
|
@ -2100,9 +2152,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
size_t join_params_size;
|
||||
s32 err = 0;
|
||||
wpa_ie_fixed_t *wpa_ie;
|
||||
wpa_ie_fixed_t *wps_ie;
|
||||
bcm_tlv_t *wpa2_ie;
|
||||
u8* wpaie = 0;
|
||||
u32 wpaie_len = 0;
|
||||
u32 wpsie_len = 0;
|
||||
u8 wpsie[IE_MAX_LEN];
|
||||
WL_DBG(("In\n"));
|
||||
CHECK_SYS_UP(wl);
|
||||
|
||||
|
|
@ -2126,7 +2181,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
|
||||
VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
|
||||
} else if (p2p_on(wl) && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
|
||||
/* This is the connect req after WPS is done [credentials exchanged]
|
||||
/* This is the connect req after WPS is done [credentials exchanged]
|
||||
* currently identified with WPA_VERSION_2 .
|
||||
* Update the previously set IEs with
|
||||
* the newly received IEs from Supplicant. This will remove the WPS IE from
|
||||
|
|
@ -2158,8 +2213,21 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
ioctlbuf, sizeof(ioctlbuf));
|
||||
}
|
||||
|
||||
/* find the WPSIE */
|
||||
memset(wpsie, 0, sizeof(wpsie));
|
||||
if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)sme->ie,
|
||||
sme->ie_len)) != NULL) {
|
||||
wpsie_len = wps_ie->length +WPA_RSN_IE_TAG_FIXED_LEN;
|
||||
memcpy(wpsie, wps_ie, wpsie_len);
|
||||
} else {
|
||||
wpsie_len = 0;
|
||||
}
|
||||
err = wl_cfgp2p_set_management_ie(wl, dev, -1,
|
||||
VNDR_IE_ASSOCREQ_FLAG, wpsie, wpsie_len);
|
||||
if (unlikely(err)) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!sme->ssid)) {
|
||||
WL_ERR(("Invalid ssid\n"));
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -2594,17 +2662,6 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef NOT_YET
|
||||
/* TODO: Removed in P2P twig, check later --lin */
|
||||
val = 0; /* assume open key. otherwise 1 */
|
||||
val = htod32(val);
|
||||
err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), false);
|
||||
if (unlikely(err)) {
|
||||
WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -3145,9 +3202,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
|
|||
wl_cfgp2p_set_management_ie(wl, dev, bssidx,
|
||||
VNDR_IE_PRBRSP_FLAG,
|
||||
(u8 *)wps_ie, wpsie_len + p2pie_len);
|
||||
/* remove WLC_E_PROBREQ_MSG event to prevent HOSTAPD
|
||||
* from responding many probe request
|
||||
*/
|
||||
}
|
||||
}
|
||||
cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL);
|
||||
|
|
@ -3198,7 +3252,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
|
|||
wifi_p2p_pub_act_frame_t *act_frm =
|
||||
(wifi_p2p_pub_act_frame_t *) (action_frame->data);
|
||||
/*
|
||||
* To make sure to send successfully action frame, we have to turn off mpc
|
||||
* To make sure to send successfully action frame, we have to turn off mpc
|
||||
*/
|
||||
if ((act_frm->subtype == P2P_PAF_GON_REQ)||
|
||||
(act_frm->subtype == P2P_PAF_GON_RSP)) {
|
||||
|
|
@ -3702,8 +3756,11 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
|
|||
} else {
|
||||
WL_DBG(("No WPSIE in beacon \n"));
|
||||
}
|
||||
wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false);
|
||||
|
||||
err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false);
|
||||
if (unlikely(err)) {
|
||||
WL_ERR(("WLC_UP error (%d)\n", err));
|
||||
return err;
|
||||
}
|
||||
memset(&join_params, 0, sizeof(join_params));
|
||||
/* join parameters starts with ssid */
|
||||
join_params_size = sizeof(join_params.ssid);
|
||||
|
|
@ -4222,7 +4279,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
|
|||
|
||||
} else {
|
||||
WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
|
||||
ntoh32(e->event_type), ntoh32(e->status)));
|
||||
ntoh32(e->event_type), ntoh32(e->status)));
|
||||
if (wl_is_linkup(wl, e, ndev)) {
|
||||
wl_link_up(wl);
|
||||
act = true;
|
||||
|
|
@ -4859,7 +4916,11 @@ static s32 wl_init_priv_mem(struct wl_priv *wl)
|
|||
WL_ERR(("pmk list alloc failed\n"));
|
||||
goto init_priv_mem_out;
|
||||
}
|
||||
|
||||
wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
|
||||
if (unlikely(!wl->sta_info)) {
|
||||
WL_ERR(("sta info alloc failed\n"));
|
||||
goto init_priv_mem_out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
init_priv_mem_out:
|
||||
|
|
@ -4892,6 +4953,8 @@ static void wl_deinit_priv_mem(struct wl_priv *wl)
|
|||
wl->fw = NULL;
|
||||
kfree(wl->pmk_list);
|
||||
wl->pmk_list = NULL;
|
||||
kfree(wl->sta_info);
|
||||
wl->sta_info = NULL;
|
||||
if (wl->ap_info) {
|
||||
kfree(wl->ap_info->wpa_ie);
|
||||
kfree(wl->ap_info->rsn_ie);
|
||||
|
|
@ -5428,6 +5491,11 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
|
|||
goto cfg80211_attach_out;
|
||||
}
|
||||
#endif
|
||||
#if defined(COEX_DHCP)
|
||||
if (wl_cfg80211_btcoex_init(wl))
|
||||
goto cfg80211_attach_out;
|
||||
#endif /* COEX_DHCP */
|
||||
|
||||
wlcfg_drv_priv = wl;
|
||||
return err;
|
||||
|
||||
|
|
@ -5444,6 +5512,11 @@ void wl_cfg80211_detach(void)
|
|||
wl = wlcfg_drv_priv;
|
||||
|
||||
WL_TRACE(("In\n"));
|
||||
|
||||
#if defined(COEX_DHCP)
|
||||
wl_cfg80211_btcoex_deinit(wl);
|
||||
#endif /* COEX_DHCP */
|
||||
|
||||
#if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL)
|
||||
if (wl_sysctl_hdr)
|
||||
unregister_sysctl_table(wl_sysctl_hdr);
|
||||
|
|
@ -6120,6 +6193,20 @@ s32 wl_cfg80211_up(void)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Private Event to Supplicant with indication that FW hangs */
|
||||
int wl_cfg80211_hang(struct net_device *dev, u16 reason)
|
||||
{
|
||||
struct wl_priv *wl;
|
||||
wl = wlcfg_drv_priv;
|
||||
|
||||
WL_ERR(("In : FW crash Eventing\n"));
|
||||
cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
|
||||
if (wl != NULL) {
|
||||
wl_link_down(wl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 wl_cfg80211_down(void)
|
||||
{
|
||||
struct wl_priv *wl;
|
||||
|
|
@ -6547,3 +6634,480 @@ static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
|
|||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(COEX_DHCP)
|
||||
/*
|
||||
* get named driver variable to uint register value and return error indication
|
||||
* calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, ®_value)
|
||||
*/
|
||||
static int
|
||||
dev_wlc_intvar_get_reg(struct net_device *dev, char *name,
|
||||
uint reg, int *retval)
|
||||
{
|
||||
union {
|
||||
char buf[WLC_IOCTL_SMLEN];
|
||||
int val;
|
||||
} var;
|
||||
int error;
|
||||
|
||||
bcm_mkiovar(name, (char *)(®), sizeof(reg),
|
||||
(char *)(&var), sizeof(var.buf));
|
||||
error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false);
|
||||
|
||||
*retval = dtoh32(var.val);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
|
||||
char ioctlbuf[1024];
|
||||
#else
|
||||
static char ioctlbuf[1024];
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
|
||||
|
||||
bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
|
||||
|
||||
return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf, sizeof(ioctlbuf), false));
|
||||
}
|
||||
/*
|
||||
get named driver variable to uint register value and return error indication
|
||||
calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value)
|
||||
*/
|
||||
static int
|
||||
dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val)
|
||||
{
|
||||
char reg_addr[8];
|
||||
|
||||
memset(reg_addr, 0, sizeof(reg_addr));
|
||||
memcpy((char *)®_addr[0], (char *)addr, 4);
|
||||
memcpy((char *)®_addr[4], (char *)val, 4);
|
||||
|
||||
return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr)));
|
||||
}
|
||||
|
||||
static bool btcoex_is_sco_active(struct net_device *dev)
|
||||
{
|
||||
int ioc_res = 0;
|
||||
bool res = FALSE;
|
||||
int sco_id_cnt = 0;
|
||||
int param27;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
|
||||
ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27);
|
||||
|
||||
WL_INFO(("%s, sample[%d], btc params: 27:%x\n",
|
||||
__FUNCTION__, i, param27));
|
||||
|
||||
if (ioc_res < 0) {
|
||||
WL_ERR(("%s ioc read btc params error\n", __FUNCTION__));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((param27 & 0x6) == 2) { /* count both sco & esco */
|
||||
sco_id_cnt++;
|
||||
}
|
||||
|
||||
if (sco_id_cnt > 2) {
|
||||
WL_INFO(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
|
||||
__FUNCTION__, sco_id_cnt, i));
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(BT_DHCP_eSCO_FIX)
|
||||
/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */
|
||||
static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
|
||||
{
|
||||
static bool saved_status = FALSE;
|
||||
|
||||
char buf_reg50va_dhcp_on[8] =
|
||||
{ 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
|
||||
char buf_reg51va_dhcp_on[8] =
|
||||
{ 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
|
||||
char buf_reg64va_dhcp_on[8] =
|
||||
{ 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
|
||||
char buf_reg65va_dhcp_on[8] =
|
||||
{ 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
|
||||
char buf_reg71va_dhcp_on[8] =
|
||||
{ 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint32 regaddr;
|
||||
static uint32 saved_reg50;
|
||||
static uint32 saved_reg51;
|
||||
static uint32 saved_reg64;
|
||||
static uint32 saved_reg65;
|
||||
static uint32 saved_reg71;
|
||||
|
||||
if (trump_sco) {
|
||||
/* this should reduce eSCO agressive retransmit
|
||||
* w/o breaking it
|
||||
*/
|
||||
|
||||
/* 1st save current */
|
||||
WL_INFO(("Do new SCO/eSCO coex algo {save &"
|
||||
"override}\n"));
|
||||
if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
|
||||
saved_status = TRUE;
|
||||
WL_INFO(("%s saved bt_params[50,51,64,65,71]:"
|
||||
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
__FUNCTION__, saved_reg50, saved_reg51,
|
||||
saved_reg64, saved_reg65, saved_reg71));
|
||||
} else {
|
||||
WL_ERR((":%s: save btc_params failed\n",
|
||||
__FUNCTION__));
|
||||
saved_status = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WL_INFO(("override with [50,51,64,65,71]:"
|
||||
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
*(u32 *)(buf_reg50va_dhcp_on+4),
|
||||
*(u32 *)(buf_reg51va_dhcp_on+4),
|
||||
*(u32 *)(buf_reg64va_dhcp_on+4),
|
||||
*(u32 *)(buf_reg65va_dhcp_on+4),
|
||||
*(u32 *)(buf_reg71va_dhcp_on+4)));
|
||||
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg50va_dhcp_on[0], 8);
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg51va_dhcp_on[0], 8);
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg64va_dhcp_on[0], 8);
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg65va_dhcp_on[0], 8);
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg71va_dhcp_on[0], 8);
|
||||
|
||||
saved_status = TRUE;
|
||||
} else if (saved_status) {
|
||||
/* restore previously saved bt params */
|
||||
WL_INFO(("Do new SCO/eSCO coex algo {save &"
|
||||
"override}\n"));
|
||||
|
||||
regaddr = 50;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg50);
|
||||
regaddr = 51;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg51);
|
||||
regaddr = 64;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg64);
|
||||
regaddr = 65;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg65);
|
||||
regaddr = 71;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg71);
|
||||
|
||||
WL_INFO(("restore bt_params[50,51,64,65,71]:"
|
||||
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
saved_reg50, saved_reg51, saved_reg64,
|
||||
saved_reg65, saved_reg71));
|
||||
|
||||
saved_status = FALSE;
|
||||
} else {
|
||||
WL_ERR((":%s att to restore not saved BTCOEX params\n",
|
||||
__FUNCTION__));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* BT_DHCP_eSCO_FIX */
|
||||
|
||||
static void
|
||||
wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
|
||||
{
|
||||
#if defined(BT_DHCP_USE_FLAGS)
|
||||
char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
|
||||
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
rtnl_lock();
|
||||
#endif
|
||||
|
||||
#if defined(BT_DHCP_eSCO_FIX)
|
||||
/* set = 1, save & turn on 0 - off & restore prev settings */
|
||||
set_btc_esco_params(dev, set);
|
||||
#endif
|
||||
|
||||
#if defined(BT_DHCP_USE_FLAGS)
|
||||
WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set));
|
||||
if (set == TRUE)
|
||||
/* Forcing bt_flag7 */
|
||||
dev_wlc_bufvar_set(dev, "btc_flags",
|
||||
(char *)&buf_flag7_dhcp_on[0],
|
||||
sizeof(buf_flag7_dhcp_on));
|
||||
else
|
||||
/* Restoring default bt flag7 */
|
||||
dev_wlc_bufvar_set(dev, "btc_flags",
|
||||
(char *)&buf_flag7_default[0],
|
||||
sizeof(buf_flag7_default));
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
rtnl_unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void wl_cfg80211_bt_timerfunc(ulong data)
|
||||
{
|
||||
struct btcoex_info *bt_local = (struct btcoex_info *)data;
|
||||
WL_TRACE(("%s\n", __FUNCTION__));
|
||||
bt_local->timer_on = 0;
|
||||
schedule_work(&bt_local->work);
|
||||
}
|
||||
|
||||
static void wl_cfg80211_bt_handler(struct work_struct *work)
|
||||
{
|
||||
struct btcoex_info *btcx_inf;
|
||||
|
||||
btcx_inf = container_of(work, struct btcoex_info, work);
|
||||
|
||||
if (btcx_inf->timer_on) {
|
||||
btcx_inf->timer_on = 0;
|
||||
del_timer_sync(&btcx_inf->timer);
|
||||
}
|
||||
|
||||
switch (btcx_inf->bt_state) {
|
||||
case BT_DHCP_START:
|
||||
/* DHCP started
|
||||
* provide OPPORTUNITY window to get DHCP address
|
||||
*/
|
||||
WL_TRACE(("%s bt_dhcp stm: started \n",
|
||||
__FUNCTION__));
|
||||
btcx_inf->bt_state = BT_DHCP_OPPR_WIN;
|
||||
mod_timer(&btcx_inf->timer,
|
||||
jiffies + BT_DHCP_OPPR_WIN_TIME*HZ/1000);
|
||||
btcx_inf->timer_on = 1;
|
||||
break;
|
||||
|
||||
case BT_DHCP_OPPR_WIN:
|
||||
if (btcx_inf->dhcp_done) {
|
||||
WL_TRACE(("%s DHCP Done before T1 expiration\n",
|
||||
__FUNCTION__));
|
||||
goto btc_coex_idle;
|
||||
}
|
||||
|
||||
/* DHCP is not over yet, start lowering BT priority
|
||||
* enforce btc_params + flags if necessary
|
||||
*/
|
||||
WL_TRACE(("%s DHCP T1:%d expired\n", __FUNCTION__,
|
||||
BT_DHCP_OPPR_WIN_TIME));
|
||||
if (btcx_inf->dev)
|
||||
wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE);
|
||||
btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
|
||||
mod_timer(&btcx_inf->timer,
|
||||
jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
|
||||
btcx_inf->timer_on = 1;
|
||||
break;
|
||||
|
||||
case BT_DHCP_FLAG_FORCE_TIMEOUT:
|
||||
if (btcx_inf->dhcp_done) {
|
||||
WL_TRACE(("%s DHCP Done before T2 expiration\n",
|
||||
__FUNCTION__));
|
||||
} else {
|
||||
/* Noo dhcp during T1+T2, restore BT priority */
|
||||
WL_TRACE(("%s DHCP wait interval T2:%d"
|
||||
"msec expired\n", __FUNCTION__,
|
||||
BT_DHCP_FLAG_FORCE_TIME));
|
||||
}
|
||||
|
||||
/* Restoring default bt priority */
|
||||
if (btcx_inf->dev)
|
||||
wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
|
||||
btc_coex_idle:
|
||||
btcx_inf->bt_state = BT_DHCP_IDLE;
|
||||
btcx_inf->timer_on = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
WL_ERR(("%s error g_status=%d !!!\n", __FUNCTION__,
|
||||
btcx_inf->bt_state));
|
||||
if (btcx_inf->dev)
|
||||
wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
|
||||
btcx_inf->bt_state = BT_DHCP_IDLE;
|
||||
btcx_inf->timer_on = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
net_os_wake_unlock(btcx_inf->dev);
|
||||
}
|
||||
|
||||
static int wl_cfg80211_btcoex_init(struct wl_priv *wl)
|
||||
{
|
||||
struct btcoex_info *btco_inf = NULL;
|
||||
|
||||
btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL);
|
||||
if (!btco_inf)
|
||||
return -ENOMEM;
|
||||
|
||||
btco_inf->bt_state = BT_DHCP_IDLE;
|
||||
btco_inf->ts_dhcp_start = 0;
|
||||
btco_inf->ts_dhcp_ok = 0;
|
||||
/* Set up timer for BT */
|
||||
btco_inf->timer_ms = 10;
|
||||
init_timer(&btco_inf->timer);
|
||||
btco_inf->timer.data = (ulong)btco_inf;
|
||||
btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
|
||||
|
||||
btco_inf->dev = wl->wdev->netdev;
|
||||
|
||||
INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler);
|
||||
|
||||
wl->btcoex_info = btco_inf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_cfg80211_btcoex_deinit(struct wl_priv *wl)
|
||||
{
|
||||
if (!wl->btcoex_info)
|
||||
return;
|
||||
|
||||
if (!wl->btcoex_info->timer_on) {
|
||||
wl->btcoex_info->timer_on = 0;
|
||||
del_timer_sync(&wl->btcoex_info->timer);
|
||||
}
|
||||
|
||||
cancel_work_sync(&wl->btcoex_info->work);
|
||||
|
||||
kfree(wl->btcoex_info);
|
||||
wl->btcoex_info = NULL;
|
||||
}
|
||||
#endif /* OEM_ANDROID */
|
||||
|
||||
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
|
||||
{
|
||||
char powermode_val = 0;
|
||||
char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
|
||||
char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
|
||||
char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
|
||||
|
||||
uint32 regaddr;
|
||||
static uint32 saved_reg66;
|
||||
static uint32 saved_reg41;
|
||||
static uint32 saved_reg68;
|
||||
static bool saved_status = FALSE;
|
||||
|
||||
#ifdef COEX_DHCP
|
||||
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
|
||||
struct btcoex_info *btco_inf = wlcfg_drv_priv->btcoex_info;
|
||||
#endif /* COEX_DHCP */
|
||||
|
||||
/* Figure out powermode 1 or o command */
|
||||
strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1);
|
||||
|
||||
if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
|
||||
|
||||
WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
|
||||
|
||||
/* Retrieve and saved orig regs value */
|
||||
if ((saved_status == FALSE) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
|
||||
(!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
|
||||
saved_status = TRUE;
|
||||
WL_INFO(("Saved 0x%x 0x%x 0x%x\n",
|
||||
saved_reg66, saved_reg41, saved_reg68));
|
||||
|
||||
/* Disable PM mode during dhpc session */
|
||||
|
||||
/* Disable PM mode during dhpc session */
|
||||
#ifdef COEX_DHCP
|
||||
/* Start BT timer only for SCO connection */
|
||||
if (btcoex_is_sco_active(dev)) {
|
||||
/* btc_params 66 */
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg66va_dhcp_on[0],
|
||||
sizeof(buf_reg66va_dhcp_on));
|
||||
/* btc_params 41 0x33 */
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg41va_dhcp_on[0],
|
||||
sizeof(buf_reg41va_dhcp_on));
|
||||
/* btc_params 68 0x190 */
|
||||
dev_wlc_bufvar_set(dev, "btc_params",
|
||||
(char *)&buf_reg68va_dhcp_on[0],
|
||||
sizeof(buf_reg68va_dhcp_on));
|
||||
saved_status = TRUE;
|
||||
|
||||
btco_inf->bt_state = BT_DHCP_START;
|
||||
btco_inf->timer_on = 1;
|
||||
mod_timer(&btco_inf->timer, btco_inf->timer.expires);
|
||||
WL_INFO(("%s enable BT DHCP Timer\n",
|
||||
__FUNCTION__));
|
||||
}
|
||||
#endif /* COEX_DHCP */
|
||||
}
|
||||
else if (saved_status == TRUE) {
|
||||
WL_ERR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__));
|
||||
}
|
||||
}
|
||||
else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
|
||||
|
||||
|
||||
/* Restoring PM mode */
|
||||
|
||||
#ifdef COEX_DHCP
|
||||
/* Stop any bt timer because DHCP session is done */
|
||||
WL_INFO(("%s disable BT DHCP Timer\n", __FUNCTION__));
|
||||
if (btco_inf->timer_on) {
|
||||
btco_inf->timer_on = 0;
|
||||
del_timer_sync(&btco_inf->timer);
|
||||
|
||||
if (btco_inf->bt_state != BT_DHCP_IDLE) {
|
||||
/* need to restore original btc flags & extra btc params */
|
||||
WL_INFO(("%s bt->bt_state:%d\n",
|
||||
__FUNCTION__, btco_inf->bt_state));
|
||||
/* wake up btcoex thread to restore btlags+params */
|
||||
schedule_work(&btco_inf->work);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restoring btc_flag paramter anyway */
|
||||
if (saved_status == TRUE)
|
||||
dev_wlc_bufvar_set(dev, "btc_flags",
|
||||
(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
|
||||
#endif /* COEX_DHCP */
|
||||
|
||||
/* Restore original values */
|
||||
if (saved_status == TRUE) {
|
||||
regaddr = 66;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg66);
|
||||
regaddr = 41;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg41);
|
||||
regaddr = 68;
|
||||
dev_wlc_intvar_set_reg(dev, "btc_params",
|
||||
(char *)®addr, (char *)&saved_reg68);
|
||||
|
||||
WL_INFO(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
|
||||
saved_reg66, saved_reg41, saved_reg68));
|
||||
}
|
||||
saved_status = FALSE;
|
||||
|
||||
}
|
||||
else {
|
||||
WL_ERR(("%s Unkwown yet power setting, ignored\n",
|
||||
__FUNCTION__));
|
||||
}
|
||||
|
||||
snprintf(command, 3, "OK");
|
||||
|
||||
return (strlen("OK"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,6 +323,27 @@ struct ap_info {
|
|||
u8 *wps_ie;
|
||||
bool security_mode;
|
||||
};
|
||||
struct btcoex_info {
|
||||
struct timer_list timer;
|
||||
uint32 timer_ms;
|
||||
uint32 timer_on;
|
||||
uint32 ts_dhcp_start; /* ms ts ecord time stats */
|
||||
uint32 ts_dhcp_ok; /* ms ts ecord time stats */
|
||||
bool dhcp_done; /* flag, indicates that host done with
|
||||
* dhcp before t1/t2 expiration
|
||||
*/
|
||||
int bt_state;
|
||||
struct work_struct work;
|
||||
struct net_device *dev;
|
||||
};
|
||||
|
||||
struct sta_info {
|
||||
/* Structure to hold WPS IE for a STA */
|
||||
u8 probe_req_ie[IE_MAX_LEN];
|
||||
u8 assoc_req_ie[IE_MAX_LEN];
|
||||
u32 probe_req_ie_len;
|
||||
u32 assoc_req_ie_len;
|
||||
};
|
||||
/* dongle private data of cfg80211 interface */
|
||||
struct wl_priv {
|
||||
struct wireless_dev *wdev; /* representing wl cfg80211 device */
|
||||
|
|
@ -343,8 +364,6 @@ struct wl_priv {
|
|||
struct wl_cfg80211_bss_info *bss_info;
|
||||
/* information element object for internal purpose */
|
||||
struct wl_ie ie;
|
||||
u8 scan_ie_buf[2048];
|
||||
int scan_ie_len;
|
||||
struct ether_addr bssid; /* bssid of currently engaged network */
|
||||
|
||||
/* for synchronization of main event thread */
|
||||
|
|
@ -357,7 +376,7 @@ struct wl_priv {
|
|||
/* control firwmare and nvram paramter downloading */
|
||||
struct wl_fw_ctrl *fw;
|
||||
struct wl_pmk_list *pmk_list; /* wpa2 pmk list */
|
||||
tsk_ctl_t event_tsk; /* task of main event handler thread */
|
||||
tsk_ctl_t event_tsk; /* task of main event handler thread */
|
||||
unsigned long status; /* current dongle status */
|
||||
void *pub;
|
||||
u32 channel; /* current channel */
|
||||
|
|
@ -385,9 +404,10 @@ struct wl_priv {
|
|||
u64 cache_cookie;
|
||||
wait_queue_head_t dongle_event_wait;
|
||||
struct ap_info *ap_info;
|
||||
struct sta_info *sta_info;
|
||||
struct p2p_info *p2p;
|
||||
bool p2p_supported;
|
||||
s8 last_eventmask[WL_EVENTING_MASK_LEN];
|
||||
struct btcoex_info *btcoex_info;
|
||||
};
|
||||
|
||||
#define wl_to_wiphy(w) (w->wdev->wiphy)
|
||||
|
|
@ -507,6 +527,7 @@ extern void wl_cfg80211_release_fw(void);
|
|||
extern s8 *wl_cfg80211_get_fwname(void);
|
||||
extern s8 *wl_cfg80211_get_nvramname(void);
|
||||
extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
|
||||
extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
|
||||
#ifdef CONFIG_SYSCTL
|
||||
extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -627,16 +627,14 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
|
|||
s32 ret = BCME_OK;
|
||||
u32 pos;
|
||||
u8 *ie_buf;
|
||||
u8 *mgmt_ie_buf;
|
||||
u32 mgmt_ie_buf_len;
|
||||
u32 *mgmt_ie_len;
|
||||
u8 *mgmt_ie_buf = NULL;
|
||||
u32 mgmt_ie_buf_len = 0;
|
||||
u32 *mgmt_ie_len = 0;
|
||||
u8 ie_id, ie_len;
|
||||
u8 delete = 0;
|
||||
#define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie)
|
||||
#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len)
|
||||
if (bssidx == -1)
|
||||
return BCME_BADARG;
|
||||
if (wl->p2p_supported && p2p_on(wl)) {
|
||||
if (wl->p2p_supported && p2p_on(wl) && bssidx != -1) {
|
||||
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
|
||||
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
|
||||
switch (pktflag) {
|
||||
|
|
@ -671,7 +669,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
|
|||
CFGP2P_ERR(("not suitable type\n"));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
} else if (get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
|
||||
switch (pktflag) {
|
||||
case VNDR_IE_PRBRSP_FLAG :
|
||||
mgmt_ie_buf = wl->ap_info->probe_res_ie;
|
||||
|
|
@ -689,37 +687,63 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
|
|||
CFGP2P_ERR(("not suitable type\n"));
|
||||
return -1;
|
||||
}
|
||||
bssidx = 0;
|
||||
} else if (bssidx == -1 && get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
|
||||
switch (pktflag) {
|
||||
case VNDR_IE_PRBREQ_FLAG :
|
||||
mgmt_ie_buf = wl->sta_info->probe_req_ie;
|
||||
mgmt_ie_len = &wl->sta_info->probe_req_ie_len;
|
||||
mgmt_ie_buf_len = sizeof(wl->sta_info->probe_req_ie);
|
||||
break;
|
||||
case VNDR_IE_ASSOCREQ_FLAG :
|
||||
mgmt_ie_buf = wl->sta_info->assoc_req_ie;
|
||||
mgmt_ie_len = &wl->sta_info->assoc_req_ie_len;
|
||||
mgmt_ie_buf_len = sizeof(wl->sta_info->assoc_req_ie);
|
||||
break;
|
||||
default:
|
||||
mgmt_ie_buf = NULL;
|
||||
mgmt_ie_len = NULL;
|
||||
CFGP2P_ERR(("not suitable type\n"));
|
||||
return -1;
|
||||
}
|
||||
bssidx = 0;
|
||||
} else {
|
||||
CFGP2P_ERR(("not suitable type\n"));
|
||||
return -1;
|
||||
}
|
||||
/* Add if there is any extra IE */
|
||||
if (vndr_ie && vndr_ie_len) {
|
||||
CFGP2P_INFO(("Request has extra IE"));
|
||||
if (vndr_ie_len > mgmt_ie_buf_len) {
|
||||
CFGP2P_ERR(("extra IE size too big\n"));
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
if (mgmt_ie_buf != NULL) {
|
||||
if ((vndr_ie_len == *mgmt_ie_len) &&
|
||||
(memcmp(mgmt_ie_buf, vndr_ie, vndr_ie_len) == 0)) {
|
||||
CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
|
||||
goto exit;
|
||||
}
|
||||
pos = 0;
|
||||
delete = 1;
|
||||
ie_buf = (u8 *) mgmt_ie_buf;
|
||||
while (pos < *mgmt_ie_len) {
|
||||
ie_id = ie_buf[pos++];
|
||||
ie_len = ie_buf[pos++];
|
||||
CFGP2P_INFO(("DELELED ID(%d), Len(%d),"
|
||||
"OUI(%02x:%02x:%02x)\n",
|
||||
ie_id, ie_len, ie_buf[pos],
|
||||
ie_buf[pos+1], ie_buf[pos+2]));
|
||||
ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag,
|
||||
ie_buf+pos, VNDR_SPEC_ELEMENT_ID,
|
||||
ie_buf+pos+3, ie_len-3, delete);
|
||||
pos += ie_len;
|
||||
}
|
||||
|
||||
if (vndr_ie_len > mgmt_ie_buf_len) {
|
||||
CFGP2P_ERR(("extra IE size too big\n"));
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
if (mgmt_ie_buf != NULL) {
|
||||
if (vndr_ie_len && (vndr_ie_len == *mgmt_ie_len) &&
|
||||
(memcmp(mgmt_ie_buf, vndr_ie, vndr_ie_len) == 0)) {
|
||||
CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
|
||||
goto exit;
|
||||
}
|
||||
pos = 0;
|
||||
delete = 1;
|
||||
ie_buf = (u8 *) mgmt_ie_buf;
|
||||
while (pos < *mgmt_ie_len) {
|
||||
ie_id = ie_buf[pos++];
|
||||
ie_len = ie_buf[pos++];
|
||||
if ((ie_id == DOT11_MNG_VS_ID) &&
|
||||
(wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
|
||||
wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
|
||||
CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
|
||||
"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
|
||||
ie_buf[pos+1], ie_buf[pos+2]));
|
||||
ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos,
|
||||
VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete);
|
||||
}
|
||||
pos += ie_len;
|
||||
}
|
||||
|
||||
}
|
||||
*mgmt_ie_len = 0;
|
||||
/* Add if there is any extra IE */
|
||||
if (vndr_ie && vndr_ie_len) {
|
||||
/* save the current IE in wl struct */
|
||||
memcpy(mgmt_ie_buf, vndr_ie, vndr_ie_len);
|
||||
*mgmt_ie_len = vndr_ie_len;
|
||||
|
|
@ -741,7 +765,6 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
|
|||
pos += ie_len;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#undef IE_TYPE
|
||||
#undef IE_TYPE_LEN
|
||||
|
|
|
|||
|
|
@ -1266,6 +1266,7 @@ wl_iw_set_dtim_skip(
|
|||
&iovbuf, sizeof(iovbuf))) >= 0) {
|
||||
p += snprintf(p, MAX_WX_STRING, "OK");
|
||||
|
||||
|
||||
net_os_set_dtim_skip(dev, bcn_li_dtim);
|
||||
|
||||
WL_TRACE(("%s: set dtim_skip %d OK\n", __FUNCTION__,
|
||||
|
|
@ -1737,6 +1738,7 @@ wl_iw_control_wl_off(
|
|||
sdioh_stop(NULL);
|
||||
#endif
|
||||
|
||||
|
||||
net_os_set_dtim_skip(dev, 0);
|
||||
|
||||
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
|
||||
|
|
@ -2415,7 +2417,7 @@ wl_iw_get_range(
|
|||
list = (wl_uint32_list_t *)channels;
|
||||
|
||||
dwrq->length = sizeof(struct iw_range);
|
||||
memset(range, 0, sizeof(range));
|
||||
memset(range, 0, sizeof(*range));
|
||||
|
||||
|
||||
range->min_nwid = range->max_nwid = 0;
|
||||
|
|
@ -4472,7 +4474,7 @@ wl_iw_set_essid(
|
|||
g_ssid.SSID_len = htod32(g_ssid.SSID_len);
|
||||
|
||||
|
||||
memset(join_params, 0, sizeof(join_params));
|
||||
memset(join_params, 0, sizeof(*join_params));
|
||||
join_params_size = sizeof(join_params->ssid);
|
||||
|
||||
memcpy(join_params->ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
|
||||
|
|
@ -6297,6 +6299,8 @@ wl_iw_add_wps_probe_req_ie(
|
|||
str_ptr += WPS_PROBE_REQ_IE_CMD_LENGTH;
|
||||
datalen = wrqu->data.length - WPS_PROBE_REQ_IE_CMD_LENGTH;
|
||||
|
||||
|
||||
|
||||
buflen = sizeof(vndr_ie_setbuf_t) + datalen - sizeof(vndr_ie_t);
|
||||
ie_setbuf = (vndr_ie_setbuf_t *)kmalloc(buflen, GFP_KERNEL);
|
||||
if (!ie_setbuf) {
|
||||
|
|
@ -6306,16 +6310,21 @@ wl_iw_add_wps_probe_req_ie(
|
|||
|
||||
memset(ie_setbuf, 0x00, buflen);
|
||||
|
||||
|
||||
strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
|
||||
ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
|
||||
|
||||
|
||||
iecount = htod32(1);
|
||||
memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int));
|
||||
|
||||
|
||||
pktflag = 0x10;
|
||||
memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, sizeof(uint32));
|
||||
memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag,
|
||||
&pktflag, sizeof(uint32));
|
||||
|
||||
memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data, str_ptr, datalen);
|
||||
memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data,
|
||||
str_ptr, datalen);
|
||||
|
||||
total_len = strlen("vndr_ie ") + buflen;
|
||||
bufptr = (char *)kmalloc(total_len, GFP_KERNEL);
|
||||
|
|
@ -7528,11 +7537,15 @@ wl_iw_set_priv(
|
|||
ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
#ifdef CONFIG_WPS2
|
||||
else if (strnicmp(extra, WPS_ADD_PROBE_REQ_IE_CMD, strlen(WPS_ADD_PROBE_REQ_IE_CMD)) == 0)
|
||||
ret = wl_iw_add_wps_probe_req_ie(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, WPS_DEL_PROBE_REQ_IE_CMD, strlen(WPS_DEL_PROBE_REQ_IE_CMD)) == 0)
|
||||
ret = wl_iw_del_wps_probe_req_ie(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
else if (strnicmp(extra, WPS_ADD_PROBE_REQ_IE_CMD,
|
||||
strlen(WPS_ADD_PROBE_REQ_IE_CMD)) == 0)
|
||||
ret = wl_iw_add_wps_probe_req_ie(dev, info,
|
||||
(union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, WPS_DEL_PROBE_REQ_IE_CMD,
|
||||
strlen(WPS_DEL_PROBE_REQ_IE_CMD)) == 0)
|
||||
ret = wl_iw_del_wps_probe_req_ie(dev, info,
|
||||
(union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
|
||||
ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
|
||||
|
|
@ -7761,8 +7774,8 @@ static const struct iw_priv_args wl_iw_priv_args[] =
|
|||
|
||||
{
|
||||
WL_AP_STA_LIST,
|
||||
0,
|
||||
IW_PRIV_TYPE_CHAR | 0,
|
||||
IW_PRIV_TYPE_CHAR | 0,
|
||||
IW_PRIV_TYPE_CHAR | 1024,
|
||||
"AP_GET_STA_LIST"
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user