diff options
Diffstat (limited to 'drivers/net/wireless/hostap/hostap_hw.c')
| -rw-r--r-- | drivers/net/wireless/hostap/hostap_hw.c | 126 |
1 files changed, 69 insertions, 57 deletions
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 0f27059bbe8..6df3ee561d5 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -38,6 +38,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/if_arp.h> #include <linux/delay.h> #include <linux/random.h> @@ -46,7 +47,6 @@ #include <linux/rtnetlink.h> #include <linux/wireless.h> #include <net/iw_handler.h> -#include <net/ieee80211.h> #include <net/lib80211.h> #include <asm/irq.h> @@ -130,8 +130,7 @@ static void prism2_check_sta_fw_version(local_info_t *local); #ifdef PRISM2_DOWNLOAD_SUPPORT /* hostap_download.c */ -static int prism2_download_aux_dump(struct net_device *dev, - unsigned int addr, int len, u8 *buf); +static const struct file_operations prism2_download_aux_dump_proc_fops; static u8 * prism2_read_pda(struct net_device *dev); static int prism2_download(local_info_t *local, struct prism2_download_param *param); @@ -348,11 +347,9 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0, return -EINTR; entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) { - printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n", - dev->name); + if (entry == NULL) return -ENOMEM; - } + atomic_set(&entry->usecnt, 1); entry->type = CMD_SLEEP; entry->cmd = cmd; @@ -516,11 +513,9 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0, } entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) { - printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc " - "failed\n", dev->name); + if (entry == NULL) return -ENOMEM; - } + atomic_set(&entry->usecnt, 1); entry->type = CMD_CALLBACK; entry->cmd = cmd; @@ -1424,13 +1419,13 @@ static int prism2_hw_init2(struct net_device *dev, int initial) prism2_check_sta_fw_version(local); if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR, - &dev->dev_addr, 6, 1) < 0) { + dev->dev_addr, 6, 1) < 0) { printk("%s: could not get own MAC address\n", dev->name); } list_for_each(ptr, &local->hostap_interfaces) { iface = list_entry(ptr, struct hostap_interface, list); - memcpy(iface->dev->dev_addr, dev->dev_addr, ETH_ALEN); + eth_hw_addr_inherit(iface->dev, dev); } } else if (local->fw_ap) prism2_check_sta_fw_version(local); @@ -1471,7 +1466,7 @@ static int prism2_hw_enable(struct net_device *dev, int initial) * before it starts acting as an AP, so reset port automatically * here just in case */ if (initial && prism2_reset_port(dev)) { - printk("%s: MAC port 0 reseting failed\n", dev->name); + printk("%s: MAC port 0 resetting failed\n", dev->name); return 1; } @@ -1562,7 +1557,7 @@ static void prism2_hw_reset(struct net_device *dev) static long last_reset = 0; /* do not reset card more than once per second to avoid ending up in a - * busy loop reseting the card */ + * busy loop resetting the card */ if (time_before_eq(jiffies, last_reset + HZ)) return; last_reset = jiffies; @@ -1683,7 +1678,7 @@ static int prism2_get_txfid_idx(local_info_t *local) PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: " "packet dropped\n"); - local->stats.tx_dropped++; + local->dev->stats.tx_dropped++; return -1; } @@ -1788,11 +1783,9 @@ static int prism2_transmit(struct net_device *dev, int idx) prism2_transmit_cb, (long) idx); if (res) { - struct net_device_stats *stats; printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT " "failed (res=%d)\n", dev->name, res); - stats = hostap_get_stats(dev); - stats->tx_dropped++; + dev->stats.tx_dropped++; netif_wake_queue(dev); return -1; } @@ -1840,8 +1833,8 @@ static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev) hdr_len = 24; skb_copy_from_linear_data(skb, &txdesc.frame_control, hdr_len); fc = le16_to_cpu(txdesc.frame_control); - if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA && - (fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS) && + if (ieee80211_is_data(txdesc.frame_control) && + ieee80211_has_a4(txdesc.frame_control) && skb->len >= 30) { /* Addr4 */ skb_copy_from_linear_data_offset(skb, hdr_len, txdesc.addr4, @@ -1899,7 +1892,7 @@ fail: /* Some SMP systems have reported number of odd errors with hostap_pci. fid * register has changed values between consecutive reads for an unknown reason. * This should really not happen, so more debugging is needed. This test - * version is a big slower, but it will detect most of such register changes + * version is a bit slower, but it will detect most of such register changes * and will try to get the correct fid eventually. */ #define EXTRA_FID_READ_TESTS @@ -1940,12 +1933,10 @@ static void prism2_rx(local_info_t *local) struct net_device *dev = local->dev; int res, rx_pending = 0; u16 len, hdr_len, rxfid, status, macport; - struct net_device_stats *stats; struct hfa384x_rx_frame rxdesc; struct sk_buff *skb = NULL; prism2_callback(local, PRISM2_CALLBACK_RX_START); - stats = hostap_get_stats(dev); rxfid = prism2_read_fid_reg(dev, HFA384X_RXFID_OFF); #ifndef final_version @@ -2032,7 +2023,7 @@ static void prism2_rx(local_info_t *local) return; rx_dropped: - stats->rx_dropped++; + dev->stats.rx_dropped++; if (skb) dev_kfree_skb(skb); goto rx_exit; @@ -2082,7 +2073,7 @@ static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb) stats.rate = rxdesc->rate; /* Convert Prism2 RX structure into IEEE 802.11 header */ - hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(rxdesc->frame_control)); + hdrlen = hostap_80211_get_hdrlen(rxdesc->frame_control); if (hdrlen > rx_hdrlen) hdrlen = rx_hdrlen; @@ -2184,7 +2175,7 @@ static void hostap_tx_callback(local_info_t *local, struct hostap_tx_callback_info *cb; /* Make sure that frame was from us. */ - if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) { + if (!ether_addr_equal(txdesc->addr2, local->dev->dev_addr)) { printk(KERN_DEBUG "%s: TX callback - foreign frame\n", local->dev->name); return; @@ -2204,7 +2195,7 @@ static void hostap_tx_callback(local_info_t *local, return; } - hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(txdesc->frame_control)); + hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control); len = le16_to_cpu(txdesc->data_len); skb = dev_alloc_skb(hdrlen + len); if (skb == NULL) { @@ -2315,8 +2306,7 @@ static void hostap_sta_tx_exc_tasklet(unsigned long data) if (skb->len >= sizeof(*txdesc)) { /* Convert Prism2 RX structure into IEEE 802.11 header */ - u16 fc = le16_to_cpu(txdesc->frame_control); - int hdrlen = hostap_80211_get_hdrlen(fc); + int hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control); memmove(skb_pull(skb, sizeof(*txdesc) - hdrlen), &txdesc->frame_control, hdrlen); @@ -2337,7 +2327,7 @@ static void prism2_txexc(local_info_t *local) struct hfa384x_tx_frame txdesc; show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR; - local->stats.tx_errors++; + dev->stats.tx_errors++; res = hostap_tx_compl_read(local, 1, &txdesc, &payload); HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF); @@ -2394,12 +2384,12 @@ static void prism2_txexc(local_info_t *local) PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x " "(%s%s%s::%d%s%s)\n", txdesc.retry_count, txdesc.tx_rate, fc, - WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT ? "Mgmt" : "", - WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL ? "Ctrl" : "", - WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA ? "Data" : "", - WLAN_FC_GET_STYPE(fc) >> 4, - fc & IEEE80211_FCTL_TODS ? " ToDS" : "", - fc & IEEE80211_FCTL_FROMDS ? " FromDS" : ""); + ieee80211_is_mgmt(txdesc.frame_control) ? "Mgmt" : "", + ieee80211_is_ctl(txdesc.frame_control) ? "Ctrl" : "", + ieee80211_is_data(txdesc.frame_control) ? "Data" : "", + (fc & IEEE80211_FCTL_STYPE) >> 4, + ieee80211_has_tods(txdesc.frame_control) ? " ToDS" : "", + ieee80211_has_fromds(txdesc.frame_control) ? " FromDS" : ""); PDEBUG(DEBUG_EXTRA, " A1=%pM A2=%pM A3=%pM A4=%pM\n", txdesc.addr1, txdesc.addr2, txdesc.addr3, txdesc.addr4); @@ -2627,6 +2617,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) iface = netdev_priv(dev); local = iface->local; + /* Detect early interrupt before driver is fully configured */ + spin_lock(&local->irq_init_lock); + if (!dev->base_addr) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", + dev->name); + } + spin_unlock(&local->irq_init_lock); + return IRQ_HANDLED; + } + spin_unlock(&local->irq_init_lock); + prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); if (local->func->card_present && !local->func->card_present(local)) { @@ -2892,19 +2894,12 @@ static void hostap_tick_timer(unsigned long data) #ifndef PRISM2_NO_PROCFS_DEBUG -static int prism2_registers_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int prism2_registers_proc_show(struct seq_file *m, void *v) { - char *p = page; - local_info_t *local = (local_info_t *) data; - - if (off != 0) { - *eof = 1; - return 0; - } + local_info_t *local = m->private; #define SHOW_REG(n) \ -p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF)) + seq_printf(m, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF)) SHOW_REG(CMD); SHOW_REG(PARAM0); @@ -2950,8 +2945,21 @@ p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF)) SHOW_REG(PCI_M1_CTL); #endif /* PRISM2_PCI */ - return (p - page); + return 0; } + +static int prism2_registers_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, prism2_registers_proc_show, PDE_DATA(inode)); +} + +static const struct file_operations prism2_registers_proc_fops = { + .open = prism2_registers_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + #endif /* PRISM2_NO_PROCFS_DEBUG */ @@ -2972,11 +2980,9 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set) local = iface->local; new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC); - if (new_entry == NULL) { - printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n", - local->dev->name); + if (new_entry == NULL) return -ENOMEM; - } + new_entry->aid = aid; new_entry->set = set; @@ -3128,7 +3134,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, local->func->reset_port = prism2_reset_port; local->func->schedule_reset = prism2_schedule_reset; #ifdef PRISM2_DOWNLOAD_SUPPORT - local->func->read_aux = prism2_download_aux_dump; + local->func->read_aux_fops = &prism2_download_aux_dump_proc_fops; local->func->download = prism2_download; #endif /* PRISM2_DOWNLOAD_SUPPORT */ local->func->tx = prism2_tx_80211; @@ -3144,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, spin_lock_init(&local->cmdlock); spin_lock_init(&local->baplock); spin_lock_init(&local->lock); + spin_lock_init(&local->irq_init_lock); mutex_init(&local->rid_bap_mtx); if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) @@ -3228,7 +3235,6 @@ while (0) hostap_setup_dev(dev, local, HOSTAP_INTERFACE_MASTER); - dev->hard_start_xmit = hostap_master_start_xmit; dev->type = ARPHRD_IEEE80211; dev->header_ops = &hostap_80211_ops; @@ -3274,8 +3280,8 @@ static int hostap_hw_ready(struct net_device *dev) } hostap_init_proc(local); #ifndef PRISM2_NO_PROCFS_DEBUG - create_proc_read_entry("registers", 0, local->proc, - prism2_registers_proc_read, local); + proc_create_data("registers", 0, local->proc, + &prism2_registers_proc_fops, local); #endif /* PRISM2_NO_PROCFS_DEBUG */ hostap_init_ap_proc(local); return 0; @@ -3311,7 +3317,13 @@ static void prism2_free_local_data(struct net_device *dev) unregister_netdev(local->dev); - flush_scheduled_work(); + flush_work(&local->reset_queue); + flush_work(&local->set_multicast_list_queue); + flush_work(&local->set_tim_queue); +#ifndef PRISM2_NO_STATION_MODES + flush_work(&local->info_queue); +#endif + flush_work(&local->comms_qual_update); lib80211_crypt_info_free(&local->crypt_info); |
