diff options
author | Srinivas <srinivasra@nvidia.com> | 2013-09-26 11:46:16 -0700 |
---|---|---|
committer | Harshada Kale <hkale@nvidia.com> | 2013-10-01 04:02:49 -0700 |
commit | f6dfb71954d5eae988074f7d2781a8e57afc0a8e (patch) | |
tree | d0da941d6c69542fdb68c94b21ee7a54ea7b063d /drivers/net | |
parent | 84f2500adc00a29415ac742ff2ccfa5514a03b96 (diff) |
bcmdhd: Define miracast modes 3 & 4
Improve QoS for Grid2shield stream by
turning off AMPDU aggregation on 11n AP's
Mode 3 - disable AMPDU for all CS's
Mode 4 - re-enable AMPDU except CS 5 & 7
Driver command MAXLINKSPEED added to
distinguish 11n and non-11n AP's
Bug 1375583
Change-Id: I36a6b2426ea53696fac54681fda38f91eabc8956
Signed-off-by: Srinivas <srinivasra@nvidia.com>
Reviewed-on: http://git-master/r/279441
Reviewed-by: Steve Lin <stlin@nvidia.com>
Reviewed-by: Narayan Reddy <narayanr@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_linux.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_android.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wldev_common.c | 200 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wldev_common.h | 8 |
4 files changed, 236 insertions, 1 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 05dd1eb74a0d..546d98b6964c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3841,6 +3841,24 @@ done: return ret; } +void dhd_set_ampdu_rx_tid(struct net_device *dev, int ampdu_rx_tid) +{ + int i, ret = 0; + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + dhd_pub_t *pub = &dhd->pub; + char iovbuf[32]; + for (i = 0; i < 8; i++) { /* One bit each for traffic class CS7 - CS0 */ + struct ampdu_tid_control atc; + atc.tid = i; + atc.enable = (ampdu_rx_tid >> i) & 1; + bcm_mkiovar("ampdu_rx_tid", (char *)&atc, sizeof(atc), iovbuf, +sizeof(iovbuf)); + ret = dhd_wl_ioctl_cmd(pub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), +TRUE, 0); + if (ret < 0) + DHD_ERROR(("%s failed %d\n", __func__, ret)); + } +} int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set) diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 03fbfa9b3306..d3eda18b1866 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -93,6 +93,8 @@ #define CMD_TEST_FORCE_HANG "TEST_FORCE_HANG" #endif #define CMD_SETMIRACAST "SETMIRACAST" +#define CMD_ASSOCRESPIE "ASSOCRESPIE" +#define CMD_MAXLINKSPEED "MAXLINKSPEED" /* CCX Private Commands */ @@ -874,7 +876,14 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) #endif /* SUPPORT_TRIGGER_HANG_EVENT */ else if (strnicmp(command, CMD_SETMIRACAST, strlen(CMD_SETMIRACAST)) == 0) { bytes_written = wldev_miracast_tuning(net, command, priv_cmd.total_len); - } + } else if (strnicmp(command, CMD_ASSOCRESPIE, strlen(CMD_ASSOCRESPIE)) +== 0) + bytes_written = wldev_get_assoc_resp_ie(net, command, +priv_cmd.total_len); + else if (strnicmp(command, CMD_MAXLINKSPEED, strlen(CMD_MAXLINKSPEED)) +== 0) + bytes_written = wldev_get_max_linkspeed(net, command, +priv_cmd.total_len); else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index 92be39632d3d..eebca8d0d9a3 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -342,6 +342,7 @@ int wldev_miracast_tuning( int mode = 0; int ampdu_mpdu; int roam_off; + int ampdu_rx_tid = -1; #ifdef VSDB_BW_ALLOCATE_ENABLE int mchan_algo; int mchan_bw; @@ -352,6 +353,8 @@ int wldev_miracast_tuning( return -1; } +set_mode: + WLDEV_ERROR(("mode: %d\n", mode)); if (mode == 0) { @@ -388,6 +391,14 @@ int wldev_miracast_tuning( mchan_algo = 0; /* Default */ mchan_bw = 50; /* 50:50 */ #endif /* VSDB_BW_ALLOCATE_ENABLE */ + } else if (mode == 3) { + ampdu_rx_tid = 0; + mode = 2; + goto set_mode; + } else if (mode == 4) { + ampdu_rx_tid = 0x5f; + mode = 0; + goto set_mode; } else { WLDEV_ERROR(("Unknown mode: %d\n", mode)); @@ -427,9 +438,198 @@ int wldev_miracast_tuning( } #endif /* VSDB_BW_ALLOCATE_ENABLE */ + if (ampdu_rx_tid != -1) + dhd_set_ampdu_rx_tid(dev, ampdu_rx_tid); + return error; } +int wldev_get_assoc_resp_ie( + struct net_device *dev, char *command, int total_len) +{ + wl_assoc_info_t *assoc_info; + char smbuf[WLC_IOCTL_SMLEN]; + char bssid[6], null_bssid[6]; + int resp_ies_len = 0; + int bytes_written = 0; + int error, i; + + bzero(bssid, 6); + bzero(null_bssid, 6); + + /* Check Association */ + error = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + if (error == BCME_NOTASSOCIATED) { + /* Not associated */ + bytes_written += snprintf(&command[bytes_written], total_len, + "NA"); + goto done; + } else if (error < 0) { + WLDEV_ERROR(("WLC_GET_BSSID failed = %d\n", error)); + return -1; + } else if (memcmp(bssid, null_bssid, ETHER_ADDR_LEN) == 0) { + /* Zero BSSID: Not associated */ + bytes_written += snprintf(&command[bytes_written], total_len, + "NA"); + goto done; + } + + /* Get assoc_info */ + bzero(smbuf, sizeof(smbuf)); + error = wldev_iovar_getbuf(dev, "assoc_info", NULL, 0, smbuf, + sizeof(smbuf), NULL); + if (error < 0) { + WLDEV_ERROR(("get assoc_info failed = %d\n", error)); + return -1; + } + + assoc_info = (wl_assoc_info_t *)smbuf; + resp_ies_len = dtoh32(assoc_info->resp_len) - + sizeof(struct dot11_assoc_resp); + + /* Retrieve assoc resp IEs */ + if (resp_ies_len) { + error = wldev_iovar_getbuf(dev, "assoc_resp_ies", NULL, 0, smbuf + , sizeof(smbuf), NULL); + if (error < 0) { + WLDEV_ERROR(("get assoc_resp_ies failed = %d\n", + error)); + return -1; + } + + /* Length */ + bytes_written += snprintf(&command[bytes_written], total_len, + "%d,", resp_ies_len); + /* IEs */ + if ((total_len - bytes_written) > resp_ies_len) { + for (i = 0; i < resp_ies_len; i++) { + bytes_written += sprintf(&command[bytes_written] + , "%02x", smbuf[i]); + } + } else { + WLDEV_ERROR(("Not enough buffer\n")); + return -1; + } + } else { + WLDEV_ERROR(("Zero Length assoc resp ies = %d\n", + resp_ies_len)); + return -1; + } + +done: + + return bytes_written; +} + +int wldev_get_max_linkspeed( + struct net_device *dev, char *command, int total_len) +{ + wl_assoc_info_t *assoc_info; + char smbuf[WLC_IOCTL_SMLEN]; + char bssid[6], null_bssid[6]; + int resp_ies_len = 0; + int bytes_written = 0; + int error, i; + + bzero(bssid, 6); + bzero(null_bssid, 6); + + /* Check Association */ + error = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + if (error == BCME_NOTASSOCIATED) { + /* Not associated */ + bytes_written += snprintf(&command[bytes_written], + total_len, "-1"); + goto done; + } else if (error < 0) { + WLDEV_ERROR(("WLC_GET_BSSID failed = %d\n", error)); + return -1; + } else if (memcmp(bssid, null_bssid, ETHER_ADDR_LEN) == 0) { + /* Zero BSSID: Not associated */ + bytes_written += snprintf(&command[bytes_written], + total_len, "-1"); + goto done; + } + /* Get assoc_info */ + bzero(smbuf, sizeof(smbuf)); + error = wldev_iovar_getbuf(dev, "assoc_info", NULL, 0, smbuf, + sizeof(smbuf), NULL); + if (error < 0) { + WLDEV_ERROR(("get assoc_info failed = %d\n", error)); + return -1; + } + + assoc_info = (wl_assoc_info_t *)smbuf; + resp_ies_len = dtoh32(assoc_info->resp_len) - + sizeof(struct dot11_assoc_resp); + + /* Retrieve assoc resp IEs */ + if (resp_ies_len) { + error = wldev_iovar_getbuf(dev, "assoc_resp_ies", NULL, 0, + smbuf, sizeof(smbuf), NULL); + if (error < 0) { + WLDEV_ERROR(("get assoc_resp_ies failed = %d\n", + error)); + return -1; + } + + { + int maxRate = 0; + struct dot11IE { + unsigned char ie; + unsigned char len; + unsigned char data[0]; + } *dot11IE = (struct dot11IE *)smbuf; + int remaining = resp_ies_len; + + while (1) { + if (remaining < 2) + break; + if (remaining < dot11IE->len + 2) + break; + switch (dot11IE->ie) { + case 0x01: /* supported rates */ + case 0x32: /* extended supported rates */ + for (i = 0; i < dot11IE->len; i++) { + int rate = ((dot11IE->data[i] & + 0x7f) / 2); + if (rate > maxRate) + maxRate = rate; + } + break; + case 0x2d: /* HT capabilities */ + case 0x3d: /* HT operation */ + /* 11n supported */ + maxRate = 150; /* Just return an 11n + rate for now. Could implement detailed + parser later. */ + break; + default: + break; + } + + /* next IE */ + dot11IE = (struct dot11IE *) + ((unsigned char *)dot11IE + dot11IE->len + 2); + remaining -= (dot11IE->len + 2); + } + bytes_written += snprintf(&command[bytes_written], + total_len, "MaxLinkSpeed %d", + maxRate); + goto done; + } + } else { + WLDEV_ERROR(("Zero Length assoc resp ies = %d\n", + resp_ies_len)); + return -1; + } + +done: + + return bytes_written; + +} + int wldev_set_country( struct net_device *dev, char *country_code, bool notify, bool user_enforced) { diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 2fdc7b7bc89e..e70faac7ad27 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -111,4 +111,12 @@ int wldev_set_band(struct net_device *dev, uint band); int wldev_miracast_tuning(struct net_device *dev, char *command, int total_len); +int wldev_get_assoc_resp_ie(struct net_device *dev, char *command, + int total_len); + +int wldev_get_max_linkspeed(struct net_device *dev, char *command, + int total_len); + +extern void dhd_set_ampdu_rx_tid(struct net_device *dev, int ampdu_rx_tid); + #endif /* __WLDEV_COMMON_H__ */ |