diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-06 15:46:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-06 15:46:08 -0500 |
commit | 28c0f02ffe8a614bc7e1aa57319a62e7ce700d04 (patch) | |
tree | 078ee8553662a5f6d82d31859c160ceab866c2d6 /drivers/net/wireless/brcm80211/brcmfmac | |
parent | 89650ad0047f039b3c3bc0f6a5823bb9c9738152 (diff) | |
parent | 1ca2760fb2c13959fcba794695cd5b306cbfa6a4 (diff) |
Merge tag 'wireless-drivers-next-for-davem-2015-03-06' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Major changes:
brcmfmac:
* sdio improvements
* add a debugfs file so users can provide us all the revinfo we could
ask for
iwlwifi:
* add triggers for firmware dump collection
* remove support for -9.ucode
* new statitics API
* rate control improvements
ath9k:
* add per-vif TX power capability
* BT coexistance fixes
ath10k:
* qca6174: enable STA transmit beamforming (TxBF) support
* disable multi-vif power save by default
bcma:
* enable support for PCIe Gen 2 host devices
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 166 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/core.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 115 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio.h | 47 |
5 files changed, 274 insertions, 97 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 7944224e3fc9..c438ccdb6ed8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -58,6 +58,14 @@ | |||
58 | #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ | 58 | #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ |
59 | #define BRCMF_DEFAULT_RXGLOM_SIZE 32 /* max rx frames in glom chain */ | 59 | #define BRCMF_DEFAULT_RXGLOM_SIZE 32 /* max rx frames in glom chain */ |
60 | 60 | ||
61 | struct brcmf_sdiod_freezer { | ||
62 | atomic_t freezing; | ||
63 | atomic_t thread_count; | ||
64 | u32 frozen_count; | ||
65 | wait_queue_head_t thread_freeze; | ||
66 | struct completion resumed; | ||
67 | }; | ||
68 | |||
61 | static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; | 69 | static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; |
62 | module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0); | 70 | module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0); |
63 | MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); | 71 | MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); |
@@ -197,6 +205,30 @@ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
197 | return 0; | 205 | return 0; |
198 | } | 206 | } |
199 | 207 | ||
208 | void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, | ||
209 | enum brcmf_sdiod_state state) | ||
210 | { | ||
211 | if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM || | ||
212 | state == sdiodev->state) | ||
213 | return; | ||
214 | |||
215 | brcmf_dbg(TRACE, "%d -> %d\n", sdiodev->state, state); | ||
216 | switch (sdiodev->state) { | ||
217 | case BRCMF_SDIOD_DATA: | ||
218 | /* any other state means bus interface is down */ | ||
219 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
220 | break; | ||
221 | case BRCMF_SDIOD_DOWN: | ||
222 | /* transition from DOWN to DATA means bus interface is up */ | ||
223 | if (state == BRCMF_SDIOD_DATA) | ||
224 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_UP); | ||
225 | break; | ||
226 | default: | ||
227 | break; | ||
228 | } | ||
229 | sdiodev->state = state; | ||
230 | } | ||
231 | |||
200 | static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, | 232 | static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, |
201 | uint regaddr, u8 byte) | 233 | uint regaddr, u8 byte) |
202 | { | 234 | { |
@@ -269,12 +301,6 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
269 | return ret; | 301 | return ret; |
270 | } | 302 | } |
271 | 303 | ||
272 | static void brcmf_sdiod_nomedium_state(struct brcmf_sdio_dev *sdiodev) | ||
273 | { | ||
274 | sdiodev->state = BRCMF_STATE_NOMEDIUM; | ||
275 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
276 | } | ||
277 | |||
278 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 304 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
279 | u8 regsz, void *data, bool write) | 305 | u8 regsz, void *data, bool write) |
280 | { | 306 | { |
@@ -282,7 +308,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
282 | s32 retry = 0; | 308 | s32 retry = 0; |
283 | int ret; | 309 | int ret; |
284 | 310 | ||
285 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) | 311 | if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) |
286 | return -ENOMEDIUM; | 312 | return -ENOMEDIUM; |
287 | 313 | ||
288 | /* | 314 | /* |
@@ -308,7 +334,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
308 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 334 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
309 | 335 | ||
310 | if (ret == -ENOMEDIUM) | 336 | if (ret == -ENOMEDIUM) |
311 | brcmf_sdiod_nomedium_state(sdiodev); | 337 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); |
312 | else if (ret != 0) { | 338 | else if (ret != 0) { |
313 | /* | 339 | /* |
314 | * SleepCSR register access can fail when | 340 | * SleepCSR register access can fail when |
@@ -331,7 +357,7 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
331 | int err = 0, i; | 357 | int err = 0, i; |
332 | u8 addr[3]; | 358 | u8 addr[3]; |
333 | 359 | ||
334 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) | 360 | if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) |
335 | return -ENOMEDIUM; | 361 | return -ENOMEDIUM; |
336 | 362 | ||
337 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; | 363 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
@@ -460,7 +486,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
460 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, | 486 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, |
461 | req_sz); | 487 | req_sz); |
462 | if (err == -ENOMEDIUM) | 488 | if (err == -ENOMEDIUM) |
463 | brcmf_sdiod_nomedium_state(sdiodev); | 489 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); |
464 | return err; | 490 | return err; |
465 | } | 491 | } |
466 | 492 | ||
@@ -595,7 +621,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
595 | 621 | ||
596 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 622 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
597 | if (ret == -ENOMEDIUM) { | 623 | if (ret == -ENOMEDIUM) { |
598 | brcmf_sdiod_nomedium_state(sdiodev); | 624 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); |
599 | break; | 625 | break; |
600 | } else if (ret != 0) { | 626 | } else if (ret != 0) { |
601 | brcmf_err("CMD53 sg block %s failed %d\n", | 627 | brcmf_err("CMD53 sg block %s failed %d\n", |
@@ -877,6 +903,87 @@ static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) | |||
877 | sdiodev->txglomsz = brcmf_sdiod_txglomsz; | 903 | sdiodev->txglomsz = brcmf_sdiod_txglomsz; |
878 | } | 904 | } |
879 | 905 | ||
906 | #ifdef CONFIG_PM_SLEEP | ||
907 | static int brcmf_sdiod_freezer_attach(struct brcmf_sdio_dev *sdiodev) | ||
908 | { | ||
909 | sdiodev->freezer = kzalloc(sizeof(*sdiodev->freezer), GFP_KERNEL); | ||
910 | if (!sdiodev->freezer) | ||
911 | return -ENOMEM; | ||
912 | atomic_set(&sdiodev->freezer->thread_count, 0); | ||
913 | atomic_set(&sdiodev->freezer->freezing, 0); | ||
914 | init_waitqueue_head(&sdiodev->freezer->thread_freeze); | ||
915 | init_completion(&sdiodev->freezer->resumed); | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev) | ||
920 | { | ||
921 | if (sdiodev->freezer) { | ||
922 | WARN_ON(atomic_read(&sdiodev->freezer->freezing)); | ||
923 | kfree(sdiodev->freezer); | ||
924 | } | ||
925 | } | ||
926 | |||
927 | static int brcmf_sdiod_freezer_on(struct brcmf_sdio_dev *sdiodev) | ||
928 | { | ||
929 | atomic_t *expect = &sdiodev->freezer->thread_count; | ||
930 | int res = 0; | ||
931 | |||
932 | sdiodev->freezer->frozen_count = 0; | ||
933 | reinit_completion(&sdiodev->freezer->resumed); | ||
934 | atomic_set(&sdiodev->freezer->freezing, 1); | ||
935 | brcmf_sdio_trigger_dpc(sdiodev->bus); | ||
936 | wait_event(sdiodev->freezer->thread_freeze, | ||
937 | atomic_read(expect) == sdiodev->freezer->frozen_count); | ||
938 | sdio_claim_host(sdiodev->func[1]); | ||
939 | res = brcmf_sdio_sleep(sdiodev->bus, true); | ||
940 | sdio_release_host(sdiodev->func[1]); | ||
941 | return res; | ||
942 | } | ||
943 | |||
944 | static void brcmf_sdiod_freezer_off(struct brcmf_sdio_dev *sdiodev) | ||
945 | { | ||
946 | sdio_claim_host(sdiodev->func[1]); | ||
947 | brcmf_sdio_sleep(sdiodev->bus, false); | ||
948 | sdio_release_host(sdiodev->func[1]); | ||
949 | atomic_set(&sdiodev->freezer->freezing, 0); | ||
950 | complete_all(&sdiodev->freezer->resumed); | ||
951 | } | ||
952 | |||
953 | bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev) | ||
954 | { | ||
955 | return atomic_read(&sdiodev->freezer->freezing); | ||
956 | } | ||
957 | |||
958 | void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev) | ||
959 | { | ||
960 | if (!brcmf_sdiod_freezing(sdiodev)) | ||
961 | return; | ||
962 | sdiodev->freezer->frozen_count++; | ||
963 | wake_up(&sdiodev->freezer->thread_freeze); | ||
964 | wait_for_completion(&sdiodev->freezer->resumed); | ||
965 | } | ||
966 | |||
967 | void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev) | ||
968 | { | ||
969 | atomic_inc(&sdiodev->freezer->thread_count); | ||
970 | } | ||
971 | |||
972 | void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev) | ||
973 | { | ||
974 | atomic_dec(&sdiodev->freezer->thread_count); | ||
975 | } | ||
976 | #else | ||
977 | static int brcmf_sdiod_freezer_attach(struct brcmf_sdio_dev *sdiodev) | ||
978 | { | ||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev) | ||
983 | { | ||
984 | } | ||
985 | #endif /* CONFIG_PM_SLEEP */ | ||
986 | |||
880 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 987 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) |
881 | { | 988 | { |
882 | if (sdiodev->bus) { | 989 | if (sdiodev->bus) { |
@@ -884,6 +991,8 @@ static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | |||
884 | sdiodev->bus = NULL; | 991 | sdiodev->bus = NULL; |
885 | } | 992 | } |
886 | 993 | ||
994 | brcmf_sdiod_freezer_detach(sdiodev); | ||
995 | |||
887 | /* Disable Function 2 */ | 996 | /* Disable Function 2 */ |
888 | sdio_claim_host(sdiodev->func[2]); | 997 | sdio_claim_host(sdiodev->func[2]); |
889 | sdio_disable_func(sdiodev->func[2]); | 998 | sdio_disable_func(sdiodev->func[2]); |
@@ -955,6 +1064,10 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | |||
955 | */ | 1064 | */ |
956 | brcmf_sdiod_sgtable_alloc(sdiodev); | 1065 | brcmf_sdiod_sgtable_alloc(sdiodev); |
957 | 1066 | ||
1067 | ret = brcmf_sdiod_freezer_attach(sdiodev); | ||
1068 | if (ret) | ||
1069 | goto out; | ||
1070 | |||
958 | /* try to attach to the target device */ | 1071 | /* try to attach to the target device */ |
959 | sdiodev->bus = brcmf_sdio_probe(sdiodev); | 1072 | sdiodev->bus = brcmf_sdio_probe(sdiodev); |
960 | if (!sdiodev->bus) { | 1073 | if (!sdiodev->bus) { |
@@ -1050,9 +1163,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
1050 | bus_if->wowl_supported = true; | 1163 | bus_if->wowl_supported = true; |
1051 | #endif | 1164 | #endif |
1052 | 1165 | ||
1053 | sdiodev->sleeping = false; | 1166 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); |
1054 | atomic_set(&sdiodev->suspend, false); | ||
1055 | init_waitqueue_head(&sdiodev->idle_wait); | ||
1056 | 1167 | ||
1057 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); | 1168 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); |
1058 | err = brcmf_sdiod_probe(sdiodev); | 1169 | err = brcmf_sdiod_probe(sdiodev); |
@@ -1114,24 +1225,22 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) | |||
1114 | #ifdef CONFIG_PM_SLEEP | 1225 | #ifdef CONFIG_PM_SLEEP |
1115 | static int brcmf_ops_sdio_suspend(struct device *dev) | 1226 | static int brcmf_ops_sdio_suspend(struct device *dev) |
1116 | { | 1227 | { |
1228 | struct sdio_func *func; | ||
1117 | struct brcmf_bus *bus_if; | 1229 | struct brcmf_bus *bus_if; |
1118 | struct brcmf_sdio_dev *sdiodev; | 1230 | struct brcmf_sdio_dev *sdiodev; |
1119 | mmc_pm_flag_t sdio_flags; | 1231 | mmc_pm_flag_t sdio_flags; |
1120 | 1232 | ||
1121 | brcmf_dbg(SDIO, "Enter\n"); | 1233 | func = container_of(dev, struct sdio_func, dev); |
1234 | brcmf_dbg(SDIO, "Enter: F%d\n", func->num); | ||
1235 | if (func->num != SDIO_FUNC_1) | ||
1236 | return 0; | ||
1237 | |||
1122 | 1238 | ||
1123 | bus_if = dev_get_drvdata(dev); | 1239 | bus_if = dev_get_drvdata(dev); |
1124 | sdiodev = bus_if->bus_priv.sdio; | 1240 | sdiodev = bus_if->bus_priv.sdio; |
1125 | 1241 | ||
1126 | /* wait for watchdog to go idle */ | 1242 | brcmf_sdiod_freezer_on(sdiodev); |
1127 | if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping, | ||
1128 | msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) { | ||
1129 | brcmf_err("bus still active\n"); | ||
1130 | return -EBUSY; | ||
1131 | } | ||
1132 | /* disable watchdog */ | ||
1133 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | 1243 | brcmf_sdio_wd_timer(sdiodev->bus, 0); |
1134 | atomic_set(&sdiodev->suspend, true); | ||
1135 | 1244 | ||
1136 | if (sdiodev->wowl_enabled) { | 1245 | if (sdiodev->wowl_enabled) { |
1137 | sdio_flags = MMC_PM_KEEP_POWER; | 1246 | sdio_flags = MMC_PM_KEEP_POWER; |
@@ -1149,12 +1258,13 @@ static int brcmf_ops_sdio_resume(struct device *dev) | |||
1149 | { | 1258 | { |
1150 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1259 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
1151 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1260 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
1261 | struct sdio_func *func = container_of(dev, struct sdio_func, dev); | ||
1152 | 1262 | ||
1153 | brcmf_dbg(SDIO, "Enter\n"); | 1263 | brcmf_dbg(SDIO, "Enter: F%d\n", func->num); |
1154 | if (sdiodev->pdata && sdiodev->pdata->oob_irq_supported) | 1264 | if (func->num != SDIO_FUNC_2) |
1155 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | 1265 | return 0; |
1156 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); | 1266 | |
1157 | atomic_set(&sdiodev->suspend, false); | 1267 | brcmf_sdiod_freezer_off(sdiodev); |
1158 | return 0; | 1268 | return 0; |
1159 | } | 1269 | } |
1160 | 1270 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 06727a61b438..9b805c9fd51e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
@@ -1050,10 +1050,6 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, | |||
1050 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | 1050 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) |
1051 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; | 1051 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; |
1052 | 1052 | ||
1053 | /* Arm scan timeout timer */ | ||
1054 | mod_timer(&cfg->escan_timeout, jiffies + | ||
1055 | WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); | ||
1056 | |||
1057 | escan_req = false; | 1053 | escan_req = false; |
1058 | if (request) { | 1054 | if (request) { |
1059 | /* scan bss */ | 1055 | /* scan bss */ |
@@ -1112,12 +1108,14 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, | |||
1112 | } | 1108 | } |
1113 | } | 1109 | } |
1114 | 1110 | ||
1111 | /* Arm scan timeout timer */ | ||
1112 | mod_timer(&cfg->escan_timeout, jiffies + | ||
1113 | WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); | ||
1114 | |||
1115 | return 0; | 1115 | return 0; |
1116 | 1116 | ||
1117 | scan_out: | 1117 | scan_out: |
1118 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 1118 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
1119 | if (timer_pending(&cfg->escan_timeout)) | ||
1120 | del_timer_sync(&cfg->escan_timeout); | ||
1121 | cfg->scan_request = NULL; | 1119 | cfg->scan_request = NULL; |
1122 | return err; | 1120 | return err; |
1123 | } | 1121 | } |
@@ -2252,7 +2250,6 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2252 | 2250 | ||
2253 | if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { | 2251 | if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { |
2254 | /* we ignore this key index in this case */ | 2252 | /* we ignore this key index in this case */ |
2255 | brcmf_err("invalid key index (%d)\n", key_idx); | ||
2256 | return -EINVAL; | 2253 | return -EINVAL; |
2257 | } | 2254 | } |
2258 | 2255 | ||
@@ -4272,7 +4269,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | |||
4272 | return -EIO; | 4269 | return -EIO; |
4273 | 4270 | ||
4274 | memcpy(&scbval.ea, params->mac, ETH_ALEN); | 4271 | memcpy(&scbval.ea, params->mac, ETH_ALEN); |
4275 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); | 4272 | scbval.val = cpu_to_le32(params->reason_code); |
4276 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | 4273 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, |
4277 | &scbval, sizeof(scbval)); | 4274 | &scbval, sizeof(scbval)); |
4278 | if (err) | 4275 | if (err) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 2d6e2cc1b12c..f8f47dcfa886 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c | |||
@@ -944,6 +944,34 @@ fail: | |||
944 | return ret; | 944 | return ret; |
945 | } | 945 | } |
946 | 946 | ||
947 | static int brcmf_revinfo_read(struct seq_file *s, void *data) | ||
948 | { | ||
949 | struct brcmf_bus *bus_if = dev_get_drvdata(s->private); | ||
950 | struct brcmf_rev_info *ri = &bus_if->drvr->revinfo; | ||
951 | char drev[BRCMU_DOTREV_LEN]; | ||
952 | char brev[BRCMU_BOARDREV_LEN]; | ||
953 | |||
954 | seq_printf(s, "vendorid: 0x%04x\n", ri->vendorid); | ||
955 | seq_printf(s, "deviceid: 0x%04x\n", ri->deviceid); | ||
956 | seq_printf(s, "radiorev: %s\n", brcmu_dotrev_str(ri->radiorev, drev)); | ||
957 | seq_printf(s, "chipnum: %u (%x)\n", ri->chipnum, ri->chipnum); | ||
958 | seq_printf(s, "chiprev: %u\n", ri->chiprev); | ||
959 | seq_printf(s, "chippkg: %u\n", ri->chippkg); | ||
960 | seq_printf(s, "corerev: %u\n", ri->corerev); | ||
961 | seq_printf(s, "boardid: 0x%04x\n", ri->boardid); | ||
962 | seq_printf(s, "boardvendor: 0x%04x\n", ri->boardvendor); | ||
963 | seq_printf(s, "boardrev: %s\n", brcmu_boardrev_str(ri->boardrev, brev)); | ||
964 | seq_printf(s, "driverrev: %s\n", brcmu_dotrev_str(ri->driverrev, drev)); | ||
965 | seq_printf(s, "ucoderev: %u\n", ri->ucoderev); | ||
966 | seq_printf(s, "bus: %u\n", ri->bus); | ||
967 | seq_printf(s, "phytype: %u\n", ri->phytype); | ||
968 | seq_printf(s, "phyrev: %u\n", ri->phyrev); | ||
969 | seq_printf(s, "anarev: %u\n", ri->anarev); | ||
970 | seq_printf(s, "nvramrev: %08x\n", ri->nvramrev); | ||
971 | |||
972 | return 0; | ||
973 | } | ||
974 | |||
947 | int brcmf_bus_start(struct device *dev) | 975 | int brcmf_bus_start(struct device *dev) |
948 | { | 976 | { |
949 | int ret = -1; | 977 | int ret = -1; |
@@ -974,6 +1002,8 @@ int brcmf_bus_start(struct device *dev) | |||
974 | if (ret < 0) | 1002 | if (ret < 0) |
975 | goto fail; | 1003 | goto fail; |
976 | 1004 | ||
1005 | brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); | ||
1006 | |||
977 | /* assure we have chipid before feature attach */ | 1007 | /* assure we have chipid before feature attach */ |
978 | if (!bus_if->chip) { | 1008 | if (!bus_if->chip) { |
979 | bus_if->chip = drvr->revinfo.chipnum; | 1009 | bus_if->chip = drvr->revinfo.chipnum; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index faec35c899ec..257ee70feb5b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
@@ -515,6 +515,7 @@ struct brcmf_sdio { | |||
515 | bool txoff; /* Transmit flow-controlled */ | 515 | bool txoff; /* Transmit flow-controlled */ |
516 | struct brcmf_sdio_count sdcnt; | 516 | struct brcmf_sdio_count sdcnt; |
517 | bool sr_enabled; /* SaveRestore enabled */ | 517 | bool sr_enabled; /* SaveRestore enabled */ |
518 | bool sleeping; | ||
518 | 519 | ||
519 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ | 520 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ |
520 | bool txglom; /* host tx glomming enable flag */ | 521 | bool txglom; /* host tx glomming enable flag */ |
@@ -1013,12 +1014,12 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1013 | 1014 | ||
1014 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", | 1015 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", |
1015 | (sleep ? "SLEEP" : "WAKE"), | 1016 | (sleep ? "SLEEP" : "WAKE"), |
1016 | (bus->sdiodev->sleeping ? "SLEEP" : "WAKE")); | 1017 | (bus->sleeping ? "SLEEP" : "WAKE")); |
1017 | 1018 | ||
1018 | /* If SR is enabled control bus state with KSO */ | 1019 | /* If SR is enabled control bus state with KSO */ |
1019 | if (bus->sr_enabled) { | 1020 | if (bus->sr_enabled) { |
1020 | /* Done if we're already in the requested state */ | 1021 | /* Done if we're already in the requested state */ |
1021 | if (sleep == bus->sdiodev->sleeping) | 1022 | if (sleep == bus->sleeping) |
1022 | goto end; | 1023 | goto end; |
1023 | 1024 | ||
1024 | /* Going to sleep */ | 1025 | /* Going to sleep */ |
@@ -1026,6 +1027,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1026 | /* Don't sleep if something is pending */ | 1027 | /* Don't sleep if something is pending */ |
1027 | if (atomic_read(&bus->intstatus) || | 1028 | if (atomic_read(&bus->intstatus) || |
1028 | atomic_read(&bus->ipend) > 0 || | 1029 | atomic_read(&bus->ipend) > 0 || |
1030 | bus->ctrl_frame_stat || | ||
1029 | (!atomic_read(&bus->fcstate) && | 1031 | (!atomic_read(&bus->fcstate) && |
1030 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | 1032 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
1031 | data_ok(bus))) { | 1033 | data_ok(bus))) { |
@@ -1065,9 +1067,7 @@ end: | |||
1065 | } else { | 1067 | } else { |
1066 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); | 1068 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
1067 | } | 1069 | } |
1068 | bus->sdiodev->sleeping = sleep; | 1070 | bus->sleeping = sleep; |
1069 | if (sleep) | ||
1070 | wake_up(&bus->sdiodev->idle_wait); | ||
1071 | brcmf_dbg(SDIO, "new state %s\n", | 1071 | brcmf_dbg(SDIO, "new state %s\n", |
1072 | (sleep ? "SLEEP" : "WAKE")); | 1072 | (sleep ? "SLEEP" : "WAKE")); |
1073 | done: | 1073 | done: |
@@ -1909,7 +1909,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1909 | bus->rxpending = true; | 1909 | bus->rxpending = true; |
1910 | 1910 | ||
1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; | 1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
1912 | !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_STATE_DATA; | 1912 | !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_SDIOD_DATA; |
1913 | rd->seq_num++, rxleft--) { | 1913 | rd->seq_num++, rxleft--) { |
1914 | 1914 | ||
1915 | /* Handle glomming separately */ | 1915 | /* Handle glomming separately */ |
@@ -2415,7 +2415,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2415 | } | 2415 | } |
2416 | 2416 | ||
2417 | /* Deflow-control stack if needed */ | 2417 | /* Deflow-control stack if needed */ |
2418 | if ((bus->sdiodev->state == BRCMF_STATE_DATA) && | 2418 | if ((bus->sdiodev->state == BRCMF_SDIOD_DATA) && |
2419 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { | 2419 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { |
2420 | bus->txoff = false; | 2420 | bus->txoff = false; |
2421 | brcmf_txflowblock(bus->sdiodev->dev, false); | 2421 | brcmf_txflowblock(bus->sdiodev->dev, false); |
@@ -2503,7 +2503,7 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
2503 | bus->watchdog_tsk = NULL; | 2503 | bus->watchdog_tsk = NULL; |
2504 | } | 2504 | } |
2505 | 2505 | ||
2506 | if (sdiodev->state != BRCMF_STATE_NOMEDIUM) { | 2506 | if (sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { |
2507 | sdio_claim_host(sdiodev->func[1]); | 2507 | sdio_claim_host(sdiodev->func[1]); |
2508 | 2508 | ||
2509 | /* Enable clock for device interrupts */ | 2509 | /* Enable clock for device interrupts */ |
@@ -2603,21 +2603,6 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
2603 | return ret; | 2603 | return ret; |
2604 | } | 2604 | } |
2605 | 2605 | ||
2606 | static int brcmf_sdio_pm_resume_wait(struct brcmf_sdio_dev *sdiodev) | ||
2607 | { | ||
2608 | #ifdef CONFIG_PM_SLEEP | ||
2609 | int retry; | ||
2610 | |||
2611 | /* Wait for possible resume to complete */ | ||
2612 | retry = 0; | ||
2613 | while ((atomic_read(&sdiodev->suspend)) && (retry++ != 50)) | ||
2614 | msleep(20); | ||
2615 | if (atomic_read(&sdiodev->suspend)) | ||
2616 | return -EIO; | ||
2617 | #endif | ||
2618 | return 0; | ||
2619 | } | ||
2620 | |||
2621 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | 2606 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) |
2622 | { | 2607 | { |
2623 | u32 newstatus = 0; | 2608 | u32 newstatus = 0; |
@@ -2628,9 +2613,6 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2628 | 2613 | ||
2629 | brcmf_dbg(TRACE, "Enter\n"); | 2614 | brcmf_dbg(TRACE, "Enter\n"); |
2630 | 2615 | ||
2631 | if (brcmf_sdio_pm_resume_wait(bus->sdiodev)) | ||
2632 | return; | ||
2633 | |||
2634 | sdio_claim_host(bus->sdiodev->func[1]); | 2616 | sdio_claim_host(bus->sdiodev->func[1]); |
2635 | 2617 | ||
2636 | /* If waiting for HTAVAIL, check status */ | 2618 | /* If waiting for HTAVAIL, check status */ |
@@ -2755,7 +2737,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2755 | brcmf_sdio_sendfromq(bus, framecnt); | 2737 | brcmf_sdio_sendfromq(bus, framecnt); |
2756 | } | 2738 | } |
2757 | 2739 | ||
2758 | if ((bus->sdiodev->state != BRCMF_STATE_DATA) || (err != 0)) { | 2740 | if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { |
2759 | brcmf_err("failed backplane access over SDIO, halting operation\n"); | 2741 | brcmf_err("failed backplane access over SDIO, halting operation\n"); |
2760 | atomic_set(&bus->intstatus, 0); | 2742 | atomic_set(&bus->intstatus, 0); |
2761 | } else if (atomic_read(&bus->intstatus) || | 2743 | } else if (atomic_read(&bus->intstatus) || |
@@ -2862,11 +2844,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2862 | qcount[prec] = pktq_plen(&bus->txq, prec); | 2844 | qcount[prec] = pktq_plen(&bus->txq, prec); |
2863 | #endif | 2845 | #endif |
2864 | 2846 | ||
2865 | if (atomic_read(&bus->dpc_tskcnt) == 0) { | 2847 | brcmf_sdio_trigger_dpc(bus); |
2866 | atomic_inc(&bus->dpc_tskcnt); | ||
2867 | queue_work(bus->brcmf_wq, &bus->datawork); | ||
2868 | } | ||
2869 | |||
2870 | return ret; | 2848 | return ret; |
2871 | } | 2849 | } |
2872 | 2850 | ||
@@ -2964,11 +2942,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2964 | bus->ctrl_frame_buf = msg; | 2942 | bus->ctrl_frame_buf = msg; |
2965 | bus->ctrl_frame_len = msglen; | 2943 | bus->ctrl_frame_len = msglen; |
2966 | bus->ctrl_frame_stat = true; | 2944 | bus->ctrl_frame_stat = true; |
2967 | if (atomic_read(&bus->dpc_tskcnt) == 0) { | ||
2968 | atomic_inc(&bus->dpc_tskcnt); | ||
2969 | queue_work(bus->brcmf_wq, &bus->datawork); | ||
2970 | } | ||
2971 | 2945 | ||
2946 | brcmf_sdio_trigger_dpc(bus); | ||
2972 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, | 2947 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, |
2973 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); | 2948 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); |
2974 | 2949 | ||
@@ -3411,7 +3386,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, | |||
3411 | } | 3386 | } |
3412 | 3387 | ||
3413 | /* Allow full data communication using DPC from now on. */ | 3388 | /* Allow full data communication using DPC from now on. */ |
3414 | bus->sdiodev->state = BRCMF_STATE_DATA; | 3389 | brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA); |
3415 | bcmerror = 0; | 3390 | bcmerror = 0; |
3416 | 3391 | ||
3417 | err: | 3392 | err: |
@@ -3548,6 +3523,14 @@ done: | |||
3548 | return err; | 3523 | return err; |
3549 | } | 3524 | } |
3550 | 3525 | ||
3526 | void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) | ||
3527 | { | ||
3528 | if (atomic_read(&bus->dpc_tskcnt) == 0) { | ||
3529 | atomic_inc(&bus->dpc_tskcnt); | ||
3530 | queue_work(bus->brcmf_wq, &bus->datawork); | ||
3531 | } | ||
3532 | } | ||
3533 | |||
3551 | void brcmf_sdio_isr(struct brcmf_sdio *bus) | 3534 | void brcmf_sdio_isr(struct brcmf_sdio *bus) |
3552 | { | 3535 | { |
3553 | brcmf_dbg(TRACE, "Enter\n"); | 3536 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -3557,7 +3540,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3557 | return; | 3540 | return; |
3558 | } | 3541 | } |
3559 | 3542 | ||
3560 | if (bus->sdiodev->state != BRCMF_STATE_DATA) { | 3543 | if (bus->sdiodev->state != BRCMF_SDIOD_DATA) { |
3561 | brcmf_err("bus is down. we have nothing to do\n"); | 3544 | brcmf_err("bus is down. we have nothing to do\n"); |
3562 | return; | 3545 | return; |
3563 | } | 3546 | } |
@@ -3602,9 +3585,8 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3602 | SDIO_CCCR_INTx, | 3585 | SDIO_CCCR_INTx, |
3603 | NULL); | 3586 | NULL); |
3604 | sdio_release_host(bus->sdiodev->func[1]); | 3587 | sdio_release_host(bus->sdiodev->func[1]); |
3605 | intstatus = | 3588 | intstatus = devpend & (INTR_STATUS_FUNC1 | |
3606 | devpend & (INTR_STATUS_FUNC1 | | 3589 | INTR_STATUS_FUNC2); |
3607 | INTR_STATUS_FUNC2); | ||
3608 | } | 3590 | } |
3609 | 3591 | ||
3610 | /* If there is something, make like the ISR and | 3592 | /* If there is something, make like the ISR and |
@@ -3623,7 +3605,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3623 | } | 3605 | } |
3624 | #ifdef DEBUG | 3606 | #ifdef DEBUG |
3625 | /* Poll for console output periodically */ | 3607 | /* Poll for console output periodically */ |
3626 | if (bus->sdiodev->state == BRCMF_STATE_DATA && | 3608 | if (bus->sdiodev->state == BRCMF_SDIOD_DATA && |
3627 | bus->console_interval != 0) { | 3609 | bus->console_interval != 0) { |
3628 | bus->console.count += BRCMF_WD_POLL_MS; | 3610 | bus->console.count += BRCMF_WD_POLL_MS; |
3629 | if (bus->console.count >= bus->console_interval) { | 3611 | if (bus->console.count >= bus->console_interval) { |
@@ -3667,6 +3649,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work) | |||
3667 | atomic_set(&bus->dpc_tskcnt, 0); | 3649 | atomic_set(&bus->dpc_tskcnt, 0); |
3668 | brcmf_sdio_dpc(bus); | 3650 | brcmf_sdio_dpc(bus); |
3669 | } | 3651 | } |
3652 | if (brcmf_sdiod_freezing(bus->sdiodev)) { | ||
3653 | brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); | ||
3654 | brcmf_sdiod_try_freeze(bus->sdiodev); | ||
3655 | brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA); | ||
3656 | } | ||
3670 | } | 3657 | } |
3671 | 3658 | ||
3672 | static void | 3659 | static void |
@@ -3944,13 +3931,19 @@ static int | |||
3944 | brcmf_sdio_watchdog_thread(void *data) | 3931 | brcmf_sdio_watchdog_thread(void *data) |
3945 | { | 3932 | { |
3946 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; | 3933 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; |
3934 | int wait; | ||
3947 | 3935 | ||
3948 | allow_signal(SIGTERM); | 3936 | allow_signal(SIGTERM); |
3949 | /* Run until signal received */ | 3937 | /* Run until signal received */ |
3938 | brcmf_sdiod_freezer_count(bus->sdiodev); | ||
3950 | while (1) { | 3939 | while (1) { |
3951 | if (kthread_should_stop()) | 3940 | if (kthread_should_stop()) |
3952 | break; | 3941 | break; |
3953 | if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { | 3942 | brcmf_sdiod_freezer_uncount(bus->sdiodev); |
3943 | wait = wait_for_completion_interruptible(&bus->watchdog_wait); | ||
3944 | brcmf_sdiod_freezer_count(bus->sdiodev); | ||
3945 | brcmf_sdiod_try_freeze(bus->sdiodev); | ||
3946 | if (!wait) { | ||
3954 | brcmf_sdio_bus_watchdog(bus); | 3947 | brcmf_sdio_bus_watchdog(bus); |
3955 | /* Count the tick for reference */ | 3948 | /* Count the tick for reference */ |
3956 | bus->sdcnt.tickcnt++; | 3949 | bus->sdcnt.tickcnt++; |
@@ -3971,7 +3964,7 @@ brcmf_sdio_watchdog(unsigned long data) | |||
3971 | /* Reschedule the watchdog */ | 3964 | /* Reschedule the watchdog */ |
3972 | if (bus->wd_timer_valid) | 3965 | if (bus->wd_timer_valid) |
3973 | mod_timer(&bus->timer, | 3966 | mod_timer(&bus->timer, |
3974 | jiffies + BRCMF_WD_POLL_MS * HZ / 1000); | 3967 | jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS)); |
3975 | } | 3968 | } |
3976 | } | 3969 | } |
3977 | 3970 | ||
@@ -4089,6 +4082,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4089 | { | 4082 | { |
4090 | int ret; | 4083 | int ret; |
4091 | struct brcmf_sdio *bus; | 4084 | struct brcmf_sdio *bus; |
4085 | struct workqueue_struct *wq; | ||
4092 | 4086 | ||
4093 | brcmf_dbg(TRACE, "Enter\n"); | 4087 | brcmf_dbg(TRACE, "Enter\n"); |
4094 | 4088 | ||
@@ -4117,12 +4111,16 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4117 | bus->sgentry_align = sdiodev->pdata->sd_sgentry_align; | 4111 | bus->sgentry_align = sdiodev->pdata->sd_sgentry_align; |
4118 | } | 4112 | } |
4119 | 4113 | ||
4120 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | 4114 | /* single-threaded workqueue */ |
4121 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); | 4115 | wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, |
4122 | if (bus->brcmf_wq == NULL) { | 4116 | dev_name(&sdiodev->func[1]->dev)); |
4117 | if (!wq) { | ||
4123 | brcmf_err("insufficient memory to create txworkqueue\n"); | 4118 | brcmf_err("insufficient memory to create txworkqueue\n"); |
4124 | goto fail; | 4119 | goto fail; |
4125 | } | 4120 | } |
4121 | brcmf_sdiod_freezer_count(sdiodev); | ||
4122 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | ||
4123 | bus->brcmf_wq = wq; | ||
4126 | 4124 | ||
4127 | /* attempt to attach to the dongle */ | 4125 | /* attempt to attach to the dongle */ |
4128 | if (!(brcmf_sdio_probe_attach(bus))) { | 4126 | if (!(brcmf_sdio_probe_attach(bus))) { |
@@ -4143,7 +4141,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4143 | /* Initialize watchdog thread */ | 4141 | /* Initialize watchdog thread */ |
4144 | init_completion(&bus->watchdog_wait); | 4142 | init_completion(&bus->watchdog_wait); |
4145 | bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread, | 4143 | bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread, |
4146 | bus, "brcmf_watchdog"); | 4144 | bus, "brcmf_wdog/%s", |
4145 | dev_name(&sdiodev->func[1]->dev)); | ||
4147 | if (IS_ERR(bus->watchdog_tsk)) { | 4146 | if (IS_ERR(bus->watchdog_tsk)) { |
4148 | pr_warn("brcmf_watchdog thread failed to start\n"); | 4147 | pr_warn("brcmf_watchdog thread failed to start\n"); |
4149 | bus->watchdog_tsk = NULL; | 4148 | bus->watchdog_tsk = NULL; |
@@ -4242,7 +4241,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
4242 | destroy_workqueue(bus->brcmf_wq); | 4241 | destroy_workqueue(bus->brcmf_wq); |
4243 | 4242 | ||
4244 | if (bus->ci) { | 4243 | if (bus->ci) { |
4245 | if (bus->sdiodev->state != BRCMF_STATE_NOMEDIUM) { | 4244 | if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { |
4246 | sdio_claim_host(bus->sdiodev->func[1]); | 4245 | sdio_claim_host(bus->sdiodev->func[1]); |
4247 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 4246 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
4248 | /* Leave the device in state where it is | 4247 | /* Leave the device in state where it is |
@@ -4277,7 +4276,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) | |||
4277 | } | 4276 | } |
4278 | 4277 | ||
4279 | /* don't start the wd until fw is loaded */ | 4278 | /* don't start the wd until fw is loaded */ |
4280 | if (bus->sdiodev->state != BRCMF_STATE_DATA) | 4279 | if (bus->sdiodev->state != BRCMF_SDIOD_DATA) |
4281 | return; | 4280 | return; |
4282 | 4281 | ||
4283 | if (wdtick) { | 4282 | if (wdtick) { |
@@ -4290,16 +4289,28 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) | |||
4290 | dynamically changed or in the first instance | 4289 | dynamically changed or in the first instance |
4291 | */ | 4290 | */ |
4292 | bus->timer.expires = | 4291 | bus->timer.expires = |
4293 | jiffies + BRCMF_WD_POLL_MS * HZ / 1000; | 4292 | jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS); |
4294 | add_timer(&bus->timer); | 4293 | add_timer(&bus->timer); |
4295 | 4294 | ||
4296 | } else { | 4295 | } else { |
4297 | /* Re arm the timer, at last watchdog period */ | 4296 | /* Re arm the timer, at last watchdog period */ |
4298 | mod_timer(&bus->timer, | 4297 | mod_timer(&bus->timer, |
4299 | jiffies + BRCMF_WD_POLL_MS * HZ / 1000); | 4298 | jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS)); |
4300 | } | 4299 | } |
4301 | 4300 | ||
4302 | bus->wd_timer_valid = true; | 4301 | bus->wd_timer_valid = true; |
4303 | bus->save_ms = wdtick; | 4302 | bus->save_ms = wdtick; |
4304 | } | 4303 | } |
4305 | } | 4304 | } |
4305 | |||
4306 | int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep) | ||
4307 | { | ||
4308 | int ret; | ||
4309 | |||
4310 | sdio_claim_host(bus->sdiodev->func[1]); | ||
4311 | ret = brcmf_sdio_bus_sleep(bus, sleep, false); | ||
4312 | sdio_release_host(bus->sdiodev->func[1]); | ||
4313 | |||
4314 | return ret; | ||
4315 | } | ||
4316 | |||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index ec2586a8425c..7328478b2d7b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h | |||
@@ -155,11 +155,17 @@ | |||
155 | /* watchdog polling interval in ms */ | 155 | /* watchdog polling interval in ms */ |
156 | #define BRCMF_WD_POLL_MS 10 | 156 | #define BRCMF_WD_POLL_MS 10 |
157 | 157 | ||
158 | /* The state of the bus */ | 158 | /** |
159 | enum brcmf_sdio_state { | 159 | * enum brcmf_sdiod_state - the state of the bus. |
160 | BRCMF_STATE_DOWN, /* Device available, still initialising */ | 160 | * |
161 | BRCMF_STATE_DATA, /* Ready for data transfers, DPC enabled */ | 161 | * @BRCMF_SDIOD_DOWN: Device can be accessed, no DPC. |
162 | BRCMF_STATE_NOMEDIUM /* No medium access to dongle possible */ | 162 | * @BRCMF_SDIOD_DATA: Ready for data transfers, DPC enabled. |
163 | * @BRCMF_SDIOD_NOMEDIUM: No medium access to dongle possible. | ||
164 | */ | ||
165 | enum brcmf_sdiod_state { | ||
166 | BRCMF_SDIOD_DOWN, | ||
167 | BRCMF_SDIOD_DATA, | ||
168 | BRCMF_SDIOD_NOMEDIUM | ||
163 | }; | 169 | }; |
164 | 170 | ||
165 | struct brcmf_sdreg { | 171 | struct brcmf_sdreg { |
@@ -169,15 +175,13 @@ struct brcmf_sdreg { | |||
169 | }; | 175 | }; |
170 | 176 | ||
171 | struct brcmf_sdio; | 177 | struct brcmf_sdio; |
178 | struct brcmf_sdiod_freezer; | ||
172 | 179 | ||
173 | struct brcmf_sdio_dev { | 180 | struct brcmf_sdio_dev { |
174 | struct sdio_func *func[SDIO_MAX_FUNCS]; | 181 | struct sdio_func *func[SDIO_MAX_FUNCS]; |
175 | u8 num_funcs; /* Supported funcs on client */ | 182 | u8 num_funcs; /* Supported funcs on client */ |
176 | u32 sbwad; /* Save backplane window address */ | 183 | u32 sbwad; /* Save backplane window address */ |
177 | struct brcmf_sdio *bus; | 184 | struct brcmf_sdio *bus; |
178 | atomic_t suspend; /* suspend flag */ | ||
179 | bool sleeping; | ||
180 | wait_queue_head_t idle_wait; | ||
181 | struct device *dev; | 185 | struct device *dev; |
182 | struct brcmf_bus *bus_if; | 186 | struct brcmf_bus *bus_if; |
183 | struct brcmfmac_sdio_platform_data *pdata; | 187 | struct brcmfmac_sdio_platform_data *pdata; |
@@ -194,7 +198,8 @@ struct brcmf_sdio_dev { | |||
194 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 198 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
195 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 199 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
196 | bool wowl_enabled; | 200 | bool wowl_enabled; |
197 | enum brcmf_sdio_state state; | 201 | enum brcmf_sdiod_state state; |
202 | struct brcmf_sdiod_freezer *freezer; | ||
198 | }; | 203 | }; |
199 | 204 | ||
200 | /* sdio core registers */ | 205 | /* sdio core registers */ |
@@ -337,6 +342,28 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
337 | 342 | ||
338 | /* Issue an abort to the specified function */ | 343 | /* Issue an abort to the specified function */ |
339 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); | 344 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
345 | void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, | ||
346 | enum brcmf_sdiod_state state); | ||
347 | #ifdef CONFIG_PM_SLEEP | ||
348 | bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev); | ||
349 | void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev); | ||
350 | void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev); | ||
351 | void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev); | ||
352 | #else | ||
353 | static inline bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev) | ||
354 | { | ||
355 | return false; | ||
356 | } | ||
357 | static inline void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev) | ||
358 | { | ||
359 | } | ||
360 | static inline void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev) | ||
361 | { | ||
362 | } | ||
363 | static inline void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev) | ||
364 | { | ||
365 | } | ||
366 | #endif /* CONFIG_PM_SLEEP */ | ||
340 | 367 | ||
341 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); | 368 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); |
342 | void brcmf_sdio_remove(struct brcmf_sdio *bus); | 369 | void brcmf_sdio_remove(struct brcmf_sdio *bus); |
@@ -344,5 +371,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus); | |||
344 | 371 | ||
345 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); | 372 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); |
346 | void brcmf_sdio_wowl_config(struct device *dev, bool enabled); | 373 | void brcmf_sdio_wowl_config(struct device *dev, bool enabled); |
374 | int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep); | ||
375 | void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus); | ||
347 | 376 | ||
348 | #endif /* BRCMFMAC_SDIO_H */ | 377 | #endif /* BRCMFMAC_SDIO_H */ |