summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas <srinivasra@nvidia.com>2013-09-26 11:46:16 -0700
committerHarshada Kale <hkale@nvidia.com>2013-10-01 04:02:49 -0700
commitf6dfb71954d5eae988074f7d2781a8e57afc0a8e (patch)
treed0da941d6c69542fdb68c94b21ee7a54ea7b063d
parent84f2500adc00a29415ac742ff2ccfa5514a03b96 (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>
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c18
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c11
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c200
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h8
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__ */