diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 31b7db05abd9..9de9dbe94399 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -121,7 +121,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
121 | return; | 121 | return; |
122 | 122 | ||
123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) | 123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) |
124 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 124 | rt2x00queue_update_beacon(rt2x00dev, vif); |
125 | } | 125 | } |
126 | 126 | ||
127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) | 127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) |
@@ -174,7 +174,13 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac, | |||
174 | vif->type != NL80211_IFTYPE_WDS) | 174 | vif->type != NL80211_IFTYPE_WDS) |
175 | return; | 175 | return; |
176 | 176 | ||
177 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 177 | /* |
178 | * Update the beacon without locking. This is safe on PCI devices | ||
179 | * as they only update the beacon periodically here. This should | ||
180 | * never be called for USB devices. | ||
181 | */ | ||
182 | WARN_ON(rt2x00_is_usb(rt2x00dev)); | ||
183 | rt2x00queue_update_beacon_locked(rt2x00dev, vif); | ||
178 | } | 184 | } |
179 | 185 | ||
180 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | 186 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) |
@@ -183,9 +189,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
183 | return; | 189 | return; |
184 | 190 | ||
185 | /* send buffered bc/mc frames out for every bssid */ | 191 | /* send buffered bc/mc frames out for every bssid */ |
186 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 192 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
187 | rt2x00lib_bc_buffer_iter, | 193 | rt2x00lib_bc_buffer_iter, |
188 | rt2x00dev); | 194 | rt2x00dev); |
189 | /* | 195 | /* |
190 | * Devices with pre tbtt interrupt don't need to update the beacon | 196 | * Devices with pre tbtt interrupt don't need to update the beacon |
191 | * here as they will fetch the next beacon directly prior to | 197 | * here as they will fetch the next beacon directly prior to |
@@ -195,9 +201,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
195 | return; | 201 | return; |
196 | 202 | ||
197 | /* fetch next beacon */ | 203 | /* fetch next beacon */ |
198 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 204 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
199 | rt2x00lib_beaconupdate_iter, | 205 | rt2x00lib_beaconupdate_iter, |
200 | rt2x00dev); | 206 | rt2x00dev); |
201 | } | 207 | } |
202 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 208 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
203 | 209 | ||
@@ -207,9 +213,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) | |||
207 | return; | 213 | return; |
208 | 214 | ||
209 | /* fetch next beacon */ | 215 | /* fetch next beacon */ |
210 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 216 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
211 | rt2x00lib_beaconupdate_iter, | 217 | rt2x00lib_beaconupdate_iter, |
212 | rt2x00dev); | 218 | rt2x00dev); |
213 | } | 219 | } |
214 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | 220 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); |
215 | 221 | ||
@@ -815,15 +821,29 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
815 | GFP_KERNEL); | 821 | GFP_KERNEL); |
816 | if (status) | 822 | if (status) |
817 | return status; | 823 | return status; |
824 | } | ||
818 | 825 | ||
819 | /* tasklet for processing the tx status reports. */ | 826 | /* |
820 | if (rt2x00dev->ops->lib->txstatus_tasklet) | 827 | * Initialize tasklets if used by the driver. Tasklets are |
821 | tasklet_init(&rt2x00dev->txstatus_tasklet, | 828 | * disabled until the interrupts are turned on. The driver |
822 | rt2x00dev->ops->lib->txstatus_tasklet, | 829 | * has to handle that. |
823 | (unsigned long)rt2x00dev); | 830 | */ |
824 | 831 | #define RT2X00_TASKLET_INIT(taskletname) \ | |
832 | if (rt2x00dev->ops->lib->taskletname) { \ | ||
833 | tasklet_init(&rt2x00dev->taskletname, \ | ||
834 | rt2x00dev->ops->lib->taskletname, \ | ||
835 | (unsigned long)rt2x00dev); \ | ||
836 | tasklet_disable(&rt2x00dev->taskletname); \ | ||
825 | } | 837 | } |
826 | 838 | ||
839 | RT2X00_TASKLET_INIT(txstatus_tasklet); | ||
840 | RT2X00_TASKLET_INIT(pretbtt_tasklet); | ||
841 | RT2X00_TASKLET_INIT(tbtt_tasklet); | ||
842 | RT2X00_TASKLET_INIT(rxdone_tasklet); | ||
843 | RT2X00_TASKLET_INIT(autowake_tasklet); | ||
844 | |||
845 | #undef RT2X00_TASKLET_INIT | ||
846 | |||
827 | /* | 847 | /* |
828 | * Register HW. | 848 | * Register HW. |
829 | */ | 849 | */ |
@@ -952,6 +972,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
952 | { | 972 | { |
953 | int retval = -ENOMEM; | 973 | int retval = -ENOMEM; |
954 | 974 | ||
975 | spin_lock_init(&rt2x00dev->irqmask_lock); | ||
955 | mutex_init(&rt2x00dev->csr_mutex); | 976 | mutex_init(&rt2x00dev->csr_mutex); |
956 | 977 | ||
957 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | 978 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
@@ -976,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
976 | BIT(NL80211_IFTYPE_WDS); | 997 | BIT(NL80211_IFTYPE_WDS); |
977 | 998 | ||
978 | /* | 999 | /* |
979 | * Initialize configuration work. | 1000 | * Initialize work. |
980 | */ | 1001 | */ |
1002 | rt2x00dev->workqueue = | ||
1003 | alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0); | ||
1004 | if (!rt2x00dev->workqueue) { | ||
1005 | retval = -ENOMEM; | ||
1006 | goto exit; | ||
1007 | } | ||
1008 | |||
981 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 1009 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
982 | 1010 | ||
983 | /* | 1011 | /* |
@@ -1036,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1036 | cancel_work_sync(&rt2x00dev->intf_work); | 1064 | cancel_work_sync(&rt2x00dev->intf_work); |
1037 | cancel_work_sync(&rt2x00dev->rxdone_work); | 1065 | cancel_work_sync(&rt2x00dev->rxdone_work); |
1038 | cancel_work_sync(&rt2x00dev->txdone_work); | 1066 | cancel_work_sync(&rt2x00dev->txdone_work); |
1067 | destroy_workqueue(rt2x00dev->workqueue); | ||
1039 | 1068 | ||
1040 | /* | 1069 | /* |
1041 | * Free the tx status fifo. | 1070 | * Free the tx status fifo. |
@@ -1046,6 +1075,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1046 | * Kill the tx status tasklet. | 1075 | * Kill the tx status tasklet. |
1047 | */ | 1076 | */ |
1048 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | 1077 | tasklet_kill(&rt2x00dev->txstatus_tasklet); |
1078 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
1079 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
1080 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
1081 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
1049 | 1082 | ||
1050 | /* | 1083 | /* |
1051 | * Uninitialize device. | 1084 | * Uninitialize device. |