Commit aca361c1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (45 commits)
  [PATCH] Restore channel setting after scan.
  [PATCH] hostap: Fix memory leak on PCI probe error path
  [PATCH] hostap: Remove dead code (duplicated idx != 0)
  [PATCH] hostap: Fix unlikely read overrun in CIS parsing
  [PATCH] hostap: Fix double free in prism2_config() error path
  [PATCH] hostap: Fix ap_add_sta() return value verification
  [PATCH] hostap: Fix hw reset after CMDCODE_ACCESS_WRITE timeout
  [PATCH] wireless/airo: cache wireless scans
  [PATCH] wireless/airo: define default MTU
  [PATCH] wireless/airo: clean up printk usage to print device name
  [PATCH] WE-20 for kernel 2.6.16
  [PATCH] softmac: remove function_enter()
  [PATCH] skge: version 1.5
  [PATCH] skge: compute available ring buffers
  [PATCH] skge: dont free skb until multi-part transmit complete
  [PATCH] skge: multicast statistics fix
  [PATCH] skge: rx_reuse called twice
  [PATCH] skge: dont use dev_alloc_skb for rx buffs
  [PATCH] skge: align receive buffers
  [PATCH] sky2: dont need to use dev_kfree_skb_any
  ...
parents cec60620 9b7c8489
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include "skge.h" #include "skge.h"
#define DRV_NAME "skge" #define DRV_NAME "skge"
#define DRV_VERSION "1.4" #define DRV_VERSION "1.5"
#define PFX DRV_NAME " " #define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128 #define DEFAULT_TX_RING_SIZE 128
...@@ -357,7 +357,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) ...@@ -357,7 +357,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev)
skge->net_stats.rx_bytes = data[1]; skge->net_stats.rx_bytes = data[1];
skge->net_stats.tx_packets = data[2] + data[4] + data[6]; skge->net_stats.tx_packets = data[2] + data[4] + data[6];
skge->net_stats.rx_packets = data[3] + data[5] + data[7]; skge->net_stats.rx_packets = data[3] + data[5] + data[7];
skge->net_stats.multicast = data[5] + data[7]; skge->net_stats.multicast = data[3] + data[5];
skge->net_stats.collisions = data[10]; skge->net_stats.collisions = data[10];
skge->net_stats.tx_aborted_errors = data[12]; skge->net_stats.tx_aborted_errors = data[12];
...@@ -781,7 +781,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, ...@@ -781,7 +781,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
* Note: DMA address is not changed by chip. * Note: DMA address is not changed by chip.
* MTU not changed while receiver active. * MTU not changed while receiver active.
*/ */
static void skge_rx_reuse(struct skge_element *e, unsigned int size) static inline void skge_rx_reuse(struct skge_element *e, unsigned int size)
{ {
struct skge_rx_desc *rd = e->desc; struct skge_rx_desc *rd = e->desc;
...@@ -829,7 +829,7 @@ static int skge_rx_fill(struct skge_port *skge) ...@@ -829,7 +829,7 @@ static int skge_rx_fill(struct skge_port *skge)
do { do {
struct sk_buff *skb; struct sk_buff *skb;
skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); skb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_KERNEL);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -847,8 +847,7 @@ static void skge_link_up(struct skge_port *skge) ...@@ -847,8 +847,7 @@ static void skge_link_up(struct skge_port *skge)
LED_BLK_OFF|LED_SYNC_OFF|LED_ON); LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
netif_carrier_on(skge->netdev); netif_carrier_on(skge->netdev);
if (skge->tx_avail > MAX_SKB_FRAGS + 1) netif_wake_queue(skge->netdev);
netif_wake_queue(skge->netdev);
if (netif_msg_link(skge)) if (netif_msg_link(skge))
printk(KERN_INFO PFX printk(KERN_INFO PFX
...@@ -2155,7 +2154,7 @@ static int skge_up(struct net_device *dev) ...@@ -2155,7 +2154,7 @@ static int skge_up(struct net_device *dev)
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
if (dev->mtu > RX_BUF_SIZE) if (dev->mtu > RX_BUF_SIZE)
skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; skge->rx_buf_size = dev->mtu + ETH_HLEN;
else else
skge->rx_buf_size = RX_BUF_SIZE; skge->rx_buf_size = RX_BUF_SIZE;
...@@ -2190,8 +2189,6 @@ static int skge_up(struct net_device *dev) ...@@ -2190,8 +2189,6 @@ static int skge_up(struct net_device *dev)
if (err) if (err)
goto free_rx_ring; goto free_rx_ring;
skge->tx_avail = skge->tx_ring.count - 1;
/* Initialize MAC */ /* Initialize MAC */
spin_lock_bh(&hw->phy_lock); spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) if (hw->chip_id == CHIP_ID_GENESIS)
...@@ -2294,6 +2291,12 @@ static int skge_down(struct net_device *dev) ...@@ -2294,6 +2291,12 @@ static int skge_down(struct net_device *dev)
return 0; return 0;
} }
static inline int skge_avail(const struct skge_ring *ring)
{
return ((ring->to_clean > ring->to_use) ? 0 : ring->count)
+ (ring->to_clean - ring->to_use) - 1;
}
static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
{ {
struct skge_port *skge = netdev_priv(dev); struct skge_port *skge = netdev_priv(dev);
...@@ -2314,7 +2317,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -2314,7 +2317,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_LOCKED; return NETDEV_TX_LOCKED;
} }
if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) {
if (!netif_queue_stopped(dev)) { if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -2390,8 +2393,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -2390,8 +2393,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
dev->name, e - ring->start, skb->len); dev->name, e - ring->start, skb->len);
ring->to_use = e->next; ring->to_use = e->next;
skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1; if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) {
if (skge->tx_avail <= MAX_SKB_FRAGS + 1) {
pr_debug("%s: transmit queue full\n", dev->name); pr_debug("%s: transmit queue full\n", dev->name);
netif_stop_queue(dev); netif_stop_queue(dev);
} }
...@@ -2404,35 +2406,37 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -2404,35 +2406,37 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) static void skge_tx_complete(struct skge_port *skge, struct skge_element *last)
{ {
/* This ring element can be skb or fragment */ struct pci_dev *pdev = skge->hw->pdev;
if (e->skb) { struct skge_element *e;
pci_unmap_single(hw->pdev,
pci_unmap_addr(e, mapaddr), for (e = skge->tx_ring.to_clean; e != last; e = e->next) {
pci_unmap_len(e, maplen), struct sk_buff *skb = e->skb;
PCI_DMA_TODEVICE); int i;
dev_kfree_skb(e->skb);
e->skb = NULL; e->skb = NULL;
} else { pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr),
pci_unmap_page(hw->pdev, skb_headlen(skb), PCI_DMA_TODEVICE);
pci_unmap_addr(e, mapaddr),
pci_unmap_len(e, maplen), for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
PCI_DMA_TODEVICE); e = e->next;
pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
skb_shinfo(skb)->frags[i].size,
PCI_DMA_TODEVICE);
}
dev_kfree_skb(skb);
} }
skge->tx_ring.to_clean = e;
} }
static void skge_tx_clean(struct skge_port *skge) static void skge_tx_clean(struct skge_port *skge)
{ {
struct skge_ring *ring = &skge->tx_ring;
struct skge_element *e;
spin_lock_bh(&skge->tx_lock); spin_lock_bh(&skge->tx_lock);
for (e = ring->to_clean; e != ring->to_use; e = e->next) { skge_tx_complete(skge, skge->tx_ring.to_use);
++skge->tx_avail; netif_wake_queue(skge->netdev);
skge_tx_free(skge->hw, e);
}
ring->to_clean = e;
spin_unlock_bh(&skge->tx_lock); spin_unlock_bh(&skge->tx_lock);
} }
...@@ -2592,7 +2596,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, ...@@ -2592,7 +2596,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
goto error; goto error;
if (len < RX_COPY_THRESHOLD) { if (len < RX_COPY_THRESHOLD) {
skb = dev_alloc_skb(len + 2); skb = alloc_skb(len + 2, GFP_ATOMIC);
if (!skb) if (!skb)
goto resubmit; goto resubmit;
...@@ -2607,10 +2611,11 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, ...@@ -2607,10 +2611,11 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
skge_rx_reuse(e, skge->rx_buf_size); skge_rx_reuse(e, skge->rx_buf_size);
} else { } else {
struct sk_buff *nskb; struct sk_buff *nskb;
nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); nskb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_ATOMIC);
if (!nskb) if (!nskb)
goto resubmit; goto resubmit;
skb_reserve(nskb, NET_IP_ALIGN);
pci_unmap_single(skge->hw->pdev, pci_unmap_single(skge->hw->pdev,
pci_unmap_addr(e, mapaddr), pci_unmap_addr(e, mapaddr),
pci_unmap_len(e, maplen), pci_unmap_len(e, maplen),
...@@ -2661,30 +2666,29 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, ...@@ -2661,30 +2666,29 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
static void skge_tx_done(struct skge_port *skge) static void skge_tx_done(struct skge_port *skge)
{ {
struct skge_ring *ring = &skge->tx_ring; struct skge_ring *ring = &skge->tx_ring;
struct skge_element *e; struct skge_element *e, *last;
spin_lock(&skge->tx_lock); spin_lock(&skge->tx_lock);
for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { last = ring->to_clean;
for (e = ring->to_clean; e != ring->to_use; e = e->next) {
struct skge_tx_desc *td = e->desc; struct skge_tx_desc *td = e->desc;
u32 control;
rmb(); if (td->control & BMU_OWN)
control = td->control;
if (control & BMU_OWN)
break; break;
if (unlikely(netif_msg_tx_done(skge))) if (td->control & BMU_EOF) {
printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", last = e->next;
skge->netdev->name, e - ring->start, td->status); if (unlikely(netif_msg_tx_done(skge)))
printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
skge_tx_free(skge->hw, e); skge->netdev->name, e - ring->start);
e->skb = NULL; }
++skge->tx_avail;
} }
ring->to_clean = e;
skge_tx_complete(skge, last);
skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
if (skge->tx_avail > MAX_SKB_FRAGS + 1) if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1)
netif_wake_queue(skge->netdev); netif_wake_queue(skge->netdev);
spin_unlock(&skge->tx_lock); spin_unlock(&skge->tx_lock);
...@@ -2718,8 +2722,7 @@ static int skge_poll(struct net_device *dev, int *budget) ...@@ -2718,8 +2722,7 @@ static int skge_poll(struct net_device *dev, int *budget)
netif_receive_skb(skb); netif_receive_skb(skb);
++work_done; ++work_done;
} else }
skge_rx_reuse(e, skge->rx_buf_size);
} }
ring->to_clean = e; ring->to_clean = e;
......
...@@ -2418,7 +2418,6 @@ struct skge_port { ...@@ -2418,7 +2418,6 @@ struct skge_port {
int port; int port;
spinlock_t tx_lock; spinlock_t tx_lock;
u32 tx_avail;
struct skge_ring tx_ring; struct skge_ring tx_ring;
struct skge_ring rx_ring; struct skge_ring rx_ring;
......
...@@ -1175,7 +1175,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -1175,7 +1175,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* just drop the packet if non-linear expansion fails */ /* just drop the packet if non-linear expansion fails */
if (skb_header_cloned(skb) && if (skb_header_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
dev_kfree_skb_any(skb); dev_kfree_skb(skb);
goto out_unlock; goto out_unlock;
} }
...@@ -1324,7 +1324,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) ...@@ -1324,7 +1324,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
} }
dev_kfree_skb_any(skb); dev_kfree_skb(skb);
} }
sky2->tx_cons = put; sky2->tx_cons = put;
...@@ -2484,7 +2484,7 @@ static const struct sky2_stat { ...@@ -2484,7 +2484,7 @@ static const struct sky2_stat {
{ "single_collisions", GM_TXF_SNG_COL }, { "single_collisions", GM_TXF_SNG_COL },
{ "multi_collisions", GM_TXF_MUL_COL }, { "multi_collisions", GM_TXF_MUL_COL },
{ "rx_short", GM_RXE_SHT }, { "rx_short", GM_RXF_SHT },
{ "rx_runt", GM_RXE_FRAG }, { "rx_runt", GM_RXE_FRAG },
{ "rx_64_byte_packets", GM_RXF_64B }, { "rx_64_byte_packets", GM_RXF_64B },
{ "rx_65_to_127_byte_packets", GM_RXF_127B }, { "rx_65_to_127_byte_packets", GM_RXF_127B },
...@@ -2607,7 +2607,7 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) ...@@ -2607,7 +2607,7 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev)
sky2->net_stats.rx_bytes = data[1]; sky2->net_stats.rx_bytes = data[1];
sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; sky2->net_stats.tx_packets = data[2] + data[4] + data[6];
sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; sky2->net_stats.rx_packets = data[3] + data[5] + data[7];
sky2->net_stats.multicast = data[5] + data[7]; sky2->net_stats.multicast = data[3] + data[5];
sky2->net_stats.collisions = data[10]; sky2->net_stats.collisions = data[10];
sky2->net_stats.tx_aborted_errors = data[12]; sky2->net_stats.tx_aborted_errors = data[12];
......
...@@ -25,6 +25,15 @@ config NET_RADIO ...@@ -25,6 +25,15 @@ config NET_RADIO
the tools from the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
config NET_WIRELESS_RTNETLINK
bool "Wireless Extension API over RtNetlink"
---help---
Support the Wireless Extension API over the RtNetlink socket
in addition to the traditional ioctl interface (selected above).
For now, few tools use this facility, but it might grow in the
future. The only downside is that it adds 4.5 kB to your kernel.
# Note : the cards are obsolete (can't buy them anymore), but the drivers # Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them... # are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)" comment "Obsolete Wireless cards support (pre-802.11)"
......
This diff is collapsed.
...@@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) ...@@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
if (ret == 1) { if (ret == 1) {
sta = ap_add_sta(ap, sta_addr); sta = ap_add_sta(ap, sta_addr);
if (!sta) if (!sta)
ret = -1; return -1;
sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->ap = 1; sta->ap = 1;
memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
......
...@@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link) ...@@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link)
parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
if (parse == NULL || hw_priv == NULL) { if (parse == NULL || hw_priv == NULL) {
kfree(parse);
kfree(hw_priv);
ret = -ENOMEM; ret = -ENOMEM;
goto failed; goto failed;
} }
......
...@@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) ...@@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL);
up(&local->rid_bap_sem); up(&local->rid_bap_sem);
if (res) { if (res) {
printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
"failed (res=%d, rid=%04x, len=%d)\n", "failed (res=%d, rid=%04x, len=%d)\n",
dev->name, res, rid, len); dev->name, res, rid, len);
return res;
}
if (res == -ETIMEDOUT) if (res == -ETIMEDOUT)
prism2_hw_reset(dev); prism2_hw_reset(dev);
}
return res; return res;
} }
......
...@@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, ...@@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
if (!sta_ptr) if (!sta_ptr)
local->tx_keyidx = i; local->tx_keyidx = i;
else if (i) {
ret = -EINVAL;
goto done;
}
} }
......
...@@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev, ...@@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
memset(hw_priv, 0, sizeof(*hw_priv)); memset(hw_priv, 0, sizeof(*hw_priv));
if (pci_enable_device(pdev)) if (pci_enable_device(pdev))
return -EIO; goto err_out_free;
phymem = pci_resource_start(pdev, 0); phymem = pci_resource_start(pdev, 0);
...@@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev, ...@@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
err_out_disable: err_out_disable:
pci_disable_device(pdev); pci_disable_device(pdev);
prism2_free_local_data(dev); prism2_free_local_data(dev);
err_out_free:
kfree(hw_priv); kfree(hw_priv);
return -ENODEV; return -ENODEV;
......
...@@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, ...@@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
switch (cis[pos]) { switch (cis[pos]) {
case CISTPL_CONFIG: case CISTPL_CONFIG:
if (cis[pos + 1] < 1) if (cis[pos + 1] < 2)
goto cis_error; goto cis_error;
rmsz = (cis[pos + 2] & 0x3c) >> 2; rmsz = (cis[pos + 2] & 0x3c) >> 2;
rasz = cis[pos + 2] & 0x03; rasz = cis[pos + 2] & 0x03;
...@@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, ...@@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
break; break;
case CISTPL_MANFID: case CISTPL_MANFID:
if (cis[pos + 1] < 4) if (cis[pos + 1] < 5)
goto cis_error; goto cis_error;
manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
...@@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, ...@@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
memset(hw_priv, 0, sizeof(*hw_priv)); memset(hw_priv, 0, sizeof(*hw_priv));
if (pci_enable_device(pdev)) if (pci_enable_device(pdev))
return -EIO; goto err_out_free;
/* National Datacomm NCP130 based on TMD7160, not PLX9052. */ /* National Datacomm NCP130 based on TMD7160, not PLX9052. */
tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131);
...@@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev, ...@@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev); return hostap_hw_ready(dev);
fail: fail:
prism2_free_local_data(dev);
kfree(hw_priv);
if (irq_registered && dev) if (irq_registered && dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
...@@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev, ...@@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev,
iounmap(attr_mem); iounmap(attr_mem);
pci_disable_device(pdev); pci_disable_device(pdev);
prism2_free_local_data(dev);
err_out_free:
kfree(hw_priv);
return -ENODEV; return -ENODEV;
} }
......
/* /*
* This file define a set of standard wireless extensions * This file define a set of standard wireless extensions
* *
* Version : 19 18.3.05 * Version : 20 17.2.06
* *
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
*/ */
#ifndef _LINUX_WIRELESS_H #ifndef _LINUX_WIRELESS_H
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
* (there is some stuff that will be added in the future...) * (there is some stuff that will be added in the future...)
* I just plan to increment with each new version. * I just plan to increment with each new version.
*/ */
#define WIRELESS_EXT 19 #define WIRELESS_EXT 20
/* /*
* Changes : * Changes :
...@@ -204,6 +204,10 @@ ...@@ -204,6 +204,10 @@
* - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
* - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
* - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
*
* V19 to V20
* ----------
* - RtNetlink requests support (SET/GET)
*/ */
/**************************** CONSTANTS ****************************/ /**************************** CONSTANTS ****************************/
......
/*
* ieee80211softmac.h - public interface to the softmac
*
* Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net>
* Joseph Jezak <josejx@gentoo.org>
* Larry Finger <Larry.Finger@lwfinger.net>
* Danny van Dyk <kugelfang@gentoo.org>
* Michael Buesch <mbuesch@freenet.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The full GNU General Public License is included in this distribution in the
* file called COPYING.
*/
#ifndef IEEE80211SOFTMAC_H_
#define IEEE80211SOFTMAC_H_
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <net/ieee80211.h>
/* Once the API is considered more or less stable,
* this should be incremented on API incompatible changes.
*/
#define IEEE80211SOFTMAC_API 0
#define IEEE80211SOFTMAC_MAX_RATES_LEN 8
#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255
struct ieee80211softmac_ratesinfo {
u8 count;
u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN];
};
/* internal structures */
struct ieee80211softmac_network;
struct ieee80211softmac_scaninfo;
struct ieee80211softmac_essid {
u8 len;
char data[IW_ESSID_MAX_SIZE+1];
};
struct ieee80211softmac_wpa {
char *IE;
int IElen;
int IEbuflen;
};
/*
* Information about association
*
* Do we need a lock for this?
* We only ever use this structure inlined
* into our global struct. I've used its lock,
* but maybe we need a local one here?
*/
struct ieee80211softmac_assoc_info {
/*
* This is the requested ESSID. It is written
* only by the WX handlers.
*
*/
struct ieee80211softmac_essid req_essid;
/*
* the ESSID of the network we're currently
* associated (or trying) to. This is
* updated to the network's actual ESSID
* even if the requested ESSID was 'ANY'
*/
struct ieee80211softmac_essid associate_essid;
/* BSSID we're trying to associate to */
char bssid[ETH_ALEN];
/* some flags.
* static_essid is valid if the essid is constant,
* this is for use by the wx handlers only.
*
* associating is true, if the network has been
* auth'ed on and we are in the process of associating.
*
* bssvalid is true if we found a matching network
* and saved it's BSSID into the bssid above.
*/
u8 static_essid:1,
associating:1,
bssvalid:1;
/* Scan retries remaining */
int scan_retry;
struct work_struct work;
struct work_struct timeout;
};
enum {
IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1,
IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2,
};
enum {
IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1,
IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2,
IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3,
IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4,
};
/* We should make these tunable
* AUTH_TIMEOUT seems really long, but that's what it is in BSD */
#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ)
#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5
#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3
struct ieee80211softmac_txrates {
/* The Bit-Rate to be used for multicast frames. */
u8 mcast_rate;
/* The Bit-Rate to be used for multicast fallback
* (If the device supports fallback and hardware-retry)
*/
u8 mcast_fallback;
/* The Bit-Rate to be used for any other (normal) data packet. */
u8 default_rate;
/* The Bit-Rate to be used for default fallback
* (If the device supports fallback and hardware-retry)
*/
u8 default_fallback;
};
/* Bits for txrates_change callback. */
#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */
#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */
#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */
#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK (1 << 3) /* mcast_fallback */
struct ieee80211softmac_device {
/* 802.11 structure for data stuff */
struct ieee80211_device *ieee;
struct net_device *dev;
/* only valid if associated, then holds the Association ID */
u16 association_id;
/* the following methods are callbacks that the driver
* using this framework has to assign
*/
/* always assign these */
void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid);
void (*set_channel)(struct net_device *dev, u8 channel);
/* assign if you need it, informational only */
void (*link_change)(struct net_device *dev);
/* If the hardware can do scanning, assign _all_ three of these callbacks.
* When the scan finishes, call ieee80211softmac_scan_finished().
*/
/* when called, start_scan is guaranteed to not be called again
* until you call ieee80211softmac_scan_finished.
* Return 0 if scanning could start, error otherwise.
* SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */
int (*start_scan)(struct net_device *dev);
/* this should block until after ieee80211softmac_scan_finished was called
* SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */
void (*wait_for_scan)(struct net_device *dev);
/* stop_scan aborts a scan, but is asynchronous.
* if you want to wait for it too, use wait_for_scan
* SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */
void (*stop_scan)(struct net_device *dev);
/* we'll need something about beacons here too, for AP or ad-hoc modes */
/* Transmission rates to be used by the driver.
* The SoftMAC figures out the best possible rates.
* The driver just needs to read them.
*/
struct ieee80211softmac_txrates txrates;
/* If the driver needs to do stuff on TX rate changes, assign this callback. */
void (*txrates_change)(struct net_device *dev,
u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */
const struct ieee80211softmac_txrates *rates_before_change);
/* private stuff follows */
/* this lock protects this structure */
spinlock_t lock;
/* couple of flags */
u8 scanning:1, /* protects scanning from being done multiple times at once */
associated:1;
struct ieee80211softmac_scaninfo *scaninfo;
struct ieee80211softmac_assoc_info associnfo;
struct list_head auth_queue;
struct list_head events;
struct ieee80211softmac_ratesinfo ratesinfo;
int txrate_badness;
/* WPA stuff */
struct ieee80211softmac_wpa wpa;
/* we need to keep a list of network structs we copied */
struct list_head network_list;
/* This must be the last item so that it points to the data
* allocated beyond this structure by alloc_ieee80211 */
u8 priv[0];
};
extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm);
static inline void * ieee80211softmac_priv(struct net_device *dev)
{
return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv;
}
extern struct net_device * alloc_ieee80211softmac(int sizeof_priv);
extern void free_ieee80211softmac(struct net_device *dev);
/* Call this function if you detect a lost TX fragment.
* (If the device indicates failure of ACK RX, for example.)
* It is wise to call this function if you are able to detect lost packets,
* because it contributes to the TX Rates auto adjustment.
*/
extern void ieee80211softmac_fragment_lost(struct net_device *dev,
u16 wireless_sequence_number);
/* Call this function before _start to tell the softmac what rates
* the hw supports. The rates parameter is copied, so you can
* free it right after calling this function.
* Note that the rates need to be sorted. */
extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
/* Start the SoftMAC. Call this after you initialized the device
* and it is ready to run.
*/
extern void ieee80211softmac_start(struct net_device *dev);
/* Stop the SoftMAC. Call this before you shutdown the device. */
extern void ieee80211softmac_stop(struct net_device *dev);
/*
* Event system
*/
/* valid event types */
#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/
#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0
#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3
#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4
#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
/* keep this updated! */
#define IEEE80211SOFTMAC_EVENT_LAST 7
/*
* If you want to be notified of certain events, you can call
* ieee80211softmac_notify[_atomic] with
* - event set to one of the constants below
* - fun set to a function pointer of the appropriate type
* - context set to the context data you want passed
* The return value is 0, or an error.
*/
typedef void (*notify_function_ptr)(struct net_device *dev, void *context);
#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
extern int ieee80211softmac_notify_gfp(struct net_device *dev,
int event, notify_function_ptr fun, void *context, gfp_t gfp_mask);
/* To clear pending work (for ifconfig down, etc.) */
extern void
ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm);
#endif /* IEEE80211SOFTMAC_H_ */
/*
* This file contains the prototypes for the wireless extension
* handlers that the softmac API provides. Include this file to
* use the wx handlers, you can assign these directly.
*
* Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net>
* Joseph Jezak <josejx@gentoo.org>
* Larry Finger <Larry.Finger@lwfinger.net>
* Danny van Dyk <kugelfang@gentoo.org>
* Michael Buesch <mbuesch@freenet.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The full GNU General Public License is included in this distribution in the
* file called COPYING.
*/
#ifndef _IEEE80211SOFTMAC_WX_H
#define _IEEE80211SOFTMAC_WX_H
#include <net/ieee80211softmac.h>
#include <net/iw_handler.h>
extern int
ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_set_essid(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_get_essid(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_set_rate(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_get_rate(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_get_wap(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_set_wap(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra);
extern int
ieee80211softmac_wx_set_genie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra);
extern int
ieee80211softmac_wx_get_genie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra);
#endif /* _IEEE80211SOFTMAC_WX */
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Version : 7 18.3.05 * Version : 7 18.3.05
* *
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved. * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
*/ */
#ifndef _IW_HANDLER_H #ifndef _IW_HANDLER_H
...@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, ...@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
/* Handle IOCTLs, called in net/core/dev.c */ /* Handle IOCTLs, called in net/core/dev.c */
extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
extern int wireless_rtnetlink_set(struct net_device * dev,
char * data,
int len);
extern int wireless_rtnetlink_get(struct net_device * dev,
char * data,
int len,
char ** p_buf,
int * p_len);
/* Second : functions that may be called by driver modules */ /* Second : functions that may be called by driver modules */
/* Send a single event to user space */ /* Send a single event to user space */
......
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
#include <net/sock.h> #include <net/sock.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/netlink.h> #include <net/netlink.h>
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
#include <linux/wireless.h>
#include <net/iw_handler.h>
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
static DEFINE_MUTEX(rtnl_mutex); static DEFINE_MUTEX(rtnl_mutex);
...@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
goto out; goto out;
} }
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (ida[IFLA_WIRELESS - 1]) {
/* Call Wireless Extensions.
* Various stuff checked in there... */
err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
if (err)
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
err = 0; err = 0;
out: out:
...@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return err; return err;
} }
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
struct ifinfomsg *ifm = NLMSG_DATA(in_nlh);
struct rtattr **ida = arg;
struct net_device *dev;
struct ifinfomsg *r;
struct nlmsghdr *nlh;
int err = -ENOBUFS;
struct sk_buff *skb;
unsigned char *b;
char *iw_buf = NULL;
int iw_buf_len = 0;
if (ifm->ifi_index >= 0)
dev = dev_get_by_index(ifm->ifi_index);
else
return -EINVAL;
if (!dev)
return -ENODEV;
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (ida[IFLA_WIRELESS - 1]) {
/* Call Wireless Extensions. We need to know the size before
* we can alloc. Various stuff checked in there... */
err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
if (err)
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
/* Create a skb big enough to include all the data.
* Some requests are way bigger than 4k... Jean II */
skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
GFP_KERNEL);
if (!skb)
goto out;
b = skb->tail;
/* Put in the message the usual good stuff */
nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
RTM_NEWLINK, sizeof(*r));
r = NLMSG_DATA(nlh);
r->ifi_family = AF_UNSPEC;
r->__ifi_pad = 0;
r->ifi_type = dev->type;
r->ifi_index = dev->ifindex;
r->ifi_flags = dev->flags;
r->ifi_change = 0;
/* Put the wireless payload if it exist */
if(iw_buf != NULL)
RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
iw_buf + IW_EV_POINT_OFF);
nlh->nlmsg_len = skb->tail - b;
/* Needed ? */
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
if (err > 0)
err = 0;
out:
if(iw_buf != NULL)
kfree(iw_buf);
dev_put(dev);
return err;
rtattr_failure:
nlmsg_failure:
kfree_skb(skb);
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{ {
int idx; int idx;
...@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len) ...@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
{ {
[RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, [RTM_GETLINK - RTM_BASE] = {
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
.doit = do_getlink,
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
.dumpit = rtnetlink_dump_ifinfo },
[RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
[RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
......
This diff is collapsed.
...@@ -66,3 +66,4 @@ config IEEE80211_CRYPT_TKIP ...@@ -66,3 +66,4 @@ config IEEE80211_CRYPT_TKIP
This can be compiled as a modules and it will be called This can be compiled as a modules and it will be called
"ieee80211_crypt_tkip". "ieee80211_crypt_tkip".
source "net/ieee80211/softmac/Kconfig"
...@@ -10,3 +10,4 @@ ieee80211-objs := \ ...@@ -10,3 +10,4 @@ ieee80211-objs := \
ieee80211_wx.o \ ieee80211_wx.o \
ieee80211_geo.o ieee80211_geo.o
obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/
...@@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ...@@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
return 0; return 0;
} }
/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
int ieee80211_rx_any(struct ieee80211_device *ieee,
struct sk_buff *skb, struct ieee80211_rx_stats *stats)
{
struct ieee80211_hdr_4addr *hdr;
int is_packet_for_us;
u16 fc;
if (ieee->iw_mode == IW_MODE_MONITOR)
return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if ((fc & IEEE80211_FCTL_VERS) != 0)
return -EINVAL;
switch (fc & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_MGMT:
ieee80211_rx_mgt(ieee, hdr, stats);
return 0;
case IEEE80211_FTYPE_DATA:
break;
case IEEE80211_FTYPE_CTL:
return 0;
default:
return -EINVAL;
}
is_packet_for_us = 0;
switch (ieee->iw_mode) {
case IW_MODE_ADHOC:
/* our BSS and not from/to DS */
if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
/* promisc: get all */
if (ieee->dev->flags & IFF_PROMISC)
is_packet_for_us = 1;
/* to us */
else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
is_packet_for_us = 1;
/* mcast */
else if (is_multicast_ether_addr(hdr->addr1))
is_packet_for_us = 1;
}
break;
case IW_MODE_INFRA:
/* our BSS (== from our AP) and from DS */
if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
/* promisc: get all */
if (ieee->dev->flags & IFF_PROMISC)
is_packet_for_us = 1;
/* to us */
else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
is_packet_for_us = 1;
/* mcast */
else if (is_multicast_ether_addr(hdr->addr1)) {
/* not our own packet bcasted from AP */
if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
is_packet_for_us = 1;
}
}
break;
default:
/* ? */
break;
}
if (is_packet_for_us)
return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
return 0;
}
#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 #define MGMT_FRAME_FIXED_PART_LENGTH 0x24
static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
......
config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL
---help---
This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack.
config IEEE80211_SOFTMAC_DEBUG
bool "Enable full debugging output"
depends on IEEE80211_SOFTMAC
obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o
ieee80211softmac-objs := \
ieee80211softmac_io.o \
ieee80211softmac_auth.o \
ieee80211softmac_module.o \
ieee80211softmac_scan.o \
ieee80211softmac_wx.o \
ieee80211softmac_assoc.o \
ieee80211softmac_event.o
This diff is collapsed.
This diff is collapsed.
/*
* Event system
* Also see comments in public header file and longer explanation below.
*
* Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
* Joseph Jezak <josejx@gentoo.org>
* Larry Finger <Larry.Finger@lwfinger.net>
* Danny van Dyk <kugelfang@gentoo.org>
* Michael Buesch <mbuesch@freenet.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The full GNU General Public License is included in this distribution in the
* file called COPYING.
*/
#include "ieee80211softmac_priv.h"
/*
* Each event has associated to it
* - an event type (see constants in public header)
* - an event context (see below)
* - the function to be called
* - a context (extra parameter to call the function with)
* - and the softmac struct
*
* The event context is private and can only be used from
* within this module. Its meaning varies with the event
* type:
* SCAN_FINISHED: no special meaning
* ASSOCIATED,
* ASSOCIATE_FAILED,
* ASSOCIATE_TIMEOUT,
* AUTHENTICATED,
* AUTH_FAILED,
* AUTH_TIMEOUT: a pointer to the network struct
* ...
* Code within this module can use the event context to be only
* called when the event is true for that specific context
* as per above table.
* If the event context is NULL, then the notification is always called,
* regardless of the event context. The event context is not passed to
* the callback, it is assumed that the context suffices.
*
* You can also use the event context only by setting the event type
* to -1 (private use only), in which case you'll be notified
* whenever the event context matches.
*/
static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
"scan finished",
"associated",
"associating failed",
"associating timed out",
"authenticated",
"authenticating failed",
"authenticating timed out",
"associating failed because no suitable network was found",
};
static void
ieee80211softmac_notify_callback(void *d)
{
struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
kfree(d);
event.fun(event.mac->dev, event.context);
}
int
ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
{
struct ieee80211softmac_event *eventptr;
unsigned long flags;
if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
return -ENOSYS;
if (!fun)
return -EINVAL;
eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
if (!eventptr)
return -ENOMEM;
eventptr->event_type = event;
INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr);
eventptr->fun = fun;
eventptr->context = context;
eventptr->mac = mac;
eventptr->event_context = event_context;
spin_lock_irqsave(&mac->lock, flags);
list_add(&eventptr->list, &mac->events);
spin_unlock_irqrestore(&mac->lock, flags);
return 0;
}
int
ieee80211softmac_notify_gfp(struct net_device *dev,
int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
return -ENOSYS;
return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
/* private -- calling all callbacks that were specified */
void
ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
{
struct ieee80211softmac_event *eventptr, *tmp;
union iwreq_data wrqu;
char *msg;
if (event >= 0) {
msg = event_descriptions[event];
wrqu.data.length = strlen(msg);
wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
}
if (!list_empty(&mac->events))
list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
if ((eventptr->event_type == event || eventptr->event_type == -1)
&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
list_del(&eventptr->list);
schedule_work(&eventptr->work);
}
}
}
void
ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
{
unsigned long flags;
spin_lock_irqsave(&mac->lock, flags);
ieee80211softmac_call_events_locked(mac, event, event_ctx);
spin_unlock_irqrestore(&mac->lock, flags);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment