blob: ebf92ae6e365b1057f422920b06e9116327110a8 [file] [log] [blame]
David Kilroy47445cb2009-02-04 23:05:48 +00001/* main.c - (formerly known as dldwd_cs.c, orinoco_cs.c and orinoco.c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
4 * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
5 *
6 * Current maintainers (as of 29 September 2003) are:
7 * Pavel Roskin <proski AT gnu.org>
8 * and David Gibson <hermes AT gibson.dropbear.id.au>
9 *
10 * (C) Copyright David Gibson, IBM Corporation 2001-2003.
11 * Copyright (C) 2000 David Gibson, Linuxcare Australia.
12 * With some help from :
13 * Copyright (C) 2001 Jean Tourrilhes, HP Labs
14 * Copyright (C) 2001 Benjamin Herrenschmidt
15 *
16 * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
17 *
18 * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
19 * AT fasta.fh-dortmund.de>
20 * http://www.stud.fh-dortmund.de/~andy/wvlan/
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License
25 * at http://www.mozilla.org/MPL/
26 *
27 * Software distributed under the License is distributed on an "AS IS"
28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
29 * the License for the specific language governing rights and
30 * limitations under the License.
31 *
32 * The initial developer of the original code is David A. Hinds
33 * <dahinds AT users.sourceforge.net>. Portions created by David
34 * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
35 * Reserved.
36 *
37 * Alternatively, the contents of this file may be used under the
38 * terms of the GNU General Public License version 2 (the "GPL"), in
39 * which case the provisions of the GPL are applicable instead of the
40 * above. If you wish to allow the use of your version of this file
41 * only under the terms of the GPL and not to allow others to use your
42 * version of this file under the MPL, indicate your decision by
43 * deleting the provisions above and replace them with the notice and
44 * other provisions required by the GPL. If you do not delete the
45 * provisions above, a recipient may use your version of this file
46 * under either the MPL or the GPL. */
47
48/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 * TODO
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 * o Handle de-encapsulation within network layer, provide 802.11
51 * headers (patch from Thomas 'Dent' Mirlacher)
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 * o Fix possible races in SPY handling.
53 * o Disconnect wireless extensions from fundamental configuration.
54 * o (maybe) Software WEP support (patch from Stano Meduna).
55 * o (maybe) Use multiple Tx buffers - driver handling queue
56 * rather than firmware.
57 */
58
59/* Locking and synchronization:
60 *
61 * The basic principle is that everything is serialized through a
62 * single spinlock, priv->lock. The lock is used in user, bh and irq
63 * context, so when taken outside hardirq context it should always be
64 * taken with interrupts disabled. The lock protects both the
65 * hardware and the struct orinoco_private.
66 *
67 * Another flag, priv->hw_unavailable indicates that the hardware is
68 * unavailable for an extended period of time (e.g. suspended, or in
69 * the middle of a hard reset). This flag is protected by the
70 * spinlock. All code which touches the hardware should check the
71 * flag after taking the lock, and if it is set, give up on whatever
72 * they are doing and drop the lock again. The orinoco_lock()
73 * function handles this (it unlocks and returns -EBUSY if
74 * hw_unavailable is non-zero).
75 */
76
77#define DRIVER_NAME "orinoco"
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#include <linux/module.h>
80#include <linux/kernel.h>
81#include <linux/init.h>
David Kilroyd03032a2008-08-21 23:28:02 +010082#include <linux/delay.h>
David Kilroy8e638262009-06-18 23:21:24 +010083#include <linux/device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#include <linux/netdevice.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/etherdevice.h>
Christoph Hellwig1fab2e82005-06-19 01:27:40 +020086#include <linux/ethtool.h>
David Kilroy39d1ffe2008-11-22 10:37:28 +000087#include <linux/suspend.h>
Pavel Roskin9c974fb2006-08-15 20:45:03 -040088#include <linux/if_arp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#include <linux/wireless.h>
Johannes Berg2c7060022008-10-30 22:09:54 +010090#include <linux/ieee80211.h>
Christoph Hellwig620554e2005-06-19 01:27:33 +020091#include <net/iw_handler.h>
David Kilroyea60a6a2009-06-18 23:21:26 +010092#include <net/cfg80211.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#include "hermes_rid.h"
David Kilroy3994d502008-08-21 23:27:54 +010095#include "hermes_dld.h"
David Kilroy712a4342009-02-04 23:05:55 +000096#include "hw.h"
David Kilroyfb791b12009-02-04 23:05:50 +000097#include "scan.h"
David Kilroy4adb4742009-02-04 23:05:51 +000098#include "mic.h"
David Kilroy37a2e562009-02-04 23:05:52 +000099#include "fw.h"
David Kilroycb1576a2009-02-04 23:05:56 +0000100#include "wext.h"
David Kilroyea60a6a2009-06-18 23:21:26 +0100101#include "cfg.h"
David Kilroycb1576a2009-02-04 23:05:56 +0000102#include "main.h"
David Kilroyfb791b12009-02-04 23:05:50 +0000103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104#include "orinoco.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/********************************************************************/
107/* Module information */
108/********************************************************************/
109
David Kilroyb2f30a02009-02-04 23:05:46 +0000110MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & "
111 "David Gibson <hermes@gibson.dropbear.id.au>");
112MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based "
113 "and similar wireless cards");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114MODULE_LICENSE("Dual MPL/GPL");
115
116/* Level of debugging. Used in the macros in orinoco.h */
117#ifdef ORINOCO_DEBUG
118int orinoco_debug = ORINOCO_DEBUG;
David Kilroy21312662009-02-04 23:05:47 +0000119EXPORT_SYMBOL(orinoco_debug);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120module_param(orinoco_debug, int, 0644);
121MODULE_PARM_DESC(orinoco_debug, "Debug level");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122#endif
123
124static int suppress_linkstatus; /* = 0 */
125module_param(suppress_linkstatus, bool, 0644);
126MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
David Kilroyb2f30a02009-02-04 23:05:46 +0000127
David Gibson7bb7c3a2005-05-12 20:02:10 -0400128static int ignore_disconnect; /* = 0 */
129module_param(ignore_disconnect, int, 0644);
David Kilroyb2f30a02009-02-04 23:05:46 +0000130MODULE_PARM_DESC(ignore_disconnect,
131 "Don't report lost link to the network layer");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
David Kilroycb1576a2009-02-04 23:05:56 +0000133int force_monitor; /* = 0 */
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200134module_param(force_monitor, int, 0644);
135MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/********************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138/* Internal constants */
139/********************************************************************/
140
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200141/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
142static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
143#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145#define ORINOCO_MIN_MTU 256
Johannes Berg2c7060022008-10-30 22:09:54 +0100146#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148#define MAX_IRQLOOPS_PER_IRQ 10
149#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
150 * how many events the
151 * device could
152 * legitimately generate */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154#define DUMMY_FID 0xFFFF
155
156/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
157 HERMES_MAX_MULTICAST : 0)*/
158#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
159
160#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
161 | HERMES_EV_TX | HERMES_EV_TXEXC \
162 | HERMES_EV_WTERR | HERMES_EV_INFO \
David Kilroya94e8422009-02-04 23:05:44 +0000163 | HERMES_EV_INFDROP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Jeff Garzik7282d492006-09-13 14:30:00 -0400165static const struct ethtool_ops orinoco_ethtool_ops;
Christoph Hellwig620554e2005-06-19 01:27:33 +0200166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167/********************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168/* Data types */
169/********************************************************************/
170
Pavel Roskin30c2d3b2006-04-07 04:10:34 -0400171/* Beginning of the Tx descriptor, used in TxExc handling */
172struct hermes_txexc_data {
173 struct hermes_tx_descriptor desc;
Pavel Roskind133ae42005-09-23 04:18:06 -0400174 __le16 frame_ctl;
175 __le16 duration_id;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200176 u8 addr1[ETH_ALEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177} __attribute__ ((packed));
178
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200179/* Rx frame header except compatibility 802.3 header */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180struct hermes_rx_descriptor {
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200181 /* Control */
Pavel Roskind133ae42005-09-23 04:18:06 -0400182 __le16 status;
183 __le32 time;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 u8 silence;
185 u8 signal;
186 u8 rate;
187 u8 rxflow;
Pavel Roskind133ae42005-09-23 04:18:06 -0400188 __le32 reserved;
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200189
190 /* 802.11 header */
Pavel Roskind133ae42005-09-23 04:18:06 -0400191 __le16 frame_ctl;
192 __le16 duration_id;
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200193 u8 addr1[ETH_ALEN];
194 u8 addr2[ETH_ALEN];
195 u8 addr3[ETH_ALEN];
Pavel Roskind133ae42005-09-23 04:18:06 -0400196 __le16 seq_ctl;
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200197 u8 addr4[ETH_ALEN];
198
199 /* Data length */
Pavel Roskind133ae42005-09-23 04:18:06 -0400200 __le16 data_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201} __attribute__ ((packed));
202
David Kilroy47166792009-01-07 00:43:54 +0000203struct orinoco_rx_data {
204 struct hermes_rx_descriptor *desc;
205 struct sk_buff *skb;
206 struct list_head list;
207};
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209/********************************************************************/
210/* Function prototypes */
211/********************************************************************/
212
David Kilroy721aa2f2009-06-18 23:21:31 +0100213static int __orinoco_set_multicast_list(struct net_device *dev);
David Kilroy6415f7d2009-06-18 23:21:30 +0100214static int __orinoco_up(struct orinoco_private *priv);
215static int __orinoco_down(struct orinoco_private *priv);
David Kilroy721aa2f2009-06-18 23:21:31 +0100216static int __orinoco_commit(struct orinoco_private *priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218/********************************************************************/
219/* Internal helper functions */
220/********************************************************************/
221
David Kilroycb1576a2009-02-04 23:05:56 +0000222void set_port_type(struct orinoco_private *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223{
224 switch (priv->iw_mode) {
David Kilroy5217c572009-06-18 23:21:32 +0100225 case NL80211_IFTYPE_STATION:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 priv->port_type = 1;
227 priv->createibss = 0;
228 break;
David Kilroy5217c572009-06-18 23:21:32 +0100229 case NL80211_IFTYPE_ADHOC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 if (priv->prefer_port3) {
231 priv->port_type = 3;
232 priv->createibss = 0;
233 } else {
234 priv->port_type = priv->ibss_port;
235 priv->createibss = 1;
236 }
237 break;
David Kilroy5217c572009-06-18 23:21:32 +0100238 case NL80211_IFTYPE_MONITOR:
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200239 priv->port_type = 3;
240 priv->createibss = 0;
241 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 default:
243 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
244 priv->ndev->name);
245 }
246}
247
David Kilroy3994d502008-08-21 23:27:54 +0100248/********************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249/* Device methods */
250/********************************************************************/
251
252static int orinoco_open(struct net_device *dev)
253{
David Kilroyea60a6a2009-06-18 23:21:26 +0100254 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 unsigned long flags;
256 int err;
257
258 if (orinoco_lock(priv, &flags) != 0)
259 return -EBUSY;
260
David Kilroya2608362009-06-18 23:21:23 +0100261 err = __orinoco_up(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
David Kilroya94e8422009-02-04 23:05:44 +0000263 if (!err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 priv->open = 1;
265
266 orinoco_unlock(priv, &flags);
267
268 return err;
269}
270
Christoph Hellwigad8f4512005-05-14 17:30:17 +0200271static int orinoco_stop(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272{
David Kilroyea60a6a2009-06-18 23:21:26 +0100273 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 int err = 0;
275
276 /* We mustn't use orinoco_lock() here, because we need to be
277 able to close the interface even if hw_unavailable is set
278 (e.g. as we're released after a PC Card removal) */
279 spin_lock_irq(&priv->lock);
280
281 priv->open = 0;
282
David Kilroya2608362009-06-18 23:21:23 +0100283 err = __orinoco_down(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285 spin_unlock_irq(&priv->lock);
286
287 return err;
288}
289
290static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
291{
David Kilroyea60a6a2009-06-18 23:21:26 +0100292 struct orinoco_private *priv = ndev_priv(dev);
David Kilroy6fe9deb2009-02-04 23:05:43 +0000293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 return &priv->stats;
295}
296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297static void orinoco_set_multicast_list(struct net_device *dev)
298{
David Kilroyea60a6a2009-06-18 23:21:26 +0100299 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 unsigned long flags;
301
302 if (orinoco_lock(priv, &flags) != 0) {
303 printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
304 "called when hw_unavailable\n", dev->name);
305 return;
306 }
307
308 __orinoco_set_multicast_list(dev);
309 orinoco_unlock(priv, &flags);
310}
311
312static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
313{
David Kilroyea60a6a2009-06-18 23:21:26 +0100314 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
David Kilroya94e8422009-02-04 23:05:44 +0000316 if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 return -EINVAL;
318
Johannes Berg2c7060022008-10-30 22:09:54 +0100319 /* MTU + encapsulation + header length */
David Kilroya94e8422009-02-04 23:05:44 +0000320 if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
321 (priv->nicbuf_size - ETH_HLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 return -EINVAL;
323
324 dev->mtu = new_mtu;
325
326 return 0;
327}
328
329/********************************************************************/
330/* Tx path */
331/********************************************************************/
332
333static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
334{
David Kilroyea60a6a2009-06-18 23:21:26 +0100335 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 struct net_device_stats *stats = &priv->stats;
337 hermes_t *hw = &priv->hw;
338 int err = 0;
339 u16 txfid = priv->txfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 struct ethhdr *eh;
David Kilroy6eecad72008-08-21 23:27:56 +0100341 int tx_control;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 unsigned long flags;
343
David Kilroya94e8422009-02-04 23:05:44 +0000344 if (!netif_running(dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 printk(KERN_ERR "%s: Tx on stopped device!\n",
346 dev->name);
Pavel Roskinb34b8672006-04-07 04:10:36 -0400347 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 }
David Kilroy6fe9deb2009-02-04 23:05:43 +0000349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 if (netif_queue_stopped(dev)) {
David Kilroy6fe9deb2009-02-04 23:05:43 +0000351 printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 dev->name);
Pavel Roskinb34b8672006-04-07 04:10:36 -0400353 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 }
David Kilroy6fe9deb2009-02-04 23:05:43 +0000355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 if (orinoco_lock(priv, &flags) != 0) {
357 printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
358 dev->name);
Pavel Roskinb34b8672006-04-07 04:10:36 -0400359 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 }
361
David Kilroy5217c572009-06-18 23:21:32 +0100362 if (!netif_carrier_ok(dev) ||
363 (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 /* Oops, the firmware hasn't established a connection,
David Kilroy6fe9deb2009-02-04 23:05:43 +0000365 silently drop the packet (this seems to be the
366 safest approach). */
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400367 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 }
369
Pavel Roskin8d5be082006-04-07 04:10:41 -0400370 /* Check packet length */
Pavel Roskina28dc812006-04-07 04:10:45 -0400371 if (skb->len < ETH_HLEN)
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400372 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
David Kilroy6eecad72008-08-21 23:27:56 +0100374 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
David Kilroy23edcc42008-08-21 23:28:05 +0100376 if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
377 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
378 HERMES_TXCTRL_MIC;
379
David Kilroy6eecad72008-08-21 23:27:56 +0100380 if (priv->has_alt_txcntl) {
381 /* WPA enabled firmwares have tx_cntl at the end of
382 * the 802.11 header. So write zeroed descriptor and
383 * 802.11 header at the same time
384 */
385 char desc[HERMES_802_3_OFFSET];
386 __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
387
388 memset(&desc, 0, sizeof(desc));
389
390 *txcntl = cpu_to_le16(tx_control);
391 err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
392 txfid, 0);
393 if (err) {
394 if (net_ratelimit())
395 printk(KERN_ERR "%s: Error %d writing Tx "
396 "descriptor to BAP\n", dev->name, err);
397 goto busy;
398 }
399 } else {
400 struct hermes_tx_descriptor desc;
401
402 memset(&desc, 0, sizeof(desc));
403
404 desc.tx_control = cpu_to_le16(tx_control);
405 err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
406 txfid, 0);
407 if (err) {
408 if (net_ratelimit())
409 printk(KERN_ERR "%s: Error %d writing Tx "
410 "descriptor to BAP\n", dev->name, err);
411 goto busy;
412 }
413
414 /* Clear the 802.11 header and data length fields - some
415 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
416 * if this isn't done. */
417 hermes_clear_words(hw, HERMES_DATA0,
418 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
David Kilroy23edcc42008-08-21 23:28:05 +0100421 eh = (struct ethhdr *)skb->data;
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* Encapsulate Ethernet-II frames */
424 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
Pavel Roskina28dc812006-04-07 04:10:45 -0400425 struct header_struct {
426 struct ethhdr eth; /* 802.3 header */
427 u8 encap[6]; /* 802.2 header */
428 } __attribute__ ((packed)) hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Pavel Roskina28dc812006-04-07 04:10:45 -0400430 /* Strip destination and source from the data */
431 skb_pull(skb, 2 * ETH_ALEN);
Pavel Roskina28dc812006-04-07 04:10:45 -0400432
433 /* And move them to a separate header */
434 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
435 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
436 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
437
David Kilroy23edcc42008-08-21 23:28:05 +0100438 /* Insert the SNAP header */
439 if (skb_headroom(skb) < sizeof(hdr)) {
440 printk(KERN_ERR
441 "%s: Not enough headroom for 802.2 headers %d\n",
442 dev->name, skb_headroom(skb));
443 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
David Kilroy23edcc42008-08-21 23:28:05 +0100445 eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
446 memcpy(eh, &hdr, sizeof(hdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 }
448
Pavel Roskina28dc812006-04-07 04:10:45 -0400449 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
David Kilroy23edcc42008-08-21 23:28:05 +0100450 txfid, HERMES_802_3_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (err) {
452 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
453 dev->name, err);
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400454 goto busy;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 }
456
David Kilroy23edcc42008-08-21 23:28:05 +0100457 /* Calculate Michael MIC */
458 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
459 u8 mic_buf[MICHAEL_MIC_LEN + 1];
460 u8 *mic;
461 size_t offset;
462 size_t len;
463
464 if (skb->len % 2) {
465 /* MIC start is on an odd boundary */
466 mic_buf[0] = skb->data[skb->len - 1];
467 mic = &mic_buf[1];
468 offset = skb->len - 1;
469 len = MICHAEL_MIC_LEN + 1;
470 } else {
471 mic = &mic_buf[0];
472 offset = skb->len;
473 len = MICHAEL_MIC_LEN;
474 }
475
David Kilroy4adb4742009-02-04 23:05:51 +0000476 orinoco_mic(priv->tx_tfm_mic,
David Kilroy23edcc42008-08-21 23:28:05 +0100477 priv->tkip_key[priv->tx_key].tx_mic,
478 eh->h_dest, eh->h_source, 0 /* priority */,
479 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
480
481 /* Write the MIC */
482 err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
483 txfid, HERMES_802_3_OFFSET + offset);
484 if (err) {
485 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
486 dev->name, err);
487 goto busy;
488 }
489 }
490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 /* Finally, we actually initiate the send */
492 netif_stop_queue(dev);
493
494 err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
495 txfid, NULL);
496 if (err) {
497 netif_start_queue(dev);
Andrew Mortonc367c212005-10-19 21:23:44 -0700498 if (net_ratelimit())
499 printk(KERN_ERR "%s: Error %d transmitting packet\n",
500 dev->name, err);
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400501 goto busy;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
503
504 dev->trans_start = jiffies;
David Kilroy23edcc42008-08-21 23:28:05 +0100505 stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400506 goto ok;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400508 drop:
509 stats->tx_errors++;
510 stats->tx_dropped++;
511
512 ok:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 orinoco_unlock(priv, &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 dev_kfree_skb(skb);
Pavel Roskinb34b8672006-04-07 04:10:36 -0400515 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Pavel Roskin470e2aa2006-04-07 04:10:43 -0400517 busy:
Jiri Benc2c1bd262006-04-07 04:10:47 -0400518 if (err == -EIO)
519 schedule_work(&priv->reset_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 orinoco_unlock(priv, &flags);
Pavel Roskinb34b8672006-04-07 04:10:36 -0400521 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522}
523
524static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
525{
David Kilroyea60a6a2009-06-18 23:21:26 +0100526 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 u16 fid = hermes_read_regn(hw, ALLOCFID);
528
529 if (fid != priv->txfid) {
530 if (fid != DUMMY_FID)
531 printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
532 dev->name, fid);
533 return;
534 }
535
536 hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
537}
538
539static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
540{
David Kilroyea60a6a2009-06-18 23:21:26 +0100541 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 struct net_device_stats *stats = &priv->stats;
543
544 stats->tx_packets++;
545
546 netif_wake_queue(dev);
547
548 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
549}
550
551static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
552{
David Kilroyea60a6a2009-06-18 23:21:26 +0100553 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 struct net_device_stats *stats = &priv->stats;
555 u16 fid = hermes_read_regn(hw, TXCOMPLFID);
Pavel Roskind133ae42005-09-23 04:18:06 -0400556 u16 status;
Pavel Roskin30c2d3b2006-04-07 04:10:34 -0400557 struct hermes_txexc_data hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 int err = 0;
559
560 if (fid == DUMMY_FID)
561 return; /* Nothing's really happened */
562
Pavel Roskin48ca7032005-09-23 04:18:06 -0400563 /* Read part of the frame header - we need status and addr1 */
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200564 err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
Pavel Roskin30c2d3b2006-04-07 04:10:34 -0400565 sizeof(struct hermes_txexc_data),
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200566 fid, 0);
567
568 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
569 stats->tx_errors++;
570
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 if (err) {
572 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
573 "(FID=%04X error %d)\n",
574 dev->name, fid, err);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200575 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 }
David Kilroy6fe9deb2009-02-04 23:05:43 +0000577
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200578 DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
579 err, fid);
David Kilroy6fe9deb2009-02-04 23:05:43 +0000580
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200581 /* We produce a TXDROP event only for retry or lifetime
582 * exceeded, because that's the only status that really mean
583 * that this particular node went away.
584 * Other errors means that *we* screwed up. - Jean II */
Pavel Roskin30c2d3b2006-04-07 04:10:34 -0400585 status = le16_to_cpu(hdr.desc.status);
Pavel Roskind133ae42005-09-23 04:18:06 -0400586 if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
Christoph Hellwig95dd91f2005-06-19 01:27:56 +0200587 union iwreq_data wrqu;
588
589 /* Copy 802.11 dest address.
590 * We use the 802.11 header because the frame may
591 * not be 802.3 or may be mangled...
592 * In Ad-Hoc mode, it will be the node address.
593 * In managed mode, it will be most likely the AP addr
594 * User space will figure out how to convert it to
595 * whatever it needs (IP address or else).
596 * - Jean II */
597 memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
598 wrqu.addr.sa_family = ARPHRD_ETHER;
599
600 /* Send event to user space */
601 wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
604 netif_wake_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605}
606
607static void orinoco_tx_timeout(struct net_device *dev)
608{
David Kilroyea60a6a2009-06-18 23:21:26 +0100609 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 struct net_device_stats *stats = &priv->stats;
611 struct hermes *hw = &priv->hw;
612
613 printk(KERN_WARNING "%s: Tx timeout! "
614 "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
615 dev->name, hermes_read_regn(hw, ALLOCFID),
616 hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
617
618 stats->tx_errors++;
619
620 schedule_work(&priv->reset_work);
621}
622
623/********************************************************************/
624/* Rx path (data frames) */
625/********************************************************************/
626
627/* Does the frame have a SNAP header indicating it should be
628 * de-encapsulated to Ethernet-II? */
629static inline int is_ethersnap(void *_hdr)
630{
631 u8 *hdr = _hdr;
632
633 /* We de-encapsulate all packets which, a) have SNAP headers
634 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
635 * and where b) the OUI of the SNAP header is 00:00:00 or
636 * 00:00:f8 - we need both because different APs appear to use
637 * different OUIs for some reason */
638 return (memcmp(hdr, &encaps_hdr, 5) == 0)
David Kilroya94e8422009-02-04 23:05:44 +0000639 && ((hdr[5] == 0x00) || (hdr[5] == 0xf8));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640}
641
642static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
643 int level, int noise)
644{
Pavel Roskin343c6862005-09-09 18:43:02 -0400645 struct iw_quality wstats;
646 wstats.level = level - 0x95;
647 wstats.noise = noise - 0x95;
648 wstats.qual = (level > noise) ? (level - noise) : 0;
Andrey Borzenkovf941f852008-11-15 17:15:09 +0300649 wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
Pavel Roskin343c6862005-09-09 18:43:02 -0400650 /* Update spy records */
651 wireless_spy_update(dev, mac, &wstats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652}
653
654static void orinoco_stat_gather(struct net_device *dev,
655 struct sk_buff *skb,
656 struct hermes_rx_descriptor *desc)
657{
David Kilroyea60a6a2009-06-18 23:21:26 +0100658 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 /* Using spy support with lots of Rx packets, like in an
661 * infrastructure (AP), will really slow down everything, because
662 * the MAC address must be compared to each entry of the spy list.
663 * If the user really asks for it (set some address in the
664 * spy list), we do it, but he will pay the price.
665 * Note that to get here, you need both WIRELESS_SPY
666 * compiled in AND some addresses in the list !!!
667 */
668 /* Note : gcc will optimise the whole section away if
669 * WIRELESS_SPY is not defined... - Jean II */
670 if (SPY_NUMBER(priv)) {
Arnaldo Carvalho de Melo98e399f2007-03-19 15:33:04 -0700671 orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 desc->signal, desc->silence);
673 }
674}
675
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200676/*
677 * orinoco_rx_monitor - handle received monitor frames.
678 *
679 * Arguments:
680 * dev network device
681 * rxfid received FID
682 * desc rx descriptor of the frame
683 *
684 * Call context: interrupt
685 */
686static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
687 struct hermes_rx_descriptor *desc)
688{
689 u32 hdrlen = 30; /* return full header by default */
690 u32 datalen = 0;
691 u16 fc;
692 int err;
693 int len;
694 struct sk_buff *skb;
David Kilroyea60a6a2009-06-18 23:21:26 +0100695 struct orinoco_private *priv = ndev_priv(dev);
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200696 struct net_device_stats *stats = &priv->stats;
697 hermes_t *hw = &priv->hw;
698
699 len = le16_to_cpu(desc->data_len);
700
701 /* Determine the size of the header and the data */
702 fc = le16_to_cpu(desc->frame_ctl);
703 switch (fc & IEEE80211_FCTL_FTYPE) {
704 case IEEE80211_FTYPE_DATA:
705 if ((fc & IEEE80211_FCTL_TODS)
706 && (fc & IEEE80211_FCTL_FROMDS))
707 hdrlen = 30;
708 else
709 hdrlen = 24;
710 datalen = len;
711 break;
712 case IEEE80211_FTYPE_MGMT:
713 hdrlen = 24;
714 datalen = len;
715 break;
716 case IEEE80211_FTYPE_CTL:
717 switch (fc & IEEE80211_FCTL_STYPE) {
718 case IEEE80211_STYPE_PSPOLL:
719 case IEEE80211_STYPE_RTS:
720 case IEEE80211_STYPE_CFEND:
721 case IEEE80211_STYPE_CFENDACK:
722 hdrlen = 16;
723 break;
724 case IEEE80211_STYPE_CTS:
725 case IEEE80211_STYPE_ACK:
726 hdrlen = 10;
727 break;
728 }
729 break;
730 default:
731 /* Unknown frame type */
732 break;
733 }
734
735 /* sanity check the length */
Johannes Berg2c7060022008-10-30 22:09:54 +0100736 if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200737 printk(KERN_DEBUG "%s: oversized monitor frame, "
738 "data length = %d\n", dev->name, datalen);
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200739 stats->rx_length_errors++;
740 goto update_stats;
741 }
742
743 skb = dev_alloc_skb(hdrlen + datalen);
744 if (!skb) {
745 printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
746 dev->name);
Florin Malitabb6e0932006-05-22 22:35:30 -0700747 goto update_stats;
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200748 }
749
750 /* Copy the 802.11 header to the skb */
751 memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -0700752 skb_reset_mac_header(skb);
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200753
754 /* If any, copy the data from the card to the skb */
755 if (datalen > 0) {
756 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
757 ALIGN(datalen, 2), rxfid,
758 HERMES_802_2_OFFSET);
759 if (err) {
760 printk(KERN_ERR "%s: error %d reading monitor frame\n",
761 dev->name, err);
762 goto drop;
763 }
764 }
765
766 skb->dev = dev;
767 skb->ip_summed = CHECKSUM_NONE;
768 skb->pkt_type = PACKET_OTHERHOST;
Harvey Harrisonc1b4aa32009-01-29 13:26:44 -0800769 skb->protocol = cpu_to_be16(ETH_P_802_2);
David Kilroy6fe9deb2009-02-04 23:05:43 +0000770
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200771 stats->rx_packets++;
772 stats->rx_bytes += skb->len;
773
774 netif_rx(skb);
775 return;
776
777 drop:
778 dev_kfree_skb_irq(skb);
779 update_stats:
780 stats->rx_errors++;
781 stats->rx_dropped++;
782}
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
785{
David Kilroyea60a6a2009-06-18 23:21:26 +0100786 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 struct net_device_stats *stats = &priv->stats;
788 struct iw_statistics *wstats = &priv->wstats;
789 struct sk_buff *skb = NULL;
David Kilroy31afcef2008-08-21 23:28:04 +0100790 u16 rxfid, status;
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200791 int length;
David Kilroy31afcef2008-08-21 23:28:04 +0100792 struct hermes_rx_descriptor *desc;
793 struct orinoco_rx_data *rx_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 int err;
795
David Kilroy31afcef2008-08-21 23:28:04 +0100796 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
797 if (!desc) {
798 printk(KERN_WARNING
799 "%s: Can't allocate space for RX descriptor\n",
800 dev->name);
801 goto update_stats;
802 }
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 rxfid = hermes_read_regn(hw, RXFID);
805
David Kilroy31afcef2008-08-21 23:28:04 +0100806 err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 rxfid, 0);
808 if (err) {
809 printk(KERN_ERR "%s: error %d reading Rx descriptor. "
810 "Frame dropped.\n", dev->name, err);
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200811 goto update_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
813
David Kilroy31afcef2008-08-21 23:28:04 +0100814 status = le16_to_cpu(desc->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200816 if (status & HERMES_RXSTAT_BADCRC) {
817 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
818 dev->name);
819 stats->rx_crc_errors++;
820 goto update_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 }
822
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200823 /* Handle frames in monitor mode */
David Kilroy5217c572009-06-18 23:21:32 +0100824 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
David Kilroy31afcef2008-08-21 23:28:04 +0100825 orinoco_rx_monitor(dev, rxfid, desc);
826 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 }
828
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200829 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
830 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
831 dev->name);
832 wstats->discard.code++;
833 goto update_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
835
David Kilroy31afcef2008-08-21 23:28:04 +0100836 length = le16_to_cpu(desc->data_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /* Sanity checks */
839 if (length < 3) { /* No for even an 802.2 LLC header */
840 /* At least on Symbol firmware with PCF we get quite a
David Kilroy6fe9deb2009-02-04 23:05:43 +0000841 lot of these legitimately - Poll frames with no
842 data. */
David Kilroy31afcef2008-08-21 23:28:04 +0100843 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
Johannes Berg2c7060022008-10-30 22:09:54 +0100845 if (length > IEEE80211_MAX_DATA_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
847 dev->name, length);
848 stats->rx_length_errors++;
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200849 goto update_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 }
851
David Kilroy23edcc42008-08-21 23:28:05 +0100852 /* Payload size does not include Michael MIC. Increase payload
853 * size to read it together with the data. */
854 if (status & HERMES_RXSTAT_MIC)
855 length += MICHAEL_MIC_LEN;
856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 /* We need space for the packet data itself, plus an ethernet
858 header, plus 2 bytes so we can align the IP header on a
859 32bit boundary, plus 1 byte so we can read in odd length
860 packets from the card, which has an IO granularity of 16
David Kilroy6fe9deb2009-02-04 23:05:43 +0000861 bits */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 skb = dev_alloc_skb(length+ETH_HLEN+2+1);
863 if (!skb) {
864 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
865 dev->name);
Christoph Hellwig98c4cae2005-06-19 01:28:06 +0200866 goto update_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 }
868
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200869 /* We'll prepend the header, so reserve space for it. The worst
870 case is no decapsulation, when 802.3 header is prepended and
871 nothing is removed. 2 is for aligning the IP header. */
872 skb_reserve(skb, ETH_HLEN + 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200874 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
875 ALIGN(length, 2), rxfid,
876 HERMES_802_2_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (err) {
878 printk(KERN_ERR "%s: error %d reading frame. "
879 "Frame dropped.\n", dev->name, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 goto drop;
881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
David Kilroy31afcef2008-08-21 23:28:04 +0100883 /* Add desc and skb to rx queue */
884 rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC);
885 if (!rx_data) {
886 printk(KERN_WARNING "%s: Can't allocate RX packet\n",
887 dev->name);
888 goto drop;
889 }
890 rx_data->desc = desc;
891 rx_data->skb = skb;
892 list_add_tail(&rx_data->list, &priv->rx_list);
893 tasklet_schedule(&priv->rx_tasklet);
894
895 return;
896
897drop:
898 dev_kfree_skb_irq(skb);
899update_stats:
900 stats->rx_errors++;
901 stats->rx_dropped++;
902out:
903 kfree(desc);
904}
905
906static void orinoco_rx(struct net_device *dev,
907 struct hermes_rx_descriptor *desc,
908 struct sk_buff *skb)
909{
David Kilroyea60a6a2009-06-18 23:21:26 +0100910 struct orinoco_private *priv = ndev_priv(dev);
David Kilroy31afcef2008-08-21 23:28:04 +0100911 struct net_device_stats *stats = &priv->stats;
912 u16 status, fc;
913 int length;
914 struct ethhdr *hdr;
915
916 status = le16_to_cpu(desc->status);
917 length = le16_to_cpu(desc->data_len);
918 fc = le16_to_cpu(desc->frame_ctl);
919
David Kilroy23edcc42008-08-21 23:28:05 +0100920 /* Calculate and check MIC */
921 if (status & HERMES_RXSTAT_MIC) {
922 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
923 HERMES_MIC_KEY_ID_SHIFT);
924 u8 mic[MICHAEL_MIC_LEN];
925 u8 *rxmic;
926 u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
927 desc->addr3 : desc->addr2;
928
929 /* Extract Michael MIC from payload */
930 rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
931
932 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
933 length -= MICHAEL_MIC_LEN;
934
David Kilroy4adb4742009-02-04 23:05:51 +0000935 orinoco_mic(priv->rx_tfm_mic,
David Kilroy23edcc42008-08-21 23:28:05 +0100936 priv->tkip_key[key_id].rx_mic,
937 desc->addr1,
938 src,
939 0, /* priority or QoS? */
940 skb->data,
941 skb->len,
942 &mic[0]);
943
944 if (memcmp(mic, rxmic,
945 MICHAEL_MIC_LEN)) {
946 union iwreq_data wrqu;
947 struct iw_michaelmicfailure wxmic;
David Kilroy23edcc42008-08-21 23:28:05 +0100948
949 printk(KERN_WARNING "%s: "
Johannes Berge1749612008-10-27 15:59:26 -0700950 "Invalid Michael MIC in data frame from %pM, "
David Kilroy23edcc42008-08-21 23:28:05 +0100951 "using key %i\n",
Johannes Berge1749612008-10-27 15:59:26 -0700952 dev->name, src, key_id);
David Kilroy23edcc42008-08-21 23:28:05 +0100953
954 /* TODO: update stats */
955
956 /* Notify userspace */
957 memset(&wxmic, 0, sizeof(wxmic));
958 wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
959 wxmic.flags |= (desc->addr1[0] & 1) ?
960 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
961 wxmic.src_addr.sa_family = ARPHRD_ETHER;
962 memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
963
964 (void) orinoco_hw_get_tkip_iv(priv, key_id,
965 &wxmic.tsc[0]);
966
967 memset(&wrqu, 0, sizeof(wrqu));
968 wrqu.data.length = sizeof(wxmic);
969 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
970 (char *) &wxmic);
971
972 goto drop;
973 }
974 }
975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 /* Handle decapsulation
977 * In most cases, the firmware tell us about SNAP frames.
978 * For some reason, the SNAP frames sent by LinkSys APs
979 * are not properly recognised by most firmwares.
980 * So, check ourselves */
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200981 if (length >= ENCAPS_OVERHEAD &&
982 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
983 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
984 is_ethersnap(skb->data))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 /* These indicate a SNAP within 802.2 LLC within
986 802.11 frame which we'll need to de-encapsulate to
987 the original EthernetII frame. */
David Kilroyb2f30a02009-02-04 23:05:46 +0000988 hdr = (struct ethhdr *)skb_push(skb,
989 ETH_HLEN - ENCAPS_OVERHEAD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 } else {
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200991 /* 802.3 frame - prepend 802.3 header as is */
992 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
993 hdr->h_proto = htons(length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
David Kilroy31afcef2008-08-21 23:28:04 +0100995 memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200996 if (fc & IEEE80211_FCTL_FROMDS)
David Kilroy31afcef2008-08-21 23:28:04 +0100997 memcpy(hdr->h_source, desc->addr3, ETH_ALEN);
Christoph Hellwig8f2abf42005-06-19 01:28:02 +0200998 else
David Kilroy31afcef2008-08-21 23:28:04 +0100999 memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 skb->protocol = eth_type_trans(skb, dev);
1002 skb->ip_summed = CHECKSUM_NONE;
Christoph Hellwig8f2abf42005-06-19 01:28:02 +02001003 if (fc & IEEE80211_FCTL_TODS)
1004 skb->pkt_type = PACKET_OTHERHOST;
David Kilroy6fe9deb2009-02-04 23:05:43 +00001005
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 /* Process the wireless stats if needed */
David Kilroy31afcef2008-08-21 23:28:04 +01001007 orinoco_stat_gather(dev, skb, desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
1009 /* Pass the packet to the networking stack */
1010 netif_rx(skb);
1011 stats->rx_packets++;
1012 stats->rx_bytes += length;
1013
1014 return;
David Kilroy23edcc42008-08-21 23:28:05 +01001015
1016 drop:
1017 dev_kfree_skb(skb);
1018 stats->rx_errors++;
1019 stats->rx_dropped++;
David Kilroy31afcef2008-08-21 23:28:04 +01001020}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
David Kilroy31afcef2008-08-21 23:28:04 +01001022static void orinoco_rx_isr_tasklet(unsigned long data)
1023{
David Kilroy53819562009-06-18 23:21:28 +01001024 struct orinoco_private *priv = (struct orinoco_private *) data;
1025 struct net_device *dev = priv->ndev;
David Kilroy31afcef2008-08-21 23:28:04 +01001026 struct orinoco_rx_data *rx_data, *temp;
1027 struct hermes_rx_descriptor *desc;
1028 struct sk_buff *skb;
David Kilroy20953ad2009-01-07 00:23:55 +00001029 unsigned long flags;
1030
1031 /* orinoco_rx requires the driver lock, and we also need to
1032 * protect priv->rx_list, so just hold the lock over the
1033 * lot.
1034 *
1035 * If orinoco_lock fails, we've unplugged the card. In this
1036 * case just abort. */
1037 if (orinoco_lock(priv, &flags) != 0)
1038 return;
David Kilroy31afcef2008-08-21 23:28:04 +01001039
1040 /* extract desc and skb from queue */
1041 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
1042 desc = rx_data->desc;
1043 skb = rx_data->skb;
1044 list_del(&rx_data->list);
1045 kfree(rx_data);
1046
1047 orinoco_rx(dev, desc, skb);
1048
1049 kfree(desc);
1050 }
David Kilroy20953ad2009-01-07 00:23:55 +00001051
1052 orinoco_unlock(priv, &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053}
1054
1055/********************************************************************/
1056/* Rx path (info frames) */
1057/********************************************************************/
1058
1059static void print_linkstatus(struct net_device *dev, u16 status)
1060{
David Kilroy21312662009-02-04 23:05:47 +00001061 char *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 if (suppress_linkstatus)
1064 return;
1065
1066 switch (status) {
1067 case HERMES_LINKSTATUS_NOT_CONNECTED:
1068 s = "Not Connected";
1069 break;
1070 case HERMES_LINKSTATUS_CONNECTED:
1071 s = "Connected";
1072 break;
1073 case HERMES_LINKSTATUS_DISCONNECTED:
1074 s = "Disconnected";
1075 break;
1076 case HERMES_LINKSTATUS_AP_CHANGE:
1077 s = "AP Changed";
1078 break;
1079 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1080 s = "AP Out of Range";
1081 break;
1082 case HERMES_LINKSTATUS_AP_IN_RANGE:
1083 s = "AP In Range";
1084 break;
1085 case HERMES_LINKSTATUS_ASSOC_FAILED:
1086 s = "Association Failed";
1087 break;
1088 default:
1089 s = "UNKNOWN";
1090 }
David Kilroy6fe9deb2009-02-04 23:05:43 +00001091
Pavel Roskin11eaea42009-01-18 23:20:58 -05001092 printk(KERN_DEBUG "%s: New link status: %s (%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 dev->name, s, status);
1094}
1095
Christoph Hellwig16739b02005-06-19 01:27:51 +02001096/* Search scan results for requested BSSID, join it if found */
David Howellsc4028952006-11-22 14:57:56 +00001097static void orinoco_join_ap(struct work_struct *work)
Christoph Hellwig16739b02005-06-19 01:27:51 +02001098{
David Howellsc4028952006-11-22 14:57:56 +00001099 struct orinoco_private *priv =
1100 container_of(work, struct orinoco_private, join_work);
1101 struct net_device *dev = priv->ndev;
Christoph Hellwig16739b02005-06-19 01:27:51 +02001102 struct hermes *hw = &priv->hw;
1103 int err;
1104 unsigned long flags;
1105 struct join_req {
1106 u8 bssid[ETH_ALEN];
Pavel Roskind133ae42005-09-23 04:18:06 -04001107 __le16 channel;
Christoph Hellwig16739b02005-06-19 01:27:51 +02001108 } __attribute__ ((packed)) req;
1109 const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
Pavel Roskinc89cc222005-09-01 20:06:06 -04001110 struct prism2_scan_apinfo *atom = NULL;
Christoph Hellwig16739b02005-06-19 01:27:51 +02001111 int offset = 4;
Pavel Roskinc89cc222005-09-01 20:06:06 -04001112 int found = 0;
Christoph Hellwig16739b02005-06-19 01:27:51 +02001113 u8 *buf;
1114 u16 len;
1115
1116 /* Allocate buffer for scan results */
1117 buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
David Kilroya94e8422009-02-04 23:05:44 +00001118 if (!buf)
Christoph Hellwig16739b02005-06-19 01:27:51 +02001119 return;
1120
1121 if (orinoco_lock(priv, &flags) != 0)
Pavel Roskinf3cb4cc2005-09-23 04:18:06 -04001122 goto fail_lock;
Christoph Hellwig16739b02005-06-19 01:27:51 +02001123
1124 /* Sanity checks in case user changed something in the meantime */
David Kilroya94e8422009-02-04 23:05:44 +00001125 if (!priv->bssid_fixed)
Christoph Hellwig16739b02005-06-19 01:27:51 +02001126 goto out;
1127
1128 if (strlen(priv->desired_essid) == 0)
1129 goto out;
1130
1131 /* Read scan results from the firmware */
1132 err = hermes_read_ltv(hw, USER_BAP,
1133 HERMES_RID_SCANRESULTSTABLE,
1134 MAX_SCAN_LEN, &len, buf);
1135 if (err) {
1136 printk(KERN_ERR "%s: Cannot read scan results\n",
1137 dev->name);
1138 goto out;
1139 }
1140
1141 len = HERMES_RECLEN_TO_BYTES(len);
1142
1143 /* Go through the scan results looking for the channel of the AP
1144 * we were requested to join */
1145 for (; offset + atom_len <= len; offset += atom_len) {
1146 atom = (struct prism2_scan_apinfo *) (buf + offset);
Pavel Roskinc89cc222005-09-01 20:06:06 -04001147 if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
1148 found = 1;
1149 break;
1150 }
Christoph Hellwig16739b02005-06-19 01:27:51 +02001151 }
1152
David Kilroya94e8422009-02-04 23:05:44 +00001153 if (!found) {
Pavel Roskinc89cc222005-09-01 20:06:06 -04001154 DEBUG(1, "%s: Requested AP not found in scan results\n",
1155 dev->name);
1156 goto out;
1157 }
Christoph Hellwig16739b02005-06-19 01:27:51 +02001158
Christoph Hellwig16739b02005-06-19 01:27:51 +02001159 memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
1160 req.channel = atom->channel; /* both are little-endian */
1161 err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
1162 &req);
1163 if (err)
1164 printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
1165
1166 out:
Christoph Hellwig16739b02005-06-19 01:27:51 +02001167 orinoco_unlock(priv, &flags);
Pavel Roskinf3cb4cc2005-09-23 04:18:06 -04001168
1169 fail_lock:
1170 kfree(buf);
Christoph Hellwig16739b02005-06-19 01:27:51 +02001171}
1172
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001173/* Send new BSSID to userspace */
David Kilroy6cd90b12008-08-21 23:28:00 +01001174static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001175{
David Howellsc4028952006-11-22 14:57:56 +00001176 struct net_device *dev = priv->ndev;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001177 struct hermes *hw = &priv->hw;
1178 union iwreq_data wrqu;
1179 int err;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001180
David Kilroy499b7022008-12-09 21:46:29 +00001181 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001182 ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
1183 if (err != 0)
David Kilroy6cd90b12008-08-21 23:28:00 +01001184 return;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001185
1186 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1187
1188 /* Send event to user space */
1189 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001190}
1191
David Kilroy06009fd2008-08-21 23:28:03 +01001192static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
1193{
1194 struct net_device *dev = priv->ndev;
1195 struct hermes *hw = &priv->hw;
1196 union iwreq_data wrqu;
1197 int err;
1198 u8 buf[88];
1199 u8 *ie;
1200
1201 if (!priv->has_wpa)
1202 return;
1203
David Kilroy499b7022008-12-09 21:46:29 +00001204 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
David Kilroy06009fd2008-08-21 23:28:03 +01001205 sizeof(buf), NULL, &buf);
1206 if (err != 0)
1207 return;
1208
1209 ie = orinoco_get_wpa_ie(buf, sizeof(buf));
1210 if (ie) {
1211 int rem = sizeof(buf) - (ie - &buf[0]);
1212 wrqu.data.length = ie[1] + 2;
1213 if (wrqu.data.length > rem)
1214 wrqu.data.length = rem;
1215
1216 if (wrqu.data.length)
1217 /* Send event to user space */
1218 wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
1219 }
1220}
1221
1222static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
1223{
1224 struct net_device *dev = priv->ndev;
1225 struct hermes *hw = &priv->hw;
1226 union iwreq_data wrqu;
1227 int err;
1228 u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
1229 u8 *ie;
1230
1231 if (!priv->has_wpa)
1232 return;
1233
David Kilroy499b7022008-12-09 21:46:29 +00001234 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
David Kilroy06009fd2008-08-21 23:28:03 +01001235 sizeof(buf), NULL, &buf);
1236 if (err != 0)
1237 return;
1238
1239 ie = orinoco_get_wpa_ie(buf, sizeof(buf));
1240 if (ie) {
1241 int rem = sizeof(buf) - (ie - &buf[0]);
1242 wrqu.data.length = ie[1] + 2;
1243 if (wrqu.data.length > rem)
1244 wrqu.data.length = rem;
1245
1246 if (wrqu.data.length)
1247 /* Send event to user space */
1248 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
1249 }
1250}
1251
David Kilroy6cd90b12008-08-21 23:28:00 +01001252static void orinoco_send_wevents(struct work_struct *work)
1253{
1254 struct orinoco_private *priv =
1255 container_of(work, struct orinoco_private, wevent_work);
1256 unsigned long flags;
1257
1258 if (orinoco_lock(priv, &flags) != 0)
1259 return;
1260
David Kilroy06009fd2008-08-21 23:28:03 +01001261 orinoco_send_assocreqie_wevent(priv);
1262 orinoco_send_assocrespie_wevent(priv);
David Kilroy6cd90b12008-08-21 23:28:00 +01001263 orinoco_send_bssid_wevent(priv);
1264
1265 orinoco_unlock(priv, &flags);
1266}
Dan Williams1e3428e2007-10-10 23:56:25 -04001267
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1269{
David Kilroyea60a6a2009-06-18 23:21:26 +01001270 struct orinoco_private *priv = ndev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 u16 infofid;
1272 struct {
Pavel Roskind133ae42005-09-23 04:18:06 -04001273 __le16 len;
1274 __le16 type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 } __attribute__ ((packed)) info;
1276 int len, type;
1277 int err;
1278
1279 /* This is an answer to an INQUIRE command that we did earlier,
1280 * or an information "event" generated by the card
1281 * The controller return to us a pseudo frame containing
1282 * the information in question - Jean II */
1283 infofid = hermes_read_regn(hw, INFOFID);
1284
1285 /* Read the info frame header - don't try too hard */
1286 err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1287 infofid, 0);
1288 if (err) {
1289 printk(KERN_ERR "%s: error %d reading info frame. "
1290 "Frame dropped.\n", dev->name, err);
1291 return;
1292 }
David Kilroy6fe9deb2009-02-04 23:05:43 +00001293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1295 type = le16_to_cpu(info.type);
1296
1297 switch (type) {
1298 case HERMES_INQ_TALLIES: {
1299 struct hermes_tallies_frame tallies;
1300 struct iw_statistics *wstats = &priv->wstats;
David Kilroy6fe9deb2009-02-04 23:05:43 +00001301
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 if (len > sizeof(tallies)) {
1303 printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
1304 dev->name, len);
1305 len = sizeof(tallies);
1306 }
David Kilroy6fe9deb2009-02-04 23:05:43 +00001307
Christoph Hellwig84d8a2f2005-05-14 17:30:22 +02001308 err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
1309 infofid, sizeof(info));
1310 if (err)
1311 break;
David Kilroy6fe9deb2009-02-04 23:05:43 +00001312
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 /* Increment our various counters */
1314 /* wstats->discard.nwid - no wrong BSSID stuff */
1315 wstats->discard.code +=
1316 le16_to_cpu(tallies.RxWEPUndecryptable);
David Kilroy6fe9deb2009-02-04 23:05:43 +00001317 if (len == sizeof(tallies))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 wstats->discard.code +=
1319 le16_to_cpu(tallies.RxDiscards_WEPICVError) +
1320 le16_to_cpu(tallies.RxDiscards_WEPExcluded);
1321 wstats->discard.misc +=
1322 le16_to_cpu(tallies.TxDiscardsWrongSA);
1323 wstats->discard.fragment +=
1324 le16_to_cpu(tallies.RxMsgInBadMsgFragments);
1325 wstats->discard.retries +=
1326 le16_to_cpu(tallies.TxRetryLimitExceeded);
1327 /* wstats->miss.beacon - no match */
1328 }
1329 break;
1330 case HERMES_INQ_LINKSTATUS: {
1331 struct hermes_linkstatus linkstatus;
1332 u16 newstatus;
1333 int connected;
1334
David Kilroy5217c572009-06-18 23:21:32 +01001335 if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
Christoph Hellwig8f2abf42005-06-19 01:28:02 +02001336 break;
1337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (len != sizeof(linkstatus)) {
1339 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1340 dev->name, len);
1341 break;
1342 }
1343
Christoph Hellwig84d8a2f2005-05-14 17:30:22 +02001344 err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
1345 infofid, sizeof(info));
1346 if (err)
1347 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 newstatus = le16_to_cpu(linkstatus.linkstatus);
1349
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001350 /* Symbol firmware uses "out of range" to signal that
1351 * the hostscan frame can be requested. */
1352 if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
1353 priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
1354 priv->has_hostscan && priv->scan_inprogress) {
1355 hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
1356 break;
1357 }
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
1360 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1361 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
1362
1363 if (connected)
1364 netif_carrier_on(dev);
David Gibson7bb7c3a2005-05-12 20:02:10 -04001365 else if (!ignore_disconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 netif_carrier_off(dev);
1367
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001368 if (newstatus != priv->last_linkstatus) {
1369 priv->last_linkstatus = newstatus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 print_linkstatus(dev, newstatus);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001371 /* The info frame contains only one word which is the
1372 * status (see hermes.h). The status is pretty boring
1373 * in itself, that's why we export the new BSSID...
1374 * Jean II */
1375 schedule_work(&priv->wevent_work);
1376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 }
1378 break;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001379 case HERMES_INQ_SCAN:
1380 if (!priv->scan_inprogress && priv->bssid_fixed &&
1381 priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
1382 schedule_work(&priv->join_work);
1383 break;
1384 }
1385 /* fall through */
1386 case HERMES_INQ_HOSTSCAN:
1387 case HERMES_INQ_HOSTSCAN_SYMBOL: {
1388 /* Result of a scanning. Contains information about
1389 * cells in the vicinity - Jean II */
1390 union iwreq_data wrqu;
1391 unsigned char *buf;
1392
Dan Williams1e3428e2007-10-10 23:56:25 -04001393 /* Scan is no longer in progress */
1394 priv->scan_inprogress = 0;
1395
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001396 /* Sanity check */
1397 if (len > 4096) {
1398 printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
1399 dev->name, len);
1400 break;
1401 }
1402
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001403 /* Allocate buffer for results */
1404 buf = kmalloc(len, GFP_ATOMIC);
1405 if (buf == NULL)
1406 /* No memory, so can't printk()... */
1407 break;
1408
1409 /* Read scan data */
1410 err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
1411 infofid, sizeof(info));
Pavel Roskin708218b2005-09-01 20:05:19 -04001412 if (err) {
1413 kfree(buf);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001414 break;
Pavel Roskin708218b2005-09-01 20:05:19 -04001415 }
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001416
1417#ifdef ORINOCO_DEBUG
1418 {
1419 int i;
1420 printk(KERN_DEBUG "Scan result [%02X", buf[0]);
David Kilroya94e8422009-02-04 23:05:44 +00001421 for (i = 1; i < (len * 2); i++)
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001422 printk(":%02X", buf[i]);
1423 printk("]\n");
1424 }
1425#endif /* ORINOCO_DEBUG */
1426
David Kilroyaea48b12009-02-04 23:05:49 +00001427 if (orinoco_process_scan_results(priv, buf, len) == 0) {
Dan Williams1e3428e2007-10-10 23:56:25 -04001428 /* Send an empty event to user space.
1429 * We don't send the received data on the event because
1430 * it would require us to do complex transcoding, and
1431 * we want to minimise the work done in the irq handler
1432 * Use a request to extract the data - Jean II */
1433 wrqu.data.length = 0;
1434 wrqu.data.flags = 0;
1435 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1436 }
1437 kfree(buf);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001438 }
1439 break;
David Kilroy01632fa2008-08-21 23:27:58 +01001440 case HERMES_INQ_CHANNELINFO:
1441 {
1442 struct agere_ext_scan_info *bss;
1443
1444 if (!priv->scan_inprogress) {
1445 printk(KERN_DEBUG "%s: Got chaninfo without scan, "
1446 "len=%d\n", dev->name, len);
1447 break;
1448 }
1449
1450 /* An empty result indicates that the scan is complete */
1451 if (len == 0) {
1452 union iwreq_data wrqu;
1453
1454 /* Scan is no longer in progress */
1455 priv->scan_inprogress = 0;
1456
1457 wrqu.data.length = 0;
1458 wrqu.data.flags = 0;
1459 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1460 break;
1461 }
1462
1463 /* Sanity check */
1464 else if (len > sizeof(*bss)) {
1465 printk(KERN_WARNING
1466 "%s: Ext scan results too large (%d bytes). "
1467 "Truncating results to %zd bytes.\n",
1468 dev->name, len, sizeof(*bss));
1469 len = sizeof(*bss);
1470 } else if (len < (offsetof(struct agere_ext_scan_info,
1471 data) + 2)) {
1472 /* Drop this result now so we don't have to
1473 * keep checking later */
1474 printk(KERN_WARNING
1475 "%s: Ext scan results too short (%d bytes)\n",
1476 dev->name, len);
1477 break;
1478 }
1479
1480 bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
1481 if (bss == NULL)
1482 break;
1483
1484 /* Read scan data */
1485 err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
1486 infofid, sizeof(info));
1487 if (err) {
1488 kfree(bss);
1489 break;
1490 }
1491
1492 orinoco_add_ext_scan_result(priv, bss);
1493
1494 kfree(bss);
1495 break;
1496 }
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001497 case HERMES_INQ_SEC_STAT_AGERE:
1498 /* Security status (Agere specific) */
1499 /* Ignore this frame for now */
1500 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
1501 break;
1502 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 default:
1504 printk(KERN_DEBUG "%s: Unknown information frame received: "
1505 "type 0x%04x, length %d\n", dev->name, type, len);
1506 /* We don't actually do anything about it */
1507 break;
1508 }
1509}
1510
1511static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
1512{
1513 if (net_ratelimit())
1514 printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
1515}
1516
1517/********************************************************************/
1518/* Internal hardware control routines */
1519/********************************************************************/
1520
David Kilroy6415f7d2009-06-18 23:21:30 +01001521static int __orinoco_up(struct orinoco_private *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522{
David Kilroya2608362009-06-18 23:21:23 +01001523 struct net_device *dev = priv->ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 struct hermes *hw = &priv->hw;
1525 int err;
1526
Christoph Hellwig84d8a2f2005-05-14 17:30:22 +02001527 netif_carrier_off(dev); /* just to make sure */
1528
David Kilroy721aa2f2009-06-18 23:21:31 +01001529 err = __orinoco_commit(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 if (err) {
1531 printk(KERN_ERR "%s: Error %d configuring card\n",
1532 dev->name, err);
1533 return err;
1534 }
1535
1536 /* Fire things up again */
1537 hermes_set_irqmask(hw, ORINOCO_INTEN);
1538 err = hermes_enable_port(hw, 0);
1539 if (err) {
1540 printk(KERN_ERR "%s: Error %d enabling MAC port\n",
1541 dev->name, err);
1542 return err;
1543 }
1544
1545 netif_start_queue(dev);
1546
1547 return 0;
1548}
1549
David Kilroy6415f7d2009-06-18 23:21:30 +01001550static int __orinoco_down(struct orinoco_private *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
David Kilroya2608362009-06-18 23:21:23 +01001552 struct net_device *dev = priv->ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 struct hermes *hw = &priv->hw;
1554 int err;
1555
1556 netif_stop_queue(dev);
1557
David Kilroya94e8422009-02-04 23:05:44 +00001558 if (!priv->hw_unavailable) {
1559 if (!priv->broken_disableport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 err = hermes_disable_port(hw, 0);
1561 if (err) {
1562 /* Some firmwares (e.g. Intersil 1.3.x) seem
1563 * to have problems disabling the port, oh
1564 * well, too bad. */
1565 printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
1566 dev->name, err);
1567 priv->broken_disableport = 1;
1568 }
1569 }
1570 hermes_set_irqmask(hw, 0);
1571 hermes_write_regn(hw, EVACK, 0xffff);
1572 }
David Kilroy6fe9deb2009-02-04 23:05:43 +00001573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 /* firmware will have to reassociate */
1575 netif_carrier_off(dev);
1576 priv->last_linkstatus = 0xffff;
1577
1578 return 0;
1579}
1580
David Kilroy6415f7d2009-06-18 23:21:30 +01001581static int orinoco_reinit_firmware(struct orinoco_private *priv)
Pavel Roskin37a6c612006-04-07 04:10:49 -04001582{
Pavel Roskin37a6c612006-04-07 04:10:49 -04001583 struct hermes *hw = &priv->hw;
1584 int err;
1585
1586 err = hermes_init(hw);
Andrey Borzenkov0df6cbb2008-10-12 20:15:43 +04001587 if (priv->do_fw_download && !err) {
1588 err = orinoco_download(priv);
1589 if (err)
1590 priv->do_fw_download = 0;
1591 }
Pavel Roskin37a6c612006-04-07 04:10:49 -04001592 if (!err)
David Kilroy42a51b92009-06-18 23:21:20 +01001593 err = orinoco_hw_allocate_fid(priv);
Pavel Roskin37a6c612006-04-07 04:10:49 -04001594
1595 return err;
1596}
1597
David Kilroy721aa2f2009-06-18 23:21:31 +01001598static int
David Kilroy5865d012009-02-04 23:05:54 +00001599__orinoco_set_multicast_list(struct net_device *dev)
1600{
David Kilroyea60a6a2009-06-18 23:21:26 +01001601 struct orinoco_private *priv = ndev_priv(dev);
David Kilroy5865d012009-02-04 23:05:54 +00001602 int err = 0;
1603 int promisc, mc_count;
1604
1605 /* The Hermes doesn't seem to have an allmulti mode, so we go
1606 * into promiscuous mode and let the upper levels deal. */
1607 if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
1608 (dev->mc_count > MAX_MULTICAST(priv))) {
1609 promisc = 1;
1610 mc_count = 0;
1611 } else {
1612 promisc = 0;
1613 mc_count = dev->mc_count;
1614 }
1615
1616 err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count,
1617 promisc);
David Kilroy721aa2f2009-06-18 23:21:31 +01001618
1619 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620}
1621
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622/* This must be called from user context, without locks held - use
1623 * schedule_work() */
David Kilroycb1576a2009-02-04 23:05:56 +00001624void orinoco_reset(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625{
David Howellsc4028952006-11-22 14:57:56 +00001626 struct orinoco_private *priv =
1627 container_of(work, struct orinoco_private, reset_work);
1628 struct net_device *dev = priv->ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 struct hermes *hw = &priv->hw;
Christoph Hellwig8551cb92005-05-14 17:30:04 +02001630 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 unsigned long flags;
1632
1633 if (orinoco_lock(priv, &flags) != 0)
1634 /* When the hardware becomes available again, whatever
1635 * detects that is responsible for re-initializing
1636 * it. So no need for anything further */
1637 return;
1638
1639 netif_stop_queue(dev);
1640
1641 /* Shut off interrupts. Depending on what state the hardware
1642 * is in, this might not work, but we'll try anyway */
1643 hermes_set_irqmask(hw, 0);
1644 hermes_write_regn(hw, EVACK, 0xffff);
1645
1646 priv->hw_unavailable++;
1647 priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
1648 netif_carrier_off(dev);
1649
1650 orinoco_unlock(priv, &flags);
1651
David Kilroy6fe9deb2009-02-04 23:05:43 +00001652 /* Scanning support: Cleanup of driver struct */
Dan Williams1e3428e2007-10-10 23:56:25 -04001653 orinoco_clear_scan_results(priv, 0);
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02001654 priv->scan_inprogress = 0;
1655
Christoph Hellwig8551cb92005-05-14 17:30:04 +02001656 if (priv->hard_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 err = (*priv->hard_reset)(priv);
Christoph Hellwig8551cb92005-05-14 17:30:04 +02001658 if (err) {
1659 printk(KERN_ERR "%s: orinoco_reset: Error %d "
1660 "performing hard reset\n", dev->name, err);
1661 goto disable;
1662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
1664
David Kilroya2608362009-06-18 23:21:23 +01001665 err = orinoco_reinit_firmware(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 if (err) {
1667 printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
1668 dev->name, err);
Christoph Hellwig8551cb92005-05-14 17:30:04 +02001669 goto disable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 }
1671
David Kilroyb2f30a02009-02-04 23:05:46 +00001672 /* This has to be called from user context */
1673 spin_lock_irq(&priv->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
1675 priv->hw_unavailable--;
1676
1677 /* priv->open or priv->hw_unavailable might have changed while
1678 * we dropped the lock */
David Kilroya94e8422009-02-04 23:05:44 +00001679 if (priv->open && (!priv->hw_unavailable)) {
David Kilroya2608362009-06-18 23:21:23 +01001680 err = __orinoco_up(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 if (err) {
1682 printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
1683 dev->name, err);
1684 } else
1685 dev->trans_start = jiffies;
1686 }
1687
1688 spin_unlock_irq(&priv->lock);
1689
1690 return;
Christoph Hellwig8551cb92005-05-14 17:30:04 +02001691 disable:
1692 hermes_set_irqmask(hw, 0);
1693 netif_device_detach(dev);
1694 printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695}
1696
David Kilroy721aa2f2009-06-18 23:21:31 +01001697static int __orinoco_commit(struct orinoco_private *priv)
1698{
1699 struct net_device *dev = priv->ndev;
1700 int err = 0;
1701
1702 err = orinoco_hw_program_rids(priv);
1703
1704 /* FIXME: what about netif_tx_lock */
1705 (void) __orinoco_set_multicast_list(dev);
1706
1707 return err;
1708}
1709
1710/* Ensures configuration changes are applied. May result in a reset.
1711 * The caller should hold priv->lock
1712 */
1713int orinoco_commit(struct orinoco_private *priv)
1714{
1715 struct net_device *dev = priv->ndev;
1716 hermes_t *hw = &priv->hw;
1717 int err;
1718
1719 if (priv->broken_disableport) {
1720 schedule_work(&priv->reset_work);
1721 return 0;
1722 }
1723
1724 err = hermes_disable_port(hw, 0);
1725 if (err) {
1726 printk(KERN_WARNING "%s: Unable to disable port "
1727 "while reconfiguring card\n", dev->name);
1728 priv->broken_disableport = 1;
1729 goto out;
1730 }
1731
1732 err = __orinoco_commit(priv);
1733 if (err) {
1734 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
1735 dev->name);
1736 goto out;
1737 }
1738
1739 err = hermes_enable_port(hw, 0);
1740 if (err) {
1741 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
1742 dev->name);
1743 goto out;
1744 }
1745
1746 out:
1747 if (err) {
1748 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
1749 schedule_work(&priv->reset_work);
1750 err = 0;
1751 }
1752 return err;
1753}
1754
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755/********************************************************************/
1756/* Interrupt handler */
1757/********************************************************************/
1758
1759static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
1760{
1761 printk(KERN_DEBUG "%s: TICK\n", dev->name);
1762}
1763
1764static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
1765{
1766 /* This seems to happen a fair bit under load, but ignoring it
1767 seems to work fine...*/
1768 printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
1769 dev->name);
1770}
1771
David Howells7d12e782006-10-05 14:55:46 +01001772irqreturn_t orinoco_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
David Kilroya2608362009-06-18 23:21:23 +01001774 struct orinoco_private *priv = dev_id;
1775 struct net_device *dev = priv->ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 hermes_t *hw = &priv->hw;
1777 int count = MAX_IRQLOOPS_PER_IRQ;
1778 u16 evstat, events;
David Kilroy21312662009-02-04 23:05:47 +00001779 /* These are used to detect a runaway interrupt situation.
1780 *
1781 * If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
1782 * we panic and shut down the hardware
1783 */
1784 /* jiffies value the last time we were called */
1785 static int last_irq_jiffy; /* = 0 */
1786 static int loops_this_jiffy; /* = 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 unsigned long flags;
1788
1789 if (orinoco_lock(priv, &flags) != 0) {
1790 /* If hw is unavailable - we don't know if the irq was
1791 * for us or not */
1792 return IRQ_HANDLED;
1793 }
1794
1795 evstat = hermes_read_regn(hw, EVSTAT);
1796 events = evstat & hw->inten;
David Kilroya94e8422009-02-04 23:05:44 +00001797 if (!events) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 orinoco_unlock(priv, &flags);
1799 return IRQ_NONE;
1800 }
David Kilroy6fe9deb2009-02-04 23:05:43 +00001801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 if (jiffies != last_irq_jiffy)
1803 loops_this_jiffy = 0;
1804 last_irq_jiffy = jiffies;
1805
1806 while (events && count--) {
1807 if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
1808 printk(KERN_WARNING "%s: IRQ handler is looping too "
1809 "much! Resetting.\n", dev->name);
1810 /* Disable interrupts for now */
1811 hermes_set_irqmask(hw, 0);
1812 schedule_work(&priv->reset_work);
1813 break;
1814 }
1815
1816 /* Check the card hasn't been removed */
David Kilroya94e8422009-02-04 23:05:44 +00001817 if (!hermes_present(hw)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 DEBUG(0, "orinoco_interrupt(): card removed\n");
1819 break;
1820 }
1821
1822 if (events & HERMES_EV_TICK)
1823 __orinoco_ev_tick(dev, hw);
1824 if (events & HERMES_EV_WTERR)
1825 __orinoco_ev_wterr(dev, hw);
1826 if (events & HERMES_EV_INFDROP)
1827 __orinoco_ev_infdrop(dev, hw);
1828 if (events & HERMES_EV_INFO)
1829 __orinoco_ev_info(dev, hw);
1830 if (events & HERMES_EV_RX)
1831 __orinoco_ev_rx(dev, hw);
1832 if (events & HERMES_EV_TXEXC)
1833 __orinoco_ev_txexc(dev, hw);
1834 if (events & HERMES_EV_TX)
1835 __orinoco_ev_tx(dev, hw);
1836 if (events & HERMES_EV_ALLOC)
1837 __orinoco_ev_alloc(dev, hw);
David Kilroy6fe9deb2009-02-04 23:05:43 +00001838
Christoph Hellwig84d8a2f2005-05-14 17:30:22 +02001839 hermes_write_regn(hw, EVACK, evstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
1841 evstat = hermes_read_regn(hw, EVSTAT);
1842 events = evstat & hw->inten;
1843 };
1844
1845 orinoco_unlock(priv, &flags);
1846 return IRQ_HANDLED;
1847}
David Kilroy21312662009-02-04 23:05:47 +00001848EXPORT_SYMBOL(orinoco_interrupt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
1850/********************************************************************/
David Kilroy39d1ffe2008-11-22 10:37:28 +00001851/* Power management */
1852/********************************************************************/
1853#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
1854static int orinoco_pm_notifier(struct notifier_block *notifier,
1855 unsigned long pm_event,
1856 void *unused)
1857{
1858 struct orinoco_private *priv = container_of(notifier,
1859 struct orinoco_private,
1860 pm_notifier);
1861
1862 /* All we need to do is cache the firmware before suspend, and
1863 * release it when we come out.
1864 *
1865 * Only need to do this if we're downloading firmware. */
1866 if (!priv->do_fw_download)
1867 return NOTIFY_DONE;
1868
1869 switch (pm_event) {
1870 case PM_HIBERNATION_PREPARE:
1871 case PM_SUSPEND_PREPARE:
1872 orinoco_cache_fw(priv, 0);
1873 break;
1874
1875 case PM_POST_RESTORE:
1876 /* Restore from hibernation failed. We need to clean
1877 * up in exactly the same way, so fall through. */
1878 case PM_POST_HIBERNATION:
1879 case PM_POST_SUSPEND:
1880 orinoco_uncache_fw(priv);
1881 break;
1882
1883 case PM_RESTORE_PREPARE:
1884 default:
1885 break;
1886 }
1887
1888 return NOTIFY_DONE;
1889}
David S. Millerf11c1792009-02-25 00:02:05 -08001890
1891static void orinoco_register_pm_notifier(struct orinoco_private *priv)
1892{
1893 priv->pm_notifier.notifier_call = orinoco_pm_notifier;
1894 register_pm_notifier(&priv->pm_notifier);
1895}
1896
1897static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
1898{
1899 unregister_pm_notifier(&priv->pm_notifier);
1900}
David Kilroy39d1ffe2008-11-22 10:37:28 +00001901#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
David S. Millerf11c1792009-02-25 00:02:05 -08001902#define orinoco_register_pm_notifier(priv) do { } while(0)
1903#define orinoco_unregister_pm_notifier(priv) do { } while(0)
David Kilroy39d1ffe2008-11-22 10:37:28 +00001904#endif
1905
1906/********************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907/* Initialization */
1908/********************************************************************/
1909
David Kilroy8e638262009-06-18 23:21:24 +01001910int orinoco_init(struct orinoco_private *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
David Kilroy8e638262009-06-18 23:21:24 +01001912 struct device *dev = priv->dev;
David Kilroyea60a6a2009-06-18 23:21:26 +01001913 struct wiphy *wiphy = priv_to_wiphy(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 hermes_t *hw = &priv->hw;
1915 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 /* No need to lock, the hw_unavailable flag is already set in
1918 * alloc_orinocodev() */
Johannes Berg2c7060022008-10-30 22:09:54 +01001919 priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920
1921 /* Initialize the firmware */
Pavel Roskin37a6c612006-04-07 04:10:49 -04001922 err = hermes_init(hw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 if (err != 0) {
David Kilroy8e638262009-06-18 23:21:24 +01001924 dev_err(dev, "Failed to initialize firmware (err = %d)\n",
1925 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 goto out;
1927 }
1928
David Kilroya2d1a422009-06-18 23:21:18 +01001929 err = determine_fw_capabilities(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (err != 0) {
David Kilroy8e638262009-06-18 23:21:24 +01001931 dev_err(dev, "Incompatible firmware, aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 goto out;
1933 }
1934
David Kilroy3994d502008-08-21 23:27:54 +01001935 if (priv->do_fw_download) {
David Kilroy39d1ffe2008-11-22 10:37:28 +00001936#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
David Kilroy74734312008-11-22 10:37:25 +00001937 orinoco_cache_fw(priv, 0);
David Kilroy39d1ffe2008-11-22 10:37:28 +00001938#endif
David Kilroy74734312008-11-22 10:37:25 +00001939
David Kilroy3994d502008-08-21 23:27:54 +01001940 err = orinoco_download(priv);
1941 if (err)
1942 priv->do_fw_download = 0;
1943
1944 /* Check firmware version again */
David Kilroya2d1a422009-06-18 23:21:18 +01001945 err = determine_fw_capabilities(priv);
David Kilroy3994d502008-08-21 23:27:54 +01001946 if (err != 0) {
David Kilroy8e638262009-06-18 23:21:24 +01001947 dev_err(dev, "Incompatible firmware, aborting\n");
David Kilroy3994d502008-08-21 23:27:54 +01001948 goto out;
1949 }
1950 }
1951
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 if (priv->has_port3)
David Kilroy8e638262009-06-18 23:21:24 +01001953 dev_info(dev, "Ad-hoc demo mode supported\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 if (priv->has_ibss)
David Kilroy8e638262009-06-18 23:21:24 +01001955 dev_info(dev, "IEEE standard IBSS ad-hoc mode supported\n");
1956 if (priv->has_wep)
1957 dev_info(dev, "WEP supported, %s-bit key\n",
1958 priv->has_big_wep ? "104" : "40");
David Kilroy23edcc42008-08-21 23:28:05 +01001959 if (priv->has_wpa) {
David Kilroy8e638262009-06-18 23:21:24 +01001960 dev_info(dev, "WPA-PSK supported\n");
David Kilroy23edcc42008-08-21 23:28:05 +01001961 if (orinoco_mic_init(priv)) {
David Kilroy8e638262009-06-18 23:21:24 +01001962 dev_err(dev, "Failed to setup MIC crypto algorithm. "
1963 "Disabling WPA support\n");
David Kilroy23edcc42008-08-21 23:28:05 +01001964 priv->has_wpa = 0;
1965 }
1966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
David Kilroy01632fa2008-08-21 23:27:58 +01001968 /* Now we have the firmware capabilities, allocate appropiate
1969 * sized scan buffers */
1970 if (orinoco_bss_data_allocate(priv))
1971 goto out;
1972 orinoco_bss_data_init(priv);
1973
David Kilroyea60a6a2009-06-18 23:21:26 +01001974 err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr);
David Kilroye9e3d012009-06-18 23:21:19 +01001975 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977
David Kilroy42a51b92009-06-18 23:21:20 +01001978 err = orinoco_hw_allocate_fid(priv);
Pavel Roskin37a6c612006-04-07 04:10:49 -04001979 if (err) {
David Kilroy8e638262009-06-18 23:21:24 +01001980 dev_err(dev, "Failed to allocate NIC buffer!\n");
Pavel Roskin37a6c612006-04-07 04:10:49 -04001981 goto out;
1982 }
1983
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 /* Set up the default configuration */
David Kilroy5217c572009-06-18 23:21:32 +01001985 priv->iw_mode = NL80211_IFTYPE_STATION;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 /* By default use IEEE/IBSS ad-hoc mode if we have it */
David Kilroya94e8422009-02-04 23:05:44 +00001987 priv->prefer_port3 = priv->has_port3 && (!priv->has_ibss);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 set_port_type(priv);
David Gibsond51d8b12005-05-12 20:03:36 -04001989 priv->channel = 0; /* use firmware default */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
1991 priv->promiscuous = 0;
David Kilroy4ae6ee22008-08-21 23:27:59 +01001992 priv->encode_alg = IW_ENCODE_ALG_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 priv->tx_key = 0;
David Kilroyd03032a2008-08-21 23:28:02 +01001994 priv->wpa_enabled = 0;
1995 priv->tkip_cm_active = 0;
1996 priv->key_mgmt = 0;
1997 priv->wpa_ie_len = 0;
1998 priv->wpa_ie = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
David Kilroyea60a6a2009-06-18 23:21:26 +01002000 if (orinoco_wiphy_register(wiphy)) {
2001 err = -ENODEV;
2002 goto out;
2003 }
2004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 /* Make the hardware available, as long as it hasn't been
2006 * removed elsewhere (e.g. by PCMCIA hot unplug) */
2007 spin_lock_irq(&priv->lock);
2008 priv->hw_unavailable--;
2009 spin_unlock_irq(&priv->lock);
2010
David Kilroy8e638262009-06-18 23:21:24 +01002011 dev_dbg(dev, "Ready\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
2013 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 return err;
2015}
David Kilroy8e638262009-06-18 23:21:24 +01002016EXPORT_SYMBOL(orinoco_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Andrey Borzenkov89ea4092009-01-21 20:46:46 +03002018static const struct net_device_ops orinoco_netdev_ops = {
Andrey Borzenkov89ea4092009-01-21 20:46:46 +03002019 .ndo_open = orinoco_open,
2020 .ndo_stop = orinoco_stop,
2021 .ndo_start_xmit = orinoco_xmit,
2022 .ndo_set_multicast_list = orinoco_set_multicast_list,
2023 .ndo_change_mtu = orinoco_change_mtu,
2024 .ndo_tx_timeout = orinoco_tx_timeout,
2025 .ndo_get_stats = orinoco_get_stats,
2026};
2027
David Kilroyea60a6a2009-06-18 23:21:26 +01002028/* Allocate private data.
2029 *
2030 * This driver has a number of structures associated with it
2031 * netdev - Net device structure for each network interface
2032 * wiphy - structure associated with wireless phy
2033 * wireless_dev (wdev) - structure for each wireless interface
2034 * hw - structure for hermes chip info
2035 * card - card specific structure for use by the card driver
2036 * (airport, orinoco_cs)
2037 * priv - orinoco private data
2038 * device - generic linux device structure
2039 *
2040 * +---------+ +---------+
2041 * | wiphy | | netdev |
2042 * | +-------+ | +-------+
2043 * | | priv | | | wdev |
2044 * | | +-----+ +-+-------+
2045 * | | | hw |
2046 * | +-+-----+
2047 * | | card |
2048 * +-+-------+
2049 *
2050 * priv has a link to netdev and device
2051 * wdev has a link to wiphy
2052 */
David Kilroya2608362009-06-18 23:21:23 +01002053struct orinoco_private
David Kilroy3994d502008-08-21 23:27:54 +01002054*alloc_orinocodev(int sizeof_card,
2055 struct device *device,
2056 int (*hard_reset)(struct orinoco_private *),
2057 int (*stop_fw)(struct orinoco_private *, int))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 struct orinoco_private *priv;
David Kilroyea60a6a2009-06-18 23:21:26 +01002060 struct wiphy *wiphy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
David Kilroyea60a6a2009-06-18 23:21:26 +01002062 /* allocate wiphy
2063 * NOTE: We only support a single virtual interface
2064 * but this may change when monitor mode is added
2065 */
2066 wiphy = wiphy_new(&orinoco_cfg_ops,
2067 sizeof(struct orinoco_private) + sizeof_card);
2068 if (!wiphy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 return NULL;
David Kilroyea60a6a2009-06-18 23:21:26 +01002070
David Kilroyea60a6a2009-06-18 23:21:26 +01002071 priv = wiphy_priv(wiphy);
David Kilroy53819562009-06-18 23:21:28 +01002072 priv->dev = device;
David Kilroyea60a6a2009-06-18 23:21:26 +01002073
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 if (sizeof_card)
Christoph Hellwig84d8a2f2005-05-14 17:30:22 +02002075 priv->card = (void *)((unsigned long)priv
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 + sizeof(struct orinoco_private));
2077 else
2078 priv->card = NULL;
2079
David Kilroyea60a6a2009-06-18 23:21:26 +01002080 orinoco_wiphy_init(wiphy);
2081
Pavel Roskin343c6862005-09-09 18:43:02 -04002082#ifdef WIRELESS_SPY
2083 priv->wireless_data.spy_data = &priv->spy_data;
Pavel Roskin343c6862005-09-09 18:43:02 -04002084#endif
David Kilroy23edcc42008-08-21 23:28:05 +01002085
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 /* Set up default callbacks */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 priv->hard_reset = hard_reset;
David Kilroy3994d502008-08-21 23:27:54 +01002088 priv->stop_fw = stop_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
2090 spin_lock_init(&priv->lock);
2091 priv->open = 0;
2092 priv->hw_unavailable = 1; /* orinoco_init() must clear this
2093 * before anything else touches the
2094 * hardware */
David Howellsc4028952006-11-22 14:57:56 +00002095 INIT_WORK(&priv->reset_work, orinoco_reset);
2096 INIT_WORK(&priv->join_work, orinoco_join_ap);
2097 INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
David Kilroy31afcef2008-08-21 23:28:04 +01002099 INIT_LIST_HEAD(&priv->rx_list);
2100 tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet,
David Kilroy53819562009-06-18 23:21:28 +01002101 (unsigned long) priv);
David Kilroy31afcef2008-08-21 23:28:04 +01002102
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 priv->last_linkstatus = 0xffff;
2104
Andrey Borzenkov2bfc5cb2009-02-28 23:09:09 +03002105#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
David Kilroy2cea7b22008-11-22 10:37:26 +00002106 priv->cached_pri_fw = NULL;
Andrey Borzenkov4fb30782008-10-19 12:06:11 +04002107 priv->cached_fw = NULL;
Andrey Borzenkov2bfc5cb2009-02-28 23:09:09 +03002108#endif
Andrey Borzenkov4fb30782008-10-19 12:06:11 +04002109
David Kilroy39d1ffe2008-11-22 10:37:28 +00002110 /* Register PM notifiers */
David S. Millerf11c1792009-02-25 00:02:05 -08002111 orinoco_register_pm_notifier(priv);
David Kilroy39d1ffe2008-11-22 10:37:28 +00002112
David Kilroya2608362009-06-18 23:21:23 +01002113 return priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114}
David Kilroy21312662009-02-04 23:05:47 +00002115EXPORT_SYMBOL(alloc_orinocodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
David Kilroy53819562009-06-18 23:21:28 +01002117/* We can only support a single interface. We provide a separate
2118 * function to set it up to distinguish between hardware
2119 * initialisation and interface setup.
2120 *
2121 * The base_addr and irq parameters are passed on to netdev for use
2122 * with SIOCGIFMAP.
2123 */
2124int orinoco_if_add(struct orinoco_private *priv,
2125 unsigned long base_addr,
2126 unsigned int irq)
2127{
2128 struct wiphy *wiphy = priv_to_wiphy(priv);
2129 struct wireless_dev *wdev;
2130 struct net_device *dev;
2131 int ret;
2132
2133 dev = alloc_etherdev(sizeof(struct wireless_dev));
2134
2135 if (!dev)
2136 return -ENOMEM;
2137
2138 /* Initialise wireless_dev */
2139 wdev = netdev_priv(dev);
2140 wdev->wiphy = wiphy;
2141 wdev->iftype = NL80211_IFTYPE_STATION;
2142
2143 /* Setup / override net_device fields */
2144 dev->ieee80211_ptr = wdev;
2145 dev->netdev_ops = &orinoco_netdev_ops;
2146 dev->watchdog_timeo = HZ; /* 1 second timeout */
2147 dev->ethtool_ops = &orinoco_ethtool_ops;
2148 dev->wireless_handlers = &orinoco_handler_def;
2149#ifdef WIRELESS_SPY
2150 dev->wireless_data = &priv->wireless_data;
2151#endif
2152 /* we use the default eth_mac_addr for setting the MAC addr */
2153
2154 /* Reserve space in skb for the SNAP header */
2155 dev->hard_header_len += ENCAPS_OVERHEAD;
2156
2157 netif_carrier_off(dev);
2158
2159 memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
2160
2161 dev->base_addr = base_addr;
2162 dev->irq = irq;
2163
2164 SET_NETDEV_DEV(dev, priv->dev);
2165 ret = register_netdev(dev);
2166 if (ret)
2167 goto fail;
2168
2169 priv->ndev = dev;
2170
2171 /* Report what we've done */
2172 dev_dbg(priv->dev, "Registerred interface %s.\n", dev->name);
2173
2174 return 0;
2175
2176 fail:
2177 free_netdev(dev);
2178 return ret;
2179}
2180EXPORT_SYMBOL(orinoco_if_add);
2181
2182void orinoco_if_del(struct orinoco_private *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183{
David Kilroya2608362009-06-18 23:21:23 +01002184 struct net_device *dev = priv->ndev;
David Kilroy53819562009-06-18 23:21:28 +01002185
2186 unregister_netdev(dev);
2187 free_netdev(dev);
2188}
2189EXPORT_SYMBOL(orinoco_if_del);
2190
2191void free_orinocodev(struct orinoco_private *priv)
2192{
David Kilroyea60a6a2009-06-18 23:21:26 +01002193 struct wiphy *wiphy = priv_to_wiphy(priv);
David Kilroy20953ad2009-01-07 00:23:55 +00002194 struct orinoco_rx_data *rx_data, *temp;
Christoph Hellwig95dd91f2005-06-19 01:27:56 +02002195
David Kilroyea60a6a2009-06-18 23:21:26 +01002196 wiphy_unregister(wiphy);
2197
David Kilroy20953ad2009-01-07 00:23:55 +00002198 /* If the tasklet is scheduled when we call tasklet_kill it
2199 * will run one final time. However the tasklet will only
2200 * drain priv->rx_list if the hw is still available. */
David Kilroy31afcef2008-08-21 23:28:04 +01002201 tasklet_kill(&priv->rx_tasklet);
David Kilroy74734312008-11-22 10:37:25 +00002202
David Kilroy20953ad2009-01-07 00:23:55 +00002203 /* Explicitly drain priv->rx_list */
2204 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
2205 list_del(&rx_data->list);
2206
2207 dev_kfree_skb(rx_data->skb);
2208 kfree(rx_data->desc);
2209 kfree(rx_data);
2210 }
2211
David S. Millerf11c1792009-02-25 00:02:05 -08002212 orinoco_unregister_pm_notifier(priv);
David Kilroy74734312008-11-22 10:37:25 +00002213 orinoco_uncache_fw(priv);
2214
David Kilroyd03032a2008-08-21 23:28:02 +01002215 priv->wpa_ie_len = 0;
2216 kfree(priv->wpa_ie);
David Kilroy23edcc42008-08-21 23:28:05 +01002217 orinoco_mic_free(priv);
Dan Williams1e3428e2007-10-10 23:56:25 -04002218 orinoco_bss_data_free(priv);
David Kilroyea60a6a2009-06-18 23:21:26 +01002219 wiphy_free(wiphy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220}
David Kilroy21312662009-02-04 23:05:47 +00002221EXPORT_SYMBOL(free_orinocodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
David Kilroy6415f7d2009-06-18 23:21:30 +01002223int orinoco_up(struct orinoco_private *priv)
2224{
2225 struct net_device *dev = priv->ndev;
2226 unsigned long flags;
2227 int err;
2228
2229 spin_lock_irqsave(&priv->lock, flags);
2230
2231 err = orinoco_reinit_firmware(priv);
2232 if (err) {
2233 printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
2234 dev->name, err);
2235 goto exit;
2236 }
2237
2238 netif_device_attach(dev);
2239 priv->hw_unavailable--;
2240
2241 if (priv->open && !priv->hw_unavailable) {
2242 err = __orinoco_up(priv);
2243 if (err)
2244 printk(KERN_ERR "%s: Error %d restarting card\n",
2245 dev->name, err);
2246 }
2247
2248exit:
2249 spin_unlock_irqrestore(&priv->lock, flags);
2250
2251 return 0;
2252}
2253EXPORT_SYMBOL(orinoco_up);
2254
2255void orinoco_down(struct orinoco_private *priv)
2256{
2257 struct net_device *dev = priv->ndev;
2258 unsigned long flags;
2259 int err;
2260
2261 spin_lock_irqsave(&priv->lock, flags);
2262 err = __orinoco_down(priv);
2263 if (err)
2264 printk(KERN_WARNING "%s: Error %d downing interface\n",
2265 dev->name, err);
2266
2267 netif_device_detach(dev);
2268 priv->hw_unavailable++;
2269 spin_unlock_irqrestore(&priv->lock, flags);
2270}
2271EXPORT_SYMBOL(orinoco_down);
2272
Christoph Hellwig1fab2e82005-06-19 01:27:40 +02002273static void orinoco_get_drvinfo(struct net_device *dev,
2274 struct ethtool_drvinfo *info)
2275{
David Kilroyea60a6a2009-06-18 23:21:26 +01002276 struct orinoco_private *priv = ndev_priv(dev);
Christoph Hellwig1fab2e82005-06-19 01:27:40 +02002277
2278 strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
2279 strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
2280 strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07002281 if (dev->dev.parent)
Kay Sieversfb28ad32008-11-10 13:55:14 -08002282 strncpy(info->bus_info, dev_name(dev->dev.parent),
Christoph Hellwig1fab2e82005-06-19 01:27:40 +02002283 sizeof(info->bus_info) - 1);
2284 else
2285 snprintf(info->bus_info, sizeof(info->bus_info) - 1,
2286 "PCMCIA %p", priv->hw.iobase);
2287}
2288
Jeff Garzik7282d492006-09-13 14:30:00 -04002289static const struct ethtool_ops orinoco_ethtool_ops = {
Christoph Hellwig1fab2e82005-06-19 01:27:40 +02002290 .get_drvinfo = orinoco_get_drvinfo,
2291 .get_link = ethtool_op_get_link,
2292};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
2294/********************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295/* Module initialization */
2296/********************************************************************/
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298/* Can't be declared "const" or the whole __initdata section will
2299 * become const */
2300static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
2301 " (David Gibson <hermes@gibson.dropbear.id.au>, "
2302 "Pavel Roskin <proski@gnu.org>, et al)";
2303
2304static int __init init_orinoco(void)
2305{
2306 printk(KERN_DEBUG "%s\n", version);
2307 return 0;
2308}
2309
2310static void __exit exit_orinoco(void)
2311{
2312}
2313
2314module_init(init_orinoco);
2315module_exit(exit_orinoco);