Netdev List
 help / color / mirror / Atom feed
* [PATCH] Fix locking in gianfar
From: Andy Fleming @ 2006-04-07  1:36 UTC (permalink / raw)
  To: Netdev

This patch fixes several bugs in the gianfar driver, including a  
major one
where spinlocks were horribly broken:

* Split gianfar locks into two types: TX and RX
* Made it so gfar_start() now clears RHALT
* Fixed a bug where calling gfar_start_xmit() with interrupts off would
corrupt the interrupt state
* Fixed a bug where a frame could potentially arrive, and never be  
handled
(if no more frames arrived
* Fixed a bug where the rx_work_limit would never be observed by the rx
completion code
* Fixed a bug where the interrupt handlers were not actually  
protected by
their spinlocks

Signed-off-by: Andy Fleming <afleming@freescale.com>

---

  drivers/net/gianfar.c         |   56 ++++++++++++++++ 
+-----------------
  drivers/net/gianfar.h         |   67 +++++++++++++++++++++++++++ 
+-------------
  drivers/net/gianfar_ethtool.c |   20 +++++++++---
  drivers/net/gianfar_sysfs.c   |   24 +++++++--------
  4 files changed, 100 insertions(+), 67 deletions(-)

5b638b01fefa46929a284b48e51ae36ad0c63009
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 771e25d..218d317 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -210,7 +210,8 @@ static int gfar_probe(struct platform_de
  		goto regs_fail;
  	}

-	spin_lock_init(&priv->lock);
+	spin_lock_init(&priv->txlock);
+	spin_lock_init(&priv->rxlock);

  	platform_set_drvdata(pdev, dev);

@@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev)
  	phy_stop(priv->phydev);

  	/* Lock it down */
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
+	spin_lock(&priv->rxlock);

  	gfar_halt(dev);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->rxlock);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	/* Free the IRQs */
  	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
@@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev)
  	tempval |= DMACTRL_INIT_SETTINGS;
  	gfar_write(&priv->regs->dmactrl, tempval);

-	/* Clear THLT, so that the DMA starts polling now */
-	gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
-
  	/* Make sure we aren't stopped */
  	tempval = gfar_read(&priv->regs->dmactrl);
  	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
  	gfar_write(&priv->regs->dmactrl, tempval);

+	/* Clear THLT/RHLT, so that the DMA starts polling now */
+	gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
+	gfar_write(&regs->rstat, RSTAT_CLEAR_RHALT);
+
  	/* Unmask the interrupts we look for */
  	gfar_write(&regs->imask, IMASK_DEFAULT);
  }
@@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buf
  	struct txfcb *fcb = NULL;
  	struct txbd8 *txbdp;
  	u16 status;
+	unsigned long flags;

  	/* Update transmit stats */
  	priv->stats.tx_bytes += skb->len;

  	/* Lock priv now */
-	spin_lock_irq(&priv->lock);
+	spin_lock_irqsave(&priv->txlock, flags);

  	/* Point at the first free tx descriptor */
  	txbdp = priv->cur_tx;
@@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buf
  	gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);

  	/* Unlock priv */
-	spin_unlock_irq(&priv->lock);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	return 0;
  }
@@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct
  	unsigned long flags;
  	u32 tempval;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);

  	priv->vlgrp = grp;

@@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct
  		gfar_write(&priv->regs->rctrl, tempval);
  	}

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
  }


@@ -1085,12 +1090,12 @@ static void gfar_vlan_rx_kill_vid(struct
  	struct gfar_private *priv = netdev_priv(dev);
  	unsigned long flags;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);

  	if (priv->vlgrp)
  		priv->vlgrp->vlan_devices[vid] = NULL;

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
  }


@@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq
  	gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);

  	/* Lock priv */
-	spin_lock(&priv->lock);
+	spin_lock(&priv->txlock);
  	bdp = priv->dirty_tx;
  	while ((bdp->status & TXBD_READY) == 0) {
  		/* If dirty_tx and cur_tx are the same, then either the */
@@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq
  	else
  		gfar_write(&priv->regs->txic, 0);

-	spin_unlock(&priv->lock);
+	spin_unlock(&priv->txlock);

  	return IRQ_HANDLED;
  }
@@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *
  {
  	struct net_device *dev = (struct net_device *) dev_id;
  	struct gfar_private *priv = netdev_priv(dev);
-
  #ifdef CONFIG_GFAR_NAPI
  	u32 tempval;
+#else
+	unsigned long flags;
  #endif

  	/* Clear IEVENT, so rx interrupt isn't called again
@@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *
  	}
  #else

-	spin_lock(&priv->lock);
+	spin_lock_irqsave(&priv->rxlock, flags);
  	gfar_clean_rx_ring(dev, priv->rx_ring_size);

  	/* If we are coalescing interrupts, update the timer */
@@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *
  	else
  		gfar_write(&priv->regs->rxic, 0);

-	spin_unlock(&priv->lock);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
  #endif

  	return IRQ_HANDLED;
@@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device
  	/* Update the current rxbd pointer to be the next one */
  	priv->cur_rx = bdp;

-	/* If no packets have arrived since the
-	 * last one we processed, clear the IEVENT RX and
-	 * BSY bits so that another interrupt won't be
-	 * generated when we set IMASK */
-	if (bdp->status & RXBD_EMPTY)
-		gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
-
  	return howmany;
  }

@@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *
  	rx_work_limit -= howmany;
  	*budget -= howmany;

-	if (rx_work_limit >= 0) {
+	if (rx_work_limit > 0) {
  		netif_rx_complete(dev);

  		/* Clear the halt bit in RSTAT */
@@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *
  			gfar_write(&priv->regs->rxic, 0);
  	}

-	return (rx_work_limit < 0) ? 1 : 0;
+	/* Return 1 if there's more work to do */
+	return (rx_work_limit > 0) ? 0 : 1;
  }
  #endif

@@ -1629,7 +1629,7 @@ static void adjust_link(struct net_devic
  	struct phy_device *phydev = priv->phydev;
  	int new_state = 0;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
  	if (phydev->link) {
  		u32 tempval = gfar_read(&regs->maccfg2);
  		u32 ecntrl = gfar_read(&regs->ecntrl);
@@ -1694,7 +1694,7 @@ static void adjust_link(struct net_devic
  	if (new_state && netif_msg_link(priv))
  		phy_print_status(phydev);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
  }

  /* Update the hash table based on the current list of multicast
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index d37d540..127c98c 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -656,43 +656,62 @@ struct gfar {
   * the buffer descriptor determines the actual condition.
   */
  struct gfar_private {
-	/* pointers to arrays of skbuffs for tx and rx */
+	/* Fields controlled by TX lock */
+	spinlock_t txlock;
+
+	/* Pointer to the array of skbuffs */
  	struct sk_buff ** tx_skbuff;
-	struct sk_buff ** rx_skbuff;

-	/* indices pointing to the next free sbk in skb arrays */
+	/* next free skb in the array */
  	u16 skb_curtx;
-	u16 skb_currx;

-	/* index of the first skb which hasn't been transmitted
-	 * yet. */
+	/* First skb in line to be transmitted */
  	u16 skb_dirtytx;

  	/* Configuration info for the coalescing features */
  	unsigned char txcoalescing;
  	unsigned short txcount;
  	unsigned short txtime;
+
+	/* Buffer descriptor pointers */
+	struct txbd8 *tx_bd_base;	/* First tx buffer descriptor */
+	struct txbd8 *cur_tx;	        /* Next free ring entry */
+	struct txbd8 *dirty_tx;		/* First buffer in line
+					   to be transmitted */
+	unsigned int tx_ring_size;
+
+	/* RX Locked fields */
+	spinlock_t rxlock;
+
+	/* skb array and index */
+	struct sk_buff ** rx_skbuff;
+	u16 skb_currx;
+
+	/* RX Coalescing values */
  	unsigned char rxcoalescing;
  	unsigned short rxcount;
  	unsigned short rxtime;

-	/* GFAR addresses */
-	struct rxbd8 *rx_bd_base;	/* Base addresses of Rx and Tx Buffers */
-	struct txbd8 *tx_bd_base;
+	struct rxbd8 *rx_bd_base;	/* First Rx buffers */
  	struct rxbd8 *cur_rx;           /* Next free rx ring entry */
-	struct txbd8 *cur_tx;	        /* Next free ring entry */
-	struct txbd8 *dirty_tx;		/* The Ring entry to be freed. */
-	struct gfar __iomem *regs;	/* Pointer to the GFAR memory mapped  
Registers */
-	u32 __iomem *hash_regs[16];
-	int hash_width;
-	struct net_device_stats stats; /* linux network statistics */
-	struct gfar_extra_stats extra_stats;
-	spinlock_t lock;
+
+	/* RX parameters */
+	unsigned int rx_ring_size;
  	unsigned int rx_buffer_size;
  	unsigned int rx_stash_size;
  	unsigned int rx_stash_index;
-	unsigned int tx_ring_size;
-	unsigned int rx_ring_size;
+
+	struct vlan_group *vlgrp;
+
+	/* Unprotected fields */
+	/* Pointer to the GFAR memory mapped Registers */
+	struct gfar __iomem *regs;
+
+	/* Hash registers and their width */
+	u32 __iomem *hash_regs[16];
+	int hash_width;
+
+	/* global parameters */
  	unsigned int fifo_threshold;
  	unsigned int fifo_starve;
  	unsigned int fifo_starve_off;
@@ -702,13 +721,15 @@ struct gfar_private {
  		extended_hash:1,
  		bd_stash_en:1;
  	unsigned short padding;
-	struct vlan_group *vlgrp;
-	/* Info structure initialized by board setup code */
+
  	unsigned int interruptTransmit;
  	unsigned int interruptReceive;
  	unsigned int interruptError;
+
+	/* info structure initialized by platform code */
  	struct gianfar_platform_data *einfo;

+	/* PHY stuff */
  	struct phy_device *phydev;
  	struct mii_bus *mii_bus;
  	int oldspeed;
@@ -716,6 +737,10 @@ struct gfar_private {
  	int oldlink;

  	uint32_t msg_enable;
+
+	/* Network Statistics */
+	struct net_device_stats stats;
+	struct gfar_extra_stats extra_stats;
  };

  static inline u32 gfar_read(volatile unsigned __iomem *addr)
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/ 
gianfar_ethtool.c
index 5de7b2e..d69698c 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_de

  		/* Halt TX and RX, and process the frames which
  		 * have already been received */
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
  		gfar_halt(dev);
  		gfar_clean_rx_ring(dev, priv->rx_ring_size);
-		spin_unlock_irqrestore(&priv->lock, flags);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);

  		/* Now we take down the rings to rebuild them */
  		stop_gfar(dev);
@@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_d

  		/* Halt TX and RX, and process the frames which
  		 * have already been received */
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
  		gfar_halt(dev);
  		gfar_clean_rx_ring(dev, priv->rx_ring_size);
-		spin_unlock_irqrestore(&priv->lock, flags);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);

  		/* Now we take down the rings to rebuild them */
  		stop_gfar(dev);
@@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_d
  	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
  		return -EOPNOTSUPP;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
  	gfar_halt(dev);

  	if (data)
@@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_d
  		dev->features &= ~NETIF_F_IP_CSUM;

  	gfar_start(dev);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	return 0;
  }
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 51ef181..a6d5c43 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct
  	else
  		return count;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);

  	/* Set the new stashing value */
  	priv->bd_stash_en = new_setting;
@@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct

  	gfar_write(&priv->regs->attr, temp);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);

  	return count;
  }
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(st
  	u32 temp;
  	unsigned long flags;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
  	if (length > priv->rx_buffer_size)
  		return count;

@@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(st

  	gfar_write(&priv->regs->attr, temp);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);

  	return count;
  }
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(s
  	u32 temp;
  	unsigned long flags;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
  	if (index > priv->rx_stash_size)
  		return count;

@@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(s
  	temp |= ATTRELI_EI(index);
  	gfar_write(&priv->regs->attreli, flags);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);

  	return count;
  }
@@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(s
  	if (length > GFAR_MAX_FIFO_THRESHOLD)
  		return count;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);

  	priv->fifo_threshold = length;

@@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(s
  	temp |= length;
  	gfar_write(&priv->regs->fifo_tx_thr, temp);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	return count;
  }
@@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(stru
  	if (num > GFAR_MAX_FIFO_STARVE)
  		return count;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);

  	priv->fifo_starve = num;

@@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(stru
  	temp |= num;
  	gfar_write(&priv->regs->fifo_tx_starve, temp);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	return count;
  }
@@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(
  	if (num > GFAR_MAX_FIFO_STARVE_OFF)
  		return count;

-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);

  	priv->fifo_starve_off = num;

@@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(
  	temp |= num;
  	gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);

-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);

  	return count;
  }
-- 
1.2.4

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: Window shrinking (was Linux v2.6.16-rc6)
From: Andy Furniss @ 2006-04-12 23:34 UTC (permalink / raw)
  To: Roberto Nibali
  Cc: Mark Butler, David S. Miller, michal.k.k.piotrowski, netdev
In-Reply-To: <443D7015.7080707@drugphish.ch>

Roberto Nibali wrote:

> 
> I had the distinct pleasure of partly get involved with debugging 
> network stalls related to Linux clients (2.6.x kernel) and a Packeteer.

Dare I suggest that it could be something as trivial as it looks like 
window scaling defaults to off on SunOS 2.5.1 and it's on on Linux - 
maybe packeteer can't handle it properly. Would be an easy test to turn 
it off on the Suse boxes.

Andy.

^ permalink raw reply

* Re: [RFC PATCH] softmac: (v2) send WEXT assoc/disassoc events to userspace
From: Johannes Berg @ 2006-04-12 23:56 UTC (permalink / raw)
  To: Dan Williams
  Cc: Larry Finger, netdev, softmac-dev, David Woodhouse, bcm43xx-dev
In-Reply-To: <1141936896.28038.6.camel@localhost.localdomain>

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

On Thu, 2006-03-09 at 15:41 -0500, Dan Williams wrote:

> Can you grab a debug log from wpa_supplicant?  Run wpa_supplicant with
> the args "-ddd", and _don't_ run it as a daemon.  Mail the output to me
> if you don't want it to go to everyone on the cc list (might include
> SSIDs and such).  That should allow us to figure out exactly where
> wpa_supplicant and/or the driver are having issues.

Did this ever happen? I'm currently trying to collect all the pending
patches

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* [PATCH] bcm43xx: fix dyn tssi2dbm memleak
From: Michael Buesch @ 2006-04-13  0:27 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ, Andrew Morton
  Cc: bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w, netdev-u79uwXL29TY76Z2rM5mHXA,
	Bunk, Adrian

This patch fixes a memory leak spotted by the Coverity checker.

Signed-off-by: Adrian Bunk <bunk-HeJ8Db2Gnd6zQB+pC5nmwQ@public.gmane.org>
Signed-off-by: Michael Buesch <mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>

Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_phy.c	2006-04-13 02:21:39.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c	2006-04-13 02:23:31.000000000 +0200
@@ -2151,6 +2151,7 @@
 				phy->tssi2dbm = NULL;
 				printk(KERN_ERR PFX "Could not generate "
 						    "tssi2dBm table\n");
+				kfree(dyn_tssi2dbm);
 				return -ENODEV;
 			}
 		phy->tssi2dbm = dyn_tssi2dbm;

-- 
Greetings Michael.

^ permalink raw reply

* [PATCH] bcm43xx: fix pctl slowclock limit calculation
From: Michael Buesch @ 2006-04-13  0:30 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ, Andrew Morton
  Cc: bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w, netdev-u79uwXL29TY76Z2rM5mHXA,
	Bunk, Adrian

This fixes coverity bug:
http://marc.theaimsgroup.com/?l=linux-netdev&m=114417628413880&w=2

Signed-off-by: Michael Buesch <mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>

Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_power.c	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.c	2006-04-13 02:10:17.000000000 +0200
@@ -35,77 +35,101 @@
 #include "bcm43xx_main.h"
 
 
+/* Get the Slow Clock Source */
+static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+{
+	u32 tmp;
+	int err;
+
+	assert(bcm->current_core == &bcm->core_chipcommon);
+	if (bcm->current_core->rev < 6) {
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+		    bcm->bustype == BCM43xx_BUSTYPE_SB)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+			assert(!err);
+			if (tmp & 0x10)
+				return BCM43xx_PCTL_CLKSRC_PCI;
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		}
+	}
+	if (bcm->current_core->rev < 10) {
+		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+		tmp &= 0x7;
+		if (tmp == 0)
+			return BCM43xx_PCTL_CLKSRC_LOPWROS;
+		if (tmp == 1)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (tmp == 2)
+			return BCM43xx_PCTL_CLKSRC_PCI;
+	}
+
+	return BCM43xx_PCTL_CLKSRC_XTALOS;
+}
+
 /* Get max/min slowclock frequency
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
 static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
 				       int get_max)
 {
-	int limit = 0;
+	int limit;
+	int clocksrc;
 	int divisor;
-	int selection;
-	int err;
 	u32 tmp;
-	struct bcm43xx_coreinfo *old_core;
 
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
-		goto out;
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err)
-		goto out;
+	assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+	assert(bcm->current_core == &bcm->core_chipcommon);
 
+	clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
 	if (bcm->current_core->rev < 6) {
-		if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
-			(bcm->bustype == BCM43xx_BUSTYPE_SB)) {
-			selection = 1;
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_PCI:
+			divisor = 64;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
 			divisor = 32;
-		} else {
-			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
-			if (err) {
-				printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
-				goto out_switchback;
-			}
-			if (tmp & 0x10) {
-				/* PCI */
-				selection = 2;
-				divisor = 64;
-			} else {
-				/* XTAL */
-				selection = 1;
-				divisor = 32;
-			}
+			break;
+		default:
+			assert(0);
+			divisor = 1;
 		}
 	} else if (bcm->current_core->rev < 10) {
-		selection = (tmp & 0x07);
-		if (selection) {
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_LOPWROS:
+			divisor = 1;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
+		case BCM43xx_PCTL_CLKSRC_PCI:
 			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-			divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		} else
+			divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+			divisor *= 4;
+			break;
+		default:
+			assert(0);
 			divisor = 1;
+		}
 	} else {
 		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
-		divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		selection = 1;
+		divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+		divisor *= 4;
 	}
-	
-	switch (selection) {
-	case 0:
-		/* LPO */
+
+	switch (clocksrc) {
+	case BCM43xx_PCTL_CLKSRC_LOPWROS:
 		if (get_max)
 			limit = 43000;
 		else
 			limit = 25000;
 		break;
-	case 1:
-		/* XTAL */
+	case BCM43xx_PCTL_CLKSRC_XTALOS:
 		if (get_max)
 			limit = 20200000;
 		else
 			limit = 19800000;
 		break;
-	case 2:
-		/* PCI */
+	case BCM43xx_PCTL_CLKSRC_PCI:
 		if (get_max)
 			limit = 34000000;
 		else
@@ -113,17 +137,14 @@
 		break;
 	default:
 		assert(0);
+		limit = 0;
 	}
 	limit /= divisor;
 
-out_switchback:
-	err = bcm43xx_switch_core(bcm, old_core);
-	assert(err == 0);
-
-out:
 	return limit;
 }
 
+
 /* init power control
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_power.h	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.h	2006-04-13 01:28:05.000000000 +0200
@@ -33,6 +33,15 @@
 
 #include <linux/types.h>
 
+/* Clock sources */
+enum {
+	/* PCI clock */
+	BCM43xx_PCTL_CLKSRC_PCI,
+	/* Crystal slow clock oscillator */
+	BCM43xx_PCTL_CLKSRC_XTALOS,
+	/* Low power oscillator */
+	BCM43xx_PCTL_CLKSRC_LOPWROS,
+};
 
 struct bcm43xx_private;
 

-- 
Greetings Michael.

^ permalink raw reply

* [PATCH] bcm43xx: sysfs code cleanup
From: Michael Buesch @ 2006-04-13  0:32 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ, Andrew Morton
  Cc: bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w, netdev-u79uwXL29TY76Z2rM5mHXA,
	Bunk, Adrian

This should also go in before 2.6.17

---

This cleans up the bcm43xx sysfs code and makes it compliant
with the unwritten sysfs rules (at least I hope so).

Signed-off-by: Michael Buesch <mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>

Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx.h	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h	2006-04-12 02:57:04.000000000 +0200
@@ -15,7 +15,6 @@
 
 #include "bcm43xx_debugfs.h"
 #include "bcm43xx_leds.h"
-#include "bcm43xx_sysfs.h"
 
 
 #define PFX				KBUILD_MODNAME ": "
@@ -638,8 +637,6 @@
 };
 
 struct bcm43xx_private {
-	struct bcm43xx_sysfs sysfs;
-
 	struct ieee80211_device *ieee;
 	struct ieee80211softmac_device *softmac;
 
@@ -772,6 +769,20 @@
 	return ieee80211softmac_priv(dev);
 }
 
+struct device;
+
+static inline
+struct bcm43xx_private * dev_to_bcm(struct device *dev)
+{
+	struct net_device *net_dev;
+	struct bcm43xx_private *bcm;
+
+	net_dev = dev_get_drvdata(dev);
+	bcm = bcm43xx_priv(net_dev);
+
+	return bcm;
+}
+
 
 /* Helper function, which returns a boolean.
  * TRUE, if PIO is used; FALSE, if DMA is used.
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c	2006-04-12 02:12:39.000000000 +0200
@@ -52,6 +52,7 @@
 #include "bcm43xx_wx.h"
 #include "bcm43xx_ethtool.h"
 #include "bcm43xx_xmit.h"
+#include "bcm43xx_sysfs.h"
 
 
 MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c	2006-04-12 03:21:55.000000000 +0200
@@ -71,14 +71,46 @@
 	return -EINVAL;
 }
 
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+{
+	int i, pos = 0;
+
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		pos += snprintf(buf + pos, buf_len - pos - 1,
+				"%04X", swab16(sprom[i]) & 0xFFFF);
+	}
+	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+
+	return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+{
+	char tmp[5] = { 0 };
+	int cnt = 0;
+	unsigned long parsed;
+
+	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+		return -EINVAL;
+
+	while (cnt < BCM43xx_SPROM_SIZE) {
+		memcpy(tmp, dump, 4);
+		dump += 4;
+		parsed = simple_strtoul(tmp, NULL, 16);
+		sprom[cnt++] = swab16((u16)parsed);
+	}
+
+	return 0;
+}
+
 static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -91,55 +123,53 @@
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_read(bcm, sprom);
-	if (!err) {
-		for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-			buf[i * 2] = sprom[i] & 0x00FF;
-			buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
-		}
-	}
+	if (!err)
+		err = sprom2hex(sprom, buf, PAGE_SIZE);
 	bcm43xx_unlock_mmio(bcm, flags);
 	kfree(sprom);
 
-	return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
+	return err;
 }
 
 static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
-		return -EINVAL;
 	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-		sprom[i] = buf[i * 2] & 0xFF;
-		sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
-	}
+	err = hex2sprom(sprom, buf, count);
+	if (err)
+		goto out_kfree;
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_write(bcm, sprom);
 	bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
 	kfree(sprom);
 
 	return err ? err : count;
 
 }
 
+static DEVICE_ATTR(sprom, 0600,
+		   bcm43xx_attr_sprom_show,
+		   bcm43xx_attr_sprom_store);
+
 static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
 					    struct device_attribute *attr,
 					    char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count = 0;
@@ -175,7 +205,7 @@
 					     struct device_attribute *attr,
 					     const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int mode;
@@ -215,11 +245,15 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(interference, 0644,
+		   bcm43xx_attr_interfmode_show,
+		   bcm43xx_attr_interfmode_store);
+
 static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count;
@@ -245,7 +279,7 @@
 					   struct device_attribute *attr,
 					   const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int value;
@@ -267,56 +301,41 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(shortpreamble, 0644,
+		   bcm43xx_attr_preamble_show,
+		   bcm43xx_attr_preamble_store);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 	int err;
 
 	assert(bcm->initialized);
 
-	sysfs->attr_sprom.attr.name = "sprom";
-	sysfs->attr_sprom.attr.owner = THIS_MODULE;
-	sysfs->attr_sprom.attr.mode = 0600;
-	sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
-	sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
-	err = device_create_file(dev, &sysfs->attr_sprom);
+	err = device_create_file(dev, &dev_attr_sprom);
 	if (err)
 		goto out;
-
-	sysfs->attr_interfmode.attr.name = "interference";
-	sysfs->attr_interfmode.attr.owner = THIS_MODULE;
-	sysfs->attr_interfmode.attr.mode = 0600;
-	sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
-	sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
-	err = device_create_file(dev, &sysfs->attr_interfmode);
+	err = device_create_file(dev, &dev_attr_interference);
 	if (err)
 		goto err_remove_sprom;
-
-	sysfs->attr_preamble.attr.name = "shortpreamble";
-	sysfs->attr_preamble.attr.owner = THIS_MODULE;
-	sysfs->attr_preamble.attr.mode = 0600;
-	sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
-	sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
-	err = device_create_file(dev, &sysfs->attr_preamble);
+	err = device_create_file(dev, &dev_attr_shortpreamble);
 	if (err)
 		goto err_remove_interfmode;
 
 out:
 	return err;
 err_remove_interfmode:
-	device_remove_file(dev, &sysfs->attr_interfmode);
+	device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_sprom);
 	goto out;
 }
 
 void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 
-	device_remove_file(dev, &sysfs->attr_preamble);
-	device_remove_file(dev, &sysfs->attr_interfmode);
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_shortpreamble);
+	device_remove_file(dev, &dev_attr_interference);
+	device_remove_file(dev, &dev_attr_sprom);
 }
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h	2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h	2006-04-12 02:12:39.000000000 +0200
@@ -1,22 +1,6 @@
 #ifndef BCM43xx_SYSFS_H_
 #define BCM43xx_SYSFS_H_
 
-#include <linux/device.h>
-
-
-struct bcm43xx_sysfs {
-	struct device_attribute attr_sprom;
-	struct device_attribute attr_interfmode;
-	struct device_attribute attr_preamble;
-};
-
-#define devattr_to_bcm(attr, attr_name)	({				\
-	struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p;		\
-	__s = container_of((attr), struct bcm43xx_sysfs, attr_name);	\
-	__p = container_of(__s, struct bcm43xx_private, sysfs);		\
-	__p;								\
-					})
-
 struct bcm43xx_private;
 
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);

-- 
Greetings Michael.

^ permalink raw reply

* [patch 4] softmac: fix event sending
From: Johannes Berg @ 2006-04-13  0:42 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville
In-Reply-To: <20060411085805.949313000@sipsolutions.net>

Softmac is sending custom events to userspace already, but it
should _really_ be sending the right WEXT events instead. This
patch fixes that.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

Index: wireless-2.6/include/net/ieee80211softmac.h
===================================================================
--- wireless-2.6.orig/include/net/ieee80211softmac.h	2006-04-13 02:35:54.686229309 +0200
+++ wireless-2.6/include/net/ieee80211softmac.h	2006-04-13 02:37:17.676229309 +0200
@@ -267,8 +267,9 @@
 #define IEEE80211SOFTMAC_EVENT_AUTH_FAILED		5
 #define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT		6
 #define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND	7
+#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED		8
 /* keep this updated! */
-#define IEEE80211SOFTMAC_EVENT_LAST			7
+#define IEEE80211SOFTMAC_EVENT_LAST			8
 /*
  * If you want to be notified of certain events, you can call
  * ieee80211softmac_notify[_atomic] with
Index: wireless-2.6/net/ieee80211/softmac/ieee80211softmac_assoc.c
===================================================================
--- wireless-2.6.orig/net/ieee80211/softmac/ieee80211softmac_assoc.c	2006-04-13 02:35:54.686229309 +0200
+++ wireless-2.6/net/ieee80211/softmac/ieee80211softmac_assoc.c	2006-04-13 02:37:17.686229309 +0200
@@ -101,6 +101,7 @@
 	/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
 	mac->associated = 0;
 	mac->associnfo.associating = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -373,6 +374,7 @@
 	spin_lock_irqsave(&mac->lock, flags);
 	mac->associnfo.bssvalid = 0;
 	mac->associated = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	schedule_work(&mac->associnfo.work);
 	spin_unlock_irqrestore(&mac->lock, flags);
 	
Index: wireless-2.6/net/ieee80211/softmac/ieee80211softmac_event.c
===================================================================
--- wireless-2.6.orig/net/ieee80211/softmac/ieee80211softmac_event.c	2006-04-13 02:35:54.686229309 +0200
+++ wireless-2.6/net/ieee80211/softmac/ieee80211softmac_event.c	2006-04-13 02:38:51.036229309 +0200
@@ -67,6 +67,7 @@
 	"authenticating failed",
 	"authenticating timed out",
 	"associating failed because no suitable network was found",
+	"disassociated",
 };
 
 
@@ -128,13 +129,36 @@
 ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
 {
 	struct ieee80211softmac_event *eventptr, *tmp;
-	union iwreq_data wrqu;
-	char *msg;
+	struct ieee80211softmac_network *network;
 	
 	if (event >= 0) {
-		msg = event_descriptions[event];
-		wrqu.data.length = strlen(msg);
-		wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
+		union iwreq_data wrqu;
+		int we_event;
+		char *msg = NULL;
+
+		switch(event) {
+		case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+			network = (struct ieee80211softmac_network *)event_ctx;
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memset(&wrqu, '\0', sizeof (union iwreq_data));
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		default:
+			msg = event_descriptions[event];
+			wrqu.data.length = strlen(msg);
+			we_event = IWEVCUSTOM;
+			break;
+		}
+		wireless_send_event(mac->dev, we_event, &wrqu, msg);
 	}
 
 	if (!list_empty(&mac->events))



^ permalink raw reply

* Re: [RFD][PATCH] typhoon and core sample for folding away VLAN stuff
From: Dave Dillow @ 2006-04-13  1:24 UTC (permalink / raw)
  To: Ingo Oeser
  Cc: Ingo Oeser, Denis Vlasenko, netdev, David S. Miller, linux-kernel,
	jgarzik
In-Reply-To: <200604122132.46113.ioe-lkml@rameria.de>

Ingo Oeser wrote:
> Dave Dillow: Is this style clean enough to have it in your driver?

Though I'm not real fond of Denis's last patch, I think I prefer it's 
style to this, solely because it removes more code when VLANs are 
disabled -- you've left the spin_locks in, and have more #ifdefs.

Regardless, I remain opposed to this particular instance of bloat 
busting. While both patches have improved in style, they remove a useful 
feature and make the code less clean, for no net gain.

> This kind of changes are important, because bloat creeps in byte by byte
> of unused features. So I really appreciate your work here Denis.

On SMP FC4, typhoon.ko has a text size of 68330, so you need to cut 2794 
bytes to see an actual difference in memory usage for a module. Non-SMP 
it is 67741, so there you only need to cut 2205 bytes to get a win.

Every byte counts, except when it doesn't.


^ permalink raw reply

* help needed in n/w
From: varun @ 2006-04-13  3:19 UTC (permalink / raw)
  To: netdev

Hi all,

            Iam new to netfilters and iam trying to play around to 
understand a few things. By default when no policies are specified then 
it allows all traffic to go out and in to the n/w. I want to change this 
to default as deny.
            That is when there is no policy all should be default deny.

          So in order to achieve that i tried to change the  code a little.
           In the file iptable_filter.c there is a variable called 
static int forward = NF_ACCEPT
            I changed this to NF_DROP and when i compiled and used it 
sure i was not able to send any or recv any packets
            but even after i give a policy like iptables -t filter -A 
INPUT -j ACCEPT
            Nothing changes. So achieve what i want what should i do? 
And where do i change?

            Another thing is that in normally when i put a policy like 
iptables -t filter -A OUTPUT -j REJECT
             Even my own self IP doesnt ping? Why should this happen?
              Isint it ok to ping local ip and loopback ip?
               If i want such implementation where i should be able to 
ping to self and local but not any other ip?
               Is it possible?
               I dont want to add policies rather is it possible just by 
changing the iptables kernel code?

               Please help me on this?

Varun

^ permalink raw reply

* Re: [PATCH] deinline a few large functions in vlan code v2
From: Denis Vlasenko @ 2006-04-13  6:04 UTC (permalink / raw)
  To: Dave Dillow; +Cc: netdev, David S. Miller, linux-kernel, jgarzik
In-Reply-To: <1144862325.18319.32.camel@dillow.idleaire.com>

On Wednesday 12 April 2006 20:18, Dave Dillow wrote:
> > > or loaded. And even if it saves 200 bytes in one 
> > > module, unless that module text was already less than 200 bytes into a
> > > page, you've saved no memory -- a 4300 byte module takes 2 pages on x86,
> > > as does a 4100 byte module.
> > 
> > Sometimes, those 200 bytes can bring module size just under 4096.
> > Thus on the average, on many modules you get the same size savings
> > as on built-in code. (Not that we have THAT many network modules...)
> 
> You're making a bogus leap from "sometimes" to "average".

It's not bogus. See below.

> Assuming an even distribution of lengths mod 4096, less than 5% of the
> time will 200 bytes save any memory on a module.

Ok, imagine perfect module size distribution, and suppose we shave 204
bytes off each module. 5% of the modules will have their size reduced
so that they occupy one 4k page less.

Those 5% of modules will have their RAM footprint reduced not
by just 204 bytes, but by 4096 bytes.

Total RAM footprint of all modules, in kb (N=number of modules):
before: sum_of_orig_module_size
after, modular: sum_of_orig_module_size - 0.05*N * 4096
after, builtin: sum_of_orig_module_size - N * 204

0.05*4096 = 204.53

> I don't like "VLAN_ENABLED" as a global define -- it looks too much like
> something local. The CONFIG_VLAN... defines were more descriptive.

That will require Kconfig changes. Maybe you would like "VLAN_ENABLED_KERNER"
name? It doesn't sound local...

> I didn't think about this before, but I'm pretty sure you're taking away
> functionality. When I wrote the typhoon driver, ISTR that I looked
> through the vlan implantation, and determined that all the #ifdefs on
> CONFIG_VLAN_8021Q were not really needed, since all the hooks were
> there. You could just load the 8021q module (even perhaps building it at
> a later date), and it would work if you had filled in the hooks in
> struct net_device. So I didn't #ifdef out code in my driver to let the
> user have the option.

IOW: currently most of VLAN code is already in kernel.
Then why do we have VLAN as a config option? Let's make it unconditional
(will add only 10k to core kernel)?

# size net/8021q/8021q.o
   text    data     bss     dec     hex filename
   9379     484     136    9999    270f net/8021q/8021q.o

> You're taking that away in the name of a total of 5K, which most users
> won't actually get back?

It started as a kernel-wide audit for huge inlines, I was not aiming
at VLAN particularly. But yes, when I saw other (not related to inlines)
opportunities to make code smaller, I decided to do it.

You know, people say that even Linux is getting fat these days.
--
vda

^ permalink raw reply

* Re: [RFD][PATCH] typhoon and core sample for folding away VLAN stuff
From: Denis Vlasenko @ 2006-04-13  8:38 UTC (permalink / raw)
  To: Dave Dillow
  Cc: Ingo Oeser, Ingo Oeser, netdev, David S. Miller, linux-kernel,
	jgarzik
In-Reply-To: <443DA830.8030209@thedillows.org>

On Thursday 13 April 2006 04:24, Dave Dillow wrote:
> Regardless, I remain opposed to this particular instance of bloat 
> busting. While both patches have improved in style, they remove a useful 
> feature and make the code less clean, for no net gain.

What happened to non-modular build? "no net gain" is not true.
 
> > This kind of changes are important, because bloat creeps in byte by byte
> > of unused features. So I really appreciate your work here Denis.
> 
> On SMP FC4, typhoon.ko has a text size of 68330, so you need to cut 2794 
> bytes to see an actual difference in memory usage for a module. Non-SMP 
> it is 67741, so there you only need to cut 2205 bytes to get a win.

This is silly. Should I go this route and try a dozen of different gcc
versions and "-O2 versus -Os" things to demonstrate that sometimes
it will matter?
--
vda

^ permalink raw reply

* Re: [patch 1/3] softmac: return -EAGAIN from getscan while scanning
From: Pete Zaitcev @ 2006-04-13  9:00 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linville
In-Reply-To: <20060411085841.252064000@sipsolutions.net>

On Tue, 11 Apr 2006 10:58:06 +0200, johannes@sipsolutions.net wrote:

> Below patch was developed after discussion with Daniel Drake who
> mentioned to me that wireless tools expect an EAGAIN return from getscan
> so that they can wait for the scan to finish before printing out the
> results.

This sounds completely wrong. Do you guys remember the Subject: string
of this discussion by any chance?

It's very likely that tools do indeed loop when they see EAGAIN, but
this is a workaround, not the main mode of operation. It seems obvious
to me that the get method should wait until the scan results are
available. Perhaps the discussion had a specific scenario where
EAGAIN would make sense, but I cannot imagine what it might be.

-- Pete

^ permalink raw reply

* Re: [patch 1/3] softmac: return -EAGAIN from getscan while scanning
From: Johannes Berg @ 2006-04-13  9:06 UTC (permalink / raw)
  To: Pete Zaitcev; +Cc: netdev, linville, softmac-dev, Jean Tourrilhes
In-Reply-To: <20060413020010.2ab16d7b.zaitcev@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 765 bytes --]

On Thu, 2006-04-13 at 02:00 -0700, Pete Zaitcev wrote:

> This sounds completely wrong. Do you guys remember the Subject: string
> of this discussion by any chance?

Discussed offline at the wireless summit, sorry.

> It's very likely that tools do indeed loop when they see EAGAIN, but
> this is a workaround, not the main mode of operation. It seems obvious
> to me that the get method should wait until the scan results are
> available. Perhaps the discussion had a specific scenario where
> EAGAIN would make sense, but I cannot imagine what it might be.

Right, they do loop, but they don't have a method to indicate
completion. Thus we'd have to actually wait for the completion in the
kernel. Jean, what is the intended use here?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* [PATCH] ipw2100: wraps the debug module param within #ifdefs
From: Zhu Yi @ 2006-04-13  9:14 UTC (permalink / raw)
  To: netdev, John W. Linville

Signed-off-by: Henrik Brix Andersen <brix@gentoo.org>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 drivers/net/wireless/ipw2100.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

e78cfdab91a809722be99c06574d2e0a60467644
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 72335c8..2cd32a4 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -184,7 +184,9 @@ MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_IPW2100_DEBUG
 static int debug = 0;
+#endif
 static int mode = 0;
 static int channel = 0;
 static int associate = 1;
@@ -194,13 +196,17 @@ static struct ipw2100_fw ipw2100_firmwar
 #endif
 
 #include <linux/moduleparam.h>
+#ifdef CONFIG_IPW2100_DEBUG
 module_param(debug, int, 0444);
+#endif
 module_param(mode, int, 0444);
 module_param(channel, int, 0444);
 module_param(associate, int, 0444);
 module_param(disable, int, 0444);
 
+#ifdef CONFIG_IPW2100_DEBUG
 MODULE_PARM_DESC(debug, "debug level");
+#endif
 MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
 MODULE_PARM_DESC(channel, "channel");
 MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
-- 
1.2.6


^ permalink raw reply related

* [PATCH 0/6] ieee80211 updates
From: Zhu Yi @ 2006-04-13  9:16 UTC (permalink / raw)
  To: netdev, John W. Linville

Hi,

Here are some patches for ieee80211, please apply.


[PATCH 1/6] ieee80211: Fix TKIP MIC calculation for QoS frames
[PATCH 2/6] ieee80211: Fix TX code doesn't enable QoS when using WPA + QoS
[PATCH 3/6] ieee80211: export list of bit rates with standard WEXT procdures
[PATCH 4/6] ieee80211: remove unnecessary CONFIG_WIRELESS_EXT checking
[PATCH 5/6] ieee80211: replace debug IEEE80211_WARNING with each own debug macro
[PATCH 6/6] ieee80211: update version stamp to 1.1.13

Thanks,
-yi

^ permalink raw reply

* [PATCH 1/6] ieee80211: Fix TKIP MIC calculation for QoS frames
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

Fix TKIP MIC verification failure when receiving QoS frames from AP.

Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 include/net/ieee80211.h              |    3 +++
 net/ieee80211/ieee80211_crypt_tkip.c |   11 ++++++++++-
 2 files changed, 13 insertions(+), 1 deletions(-)

2a0ee963da3c8a125e2af4dec07aca8bf4357d03
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4725ff8..66dc136 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -104,6 +104,9 @@
 #define IEEE80211_SCTL_FRAG		0x000F
 #define IEEE80211_SCTL_SEQ		0xFFF0
 
+/* QOS control */
+#define IEEE80211_QCTL_TID		0x000F
+
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 93def94..3fa5df2 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -501,8 +501,11 @@ static int michael_mic(struct ieee80211_
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
 	struct ieee80211_hdr_4addr *hdr11;
+	u16 stype;
 
 	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
+	stype  = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
+
 	switch (le16_to_cpu(hdr11->frame_ctl) &
 		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
 	case IEEE80211_FCTL_TODS:
@@ -523,7 +526,13 @@ static void michael_mic_hdr(struct sk_bu
 		break;
 	}
 
-	hdr[12] = 0;		/* priority */
+	if (stype & IEEE80211_STYPE_QOS_DATA) {
+		const struct ieee80211_hdr_3addrqos *qoshdr =
+			(struct ieee80211_hdr_3addrqos *)skb->data;
+		hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
+	} else
+		hdr[12] = 0;		/* priority */
+
 	hdr[13] = hdr[14] = hdr[15] = 0;	/* reserved */
 }
 
-- 
1.2.6


^ permalink raw reply related

* [PATCH 2/6] ieee80211: Fix TX code doesn't enable QoS when using WPA + QoS
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

Fix ieee80211 TX code when using WPA+QOS. TKIP/CCMP will use
the TID field of qos_ctl in 802.11 frame header to do encryption. We
cannot ignore this field when doing host encryption and add the qos_ctl
field later.

Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 include/net/ieee80211.h      |    1 +
 net/ieee80211/ieee80211_tx.c |   63 ++++++++++++++++++++++++++++++++++--------
 2 files changed, 52 insertions(+), 12 deletions(-)

809115bccebe1ccae12c66466dad2c3d6874ac8b
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 66dc136..bc6bdd6 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1076,6 +1076,7 @@ struct ieee80211_device {
 
 	int (*handle_management) (struct net_device * dev,
 				  struct ieee80211_network * network, u16 type);
+	int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
 
 	/* Typical STA methods */
 	int (*handle_auth) (struct net_device * dev,
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 8b4332f..233d527 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -220,13 +220,43 @@ static struct ieee80211_txb *ieee80211_a
 	return txb;
 }
 
+static int ieee80211_classify(struct sk_buff *skb)
+{
+	struct ethhdr *eth;
+	struct iphdr *ip;
+
+	eth = (struct ethhdr *)skb->data;
+	if (eth->h_proto != __constant_htons(ETH_P_IP))
+		return 0;
+
+	ip = skb->nh.iph;
+	switch (ip->tos & 0xfc) {
+	case 0x20:
+		return 2;
+	case 0x40:
+		return 1;
+	case 0x60:
+		return 3;
+	case 0x80:
+		return 4;
+	case 0xa0:
+		return 5;
+	case 0xc0:
+		return 6;
+	case 0xe0:
+		return 7;
+	default:
+		return 0;
+	}
+}
+
 /* Incoming skb is converted to a txb which consists of
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
-	struct ieee80211_hdr_3addr *frag_hdr;
+	struct ieee80211_hdr_3addrqos *frag_hdr;
 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
 	    rts_required;
 	unsigned long flags;
@@ -234,9 +264,10 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
-	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
+	struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
 		.duration_id = 0,
-		.seq_ctl = 0
+		.seq_ctl = 0,
+		.qos_ctl = 0
 	};
 	u8 dest[ETH_ALEN], src[ETH_ALEN];
 	struct ieee80211_crypt_data *crypt;
@@ -282,12 +313,6 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	memcpy(dest, skb->data, ETH_ALEN);
 	memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
 
-	/* Advance the SKB to the start of the payload */
-	skb_pull(skb, sizeof(struct ethhdr));
-
-	/* Determine total amount of storage required for TXB packets */
-	bytes = skb->len + SNAP_SIZE + sizeof(u16);
-
 	if (host_encrypt || host_build_iv)
 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
 		    IEEE80211_FCTL_PROTECTED;
@@ -306,9 +331,23 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		memcpy(header.addr2, src, ETH_ALEN);
 		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
 	}
-	header.frame_ctl = cpu_to_le16(fc);
 	hdr_len = IEEE80211_3ADDR_LEN;
 
+	if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
+		fc |= IEEE80211_STYPE_QOS_DATA;
+		hdr_len += 2;
+
+		skb->priority = ieee80211_classify(skb);
+		header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID;
+	}
+	header.frame_ctl = cpu_to_le16(fc);
+
+	/* Advance the SKB to the start of the payload */
+	skb_pull(skb, sizeof(struct ethhdr));
+
+	/* Determine total amount of storage required for TXB packets */
+	bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
 	/* Encrypt msdu first on the whole data packet. */
 	if ((host_encrypt || host_encrypt_msdu) &&
 	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
@@ -402,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	if (rts_required) {
 		skb_frag = txb->fragments[0];
 		frag_hdr =
-		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+		    (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
 
 		/*
 		 * Set header frame_ctl to the RTS.
@@ -433,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 				    crypt->ops->extra_mpdu_prefix_len);
 
 		frag_hdr =
-		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+		    (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
 		memcpy(frag_hdr, &header, hdr_len);
 
 		/* If this is not the last fragment, then add the MOREFRAGS
-- 
1.2.6


^ permalink raw reply related

* [PATCH 3/6] ieee80211: export list of bit rates with standard WEXT procddures
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

The patch replace the way to export the list of bit rates in scan results
from IWEVCUSTOM to SIOCGIWRATE. It also removes the max_rate item exported
with SIOCGIWRATE since this should be done by userspace.

Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 net/ieee80211/ieee80211_wx.c |   44 ++++++++++++++++++++----------------------
 1 files changed, 21 insertions(+), 23 deletions(-)

d0da9825b30b4db3df3bbe2718e220f4119e0b64
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index b885fd1..0ea55cb 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -50,7 +50,8 @@ static char *ieee80211_translate_scan(st
 	char *p;
 	struct iw_event iwe;
 	int i, j;
-	u8 max_rate, rate;
+	char *current_val;	/* For rates */
+	u8 rate;
 
 	/* First entry *MUST* be the AP MAC address */
 	iwe.cmd = SIOCGIWAP;
@@ -107,9 +108,13 @@ static char *ieee80211_translate_scan(st
 	start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
 
 	/* Add basic and extended rates */
-	max_rate = 0;
-	p = custom;
-	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+	/* Rate : stuffing multiple values in a single event require a bit
+	 * more of magic - Jean II */
+	current_val = start + IW_EV_LCP_LEN;
+	iwe.cmd = SIOCGIWRATE;
+	/* Those two flags are ignored... */
+	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
 	for (i = 0, j = 0; i < network->rates_len;) {
 		if (j < network->rates_ex_len &&
 		    ((network->rates_ex[j] & 0x7F) <
@@ -117,28 +122,21 @@ static char *ieee80211_translate_scan(st
 			rate = network->rates_ex[j++] & 0x7F;
 		else
 			rate = network->rates[i++] & 0x7F;
-		if (rate > max_rate)
-			max_rate = rate;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+		/* Add new value to event */
+		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	for (; j < network->rates_ex_len; j++) {
 		rate = network->rates_ex[j] & 0x7F;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
-		if (rate > max_rate)
-			max_rate = rate;
-	}
-
-	iwe.cmd = SIOCGIWRATE;
-	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-	iwe.u.bitrate.value = max_rate * 500000;
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
-
-	iwe.cmd = IWEVCUSTOM;
-	iwe.u.data.length = p - custom;
-	if (iwe.u.data.length)
-		start = iwe_stream_add_point(start, stop, &iwe, custom);
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+		/* Add new value to event */
+		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
+	}
+	/* Check if we added any rate */
+	if((current_val - start) > IW_EV_LCP_LEN)
+		start = current_val;
 
 	/* Add quality statistics */
 	iwe.cmd = IWEVQUAL;
-- 
1.2.6


^ permalink raw reply related

* [PATCH 4/6] ieee80211: remove unnecessary CONFIG_WIRELESS_EXT checking
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 net/ieee80211/ieee80211_rx.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

06f3e8b703c93ff8dbadf005878850fcd3393e5f
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 604b7b0..0d18742 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -369,7 +369,6 @@ int ieee80211_rx(struct ieee80211_device
 
 	/* Put this code here so that we avoid duplicating it in all
 	 * Rx paths. - Jean II */
-#ifdef CONFIG_WIRELESS_EXT
 #ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
 	/* If spy monitoring on */
 	if (ieee->spy_data.spy_number > 0) {
@@ -398,7 +397,6 @@ int ieee80211_rx(struct ieee80211_device
 		wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
 	}
 #endif				/* IW_WIRELESS_SPY */
-#endif				/* CONFIG_WIRELESS_EXT */
 
 #ifdef NOT_YET
 	hostap_update_rx_stats(local->ap, hdr, rx_stats);
-- 
1.2.6


^ permalink raw reply related

* [PATCH 5/6] ieee80211: replace debug IEEE80211_WARNING with each own debug macro
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 net/ieee80211/ieee80211_rx.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

7a5148115c33ea94ff352a305ad2b2646a573219
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 0d18742..2bf567f 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1690,8 +1690,8 @@ void ieee80211_rx_mgt(struct ieee80211_d
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
-		IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
-				  ieee->dev->name);
+		IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n",
+				     ieee->dev->name);
 		if (ieee->handle_reassoc_request != NULL)
 			ieee->handle_reassoc_request(ieee->dev,
 						    (struct ieee80211_reassoc_request *)
@@ -1703,8 +1703,8 @@ void ieee80211_rx_mgt(struct ieee80211_d
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
-		IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
-				  ieee->dev->name);
+		IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n",
+				     ieee->dev->name);
 		if (ieee->handle_assoc_request != NULL)
 			ieee->handle_assoc_request(ieee->dev);
 		break;
@@ -1720,10 +1720,10 @@ void ieee80211_rx_mgt(struct ieee80211_d
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
-		IEEE80211_WARNING("%s: Unknown management packet: %d\n",
-				  ieee->dev->name,
-				  WLAN_FC_GET_STYPE(le16_to_cpu
-						    (header->frame_ctl)));
+		IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n",
+				     ieee->dev->name,
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		break;
 	}
 }
-- 
1.2.6


^ permalink raw reply related

* [PATCH 6/6] ieee80211: update version stamp to 1.1.13
From: Zhu Yi @ 2006-04-13  9:17 UTC (permalink / raw)
  To: netdev, John W. Linville

Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 include/net/ieee80211.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

ad81572a2505f80d22a1ceae5c055966e92df09f
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index bc6bdd6..4087dfc 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
-#define IEEE80211_VERSION "git-1.1.7"
+#define IEEE80211_VERSION "git-1.1.13"
 
 #define IEEE80211_DATA_LEN		2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
-- 
1.2.6


^ permalink raw reply related

* [PATCH 00/18] ipw2200 driver updates
From: Zhu Yi @ 2006-04-13  9:18 UTC (permalink / raw)
  To: netdev, John W. Linville

Hi,

The following patches are ipw2200 driver recently update. Please apply.


[PATCH 01/18] ipw2200: Exponential averaging for signal and noise Level
[PATCH 02/18] ipw2200: Fix TX QoS enabled frames problem
[PATCH 03/18] ipw2200: generates a scan event after a scan has completed
[PATCH 04/18] ipw2200: add module_param support for antenna selection
[PATCH 05/18] ipw2200: fix compile warning when !CONFIG_IPW2200_DEBUG
[PATCH 06/18] ipw2200: Do not continue loading the firmware if kmalloc fails
[PATCH 07/18] ipw2200: turn off signal debug log
[PATCH 08/18] ipw2200: Set the 'fixed' flags in wext get_rate
[PATCH 09/18] ipw2200: Fix endian issues with v3.0 fw image format
[PATCH 10/18] README.ipw2200: rename CONFIG_IPW_DEBUG to CONFIG_IPW2200_DEBUG
[PATCH 11/18] ipw2200: Enable rtap interface for RF promiscuous mode while associated
[PATCH 12/18] ipw2200: version string rework
[PATCH 13/18] ipw2200: update version stamp to 1.1.2
[PATCH 14/18] ipw2200: rename CONFIG_IPW_QOS to CONFIG_IPW2200_QOS
[PATCH 15/18] wireless Kconfig add IPW2200_RADIOTAP
[PATCH 16/18] ipw2200: rename CONFIG_IEEE80211_RADIOTAP to CONFIG_IPW2200_RADIOTAP
[PATCH 17/18] ipw2200: remove priv->last_noise reference
[PATCH 18/18] ipw2200: Fix wpa_supplicant association problem


Thanks,
-yi

^ permalink raw reply

* [PATCH 01/18] ipw2200: Exponential averaging for signal and noise Level
From: Zhu Yi @ 2006-04-13  9:19 UTC (permalink / raw)
  To: netdev, John W. Linville

This patch replaces sliding averaging by exponential averaging for
reporting the wireless statistics for signal and noise level for ipw2200.
See details from: http://www.ces.clemson.edu/linux/ipw2200_averages.shtml

Signed-off-by: Bill Moss <bmoss@clemson.edu>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 drivers/net/wireless/ipw2200.c |   34 ++++++++++++++++++++--------------
 drivers/net/wireless/ipw2200.h |    6 ++----
 2 files changed, 22 insertions(+), 18 deletions(-)

1864e427f7b49b5dc9e419f2c6b02ea8b682ead7
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522..77caeac 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -3771,6 +3771,13 @@ static void inline average_init(struct a
 	memset(avg, 0, sizeof(*avg));
 }
 
+#define DEPTH_RSSI 8
+#define DEPTH_NOISE 16
+static s16 exponential_average(s16 prev_avg, s16 val, u8 depth)
+{
+	return ((depth-1)*prev_avg +  val)/depth;
+}
+
 static void average_add(struct average *avg, s16 val)
 {
 	avg->sum -= avg->entries[avg->pos];
@@ -3800,8 +3807,8 @@ static void ipw_reset_stats(struct ipw_p
 	priv->quality = 0;
 
 	average_init(&priv->average_missed_beacons);
-	average_init(&priv->average_rssi);
-	average_init(&priv->average_noise);
+	priv->exp_avg_rssi = -60;
+	priv->exp_avg_noise = -85 + 0x100;
 
 	priv->last_rate = 0;
 	priv->last_missed_beacons = 0;
@@ -4008,7 +4015,7 @@ static void ipw_gather_stats(struct ipw_
 	IPW_DEBUG_STATS("Tx quality   : %3d%% (%u errors, %u packets)\n",
 			tx_quality, tx_failures_delta, tx_packets_delta);
 
-	rssi = average_value(&priv->average_rssi);
+	rssi = priv->exp_avg_rssi;
 	signal_quality =
 	    (100 *
 	     (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
@@ -4023,7 +4030,7 @@ static void ipw_gather_stats(struct ipw_
 	else if (signal_quality < 1)
 		signal_quality = 0;
 
-	IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
+	IPW_ERROR("Signal level : %3d%% (%d dBm)\n",
 			signal_quality, rssi);
 
 	quality = min(beacon_quality,
@@ -4577,11 +4584,10 @@ static void ipw_rx_notification(struct i
 
 	case HOST_NOTIFICATION_NOISE_STATS:{
 			if (notif->size == sizeof(u32)) {
-				priv->last_noise =
-				    (u8) (le32_to_cpu(notif->u.noise.value) &
-					  0xff);
-				average_add(&priv->average_noise,
-					    priv->last_noise);
+				priv->exp_avg_noise =
+				    exponential_average(priv->exp_avg_noise,
+				    (u8) (le32_to_cpu(notif->u.noise.value) & 0xff),
+				    DEPTH_NOISE);
 				break;
 			}
 
@@ -7840,9 +7846,9 @@ static void ipw_rx(struct ipw_priv *priv
 				if (network_packet && priv->assoc_network) {
 					priv->assoc_network->stats.rssi =
 					    stats.rssi;
-					average_add(&priv->average_rssi,
-						    stats.rssi);
-					priv->last_rx_rssi = stats.rssi;
+					priv->exp_avg_rssi =
+					    exponential_average(priv->exp_avg_rssi,
+					    stats.rssi, DEPTH_RSSI);
 				}
 
 				IPW_DEBUG_RX("Frame: len=%u\n",
@@ -9582,8 +9588,8 @@ static struct iw_statistics *ipw_get_wir
 	}
 
 	wstats->qual.qual = priv->quality;
-	wstats->qual.level = average_value(&priv->average_rssi);
-	wstats->qual.noise = average_value(&priv->average_noise);
+	wstats->qual.level = priv->exp_avg_rssi;
+	wstats->qual.noise = priv->exp_avg_noise;
 	wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
 	    IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;
 
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 4b98049..1f2cab3 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1153,11 +1153,9 @@ struct ipw_priv {
 	u32 config;
 	u32 capability;
 
-	u8 last_rx_rssi;
-	u8 last_noise;
 	struct average average_missed_beacons;
-	struct average average_rssi;
-	struct average average_noise;
+	s16 exp_avg_rssi;
+	s16 exp_avg_noise;
 	u32 port_type;
 	int rx_bufs_min;	  /**< minimum number of bufs in Rx queue */
 	int rx_pend_max;	  /**< maximum pending buffers for one IRQ */
-- 
1.2.6


^ permalink raw reply related

* [PATCH 02/18] ipw2200: Fix TX QoS enabled frames problem
From: Zhu Yi @ 2006-04-13  9:19 UTC (permalink / raw)
  To: netdev, John W. Linville

This patch works with the ieee80211 stack to set the correct QoS bit to the
ipw2200 card. It fixed the TX failure problem for using WPA with QoS.

Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 drivers/net/wireless/ipw2200.c |   71 +++++++++++++++++++---------------------
 1 files changed, 33 insertions(+), 38 deletions(-)

3c5ca65d97d901329cf04807d51cf854f6385755
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 77caeac..a4d8d49 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -6862,61 +6862,55 @@ static int ipw_get_tx_queue_number(struc
 	return from_priority_to_tx_queue[priority] - 1;
 }
 
-/*
-* add QoS parameter to the TX command
-*/
-static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
-					u16 priority,
-					struct tfd_data *tfd, u8 unicast)
+static int ipw_is_qos_active(struct net_device *dev,
+			     struct sk_buff *skb)
 {
-	int ret = 0;
-	int tx_queue_id = 0;
+	struct ipw_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_qos_data *qos_data = NULL;
 	int active, supported;
-	unsigned long flags;
+	u8 *daddr = skb->data + ETH_ALEN;
+	int unicast = !is_multicast_ether_addr(daddr);
 
 	if (!(priv->status & STATUS_ASSOCIATED))
 		return 0;
 
 	qos_data = &priv->assoc_network->qos_data;
 
-	spin_lock_irqsave(&priv->ieee->lock, flags);
-
 	if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
 		if (unicast == 0)
 			qos_data->active = 0;
 		else
 			qos_data->active = qos_data->supported;
 	}
-
 	active = qos_data->active;
 	supported = qos_data->supported;
-
-	spin_unlock_irqrestore(&priv->ieee->lock, flags);
-
 	IPW_DEBUG_QOS("QoS  %d network is QoS active %d  supported %d  "
 		      "unicast %d\n",
 		      priv->qos_data.qos_enable, active, supported, unicast);
-	if (active && priv->qos_data.qos_enable) {
-		ret = from_priority_to_tx_queue[priority];
-		tx_queue_id = ret - 1;
-		IPW_DEBUG_QOS("QoS packet priority is %d \n", priority);
-		if (priority <= 7) {
-			tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
-			tfd->tfd.tfd_26.mchdr.qos_ctrl = priority;
-			tfd->tfd.tfd_26.mchdr.frame_ctl |=
-			    IEEE80211_STYPE_QOS_DATA;
-
-			if (priv->qos_data.qos_no_ack_mask &
-			    (1UL << tx_queue_id)) {
-				tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
-				tfd->tfd.tfd_26.mchdr.qos_ctrl |=
-				    CTRL_QOS_NO_ACK;
-			}
-		}
-	}
+	if (active && priv->qos_data.qos_enable)
+		return 1;
 
-	return ret;
+	return 0;
+
+}
+/*
+* add QoS parameter to the TX command
+*/
+static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
+					u16 priority,
+					struct tfd_data *tfd)
+{
+	int tx_queue_id = 0;
+
+
+	tx_queue_id = from_priority_to_tx_queue[priority] - 1;
+	tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
+
+	if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) {
+		tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
+		tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK;
+	}
+	return 0;
 }
 
 /*
@@ -9656,7 +9650,7 @@ we need to heavily modify the ieee80211_
 static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
 			     int pri)
 {
-	struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+	struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *)
 	    txb->fragments[0]->data;
 	int i = 0;
 	struct tfd_frame *tfd;
@@ -9671,9 +9665,9 @@ static int ipw_tx_skb(struct ipw_priv *p
 	u16 remaining_bytes;
 	int fc;
 
+	hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:
-		hdr_len = IEEE80211_3ADDR_LEN;
 		unicast = !is_multicast_ether_addr(hdr->addr1);
 		id = ipw_find_station(priv, hdr->addr1);
 		if (id == IPW_INVALID_STATION) {
@@ -9690,7 +9684,6 @@ static int ipw_tx_skb(struct ipw_priv *p
 	case IW_MODE_INFRA:
 	default:
 		unicast = !is_multicast_ether_addr(hdr->addr3);
-		hdr_len = IEEE80211_3ADDR_LEN;
 		id = 0;
 		break;
 	}
@@ -9769,7 +9762,8 @@ static int ipw_tx_skb(struct ipw_priv *p
 		tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP;
 
 #ifdef CONFIG_IPW_QOS
-	ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast);
+	if (fc & IEEE80211_STYPE_QOS_DATA)
+		ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data));
 #endif				/* CONFIG_IPW_QOS */
 
 	/* payload */
@@ -10969,6 +10963,7 @@ static int ipw_pci_probe(struct pci_dev 
 	priv->ieee->is_queue_full = ipw_net_is_queue_full;
 
 #ifdef CONFIG_IPW_QOS
+	priv->ieee->is_qos_active = ipw_is_qos_active;
 	priv->ieee->handle_probe_response = ipw_handle_beacon;
 	priv->ieee->handle_beacon = ipw_handle_probe_response;
 	priv->ieee->handle_assoc_response = ipw_handle_assoc_response;
-- 
1.2.6


^ permalink raw reply related

* [PATCH 03/18] ipw2200: generates a scan event after a scan has completed
From: Zhu Yi @ 2006-04-13  9:19 UTC (permalink / raw)
  To: netdev, John W. Linville

The patch make ipw2200 generate the scan event every time a scan has
completed, so that user space know when to get fresh results.
Dan Williams would like to go towards this model in Network Manager
rather than having to poll.

Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>

---

 drivers/net/wireless/ipw2200.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

edf85b053dafee701cbdda19507485455f97e544
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index a4d8d49..536af9f 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4489,6 +4489,24 @@ static void ipw_rx_notification(struct i
 				 && priv->status & STATUS_ASSOCIATED)
 				queue_delayed_work(priv->workqueue,
 						   &priv->request_scan, HZ);
+
+			/* Send an empty event to user space.
+			 * We don't send the received data on the event because
+			 * it would require us to do complex transcoding, and
+			 * we want to minimise the work done in the irq handler
+			 * Use a request to extract the data.
+			 * Also, we generate this even for any scan, regardless
+			 * on how the scan was initiated. User space can just
+			 * sync on periodic scan to get fresh data...
+			 * Jean II */
+			if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) {
+				union iwreq_data wrqu;
+
+				wrqu.data.length = 0;
+				wrqu.data.flags = 0;
+				wireless_send_event(priv->net_dev, SIOCGIWSCAN,
+						    &wrqu, NULL);
+			}
 			break;
 		}
 
@@ -8382,7 +8400,8 @@ static int ipw_wx_get_range(struct net_d
 	/* Event capability (kernel + driver) */
 	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
 				IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
-				IW_EVENT_CAPA_MASK(SIOCGIWAP));
+				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
 
 	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-- 
1.2.6


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox