Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

zd1211rw: don't let zd_mac_config_beacon() run too long from beacon interrupt handler

zd_mac_config_beacon() has only limited time to set up beacon when called from
beacon interrupt handler/worker. So do not let it retry acquiring beacon fifo
semaphore in interrupt handler. Beacon fifo semaphore should not be locked by
firmware anyway at this time, it's only locked when device is using/txing
beacon.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Jussi Kivilinna and committed by
John W. Linville
dde4673b c900eff3

+12 -7
+12 -7
drivers/net/wireless/zd1211rw/zd_mac.c
··· 143 143 static void beacon_disable(struct zd_mac *mac); 144 144 static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble); 145 145 static int zd_mac_config_beacon(struct ieee80211_hw *hw, 146 - struct sk_buff *beacon); 146 + struct sk_buff *beacon, bool in_intr); 147 147 148 148 static int zd_reg2alpha2(u8 regdomain, char *alpha2) 149 149 { ··· 404 404 if (mac->vif != NULL) { 405 405 beacon = ieee80211_beacon_get(mac->hw, mac->vif); 406 406 if (beacon) 407 - zd_mac_config_beacon(mac->hw, beacon); 407 + zd_mac_config_beacon(mac->hw, beacon, false); 408 408 } 409 409 410 410 zd_set_beacon_interval(&mac->chip, beacon_interval, ··· 704 704 mutex_unlock(&mac->chip.mutex); 705 705 } 706 706 707 - static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) 707 + static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon, 708 + bool in_intr) 708 709 { 709 710 struct zd_mac *mac = zd_hw_mac(hw); 710 711 int r, ret, num_cmds, req_pos = 0; ··· 737 736 r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE); 738 737 if (r < 0) 739 738 goto release_sema; 739 + if (in_intr && tmp & 0x2) { 740 + r = -EBUSY; 741 + goto release_sema; 742 + } 740 743 741 744 end_jiffies = jiffies + HZ / 2; /*~500ms*/ 742 745 message_jiffies = jiffies + HZ / 10; /*~100ms*/ ··· 795 790 end_jiffies = jiffies + HZ / 2; /*~500ms*/ 796 791 ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE); 797 792 while (ret < 0) { 798 - if (time_is_before_eq_jiffies(end_jiffies)) { 793 + if (in_intr || time_is_before_eq_jiffies(end_jiffies)) { 799 794 ret = -ETIMEDOUT; 800 795 break; 801 796 } ··· 1166 1161 */ 1167 1162 beacon = ieee80211_beacon_get(mac->hw, mac->vif); 1168 1163 if (beacon) 1169 - zd_mac_config_beacon(mac->hw, beacon); 1164 + zd_mac_config_beacon(mac->hw, beacon, true); 1170 1165 1171 1166 spin_lock_irq(&mac->lock); 1172 1167 mac->beacon.last_update = jiffies; ··· 1291 1286 1292 1287 if (beacon) { 1293 1288 zd_chip_disable_hwint(&mac->chip); 1294 - zd_mac_config_beacon(hw, beacon); 1289 + zd_mac_config_beacon(hw, beacon, false); 1295 1290 zd_chip_enable_hwint(&mac->chip); 1296 1291 } 1297 1292 } ··· 1444 1439 if (beacon) { 1445 1440 zd_mac_free_cur_beacon(mac); 1446 1441 1447 - zd_mac_config_beacon(mac->hw, beacon); 1442 + zd_mac_config_beacon(mac->hw, beacon, false); 1448 1443 } 1449 1444 1450 1445 zd_set_beacon_interval(&mac->chip, interval, period, mac->type);