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

orinoco: convert scanning to cfg80211

This removes the custom scan cache used by orinoco.

We also have to avoid calling cfg80211_scan_done from the hard
interrupt, so we offload the entirety of scan processing to a workqueue.

This may behave strangely if you start scanning just prior to
suspending...

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

David Kilroy and committed by
John W. Linville
c63cdbe8 5217c571

+379 -745
+20
drivers/net/wireless/orinoco/cfg.c
··· 137 137 return err; 138 138 } 139 139 140 + static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, 141 + struct cfg80211_scan_request *request) 142 + { 143 + struct orinoco_private *priv = wiphy_priv(wiphy); 144 + int err; 145 + 146 + if (!request) 147 + return -EINVAL; 148 + 149 + if (priv->scan_request && priv->scan_request != request) 150 + return -EBUSY; 151 + 152 + priv->scan_request = request; 153 + 154 + err = orinoco_hw_trigger_scan(priv, request->ssids); 155 + 156 + return err; 157 + } 158 + 140 159 const struct cfg80211_ops orinoco_cfg_ops = { 141 160 .change_virtual_intf = orinoco_change_vif, 161 + .scan = orinoco_scan, 142 162 };
+1 -1
drivers/net/wireless/orinoco/hermes.h
··· 342 342 __le64 timestamp; 343 343 __le16 beacon_interval; 344 344 __le16 capabilities; 345 - u8 data[316]; 345 + u8 data[0]; 346 346 } __attribute__ ((packed)); 347 347 348 348 #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
+85
drivers/net/wireless/orinoco/hw.c
··· 1157 1157 1158 1158 return 0; 1159 1159 } 1160 + 1161 + int orinoco_hw_trigger_scan(struct orinoco_private *priv, 1162 + const struct cfg80211_ssid *ssid) 1163 + { 1164 + struct net_device *dev = priv->ndev; 1165 + hermes_t *hw = &priv->hw; 1166 + unsigned long flags; 1167 + int err = 0; 1168 + 1169 + if (orinoco_lock(priv, &flags) != 0) 1170 + return -EBUSY; 1171 + 1172 + /* Scanning with port 0 disabled would fail */ 1173 + if (!netif_running(dev)) { 1174 + err = -ENETDOWN; 1175 + goto out; 1176 + } 1177 + 1178 + /* In monitor mode, the scan results are always empty. 1179 + * Probe responses are passed to the driver as received 1180 + * frames and could be processed in software. */ 1181 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { 1182 + err = -EOPNOTSUPP; 1183 + goto out; 1184 + } 1185 + 1186 + if (priv->has_hostscan) { 1187 + switch (priv->firmware_type) { 1188 + case FIRMWARE_TYPE_SYMBOL: 1189 + err = hermes_write_wordrec(hw, USER_BAP, 1190 + HERMES_RID_CNFHOSTSCAN_SYMBOL, 1191 + HERMES_HOSTSCAN_SYMBOL_ONCE | 1192 + HERMES_HOSTSCAN_SYMBOL_BCAST); 1193 + break; 1194 + case FIRMWARE_TYPE_INTERSIL: { 1195 + __le16 req[3]; 1196 + 1197 + req[0] = cpu_to_le16(0x3fff); /* All channels */ 1198 + req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ 1199 + req[2] = 0; /* Any ESSID */ 1200 + err = HERMES_WRITE_RECORD(hw, USER_BAP, 1201 + HERMES_RID_CNFHOSTSCAN, &req); 1202 + break; 1203 + } 1204 + case FIRMWARE_TYPE_AGERE: 1205 + if (ssid->ssid_len > 0) { 1206 + struct hermes_idstring idbuf; 1207 + size_t len = ssid->ssid_len; 1208 + 1209 + idbuf.len = cpu_to_le16(len); 1210 + memcpy(idbuf.val, ssid->ssid, len); 1211 + 1212 + err = hermes_write_ltv(hw, USER_BAP, 1213 + HERMES_RID_CNFSCANSSID_AGERE, 1214 + HERMES_BYTES_TO_RECLEN(len + 2), 1215 + &idbuf); 1216 + } else 1217 + err = hermes_write_wordrec(hw, USER_BAP, 1218 + HERMES_RID_CNFSCANSSID_AGERE, 1219 + 0); /* Any ESSID */ 1220 + if (err) 1221 + break; 1222 + 1223 + if (priv->has_ext_scan) { 1224 + err = hermes_write_wordrec(hw, USER_BAP, 1225 + HERMES_RID_CNFSCANCHANNELS2GHZ, 1226 + 0x7FFF); 1227 + if (err) 1228 + goto out; 1229 + 1230 + err = hermes_inquire(hw, 1231 + HERMES_INQ_CHANNELINFO); 1232 + } else 1233 + err = hermes_inquire(hw, HERMES_INQ_SCAN); 1234 + 1235 + break; 1236 + } 1237 + } else 1238 + err = hermes_inquire(hw, HERMES_INQ_SCAN); 1239 + 1240 + out: 1241 + orinoco_unlock(priv, &flags); 1242 + 1243 + return err; 1244 + }
+3
drivers/net/wireless/orinoco/hw.h
··· 7 7 8 8 #include <linux/types.h> 9 9 #include <linux/wireless.h> 10 + #include <net/cfg80211.h> 10 11 11 12 /* Hardware BAPs */ 12 13 #define USER_BAP 0 ··· 48 47 int orinoco_hw_get_freq(struct orinoco_private *priv); 49 48 int orinoco_hw_get_bitratelist(struct orinoco_private *priv, 50 49 int *numrates, s32 *rates, int max); 50 + int orinoco_hw_trigger_scan(struct orinoco_private *priv, 51 + const struct cfg80211_ssid *ssid); 51 52 52 53 #endif /* _ORINOCO_HW_H_ */
+116 -51
drivers/net/wireless/orinoco/main.c
··· 206 206 struct list_head list; 207 207 }; 208 208 209 + struct orinoco_scan_data { 210 + void *buf; 211 + size_t len; 212 + int type; 213 + struct list_head list; 214 + }; 215 + 209 216 /********************************************************************/ 210 217 /* Function prototypes */ 211 218 /********************************************************************/ ··· 1272 1265 orinoco_unlock(priv, &flags); 1273 1266 } 1274 1267 1268 + static void qbuf_scan(struct orinoco_private *priv, void *buf, 1269 + int len, int type) 1270 + { 1271 + struct orinoco_scan_data *sd; 1272 + unsigned long flags; 1273 + 1274 + sd = kmalloc(sizeof(*sd), GFP_ATOMIC); 1275 + sd->buf = buf; 1276 + sd->len = len; 1277 + sd->type = type; 1278 + 1279 + spin_lock_irqsave(&priv->scan_lock, flags); 1280 + list_add_tail(&sd->list, &priv->scan_list); 1281 + spin_unlock_irqrestore(&priv->scan_lock, flags); 1282 + 1283 + schedule_work(&priv->process_scan); 1284 + } 1285 + 1286 + static void qabort_scan(struct orinoco_private *priv) 1287 + { 1288 + struct orinoco_scan_data *sd; 1289 + unsigned long flags; 1290 + 1291 + sd = kmalloc(sizeof(*sd), GFP_ATOMIC); 1292 + sd->len = -1; /* Abort */ 1293 + 1294 + spin_lock_irqsave(&priv->scan_lock, flags); 1295 + list_add_tail(&sd->list, &priv->scan_list); 1296 + spin_unlock_irqrestore(&priv->scan_lock, flags); 1297 + 1298 + schedule_work(&priv->process_scan); 1299 + } 1300 + 1301 + static void orinoco_process_scan_results(struct work_struct *work) 1302 + { 1303 + struct orinoco_private *priv = 1304 + container_of(work, struct orinoco_private, process_scan); 1305 + struct orinoco_scan_data *sd, *temp; 1306 + unsigned long flags; 1307 + void *buf; 1308 + int len; 1309 + int type; 1310 + 1311 + spin_lock_irqsave(&priv->scan_lock, flags); 1312 + list_for_each_entry_safe(sd, temp, &priv->scan_list, list) { 1313 + spin_unlock_irqrestore(&priv->scan_lock, flags); 1314 + 1315 + buf = sd->buf; 1316 + len = sd->len; 1317 + type = sd->type; 1318 + 1319 + list_del(&sd->list); 1320 + kfree(sd); 1321 + 1322 + if (len > 0) { 1323 + if (type == HERMES_INQ_CHANNELINFO) 1324 + orinoco_add_extscan_result(priv, buf, len); 1325 + else 1326 + orinoco_add_hostscan_results(priv, buf, len); 1327 + 1328 + kfree(buf); 1329 + } else if (priv->scan_request) { 1330 + /* Either abort or complete the scan */ 1331 + cfg80211_scan_done(priv->scan_request, (len < 0)); 1332 + priv->scan_request = NULL; 1333 + } 1334 + 1335 + spin_lock_irqsave(&priv->scan_lock, flags); 1336 + } 1337 + spin_unlock_irqrestore(&priv->scan_lock, flags); 1338 + } 1339 + 1275 1340 static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) 1276 1341 { 1277 1342 struct orinoco_private *priv = ndev_priv(dev); ··· 1430 1351 * the hostscan frame can be requested. */ 1431 1352 if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && 1432 1353 priv->firmware_type == FIRMWARE_TYPE_SYMBOL && 1433 - priv->has_hostscan && priv->scan_inprogress) { 1354 + priv->has_hostscan && priv->scan_request) { 1434 1355 hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); 1435 1356 break; 1436 1357 } ··· 1456 1377 } 1457 1378 break; 1458 1379 case HERMES_INQ_SCAN: 1459 - if (!priv->scan_inprogress && priv->bssid_fixed && 1380 + if (!priv->scan_request && priv->bssid_fixed && 1460 1381 priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { 1461 1382 schedule_work(&priv->join_work); 1462 1383 break; ··· 1466 1387 case HERMES_INQ_HOSTSCAN_SYMBOL: { 1467 1388 /* Result of a scanning. Contains information about 1468 1389 * cells in the vicinity - Jean II */ 1469 - union iwreq_data wrqu; 1470 1390 unsigned char *buf; 1471 - 1472 - /* Scan is no longer in progress */ 1473 - priv->scan_inprogress = 0; 1474 1391 1475 1392 /* Sanity check */ 1476 1393 if (len > 4096) { 1477 1394 printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", 1478 1395 dev->name, len); 1396 + qabort_scan(priv); 1479 1397 break; 1480 1398 } 1481 1399 1482 1400 /* Allocate buffer for results */ 1483 1401 buf = kmalloc(len, GFP_ATOMIC); 1484 - if (buf == NULL) 1402 + if (buf == NULL) { 1485 1403 /* No memory, so can't printk()... */ 1404 + qabort_scan(priv); 1486 1405 break; 1406 + } 1487 1407 1488 1408 /* Read scan data */ 1489 1409 err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, 1490 1410 infofid, sizeof(info)); 1491 1411 if (err) { 1492 1412 kfree(buf); 1413 + qabort_scan(priv); 1493 1414 break; 1494 1415 } 1495 1416 ··· 1503 1424 } 1504 1425 #endif /* ORINOCO_DEBUG */ 1505 1426 1506 - if (orinoco_process_scan_results(priv, buf, len) == 0) { 1507 - /* Send an empty event to user space. 1508 - * We don't send the received data on the event because 1509 - * it would require us to do complex transcoding, and 1510 - * we want to minimise the work done in the irq handler 1511 - * Use a request to extract the data - Jean II */ 1512 - wrqu.data.length = 0; 1513 - wrqu.data.flags = 0; 1514 - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 1515 - } 1516 - kfree(buf); 1427 + qbuf_scan(priv, buf, len, type); 1517 1428 } 1518 1429 break; 1519 1430 case HERMES_INQ_CHANNELINFO: 1520 1431 { 1521 1432 struct agere_ext_scan_info *bss; 1522 1433 1523 - if (!priv->scan_inprogress) { 1434 + if (!priv->scan_request) { 1524 1435 printk(KERN_DEBUG "%s: Got chaninfo without scan, " 1525 1436 "len=%d\n", dev->name, len); 1526 1437 break; ··· 1518 1449 1519 1450 /* An empty result indicates that the scan is complete */ 1520 1451 if (len == 0) { 1521 - union iwreq_data wrqu; 1522 - 1523 - /* Scan is no longer in progress */ 1524 - priv->scan_inprogress = 0; 1525 - 1526 - wrqu.data.length = 0; 1527 - wrqu.data.flags = 0; 1528 - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 1452 + qbuf_scan(priv, NULL, len, type); 1529 1453 break; 1530 1454 } 1531 1455 1532 1456 /* Sanity check */ 1533 - else if (len > sizeof(*bss)) { 1534 - printk(KERN_WARNING 1535 - "%s: Ext scan results too large (%d bytes). " 1536 - "Truncating results to %zd bytes.\n", 1537 - dev->name, len, sizeof(*bss)); 1538 - len = sizeof(*bss); 1539 - } else if (len < (offsetof(struct agere_ext_scan_info, 1457 + else if (len < (offsetof(struct agere_ext_scan_info, 1540 1458 data) + 2)) { 1541 1459 /* Drop this result now so we don't have to 1542 1460 * keep checking later */ ··· 1533 1477 break; 1534 1478 } 1535 1479 1536 - bss = kmalloc(sizeof(*bss), GFP_ATOMIC); 1480 + bss = kmalloc(len, GFP_ATOMIC); 1537 1481 if (bss == NULL) 1538 1482 break; 1539 1483 1540 1484 /* Read scan data */ 1541 1485 err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len, 1542 1486 infofid, sizeof(info)); 1543 - if (err) { 1487 + if (err) 1544 1488 kfree(bss); 1545 - break; 1546 - } 1489 + else 1490 + qbuf_scan(priv, bss, len, type); 1547 1491 1548 - orinoco_add_ext_scan_result(priv, bss); 1549 - 1550 - kfree(bss); 1551 1492 break; 1552 1493 } 1553 1494 case HERMES_INQ_SEC_STAT_AGERE: ··· 1559 1506 /* We don't actually do anything about it */ 1560 1507 break; 1561 1508 } 1509 + 1510 + return; 1562 1511 } 1563 1512 1564 1513 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) ··· 1704 1649 1705 1650 orinoco_unlock(priv, &flags); 1706 1651 1707 - /* Scanning support: Cleanup of driver struct */ 1708 - orinoco_clear_scan_results(priv, 0); 1709 - priv->scan_inprogress = 0; 1652 + /* Scanning support: Notify scan cancellation */ 1653 + if (priv->scan_request) { 1654 + cfg80211_scan_done(priv->scan_request, 1); 1655 + priv->scan_request = NULL; 1656 + } 1710 1657 1711 1658 if (priv->hard_reset) { 1712 1659 err = (*priv->hard_reset)(priv); ··· 2022 1965 } 2023 1966 } 2024 1967 2025 - /* Now we have the firmware capabilities, allocate appropiate 2026 - * sized scan buffers */ 2027 - if (orinoco_bss_data_allocate(priv)) 2028 - goto out; 2029 - orinoco_bss_data_init(priv); 2030 - 2031 1968 err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr); 2032 1969 if (err) 2033 1970 goto out; ··· 2151 2100 tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet, 2152 2101 (unsigned long) priv); 2153 2102 2103 + spin_lock_init(&priv->scan_lock); 2104 + INIT_LIST_HEAD(&priv->scan_list); 2105 + INIT_WORK(&priv->process_scan, orinoco_process_scan_results); 2106 + 2154 2107 priv->last_linkstatus = 0xffff; 2155 2108 2156 2109 #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) ··· 2247 2192 { 2248 2193 struct wiphy *wiphy = priv_to_wiphy(priv); 2249 2194 struct orinoco_rx_data *rx_data, *temp; 2195 + struct orinoco_scan_data *sd, *sdtemp; 2250 2196 2251 2197 wiphy_unregister(wiphy); 2252 2198 ··· 2265 2209 kfree(rx_data); 2266 2210 } 2267 2211 2212 + cancel_work_sync(&priv->process_scan); 2213 + /* Explicitly drain priv->scan_list */ 2214 + list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { 2215 + list_del(&sd->list); 2216 + 2217 + if ((sd->len > 0) && sd->buf) 2218 + kfree(sd->buf); 2219 + kfree(sd); 2220 + } 2221 + 2268 2222 orinoco_unregister_pm_notifier(priv); 2269 2223 orinoco_uncache_fw(priv); 2270 2224 2271 2225 priv->wpa_ie_len = 0; 2272 2226 kfree(priv->wpa_ie); 2273 2227 orinoco_mic_free(priv); 2274 - orinoco_bss_data_free(priv); 2275 2228 wiphy_free(wiphy); 2276 2229 } 2277 2230 EXPORT_SYMBOL(free_orinocodev);
+4 -18
drivers/net/wireless/orinoco/orinoco.h
··· 48 48 FIRMWARE_TYPE_SYMBOL 49 49 } fwtype_t; 50 50 51 - struct bss_element { 52 - union hermes_scan_info bss; 53 - unsigned long last_scanned; 54 - struct list_head list; 55 - }; 56 - 57 - struct xbss_element { 58 - struct agere_ext_scan_info bss; 59 - unsigned long last_scanned; 60 - struct list_head list; 61 - }; 62 - 63 51 struct firmware; 64 52 65 53 struct orinoco_private { ··· 133 145 int promiscuous, mc_count; 134 146 135 147 /* Scanning support */ 136 - struct list_head bss_list; 137 - struct list_head bss_free_list; 138 - void *bss_xbss_data; 139 - 140 - int scan_inprogress; /* Scan pending... */ 141 - u32 scan_mode; /* Type of scan done */ 148 + struct cfg80211_scan_request *scan_request; 149 + struct work_struct process_scan; 150 + struct list_head scan_list; 151 + spinlock_t scan_lock; /* protects the scan list */ 142 152 143 153 /* WPA support */ 144 154 u8 *wpa_ie;
+142 -145
drivers/net/wireless/orinoco/scan.c
··· 5 5 6 6 #include <linux/kernel.h> 7 7 #include <linux/string.h> 8 - #include <linux/etherdevice.h> 8 + #include <linux/ieee80211.h> 9 + #include <net/cfg80211.h> 9 10 10 11 #include "hermes.h" 11 12 #include "orinoco.h" 13 + #include "main.h" 12 14 13 15 #include "scan.h" 14 16 15 - #define ORINOCO_MAX_BSS_COUNT 64 17 + #define ZERO_DBM_OFFSET 0x95 18 + #define MAX_SIGNAL_LEVEL 0x8A 19 + #define MIN_SIGNAL_LEVEL 0x2F 16 20 17 - #define PRIV_BSS ((struct bss_element *)priv->bss_xbss_data) 18 - #define PRIV_XBSS ((struct xbss_element *)priv->bss_xbss_data) 21 + #define SIGNAL_TO_DBM(x) \ 22 + (clamp_t(s32, (x), MIN_SIGNAL_LEVEL, MAX_SIGNAL_LEVEL) \ 23 + - ZERO_DBM_OFFSET) 24 + #define SIGNAL_TO_MBM(x) (SIGNAL_TO_DBM(x) * 100) 19 25 20 - int orinoco_bss_data_allocate(struct orinoco_private *priv) 26 + static int symbol_build_supp_rates(u8 *buf, const __le16 *rates) 21 27 { 22 - if (priv->bss_xbss_data) 23 - return 0; 28 + int i; 29 + u8 rate; 24 30 25 - if (priv->has_ext_scan) 26 - priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT * 27 - sizeof(struct xbss_element), 28 - GFP_KERNEL); 29 - else 30 - priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT * 31 - sizeof(struct bss_element), 32 - GFP_KERNEL); 33 - 34 - if (!priv->bss_xbss_data) { 35 - printk(KERN_WARNING "Out of memory allocating beacons"); 36 - return -ENOMEM; 31 + buf[0] = WLAN_EID_SUPP_RATES; 32 + for (i = 0; i < 5; i++) { 33 + rate = le16_to_cpu(rates[i]); 34 + /* NULL terminated */ 35 + if (rate == 0x0) 36 + break; 37 + buf[i + 2] = rate; 37 38 } 38 - return 0; 39 + buf[1] = i; 40 + 41 + return i + 2; 39 42 } 40 43 41 - void orinoco_bss_data_free(struct orinoco_private *priv) 42 - { 43 - kfree(priv->bss_xbss_data); 44 - priv->bss_xbss_data = NULL; 45 - } 46 - 47 - void orinoco_bss_data_init(struct orinoco_private *priv) 44 + static int prism_build_supp_rates(u8 *buf, const u8 *rates) 48 45 { 49 46 int i; 50 47 51 - INIT_LIST_HEAD(&priv->bss_free_list); 52 - INIT_LIST_HEAD(&priv->bss_list); 53 - if (priv->has_ext_scan) 54 - for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++) 55 - list_add_tail(&(PRIV_XBSS[i].list), 56 - &priv->bss_free_list); 57 - else 58 - for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++) 59 - list_add_tail(&(PRIV_BSS[i].list), 60 - &priv->bss_free_list); 61 - 62 - } 63 - 64 - void orinoco_clear_scan_results(struct orinoco_private *priv, 65 - unsigned long scan_age) 66 - { 67 - if (priv->has_ext_scan) { 68 - struct xbss_element *bss; 69 - struct xbss_element *tmp_bss; 70 - 71 - /* Blow away current list of scan results */ 72 - list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) { 73 - if (!scan_age || 74 - time_after(jiffies, bss->last_scanned + scan_age)) { 75 - list_move_tail(&bss->list, 76 - &priv->bss_free_list); 77 - /* Don't blow away ->list, just BSS data */ 78 - memset(&bss->bss, 0, sizeof(bss->bss)); 79 - bss->last_scanned = 0; 80 - } 81 - } 82 - } else { 83 - struct bss_element *bss; 84 - struct bss_element *tmp_bss; 85 - 86 - /* Blow away current list of scan results */ 87 - list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) { 88 - if (!scan_age || 89 - time_after(jiffies, bss->last_scanned + scan_age)) { 90 - list_move_tail(&bss->list, 91 - &priv->bss_free_list); 92 - /* Don't blow away ->list, just BSS data */ 93 - memset(&bss->bss, 0, sizeof(bss->bss)); 94 - bss->last_scanned = 0; 95 - } 96 - } 48 + buf[0] = WLAN_EID_SUPP_RATES; 49 + for (i = 0; i < 8; i++) { 50 + /* NULL terminated */ 51 + if (rates[i] == 0x0) 52 + break; 53 + buf[i + 2] = rates[i]; 97 54 } 55 + buf[1] = i; 56 + 57 + /* We might still have another 2 rates, which need to go in 58 + * extended supported rates */ 59 + if (i == 8 && rates[i] > 0) { 60 + buf[10] = WLAN_EID_EXT_SUPP_RATES; 61 + for (; i < 10; i++) { 62 + /* NULL terminated */ 63 + if (rates[i] == 0x0) 64 + break; 65 + buf[i + 2] = rates[i]; 66 + } 67 + buf[11] = i - 8; 68 + } 69 + 70 + return (i < 8) ? i + 2 : i + 4; 98 71 } 99 72 100 - void orinoco_add_ext_scan_result(struct orinoco_private *priv, 101 - struct agere_ext_scan_info *atom) 73 + static void orinoco_add_hostscan_result(struct orinoco_private *priv, 74 + const union hermes_scan_info *bss) 102 75 { 103 - struct xbss_element *bss = NULL; 104 - int found = 0; 76 + struct wiphy *wiphy = priv_to_wiphy(priv); 77 + struct ieee80211_channel *channel; 78 + u8 *ie; 79 + u8 ie_buf[46]; 80 + u64 timestamp; 81 + s32 signal; 82 + u16 capability; 83 + u16 beacon_interval; 84 + int ie_len; 85 + int freq; 86 + int len; 105 87 106 - /* Try to update an existing bss first */ 107 - list_for_each_entry(bss, &priv->bss_list, list) { 108 - if (compare_ether_addr(bss->bss.bssid, atom->bssid)) 109 - continue; 110 - /* ESSID lengths */ 111 - if (bss->bss.data[1] != atom->data[1]) 112 - continue; 113 - if (memcmp(&bss->bss.data[2], &atom->data[2], 114 - atom->data[1])) 115 - continue; 116 - found = 1; 88 + len = le16_to_cpu(bss->a.essid_len); 89 + 90 + /* Reconstruct SSID and bitrate IEs to pass up */ 91 + ie_buf[0] = WLAN_EID_SSID; 92 + ie_buf[1] = len; 93 + memcpy(&ie_buf[2], bss->a.essid, len); 94 + 95 + ie = ie_buf + len + 2; 96 + ie_len = ie_buf[1] + 2; 97 + switch (priv->firmware_type) { 98 + case FIRMWARE_TYPE_SYMBOL: 99 + ie_len += symbol_build_supp_rates(ie, bss->s.rates); 100 + break; 101 + 102 + case FIRMWARE_TYPE_INTERSIL: 103 + ie_len += prism_build_supp_rates(ie, bss->p.rates); 104 + break; 105 + 106 + case FIRMWARE_TYPE_AGERE: 107 + default: 117 108 break; 118 109 } 119 110 120 - /* Grab a bss off the free list */ 121 - if (!found && !list_empty(&priv->bss_free_list)) { 122 - bss = list_entry(priv->bss_free_list.next, 123 - struct xbss_element, list); 124 - list_del(priv->bss_free_list.next); 111 + freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel)); 112 + channel = ieee80211_get_channel(wiphy, freq); 113 + timestamp = 0; 114 + capability = le16_to_cpu(bss->a.capabilities); 115 + beacon_interval = le16_to_cpu(bss->a.beacon_interv); 116 + signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level)); 125 117 126 - list_add_tail(&bss->list, &priv->bss_list); 127 - } 128 - 129 - if (bss) { 130 - /* Always update the BSS to get latest beacon info */ 131 - memcpy(&bss->bss, atom, sizeof(bss->bss)); 132 - bss->last_scanned = jiffies; 133 - } 118 + cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, 119 + capability, beacon_interval, ie_buf, ie_len, 120 + signal, GFP_KERNEL); 134 121 } 135 122 136 - int orinoco_process_scan_results(struct orinoco_private *priv, 137 - unsigned char *buf, 138 - int len) 123 + void orinoco_add_extscan_result(struct orinoco_private *priv, 124 + struct agere_ext_scan_info *bss, 125 + size_t len) 139 126 { 140 - int offset; /* In the scan data */ 141 - union hermes_scan_info *atom; 142 - int atom_len; 127 + struct wiphy *wiphy = priv_to_wiphy(priv); 128 + struct ieee80211_channel *channel; 129 + u8 *ie; 130 + u64 timestamp; 131 + s32 signal; 132 + u16 capability; 133 + u16 beacon_interval; 134 + size_t ie_len; 135 + int chan, freq; 136 + 137 + ie_len = len - sizeof(*bss); 138 + ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS); 139 + chan = ie ? ie[2] : 0; 140 + freq = ieee80211_dsss_chan_to_freq(chan); 141 + channel = ieee80211_get_channel(wiphy, freq); 142 + 143 + timestamp = le64_to_cpu(bss->timestamp); 144 + capability = le16_to_cpu(bss->capabilities); 145 + beacon_interval = le16_to_cpu(bss->beacon_interval); 146 + ie = bss->data; 147 + signal = SIGNAL_TO_MBM(bss->level); 148 + 149 + cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, 150 + capability, beacon_interval, ie, ie_len, 151 + signal, GFP_KERNEL); 152 + } 153 + 154 + void orinoco_add_hostscan_results(struct orinoco_private *priv, 155 + unsigned char *buf, 156 + size_t len) 157 + { 158 + int offset; /* In the scan data */ 159 + size_t atom_len; 160 + bool abort = false; 143 161 144 162 switch (priv->firmware_type) { 145 163 case FIRMWARE_TYPE_AGERE: 146 164 atom_len = sizeof(struct agere_scan_apinfo); 147 165 offset = 0; 148 166 break; 167 + 149 168 case FIRMWARE_TYPE_SYMBOL: 150 169 /* Lack of documentation necessitates this hack. 151 170 * Different firmwares have 68 or 76 byte long atoms. ··· 182 163 atom_len = 68; 183 164 offset = 0; 184 165 break; 166 + 185 167 case FIRMWARE_TYPE_INTERSIL: 186 168 offset = 4; 187 169 if (priv->has_hostscan) { ··· 192 172 printk(KERN_ERR "%s: Invalid atom_len in scan " 193 173 "data: %d\n", priv->ndev->name, 194 174 atom_len); 195 - return -EIO; 175 + abort = true; 176 + goto scan_abort; 196 177 } 197 178 } else 198 179 atom_len = offsetof(struct prism2_scan_apinfo, atim); 199 180 break; 181 + 200 182 default: 201 - return -EOPNOTSUPP; 183 + abort = true; 184 + goto scan_abort; 202 185 } 203 186 204 187 /* Check that we got an whole number of atoms */ ··· 209 186 printk(KERN_ERR "%s: Unexpected scan data length %d, " 210 187 "atom_len %d, offset %d\n", priv->ndev->name, len, 211 188 atom_len, offset); 212 - return -EIO; 189 + abort = true; 190 + goto scan_abort; 213 191 } 214 192 215 - orinoco_clear_scan_results(priv, msecs_to_jiffies(15000)); 216 - 217 - /* Read the entries one by one */ 193 + /* Process the entries one by one */ 218 194 for (; offset + atom_len <= len; offset += atom_len) { 219 - int found = 0; 220 - struct bss_element *bss = NULL; 195 + union hermes_scan_info *atom; 221 196 222 - /* Get next atom */ 223 197 atom = (union hermes_scan_info *) (buf + offset); 224 198 225 - /* Try to update an existing bss first */ 226 - list_for_each_entry(bss, &priv->bss_list, list) { 227 - if (compare_ether_addr(bss->bss.a.bssid, atom->a.bssid)) 228 - continue; 229 - if (le16_to_cpu(bss->bss.a.essid_len) != 230 - le16_to_cpu(atom->a.essid_len)) 231 - continue; 232 - if (memcmp(bss->bss.a.essid, atom->a.essid, 233 - le16_to_cpu(atom->a.essid_len))) 234 - continue; 235 - found = 1; 236 - break; 237 - } 238 - 239 - /* Grab a bss off the free list */ 240 - if (!found && !list_empty(&priv->bss_free_list)) { 241 - bss = list_entry(priv->bss_free_list.next, 242 - struct bss_element, list); 243 - list_del(priv->bss_free_list.next); 244 - 245 - list_add_tail(&bss->list, &priv->bss_list); 246 - } 247 - 248 - if (bss) { 249 - /* Always update the BSS to get latest beacon info */ 250 - memcpy(&bss->bss, atom, sizeof(bss->bss)); 251 - bss->last_scanned = jiffies; 252 - } 199 + orinoco_add_hostscan_result(priv, atom); 253 200 } 254 201 255 - return 0; 202 + scan_abort: 203 + if (priv->scan_request) { 204 + cfg80211_scan_done(priv->scan_request, abort); 205 + priv->scan_request = NULL; 206 + } 256 207 }
+6 -15
drivers/net/wireless/orinoco/scan.h
··· 9 9 struct orinoco_private; 10 10 struct agere_ext_scan_info; 11 11 12 - /* Setup and free memory for scan results */ 13 - int orinoco_bss_data_allocate(struct orinoco_private *priv); 14 - void orinoco_bss_data_free(struct orinoco_private *priv); 15 - void orinoco_bss_data_init(struct orinoco_private *priv); 16 - 17 12 /* Add scan results */ 18 - void orinoco_add_ext_scan_result(struct orinoco_private *priv, 19 - struct agere_ext_scan_info *atom); 20 - int orinoco_process_scan_results(struct orinoco_private *dev, 21 - unsigned char *buf, 22 - int len); 23 - 24 - /* Clear scan results */ 25 - void orinoco_clear_scan_results(struct orinoco_private *priv, 26 - unsigned long scan_age); 27 - 13 + void orinoco_add_extscan_result(struct orinoco_private *priv, 14 + struct agere_ext_scan_info *atom, 15 + size_t len); 16 + void orinoco_add_hostscan_results(struct orinoco_private *dev, 17 + unsigned char *buf, 18 + size_t len); 28 19 29 20 #endif /* _ORINOCO_SCAN_H_ */
+2 -515
drivers/net/wireless/orinoco/wext.c
··· 1583 1583 return err; 1584 1584 } 1585 1585 1586 - /* Trigger a scan (look for other cells in the vicinity) */ 1587 - static int orinoco_ioctl_setscan(struct net_device *dev, 1588 - struct iw_request_info *info, 1589 - struct iw_point *srq, 1590 - char *extra) 1591 - { 1592 - struct orinoco_private *priv = ndev_priv(dev); 1593 - hermes_t *hw = &priv->hw; 1594 - struct iw_scan_req *si = (struct iw_scan_req *) extra; 1595 - int err = 0; 1596 - unsigned long flags; 1597 - 1598 - /* Note : you may have realised that, as this is a SET operation, 1599 - * this is privileged and therefore a normal user can't 1600 - * perform scanning. 1601 - * This is not an error, while the device perform scanning, 1602 - * traffic doesn't flow, so it's a perfect DoS... 1603 - * Jean II */ 1604 - 1605 - if (orinoco_lock(priv, &flags) != 0) 1606 - return -EBUSY; 1607 - 1608 - /* Scanning with port 0 disabled would fail */ 1609 - if (!netif_running(dev)) { 1610 - err = -ENETDOWN; 1611 - goto out; 1612 - } 1613 - 1614 - /* In monitor mode, the scan results are always empty. 1615 - * Probe responses are passed to the driver as received 1616 - * frames and could be processed in software. */ 1617 - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { 1618 - err = -EOPNOTSUPP; 1619 - goto out; 1620 - } 1621 - 1622 - /* Note : because we don't lock out the irq handler, the way 1623 - * we access scan variables in priv is critical. 1624 - * o scan_inprogress : not touched by irq handler 1625 - * o scan_mode : not touched by irq handler 1626 - * Before modifying anything on those variables, please think hard ! 1627 - * Jean II */ 1628 - 1629 - /* Save flags */ 1630 - priv->scan_mode = srq->flags; 1631 - 1632 - /* Always trigger scanning, even if it's in progress. 1633 - * This way, if the info frame get lost, we will recover somewhat 1634 - * gracefully - Jean II */ 1635 - 1636 - if (priv->has_hostscan) { 1637 - switch (priv->firmware_type) { 1638 - case FIRMWARE_TYPE_SYMBOL: 1639 - err = hermes_write_wordrec(hw, USER_BAP, 1640 - HERMES_RID_CNFHOSTSCAN_SYMBOL, 1641 - HERMES_HOSTSCAN_SYMBOL_ONCE | 1642 - HERMES_HOSTSCAN_SYMBOL_BCAST); 1643 - break; 1644 - case FIRMWARE_TYPE_INTERSIL: { 1645 - __le16 req[3]; 1646 - 1647 - req[0] = cpu_to_le16(0x3fff); /* All channels */ 1648 - req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ 1649 - req[2] = 0; /* Any ESSID */ 1650 - err = HERMES_WRITE_RECORD(hw, USER_BAP, 1651 - HERMES_RID_CNFHOSTSCAN, &req); 1652 - } 1653 - break; 1654 - case FIRMWARE_TYPE_AGERE: 1655 - if (priv->scan_mode & IW_SCAN_THIS_ESSID) { 1656 - struct hermes_idstring idbuf; 1657 - size_t len = min(sizeof(idbuf.val), 1658 - (size_t) si->essid_len); 1659 - idbuf.len = cpu_to_le16(len); 1660 - memcpy(idbuf.val, si->essid, len); 1661 - 1662 - err = hermes_write_ltv(hw, USER_BAP, 1663 - HERMES_RID_CNFSCANSSID_AGERE, 1664 - HERMES_BYTES_TO_RECLEN(len + 2), 1665 - &idbuf); 1666 - } else 1667 - err = hermes_write_wordrec(hw, USER_BAP, 1668 - HERMES_RID_CNFSCANSSID_AGERE, 1669 - 0); /* Any ESSID */ 1670 - if (err) 1671 - break; 1672 - 1673 - if (priv->has_ext_scan) { 1674 - /* Clear scan results at the start of 1675 - * an extended scan */ 1676 - orinoco_clear_scan_results(priv, 1677 - msecs_to_jiffies(15000)); 1678 - 1679 - /* TODO: Is this available on older firmware? 1680 - * Can we use it to scan specific channels 1681 - * for IW_SCAN_THIS_FREQ? */ 1682 - err = hermes_write_wordrec(hw, USER_BAP, 1683 - HERMES_RID_CNFSCANCHANNELS2GHZ, 1684 - 0x7FFF); 1685 - if (err) 1686 - goto out; 1687 - 1688 - err = hermes_inquire(hw, 1689 - HERMES_INQ_CHANNELINFO); 1690 - } else 1691 - err = hermes_inquire(hw, HERMES_INQ_SCAN); 1692 - break; 1693 - } 1694 - } else 1695 - err = hermes_inquire(hw, HERMES_INQ_SCAN); 1696 - 1697 - /* One more client */ 1698 - if (!err) 1699 - priv->scan_inprogress = 1; 1700 - 1701 - out: 1702 - orinoco_unlock(priv, &flags); 1703 - return err; 1704 - } 1705 - 1706 - #define MAX_CUSTOM_LEN 64 1707 - 1708 - /* Translate scan data returned from the card to a card independant 1709 - * format that the Wireless Tools will understand - Jean II */ 1710 - static inline char *orinoco_translate_scan(struct net_device *dev, 1711 - struct iw_request_info *info, 1712 - char *current_ev, 1713 - char *end_buf, 1714 - union hermes_scan_info *bss, 1715 - unsigned long last_scanned) 1716 - { 1717 - struct orinoco_private *priv = ndev_priv(dev); 1718 - u16 capabilities; 1719 - u16 channel; 1720 - struct iw_event iwe; /* Temporary buffer */ 1721 - char custom[MAX_CUSTOM_LEN]; 1722 - 1723 - memset(&iwe, 0, sizeof(iwe)); 1724 - 1725 - /* First entry *MUST* be the AP MAC address */ 1726 - iwe.cmd = SIOCGIWAP; 1727 - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 1728 - memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN); 1729 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1730 - &iwe, IW_EV_ADDR_LEN); 1731 - 1732 - /* Other entries will be displayed in the order we give them */ 1733 - 1734 - /* Add the ESSID */ 1735 - iwe.u.data.length = le16_to_cpu(bss->a.essid_len); 1736 - if (iwe.u.data.length > 32) 1737 - iwe.u.data.length = 32; 1738 - iwe.cmd = SIOCGIWESSID; 1739 - iwe.u.data.flags = 1; 1740 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1741 - &iwe, bss->a.essid); 1742 - 1743 - /* Add mode */ 1744 - iwe.cmd = SIOCGIWMODE; 1745 - capabilities = le16_to_cpu(bss->a.capabilities); 1746 - if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { 1747 - if (capabilities & WLAN_CAPABILITY_ESS) 1748 - iwe.u.mode = IW_MODE_MASTER; 1749 - else 1750 - iwe.u.mode = IW_MODE_ADHOC; 1751 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1752 - &iwe, IW_EV_UINT_LEN); 1753 - } 1754 - 1755 - channel = bss->s.channel; 1756 - if ((channel >= 1) && (channel <= NUM_CHANNELS)) { 1757 - /* Add channel and frequency */ 1758 - iwe.cmd = SIOCGIWFREQ; 1759 - iwe.u.freq.m = channel; 1760 - iwe.u.freq.e = 0; 1761 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1762 - &iwe, IW_EV_FREQ_LEN); 1763 - 1764 - iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; 1765 - iwe.u.freq.e = 1; 1766 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1767 - &iwe, IW_EV_FREQ_LEN); 1768 - } 1769 - 1770 - /* Add quality statistics. level and noise in dB. No link quality */ 1771 - iwe.cmd = IWEVQUAL; 1772 - iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID; 1773 - iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95; 1774 - iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95; 1775 - /* Wireless tools prior to 27.pre22 will show link quality 1776 - * anyway, so we provide a reasonable value. */ 1777 - if (iwe.u.qual.level > iwe.u.qual.noise) 1778 - iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; 1779 - else 1780 - iwe.u.qual.qual = 0; 1781 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1782 - &iwe, IW_EV_QUAL_LEN); 1783 - 1784 - /* Add encryption capability */ 1785 - iwe.cmd = SIOCGIWENCODE; 1786 - if (capabilities & WLAN_CAPABILITY_PRIVACY) 1787 - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 1788 - else 1789 - iwe.u.data.flags = IW_ENCODE_DISABLED; 1790 - iwe.u.data.length = 0; 1791 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1792 - &iwe, NULL); 1793 - 1794 - /* Bit rate is not available in Lucent/Agere firmwares */ 1795 - if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { 1796 - char *current_val = current_ev + iwe_stream_lcp_len(info); 1797 - int i; 1798 - int step; 1799 - 1800 - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) 1801 - step = 2; 1802 - else 1803 - step = 1; 1804 - 1805 - iwe.cmd = SIOCGIWRATE; 1806 - /* Those two flags are ignored... */ 1807 - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 1808 - /* Max 10 values */ 1809 - for (i = 0; i < 10; i += step) { 1810 - /* NULL terminated */ 1811 - if (bss->p.rates[i] == 0x0) 1812 - break; 1813 - /* Bit rate given in 500 kb/s units (+ 0x80) */ 1814 - iwe.u.bitrate.value = 1815 - ((bss->p.rates[i] & 0x7f) * 500000); 1816 - current_val = iwe_stream_add_value(info, current_ev, 1817 - current_val, 1818 - end_buf, &iwe, 1819 - IW_EV_PARAM_LEN); 1820 - } 1821 - /* Check if we added any event */ 1822 - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) 1823 - current_ev = current_val; 1824 - } 1825 - 1826 - /* Beacon interval */ 1827 - iwe.cmd = IWEVCUSTOM; 1828 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1829 - "bcn_int=%d", 1830 - le16_to_cpu(bss->a.beacon_interv)); 1831 - if (iwe.u.data.length) 1832 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1833 - &iwe, custom); 1834 - 1835 - /* Capabilites */ 1836 - iwe.cmd = IWEVCUSTOM; 1837 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1838 - "capab=0x%04x", 1839 - capabilities); 1840 - if (iwe.u.data.length) 1841 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1842 - &iwe, custom); 1843 - 1844 - /* Add EXTRA: Age to display seconds since last beacon/probe response 1845 - * for given network. */ 1846 - iwe.cmd = IWEVCUSTOM; 1847 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1848 - " Last beacon: %dms ago", 1849 - jiffies_to_msecs(jiffies - last_scanned)); 1850 - if (iwe.u.data.length) 1851 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1852 - &iwe, custom); 1853 - 1854 - return current_ev; 1855 - } 1856 - 1857 - static inline char *orinoco_translate_ext_scan(struct net_device *dev, 1858 - struct iw_request_info *info, 1859 - char *current_ev, 1860 - char *end_buf, 1861 - struct agere_ext_scan_info *bss, 1862 - unsigned long last_scanned) 1863 - { 1864 - u16 capabilities; 1865 - u16 channel; 1866 - struct iw_event iwe; /* Temporary buffer */ 1867 - char custom[MAX_CUSTOM_LEN]; 1868 - u8 *ie; 1869 - 1870 - memset(&iwe, 0, sizeof(iwe)); 1871 - 1872 - /* First entry *MUST* be the AP MAC address */ 1873 - iwe.cmd = SIOCGIWAP; 1874 - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 1875 - memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); 1876 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1877 - &iwe, IW_EV_ADDR_LEN); 1878 - 1879 - /* Other entries will be displayed in the order we give them */ 1880 - 1881 - /* Add the ESSID */ 1882 - ie = bss->data; 1883 - iwe.u.data.length = ie[1]; 1884 - if (iwe.u.data.length) { 1885 - if (iwe.u.data.length > 32) 1886 - iwe.u.data.length = 32; 1887 - iwe.cmd = SIOCGIWESSID; 1888 - iwe.u.data.flags = 1; 1889 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1890 - &iwe, &ie[2]); 1891 - } 1892 - 1893 - /* Add mode */ 1894 - capabilities = le16_to_cpu(bss->capabilities); 1895 - if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { 1896 - iwe.cmd = SIOCGIWMODE; 1897 - if (capabilities & WLAN_CAPABILITY_ESS) 1898 - iwe.u.mode = IW_MODE_MASTER; 1899 - else 1900 - iwe.u.mode = IW_MODE_ADHOC; 1901 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1902 - &iwe, IW_EV_UINT_LEN); 1903 - } 1904 - 1905 - ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS); 1906 - channel = ie ? ie[2] : 0; 1907 - if ((channel >= 1) && (channel <= NUM_CHANNELS)) { 1908 - /* Add channel and frequency */ 1909 - iwe.cmd = SIOCGIWFREQ; 1910 - iwe.u.freq.m = channel; 1911 - iwe.u.freq.e = 0; 1912 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1913 - &iwe, IW_EV_FREQ_LEN); 1914 - 1915 - iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; 1916 - iwe.u.freq.e = 1; 1917 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1918 - &iwe, IW_EV_FREQ_LEN); 1919 - } 1920 - 1921 - /* Add quality statistics. level and noise in dB. No link quality */ 1922 - iwe.cmd = IWEVQUAL; 1923 - iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID; 1924 - iwe.u.qual.level = bss->level - 0x95; 1925 - iwe.u.qual.noise = bss->noise - 0x95; 1926 - /* Wireless tools prior to 27.pre22 will show link quality 1927 - * anyway, so we provide a reasonable value. */ 1928 - if (iwe.u.qual.level > iwe.u.qual.noise) 1929 - iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; 1930 - else 1931 - iwe.u.qual.qual = 0; 1932 - current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1933 - &iwe, IW_EV_QUAL_LEN); 1934 - 1935 - /* Add encryption capability */ 1936 - iwe.cmd = SIOCGIWENCODE; 1937 - if (capabilities & WLAN_CAPABILITY_PRIVACY) 1938 - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 1939 - else 1940 - iwe.u.data.flags = IW_ENCODE_DISABLED; 1941 - iwe.u.data.length = 0; 1942 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1943 - &iwe, NULL); 1944 - 1945 - /* WPA IE */ 1946 - ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data)); 1947 - if (ie) { 1948 - iwe.cmd = IWEVGENIE; 1949 - iwe.u.data.length = ie[1] + 2; 1950 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1951 - &iwe, ie); 1952 - } 1953 - 1954 - /* RSN IE */ 1955 - ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN); 1956 - if (ie) { 1957 - iwe.cmd = IWEVGENIE; 1958 - iwe.u.data.length = ie[1] + 2; 1959 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1960 - &iwe, ie); 1961 - } 1962 - 1963 - ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES); 1964 - if (ie) { 1965 - char *p = current_ev + iwe_stream_lcp_len(info); 1966 - int i; 1967 - 1968 - iwe.cmd = SIOCGIWRATE; 1969 - /* Those two flags are ignored... */ 1970 - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 1971 - 1972 - for (i = 2; i < (ie[1] + 2); i++) { 1973 - iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000); 1974 - p = iwe_stream_add_value(info, current_ev, p, end_buf, 1975 - &iwe, IW_EV_PARAM_LEN); 1976 - } 1977 - /* Check if we added any event */ 1978 - if (p > (current_ev + iwe_stream_lcp_len(info))) 1979 - current_ev = p; 1980 - } 1981 - 1982 - /* Timestamp */ 1983 - iwe.cmd = IWEVCUSTOM; 1984 - iwe.u.data.length = 1985 - snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx", 1986 - (unsigned long long) le64_to_cpu(bss->timestamp)); 1987 - if (iwe.u.data.length) 1988 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1989 - &iwe, custom); 1990 - 1991 - /* Beacon interval */ 1992 - iwe.cmd = IWEVCUSTOM; 1993 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1994 - "bcn_int=%d", 1995 - le16_to_cpu(bss->beacon_interval)); 1996 - if (iwe.u.data.length) 1997 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1998 - &iwe, custom); 1999 - 2000 - /* Capabilites */ 2001 - iwe.cmd = IWEVCUSTOM; 2002 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 2003 - "capab=0x%04x", 2004 - capabilities); 2005 - if (iwe.u.data.length) 2006 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2007 - &iwe, custom); 2008 - 2009 - /* Add EXTRA: Age to display seconds since last beacon/probe response 2010 - * for given network. */ 2011 - iwe.cmd = IWEVCUSTOM; 2012 - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 2013 - " Last beacon: %dms ago", 2014 - jiffies_to_msecs(jiffies - last_scanned)); 2015 - if (iwe.u.data.length) 2016 - current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2017 - &iwe, custom); 2018 - 2019 - return current_ev; 2020 - } 2021 - 2022 - /* Return results of a scan */ 2023 - static int orinoco_ioctl_getscan(struct net_device *dev, 2024 - struct iw_request_info *info, 2025 - struct iw_point *srq, 2026 - char *extra) 2027 - { 2028 - struct orinoco_private *priv = ndev_priv(dev); 2029 - int err = 0; 2030 - unsigned long flags; 2031 - char *current_ev = extra; 2032 - 2033 - if (orinoco_lock(priv, &flags) != 0) 2034 - return -EBUSY; 2035 - 2036 - if (priv->scan_inprogress) { 2037 - /* Important note : we don't want to block the caller 2038 - * until results are ready for various reasons. 2039 - * First, managing wait queues is complex and racy. 2040 - * Second, we grab some rtnetlink lock before comming 2041 - * here (in dev_ioctl()). 2042 - * Third, we generate an Wireless Event, so the 2043 - * caller can wait itself on that - Jean II */ 2044 - err = -EAGAIN; 2045 - goto out; 2046 - } 2047 - 2048 - if (priv->has_ext_scan) { 2049 - struct xbss_element *bss; 2050 - 2051 - list_for_each_entry(bss, &priv->bss_list, list) { 2052 - /* Translate this entry to WE format */ 2053 - current_ev = 2054 - orinoco_translate_ext_scan(dev, info, 2055 - current_ev, 2056 - extra + srq->length, 2057 - &bss->bss, 2058 - bss->last_scanned); 2059 - 2060 - /* Check if there is space for one more entry */ 2061 - if ((extra + srq->length - current_ev) 2062 - <= IW_EV_ADDR_LEN) { 2063 - /* Ask user space to try again with a 2064 - * bigger buffer */ 2065 - err = -E2BIG; 2066 - goto out; 2067 - } 2068 - } 2069 - 2070 - } else { 2071 - struct bss_element *bss; 2072 - 2073 - list_for_each_entry(bss, &priv->bss_list, list) { 2074 - /* Translate this entry to WE format */ 2075 - current_ev = orinoco_translate_scan(dev, info, 2076 - current_ev, 2077 - extra + srq->length, 2078 - &bss->bss, 2079 - bss->last_scanned); 2080 - 2081 - /* Check if there is space for one more entry */ 2082 - if ((extra + srq->length - current_ev) 2083 - <= IW_EV_ADDR_LEN) { 2084 - /* Ask user space to try again with a 2085 - * bigger buffer */ 2086 - err = -E2BIG; 2087 - goto out; 2088 - } 2089 - } 2090 - } 2091 - 2092 - srq->length = (current_ev - extra); 2093 - srq->flags = (__u16) priv->scan_mode; 2094 - 2095 - out: 2096 - orinoco_unlock(priv, &flags); 2097 - return err; 2098 - } 2099 1586 2100 1587 /* Commit handler, called after set operations */ 2101 1588 static int orinoco_ioctl_commit(struct net_device *dev, ··· 1648 2161 STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), 1649 2162 STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), 1650 2163 STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), 1651 - STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan), 1652 - STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan), 2164 + STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), 2165 + STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), 1653 2166 STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), 1654 2167 STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), 1655 2168 STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),