}
/* 8-bit direct write (low 4K) */
-#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
+static inline void _ipw_write8(struct ipw_priv *ipw, unsigned long ofs,
+ u8 val)
+{
+ writeb(val, ipw->hw_base + ofs);
+}
/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write8(ipw, ofs, val) do { \
- IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
- _ipw_write8(ipw, ofs, val); \
- } while (0)
+ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, \
+ __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write8(ipw, ofs, val); \
+} while (0)
/* 16-bit direct write (low 4K) */
-#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
+static inline void _ipw_write16(struct ipw_priv *ipw, unsigned long ofs,
+ u16 val)
+{
+ writew(val, ipw->hw_base + ofs);
+}
/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
-#define ipw_write16(ipw, ofs, val) \
- IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
- _ipw_write16(ipw, ofs, val)
+#define ipw_write16(ipw, ofs, val) do { \
+ IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, \
+ __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write16(ipw, ofs, val); \
+} while (0)
/* 32-bit direct write (low 4K) */
-#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
+static inline void _ipw_write32(struct ipw_priv *ipw, unsigned long ofs,
+ u32 val)
+{
+ writel(val, ipw->hw_base + ofs);
+}
/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
-#define ipw_write32(ipw, ofs, val) \
- IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
- _ipw_write32(ipw, ofs, val)
+#define ipw_write32(ipw, ofs, val) do { \
+ IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, \
+ __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write32(ipw, ofs, val); \
+} while (0)
/* 8-bit direct read (low 4K) */
-#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
-
-/* 8-bit direct read (low 4K), with debug wrapper */
-static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+static inline u8 _ipw_read8(struct ipw_priv *ipw, unsigned long ofs)
{
- IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
- return _ipw_read8(ipw, ofs);
+ return readb(ipw->hw_base + ofs);
}
/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */
-#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
+#define ipw_read8(ipw, ofs) ({ \
+ IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", __FILE__, __LINE__, \
+ (u32)(ofs)); \
+ _ipw_read8(ipw, ofs); \
+})
/* 16-bit direct read (low 4K) */
-#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
-
-/* 16-bit direct read (low 4K), with debug wrapper */
-static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+static inline u16 _ipw_read16(struct ipw_priv *ipw, unsigned long ofs)
{
- IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
- return _ipw_read16(ipw, ofs);
+ return readw(ipw->hw_base + ofs);
}
/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */
-#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
+#define ipw_read16(ipw, ofs) ({ \
+ IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", __FILE__, __LINE__, \
+ (u32)(ofs)); \
+ _ipw_read16(ipw, ofs); \
+})
/* 32-bit direct read (low 4K) */
-#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
-
-/* 32-bit direct read (low 4K), with debug wrapper */
-static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+static inline u32 _ipw_read32(struct ipw_priv *ipw, unsigned long ofs)
{
- IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
- return _ipw_read32(ipw, ofs);
+ return readl(ipw->hw_base + ofs);
}
/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */
-#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
+#define ipw_read32(ipw, ofs) ({ \
+ IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", __FILE__, __LINE__, \
+ (u32)(ofs)); \
+ _ipw_read32(ipw, ofs); \
+})
-/* multi-byte read (above 4K), with debug wrapper */
static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
-static inline void __ipw_read_indirect(const char *f, int l,
- struct ipw_priv *a, u32 b, u8 * c, int d)
-{
- IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", f, l, (u32) (b),
- d);
- _ipw_read_indirect(a, b, c, d);
-}
-
/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
-#define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d)
+#define ipw_read_indirect(a, b, c, d) ({ \
+ IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %u bytes\n", __FILE__, \
+ __LINE__, (u32)(b), (u32)(d)); \
+ _ipw_read_indirect(a, b, c, d); \
+})
/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
int num);
-#define ipw_write_indirect(a, b, c, d) \
- IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
- _ipw_write_indirect(a, b, c, d)
+#define ipw_write_indirect(a, b, c, d) do { \
+ IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %u bytes\n", __FILE__, \
+ __LINE__, (u32)(b), (u32)(d)); \
+ _ipw_write_indirect(a, b, c, d); \
+} while (0)
/* 32-bit indirect write (above 4K) */
static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
return 0;
ipw_send_disassociate(data, 0);
+ netif_carrier_off(priv->net_dev);
return 1;
}
return;
}
- if (priv->status & STATUS_SCANNING) {
+ if (priv->status & STATUS_SCANNING &&
+ missed_count > IPW_MB_SCAN_CANCEL_THRESHOLD) {
/* Stop scan to keep fw from getting
* stuck (only if we aren't roaming --
* otherwise we'll never scan more than 2 or 3
}
}
+static int ipw_passive_dwell_time(struct ipw_priv *priv)
+{
+ /* staying on passive channels longer than the DTIM interval during a
+ * scan, while associated, causes the firmware to cancel the scan
+ * without notification. Hence, don't stay on passive channels longer
+ * than the beacon interval.
+ */
+ if (priv->status & STATUS_ASSOCIATED
+ && priv->assoc_network->beacon_interval > 10)
+ return priv->assoc_network->beacon_interval - 10;
+ else
+ return 120;
+}
+
static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
{
struct ipw_scan_request_ext scan;
scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
if (type == IW_SCAN_TYPE_PASSIVE) {
- IPW_DEBUG_WX("use passive scanning\n");
- scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
+ IPW_DEBUG_WX("use passive scanning\n");
+ scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
- cpu_to_le16(120);
+ cpu_to_le16(ipw_passive_dwell_time(priv));
ipw_add_scan_channels(priv, &scan, scan_type);
goto send_request;
}
/* Use active scan by default. */
- if (priv->config & CFG_SPEED_SCAN)
+ if (priv->config & CFG_SPEED_SCAN)
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
cpu_to_le16(30);
else
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
cpu_to_le16(20);
- scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
+ scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
+ cpu_to_le16(ipw_passive_dwell_time(priv));
scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
#ifdef CONFIG_IPW2200_MONITOR
struct ipw_rx_mem_buffer *rxb,
struct ieee80211_rx_stats *stats)
{
+ struct net_device *dev = priv->net_dev;
struct ieee80211_hdr_4addr *hdr;
struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
/* We received data from the HW, so stop the watchdog */
- priv->net_dev->trans_start = jiffies;
+ dev->trans_start = jiffies;
/* We only process data packets if the
* interface is open */
if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) >
skb_tailroom(rxb->skb))) {
- priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
priv->wstats.discard.misc++;
IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
return;
} else if (unlikely(!netif_running(priv->net_dev))) {
- priv->ieee->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
priv->wstats.discard.misc++;
IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
return;
ipw_rebuild_decrypted_skb(priv, rxb->skb);
if (!ieee80211_rx(priv->ieee, rxb->skb, stats))
- priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
else { /* ieee80211_rx succeeded, so it now owns the SKB */
rxb->skb = NULL;
__ipw_led_activity_on(priv);
struct ipw_rx_mem_buffer *rxb,
struct ieee80211_rx_stats *stats)
{
+ struct net_device *dev = priv->net_dev;
struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
struct ipw_rx_frame *frame = &pkt->u.frame;
short len = le16_to_cpu(pkt->u.frame.length);
/* We received data from the HW, so stop the watchdog */
- priv->net_dev->trans_start = jiffies;
+ dev->trans_start = jiffies;
/* We only process data packets if the
* interface is open */
if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) >
skb_tailroom(rxb->skb))) {
- priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
priv->wstats.discard.misc++;
IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
return;
} else if (unlikely(!netif_running(priv->net_dev))) {
- priv->ieee->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
priv->wstats.discard.misc++;
IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
return;
* that now */
if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) {
/* FIXME: Should alloc bigger skb instead */
- priv->ieee->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
priv->wstats.discard.misc++;
IPW_DEBUG_DROP("Dropping too large packet in monitor\n");
return;
memmove(rxb->skb->data + sizeof(struct ipw_rt_hdr),
rxb->skb->data + IPW_RX_FRAME_SIZE, len);
- /* Zero the radiotap static buffer ... We only need to zero the bytes NOT
- * part of our real header, saves a little time.
- *
- * No longer necessary since we fill in all our data. Purge before merging
- * patch officially.
- * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
- * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
- */
-
ipw_rt = (struct ipw_rt_hdr *)rxb->skb->data;
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
if (!ieee80211_rx(priv->ieee, rxb->skb, stats))
- priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
else { /* ieee80211_rx succeeded, so it now owns the SKB */
rxb->skb = NULL;
/* no LED during capture */
struct ipw_rx_mem_buffer *rxb,
struct ieee80211_rx_stats *stats)
{
+ struct net_device *dev = priv->prom_net_dev;
struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
struct ipw_rx_frame *frame = &pkt->u.frame;
struct ipw_rt_hdr *ipw_rt;
return;
/* We received data from the HW, so stop the watchdog */
- priv->prom_net_dev->trans_start = jiffies;
+ dev->trans_start = jiffies;
if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
- priv->prom_priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
return;
}
/* We only process data packets if the interface is open */
- if (unlikely(!netif_running(priv->prom_net_dev))) {
- priv->prom_priv->ieee->stats.rx_dropped++;
+ if (unlikely(!netif_running(dev))) {
+ dev->stats.rx_dropped++;
IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
return;
}
* that now */
if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) {
/* FIXME: Should alloc bigger skb instead */
- priv->prom_priv->ieee->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
IPW_DEBUG_DROP("Dropping too large packet in monitor\n");
return;
}
memcpy(ipw_rt->payload, hdr, len);
- /* Zero the radiotap static buffer ... We only need to zero the bytes
- * NOT part of our real header, saves a little time.
- *
- * No longer necessary since we fill in all our data. Purge before
- * merging patch officially.
- * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
- * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
- */
-
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*ipw_rt)); /* total header+data */
IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len);
if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) {
- priv->prom_priv->ieee->stats.rx_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb_any(skb);
}
}
skb_reset_mac_header(skb);
skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = __constant_htons(ETH_P_80211_STATS);
+ skb->protocol = cpu_to_be16(ETH_P_80211_STATS);
memset(skb->cb, 0, sizeof(rxb->skb->cb));
netif_rx(skb);
rxb->skb = NULL;
IPW_DEBUG_DROP
("Received packet is too small. "
"Dropping.\n");
- priv->ieee->stats.rx_errors++;
+ priv->net_dev->stats.rx_errors++;
priv->wstats.discard.misc++;
break;
}
u16 remaining_bytes;
int fc;
+ if (!(priv->status & STATUS_ASSOCIATED))
+ goto drop;
+
hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
} else
len = src->len;
- dst = alloc_skb(
- len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC);
- if (!dst) continue;
+ dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+ if (!dst)
+ continue;
rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr));
return ret;
}
-static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
-{
- struct ipw_priv *priv = ieee80211_priv(dev);
-
- priv->ieee->stats.tx_packets = priv->tx_packets;
- priv->ieee->stats.rx_packets = priv->rx_packets;
- return &priv->ieee->stats;
-}
-
static void ipw_net_set_multicast_list(struct net_device *dev)
{
{
int rc, i, j;
+ /* Age scan list entries found before suspend */
+ if (priv->suspend_time) {
+ ieee80211_networks_age(priv->ieee, priv->suspend_time);
+ priv->suspend_time = 0;
+ }
+
if (priv->status & STATUS_EXIT_PENDING)
return -EIO;
return -EOPNOTSUPP;
}
-static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev)
-{
- struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
- return &prom_priv->ieee->stats;
-}
+static const struct net_device_ops ipw_prom_netdev_ops = {
+ .ndo_open = ipw_prom_open,
+ .ndo_stop = ipw_prom_stop,
+ .ndo_start_xmit = ipw_prom_hard_start_xmit,
+ .ndo_change_mtu = ieee80211_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static int ipw_prom_alloc(struct ipw_priv *priv)
{
memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
- priv->prom_net_dev->open = ipw_prom_open;
- priv->prom_net_dev->stop = ipw_prom_stop;
- priv->prom_net_dev->get_stats = ipw_prom_get_stats;
- priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit;
+ priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;
priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev);
#endif
+static const struct net_device_ops ipw_netdev_ops = {
+ .ndo_init = ipw_net_init,
+ .ndo_open = ipw_net_open,
+ .ndo_stop = ipw_net_stop,
+ .ndo_set_multicast_list = ipw_net_set_multicast_list,
+ .ndo_set_mac_address = ipw_net_set_mac_address,
+ .ndo_start_xmit = ieee80211_xmit,
+ .ndo_change_mtu = ieee80211_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static int __devinit ipw_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
priv->ieee->perfect_rssi = -20;
priv->ieee->worst_rssi = -85;
- net_dev->open = ipw_net_open;
- net_dev->stop = ipw_net_stop;
- net_dev->init = ipw_net_init;
- net_dev->get_stats = ipw_net_get_stats;
- net_dev->set_multicast_list = ipw_net_set_multicast_list;
- net_dev->set_mac_address = ipw_net_set_mac_address;
+ net_dev->netdev_ops = &ipw_netdev_ops;
priv->wireless_data.spy_data = &priv->ieee->spy_data;
net_dev->wireless_data = &priv->wireless_data;
net_dev->wireless_handlers = &ipw_wx_handler_def;
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ priv->suspend_at = get_seconds();
+
return 0;
}
* the queue of needed */
netif_device_attach(dev);
+ priv->suspend_time = get_seconds() - priv->suspend_at;
+
/* Bring the device back up */
queue_work(priv->workqueue, &priv->up);