diff options
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r-- | drivers/net/wireless/orinoco.c | 248 |
1 files changed, 85 insertions, 163 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 15ceaf615756..488ab06fb79f 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -77,30 +77,16 @@ | |||
77 | #define DRIVER_NAME "orinoco" | 77 | #define DRIVER_NAME "orinoco" |
78 | 78 | ||
79 | #include <linux/config.h> | 79 | #include <linux/config.h> |
80 | |||
81 | #include <linux/module.h> | 80 | #include <linux/module.h> |
82 | #include <linux/kernel.h> | 81 | #include <linux/kernel.h> |
83 | #include <linux/init.h> | 82 | #include <linux/init.h> |
84 | #include <linux/ptrace.h> | ||
85 | #include <linux/slab.h> | ||
86 | #include <linux/string.h> | ||
87 | #include <linux/timer.h> | ||
88 | #include <linux/ioport.h> | ||
89 | #include <linux/netdevice.h> | 83 | #include <linux/netdevice.h> |
90 | #include <linux/if_arp.h> | ||
91 | #include <linux/etherdevice.h> | 84 | #include <linux/etherdevice.h> |
92 | #include <linux/ethtool.h> | 85 | #include <linux/ethtool.h> |
93 | #include <linux/wireless.h> | 86 | #include <linux/wireless.h> |
94 | #include <net/iw_handler.h> | 87 | #include <net/iw_handler.h> |
95 | #include <net/ieee80211.h> | 88 | #include <net/ieee80211.h> |
96 | 89 | ||
97 | #include <net/ieee80211.h> | ||
98 | |||
99 | #include <asm/uaccess.h> | ||
100 | #include <asm/io.h> | ||
101 | #include <asm/system.h> | ||
102 | |||
103 | #include "hermes.h" | ||
104 | #include "hermes_rid.h" | 90 | #include "hermes_rid.h" |
105 | #include "orinoco.h" | 91 | #include "orinoco.h" |
106 | 92 | ||
@@ -137,7 +123,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); | |||
137 | 123 | ||
138 | /* We do this this way to avoid ifdefs in the actual code */ | 124 | /* We do this this way to avoid ifdefs in the actual code */ |
139 | #ifdef WIRELESS_SPY | 125 | #ifdef WIRELESS_SPY |
140 | #define SPY_NUMBER(priv) (priv->spy_number) | 126 | #define SPY_NUMBER(priv) (priv->spy_data.spy_number) |
141 | #else | 127 | #else |
142 | #define SPY_NUMBER(priv) 0 | 128 | #define SPY_NUMBER(priv) 0 |
143 | #endif /* WIRELESS_SPY */ | 129 | #endif /* WIRELESS_SPY */ |
@@ -216,31 +202,32 @@ static struct { | |||
216 | /********************************************************************/ | 202 | /********************************************************************/ |
217 | 203 | ||
218 | /* Used in Event handling. | 204 | /* Used in Event handling. |
219 | * We avoid nested structres as they break on ARM -- Moustafa */ | 205 | * We avoid nested structures as they break on ARM -- Moustafa */ |
220 | struct hermes_tx_descriptor_802_11 { | 206 | struct hermes_tx_descriptor_802_11 { |
221 | /* hermes_tx_descriptor */ | 207 | /* hermes_tx_descriptor */ |
222 | u16 status; | 208 | __le16 status; |
223 | u16 reserved1; | 209 | __le16 reserved1; |
224 | u16 reserved2; | 210 | __le16 reserved2; |
225 | u32 sw_support; | 211 | __le32 sw_support; |
226 | u8 retry_count; | 212 | u8 retry_count; |
227 | u8 tx_rate; | 213 | u8 tx_rate; |
228 | u16 tx_control; | 214 | __le16 tx_control; |
229 | 215 | ||
230 | /* ieee802_11_hdr */ | 216 | /* ieee80211_hdr */ |
231 | u16 frame_ctl; | 217 | __le16 frame_ctl; |
232 | u16 duration_id; | 218 | __le16 duration_id; |
233 | u8 addr1[ETH_ALEN]; | 219 | u8 addr1[ETH_ALEN]; |
234 | u8 addr2[ETH_ALEN]; | 220 | u8 addr2[ETH_ALEN]; |
235 | u8 addr3[ETH_ALEN]; | 221 | u8 addr3[ETH_ALEN]; |
236 | u16 seq_ctl; | 222 | __le16 seq_ctl; |
237 | u8 addr4[ETH_ALEN]; | 223 | u8 addr4[ETH_ALEN]; |
238 | u16 data_len; | 224 | |
225 | __le16 data_len; | ||
239 | 226 | ||
240 | /* ethhdr */ | 227 | /* ethhdr */ |
241 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ | 228 | u8 h_dest[ETH_ALEN]; /* destination eth addr */ |
242 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ | 229 | u8 h_source[ETH_ALEN]; /* source ether addr */ |
243 | unsigned short h_proto; /* packet type ID field */ | 230 | __be16 h_proto; /* packet type ID field */ |
244 | 231 | ||
245 | /* p8022_hdr */ | 232 | /* p8022_hdr */ |
246 | u8 dsap; | 233 | u8 dsap; |
@@ -248,31 +235,31 @@ struct hermes_tx_descriptor_802_11 { | |||
248 | u8 ctrl; | 235 | u8 ctrl; |
249 | u8 oui[3]; | 236 | u8 oui[3]; |
250 | 237 | ||
251 | u16 ethertype; | 238 | __be16 ethertype; |
252 | } __attribute__ ((packed)); | 239 | } __attribute__ ((packed)); |
253 | 240 | ||
254 | /* Rx frame header except compatibility 802.3 header */ | 241 | /* Rx frame header except compatibility 802.3 header */ |
255 | struct hermes_rx_descriptor { | 242 | struct hermes_rx_descriptor { |
256 | /* Control */ | 243 | /* Control */ |
257 | u16 status; | 244 | __le16 status; |
258 | u32 time; | 245 | __le32 time; |
259 | u8 silence; | 246 | u8 silence; |
260 | u8 signal; | 247 | u8 signal; |
261 | u8 rate; | 248 | u8 rate; |
262 | u8 rxflow; | 249 | u8 rxflow; |
263 | u32 reserved; | 250 | __le32 reserved; |
264 | 251 | ||
265 | /* 802.11 header */ | 252 | /* 802.11 header */ |
266 | u16 frame_ctl; | 253 | __le16 frame_ctl; |
267 | u16 duration_id; | 254 | __le16 duration_id; |
268 | u8 addr1[ETH_ALEN]; | 255 | u8 addr1[ETH_ALEN]; |
269 | u8 addr2[ETH_ALEN]; | 256 | u8 addr2[ETH_ALEN]; |
270 | u8 addr3[ETH_ALEN]; | 257 | u8 addr3[ETH_ALEN]; |
271 | u16 seq_ctl; | 258 | __le16 seq_ctl; |
272 | u8 addr4[ETH_ALEN]; | 259 | u8 addr4[ETH_ALEN]; |
273 | 260 | ||
274 | /* Data length */ | 261 | /* Data length */ |
275 | u16 data_len; | 262 | __le16 data_len; |
276 | } __attribute__ ((packed)); | 263 | } __attribute__ ((packed)); |
277 | 264 | ||
278 | /********************************************************************/ | 265 | /********************************************************************/ |
@@ -396,14 +383,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | |||
396 | /* If a spy address is defined, we report stats of the | 383 | /* If a spy address is defined, we report stats of the |
397 | * first spy address - Jean II */ | 384 | * first spy address - Jean II */ |
398 | if (SPY_NUMBER(priv)) { | 385 | if (SPY_NUMBER(priv)) { |
399 | wstats->qual.qual = priv->spy_stat[0].qual; | 386 | wstats->qual.qual = priv->spy_data.spy_stat[0].qual; |
400 | wstats->qual.level = priv->spy_stat[0].level; | 387 | wstats->qual.level = priv->spy_data.spy_stat[0].level; |
401 | wstats->qual.noise = priv->spy_stat[0].noise; | 388 | wstats->qual.noise = priv->spy_data.spy_stat[0].noise; |
402 | wstats->qual.updated = priv->spy_stat[0].updated; | 389 | wstats->qual.updated = priv->spy_data.spy_stat[0].updated; |
403 | } | 390 | } |
404 | } else { | 391 | } else { |
405 | struct { | 392 | struct { |
406 | u16 qual, signal, noise; | 393 | __le16 qual, signal, noise; |
407 | } __attribute__ ((packed)) cq; | 394 | } __attribute__ ((packed)) cq; |
408 | 395 | ||
409 | err = HERMES_READ_RECORD(hw, USER_BAP, | 396 | err = HERMES_READ_RECORD(hw, USER_BAP, |
@@ -503,13 +490,12 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
503 | return 0; | 490 | return 0; |
504 | } | 491 | } |
505 | 492 | ||
506 | /* Check packet length, pad short packets, round up odd length */ | 493 | /* Length of the packet body */ |
494 | /* FIXME: what if the skb is smaller than this? */ | ||
507 | len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); | 495 | len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); |
508 | if (skb->len < len) { | 496 | skb = skb_padto(skb, len); |
509 | skb = skb_padto(skb, len); | 497 | if (skb == NULL) |
510 | if (skb == NULL) | 498 | goto fail; |
511 | goto fail; | ||
512 | } | ||
513 | len -= ETH_HLEN; | 499 | len -= ETH_HLEN; |
514 | 500 | ||
515 | eh = (struct ethhdr *)skb->data; | 501 | eh = (struct ethhdr *)skb->data; |
@@ -556,13 +542,21 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
556 | stats->tx_errors++; | 542 | stats->tx_errors++; |
557 | goto fail; | 543 | goto fail; |
558 | } | 544 | } |
545 | /* Actual xfer length - allow for padding */ | ||
546 | len = ALIGN(data_len, 2); | ||
547 | if (len < ETH_ZLEN - ETH_HLEN) | ||
548 | len = ETH_ZLEN - ETH_HLEN; | ||
559 | } else { /* IEEE 802.3 frame */ | 549 | } else { /* IEEE 802.3 frame */ |
560 | data_len = len + ETH_HLEN; | 550 | data_len = len + ETH_HLEN; |
561 | data_off = HERMES_802_3_OFFSET; | 551 | data_off = HERMES_802_3_OFFSET; |
562 | p = skb->data; | 552 | p = skb->data; |
553 | /* Actual xfer length - round up for odd length packets */ | ||
554 | len = ALIGN(data_len, 2); | ||
555 | if (len < ETH_ZLEN) | ||
556 | len = ETH_ZLEN; | ||
563 | } | 557 | } |
564 | 558 | ||
565 | err = hermes_bap_pwrite(hw, USER_BAP, p, data_len, | 559 | err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len, |
566 | txfid, data_off); | 560 | txfid, data_off); |
567 | if (err) { | 561 | if (err) { |
568 | printk(KERN_ERR "%s: Error %d writing packet to BAP\n", | 562 | printk(KERN_ERR "%s: Error %d writing packet to BAP\n", |
@@ -634,16 +628,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
634 | struct orinoco_private *priv = netdev_priv(dev); | 628 | struct orinoco_private *priv = netdev_priv(dev); |
635 | struct net_device_stats *stats = &priv->stats; | 629 | struct net_device_stats *stats = &priv->stats; |
636 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); | 630 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); |
631 | u16 status; | ||
637 | struct hermes_tx_descriptor_802_11 hdr; | 632 | struct hermes_tx_descriptor_802_11 hdr; |
638 | int err = 0; | 633 | int err = 0; |
639 | 634 | ||
640 | if (fid == DUMMY_FID) | 635 | if (fid == DUMMY_FID) |
641 | return; /* Nothing's really happened */ | 636 | return; /* Nothing's really happened */ |
642 | 637 | ||
643 | /* Read the frame header */ | 638 | /* Read part of the frame header - we need status and addr1 */ |
644 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, | 639 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, |
645 | sizeof(struct hermes_tx_descriptor) + | 640 | offsetof(struct hermes_tx_descriptor_802_11, |
646 | sizeof(struct ieee80211_hdr), | 641 | addr2), |
647 | fid, 0); | 642 | fid, 0); |
648 | 643 | ||
649 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | 644 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); |
@@ -663,8 +658,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
663 | * exceeded, because that's the only status that really mean | 658 | * exceeded, because that's the only status that really mean |
664 | * that this particular node went away. | 659 | * that this particular node went away. |
665 | * Other errors means that *we* screwed up. - Jean II */ | 660 | * Other errors means that *we* screwed up. - Jean II */ |
666 | hdr.status = le16_to_cpu(hdr.status); | 661 | status = le16_to_cpu(hdr.status); |
667 | if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { | 662 | if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { |
668 | union iwreq_data wrqu; | 663 | union iwreq_data wrqu; |
669 | 664 | ||
670 | /* Copy 802.11 dest address. | 665 | /* Copy 802.11 dest address. |
@@ -723,18 +718,13 @@ static inline int is_ethersnap(void *_hdr) | |||
723 | static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, | 718 | static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, |
724 | int level, int noise) | 719 | int level, int noise) |
725 | { | 720 | { |
726 | struct orinoco_private *priv = netdev_priv(dev); | 721 | struct iw_quality wstats; |
727 | int i; | 722 | wstats.level = level - 0x95; |
728 | 723 | wstats.noise = noise - 0x95; | |
729 | /* Gather wireless spy statistics: for each packet, compare the | 724 | wstats.qual = (level > noise) ? (level - noise) : 0; |
730 | * source address with out list, and if match, get the stats... */ | 725 | wstats.updated = 7; |
731 | for (i = 0; i < priv->spy_number; i++) | 726 | /* Update spy records */ |
732 | if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { | 727 | wireless_spy_update(dev, mac, &wstats); |
733 | priv->spy_stat[i].level = level - 0x95; | ||
734 | priv->spy_stat[i].noise = noise - 0x95; | ||
735 | priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0; | ||
736 | priv->spy_stat[i].updated = 7; | ||
737 | } | ||
738 | } | 728 | } |
739 | 729 | ||
740 | static void orinoco_stat_gather(struct net_device *dev, | 730 | static void orinoco_stat_gather(struct net_device *dev, |
@@ -1055,7 +1045,7 @@ static void orinoco_join_ap(struct net_device *dev) | |||
1055 | unsigned long flags; | 1045 | unsigned long flags; |
1056 | struct join_req { | 1046 | struct join_req { |
1057 | u8 bssid[ETH_ALEN]; | 1047 | u8 bssid[ETH_ALEN]; |
1058 | u16 channel; | 1048 | __le16 channel; |
1059 | } __attribute__ ((packed)) req; | 1049 | } __attribute__ ((packed)) req; |
1060 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); | 1050 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); |
1061 | struct prism2_scan_apinfo *atom = NULL; | 1051 | struct prism2_scan_apinfo *atom = NULL; |
@@ -1070,7 +1060,7 @@ static void orinoco_join_ap(struct net_device *dev) | |||
1070 | return; | 1060 | return; |
1071 | 1061 | ||
1072 | if (orinoco_lock(priv, &flags) != 0) | 1062 | if (orinoco_lock(priv, &flags) != 0) |
1073 | goto out; | 1063 | goto fail_lock; |
1074 | 1064 | ||
1075 | /* Sanity checks in case user changed something in the meantime */ | 1065 | /* Sanity checks in case user changed something in the meantime */ |
1076 | if (! priv->bssid_fixed) | 1066 | if (! priv->bssid_fixed) |
@@ -1115,8 +1105,10 @@ static void orinoco_join_ap(struct net_device *dev) | |||
1115 | printk(KERN_ERR "%s: Error issuing join request\n", dev->name); | 1105 | printk(KERN_ERR "%s: Error issuing join request\n", dev->name); |
1116 | 1106 | ||
1117 | out: | 1107 | out: |
1118 | kfree(buf); | ||
1119 | orinoco_unlock(priv, &flags); | 1108 | orinoco_unlock(priv, &flags); |
1109 | |||
1110 | fail_lock: | ||
1111 | kfree(buf); | ||
1120 | } | 1112 | } |
1121 | 1113 | ||
1122 | /* Send new BSSID to userspace */ | 1114 | /* Send new BSSID to userspace */ |
@@ -1134,12 +1126,14 @@ static void orinoco_send_wevents(struct net_device *dev) | |||
1134 | err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, | 1126 | err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, |
1135 | ETH_ALEN, NULL, wrqu.ap_addr.sa_data); | 1127 | ETH_ALEN, NULL, wrqu.ap_addr.sa_data); |
1136 | if (err != 0) | 1128 | if (err != 0) |
1137 | return; | 1129 | goto out; |
1138 | 1130 | ||
1139 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 1131 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
1140 | 1132 | ||
1141 | /* Send event to user space */ | 1133 | /* Send event to user space */ |
1142 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 1134 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); |
1135 | |||
1136 | out: | ||
1143 | orinoco_unlock(priv, &flags); | 1137 | orinoco_unlock(priv, &flags); |
1144 | } | 1138 | } |
1145 | 1139 | ||
@@ -1148,8 +1142,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1148 | struct orinoco_private *priv = netdev_priv(dev); | 1142 | struct orinoco_private *priv = netdev_priv(dev); |
1149 | u16 infofid; | 1143 | u16 infofid; |
1150 | struct { | 1144 | struct { |
1151 | u16 len; | 1145 | __le16 len; |
1152 | u16 type; | 1146 | __le16 type; |
1153 | } __attribute__ ((packed)) info; | 1147 | } __attribute__ ((packed)) info; |
1154 | int len, type; | 1148 | int len, type; |
1155 | int err; | 1149 | int err; |
@@ -2464,6 +2458,10 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2464 | dev->get_stats = orinoco_get_stats; | 2458 | dev->get_stats = orinoco_get_stats; |
2465 | dev->ethtool_ops = &orinoco_ethtool_ops; | 2459 | dev->ethtool_ops = &orinoco_ethtool_ops; |
2466 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; | 2460 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; |
2461 | #ifdef WIRELESS_SPY | ||
2462 | priv->wireless_data.spy_data = &priv->spy_data; | ||
2463 | dev->wireless_data = &priv->wireless_data; | ||
2464 | #endif | ||
2467 | dev->change_mtu = orinoco_change_mtu; | 2465 | dev->change_mtu = orinoco_change_mtu; |
2468 | dev->set_multicast_list = orinoco_set_multicast_list; | 2466 | dev->set_multicast_list = orinoco_set_multicast_list; |
2469 | /* we use the default eth_mac_addr for setting the MAC addr */ | 2467 | /* we use the default eth_mac_addr for setting the MAC addr */ |
@@ -2835,7 +2833,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, | |||
2835 | } | 2833 | } |
2836 | } | 2834 | } |
2837 | 2835 | ||
2838 | if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | 2836 | if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){ |
2839 | /* Quality stats meaningless in ad-hoc mode */ | 2837 | /* Quality stats meaningless in ad-hoc mode */ |
2840 | } else { | 2838 | } else { |
2841 | range->max_qual.qual = 0x8b - 0x2f; | 2839 | range->max_qual.qual = 0x8b - 0x2f; |
@@ -2882,6 +2880,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, | |||
2882 | range->min_r_time = 0; | 2880 | range->min_r_time = 0; |
2883 | range->max_r_time = 65535 * 1000; /* ??? */ | 2881 | range->max_r_time = 65535 * 1000; /* ??? */ |
2884 | 2882 | ||
2883 | /* Event capability (kernel) */ | ||
2884 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | ||
2885 | /* Event capability (driver) */ | ||
2886 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); | ||
2887 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | ||
2888 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); | ||
2889 | IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); | ||
2890 | |||
2885 | TRACE_EXIT(dev->name); | 2891 | TRACE_EXIT(dev->name); |
2886 | 2892 | ||
2887 | return 0; | 2893 | return 0; |
@@ -3841,92 +3847,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev, | |||
3841 | return err; | 3847 | return err; |
3842 | } | 3848 | } |
3843 | 3849 | ||
3844 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode | ||
3845 | * Jean II */ | ||
3846 | static int orinoco_ioctl_setspy(struct net_device *dev, | ||
3847 | struct iw_request_info *info, | ||
3848 | struct iw_point *srq, | ||
3849 | char *extra) | ||
3850 | |||
3851 | { | ||
3852 | struct orinoco_private *priv = netdev_priv(dev); | ||
3853 | struct sockaddr *address = (struct sockaddr *) extra; | ||
3854 | int number = srq->length; | ||
3855 | int i; | ||
3856 | unsigned long flags; | ||
3857 | |||
3858 | /* Make sure nobody mess with the structure while we do */ | ||
3859 | if (orinoco_lock(priv, &flags) != 0) | ||
3860 | return -EBUSY; | ||
3861 | |||
3862 | /* orinoco_lock() doesn't disable interrupts, so make sure the | ||
3863 | * interrupt rx path don't get confused while we copy */ | ||
3864 | priv->spy_number = 0; | ||
3865 | |||
3866 | if (number > 0) { | ||
3867 | /* Extract the addresses */ | ||
3868 | for (i = 0; i < number; i++) | ||
3869 | memcpy(priv->spy_address[i], address[i].sa_data, | ||
3870 | ETH_ALEN); | ||
3871 | /* Reset stats */ | ||
3872 | memset(priv->spy_stat, 0, | ||
3873 | sizeof(struct iw_quality) * IW_MAX_SPY); | ||
3874 | /* Set number of addresses */ | ||
3875 | priv->spy_number = number; | ||
3876 | } | ||
3877 | |||
3878 | /* Now, let the others play */ | ||
3879 | orinoco_unlock(priv, &flags); | ||
3880 | |||
3881 | /* Do NOT call commit handler */ | ||
3882 | return 0; | ||
3883 | } | ||
3884 | |||
3885 | static int orinoco_ioctl_getspy(struct net_device *dev, | ||
3886 | struct iw_request_info *info, | ||
3887 | struct iw_point *srq, | ||
3888 | char *extra) | ||
3889 | { | ||
3890 | struct orinoco_private *priv = netdev_priv(dev); | ||
3891 | struct sockaddr *address = (struct sockaddr *) extra; | ||
3892 | int number; | ||
3893 | int i; | ||
3894 | unsigned long flags; | ||
3895 | |||
3896 | if (orinoco_lock(priv, &flags) != 0) | ||
3897 | return -EBUSY; | ||
3898 | |||
3899 | number = priv->spy_number; | ||
3900 | /* Create address struct */ | ||
3901 | for (i = 0; i < number; i++) { | ||
3902 | memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); | ||
3903 | address[i].sa_family = AF_UNIX; | ||
3904 | } | ||
3905 | if (number > 0) { | ||
3906 | /* Create address struct */ | ||
3907 | for (i = 0; i < number; i++) { | ||
3908 | memcpy(address[i].sa_data, priv->spy_address[i], | ||
3909 | ETH_ALEN); | ||
3910 | address[i].sa_family = AF_UNIX; | ||
3911 | } | ||
3912 | /* Copy stats */ | ||
3913 | /* In theory, we should disable irqs while copying the stats | ||
3914 | * because the rx path might update it in the middle... | ||
3915 | * Bah, who care ? - Jean II */ | ||
3916 | memcpy(extra + (sizeof(struct sockaddr) * number), | ||
3917 | priv->spy_stat, sizeof(struct iw_quality) * number); | ||
3918 | } | ||
3919 | /* Reset updated flags. */ | ||
3920 | for (i = 0; i < number; i++) | ||
3921 | priv->spy_stat[i].updated = 0; | ||
3922 | |||
3923 | orinoco_unlock(priv, &flags); | ||
3924 | |||
3925 | srq->length = number; | ||
3926 | |||
3927 | return 0; | ||
3928 | } | ||
3929 | |||
3930 | /* Trigger a scan (look for other cells in the vicinity */ | 3850 | /* Trigger a scan (look for other cells in the vicinity */ |
3931 | static int orinoco_ioctl_setscan(struct net_device *dev, | 3851 | static int orinoco_ioctl_setscan(struct net_device *dev, |
3932 | struct iw_request_info *info, | 3852 | struct iw_request_info *info, |
@@ -3999,7 +3919,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
3999 | HERMES_HOSTSCAN_SYMBOL_BCAST); | 3919 | HERMES_HOSTSCAN_SYMBOL_BCAST); |
4000 | break; | 3920 | break; |
4001 | case FIRMWARE_TYPE_INTERSIL: { | 3921 | case FIRMWARE_TYPE_INTERSIL: { |
4002 | u16 req[3]; | 3922 | __le16 req[3]; |
4003 | 3923 | ||
4004 | req[0] = cpu_to_le16(0x3fff); /* All channels */ | 3924 | req[0] = cpu_to_le16(0x3fff); /* All channels */ |
4005 | req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ | 3925 | req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ |
@@ -4073,7 +3993,7 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
4073 | case FIRMWARE_TYPE_INTERSIL: | 3993 | case FIRMWARE_TYPE_INTERSIL: |
4074 | offset = 4; | 3994 | offset = 4; |
4075 | if (priv->has_hostscan) { | 3995 | if (priv->has_hostscan) { |
4076 | atom_len = le16_to_cpup((u16 *)scan); | 3996 | atom_len = le16_to_cpup((__le16 *)scan); |
4077 | /* Sanity check for atom_len */ | 3997 | /* Sanity check for atom_len */ |
4078 | if (atom_len < sizeof(struct prism2_scan_apinfo)) { | 3998 | if (atom_len < sizeof(struct prism2_scan_apinfo)) { |
4079 | printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n", | 3999 | printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n", |
@@ -4357,8 +4277,10 @@ static const iw_handler orinoco_handler[] = { | |||
4357 | [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens, | 4277 | [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens, |
4358 | [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens, | 4278 | [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens, |
4359 | [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange, | 4279 | [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange, |
4360 | [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy, | 4280 | [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, |
4361 | [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy, | 4281 | [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, |
4282 | [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, | ||
4283 | [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, | ||
4362 | [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap, | 4284 | [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap, |
4363 | [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap, | 4285 | [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap, |
4364 | [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan, | 4286 | [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan, |