diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-08-03 23:12:09 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-08-03 23:12:09 +0200 |
commit | 52215890ef7c4d06fd3323f8315d85f14d637a91 (patch) | |
tree | 2f97aaab909de9fa903ba52224f6f643e2f25cf5 /drivers | |
parent | 4309a7ffa8aa46ac2fc4090cebc3efeb00dce72f (diff) | |
download | kernel_samsung_smdk4412-52215890ef7c4d06fd3323f8315d85f14d637a91.zip kernel_samsung_smdk4412-52215890ef7c4d06fd3323f8315d85f14d637a91.tar.gz kernel_samsung_smdk4412-52215890ef7c4d06fd3323f8315d85f14d637a91.tar.bz2 |
samsung opensource update4
Change-Id: I9db25f213bb1577c4468873c66b230a0566b6cf2
Diffstat (limited to 'drivers')
28 files changed, 801 insertions, 327 deletions
diff --git a/drivers/media/video/s5c73m3.c b/drivers/media/video/s5c73m3.c index 5db5f7f..47c4297 100644 --- a/drivers/media/video/s5c73m3.c +++ b/drivers/media/video/s5c73m3.c @@ -70,9 +70,8 @@ static const struct s5c73m3_frmsizeenum preview_frmsizes[] = { { S5C73M3_PREVIEW_QVGA, 320, 240, 0x01 }, { S5C73M3_PREVIEW_CIF, 352, 288, 0x0E }, { S5C73M3_PREVIEW_VGA, 640, 480, 0x02 }, - { S5C73M3_PREVIEW_704X576, 704, 576, 0x09 }, + { S5C73M3_PREVIEW_800X600, 800, 600, 0x09 }, { S5C73M3_PREVIEW_880X720, 880, 720, 0x03 }, - { S5C73M3_PREVIEW_960X640, 960, 640, 0x0B }, { S5C73M3_PREVIEW_960X720, 960, 720, 0x04 }, { S5C73M3_PREVIEW_1008X672, 1008, 672, 0x0F }, { S5C73M3_PREVIEW_1184X666, 1184, 666, 0x05 }, @@ -80,10 +79,13 @@ static const struct s5c73m3_frmsizeenum preview_frmsizes[] = { { S5C73M3_VDIS_720P, 1536, 864, 0x07 }, { S5C73M3_PREVIEW_1080P, 1920, 1080, 0x0A}, { S5C73M3_VDIS_1080P, 2304, 1296, 0x0C}, + { S5C73M3_PREVIEW_D1, 720, 480, 0x0B }, }; static const struct s5c73m3_frmsizeenum capture_frmsizes[] = { { S5C73M3_CAPTURE_VGA, 640, 480, 0x10 }, + { S5C73M3_CAPTURE_960x540, 960, 540, 0x20 }, + { S5C73M3_CAPTURE_960x720, 960, 720, 0x30 }, { S5C73M3_CAPTURE_1024X768, 1024, 768, 0xD0 }, { S5C73M3_CAPTURE_HD, 1280, 720, 0x40 }, { S5C73M3_CAPTURE_2MP, 1600, 1200, 0x70 }, diff --git a/drivers/media/video/s5c73m3.h b/drivers/media/video/s5c73m3.h index 40d7eaf..aaf4007 100644 --- a/drivers/media/video/s5c73m3.h +++ b/drivers/media/video/s5c73m3.h @@ -71,7 +71,7 @@ enum s5c73m3_prev_frmsize { S5C73M3_PREVIEW_VGA, S5C73M3_PREVIEW_D1, S5C73M3_PREVIEW_WVGA, - S5C73M3_PREVIEW_704X576, + S5C73M3_PREVIEW_800X600, S5C73M3_PREVIEW_880X720, S5C73M3_PREVIEW_960X640, S5C73M3_PREVIEW_960X720, @@ -88,6 +88,8 @@ enum s5c73m3_prev_frmsize { enum s5c73m3_cap_frmsize { S5C73M3_CAPTURE_VGA, /* 640 x 480 */ S5C73M3_CAPTURE_WVGA, /* 800 x 480 */ + S5C73M3_CAPTURE_960x540, /* 960 x 540 */ + S5C73M3_CAPTURE_960x720, /* 960 x 720 */ S5C73M3_CAPTURE_1024X768, /* 1024 x 768 */ S5C73M3_CAPTURE_HD, /* 1280 x 720 */ S5C73M3_CAPTURE_W1MP, /* 1600 x 960 */ diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0b2b5b4..e33a805 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -268,8 +268,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, wait_for_completion(&mrq->completion); cmd = mrq->cmd; - if (!cmd->error || !cmd->retries || - mmc_card_removed(host->card)) + + if (mmc_card_removed(host->card)) return; /* if card is mmc type and nonremovable, and there are erros after diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9f23876..b876dcc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -643,9 +643,14 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) /* timeout in us */ if (!data) target_timeout = cmd->cmd_timeout_ms * 1000; - else - target_timeout = data->timeout_ns / 1000 + - data->timeout_clks / host->clock; + else { + /* patch added for divide by zero once issue. */ + if (host && host->clock) + target_timeout = data->timeout_ns / 1000 + + data->timeout_clks / host->clock; + else + return 0; + } if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) host->timeout_clk = host->clock / 1000; diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 1a27ef0..48e5226 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -17,6 +17,8 @@ DHDCFLAGS += -DPROP_TXSTATUS DHDCFLAGS += -DVSDB -DHT40_GO DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST DHDCFLAGS += -DDHD_USE_IDLECOUNT +DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD +DHDCFLAGS += -DVSDB_DYNAMIC_F2_BLKSIZE -DSDIO_F2_BLKSIZE=512 -DVSDB_F2_BLKSIZE=64 endif ifeq ($(CONFIG_BCM4334),y) DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DBCM4334_CHECK_CHIP_REV @@ -25,26 +27,32 @@ DHDCFLAGS += -DPROP_TXSTATUS DHDCFLAGS += -DVSDB -DHT40_GO DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST DHDCFLAGS += -DDHD_USE_IDLECOUNT +DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD +DHDCFLAGS += -DVSDB_DYNAMIC_F2_BLKSIZE -DSDIO_F2_BLKSIZE=512 -DVSDB_F2_BLKSIZE=64 endif ifeq ($(CONFIG_BCM4330),m) DHDCFLAGS += -DBCM4330_CHIP DHDCFLAGS += -DMCAST_LIST_ACCUMULATION DHDCFLAGS += -DCONFIG_CONTROL_PM +DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE endif ifeq ($(CONFIG_BCM4330),y) DHDCFLAGS += -DBCM4330_CHIP DHDCFLAGS += -DMCAST_LIST_ACCUMULATION DHDCFLAGS += -DCONFIG_CONTROL_PM +DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE endif ifeq ($(CONFIG_BCM43241),m) DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB DHDCFLAGS += -DMCAST_LIST_ACCUMULATION +DHDCFLAGS += -DMIMO_ANT_SETTING -DCONFIG_CONTROL_PM DHDCFLAGS += -fno-pic endif ifeq ($(CONFIG_BCM43241),y) DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB DHDCFLAGS += -DMCAST_LIST_ACCUMULATION +DHDCFLAGS += -DMIMO_ANT_SETTING -DCONFIG_CONTROL_PM endif # For p2p connection issue @@ -70,6 +78,10 @@ ifeq ($(CONFIG_MACH_SAMSUNG_T1),y) DHDCFLAGS += -DUSE_CID_CHECK -DWRITE_MACADDR endif +ifeq ($(CONFIG_MACH_U1_NA_SPR),y) +DHDCFLAGS += -DRDWR_MACADDR +endif + DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API # For Static Buffer @@ -78,7 +90,7 @@ DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF endif # For CCX -ifneq ($(CONFIG_TARGET_LOCALE_KOR),y) +ifeq ($(CONFIG_BRCM_CCX),y) DHDCFLAGS += -DBCMCCX endif @@ -100,7 +112,7 @@ endif ############################################################## # dhd_sec_feature.h -REGION_CODE := $(CONFIG_WLAN_REGION_CODE) +REGION_CODE := 100 ifeq ($(CONFIG_TARGET_LOCALE_KOR),y) REGION_CODE=200 @@ -120,6 +132,10 @@ REGION_CODE=101 endif endif +ifdef CONFIG_WLAN_REGION_CODE +REGION_CODE=$(CONFIG_WLAN_REGION_CODE) +endif + DHDCFLAGS += -DWLAN_REGION_CODE=$(REGION_CODE) ############################################################## @@ -137,7 +153,11 @@ EXTRA_CFLAGS += -I$(src)/src/shared/ EXTRA_CFLAGS += -I$(src)/src/wl/bcmwifi/src/ EXTRA_CFLAGS += -I$(src)/src/wl/bcmwifi/include/ +ifeq ($(CONFIG_MACH_T0), y) +#EXTRA_LDFLAGS += --strip-debug +else EXTRA_LDFLAGS += --strip-debug +endif KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) obj-m += dhd.o diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c index f7676d8..400397e 100644 --- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c @@ -51,7 +51,7 @@ extern void dhdsdio_isr(void * args); #if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) /*SLP_wakelock_alternative_code*/ -struct device *pm_dev; +struct device *pm_dev; #endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ /** * SDIO Host Controller info @@ -188,6 +188,10 @@ int bcmsdh_probe(struct device *dev) /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */ irq = dhd_customer_oob_irq_map(&irq_flags); +#if defined(BCMHOST) + /* Do not disable this IRQ during suspend */ + irq_flags |= IRQF_NO_SUSPEND; +#endif if (irq < 0) { SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); return 1; @@ -237,7 +241,7 @@ int bcmsdh_probe(struct device *dev) #if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) /*SLP_wakelock_alternative_code*/ - pm_dev=sdhc->dev; + pm_dev=sdhc->dev; ret = device_init_wakeup(pm_dev, 1); printf("%s : device_init_wakeup(pm_dev) enable, ret = %d\n", __func__, ret); #endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c index 7d5bcac..d6a110a 100644 --- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c @@ -522,6 +522,19 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, /* Now set it */ si->client_block_size[func] = blksize; +#ifdef VSDB_DYNAMIC_F2_BLKSIZE + if (gInstance == NULL || gInstance->func[func] == NULL) { + sd_err(("%s: SDIO Device not present\n", __FUNCTION__)); + bcmerror = BCME_NORESOURCE; + break; + } + sdio_claim_host(gInstance->func[func]); + bcmerror = sdio_set_block_size(gInstance->func[func], blksize); + if (bcmerror) { + sd_err(("%s: Failed to set F%d blocksize to %d\n", __FUNCTION__, func, blksize)); + } + sdio_release_host(gInstance->func[func]); +#endif break; } @@ -1044,6 +1057,10 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, else if(pkt_len % DHD_SDALIGN) // write pkt_len += DHD_SDALIGN - (pkt_len % DHD_SDALIGN); +#ifdef VSDB_DYNAMIC_F2_BLKSIZE + if (write && pkt_len > 64 && (pkt_len % 64) == 32) + pkt_len += 32; +#endif #ifdef CONFIG_MMC_MSM7X00A if ((pkt_len % 64) == 32) { sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c index 83c1192..ca8478b 100644 --- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c @@ -202,7 +202,7 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) dhd_mmc_suspend = TRUE; #if defined (CUSTOMER_HW_SAMSUNG) && defined (CONFIG_ARCH_TEGRA) irq_set_irq_wake(390, 1); -#endif +#endif smp_mb(); return 0; @@ -225,7 +225,7 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) #if defined (CUSTOMER_HW_SAMSUNG) && defined (CONFIG_ARCH_TEGRA) if (func->num == 2) irq_set_irq_wake(390, 0); -#endif +#endif smp_mb(); return 0; @@ -276,11 +276,13 @@ static struct sdio_driver bcmsdh_sdmmc_driver = { .remove = bcmsdh_sdmmc_remove, .name = "bcmsdh_sdmmc", .id_table = bcmsdh_sdmmc_ids, +#if !defined(BCMHOST) #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) .drv = { .pm = &bcmsdh_sdmmc_pm_ops, }, #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ +#endif }; struct sdos_info { diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h index 5095aba..44fd410 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h @@ -257,6 +257,7 @@ typedef struct dhd_pub { int wlfc_enabled; void* wlfc_state; #endif + bool roam_env_detection; bool dongle_isolation; bool dongle_trap_occured; int hang_was_sent; @@ -700,6 +701,8 @@ extern char fw_down_path[MOD_PARAM_PATHLEN]; #define DHD_DEL_IF -0xe #define DHD_BAD_IF -0xf +#define WL_AUTO_ROAM_TRIGGER -75 + #ifdef PROP_TXSTATUS /* Please be mindful that total pkttag space is 32 octets only */ typedef struct dhd_pkttag { diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c index 1610b7f..0cb4fb4 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c @@ -69,6 +69,11 @@ typedef struct dhd_wlfc_commit_info { } dhd_wlfc_commit_info_t; #endif /* PROP_TXSTATUS */ +#ifdef VSDB_DYNAMIC_F2_BLKSIZE +extern uint sd_f2_blocksize; +extern int +dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); +#endif typedef struct dhd_prot { uint16 reqid; uint8 pending; @@ -458,10 +463,12 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ea = interfaces[i].ea; bcm_bprintf(strbuf, "INTERFACE[%d].ea = " - "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d, type: %s\n", i, + "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d, type: %s" + "netif_flow_control:%s\n", i, ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], interfaces[i].interface_id, - iftype_desc); + iftype_desc, ((wlfc->hostif_flow_state[i] == OFF) + ? " OFF":" ON")); bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ(len,state,credit)" "= (%d,%s,%d)\n", @@ -696,6 +703,32 @@ dhd_wlfc_hanger_get_free_slot(void* hanger) } static int +dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen) +{ + int rc = BCME_OK; + wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + + *gen = 0xff; + + /* this packet was not pushed at the time it went to the firmware */ + if (slot_id == WLFC_HANGER_MAXITEMS) + return BCME_NOTFOUND; + + if (h) { + if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) || + (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) { + *gen = h->items[slot_id].gen; + } + else { + rc = BCME_NOTFOUND; + } + } + else + rc = BCME_BADARG; + return rc; +} + +static int dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id) { int rc = BCME_OK; @@ -729,13 +762,14 @@ dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_f return BCME_NOTFOUND; if (h) { - if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { + if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) { *pktout = h->items[slot_id].pkt; if (remove_from_hanger) { h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_FREE; h->items[slot_id].pkt = NULL; h->items[slot_id].identifier = 0; + h->items[slot_id].gen = 0xff; h->popped++; } } @@ -750,6 +784,29 @@ dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_f } static int +dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen) +{ + int rc = BCME_OK; + wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + + /* this packet was not pushed at the time it went to the firmware */ + if (slot_id == WLFC_HANGER_MAXITEMS) + return BCME_NOTFOUND; + if (h) { + h->items[slot_id].gen = gen; + if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { + h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED; + } + else + rc = BCME_BADARG; + } + else + rc = BCME_BADARG; + + return rc; +} + +static int _dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal, uint8 tim_bmp, uint8 mac_handle, uint32 htodtag) { @@ -934,7 +991,9 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint pq->len, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("F")); - /* dhd_txflowcontrol(ctx->dhdp, if_id, OFF); */ +#ifndef BCMDBUS + dhd_txflowcontrol(ctx->dhdp, if_id, OFF); +#endif ctx->toggle_host_if = 0; } if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { @@ -945,7 +1004,10 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint pq->len, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("N")); - /* dhd_txflowcontrol(ctx->dhdp, if_id, ON); */ + /* XXX: debug in progress */ +#ifndef BCMDBUS + dhd_txflowcontrol(ctx->dhdp, if_id, ON); +#endif ctx->host_ifidx = if_id; ctx->toggle_host_if = 1; } @@ -1079,6 +1141,8 @@ _dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, hslot = dhd_wlfc_hanger_get_free_slot(ctx->hanger); free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); + WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); + entry->transit_count++; } else { hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); @@ -1089,7 +1153,7 @@ _dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1); WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); - WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); + if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { /* @@ -1127,10 +1191,15 @@ _dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, } } else { + int gen; + /* remove old header */ _dhd_wlfc_pullheader(ctx, p); hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); + dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen); + + WLFC_PKTFLAG_SET_GENERATION(htod, gen); free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); /* push new header */ _dhd_wlfc_pushheader(ctx, p, send_tim_update, @@ -1195,17 +1264,27 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, /* higher precedence will be picked up first, i.e. suppressed packets before delayed ones */ - (NBITVAL((prec << 1) + 1) | NBITVAL((prec << 1))), - &pout); + NBITVAL((prec << 1) + 1), &pout); + *needs_hdr = 0; + + if (p == NULL) { + if (entry->suppressed == TRUE) { + if ((entry->suppr_transit_count <= + entry->suppress_count)) { + entry->suppressed = FALSE; + } else { + return NULL; + } + } + /* De-Q from delay Q */ + p = pktq_mdeq(&entry->psq, + NBITVAL((prec << 1)), + &pout); + *needs_hdr = 1; + } + if (p != NULL) { /* did the packet come from suppress sub-queue? */ - if (pout == ((prec << 1) + 1)) { - /* - this packet was suppressed and was sent on the bus - previously; this already has a header - */ - *needs_hdr = 0; - } if (entry->requested_credit > 0) { entry->requested_credit--; #ifdef PROP_TXSTATUS_DEBUG @@ -1248,13 +1327,11 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, } static void* -_dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec, uint8* ac_credit_spent) +_dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec) { wlfc_mac_descriptor_t* entry; void* p; - /* most cases a packet will count against FIFO credit */ - *ac_credit_spent = 1; p = pktq_pdeq(&ctx->SENDQ, prec); if (p != NULL) { @@ -1269,7 +1346,7 @@ _dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec, uint8* ac_credit_s return p; } - while ((p != NULL) && _dhd_wlfc_is_destination_closed(ctx, entry, prec)) { + while ((p != NULL)) { /* - suppressed packets go to sub_queue[2*prec + 1] AND - delayed packets go to sub_queue[2*prec + 0] to ensure @@ -1286,7 +1363,7 @@ _dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec, uint8* ac_credit_s if applicable */ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); - _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p))); + p = pktq_pdeq(&ctx->SENDQ, prec); if (p == NULL) break; @@ -1297,23 +1374,6 @@ _dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec, uint8* ac_credit_s return p; } } - if (p) { - if (entry->requested_packet == 0) { - if (entry->requested_credit > 0) - entry->requested_credit--; - } - else { - entry->requested_packet--; - DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); - } - if (entry->state == WLFC_STATE_CLOSE) - *ac_credit_spent = 0; -#ifdef PROP_TXSTATUS_DEBUG - entry->dstncredit_sent_packets++; -#endif - } - if (p) - _dhd_wlfc_flow_control_check(ctx, &ctx->SENDQ, DHD_PKTTAG_IF(PKTTAG(p))); } return p; } @@ -1444,41 +1504,13 @@ dhd_wlfc_enque_sendq(void* state, int prec, void* p) } int -dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) +_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) { - int ac; - int credit; - uint8 ac_fifo_credit_spent; - uint8 needs_hdr; uint32 hslot; - void* p; int rc; - athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; - wlfc_mac_descriptor_t* mac_entry; - - if ((state == NULL) || - (fcommit == NULL)) { - WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); - return BCME_BADARG; - } /* - Commit packets for regular AC traffic. Higher priority first. - - -NOTE: - If the bus between the host and firmware is overwhelmed by the - traffic from host, it is possible that higher priority traffic - starves the lower priority queue. If that occurs often, we may - have to employ weighted round-robin or ucode scheme to avoid - low priority packet starvation. - */ - for (ac = AC_COUNT; ac >= 0; 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) - break; - /* if ac_fifo_credit_spent = 0 This packet will not count against the FIFO credit. @@ -1491,77 +1523,227 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) 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); + 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, p); + rc = fcommit(commit_ctx, commit_info->p); else ctx->stats.generic_error++; if (rc == BCME_OK) { ctx->stats.pkt2bus++; - if (ac_fifo_credit_spent) { + if (commit_info->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. - */ - credit++; } } else { - /* bus commit has failed, rollback. */ - rc = _dhd_wlfc_rollback_packet_toq(ctx, - p, /* + bus commit has failed, rollback. - remove wl-header for a delayed packet - save wl-header header for suppressed packets */ - (needs_hdr ? eWLFC_PKTTYPE_DELAYED : - eWLFC_PKTTYPE_SUPPRESSED), - hslot); + 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; + int rc; + dhd_wlfc_commit_info_t commit_info; + athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; + int credit_count = 0; + int bus_retry_count = 0; + uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */ + + if ((state == NULL) || + (fcommit == NULL)) { + WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); + return BCME_BADARG; } - ctx->FIFO_credit[ac] -= credit; - /* packets from SENDQ are fresh and they'd need header */ - needs_hdr = 1; + + 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 + traffic from host, it is possible that higher priority traffic + starves the lower priority queue. If that occurs often, we may + 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]; + + /* 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; + + do { + commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac); + if (commit_info.p == NULL) + break; + else if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(commit_info.p)))) { + ASSERT(ac == AC_COUNT); + + if (ctx->FIFO_credit[ac]) { + 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((" %s: bus error\n", + __FUNCTION__)); + return rc; + } + } + } + } + + } while (commit_info.p); + 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_delayedq(ctx, ac, + &(commit_info.ac_fifo_credit_spent), + &(commit_info.needs_hdr), + &(commit_info.mac_entry)); + + 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++; + 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) { - 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; + } + } + } + return BCME_OK; } @@ -1676,10 +1858,16 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) return ret; } + entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); + if (!remove_from_hanger) { /* this packet was suppressed */ - - entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); + if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { + entry->suppressed = TRUE; + entry->suppress_count = pktq_mlen(&entry->psq, + NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); + entry->suppr_transit_count = entry->transit_count; + } entry->generation = WLFC_PKTID_GEN(status); } @@ -1754,11 +1942,28 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) /* indicate failure and free the packet */ dhd_txcomplete(dhd, pktbuf, FALSE); + entry->transit_count--; + /* This packet is transmitted Successfully by dongle even after first suppress. */ + if (entry->suppressed){ + entry->suppr_transit_count--; + } PKTFREE(wlfc->osh, pktbuf, TRUE); + } else { + /* Mark suppressed to avoid a double free during wlfc cleanup */ + + dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, + WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); + entry->suppress_count++; } } else { dhd_txcomplete(dhd, pktbuf, TRUE); + entry->transit_count--; + + /* This packet is transmitted Successfully by dongle even after first suppress. */ + if (entry->suppressed){ + entry->suppr_transit_count--; + } /* free the packet */ PKTFREE(wlfc->osh, pktbuf, TRUE); } @@ -2093,6 +2298,7 @@ dhd_wlfc_init(dhd_pub_t *dhd) WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS | WLFC_FLAGS_CREDIT_STATUS_SIGNALS | + WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; /* WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; */ @@ -2168,7 +2374,9 @@ dhd_wlfc_enable(dhd_pub_t *dhd) wlfc->allow_credit_borrow = TRUE; wlfc->borrow_defer_timestamp = 0; - +#ifdef VSDB_DYNAMIC_F2_BLKSIZE + dhdsdio_func_blocksize(dhd, 2, VSDB_F2_BLKSIZE); +#endif return BCME_OK; } @@ -2210,8 +2418,9 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; - h->items[i].pkt = NULL; - h->items[i].identifier = 0; + } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { + /* These are freed from the psq so no need to free again */ + h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; } } return; @@ -2232,7 +2441,7 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) int i; wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger; for (i = 0; i < h->max_items; i++) { - if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { + if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) { WLFC_DBGMESG(("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n", __FUNCTION__, i, h->items[i].pkt, DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt)))); @@ -2246,6 +2455,9 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) /* free top structure */ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); dhd->wlfc_state = NULL; +#ifdef VSDB_DYNAMIC_F2_BLKSIZE + dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); +#endif return; } #endif /* PROP_TXSTATUS */ diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c index c0ef0bd..61369cb 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c @@ -507,7 +507,6 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) int i; #endif - /* Figure out powermode 1 or o command */ strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); WL_ERR(("%s: DHCP session Enter\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c index f9f8c20..9fda3c1 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c @@ -295,16 +295,17 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le #ifdef CUSTOMER_HW_SAMSUNG if (ret < 0) { if (ioc->cmd == WLC_GET_VAR) - DHD_ERROR(("%s: WLC_GET_VAR: %s, error = %d\n", + DHD_ERROR(("%s: WLC_GET_VAR: %s, ret = %d\n", __FUNCTION__, (char *)ioc->buf, ret)); else if (ioc->cmd == WLC_SET_VAR) - DHD_ERROR(("%s: WLC_SET_VAR: %s, error = %d\n", + DHD_ERROR(("%s: WLC_SET_VAR: %s, ret = %d\n", __FUNCTION__, (char *)ioc->buf, ret)); else - DHD_ERROR(("%s: WLC_IOCTL: cmd: %d, error = %d\n", + DHD_ERROR(("%s: WLC_IOCTL: cmd: %d, ret = %d\n", __FUNCTION__, ioc->cmd, ret)); } #endif /* CUSTOMER_HW_SAMSUNG */ + return ret; } diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c index 4ef1dcb..74c5da3 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c @@ -35,6 +35,7 @@ extern int _dhd_set_mac_address(struct dhd_info *dhd, #define CIDINFO "/opt/etc/.cid.info" #define PSMINFO "/opt/etc/.psm.info" #define MACINFO "/opt/etc/.mac.info" +#define MACINFO_EFS NULL #define REVINFO "/data/.rev" #else #define MACINFO "/data/.mac.info" @@ -585,14 +586,14 @@ int dhd_check_module_cid(dhd_pub_t *dhd) ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { - DHD_ERROR(("%s: CIS reading failed, err=%d\n", + DHD_TRACE(("%s: CIS reading failed, err=%d\n", __FUNCTION__, ret)); return ret; } else { #ifdef BCM4334_CHIP unsigned char semco_id[4] = {0x00, 0x00, 0x33, 0x33}; unsigned char semco_id_sh[4] = {0x00, 0x00, 0xFB, 0x50}; //for SHARP FEM(new) - DHD_ERROR(("%s: CIS reading success, err=%d\n", + DHD_ERROR(("%s: CIS reading success, ret=%d\n", __FUNCTION__, ret)); #ifdef DUMP_CIS dump_cis(cis_buf, 48); @@ -725,7 +726,7 @@ int dhd_check_module_mac(dhd_pub_t *dhd) ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { - DHD_ERROR(("%s: CIS reading failed, err=%d\n", __func__, + DHD_TRACE(("%s: CIS reading failed, err=%d\n", __func__, ret)); return ret; } else { @@ -814,6 +815,11 @@ startwrite: filp_close(fp_mac, NULL); /* end of /data/.mac.info */ + if (filepath_efs == NULL) { + DHD_ERROR(("[WIFI]%s : no efs filepath", __func__)); + return 0; + } + /* File will be created /efs/wifi/.mac.info. */ fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c index ca43dda..0cd3971 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c @@ -556,7 +556,7 @@ static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) { int ret = NOTIFY_DONE; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) || defined(BCMHOST) switch (action) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: @@ -1237,13 +1237,13 @@ dhd_op_if(dhd_if_t *ifp) /* dhd_op_if is called again from some other context */ ifp->state = DHD_IF_DELETING; if (ifp->net != NULL) { - DHD_TRACE(("\n%s: got 'DHD_IF_DEL' state\n", __FUNCTION__)); + DHD_ERROR(("\n%s: (WAR TRACE) got 'DHD_IF_DEL' state\n", __FUNCTION__)); + netif_stop_queue(ifp->net); #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { wl_cfg80211_notify_ifdel(ifp->net); } #endif - netif_stop_queue(ifp->net); unregister_netdev(ifp->net); ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ } @@ -1347,7 +1347,7 @@ _dhd_sysioc_thread(void *data) } if (dhd->set_macaddress == i+1) { dhd->set_macaddress = 0; - if (0 == _dhd_set_mac_address(dhd, i, &dhd->macvalue)) + if (0 == _dhd_set_mac_address(dhd, i, &dhd->macvalue)) DHD_INFO(("dhd_sysioc_thread: MACID is overwritten\n")); else DHD_ERROR(("dhd_sysioc_thread: _dhd_set_mac_address() failed\n")); @@ -1530,7 +1530,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) * kernel panic issue when first bootup time, * rmmod without interface down make unnecessary hang event. */ - if (dhd->pub.busstate == DHD_BUS_DOWN) { + if (dhd->pub.busstate == DHD_BUS_DOWN || dhd->pub.hang_was_sent) { DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n", __FUNCTION__, dhd->pub.up, dhd->pub.busstate)); netif_stop_queue(net); @@ -2363,8 +2363,17 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) { + dhd_info_t * dhd; + if (!dhdp) return FALSE; + + dhd = (dhd_info_t *)dhdp->info; + if (dhd->thr_sysioc_ctl.thr_pid <0) { + DHD_ERROR(("%s : skipped due to negative pid - unloading?\n", __FUNCTION__)); + return FALSE; + } + if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || ((dhdp->busstate == DHD_BUS_DOWN)&&(!dhdp->dongle_reset))) { DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__, @@ -2612,7 +2621,7 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) for (i = 1; i < DHD_MAX_IFS; i++) { if (dhd->iflist[i]) { - DHD_TRACE(("Deleting IF: %d \n", i)); + DHD_ERROR(("(WAR TRACE)Deleting IF: %d \n", i)); if ((dhd->iflist[i]->state != DHD_IF_DEL) && (dhd->iflist[i]->state != DHD_IF_DELETING)) { dhd->iflist[i]->state = DHD_IF_DEL; @@ -2646,7 +2655,7 @@ dhd_stop(struct net_device *net) int ifidx; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); DHD_OS_WAKE_LOCK(&dhd->pub); - DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net)); + DHD_TRACE(("%s: (WAR TRACE)Enter %p\n", __FUNCTION__, net)); if (dhd->pub.up == 0) { goto exit; } @@ -3429,9 +3438,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef CUSTOMER_HW_SAMSUNG #ifdef ROAM_ENABLE uint roamvar = 0; - int roam_trigger[2] = {-75, WLC_BAND_ALL}; + int roam_trigger[2] = {WL_AUTO_ROAM_TRIGGER, WLC_BAND_ALL}; int roam_scan_period[2] = {10, WLC_BAND_ALL}; int roam_delta[2] = {10, WLC_BAND_ALL}; + int roam_env_mode = AP_ENV_INDETERMINATE; #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC int roam_fullscan_period = 60; #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ @@ -3639,6 +3649,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, sizeof(roam_delta), TRUE, 0); bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) { + bcm_mkiovar("roam_env_detection", (char *)&roam_env_mode, 4, iovbuf, sizeof(iovbuf)); + if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) == BCME_OK) + dhd->roam_env_detection = TRUE; + else + dhd->roam_env_detection = FALSE; + } #endif #ifdef OKC_SUPPORT @@ -3735,7 +3752,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_MIC_ERROR); setbit(eventmask, WLC_E_ASSOC_REQ_IE); setbit(eventmask, WLC_E_ASSOC_RESP_IE); +#ifndef WL_CFG80211 setbit(eventmask, WLC_E_PMKID_CACHE); +#endif setbit(eventmask, WLC_E_TXFAIL); setbit(eventmask, WLC_E_JOIN_START); setbit(eventmask, WLC_E_SCAN_COMPLETE); @@ -3833,7 +3852,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* defined(SOFTAP) */ if (dhd->pktfilter_count) { int i; - + for (i = 0; i < dhd->pktfilter_count; i++) dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); } @@ -5089,7 +5108,7 @@ int net_os_set_packet_filter(struct net_device *dev, int val) for (i = 0; i < dhd->pub.pktfilter_count; i++) dhd_pktfilter_offload_enable(&dhd->pub, dhd->pub.pktfilter[i], val, dhd_master_mode); - } + } } } return ret; @@ -5375,7 +5394,7 @@ int dhd_os_wake_lock(dhd_pub_t *pub) wake_lock(&dhd->wl_wifi); #elif defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) /*SLP_wakelock_alternative_code*/ - pm_stay_awake(pm_dev); + pm_stay_awake(pm_dev); #endif dhd->wakelock_counter++; ret = dhd->wakelock_counter; @@ -5410,7 +5429,7 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) wake_unlock(&dhd->wl_wifi); #elif defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) /*SLP_wakelock_alternative_code*/ - pm_relax(pm_dev); + pm_relax(pm_dev); #endif ret = dhd->wakelock_counter; } @@ -5438,7 +5457,7 @@ int dhd_os_check_wakelock(void *dhdp) if (!pub) return 0; - dhd = (dhd_info_t *)(pub->info); + dhd = (dhd_info_t *)(pub->info); DHD_ERROR(("%s : wakelock_count = %d\n", __func__, dhd->wakelock_counter )); diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c index 052eaaf..211c865 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c @@ -179,6 +179,8 @@ char fw_down_path[MOD_PARAM_PATHLEN]; #define MIN_RSRC_SR 0x3 #define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c) #define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1) +#define RCTL_MACPHY_DISABLE_MASK (1 << 26) +#define RCTL_LOGIC_DISABLE_MASK (1 << 27) #define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup) #define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */ @@ -609,22 +611,21 @@ static bool dhdsdio_sr_cap(dhd_bus_t *bus) { bool cap = FALSE; - uint32 min = 0, core_capext; + uint32 min = 0, core_capext, data; core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4); if (!(core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK)) return FALSE; + if (bus->sih->chip == BCM4324_CHIP_ID) { min = bcmsdh_reg_read(bus->sdh, MIN_RSRC_ADDR, 4); - if (min == MIN_RSRC_SR) { + if (min == MIN_RSRC_SR) cap = TRUE; - - if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev < 3)) { - cap = FALSE; - - DHD_ERROR(("Only 4334 >= B2 supports SR: curr rev %d\n", - bus->sih->chiprev)); - } + } else { + data = bcmsdh_reg_read(bus->sdh, + SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4); + if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0) + cap = TRUE; } return cap; @@ -1313,6 +1314,38 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) return err; } +#ifdef VSDB_DYNAMIC_F2_BLKSIZE +int +dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) +{ + int func_blk_size = function_num; + int bcmerr = 0; + int result; + + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, sizeof(int), &result, sizeof(int), 0); + + if (bcmerr != BCME_OK) { + DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num)); + return BCME_ERROR; + } + + if (result != block_size) { + + DHD_ERROR(("%s: F%d Block size set from %d to %d\n", __FUNCTION__, function_num, result, block_size)); + + func_blk_size = function_num << 16 | block_size ; + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, sizeof(int32), &result, sizeof(int32), 1); + + if (bcmerr != BCME_OK) { + DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__)); + return BCME_ERROR; + } + } + + return BCME_OK; + +} +#endif #if defined(OOB_INTR_ONLY) void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) @@ -1955,10 +1988,10 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) #endif #endif /* DHD_DEBUG */ } else if (pending == TRUE) { - DHD_CTL(("%s: canceled\n", __FUNCTION__)); + DHD_ERROR(("%s: canceled\n", __FUNCTION__)); return -ERESTARTSYS; } else { - DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); + DHD_ERROR(("%s: resumed for unknown reason?\n", __FUNCTION__)); #ifdef DHD_DEBUG dhd_os_sdlock(bus->dhd); dhdsdio_checkdied(bus, NULL, 0); @@ -3942,7 +3975,10 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) uint8 *dptr, num = 0; uint16 sublen, check; - void *pfirst, *plast, *pnext, *save_pfirst; + void *pfirst, *plast, *pnext; + void * list_tail[DHD_MAX_IFS] = { NULL }; + void * list_head[DHD_MAX_IFS] = { NULL }; + uint8 idx; osl_t *osh = bus->dhd->osh; int errcode; @@ -4231,7 +4267,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) } /* Basic SD framing looks ok - process each packet (header) */ - save_pfirst = pfirst; bus->glom = NULL; plast = NULL; @@ -4274,9 +4309,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) PKTFREE(bus->dhd->osh, pfirst, FALSE); if (plast) { PKTSETNEXT(osh, plast, pnext); - } else { - ASSERT(save_pfirst == pfirst); - save_pfirst = pnext; } continue; } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf, @@ -4286,9 +4318,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) PKTFREE(osh, pfirst, FALSE); if (plast) { PKTSETNEXT(osh, plast, pnext); - } else { - ASSERT(save_pfirst == pfirst); - save_pfirst = pnext; } continue; } @@ -4304,9 +4333,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) if (free_buf_count == 0) { if (plast) { PKTSETNEXT(osh, plast, pnext); - } else { - ASSERT(save_pfirst == pfirst); - save_pfirst = pnext; } continue; } @@ -4319,15 +4345,14 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) temp = PKTNEXT(osh, temp); } pfirst = temp; - if (plast) { - PKTSETNEXT(osh, plast, ppfirst); + if (list_tail[ifidx] == NULL) { + list_head[ifidx] = ppfirst; + list_tail[ifidx] = pfirst; } else { - /* first one in the chain */ - save_pfirst = ppfirst; + PKTSETNEXT(osh, list_tail[ifidx], ppfirst); + list_tail[ifidx] = pfirst; } - - PKTSETNEXT(osh, pfirst, pnext); plast = pfirst; } @@ -4335,8 +4360,14 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) } else { /* this packet will go up, link back into chain and count it */ - PKTSETNEXT(osh, pfirst, pnext); plast = pfirst; + if (list_tail[ifidx] == NULL) { + list_head[ifidx] = list_tail[ifidx] = pfirst; + } + else { + PKTSETNEXT(osh, list_tail[ifidx], pfirst); + list_tail[ifidx] = pfirst; + } num++; } #ifdef DHD_DEBUG @@ -4351,12 +4382,22 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) #endif /* DHD_DEBUG */ } dhd_os_sdunlock_rxq(bus->dhd); - if (num) { - dhd_os_sdunlock(bus->dhd); - dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num, 0); - dhd_os_sdlock(bus->dhd); + for (idx = 0; idx < DHD_MAX_IFS; idx++) { + if (list_head[idx]) { + void *temp; + uint8 cnt = 0; + temp = list_head[idx]; + do { + temp = PKTNEXT(osh, temp); + cnt++; + } while (temp); + if (cnt) { + dhd_os_sdunlock(bus->dhd); + dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0); + dhd_os_sdlock(bus->dhd); + } + } } - bus->rxglomframes++; bus->rxglompkts += num; } @@ -5805,7 +5846,7 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) } else dhdsdio_clkctl(bus, CLK_NONE, FALSE); - bus->idlecount = 0; + bus->idlecount = 0; } } #else @@ -6130,7 +6171,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, #ifdef BCMHOST_XTAL_PU_TIME_MOD #ifdef BCM4334_CHIP bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11); - bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00A60001); + bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001); #endif #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h index 2d1d200..d6bb7f0 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h @@ -49,11 +49,20 @@ #define WRITE_MACADDR #endif +#ifdef CONFIG_ARCH_MSM7X30 +#define HW_OOB +#define READ_MACADDR +#endif + #ifdef CONFIG_MACH_GC1 #undef USE_CID_CHECK #define READ_MACADDR #endif +#ifdef CONFIG_MACH_P10 +#define READ_MACADDR +#endif + /* REGION CODE */ #if (WLAN_REGION_CODE >= 100) && (WLAN_REGION_CODE < 200) /*EUR*/ @@ -89,7 +98,7 @@ #undef WRITE_MACADDR #undef READ_MACADDR #ifdef CONFIG_BCM4334 -#define RDWR_KORICS_MACADDR +#define READ_MACADDR #else #define RDWR_MACADDR #endif @@ -115,3 +124,4 @@ #if !defined(READ_MACADDR) && !defined(WRITE_MACADDR) && !defined(RDWR_KORICS_MACADDR) && !defined(RDWR_MACADDR) #define GET_MAC_FROM_OTP #endif + diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_wlfc.h index c8b3181..308e318 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_wlfc.h +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_wlfc.h @@ -29,6 +29,7 @@ #define WLFC_HANGER_ITEM_STATE_FREE 1 #define WLFC_HANGER_ITEM_STATE_INUSE 2 +#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 #define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ #define WLFC_PKTID_HSLOT_SHIFT 8 @@ -68,7 +69,8 @@ typedef enum ewlfc_mac_entry_action { typedef struct wlfc_hanger_item { uint8 state; - uint8 pad[3]; + uint8 gen; + uint8 pad[2]; uint32 identifier; void* pkt; #ifdef PROP_TXSTATUS_DEBUG @@ -93,12 +95,12 @@ typedef struct wlfc_hanger { #define WLFC_STATE_CLOSE 2 #define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */ -#define WLFC_PSQ_LEN 64 -#define WLFC_SENDQ_LEN 256 +#define WLFC_PSQ_LEN 2048 +#define WLFC_SENDQ_LEN 256 /* XXX: Match dhd_sdio txq length */ + +#define WLFC_FLOWCONTROL_HIWATER (2048 - 256) +#define WLFC_FLOWCONTROL_LOWATER 256 -#define WLFC_FLOWCONTROL_DELTA 8 -#define WLFC_FLOWCONTROL_HIWATER (WLFC_PSQ_LEN - WLFC_FLOWCONTROL_DELTA) -#define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER - WLFC_FLOWCONTROL_DELTA) typedef struct wlfc_mac_descriptor { uint8 occupied; @@ -123,6 +125,11 @@ typedef struct wlfc_mac_descriptor { /* 1= send on next opportunity */ uint8 send_tim_signal; uint8 mac_handle; + uint transit_count; + uint suppr_transit_count; + uint suppress_count; + uint8 suppressed; + #ifdef PROP_TXSTATUS_DEBUG uint32 dstncredit_sent_packets; uint32 dstncredit_acks; diff --git a/drivers/net/wireless/bcmdhd/src/include/epivers.h b/drivers/net/wireless/bcmdhd/src/include/epivers.h index 8be59f6..4e873bb 100644 --- a/drivers/net/wireless/bcmdhd/src/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/src/include/epivers.h @@ -30,19 +30,19 @@ #define EPI_MINOR_VERSION 15 -#define EPI_RC_NUMBER 12 +#define EPI_RC_NUMBER 15 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 15, 12, 0 +#define EPI_VERSION 1, 15, 15, 0 -#define EPI_VERSION_NUM 0x010f0900 +#define EPI_VERSION_NUM 0x010f0f00 -#define EPI_VERSION_DEV 1.15.12 +#define EPI_VERSION_DEV 1.15.15 -#define EPI_VERSION_STR "1.15.12" +#define EPI_VERSION_STR "1.15.15" #endif /* _epivers_h_ */ diff --git a/drivers/net/wireless/bcmdhd/src/include/sbchipc.h b/drivers/net/wireless/bcmdhd/src/include/sbchipc.h index e6a76b8..03039a6 100644 --- a/drivers/net/wireless/bcmdhd/src/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/src/include/sbchipc.h @@ -289,7 +289,11 @@ typedef volatile struct { uint32 pllcontrol_data; uint32 pmustrapopt; uint32 pmu_xtalfreq; - uint32 PAD[100]; + uint32 retention_ctl; + uint32 PAD[3]; + uint32 retention_grpidx; + uint32 retention_grpctl; + uint32 PAD[94]; uint16 sromotp[512]; uint32 nand_revision; diff --git a/drivers/net/wireless/bcmdhd/src/include/wlioctl.h b/drivers/net/wireless/bcmdhd/src/include/wlioctl.h index 72a54ce..d6bdb8f 100644 --- a/drivers/net/wireless/bcmdhd/src/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/src/include/wlioctl.h @@ -1867,6 +1867,12 @@ typedef struct wl_po { #define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ #define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ +/* AP environment */ +#define AP_ENV_DETECT_NOT_USED 0 /* We aren't using AP environment detection */ +#define AP_ENV_DENSE 1 /* "Corporate" or other AP dense environment */ +#define AP_ENV_SPARSE 2 /* "Home" or other sparse environment */ +#define AP_ENV_INDETERMINATE 3 /* AP environment hasn't been identified */ + typedef struct wl_aci_args { int enter_aci_thresh; /* Trigger level to start detecting ACI */ int exit_aci_thresh; /* Trigger level to exit ACI mode */ diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c index 49782c5..7f1b86c 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c @@ -129,9 +129,10 @@ typedef struct cmd_tlv { #define CMD_OKC_ENABLE "OKC_ENABLE" #endif -#ifdef BCM4334_CHIP //ampdu_mpdu +#ifdef SUPPORT_AMPDU_MPDU_CMD #define CMD_AMPDU_MPDU "AMPDU_MPDU" #endif + #ifdef VSDB #define CMD_CHANGE_RL "CHANGE_RL" #define CMD_RESTORE_RL "RESTORE_RL" @@ -234,11 +235,11 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int if (!dhd_download_fw_on_driverload) { #endif /* CUSTOMER_HW_SAMSUNG */ suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0'; - + if (suspend_flag != 0) suspend_flag = 1; ret_now = net_os_set_suspend_disable(dev, suspend_flag); - + if (ret_now != suspend_flag) { if (!(ret = net_os_set_suspend(dev, ret_now))) DHD_INFO(("%s: Suspend Flag %d -> %d\n", @@ -407,13 +408,9 @@ static int wl_android_get_country_rev( __func__, error)); return -1; } else { - DHD_INFO(("%s: get country '%c%c %d'\n", - __func__, cspec.ccode[0], cspec.ccode[1], cspec.rev)); + DHD_INFO(("%s: get country '%s %d'\n", __func__, smbuf, smbuf[WLC_CNTRY_BUF_SZ])); } - - bytes_written = snprintf(command, total_len, "%c%c %d", - cspec.ccode[0], cspec.ccode[1], cspec.rev); - + bytes_written = snprintf(command, total_len, "%s %s %d", CMD_COUNTRYREV_GET, smbuf, smbuf[WLC_CNTRY_BUF_SZ]); return bytes_written; } #endif /* ROAM_API */ @@ -706,20 +703,6 @@ static int wl_android_set_fwpath(struct net_device *net, char *command, int tota return 0; } -static int my_atoi(const char *string_num) -{ - int int_val=0; - for(;; string_num++) { - switch (*string_num) { - case '0'...'9' : - int_val = 10 * int_val + (*string_num-'0'); - break; - default: - return int_val; - } - } - return int_val; -} static int wl_android_set_auto_channel(struct net_device *dev, const char* string_num, @@ -737,7 +720,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* string_num, /* Auto channel select */ wl_uint32_list_t request; - channel = my_atoi(string_num); + channel = bcm_atoi(string_num); DHD_INFO(("%s : HAPD_AUTO_CHANNEL = %d\n", __FUNCTION__, channel)); if (channel == 20) @@ -794,7 +777,7 @@ wl_android_set_max_num_sta(struct net_device *dev, const char* string_num) { int max_assoc; - max_assoc = my_atoi(string_num); + max_assoc = bcm_atoi(string_num); DHD_INFO(("%s : HAPD_MAX_NUM_STA = %d\n", __FUNCTION__, max_assoc)); wldev_iovar_setint(dev, "maxassoc", max_assoc); return 1; @@ -823,7 +806,7 @@ wl_android_set_hide_ssid(struct net_device *dev, const char* string_num) int hide_ssid; int enable = 0; - hide_ssid = my_atoi(string_num); + hide_ssid = bcm_atoi(string_num); DHD_INFO(("%s: HAPD_HIDE_SSID = %d\n", __FUNCTION__, hide_ssid)); if (hide_ssid) enable = 1; @@ -926,7 +909,8 @@ wl_android_ch_res_rl(struct net_device *dev, bool change) } #endif -#ifdef BCM4334_CHIP //ampdu_mpdu +#ifdef SUPPORT_AMPDU_MPDU_CMD +/* CMD_AMPDU_MPDU */ static int wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) { @@ -946,7 +930,7 @@ wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) DHD_ERROR(("%s : ampdu_mpdu set error. %d\n", __FUNCTION__, err)); return -1; } - + return 0; } #endif @@ -1060,6 +1044,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; bytes_written = wldev_set_band(net, band); + wl_update_wiphybands(NULL); } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); @@ -1189,7 +1174,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_get_assoc_res_ies(net, command); } #endif /* BCMCCX */ -#ifdef BCM4334_CHIP //ampdu_mpdu +#ifdef SUPPORT_AMPDU_MPDU_CMD + /* CMD_AMPDU_MPDU */ else if (strnicmp(command, CMD_AMPDU_MPDU,strlen(CMD_AMPDU_MPDU)) == 0) { int skip = strlen(CMD_AMPDU_MPDU) + 1; bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip); @@ -1426,6 +1412,10 @@ int dhd_os_check_wakelock(void *dhdp); static int wifi_suspend(struct platform_device *pdev, pm_message_t state) { DHD_TRACE(("##> %s\n", __FUNCTION__)); +#if defined(BCMHOST) + if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) + return -EBUSY; +#endif #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1 bcmsdh_oob_intr_set(0); #endif /* (OOB_INTR_ONLY) */ diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c index c74adcc..e3bb3e4 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c @@ -63,7 +63,7 @@ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) #define DAEMONIZE(a) daemonize(a); \ allow_signal(SIGKILL); \ - allow_signal(SIGTERM); +allow_signal(SIGTERM); #else /* Linux 2.4 (w/o preemption patch) */ #define DAEMONIZE(a) daemonize(); \ do { if (a) \ @@ -144,6 +144,8 @@ u32 wl_dbg_level = WL_DBG_ERR; #define DNGL_FUNC(func, parameters) func parameters; #define COEX_DHCP +#define WLAN_EID_SSID 0 + /* Set this to 1 to use a seperate interface (p2p0) * for p2p operations. */ @@ -370,8 +372,8 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done); +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, @@ -2167,11 +2169,32 @@ scan_out: err = -EBUSY; } - /*if continuous busy state , abort scan */ +#define SCAN_EBUSY_RETRY_LIMIT 10 if (err == -EBUSY) { - if (busy_count++ > 5) { + if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) { + struct ether_addr bssid; + s32 ret = 0; busy_count = 0; - wl_cfg80211_scan_abort(wl, ndev); + WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n", + wl_get_drv_status(wl, SCANNING, ndev), + wl_get_drv_status(wl, SCAN_ABORTING, ndev), + wl_get_drv_status(wl, CONNECTING, ndev), + wl_get_drv_status(wl, CONNECTED, ndev), + wl_get_drv_status(wl, DISCONNECTING, ndev), + wl_get_drv_status(wl, AP_CREATING, ndev), + wl_get_drv_status(wl, AP_CREATED, ndev), + wl_get_drv_status(wl, SENDING_ACT_FRM, ndev), + wl_get_drv_status(wl, SENDING_ACT_FRM, ndev))); + + bzero(&bssid, sizeof(bssid)); + if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, + &bssid, ETHER_ADDR_LEN, false)) == 0) + WL_ERR(("FW is connected with " MACSTR "/n", + MAC2STR(bssid.octet))); + else + WL_ERR(("GET BSSID failed with %d\n", ret)); + + wl_cfg80211_disconnect(wiphy, ndev, DOT11_RC_DISASSOC_LEAVING); } } else { busy_count = 0; @@ -2771,6 +2794,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, wl_extjoin_params_t *ext_join_params; struct wl_join_params join_params; size_t join_params_size; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); s32 err = 0; wpa_ie_fixed_t *wpa_ie; wpa_ie_fixed_t *wps_ie; @@ -2920,7 +2944,15 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return err; } } - + if (dhd->roam_env_detection && (wldev_iovar_setint(dev, "roam_env_detection", + AP_ENV_DETECT_NOT_USED) == BCME_OK)) { + s32 roam_trigger[2] = {WL_AUTO_ROAM_TRIGGER, WLC_BAND_ALL}; + err = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), true); + if (unlikely(err)) { + WL_ERR((" failed to restore roam_trigger for auto env detection\n")); + } + } if (chan) { #ifdef ROAM_CHANNEL_CACHE wlc_ssid_t ssid; @@ -3567,7 +3599,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, WL_DBG((" Enter\n")); if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, - ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); if (err < 0) { WL_ERR(("GET STA INFO failed, %d\n", err)); return err; @@ -4542,10 +4574,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, memcpy(wl->afx_hdl->tx_dst_addr.octet, af_params->action_frame.da.octet, sizeof(wl->afx_hdl->tx_dst_addr.octet)); - if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) && - (p2p_ie = wl_cfgp2p_find_p2pie((u8 *)act_frm->elts, action_frame->len)) != NULL) { - if ((ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID))) { - is_PROVDIS_REQ_GO = true; + if (act_frm && act_frm->elts) { + if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) && + (p2p_ie = wl_cfgp2p_find_p2pie((u8 *)act_frm->elts, + action_frame->len)) != NULL) { + if ((ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID))) { + is_PROVDIS_REQ_GO = true; + } } } @@ -5535,7 +5570,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) #ifdef ROAM_CHANNEL_CACHE add_roam_cache(bi); #endif - err = wl_inform_single_bss(wl, bi); + err = wl_inform_single_bss(wl, bi, 0); if (unlikely(err)) break; } @@ -5545,7 +5580,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) return err; } -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done) { struct wiphy *wiphy = wiphy_from_scan(wl); struct ieee80211_mgmt *mgmt; @@ -5559,6 +5594,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) s32 signal; u32 freq; s32 err = 0; + u8 * ie_offset = NULL; gfp_t aflags; if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { @@ -5586,7 +5622,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) return err; } - notif_bss_info->rssi = dtoh16(bi->RSSI); + notif_bss_info->rssi = dtoh16(bi->RSSI) + RSSI_OFFSET; memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); mgmt_type = wl->active_scan ? IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON; @@ -5601,7 +5637,35 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) beacon_proberesp->capab_info = cpu_to_le16(bi->capability); wl_rst_ie(wl); - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + ie_offset = ((u8 *) bi) + bi->ie_offset; + + if (is_roam_done && ((int)(*(ie_offset)) == WLAN_EID_SSID && + ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { + u8 *ie_new_offset = NULL; + uint8 ie_new_length; + + WL_ERR(("WAR trace: Changing the SSID Info, from beacon %d\n", bi->flags & WL_BSS_FLAGS_FROM_BEACON)); + + ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (ie_new_offset) { + *(ie_new_offset) = WLAN_EID_SSID; + *(ie_new_offset+1) = bi->SSID_len; + memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); + ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; + + /* Copy the remaining IE apart from SSID IE from bi */ + memcpy( ie_new_offset+2 + bi->SSID_len, + ie_offset+2 + *(ie_offset+1), + bi->ie_length - 2 - *(ie_offset+1)); + wl_mrg_ie(wl, ie_new_offset , ie_new_length); + kfree(ie_new_offset); + } else { + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + } + } else { + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + } + wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - offsetof(struct wl_cfg80211_bss_info, frame_buf)); notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, @@ -5626,21 +5690,6 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) notif_bss_info->frame_len)); signal = notif_bss_info->rssi * 100; -#if defined(WLP2P) && (ENABLE_P2P_INTERFACE) - if (wl->p2p_net && wl->scan_request && - wl->scan_request->dev == wl->p2p_net) { -#else - if (p2p_is_on(wl) && p2p_scan(wl)) { -#endif - /* find the P2PIE, if we do not find it, we will discard this frame */ - wifi_p2p_ie_t *p2p_ie; - if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)beacon_proberesp->variable, - wl_get_ielen(wl))) == NULL) { - WL_ERR(("Couldn't find P2PIE in probe response/beacon\n")); - kfree(notif_bss_info); - return err; - } - } cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); @@ -5771,8 +5820,9 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, } if (len) memcpy(body, data, len); + wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", - NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); + NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); switch (event) { @@ -5920,7 +5970,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_get_drv_status(wl, CONNECTED, ndev)) { scb_val_t scbval; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - printk("link down, call cfg80211_disconnected\n"); + printk("link down, call cfg80211_disconnected. (reason=%d)\n", + ntoh32(e->reason)); WL_DBG(("con=%02x:%02x:%02x:%02x:%02x:%02x\n", curbssid[0], curbssid[1], curbssid[2], curbssid[3],curbssid[4], curbssid[5])); @@ -6127,7 +6178,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, } } -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done) { struct cfg80211_bss *bss; struct wl_bss_info *bi; @@ -6167,7 +6218,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) err = -EIO; goto update_bss_info_out; } - err = wl_inform_single_bss(wl, bi); + err = wl_inform_single_bss(wl, bi, is_roam_done); if (unlikely(err)) goto update_bss_info_out; @@ -6218,7 +6269,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev); + wl_update_bss_info(wl, ndev, 1); wl_update_pmklist(ndev, wl->pmk_list, err); cfg80211_roamed(ndev, #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) @@ -6239,6 +6290,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data, bool completed) { struct wl_connect_info *conn_info = wl_to_conn(wl); + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); s32 err = 0; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); @@ -6279,9 +6331,11 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, } wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev); + wl_update_bss_info(wl, ndev, 0); wl_update_pmklist(ndev, wl->pmk_list, err); wl_set_drv_status(wl, CONNECTED, ndev); + if (dhd->roam_env_detection) + wldev_iovar_setint(ndev, "roam_env_detection", AP_ENV_INDETERMINATE); } cfg80211_connect_result(ndev, curbssid, @@ -6498,7 +6552,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, #endif if (event == WLC_E_ACTION_FRAME_RX) { wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", - NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); + NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); if( err < 0) { @@ -7211,6 +7265,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_escan_result_t *escan_result; wl_bss_info_t *bss = NULL; wl_scan_results_t *list; + wifi_p2p_ie_t * p2p_ie; u32 bi_length; u32 i; u8 *p2p_dev_addr = NULL; @@ -7288,6 +7343,21 @@ static s32 wl_escan_handler(struct wl_priv *wl, } else { int cur_len = 0; list = (wl_scan_results_t *)wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2]; +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + if (wl->p2p_net && wl->scan_request && + wl->scan_request->dev == wl->p2p_net) { +#else + if (p2p_is_on(wl) && p2p_scan(wl)) { +#endif + /* p2p scan && allow only probe response */ + if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) + goto exit; + if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, + bi->ie_length)) == NULL) { + WL_ERR(("Couldn't find P2PIE in probe response/beacon\n")); + goto exit; + } + } #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -7296,41 +7366,73 @@ static s32 wl_escan_handler(struct wl_priv *wl, CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) && bi->SSID_len == bss->SSID_len && !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { - if (bss->dtoh32(ie_length) != bi_length) { - int prev_len = dtoh32(bss->length); - WL_SCAN2(("bss info replacement is occured(bcast:%d->probresp%d)\n", - bss->ie_length, bi->ie_length)); - /* prev : broadcast, cur : prob_resp */ - if (list->count != 1 && i < list->count -1) { - /* memory copy required by this case only */ - memcpy((u8 *)bss, - (u8 *)bss + prev_len, list->buflen - cur_len - prev_len); - } - list->buflen -= prev_len; - if (bi_length > ESCAN_BUF_SIZE - list->buflen) { - WL_ERR(("Buffer is too small: ignoring\n")); - goto exit; - } - memcpy(&(((u8 *)list)[list->buflen]), bi, bi_length); - list->version = dtoh32(bi->version); - list->buflen += bi_length; + + /* do not allow beacon data to update + *the data recd from a probe response + */ + if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) && + (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) goto exit; - } - if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == - (bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) { + + WL_DBG(("%s("MACSTR"), i=%d prev: RSSI %d" + " flags 0x%x, new: RSSI %d flags 0x%x\n", + bss->SSID, MAC2STR(bi->BSSID.octet), i, + bss->RSSI, bss->flags, bi->RSSI, bi->flags)); + + if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == + (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) { /* preserve max RSSI if the measurements are * both on-channel or both off-channel */ - bss->RSSI = MAX(bss->RSSI, bi->RSSI); - } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && - (bi->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { + WL_SCAN(("%s("MACSTR"), same onchan" + ", RSSI: prev %d new %d\n", + bss->SSID, MAC2STR(bi->BSSID.octet), + bss->RSSI, bi->RSSI)); + bi->RSSI = MAX(bss->RSSI, bi->RSSI); + } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && + (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) { /* preserve the on-channel rssi measurement * if the new measurement is off channel */ - bss->RSSI = bi->RSSI; - bss->flags |= WLC_BSS_RSSI_ON_CHANNEL; + WL_SCAN(("%s("MACSTR"), prev onchan" + ", RSSI: prev %d new %d\n", + bss->SSID, MAC2STR(bi->BSSID.octet), + bss->RSSI, bi->RSSI)); + bi->RSSI = bss->RSSI; + bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; } + if (dtoh32(bss->length) != bi_length) { + u32 prev_len = dtoh32(bss->length); + WL_SCAN(("bss info replacement" + " is occured(bcast:%d->probresp%d)\n", + bss->ie_length, bi->ie_length)); + WL_DBG(("%s("MACSTR"), replacement!(%d -> %d)\n", + bss->SSID, MAC2STR(bi->BSSID.octet), + prev_len, bi_length)); + + if (list->buflen - prev_len + bi_length + > ESCAN_BUF_SIZE) { + WL_ERR(("Buffer is too small: keep the" + " previous result of this AP\n")); + /* Only update RSSI */ + bss->RSSI = bi->RSSI; + bss->flags |= (bi->flags + & WL_BSS_FLAGS_RSSI_ONCHANNEL); + goto exit; + } + + if (i < list->count - 1) { + /* memory copy required by this case only */ + memmove((u8 *)bss + bi_length, + (u8 *)bss + prev_len, + list->buflen - cur_len - prev_len); + } + list->buflen -= prev_len; + list->buflen += bi_length; + } + list->version = dtoh32(bi->version); + memcpy((u8 *)bss, (u8 *)bi, bi_length); goto exit; } cur_len += dtoh32(bss->length); @@ -7435,7 +7537,6 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in { s32 pm = PM_FAST; s32 err = BCME_OK; - s32 glom = -1; u32 chan = 0; u32 chanspec = 0; u32 prev_chan = 0; @@ -7493,12 +7594,7 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in if ((wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) && p2p_is_on(wl)) if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n")); - if (!wl->vsdb_mode && (connected_cnt > 1)) { - if (wldev_iovar_getint(primary_dev, "bus:txglom", (s32 *)&glom) == BCME_OK) { - wl->glom = glom; - wldev_iovar_setint(primary_dev, "bus:txglom", 0); - } - } + break; } default: @@ -7531,9 +7627,6 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in } } } - if (wl->glom != -1) - wldev_iovar_setint(primary_dev, "bus:txglom", wl->glom); - wl->glom = -1; } if ((wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) && p2p_is_on(wl)) if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) @@ -7596,7 +7689,8 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->rf_blocked = false; wl->first_remain = true; wl->wlfc_on = false; - wl->glom = -1; + + /* register interested state */ set_bit(WL_STATUS_CONNECTED, &wl->interrested_state); spin_lock_init(&wl->cfgdrv_lock); mutex_init(&wl->ioctl_buf_sync); @@ -8231,6 +8325,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl) s32 index = 0; s32 nmode = 0; s32 bw_cap = 0; + s32 cur_band = -1; if (wl == NULL) wl = wlcfg_drv_priv; dev = wl_to_prmry_ndev(wl); @@ -8243,6 +8338,13 @@ s32 wl_update_wiphybands(struct wl_priv *wl) WL_ERR(("error (%d)\n", err)); return err; } + err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band, + sizeof(s32), false); + if (unlikely(err)) { + WL_ERR(("error (%d)\n", err)); + return err; + } + err = wldev_iovar_getint(dev, "nmode", &nmode); if (err) { return err; @@ -8258,6 +8360,11 @@ s32 wl_update_wiphybands(struct wl_priv *wl) WL_ERR(("wl_construct_reginfo() fails err=%d\n", err)); return err; } + if ((cur_band == WLC_BAND_2G) || + (cur_band == WLC_BAND_5G)) { + bandlist[0] = 1; + bandlist[1] = cur_band; + } wiphy = wl_to_wiphy(wl); nband = bandlist[0]; @@ -8706,8 +8813,8 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* In case of p2p_listen command, supplicant send remain_on_channel - * without turning on P2P - */ + * without turning on P2P + */ p2p_on(wl) = true; ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0); @@ -8817,7 +8924,7 @@ static void wl_cfg80211_clear_parent_dev(void) static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) { wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL, - 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); + 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync); memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN); } int wl_cfg80211_do_driver_init(struct net_device *net) diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h index 04bd49e..4c9e516 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h @@ -455,7 +455,6 @@ struct wl_priv { void *pub; u32 iface_cnt; u32 channel; /* current channel */ - s32 glom; #ifdef WL_CFG80211_SYNC_GON_TIME u32 af_sent_channel; /* channel action frame is sent */ /* save the next gon af subtype when it needs to wait more time for next gon af diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c index fdc2ed8..9071637 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c @@ -1137,8 +1137,7 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u /* If the contents match the SAMSUNG OUI */ if (ie[TLV_LEN_OFF] >= oui_len + 1 && - !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) && - !bcmp(oui, SAMSUNG_OUI, SAMSUNG_OUI_LEN)) { + !bcmp(&ie[TLV_BODY_OFF], oui, oui_len)) { return TRUE; } @@ -1318,7 +1317,7 @@ s32 wl_cfgp2p_p2p_listen_suspend(void) if ((ret = wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, enable)) != BCME_OK) { CFGP2P_ERR((" failed to %s WLC_E_P2P_PROPREQ_MSG\n", enable? "set":"unset" )); } - + } exit: return ret; @@ -1369,8 +1368,10 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev); #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ - cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, - &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); + if (ndev && (ndev->ieee80211_ptr != NULL)) { + cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, + &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); + } } if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) { CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); @@ -1442,7 +1443,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) /* Clear WLC_E_P2P_PROBREQ_MSG in case of early suspend and p2p ie != 0 */ enable = false; } - + if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, enable) != BCME_OK) { CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n")); } @@ -1730,7 +1731,7 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) ret = wldev_iovar_getint(ndev, "p2p", &p2p_supported); if (ret < 0) { - CFGP2P_ERR(("wl p2p error %d\n", ret)); + CFGP2P_ERR(("wl p2p supported IOVAR = %d\n", ret)); return 0; } if (p2p_supported == 1) { diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.c index 9824555..c25f173 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.c @@ -1416,6 +1416,7 @@ wl_iw_get_scan( struct iw_event iwe; wl_bss_info_t *bi = NULL; int error, i, j; + int rssi = 0; char *event = extra, *end = extra + dwrq->length, *value; uint buflen = dwrq->length; @@ -1482,10 +1483,13 @@ wl_iw_get_scan( iwe.u.freq.e = 6; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); - iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); + rssi = dtoh16(bi->RSSI); + if (rssi >= WL_IW_RSSI_INVALID) + rssi = WL_IW_RSSI_MAXVAL; + + iwe.u.qual.qual = rssi_to_qual(rssi); + iwe.u.qual.level = 0x100 + rssi; iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); @@ -1607,8 +1611,12 @@ wl_iw_iscan_get_scan( iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); - iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); + rssi = dtoh16(bi->RSSI); + if (rssi >= WL_IW_RSSI_INVALID) + rssi = WL_IW_RSSI_MAXVAL; + + iwe.u.qual.qual = rssi_to_qual(rssi); + iwe.u.qual.level = 0x100 + rssi; iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); @@ -3405,6 +3413,9 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat goto done; rssi = dtoh32(scb_val.val); + if (rssi >= WL_IW_RSSI_INVALID) + rssi = WL_IW_RSSI_MAXVAL; + WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi)); if (rssi <= WL_IW_RSSI_NO_SIGNAL) wstats->qual.qual = 0; diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.h index b38f20f..3929e6c 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_iw.h @@ -77,6 +77,7 @@ struct cntry_locales_custom { #define WL_IW_RSSI_VERY_GOOD -58 #define WL_IW_RSSI_EXCELLENT -57 #define WL_IW_RSSI_INVALID 0 +#define WL_IW_RSSI_MAXVAL -15 #define MAX_WX_STRING 80 #define SSID_FMT_BUF_LEN ((4 * 32) + 1) #define isprint(c) bcm_isprint(c) diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c index b4ecf11..516da89 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c @@ -31,6 +31,7 @@ #include <wldev_common.h> #include <bcmutils.h> +#include <wl_iw.h> #define htod32(i) i #define htod16(i) i @@ -41,13 +42,13 @@ #define WLDEV_ERROR(args) \ do { \ - printk(KERN_ERR "WLDEV-ERROR) %s : ", __func__); \ + printk(KERN_ERR "WLDEV-INFO2) %s : ", __func__); \ printk args; \ } while (0) #define WLDEV_INFO(args) \ do { \ - printk(KERN_INFO "WLDEV-ERROR) %s : ", __func__); \ + printk(KERN_INFO "WLDEV-INFO) %s : ", __func__); \ printk args; \ } while (0) @@ -300,6 +301,10 @@ int wldev_get_rssi( return error; *prssi = dtoh32(scb_val.val); + /* when the return value is zero. skip overrinding code */ + if (*prssi > WL_IW_RSSI_INVALID) + *prssi = WL_IW_RSSI_MAXVAL; + return error; } diff --git a/drivers/video/samsung/s5p-dsim.c b/drivers/video/samsung/s5p-dsim.c index 4f2cb7f..d128618 100644 --- a/drivers/video/samsung/s5p-dsim.c +++ b/drivers/video/samsung/s5p-dsim.c @@ -143,8 +143,13 @@ void set_dsim_hs_clk_toggle_count(u8 count) struct dsim_global *dsim = g_dsim; dsim->dsim_toggle_per_frame_count = count; - if (dsim->dsim_lcd_info->lcd_enabled) - s5p_dsim_frame_done_interrupt_enable(dsim, count ? 1 : 0); + if (dsim->dsim_lcd_info->lcd_enabled) { + if (dsim->dsim_info->hs_toggle) { + s5p_dsim_frame_done_interrupt_enable(dsim, 1); + schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(60000)); + } else + s5p_dsim_frame_done_interrupt_enable(dsim, count ? 1 : 0); + } } static void dsim_work_q_handler(struct work_struct *work) @@ -162,7 +167,7 @@ static void dsim_check_hs_toggle_work_q_handler(struct work_struct *work) if (dsim->dsim_info->hs_toggle) { dev_info(dsim->dev, "check_hs_toggle\n"); - schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000)); + schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(60000)); } } @@ -439,7 +444,7 @@ static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) s5p_dsim_toggle_hs_clock(dsim->reg_base); if (!dsim->dsim_toggle_per_frame_count) { s5p_dsim_frame_done_interrupt_enable(dsim, 0); - if (likely(dsim->dsim_info->hs_toggle - 1)) + if (likely(dsim->dsim_info->hs_toggle)) schedule_delayed_work(&dsim->dsim_work, dsim->dsim_info->hs_toggle); } if (dsim->dsim_toggle_per_frame_count) @@ -1219,15 +1224,10 @@ static int hs_toggle_store(struct device *dev, else { dev_info(dev, "%s - %d, %d\n", __func__, jiffies_to_msecs(dsim->dsim_info->hs_toggle), value); - if (value == 1) { + if (value == 1) dsim->dsim_info->hs_toggle = msecs_to_jiffies(3000); - s5p_dsim_frame_done_interrupt_enable(dsim, 1); - schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000)); - } else { + else dsim->dsim_info->hs_toggle = 0; - s5p_dsim_frame_done_interrupt_enable(dsim, 0); - cancel_delayed_work(&dsim->check_hs_toggle_work); - } } return size; } |