X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Forinoco.c;fp=drivers%2Fnet%2Fwireless%2Forinoco.c;h=6fd0bf736830f4c7a0694005d32b50613f05818b;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=317ace7f9aae3af7191323c45953f9416875ed3b;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 317ace7f9..6fd0bf736 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -76,6 +76,7 @@ #define DRIVER_NAME "orinoco" +#include #include #include #include @@ -200,12 +201,41 @@ static struct { /* Data types */ /********************************************************************/ -/* Beginning of the Tx descriptor, used in TxExc handling */ -struct hermes_txexc_data { - struct hermes_tx_descriptor desc; +/* Used in Event handling. + * We avoid nested structures as they break on ARM -- Moustafa */ +struct hermes_tx_descriptor_802_11 { + /* hermes_tx_descriptor */ + __le16 status; + __le16 reserved1; + __le16 reserved2; + __le32 sw_support; + u8 retry_count; + u8 tx_rate; + __le16 tx_control; + + /* ieee80211_hdr */ __le16 frame_ctl; __le16 duration_id; u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 addr4[ETH_ALEN]; + + __le16 data_len; + + /* ethhdr */ + u8 h_dest[ETH_ALEN]; /* destination eth addr */ + u8 h_source[ETH_ALEN]; /* source ether addr */ + __be16 h_proto; /* packet type ID field */ + + /* p8022_hdr */ + u8 dsap; + u8 ssap; + u8 ctrl; + u8 oui[3]; + + __be16 ethertype; } __attribute__ ((packed)); /* Rx frame header except compatibility 802.3 header */ @@ -360,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) } } else { struct { - __le16 qual, signal, noise, unused; + __le16 qual, signal, noise; } __attribute__ ((packed)) cq; err = HERMES_READ_RECORD(hw, USER_BAP, @@ -420,39 +450,53 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) hermes_t *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; + char *p; struct ethhdr *eh; - int data_off; + int len, data_len, data_off; struct hermes_tx_descriptor desc; unsigned long flags; + TRACE_ENTER(dev->name); + if (! netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name); - return NETDEV_TX_BUSY; + TRACE_EXIT(dev->name); + return 1; } if (netif_queue_stopped(dev)) { printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", dev->name); - return NETDEV_TX_BUSY; + TRACE_EXIT(dev->name); + return 1; } if (orinoco_lock(priv, &flags) != 0) { printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", dev->name); - return NETDEV_TX_BUSY; + TRACE_EXIT(dev->name); + return 1; } if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ - goto drop; + stats->tx_errors++; + orinoco_unlock(priv, &flags); + dev_kfree_skb(skb); + TRACE_EXIT(dev->name); + return 0; } - /* Check packet length */ - if (skb->len < ETH_HLEN) - goto drop; + /* Length of the packet body */ + /* FIXME: what if the skb is smaller than this? */ + len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); + skb = skb_padto(skb, len); + if (skb == NULL) + goto fail; + len -= ETH_HLEN; eh = (struct ethhdr *)skb->data; @@ -463,7 +507,8 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx descriptor " "to BAP\n", dev->name, err); - goto busy; + stats->tx_errors++; + goto fail; } /* Clear the 802.11 header and data length fields - some @@ -474,38 +519,50 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) /* Encapsulate Ethernet-II frames */ if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct { - struct ethhdr eth; /* 802.3 header */ - u8 encap[6]; /* 802.2 header */ - } __attribute__ ((packed)) hdr; - - /* Strip destination and source from the data */ - skb_pull(skb, 2 * ETH_ALEN); - data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr); - - /* And move them to a separate header */ - memcpy(&hdr.eth, eh, 2 * ETH_ALEN); - hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); - memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); - - err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), - txfid, HERMES_802_3_OFFSET); + struct header_struct hdr; + data_len = len; + data_off = HERMES_802_3_OFFSET + sizeof(hdr); + p = skb->data + ETH_HLEN; + + /* 802.3 header */ + memcpy(hdr.dest, eh->h_dest, ETH_ALEN); + memcpy(hdr.src, eh->h_source, ETH_ALEN); + hdr.len = htons(data_len + ENCAPS_OVERHEAD); + + /* 802.2 header */ + memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr)); + + hdr.ethertype = eh->h_proto; + err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), + txfid, HERMES_802_3_OFFSET); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing packet " "header to BAP\n", dev->name, err); - goto busy; + stats->tx_errors++; + goto fail; } + /* Actual xfer length - allow for padding */ + len = ALIGN(data_len, 2); + if (len < ETH_ZLEN - ETH_HLEN) + len = ETH_ZLEN - ETH_HLEN; } else { /* IEEE 802.3 frame */ + data_len = len + ETH_HLEN; data_off = HERMES_802_3_OFFSET; + p = skb->data; + /* Actual xfer length - round up for odd length packets */ + len = ALIGN(data_len, 2); + if (len < ETH_ZLEN) + len = ETH_ZLEN; } - err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, + err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len, txfid, data_off); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); - goto busy; + stats->tx_errors++; + goto fail; } /* Finally, we actually initiate the send */ @@ -518,27 +575,25 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) if (net_ratelimit()) printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - goto busy; + stats->tx_errors++; + goto fail; } dev->trans_start = jiffies; - stats->tx_bytes += data_off + skb->len; - goto ok; + stats->tx_bytes += data_off + data_len; - drop: - stats->tx_errors++; - stats->tx_dropped++; - - ok: orinoco_unlock(priv, &flags); + dev_kfree_skb(skb); - return NETDEV_TX_OK; - busy: - if (err == -EIO) - schedule_work(&priv->reset_work); + TRACE_EXIT(dev->name); + + return 0; + fail: + TRACE_EXIT(dev->name); + orinoco_unlock(priv, &flags); - return NETDEV_TX_BUSY; + return err; } static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) @@ -574,7 +629,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); u16 status; - struct hermes_txexc_data hdr; + struct hermes_tx_descriptor_802_11 hdr; int err = 0; if (fid == DUMMY_FID) @@ -582,7 +637,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) /* Read part of the frame header - we need status and addr1 */ err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - sizeof(struct hermes_txexc_data), + offsetof(struct hermes_tx_descriptor_802_11, + addr2), fid, 0); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); @@ -602,7 +658,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) * exceeded, because that's the only status that really mean * that this particular node went away. * Other errors means that *we* screwed up. - Jean II */ - status = le16_to_cpu(hdr.desc.status); + status = le16_to_cpu(hdr.status); if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { union iwreq_data wrqu; @@ -756,6 +812,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, if (datalen > IEEE80211_DATA_LEN + 12) { printk(KERN_DEBUG "%s: oversized monitor frame, " "data length = %d\n", dev->name, datalen); + err = -EIO; stats->rx_length_errors++; goto update_stats; } @@ -764,7 +821,8 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, if (!skb) { printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", dev->name); - goto update_stats; + err = -ENOMEM; + goto drop; } /* Copy the 802.11 header to the skb */ @@ -1342,12 +1400,16 @@ int __orinoco_down(struct net_device *dev) return 0; } -static int orinoco_allocate_fid(struct net_device *dev) +int orinoco_reinit_firmware(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; int err; + err = hermes_init(hw); + if (err) + return err; + err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { /* Try workaround for old Symbol firmware bug */ @@ -1366,19 +1428,6 @@ static int orinoco_allocate_fid(struct net_device *dev) return err; } -int orinoco_reinit_firmware(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - - err = hermes_init(hw); - if (!err) - err = orinoco_allocate_fid(dev); - - return err; -} - static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; @@ -1786,9 +1835,7 @@ static int __orinoco_program_rids(struct net_device *dev) /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->mc_count = 0; - - /* FIXME: what about netif_tx_lock */ - __orinoco_set_multicast_list(dev); + __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ return 0; } @@ -2227,12 +2274,14 @@ static int orinoco_init(struct net_device *dev) u16 reclen; int len; + TRACE_ENTER(dev->name); + /* No need to lock, the hw_unavailable flag is already set in * alloc_orinocodev() */ priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN; /* Initialize the firmware */ - err = hermes_init(hw); + err = orinoco_reinit_firmware(dev); if (err != 0) { printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n", dev->name, err); @@ -2290,13 +2339,6 @@ static int orinoco_init(struct net_device *dev) printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); - err = orinoco_allocate_fid(dev); - if (err) { - printk(KERN_ERR "%s: failed to allocate NIC buffer!\n", - dev->name); - goto out; - } - /* Get allowed channels */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, &priv->channel_mask); @@ -2387,6 +2429,7 @@ static int orinoco_init(struct net_device *dev) printk(KERN_DEBUG "%s: ready\n", dev->name); out: + TRACE_EXIT(dev->name); return err; } @@ -2754,6 +2797,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, int numrates; int i, k; + TRACE_ENTER(dev->name); + rrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); @@ -2843,6 +2888,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); + TRACE_EXIT(dev->name); + return 0; } @@ -2875,7 +2922,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - if (erq->length > 0) { + if (erq->pointer) { if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) index = priv->tx_key; @@ -2918,7 +2965,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (erq->flags & IW_ENCODE_RESTRICTED) restricted = 1; - if (erq->pointer && erq->length > 0) { + if (erq->pointer) { priv->keys[index].len = cpu_to_le16(xlen); memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); @@ -3024,6 +3071,8 @@ static int orinoco_ioctl_getessid(struct net_device *dev, int err = 0; unsigned long flags; + TRACE_ENTER(dev->name); + if (netif_running(dev)) { err = orinoco_hw_get_essid(priv, &active, essidbuf); if (err) @@ -3038,6 +3087,8 @@ static int orinoco_ioctl_getessid(struct net_device *dev, erq->flags = 1; erq->length = strlen(essidbuf) + 1; + TRACE_EXIT(dev->name); + return 0; } @@ -3807,7 +3858,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev, unsigned long flags; /* Note : you may have realised that, as this is a SET operation, - * this is privileged and therefore a normal user can't + * this is priviledged and therefore a normal user can't * perform scanning. * This is not an error, while the device perform scanning, * traffic doesn't flow, so it's a perfect DoS... @@ -4297,6 +4348,69 @@ static struct ethtool_ops orinoco_ethtool_ops = { .get_link = ethtool_op_get_link, }; +/********************************************************************/ +/* Debugging */ +/********************************************************************/ + +#if 0 +static void show_rx_frame(struct orinoco_rxframe_hdr *frame) +{ + printk(KERN_DEBUG "RX descriptor:\n"); + printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); + printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); + printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); + printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); + printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); + printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); + printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); + + printk(KERN_DEBUG "IEEE 802.11 header:\n"); + printk(KERN_DEBUG " frame_ctl = 0x%04x\n", + frame->p80211.frame_ctl); + printk(KERN_DEBUG " duration_id = 0x%04x\n", + frame->p80211.duration_id); + printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr1[0], frame->p80211.addr1[1], + frame->p80211.addr1[2], frame->p80211.addr1[3], + frame->p80211.addr1[4], frame->p80211.addr1[5]); + printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr2[0], frame->p80211.addr2[1], + frame->p80211.addr2[2], frame->p80211.addr2[3], + frame->p80211.addr2[4], frame->p80211.addr2[5]); + printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr3[0], frame->p80211.addr3[1], + frame->p80211.addr3[2], frame->p80211.addr3[3], + frame->p80211.addr3[4], frame->p80211.addr3[5]); + printk(KERN_DEBUG " seq_ctl = 0x%04x\n", + frame->p80211.seq_ctl); + printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr4[0], frame->p80211.addr4[1], + frame->p80211.addr4[2], frame->p80211.addr4[3], + frame->p80211.addr4[4], frame->p80211.addr4[5]); + printk(KERN_DEBUG " data_len = 0x%04x\n", + frame->p80211.data_len); + + printk(KERN_DEBUG "IEEE 802.3 header:\n"); + printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p8023.h_dest[0], frame->p8023.h_dest[1], + frame->p8023.h_dest[2], frame->p8023.h_dest[3], + frame->p8023.h_dest[4], frame->p8023.h_dest[5]); + printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p8023.h_source[0], frame->p8023.h_source[1], + frame->p8023.h_source[2], frame->p8023.h_source[3], + frame->p8023.h_source[4], frame->p8023.h_source[5]); + printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); + + printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); + printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); + printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); + printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); + printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", + frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); + printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); +} +#endif /* 0 */ + /********************************************************************/ /* Module initialization */ /********************************************************************/