aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorShahar Levi <shahar_levi@ti.com>2011-03-06 09:32:12 -0500
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:48:59 -0400
commit13b107dd9808343d05627f0fba7fbc764c86738e (patch)
tree88c804a3f3d5734a019cb97b97d953ef4bfdeee2 /drivers/net
parent5ea417ae7749076ddaacb5b36487cae6ac920413 (diff)
wl12xx: 1281/1283 support - use dynamic memory for the RX/TX pools
Separate the memory configuration to chip-specific structures and implement dynamic memory for wl128x. This feature allows us to move TX memory blocks to the RX pool when the RX path is overloaded. Thanks for Arik Nemtsov <arik@wizery.com> for helping simplify the wl1271_fw_status() code. [Rewrote the commit subject and message for clarity; improved some comments and changed "spare" to "padding" for consistency; added a FIXME for the AP memory configuration -- Luca] Signed-off-by: Shahar Levi <shahar_levi@ti.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/acx.c35
-rw-r--r--drivers/net/wireless/wl12xx/conf.h3
-rw-r--r--drivers/net/wireless/wl12xx/main.c48
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h5
4 files changed, 70 insertions, 21 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 50676b36ad26..e005aa40ef84 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -965,10 +965,13 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
965 } 965 }
966 966
967 /* memory config */ 967 /* memory config */
968 mem_conf->num_stations = wl->conf.mem.num_stations; 968 /* FIXME: for now we always use mem_wl127x for AP, because it
969 mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; 969 * doesn't support dynamic memory and we don't have the
970 mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; 970 * optimal values for wl128x without dynamic memory yet */
971 mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; 971 mem_conf->num_stations = wl->conf.mem_wl127x.num_stations;
972 mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num;
973 mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num;
974 mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles;
972 mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); 975 mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
973 976
974 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, 977 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@@ -986,6 +989,7 @@ out:
986int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) 989int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
987{ 990{
988 struct wl1271_acx_sta_config_memory *mem_conf; 991 struct wl1271_acx_sta_config_memory *mem_conf;
992 struct conf_memory_settings *mem;
989 int ret; 993 int ret;
990 994
991 wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); 995 wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -996,16 +1000,21 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
996 goto out; 1000 goto out;
997 } 1001 }
998 1002
1003 if (wl->chip.id == CHIP_ID_1283_PG20)
1004 mem = &wl->conf.mem_wl128x;
1005 else
1006 mem = &wl->conf.mem_wl127x;
1007
999 /* memory config */ 1008 /* memory config */
1000 mem_conf->num_stations = wl->conf.mem.num_stations; 1009 mem_conf->num_stations = mem->num_stations;
1001 mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; 1010 mem_conf->rx_mem_block_num = mem->rx_block_num;
1002 mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; 1011 mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
1003 mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; 1012 mem_conf->num_ssid_profiles = mem->ssid_profiles;
1004 mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); 1013 mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
1005 mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory; 1014 mem_conf->dyn_mem_enable = mem->dynamic_memory;
1006 mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks; 1015 mem_conf->tx_free_req = mem->min_req_tx_blocks;
1007 mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks; 1016 mem_conf->rx_free_req = mem->min_req_rx_blocks;
1008 mem_conf->tx_min = wl->conf.mem.tx_min; 1017 mem_conf->tx_min = mem->tx_min;
1009 1018
1010 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, 1019 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
1011 sizeof(*mem_conf)); 1020 sizeof(*mem_conf));
@@ -1072,6 +1081,8 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl)
1072 wl1271_debug(DEBUG_TX, "available tx blocks: %d", 1081 wl1271_debug(DEBUG_TX, "available tx blocks: %d",
1073 wl->tx_blocks_available); 1082 wl->tx_blocks_available);
1074 1083
1084 wl->tx_new_total = wl->tx_blocks_available;
1085
1075 return 0; 1086 return 0;
1076} 1087}
1077 1088
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a00f22c6c74f..743bd0beb63b 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1204,7 +1204,8 @@ struct conf_drv_settings {
1204 struct conf_scan_settings scan; 1204 struct conf_scan_settings scan;
1205 struct conf_rf_settings rf; 1205 struct conf_rf_settings rf;
1206 struct conf_ht_setting ht; 1206 struct conf_ht_setting ht;
1207 struct conf_memory_settings mem; 1207 struct conf_memory_settings mem_wl127x;
1208 struct conf_memory_settings mem_wl128x;
1208}; 1209};
1209 1210
1210#endif 1211#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index fe0cf47a656c..3c381ceadb98 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -298,7 +298,7 @@ static struct conf_drv_settings default_conf = {
298 .tx_ba_win_size = 64, 298 .tx_ba_win_size = 64,
299 .inactivity_timeout = 10000, 299 .inactivity_timeout = 10000,
300 }, 300 },
301 .mem = { 301 .mem_wl127x = {
302 .num_stations = 1, 302 .num_stations = 1,
303 .ssid_profiles = 1, 303 .ssid_profiles = 1,
304 .rx_block_num = 70, 304 .rx_block_num = 70,
@@ -307,7 +307,17 @@ static struct conf_drv_settings default_conf = {
307 .min_req_tx_blocks = 100, 307 .min_req_tx_blocks = 100,
308 .min_req_rx_blocks = 22, 308 .min_req_rx_blocks = 22,
309 .tx_min = 27, 309 .tx_min = 27,
310 } 310 },
311 .mem_wl128x = {
312 .num_stations = 1,
313 .ssid_profiles = 1,
314 .rx_block_num = 40,
315 .tx_min_block_num = 40,
316 .dynamic_memory = 1,
317 .min_req_tx_blocks = 45,
318 .min_req_rx_blocks = 22,
319 .tx_min = 27,
320 },
311}; 321};
312 322
313static void __wl1271_op_remove_interface(struct wl1271 *wl); 323static void __wl1271_op_remove_interface(struct wl1271 *wl);
@@ -608,16 +618,27 @@ static void wl1271_fw_status(struct wl1271 *wl,
608{ 618{
609 struct wl1271_fw_common_status *status = &full_status->common; 619 struct wl1271_fw_common_status *status = &full_status->common;
610 struct timespec ts; 620 struct timespec ts;
621 u32 old_tx_blk_count = wl->tx_blocks_available;
611 u32 total = 0; 622 u32 total = 0;
612 int i; 623 int i;
613 624
614 if (wl->bss_type == BSS_TYPE_AP_BSS) 625 if (wl->bss_type == BSS_TYPE_AP_BSS) {
615 wl1271_raw_read(wl, FW_STATUS_ADDR, status, 626 wl1271_raw_read(wl, FW_STATUS_ADDR, status,
616 sizeof(struct wl1271_fw_ap_status), false); 627 sizeof(struct wl1271_fw_ap_status), false);
617 else 628 } else {
618 wl1271_raw_read(wl, FW_STATUS_ADDR, status, 629 wl1271_raw_read(wl, FW_STATUS_ADDR, status,
619 sizeof(struct wl1271_fw_sta_status), false); 630 sizeof(struct wl1271_fw_sta_status), false);
620 631
632 /* Update tx total blocks change */
633 wl->tx_total_diff +=
634 ((struct wl1271_fw_sta_status *)status)->tx_total -
635 wl->tx_new_total;
636
637 /* Update total tx blocks */
638 wl->tx_new_total =
639 ((struct wl1271_fw_sta_status *)status)->tx_total;
640 }
641
621 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " 642 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
622 "drv_rx_counter = %d, tx_results_counter = %d)", 643 "drv_rx_counter = %d, tx_results_counter = %d)",
623 status->intr, 644 status->intr,
@@ -627,17 +648,28 @@ static void wl1271_fw_status(struct wl1271 *wl,
627 648
628 /* update number of available TX blocks */ 649 /* update number of available TX blocks */
629 for (i = 0; i < NUM_TX_QUEUES; i++) { 650 for (i = 0; i < NUM_TX_QUEUES; i++) {
630 u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - 651 total += le32_to_cpu(status->tx_released_blks[i]) -
631 wl->tx_blocks_freed[i]; 652 wl->tx_blocks_freed[i];
632 653
633 wl->tx_blocks_freed[i] = 654 wl->tx_blocks_freed[i] =
634 le32_to_cpu(status->tx_released_blks[i]); 655 le32_to_cpu(status->tx_released_blks[i]);
635 wl->tx_blocks_available += cnt; 656
636 total += cnt; 657 }
658
659 /*
660 * By adding the freed blocks to tx_total_diff we are actually
661 * moving them to the RX pool.
662 */
663 wl->tx_total_diff += total;
664
665 /* if we have positive difference, add the blocks to the TX pool */
666 if (wl->tx_total_diff >= 0) {
667 wl->tx_blocks_available += wl->tx_total_diff;
668 wl->tx_total_diff = 0;
637 } 669 }
638 670
639 /* if more blocks are available now, tx work can be scheduled */ 671 /* if more blocks are available now, tx work can be scheduled */
640 if (total) 672 if (wl->tx_blocks_available > old_tx_blk_count)
641 clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); 673 clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
642 674
643 /* for AP update num of allocated TX blocks per link and ps status */ 675 /* for AP update num of allocated TX blocks per link and ps status */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 4b556776fd57..ad04b8337a25 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -267,6 +267,8 @@ struct wl1271_fw_sta_status {
267 u8 tx_total; 267 u8 tx_total;
268 u8 reserved1; 268 u8 reserved1;
269 __le16 reserved2; 269 __le16 reserved2;
270 /* Total structure size is 68 bytes */
271 u32 padding;
270} __packed; 272} __packed;
271 273
272struct wl1271_fw_full_status { 274struct wl1271_fw_full_status {
@@ -397,6 +399,9 @@ struct wl1271 {
397 u32 tx_blocks_freed[NUM_TX_QUEUES]; 399 u32 tx_blocks_freed[NUM_TX_QUEUES];
398 u32 tx_blocks_available; 400 u32 tx_blocks_available;
399 u32 tx_results_count; 401 u32 tx_results_count;
402 /* Indicates how many memory blocks should be moved to the RX pool */
403 int tx_total_diff;
404 u32 tx_new_total;
400 405
401 /* Transmitted TX packets counter for chipset interface */ 406 /* Transmitted TX packets counter for chipset interface */
402 u32 tx_packets_count; 407 u32 tx_packets_count;