aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-10-11 15:56:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-11 15:56:29 -0400
commit5dde8e174909eee6945d5b294fad443c5bf094eb (patch)
treef123e7926f3f5bfef11f13b0a0fcf0e38c1f99f8
parent5b435de0d786869c95d1962121af0d7df2542009 (diff)
parent694440d93b9963a2c426708cb11494236c0b2552 (diff)
Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx
-rw-r--r--drivers/net/wireless/wl12xx/acx.c16
-rw-r--r--drivers/net/wireless/wl12xx/acx.h1
-rw-r--r--drivers/net/wireless/wl12xx/boot.c6
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c63
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h20
-rw-r--r--drivers/net/wireless/wl12xx/conf.h6
-rw-r--r--drivers/net/wireless/wl12xx/event.c15
-rw-r--r--drivers/net/wireless/wl12xx/main.c48
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h7
9 files changed, 158 insertions, 24 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 399849eeb247..ca044a743191 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -777,7 +777,23 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
777 acx->rate_policy.long_retry_limit = c->long_retry_limit; 777 acx->rate_policy.long_retry_limit = c->long_retry_limit;
778 acx->rate_policy.aflags = c->aflags; 778 acx->rate_policy.aflags = c->aflags;
779 779
780 ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
781 if (ret < 0) {
782 wl1271_warning("Setting of rate policies failed: %d", ret);
783 goto out;
784 }
780 785
786 /*
787 * configure one rate class for basic p2p operations.
788 * (p2p packets should always go out with OFDM rates, even
789 * if we are currently connected to 11b AP)
790 */
791 acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P);
792 acx->rate_policy.enabled_rates =
793 cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
794 acx->rate_policy.short_retry_limit = c->short_retry_limit;
795 acx->rate_policy.long_retry_limit = c->long_retry_limit;
796 acx->rate_policy.aflags = c->aflags;
781 797
782 ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); 798 ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
783 if (ret < 0) { 799 if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 556ee4e282d5..e3f93b4b3429 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -656,6 +656,7 @@ struct acx_rate_class {
656 656
657#define ACX_TX_BASIC_RATE 0 657#define ACX_TX_BASIC_RATE 0
658#define ACX_TX_AP_FULL_RATE 1 658#define ACX_TX_AP_FULL_RATE 1
659#define ACX_TX_BASIC_RATE_P2P 2
659#define ACX_TX_AP_MODE_MGMT_RATE 4 660#define ACX_TX_AP_MODE_MGMT_RATE 4
660#define ACX_TX_AP_MODE_BCST_RATE 5 661#define ACX_TX_AP_MODE_BCST_RATE 5
661struct acx_rate_policy { 662struct acx_rate_policy {
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 6d5664bfc37d..d4e628db76b0 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -503,7 +503,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
503 BA_SESSION_RX_CONSTRAINT_EVENT_ID | 503 BA_SESSION_RX_CONSTRAINT_EVENT_ID |
504 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | 504 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
505 INACTIVE_STA_EVENT_ID | 505 INACTIVE_STA_EVENT_ID |
506 MAX_TX_RETRY_EVENT_ID; 506 MAX_TX_RETRY_EVENT_ID |
507 CHANNEL_SWITCH_COMPLETE_EVENT_ID;
507 508
508 ret = wl1271_event_unmask(wl); 509 ret = wl1271_event_unmask(wl);
509 if (ret < 0) { 510 if (ret < 0) {
@@ -769,9 +770,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
769 clk |= (wl->ref_clock << 1) << 4; 770 clk |= (wl->ref_clock << 1) << 4;
770 } 771 }
771 772
772 if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
773 clk |= SCRATCH_ENABLE_LPD;
774
775 wl1271_write32(wl, DRPW_SCRATCH_START, clk); 773 wl1271_write32(wl, DRPW_SCRATCH_START, clk);
776 774
777 wl1271_set_partition(wl, &part_table[PART_WORK]); 775 wl1271_set_partition(wl, &part_table[PART_WORK]);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 287fe95ecb40..a52299e548fa 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -134,11 +134,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
134 /* Override the REF CLK from the NVS with the one from platform data */ 134 /* Override the REF CLK from the NVS with the one from platform data */
135 gen_parms->general_params.ref_clock = wl->ref_clock; 135 gen_parms->general_params.ref_clock = wl->ref_clock;
136 136
137 /* LPD mode enable (bits 6-7) in WL1271 AP mode only */
138 if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
139 gen_parms->general_params.general_settings |=
140 GENERAL_SETTINGS_DRPW_LPD;
141
142 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); 137 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
143 if (ret < 0) { 138 if (ret < 0) {
144 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 139 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
@@ -1700,3 +1695,61 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
1700out: 1695out:
1701 return ret; 1696 return ret;
1702} 1697}
1698
1699int wl12xx_cmd_channel_switch(struct wl1271 *wl,
1700 struct ieee80211_channel_switch *ch_switch)
1701{
1702 struct wl12xx_cmd_channel_switch *cmd;
1703 int ret;
1704
1705 wl1271_debug(DEBUG_ACX, "cmd channel switch");
1706
1707 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1708 if (!cmd) {
1709 ret = -ENOMEM;
1710 goto out;
1711 }
1712
1713 cmd->channel = ch_switch->channel->hw_value;
1714 cmd->switch_time = ch_switch->count;
1715 cmd->tx_suspend = ch_switch->block_tx;
1716 cmd->flush = 0; /* this value is ignored by the FW */
1717
1718 ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
1719 if (ret < 0) {
1720 wl1271_error("failed to send channel switch command");
1721 goto out_free;
1722 }
1723
1724out_free:
1725 kfree(cmd);
1726
1727out:
1728 return ret;
1729}
1730
1731int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
1732{
1733 struct wl12xx_cmd_stop_channel_switch *cmd;
1734 int ret;
1735
1736 wl1271_debug(DEBUG_ACX, "cmd stop channel switch");
1737
1738 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1739 if (!cmd) {
1740 ret = -ENOMEM;
1741 goto out;
1742 }
1743
1744 ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0);
1745 if (ret < 0) {
1746 wl1271_error("failed to stop channel switch command");
1747 goto out_free;
1748 }
1749
1750out_free:
1751 kfree(cmd);
1752
1753out:
1754 return ret;
1755}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 8e4d11ec0c55..b7bd42769aa7 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -79,6 +79,9 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
79int wl12xx_cmd_config_fwlog(struct wl1271 *wl); 79int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
80int wl12xx_cmd_start_fwlog(struct wl1271 *wl); 80int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
81int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); 81int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
82int wl12xx_cmd_channel_switch(struct wl1271 *wl,
83 struct ieee80211_channel_switch *ch_switch);
84int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
82 85
83enum wl1271_commands { 86enum wl1271_commands {
84 CMD_INTERROGATE = 1, /*use this to read information elements*/ 87 CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -677,4 +680,21 @@ struct wl12xx_cmd_stop_fwlog {
677 struct wl1271_cmd_header header; 680 struct wl1271_cmd_header header;
678} __packed; 681} __packed;
679 682
683struct wl12xx_cmd_channel_switch {
684 struct wl1271_cmd_header header;
685
686 /* The new serving channel */
687 u8 channel;
688 /* Relative time of the serving channel switch in TBTT units */
689 u8 switch_time;
690 /* 1: Suspend TX till switch time; 0: Do not suspend TX */
691 u8 tx_suspend;
692 /* 1: Flush TX at switch time; 0: Do not flush */
693 u8 flush;
694} __packed;
695
696struct wl12xx_cmd_stop_channel_switch {
697 struct wl1271_cmd_header header;
698} __packed;
699
680#endif /* __WL1271_CMD_H__ */ 700#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 6a6805c3cc74..04bb8fbf93f9 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -416,13 +416,17 @@ struct conf_rx_settings {
416 u8 queue_type; 416 u8 queue_type;
417}; 417};
418 418
419#define CONF_TX_MAX_RATE_CLASSES 8 419#define CONF_TX_MAX_RATE_CLASSES 10
420 420
421#define CONF_TX_RATE_MASK_UNSPECIFIED 0 421#define CONF_TX_RATE_MASK_UNSPECIFIED 0
422#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ 422#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
423 CONF_HW_BIT_RATE_2MBPS) 423 CONF_HW_BIT_RATE_2MBPS)
424#define CONF_TX_RATE_RETRY_LIMIT 10 424#define CONF_TX_RATE_RETRY_LIMIT 10
425 425
426/* basic rates for p2p operations (probe req/resp, etc.) */
427#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \
428 CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
429
426/* 430/*
427 * Rates supported for data packets when operating as AP. Note the absence 431 * Rates supported for data packets when operating as AP. Note the absence
428 * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop 432 * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index e66db69f8d17..674ad2a9e409 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -300,6 +300,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
300 wl1271_stop_ba_event(wl); 300 wl1271_stop_ba_event(wl);
301 } 301 }
302 302
303 if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
304 wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
305 "status = 0x%x",
306 mbox->channel_switch_status);
307 /*
308 * That event uses for two cases:
309 * 1) channel switch complete with status=0
310 * 2) channel switch failed status=1
311 */
312 if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
313 (wl->vif))
314 ieee80211_chswitch_done(wl->vif,
315 mbox->channel_switch_status ? false : true);
316 }
317
303 if ((vector & DUMMY_PACKET_EVENT_ID)) { 318 if ((vector & DUMMY_PACKET_EVENT_ID)) {
304 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); 319 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
305 if (wl->vif) 320 if (wl->vif)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e2d6edd2fcd2..884f82b63219 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1333,14 +1333,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
1333 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", 1333 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
1334 wl->chip.id); 1334 wl->chip.id);
1335 1335
1336 /*
1337 * 'end-of-transaction flag' and 'LPD mode flag'
1338 * should be set in wl127x AP mode only
1339 */
1340 if (wl->bss_type == BSS_TYPE_AP_BSS)
1341 wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |
1342 WL12XX_QUIRK_LPD_MODE);
1343
1344 ret = wl1271_setup(wl); 1336 ret = wl1271_setup(wl);
1345 if (ret < 0) 1337 if (ret < 0)
1346 goto out; 1338 goto out;
@@ -2222,6 +2214,11 @@ static int wl1271_unjoin(struct wl1271 *wl)
2222{ 2214{
2223 int ret; 2215 int ret;
2224 2216
2217 if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
2218 wl12xx_cmd_stop_channel_switch(wl);
2219 ieee80211_chswitch_done(wl->vif, false);
2220 }
2221
2225 /* to stop listening to a channel, we disconnect */ 2222 /* to stop listening to a channel, we disconnect */
2226 ret = wl12xx_cmd_role_stop_sta(wl); 2223 ret = wl12xx_cmd_role_stop_sta(wl);
2227 if (ret < 0) 2224 if (ret < 0)
@@ -4130,6 +4127,37 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
4130 return 0; 4127 return 0;
4131} 4128}
4132 4129
4130static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
4131 struct ieee80211_channel_switch *ch_switch)
4132{
4133 struct wl1271 *wl = hw->priv;
4134 int ret;
4135
4136 wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
4137
4138 mutex_lock(&wl->mutex);
4139
4140 if (unlikely(wl->state == WL1271_STATE_OFF)) {
4141 mutex_unlock(&wl->mutex);
4142 ieee80211_chswitch_done(wl->vif, false);
4143 return;
4144 }
4145
4146 ret = wl1271_ps_elp_wakeup(wl);
4147 if (ret < 0)
4148 goto out;
4149
4150 ret = wl12xx_cmd_channel_switch(wl, ch_switch);
4151
4152 if (!ret)
4153 set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
4154
4155 wl1271_ps_elp_sleep(wl);
4156
4157out:
4158 mutex_unlock(&wl->mutex);
4159}
4160
4133static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) 4161static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
4134{ 4162{
4135 struct wl1271 *wl = hw->priv; 4163 struct wl1271 *wl = hw->priv;
@@ -4406,6 +4434,7 @@ static const struct ieee80211_ops wl1271_ops = {
4406 .ampdu_action = wl1271_op_ampdu_action, 4434 .ampdu_action = wl1271_op_ampdu_action,
4407 .tx_frames_pending = wl1271_tx_frames_pending, 4435 .tx_frames_pending = wl1271_tx_frames_pending,
4408 .set_bitrate_mask = wl12xx_set_bitrate_mask, 4436 .set_bitrate_mask = wl12xx_set_bitrate_mask,
4437 .channel_switch = wl12xx_op_channel_switch,
4409 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 4438 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
4410}; 4439};
4411 4440
@@ -4679,6 +4708,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
4679 wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - 4708 wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
4680 sizeof(struct ieee80211_header); 4709 sizeof(struct ieee80211_header);
4681 4710
4711 wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
4712 sizeof(struct ieee80211_header);
4713
4682 wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; 4714 wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
4683 4715
4684 /* make sure all our channels fit in the scanned_ch bitmask */ 4716 /* make sure all our channels fit in the scanned_ch bitmask */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 997f53245011..1ec90fc7505e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -348,6 +348,7 @@ enum wl12xx_flags {
348 WL1271_FLAG_SOFT_GEMINI, 348 WL1271_FLAG_SOFT_GEMINI,
349 WL1271_FLAG_RX_STREAMING_STARTED, 349 WL1271_FLAG_RX_STREAMING_STARTED,
350 WL1271_FLAG_RECOVERY_IN_PROGRESS, 350 WL1271_FLAG_RECOVERY_IN_PROGRESS,
351 WL1271_FLAG_CS_PROGRESS,
351}; 352};
352 353
353struct wl1271_link { 354struct wl1271_link {
@@ -671,12 +672,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
671/* WL128X requires aggregated packets to be aligned to the SDIO block size */ 672/* WL128X requires aggregated packets to be aligned to the SDIO block size */
672#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) 673#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
673 674
674/*
675 * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
676 * consumption
677 */
678#define WL12XX_QUIRK_LPD_MODE BIT(3)
679
680/* Older firmwares did not implement the FW logger over bus feature */ 675/* Older firmwares did not implement the FW logger over bus feature */
681#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4) 676#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
682 677