diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 404 |
1 files changed, 171 insertions, 233 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7205a936ec74..14c44df584d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -44,8 +44,9 @@ | |||
44 | #include "b43.h" | 44 | #include "b43.h" |
45 | #include "main.h" | 45 | #include "main.h" |
46 | #include "debugfs.h" | 46 | #include "debugfs.h" |
47 | #include "phy.h" | 47 | #include "phy_common.h" |
48 | #include "nphy.h" | 48 | #include "phy_g.h" |
49 | #include "phy_n.h" | ||
49 | #include "dma.h" | 50 | #include "dma.h" |
50 | #include "pio.h" | 51 | #include "pio.h" |
51 | #include "sysfs.h" | 52 | #include "sysfs.h" |
@@ -814,7 +815,7 @@ void b43_dummy_transmission(struct b43_wldev *dev) | |||
814 | break; | 815 | break; |
815 | udelay(10); | 816 | udelay(10); |
816 | } | 817 | } |
817 | for (i = 0x00; i < 0x0A; i++) { | 818 | for (i = 0x00; i < 0x19; i++) { |
818 | value = b43_read16(dev, 0x0690); | 819 | value = b43_read16(dev, 0x0690); |
819 | if (!(value & 0x0100)) | 820 | if (!(value & 0x0100)) |
820 | break; | 821 | break; |
@@ -1051,23 +1052,6 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) | |||
1051 | } | 1052 | } |
1052 | } | 1053 | } |
1053 | 1054 | ||
1054 | /* Turn the Analog ON/OFF */ | ||
1055 | static void b43_switch_analog(struct b43_wldev *dev, int on) | ||
1056 | { | ||
1057 | switch (dev->phy.type) { | ||
1058 | case B43_PHYTYPE_A: | ||
1059 | case B43_PHYTYPE_G: | ||
1060 | b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); | ||
1061 | break; | ||
1062 | case B43_PHYTYPE_N: | ||
1063 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, | ||
1064 | on ? 0 : 0x7FFF); | ||
1065 | break; | ||
1066 | default: | ||
1067 | B43_WARN_ON(1); | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) | 1055 | void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) |
1072 | { | 1056 | { |
1073 | u32 tmslow; | 1057 | u32 tmslow; |
@@ -1090,8 +1074,12 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) | |||
1090 | ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ | 1074 | ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ |
1091 | msleep(1); | 1075 | msleep(1); |
1092 | 1076 | ||
1093 | /* Turn Analog ON */ | 1077 | /* Turn Analog ON, but only if we already know the PHY-type. |
1094 | b43_switch_analog(dev, 1); | 1078 | * This protects against very early setup where we don't know the |
1079 | * PHY-type, yet. wireless_core_reset will be called once again later, | ||
1080 | * when we know the PHY-type. */ | ||
1081 | if (dev->phy.ops) | ||
1082 | dev->phy.ops->switch_analog(dev, 1); | ||
1095 | 1083 | ||
1096 | macctl = b43_read32(dev, B43_MMIO_MACCTL); | 1084 | macctl = b43_read32(dev, B43_MMIO_MACCTL); |
1097 | macctl &= ~B43_MACCTL_GMODE; | 1085 | macctl &= ~B43_MACCTL_GMODE; |
@@ -1174,6 +1162,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | |||
1174 | { | 1162 | { |
1175 | /* Top half of Link Quality calculation. */ | 1163 | /* Top half of Link Quality calculation. */ |
1176 | 1164 | ||
1165 | if (dev->phy.type != B43_PHYTYPE_G) | ||
1166 | return; | ||
1177 | if (dev->noisecalc.calculation_running) | 1167 | if (dev->noisecalc.calculation_running) |
1178 | return; | 1168 | return; |
1179 | dev->noisecalc.calculation_running = 1; | 1169 | dev->noisecalc.calculation_running = 1; |
@@ -1184,7 +1174,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | |||
1184 | 1174 | ||
1185 | static void handle_irq_noise(struct b43_wldev *dev) | 1175 | static void handle_irq_noise(struct b43_wldev *dev) |
1186 | { | 1176 | { |
1187 | struct b43_phy *phy = &dev->phy; | 1177 | struct b43_phy_g *phy = dev->phy.g; |
1188 | u16 tmp; | 1178 | u16 tmp; |
1189 | u8 noise[4]; | 1179 | u8 noise[4]; |
1190 | u8 i, j; | 1180 | u8 i, j; |
@@ -1192,6 +1182,9 @@ static void handle_irq_noise(struct b43_wldev *dev) | |||
1192 | 1182 | ||
1193 | /* Bottom half of Link Quality calculation. */ | 1183 | /* Bottom half of Link Quality calculation. */ |
1194 | 1184 | ||
1185 | if (dev->phy.type != B43_PHYTYPE_G) | ||
1186 | return; | ||
1187 | |||
1195 | /* Possible race condition: It might be possible that the user | 1188 | /* Possible race condition: It might be possible that the user |
1196 | * changed to a different channel in the meantime since we | 1189 | * changed to a different channel in the meantime since we |
1197 | * started the calculation. We ignore that fact, since it's | 1190 | * started the calculation. We ignore that fact, since it's |
@@ -1251,13 +1244,13 @@ generate_new: | |||
1251 | 1244 | ||
1252 | static void handle_irq_tbtt_indication(struct b43_wldev *dev) | 1245 | static void handle_irq_tbtt_indication(struct b43_wldev *dev) |
1253 | { | 1246 | { |
1254 | if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) { | 1247 | if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) { |
1255 | ///TODO: PS TBTT | 1248 | ///TODO: PS TBTT |
1256 | } else { | 1249 | } else { |
1257 | if (1 /*FIXME: the last PSpoll frame was sent successfully */ ) | 1250 | if (1 /*FIXME: the last PSpoll frame was sent successfully */ ) |
1258 | b43_power_saving_ctl_bits(dev, 0); | 1251 | b43_power_saving_ctl_bits(dev, 0); |
1259 | } | 1252 | } |
1260 | if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) | 1253 | if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) |
1261 | dev->dfq_valid = 1; | 1254 | dev->dfq_valid = 1; |
1262 | } | 1255 | } |
1263 | 1256 | ||
@@ -1606,8 +1599,8 @@ static void handle_irq_beacon(struct b43_wldev *dev) | |||
1606 | struct b43_wl *wl = dev->wl; | 1599 | struct b43_wl *wl = dev->wl; |
1607 | u32 cmd, beacon0_valid, beacon1_valid; | 1600 | u32 cmd, beacon0_valid, beacon1_valid; |
1608 | 1601 | ||
1609 | if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) && | 1602 | if (!b43_is_mode(wl, NL80211_IFTYPE_AP) && |
1610 | !b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | 1603 | !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) |
1611 | return; | 1604 | return; |
1612 | 1605 | ||
1613 | /* This is the bottom half of the asynchronous beacon update. */ | 1606 | /* This is the bottom half of the asynchronous beacon update. */ |
@@ -2575,10 +2568,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev) | |||
2575 | ctl &= ~B43_MACCTL_BEACPROMISC; | 2568 | ctl &= ~B43_MACCTL_BEACPROMISC; |
2576 | ctl |= B43_MACCTL_INFRA; | 2569 | ctl |= B43_MACCTL_INFRA; |
2577 | 2570 | ||
2578 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || | 2571 | if (b43_is_mode(wl, NL80211_IFTYPE_AP) || |
2579 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | 2572 | b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) |
2580 | ctl |= B43_MACCTL_AP; | 2573 | ctl |= B43_MACCTL_AP; |
2581 | else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) | 2574 | else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) |
2582 | ctl &= ~B43_MACCTL_INFRA; | 2575 | ctl &= ~B43_MACCTL_INFRA; |
2583 | 2576 | ||
2584 | if (wl->filter_flags & FIF_CONTROL) | 2577 | if (wl->filter_flags & FIF_CONTROL) |
@@ -2688,9 +2681,8 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) | |||
2688 | /* This is the opposite of b43_chip_init() */ | 2681 | /* This is the opposite of b43_chip_init() */ |
2689 | static void b43_chip_exit(struct b43_wldev *dev) | 2682 | static void b43_chip_exit(struct b43_wldev *dev) |
2690 | { | 2683 | { |
2691 | b43_radio_turn_off(dev, 1); | 2684 | b43_phy_exit(dev); |
2692 | b43_gpio_cleanup(dev); | 2685 | b43_gpio_cleanup(dev); |
2693 | b43_lo_g_cleanup(dev); | ||
2694 | /* firmware is released later */ | 2686 | /* firmware is released later */ |
2695 | } | 2687 | } |
2696 | 2688 | ||
@@ -2700,7 +2692,7 @@ static void b43_chip_exit(struct b43_wldev *dev) | |||
2700 | static int b43_chip_init(struct b43_wldev *dev) | 2692 | static int b43_chip_init(struct b43_wldev *dev) |
2701 | { | 2693 | { |
2702 | struct b43_phy *phy = &dev->phy; | 2694 | struct b43_phy *phy = &dev->phy; |
2703 | int err, tmp; | 2695 | int err; |
2704 | u32 value32, macctl; | 2696 | u32 value32, macctl; |
2705 | u16 value16; | 2697 | u16 value16; |
2706 | 2698 | ||
@@ -2725,19 +2717,20 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2725 | err = b43_upload_initvals(dev); | 2717 | err = b43_upload_initvals(dev); |
2726 | if (err) | 2718 | if (err) |
2727 | goto err_gpio_clean; | 2719 | goto err_gpio_clean; |
2728 | b43_radio_turn_on(dev); | ||
2729 | 2720 | ||
2730 | b43_write16(dev, 0x03E6, 0x0000); | 2721 | /* Turn the Analog on and initialize the PHY. */ |
2722 | phy->ops->switch_analog(dev, 1); | ||
2731 | err = b43_phy_init(dev); | 2723 | err = b43_phy_init(dev); |
2732 | if (err) | 2724 | if (err) |
2733 | goto err_radio_off; | 2725 | goto err_gpio_clean; |
2734 | 2726 | ||
2735 | /* Select initial Interference Mitigation. */ | 2727 | /* Disable Interference Mitigation. */ |
2736 | tmp = phy->interfmode; | 2728 | if (phy->ops->interf_mitigation) |
2737 | phy->interfmode = B43_INTERFMODE_NONE; | 2729 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); |
2738 | b43_radio_set_interference_mitigation(dev, tmp); | ||
2739 | 2730 | ||
2740 | b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | 2731 | /* Select the antennae */ |
2732 | if (phy->ops->set_rx_antenna) | ||
2733 | phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | ||
2741 | b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); | 2734 | b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); |
2742 | 2735 | ||
2743 | if (phy->type == B43_PHYTYPE_B) { | 2736 | if (phy->type == B43_PHYTYPE_B) { |
@@ -2790,8 +2783,6 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2790 | out: | 2783 | out: |
2791 | return err; | 2784 | return err; |
2792 | 2785 | ||
2793 | err_radio_off: | ||
2794 | b43_radio_turn_off(dev, 1); | ||
2795 | err_gpio_clean: | 2786 | err_gpio_clean: |
2796 | b43_gpio_cleanup(dev); | 2787 | b43_gpio_cleanup(dev); |
2797 | return err; | 2788 | return err; |
@@ -2799,25 +2790,13 @@ err_gpio_clean: | |||
2799 | 2790 | ||
2800 | static void b43_periodic_every60sec(struct b43_wldev *dev) | 2791 | static void b43_periodic_every60sec(struct b43_wldev *dev) |
2801 | { | 2792 | { |
2802 | struct b43_phy *phy = &dev->phy; | 2793 | const struct b43_phy_operations *ops = dev->phy.ops; |
2803 | 2794 | ||
2804 | if (phy->type != B43_PHYTYPE_G) | 2795 | if (ops->pwork_60sec) |
2805 | return; | 2796 | ops->pwork_60sec(dev); |
2806 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { | 2797 | |
2807 | b43_mac_suspend(dev); | 2798 | /* Force check the TX power emission now. */ |
2808 | b43_calc_nrssi_slope(dev); | 2799 | b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME); |
2809 | if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { | ||
2810 | u8 old_chan = phy->channel; | ||
2811 | |||
2812 | /* VCO Calibration */ | ||
2813 | if (old_chan >= 8) | ||
2814 | b43_radio_selectchannel(dev, 1, 0); | ||
2815 | else | ||
2816 | b43_radio_selectchannel(dev, 13, 0); | ||
2817 | b43_radio_selectchannel(dev, old_chan, 0); | ||
2818 | } | ||
2819 | b43_mac_enable(dev); | ||
2820 | } | ||
2821 | } | 2800 | } |
2822 | 2801 | ||
2823 | static void b43_periodic_every30sec(struct b43_wldev *dev) | 2802 | static void b43_periodic_every30sec(struct b43_wldev *dev) |
@@ -2845,32 +2824,8 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | |||
2845 | } | 2824 | } |
2846 | } | 2825 | } |
2847 | 2826 | ||
2848 | if (phy->type == B43_PHYTYPE_G) { | 2827 | if (phy->ops->pwork_15sec) |
2849 | //TODO: update_aci_moving_average | 2828 | phy->ops->pwork_15sec(dev); |
2850 | if (phy->aci_enable && phy->aci_wlan_automatic) { | ||
2851 | b43_mac_suspend(dev); | ||
2852 | if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) { | ||
2853 | if (0 /*TODO: bunch of conditions */ ) { | ||
2854 | b43_radio_set_interference_mitigation | ||
2855 | (dev, B43_INTERFMODE_MANUALWLAN); | ||
2856 | } | ||
2857 | } else if (1 /*TODO*/) { | ||
2858 | /* | ||
2859 | if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) { | ||
2860 | b43_radio_set_interference_mitigation(dev, | ||
2861 | B43_INTERFMODE_NONE); | ||
2862 | } | ||
2863 | */ | ||
2864 | } | ||
2865 | b43_mac_enable(dev); | ||
2866 | } else if (phy->interfmode == B43_INTERFMODE_NONWLAN && | ||
2867 | phy->rev == 1) { | ||
2868 | //TODO: implement rev1 workaround | ||
2869 | } | ||
2870 | } | ||
2871 | b43_phy_xmitpower(dev); //FIXME: unless scanning? | ||
2872 | b43_lo_g_maintanance_work(dev); | ||
2873 | //TODO for APHY (temperature?) | ||
2874 | 2829 | ||
2875 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 2830 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
2876 | wmb(); | 2831 | wmb(); |
@@ -3104,36 +3059,31 @@ static void b43_qos_params_upload(struct b43_wldev *dev, | |||
3104 | } | 3059 | } |
3105 | } | 3060 | } |
3106 | 3061 | ||
3107 | /* Update the QOS parameters in hardware. */ | 3062 | /* Mapping of mac80211 queue numbers to b43 QoS SHM offsets. */ |
3108 | static void b43_qos_update(struct b43_wldev *dev) | 3063 | static const u16 b43_qos_shm_offsets[] = { |
3064 | /* [mac80211-queue-nr] = SHM_OFFSET, */ | ||
3065 | [0] = B43_QOS_VOICE, | ||
3066 | [1] = B43_QOS_VIDEO, | ||
3067 | [2] = B43_QOS_BESTEFFORT, | ||
3068 | [3] = B43_QOS_BACKGROUND, | ||
3069 | }; | ||
3070 | |||
3071 | /* Update all QOS parameters in hardware. */ | ||
3072 | static void b43_qos_upload_all(struct b43_wldev *dev) | ||
3109 | { | 3073 | { |
3110 | struct b43_wl *wl = dev->wl; | 3074 | struct b43_wl *wl = dev->wl; |
3111 | struct b43_qos_params *params; | 3075 | struct b43_qos_params *params; |
3112 | unsigned long flags; | ||
3113 | unsigned int i; | 3076 | unsigned int i; |
3114 | 3077 | ||
3115 | /* Mapping of mac80211 queues to b43 SHM offsets. */ | 3078 | BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != |
3116 | static const u16 qos_shm_offsets[] = { | 3079 | ARRAY_SIZE(wl->qos_params)); |
3117 | [0] = B43_QOS_VOICE, | ||
3118 | [1] = B43_QOS_VIDEO, | ||
3119 | [2] = B43_QOS_BESTEFFORT, | ||
3120 | [3] = B43_QOS_BACKGROUND, | ||
3121 | }; | ||
3122 | BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params)); | ||
3123 | 3080 | ||
3124 | b43_mac_suspend(dev); | 3081 | b43_mac_suspend(dev); |
3125 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3126 | |||
3127 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | 3082 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { |
3128 | params = &(wl->qos_params[i]); | 3083 | params = &(wl->qos_params[i]); |
3129 | if (params->need_hw_update) { | 3084 | b43_qos_params_upload(dev, &(params->p), |
3130 | b43_qos_params_upload(dev, &(params->p), | 3085 | b43_qos_shm_offsets[i]); |
3131 | qos_shm_offsets[i]); | ||
3132 | params->need_hw_update = 0; | ||
3133 | } | ||
3134 | } | 3086 | } |
3135 | |||
3136 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3137 | b43_mac_enable(dev); | 3087 | b43_mac_enable(dev); |
3138 | } | 3088 | } |
3139 | 3089 | ||
@@ -3142,25 +3092,50 @@ static void b43_qos_clear(struct b43_wl *wl) | |||
3142 | struct b43_qos_params *params; | 3092 | struct b43_qos_params *params; |
3143 | unsigned int i; | 3093 | unsigned int i; |
3144 | 3094 | ||
3095 | /* Initialize QoS parameters to sane defaults. */ | ||
3096 | |||
3097 | BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != | ||
3098 | ARRAY_SIZE(wl->qos_params)); | ||
3099 | |||
3145 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | 3100 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { |
3146 | params = &(wl->qos_params[i]); | 3101 | params = &(wl->qos_params[i]); |
3147 | 3102 | ||
3148 | memset(&(params->p), 0, sizeof(params->p)); | 3103 | switch (b43_qos_shm_offsets[i]) { |
3149 | params->p.aifs = -1; | 3104 | case B43_QOS_VOICE: |
3150 | params->need_hw_update = 1; | 3105 | params->p.txop = 0; |
3106 | params->p.aifs = 2; | ||
3107 | params->p.cw_min = 0x0001; | ||
3108 | params->p.cw_max = 0x0001; | ||
3109 | break; | ||
3110 | case B43_QOS_VIDEO: | ||
3111 | params->p.txop = 0; | ||
3112 | params->p.aifs = 2; | ||
3113 | params->p.cw_min = 0x0001; | ||
3114 | params->p.cw_max = 0x0001; | ||
3115 | break; | ||
3116 | case B43_QOS_BESTEFFORT: | ||
3117 | params->p.txop = 0; | ||
3118 | params->p.aifs = 3; | ||
3119 | params->p.cw_min = 0x0001; | ||
3120 | params->p.cw_max = 0x03FF; | ||
3121 | break; | ||
3122 | case B43_QOS_BACKGROUND: | ||
3123 | params->p.txop = 0; | ||
3124 | params->p.aifs = 7; | ||
3125 | params->p.cw_min = 0x0001; | ||
3126 | params->p.cw_max = 0x03FF; | ||
3127 | break; | ||
3128 | default: | ||
3129 | B43_WARN_ON(1); | ||
3130 | } | ||
3151 | } | 3131 | } |
3152 | } | 3132 | } |
3153 | 3133 | ||
3154 | /* Initialize the core's QOS capabilities */ | 3134 | /* Initialize the core's QOS capabilities */ |
3155 | static void b43_qos_init(struct b43_wldev *dev) | 3135 | static void b43_qos_init(struct b43_wldev *dev) |
3156 | { | 3136 | { |
3157 | struct b43_wl *wl = dev->wl; | ||
3158 | unsigned int i; | ||
3159 | |||
3160 | /* Upload the current QOS parameters. */ | 3137 | /* Upload the current QOS parameters. */ |
3161 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) | 3138 | b43_qos_upload_all(dev); |
3162 | wl->qos_params[i].need_hw_update = 1; | ||
3163 | b43_qos_update(dev); | ||
3164 | 3139 | ||
3165 | /* Enable QOS support. */ | 3140 | /* Enable QOS support. */ |
3166 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | 3141 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); |
@@ -3169,25 +3144,13 @@ static void b43_qos_init(struct b43_wldev *dev) | |||
3169 | | B43_MMIO_IFSCTL_USE_EDCF); | 3144 | | B43_MMIO_IFSCTL_USE_EDCF); |
3170 | } | 3145 | } |
3171 | 3146 | ||
3172 | static void b43_qos_update_work(struct work_struct *work) | ||
3173 | { | ||
3174 | struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work); | ||
3175 | struct b43_wldev *dev; | ||
3176 | |||
3177 | mutex_lock(&wl->mutex); | ||
3178 | dev = wl->current_dev; | ||
3179 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) | ||
3180 | b43_qos_update(dev); | ||
3181 | mutex_unlock(&wl->mutex); | ||
3182 | } | ||
3183 | |||
3184 | static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, | 3147 | static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, |
3185 | const struct ieee80211_tx_queue_params *params) | 3148 | const struct ieee80211_tx_queue_params *params) |
3186 | { | 3149 | { |
3187 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3150 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3188 | unsigned long flags; | 3151 | struct b43_wldev *dev; |
3189 | unsigned int queue = (unsigned int)_queue; | 3152 | unsigned int queue = (unsigned int)_queue; |
3190 | struct b43_qos_params *p; | 3153 | int err = -ENODEV; |
3191 | 3154 | ||
3192 | if (queue >= ARRAY_SIZE(wl->qos_params)) { | 3155 | if (queue >= ARRAY_SIZE(wl->qos_params)) { |
3193 | /* Queue not available or don't support setting | 3156 | /* Queue not available or don't support setting |
@@ -3195,16 +3158,25 @@ static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, | |||
3195 | * confuse mac80211. */ | 3158 | * confuse mac80211. */ |
3196 | return 0; | 3159 | return 0; |
3197 | } | 3160 | } |
3161 | BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != | ||
3162 | ARRAY_SIZE(wl->qos_params)); | ||
3198 | 3163 | ||
3199 | spin_lock_irqsave(&wl->irq_lock, flags); | 3164 | mutex_lock(&wl->mutex); |
3200 | p = &(wl->qos_params[queue]); | 3165 | dev = wl->current_dev; |
3201 | memcpy(&(p->p), params, sizeof(p->p)); | 3166 | if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) |
3202 | p->need_hw_update = 1; | 3167 | goto out_unlock; |
3203 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3204 | 3168 | ||
3205 | queue_work(hw->workqueue, &wl->qos_update_work); | 3169 | memcpy(&(wl->qos_params[queue].p), params, sizeof(*params)); |
3170 | b43_mac_suspend(dev); | ||
3171 | b43_qos_params_upload(dev, &(wl->qos_params[queue].p), | ||
3172 | b43_qos_shm_offsets[queue]); | ||
3173 | b43_mac_enable(dev); | ||
3174 | err = 0; | ||
3206 | 3175 | ||
3207 | return 0; | 3176 | out_unlock: |
3177 | mutex_unlock(&wl->mutex); | ||
3178 | |||
3179 | return err; | ||
3208 | } | 3180 | } |
3209 | 3181 | ||
3210 | static int b43_op_get_tx_stats(struct ieee80211_hw *hw, | 3182 | static int b43_op_get_tx_stats(struct ieee80211_hw *hw, |
@@ -3401,7 +3373,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3401 | /* Switch to the requested channel. | 3373 | /* Switch to the requested channel. |
3402 | * The firmware takes care of races with the TX handler. */ | 3374 | * The firmware takes care of races with the TX handler. */ |
3403 | if (conf->channel->hw_value != phy->channel) | 3375 | if (conf->channel->hw_value != phy->channel) |
3404 | b43_radio_selectchannel(dev, conf->channel->hw_value, 0); | 3376 | b43_switch_channel(dev, conf->channel->hw_value); |
3405 | 3377 | ||
3406 | /* Enable/Disable ShortSlot timing. */ | 3378 | /* Enable/Disable ShortSlot timing. */ |
3407 | if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != | 3379 | if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != |
@@ -3417,26 +3389,30 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3417 | 3389 | ||
3418 | /* Adjust the desired TX power level. */ | 3390 | /* Adjust the desired TX power level. */ |
3419 | if (conf->power_level != 0) { | 3391 | if (conf->power_level != 0) { |
3420 | if (conf->power_level != phy->power_level) { | 3392 | spin_lock_irqsave(&wl->irq_lock, flags); |
3421 | phy->power_level = conf->power_level; | 3393 | if (conf->power_level != phy->desired_txpower) { |
3422 | b43_phy_xmitpower(dev); | 3394 | phy->desired_txpower = conf->power_level; |
3395 | b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME | | ||
3396 | B43_TXPWR_IGNORE_TSSI); | ||
3423 | } | 3397 | } |
3398 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3424 | } | 3399 | } |
3425 | 3400 | ||
3426 | /* Antennas for RX and management frame TX. */ | 3401 | /* Antennas for RX and management frame TX. */ |
3427 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); | 3402 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); |
3428 | b43_mgmtframe_txantenna(dev, antenna); | 3403 | b43_mgmtframe_txantenna(dev, antenna); |
3429 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); | 3404 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); |
3430 | b43_set_rx_antenna(dev, antenna); | 3405 | if (phy->ops->set_rx_antenna) |
3406 | phy->ops->set_rx_antenna(dev, antenna); | ||
3431 | 3407 | ||
3432 | /* Update templates for AP/mesh mode. */ | 3408 | /* Update templates for AP/mesh mode. */ |
3433 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || | 3409 | if (b43_is_mode(wl, NL80211_IFTYPE_AP) || |
3434 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | 3410 | b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) |
3435 | b43_set_beacon_int(dev, conf->beacon_int); | 3411 | b43_set_beacon_int(dev, conf->beacon_int); |
3436 | 3412 | ||
3437 | if (!!conf->radio_enabled != phy->radio_on) { | 3413 | if (!!conf->radio_enabled != phy->radio_on) { |
3438 | if (conf->radio_enabled) { | 3414 | if (conf->radio_enabled) { |
3439 | b43_radio_turn_on(dev); | 3415 | b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); |
3440 | b43info(dev->wl, "Radio turned on by software\n"); | 3416 | b43info(dev->wl, "Radio turned on by software\n"); |
3441 | if (!dev->radio_hw_enable) { | 3417 | if (!dev->radio_hw_enable) { |
3442 | b43info(dev->wl, "The hardware RF-kill button " | 3418 | b43info(dev->wl, "The hardware RF-kill button " |
@@ -3444,7 +3420,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3444 | "Press the button to turn it on.\n"); | 3420 | "Press the button to turn it on.\n"); |
3445 | } | 3421 | } |
3446 | } else { | 3422 | } else { |
3447 | b43_radio_turn_off(dev, 0); | 3423 | b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); |
3448 | b43info(dev->wl, "Radio turned off by software\n"); | 3424 | b43info(dev->wl, "Radio turned off by software\n"); |
3449 | } | 3425 | } |
3450 | } | 3426 | } |
@@ -3619,14 +3595,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, | |||
3619 | else | 3595 | else |
3620 | memset(wl->bssid, 0, ETH_ALEN); | 3596 | memset(wl->bssid, 0, ETH_ALEN); |
3621 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { | 3597 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { |
3622 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || | 3598 | if (b43_is_mode(wl, NL80211_IFTYPE_AP) || |
3623 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { | 3599 | b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { |
3624 | B43_WARN_ON(vif->type != wl->if_type); | 3600 | B43_WARN_ON(vif->type != wl->if_type); |
3625 | if (conf->changed & IEEE80211_IFCC_SSID) | 3601 | if (conf->changed & IEEE80211_IFCC_SSID) |
3626 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); | 3602 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); |
3627 | if (conf->changed & IEEE80211_IFCC_BEACON) | 3603 | if (conf->changed & IEEE80211_IFCC_BEACON) |
3628 | b43_update_templates(wl); | 3604 | b43_update_templates(wl); |
3629 | } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { | 3605 | } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { |
3630 | if (conf->changed & IEEE80211_IFCC_BEACON) | 3606 | if (conf->changed & IEEE80211_IFCC_BEACON) |
3631 | b43_update_templates(wl); | 3607 | b43_update_templates(wl); |
3632 | } | 3608 | } |
@@ -3818,48 +3794,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3818 | static void setup_struct_phy_for_init(struct b43_wldev *dev, | 3794 | static void setup_struct_phy_for_init(struct b43_wldev *dev, |
3819 | struct b43_phy *phy) | 3795 | struct b43_phy *phy) |
3820 | { | 3796 | { |
3821 | struct b43_txpower_lo_control *lo; | ||
3822 | int i; | ||
3823 | |||
3824 | memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); | ||
3825 | memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); | ||
3826 | |||
3827 | phy->aci_enable = 0; | ||
3828 | phy->aci_wlan_automatic = 0; | ||
3829 | phy->aci_hw_rssi = 0; | ||
3830 | |||
3831 | phy->radio_off_context.valid = 0; | ||
3832 | |||
3833 | lo = phy->lo_control; | ||
3834 | if (lo) { | ||
3835 | memset(lo, 0, sizeof(*(phy->lo_control))); | ||
3836 | lo->tx_bias = 0xFF; | ||
3837 | INIT_LIST_HEAD(&lo->calib_list); | ||
3838 | } | ||
3839 | phy->max_lb_gain = 0; | ||
3840 | phy->trsw_rx_gain = 0; | ||
3841 | phy->txpwr_offset = 0; | ||
3842 | |||
3843 | /* NRSSI */ | ||
3844 | phy->nrssislope = 0; | ||
3845 | for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++) | ||
3846 | phy->nrssi[i] = -1000; | ||
3847 | for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++) | ||
3848 | phy->nrssi_lt[i] = i; | ||
3849 | |||
3850 | phy->lofcal = 0xFFFF; | ||
3851 | phy->initval = 0xFFFF; | ||
3852 | |||
3853 | phy->interfmode = B43_INTERFMODE_NONE; | ||
3854 | phy->channel = 0xFF; | ||
3855 | |||
3856 | phy->hardware_power_control = !!modparam_hwpctl; | 3797 | phy->hardware_power_control = !!modparam_hwpctl; |
3857 | 3798 | phy->next_txpwr_check_time = jiffies; | |
3858 | /* PHY TX errors counter. */ | 3799 | /* PHY TX errors counter. */ |
3859 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 3800 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
3860 | |||
3861 | /* OFDM-table address caching. */ | ||
3862 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN; | ||
3863 | } | 3801 | } |
3864 | 3802 | ||
3865 | static void setup_struct_wldev_for_init(struct b43_wldev *dev) | 3803 | static void setup_struct_wldev_for_init(struct b43_wldev *dev) |
@@ -3965,7 +3903,7 @@ static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) | |||
3965 | pu_delay = 3700; | 3903 | pu_delay = 3700; |
3966 | else | 3904 | else |
3967 | pu_delay = 1050; | 3905 | pu_delay = 1050; |
3968 | if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) | 3906 | if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle) |
3969 | pu_delay = 500; | 3907 | pu_delay = 500; |
3970 | if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) | 3908 | if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) |
3971 | pu_delay = max(pu_delay, (u16)2400); | 3909 | pu_delay = max(pu_delay, (u16)2400); |
@@ -3979,7 +3917,7 @@ static void b43_set_pretbtt(struct b43_wldev *dev) | |||
3979 | u16 pretbtt; | 3917 | u16 pretbtt; |
3980 | 3918 | ||
3981 | /* The time value is in microseconds. */ | 3919 | /* The time value is in microseconds. */ |
3982 | if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) { | 3920 | if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) { |
3983 | pretbtt = 2; | 3921 | pretbtt = 2; |
3984 | } else { | 3922 | } else { |
3985 | if (dev->phy.type == B43_PHYTYPE_A) | 3923 | if (dev->phy.type == B43_PHYTYPE_A) |
@@ -3995,7 +3933,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev) | |||
3995 | /* Locking: wl->mutex */ | 3933 | /* Locking: wl->mutex */ |
3996 | static void b43_wireless_core_exit(struct b43_wldev *dev) | 3934 | static void b43_wireless_core_exit(struct b43_wldev *dev) |
3997 | { | 3935 | { |
3998 | struct b43_phy *phy = &dev->phy; | ||
3999 | u32 macctl; | 3936 | u32 macctl; |
4000 | 3937 | ||
4001 | B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); | 3938 | B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); |
@@ -4016,12 +3953,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
4016 | b43_dma_free(dev); | 3953 | b43_dma_free(dev); |
4017 | b43_pio_free(dev); | 3954 | b43_pio_free(dev); |
4018 | b43_chip_exit(dev); | 3955 | b43_chip_exit(dev); |
4019 | b43_radio_turn_off(dev, 1); | 3956 | dev->phy.ops->switch_analog(dev, 0); |
4020 | b43_switch_analog(dev, 0); | ||
4021 | if (phy->dyn_tssi_tbl) | ||
4022 | kfree(phy->tssi2dbm); | ||
4023 | kfree(phy->lo_control); | ||
4024 | phy->lo_control = NULL; | ||
4025 | if (dev->wl->current_beacon) { | 3957 | if (dev->wl->current_beacon) { |
4026 | dev_kfree_skb_any(dev->wl->current_beacon); | 3958 | dev_kfree_skb_any(dev->wl->current_beacon); |
4027 | dev->wl->current_beacon = NULL; | 3959 | dev->wl->current_beacon = NULL; |
@@ -4052,29 +3984,23 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4052 | b43_wireless_core_reset(dev, tmp); | 3984 | b43_wireless_core_reset(dev, tmp); |
4053 | } | 3985 | } |
4054 | 3986 | ||
4055 | if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) { | 3987 | /* Reset all data structures. */ |
4056 | phy->lo_control = | ||
4057 | kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL); | ||
4058 | if (!phy->lo_control) { | ||
4059 | err = -ENOMEM; | ||
4060 | goto err_busdown; | ||
4061 | } | ||
4062 | } | ||
4063 | setup_struct_wldev_for_init(dev); | 3988 | setup_struct_wldev_for_init(dev); |
4064 | 3989 | phy->ops->prepare_structs(dev); | |
4065 | err = b43_phy_init_tssi2dbm_table(dev); | ||
4066 | if (err) | ||
4067 | goto err_kfree_lo_control; | ||
4068 | 3990 | ||
4069 | /* Enable IRQ routing to this device. */ | 3991 | /* Enable IRQ routing to this device. */ |
4070 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); | 3992 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); |
4071 | 3993 | ||
4072 | b43_imcfglo_timeouts_workaround(dev); | 3994 | b43_imcfglo_timeouts_workaround(dev); |
4073 | b43_bluetooth_coext_disable(dev); | 3995 | b43_bluetooth_coext_disable(dev); |
4074 | b43_phy_early_init(dev); | 3996 | if (phy->ops->prepare_hardware) { |
3997 | err = phy->ops->prepare_hardware(dev); | ||
3998 | if (err) | ||
3999 | goto err_busdown; | ||
4000 | } | ||
4075 | err = b43_chip_init(dev); | 4001 | err = b43_chip_init(dev); |
4076 | if (err) | 4002 | if (err) |
4077 | goto err_kfree_tssitbl; | 4003 | goto err_busdown; |
4078 | b43_shm_write16(dev, B43_SHM_SHARED, | 4004 | b43_shm_write16(dev, B43_SHM_SHARED, |
4079 | B43_SHM_SH_WLCOREREV, dev->dev->id.revision); | 4005 | B43_SHM_SH_WLCOREREV, dev->dev->id.revision); |
4080 | hf = b43_hf_read(dev); | 4006 | hf = b43_hf_read(dev); |
@@ -4140,15 +4066,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4140 | out: | 4066 | out: |
4141 | return err; | 4067 | return err; |
4142 | 4068 | ||
4143 | err_chip_exit: | 4069 | err_chip_exit: |
4144 | b43_chip_exit(dev); | 4070 | b43_chip_exit(dev); |
4145 | err_kfree_tssitbl: | 4071 | err_busdown: |
4146 | if (phy->dyn_tssi_tbl) | ||
4147 | kfree(phy->tssi2dbm); | ||
4148 | err_kfree_lo_control: | ||
4149 | kfree(phy->lo_control); | ||
4150 | phy->lo_control = NULL; | ||
4151 | err_busdown: | ||
4152 | ssb_bus_may_powerdown(bus); | 4072 | ssb_bus_may_powerdown(bus); |
4153 | B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); | 4073 | B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); |
4154 | return err; | 4074 | return err; |
@@ -4164,11 +4084,11 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4164 | 4084 | ||
4165 | /* TODO: allow WDS/AP devices to coexist */ | 4085 | /* TODO: allow WDS/AP devices to coexist */ |
4166 | 4086 | ||
4167 | if (conf->type != IEEE80211_IF_TYPE_AP && | 4087 | if (conf->type != NL80211_IFTYPE_AP && |
4168 | conf->type != IEEE80211_IF_TYPE_MESH_POINT && | 4088 | conf->type != NL80211_IFTYPE_MESH_POINT && |
4169 | conf->type != IEEE80211_IF_TYPE_STA && | 4089 | conf->type != NL80211_IFTYPE_STATION && |
4170 | conf->type != IEEE80211_IF_TYPE_WDS && | 4090 | conf->type != NL80211_IFTYPE_WDS && |
4171 | conf->type != IEEE80211_IF_TYPE_IBSS) | 4091 | conf->type != NL80211_IFTYPE_ADHOC) |
4172 | return -EOPNOTSUPP; | 4092 | return -EOPNOTSUPP; |
4173 | 4093 | ||
4174 | mutex_lock(&wl->mutex); | 4094 | mutex_lock(&wl->mutex); |
@@ -4283,7 +4203,6 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
4283 | struct b43_wldev *dev = wl->current_dev; | 4203 | struct b43_wldev *dev = wl->current_dev; |
4284 | 4204 | ||
4285 | b43_rfkill_exit(dev); | 4205 | b43_rfkill_exit(dev); |
4286 | cancel_work_sync(&(wl->qos_update_work)); | ||
4287 | cancel_work_sync(&(wl->beacon_update_trigger)); | 4206 | cancel_work_sync(&(wl->beacon_update_trigger)); |
4288 | 4207 | ||
4289 | mutex_lock(&wl->mutex); | 4208 | mutex_lock(&wl->mutex); |
@@ -4291,6 +4210,8 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
4291 | b43_wireless_core_stop(dev); | 4210 | b43_wireless_core_stop(dev); |
4292 | b43_wireless_core_exit(dev); | 4211 | b43_wireless_core_exit(dev); |
4293 | mutex_unlock(&wl->mutex); | 4212 | mutex_unlock(&wl->mutex); |
4213 | |||
4214 | cancel_work_sync(&(wl->txpower_adjust_work)); | ||
4294 | } | 4215 | } |
4295 | 4216 | ||
4296 | static int b43_op_set_retry_limit(struct ieee80211_hw *hw, | 4217 | static int b43_op_set_retry_limit(struct ieee80211_hw *hw, |
@@ -4313,7 +4234,8 @@ out_unlock: | |||
4313 | return err; | 4234 | return err; |
4314 | } | 4235 | } |
4315 | 4236 | ||
4316 | static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) | 4237 | static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, |
4238 | struct ieee80211_sta *sta, bool set) | ||
4317 | { | 4239 | { |
4318 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4240 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4319 | unsigned long flags; | 4241 | unsigned long flags; |
@@ -4328,7 +4250,7 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) | |||
4328 | static void b43_op_sta_notify(struct ieee80211_hw *hw, | 4250 | static void b43_op_sta_notify(struct ieee80211_hw *hw, |
4329 | struct ieee80211_vif *vif, | 4251 | struct ieee80211_vif *vif, |
4330 | enum sta_notify_cmd notify_cmd, | 4252 | enum sta_notify_cmd notify_cmd, |
4331 | const u8 *addr) | 4253 | struct ieee80211_sta *sta) |
4332 | { | 4254 | { |
4333 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4255 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4334 | 4256 | ||
@@ -4422,6 +4344,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev) | |||
4422 | /* We release firmware that late to not be required to re-request | 4344 | /* We release firmware that late to not be required to re-request |
4423 | * is all the time when we reinit the core. */ | 4345 | * is all the time when we reinit the core. */ |
4424 | b43_release_firmware(dev); | 4346 | b43_release_firmware(dev); |
4347 | b43_phy_free(dev); | ||
4425 | } | 4348 | } |
4426 | 4349 | ||
4427 | static int b43_wireless_core_attach(struct b43_wldev *dev) | 4350 | static int b43_wireless_core_attach(struct b43_wldev *dev) |
@@ -4495,30 +4418,35 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4495 | } | 4418 | } |
4496 | } | 4419 | } |
4497 | 4420 | ||
4421 | err = b43_phy_allocate(dev); | ||
4422 | if (err) | ||
4423 | goto err_powerdown; | ||
4424 | |||
4498 | dev->phy.gmode = have_2ghz_phy; | 4425 | dev->phy.gmode = have_2ghz_phy; |
4499 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; | 4426 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; |
4500 | b43_wireless_core_reset(dev, tmp); | 4427 | b43_wireless_core_reset(dev, tmp); |
4501 | 4428 | ||
4502 | err = b43_validate_chipaccess(dev); | 4429 | err = b43_validate_chipaccess(dev); |
4503 | if (err) | 4430 | if (err) |
4504 | goto err_powerdown; | 4431 | goto err_phy_free; |
4505 | err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); | 4432 | err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); |
4506 | if (err) | 4433 | if (err) |
4507 | goto err_powerdown; | 4434 | goto err_phy_free; |
4508 | 4435 | ||
4509 | /* Now set some default "current_dev" */ | 4436 | /* Now set some default "current_dev" */ |
4510 | if (!wl->current_dev) | 4437 | if (!wl->current_dev) |
4511 | wl->current_dev = dev; | 4438 | wl->current_dev = dev; |
4512 | INIT_WORK(&dev->restart_work, b43_chip_reset); | 4439 | INIT_WORK(&dev->restart_work, b43_chip_reset); |
4513 | 4440 | ||
4514 | b43_radio_turn_off(dev, 1); | 4441 | dev->phy.ops->switch_analog(dev, 0); |
4515 | b43_switch_analog(dev, 0); | ||
4516 | ssb_device_disable(dev->dev, 0); | 4442 | ssb_device_disable(dev->dev, 0); |
4517 | ssb_bus_may_powerdown(bus); | 4443 | ssb_bus_may_powerdown(bus); |
4518 | 4444 | ||
4519 | out: | 4445 | out: |
4520 | return err; | 4446 | return err; |
4521 | 4447 | ||
4448 | err_phy_free: | ||
4449 | b43_phy_free(dev); | ||
4522 | err_powerdown: | 4450 | err_powerdown: |
4523 | ssb_bus_may_powerdown(bus); | 4451 | ssb_bus_may_powerdown(bus); |
4524 | return err; | 4452 | return err; |
@@ -4615,9 +4543,11 @@ static void b43_sprom_fixup(struct ssb_bus *bus) | |||
4615 | pdev = bus->host_pci; | 4543 | pdev = bus->host_pci; |
4616 | if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || | 4544 | if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || |
4617 | IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || | 4545 | IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || |
4546 | IS_PDEV(pdev, BROADCOM, 0x4320, HP, 0x12f8) || | ||
4618 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || | 4547 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || |
4619 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || | 4548 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || |
4620 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) | 4549 | IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) || |
4550 | IS_PDEV(pdev, BROADCOM, 0x4320, MOTOROLA, 0x7010)) | ||
4621 | bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; | 4551 | bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; |
4622 | } | 4552 | } |
4623 | } | 4553 | } |
@@ -4650,7 +4580,15 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4650 | IEEE80211_HW_SIGNAL_DBM | | 4580 | IEEE80211_HW_SIGNAL_DBM | |
4651 | IEEE80211_HW_NOISE_DBM; | 4581 | IEEE80211_HW_NOISE_DBM; |
4652 | 4582 | ||
4583 | hw->wiphy->interface_modes = | ||
4584 | BIT(NL80211_IFTYPE_AP) | | ||
4585 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
4586 | BIT(NL80211_IFTYPE_STATION) | | ||
4587 | BIT(NL80211_IFTYPE_WDS) | | ||
4588 | BIT(NL80211_IFTYPE_ADHOC); | ||
4589 | |||
4653 | hw->queues = b43_modparam_qos ? 4 : 1; | 4590 | hw->queues = b43_modparam_qos ? 4 : 1; |
4591 | hw->max_altrates = 1; | ||
4654 | SET_IEEE80211_DEV(hw, dev->dev); | 4592 | SET_IEEE80211_DEV(hw, dev->dev); |
4655 | if (is_valid_ether_addr(sprom->et1mac)) | 4593 | if (is_valid_ether_addr(sprom->et1mac)) |
4656 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); | 4594 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |
@@ -4667,8 +4605,8 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4667 | spin_lock_init(&wl->shm_lock); | 4605 | spin_lock_init(&wl->shm_lock); |
4668 | mutex_init(&wl->mutex); | 4606 | mutex_init(&wl->mutex); |
4669 | INIT_LIST_HEAD(&wl->devlist); | 4607 | INIT_LIST_HEAD(&wl->devlist); |
4670 | INIT_WORK(&wl->qos_update_work, b43_qos_update_work); | ||
4671 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); | 4608 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); |
4609 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | ||
4672 | 4610 | ||
4673 | ssb_set_devtypedata(dev, wl); | 4611 | ssb_set_devtypedata(dev, wl); |
4674 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); | 4612 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); |