diff options
Diffstat (limited to 'drivers/net')
68 files changed, 1623 insertions, 1245 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 6169fbd23ed1..4521342c62cc 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -159,6 +159,7 @@ struct ath_common { | |||
159 | 159 | ||
160 | bool btcoex_enabled; | 160 | bool btcoex_enabled; |
161 | bool disable_ani; | 161 | bool disable_ani; |
162 | bool antenna_diversity; | ||
162 | }; | 163 | }; |
163 | 164 | ||
164 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | 165 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a0a202de1109..9fd6d9a9942e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -2446,6 +2446,7 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) | |||
2446 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 2446 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
2447 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 2447 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
2448 | IEEE80211_HW_SIGNAL_DBM | | 2448 | IEEE80211_HW_SIGNAL_DBM | |
2449 | IEEE80211_HW_MFP_CAPABLE | | ||
2449 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | 2450 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; |
2450 | 2451 | ||
2451 | hw->wiphy->interface_modes = | 2452 | hw->wiphy->interface_modes = |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index df61a09adb6d..7a28538e6e05 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -489,6 +489,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
489 | if (ath5k_modparam_nohwcrypt) | 489 | if (ath5k_modparam_nohwcrypt) |
490 | return -EOPNOTSUPP; | 490 | return -EOPNOTSUPP; |
491 | 491 | ||
492 | if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) | ||
493 | return -EOPNOTSUPP; | ||
494 | |||
492 | if (vif->type == NL80211_IFTYPE_ADHOC && | 495 | if (vif->type == NL80211_IFTYPE_ADHOC && |
493 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | 496 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || |
494 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | 497 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && |
@@ -523,7 +526,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
523 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | 526 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
524 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 527 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
525 | if (key->cipher == WLAN_CIPHER_SUITE_CCMP) | 528 | if (key->cipher == WLAN_CIPHER_SUITE_CCMP) |
526 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 529 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
527 | ret = 0; | 530 | ret = 0; |
528 | } | 531 | } |
529 | break; | 532 | break; |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 01c90ed58453..ab363f34b4df 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1975,11 +1975,13 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1975 | spur_delta_phase = (spur_offset << 18) / 25; | 1975 | spur_delta_phase = (spur_offset << 18) / 25; |
1976 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | 1976 | spur_freq_sigma_delta = (spur_delta_phase >> 10); |
1977 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; | 1977 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; |
1978 | break; | ||
1978 | case AR5K_BWMODE_5MHZ: | 1979 | case AR5K_BWMODE_5MHZ: |
1979 | /* Both sample_freq and chip_freq are 10MHz (?) */ | 1980 | /* Both sample_freq and chip_freq are 10MHz (?) */ |
1980 | spur_delta_phase = (spur_offset << 19) / 25; | 1981 | spur_delta_phase = (spur_offset << 19) / 25; |
1981 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | 1982 | spur_freq_sigma_delta = (spur_delta_phase >> 10); |
1982 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; | 1983 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; |
1984 | break; | ||
1983 | default: | 1985 | default: |
1984 | if (channel->band == IEEE80211_BAND_5GHZ) { | 1986 | if (channel->band == IEEE80211_BAND_5GHZ) { |
1985 | /* Both sample_freq and chip_freq are 40MHz */ | 1987 | /* Both sample_freq and chip_freq are 40MHz */ |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 86aeef4b9d7e..7089f8160ad5 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -1488,7 +1488,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy, | |||
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy, | 1490 | static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy, |
1491 | char *name, | 1491 | const char *name, |
1492 | enum nl80211_iftype type, | 1492 | enum nl80211_iftype type, |
1493 | u32 *flags, | 1493 | u32 *flags, |
1494 | struct vif_params *params) | 1494 | struct vif_params *params) |
@@ -3477,7 +3477,7 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) | |||
3477 | ar->num_vif--; | 3477 | ar->num_vif--; |
3478 | } | 3478 | } |
3479 | 3479 | ||
3480 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name, | 3480 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, |
3481 | enum nl80211_iftype type, | 3481 | enum nl80211_iftype type, |
3482 | u8 fw_vif_idx, u8 nw_type) | 3482 | u8 fw_vif_idx, u8 nw_type) |
3483 | { | 3483 | { |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 56b1ebe79812..780f77775a91 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -25,7 +25,7 @@ enum ath6kl_cfg_suspend_mode { | |||
25 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, | 25 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name, | 28 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, |
29 | enum nl80211_iftype type, | 29 | enum nl80211_iftype type, |
30 | u8 fw_vif_idx, u8 nw_type); | 30 | u8 fw_vif_idx, u8 nw_type); |
31 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | 31 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, |
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c index bbcfeb3b2a60..664844c5d3d5 100644 --- a/drivers/net/wireless/ath/ath9k/antenna.c +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
@@ -311,6 +311,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
311 | struct ath_ant_comb *antcomb, | 311 | struct ath_ant_comb *antcomb, |
312 | int alt_ratio) | 312 | int alt_ratio) |
313 | { | 313 | { |
314 | ant_conf->main_gaintb = 0; | ||
315 | ant_conf->alt_gaintb = 0; | ||
316 | |||
314 | if (ant_conf->div_group == 0) { | 317 | if (ant_conf->div_group == 0) { |
315 | /* Adjust the fast_div_bias based on main and alt lna conf */ | 318 | /* Adjust the fast_div_bias based on main and alt lna conf */ |
316 | switch ((ant_conf->main_lna_conf << 4) | | 319 | switch ((ant_conf->main_lna_conf << 4) | |
@@ -360,18 +363,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
360 | ant_conf->alt_lna_conf) { | 363 | ant_conf->alt_lna_conf) { |
361 | case 0x01: /* A-B LNA2 */ | 364 | case 0x01: /* A-B LNA2 */ |
362 | ant_conf->fast_div_bias = 0x1; | 365 | ant_conf->fast_div_bias = 0x1; |
363 | ant_conf->main_gaintb = 0; | ||
364 | ant_conf->alt_gaintb = 0; | ||
365 | break; | 366 | break; |
366 | case 0x02: /* A-B LNA1 */ | 367 | case 0x02: /* A-B LNA1 */ |
367 | ant_conf->fast_div_bias = 0x1; | 368 | ant_conf->fast_div_bias = 0x1; |
368 | ant_conf->main_gaintb = 0; | ||
369 | ant_conf->alt_gaintb = 0; | ||
370 | break; | 369 | break; |
371 | case 0x03: /* A-B A+B */ | 370 | case 0x03: /* A-B A+B */ |
372 | ant_conf->fast_div_bias = 0x1; | 371 | ant_conf->fast_div_bias = 0x1; |
373 | ant_conf->main_gaintb = 0; | ||
374 | ant_conf->alt_gaintb = 0; | ||
375 | break; | 372 | break; |
376 | case 0x10: /* LNA2 A-B */ | 373 | case 0x10: /* LNA2 A-B */ |
377 | if (!(antcomb->scan) && | 374 | if (!(antcomb->scan) && |
@@ -379,13 +376,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
379 | ant_conf->fast_div_bias = 0x3f; | 376 | ant_conf->fast_div_bias = 0x3f; |
380 | else | 377 | else |
381 | ant_conf->fast_div_bias = 0x1; | 378 | ant_conf->fast_div_bias = 0x1; |
382 | ant_conf->main_gaintb = 0; | ||
383 | ant_conf->alt_gaintb = 0; | ||
384 | break; | 379 | break; |
385 | case 0x12: /* LNA2 LNA1 */ | 380 | case 0x12: /* LNA2 LNA1 */ |
386 | ant_conf->fast_div_bias = 0x1; | 381 | ant_conf->fast_div_bias = 0x1; |
387 | ant_conf->main_gaintb = 0; | ||
388 | ant_conf->alt_gaintb = 0; | ||
389 | break; | 382 | break; |
390 | case 0x13: /* LNA2 A+B */ | 383 | case 0x13: /* LNA2 A+B */ |
391 | if (!(antcomb->scan) && | 384 | if (!(antcomb->scan) && |
@@ -393,8 +386,6 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
393 | ant_conf->fast_div_bias = 0x3f; | 386 | ant_conf->fast_div_bias = 0x3f; |
394 | else | 387 | else |
395 | ant_conf->fast_div_bias = 0x1; | 388 | ant_conf->fast_div_bias = 0x1; |
396 | ant_conf->main_gaintb = 0; | ||
397 | ant_conf->alt_gaintb = 0; | ||
398 | break; | 389 | break; |
399 | case 0x20: /* LNA1 A-B */ | 390 | case 0x20: /* LNA1 A-B */ |
400 | if (!(antcomb->scan) && | 391 | if (!(antcomb->scan) && |
@@ -402,13 +393,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
402 | ant_conf->fast_div_bias = 0x3f; | 393 | ant_conf->fast_div_bias = 0x3f; |
403 | else | 394 | else |
404 | ant_conf->fast_div_bias = 0x1; | 395 | ant_conf->fast_div_bias = 0x1; |
405 | ant_conf->main_gaintb = 0; | ||
406 | ant_conf->alt_gaintb = 0; | ||
407 | break; | 396 | break; |
408 | case 0x21: /* LNA1 LNA2 */ | 397 | case 0x21: /* LNA1 LNA2 */ |
409 | ant_conf->fast_div_bias = 0x1; | 398 | ant_conf->fast_div_bias = 0x1; |
410 | ant_conf->main_gaintb = 0; | ||
411 | ant_conf->alt_gaintb = 0; | ||
412 | break; | 399 | break; |
413 | case 0x23: /* LNA1 A+B */ | 400 | case 0x23: /* LNA1 A+B */ |
414 | if (!(antcomb->scan) && | 401 | if (!(antcomb->scan) && |
@@ -416,23 +403,15 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
416 | ant_conf->fast_div_bias = 0x3f; | 403 | ant_conf->fast_div_bias = 0x3f; |
417 | else | 404 | else |
418 | ant_conf->fast_div_bias = 0x1; | 405 | ant_conf->fast_div_bias = 0x1; |
419 | ant_conf->main_gaintb = 0; | ||
420 | ant_conf->alt_gaintb = 0; | ||
421 | break; | 406 | break; |
422 | case 0x30: /* A+B A-B */ | 407 | case 0x30: /* A+B A-B */ |
423 | ant_conf->fast_div_bias = 0x1; | 408 | ant_conf->fast_div_bias = 0x1; |
424 | ant_conf->main_gaintb = 0; | ||
425 | ant_conf->alt_gaintb = 0; | ||
426 | break; | 409 | break; |
427 | case 0x31: /* A+B LNA2 */ | 410 | case 0x31: /* A+B LNA2 */ |
428 | ant_conf->fast_div_bias = 0x1; | 411 | ant_conf->fast_div_bias = 0x1; |
429 | ant_conf->main_gaintb = 0; | ||
430 | ant_conf->alt_gaintb = 0; | ||
431 | break; | 412 | break; |
432 | case 0x32: /* A+B LNA1 */ | 413 | case 0x32: /* A+B LNA1 */ |
433 | ant_conf->fast_div_bias = 0x1; | 414 | ant_conf->fast_div_bias = 0x1; |
434 | ant_conf->main_gaintb = 0; | ||
435 | ant_conf->alt_gaintb = 0; | ||
436 | break; | 415 | break; |
437 | default: | 416 | default: |
438 | break; | 417 | break; |
@@ -443,18 +422,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
443 | ant_conf->alt_lna_conf) { | 422 | ant_conf->alt_lna_conf) { |
444 | case 0x01: /* A-B LNA2 */ | 423 | case 0x01: /* A-B LNA2 */ |
445 | ant_conf->fast_div_bias = 0x1; | 424 | ant_conf->fast_div_bias = 0x1; |
446 | ant_conf->main_gaintb = 0; | ||
447 | ant_conf->alt_gaintb = 0; | ||
448 | break; | 425 | break; |
449 | case 0x02: /* A-B LNA1 */ | 426 | case 0x02: /* A-B LNA1 */ |
450 | ant_conf->fast_div_bias = 0x1; | 427 | ant_conf->fast_div_bias = 0x1; |
451 | ant_conf->main_gaintb = 0; | ||
452 | ant_conf->alt_gaintb = 0; | ||
453 | break; | 428 | break; |
454 | case 0x03: /* A-B A+B */ | 429 | case 0x03: /* A-B A+B */ |
455 | ant_conf->fast_div_bias = 0x1; | 430 | ant_conf->fast_div_bias = 0x1; |
456 | ant_conf->main_gaintb = 0; | ||
457 | ant_conf->alt_gaintb = 0; | ||
458 | break; | 431 | break; |
459 | case 0x10: /* LNA2 A-B */ | 432 | case 0x10: /* LNA2 A-B */ |
460 | if (!(antcomb->scan) && | 433 | if (!(antcomb->scan) && |
@@ -462,13 +435,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
462 | ant_conf->fast_div_bias = 0x1; | 435 | ant_conf->fast_div_bias = 0x1; |
463 | else | 436 | else |
464 | ant_conf->fast_div_bias = 0x2; | 437 | ant_conf->fast_div_bias = 0x2; |
465 | ant_conf->main_gaintb = 0; | ||
466 | ant_conf->alt_gaintb = 0; | ||
467 | break; | 438 | break; |
468 | case 0x12: /* LNA2 LNA1 */ | 439 | case 0x12: /* LNA2 LNA1 */ |
469 | ant_conf->fast_div_bias = 0x1; | 440 | ant_conf->fast_div_bias = 0x1; |
470 | ant_conf->main_gaintb = 0; | ||
471 | ant_conf->alt_gaintb = 0; | ||
472 | break; | 441 | break; |
473 | case 0x13: /* LNA2 A+B */ | 442 | case 0x13: /* LNA2 A+B */ |
474 | if (!(antcomb->scan) && | 443 | if (!(antcomb->scan) && |
@@ -476,8 +445,6 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
476 | ant_conf->fast_div_bias = 0x1; | 445 | ant_conf->fast_div_bias = 0x1; |
477 | else | 446 | else |
478 | ant_conf->fast_div_bias = 0x2; | 447 | ant_conf->fast_div_bias = 0x2; |
479 | ant_conf->main_gaintb = 0; | ||
480 | ant_conf->alt_gaintb = 0; | ||
481 | break; | 448 | break; |
482 | case 0x20: /* LNA1 A-B */ | 449 | case 0x20: /* LNA1 A-B */ |
483 | if (!(antcomb->scan) && | 450 | if (!(antcomb->scan) && |
@@ -485,13 +452,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
485 | ant_conf->fast_div_bias = 0x1; | 452 | ant_conf->fast_div_bias = 0x1; |
486 | else | 453 | else |
487 | ant_conf->fast_div_bias = 0x2; | 454 | ant_conf->fast_div_bias = 0x2; |
488 | ant_conf->main_gaintb = 0; | ||
489 | ant_conf->alt_gaintb = 0; | ||
490 | break; | 455 | break; |
491 | case 0x21: /* LNA1 LNA2 */ | 456 | case 0x21: /* LNA1 LNA2 */ |
492 | ant_conf->fast_div_bias = 0x1; | 457 | ant_conf->fast_div_bias = 0x1; |
493 | ant_conf->main_gaintb = 0; | ||
494 | ant_conf->alt_gaintb = 0; | ||
495 | break; | 458 | break; |
496 | case 0x23: /* LNA1 A+B */ | 459 | case 0x23: /* LNA1 A+B */ |
497 | if (!(antcomb->scan) && | 460 | if (!(antcomb->scan) && |
@@ -499,23 +462,77 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
499 | ant_conf->fast_div_bias = 0x1; | 462 | ant_conf->fast_div_bias = 0x1; |
500 | else | 463 | else |
501 | ant_conf->fast_div_bias = 0x2; | 464 | ant_conf->fast_div_bias = 0x2; |
502 | ant_conf->main_gaintb = 0; | ||
503 | ant_conf->alt_gaintb = 0; | ||
504 | break; | 465 | break; |
505 | case 0x30: /* A+B A-B */ | 466 | case 0x30: /* A+B A-B */ |
506 | ant_conf->fast_div_bias = 0x1; | 467 | ant_conf->fast_div_bias = 0x1; |
507 | ant_conf->main_gaintb = 0; | ||
508 | ant_conf->alt_gaintb = 0; | ||
509 | break; | 468 | break; |
510 | case 0x31: /* A+B LNA2 */ | 469 | case 0x31: /* A+B LNA2 */ |
511 | ant_conf->fast_div_bias = 0x1; | 470 | ant_conf->fast_div_bias = 0x1; |
512 | ant_conf->main_gaintb = 0; | ||
513 | ant_conf->alt_gaintb = 0; | ||
514 | break; | 471 | break; |
515 | case 0x32: /* A+B LNA1 */ | 472 | case 0x32: /* A+B LNA1 */ |
516 | ant_conf->fast_div_bias = 0x1; | 473 | ant_conf->fast_div_bias = 0x1; |
517 | ant_conf->main_gaintb = 0; | 474 | break; |
518 | ant_conf->alt_gaintb = 0; | 475 | default: |
476 | break; | ||
477 | } | ||
478 | } else if (ant_conf->div_group == 3) { | ||
479 | switch ((ant_conf->main_lna_conf << 4) | | ||
480 | ant_conf->alt_lna_conf) { | ||
481 | case 0x01: /* A-B LNA2 */ | ||
482 | ant_conf->fast_div_bias = 0x1; | ||
483 | break; | ||
484 | case 0x02: /* A-B LNA1 */ | ||
485 | ant_conf->fast_div_bias = 0x39; | ||
486 | break; | ||
487 | case 0x03: /* A-B A+B */ | ||
488 | ant_conf->fast_div_bias = 0x1; | ||
489 | break; | ||
490 | case 0x10: /* LNA2 A-B */ | ||
491 | if ((antcomb->scan == 0) && | ||
492 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
493 | ant_conf->fast_div_bias = 0x3f; | ||
494 | } else { | ||
495 | ant_conf->fast_div_bias = 0x1; | ||
496 | } | ||
497 | break; | ||
498 | case 0x12: /* LNA2 LNA1 */ | ||
499 | ant_conf->fast_div_bias = 0x39; | ||
500 | break; | ||
501 | case 0x13: /* LNA2 A+B */ | ||
502 | if ((antcomb->scan == 0) && | ||
503 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
504 | ant_conf->fast_div_bias = 0x3f; | ||
505 | } else { | ||
506 | ant_conf->fast_div_bias = 0x1; | ||
507 | } | ||
508 | break; | ||
509 | case 0x20: /* LNA1 A-B */ | ||
510 | if ((antcomb->scan == 0) && | ||
511 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
512 | ant_conf->fast_div_bias = 0x3f; | ||
513 | } else { | ||
514 | ant_conf->fast_div_bias = 0x4; | ||
515 | } | ||
516 | break; | ||
517 | case 0x21: /* LNA1 LNA2 */ | ||
518 | ant_conf->fast_div_bias = 0x6; | ||
519 | break; | ||
520 | case 0x23: /* LNA1 A+B */ | ||
521 | if ((antcomb->scan == 0) && | ||
522 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
523 | ant_conf->fast_div_bias = 0x3f; | ||
524 | } else { | ||
525 | ant_conf->fast_div_bias = 0x6; | ||
526 | } | ||
527 | break; | ||
528 | case 0x30: /* A+B A-B */ | ||
529 | ant_conf->fast_div_bias = 0x1; | ||
530 | break; | ||
531 | case 0x31: /* A+B LNA2 */ | ||
532 | ant_conf->fast_div_bias = 0x6; | ||
533 | break; | ||
534 | case 0x32: /* A+B LNA1 */ | ||
535 | ant_conf->fast_div_bias = 0x1; | ||
519 | break; | 536 | break; |
520 | default: | 537 | default: |
521 | break; | 538 | break; |
@@ -759,6 +776,7 @@ div_comb_done: | |||
759 | void ath_ant_comb_update(struct ath_softc *sc) | 776 | void ath_ant_comb_update(struct ath_softc *sc) |
760 | { | 777 | { |
761 | struct ath_hw *ah = sc->sc_ah; | 778 | struct ath_hw *ah = sc->sc_ah; |
779 | struct ath_common *common = ath9k_hw_common(ah); | ||
762 | struct ath_hw_antcomb_conf div_ant_conf; | 780 | struct ath_hw_antcomb_conf div_ant_conf; |
763 | u8 lna_conf; | 781 | u8 lna_conf; |
764 | 782 | ||
@@ -773,4 +791,7 @@ void ath_ant_comb_update(struct ath_softc *sc) | |||
773 | div_ant_conf.alt_lna_conf = lna_conf; | 791 | div_ant_conf.alt_lna_conf = lna_conf; |
774 | 792 | ||
775 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | 793 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); |
794 | |||
795 | if (common->antenna_diversity) | ||
796 | ath9k_hw_antctrl_shared_chain_lnadiv(ah, true); | ||
776 | } | 797 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 884f9f0014ae..5bbe5057ba18 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3566,9 +3566,9 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, int chain, | |||
3566 | 3566 | ||
3567 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | 3567 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) |
3568 | { | 3568 | { |
3569 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
3569 | int chain; | 3570 | int chain; |
3570 | u32 regval; | 3571 | u32 regval; |
3571 | u32 ant_div_ctl1; | ||
3572 | static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { | 3572 | static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { |
3573 | AR_PHY_SWITCH_CHAIN_0, | 3573 | AR_PHY_SWITCH_CHAIN_0, |
3574 | AR_PHY_SWITCH_CHAIN_1, | 3574 | AR_PHY_SWITCH_CHAIN_1, |
@@ -3633,6 +3633,16 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3633 | /* enable_lnadiv */ | 3633 | /* enable_lnadiv */ |
3634 | regval &= (~AR_PHY_ANT_DIV_LNADIV); | 3634 | regval &= (~AR_PHY_ANT_DIV_LNADIV); |
3635 | regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; | 3635 | regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; |
3636 | |||
3637 | if (AR_SREV_9565(ah)) { | ||
3638 | if (ah->shared_chain_lnadiv) { | ||
3639 | regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); | ||
3640 | } else { | ||
3641 | regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); | ||
3642 | regval &= ~(1 << AR_PHY_ANT_SW_RX_PROT_S); | ||
3643 | } | ||
3644 | } | ||
3645 | |||
3636 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 3646 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
3637 | 3647 | ||
3638 | /*enable fast_div */ | 3648 | /*enable fast_div */ |
@@ -3640,9 +3650,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3640 | regval &= (~AR_FAST_DIV_ENABLE); | 3650 | regval &= (~AR_FAST_DIV_ENABLE); |
3641 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | 3651 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; |
3642 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | 3652 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); |
3643 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | 3653 | |
3644 | /* check whether antenna diversity is enabled */ | 3654 | if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { |
3645 | if ((ant_div_ctl1 >> 0x6) == 0x3) { | ||
3646 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | 3655 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); |
3647 | /* | 3656 | /* |
3648 | * clear bits 25-30 main_lnaconf, alt_lnaconf, | 3657 | * clear bits 25-30 main_lnaconf, alt_lnaconf, |
@@ -3659,10 +3668,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3659 | AR_PHY_ANT_DIV_ALT_LNACONF_S); | 3668 | AR_PHY_ANT_DIV_ALT_LNACONF_S); |
3660 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 3669 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
3661 | } | 3670 | } |
3662 | |||
3663 | |||
3664 | } | 3671 | } |
3665 | |||
3666 | } | 3672 | } |
3667 | 3673 | ||
3668 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) | 3674 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index b2e39e8a21b5..8dbb60b53f1a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -1027,6 +1027,7 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) | |||
1027 | 1027 | ||
1028 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) | 1028 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) |
1029 | ar9003_mci_osla_setup(ah, true); | 1029 | ar9003_mci_osla_setup(ah, true); |
1030 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); | ||
1030 | } else { | 1031 | } else { |
1031 | ar9003_mci_send_lna_take(ah, true); | 1032 | ar9003_mci_send_lna_take(ah, true); |
1032 | udelay(5); | 1033 | udelay(5); |
@@ -1235,6 +1236,10 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) | |||
1235 | case MCI_STATE_NEED_FTP_STOMP: | 1236 | case MCI_STATE_NEED_FTP_STOMP: |
1236 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); | 1237 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); |
1237 | break; | 1238 | break; |
1239 | case MCI_STATE_NEED_FLUSH_BT_INFO: | ||
1240 | value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; | ||
1241 | mci->need_flush_btinfo = false; | ||
1242 | break; | ||
1238 | default: | 1243 | default: |
1239 | break; | 1244 | break; |
1240 | } | 1245 | } |
@@ -1284,7 +1289,7 @@ void ar9003_mci_set_power_awake(struct ath_hw *ah) | |||
1284 | } | 1289 | } |
1285 | REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); | 1290 | REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); |
1286 | lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; | 1291 | lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; |
1287 | bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP; | 1292 | bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP); |
1288 | 1293 | ||
1289 | REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); | 1294 | REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); |
1290 | REG_WRITE(ah, AR_DIAG_SW, diag_sw); | 1295 | REG_WRITE(ah, AR_DIAG_SW, diag_sw); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index f3bef8d69edd..30acf2869aa4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -200,6 +200,7 @@ enum mci_state_type { | |||
200 | MCI_STATE_RECOVER_RX, | 200 | MCI_STATE_RECOVER_RX, |
201 | MCI_STATE_NEED_FTP_STOMP, | 201 | MCI_STATE_NEED_FTP_STOMP, |
202 | MCI_STATE_DEBUG, | 202 | MCI_STATE_DEBUG, |
203 | MCI_STATE_NEED_FLUSH_BT_INFO, | ||
203 | MCI_STATE_MAX | 204 | MCI_STATE_MAX |
204 | }; | 205 | }; |
205 | 206 | ||
@@ -211,7 +212,8 @@ enum mci_gpm_coex_opcode { | |||
211 | MCI_GPM_COEX_WLAN_CHANNELS, | 212 | MCI_GPM_COEX_WLAN_CHANNELS, |
212 | MCI_GPM_COEX_BT_PROFILE_INFO, | 213 | MCI_GPM_COEX_BT_PROFILE_INFO, |
213 | MCI_GPM_COEX_BT_STATUS_UPDATE, | 214 | MCI_GPM_COEX_BT_STATUS_UPDATE, |
214 | MCI_GPM_COEX_BT_UPDATE_FLAGS | 215 | MCI_GPM_COEX_BT_UPDATE_FLAGS, |
216 | MCI_GPM_COEX_NOOP, | ||
215 | }; | 217 | }; |
216 | 218 | ||
217 | #define MCI_GPM_NOMORE 0 | 219 | #define MCI_GPM_NOMORE 0 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 0d800c62e227..fc67844a1430 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -605,9 +605,6 @@ static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | |||
605 | 605 | ||
606 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) | 606 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
607 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | 607 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); |
608 | else if (AR_SREV_9462(ah)) | ||
609 | /* xxx only when MCI support is enabled */ | ||
610 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | ||
611 | else | 608 | else |
612 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | 609 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); |
613 | 610 | ||
@@ -1294,6 +1291,9 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, | |||
1294 | } else if (AR_SREV_9485(ah)) { | 1291 | } else if (AR_SREV_9485(ah)) { |
1295 | antconf->lna1_lna2_delta = -9; | 1292 | antconf->lna1_lna2_delta = -9; |
1296 | antconf->div_group = 2; | 1293 | antconf->div_group = 2; |
1294 | } else if (AR_SREV_9565(ah)) { | ||
1295 | antconf->lna1_lna2_delta = -3; | ||
1296 | antconf->div_group = 3; | ||
1297 | } else { | 1297 | } else { |
1298 | antconf->lna1_lna2_delta = -3; | 1298 | antconf->lna1_lna2_delta = -3; |
1299 | antconf->div_group = 0; | 1299 | antconf->div_group = 0; |
@@ -1325,6 +1325,65 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
1325 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 1325 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, | ||
1329 | bool enable) | ||
1330 | { | ||
1331 | u8 ant_div_ctl1; | ||
1332 | u32 regval; | ||
1333 | |||
1334 | if (!AR_SREV_9565(ah)) | ||
1335 | return; | ||
1336 | |||
1337 | ah->shared_chain_lnadiv = enable; | ||
1338 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
1339 | |||
1340 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1341 | regval &= (~AR_ANT_DIV_CTRL_ALL); | ||
1342 | regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; | ||
1343 | regval &= ~AR_PHY_ANT_DIV_LNADIV; | ||
1344 | regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; | ||
1345 | |||
1346 | if (enable) | ||
1347 | regval |= AR_ANT_DIV_ENABLE; | ||
1348 | |||
1349 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1350 | |||
1351 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
1352 | regval &= ~AR_FAST_DIV_ENABLE; | ||
1353 | regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | ||
1354 | |||
1355 | if (enable) | ||
1356 | regval |= AR_FAST_DIV_ENABLE; | ||
1357 | |||
1358 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
1359 | |||
1360 | if (enable) { | ||
1361 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1362 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1363 | if (IS_CHAN_2GHZ(ah->curchan)) | ||
1364 | REG_SET_BIT(ah, AR_PHY_RESTART, | ||
1365 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
1366 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1367 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1368 | } else { | ||
1369 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE); | ||
1370 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1371 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1372 | REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE); | ||
1373 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1374 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1375 | |||
1376 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1377 | regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF | | ||
1378 | AR_PHY_ANT_DIV_ALT_LNACONF | | ||
1379 | AR_PHY_ANT_DIV_MAIN_GAINTB | | ||
1380 | AR_PHY_ANT_DIV_ALT_GAINTB); | ||
1381 | regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S); | ||
1382 | regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S); | ||
1383 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1328 | static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | 1387 | static int ar9003_hw_fast_chan_change(struct ath_hw *ah, |
1329 | struct ath9k_channel *chan, | 1388 | struct ath9k_channel *chan, |
1330 | u8 *ini_reloaded) | 1389 | u8 *ini_reloaded) |
@@ -1423,6 +1482,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1423 | 1482 | ||
1424 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; | 1483 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; |
1425 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; | 1484 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; |
1485 | ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv; | ||
1426 | 1486 | ||
1427 | ar9003_hw_set_nf_limits(ah); | 1487 | ar9003_hw_set_nf_limits(ah); |
1428 | ar9003_hw_set_radar_conf(ah); | 1488 | ar9003_hw_set_radar_conf(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index fdabc9a28a96..9a48e3d2f231 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -282,6 +282,8 @@ | |||
282 | 282 | ||
283 | #define AR_PHY_ANT_FAST_DIV_BIAS 0x00007e00 | 283 | #define AR_PHY_ANT_FAST_DIV_BIAS 0x00007e00 |
284 | #define AR_PHY_ANT_FAST_DIV_BIAS_S 9 | 284 | #define AR_PHY_ANT_FAST_DIV_BIAS_S 9 |
285 | #define AR_PHY_ANT_SW_RX_PROT 0x00800000 | ||
286 | #define AR_PHY_ANT_SW_RX_PROT_S 23 | ||
285 | #define AR_PHY_ANT_DIV_LNADIV 0x01000000 | 287 | #define AR_PHY_ANT_DIV_LNADIV 0x01000000 |
286 | #define AR_PHY_ANT_DIV_LNADIV_S 24 | 288 | #define AR_PHY_ANT_DIV_LNADIV_S 24 |
287 | #define AR_PHY_ANT_DIV_ALT_LNACONF 0x06000000 | 289 | #define AR_PHY_ANT_DIV_ALT_LNACONF 0x06000000 |
@@ -422,6 +424,8 @@ | |||
422 | #define AR_PHY_FIND_SIG_RELSTEP 0x1f | 424 | #define AR_PHY_FIND_SIG_RELSTEP 0x1f |
423 | #define AR_PHY_FIND_SIG_RELSTEP_S 0 | 425 | #define AR_PHY_FIND_SIG_RELSTEP_S 0 |
424 | #define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5 | 426 | #define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5 |
427 | #define AR_PHY_RESTART_ENABLE_DIV_M2FLAG 0x00200000 | ||
428 | #define AR_PHY_RESTART_ENABLE_DIV_M2FLAG_S 21 | ||
425 | #define AR_PHY_RESTART_DIV_GC 0x001C0000 | 429 | #define AR_PHY_RESTART_DIV_GC 0x001C0000 |
426 | #define AR_PHY_RESTART_DIV_GC_S 18 | 430 | #define AR_PHY_RESTART_DIV_GC_S 18 |
427 | #define AR_PHY_RESTART_ENA 0x01 | 431 | #define AR_PHY_RESTART_ENA 0x01 |
@@ -1261,4 +1265,24 @@ | |||
1261 | #define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f | 1265 | #define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f |
1262 | #define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0 | 1266 | #define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0 |
1263 | 1267 | ||
1268 | #define AR_BTCOEX_WL_LNADIV 0x1a64 | ||
1269 | #define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD 0x00003FFF | ||
1270 | #define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD_S 0 | ||
1271 | #define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY 0x00004000 | ||
1272 | #define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY_S 14 | ||
1273 | #define AR_BTCOEX_WL_LNADIV_FORCE_ON 0x00008000 | ||
1274 | #define AR_BTCOEX_WL_LNADIV_FORCE_ON_S 15 | ||
1275 | #define AR_BTCOEX_WL_LNADIV_MODE_OPTION 0x00030000 | ||
1276 | #define AR_BTCOEX_WL_LNADIV_MODE_OPTION_S 16 | ||
1277 | #define AR_BTCOEX_WL_LNADIV_MODE 0x007c0000 | ||
1278 | #define AR_BTCOEX_WL_LNADIV_MODE_S 18 | ||
1279 | #define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ 0x00800000 | ||
1280 | #define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ_S 23 | ||
1281 | #define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE 0x01000000 | ||
1282 | #define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE_S 24 | ||
1283 | #define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT 0x02000000 | ||
1284 | #define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT_S 25 | ||
1285 | #define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD 0xFC000000 | ||
1286 | #define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S 26 | ||
1287 | |||
1264 | #endif /* AR9003_PHY_H */ | 1288 | #endif /* AR9003_PHY_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index fa9e0932769c..843e79f67ff2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | |||
@@ -58,8 +58,6 @@ static const u32 ar9565_1p0_mac_core[][2] = { | |||
58 | {0x00008040, 0x00000000}, | 58 | {0x00008040, 0x00000000}, |
59 | {0x00008044, 0x00000000}, | 59 | {0x00008044, 0x00000000}, |
60 | {0x00008048, 0x00000000}, | 60 | {0x00008048, 0x00000000}, |
61 | {0x0000804c, 0xffffffff}, | ||
62 | {0x00008050, 0xffffffff}, | ||
63 | {0x00008054, 0x00000000}, | 61 | {0x00008054, 0x00000000}, |
64 | {0x00008058, 0x00000000}, | 62 | {0x00008058, 0x00000000}, |
65 | {0x0000805c, 0x000fc78f}, | 63 | {0x0000805c, 0x000fc78f}, |
@@ -246,7 +244,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
246 | {0x00009e50, 0x00ff03f1}, | 244 | {0x00009e50, 0x00ff03f1}, |
247 | {0x00009e54, 0xe4c355c7}, | 245 | {0x00009e54, 0xe4c355c7}, |
248 | {0x00009e5c, 0xe9198724}, | 246 | {0x00009e5c, 0xe9198724}, |
249 | {0x00009fc0, 0x823e4788}, | 247 | {0x00009fc0, 0x823e4fc8}, |
250 | {0x00009fc4, 0x0001efb5}, | 248 | {0x00009fc4, 0x0001efb5}, |
251 | {0x00009fcc, 0x40000014}, | 249 | {0x00009fcc, 0x40000014}, |
252 | {0x0000a20c, 0x00000000}, | 250 | {0x0000a20c, 0x00000000}, |
@@ -291,7 +289,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
291 | {0x0000a3ec, 0x20202020}, | 289 | {0x0000a3ec, 0x20202020}, |
292 | {0x0000a3f0, 0x00000000}, | 290 | {0x0000a3f0, 0x00000000}, |
293 | {0x0000a3f4, 0x00000006}, | 291 | {0x0000a3f4, 0x00000006}, |
294 | {0x0000a3f8, 0x0cdbd380}, | 292 | {0x0000a3f8, 0x0c9bd380}, |
295 | {0x0000a3fc, 0x000f0f01}, | 293 | {0x0000a3fc, 0x000f0f01}, |
296 | {0x0000a400, 0x8fa91f01}, | 294 | {0x0000a400, 0x8fa91f01}, |
297 | {0x0000a404, 0x00000000}, | 295 | {0x0000a404, 0x00000000}, |
@@ -355,11 +353,11 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { | |||
355 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
356 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 354 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
357 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 355 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
358 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, | 356 | {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, |
359 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 357 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
360 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 358 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
361 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 359 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
362 | {0x0000a204, 0x033187c0, 0x033187c4, 0x033187c4, 0x033187c0}, | 360 | {0x0000a204, 0x07318fc0, 0x07318fc4, 0x07318fc4, 0x07318fc0}, |
363 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | 361 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, |
364 | {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, | 362 | {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, |
365 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, | 363 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, |
@@ -375,9 +373,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { | |||
375 | {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | 373 | {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, |
376 | {0x0000a288, 0x00100510, 0x00100510, 0x00100510, 0x00100510}, | 374 | {0x0000a288, 0x00100510, 0x00100510, 0x00100510, 0x00100510}, |
377 | {0x0000a28c, 0x00021551, 0x00021551, 0x00021551, 0x00021551}, | 375 | {0x0000a28c, 0x00021551, 0x00021551, 0x00021551, 0x00021551}, |
378 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 376 | {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, |
379 | {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, | 377 | {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, |
380 | {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, | 378 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
381 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 379 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
382 | {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 380 | {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, |
383 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 381 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
@@ -417,7 +415,7 @@ static const u32 ar9565_1p0_radio_core[][2] = { | |||
417 | {0x00016144, 0x02084080}, | 415 | {0x00016144, 0x02084080}, |
418 | {0x00016148, 0x000080c0}, | 416 | {0x00016148, 0x000080c0}, |
419 | {0x00016280, 0x050a0001}, | 417 | {0x00016280, 0x050a0001}, |
420 | {0x00016284, 0x3d841400}, | 418 | {0x00016284, 0x3d841440}, |
421 | {0x00016288, 0x00000000}, | 419 | {0x00016288, 0x00000000}, |
422 | {0x0001628c, 0xe3000000}, | 420 | {0x0001628c, 0xe3000000}, |
423 | {0x00016290, 0xa1004080}, | 421 | {0x00016290, 0xa1004080}, |
@@ -840,27 +838,27 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { | |||
840 | {0x0000a0b4, 0x00000000}, | 838 | {0x0000a0b4, 0x00000000}, |
841 | {0x0000a0b8, 0x00000000}, | 839 | {0x0000a0b8, 0x00000000}, |
842 | {0x0000a0bc, 0x00000000}, | 840 | {0x0000a0bc, 0x00000000}, |
843 | {0x0000a0c0, 0x301f3000}, | 841 | {0x0000a0c0, 0x00bf00a0}, |
844 | {0x0000a0c4, 0x41004101}, | 842 | {0x0000a0c4, 0x11a011a1}, |
845 | {0x0000a0c8, 0x411e411f}, | 843 | {0x0000a0c8, 0x11be11bf}, |
846 | {0x0000a0cc, 0x411c411d}, | 844 | {0x0000a0cc, 0x11bc11bd}, |
847 | {0x0000a0d0, 0x42434244}, | 845 | {0x0000a0d0, 0x22632264}, |
848 | {0x0000a0d4, 0x42414242}, | 846 | {0x0000a0d4, 0x22612262}, |
849 | {0x0000a0d8, 0x425f4240}, | 847 | {0x0000a0d8, 0x227f2260}, |
850 | {0x0000a0dc, 0x5342425e}, | 848 | {0x0000a0dc, 0x4322227e}, |
851 | {0x0000a0e0, 0x53405341}, | 849 | {0x0000a0e0, 0x43204321}, |
852 | {0x0000a0e4, 0x535e535f}, | 850 | {0x0000a0e4, 0x433e433f}, |
853 | {0x0000a0e8, 0x7402535d}, | 851 | {0x0000a0e8, 0x4462433d}, |
854 | {0x0000a0ec, 0x74007401}, | 852 | {0x0000a0ec, 0x44604461}, |
855 | {0x0000a0f0, 0x741e741f}, | 853 | {0x0000a0f0, 0x447e447f}, |
856 | {0x0000a0f4, 0x7522741d}, | 854 | {0x0000a0f4, 0x5582447d}, |
857 | {0x0000a0f8, 0x75207521}, | 855 | {0x0000a0f8, 0x55805581}, |
858 | {0x0000a0fc, 0x753e753f}, | 856 | {0x0000a0fc, 0x559e559f}, |
859 | {0x0000a100, 0x76617662}, | 857 | {0x0000a100, 0x66816682}, |
860 | {0x0000a104, 0x767f7660}, | 858 | {0x0000a104, 0x669f6680}, |
861 | {0x0000a108, 0x767d767e}, | 859 | {0x0000a108, 0x669d669e}, |
862 | {0x0000a10c, 0x77e277e3}, | 860 | {0x0000a10c, 0x77627763}, |
863 | {0x0000a110, 0x77e077e1}, | 861 | {0x0000a110, 0x77607761}, |
864 | {0x0000a114, 0x00000000}, | 862 | {0x0000a114, 0x00000000}, |
865 | {0x0000a118, 0x00000000}, | 863 | {0x0000a118, 0x00000000}, |
866 | {0x0000a11c, 0x00000000}, | 864 | {0x0000a11c, 0x00000000}, |
@@ -872,27 +870,27 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { | |||
872 | {0x0000a134, 0x00000000}, | 870 | {0x0000a134, 0x00000000}, |
873 | {0x0000a138, 0x00000000}, | 871 | {0x0000a138, 0x00000000}, |
874 | {0x0000a13c, 0x00000000}, | 872 | {0x0000a13c, 0x00000000}, |
875 | {0x0000a140, 0x301f3000}, | 873 | {0x0000a140, 0x00bf00a0}, |
876 | {0x0000a144, 0x41004101}, | 874 | {0x0000a144, 0x11a011a1}, |
877 | {0x0000a148, 0x411e411f}, | 875 | {0x0000a148, 0x11be11bf}, |
878 | {0x0000a14c, 0x411c411d}, | 876 | {0x0000a14c, 0x11bc11bd}, |
879 | {0x0000a150, 0x42434244}, | 877 | {0x0000a150, 0x22632264}, |
880 | {0x0000a154, 0x42414242}, | 878 | {0x0000a154, 0x22612262}, |
881 | {0x0000a158, 0x425f4240}, | 879 | {0x0000a158, 0x227f2260}, |
882 | {0x0000a15c, 0x5342425e}, | 880 | {0x0000a15c, 0x4322227e}, |
883 | {0x0000a160, 0x53405341}, | 881 | {0x0000a160, 0x43204321}, |
884 | {0x0000a164, 0x535e535f}, | 882 | {0x0000a164, 0x433e433f}, |
885 | {0x0000a168, 0x7402535d}, | 883 | {0x0000a168, 0x4462433d}, |
886 | {0x0000a16c, 0x74007401}, | 884 | {0x0000a16c, 0x44604461}, |
887 | {0x0000a170, 0x741e741f}, | 885 | {0x0000a170, 0x447e447f}, |
888 | {0x0000a174, 0x7522741d}, | 886 | {0x0000a174, 0x5582447d}, |
889 | {0x0000a178, 0x75207521}, | 887 | {0x0000a178, 0x55805581}, |
890 | {0x0000a17c, 0x753e753f}, | 888 | {0x0000a17c, 0x559e559f}, |
891 | {0x0000a180, 0x76617662}, | 889 | {0x0000a180, 0x66816682}, |
892 | {0x0000a184, 0x767f7660}, | 890 | {0x0000a184, 0x669f6680}, |
893 | {0x0000a188, 0x767d767e}, | 891 | {0x0000a188, 0x669d669e}, |
894 | {0x0000a18c, 0x77e277e3}, | 892 | {0x0000a18c, 0x77627763}, |
895 | {0x0000a190, 0x77e077e1}, | 893 | {0x0000a190, 0x77607761}, |
896 | {0x0000a194, 0x00000000}, | 894 | {0x0000a194, 0x00000000}, |
897 | {0x0000a198, 0x00000000}, | 895 | {0x0000a198, 0x00000000}, |
898 | {0x0000a19c, 0x00000000}, | 896 | {0x0000a19c, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 96b8331ef9e7..8e27f4fb21fe 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -537,6 +537,7 @@ struct ath9k_wow_pattern { | |||
537 | #ifdef CONFIG_MAC80211_LEDS | 537 | #ifdef CONFIG_MAC80211_LEDS |
538 | void ath_init_leds(struct ath_softc *sc); | 538 | void ath_init_leds(struct ath_softc *sc); |
539 | void ath_deinit_leds(struct ath_softc *sc); | 539 | void ath_deinit_leds(struct ath_softc *sc); |
540 | void ath_fill_led_pin(struct ath_softc *sc); | ||
540 | #else | 541 | #else |
541 | static inline void ath_init_leds(struct ath_softc *sc) | 542 | static inline void ath_init_leds(struct ath_softc *sc) |
542 | { | 543 | { |
@@ -545,6 +546,9 @@ static inline void ath_init_leds(struct ath_softc *sc) | |||
545 | static inline void ath_deinit_leds(struct ath_softc *sc) | 546 | static inline void ath_deinit_leds(struct ath_softc *sc) |
546 | { | 547 | { |
547 | } | 548 | } |
549 | static inline void ath_fill_led_pin(struct ath_softc *sc) | ||
550 | { | ||
551 | } | ||
548 | #endif | 552 | #endif |
549 | 553 | ||
550 | /*******************************/ | 554 | /*******************************/ |
@@ -596,8 +600,6 @@ struct ath_ant_comb { | |||
596 | int main_conf; | 600 | int main_conf; |
597 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; | 601 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; |
598 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; | 602 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; |
599 | int first_bias; | ||
600 | int second_bias; | ||
601 | bool first_ratio; | 603 | bool first_ratio; |
602 | bool second_ratio; | 604 | bool second_ratio; |
603 | unsigned long scan_start_time; | 605 | unsigned long scan_start_time; |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 45f24220b16e..bf7d29ec1a87 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -44,25 +44,6 @@ void ath_init_leds(struct ath_softc *sc) | |||
44 | if (AR_SREV_9100(sc->sc_ah)) | 44 | if (AR_SREV_9100(sc->sc_ah)) |
45 | return; | 45 | return; |
46 | 46 | ||
47 | if (sc->sc_ah->led_pin < 0) { | ||
48 | if (AR_SREV_9287(sc->sc_ah)) | ||
49 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | ||
50 | else if (AR_SREV_9485(sc->sc_ah)) | ||
51 | sc->sc_ah->led_pin = ATH_LED_PIN_9485; | ||
52 | else if (AR_SREV_9300(sc->sc_ah)) | ||
53 | sc->sc_ah->led_pin = ATH_LED_PIN_9300; | ||
54 | else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) | ||
55 | sc->sc_ah->led_pin = ATH_LED_PIN_9462; | ||
56 | else | ||
57 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | ||
58 | } | ||
59 | |||
60 | /* Configure gpio 1 for output */ | ||
61 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, | ||
62 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
63 | /* LED off, active low */ | ||
64 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
65 | |||
66 | if (!led_blink) | 47 | if (!led_blink) |
67 | sc->led_cdev.default_trigger = | 48 | sc->led_cdev.default_trigger = |
68 | ieee80211_get_radio_led_name(sc->hw); | 49 | ieee80211_get_radio_led_name(sc->hw); |
@@ -78,6 +59,31 @@ void ath_init_leds(struct ath_softc *sc) | |||
78 | 59 | ||
79 | sc->led_registered = true; | 60 | sc->led_registered = true; |
80 | } | 61 | } |
62 | |||
63 | void ath_fill_led_pin(struct ath_softc *sc) | ||
64 | { | ||
65 | struct ath_hw *ah = sc->sc_ah; | ||
66 | |||
67 | if (AR_SREV_9100(ah) || (ah->led_pin >= 0)) | ||
68 | return; | ||
69 | |||
70 | if (AR_SREV_9287(ah)) | ||
71 | ah->led_pin = ATH_LED_PIN_9287; | ||
72 | else if (AR_SREV_9485(sc->sc_ah)) | ||
73 | ah->led_pin = ATH_LED_PIN_9485; | ||
74 | else if (AR_SREV_9300(sc->sc_ah)) | ||
75 | ah->led_pin = ATH_LED_PIN_9300; | ||
76 | else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) | ||
77 | ah->led_pin = ATH_LED_PIN_9462; | ||
78 | else | ||
79 | ah->led_pin = ATH_LED_PIN_DEF; | ||
80 | |||
81 | /* Configure gpio 1 for output */ | ||
82 | ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
83 | |||
84 | /* LED off, active low */ | ||
85 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
86 | } | ||
81 | #endif | 87 | #endif |
82 | 88 | ||
83 | /*******************/ | 89 | /*******************/ |
@@ -314,8 +320,10 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) | |||
314 | ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); | 320 | ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); |
315 | 321 | ||
316 | /* make sure duty cycle timer is also stopped when resuming */ | 322 | /* make sure duty cycle timer is also stopped when resuming */ |
317 | if (btcoex->hw_timer_enabled) | 323 | if (btcoex->hw_timer_enabled) { |
318 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | 324 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); |
325 | btcoex->hw_timer_enabled = false; | ||
326 | } | ||
319 | 327 | ||
320 | btcoex->bt_priority_cnt = 0; | 328 | btcoex->bt_priority_cnt = 0; |
321 | btcoex->bt_priority_time = jiffies; | 329 | btcoex->bt_priority_time = jiffies; |
@@ -336,18 +344,20 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) | |||
336 | 344 | ||
337 | del_timer_sync(&btcoex->period_timer); | 345 | del_timer_sync(&btcoex->period_timer); |
338 | 346 | ||
339 | if (btcoex->hw_timer_enabled) | 347 | if (btcoex->hw_timer_enabled) { |
340 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | 348 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); |
341 | 349 | btcoex->hw_timer_enabled = false; | |
342 | btcoex->hw_timer_enabled = false; | 350 | } |
343 | } | 351 | } |
344 | 352 | ||
345 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) | 353 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) |
346 | { | 354 | { |
347 | struct ath_btcoex *btcoex = &sc->btcoex; | 355 | struct ath_btcoex *btcoex = &sc->btcoex; |
348 | 356 | ||
349 | if (btcoex->hw_timer_enabled) | 357 | if (btcoex->hw_timer_enabled) { |
350 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | 358 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); |
359 | btcoex->hw_timer_enabled = false; | ||
360 | } | ||
351 | } | 361 | } |
352 | 362 | ||
353 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) | 363 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index ee6e50aebf8d..924c4616c3d9 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -1072,14 +1072,15 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) | |||
1072 | */ | 1072 | */ |
1073 | static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) | 1073 | static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) |
1074 | { | 1074 | { |
1075 | struct device *parent = hif_dev->udev->dev.parent; | 1075 | struct device *dev = &hif_dev->udev->dev; |
1076 | struct device *parent = dev->parent; | ||
1076 | 1077 | ||
1077 | complete(&hif_dev->fw_done); | 1078 | complete(&hif_dev->fw_done); |
1078 | 1079 | ||
1079 | if (parent) | 1080 | if (parent) |
1080 | device_lock(parent); | 1081 | device_lock(parent); |
1081 | 1082 | ||
1082 | device_release_driver(&hif_dev->udev->dev); | 1083 | device_release_driver(dev); |
1083 | 1084 | ||
1084 | if (parent) | 1085 | if (parent) |
1085 | device_unlock(parent); | 1086 | device_unlock(parent); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 61d096e3596f..ca78e33ca23e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1445,7 +1445,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1445 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1445 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1446 | if (priv->ah->sw_mgmt_crypto && | 1446 | if (priv->ah->sw_mgmt_crypto && |
1447 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | 1447 | key->cipher == WLAN_CIPHER_SUITE_CCMP) |
1448 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1448 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
1449 | ret = 0; | 1449 | ret = 0; |
1450 | } | 1450 | } |
1451 | break; | 1451 | break; |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 265bf77598a2..0f2b97f6b739 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -78,6 +78,13 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); | 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline void ath9k_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, | ||
82 | bool enable) | ||
83 | { | ||
84 | if (ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv) | ||
85 | ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv(ah, enable); | ||
86 | } | ||
87 | |||
81 | /* Private hardware call ops */ | 88 | /* Private hardware call ops */ |
82 | 89 | ||
83 | /* PHY ops */ | 90 | /* PHY ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 40f57aa2564e..f9a6ec5cf470 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "rc.h" | 24 | #include "rc.h" |
25 | #include "ar9003_mac.h" | 25 | #include "ar9003_mac.h" |
26 | #include "ar9003_mci.h" | 26 | #include "ar9003_mci.h" |
27 | #include "ar9003_phy.h" | ||
27 | #include "debug.h" | 28 | #include "debug.h" |
28 | #include "ath9k.h" | 29 | #include "ath9k.h" |
29 | 30 | ||
@@ -1733,12 +1734,12 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1733 | if (!ret) | 1734 | if (!ret) |
1734 | goto fail; | 1735 | goto fail; |
1735 | 1736 | ||
1736 | ath9k_hw_loadnf(ah, ah->curchan); | ||
1737 | ath9k_hw_start_nfcal(ah, true); | ||
1738 | |||
1739 | if (ath9k_hw_mci_is_enabled(ah)) | 1737 | if (ath9k_hw_mci_is_enabled(ah)) |
1740 | ar9003_mci_2g5g_switch(ah, false); | 1738 | ar9003_mci_2g5g_switch(ah, false); |
1741 | 1739 | ||
1740 | ath9k_hw_loadnf(ah, ah->curchan); | ||
1741 | ath9k_hw_start_nfcal(ah, true); | ||
1742 | |||
1742 | if (AR_SREV_9271(ah)) | 1743 | if (AR_SREV_9271(ah)) |
1743 | ar9002_hw_load_ani_reg(ah, chan); | 1744 | ar9002_hw_load_ani_reg(ah, chan); |
1744 | 1745 | ||
@@ -2025,6 +2026,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2025 | 2026 | ||
2026 | ath9k_hw_apply_gpio_override(ah); | 2027 | ath9k_hw_apply_gpio_override(ah); |
2027 | 2028 | ||
2029 | if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv) | ||
2030 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
2031 | |||
2028 | return 0; | 2032 | return 0; |
2029 | } | 2033 | } |
2030 | EXPORT_SYMBOL(ath9k_hw_reset); | 2034 | EXPORT_SYMBOL(ath9k_hw_reset); |
@@ -2535,7 +2539,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2535 | } | 2539 | } |
2536 | 2540 | ||
2537 | 2541 | ||
2538 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) { | 2542 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { |
2539 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | 2543 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); |
2540 | /* | 2544 | /* |
2541 | * enable the diversity-combining algorithm only when | 2545 | * enable the diversity-combining algorithm only when |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index f0798cc50dc1..566a4ce4f156 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -686,7 +686,7 @@ struct ath_hw_ops { | |||
686 | struct ath_hw_antcomb_conf *antconf); | 686 | struct ath_hw_antcomb_conf *antconf); |
687 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, | 687 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, |
688 | struct ath_hw_antcomb_conf *antconf); | 688 | struct ath_hw_antcomb_conf *antconf); |
689 | 689 | void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable); | |
690 | }; | 690 | }; |
691 | 691 | ||
692 | struct ath_nf_limits { | 692 | struct ath_nf_limits { |
@@ -730,6 +730,7 @@ struct ath_hw { | |||
730 | bool aspm_enabled; | 730 | bool aspm_enabled; |
731 | bool is_monitoring; | 731 | bool is_monitoring; |
732 | bool need_an_top2_fixup; | 732 | bool need_an_top2_fixup; |
733 | bool shared_chain_lnadiv; | ||
733 | u16 tx_trig_level; | 734 | u16 tx_trig_level; |
734 | 735 | ||
735 | u32 nf_regs[6]; | 736 | u32 nf_regs[6]; |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index f3ce5ca2f1d3..fad3ccd5cd91 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -46,6 +46,10 @@ static int ath9k_btcoex_enable; | |||
46 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); | 46 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); |
47 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); | 47 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); |
48 | 48 | ||
49 | static int ath9k_enable_diversity; | ||
50 | module_param_named(enable_diversity, ath9k_enable_diversity, int, 0444); | ||
51 | MODULE_PARM_DESC(enable_diversity, "Enable Antenna diversity for AR9565"); | ||
52 | |||
49 | bool is_ath9k_unloaded; | 53 | bool is_ath9k_unloaded; |
50 | /* We use the hw_value as an index into our private channel structure */ | 54 | /* We use the hw_value as an index into our private channel structure */ |
51 | 55 | ||
@@ -546,6 +550,14 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
546 | common->debug_mask = ath9k_debug; | 550 | common->debug_mask = ath9k_debug; |
547 | common->btcoex_enabled = ath9k_btcoex_enable == 1; | 551 | common->btcoex_enabled = ath9k_btcoex_enable == 1; |
548 | common->disable_ani = false; | 552 | common->disable_ani = false; |
553 | |||
554 | /* | ||
555 | * Enable Antenna diversity only when BTCOEX is disabled | ||
556 | * and the user manually requests the feature. | ||
557 | */ | ||
558 | if (!common->btcoex_enabled && ath9k_enable_diversity) | ||
559 | common->antenna_diversity = 1; | ||
560 | |||
549 | spin_lock_init(&common->cc_lock); | 561 | spin_lock_init(&common->cc_lock); |
550 | 562 | ||
551 | spin_lock_init(&sc->sc_serial_rw); | 563 | spin_lock_init(&sc->sc_serial_rw); |
@@ -597,6 +609,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
597 | 609 | ||
598 | ath9k_cmn_init_crypto(sc->sc_ah); | 610 | ath9k_cmn_init_crypto(sc->sc_ah); |
599 | ath9k_init_misc(sc); | 611 | ath9k_init_misc(sc); |
612 | ath_fill_led_pin(sc); | ||
600 | 613 | ||
601 | if (common->bus_ops->aspm_init) | 614 | if (common->bus_ops->aspm_init) |
602 | common->bus_ops->aspm_init(common); | 615 | common->bus_ops->aspm_init(common); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3923ad933aef..31ab82e3ba85 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1406,7 +1406,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1406 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1406 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1407 | if (sc->sc_ah->sw_mgmt_crypto && | 1407 | if (sc->sc_ah->sw_mgmt_crypto && |
1408 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | 1408 | key->cipher == WLAN_CIPHER_SUITE_CCMP) |
1409 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1409 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
1410 | ret = 0; | 1410 | ret = 0; |
1411 | } | 1411 | } |
1412 | break; | 1412 | break; |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 8f0e8d9c2054..8f51e9e358fd 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -80,6 +80,7 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci) | |||
80 | struct ath_mci_profile_info *info, *tinfo; | 80 | struct ath_mci_profile_info *info, *tinfo; |
81 | 81 | ||
82 | mci->aggr_limit = 0; | 82 | mci->aggr_limit = 0; |
83 | mci->num_mgmt = 0; | ||
83 | 84 | ||
84 | if (list_empty(&mci->info)) | 85 | if (list_empty(&mci->info)) |
85 | return; | 86 | return; |
@@ -120,7 +121,14 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
120 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) | 121 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) |
121 | goto skip_tuning; | 122 | goto skip_tuning; |
122 | 123 | ||
124 | mci->aggr_limit = 0; | ||
123 | btcoex->duty_cycle = ath_mci_duty_cycle[num_profile]; | 125 | btcoex->duty_cycle = ath_mci_duty_cycle[num_profile]; |
126 | btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; | ||
127 | if (NUM_PROF(mci)) | ||
128 | btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
129 | else | ||
130 | btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : | ||
131 | ATH_BTCOEX_STOMP_LOW; | ||
124 | 132 | ||
125 | if (num_profile == 1) { | 133 | if (num_profile == 1) { |
126 | info = list_first_entry(&mci->info, | 134 | info = list_first_entry(&mci->info, |
@@ -132,7 +140,8 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
132 | else if (info->T == 6) { | 140 | else if (info->T == 6) { |
133 | mci->aggr_limit = 6; | 141 | mci->aggr_limit = 6; |
134 | btcoex->duty_cycle = 30; | 142 | btcoex->duty_cycle = 30; |
135 | } | 143 | } else |
144 | mci->aggr_limit = 6; | ||
136 | ath_dbg(common, MCI, | 145 | ath_dbg(common, MCI, |
137 | "Single SCO, aggregation limit %d 1/4 ms\n", | 146 | "Single SCO, aggregation limit %d 1/4 ms\n", |
138 | mci->aggr_limit); | 147 | mci->aggr_limit); |
@@ -241,8 +250,8 @@ static void ath9k_mci_work(struct work_struct *work) | |||
241 | ath_mci_update_scheme(sc); | 250 | ath_mci_update_scheme(sc); |
242 | } | 251 | } |
243 | 252 | ||
244 | static void ath_mci_process_profile(struct ath_softc *sc, | 253 | static u8 ath_mci_process_profile(struct ath_softc *sc, |
245 | struct ath_mci_profile_info *info) | 254 | struct ath_mci_profile_info *info) |
246 | { | 255 | { |
247 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 256 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
248 | struct ath_btcoex *btcoex = &sc->btcoex; | 257 | struct ath_btcoex *btcoex = &sc->btcoex; |
@@ -268,25 +277,15 @@ static void ath_mci_process_profile(struct ath_softc *sc, | |||
268 | 277 | ||
269 | if (info->start) { | 278 | if (info->start) { |
270 | if (!entry && !ath_mci_add_profile(common, mci, info)) | 279 | if (!entry && !ath_mci_add_profile(common, mci, info)) |
271 | return; | 280 | return 0; |
272 | } else | 281 | } else |
273 | ath_mci_del_profile(common, mci, entry); | 282 | ath_mci_del_profile(common, mci, entry); |
274 | 283 | ||
275 | btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; | 284 | return 1; |
276 | mci->aggr_limit = mci->num_sco ? 6 : 0; | ||
277 | |||
278 | btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)]; | ||
279 | if (NUM_PROF(mci)) | ||
280 | btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
281 | else | ||
282 | btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : | ||
283 | ATH_BTCOEX_STOMP_LOW; | ||
284 | |||
285 | ieee80211_queue_work(sc->hw, &sc->mci_work); | ||
286 | } | 285 | } |
287 | 286 | ||
288 | static void ath_mci_process_status(struct ath_softc *sc, | 287 | static u8 ath_mci_process_status(struct ath_softc *sc, |
289 | struct ath_mci_profile_status *status) | 288 | struct ath_mci_profile_status *status) |
290 | { | 289 | { |
291 | struct ath_btcoex *btcoex = &sc->btcoex; | 290 | struct ath_btcoex *btcoex = &sc->btcoex; |
292 | struct ath_mci_profile *mci = &btcoex->mci; | 291 | struct ath_mci_profile *mci = &btcoex->mci; |
@@ -295,14 +294,14 @@ static void ath_mci_process_status(struct ath_softc *sc, | |||
295 | 294 | ||
296 | /* Link status type are not handled */ | 295 | /* Link status type are not handled */ |
297 | if (status->is_link) | 296 | if (status->is_link) |
298 | return; | 297 | return 0; |
299 | 298 | ||
300 | info.conn_handle = status->conn_handle; | 299 | info.conn_handle = status->conn_handle; |
301 | if (ath_mci_find_profile(mci, &info)) | 300 | if (ath_mci_find_profile(mci, &info)) |
302 | return; | 301 | return 0; |
303 | 302 | ||
304 | if (status->conn_handle >= ATH_MCI_MAX_PROFILE) | 303 | if (status->conn_handle >= ATH_MCI_MAX_PROFILE) |
305 | return; | 304 | return 0; |
306 | 305 | ||
307 | if (status->is_critical) | 306 | if (status->is_critical) |
308 | __set_bit(status->conn_handle, mci->status); | 307 | __set_bit(status->conn_handle, mci->status); |
@@ -316,7 +315,9 @@ static void ath_mci_process_status(struct ath_softc *sc, | |||
316 | } while (++i < ATH_MCI_MAX_PROFILE); | 315 | } while (++i < ATH_MCI_MAX_PROFILE); |
317 | 316 | ||
318 | if (old_num_mgmt != mci->num_mgmt) | 317 | if (old_num_mgmt != mci->num_mgmt) |
319 | ieee80211_queue_work(sc->hw, &sc->mci_work); | 318 | return 1; |
319 | |||
320 | return 0; | ||
320 | } | 321 | } |
321 | 322 | ||
322 | static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | 323 | static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) |
@@ -325,9 +326,16 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
325 | struct ath_mci_profile_info profile_info; | 326 | struct ath_mci_profile_info profile_info; |
326 | struct ath_mci_profile_status profile_status; | 327 | struct ath_mci_profile_status profile_status; |
327 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 328 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
328 | u8 major, minor; | 329 | u8 major, minor, update_scheme = 0; |
329 | u32 seq_num; | 330 | u32 seq_num; |
330 | 331 | ||
332 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FLUSH_BT_INFO) && | ||
333 | ar9003_mci_state(ah, MCI_STATE_ENABLE)) { | ||
334 | ath_dbg(common, MCI, "(MCI) Need to flush BT profiles\n"); | ||
335 | ath_mci_flush_profile(&sc->btcoex.mci); | ||
336 | ar9003_mci_state(ah, MCI_STATE_SEND_STATUS_QUERY); | ||
337 | } | ||
338 | |||
331 | switch (opcode) { | 339 | switch (opcode) { |
332 | case MCI_GPM_COEX_VERSION_QUERY: | 340 | case MCI_GPM_COEX_VERSION_QUERY: |
333 | ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION); | 341 | ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION); |
@@ -353,7 +361,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
353 | break; | 361 | break; |
354 | } | 362 | } |
355 | 363 | ||
356 | ath_mci_process_profile(sc, &profile_info); | 364 | update_scheme += ath_mci_process_profile(sc, &profile_info); |
357 | break; | 365 | break; |
358 | case MCI_GPM_COEX_BT_STATUS_UPDATE: | 366 | case MCI_GPM_COEX_BT_STATUS_UPDATE: |
359 | profile_status.is_link = *(rx_payload + | 367 | profile_status.is_link = *(rx_payload + |
@@ -369,12 +377,14 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
369 | profile_status.is_link, profile_status.conn_handle, | 377 | profile_status.is_link, profile_status.conn_handle, |
370 | profile_status.is_critical, seq_num); | 378 | profile_status.is_critical, seq_num); |
371 | 379 | ||
372 | ath_mci_process_status(sc, &profile_status); | 380 | update_scheme += ath_mci_process_status(sc, &profile_status); |
373 | break; | 381 | break; |
374 | default: | 382 | default: |
375 | ath_dbg(common, MCI, "Unknown GPM COEX message = 0x%02x\n", opcode); | 383 | ath_dbg(common, MCI, "Unknown GPM COEX message = 0x%02x\n", opcode); |
376 | break; | 384 | break; |
377 | } | 385 | } |
386 | if (update_scheme) | ||
387 | ieee80211_queue_work(sc->hw, &sc->mci_work); | ||
378 | } | 388 | } |
379 | 389 | ||
380 | int ath_mci_setup(struct ath_softc *sc) | 390 | int ath_mci_setup(struct ath_softc *sc) |
@@ -568,9 +578,11 @@ void ath_mci_intr(struct ath_softc *sc) | |||
568 | } | 578 | } |
569 | 579 | ||
570 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || | 580 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || |
571 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) | 581 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { |
572 | mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | | 582 | mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | |
573 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); | 583 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); |
584 | ath_mci_msg(sc, MCI_GPM_COEX_NOOP, NULL); | ||
585 | } | ||
574 | } | 586 | } |
575 | 587 | ||
576 | void ath_mci_enable(struct ath_softc *sc) | 588 | void ath_mci_enable(struct ath_softc *sc) |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index a8f6126f6b2d..c0c599673eeb 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -128,8 +128,9 @@ static void ath_pci_aspm_init(struct ath_common *common) | |||
128 | if (!parent) | 128 | if (!parent) |
129 | return; | 129 | return; |
130 | 130 | ||
131 | if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { | 131 | if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && |
132 | /* Bluetooth coexistance requires disabling ASPM. */ | 132 | (AR_SREV_9285(ah))) { |
133 | /* Bluetooth coexistance requires disabling ASPM for AR9285. */ | ||
133 | pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); | 134 | pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); |
134 | aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); | 135 | aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); |
135 | pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); | 136 | pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4b12c347d188..27ed80b54881 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1222,11 +1222,14 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
1222 | caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; | 1222 | caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; |
1223 | else if (sta->ht_cap.mcs.rx_mask[1]) | 1223 | else if (sta->ht_cap.mcs.rx_mask[1]) |
1224 | caps |= WLAN_RC_DS_FLAG; | 1224 | caps |= WLAN_RC_DS_FLAG; |
1225 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 1225 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
1226 | caps |= WLAN_RC_40_FLAG; | 1226 | caps |= WLAN_RC_40_FLAG; |
1227 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40 || | 1227 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) |
1228 | sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) | 1228 | caps |= WLAN_RC_SGI_FLAG; |
1229 | caps |= WLAN_RC_SGI_FLAG; | 1229 | } else { |
1230 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) | ||
1231 | caps |= WLAN_RC_SGI_FLAG; | ||
1232 | } | ||
1230 | } | 1233 | } |
1231 | 1234 | ||
1232 | return caps; | 1235 | return caps; |
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index f8676280dc36..e3b1b6e87760 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c | |||
@@ -304,7 +304,8 @@ int carl9170_set_operating_mode(struct ar9170 *ar) | |||
304 | struct ath_common *common = &ar->common; | 304 | struct ath_common *common = &ar->common; |
305 | u8 *mac_addr, *bssid; | 305 | u8 *mac_addr, *bssid; |
306 | u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; | 306 | u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; |
307 | u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS; | 307 | u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS | |
308 | AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE; | ||
308 | u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | | 309 | u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | |
309 | AR9170_MAC_RX_CTRL_SHORT_FILTER; | 310 | AR9170_MAC_RX_CTRL_SHORT_FILTER; |
310 | u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; | 311 | u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 18554ab76733..67997b39aba7 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -1149,6 +1149,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1149 | break; | 1149 | break; |
1150 | case WLAN_CIPHER_SUITE_CCMP: | 1150 | case WLAN_CIPHER_SUITE_CCMP: |
1151 | ktype = AR9170_ENC_ALG_AESCCMP; | 1151 | ktype = AR9170_ENC_ALG_AESCCMP; |
1152 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | ||
1152 | break; | 1153 | break; |
1153 | default: | 1154 | default: |
1154 | return -EOPNOTSUPP; | 1155 | return -EOPNOTSUPP; |
@@ -1780,6 +1781,7 @@ void *carl9170_alloc(size_t priv_size) | |||
1780 | hw->wiphy->interface_modes = 0; | 1781 | hw->wiphy->interface_modes = 0; |
1781 | 1782 | ||
1782 | hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | | 1783 | hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | |
1784 | IEEE80211_HW_MFP_CAPABLE | | ||
1783 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 1785 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
1784 | IEEE80211_HW_SUPPORTS_PS | | 1786 | IEEE80211_HW_SUPPORTS_PS | |
1785 | IEEE80211_HW_PS_NULLFUNC_STACK | | 1787 | IEEE80211_HW_PS_NULLFUNC_STACK | |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8e7e6928c936..3b2c4c20e7fc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -185,7 +185,7 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
185 | return err; | 185 | return err; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int | 188 | int |
189 | brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 189 | brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
190 | void *data, bool write) | 190 | void *data, bool write) |
191 | { | 191 | { |
@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
249 | int retval; | 249 | int retval; |
250 | 250 | ||
251 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 251 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
252 | sdio_claim_host(sdiodev->func[1]); | ||
252 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 253 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
254 | sdio_release_host(sdiodev->func[1]); | ||
253 | brcmf_dbg(INFO, "data:0x%02x\n", data); | 255 | brcmf_dbg(INFO, "data:0x%02x\n", data); |
254 | 256 | ||
255 | if (ret) | 257 | if (ret) |
@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
264 | int retval; | 266 | int retval; |
265 | 267 | ||
266 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 268 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
269 | sdio_claim_host(sdiodev->func[1]); | ||
267 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 270 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
271 | sdio_release_host(sdiodev->func[1]); | ||
268 | brcmf_dbg(INFO, "data:0x%08x\n", data); | 272 | brcmf_dbg(INFO, "data:0x%08x\n", data); |
269 | 273 | ||
270 | if (ret) | 274 | if (ret) |
@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
279 | int retval; | 283 | int retval; |
280 | 284 | ||
281 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); | 285 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); |
286 | sdio_claim_host(sdiodev->func[1]); | ||
282 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 287 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
288 | sdio_release_host(sdiodev->func[1]); | ||
283 | 289 | ||
284 | if (ret) | 290 | if (ret) |
285 | *ret = retval; | 291 | *ret = retval; |
@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
291 | int retval; | 297 | int retval; |
292 | 298 | ||
293 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); | 299 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); |
300 | sdio_claim_host(sdiodev->func[1]); | ||
294 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 301 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
302 | sdio_release_host(sdiodev->func[1]); | ||
295 | 303 | ||
296 | if (ret) | 304 | if (ret) |
297 | *ret = retval; | 305 | *ret = retval; |
@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
356 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 364 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", |
357 | fn, addr, pkt->len); | 365 | fn, addr, pkt->len); |
358 | 366 | ||
367 | sdio_claim_host(sdiodev->func[1]); | ||
368 | |||
359 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 369 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
360 | err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); | 370 | err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); |
361 | if (err) | 371 | if (err) |
362 | return err; | 372 | goto done; |
363 | 373 | ||
364 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | 374 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; |
365 | err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, | 375 | err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, |
366 | fn, addr, pkt); | 376 | fn, addr, pkt); |
367 | 377 | ||
378 | done: | ||
379 | sdio_release_host(sdiodev->func[1]); | ||
380 | |||
368 | return err; | 381 | return err; |
369 | } | 382 | } |
370 | 383 | ||
@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
378 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 391 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", |
379 | fn, addr, pktq->qlen); | 392 | fn, addr, pktq->qlen); |
380 | 393 | ||
394 | sdio_claim_host(sdiodev->func[1]); | ||
395 | |||
381 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 396 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
382 | err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); | 397 | err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); |
383 | if (err) | 398 | if (err) |
384 | return err; | 399 | goto done; |
385 | 400 | ||
386 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | 401 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; |
387 | err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, | 402 | err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, |
388 | pktq); | 403 | pktq); |
389 | 404 | ||
405 | done: | ||
406 | sdio_release_host(sdiodev->func[1]); | ||
407 | |||
390 | return err; | 408 | return err; |
391 | } | 409 | } |
392 | 410 | ||
@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
428 | if (flags & SDIO_REQ_ASYNC) | 446 | if (flags & SDIO_REQ_ASYNC) |
429 | return -ENOTSUPP; | 447 | return -ENOTSUPP; |
430 | 448 | ||
449 | sdio_claim_host(sdiodev->func[1]); | ||
450 | |||
431 | if (bar0 != sdiodev->sbwad) { | 451 | if (bar0 != sdiodev->sbwad) { |
432 | err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); | 452 | err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); |
433 | if (err) | 453 | if (err) |
434 | return err; | 454 | goto done; |
435 | 455 | ||
436 | sdiodev->sbwad = bar0; | 456 | sdiodev->sbwad = bar0; |
437 | } | 457 | } |
@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
443 | if (width == 4) | 463 | if (width == 4) |
444 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 464 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; |
445 | 465 | ||
446 | return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, | 466 | err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, |
447 | addr, pkt); | 467 | addr, pkt); |
468 | |||
469 | done: | ||
470 | sdio_release_host(sdiodev->func[1]); | ||
471 | |||
472 | return err; | ||
448 | } | 473 | } |
449 | 474 | ||
450 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, | 475 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, |
@@ -485,8 +510,10 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | |||
485 | brcmf_dbg(TRACE, "Enter\n"); | 510 | brcmf_dbg(TRACE, "Enter\n"); |
486 | 511 | ||
487 | /* issue abort cmd52 command through F0 */ | 512 | /* issue abort cmd52 command through F0 */ |
513 | sdio_claim_host(sdiodev->func[1]); | ||
488 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, | 514 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, |
489 | SDIO_CCCR_ABORT, &t_func); | 515 | SDIO_CCCR_ABORT, &t_func); |
516 | sdio_release_host(sdiodev->func[1]); | ||
490 | 517 | ||
491 | brcmf_dbg(TRACE, "Exit\n"); | 518 | brcmf_dbg(TRACE, "Exit\n"); |
492 | return 0; | 519 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 372f74eac1e7..c3247d5b3c22 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, | |||
103 | if (regaddr == SDIO_CCCR_IOEx) { | 103 | if (regaddr == SDIO_CCCR_IOEx) { |
104 | sdfunc = sdiodev->func[2]; | 104 | sdfunc = sdiodev->func[2]; |
105 | if (sdfunc) { | 105 | if (sdfunc) { |
106 | sdio_claim_host(sdfunc); | ||
107 | if (*byte & SDIO_FUNC_ENABLE_2) { | 106 | if (*byte & SDIO_FUNC_ENABLE_2) { |
108 | /* Enable Function 2 */ | 107 | /* Enable Function 2 */ |
109 | err_ret = sdio_enable_func(sdfunc); | 108 | err_ret = sdio_enable_func(sdfunc); |
@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, | |||
119 | "Disable F2 failed:%d\n", | 118 | "Disable F2 failed:%d\n", |
120 | err_ret); | 119 | err_ret); |
121 | } | 120 | } |
122 | sdio_release_host(sdfunc); | ||
123 | } | 121 | } |
124 | } else if ((regaddr == SDIO_CCCR_ABORT) || | 122 | } else if ((regaddr == SDIO_CCCR_ABORT) || |
125 | (regaddr == SDIO_CCCR_IENx)) { | 123 | (regaddr == SDIO_CCCR_IENx)) { |
@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, | |||
128 | if (!sdfunc) | 126 | if (!sdfunc) |
129 | return -ENOMEM; | 127 | return -ENOMEM; |
130 | sdfunc->num = 0; | 128 | sdfunc->num = 0; |
131 | sdio_claim_host(sdfunc); | ||
132 | sdio_writeb(sdfunc, *byte, regaddr, &err_ret); | 129 | sdio_writeb(sdfunc, *byte, regaddr, &err_ret); |
133 | sdio_release_host(sdfunc); | ||
134 | kfree(sdfunc); | 130 | kfree(sdfunc); |
135 | } else if (regaddr < 0xF0) { | 131 | } else if (regaddr < 0xF0) { |
136 | brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); | 132 | brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); |
137 | err_ret = -EPERM; | 133 | err_ret = -EPERM; |
138 | } else { | 134 | } else { |
139 | sdio_claim_host(sdfunc); | ||
140 | sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); | 135 | sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); |
141 | sdio_release_host(sdfunc); | ||
142 | } | 136 | } |
143 | 137 | ||
144 | return err_ret; | 138 | return err_ret; |
@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | |||
159 | /* handle F0 separately */ | 153 | /* handle F0 separately */ |
160 | err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); | 154 | err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); |
161 | } else { | 155 | } else { |
162 | sdio_claim_host(sdiodev->func[func]); | ||
163 | if (rw) /* CMD52 Write */ | 156 | if (rw) /* CMD52 Write */ |
164 | sdio_writeb(sdiodev->func[func], *byte, regaddr, | 157 | sdio_writeb(sdiodev->func[func], *byte, regaddr, |
165 | &err_ret); | 158 | &err_ret); |
@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | |||
170 | *byte = sdio_readb(sdiodev->func[func], regaddr, | 163 | *byte = sdio_readb(sdiodev->func[func], regaddr, |
171 | &err_ret); | 164 | &err_ret); |
172 | } | 165 | } |
173 | sdio_release_host(sdiodev->func[func]); | ||
174 | } | 166 | } |
175 | 167 | ||
176 | if (err_ret) | 168 | if (err_ret) |
@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | |||
197 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | 189 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); |
198 | if (brcmf_pm_resume_error(sdiodev)) | 190 | if (brcmf_pm_resume_error(sdiodev)) |
199 | return -EIO; | 191 | return -EIO; |
200 | /* Claim host controller */ | ||
201 | sdio_claim_host(sdiodev->func[func]); | ||
202 | 192 | ||
203 | if (rw) { /* CMD52 Write */ | 193 | if (rw) { /* CMD52 Write */ |
204 | if (nbytes == 4) | 194 | if (nbytes == 4) |
@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | |||
219 | brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); | 209 | brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); |
220 | } | 210 | } |
221 | 211 | ||
222 | /* Release host controller */ | ||
223 | sdio_release_host(sdiodev->func[func]); | ||
224 | |||
225 | if (err_ret) | 212 | if (err_ret) |
226 | brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", | 213 | brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", |
227 | rw ? "write" : "read", err_ret); | 214 | rw ? "write" : "read", err_ret); |
@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
275 | if (brcmf_pm_resume_error(sdiodev)) | 262 | if (brcmf_pm_resume_error(sdiodev)) |
276 | return -EIO; | 263 | return -EIO; |
277 | 264 | ||
278 | /* Claim host controller */ | ||
279 | sdio_claim_host(sdiodev->func[func]); | ||
280 | |||
281 | skb_queue_walk(pktq, pkt) { | 265 | skb_queue_walk(pktq, pkt) { |
282 | uint pkt_len = pkt->len; | 266 | uint pkt_len = pkt->len; |
283 | pkt_len += 3; | 267 | pkt_len += 3; |
@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
300 | SGCount++; | 284 | SGCount++; |
301 | } | 285 | } |
302 | 286 | ||
303 | /* Release host controller */ | ||
304 | sdio_release_host(sdiodev->func[func]); | ||
305 | |||
306 | brcmf_dbg(TRACE, "Exit\n"); | 287 | brcmf_dbg(TRACE, "Exit\n"); |
307 | return err_ret; | 288 | return err_ret; |
308 | } | 289 | } |
@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
328 | if (brcmf_pm_resume_error(sdiodev)) | 309 | if (brcmf_pm_resume_error(sdiodev)) |
329 | return -EIO; | 310 | return -EIO; |
330 | 311 | ||
331 | /* Claim host controller */ | ||
332 | sdio_claim_host(sdiodev->func[func]); | ||
333 | |||
334 | pkt_len += 3; | 312 | pkt_len += 3; |
335 | pkt_len &= (uint)~3; | 313 | pkt_len &= (uint)~3; |
336 | 314 | ||
@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
344 | write ? "TX" : "RX", pkt, addr, pkt_len); | 322 | write ? "TX" : "RX", pkt, addr, pkt_len); |
345 | } | 323 | } |
346 | 324 | ||
347 | /* Release host controller */ | ||
348 | sdio_release_host(sdiodev->func[func]); | ||
349 | |||
350 | return status; | 325 | return status; |
351 | } | 326 | } |
352 | 327 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 4766d9f35696..55e489d2147d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -682,10 +682,6 @@ extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, | |||
682 | 682 | ||
683 | extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); | 683 | extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); |
684 | 684 | ||
685 | /* Send packet to dongle via data channel */ | ||
686 | extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ | ||
687 | struct sk_buff *pkt); | ||
688 | |||
689 | extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); | 685 | extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); |
690 | extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, | 686 | extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, |
691 | int enable, int master_mode); | 687 | int enable, int master_mode); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 8121dbabbff6..aa4f719a51a9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -80,8 +80,10 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) | |||
80 | strncpy(buf, name, buflen); | 80 | strncpy(buf, name, buflen); |
81 | 81 | ||
82 | /* append data onto the end of the name string */ | 82 | /* append data onto the end of the name string */ |
83 | memcpy(&buf[len], data, datalen); | 83 | if (data && datalen) { |
84 | len += datalen; | 84 | memcpy(&buf[len], data, datalen); |
85 | len += datalen; | ||
86 | } | ||
85 | 87 | ||
86 | return len; | 88 | return len; |
87 | } | 89 | } |
@@ -431,13 +433,7 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) | |||
431 | } | 433 | } |
432 | 434 | ||
433 | /* show any appended data */ | 435 | /* show any appended data */ |
434 | if (datalen) { | 436 | brcmf_dbg_hex_dump(datalen, event_data, datalen, "Received data"); |
435 | buf = (unsigned char *) event_data; | ||
436 | brcmf_dbg(EVENT, " data (%d) : ", datalen); | ||
437 | for (i = 0; i < datalen; i++) | ||
438 | brcmf_dbg(EVENT, " 0x%02x ", *buf++); | ||
439 | brcmf_dbg(EVENT, "\n"); | ||
440 | } | ||
441 | } | 437 | } |
442 | #endif /* DEBUG */ | 438 | #endif /* DEBUG */ |
443 | 439 | ||
@@ -528,8 +524,9 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, | |||
528 | } | 524 | } |
529 | 525 | ||
530 | #ifdef DEBUG | 526 | #ifdef DEBUG |
531 | brcmf_c_show_host_event(event, event_data); | 527 | if (BRCMF_EVENT_ON()) |
532 | #endif /* DEBUG */ | 528 | brcmf_c_show_host_event(event, event_data); |
529 | #endif /* DEBUG */ | ||
533 | 530 | ||
534 | return 0; | 531 | return 0; |
535 | } | 532 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index b784920532d3..fb508c2256dd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -55,6 +55,7 @@ do { \ | |||
55 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) | 55 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) |
56 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) | 56 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) |
57 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) | 57 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) |
58 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) | ||
58 | 59 | ||
59 | #else /* (defined DEBUG) || (defined DEBUG) */ | 60 | #else /* (defined DEBUG) || (defined DEBUG) */ |
60 | 61 | ||
@@ -65,6 +66,7 @@ do { \ | |||
65 | #define BRCMF_HDRS_ON() 0 | 66 | #define BRCMF_HDRS_ON() 0 |
66 | #define BRCMF_BYTES_ON() 0 | 67 | #define BRCMF_BYTES_ON() 0 |
67 | #define BRCMF_GLOM_ON() 0 | 68 | #define BRCMF_GLOM_ON() 0 |
69 | #define BRCMF_EVENT_ON() 0 | ||
68 | 70 | ||
69 | #endif /* defined(DEBUG) */ | 71 | #endif /* defined(DEBUG) */ |
70 | 72 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index b08f3474d8e7..d7c76ce9d8cb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -272,30 +272,6 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) | |||
272 | schedule_work(&drvr->multicast_work); | 272 | schedule_work(&drvr->multicast_work); |
273 | } | 273 | } |
274 | 274 | ||
275 | int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) | ||
276 | { | ||
277 | /* Reject if down */ | ||
278 | if (!drvr->bus_if->drvr_up || (drvr->bus_if->state == BRCMF_BUS_DOWN)) | ||
279 | return -ENODEV; | ||
280 | |||
281 | /* Update multicast statistic */ | ||
282 | if (pktbuf->len >= ETH_ALEN) { | ||
283 | u8 *pktdata = (u8 *) (pktbuf->data); | ||
284 | struct ethhdr *eh = (struct ethhdr *)pktdata; | ||
285 | |||
286 | if (is_multicast_ether_addr(eh->h_dest)) | ||
287 | drvr->tx_multicast++; | ||
288 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
289 | atomic_inc(&drvr->pend_8021x_cnt); | ||
290 | } | ||
291 | |||
292 | /* If the protocol uses a data header, apply it */ | ||
293 | brcmf_proto_hdrpush(drvr, ifidx, pktbuf); | ||
294 | |||
295 | /* Use bus module to send data frame */ | ||
296 | return drvr->bus_if->brcmf_bus_txdata(drvr->dev, pktbuf); | ||
297 | } | ||
298 | |||
299 | static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 275 | static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
300 | { | 276 | { |
301 | int ret; | 277 | int ret; |
@@ -338,7 +314,22 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
338 | } | 314 | } |
339 | } | 315 | } |
340 | 316 | ||
341 | ret = brcmf_sendpkt(drvr, ifp->idx, skb); | 317 | /* Update multicast statistic */ |
318 | if (skb->len >= ETH_ALEN) { | ||
319 | u8 *pktdata = (u8 *)(skb->data); | ||
320 | struct ethhdr *eh = (struct ethhdr *)pktdata; | ||
321 | |||
322 | if (is_multicast_ether_addr(eh->h_dest)) | ||
323 | drvr->tx_multicast++; | ||
324 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
325 | atomic_inc(&drvr->pend_8021x_cnt); | ||
326 | } | ||
327 | |||
328 | /* If the protocol uses a data header, apply it */ | ||
329 | brcmf_proto_hdrpush(drvr, ifp->idx, skb); | ||
330 | |||
331 | /* Use bus module to send data frame */ | ||
332 | ret = drvr->bus_if->brcmf_bus_txdata(drvr->dev, skb); | ||
342 | 333 | ||
343 | done: | 334 | done: |
344 | if (ret) | 335 | if (ret) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 4580ff34c2d0..3564686add9a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -482,6 +482,15 @@ struct sdpcm_shared_le { | |||
482 | __le32 brpt_addr; | 482 | __le32 brpt_addr; |
483 | }; | 483 | }; |
484 | 484 | ||
485 | /* SDIO read frame info */ | ||
486 | struct brcmf_sdio_read { | ||
487 | u8 seq_num; | ||
488 | u8 channel; | ||
489 | u16 len; | ||
490 | u16 len_left; | ||
491 | u16 len_nxtfrm; | ||
492 | u8 dat_offset; | ||
493 | }; | ||
485 | 494 | ||
486 | /* misc chip info needed by some of the routines */ | 495 | /* misc chip info needed by some of the routines */ |
487 | /* Private data for SDIO bus interaction */ | 496 | /* Private data for SDIO bus interaction */ |
@@ -494,9 +503,8 @@ struct brcmf_sdio { | |||
494 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ | 503 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ |
495 | 504 | ||
496 | u32 hostintmask; /* Copy of Host Interrupt Mask */ | 505 | u32 hostintmask; /* Copy of Host Interrupt Mask */ |
497 | u32 intstatus; /* Intstatus bits (events) pending */ | 506 | atomic_t intstatus; /* Intstatus bits (events) pending */ |
498 | bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ | 507 | atomic_t fcstate; /* State of dongle flow-control */ |
499 | bool fcstate; /* State of dongle flow-control */ | ||
500 | 508 | ||
501 | uint blocksize; /* Block size of SDIO transfers */ | 509 | uint blocksize; /* Block size of SDIO transfers */ |
502 | uint roundup; /* Max roundup limit */ | 510 | uint roundup; /* Max roundup limit */ |
@@ -508,9 +516,11 @@ struct brcmf_sdio { | |||
508 | 516 | ||
509 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; | 517 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; |
510 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ | 518 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ |
511 | u16 nextlen; /* Next Read Len from last header */ | ||
512 | u8 rx_seq; /* Receive sequence number (expected) */ | 519 | u8 rx_seq; /* Receive sequence number (expected) */ |
520 | struct brcmf_sdio_read cur_read; | ||
521 | /* info of current read frame */ | ||
513 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ | 522 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ |
523 | bool rxpending; /* Data frame pending in dongle */ | ||
514 | 524 | ||
515 | uint rxbound; /* Rx frames to read before resched */ | 525 | uint rxbound; /* Rx frames to read before resched */ |
516 | uint txbound; /* Tx frames to send before resched */ | 526 | uint txbound; /* Tx frames to send before resched */ |
@@ -531,7 +541,7 @@ struct brcmf_sdio { | |||
531 | 541 | ||
532 | bool intr; /* Use interrupts */ | 542 | bool intr; /* Use interrupts */ |
533 | bool poll; /* Use polling */ | 543 | bool poll; /* Use polling */ |
534 | bool ipend; /* Device interrupt is pending */ | 544 | atomic_t ipend; /* Device interrupt is pending */ |
535 | uint spurious; /* Count of spurious interrupts */ | 545 | uint spurious; /* Count of spurious interrupts */ |
536 | uint pollrate; /* Ticks between device polls */ | 546 | uint pollrate; /* Ticks between device polls */ |
537 | uint polltick; /* Tick counter */ | 547 | uint polltick; /* Tick counter */ |
@@ -549,12 +559,9 @@ struct brcmf_sdio { | |||
549 | s32 idleclock; /* How to set bus driver when idle */ | 559 | s32 idleclock; /* How to set bus driver when idle */ |
550 | s32 sd_rxchain; | 560 | s32 sd_rxchain; |
551 | bool use_rxchain; /* If brcmf should use PKT chains */ | 561 | bool use_rxchain; /* If brcmf should use PKT chains */ |
552 | bool sleeping; /* Is SDIO bus sleeping? */ | ||
553 | bool rxflow_mode; /* Rx flow control mode */ | 562 | bool rxflow_mode; /* Rx flow control mode */ |
554 | bool rxflow; /* Is rx flow control on */ | 563 | bool rxflow; /* Is rx flow control on */ |
555 | bool alp_only; /* Don't use HT clock (ALP only) */ | 564 | bool alp_only; /* Don't use HT clock (ALP only) */ |
556 | /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ | ||
557 | bool usebufpool; | ||
558 | 565 | ||
559 | u8 *ctrl_frame_buf; | 566 | u8 *ctrl_frame_buf; |
560 | u32 ctrl_frame_len; | 567 | u32 ctrl_frame_len; |
@@ -570,8 +577,8 @@ struct brcmf_sdio { | |||
570 | bool wd_timer_valid; | 577 | bool wd_timer_valid; |
571 | uint save_ms; | 578 | uint save_ms; |
572 | 579 | ||
573 | struct task_struct *dpc_tsk; | 580 | struct workqueue_struct *brcmf_wq; |
574 | struct completion dpc_wait; | 581 | struct work_struct datawork; |
575 | struct list_head dpc_tsklst; | 582 | struct list_head dpc_tsklst; |
576 | spinlock_t dpc_tl_lock; | 583 | spinlock_t dpc_tl_lock; |
577 | 584 | ||
@@ -657,15 +664,6 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) | |||
657 | 664 | ||
658 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | 665 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) |
659 | 666 | ||
660 | /* Packet free applicable unconditionally for sdio and sdspi. | ||
661 | * Conditional if bufpool was present for gspi bus. | ||
662 | */ | ||
663 | static void brcmf_sdbrcm_pktfree2(struct brcmf_sdio *bus, struct sk_buff *pkt) | ||
664 | { | ||
665 | if (bus->usebufpool) | ||
666 | brcmu_pkt_buf_free_skb(pkt); | ||
667 | } | ||
668 | |||
669 | /* Turn backplane clock on or off */ | 667 | /* Turn backplane clock on or off */ |
670 | static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | 668 | static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) |
671 | { | 669 | { |
@@ -853,81 +851,6 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
853 | return 0; | 851 | return 0; |
854 | } | 852 | } |
855 | 853 | ||
856 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | ||
857 | { | ||
858 | int ret; | ||
859 | |||
860 | brcmf_dbg(INFO, "request %s (currently %s)\n", | ||
861 | sleep ? "SLEEP" : "WAKE", | ||
862 | bus->sleeping ? "SLEEP" : "WAKE"); | ||
863 | |||
864 | /* Done if we're already in the requested state */ | ||
865 | if (sleep == bus->sleeping) | ||
866 | return 0; | ||
867 | |||
868 | /* Going to sleep: set the alarm and turn off the lights... */ | ||
869 | if (sleep) { | ||
870 | /* Don't sleep if something is pending */ | ||
871 | if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) | ||
872 | return -EBUSY; | ||
873 | |||
874 | /* Make sure the controller has the bus up */ | ||
875 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
876 | |||
877 | /* Tell device to start using OOB wakeup */ | ||
878 | ret = w_sdreg32(bus, SMB_USE_OOB, | ||
879 | offsetof(struct sdpcmd_regs, tosbmailbox)); | ||
880 | if (ret != 0) | ||
881 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); | ||
882 | |||
883 | /* Turn off our contribution to the HT clock request */ | ||
884 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
885 | |||
886 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
887 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); | ||
888 | |||
889 | /* Isolate the bus */ | ||
890 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | ||
891 | SBSDIO_DEVCTL_PADS_ISO, NULL); | ||
892 | |||
893 | /* Change state */ | ||
894 | bus->sleeping = true; | ||
895 | |||
896 | } else { | ||
897 | /* Waking up: bus power up is ok, set local state */ | ||
898 | |||
899 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
900 | 0, NULL); | ||
901 | |||
902 | /* Make sure the controller has the bus up */ | ||
903 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
904 | |||
905 | /* Send misc interrupt to indicate OOB not needed */ | ||
906 | ret = w_sdreg32(bus, 0, | ||
907 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); | ||
908 | if (ret == 0) | ||
909 | ret = w_sdreg32(bus, SMB_DEV_INT, | ||
910 | offsetof(struct sdpcmd_regs, tosbmailbox)); | ||
911 | |||
912 | if (ret != 0) | ||
913 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); | ||
914 | |||
915 | /* Make sure we have SD bus access */ | ||
916 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
917 | |||
918 | /* Change state */ | ||
919 | bus->sleeping = false; | ||
920 | } | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static void bus_wake(struct brcmf_sdio *bus) | ||
926 | { | ||
927 | if (bus->sleeping) | ||
928 | brcmf_sdbrcm_bussleep(bus, false); | ||
929 | } | ||
930 | |||
931 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | 854 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) |
932 | { | 855 | { |
933 | u32 intstatus = 0; | 856 | u32 intstatus = 0; |
@@ -1056,7 +979,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1056 | } | 979 | } |
1057 | 980 | ||
1058 | /* Clear partial in any case */ | 981 | /* Clear partial in any case */ |
1059 | bus->nextlen = 0; | 982 | bus->cur_read.len = 0; |
1060 | 983 | ||
1061 | /* If we can't reach the device, signal failure */ | 984 | /* If we can't reach the device, signal failure */ |
1062 | if (err) | 985 | if (err) |
@@ -1108,6 +1031,96 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1108 | } | 1031 | } |
1109 | } | 1032 | } |
1110 | 1033 | ||
1034 | static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | ||
1035 | struct brcmf_sdio_read *rd) | ||
1036 | { | ||
1037 | u16 len, checksum; | ||
1038 | u8 rx_seq, fc, tx_seq_max; | ||
1039 | |||
1040 | /* | ||
1041 | * 4 bytes hardware header (frame tag) | ||
1042 | * Byte 0~1: Frame length | ||
1043 | * Byte 2~3: Checksum, bit-wise inverse of frame length | ||
1044 | */ | ||
1045 | len = get_unaligned_le16(header); | ||
1046 | checksum = get_unaligned_le16(header + sizeof(u16)); | ||
1047 | /* All zero means no more to read */ | ||
1048 | if (!(len | checksum)) { | ||
1049 | bus->rxpending = false; | ||
1050 | return false; | ||
1051 | } | ||
1052 | if ((u16)(~(len ^ checksum))) { | ||
1053 | brcmf_dbg(ERROR, "HW header checksum error\n"); | ||
1054 | bus->sdcnt.rx_badhdr++; | ||
1055 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1056 | return false; | ||
1057 | } | ||
1058 | if (len < SDPCM_HDRLEN) { | ||
1059 | brcmf_dbg(ERROR, "HW header length error\n"); | ||
1060 | return false; | ||
1061 | } | ||
1062 | rd->len = len; | ||
1063 | |||
1064 | /* | ||
1065 | * 8 bytes hardware header | ||
1066 | * Byte 0: Rx sequence number | ||
1067 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag | ||
1068 | * Byte 2: Length of next data frame | ||
1069 | * Byte 3: Data offset | ||
1070 | * Byte 4: Flow control bits | ||
1071 | * Byte 5: Maximum Sequence number allow for Tx | ||
1072 | * Byte 6~7: Reserved | ||
1073 | */ | ||
1074 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); | ||
1075 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); | ||
1076 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) { | ||
1077 | brcmf_dbg(ERROR, "HW header length too long\n"); | ||
1078 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1079 | bus->sdcnt.rx_toolong++; | ||
1080 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1081 | rd->len = 0; | ||
1082 | return false; | ||
1083 | } | ||
1084 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1085 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { | ||
1086 | brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq); | ||
1087 | bus->sdcnt.rx_badhdr++; | ||
1088 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1089 | rd->len = 0; | ||
1090 | return false; | ||
1091 | } | ||
1092 | if (rd->seq_num != rx_seq) { | ||
1093 | brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n", | ||
1094 | rx_seq, rd->seq_num); | ||
1095 | bus->sdcnt.rx_badseq++; | ||
1096 | rd->seq_num = rx_seq; | ||
1097 | } | ||
1098 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | ||
1099 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { | ||
1100 | /* only warm for NON glom packet */ | ||
1101 | if (rd->channel != SDPCM_GLOM_CHANNEL) | ||
1102 | brcmf_dbg(ERROR, "seq %d: next length error\n", rx_seq); | ||
1103 | rd->len_nxtfrm = 0; | ||
1104 | } | ||
1105 | fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1106 | if (bus->flowcontrol != fc) { | ||
1107 | if (~bus->flowcontrol & fc) | ||
1108 | bus->sdcnt.fc_xoff++; | ||
1109 | if (bus->flowcontrol & ~fc) | ||
1110 | bus->sdcnt.fc_xon++; | ||
1111 | bus->sdcnt.fc_rcvd++; | ||
1112 | bus->flowcontrol = fc; | ||
1113 | } | ||
1114 | tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1115 | if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) { | ||
1116 | brcmf_dbg(ERROR, "seq %d: max tx seq number error\n", rx_seq); | ||
1117 | tx_seq_max = bus->tx_seq + 2; | ||
1118 | } | ||
1119 | bus->tx_max = tx_seq_max; | ||
1120 | |||
1121 | return true; | ||
1122 | } | ||
1123 | |||
1111 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1124 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
1112 | { | 1125 | { |
1113 | u16 dlen, totlen; | 1126 | u16 dlen, totlen; |
@@ -1122,6 +1135,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1122 | 1135 | ||
1123 | int ifidx = 0; | 1136 | int ifidx = 0; |
1124 | bool usechain = bus->use_rxchain; | 1137 | bool usechain = bus->use_rxchain; |
1138 | u16 next_len; | ||
1125 | 1139 | ||
1126 | /* If packets, issue read(s) and send up packet chain */ | 1140 | /* If packets, issue read(s) and send up packet chain */ |
1127 | /* Return sequence numbers consumed? */ | 1141 | /* Return sequence numbers consumed? */ |
@@ -1185,10 +1199,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1185 | if (pnext) { | 1199 | if (pnext) { |
1186 | brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", | 1200 | brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", |
1187 | totlen, num); | 1201 | totlen, num); |
1188 | if (BRCMF_GLOM_ON() && bus->nextlen && | 1202 | if (BRCMF_GLOM_ON() && bus->cur_read.len && |
1189 | totlen != bus->nextlen) { | 1203 | totlen != bus->cur_read.len) { |
1190 | brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", | 1204 | brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", |
1191 | bus->nextlen, totlen, rxseq); | 1205 | bus->cur_read.len, totlen, rxseq); |
1192 | } | 1206 | } |
1193 | pfirst = pnext = NULL; | 1207 | pfirst = pnext = NULL; |
1194 | } else { | 1208 | } else { |
@@ -1199,7 +1213,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1199 | /* Done with descriptor packet */ | 1213 | /* Done with descriptor packet */ |
1200 | brcmu_pkt_buf_free_skb(bus->glomd); | 1214 | brcmu_pkt_buf_free_skb(bus->glomd); |
1201 | bus->glomd = NULL; | 1215 | bus->glomd = NULL; |
1202 | bus->nextlen = 0; | 1216 | bus->cur_read.len = 0; |
1203 | } | 1217 | } |
1204 | 1218 | ||
1205 | /* Ok -- either we just generated a packet chain, | 1219 | /* Ok -- either we just generated a packet chain, |
@@ -1272,12 +1286,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1272 | 1286 | ||
1273 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | 1287 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); |
1274 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | 1288 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); |
1275 | bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | 1289 | next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; |
1276 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | 1290 | if ((next_len << 4) > MAX_RX_DATASZ) { |
1277 | brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", | 1291 | brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", |
1278 | bus->nextlen, seq); | 1292 | next_len, seq); |
1279 | bus->nextlen = 0; | 1293 | next_len = 0; |
1280 | } | 1294 | } |
1295 | bus->cur_read.len = next_len << 4; | ||
1281 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1296 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
1282 | txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1297 | txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
1283 | 1298 | ||
@@ -1378,7 +1393,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1378 | bus->sdcnt.rxglomfail++; | 1393 | bus->sdcnt.rxglomfail++; |
1379 | brcmf_sdbrcm_free_glom(bus); | 1394 | brcmf_sdbrcm_free_glom(bus); |
1380 | } | 1395 | } |
1381 | bus->nextlen = 0; | 1396 | bus->cur_read.len = 0; |
1382 | return 0; | 1397 | return 0; |
1383 | } | 1398 | } |
1384 | 1399 | ||
@@ -1573,422 +1588,166 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | |||
1573 | } | 1588 | } |
1574 | } | 1589 | } |
1575 | 1590 | ||
1576 | static void | 1591 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) |
1577 | brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, | ||
1578 | struct sk_buff **pkt, u8 **rxbuf) | ||
1579 | { | 1592 | { |
1580 | int sdret; /* Return code from calls */ | ||
1581 | |||
1582 | *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); | ||
1583 | if (*pkt == NULL) | ||
1584 | return; | ||
1585 | |||
1586 | pkt_align(*pkt, rdlen, BRCMF_SDALIGN); | ||
1587 | *rxbuf = (u8 *) ((*pkt)->data); | ||
1588 | /* Read the entire frame */ | ||
1589 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | ||
1590 | SDIO_FUNC_2, F2SYNC, *pkt); | ||
1591 | bus->sdcnt.f2rxdata++; | ||
1592 | |||
1593 | if (sdret < 0) { | ||
1594 | brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", | ||
1595 | rdlen, sdret); | ||
1596 | brcmu_pkt_buf_free_skb(*pkt); | ||
1597 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1598 | /* Force retry w/normal header read. | ||
1599 | * Don't attempt NAK for | ||
1600 | * gSPI | ||
1601 | */ | ||
1602 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1603 | *pkt = NULL; | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | /* Checks the header */ | ||
1608 | static int | ||
1609 | brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, | ||
1610 | u8 rxseq, u16 nextlen, u16 *len) | ||
1611 | { | ||
1612 | u16 check; | ||
1613 | bool len_consistent; /* Result of comparing readahead len and | ||
1614 | len from hw-hdr */ | ||
1615 | |||
1616 | memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); | ||
1617 | |||
1618 | /* Extract hardware header fields */ | ||
1619 | *len = get_unaligned_le16(bus->rxhdr); | ||
1620 | check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); | ||
1621 | |||
1622 | /* All zeros means readahead info was bad */ | ||
1623 | if (!(*len | check)) { | ||
1624 | brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); | ||
1625 | goto fail; | ||
1626 | } | ||
1627 | |||
1628 | /* Validate check bytes */ | ||
1629 | if ((u16)~(*len ^ check)) { | ||
1630 | brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", | ||
1631 | nextlen, *len, check); | ||
1632 | bus->sdcnt.rx_badhdr++; | ||
1633 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1634 | goto fail; | ||
1635 | } | ||
1636 | |||
1637 | /* Validate frame length */ | ||
1638 | if (*len < SDPCM_HDRLEN) { | ||
1639 | brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", | ||
1640 | *len); | ||
1641 | goto fail; | ||
1642 | } | ||
1643 | |||
1644 | /* Check for consistency with readahead info */ | ||
1645 | len_consistent = (nextlen != (roundup(*len, 16) >> 4)); | ||
1646 | if (len_consistent) { | ||
1647 | /* Mismatch, force retry w/normal | ||
1648 | header (may be >4K) */ | ||
1649 | brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", | ||
1650 | nextlen, *len, roundup(*len, 16), | ||
1651 | rxseq); | ||
1652 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1653 | goto fail; | ||
1654 | } | ||
1655 | |||
1656 | return 0; | ||
1657 | |||
1658 | fail: | ||
1659 | brcmf_sdbrcm_pktfree2(bus, pkt); | ||
1660 | return -EINVAL; | ||
1661 | } | ||
1662 | |||
1663 | /* Return true if there may be more frames to read */ | ||
1664 | static uint | ||
1665 | brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | ||
1666 | { | ||
1667 | u16 len, check; /* Extracted hardware header fields */ | ||
1668 | u8 chan, seq, doff; /* Extracted software header fields */ | ||
1669 | u8 fcbits; /* Extracted fcbits from software header */ | ||
1670 | |||
1671 | struct sk_buff *pkt; /* Packet for event or data frames */ | 1593 | struct sk_buff *pkt; /* Packet for event or data frames */ |
1672 | u16 pad; /* Number of pad bytes to read */ | 1594 | u16 pad; /* Number of pad bytes to read */ |
1673 | u16 rdlen; /* Total number of bytes to read */ | ||
1674 | u8 rxseq; /* Next sequence number to expect */ | ||
1675 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1595 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1676 | int sdret; /* Return code from calls */ | 1596 | int sdret; /* Return code from calls */ |
1677 | u8 txmax; /* Maximum tx sequence offered */ | ||
1678 | u8 *rxbuf; | ||
1679 | int ifidx = 0; | 1597 | int ifidx = 0; |
1680 | uint rxcount = 0; /* Total frames read */ | 1598 | uint rxcount = 0; /* Total frames read */ |
1599 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | ||
1600 | u8 head_read = 0; | ||
1681 | 1601 | ||
1682 | brcmf_dbg(TRACE, "Enter\n"); | 1602 | brcmf_dbg(TRACE, "Enter\n"); |
1683 | 1603 | ||
1684 | /* Not finished unless we encounter no more frames indication */ | 1604 | /* Not finished unless we encounter no more frames indication */ |
1685 | *finished = false; | 1605 | bus->rxpending = true; |
1686 | 1606 | ||
1687 | for (rxseq = bus->rx_seq, rxleft = maxframes; | 1607 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
1688 | !bus->rxskip && rxleft && | 1608 | !bus->rxskip && rxleft && |
1689 | bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; | 1609 | bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; |
1690 | rxseq++, rxleft--) { | 1610 | rd->seq_num++, rxleft--) { |
1691 | 1611 | ||
1692 | /* Handle glomming separately */ | 1612 | /* Handle glomming separately */ |
1693 | if (bus->glomd || !skb_queue_empty(&bus->glom)) { | 1613 | if (bus->glomd || !skb_queue_empty(&bus->glom)) { |
1694 | u8 cnt; | 1614 | u8 cnt; |
1695 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", | 1615 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", |
1696 | bus->glomd, skb_peek(&bus->glom)); | 1616 | bus->glomd, skb_peek(&bus->glom)); |
1697 | cnt = brcmf_sdbrcm_rxglom(bus, rxseq); | 1617 | cnt = brcmf_sdbrcm_rxglom(bus, rd->seq_num); |
1698 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); | 1618 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); |
1699 | rxseq += cnt - 1; | 1619 | rd->seq_num += cnt - 1; |
1700 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; | 1620 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; |
1701 | continue; | 1621 | continue; |
1702 | } | 1622 | } |
1703 | 1623 | ||
1704 | /* Try doing single read if we can */ | 1624 | rd->len_left = rd->len; |
1705 | if (bus->nextlen) { | 1625 | /* read header first for unknow frame length */ |
1706 | u16 nextlen = bus->nextlen; | 1626 | if (!rd->len) { |
1707 | bus->nextlen = 0; | 1627 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, |
1708 | 1628 | bus->sdiodev->sbwad, | |
1709 | rdlen = len = nextlen << 4; | 1629 | SDIO_FUNC_2, F2SYNC, |
1710 | brcmf_pad(bus, &pad, &rdlen); | 1630 | bus->rxhdr, |
1711 | 1631 | BRCMF_FIRSTREAD); | |
1712 | /* | 1632 | bus->sdcnt.f2rxhdrs++; |
1713 | * After the frame is received we have to | 1633 | if (sdret < 0) { |
1714 | * distinguish whether it is data | 1634 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", |
1715 | * or non-data frame. | 1635 | sdret); |
1716 | */ | 1636 | bus->sdcnt.rx_hdrfail++; |
1717 | brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); | 1637 | brcmf_sdbrcm_rxfail(bus, true, true); |
1718 | if (pkt == NULL) { | ||
1719 | /* Give up on data, request rtx of events */ | ||
1720 | brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", | ||
1721 | len, rdlen, rxseq); | ||
1722 | continue; | ||
1723 | } | ||
1724 | |||
1725 | if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, | ||
1726 | &len) < 0) | ||
1727 | continue; | 1638 | continue; |
1728 | |||
1729 | /* Extract software header fields */ | ||
1730 | chan = SDPCM_PACKET_CHANNEL( | ||
1731 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1732 | seq = SDPCM_PACKET_SEQUENCE( | ||
1733 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1734 | doff = SDPCM_DOFFSET_VALUE( | ||
1735 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1736 | txmax = SDPCM_WINDOW_VALUE( | ||
1737 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1738 | |||
1739 | bus->nextlen = | ||
1740 | bus->rxhdr[SDPCM_FRAMETAG_LEN + | ||
1741 | SDPCM_NEXTLEN_OFFSET]; | ||
1742 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | ||
1743 | brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", | ||
1744 | bus->nextlen, seq); | ||
1745 | bus->nextlen = 0; | ||
1746 | } | 1639 | } |
1747 | 1640 | ||
1748 | bus->sdcnt.rx_readahead_cnt++; | 1641 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), |
1749 | |||
1750 | /* Handle Flow Control */ | ||
1751 | fcbits = SDPCM_FCMASK_VALUE( | ||
1752 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1753 | |||
1754 | if (bus->flowcontrol != fcbits) { | ||
1755 | if (~bus->flowcontrol & fcbits) | ||
1756 | bus->sdcnt.fc_xoff++; | ||
1757 | |||
1758 | if (bus->flowcontrol & ~fcbits) | ||
1759 | bus->sdcnt.fc_xon++; | ||
1760 | |||
1761 | bus->sdcnt.fc_rcvd++; | ||
1762 | bus->flowcontrol = fcbits; | ||
1763 | } | ||
1764 | |||
1765 | /* Check and update sequence number */ | ||
1766 | if (rxseq != seq) { | ||
1767 | brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", | ||
1768 | seq, rxseq); | ||
1769 | bus->sdcnt.rx_badseq++; | ||
1770 | rxseq = seq; | ||
1771 | } | ||
1772 | |||
1773 | /* Check window for sanity */ | ||
1774 | if ((u8) (txmax - bus->tx_seq) > 0x40) { | ||
1775 | brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", | ||
1776 | txmax, bus->tx_seq); | ||
1777 | txmax = bus->tx_seq + 2; | ||
1778 | } | ||
1779 | bus->tx_max = txmax; | ||
1780 | |||
1781 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | ||
1782 | rxbuf, len, "Rx Data:\n"); | ||
1783 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && | ||
1784 | BRCMF_DATA_ON()) && | ||
1785 | BRCMF_HDRS_ON(), | ||
1786 | bus->rxhdr, SDPCM_HDRLEN, | 1642 | bus->rxhdr, SDPCM_HDRLEN, |
1787 | "RxHdr:\n"); | 1643 | "RxHdr:\n"); |
1788 | 1644 | ||
1789 | if (chan == SDPCM_CONTROL_CHANNEL) { | 1645 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) { |
1790 | brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", | 1646 | if (!bus->rxpending) |
1791 | seq); | 1647 | break; |
1792 | /* Force retry w/normal header read */ | 1648 | else |
1793 | bus->nextlen = 0; | 1649 | continue; |
1794 | brcmf_sdbrcm_rxfail(bus, false, true); | ||
1795 | brcmf_sdbrcm_pktfree2(bus, pkt); | ||
1796 | continue; | ||
1797 | } | 1650 | } |
1798 | 1651 | ||
1799 | /* Validate data offset */ | 1652 | if (rd->channel == SDPCM_CONTROL_CHANNEL) { |
1800 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { | 1653 | brcmf_sdbrcm_read_control(bus, bus->rxhdr, |
1801 | brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", | 1654 | rd->len, |
1802 | doff, len, SDPCM_HDRLEN); | 1655 | rd->dat_offset); |
1803 | brcmf_sdbrcm_rxfail(bus, false, false); | 1656 | /* prepare the descriptor for the next read */ |
1804 | brcmf_sdbrcm_pktfree2(bus, pkt); | 1657 | rd->len = rd->len_nxtfrm << 4; |
1658 | rd->len_nxtfrm = 0; | ||
1659 | /* treat all packet as event if we don't know */ | ||
1660 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
1805 | continue; | 1661 | continue; |
1806 | } | 1662 | } |
1807 | 1663 | rd->len_left = rd->len > BRCMF_FIRSTREAD ? | |
1808 | /* All done with this one -- now deliver the packet */ | 1664 | rd->len - BRCMF_FIRSTREAD : 0; |
1809 | goto deliver; | 1665 | head_read = BRCMF_FIRSTREAD; |
1810 | } | ||
1811 | |||
1812 | /* Read frame header (hardware and software) */ | ||
1813 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, | ||
1814 | SDIO_FUNC_2, F2SYNC, bus->rxhdr, | ||
1815 | BRCMF_FIRSTREAD); | ||
1816 | bus->sdcnt.f2rxhdrs++; | ||
1817 | |||
1818 | if (sdret < 0) { | ||
1819 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); | ||
1820 | bus->sdcnt.rx_hdrfail++; | ||
1821 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1822 | continue; | ||
1823 | } | ||
1824 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), | ||
1825 | bus->rxhdr, SDPCM_HDRLEN, "RxHdr:\n"); | ||
1826 | |||
1827 | |||
1828 | /* Extract hardware header fields */ | ||
1829 | len = get_unaligned_le16(bus->rxhdr); | ||
1830 | check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); | ||
1831 | |||
1832 | /* All zeros means no more frames */ | ||
1833 | if (!(len | check)) { | ||
1834 | *finished = true; | ||
1835 | break; | ||
1836 | } | 1666 | } |
1837 | 1667 | ||
1838 | /* Validate check bytes */ | 1668 | brcmf_pad(bus, &pad, &rd->len_left); |
1839 | if ((u16) ~(len ^ check)) { | ||
1840 | brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", | ||
1841 | len, check); | ||
1842 | bus->sdcnt.rx_badhdr++; | ||
1843 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1844 | continue; | ||
1845 | } | ||
1846 | 1669 | ||
1847 | /* Validate frame length */ | 1670 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + |
1848 | if (len < SDPCM_HDRLEN) { | 1671 | BRCMF_SDALIGN); |
1849 | brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); | ||
1850 | continue; | ||
1851 | } | ||
1852 | |||
1853 | /* Extract software header fields */ | ||
1854 | chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1855 | seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1856 | doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1857 | txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1858 | |||
1859 | /* Validate data offset */ | ||
1860 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { | ||
1861 | brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", | ||
1862 | doff, len, SDPCM_HDRLEN, seq); | ||
1863 | bus->sdcnt.rx_badhdr++; | ||
1864 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1865 | continue; | ||
1866 | } | ||
1867 | |||
1868 | /* Save the readahead length if there is one */ | ||
1869 | bus->nextlen = | ||
1870 | bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | ||
1871 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | ||
1872 | brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", | ||
1873 | bus->nextlen, seq); | ||
1874 | bus->nextlen = 0; | ||
1875 | } | ||
1876 | |||
1877 | /* Handle Flow Control */ | ||
1878 | fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1879 | |||
1880 | if (bus->flowcontrol != fcbits) { | ||
1881 | if (~bus->flowcontrol & fcbits) | ||
1882 | bus->sdcnt.fc_xoff++; | ||
1883 | |||
1884 | if (bus->flowcontrol & ~fcbits) | ||
1885 | bus->sdcnt.fc_xon++; | ||
1886 | |||
1887 | bus->sdcnt.fc_rcvd++; | ||
1888 | bus->flowcontrol = fcbits; | ||
1889 | } | ||
1890 | |||
1891 | /* Check and update sequence number */ | ||
1892 | if (rxseq != seq) { | ||
1893 | brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); | ||
1894 | bus->sdcnt.rx_badseq++; | ||
1895 | rxseq = seq; | ||
1896 | } | ||
1897 | |||
1898 | /* Check window for sanity */ | ||
1899 | if ((u8) (txmax - bus->tx_seq) > 0x40) { | ||
1900 | brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", | ||
1901 | txmax, bus->tx_seq); | ||
1902 | txmax = bus->tx_seq + 2; | ||
1903 | } | ||
1904 | bus->tx_max = txmax; | ||
1905 | |||
1906 | /* Call a separate function for control frames */ | ||
1907 | if (chan == SDPCM_CONTROL_CHANNEL) { | ||
1908 | brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); | ||
1909 | continue; | ||
1910 | } | ||
1911 | |||
1912 | /* precondition: chan is either SDPCM_DATA_CHANNEL, | ||
1913 | SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or | ||
1914 | SDPCM_GLOM_CHANNEL */ | ||
1915 | |||
1916 | /* Length to read */ | ||
1917 | rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; | ||
1918 | |||
1919 | /* May pad read to blocksize for efficiency */ | ||
1920 | if (bus->roundup && bus->blocksize && | ||
1921 | (rdlen > bus->blocksize)) { | ||
1922 | pad = bus->blocksize - (rdlen % bus->blocksize); | ||
1923 | if ((pad <= bus->roundup) && (pad < bus->blocksize) && | ||
1924 | ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) | ||
1925 | rdlen += pad; | ||
1926 | } else if (rdlen % BRCMF_SDALIGN) { | ||
1927 | rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); | ||
1928 | } | ||
1929 | |||
1930 | /* Satisfy length-alignment requirements */ | ||
1931 | if (rdlen & (ALIGNMENT - 1)) | ||
1932 | rdlen = roundup(rdlen, ALIGNMENT); | ||
1933 | |||
1934 | if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { | ||
1935 | /* Too long -- skip this frame */ | ||
1936 | brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", | ||
1937 | len, rdlen); | ||
1938 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1939 | bus->sdcnt.rx_toolong++; | ||
1940 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1941 | continue; | ||
1942 | } | ||
1943 | |||
1944 | pkt = brcmu_pkt_buf_get_skb(rdlen + | ||
1945 | BRCMF_FIRSTREAD + BRCMF_SDALIGN); | ||
1946 | if (!pkt) { | 1672 | if (!pkt) { |
1947 | /* Give up on data, request rtx of events */ | 1673 | /* Give up on data, request rtx of events */ |
1948 | brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", | 1674 | brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed\n"); |
1949 | rdlen, chan); | ||
1950 | bus->sdiodev->bus_if->dstats.rx_dropped++; | 1675 | bus->sdiodev->bus_if->dstats.rx_dropped++; |
1951 | brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); | 1676 | brcmf_sdbrcm_rxfail(bus, false, |
1677 | RETRYCHAN(rd->channel)); | ||
1952 | continue; | 1678 | continue; |
1953 | } | 1679 | } |
1680 | skb_pull(pkt, head_read); | ||
1681 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | ||
1954 | 1682 | ||
1955 | /* Leave room for what we already read, and align remainder */ | ||
1956 | skb_pull(pkt, BRCMF_FIRSTREAD); | ||
1957 | pkt_align(pkt, rdlen, BRCMF_SDALIGN); | ||
1958 | |||
1959 | /* Read the remaining frame data */ | ||
1960 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1683 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1961 | SDIO_FUNC_2, F2SYNC, pkt); | 1684 | SDIO_FUNC_2, F2SYNC, pkt); |
1962 | bus->sdcnt.f2rxdata++; | 1685 | bus->sdcnt.f2rxdata++; |
1963 | 1686 | ||
1964 | if (sdret < 0) { | 1687 | if (sdret < 0) { |
1965 | brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, | 1688 | brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n", |
1966 | ((chan == SDPCM_EVENT_CHANNEL) ? "event" | 1689 | rd->len, rd->channel, sdret); |
1967 | : ((chan == SDPCM_DATA_CHANNEL) ? "data" | ||
1968 | : "test")), sdret); | ||
1969 | brcmu_pkt_buf_free_skb(pkt); | 1690 | brcmu_pkt_buf_free_skb(pkt); |
1970 | bus->sdiodev->bus_if->dstats.rx_errors++; | 1691 | bus->sdiodev->bus_if->dstats.rx_errors++; |
1971 | brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); | 1692 | brcmf_sdbrcm_rxfail(bus, true, |
1693 | RETRYCHAN(rd->channel)); | ||
1972 | continue; | 1694 | continue; |
1973 | } | 1695 | } |
1974 | 1696 | ||
1975 | /* Copy the already-read portion */ | 1697 | if (head_read) { |
1976 | skb_push(pkt, BRCMF_FIRSTREAD); | 1698 | skb_push(pkt, head_read); |
1977 | memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); | 1699 | memcpy(pkt->data, bus->rxhdr, head_read); |
1700 | head_read = 0; | ||
1701 | } else { | ||
1702 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); | ||
1703 | rd_new.seq_num = rd->seq_num; | ||
1704 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) { | ||
1705 | rd->len = 0; | ||
1706 | brcmu_pkt_buf_free_skb(pkt); | ||
1707 | } | ||
1708 | bus->sdcnt.rx_readahead_cnt++; | ||
1709 | if (rd->len != roundup(rd_new.len, 16)) { | ||
1710 | brcmf_dbg(ERROR, "frame length mismatch:read %d, should be %d\n", | ||
1711 | rd->len, | ||
1712 | roundup(rd_new.len, 16) >> 4); | ||
1713 | rd->len = 0; | ||
1714 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1715 | brcmu_pkt_buf_free_skb(pkt); | ||
1716 | continue; | ||
1717 | } | ||
1718 | rd->len_nxtfrm = rd_new.len_nxtfrm; | ||
1719 | rd->channel = rd_new.channel; | ||
1720 | rd->dat_offset = rd_new.dat_offset; | ||
1721 | |||
1722 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && | ||
1723 | BRCMF_DATA_ON()) && | ||
1724 | BRCMF_HDRS_ON(), | ||
1725 | bus->rxhdr, SDPCM_HDRLEN, | ||
1726 | "RxHdr:\n"); | ||
1727 | |||
1728 | if (rd_new.channel == SDPCM_CONTROL_CHANNEL) { | ||
1729 | brcmf_dbg(ERROR, "readahead on control packet %d?\n", | ||
1730 | rd_new.seq_num); | ||
1731 | /* Force retry w/normal header read */ | ||
1732 | rd->len = 0; | ||
1733 | brcmf_sdbrcm_rxfail(bus, false, true); | ||
1734 | brcmu_pkt_buf_free_skb(pkt); | ||
1735 | continue; | ||
1736 | } | ||
1737 | } | ||
1978 | 1738 | ||
1979 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | 1739 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), |
1980 | pkt->data, len, "Rx Data:\n"); | 1740 | pkt->data, rd->len, "Rx Data:\n"); |
1981 | 1741 | ||
1982 | deliver: | ||
1983 | /* Save superframe descriptor and allocate packet frame */ | 1742 | /* Save superframe descriptor and allocate packet frame */ |
1984 | if (chan == SDPCM_GLOM_CHANNEL) { | 1743 | if (rd->channel == SDPCM_GLOM_CHANNEL) { |
1985 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { | 1744 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { |
1986 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", | 1745 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", |
1987 | len); | 1746 | rd->len); |
1988 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1747 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
1989 | pkt->data, len, | 1748 | pkt->data, rd->len, |
1990 | "Glom Data:\n"); | 1749 | "Glom Data:\n"); |
1991 | __skb_trim(pkt, len); | 1750 | __skb_trim(pkt, rd->len); |
1992 | skb_pull(pkt, SDPCM_HDRLEN); | 1751 | skb_pull(pkt, SDPCM_HDRLEN); |
1993 | bus->glomd = pkt; | 1752 | bus->glomd = pkt; |
1994 | } else { | 1753 | } else { |
@@ -1996,12 +1755,23 @@ deliver: | |||
1996 | "descriptor!\n", __func__); | 1755 | "descriptor!\n", __func__); |
1997 | brcmf_sdbrcm_rxfail(bus, false, false); | 1756 | brcmf_sdbrcm_rxfail(bus, false, false); |
1998 | } | 1757 | } |
1758 | /* prepare the descriptor for the next read */ | ||
1759 | rd->len = rd->len_nxtfrm << 4; | ||
1760 | rd->len_nxtfrm = 0; | ||
1761 | /* treat all packet as event if we don't know */ | ||
1762 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
1999 | continue; | 1763 | continue; |
2000 | } | 1764 | } |
2001 | 1765 | ||
2002 | /* Fill in packet len and prio, deliver upward */ | 1766 | /* Fill in packet len and prio, deliver upward */ |
2003 | __skb_trim(pkt, len); | 1767 | __skb_trim(pkt, rd->len); |
2004 | skb_pull(pkt, doff); | 1768 | skb_pull(pkt, rd->dat_offset); |
1769 | |||
1770 | /* prepare the descriptor for the next read */ | ||
1771 | rd->len = rd->len_nxtfrm << 4; | ||
1772 | rd->len_nxtfrm = 0; | ||
1773 | /* treat all packet as event if we don't know */ | ||
1774 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
2005 | 1775 | ||
2006 | if (pkt->len == 0) { | 1776 | if (pkt->len == 0) { |
2007 | brcmu_pkt_buf_free_skb(pkt); | 1777 | brcmu_pkt_buf_free_skb(pkt); |
@@ -2019,17 +1789,17 @@ deliver: | |||
2019 | brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); | 1789 | brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); |
2020 | down(&bus->sdsem); | 1790 | down(&bus->sdsem); |
2021 | } | 1791 | } |
1792 | |||
2022 | rxcount = maxframes - rxleft; | 1793 | rxcount = maxframes - rxleft; |
2023 | /* Message if we hit the limit */ | 1794 | /* Message if we hit the limit */ |
2024 | if (!rxleft) | 1795 | if (!rxleft) |
2025 | brcmf_dbg(DATA, "hit rx limit of %d frames\n", | 1796 | brcmf_dbg(DATA, "hit rx limit of %d frames\n", maxframes); |
2026 | maxframes); | ||
2027 | else | 1797 | else |
2028 | brcmf_dbg(DATA, "processed %d frames\n", rxcount); | 1798 | brcmf_dbg(DATA, "processed %d frames\n", rxcount); |
2029 | /* Back off rxseq if awaiting rtx, update rx_seq */ | 1799 | /* Back off rxseq if awaiting rtx, update rx_seq */ |
2030 | if (bus->rxskip) | 1800 | if (bus->rxskip) |
2031 | rxseq--; | 1801 | rd->seq_num--; |
2032 | bus->rx_seq = rxseq; | 1802 | bus->rx_seq = rd->seq_num; |
2033 | 1803 | ||
2034 | return rxcount; | 1804 | return rxcount; |
2035 | } | 1805 | } |
@@ -2227,7 +1997,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2227 | if (ret != 0) | 1997 | if (ret != 0) |
2228 | break; | 1998 | break; |
2229 | if (intstatus & bus->hostintmask) | 1999 | if (intstatus & bus->hostintmask) |
2230 | bus->ipend = true; | 2000 | atomic_set(&bus->ipend, 1); |
2231 | } | 2001 | } |
2232 | } | 2002 | } |
2233 | 2003 | ||
@@ -2259,16 +2029,8 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2259 | bus->watchdog_tsk = NULL; | 2029 | bus->watchdog_tsk = NULL; |
2260 | } | 2030 | } |
2261 | 2031 | ||
2262 | if (bus->dpc_tsk && bus->dpc_tsk != current) { | ||
2263 | send_sig(SIGTERM, bus->dpc_tsk, 1); | ||
2264 | kthread_stop(bus->dpc_tsk); | ||
2265 | bus->dpc_tsk = NULL; | ||
2266 | } | ||
2267 | |||
2268 | down(&bus->sdsem); | 2032 | down(&bus->sdsem); |
2269 | 2033 | ||
2270 | bus_wake(bus); | ||
2271 | |||
2272 | /* Enable clock for device interrupts */ | 2034 | /* Enable clock for device interrupts */ |
2273 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2035 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
2274 | 2036 | ||
@@ -2327,7 +2089,7 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2327 | unsigned long flags; | 2089 | unsigned long flags; |
2328 | 2090 | ||
2329 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); | 2091 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); |
2330 | if (!bus->sdiodev->irq_en && !bus->ipend) { | 2092 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { |
2331 | enable_irq(bus->sdiodev->irq); | 2093 | enable_irq(bus->sdiodev->irq); |
2332 | bus->sdiodev->irq_en = true; | 2094 | bus->sdiodev->irq_en = true; |
2333 | } | 2095 | } |
@@ -2339,21 +2101,69 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2339 | } | 2101 | } |
2340 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | 2102 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ |
2341 | 2103 | ||
2342 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2104 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) |
2105 | { | ||
2106 | struct list_head *new_hd; | ||
2107 | unsigned long flags; | ||
2108 | |||
2109 | if (in_interrupt()) | ||
2110 | new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | ||
2111 | else | ||
2112 | new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); | ||
2113 | if (new_hd == NULL) | ||
2114 | return; | ||
2115 | |||
2116 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2117 | list_add_tail(new_hd, &bus->dpc_tsklst); | ||
2118 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2119 | } | ||
2120 | |||
2121 | static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | ||
2343 | { | 2122 | { |
2344 | u32 intstatus, newstatus = 0; | 2123 | u8 idx; |
2124 | u32 addr; | ||
2125 | unsigned long val; | ||
2126 | int n, ret; | ||
2127 | |||
2128 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
2129 | addr = bus->ci->c_inf[idx].base + | ||
2130 | offsetof(struct sdpcmd_regs, intstatus); | ||
2131 | |||
2132 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false); | ||
2133 | bus->sdcnt.f1regdata++; | ||
2134 | if (ret != 0) | ||
2135 | val = 0; | ||
2136 | |||
2137 | val &= bus->hostintmask; | ||
2138 | atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE)); | ||
2139 | |||
2140 | /* Clear interrupts */ | ||
2141 | if (val) { | ||
2142 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true); | ||
2143 | bus->sdcnt.f1regdata++; | ||
2144 | } | ||
2145 | |||
2146 | if (ret) { | ||
2147 | atomic_set(&bus->intstatus, 0); | ||
2148 | } else if (val) { | ||
2149 | for_each_set_bit(n, &val, 32) | ||
2150 | set_bit(n, (unsigned long *)&bus->intstatus.counter); | ||
2151 | } | ||
2152 | |||
2153 | return ret; | ||
2154 | } | ||
2155 | |||
2156 | static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | ||
2157 | { | ||
2158 | u32 newstatus = 0; | ||
2159 | unsigned long intstatus; | ||
2345 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ | 2160 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ |
2346 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ | 2161 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ |
2347 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ | 2162 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ |
2348 | bool rxdone = true; /* Flag for no more read data */ | 2163 | int err = 0, n; |
2349 | bool resched = false; /* Flag indicating resched wanted */ | ||
2350 | int err; | ||
2351 | 2164 | ||
2352 | brcmf_dbg(TRACE, "Enter\n"); | 2165 | brcmf_dbg(TRACE, "Enter\n"); |
2353 | 2166 | ||
2354 | /* Start with leftover status bits */ | ||
2355 | intstatus = bus->intstatus; | ||
2356 | |||
2357 | down(&bus->sdsem); | 2167 | down(&bus->sdsem); |
2358 | 2168 | ||
2359 | /* If waiting for HTAVAIL, check status */ | 2169 | /* If waiting for HTAVAIL, check status */ |
@@ -2399,39 +2209,22 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2399 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2209 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2400 | } | 2210 | } |
2401 | bus->clkstate = CLK_AVAIL; | 2211 | bus->clkstate = CLK_AVAIL; |
2402 | } else { | ||
2403 | goto clkwait; | ||
2404 | } | 2212 | } |
2405 | } | 2213 | } |
2406 | 2214 | ||
2407 | bus_wake(bus); | ||
2408 | |||
2409 | /* Make sure backplane clock is on */ | 2215 | /* Make sure backplane clock is on */ |
2410 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); | 2216 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); |
2411 | if (bus->clkstate == CLK_PENDING) | ||
2412 | goto clkwait; | ||
2413 | 2217 | ||
2414 | /* Pending interrupt indicates new device status */ | 2218 | /* Pending interrupt indicates new device status */ |
2415 | if (bus->ipend) { | 2219 | if (atomic_read(&bus->ipend) > 0) { |
2416 | bus->ipend = false; | 2220 | atomic_set(&bus->ipend, 0); |
2417 | err = r_sdreg32(bus, &newstatus, | 2221 | sdio_claim_host(bus->sdiodev->func[1]); |
2418 | offsetof(struct sdpcmd_regs, intstatus)); | 2222 | err = brcmf_sdio_intr_rstatus(bus); |
2419 | bus->sdcnt.f1regdata++; | 2223 | sdio_release_host(bus->sdiodev->func[1]); |
2420 | if (err != 0) | ||
2421 | newstatus = 0; | ||
2422 | newstatus &= bus->hostintmask; | ||
2423 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); | ||
2424 | if (newstatus) { | ||
2425 | err = w_sdreg32(bus, newstatus, | ||
2426 | offsetof(struct sdpcmd_regs, | ||
2427 | intstatus)); | ||
2428 | bus->sdcnt.f1regdata++; | ||
2429 | } | ||
2430 | } | 2224 | } |
2431 | 2225 | ||
2432 | /* Merge new bits with previous */ | 2226 | /* Start with leftover status bits */ |
2433 | intstatus |= newstatus; | 2227 | intstatus = atomic_xchg(&bus->intstatus, 0); |
2434 | bus->intstatus = 0; | ||
2435 | 2228 | ||
2436 | /* Handle flow-control change: read new state in case our ack | 2229 | /* Handle flow-control change: read new state in case our ack |
2437 | * crossed another change interrupt. If change still set, assume | 2230 | * crossed another change interrupt. If change still set, assume |
@@ -2445,8 +2238,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2445 | err = r_sdreg32(bus, &newstatus, | 2238 | err = r_sdreg32(bus, &newstatus, |
2446 | offsetof(struct sdpcmd_regs, intstatus)); | 2239 | offsetof(struct sdpcmd_regs, intstatus)); |
2447 | bus->sdcnt.f1regdata += 2; | 2240 | bus->sdcnt.f1regdata += 2; |
2448 | bus->fcstate = | 2241 | atomic_set(&bus->fcstate, |
2449 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); | 2242 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE))); |
2450 | intstatus |= (newstatus & bus->hostintmask); | 2243 | intstatus |= (newstatus & bus->hostintmask); |
2451 | } | 2244 | } |
2452 | 2245 | ||
@@ -2483,32 +2276,34 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2483 | intstatus &= ~I_HMB_FRAME_IND; | 2276 | intstatus &= ~I_HMB_FRAME_IND; |
2484 | 2277 | ||
2485 | /* On frame indication, read available frames */ | 2278 | /* On frame indication, read available frames */ |
2486 | if (PKT_AVAILABLE()) { | 2279 | if (PKT_AVAILABLE() && bus->clkstate == CLK_AVAIL) { |
2487 | framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); | 2280 | framecnt = brcmf_sdio_readframes(bus, rxlimit); |
2488 | if (rxdone || bus->rxskip) | 2281 | if (!bus->rxpending) |
2489 | intstatus &= ~I_HMB_FRAME_IND; | 2282 | intstatus &= ~I_HMB_FRAME_IND; |
2490 | rxlimit -= min(framecnt, rxlimit); | 2283 | rxlimit -= min(framecnt, rxlimit); |
2491 | } | 2284 | } |
2492 | 2285 | ||
2493 | /* Keep still-pending events for next scheduling */ | 2286 | /* Keep still-pending events for next scheduling */ |
2494 | bus->intstatus = intstatus; | 2287 | if (intstatus) { |
2288 | for_each_set_bit(n, &intstatus, 32) | ||
2289 | set_bit(n, (unsigned long *)&bus->intstatus.counter); | ||
2290 | } | ||
2495 | 2291 | ||
2496 | clkwait: | ||
2497 | brcmf_sdbrcm_clrintr(bus); | 2292 | brcmf_sdbrcm_clrintr(bus); |
2498 | 2293 | ||
2499 | if (data_ok(bus) && bus->ctrl_frame_stat && | 2294 | if (data_ok(bus) && bus->ctrl_frame_stat && |
2500 | (bus->clkstate == CLK_AVAIL)) { | 2295 | (bus->clkstate == CLK_AVAIL)) { |
2501 | int ret, i; | 2296 | int i; |
2502 | 2297 | ||
2503 | ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, | 2298 | err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, |
2504 | SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, | 2299 | SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, |
2505 | (u32) bus->ctrl_frame_len); | 2300 | (u32) bus->ctrl_frame_len); |
2506 | 2301 | ||
2507 | if (ret < 0) { | 2302 | if (err < 0) { |
2508 | /* On failure, abort the command and | 2303 | /* On failure, abort the command and |
2509 | terminate the frame */ | 2304 | terminate the frame */ |
2510 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", | 2305 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", |
2511 | ret); | 2306 | err); |
2512 | bus->sdcnt.tx_sderrs++; | 2307 | bus->sdcnt.tx_sderrs++; |
2513 | 2308 | ||
2514 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2309 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
@@ -2530,42 +2325,34 @@ clkwait: | |||
2530 | break; | 2325 | break; |
2531 | } | 2326 | } |
2532 | 2327 | ||
2533 | } | 2328 | } else { |
2534 | if (ret == 0) | ||
2535 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | 2329 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; |
2536 | 2330 | } | |
2537 | brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); | ||
2538 | bus->ctrl_frame_stat = false; | 2331 | bus->ctrl_frame_stat = false; |
2539 | brcmf_sdbrcm_wait_event_wakeup(bus); | 2332 | brcmf_sdbrcm_wait_event_wakeup(bus); |
2540 | } | 2333 | } |
2541 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2334 | /* Send queued frames (limit 1 if rx may still be pending) */ |
2542 | else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && | 2335 | else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
2543 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit | 2336 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit |
2544 | && data_ok(bus)) { | 2337 | && data_ok(bus)) { |
2545 | framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); | 2338 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : |
2339 | txlimit; | ||
2546 | framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); | 2340 | framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); |
2547 | txlimit -= framecnt; | 2341 | txlimit -= framecnt; |
2548 | } | 2342 | } |
2549 | 2343 | ||
2550 | /* Resched if events or tx frames are pending, | ||
2551 | else await next interrupt */ | ||
2552 | /* On failed register access, all bets are off: | ||
2553 | no resched or interrupts */ | ||
2554 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { | 2344 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { |
2555 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); | 2345 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); |
2556 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2346 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2557 | bus->intstatus = 0; | 2347 | atomic_set(&bus->intstatus, 0); |
2558 | } else if (bus->clkstate == CLK_PENDING) { | 2348 | } else if (atomic_read(&bus->intstatus) || |
2559 | brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); | 2349 | atomic_read(&bus->ipend) > 0 || |
2560 | resched = true; | 2350 | (!atomic_read(&bus->fcstate) && |
2561 | } else if (bus->intstatus || bus->ipend || | 2351 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
2562 | (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) | 2352 | data_ok(bus)) || PKT_AVAILABLE()) { |
2563 | && data_ok(bus)) || PKT_AVAILABLE()) { | 2353 | brcmf_sdbrcm_adddpctsk(bus); |
2564 | resched = true; | ||
2565 | } | 2354 | } |
2566 | 2355 | ||
2567 | bus->dpc_sched = resched; | ||
2568 | |||
2569 | /* If we're done for now, turn off clock request. */ | 2356 | /* If we're done for now, turn off clock request. */ |
2570 | if ((bus->clkstate != CLK_PENDING) | 2357 | if ((bus->clkstate != CLK_PENDING) |
2571 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { | 2358 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { |
@@ -2574,65 +2361,6 @@ clkwait: | |||
2574 | } | 2361 | } |
2575 | 2362 | ||
2576 | up(&bus->sdsem); | 2363 | up(&bus->sdsem); |
2577 | |||
2578 | return resched; | ||
2579 | } | ||
2580 | |||
2581 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) | ||
2582 | { | ||
2583 | struct list_head *new_hd; | ||
2584 | unsigned long flags; | ||
2585 | |||
2586 | if (in_interrupt()) | ||
2587 | new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | ||
2588 | else | ||
2589 | new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); | ||
2590 | if (new_hd == NULL) | ||
2591 | return; | ||
2592 | |||
2593 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2594 | list_add_tail(new_hd, &bus->dpc_tsklst); | ||
2595 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2596 | } | ||
2597 | |||
2598 | static int brcmf_sdbrcm_dpc_thread(void *data) | ||
2599 | { | ||
2600 | struct brcmf_sdio *bus = (struct brcmf_sdio *) data; | ||
2601 | struct list_head *cur_hd, *tmp_hd; | ||
2602 | unsigned long flags; | ||
2603 | |||
2604 | allow_signal(SIGTERM); | ||
2605 | /* Run until signal received */ | ||
2606 | while (1) { | ||
2607 | if (kthread_should_stop()) | ||
2608 | break; | ||
2609 | |||
2610 | if (list_empty(&bus->dpc_tsklst)) | ||
2611 | if (wait_for_completion_interruptible(&bus->dpc_wait)) | ||
2612 | break; | ||
2613 | |||
2614 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2615 | list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { | ||
2616 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2617 | |||
2618 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { | ||
2619 | /* after stopping the bus, exit thread */ | ||
2620 | brcmf_sdbrcm_bus_stop(bus->sdiodev->dev); | ||
2621 | bus->dpc_tsk = NULL; | ||
2622 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2623 | break; | ||
2624 | } | ||
2625 | |||
2626 | if (brcmf_sdbrcm_dpc(bus)) | ||
2627 | brcmf_sdbrcm_adddpctsk(bus); | ||
2628 | |||
2629 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2630 | list_del(cur_hd); | ||
2631 | kfree(cur_hd); | ||
2632 | } | ||
2633 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2634 | } | ||
2635 | return 0; | ||
2636 | } | 2364 | } |
2637 | 2365 | ||
2638 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2366 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) |
@@ -2642,6 +2370,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2642 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2370 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2643 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2371 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2644 | struct brcmf_sdio *bus = sdiodev->bus; | 2372 | struct brcmf_sdio *bus = sdiodev->bus; |
2373 | unsigned long flags; | ||
2645 | 2374 | ||
2646 | brcmf_dbg(TRACE, "Enter\n"); | 2375 | brcmf_dbg(TRACE, "Enter\n"); |
2647 | 2376 | ||
@@ -2680,13 +2409,15 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2680 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) | 2409 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) |
2681 | qcount[prec] = pktq_plen(&bus->txq, prec); | 2410 | qcount[prec] = pktq_plen(&bus->txq, prec); |
2682 | #endif | 2411 | #endif |
2683 | /* Schedule DPC if needed to send queued packet(s) */ | 2412 | |
2684 | if (!bus->dpc_sched) { | 2413 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
2685 | bus->dpc_sched = true; | 2414 | if (list_empty(&bus->dpc_tsklst)) { |
2686 | if (bus->dpc_tsk) { | 2415 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); |
2687 | brcmf_sdbrcm_adddpctsk(bus); | 2416 | |
2688 | complete(&bus->dpc_wait); | 2417 | brcmf_sdbrcm_adddpctsk(bus); |
2689 | } | 2418 | queue_work(bus->brcmf_wq, &bus->datawork); |
2419 | } else { | ||
2420 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2690 | } | 2421 | } |
2691 | 2422 | ||
2692 | return ret; | 2423 | return ret; |
@@ -2707,6 +2438,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, | |||
2707 | else | 2438 | else |
2708 | dsize = size; | 2439 | dsize = size; |
2709 | 2440 | ||
2441 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2442 | |||
2710 | /* Set the backplane window to include the start address */ | 2443 | /* Set the backplane window to include the start address */ |
2711 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); | 2444 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); |
2712 | if (bcmerror) { | 2445 | if (bcmerror) { |
@@ -2748,6 +2481,8 @@ xfer_done: | |||
2748 | brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", | 2481 | brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", |
2749 | bus->sdiodev->sbwad); | 2482 | bus->sdiodev->sbwad); |
2750 | 2483 | ||
2484 | sdio_release_host(bus->sdiodev->func[1]); | ||
2485 | |||
2751 | return bcmerror; | 2486 | return bcmerror; |
2752 | } | 2487 | } |
2753 | 2488 | ||
@@ -2882,6 +2617,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2882 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2617 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2883 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2618 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2884 | struct brcmf_sdio *bus = sdiodev->bus; | 2619 | struct brcmf_sdio *bus = sdiodev->bus; |
2620 | unsigned long flags; | ||
2885 | 2621 | ||
2886 | brcmf_dbg(TRACE, "Enter\n"); | 2622 | brcmf_dbg(TRACE, "Enter\n"); |
2887 | 2623 | ||
@@ -2918,8 +2654,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2918 | /* Need to lock here to protect txseq and SDIO tx calls */ | 2654 | /* Need to lock here to protect txseq and SDIO tx calls */ |
2919 | down(&bus->sdsem); | 2655 | down(&bus->sdsem); |
2920 | 2656 | ||
2921 | bus_wake(bus); | ||
2922 | |||
2923 | /* Make sure backplane clock is on */ | 2657 | /* Make sure backplane clock is on */ |
2924 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2658 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
2925 | 2659 | ||
@@ -2967,9 +2701,15 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2967 | } while (ret < 0 && retries++ < TXRETRIES); | 2701 | } while (ret < 0 && retries++ < TXRETRIES); |
2968 | } | 2702 | } |
2969 | 2703 | ||
2970 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { | 2704 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
2705 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && | ||
2706 | list_empty(&bus->dpc_tsklst)) { | ||
2707 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2708 | |||
2971 | bus->activity = false; | 2709 | bus->activity = false; |
2972 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2710 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); |
2711 | } else { | ||
2712 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2973 | } | 2713 | } |
2974 | 2714 | ||
2975 | up(&bus->sdsem); | 2715 | up(&bus->sdsem); |
@@ -3774,23 +3514,20 @@ void brcmf_sdbrcm_isr(void *arg) | |||
3774 | } | 3514 | } |
3775 | /* Count the interrupt call */ | 3515 | /* Count the interrupt call */ |
3776 | bus->sdcnt.intrcount++; | 3516 | bus->sdcnt.intrcount++; |
3777 | bus->ipend = true; | 3517 | if (in_interrupt()) |
3778 | 3518 | atomic_set(&bus->ipend, 1); | |
3779 | /* Shouldn't get this interrupt if we're sleeping? */ | 3519 | else |
3780 | if (bus->sleeping) { | 3520 | if (brcmf_sdio_intr_rstatus(bus)) { |
3781 | brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); | 3521 | brcmf_dbg(ERROR, "failed backplane access\n"); |
3782 | return; | 3522 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
3783 | } | 3523 | } |
3784 | 3524 | ||
3785 | /* Disable additional interrupts (is this needed now)? */ | 3525 | /* Disable additional interrupts (is this needed now)? */ |
3786 | if (!bus->intr) | 3526 | if (!bus->intr) |
3787 | brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); | 3527 | brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); |
3788 | 3528 | ||
3789 | bus->dpc_sched = true; | 3529 | brcmf_sdbrcm_adddpctsk(bus); |
3790 | if (bus->dpc_tsk) { | 3530 | queue_work(bus->brcmf_wq, &bus->datawork); |
3791 | brcmf_sdbrcm_adddpctsk(bus); | ||
3792 | complete(&bus->dpc_wait); | ||
3793 | } | ||
3794 | } | 3531 | } |
3795 | 3532 | ||
3796 | static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | 3533 | static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) |
@@ -3798,13 +3535,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3798 | #ifdef DEBUG | 3535 | #ifdef DEBUG |
3799 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | 3536 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); |
3800 | #endif /* DEBUG */ | 3537 | #endif /* DEBUG */ |
3538 | unsigned long flags; | ||
3801 | 3539 | ||
3802 | brcmf_dbg(TIMER, "Enter\n"); | 3540 | brcmf_dbg(TIMER, "Enter\n"); |
3803 | 3541 | ||
3804 | /* Ignore the timer if simulating bus down */ | ||
3805 | if (bus->sleeping) | ||
3806 | return false; | ||
3807 | |||
3808 | down(&bus->sdsem); | 3542 | down(&bus->sdsem); |
3809 | 3543 | ||
3810 | /* Poll period: check device if appropriate. */ | 3544 | /* Poll period: check device if appropriate. */ |
@@ -3818,27 +3552,30 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3818 | if (!bus->intr || | 3552 | if (!bus->intr || |
3819 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { | 3553 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { |
3820 | 3554 | ||
3821 | if (!bus->dpc_sched) { | 3555 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
3556 | if (list_empty(&bus->dpc_tsklst)) { | ||
3822 | u8 devpend; | 3557 | u8 devpend; |
3558 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | ||
3559 | flags); | ||
3823 | devpend = brcmf_sdio_regrb(bus->sdiodev, | 3560 | devpend = brcmf_sdio_regrb(bus->sdiodev, |
3824 | SDIO_CCCR_INTx, | 3561 | SDIO_CCCR_INTx, |
3825 | NULL); | 3562 | NULL); |
3826 | intstatus = | 3563 | intstatus = |
3827 | devpend & (INTR_STATUS_FUNC1 | | 3564 | devpend & (INTR_STATUS_FUNC1 | |
3828 | INTR_STATUS_FUNC2); | 3565 | INTR_STATUS_FUNC2); |
3566 | } else { | ||
3567 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | ||
3568 | flags); | ||
3829 | } | 3569 | } |
3830 | 3570 | ||
3831 | /* If there is something, make like the ISR and | 3571 | /* If there is something, make like the ISR and |
3832 | schedule the DPC */ | 3572 | schedule the DPC */ |
3833 | if (intstatus) { | 3573 | if (intstatus) { |
3834 | bus->sdcnt.pollcnt++; | 3574 | bus->sdcnt.pollcnt++; |
3835 | bus->ipend = true; | 3575 | atomic_set(&bus->ipend, 1); |
3836 | 3576 | ||
3837 | bus->dpc_sched = true; | 3577 | brcmf_sdbrcm_adddpctsk(bus); |
3838 | if (bus->dpc_tsk) { | 3578 | queue_work(bus->brcmf_wq, &bus->datawork); |
3839 | brcmf_sdbrcm_adddpctsk(bus); | ||
3840 | complete(&bus->dpc_wait); | ||
3841 | } | ||
3842 | } | 3579 | } |
3843 | } | 3580 | } |
3844 | 3581 | ||
@@ -3876,7 +3613,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3876 | 3613 | ||
3877 | up(&bus->sdsem); | 3614 | up(&bus->sdsem); |
3878 | 3615 | ||
3879 | return bus->ipend; | 3616 | return (atomic_read(&bus->ipend) > 0); |
3880 | } | 3617 | } |
3881 | 3618 | ||
3882 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) | 3619 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) |
@@ -3892,6 +3629,26 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) | |||
3892 | return false; | 3629 | return false; |
3893 | } | 3630 | } |
3894 | 3631 | ||
3632 | static void brcmf_sdio_dataworker(struct work_struct *work) | ||
3633 | { | ||
3634 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, | ||
3635 | datawork); | ||
3636 | struct list_head *cur_hd, *tmp_hd; | ||
3637 | unsigned long flags; | ||
3638 | |||
3639 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3640 | list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { | ||
3641 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3642 | |||
3643 | brcmf_sdbrcm_dpc(bus); | ||
3644 | |||
3645 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3646 | list_del(cur_hd); | ||
3647 | kfree(cur_hd); | ||
3648 | } | ||
3649 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3650 | } | ||
3651 | |||
3895 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) | 3652 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) |
3896 | { | 3653 | { |
3897 | brcmf_dbg(TRACE, "Enter\n"); | 3654 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -4024,7 +3781,6 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
4024 | SDIO_FUNC_ENABLE_1, NULL); | 3781 | SDIO_FUNC_ENABLE_1, NULL); |
4025 | 3782 | ||
4026 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 3783 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
4027 | bus->sleeping = false; | ||
4028 | bus->rxflow = false; | 3784 | bus->rxflow = false; |
4029 | 3785 | ||
4030 | /* Done with backplane-dependent accesses, can drop clock... */ | 3786 | /* Done with backplane-dependent accesses, can drop clock... */ |
@@ -4105,6 +3861,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | |||
4105 | /* De-register interrupt handler */ | 3861 | /* De-register interrupt handler */ |
4106 | brcmf_sdio_intr_unregister(bus->sdiodev); | 3862 | brcmf_sdio_intr_unregister(bus->sdiodev); |
4107 | 3863 | ||
3864 | cancel_work_sync(&bus->datawork); | ||
3865 | destroy_workqueue(bus->brcmf_wq); | ||
3866 | |||
4108 | if (bus->sdiodev->bus_if->drvr) { | 3867 | if (bus->sdiodev->bus_if->drvr) { |
4109 | brcmf_detach(bus->sdiodev->dev); | 3868 | brcmf_detach(bus->sdiodev->dev); |
4110 | brcmf_sdbrcm_release_dongle(bus); | 3869 | brcmf_sdbrcm_release_dongle(bus); |
@@ -4144,8 +3903,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4144 | bus->rxbound = BRCMF_RXBOUND; | 3903 | bus->rxbound = BRCMF_RXBOUND; |
4145 | bus->txminmax = BRCMF_TXMINMAX; | 3904 | bus->txminmax = BRCMF_TXMINMAX; |
4146 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; | 3905 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; |
4147 | bus->usebufpool = false; /* Use bufpool if allocated, | ||
4148 | else use locally malloced rxbuf */ | ||
4149 | 3906 | ||
4150 | /* attempt to attach to the dongle */ | 3907 | /* attempt to attach to the dongle */ |
4151 | if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { | 3908 | if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { |
@@ -4157,6 +3914,13 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4157 | init_waitqueue_head(&bus->ctrl_wait); | 3914 | init_waitqueue_head(&bus->ctrl_wait); |
4158 | init_waitqueue_head(&bus->dcmd_resp_wait); | 3915 | init_waitqueue_head(&bus->dcmd_resp_wait); |
4159 | 3916 | ||
3917 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); | ||
3918 | if (bus->brcmf_wq == NULL) { | ||
3919 | brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n"); | ||
3920 | goto fail; | ||
3921 | } | ||
3922 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | ||
3923 | |||
4160 | /* Set up the watchdog timer */ | 3924 | /* Set up the watchdog timer */ |
4161 | init_timer(&bus->timer); | 3925 | init_timer(&bus->timer); |
4162 | bus->timer.data = (unsigned long)bus; | 3926 | bus->timer.data = (unsigned long)bus; |
@@ -4174,15 +3938,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4174 | bus->watchdog_tsk = NULL; | 3938 | bus->watchdog_tsk = NULL; |
4175 | } | 3939 | } |
4176 | /* Initialize DPC thread */ | 3940 | /* Initialize DPC thread */ |
4177 | init_completion(&bus->dpc_wait); | ||
4178 | INIT_LIST_HEAD(&bus->dpc_tsklst); | 3941 | INIT_LIST_HEAD(&bus->dpc_tsklst); |
4179 | spin_lock_init(&bus->dpc_tl_lock); | 3942 | spin_lock_init(&bus->dpc_tl_lock); |
4180 | bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, | ||
4181 | bus, "brcmf_dpc"); | ||
4182 | if (IS_ERR(bus->dpc_tsk)) { | ||
4183 | pr_warn("brcmf_dpc thread failed to start\n"); | ||
4184 | bus->dpc_tsk = NULL; | ||
4185 | } | ||
4186 | 3943 | ||
4187 | /* Assign bus interface call back */ | 3944 | /* Assign bus interface call back */ |
4188 | bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop; | 3945 | bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 29bf78d264e0..0d30afd8c672 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -174,6 +174,8 @@ extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
174 | u8 data, int *ret); | 174 | u8 data, int *ret); |
175 | extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | 175 | extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
176 | u32 data, int *ret); | 176 | u32 data, int *ret); |
177 | extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | ||
178 | void *data, bool write); | ||
177 | 179 | ||
178 | /* Buffer transfer to/from device (client) core via cmd53. | 180 | /* Buffer transfer to/from device (client) core via cmd53. |
179 | * fn: function number | 181 | * fn: function number |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index c6d5aeb27a02..5fe6ec7f838e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -81,10 +81,12 @@ enum usbdev_suspend_state { | |||
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct brcmf_usb_image { | 83 | struct brcmf_usb_image { |
84 | void *data; | 84 | struct list_head list; |
85 | u32 len; | 85 | s8 *fwname; |
86 | u8 *image; | ||
87 | int image_len; | ||
86 | }; | 88 | }; |
87 | static struct brcmf_usb_image g_image = { NULL, 0 }; | 89 | static struct list_head fw_image_list; |
88 | 90 | ||
89 | struct intr_transfer_buf { | 91 | struct intr_transfer_buf { |
90 | u32 notification; | 92 | u32 notification; |
@@ -132,8 +134,6 @@ struct brcmf_usbdev_info { | |||
132 | wait_queue_head_t ctrl_wait; | 134 | wait_queue_head_t ctrl_wait; |
133 | ulong ctl_op; | 135 | ulong ctl_op; |
134 | 136 | ||
135 | bool rxctl_deferrespok; | ||
136 | |||
137 | struct urb *bulk_urb; /* used for FW download */ | 137 | struct urb *bulk_urb; /* used for FW download */ |
138 | struct urb *intr_urb; /* URB for interrupt endpoint */ | 138 | struct urb *intr_urb; /* URB for interrupt endpoint */ |
139 | int intr_size; /* Size of interrupt message */ | 139 | int intr_size; /* Size of interrupt message */ |
@@ -299,17 +299,9 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) | |||
299 | devinfo->ctl_read.wLength = cpu_to_le16p(&size); | 299 | devinfo->ctl_read.wLength = cpu_to_le16p(&size); |
300 | devinfo->ctl_urb->transfer_buffer_length = size; | 300 | devinfo->ctl_urb->transfer_buffer_length = size; |
301 | 301 | ||
302 | if (devinfo->rxctl_deferrespok) { | 302 | devinfo->ctl_read.bRequestType = USB_DIR_IN |
303 | /* BMAC model */ | 303 | | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
304 | devinfo->ctl_read.bRequestType = USB_DIR_IN | 304 | devinfo->ctl_read.bRequest = 1; |
305 | | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; | ||
306 | devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK; | ||
307 | } else { | ||
308 | /* full dongle model */ | ||
309 | devinfo->ctl_read.bRequestType = USB_DIR_IN | ||
310 | | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
311 | devinfo->ctl_read.bRequest = 1; | ||
312 | } | ||
313 | 305 | ||
314 | usb_fill_control_urb(devinfo->ctl_urb, | 306 | usb_fill_control_urb(devinfo->ctl_urb, |
315 | devinfo->usbdev, | 307 | devinfo->usbdev, |
@@ -345,6 +337,7 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) | |||
345 | err = brcmf_usb_send_ctl(devinfo, buf, len); | 337 | err = brcmf_usb_send_ctl(devinfo, buf, len); |
346 | if (err) { | 338 | if (err) { |
347 | brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); | 339 | brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); |
340 | clear_bit(0, &devinfo->ctl_op); | ||
348 | return err; | 341 | return err; |
349 | } | 342 | } |
350 | 343 | ||
@@ -375,6 +368,7 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) | |||
375 | err = brcmf_usb_recv_ctl(devinfo, buf, len); | 368 | err = brcmf_usb_recv_ctl(devinfo, buf, len); |
376 | if (err) { | 369 | if (err) { |
377 | brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); | 370 | brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); |
371 | clear_bit(0, &devinfo->ctl_op); | ||
378 | return err; | 372 | return err; |
379 | } | 373 | } |
380 | devinfo->ctl_completed = false; | 374 | devinfo->ctl_completed = false; |
@@ -1152,10 +1146,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) | |||
1152 | { | 1146 | { |
1153 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); | 1147 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); |
1154 | 1148 | ||
1155 | /* store the image globally */ | ||
1156 | g_image.data = devinfo->image; | ||
1157 | g_image.len = devinfo->image_len; | ||
1158 | |||
1159 | /* free the URBS */ | 1149 | /* free the URBS */ |
1160 | brcmf_usb_free_q(&devinfo->rx_freeq, false); | 1150 | brcmf_usb_free_q(&devinfo->rx_freeq, false); |
1161 | brcmf_usb_free_q(&devinfo->tx_freeq, false); | 1151 | brcmf_usb_free_q(&devinfo->tx_freeq, false); |
@@ -1207,17 +1197,9 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1207 | { | 1197 | { |
1208 | s8 *fwname; | 1198 | s8 *fwname; |
1209 | const struct firmware *fw; | 1199 | const struct firmware *fw; |
1200 | struct brcmf_usb_image *fw_image; | ||
1210 | int err; | 1201 | int err; |
1211 | 1202 | ||
1212 | devinfo->image = g_image.data; | ||
1213 | devinfo->image_len = g_image.len; | ||
1214 | |||
1215 | /* | ||
1216 | * if we have an image we can leave here. | ||
1217 | */ | ||
1218 | if (devinfo->image) | ||
1219 | return 0; | ||
1220 | |||
1221 | switch (devinfo->bus_pub.devid) { | 1203 | switch (devinfo->bus_pub.devid) { |
1222 | case 43143: | 1204 | case 43143: |
1223 | fwname = BRCMF_USB_43143_FW_NAME; | 1205 | fwname = BRCMF_USB_43143_FW_NAME; |
@@ -1235,6 +1217,14 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1235 | break; | 1217 | break; |
1236 | } | 1218 | } |
1237 | 1219 | ||
1220 | list_for_each_entry(fw_image, &fw_image_list, list) { | ||
1221 | if (fw_image->fwname == fwname) { | ||
1222 | devinfo->image = fw_image->image; | ||
1223 | devinfo->image_len = fw_image->image_len; | ||
1224 | return 0; | ||
1225 | } | ||
1226 | } | ||
1227 | /* fw image not yet loaded. Load it now and add to list */ | ||
1238 | err = request_firmware(&fw, fwname, devinfo->dev); | 1228 | err = request_firmware(&fw, fwname, devinfo->dev); |
1239 | if (!fw) { | 1229 | if (!fw) { |
1240 | brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); | 1230 | brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); |
@@ -1245,14 +1235,24 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1245 | return -EINVAL; | 1235 | return -EINVAL; |
1246 | } | 1236 | } |
1247 | 1237 | ||
1248 | devinfo->image = vmalloc(fw->size); /* plus nvram */ | 1238 | fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC); |
1249 | if (!devinfo->image) | 1239 | if (!fw_image) |
1240 | return -ENOMEM; | ||
1241 | INIT_LIST_HEAD(&fw_image->list); | ||
1242 | list_add_tail(&fw_image->list, &fw_image_list); | ||
1243 | fw_image->fwname = fwname; | ||
1244 | fw_image->image = vmalloc(fw->size); | ||
1245 | if (!fw_image->image) | ||
1250 | return -ENOMEM; | 1246 | return -ENOMEM; |
1251 | 1247 | ||
1252 | memcpy(devinfo->image, fw->data, fw->size); | 1248 | memcpy(fw_image->image, fw->data, fw->size); |
1253 | devinfo->image_len = fw->size; | 1249 | fw_image->image_len = fw->size; |
1254 | 1250 | ||
1255 | release_firmware(fw); | 1251 | release_firmware(fw); |
1252 | |||
1253 | devinfo->image = fw_image->image; | ||
1254 | devinfo->image_len = fw_image->image_len; | ||
1255 | |||
1256 | return 0; | 1256 | return 0; |
1257 | } | 1257 | } |
1258 | 1258 | ||
@@ -1304,8 +1304,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, | |||
1304 | brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n"); | 1304 | brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n"); |
1305 | goto error; | 1305 | goto error; |
1306 | } | 1306 | } |
1307 | devinfo->rxctl_deferrespok = 0; | ||
1308 | |||
1309 | devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC); | 1307 | devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC); |
1310 | if (!devinfo->bulk_urb) { | 1308 | if (!devinfo->bulk_urb) { |
1311 | brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n"); | 1309 | brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n"); |
@@ -1340,10 +1338,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, | |||
1340 | struct device *dev = devinfo->dev; | 1338 | struct device *dev = devinfo->dev; |
1341 | 1339 | ||
1342 | bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); | 1340 | bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); |
1343 | if (!bus_pub) { | 1341 | if (!bus_pub) |
1344 | ret = -ENODEV; | 1342 | return -ENODEV; |
1345 | goto fail; | ||
1346 | } | ||
1347 | 1343 | ||
1348 | bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); | 1344 | bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); |
1349 | if (!bus) { | 1345 | if (!bus) { |
@@ -1596,15 +1592,25 @@ static struct usb_driver brcmf_usbdrvr = { | |||
1596 | .disable_hub_initiated_lpm = 1, | 1592 | .disable_hub_initiated_lpm = 1, |
1597 | }; | 1593 | }; |
1598 | 1594 | ||
1595 | static void brcmf_release_fw(struct list_head *q) | ||
1596 | { | ||
1597 | struct brcmf_usb_image *fw_image, *next; | ||
1598 | |||
1599 | list_for_each_entry_safe(fw_image, next, q, list) { | ||
1600 | vfree(fw_image->image); | ||
1601 | list_del_init(&fw_image->list); | ||
1602 | } | ||
1603 | } | ||
1604 | |||
1605 | |||
1599 | void brcmf_usb_exit(void) | 1606 | void brcmf_usb_exit(void) |
1600 | { | 1607 | { |
1601 | usb_deregister(&brcmf_usbdrvr); | 1608 | usb_deregister(&brcmf_usbdrvr); |
1602 | vfree(g_image.data); | 1609 | brcmf_release_fw(&fw_image_list); |
1603 | g_image.data = NULL; | ||
1604 | g_image.len = 0; | ||
1605 | } | 1610 | } |
1606 | 1611 | ||
1607 | void brcmf_usb_init(void) | 1612 | void brcmf_usb_init(void) |
1608 | { | 1613 | { |
1614 | INIT_LIST_HEAD(&fw_image_list); | ||
1609 | usb_register(&brcmf_usbdrvr); | 1615 | usb_register(&brcmf_usbdrvr); |
1610 | } | 1616 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 32ee05297ccf..af396e4ab977 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -36,6 +36,18 @@ | |||
36 | #include "dhd.h" | 36 | #include "dhd.h" |
37 | #include "wl_cfg80211.h" | 37 | #include "wl_cfg80211.h" |
38 | 38 | ||
39 | #define BRCMF_SCAN_IE_LEN_MAX 2048 | ||
40 | #define BRCMF_PNO_VERSION 2 | ||
41 | #define BRCMF_PNO_TIME 30 | ||
42 | #define BRCMF_PNO_REPEAT 4 | ||
43 | #define BRCMF_PNO_FREQ_EXPO_MAX 3 | ||
44 | #define BRCMF_PNO_MAX_PFN_COUNT 16 | ||
45 | #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 | ||
46 | #define BRCMF_PNO_HIDDEN_BIT 2 | ||
47 | #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF | ||
48 | #define BRCMF_PNO_SCAN_COMPLETE 1 | ||
49 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | ||
50 | |||
39 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ | 51 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ |
40 | (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) | 52 | (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) |
41 | 53 | ||
@@ -700,11 +712,11 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
700 | u32 n_channels; | 712 | u32 n_channels; |
701 | s32 i; | 713 | s32 i; |
702 | s32 offset; | 714 | s32 offset; |
703 | __le16 chanspec; | 715 | u16 chanspec; |
704 | u16 channel; | 716 | u16 channel; |
705 | struct ieee80211_channel *req_channel; | 717 | struct ieee80211_channel *req_channel; |
706 | char *ptr; | 718 | char *ptr; |
707 | struct brcmf_ssid ssid; | 719 | struct brcmf_ssid_le ssid_le; |
708 | 720 | ||
709 | memcpy(params_le->bssid, ether_bcast, ETH_ALEN); | 721 | memcpy(params_le->bssid, ether_bcast, ETH_ALEN); |
710 | params_le->bss_type = DOT11_BSSTYPE_ANY; | 722 | params_le->bss_type = DOT11_BSSTYPE_ANY; |
@@ -747,13 +759,10 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
747 | chanspec |= WL_CHANSPEC_CTL_SB_UPPER; | 759 | chanspec |= WL_CHANSPEC_CTL_SB_UPPER; |
748 | } | 760 | } |
749 | 761 | ||
750 | params_le->channel_list[i] = | 762 | chanspec |= (channel & WL_CHANSPEC_CHAN_MASK); |
751 | (channel & WL_CHANSPEC_CHAN_MASK) | | ||
752 | chanspec; | ||
753 | WL_SCAN("Chan : %d, Channel spec: %x\n", | 763 | WL_SCAN("Chan : %d, Channel spec: %x\n", |
754 | channel, params_le->channel_list[i]); | 764 | channel, chanspec); |
755 | params_le->channel_list[i] = | 765 | params_le->channel_list[i] = cpu_to_le16(chanspec); |
756 | cpu_to_le16(params_le->channel_list[i]); | ||
757 | } | 766 | } |
758 | } else { | 767 | } else { |
759 | WL_SCAN("Scanning all channels\n"); | 768 | WL_SCAN("Scanning all channels\n"); |
@@ -766,17 +775,18 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
766 | offset = roundup(offset, sizeof(u32)); | 775 | offset = roundup(offset, sizeof(u32)); |
767 | ptr = (char *)params_le + offset; | 776 | ptr = (char *)params_le + offset; |
768 | for (i = 0; i < n_ssids; i++) { | 777 | for (i = 0; i < n_ssids; i++) { |
769 | memset(&ssid, 0, sizeof(ssid)); | 778 | memset(&ssid_le, 0, sizeof(ssid_le)); |
770 | ssid.SSID_len = cpu_to_le32(request->ssids[i].ssid_len); | 779 | ssid_le.SSID_len = |
771 | memcpy(ssid.SSID, request->ssids[i].ssid, | 780 | cpu_to_le32(request->ssids[i].ssid_len); |
772 | request->ssids[i].ssid_len); | 781 | memcpy(ssid_le.SSID, request->ssids[i].ssid, |
773 | if (!ssid.SSID_len) | 782 | request->ssids[i].ssid_len); |
783 | if (!ssid_le.SSID_len) | ||
774 | WL_SCAN("%d: Broadcast scan\n", i); | 784 | WL_SCAN("%d: Broadcast scan\n", i); |
775 | else | 785 | else |
776 | WL_SCAN("%d: scan for %s size =%d\n", i, | 786 | WL_SCAN("%d: scan for %s size =%d\n", i, |
777 | ssid.SSID, ssid.SSID_len); | 787 | ssid_le.SSID, ssid_le.SSID_len); |
778 | memcpy(ptr, &ssid, sizeof(ssid)); | 788 | memcpy(ptr, &ssid_le, sizeof(ssid_le)); |
779 | ptr += sizeof(ssid); | 789 | ptr += sizeof(ssid_le); |
780 | } | 790 | } |
781 | } else { | 791 | } else { |
782 | WL_SCAN("Broadcast scan %p\n", request->ssids); | 792 | WL_SCAN("Broadcast scan %p\n", request->ssids); |
@@ -834,7 +844,17 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, | |||
834 | if (err) | 844 | if (err) |
835 | WL_ERR("Scan abort failed\n"); | 845 | WL_ERR("Scan abort failed\n"); |
836 | } | 846 | } |
837 | if (scan_request) { | 847 | /* |
848 | * e-scan can be initiated by scheduled scan | ||
849 | * which takes precedence. | ||
850 | */ | ||
851 | if (cfg_priv->sched_escan) { | ||
852 | WL_SCAN("scheduled scan completed\n"); | ||
853 | cfg_priv->sched_escan = false; | ||
854 | if (!aborted) | ||
855 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg_priv)); | ||
856 | brcmf_set_mpc(ndev, 1); | ||
857 | } else if (scan_request) { | ||
838 | WL_SCAN("ESCAN Completed scan: %s\n", | 858 | WL_SCAN("ESCAN Completed scan: %s\n", |
839 | aborted ? "Aborted" : "Done"); | 859 | aborted ? "Aborted" : "Done"); |
840 | cfg80211_scan_done(scan_request, aborted); | 860 | cfg80211_scan_done(scan_request, aborted); |
@@ -2593,11 +2613,13 @@ update_bss_info_out: | |||
2593 | return err; | 2613 | return err; |
2594 | } | 2614 | } |
2595 | 2615 | ||
2596 | static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) | 2616 | static void brcmf_abort_scanning(struct brcmf_cfg80211_priv *cfg_priv) |
2597 | { | 2617 | { |
2598 | struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); | 2618 | struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); |
2619 | struct escan_info *escan = &cfg_priv->escan_info; | ||
2599 | struct brcmf_ssid ssid; | 2620 | struct brcmf_ssid ssid; |
2600 | 2621 | ||
2622 | set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | ||
2601 | if (cfg_priv->iscan_on) { | 2623 | if (cfg_priv->iscan_on) { |
2602 | iscan->state = WL_ISCAN_STATE_IDLE; | 2624 | iscan->state = WL_ISCAN_STATE_IDLE; |
2603 | 2625 | ||
@@ -2611,7 +2633,20 @@ static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) | |||
2611 | /* Abort iscan running in FW */ | 2633 | /* Abort iscan running in FW */ |
2612 | memset(&ssid, 0, sizeof(ssid)); | 2634 | memset(&ssid, 0, sizeof(ssid)); |
2613 | brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); | 2635 | brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); |
2636 | |||
2637 | if (cfg_priv->scan_request) { | ||
2638 | /* Indidate scan abort to cfg80211 layer */ | ||
2639 | WL_INFO("Terminating scan in progress\n"); | ||
2640 | cfg80211_scan_done(cfg_priv->scan_request, true); | ||
2641 | cfg_priv->scan_request = NULL; | ||
2642 | } | ||
2614 | } | 2643 | } |
2644 | if (cfg_priv->escan_on && cfg_priv->scan_request) { | ||
2645 | escan->escan_state = WL_ESCAN_STATE_IDLE; | ||
2646 | brcmf_notify_escan_complete(cfg_priv, escan->ndev, true, true); | ||
2647 | } | ||
2648 | clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); | ||
2649 | clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | ||
2615 | } | 2650 | } |
2616 | 2651 | ||
2617 | static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, | 2652 | static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, |
@@ -2842,10 +2877,13 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss, | |||
2842 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { | 2877 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { |
2843 | if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == | 2878 | if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == |
2844 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) { | 2879 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) { |
2880 | s16 bss_rssi = le16_to_cpu(bss->RSSI); | ||
2881 | s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI); | ||
2882 | |||
2845 | /* preserve max RSSI if the measurements are | 2883 | /* preserve max RSSI if the measurements are |
2846 | * both on-channel or both off-channel | 2884 | * both on-channel or both off-channel |
2847 | */ | 2885 | */ |
2848 | if (bss_info_le->RSSI > bss->RSSI) | 2886 | if (bss_info_rssi > bss_rssi) |
2849 | bss->RSSI = bss_info_le->RSSI; | 2887 | bss->RSSI = bss_info_le->RSSI; |
2850 | } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && | 2888 | } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && |
2851 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { | 2889 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { |
@@ -2873,6 +2911,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, | |||
2873 | u32 bi_length; | 2911 | u32 bi_length; |
2874 | struct brcmf_scan_results *list; | 2912 | struct brcmf_scan_results *list; |
2875 | u32 i; | 2913 | u32 i; |
2914 | bool aborted; | ||
2876 | 2915 | ||
2877 | status = be32_to_cpu(e->status); | 2916 | status = be32_to_cpu(e->status); |
2878 | 2917 | ||
@@ -2945,16 +2984,9 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, | |||
2945 | cfg_priv->bss_list = (struct brcmf_scan_results *) | 2984 | cfg_priv->bss_list = (struct brcmf_scan_results *) |
2946 | cfg_priv->escan_info.escan_buf; | 2985 | cfg_priv->escan_info.escan_buf; |
2947 | brcmf_inform_bss(cfg_priv); | 2986 | brcmf_inform_bss(cfg_priv); |
2948 | if (status == BRCMF_E_STATUS_SUCCESS) { | 2987 | aborted = status != BRCMF_E_STATUS_SUCCESS; |
2949 | WL_SCAN("ESCAN Completed\n"); | 2988 | brcmf_notify_escan_complete(cfg_priv, ndev, aborted, |
2950 | brcmf_notify_escan_complete(cfg_priv, ndev, | 2989 | false); |
2951 | false, false); | ||
2952 | } else { | ||
2953 | WL_ERR("ESCAN Aborted, Event 0x%x\n", status); | ||
2954 | brcmf_notify_escan_complete(cfg_priv, ndev, | ||
2955 | true, false); | ||
2956 | } | ||
2957 | brcmf_set_mpc(ndev, 1); | ||
2958 | } else | 2990 | } else |
2959 | WL_ERR("Unexpected scan result 0x%x\n", status); | 2991 | WL_ERR("Unexpected scan result 0x%x\n", status); |
2960 | } | 2992 | } |
@@ -3039,18 +3071,10 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
3039 | brcmf_delay(500); | 3071 | brcmf_delay(500); |
3040 | } | 3072 | } |
3041 | 3073 | ||
3042 | set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | ||
3043 | if (test_bit(WL_STATUS_READY, &cfg_priv->status)) | 3074 | if (test_bit(WL_STATUS_READY, &cfg_priv->status)) |
3044 | brcmf_term_iscan(cfg_priv); | 3075 | brcmf_abort_scanning(cfg_priv); |
3045 | 3076 | else | |
3046 | if (cfg_priv->scan_request) { | 3077 | clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); |
3047 | /* Indidate scan abort to cfg80211 layer */ | ||
3048 | WL_INFO("Terminating scan in progress\n"); | ||
3049 | cfg80211_scan_done(cfg_priv->scan_request, true); | ||
3050 | cfg_priv->scan_request = NULL; | ||
3051 | } | ||
3052 | clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); | ||
3053 | clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | ||
3054 | 3078 | ||
3055 | /* Turn off watchdog timer */ | 3079 | /* Turn off watchdog timer */ |
3056 | if (test_bit(WL_STATUS_READY, &cfg_priv->status)) | 3080 | if (test_bit(WL_STATUS_READY, &cfg_priv->status)) |
@@ -3229,6 +3253,269 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) | |||
3229 | 3253 | ||
3230 | } | 3254 | } |
3231 | 3255 | ||
3256 | /* | ||
3257 | * PFN result doesn't have all the info which are | ||
3258 | * required by the supplicant | ||
3259 | * (For e.g IEs) Do a target Escan so that sched scan results are reported | ||
3260 | * via wl_inform_single_bss in the required format. Escan does require the | ||
3261 | * scan request in the form of cfg80211_scan_request. For timebeing, create | ||
3262 | * cfg80211_scan_request one out of the received PNO event. | ||
3263 | */ | ||
3264 | static s32 | ||
3265 | brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv, | ||
3266 | struct net_device *ndev, | ||
3267 | const struct brcmf_event_msg *e, void *data) | ||
3268 | { | ||
3269 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; | ||
3270 | struct cfg80211_scan_request *request = NULL; | ||
3271 | struct cfg80211_ssid *ssid = NULL; | ||
3272 | struct ieee80211_channel *channel = NULL; | ||
3273 | struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); | ||
3274 | int err = 0; | ||
3275 | int channel_req = 0; | ||
3276 | int band = 0; | ||
3277 | struct brcmf_pno_scanresults_le *pfn_result; | ||
3278 | u32 result_count; | ||
3279 | u32 status; | ||
3280 | |||
3281 | WL_SCAN("Enter\n"); | ||
3282 | |||
3283 | if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) { | ||
3284 | WL_SCAN("PFN NET LOST event. Do Nothing\n"); | ||
3285 | return 0; | ||
3286 | } | ||
3287 | |||
3288 | pfn_result = (struct brcmf_pno_scanresults_le *)data; | ||
3289 | result_count = le32_to_cpu(pfn_result->count); | ||
3290 | status = le32_to_cpu(pfn_result->status); | ||
3291 | |||
3292 | /* | ||
3293 | * PFN event is limited to fit 512 bytes so we may get | ||
3294 | * multiple NET_FOUND events. For now place a warning here. | ||
3295 | */ | ||
3296 | WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); | ||
3297 | WL_SCAN("PFN NET FOUND event. count: %d\n", result_count); | ||
3298 | if (result_count > 0) { | ||
3299 | int i; | ||
3300 | |||
3301 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
3302 | ssid = kzalloc(sizeof(*ssid) * result_count, GFP_KERNEL); | ||
3303 | channel = kzalloc(sizeof(*channel) * result_count, GFP_KERNEL); | ||
3304 | if (!request || !ssid || !channel) { | ||
3305 | err = -ENOMEM; | ||
3306 | goto out_err; | ||
3307 | } | ||
3308 | |||
3309 | request->wiphy = wiphy; | ||
3310 | data += sizeof(struct brcmf_pno_scanresults_le); | ||
3311 | netinfo_start = (struct brcmf_pno_net_info_le *)data; | ||
3312 | |||
3313 | for (i = 0; i < result_count; i++) { | ||
3314 | netinfo = &netinfo_start[i]; | ||
3315 | if (!netinfo) { | ||
3316 | WL_ERR("Invalid netinfo ptr. index: %d\n", i); | ||
3317 | err = -EINVAL; | ||
3318 | goto out_err; | ||
3319 | } | ||
3320 | |||
3321 | WL_SCAN("SSID:%s Channel:%d\n", | ||
3322 | netinfo->SSID, netinfo->channel); | ||
3323 | memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); | ||
3324 | ssid[i].ssid_len = netinfo->SSID_len; | ||
3325 | request->n_ssids++; | ||
3326 | |||
3327 | channel_req = netinfo->channel; | ||
3328 | if (channel_req <= CH_MAX_2G_CHANNEL) | ||
3329 | band = NL80211_BAND_2GHZ; | ||
3330 | else | ||
3331 | band = NL80211_BAND_5GHZ; | ||
3332 | channel[i].center_freq = | ||
3333 | ieee80211_channel_to_frequency(channel_req, | ||
3334 | band); | ||
3335 | channel[i].band = band; | ||
3336 | channel[i].flags |= IEEE80211_CHAN_NO_HT40; | ||
3337 | request->channels[i] = &channel[i]; | ||
3338 | request->n_channels++; | ||
3339 | } | ||
3340 | |||
3341 | /* assign parsed ssid array */ | ||
3342 | if (request->n_ssids) | ||
3343 | request->ssids = &ssid[0]; | ||
3344 | |||
3345 | if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { | ||
3346 | /* Abort any on-going scan */ | ||
3347 | brcmf_abort_scanning(cfg_priv); | ||
3348 | } | ||
3349 | |||
3350 | set_bit(WL_STATUS_SCANNING, &cfg_priv->status); | ||
3351 | err = brcmf_do_escan(cfg_priv, wiphy, ndev, request); | ||
3352 | if (err) { | ||
3353 | clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); | ||
3354 | goto out_err; | ||
3355 | } | ||
3356 | cfg_priv->sched_escan = true; | ||
3357 | cfg_priv->scan_request = request; | ||
3358 | } else { | ||
3359 | WL_ERR("FALSE PNO Event. (pfn_count == 0)\n"); | ||
3360 | goto out_err; | ||
3361 | } | ||
3362 | |||
3363 | kfree(ssid); | ||
3364 | kfree(channel); | ||
3365 | kfree(request); | ||
3366 | return 0; | ||
3367 | |||
3368 | out_err: | ||
3369 | kfree(ssid); | ||
3370 | kfree(channel); | ||
3371 | kfree(request); | ||
3372 | cfg80211_sched_scan_stopped(wiphy); | ||
3373 | return err; | ||
3374 | } | ||
3375 | |||
3376 | #ifndef CONFIG_BRCMISCAN | ||
3377 | static int brcmf_dev_pno_clean(struct net_device *ndev) | ||
3378 | { | ||
3379 | char iovbuf[128]; | ||
3380 | int ret; | ||
3381 | |||
3382 | /* Disable pfn */ | ||
3383 | ret = brcmf_dev_intvar_set(ndev, "pfn", 0); | ||
3384 | if (ret == 0) { | ||
3385 | /* clear pfn */ | ||
3386 | ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0, | ||
3387 | iovbuf, sizeof(iovbuf)); | ||
3388 | } | ||
3389 | if (ret < 0) | ||
3390 | WL_ERR("failed code %d\n", ret); | ||
3391 | |||
3392 | return ret; | ||
3393 | } | ||
3394 | |||
3395 | static int brcmf_dev_pno_config(struct net_device *ndev) | ||
3396 | { | ||
3397 | struct brcmf_pno_param_le pfn_param; | ||
3398 | char iovbuf[128]; | ||
3399 | |||
3400 | memset(&pfn_param, 0, sizeof(pfn_param)); | ||
3401 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); | ||
3402 | |||
3403 | /* set extra pno params */ | ||
3404 | pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); | ||
3405 | pfn_param.repeat = BRCMF_PNO_REPEAT; | ||
3406 | pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; | ||
3407 | |||
3408 | /* set up pno scan fr */ | ||
3409 | pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); | ||
3410 | |||
3411 | return brcmf_dev_iovar_setbuf(ndev, "pfn_set", | ||
3412 | &pfn_param, sizeof(pfn_param), | ||
3413 | iovbuf, sizeof(iovbuf)); | ||
3414 | } | ||
3415 | |||
3416 | static int | ||
3417 | brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | ||
3418 | struct net_device *ndev, | ||
3419 | struct cfg80211_sched_scan_request *request) | ||
3420 | { | ||
3421 | char iovbuf[128]; | ||
3422 | struct brcmf_cfg80211_priv *cfg_priv = wiphy_priv(wiphy); | ||
3423 | struct brcmf_pno_net_param_le pfn; | ||
3424 | int i; | ||
3425 | int ret = 0; | ||
3426 | |||
3427 | WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", | ||
3428 | request->n_match_sets, request->n_ssids); | ||
3429 | if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { | ||
3430 | WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); | ||
3431 | return -EAGAIN; | ||
3432 | } | ||
3433 | |||
3434 | if (!request || !request->n_ssids || !request->n_match_sets) { | ||
3435 | WL_ERR("Invalid sched scan req!! n_ssids:%d\n", | ||
3436 | request->n_ssids); | ||
3437 | return -EINVAL; | ||
3438 | } | ||
3439 | |||
3440 | if (request->n_ssids > 0) { | ||
3441 | for (i = 0; i < request->n_ssids; i++) { | ||
3442 | /* Active scan req for ssids */ | ||
3443 | WL_SCAN(">>> Active scan req for ssid (%s)\n", | ||
3444 | request->ssids[i].ssid); | ||
3445 | |||
3446 | /* | ||
3447 | * match_set ssids is a supert set of n_ssid list, | ||
3448 | * so we need not add these set seperately. | ||
3449 | */ | ||
3450 | } | ||
3451 | } | ||
3452 | |||
3453 | if (request->n_match_sets > 0) { | ||
3454 | /* clean up everything */ | ||
3455 | ret = brcmf_dev_pno_clean(ndev); | ||
3456 | if (ret < 0) { | ||
3457 | WL_ERR("failed error=%d\n", ret); | ||
3458 | return ret; | ||
3459 | } | ||
3460 | |||
3461 | /* configure pno */ | ||
3462 | ret = brcmf_dev_pno_config(ndev); | ||
3463 | if (ret < 0) { | ||
3464 | WL_ERR("PNO setup failed!! ret=%d\n", ret); | ||
3465 | return -EINVAL; | ||
3466 | } | ||
3467 | |||
3468 | /* configure each match set */ | ||
3469 | for (i = 0; i < request->n_match_sets; i++) { | ||
3470 | struct cfg80211_ssid *ssid; | ||
3471 | u32 ssid_len; | ||
3472 | |||
3473 | ssid = &request->match_sets[i].ssid; | ||
3474 | ssid_len = ssid->ssid_len; | ||
3475 | |||
3476 | if (!ssid_len) { | ||
3477 | WL_ERR("skip broadcast ssid\n"); | ||
3478 | continue; | ||
3479 | } | ||
3480 | pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); | ||
3481 | pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); | ||
3482 | pfn.wsec = cpu_to_le32(0); | ||
3483 | pfn.infra = cpu_to_le32(1); | ||
3484 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); | ||
3485 | pfn.ssid.SSID_len = cpu_to_le32(ssid_len); | ||
3486 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); | ||
3487 | ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add", | ||
3488 | &pfn, sizeof(pfn), | ||
3489 | iovbuf, sizeof(iovbuf)); | ||
3490 | WL_SCAN(">>> PNO filter %s for ssid (%s)\n", | ||
3491 | ret == 0 ? "set" : "failed", | ||
3492 | ssid->ssid); | ||
3493 | } | ||
3494 | /* Enable the PNO */ | ||
3495 | if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) { | ||
3496 | WL_ERR("PNO enable failed!! ret=%d\n", ret); | ||
3497 | return -EINVAL; | ||
3498 | } | ||
3499 | } else { | ||
3500 | return -EINVAL; | ||
3501 | } | ||
3502 | |||
3503 | return 0; | ||
3504 | } | ||
3505 | |||
3506 | static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, | ||
3507 | struct net_device *ndev) | ||
3508 | { | ||
3509 | struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); | ||
3510 | |||
3511 | WL_SCAN("enter\n"); | ||
3512 | brcmf_dev_pno_clean(ndev); | ||
3513 | if (cfg_priv->sched_escan) | ||
3514 | brcmf_notify_escan_complete(cfg_priv, ndev, true, true); | ||
3515 | return 0; | ||
3516 | } | ||
3517 | #endif /* CONFIG_BRCMISCAN */ | ||
3518 | |||
3232 | #ifdef CONFIG_NL80211_TESTMODE | 3519 | #ifdef CONFIG_NL80211_TESTMODE |
3233 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) | 3520 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) |
3234 | { | 3521 | { |
@@ -3271,6 +3558,11 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
3271 | .set_pmksa = brcmf_cfg80211_set_pmksa, | 3558 | .set_pmksa = brcmf_cfg80211_set_pmksa, |
3272 | .del_pmksa = brcmf_cfg80211_del_pmksa, | 3559 | .del_pmksa = brcmf_cfg80211_del_pmksa, |
3273 | .flush_pmksa = brcmf_cfg80211_flush_pmksa, | 3560 | .flush_pmksa = brcmf_cfg80211_flush_pmksa, |
3561 | #ifndef CONFIG_BRCMISCAN | ||
3562 | /* scheduled scan need e-scan, which is mutual exclusive with i-scan */ | ||
3563 | .sched_scan_start = brcmf_cfg80211_sched_scan_start, | ||
3564 | .sched_scan_stop = brcmf_cfg80211_sched_scan_stop, | ||
3565 | #endif | ||
3274 | #ifdef CONFIG_NL80211_TESTMODE | 3566 | #ifdef CONFIG_NL80211_TESTMODE |
3275 | .testmode_cmd = brcmf_cfg80211_testmode | 3567 | .testmode_cmd = brcmf_cfg80211_testmode |
3276 | #endif | 3568 | #endif |
@@ -3292,6 +3584,17 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode) | |||
3292 | return err; | 3584 | return err; |
3293 | } | 3585 | } |
3294 | 3586 | ||
3587 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | ||
3588 | { | ||
3589 | #ifndef CONFIG_BRCMFISCAN | ||
3590 | /* scheduled scan settings */ | ||
3591 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | ||
3592 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | ||
3593 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
3594 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
3595 | #endif | ||
3596 | } | ||
3597 | |||
3295 | static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, | 3598 | static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, |
3296 | struct device *ndev) | 3599 | struct device *ndev) |
3297 | { | 3600 | { |
@@ -3330,6 +3633,7 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, | |||
3330 | * save mode | 3633 | * save mode |
3331 | * by default | 3634 | * by default |
3332 | */ | 3635 | */ |
3636 | brcmf_wiphy_pno_params(wdev->wiphy); | ||
3333 | err = wiphy_register(wdev->wiphy); | 3637 | err = wiphy_register(wdev->wiphy); |
3334 | if (err < 0) { | 3638 | if (err < 0) { |
3335 | WL_ERR("Could not register wiphy device (%d)\n", err); | 3639 | WL_ERR("Could not register wiphy device (%d)\n", err); |
@@ -3732,6 +4036,7 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) | |||
3732 | el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; | 4036 | el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; |
3733 | el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; | 4037 | el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; |
3734 | el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; | 4038 | el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; |
4039 | el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results; | ||
3735 | } | 4040 | } |
3736 | 4041 | ||
3737 | static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) | 4042 | static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) |
@@ -3957,13 +4262,13 @@ static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) | |||
3957 | cfg_priv->dongle_up = false; /* dongle down */ | 4262 | cfg_priv->dongle_up = false; /* dongle down */ |
3958 | brcmf_flush_eq(cfg_priv); | 4263 | brcmf_flush_eq(cfg_priv); |
3959 | brcmf_link_down(cfg_priv); | 4264 | brcmf_link_down(cfg_priv); |
3960 | brcmf_term_iscan(cfg_priv); | 4265 | brcmf_abort_scanning(cfg_priv); |
3961 | brcmf_deinit_priv_mem(cfg_priv); | 4266 | brcmf_deinit_priv_mem(cfg_priv); |
3962 | } | 4267 | } |
3963 | 4268 | ||
3964 | struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, | 4269 | struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, |
3965 | struct device *busdev, | 4270 | struct device *busdev, |
3966 | void *data) | 4271 | struct brcmf_pub *drvr) |
3967 | { | 4272 | { |
3968 | struct wireless_dev *wdev; | 4273 | struct wireless_dev *wdev; |
3969 | struct brcmf_cfg80211_priv *cfg_priv; | 4274 | struct brcmf_cfg80211_priv *cfg_priv; |
@@ -3988,7 +4293,7 @@ struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, | |||
3988 | wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); | 4293 | wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); |
3989 | cfg_priv = wdev_to_cfg(wdev); | 4294 | cfg_priv = wdev_to_cfg(wdev); |
3990 | cfg_priv->wdev = wdev; | 4295 | cfg_priv->wdev = wdev; |
3991 | cfg_priv->pub = data; | 4296 | cfg_priv->pub = drvr; |
3992 | ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; | 4297 | ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; |
3993 | ci->cfg_priv = cfg_priv; | 4298 | ci->cfg_priv = cfg_priv; |
3994 | ndev->ieee80211_ptr = wdev; | 4299 | ndev->ieee80211_ptr = wdev; |
@@ -4103,6 +4408,7 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev) | |||
4103 | setbit(eventmask, BRCMF_E_JOIN_START); | 4408 | setbit(eventmask, BRCMF_E_JOIN_START); |
4104 | setbit(eventmask, BRCMF_E_SCAN_COMPLETE); | 4409 | setbit(eventmask, BRCMF_E_SCAN_COMPLETE); |
4105 | setbit(eventmask, BRCMF_E_ESCAN_RESULT); | 4410 | setbit(eventmask, BRCMF_E_ESCAN_RESULT); |
4411 | setbit(eventmask, BRCMF_E_PFN_NET_FOUND); | ||
4106 | 4412 | ||
4107 | brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, | 4413 | brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, |
4108 | iovbuf, sizeof(iovbuf)); | 4414 | iovbuf, sizeof(iovbuf)); |
@@ -4235,7 +4541,7 @@ static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) | |||
4235 | return err; | 4541 | return err; |
4236 | } | 4542 | } |
4237 | 4543 | ||
4238 | phy = ((char *)&phy_list)[1]; | 4544 | phy = ((char *)&phy_list)[0]; |
4239 | WL_INFO("%c phy\n", phy); | 4545 | WL_INFO("%c phy\n", phy); |
4240 | if (phy == 'n' || phy == 'a') { | 4546 | if (phy == 'n' || phy == 'a') { |
4241 | wiphy = cfg_to_wiphy(cfg_priv); | 4547 | wiphy = cfg_to_wiphy(cfg_priv); |
@@ -4368,17 +4674,8 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) | |||
4368 | brcmf_delay(500); | 4674 | brcmf_delay(500); |
4369 | } | 4675 | } |
4370 | 4676 | ||
4371 | set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | 4677 | brcmf_abort_scanning(cfg_priv); |
4372 | brcmf_term_iscan(cfg_priv); | ||
4373 | if (cfg_priv->scan_request) { | ||
4374 | cfg80211_scan_done(cfg_priv->scan_request, true); | ||
4375 | /* May need to perform this to cover rmmod */ | ||
4376 | /* wl_set_mpc(cfg_to_ndev(wl), 1); */ | ||
4377 | cfg_priv->scan_request = NULL; | ||
4378 | } | ||
4379 | clear_bit(WL_STATUS_READY, &cfg_priv->status); | 4678 | clear_bit(WL_STATUS_READY, &cfg_priv->status); |
4380 | clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); | ||
4381 | clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); | ||
4382 | 4679 | ||
4383 | brcmf_debugfs_remove_netdev(cfg_priv); | 4680 | brcmf_debugfs_remove_netdev(cfg_priv); |
4384 | 4681 | ||
@@ -4411,20 +4708,3 @@ s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) | |||
4411 | return err; | 4708 | return err; |
4412 | } | 4709 | } |
4413 | 4710 | ||
4414 | static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv, | ||
4415 | u8 t, u8 l, u8 *v) | ||
4416 | { | ||
4417 | struct brcmf_cfg80211_ie *ie = &cfg_priv->ie; | ||
4418 | s32 err = 0; | ||
4419 | |||
4420 | if (ie->offset + l + 2 > WL_TLV_INFO_MAX) { | ||
4421 | WL_ERR("ei crosses buffer boundary\n"); | ||
4422 | return -ENOSPC; | ||
4423 | } | ||
4424 | ie->buf[ie->offset] = t; | ||
4425 | ie->buf[ie->offset + 1] = l; | ||
4426 | memcpy(&ie->buf[ie->offset + 2], v, l); | ||
4427 | ie->offset += l + 2; | ||
4428 | |||
4429 | return err; | ||
4430 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 3b2129738d30..52e408ed6f41 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -295,50 +295,168 @@ struct escan_info { | |||
295 | struct net_device *ndev; | 295 | struct net_device *ndev; |
296 | }; | 296 | }; |
297 | 297 | ||
298 | /* dongle private data of cfg80211 interface */ | 298 | /** |
299 | * struct brcmf_pno_param_le - PNO scan configuration parameters | ||
300 | * | ||
301 | * @version: PNO parameters version. | ||
302 | * @scan_freq: scan frequency. | ||
303 | * @lost_network_timeout: #sec. to declare discovered network as lost. | ||
304 | * @flags: Bit field to control features of PFN such as sort criteria auto | ||
305 | * enable switch and background scan. | ||
306 | * @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort | ||
307 | * criteria. | ||
308 | * @bestn: number of best networks in each scan. | ||
309 | * @mscan: number of scans recorded. | ||
310 | * @repeat: minimum number of scan intervals before scan frequency changes | ||
311 | * in adaptive scan. | ||
312 | * @exp: exponent of 2 for maximum scan interval. | ||
313 | * @slow_freq: slow scan period. | ||
314 | */ | ||
315 | struct brcmf_pno_param_le { | ||
316 | __le32 version; | ||
317 | __le32 scan_freq; | ||
318 | __le32 lost_network_timeout; | ||
319 | __le16 flags; | ||
320 | __le16 rssi_margin; | ||
321 | u8 bestn; | ||
322 | u8 mscan; | ||
323 | u8 repeat; | ||
324 | u8 exp; | ||
325 | __le32 slow_freq; | ||
326 | }; | ||
327 | |||
328 | /** | ||
329 | * struct brcmf_pno_net_param_le - scan parameters per preferred network. | ||
330 | * | ||
331 | * @ssid: ssid name and its length. | ||
332 | * @flags: bit2: hidden. | ||
333 | * @infra: BSS vs IBSS. | ||
334 | * @auth: Open vs Closed. | ||
335 | * @wpa_auth: WPA type. | ||
336 | * @wsec: wsec value. | ||
337 | */ | ||
338 | struct brcmf_pno_net_param_le { | ||
339 | struct brcmf_ssid_le ssid; | ||
340 | __le32 flags; | ||
341 | __le32 infra; | ||
342 | __le32 auth; | ||
343 | __le32 wpa_auth; | ||
344 | __le32 wsec; | ||
345 | }; | ||
346 | |||
347 | /** | ||
348 | * struct brcmf_pno_net_info_le - information per found network. | ||
349 | * | ||
350 | * @bssid: BSS network identifier. | ||
351 | * @channel: channel number only. | ||
352 | * @SSID_len: length of ssid. | ||
353 | * @SSID: ssid characters. | ||
354 | * @RSSI: receive signal strength (in dBm). | ||
355 | * @timestamp: age in seconds. | ||
356 | */ | ||
357 | struct brcmf_pno_net_info_le { | ||
358 | u8 bssid[ETH_ALEN]; | ||
359 | u8 channel; | ||
360 | u8 SSID_len; | ||
361 | u8 SSID[32]; | ||
362 | __le16 RSSI; | ||
363 | __le16 timestamp; | ||
364 | }; | ||
365 | |||
366 | /** | ||
367 | * struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event. | ||
368 | * | ||
369 | * @version: PNO version identifier. | ||
370 | * @status: indicates completion status of PNO scan. | ||
371 | * @count: amount of brcmf_pno_net_info_le entries appended. | ||
372 | */ | ||
373 | struct brcmf_pno_scanresults_le { | ||
374 | __le32 version; | ||
375 | __le32 status; | ||
376 | __le32 count; | ||
377 | }; | ||
378 | |||
379 | /** | ||
380 | * struct brcmf_cfg80211_priv - dongle private data of cfg80211 interface | ||
381 | * | ||
382 | * @wdev: representing wl cfg80211 device. | ||
383 | * @conf: dongle configuration. | ||
384 | * @scan_request: cfg80211 scan request object. | ||
385 | * @el: main event loop. | ||
386 | * @evt_q_list: used for event queue. | ||
387 | * @evt_q_lock: for event queue synchronization. | ||
388 | * @usr_sync: mainly for dongle up/down synchronization. | ||
389 | * @bss_list: bss_list holding scanned ap information. | ||
390 | * @scan_results: results of the last scan. | ||
391 | * @scan_req_int: internal scan request object. | ||
392 | * @bss_info: bss information for cfg80211 layer. | ||
393 | * @ie: information element object for internal purpose. | ||
394 | * @profile: holding dongle profile. | ||
395 | * @iscan: iscan controller information. | ||
396 | * @conn_info: association info. | ||
397 | * @pmk_list: wpa2 pmk list. | ||
398 | * @event_work: event handler work struct. | ||
399 | * @status: current dongle status. | ||
400 | * @pub: common driver information. | ||
401 | * @channel: current channel. | ||
402 | * @iscan_on: iscan on/off switch. | ||
403 | * @iscan_kickstart: indicate iscan already started. | ||
404 | * @active_scan: current scan mode. | ||
405 | * @sched_escan: e-scan for scheduled scan support running. | ||
406 | * @ibss_starter: indicates this sta is ibss starter. | ||
407 | * @link_up: link/connection up flag. | ||
408 | * @pwr_save: indicate whether dongle to support power save mode. | ||
409 | * @dongle_up: indicate whether dongle up or not. | ||
410 | * @roam_on: on/off switch for dongle self-roaming. | ||
411 | * @scan_tried: indicates if first scan attempted. | ||
412 | * @dcmd_buf: dcmd buffer. | ||
413 | * @extra_buf: mainly to grab assoc information. | ||
414 | * @debugfsdir: debugfs folder for this device. | ||
415 | * @escan_on: escan on/off switch. | ||
416 | * @escan_info: escan information. | ||
417 | * @escan_timeout: Timer for catch scan timeout. | ||
418 | * @escan_timeout_work: scan timeout worker. | ||
419 | * @escan_ioctl_buf: dongle command buffer for escan commands. | ||
420 | * @ci: used to link this structure to netdev private data. | ||
421 | */ | ||
299 | struct brcmf_cfg80211_priv { | 422 | struct brcmf_cfg80211_priv { |
300 | struct wireless_dev *wdev; /* representing wl cfg80211 device */ | 423 | struct wireless_dev *wdev; |
301 | struct brcmf_cfg80211_conf *conf; /* dongle configuration */ | 424 | struct brcmf_cfg80211_conf *conf; |
302 | struct cfg80211_scan_request *scan_request; /* scan request | 425 | struct cfg80211_scan_request *scan_request; |
303 | object */ | 426 | struct brcmf_cfg80211_event_loop el; |
304 | struct brcmf_cfg80211_event_loop el; /* main event loop */ | 427 | struct list_head evt_q_list; |
305 | struct list_head evt_q_list; /* used for event queue */ | 428 | spinlock_t evt_q_lock; |
306 | spinlock_t evt_q_lock; /* for event queue synchronization */ | 429 | struct mutex usr_sync; |
307 | struct mutex usr_sync; /* maily for dongle up/down synchronization */ | 430 | struct brcmf_scan_results *bss_list; |
308 | struct brcmf_scan_results *bss_list; /* bss_list holding scanned | ||
309 | ap information */ | ||
310 | struct brcmf_scan_results *scan_results; | 431 | struct brcmf_scan_results *scan_results; |
311 | struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object | 432 | struct brcmf_cfg80211_scan_req *scan_req_int; |
312 | for internal purpose */ | 433 | struct wl_cfg80211_bss_info *bss_info; |
313 | struct wl_cfg80211_bss_info *bss_info; /* bss information for | 434 | struct brcmf_cfg80211_ie ie; |
314 | cfg80211 layer */ | 435 | struct brcmf_cfg80211_profile *profile; |
315 | struct brcmf_cfg80211_ie ie; /* information element object for | 436 | struct brcmf_cfg80211_iscan_ctrl *iscan; |
316 | internal purpose */ | 437 | struct brcmf_cfg80211_connect_info conn_info; |
317 | struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ | 438 | struct brcmf_cfg80211_pmk_list *pmk_list; |
318 | struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ | 439 | struct work_struct event_work; |
319 | struct brcmf_cfg80211_connect_info conn_info; /* association info */ | 440 | unsigned long status; |
320 | struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ | 441 | struct brcmf_pub *pub; |
321 | struct work_struct event_work; /* event handler work struct */ | 442 | u32 channel; |
322 | unsigned long status; /* current dongle status */ | 443 | bool iscan_on; |
323 | void *pub; | 444 | bool iscan_kickstart; |
324 | u32 channel; /* current channel */ | 445 | bool active_scan; |
325 | bool iscan_on; /* iscan on/off switch */ | 446 | bool sched_escan; |
326 | bool iscan_kickstart; /* indicate iscan already started */ | 447 | bool ibss_starter; |
327 | bool active_scan; /* current scan mode */ | 448 | bool link_up; |
328 | bool ibss_starter; /* indicates this sta is ibss starter */ | 449 | bool pwr_save; |
329 | bool link_up; /* link/connection up flag */ | 450 | bool dongle_up; |
330 | bool pwr_save; /* indicate whether dongle to support | 451 | bool roam_on; |
331 | power save mode */ | 452 | bool scan_tried; |
332 | bool dongle_up; /* indicate whether dongle up or not */ | 453 | u8 *dcmd_buf; |
333 | bool roam_on; /* on/off switch for dongle self-roaming */ | 454 | u8 *extra_buf; |
334 | bool scan_tried; /* indicates if first scan attempted */ | ||
335 | u8 *dcmd_buf; /* dcmd buffer */ | ||
336 | u8 *extra_buf; /* maily to grab assoc information */ | ||
337 | struct dentry *debugfsdir; | 455 | struct dentry *debugfsdir; |
338 | bool escan_on; /* escan on/off switch */ | 456 | bool escan_on; |
339 | struct escan_info escan_info; /* escan information */ | 457 | struct escan_info escan_info; |
340 | struct timer_list escan_timeout; /* Timer for catch scan timeout */ | 458 | struct timer_list escan_timeout; |
341 | struct work_struct escan_timeout_work; /* scan timeout worker */ | 459 | struct work_struct escan_timeout_work; |
342 | u8 *escan_ioctl_buf; | 460 | u8 *escan_ioctl_buf; |
343 | u8 ci[0] __aligned(NETDEV_ALIGN); | 461 | u8 ci[0] __aligned(NETDEV_ALIGN); |
344 | }; | 462 | }; |
@@ -379,7 +497,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) | |||
379 | 497 | ||
380 | extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, | 498 | extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, |
381 | struct device *busdev, | 499 | struct device *busdev, |
382 | void *data); | 500 | struct brcmf_pub *drvr); |
383 | extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); | 501 | extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); |
384 | 502 | ||
385 | /* event handler from dongle */ | 503 | /* event handler from dongle */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 718da8d6d658..a744ea5a9559 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -304,7 +304,10 @@ static int brcms_ops_start(struct ieee80211_hw *hw) | |||
304 | wl->mute_tx = true; | 304 | wl->mute_tx = true; |
305 | 305 | ||
306 | if (!wl->pub->up) | 306 | if (!wl->pub->up) |
307 | err = brcms_up(wl); | 307 | if (!blocked) |
308 | err = brcms_up(wl); | ||
309 | else | ||
310 | err = -ERFKILL; | ||
308 | else | 311 | else |
309 | err = -ENODEV; | 312 | err = -ENODEV; |
310 | spin_unlock_bh(&wl->lock); | 313 | spin_unlock_bh(&wl->lock); |
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index 1571505b1a38..54aba4744438 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c | |||
@@ -675,7 +675,7 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, | |||
675 | } | 675 | } |
676 | done: | 676 | done: |
677 | if (ieee->set_security) | 677 | if (ieee->set_security) |
678 | ieee->set_security(ieee->dev, &sec); | 678 | ieee->set_security(dev, &sec); |
679 | 679 | ||
680 | return ret; | 680 | return ret; |
681 | } | 681 | } |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index eb9987520d61..318ed3c9fe74 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -1586,9 +1586,9 @@ il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame, | |||
1586 | return 0; | 1586 | return 0; |
1587 | 1587 | ||
1588 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 1588 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); |
1589 | memcpy(frame->da, il_bcast_addr, ETH_ALEN); | 1589 | eth_broadcast_addr(frame->da); |
1590 | memcpy(frame->sa, ta, ETH_ALEN); | 1590 | memcpy(frame->sa, ta, ETH_ALEN); |
1591 | memcpy(frame->bssid, il_bcast_addr, ETH_ALEN); | 1591 | eth_broadcast_addr(frame->bssid); |
1592 | frame->seq_ctrl = 0; | 1592 | frame->seq_ctrl = 0; |
1593 | 1593 | ||
1594 | len += 24; | 1594 | len += 24; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index e3467fa86899..bb9f6252d28f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -612,9 +612,9 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | |||
612 | return 0; | 612 | return 0; |
613 | 613 | ||
614 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 614 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); |
615 | memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); | 615 | eth_broadcast_addr(frame->da); |
616 | memcpy(frame->sa, ta, ETH_ALEN); | 616 | memcpy(frame->sa, ta, ETH_ALEN); |
617 | memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); | 617 | eth_broadcast_addr(frame->bssid); |
618 | frame->seq_ctrl = 0; | 618 | frame->seq_ctrl = 0; |
619 | 619 | ||
620 | len += 24; | 620 | len += 24; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index fe36a38f3505..cd9b6de4273e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -128,10 +128,11 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
128 | struct iwl_device_cmd *cmd) | 128 | struct iwl_device_cmd *cmd) |
129 | { | 129 | { |
130 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 130 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
131 | struct iwl_addsta_cmd *addsta = | ||
132 | (struct iwl_addsta_cmd *) cmd->payload; | ||
133 | 131 | ||
134 | return iwl_process_add_sta_resp(priv, addsta, pkt); | 132 | if (!cmd) |
133 | return 0; | ||
134 | |||
135 | return iwl_process_add_sta_resp(priv, (void *)cmd->payload, pkt); | ||
135 | } | 136 | } |
136 | 137 | ||
137 | int iwl_send_add_sta(struct iwl_priv *priv, | 138 | int iwl_send_add_sta(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 6d8d6dd7943f..2cb1efbc5ed1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -295,7 +295,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
295 | static int iwl_verify_sec_sparse(struct iwl_priv *priv, | 295 | static int iwl_verify_sec_sparse(struct iwl_priv *priv, |
296 | const struct fw_desc *fw_desc) | 296 | const struct fw_desc *fw_desc) |
297 | { | 297 | { |
298 | __le32 *image = (__le32 *)fw_desc->v_addr; | 298 | __le32 *image = (__le32 *)fw_desc->data; |
299 | u32 len = fw_desc->len; | 299 | u32 len = fw_desc->len; |
300 | u32 val; | 300 | u32 val; |
301 | u32 i; | 301 | u32 i; |
@@ -319,7 +319,7 @@ static int iwl_verify_sec_sparse(struct iwl_priv *priv, | |||
319 | static void iwl_print_mismatch_sec(struct iwl_priv *priv, | 319 | static void iwl_print_mismatch_sec(struct iwl_priv *priv, |
320 | const struct fw_desc *fw_desc) | 320 | const struct fw_desc *fw_desc) |
321 | { | 321 | { |
322 | __le32 *image = (__le32 *)fw_desc->v_addr; | 322 | __le32 *image = (__le32 *)fw_desc->data; |
323 | u32 len = fw_desc->len; | 323 | u32 len = fw_desc->len; |
324 | u32 val; | 324 | u32 val; |
325 | u32 offs; | 325 | u32 offs; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 48d6d44c16d0..198634b75ed0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/dma-mapping.h> | 64 | #include <linux/dma-mapping.h> |
65 | #include <linux/firmware.h> | 65 | #include <linux/firmware.h> |
66 | #include <linux/module.h> | 66 | #include <linux/module.h> |
67 | #include <linux/vmalloc.h> | ||
67 | 68 | ||
68 | #include "iwl-drv.h" | 69 | #include "iwl-drv.h" |
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
@@ -164,10 +165,8 @@ struct fw_sec { | |||
164 | 165 | ||
165 | static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) | 166 | static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) |
166 | { | 167 | { |
167 | if (desc->v_addr) | 168 | vfree(desc->data); |
168 | dma_free_coherent(drv->trans->dev, desc->len, | 169 | desc->data = NULL; |
169 | desc->v_addr, desc->p_addr); | ||
170 | desc->v_addr = NULL; | ||
171 | desc->len = 0; | 170 | desc->len = 0; |
172 | } | 171 | } |
173 | 172 | ||
@@ -186,21 +185,24 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) | |||
186 | } | 185 | } |
187 | 186 | ||
188 | static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, | 187 | static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, |
189 | struct fw_sec *sec) | 188 | struct fw_sec *sec) |
190 | { | 189 | { |
191 | if (!sec || !sec->size) { | 190 | void *data; |
192 | desc->v_addr = NULL; | 191 | |
192 | desc->data = NULL; | ||
193 | |||
194 | if (!sec || !sec->size) | ||
193 | return -EINVAL; | 195 | return -EINVAL; |
194 | } | ||
195 | 196 | ||
196 | desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size, | 197 | data = vmalloc(sec->size); |
197 | &desc->p_addr, GFP_KERNEL); | 198 | if (!data) |
198 | if (!desc->v_addr) | ||
199 | return -ENOMEM; | 199 | return -ENOMEM; |
200 | 200 | ||
201 | desc->len = sec->size; | 201 | desc->len = sec->size; |
202 | desc->offset = sec->offset; | 202 | desc->offset = sec->offset; |
203 | memcpy(desc->v_addr, sec->data, sec->size); | 203 | memcpy(data, sec->data, desc->len); |
204 | desc->data = data; | ||
205 | |||
204 | return 0; | 206 | return 0; |
205 | } | 207 | } |
206 | 208 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 2153e4cc5572..d1a86b66bc51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -124,8 +124,7 @@ struct iwl_ucode_capabilities { | |||
124 | 124 | ||
125 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ | 125 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ |
126 | struct fw_desc { | 126 | struct fw_desc { |
127 | dma_addr_t p_addr; /* hardware address */ | 127 | const void *data; /* vmalloc'ed data */ |
128 | void *v_addr; /* software address */ | ||
129 | u32 len; /* size in bytes */ | 128 | u32 len; /* size in bytes */ |
130 | u32 offset; /* offset in the device */ | 129 | u32 offset; /* offset in the device */ |
131 | }; | 130 | }; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 89bfb43f4946..2a4675396707 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -263,8 +263,6 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); | |||
263 | /* PCI registers */ | 263 | /* PCI registers */ |
264 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | 264 | #define PCI_CFG_RETRY_TIMEOUT 0x041 |
265 | 265 | ||
266 | #ifndef CONFIG_IWLWIFI_IDI | ||
267 | |||
268 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 266 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
269 | { | 267 | { |
270 | const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 268 | const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
@@ -307,8 +305,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
307 | pci_set_drvdata(pdev, NULL); | 305 | pci_set_drvdata(pdev, NULL); |
308 | } | 306 | } |
309 | 307 | ||
310 | #endif /* CONFIG_IWLWIFI_IDI */ | ||
311 | |||
312 | #ifdef CONFIG_PM_SLEEP | 308 | #ifdef CONFIG_PM_SLEEP |
313 | 309 | ||
314 | static int iwl_pci_suspend(struct device *device) | 310 | static int iwl_pci_suspend(struct device *device) |
@@ -353,15 +349,6 @@ static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); | |||
353 | 349 | ||
354 | #endif | 350 | #endif |
355 | 351 | ||
356 | #ifdef CONFIG_IWLWIFI_IDI | ||
357 | /* | ||
358 | * Defined externally in iwl-idi.c | ||
359 | */ | ||
360 | int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | ||
361 | void __devexit iwl_pci_remove(struct pci_dev *pdev); | ||
362 | |||
363 | #endif /* CONFIG_IWLWIFI_IDI */ | ||
364 | |||
365 | static struct pci_driver iwl_pci_driver = { | 352 | static struct pci_driver iwl_pci_driver = { |
366 | .name = DRV_NAME, | 353 | .name = DRV_NAME, |
367 | .id_table = iwl_hw_card_ids, | 354 | .id_table = iwl_hw_card_ids, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 71c79943e633..401178f44a3b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -311,7 +311,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); | |||
311 | ******************************************************/ | 311 | ******************************************************/ |
312 | void iwl_bg_rx_replenish(struct work_struct *data); | 312 | void iwl_bg_rx_replenish(struct work_struct *data); |
313 | void iwl_irq_tasklet(struct iwl_trans *trans); | 313 | void iwl_irq_tasklet(struct iwl_trans *trans); |
314 | void iwlagn_rx_replenish(struct iwl_trans *trans); | 314 | void iwl_rx_replenish(struct iwl_trans *trans); |
315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | 315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, |
316 | struct iwl_rx_queue *q); | 316 | struct iwl_rx_queue *q); |
317 | 317 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 498372008810..17c8e5d82681 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -35,10 +35,6 @@ | |||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | #include "iwl-op-mode.h" | 36 | #include "iwl-op-mode.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | ||
39 | #include "iwl-amfh.h" | ||
40 | #endif | ||
41 | |||
42 | /****************************************************************************** | 38 | /****************************************************************************** |
43 | * | 39 | * |
44 | * RX path functions | 40 | * RX path functions |
@@ -181,15 +177,15 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
181 | } | 177 | } |
182 | 178 | ||
183 | /** | 179 | /** |
184 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | 180 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr |
185 | */ | 181 | */ |
186 | static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | 182 | static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) |
187 | { | 183 | { |
188 | return cpu_to_le32((u32)(dma_addr >> 8)); | 184 | return cpu_to_le32((u32)(dma_addr >> 8)); |
189 | } | 185 | } |
190 | 186 | ||
191 | /** | 187 | /** |
192 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | 188 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool |
193 | * | 189 | * |
194 | * If there are slots in the RX queue that need to be restocked, | 190 | * If there are slots in the RX queue that need to be restocked, |
195 | * and we have free pre-allocated buffers, fill the ranks as much | 191 | * and we have free pre-allocated buffers, fill the ranks as much |
@@ -199,7 +195,7 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | |||
199 | * also updates the memory address in the firmware to reference the new | 195 | * also updates the memory address in the firmware to reference the new |
200 | * target buffer. | 196 | * target buffer. |
201 | */ | 197 | */ |
202 | static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | 198 | static void iwl_rx_queue_restock(struct iwl_trans *trans) |
203 | { | 199 | { |
204 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 200 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
205 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 201 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -207,6 +203,17 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
207 | struct iwl_rx_mem_buffer *rxb; | 203 | struct iwl_rx_mem_buffer *rxb; |
208 | unsigned long flags; | 204 | unsigned long flags; |
209 | 205 | ||
206 | /* | ||
207 | * If the device isn't enabled - not need to try to add buffers... | ||
208 | * This can happen when we stop the device and still have an interrupt | ||
209 | * pending. We stop the APM before we sync the interrupts / tasklets | ||
210 | * because we have to (see comment there). On the other hand, since | ||
211 | * the APM is stopped, we cannot access the HW (in particular not prph). | ||
212 | * So don't try to restock if the APM has been already stopped. | ||
213 | */ | ||
214 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) | ||
215 | return; | ||
216 | |||
210 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
211 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | 218 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { |
212 | /* The overwritten rxb must be a used one */ | 219 | /* The overwritten rxb must be a used one */ |
@@ -219,7 +226,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
219 | list_del(element); | 226 | list_del(element); |
220 | 227 | ||
221 | /* Point to Rx buffer via next RBD in circular buffer */ | 228 | /* Point to Rx buffer via next RBD in circular buffer */ |
222 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); | 229 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); |
223 | rxq->queue[rxq->write] = rxb; | 230 | rxq->queue[rxq->write] = rxb; |
224 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 231 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
225 | rxq->free_count--; | 232 | rxq->free_count--; |
@@ -230,7 +237,6 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
230 | if (rxq->free_count <= RX_LOW_WATERMARK) | 237 | if (rxq->free_count <= RX_LOW_WATERMARK) |
231 | schedule_work(&trans_pcie->rx_replenish); | 238 | schedule_work(&trans_pcie->rx_replenish); |
232 | 239 | ||
233 | |||
234 | /* If we've added more space for the firmware to place data, tell it. | 240 | /* If we've added more space for the firmware to place data, tell it. |
235 | * Increment device's write pointer in multiples of 8. */ | 241 | * Increment device's write pointer in multiples of 8. */ |
236 | if (rxq->write_actual != (rxq->write & ~0x7)) { | 242 | if (rxq->write_actual != (rxq->write & ~0x7)) { |
@@ -241,15 +247,16 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
241 | } | 247 | } |
242 | } | 248 | } |
243 | 249 | ||
244 | /** | 250 | /* |
245 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | 251 | * iwl_rx_allocate - allocate a page for each used RBD |
246 | * | ||
247 | * When moving to rx_free an SKB is allocated for the slot. | ||
248 | * | 252 | * |
249 | * Also restock the Rx queue via iwl_rx_queue_restock. | 253 | * A used RBD is an Rx buffer that has been given to the stack. To use it again |
250 | * This is called as a scheduled work item (except for during initialization) | 254 | * a page must be allocated and the RBD must point to the page. This function |
255 | * doesn't change the HW pointer but handles the list of pages that is used by | ||
256 | * iwl_rx_queue_restock. The latter function will update the HW to use the newly | ||
257 | * allocated buffers. | ||
251 | */ | 258 | */ |
252 | static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | 259 | static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) |
253 | { | 260 | { |
254 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 261 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
255 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 262 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -328,23 +335,31 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
328 | } | 335 | } |
329 | } | 336 | } |
330 | 337 | ||
331 | void iwlagn_rx_replenish(struct iwl_trans *trans) | 338 | /* |
339 | * iwl_rx_replenish - Move all used buffers from rx_used to rx_free | ||
340 | * | ||
341 | * When moving to rx_free an page is allocated for the slot. | ||
342 | * | ||
343 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
344 | * This is called as a scheduled work item (except for during initialization) | ||
345 | */ | ||
346 | void iwl_rx_replenish(struct iwl_trans *trans) | ||
332 | { | 347 | { |
333 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 348 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
334 | unsigned long flags; | 349 | unsigned long flags; |
335 | 350 | ||
336 | iwlagn_rx_allocate(trans, GFP_KERNEL); | 351 | iwl_rx_allocate(trans, GFP_KERNEL); |
337 | 352 | ||
338 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 353 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
339 | iwlagn_rx_queue_restock(trans); | 354 | iwl_rx_queue_restock(trans); |
340 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 355 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
341 | } | 356 | } |
342 | 357 | ||
343 | static void iwlagn_rx_replenish_now(struct iwl_trans *trans) | 358 | static void iwl_rx_replenish_now(struct iwl_trans *trans) |
344 | { | 359 | { |
345 | iwlagn_rx_allocate(trans, GFP_ATOMIC); | 360 | iwl_rx_allocate(trans, GFP_ATOMIC); |
346 | 361 | ||
347 | iwlagn_rx_queue_restock(trans); | 362 | iwl_rx_queue_restock(trans); |
348 | } | 363 | } |
349 | 364 | ||
350 | void iwl_bg_rx_replenish(struct work_struct *data) | 365 | void iwl_bg_rx_replenish(struct work_struct *data) |
@@ -352,7 +367,7 @@ void iwl_bg_rx_replenish(struct work_struct *data) | |||
352 | struct iwl_trans_pcie *trans_pcie = | 367 | struct iwl_trans_pcie *trans_pcie = |
353 | container_of(data, struct iwl_trans_pcie, rx_replenish); | 368 | container_of(data, struct iwl_trans_pcie, rx_replenish); |
354 | 369 | ||
355 | iwlagn_rx_replenish(trans_pcie->trans); | 370 | iwl_rx_replenish(trans_pcie->trans); |
356 | } | 371 | } |
357 | 372 | ||
358 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | 373 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, |
@@ -530,7 +545,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
530 | count++; | 545 | count++; |
531 | if (count >= 8) { | 546 | if (count >= 8) { |
532 | rxq->read = i; | 547 | rxq->read = i; |
533 | iwlagn_rx_replenish_now(trans); | 548 | iwl_rx_replenish_now(trans); |
534 | count = 0; | 549 | count = 0; |
535 | } | 550 | } |
536 | } | 551 | } |
@@ -539,9 +554,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
539 | /* Backtrack one entry */ | 554 | /* Backtrack one entry */ |
540 | rxq->read = i; | 555 | rxq->read = i; |
541 | if (fill_rx) | 556 | if (fill_rx) |
542 | iwlagn_rx_replenish_now(trans); | 557 | iwl_rx_replenish_now(trans); |
543 | else | 558 | else |
544 | iwlagn_rx_queue_restock(trans); | 559 | iwl_rx_queue_restock(trans); |
545 | } | 560 | } |
546 | 561 | ||
547 | /** | 562 | /** |
@@ -723,11 +738,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
723 | /* Disable periodic interrupt; we use it as just a one-shot. */ | 738 | /* Disable periodic interrupt; we use it as just a one-shot. */ |
724 | iwl_write8(trans, CSR_INT_PERIODIC_REG, | 739 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
725 | CSR_INT_PERIODIC_DIS); | 740 | CSR_INT_PERIODIC_DIS); |
726 | #ifdef CONFIG_IWLWIFI_IDI | 741 | |
727 | iwl_amfh_rx_handler(); | ||
728 | #else | ||
729 | iwl_rx_handle(trans); | 742 | iwl_rx_handle(trans); |
730 | #endif | 743 | |
731 | /* | 744 | /* |
732 | * Enable periodic interrupt in 8 msec only if we received | 745 | * Enable periodic interrupt in 8 msec only if we received |
733 | * real RX interrupt (instead of just periodic int), to catch | 746 | * real RX interrupt (instead of just periodic int), to catch |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 76aa5031f7ba..34aee0688e0d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -216,7 +216,7 @@ static int iwl_rx_init(struct iwl_trans *trans) | |||
216 | rxq->free_count = 0; | 216 | rxq->free_count = 0; |
217 | spin_unlock_irqrestore(&rxq->lock, flags); | 217 | spin_unlock_irqrestore(&rxq->lock, flags); |
218 | 218 | ||
219 | iwlagn_rx_replenish(trans); | 219 | iwl_rx_replenish(trans); |
220 | 220 | ||
221 | iwl_trans_rx_hw_init(trans, rxq); | 221 | iwl_trans_rx_hw_init(trans, rxq); |
222 | 222 | ||
@@ -855,10 +855,8 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
855 | 855 | ||
856 | iwl_op_mode_nic_config(trans->op_mode); | 856 | iwl_op_mode_nic_config(trans->op_mode); |
857 | 857 | ||
858 | #ifndef CONFIG_IWLWIFI_IDI | ||
859 | /* Allocate the RX queue, or reset if it is already allocated */ | 858 | /* Allocate the RX queue, or reset if it is already allocated */ |
860 | iwl_rx_init(trans); | 859 | iwl_rx_init(trans); |
861 | #endif | ||
862 | 860 | ||
863 | /* Allocate or reset and init all Tx and Command queues */ | 861 | /* Allocate or reset and init all Tx and Command queues */ |
864 | if (iwl_tx_init(trans)) | 862 | if (iwl_tx_init(trans)) |
@@ -925,13 +923,10 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans) | |||
925 | /* | 923 | /* |
926 | * ucode | 924 | * ucode |
927 | */ | 925 | */ |
928 | static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | 926 | static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, |
929 | const struct fw_desc *section) | 927 | dma_addr_t phy_addr, u32 byte_cnt) |
930 | { | 928 | { |
931 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 929 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
932 | dma_addr_t phy_addr = section->p_addr; | ||
933 | u32 byte_cnt = section->len; | ||
934 | u32 dst_addr = section->offset; | ||
935 | int ret; | 930 | int ret; |
936 | 931 | ||
937 | trans_pcie->ucode_write_complete = false; | 932 | trans_pcie->ucode_write_complete = false; |
@@ -945,8 +940,8 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | |||
945 | dst_addr); | 940 | dst_addr); |
946 | 941 | ||
947 | iwl_write_direct32(trans, | 942 | iwl_write_direct32(trans, |
948 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | 943 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), |
949 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | 944 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); |
950 | 945 | ||
951 | iwl_write_direct32(trans, | 946 | iwl_write_direct32(trans, |
952 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | 947 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), |
@@ -965,33 +960,64 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | |||
965 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 960 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
966 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 961 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
967 | 962 | ||
968 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", | ||
969 | section_num); | ||
970 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, | 963 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, |
971 | trans_pcie->ucode_write_complete, 5 * HZ); | 964 | trans_pcie->ucode_write_complete, 5 * HZ); |
972 | if (!ret) { | 965 | if (!ret) { |
973 | IWL_ERR(trans, "Could not load the [%d] uCode section\n", | 966 | IWL_ERR(trans, "Failed to load firmware chunk!\n"); |
974 | section_num); | ||
975 | return -ETIMEDOUT; | 967 | return -ETIMEDOUT; |
976 | } | 968 | } |
977 | 969 | ||
978 | return 0; | 970 | return 0; |
979 | } | 971 | } |
980 | 972 | ||
981 | static int iwl_load_given_ucode(struct iwl_trans *trans, | 973 | static int iwl_load_section(struct iwl_trans *trans, u8 section_num, |
982 | const struct fw_img *image) | 974 | const struct fw_desc *section) |
983 | { | 975 | { |
976 | u8 *v_addr; | ||
977 | dma_addr_t p_addr; | ||
978 | u32 offset; | ||
984 | int ret = 0; | 979 | int ret = 0; |
985 | int i; | ||
986 | 980 | ||
987 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | 981 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", |
988 | if (!image->sec[i].p_addr) | 982 | section_num); |
989 | break; | ||
990 | 983 | ||
991 | ret = iwl_load_section(trans, i, &image->sec[i]); | 984 | v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); |
992 | if (ret) | 985 | if (!v_addr) |
993 | return ret; | 986 | return -ENOMEM; |
987 | |||
988 | for (offset = 0; offset < section->len; offset += PAGE_SIZE) { | ||
989 | u32 copy_size; | ||
990 | |||
991 | copy_size = min_t(u32, PAGE_SIZE, section->len - offset); | ||
992 | |||
993 | memcpy(v_addr, (u8 *)section->data + offset, copy_size); | ||
994 | ret = iwl_load_firmware_chunk(trans, section->offset + offset, | ||
995 | p_addr, copy_size); | ||
996 | if (ret) { | ||
997 | IWL_ERR(trans, | ||
998 | "Could not load the [%d] uCode section\n", | ||
999 | section_num); | ||
1000 | break; | ||
994 | } | 1001 | } |
1002 | } | ||
1003 | |||
1004 | dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | static int iwl_load_given_ucode(struct iwl_trans *trans, | ||
1009 | const struct fw_img *image) | ||
1010 | { | ||
1011 | int i, ret = 0; | ||
1012 | |||
1013 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | ||
1014 | if (!image->sec[i].data) | ||
1015 | break; | ||
1016 | |||
1017 | ret = iwl_load_section(trans, i, &image->sec[i]); | ||
1018 | if (ret) | ||
1019 | return ret; | ||
1020 | } | ||
995 | 1021 | ||
996 | /* Remove all resets to allow NIC to operate */ | 1022 | /* Remove all resets to allow NIC to operate */ |
997 | iwl_write32(trans, CSR_RESET, 0); | 1023 | iwl_write32(trans, CSR_RESET, 0); |
@@ -1184,9 +1210,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1184 | */ | 1210 | */ |
1185 | if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { | 1211 | if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { |
1186 | iwl_trans_tx_stop(trans); | 1212 | iwl_trans_tx_stop(trans); |
1187 | #ifndef CONFIG_IWLWIFI_IDI | ||
1188 | iwl_trans_rx_stop(trans); | 1213 | iwl_trans_rx_stop(trans); |
1189 | #endif | 1214 | |
1190 | /* Power-down device's busmaster DMA clocks */ | 1215 | /* Power-down device's busmaster DMA clocks */ |
1191 | iwl_write_prph(trans, APMG_CLK_DIS_REG, | 1216 | iwl_write_prph(trans, APMG_CLK_DIS_REG, |
1192 | APMG_CLK_VAL_DMA_CLK_RQT); | 1217 | APMG_CLK_VAL_DMA_CLK_RQT); |
@@ -1457,14 +1482,16 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | |||
1457 | bool hw_rfkill; | 1482 | bool hw_rfkill; |
1458 | unsigned long flags; | 1483 | unsigned long flags; |
1459 | 1484 | ||
1485 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
1486 | iwl_disable_interrupts(trans); | ||
1487 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
1488 | |||
1460 | iwl_apm_stop(trans); | 1489 | iwl_apm_stop(trans); |
1461 | 1490 | ||
1462 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1491 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
1463 | iwl_disable_interrupts(trans); | 1492 | iwl_disable_interrupts(trans); |
1464 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1493 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1465 | 1494 | ||
1466 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1467 | |||
1468 | if (!op_mode_leaving) { | 1495 | if (!op_mode_leaving) { |
1469 | /* | 1496 | /* |
1470 | * Even if we stop the HW, we still want the RF kill | 1497 | * Even if we stop the HW, we still want the RF kill |
@@ -1552,9 +1579,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1552 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1579 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1553 | 1580 | ||
1554 | iwl_trans_pcie_tx_free(trans); | 1581 | iwl_trans_pcie_tx_free(trans); |
1555 | #ifndef CONFIG_IWLWIFI_IDI | ||
1556 | iwl_trans_pcie_rx_free(trans); | 1582 | iwl_trans_pcie_rx_free(trans); |
1557 | #endif | 1583 | |
1558 | if (trans_pcie->irq_requested == true) { | 1584 | if (trans_pcie->irq_requested == true) { |
1559 | free_irq(trans_pcie->irq, trans); | 1585 | free_irq(trans_pcie->irq, trans); |
1560 | iwl_free_isr_ict(trans); | 1586 | iwl_free_isr_ict(trans); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 9d45b3bb974c..429ca3215fdb 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -2056,7 +2056,7 @@ failed: | |||
2056 | mac80211_hwsim_free(); | 2056 | mac80211_hwsim_free(); |
2057 | return err; | 2057 | return err; |
2058 | } | 2058 | } |
2059 | 2059 | module_init(init_mac80211_hwsim); | |
2060 | 2060 | ||
2061 | static void __exit exit_mac80211_hwsim(void) | 2061 | static void __exit exit_mac80211_hwsim(void) |
2062 | { | 2062 | { |
@@ -2067,7 +2067,4 @@ static void __exit exit_mac80211_hwsim(void) | |||
2067 | mac80211_hwsim_free(); | 2067 | mac80211_hwsim_free(); |
2068 | unregister_netdev(hwsim_mon); | 2068 | unregister_netdev(hwsim_mon); |
2069 | } | 2069 | } |
2070 | |||
2071 | |||
2072 | module_init(init_mac80211_hwsim); | ||
2073 | module_exit(exit_mac80211_hwsim); | 2070 | module_exit(exit_mac80211_hwsim); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b9f7b3e6912d..c24824f8c8a1 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1502,6 +1502,12 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1502 | 1502 | ||
1503 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); | 1503 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); |
1504 | 1504 | ||
1505 | if (atomic_read(&priv->wmm.tx_pkts_queued) >= | ||
1506 | MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) { | ||
1507 | dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n"); | ||
1508 | return -EBUSY; | ||
1509 | } | ||
1510 | |||
1505 | priv->scan_request = request; | 1511 | priv->scan_request = request; |
1506 | 1512 | ||
1507 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), | 1513 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), |
@@ -1630,7 +1636,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
1630 | * create a new virtual interface with the given name | 1636 | * create a new virtual interface with the given name |
1631 | */ | 1637 | */ |
1632 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | 1638 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, |
1633 | char *name, | 1639 | const char *name, |
1634 | enum nl80211_iftype type, | 1640 | enum nl80211_iftype type, |
1635 | u32 *flags, | 1641 | u32 *flags, |
1636 | struct vif_params *params) | 1642 | struct vif_params *params) |
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index 1d8dd003e396..fa3a80fb8c01 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -160,7 +160,7 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, | |||
160 | u16 len; | 160 | u16 len; |
161 | int ret; | 161 | int ret; |
162 | 162 | ||
163 | ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 163 | ap_custom_ie = kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL); |
164 | if (!ap_custom_ie) | 164 | if (!ap_custom_ie) |
165 | return -ENOMEM; | 165 | return -ENOMEM; |
166 | 166 | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 9c1549ee4c09..b2ba262f8a13 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -118,6 +118,7 @@ static void scan_delay_timer_fn(unsigned long data) | |||
118 | 118 | ||
119 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | 119 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, |
120 | true); | 120 | true); |
121 | queue_work(adapter->workqueue, &adapter->main_work); | ||
121 | goto done; | 122 | goto done; |
122 | } | 123 | } |
123 | } else { | 124 | } else { |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 12ceea47b4b4..90b64b015447 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -91,6 +91,8 @@ enum { | |||
91 | #define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10 | 91 | #define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10 |
92 | #define MWIFIEX_SCAN_DELAY_MSEC 20 | 92 | #define MWIFIEX_SCAN_DELAY_MSEC 20 |
93 | 93 | ||
94 | #define MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN 2 | ||
95 | |||
94 | #define RSN_GTK_OUI_OFFSET 2 | 96 | #define RSN_GTK_OUI_OFFSET 2 |
95 | 97 | ||
96 | #define MWIFIEX_OUI_NOT_PRESENT 0 | 98 | #define MWIFIEX_OUI_NOT_PRESENT 0 |
@@ -1031,7 +1033,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | |||
1031 | struct mwifiex_bssdescriptor *bss_desc); | 1033 | struct mwifiex_bssdescriptor *bss_desc); |
1032 | 1034 | ||
1033 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | 1035 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, |
1034 | char *name, | 1036 | const char *name, |
1035 | enum nl80211_iftype type, | 1037 | enum nl80211_iftype type, |
1036 | u32 *flags, | 1038 | u32 *flags, |
1037 | struct vif_params *params); | 1039 | struct vif_params *params); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index d7ad2d4a069f..731562f026f5 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -26,6 +26,9 @@ | |||
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "cfg80211.h" | 27 | #include "cfg80211.h" |
28 | 28 | ||
29 | static int disconnect_on_suspend = 1; | ||
30 | module_param(disconnect_on_suspend, int, 0644); | ||
31 | |||
29 | /* | 32 | /* |
30 | * Copies the multicast address list from device to driver. | 33 | * Copies the multicast address list from device to driver. |
31 | * | 34 | * |
@@ -448,6 +451,16 @@ EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); | |||
448 | int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | 451 | int mwifiex_enable_hs(struct mwifiex_adapter *adapter) |
449 | { | 452 | { |
450 | struct mwifiex_ds_hs_cfg hscfg; | 453 | struct mwifiex_ds_hs_cfg hscfg; |
454 | struct mwifiex_private *priv; | ||
455 | int i; | ||
456 | |||
457 | if (disconnect_on_suspend) { | ||
458 | for (i = 0; i < adapter->priv_num; i++) { | ||
459 | priv = adapter->priv[i]; | ||
460 | if (priv) | ||
461 | mwifiex_deauthenticate(priv, NULL); | ||
462 | } | ||
463 | } | ||
451 | 464 | ||
452 | if (adapter->hs_activated) { | 465 | if (adapter->hs_activated) { |
453 | dev_dbg(adapter->dev, "cmd: HS Already actived\n"); | 466 | dev_dbg(adapter->dev, "cmd: HS Already actived\n"); |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 2969d5321ca6..aadda99989c0 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -515,6 +515,17 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
515 | if (modparam_nohwcrypt) | 515 | if (modparam_nohwcrypt) |
516 | return -EOPNOTSUPP; | 516 | return -EOPNOTSUPP; |
517 | 517 | ||
518 | if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { | ||
519 | /* | ||
520 | * Unfortunately most/all firmwares are trying to decrypt | ||
521 | * incoming management frames if a suitable key can be found. | ||
522 | * However, in doing so the data in these frames gets | ||
523 | * corrupted. So, we can't have firmware supported crypto | ||
524 | * offload in this case. | ||
525 | */ | ||
526 | return -EOPNOTSUPP; | ||
527 | } | ||
528 | |||
518 | mutex_lock(&priv->conf_mutex); | 529 | mutex_lock(&priv->conf_mutex); |
519 | if (cmd == SET_KEY) { | 530 | if (cmd == SET_KEY) { |
520 | switch (key->cipher) { | 531 | switch (key->cipher) { |
@@ -738,6 +749,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
738 | IEEE80211_HW_SIGNAL_DBM | | 749 | IEEE80211_HW_SIGNAL_DBM | |
739 | IEEE80211_HW_SUPPORTS_PS | | 750 | IEEE80211_HW_SUPPORTS_PS | |
740 | IEEE80211_HW_PS_NULLFUNC_STACK | | 751 | IEEE80211_HW_PS_NULLFUNC_STACK | |
752 | IEEE80211_HW_MFP_CAPABLE | | ||
741 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | 753 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; |
742 | 754 | ||
743 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 755 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 6458ab87717b..e3a2d9070cf6 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1789,7 +1789,6 @@ static const struct data_queue_desc rt2400pci_queue_atim = { | |||
1789 | 1789 | ||
1790 | static const struct rt2x00_ops rt2400pci_ops = { | 1790 | static const struct rt2x00_ops rt2400pci_ops = { |
1791 | .name = KBUILD_MODNAME, | 1791 | .name = KBUILD_MODNAME, |
1792 | .max_sta_intf = 1, | ||
1793 | .max_ap_intf = 1, | 1792 | .max_ap_intf = 1, |
1794 | .eeprom_size = EEPROM_SIZE, | 1793 | .eeprom_size = EEPROM_SIZE, |
1795 | .rf_size = RF_SIZE, | 1794 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 68bca1456cda..479d756e275b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -2081,7 +2081,6 @@ static const struct data_queue_desc rt2500pci_queue_atim = { | |||
2081 | 2081 | ||
2082 | static const struct rt2x00_ops rt2500pci_ops = { | 2082 | static const struct rt2x00_ops rt2500pci_ops = { |
2083 | .name = KBUILD_MODNAME, | 2083 | .name = KBUILD_MODNAME, |
2084 | .max_sta_intf = 1, | ||
2085 | .max_ap_intf = 1, | 2084 | .max_ap_intf = 1, |
2086 | .eeprom_size = EEPROM_SIZE, | 2085 | .eeprom_size = EEPROM_SIZE, |
2087 | .rf_size = RF_SIZE, | 2086 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index f95b5516c50a..a12e84f892be 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1896,7 +1896,6 @@ static const struct data_queue_desc rt2500usb_queue_atim = { | |||
1896 | 1896 | ||
1897 | static const struct rt2x00_ops rt2500usb_ops = { | 1897 | static const struct rt2x00_ops rt2500usb_ops = { |
1898 | .name = KBUILD_MODNAME, | 1898 | .name = KBUILD_MODNAME, |
1899 | .max_sta_intf = 1, | ||
1900 | .max_ap_intf = 1, | 1899 | .max_ap_intf = 1, |
1901 | .eeprom_size = EEPROM_SIZE, | 1900 | .eeprom_size = EEPROM_SIZE, |
1902 | .rf_size = RF_SIZE, | 1901 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9e09367c9739..540c94f8505a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1763,36 +1763,15 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, | |||
1763 | 1763 | ||
1764 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | 1764 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); |
1765 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); | 1765 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); |
1766 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, | ||
1767 | rt2x00dev->default_ant.rx_chain_num <= 1); | ||
1768 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, | ||
1769 | rt2x00dev->default_ant.rx_chain_num <= 2); | ||
1766 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); | 1770 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); |
1767 | if (rt2x00_rt(rt2x00dev, RT3390)) { | 1771 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, |
1768 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, | 1772 | rt2x00dev->default_ant.tx_chain_num <= 1); |
1769 | rt2x00dev->default_ant.rx_chain_num == 1); | 1773 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, |
1770 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, | 1774 | rt2x00dev->default_ant.tx_chain_num <= 2); |
1771 | rt2x00dev->default_ant.tx_chain_num == 1); | ||
1772 | } else { | ||
1773 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); | ||
1774 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); | ||
1775 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | ||
1776 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | ||
1777 | |||
1778 | switch (rt2x00dev->default_ant.tx_chain_num) { | ||
1779 | case 1: | ||
1780 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); | ||
1781 | /* fall through */ | ||
1782 | case 2: | ||
1783 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); | ||
1784 | break; | ||
1785 | } | ||
1786 | |||
1787 | switch (rt2x00dev->default_ant.rx_chain_num) { | ||
1788 | case 1: | ||
1789 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); | ||
1790 | /* fall through */ | ||
1791 | case 2: | ||
1792 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); | ||
1793 | break; | ||
1794 | } | ||
1795 | } | ||
1796 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | 1775 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); |
1797 | 1776 | ||
1798 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | 1777 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); |
@@ -2896,23 +2875,32 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); | |||
2896 | 2875 | ||
2897 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | 2876 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) |
2898 | { | 2877 | { |
2878 | u8 vgc; | ||
2879 | |||
2899 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 2880 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
2900 | if (rt2x00_rt(rt2x00dev, RT3070) || | 2881 | if (rt2x00_rt(rt2x00dev, RT3070) || |
2901 | rt2x00_rt(rt2x00dev, RT3071) || | 2882 | rt2x00_rt(rt2x00dev, RT3071) || |
2902 | rt2x00_rt(rt2x00dev, RT3090) || | 2883 | rt2x00_rt(rt2x00dev, RT3090) || |
2903 | rt2x00_rt(rt2x00dev, RT3290) || | 2884 | rt2x00_rt(rt2x00dev, RT3290) || |
2904 | rt2x00_rt(rt2x00dev, RT3390) || | 2885 | rt2x00_rt(rt2x00dev, RT3390) || |
2886 | rt2x00_rt(rt2x00dev, RT3572) || | ||
2905 | rt2x00_rt(rt2x00dev, RT5390) || | 2887 | rt2x00_rt(rt2x00dev, RT5390) || |
2906 | rt2x00_rt(rt2x00dev, RT5392)) | 2888 | rt2x00_rt(rt2x00dev, RT5392)) |
2907 | return 0x1c + (2 * rt2x00dev->lna_gain); | 2889 | vgc = 0x1c + (2 * rt2x00dev->lna_gain); |
2908 | else | 2890 | else |
2909 | return 0x2e + rt2x00dev->lna_gain; | 2891 | vgc = 0x2e + rt2x00dev->lna_gain; |
2892 | } else { /* 5GHZ band */ | ||
2893 | if (rt2x00_rt(rt2x00dev, RT3572)) | ||
2894 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; | ||
2895 | else { | ||
2896 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | ||
2897 | vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; | ||
2898 | else | ||
2899 | vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3; | ||
2900 | } | ||
2910 | } | 2901 | } |
2911 | 2902 | ||
2912 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | 2903 | return vgc; |
2913 | return 0x32 + (rt2x00dev->lna_gain * 5) / 3; | ||
2914 | else | ||
2915 | return 0x3a + (rt2x00dev->lna_gain * 5) / 3; | ||
2916 | } | 2904 | } |
2917 | 2905 | ||
2918 | static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | 2906 | static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, |
@@ -3081,7 +3069,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
3081 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 3069 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
3082 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3070 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3083 | } else if (rt2x00_rt(rt2x00dev, RT5390) || | 3071 | } else if (rt2x00_rt(rt2x00dev, RT5390) || |
3084 | rt2x00_rt(rt2x00dev, RT5392)) { | 3072 | rt2x00_rt(rt2x00dev, RT5392)) { |
3085 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); | 3073 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); |
3086 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3074 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3087 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 3075 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -3526,6 +3514,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3526 | } else if (rt2800_is_305x_soc(rt2x00dev)) { | 3514 | } else if (rt2800_is_305x_soc(rt2x00dev)) { |
3527 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 3515 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
3528 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 3516 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
3517 | } else if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3518 | rt2800_bbp_write(rt2x00dev, 74, 0x0b); | ||
3519 | rt2800_bbp_write(rt2x00dev, 79, 0x18); | ||
3520 | rt2800_bbp_write(rt2x00dev, 80, 0x09); | ||
3521 | rt2800_bbp_write(rt2x00dev, 81, 0x33); | ||
3529 | } else if (rt2x00_rt(rt2x00dev, RT3352)) { | 3522 | } else if (rt2x00_rt(rt2x00dev, RT3352)) { |
3530 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 3523 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
3531 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 3524 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
@@ -3534,13 +3527,6 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3534 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | 3527 | rt2800_bbp_write(rt2x00dev, 81, 0x37); |
3535 | } | 3528 | } |
3536 | 3529 | ||
3537 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3538 | rt2800_bbp_write(rt2x00dev, 74, 0x0b); | ||
3539 | rt2800_bbp_write(rt2x00dev, 79, 0x18); | ||
3540 | rt2800_bbp_write(rt2x00dev, 80, 0x09); | ||
3541 | rt2800_bbp_write(rt2x00dev, 81, 0x33); | ||
3542 | } | ||
3543 | |||
3544 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 3530 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
3545 | if (rt2x00_rt(rt2x00dev, RT3290) || | 3531 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3546 | rt2x00_rt(rt2x00dev, RT5390) || | 3532 | rt2x00_rt(rt2x00dev, RT5390) || |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 391e08fa054b..27829e1e2e38 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1088,7 +1088,6 @@ static const struct data_queue_desc rt2800pci_queue_bcn = { | |||
1088 | static const struct rt2x00_ops rt2800pci_ops = { | 1088 | static const struct rt2x00_ops rt2800pci_ops = { |
1089 | .name = KBUILD_MODNAME, | 1089 | .name = KBUILD_MODNAME, |
1090 | .drv_data_size = sizeof(struct rt2800_drv_data), | 1090 | .drv_data_size = sizeof(struct rt2800_drv_data), |
1091 | .max_sta_intf = 1, | ||
1092 | .max_ap_intf = 8, | 1091 | .max_ap_intf = 8, |
1093 | .eeprom_size = EEPROM_SIZE, | 1092 | .eeprom_size = EEPROM_SIZE, |
1094 | .rf_size = RF_SIZE, | 1093 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 603b65d6f28b..c9e9370eb789 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -870,7 +870,6 @@ static const struct data_queue_desc rt2800usb_queue_bcn = { | |||
870 | static const struct rt2x00_ops rt2800usb_ops = { | 870 | static const struct rt2x00_ops rt2800usb_ops = { |
871 | .name = KBUILD_MODNAME, | 871 | .name = KBUILD_MODNAME, |
872 | .drv_data_size = sizeof(struct rt2800_drv_data), | 872 | .drv_data_size = sizeof(struct rt2800_drv_data), |
873 | .max_sta_intf = 1, | ||
874 | .max_ap_intf = 8, | 873 | .max_ap_intf = 8, |
875 | .eeprom_size = EEPROM_SIZE, | 874 | .eeprom_size = EEPROM_SIZE, |
876 | .rf_size = RF_SIZE, | 875 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 49375c86c334..0751b35ef6dc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -656,7 +656,6 @@ struct rt2x00lib_ops { | |||
656 | struct rt2x00_ops { | 656 | struct rt2x00_ops { |
657 | const char *name; | 657 | const char *name; |
658 | const unsigned int drv_data_size; | 658 | const unsigned int drv_data_size; |
659 | const unsigned int max_sta_intf; | ||
660 | const unsigned int max_ap_intf; | 659 | const unsigned int max_ap_intf; |
661 | const unsigned int eeprom_size; | 660 | const unsigned int eeprom_size; |
662 | const unsigned int rf_size; | 661 | const unsigned int rf_size; |
@@ -742,6 +741,14 @@ enum rt2x00_capability_flags { | |||
742 | }; | 741 | }; |
743 | 742 | ||
744 | /* | 743 | /* |
744 | * Interface combinations | ||
745 | */ | ||
746 | enum { | ||
747 | IF_COMB_AP = 0, | ||
748 | NUM_IF_COMB, | ||
749 | }; | ||
750 | |||
751 | /* | ||
745 | * rt2x00 device structure. | 752 | * rt2x00 device structure. |
746 | */ | 753 | */ |
747 | struct rt2x00_dev { | 754 | struct rt2x00_dev { |
@@ -868,6 +875,12 @@ struct rt2x00_dev { | |||
868 | unsigned int intf_beaconing; | 875 | unsigned int intf_beaconing; |
869 | 876 | ||
870 | /* | 877 | /* |
878 | * Interface combinations | ||
879 | */ | ||
880 | struct ieee80211_iface_limit if_limits_ap; | ||
881 | struct ieee80211_iface_combination if_combinations[NUM_IF_COMB]; | ||
882 | |||
883 | /* | ||
871 | * Link quality | 884 | * Link quality |
872 | */ | 885 | */ |
873 | struct link link; | 886 | struct link link; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 10cf67267775..69097d1faeb6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1118,6 +1118,34 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) | |||
1118 | rt2x00dev->intf_associated = 0; | 1118 | rt2x00dev->intf_associated = 0; |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) | ||
1122 | { | ||
1123 | struct ieee80211_iface_limit *if_limit; | ||
1124 | struct ieee80211_iface_combination *if_combination; | ||
1125 | |||
1126 | /* | ||
1127 | * Build up AP interface limits structure. | ||
1128 | */ | ||
1129 | if_limit = &rt2x00dev->if_limits_ap; | ||
1130 | if_limit->max = rt2x00dev->ops->max_ap_intf; | ||
1131 | if_limit->types = BIT(NL80211_IFTYPE_AP); | ||
1132 | |||
1133 | /* | ||
1134 | * Build up AP interface combinations structure. | ||
1135 | */ | ||
1136 | if_combination = &rt2x00dev->if_combinations[IF_COMB_AP]; | ||
1137 | if_combination->limits = if_limit; | ||
1138 | if_combination->n_limits = 1; | ||
1139 | if_combination->max_interfaces = if_limit->max; | ||
1140 | if_combination->num_different_channels = 1; | ||
1141 | |||
1142 | /* | ||
1143 | * Finally, specify the possible combinations to mac80211. | ||
1144 | */ | ||
1145 | rt2x00dev->hw->wiphy->iface_combinations = rt2x00dev->if_combinations; | ||
1146 | rt2x00dev->hw->wiphy->n_iface_combinations = 1; | ||
1147 | } | ||
1148 | |||
1121 | /* | 1149 | /* |
1122 | * driver allocation handlers. | 1150 | * driver allocation handlers. |
1123 | */ | 1151 | */ |
@@ -1126,6 +1154,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1126 | int retval = -ENOMEM; | 1154 | int retval = -ENOMEM; |
1127 | 1155 | ||
1128 | /* | 1156 | /* |
1157 | * Set possible interface combinations. | ||
1158 | */ | ||
1159 | rt2x00lib_set_if_combinations(rt2x00dev); | ||
1160 | |||
1161 | /* | ||
1129 | * Allocate the driver data memory, if necessary. | 1162 | * Allocate the driver data memory, if necessary. |
1130 | */ | 1163 | */ |
1131 | if (rt2x00dev->ops->drv_data_size > 0) { | 1164 | if (rt2x00dev->ops->drv_data_size > 0) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c3d0f2f87b69..98a9e48f8e4a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -214,46 +214,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
214 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | 214 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
215 | return -ENODEV; | 215 | return -ENODEV; |
216 | 216 | ||
217 | switch (vif->type) { | ||
218 | case NL80211_IFTYPE_AP: | ||
219 | /* | ||
220 | * We don't support mixed combinations of | ||
221 | * sta and ap interfaces. | ||
222 | */ | ||
223 | if (rt2x00dev->intf_sta_count) | ||
224 | return -ENOBUFS; | ||
225 | |||
226 | /* | ||
227 | * Check if we exceeded the maximum amount | ||
228 | * of supported interfaces. | ||
229 | */ | ||
230 | if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) | ||
231 | return -ENOBUFS; | ||
232 | |||
233 | break; | ||
234 | case NL80211_IFTYPE_STATION: | ||
235 | case NL80211_IFTYPE_ADHOC: | ||
236 | case NL80211_IFTYPE_MESH_POINT: | ||
237 | case NL80211_IFTYPE_WDS: | ||
238 | /* | ||
239 | * We don't support mixed combinations of | ||
240 | * sta and ap interfaces. | ||
241 | */ | ||
242 | if (rt2x00dev->intf_ap_count) | ||
243 | return -ENOBUFS; | ||
244 | |||
245 | /* | ||
246 | * Check if we exceeded the maximum amount | ||
247 | * of supported interfaces. | ||
248 | */ | ||
249 | if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) | ||
250 | return -ENOBUFS; | ||
251 | |||
252 | break; | ||
253 | default: | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | /* | 217 | /* |
258 | * Loop through all beacon queues to find a free | 218 | * Loop through all beacon queues to find a free |
259 | * entry. Since there are as much beacon entries | 219 | * entry. Since there are as much beacon entries |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2673e058caaf..d6582a2fa353 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -3045,7 +3045,6 @@ static const struct data_queue_desc rt61pci_queue_bcn = { | |||
3045 | 3045 | ||
3046 | static const struct rt2x00_ops rt61pci_ops = { | 3046 | static const struct rt2x00_ops rt61pci_ops = { |
3047 | .name = KBUILD_MODNAME, | 3047 | .name = KBUILD_MODNAME, |
3048 | .max_sta_intf = 1, | ||
3049 | .max_ap_intf = 4, | 3048 | .max_ap_intf = 4, |
3050 | .eeprom_size = EEPROM_SIZE, | 3049 | .eeprom_size = EEPROM_SIZE, |
3051 | .rf_size = RF_SIZE, | 3050 | .rf_size = RF_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index cfa9f37cccc2..e5eb43b3eee7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2382,7 +2382,6 @@ static const struct data_queue_desc rt73usb_queue_bcn = { | |||
2382 | 2382 | ||
2383 | static const struct rt2x00_ops rt73usb_ops = { | 2383 | static const struct rt2x00_ops rt73usb_ops = { |
2384 | .name = KBUILD_MODNAME, | 2384 | .name = KBUILD_MODNAME, |
2385 | .max_sta_intf = 1, | ||
2386 | .max_ap_intf = 4, | 2385 | .max_ap_intf = 4, |
2387 | .eeprom_size = EEPROM_SIZE, | 2386 | .eeprom_size = EEPROM_SIZE, |
2388 | .rf_size = RF_SIZE, | 2387 | .rf_size = RF_SIZE, |