aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:27:58 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:05 -0400
commit01632fa4af34addf78ce999eabb4430f33942ee2 (patch)
treec2127215d99e2d67dd402e07286b4c66df64efb3 /drivers/net/wireless/orinoco.c
parent3056c40426b9cd4f7c334d773d69db64e195431d (diff)
orinoco: Use extended Agere scans available on 9.x series firmwares
This provides more information than the standard Agere scan, including the WPA IE. Signed-off-by: David Kilroy <kilroyd@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c448
1 files changed, 405 insertions, 43 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 3d5570d0a262..22718e8176ff 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -275,13 +275,19 @@ static inline void set_port_type(struct orinoco_private *priv)
275#define ORINOCO_MAX_BSS_COUNT 64 275#define ORINOCO_MAX_BSS_COUNT 64
276static int orinoco_bss_data_allocate(struct orinoco_private *priv) 276static int orinoco_bss_data_allocate(struct orinoco_private *priv)
277{ 277{
278 if (priv->bss_data) 278 if (priv->bss_xbss_data)
279 return 0; 279 return 0;
280 280
281 priv->bss_data = 281 if (priv->has_ext_scan)
282 kzalloc(ORINOCO_MAX_BSS_COUNT * sizeof(struct bss_element), 282 priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
283 GFP_KERNEL); 283 sizeof(struct xbss_element),
284 if (!priv->bss_data) { 284 GFP_KERNEL);
285 else
286 priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
287 sizeof(struct bss_element),
288 GFP_KERNEL);
289
290 if (!priv->bss_xbss_data) {
285 printk(KERN_WARNING "Out of memory allocating beacons"); 291 printk(KERN_WARNING "Out of memory allocating beacons");
286 return -ENOMEM; 292 return -ENOMEM;
287 } 293 }
@@ -290,18 +296,53 @@ static int orinoco_bss_data_allocate(struct orinoco_private *priv)
290 296
291static void orinoco_bss_data_free(struct orinoco_private *priv) 297static void orinoco_bss_data_free(struct orinoco_private *priv)
292{ 298{
293 kfree(priv->bss_data); 299 kfree(priv->bss_xbss_data);
294 priv->bss_data = NULL; 300 priv->bss_xbss_data = NULL;
295} 301}
296 302
303#define PRIV_BSS ((struct bss_element *)priv->bss_xbss_data)
304#define PRIV_XBSS ((struct xbss_element *)priv->bss_xbss_data)
297static void orinoco_bss_data_init(struct orinoco_private *priv) 305static void orinoco_bss_data_init(struct orinoco_private *priv)
298{ 306{
299 int i; 307 int i;
300 308
301 INIT_LIST_HEAD(&priv->bss_free_list); 309 INIT_LIST_HEAD(&priv->bss_free_list);
302 INIT_LIST_HEAD(&priv->bss_list); 310 INIT_LIST_HEAD(&priv->bss_list);
303 for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++) 311 if (priv->has_ext_scan)
304 list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list); 312 for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
313 list_add_tail(&(PRIV_XBSS[i].list),
314 &priv->bss_free_list);
315 else
316 for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
317 list_add_tail(&(PRIV_BSS[i].list),
318 &priv->bss_free_list);
319
320}
321
322static inline u8 *orinoco_get_ie(u8 *data, size_t len,
323 enum ieee80211_mfie eid)
324{
325 u8 *p = data;
326 while ((p + 2) < (data + len)) {
327 if (p[0] == eid)
328 return p;
329 p += p[1] + 2;
330 }
331 return NULL;
332}
333
334#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
335#define WPA_SELECTOR_LEN 4
336static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
337{
338 u8 *p = data;
339 while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
340 if ((p[0] == MFIE_TYPE_GENERIC) &&
341 (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
342 return p;
343 p += p[1] + 2;
344 }
345 return NULL;
305} 346}
306 347
307 348
@@ -1414,18 +1455,72 @@ static void orinoco_send_wevents(struct work_struct *work)
1414static inline void orinoco_clear_scan_results(struct orinoco_private *priv, 1455static inline void orinoco_clear_scan_results(struct orinoco_private *priv,
1415 unsigned long scan_age) 1456 unsigned long scan_age)
1416{ 1457{
1417 struct bss_element *bss; 1458 if (priv->has_ext_scan) {
1418 struct bss_element *tmp_bss; 1459 struct xbss_element *bss;
1419 1460 struct xbss_element *tmp_bss;
1420 /* Blow away current list of scan results */ 1461
1421 list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) { 1462 /* Blow away current list of scan results */
1422 if (!scan_age || 1463 list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
1423 time_after(jiffies, bss->last_scanned + scan_age)) { 1464 if (!scan_age ||
1424 list_move_tail(&bss->list, &priv->bss_free_list); 1465 time_after(jiffies, bss->last_scanned + scan_age)) {
1425 /* Don't blow away ->list, just BSS data */ 1466 list_move_tail(&bss->list,
1426 memset(bss, 0, sizeof(bss->bss)); 1467 &priv->bss_free_list);
1427 bss->last_scanned = 0; 1468 /* Don't blow away ->list, just BSS data */
1469 memset(&bss->bss, 0, sizeof(bss->bss));
1470 bss->last_scanned = 0;
1471 }
1428 } 1472 }
1473 } else {
1474 struct bss_element *bss;
1475 struct bss_element *tmp_bss;
1476
1477 /* Blow away current list of scan results */
1478 list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
1479 if (!scan_age ||
1480 time_after(jiffies, bss->last_scanned + scan_age)) {
1481 list_move_tail(&bss->list,
1482 &priv->bss_free_list);
1483 /* Don't blow away ->list, just BSS data */
1484 memset(&bss->bss, 0, sizeof(bss->bss));
1485 bss->last_scanned = 0;
1486 }
1487 }
1488 }
1489}
1490
1491static void orinoco_add_ext_scan_result(struct orinoco_private *priv,
1492 struct agere_ext_scan_info *atom)
1493{
1494 struct xbss_element *bss = NULL;
1495 int found = 0;
1496
1497 /* Try to update an existing bss first */
1498 list_for_each_entry(bss, &priv->bss_list, list) {
1499 if (compare_ether_addr(bss->bss.bssid, atom->bssid))
1500 continue;
1501 /* ESSID lengths */
1502 if (bss->bss.data[1] != atom->data[1])
1503 continue;
1504 if (memcmp(&bss->bss.data[2], &atom->data[2],
1505 atom->data[1]))
1506 continue;
1507 found = 1;
1508 break;
1509 }
1510
1511 /* Grab a bss off the free list */
1512 if (!found && !list_empty(&priv->bss_free_list)) {
1513 bss = list_entry(priv->bss_free_list.next,
1514 struct xbss_element, list);
1515 list_del(priv->bss_free_list.next);
1516
1517 list_add_tail(&bss->list, &priv->bss_list);
1518 }
1519
1520 if (bss) {
1521 /* Always update the BSS to get latest beacon info */
1522 memcpy(&bss->bss, atom, sizeof(bss->bss));
1523 bss->last_scanned = jiffies;
1429 } 1524 }
1430} 1525}
1431 1526
@@ -1700,6 +1795,63 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1700 kfree(buf); 1795 kfree(buf);
1701 } 1796 }
1702 break; 1797 break;
1798 case HERMES_INQ_CHANNELINFO:
1799 {
1800 struct agere_ext_scan_info *bss;
1801
1802 if (!priv->scan_inprogress) {
1803 printk(KERN_DEBUG "%s: Got chaninfo without scan, "
1804 "len=%d\n", dev->name, len);
1805 break;
1806 }
1807
1808 /* An empty result indicates that the scan is complete */
1809 if (len == 0) {
1810 union iwreq_data wrqu;
1811
1812 /* Scan is no longer in progress */
1813 priv->scan_inprogress = 0;
1814
1815 wrqu.data.length = 0;
1816 wrqu.data.flags = 0;
1817 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1818 break;
1819 }
1820
1821 /* Sanity check */
1822 else if (len > sizeof(*bss)) {
1823 printk(KERN_WARNING
1824 "%s: Ext scan results too large (%d bytes). "
1825 "Truncating results to %zd bytes.\n",
1826 dev->name, len, sizeof(*bss));
1827 len = sizeof(*bss);
1828 } else if (len < (offsetof(struct agere_ext_scan_info,
1829 data) + 2)) {
1830 /* Drop this result now so we don't have to
1831 * keep checking later */
1832 printk(KERN_WARNING
1833 "%s: Ext scan results too short (%d bytes)\n",
1834 dev->name, len);
1835 break;
1836 }
1837
1838 bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
1839 if (bss == NULL)
1840 break;
1841
1842 /* Read scan data */
1843 err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
1844 infofid, sizeof(info));
1845 if (err) {
1846 kfree(bss);
1847 break;
1848 }
1849
1850 orinoco_add_ext_scan_result(priv, bss);
1851
1852 kfree(bss);
1853 break;
1854 }
1703 case HERMES_INQ_SEC_STAT_AGERE: 1855 case HERMES_INQ_SEC_STAT_AGERE:
1704 /* Security status (Agere specific) */ 1856 /* Security status (Agere specific) */
1705 /* Ignore this frame for now */ 1857 /* Ignore this frame for now */
@@ -2557,6 +2709,7 @@ static int determine_firmware(struct net_device *dev)
2557 priv->has_wep = 0; 2709 priv->has_wep = 0;
2558 priv->has_big_wep = 0; 2710 priv->has_big_wep = 0;
2559 priv->has_alt_txcntl = 0; 2711 priv->has_alt_txcntl = 0;
2712 priv->has_ext_scan = 0;
2560 priv->do_fw_download = 0; 2713 priv->do_fw_download = 0;
2561 2714
2562 /* Determine capabilities from the firmware version */ 2715 /* Determine capabilities from the firmware version */
@@ -2580,7 +2733,7 @@ static int determine_firmware(struct net_device *dev)
2580 priv->do_fw_download = 1; 2733 priv->do_fw_download = 1;
2581 priv->broken_monitor = (firmver >= 0x80000); 2734 priv->broken_monitor = (firmver >= 0x80000);
2582 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */ 2735 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
2583 2736 priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
2584 /* Tested with Agere firmware : 2737 /* Tested with Agere firmware :
2585 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II 2738 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
2586 * Tested CableTron firmware : 4.32 => Anton */ 2739 * Tested CableTron firmware : 4.32 => Anton */
@@ -2735,6 +2888,12 @@ static int orinoco_init(struct net_device *dev)
2735 printk("40-bit key\n"); 2888 printk("40-bit key\n");
2736 } 2889 }
2737 2890
2891 /* Now we have the firmware capabilities, allocate appropiate
2892 * sized scan buffers */
2893 if (orinoco_bss_data_allocate(priv))
2894 goto out;
2895 orinoco_bss_data_init(priv);
2896
2738 /* Get the MAC address */ 2897 /* Get the MAC address */
2739 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, 2898 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
2740 ETH_ALEN, NULL, dev->dev_addr); 2899 ETH_ALEN, NULL, dev->dev_addr);
@@ -2885,10 +3044,6 @@ struct net_device
2885 priv->card = NULL; 3044 priv->card = NULL;
2886 priv->dev = device; 3045 priv->dev = device;
2887 3046
2888 if (orinoco_bss_data_allocate(priv))
2889 goto err_out_free;
2890 orinoco_bss_data_init(priv);
2891
2892 /* Setup / override net_device fields */ 3047 /* Setup / override net_device fields */
2893 dev->init = orinoco_init; 3048 dev->init = orinoco_init;
2894 dev->hard_start_xmit = orinoco_xmit; 3049 dev->hard_start_xmit = orinoco_xmit;
@@ -2924,10 +3079,6 @@ struct net_device
2924 priv->last_linkstatus = 0xffff; 3079 priv->last_linkstatus = 0xffff;
2925 3080
2926 return dev; 3081 return dev;
2927
2928err_out_free:
2929 free_netdev(dev);
2930 return NULL;
2931} 3082}
2932 3083
2933void free_orinocodev(struct net_device *dev) 3084void free_orinocodev(struct net_device *dev)
@@ -4375,7 +4526,25 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
4375 if (err) 4526 if (err)
4376 break; 4527 break;
4377 4528
4378 err = hermes_inquire(hw, HERMES_INQ_SCAN); 4529 if (priv->has_ext_scan) {
4530 /* Clear scan results at the start of
4531 * an extended scan */
4532 orinoco_clear_scan_results(priv,
4533 msecs_to_jiffies(15000));
4534
4535 /* TODO: Is this available on older firmware?
4536 * Can we use it to scan specific channels
4537 * for IW_SCAN_THIS_FREQ? */
4538 err = hermes_write_wordrec(hw, USER_BAP,
4539 HERMES_RID_CNFSCANCHANNELS2GHZ,
4540 0x7FFF);
4541 if (err)
4542 goto out;
4543
4544 err = hermes_inquire(hw,
4545 HERMES_INQ_CHANNELINFO);
4546 } else
4547 err = hermes_inquire(hw, HERMES_INQ_SCAN);
4379 break; 4548 break;
4380 } 4549 }
4381 } else 4550 } else
@@ -4541,6 +4710,171 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
4541 return current_ev; 4710 return current_ev;
4542} 4711}
4543 4712
4713static inline char *orinoco_translate_ext_scan(struct net_device *dev,
4714 struct iw_request_info *info,
4715 char *current_ev,
4716 char *end_buf,
4717 struct agere_ext_scan_info *bss,
4718 unsigned int last_scanned)
4719{
4720 u16 capabilities;
4721 u16 channel;
4722 struct iw_event iwe; /* Temporary buffer */
4723 char custom[MAX_CUSTOM_LEN];
4724 u8 *ie;
4725
4726 memset(&iwe, 0, sizeof(iwe));
4727
4728 /* First entry *MUST* be the AP MAC address */
4729 iwe.cmd = SIOCGIWAP;
4730 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4731 memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
4732 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4733 &iwe, IW_EV_ADDR_LEN);
4734
4735 /* Other entries will be displayed in the order we give them */
4736
4737 /* Add the ESSID */
4738 ie = bss->data;
4739 iwe.u.data.length = ie[1];
4740 if (iwe.u.data.length) {
4741 if (iwe.u.data.length > 32)
4742 iwe.u.data.length = 32;
4743 iwe.cmd = SIOCGIWESSID;
4744 iwe.u.data.flags = 1;
4745 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4746 &iwe, &ie[2]);
4747 }
4748
4749 /* Add mode */
4750 capabilities = le16_to_cpu(bss->capabilities);
4751 if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
4752 iwe.cmd = SIOCGIWMODE;
4753 if (capabilities & WLAN_CAPABILITY_ESS)
4754 iwe.u.mode = IW_MODE_MASTER;
4755 else
4756 iwe.u.mode = IW_MODE_ADHOC;
4757 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4758 &iwe, IW_EV_UINT_LEN);
4759 }
4760
4761 ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_DS_SET);
4762 channel = ie ? ie[2] : 0;
4763 if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
4764 /* Add channel and frequency */
4765 iwe.cmd = SIOCGIWFREQ;
4766 iwe.u.freq.m = channel;
4767 iwe.u.freq.e = 0;
4768 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4769 &iwe, IW_EV_FREQ_LEN);
4770
4771 iwe.u.freq.m = channel_frequency[channel-1] * 100000;
4772 iwe.u.freq.e = 1;
4773 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4774 &iwe, IW_EV_FREQ_LEN);
4775 }
4776
4777 /* Add quality statistics. level and noise in dB. No link quality */
4778 iwe.cmd = IWEVQUAL;
4779 iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
4780 iwe.u.qual.level = bss->level - 0x95;
4781 iwe.u.qual.noise = bss->noise - 0x95;
4782 /* Wireless tools prior to 27.pre22 will show link quality
4783 * anyway, so we provide a reasonable value. */
4784 if (iwe.u.qual.level > iwe.u.qual.noise)
4785 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
4786 else
4787 iwe.u.qual.qual = 0;
4788 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4789 &iwe, IW_EV_QUAL_LEN);
4790
4791 /* Add encryption capability */
4792 iwe.cmd = SIOCGIWENCODE;
4793 if (capabilities & WLAN_CAPABILITY_PRIVACY)
4794 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4795 else
4796 iwe.u.data.flags = IW_ENCODE_DISABLED;
4797 iwe.u.data.length = 0;
4798 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4799 &iwe, NULL);
4800
4801 /* WPA IE */
4802 ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
4803 if (ie) {
4804 iwe.cmd = IWEVGENIE;
4805 iwe.u.data.length = ie[1] + 2;
4806 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4807 &iwe, ie);
4808 }
4809
4810 /* RSN IE */
4811 ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RSN);
4812 if (ie) {
4813 iwe.cmd = IWEVGENIE;
4814 iwe.u.data.length = ie[1] + 2;
4815 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4816 &iwe, ie);
4817 }
4818
4819 ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RATES);
4820 if (ie) {
4821 char *p = current_ev + iwe_stream_lcp_len(info);
4822 int i;
4823
4824 iwe.cmd = SIOCGIWRATE;
4825 /* Those two flags are ignored... */
4826 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4827
4828 for (i = 2; i < (ie[1] + 2); i++) {
4829 iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
4830 p = iwe_stream_add_value(info, current_ev, p, end_buf,
4831 &iwe, IW_EV_PARAM_LEN);
4832 }
4833 /* Check if we added any event */
4834 if (p > (current_ev + iwe_stream_lcp_len(info)))
4835 current_ev = p;
4836 }
4837
4838 /* Timestamp */
4839 iwe.cmd = IWEVCUSTOM;
4840 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
4841 "tsf=%016llx",
4842 le64_to_cpu(bss->timestamp));
4843 if (iwe.u.data.length)
4844 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4845 &iwe, custom);
4846
4847 /* Beacon interval */
4848 iwe.cmd = IWEVCUSTOM;
4849 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
4850 "bcn_int=%d",
4851 le16_to_cpu(bss->beacon_interval));
4852 if (iwe.u.data.length)
4853 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4854 &iwe, custom);
4855
4856 /* Capabilites */
4857 iwe.cmd = IWEVCUSTOM;
4858 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
4859 "capab=0x%04x",
4860 capabilities);
4861 if (iwe.u.data.length)
4862 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4863 &iwe, custom);
4864
4865 /* Add EXTRA: Age to display seconds since last beacon/probe response
4866 * for given network. */
4867 iwe.cmd = IWEVCUSTOM;
4868 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
4869 " Last beacon: %dms ago",
4870 jiffies_to_msecs(jiffies - last_scanned));
4871 if (iwe.u.data.length)
4872 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4873 &iwe, custom);
4874
4875 return current_ev;
4876}
4877
4544/* Return results of a scan */ 4878/* Return results of a scan */
4545static int orinoco_ioctl_getscan(struct net_device *dev, 4879static int orinoco_ioctl_getscan(struct net_device *dev,
4546 struct iw_request_info *info, 4880 struct iw_request_info *info,
@@ -4548,7 +4882,6 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
4548 char *extra) 4882 char *extra)
4549{ 4883{
4550 struct orinoco_private *priv = netdev_priv(dev); 4884 struct orinoco_private *priv = netdev_priv(dev);
4551 struct bss_element *bss;
4552 int err = 0; 4885 int err = 0;
4553 unsigned long flags; 4886 unsigned long flags;
4554 char *current_ev = extra; 4887 char *current_ev = extra;
@@ -4568,18 +4901,47 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
4568 goto out; 4901 goto out;
4569 } 4902 }
4570 4903
4571 list_for_each_entry(bss, &priv->bss_list, list) { 4904 if (priv->has_ext_scan) {
4572 /* Translate to WE format this entry */ 4905 struct xbss_element *bss;
4573 current_ev = orinoco_translate_scan(dev, info, current_ev, 4906
4574 extra + srq->length, 4907 list_for_each_entry(bss, &priv->bss_list, list) {
4575 &bss->bss, 4908 /* Translate this entry to WE format */
4576 bss->last_scanned); 4909 current_ev =
4577 4910 orinoco_translate_ext_scan(dev, info,
4578 /* Check if there is space for one more entry */ 4911 current_ev,
4579 if ((extra + srq->length - current_ev) <= IW_EV_ADDR_LEN) { 4912 extra + srq->length,
4580 /* Ask user space to try again with a bigger buffer */ 4913 &bss->bss,
4581 err = -E2BIG; 4914 bss->last_scanned);
4582 goto out; 4915
4916 /* Check if there is space for one more entry */
4917 if ((extra + srq->length - current_ev)
4918 <= IW_EV_ADDR_LEN) {
4919 /* Ask user space to try again with a
4920 * bigger buffer */
4921 err = -E2BIG;
4922 goto out;
4923 }
4924 }
4925
4926 } else {
4927 struct bss_element *bss;
4928
4929 list_for_each_entry(bss, &priv->bss_list, list) {
4930 /* Translate this entry to WE format */
4931 current_ev = orinoco_translate_scan(dev, info,
4932 current_ev,
4933 extra + srq->length,
4934 &bss->bss,
4935 bss->last_scanned);
4936
4937 /* Check if there is space for one more entry */
4938 if ((extra + srq->length - current_ev)
4939 <= IW_EV_ADDR_LEN) {
4940 /* Ask user space to try again with a
4941 * bigger buffer */
4942 err = -E2BIG;
4943 goto out;
4944 }
4583 } 4945 }
4584 } 4946 }
4585 4947