aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorZhaoyang Liu <liuzy@marvell.com>2015-03-13 08:07:58 -0400
committerKalle Valo <kvalo@codeaurora.org>2015-03-16 12:12:39 -0400
commit92263a841b1502d2ef19199deaa669fe4c0102e9 (patch)
tree07d9948bab9049994f2bf00276b6a06f814afb68 /drivers/net/wireless/mwifiex
parente35000ead491d71e59ab6f7458971321e06150a0 (diff)
mwifiex: add SDIO rx single port aggregation
This patch brings in support for SDIO single port rx aggregation to mwifiex. Maximum read size support by SDIO cmd53 is 64K. Based on multi port aggregation which is already part of mwifiex, idea here is multiple packets received in FW can be aggregated into single buffer. A separate upload type is defined for such packet aggregated to single port. Packets from this single buffer are later deaggregated into individual packets. This way, driver can receive more packets each time through single SDIO cmd53; thereby reducing no of times MMC bus is accessed. SDIO SP aggregation support is advertised by FW during load time and driver would get FW block size in command response of HostCmd_CMD_SDIO_SP_RX_AGGR_CFG. Signed-off-by: Zhaoyang Liu <liuzy@marvell.com> Signed-off-by: Marc Yang <yangyang@marvell.com> Reviewed-by: Amitkumar Karwar <akarwar@marvell.com> Reviewed-by: Cathy Luo <cluo@marvell.com> Reviewed-by: Avinash Patil <patila@marvell.com> Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r--drivers/net/wireless/mwifiex/decl.h8
-rw-r--r--drivers/net/wireless/mwifiex/fw.h9
-rw-r--r--drivers/net/wireless/mwifiex/main.c10
-rw-r--r--drivers/net/wireless/mwifiex/main.h4
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c103
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c40
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c21
7 files changed, 184 insertions, 11 deletions
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 6ce19bed0e91..38f24e0427d2 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -112,6 +112,11 @@
112 112
113#define MWIFIEX_A_BAND_START_FREQ 5000 113#define MWIFIEX_A_BAND_START_FREQ 5000
114 114
115/* SDIO Aggr data packet special info */
116#define SDIO_MAX_AGGR_BUF_SIZE (256 * 255)
117#define BLOCK_NUMBER_OFFSET 15
118#define SDIO_HEADER_OFFSET 28
119
115enum mwifiex_bss_type { 120enum mwifiex_bss_type {
116 MWIFIEX_BSS_TYPE_STA = 0, 121 MWIFIEX_BSS_TYPE_STA = 0,
117 MWIFIEX_BSS_TYPE_UAP = 1, 122 MWIFIEX_BSS_TYPE_UAP = 1,
@@ -169,10 +174,11 @@ struct mwifiex_wait_queue {
169}; 174};
170 175
171struct mwifiex_rxinfo { 176struct mwifiex_rxinfo {
177 struct sk_buff *parent;
172 u8 bss_num; 178 u8 bss_num;
173 u8 bss_type; 179 u8 bss_type;
174 struct sk_buff *parent;
175 u8 use_count; 180 u8 use_count;
181 u8 buf_type;
176}; 182};
177 183
178struct mwifiex_txinfo { 184struct mwifiex_txinfo {
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 21a942fd2226..59d8964dd0dc 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -197,6 +197,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
197 197
198#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) 198#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
199#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) 199#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
200#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
200 201
201#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ 202#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \
202 (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ 203 (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
@@ -353,6 +354,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
353#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d 354#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
354#define HostCmd_CMD_11AC_CFG 0x0112 355#define HostCmd_CMD_11AC_CFG 0x0112
355#define HostCmd_CMD_TDLS_OPER 0x0122 356#define HostCmd_CMD_TDLS_OPER 0x0122
357#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
356 358
357#define PROTOCOL_NO_SECURITY 0x01 359#define PROTOCOL_NO_SECURITY 0x01
358#define PROTOCOL_STATIC_WEP 0x02 360#define PROTOCOL_STATIC_WEP 0x02
@@ -1242,6 +1244,12 @@ struct host_cmd_ds_chan_rpt_event {
1242 u8 tlvbuf[0]; 1244 u8 tlvbuf[0];
1243} __packed; 1245} __packed;
1244 1246
1247struct host_cmd_sdio_sp_rx_aggr_cfg {
1248 u8 action;
1249 u8 enable;
1250 __le16 block_size;
1251} __packed;
1252
1245struct mwifiex_fixed_bcn_param { 1253struct mwifiex_fixed_bcn_param {
1246 __le64 timestamp; 1254 __le64 timestamp;
1247 __le16 beacon_period; 1255 __le16 beacon_period;
@@ -1964,6 +1972,7 @@ struct host_cmd_ds_command {
1964 struct host_cmd_ds_coalesce_cfg coalesce_cfg; 1972 struct host_cmd_ds_coalesce_cfg coalesce_cfg;
1965 struct host_cmd_ds_tdls_oper tdls_oper; 1973 struct host_cmd_ds_tdls_oper tdls_oper;
1966 struct host_cmd_ds_chan_rpt_req chan_rpt_req; 1974 struct host_cmd_ds_chan_rpt_req chan_rpt_req;
1975 struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
1967 } params; 1976 } params;
1968} __packed; 1977} __packed;
1969 1978
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index b242c3e8df3f..eaaacecbdef6 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -163,6 +163,7 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
163{ 163{
164 unsigned long flags; 164 unsigned long flags;
165 struct sk_buff *skb; 165 struct sk_buff *skb;
166 struct mwifiex_rxinfo *rx_info;
166 167
167 spin_lock_irqsave(&adapter->rx_proc_lock, flags); 168 spin_lock_irqsave(&adapter->rx_proc_lock, flags);
168 if (adapter->rx_processing || adapter->rx_locked) { 169 if (adapter->rx_processing || adapter->rx_locked) {
@@ -184,7 +185,14 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
184 adapter->delay_main_work = false; 185 adapter->delay_main_work = false;
185 mwifiex_queue_main_work(adapter); 186 mwifiex_queue_main_work(adapter);
186 } 187 }
187 mwifiex_handle_rx_packet(adapter, skb); 188 rx_info = MWIFIEX_SKB_RXCB(skb);
189 if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) {
190 if (adapter->if_ops.deaggr_pkt)
191 adapter->if_ops.deaggr_pkt(adapter, skb);
192 dev_kfree_skb_any(skb);
193 } else {
194 mwifiex_handle_rx_packet(adapter, skb);
195 }
188 } 196 }
189 spin_lock_irqsave(&adapter->rx_proc_lock, flags); 197 spin_lock_irqsave(&adapter->rx_proc_lock, flags);
190 adapter->rx_processing = false; 198 adapter->rx_processing = false;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 11db09c73e85..842fa0beb188 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -121,6 +121,7 @@ enum {
121 121
122#define MWIFIEX_TYPE_CMD 1 122#define MWIFIEX_TYPE_CMD 1
123#define MWIFIEX_TYPE_DATA 0 123#define MWIFIEX_TYPE_DATA 0
124#define MWIFIEX_TYPE_AGGR_DATA 10
124#define MWIFIEX_TYPE_EVENT 3 125#define MWIFIEX_TYPE_EVENT 3
125 126
126#define MAX_BITMAP_RATES_SIZE 18 127#define MAX_BITMAP_RATES_SIZE 18
@@ -744,6 +745,7 @@ struct mwifiex_if_ops {
744 int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); 745 int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
745 void (*iface_work)(struct work_struct *work); 746 void (*iface_work)(struct work_struct *work);
746 void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); 747 void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
748 void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *);
747}; 749};
748 750
749struct mwifiex_adapter { 751struct mwifiex_adapter {
@@ -787,6 +789,8 @@ struct mwifiex_adapter {
787 u8 more_task_flag; 789 u8 more_task_flag;
788 u16 tx_buf_size; 790 u16 tx_buf_size;
789 u16 curr_tx_buf_size; 791 u16 curr_tx_buf_size;
792 bool sdio_rx_aggr_enable;
793 u16 sdio_rx_block_size;
790 u32 ioport; 794 u32 ioport;
791 enum MWIFIEX_HARDWARE_STATUS hw_status; 795 enum MWIFIEX_HARDWARE_STATUS hw_status;
792 u16 number_of_antenna; 796 u16 number_of_antenna;
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 509204f5ae6f..fdeeb67f790a 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1043,6 +1043,59 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
1043} 1043}
1044 1044
1045/* 1045/*
1046 * This function decode sdio aggreation pkt.
1047 *
1048 * Based on the the data block size and pkt_len,
1049 * skb data will be decoded to few packets.
1050 */
1051static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
1052 struct sk_buff *skb)
1053{
1054 u32 total_pkt_len, pkt_len;
1055 struct sk_buff *skb_deaggr;
1056 u32 pkt_type;
1057 u16 blk_size;
1058 u8 blk_num;
1059 u8 *data;
1060
1061 data = skb->data;
1062 total_pkt_len = skb->len;
1063
1064 while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
1065 if (total_pkt_len < adapter->sdio_rx_block_size)
1066 break;
1067 blk_num = *(data + BLOCK_NUMBER_OFFSET);
1068 blk_size = adapter->sdio_rx_block_size * blk_num;
1069 if (blk_size > total_pkt_len) {
1070 dev_err(adapter->dev, "%s: error in pkt,\t"
1071 "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
1072 __func__, blk_num, blk_size, total_pkt_len);
1073 break;
1074 }
1075 pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
1076 pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
1077 2));
1078 if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
1079 dev_err(adapter->dev, "%s: error in pkt,\t"
1080 "pkt_len=%d, blk_size=%d\n",
1081 __func__, pkt_len, blk_size);
1082 break;
1083 }
1084 skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
1085 GFP_KERNEL | GFP_DMA);
1086 if (!skb_deaggr)
1087 break;
1088 skb_put(skb_deaggr, pkt_len);
1089 memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
1090 skb_pull(skb_deaggr, INTF_HEADER_LEN);
1091
1092 mwifiex_handle_rx_packet(adapter, skb_deaggr);
1093 data += blk_size;
1094 total_pkt_len -= blk_size;
1095 }
1096}
1097
1098/*
1046 * This function decodes a received packet. 1099 * This function decodes a received packet.
1047 * 1100 *
1048 * Based on the type, the packet is treated as either a data, or 1101 * Based on the type, the packet is treated as either a data, or
@@ -1055,11 +1108,28 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
1055 u8 *cmd_buf; 1108 u8 *cmd_buf;
1056 __le16 *curr_ptr = (__le16 *)skb->data; 1109 __le16 *curr_ptr = (__le16 *)skb->data;
1057 u16 pkt_len = le16_to_cpu(*curr_ptr); 1110 u16 pkt_len = le16_to_cpu(*curr_ptr);
1111 struct mwifiex_rxinfo *rx_info;
1058 1112
1059 skb_trim(skb, pkt_len); 1113 if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
1060 skb_pull(skb, INTF_HEADER_LEN); 1114 skb_trim(skb, pkt_len);
1115 skb_pull(skb, INTF_HEADER_LEN);
1116 }
1061 1117
1062 switch (upld_typ) { 1118 switch (upld_typ) {
1119 case MWIFIEX_TYPE_AGGR_DATA:
1120 dev_dbg(adapter->dev, "info: --- Rx: Aggr Data packet ---\n");
1121 rx_info = MWIFIEX_SKB_RXCB(skb);
1122 rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA;
1123 if (adapter->rx_work_enabled) {
1124 skb_queue_tail(&adapter->rx_data_q, skb);
1125 atomic_inc(&adapter->rx_pending);
1126 adapter->data_received = true;
1127 } else {
1128 mwifiex_deaggr_sdio_pkt(adapter, skb);
1129 dev_kfree_skb_any(skb);
1130 }
1131 break;
1132
1063 case MWIFIEX_TYPE_DATA: 1133 case MWIFIEX_TYPE_DATA:
1064 dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); 1134 dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n");
1065 if (adapter->rx_work_enabled) { 1135 if (adapter->rx_work_enabled) {
@@ -1247,8 +1317,10 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
1247 /* copy pkt to deaggr buf */ 1317 /* copy pkt to deaggr buf */
1248 skb_deaggr = card->mpa_rx.skb_arr[pind]; 1318 skb_deaggr = card->mpa_rx.skb_arr[pind];
1249 1319
1250 if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= 1320 if ((pkt_type == MWIFIEX_TYPE_DATA ||
1251 card->mpa_rx.len_arr[pind])) { 1321 (pkt_type == MWIFIEX_TYPE_AGGR_DATA &&
1322 adapter->sdio_rx_aggr_enable)) &&
1323 (pkt_len <= card->mpa_rx.len_arr[pind])) {
1252 1324
1253 memcpy(skb_deaggr->data, curr_ptr, pkt_len); 1325 memcpy(skb_deaggr->data, curr_ptr, pkt_len);
1254 1326
@@ -1258,8 +1330,10 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
1258 mwifiex_decode_rx_packet(adapter, skb_deaggr, 1330 mwifiex_decode_rx_packet(adapter, skb_deaggr,
1259 pkt_type); 1331 pkt_type);
1260 } else { 1332 } else {
1261 dev_err(adapter->dev, "wrong aggr pkt:" 1333 dev_err(adapter->dev, "wrong aggr pkt:\t"
1262 " type=%d len=%d max_len=%d\n", 1334 "sdio_single_port_rx_aggr=%d\t"
1335 "type=%d len=%d max_len=%d\n",
1336 adapter->sdio_rx_aggr_enable,
1263 pkt_type, pkt_len, 1337 pkt_type, pkt_len,
1264 card->mpa_rx.len_arr[pind]); 1338 card->mpa_rx.len_arr[pind]);
1265 dev_kfree_skb_any(skb_deaggr); 1339 dev_kfree_skb_any(skb_deaggr);
@@ -1278,6 +1352,13 @@ rx_curr_single:
1278 skb->data, skb->len, 1352 skb->data, skb->len,
1279 adapter->ioport + port)) 1353 adapter->ioport + port))
1280 goto error; 1354 goto error;
1355 if (!adapter->sdio_rx_aggr_enable &&
1356 pkt_type == MWIFIEX_TYPE_AGGR_DATA) {
1357 dev_err(adapter->dev, "Wrong pkt type %d\t"
1358 "Current SDIO RX Aggr not enabled\n",
1359 pkt_type);
1360 goto error;
1361 }
1281 1362
1282 mwifiex_decode_rx_packet(adapter, skb, pkt_type); 1363 mwifiex_decode_rx_packet(adapter, skb, pkt_type);
1283 } 1364 }
@@ -1452,7 +1533,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
1452 1) / MWIFIEX_SDIO_BLOCK_SIZE; 1533 1) / MWIFIEX_SDIO_BLOCK_SIZE;
1453 if (rx_len <= INTF_HEADER_LEN || 1534 if (rx_len <= INTF_HEADER_LEN ||
1454 (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > 1535 (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
1455 MWIFIEX_RX_DATA_BUF_SIZE) { 1536 card->mpa_rx.buf_size) {
1456 dev_err(adapter->dev, "invalid rx_len=%d\n", 1537 dev_err(adapter->dev, "invalid rx_len=%d\n",
1457 rx_len); 1538 rx_len);
1458 return -1; 1539 return -1;
@@ -1742,6 +1823,7 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter,
1742 u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) 1823 u32 mpa_tx_buf_size, u32 mpa_rx_buf_size)
1743{ 1824{
1744 struct sdio_mmc_card *card = adapter->card; 1825 struct sdio_mmc_card *card = adapter->card;
1826 u32 rx_buf_size;
1745 int ret = 0; 1827 int ret = 0;
1746 1828
1747 card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); 1829 card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL);
@@ -1752,13 +1834,15 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter,
1752 1834
1753 card->mpa_tx.buf_size = mpa_tx_buf_size; 1835 card->mpa_tx.buf_size = mpa_tx_buf_size;
1754 1836
1755 card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); 1837 rx_buf_size = max_t(u32, mpa_rx_buf_size,
1838 (u32)SDIO_MAX_AGGR_BUF_SIZE);
1839 card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL);
1756 if (!card->mpa_rx.buf) { 1840 if (!card->mpa_rx.buf) {
1757 ret = -1; 1841 ret = -1;
1758 goto error; 1842 goto error;
1759 } 1843 }
1760 1844
1761 card->mpa_rx.buf_size = mpa_rx_buf_size; 1845 card->mpa_rx.buf_size = rx_buf_size;
1762 1846
1763error: 1847error:
1764 if (ret) { 1848 if (ret) {
@@ -2298,6 +2382,7 @@ static struct mwifiex_if_ops sdio_ops = {
2298 .iface_work = mwifiex_sdio_work, 2382 .iface_work = mwifiex_sdio_work,
2299 .fw_dump = mwifiex_sdio_fw_dump, 2383 .fw_dump = mwifiex_sdio_fw_dump,
2300 .reg_dump = mwifiex_sdio_reg_dump, 2384 .reg_dump = mwifiex_sdio_reg_dump,
2385 .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
2301}; 2386};
2302 2387
2303/* 2388/*
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index b23eaed84701..49422f2a5380 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1671,6 +1671,25 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
1671 1671
1672 return 0; 1672 return 0;
1673} 1673}
1674
1675/* This function prepares command of sdio rx aggr info. */
1676static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd,
1677 u16 cmd_action, void *data_buf)
1678{
1679 struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
1680 &cmd->params.sdio_rx_aggr_cfg;
1681
1682 cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
1683 cmd->size =
1684 cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) +
1685 S_DS_GEN);
1686 cfg->action = cmd_action;
1687 if (cmd_action == HostCmd_ACT_GEN_SET)
1688 cfg->enable = *(u8 *)data_buf;
1689
1690 return 0;
1691}
1692
1674/* 1693/*
1675 * This function prepares the commands before sending them to the firmware. 1694 * This function prepares the commands before sending them to the firmware.
1676 * 1695 *
@@ -1908,6 +1927,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1908 ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, 1927 ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
1909 data_buf); 1928 data_buf);
1910 break; 1929 break;
1930 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
1931 ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action,
1932 data_buf);
1933 break;
1911 default: 1934 default:
1912 dev_err(priv->adapter->dev, 1935 dev_err(priv->adapter->dev,
1913 "PREP_CMD: unknown cmd- %#x\n", cmd_no); 1936 "PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -1947,6 +1970,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
1947 struct mwifiex_ds_auto_ds auto_ds; 1970 struct mwifiex_ds_auto_ds auto_ds;
1948 enum state_11d_t state_11d; 1971 enum state_11d_t state_11d;
1949 struct mwifiex_ds_11n_tx_cfg tx_cfg; 1972 struct mwifiex_ds_11n_tx_cfg tx_cfg;
1973 u8 sdio_sp_rx_aggr_enable;
1950 1974
1951 if (first_sta) { 1975 if (first_sta) {
1952 if (priv->adapter->iface_type == MWIFIEX_PCIE) { 1976 if (priv->adapter->iface_type == MWIFIEX_PCIE) {
@@ -1990,6 +2014,22 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
1990 if (ret) 2014 if (ret)
1991 return -1; 2015 return -1;
1992 2016
2017 /** Set SDIO Single Port RX Aggr Info */
2018 if (priv->adapter->iface_type == MWIFIEX_SDIO &&
2019 ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) {
2020 sdio_sp_rx_aggr_enable = true;
2021 ret = mwifiex_send_cmd(priv,
2022 HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
2023 HostCmd_ACT_GEN_SET, 0,
2024 &sdio_sp_rx_aggr_enable,
2025 true);
2026 if (ret) {
2027 dev_err(priv->adapter->dev,
2028 "error while enabling SP aggregation..disable it");
2029 adapter->sdio_rx_aggr_enable = false;
2030 }
2031 }
2032
1993 /* Reconfigure tx buf size */ 2033 /* Reconfigure tx buf size */
1994 ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, 2034 ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
1995 HostCmd_ACT_GEN_SET, 0, 2035 HostCmd_ACT_GEN_SET, 0,
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 5f8da5924666..88dc6b672ef4 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -90,6 +90,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
90 case HostCmd_CMD_MAC_CONTROL: 90 case HostCmd_CMD_MAC_CONTROL:
91 break; 91 break;
92 92
93 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
94 dev_err(priv->adapter->dev, "SDIO RX single-port aggregation Not support\n");
95 break;
96
93 default: 97 default:
94 break; 98 break;
95 } 99 }
@@ -943,6 +947,20 @@ static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
943 return 0; 947 return 0;
944} 948}
945 949
950/** This Function handles the command response of sdio rx aggr */
951static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv,
952 struct host_cmd_ds_command *resp)
953{
954 struct mwifiex_adapter *adapter = priv->adapter;
955 struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
956 &resp->params.sdio_rx_aggr_cfg;
957
958 adapter->sdio_rx_aggr_enable = cfg->enable;
959 adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
960
961 return 0;
962}
963
946/* 964/*
947 * This function handles the command responses. 965 * This function handles the command responses.
948 * 966 *
@@ -1124,6 +1142,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
1124 break; 1142 break;
1125 case HostCmd_CMD_CHAN_REPORT_REQUEST: 1143 case HostCmd_CMD_CHAN_REPORT_REQUEST:
1126 break; 1144 break;
1145 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
1146 ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
1147 break;
1127 default: 1148 default:
1128 dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", 1149 dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
1129 resp->command); 1150 resp->command);