diff options
author | Dan Williams <dcbw@redhat.com> | 2007-05-25 22:18:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-06-11 14:28:43 -0400 |
commit | 80e78ef74dffb2195e2a1164c18579180a76fd5b (patch) | |
tree | 362cae9f290534bb810f263477c977c6d082cebe /drivers/net/wireless/libertas/scan.c | |
parent | 94b23855c034ffa50e1f94f43ef4500520e4c36e (diff) |
[PATCH] libertas: fix deadlock SIOCGIWSCAN handler
Update signal quality before the locked scan result translation loop,
because calling libertas_prepare_and_send_command() with the
'waitforrsp' option grabs adapter->lock in the command return processing,
leading to the deadlock.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index abc9d563ce46..8aaac5f6c9de 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -1506,7 +1506,6 @@ static inline char *libertas_translate_scan(wlan_private *priv, | |||
1506 | char *current_val; /* For rates */ | 1506 | char *current_val; /* For rates */ |
1507 | struct iw_event iwe; /* Temporary buffer */ | 1507 | struct iw_event iwe; /* Temporary buffer */ |
1508 | int j; | 1508 | int j; |
1509 | int ret; | ||
1510 | #define PERFECT_RSSI ((u8)50) | 1509 | #define PERFECT_RSSI ((u8)50) |
1511 | #define WORST_RSSI ((u8)0) | 1510 | #define WORST_RSSI ((u8)0) |
1512 | #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) | 1511 | #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) |
@@ -1560,22 +1559,18 @@ static inline char *libertas_translate_scan(wlan_private *priv, | |||
1560 | iwe.u.qual.noise = | 1559 | iwe.u.qual.noise = |
1561 | CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); | 1560 | CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); |
1562 | } | 1561 | } |
1563 | if ((adapter->mode == IW_MODE_AUTO) && | 1562 | |
1564 | !libertas_SSID_cmp(&adapter->curbssparams.ssid, &bss->ssid) | 1563 | /* Locally created ad-hoc BSSs won't have beacons if this is the |
1565 | && adapter->adhoccreate) { | 1564 | * only station in the adhoc network; so get signal strength |
1566 | ret = libertas_prepare_and_send_command(priv, | 1565 | * from receive statistics. |
1567 | cmd_802_11_rssi, | 1566 | */ |
1568 | 0, | 1567 | if ((adapter->mode == IW_MODE_ADHOC) |
1569 | cmd_option_waitforrsp, | 1568 | && adapter->adhoccreate |
1570 | 0, NULL); | 1569 | && !libertas_SSID_cmp(&adapter->curbssparams.ssid, &bss->ssid)) { |
1571 | 1570 | int snr, nf; | |
1572 | if (!ret) { | 1571 | snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
1573 | iwe.u.qual.level = | 1572 | nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
1574 | CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / | 1573 | iwe.u.qual.level = CAL_RSSI(snr, nf); |
1575 | AVG_SCALE, | ||
1576 | adapter->NF[TYPE_RXPD][TYPE_AVG] / | ||
1577 | AVG_SCALE); | ||
1578 | } | ||
1579 | } | 1574 | } |
1580 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); | 1575 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); |
1581 | 1576 | ||
@@ -1665,6 +1660,12 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1665 | if (!adapter->nr_cmd_pending && adapter->last_scanned_channel) | 1660 | if (!adapter->nr_cmd_pending && adapter->last_scanned_channel) |
1666 | wlan_scan_networks(priv, NULL, 0); | 1661 | wlan_scan_networks(priv, NULL, 0); |
1667 | 1662 | ||
1663 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | ||
1664 | if ((adapter->inframode == wlan802_11ibss) && adapter->adhoccreate) { | ||
1665 | libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0, | ||
1666 | cmd_option_waitforrsp, 0, NULL); | ||
1667 | } | ||
1668 | |||
1668 | mutex_lock(&adapter->lock); | 1669 | mutex_lock(&adapter->lock); |
1669 | list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { | 1670 | list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { |
1670 | char * next_ev; | 1671 | char * next_ev; |