Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 2.6.25 2/4]S2io: Multiqueue network device support - FIFO selection based on L4 ports
From: Patrick McHardy @ 2008-02-20 23:15 UTC (permalink / raw)
  To: David Miller; +Cc: Ramkrishna.Vepa, Sreenivasa.Honnur, netdev, jeff, support
In-Reply-To: <20080220.151244.79005114.davem@davemloft.net>

David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Thu, 21 Feb 2008 00:08:52 +0100
>
>   
>> Ramkrishna Vepa wrote:
>>     
>>>> Sreenivasa Honnur wrote:
>>>>     
>>>>         
>>>>> - Resubmit #2
>>>>> - Transmit fifo selection based on TCP/UDP ports.
>>>>> - Added tx_steering_type loadable parameter for transmit fifo
>>>>>       
>>>>>           
>>> selection.
>>>   
>>>       
>>>>>   0x0 NO_STEERING: Default FIFO is selected.
>>>>>   0x1 TX_PRIORITY_STEERING: FIFO is selected based on skb->priority.
>>>>>   0x2 TX_DEFAULT_STEERING: FIFO is selected based on L4 Ports.
>>>>>
>>>>>       
>>>>>           
>>>> Why duplicate the generic multiqueue classification?
>>>>     
>>>>         
>>> [Ram] Could you be more specific?
>>>   
>>>       
>> The generic multiqueue support classifies packets by setting
>> skb->queue_mapping using qdisc classifiers, which is more
>> flexible and avoids using module parameters.
>>     
>
> But it doesn't do what these multiqueue TX queue hardware devices
> want.  These devices don't want packet scheduler "classification",
> they want load balancing using some key (current cpu number,
> hashing on the packet headers, etc.)  And that's not what our
> packet scheduler classifiers do or should do.
>   

Its what the flow classifier does :)
> We don't want to have to tell people "you have to run 'tc' magic
> foo to use all of the TX queues on your network card."  That's
> completely unreasonable and stupid.
>
> We have to resolve this somehow, and there have been many discussions
> about this a month or so ago.
>   

I see. I missed those discussions, but this has already been
agreed on, fine by me. It would still be preferable to use
queue_mapping instead of priority IMO, even if its activated
by a module parameter, since that leaves the option to use
classifiers.


^ permalink raw reply

* Re: TG3 network data corruption regression 2.6.24/2.6.23.4
From: Michael Chan @ 2008-02-20 23:17 UTC (permalink / raw)
  To: David Miller; +Cc: tonyb, mcarlson, herbert, netdev, gregkh, linux-kernel
In-Reply-To: <20080220.150850.56732755.davem@davemloft.net>

On Wed, 2008-02-20 at 15:08 -0800, David Miller wrote:
> From: Tony Battersby <tonyb@cybernetics.com>
> Date: Wed, 20 Feb 2008 18:04:09 -0500
> 
> > The following patch fixes the problem for me.  Do we want to accept this
> > patch and call it a day or continue investigating the source of the problem?
> > 
> > Patch applies to 2.6.24.2, but doesn't apply to 2.6.25-rc.  If everyone
> > agrees that this is the right solution, I will resubmit with a proper
> > subject line and description.
> 
> A chipset bug, if it even exists, should be worked around in the
> driver for that hardware.  We shouldn't make every other piece
> of hardware in the world suffer too.
> 
> 

Yes, we should workaround this in the TG3 driver once we understand what
the problem is and how to workaround it.  We are still looking through
the errata list to sort this out.  It looks like it is the starting DMA
address of the TX buffer that is causing the problem.

^ permalink raw reply

* Re: [PATCH 2.6.25 2/4]S2io: Multiqueue network device support - FIFO selection based on L4 ports
From: David Miller @ 2008-02-20 23:18 UTC (permalink / raw)
  To: kaber; +Cc: Ramkrishna.Vepa, Sreenivasa.Honnur, netdev, jeff, support
In-Reply-To: <47BCB481.8050203@trash.net>

From: Patrick McHardy <kaber@trash.net>
Date: Thu, 21 Feb 2008 00:15:13 +0100

> I missed those discussions, but this has already been agreed on,
> fine by me. It would still be preferable to use queue_mapping
> instead of priority IMO, even if its activated by a module
> parameter, since that leaves the option to use classifiers.

I think the driver should compute the value in it's transmit
routine and keep the value local.  It shouldn't be setting
skb->foo values at all, they don't belong to the driver
and this could confuse other code.

^ permalink raw reply

* Re: [PATCH 2.6.25 2/4]S2io: Multiqueue network device support - FIFO selection based on L4 ports
From: Patrick McHardy @ 2008-02-20 23:21 UTC (permalink / raw)
  To: David Miller; +Cc: Ramkrishna.Vepa, Sreenivasa.Honnur, netdev, jeff, support
In-Reply-To: <20080220.151834.133850272.davem@davemloft.net>

David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Thu, 21 Feb 2008 00:15:13 +0100
>
>   
>> I missed those discussions, but this has already been agreed on,
>> fine by me. It would still be preferable to use queue_mapping
>> instead of priority IMO, even if its activated by a module
>> parameter, since that leaves the option to use classifiers.
>>     
>
> I think the driver should compute the value in it's transmit
> routine and keep the value local.  It shouldn't be setting
> skb->foo values at all, they don't belong to the driver
> and this could confuse other code.
>   

Yes, I didn't meant it should set anything, but on of the options
this patch introduces is to _use_ skb->priority for classification,
so the classification is already external, in which case it might
as well offer the full flexibility (as one option) to use qdisc
classifiers.




^ permalink raw reply

* [PATCH 2.6.25] RDMA/cxgb3: Shift calculation wrong for single sge entries.
From: Steve Wise @ 2008-02-20 23:31 UTC (permalink / raw)
  To: rdreier; +Cc: netdev, general, linux-kernel


RDMA/cxgb3: Shift calculation wrong for single sge entries.

A single entry (addr 0x10001000, size 0x2000) will get converted to
page address 0x10000000 with a page size of 0x4000.  The code as it
stands doesn't address the single buffer case, but in fact it allows
the subsequent single-buffer special case to be eliminated entirely.
Because the mask now includes the (page adjusted) starting and ending
addresses, the general case works for the single buffer case as well.

Signed-off-by: Bryan Rosenburg <rosnbrg@us.ibm.com>
Acked-by: Steve Wise <swise@opengridcomputing.com>
---

 drivers/infiniband/hw/cxgb3/iwch_mem.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
index 73bfd16..b8797c6 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
@@ -136,14 +136,8 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
 
 	/* Find largest page shift we can use to cover buffers */
 	for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
-		if (num_phys_buf > 1) {
-			if ((1ULL << *shift) & mask)
-				break;
-		} else
-			if (1ULL << *shift >=
-			    buffer_list[0].size +
-			    (buffer_list[0].addr & ((1ULL << *shift) - 1)))
-				break;
+		if ((1ULL << *shift) & mask)
+			break;
 
 	buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
 	buffer_list[0].addr &= ~0ull << *shift;

^ permalink raw reply related

* RE: [PATCH 2.6.25 2/4]S2io: Multiqueue network device support - FIFO selection based on L4 ports
From: Ramkrishna Vepa @ 2008-02-20 23:49 UTC (permalink / raw)
  To: Patrick McHardy, David Miller; +Cc: Sreenivasa Honnur, netdev, jeff, support
In-Reply-To: <47BCB60C.3040409@trash.net>

> From: Patrick McHardy [mailto:kaber@trash.net]
> Sent: Wednesday, February 20, 2008 3:22 PM
> To: David Miller
> Cc: Ramkrishna Vepa; Sreenivasa Honnur; netdev@vger.kernel.org;
> jeff@garzik.org; support
> Subject: Re: [PATCH 2.6.25 2/4]S2io: Multiqueue network device support
-
> FIFO selection based on L4 ports
> 
> David Miller wrote:
> > From: Patrick McHardy <kaber@trash.net>
> > Date: Thu, 21 Feb 2008 00:15:13 +0100
> >
> >
> >> I missed those discussions, but this has already been agreed on,
> >> fine by me. It would still be preferable to use queue_mapping
> >> instead of priority IMO, even if its activated by a module
> >> parameter, since that leaves the option to use classifiers.
> >>
> >
> > I think the driver should compute the value in it's transmit
> > routine and keep the value local.  It shouldn't be setting
> > skb->foo values at all, they don't belong to the driver
> > and this could confuse other code.
> >
> 
> Yes, I didn't meant it should set anything, but on of the options
> this patch introduces is to _use_ skb->priority for classification,
> so the classification is already external, in which case it might
> as well offer the full flexibility (as one option) to use qdisc
> classifiers.
[Ram] Yes, this should be possible. We can add an additional option to
use qdisc classifiers and submit it as a patch later on.

Ram

^ permalink raw reply

* Re: [git patches] net driver updates
From: Divy Le Ray @ 2008-02-21  1:16 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: David Miller, netdev, LKML
In-Reply-To: <47BC8FBD.2070401@garzik.org>

Jeff Garzik wrote:
> Divy Le Ray wrote:
>> Jeff Garzik wrote:
>>> Mostly fixes, a few cleanups (generally assisting fixes), and an
>>> exception for PS3 wireless because it had been posted, reviewed and
>>> acked for a while, just not committed.
>>>
>>> Please pull from 'upstream-davem' branch of
>>> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git 
>>> upstream-davem
>>>
>>> to receive the following updates:
>>>
>>>  
>>>  drivers/net/cxgb3/sge.c          |   35 +-
>>>    diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
>>> index 9ca8c66..979f3fc 100644
>>> --- a/drivers/net/cxgb3/sge.c
>>> +++ b/drivers/net/cxgb3/sge.c
>>> @@ -1059,6 +1059,14 @@ static void write_tx_pkt_wr(struct adapter 
>>> *adap, struct sk_buff *skb,
>>>               htonl(V_WR_TID(q->token)));
>>>  }
>>>  
>>> +static inline void t3_stop_queue(struct net_device *dev, struct 
>>> sge_qset *qs,
>>> +                 struct sge_txq *q)
>>> +{
>>> +    netif_stop_queue(dev);
>>> +    set_bit(TXQ_ETH, &qs->txq_stopped);
>>> +    q->stops++;
>>> +}
>>> +
>>>  /**
>>>   *    eth_xmit - add a packet to the Ethernet Tx queue
>>>   *    @skb: the packet
>>> @@ -1090,31 +1098,18 @@ int t3_eth_xmit(struct sk_buff *skb, struct 
>>> net_device *dev)
>>>      ndesc = calc_tx_descs(skb);
>>>  
>>>      if (unlikely(credits < ndesc)) {
>>> -        if (!netif_queue_stopped(dev)) {
>>> -            netif_stop_queue(dev);
>>> -            set_bit(TXQ_ETH, &qs->txq_stopped);
>>> -            q->stops++;
>>> -            dev_err(&adap->pdev->dev,
>>> -                "%s: Tx ring %u full while queue awake!\n",
>>> -                dev->name, q->cntxt_id & 7);
>>> -        }
>>> +        t3_stop_queue(dev, qs, q);
>>> +        dev_err(&adap->pdev->dev,
>>> +            "%s: Tx ring %u full while queue awake!\n",
>>> +            dev->name, q->cntxt_id & 7);
>>>          spin_unlock(&q->lock);
>>>          return NETDEV_TX_BUSY;
>>>      }
>>>  
>>>      q->in_use += ndesc;
>>> -    if (unlikely(credits - ndesc < q->stop_thres)) {
>>> -        q->stops++;
>>> -        netif_stop_queue(dev);
>>> -        set_bit(TXQ_ETH, &qs->txq_stopped);
>>> -#if !USE_GTS
>>> -        if (should_restart_tx(q) &&
>>> -            test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
>>> -            q->restarts++;
>>> -            netif_wake_queue(dev);
>>> -        }
>>> -#endif
>>> -    }
>>> +    if (unlikely(credits - ndesc < q->stop_thres))
>>> +        if (USE_GTS || !should_restart_tx(q))
>>> +            t3_stop_queue(dev, qs, q);
>>>  
>>>      gen = q->gen;
>>>      q->unacked += ndesc;
>>>   
>> Hi Jeff,
>>
>> I thought I had NAK'ed the patch modifying sge.c from Krishna Kumar.
>> Looking back at my answer at the time, I was obviously unclear.
>> Can you please revert the drivers/net/cxgb3sge.c change ?
>
> Explain why, so I can include it in the changelog please...

Hi Jeff,

The first part of the patch removes the !netif_queue_stopped(dev).
It opens the race discussed a while ago between Stephen hemminger and 
David Miller:
http://marc.info/?l=linux-netdev&m=113383224512427&w=2

The second part of the patch breaks the current usage of txq_stopped and 
the logic that stops and restarts the Tx queue.

Cheers,
Divy


^ permalink raw reply

* pull request: wireless-2.6 2008-02-20
From: John W. Linville @ 2008-02-21  2:11 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA

David,

Here are some fixes intended for 2.6.25.  These are mostly small things:
a couple of USB IDs, some sparse warnings, and an ath5k warning you
should recognize.  :-)  There are also a number of SSB bus fixes --
Michael has been hacking on a new AP...

Please let me know if there are problems!

Thanks,

John

---

Individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/

---

The following changes since commit da12f7356da1dfb97f1c6c418f828b7ce442fef9:
  Denis V. Lunev (1):
        [NETNS]: Namespace leak in pneigh_lookup.

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master

David Miller (1):
      ath5k: Fix build warnings on some 64-bit platforms.

Ivo Couckuyt (1):
      p54usb: add USB ID for Phillips CPWUA054

Jiri Slaby (2):
      WDEV: ath5k, fix lock imbalance
      WDEV, ath5k, don't return int from bool function

Johannes Berg (2):
      rtl818x: fix sparse warnings
      zd1211rw: fix sparse warnings

John W. Linville (1):
      p54usb: add USB ID for Linksys WUSB54G ver 2

Michael Buesch (6):
      ssb: Fix serial console on new bcm47xx devices
      ssb: Fix watchdog access for devices without a chipcommon
      ssb: Fix the GPIO API
      ssb: Make the GPIO API reentrancy safe
      ssb: Fix pcicore cardbus mode
      ssb: Fix support for PCI devices behind a SSB->PCI bridge

 drivers/net/wireless/ath5k/ath5k.h        |    2 +-
 drivers/net/wireless/ath5k/base.c         |   20 +++--
 drivers/net/wireless/ath5k/hw.c           |    8 +-
 drivers/net/wireless/p54usb.c             |    2 +
 drivers/net/wireless/rtl8180_dev.c        |    4 +-
 drivers/net/wireless/rtl8187_dev.c        |    4 +-
 drivers/net/wireless/zd1211rw/zd_mac.c    |   12 ++-
 drivers/ssb/Kconfig                       |    6 ++
 drivers/ssb/Makefile                      |    1 +
 drivers/ssb/driver_chipcommon.c           |   65 ++++++++++++---
 drivers/ssb/driver_extif.c                |   25 +++++-
 drivers/ssb/driver_pcicore.c              |   45 ++++++++--
 drivers/ssb/embedded.c                    |  132 +++++++++++++++++++++++++++++
 drivers/ssb/main.c                        |    4 +
 include/linux/ssb/ssb.h                   |   12 +++
 include/linux/ssb/ssb_driver_chipcommon.h |   18 +++-
 include/linux/ssb/ssb_driver_extif.h      |   18 +++-
 include/linux/ssb/ssb_driver_pci.h        |    5 +
 include/linux/ssb/ssb_embedded.h          |   18 ++++
 19 files changed, 354 insertions(+), 47 deletions(-)
 create mode 100644 drivers/ssb/embedded.c
 create mode 100644 include/linux/ssb/ssb_embedded.h

diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index c79066b..69dea33 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -1035,7 +1035,7 @@ struct ath5k_hw {
 		unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
 		unsigned int, unsigned int, unsigned int, unsigned int,
 		unsigned int, unsigned int, unsigned int);
-	bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+	int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
 		unsigned int, unsigned int, unsigned int, unsigned int,
 		unsigned int, unsigned int);
 	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index dfdaec0..bef967c 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -668,7 +668,10 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 	 * return false w/o doing anything.  MAC's that do
 	 * support it will return true w/o doing anything.
 	 */
-	if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0))
+	ret = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
+	if (ret < 0)
+		goto err;
+	if (ret > 0)
 		__set_bit(ATH_STAT_MRRETRY, sc->status);
 
 	/*
@@ -1715,6 +1718,7 @@ ath5k_tasklet_rx(unsigned long data)
 			break;
 		else if (unlikely(ret)) {
 			ATH5K_ERR(sc, "error in processing rx descriptor\n");
+			spin_unlock(&sc->rxbuflock);
 			return;
 		}
 
@@ -2126,8 +2130,9 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 			"updated timers based on beacon TSF\n");
 
 	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-		"bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
-		bc_tsf, hw_tsf, bc_tu, hw_tu, nexttbtt);
+			  "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
+			  (unsigned long long) bc_tsf,
+			  (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
 	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
 		intval & AR5K_BEACON_PERIOD,
 		intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
@@ -2385,10 +2390,11 @@ ath5k_intr(int irq, void *dev_id)
 					u64 tsf = ath5k_hw_get_tsf64(ah);
 					sc->nexttbtt += sc->bintval;
 					ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-						"SWBA nexttbtt: %x hw_tu: %x "
-						"TSF: %llx\n",
-						sc->nexttbtt,
-						TSF_TO_TU(tsf), tsf);
+						  "SWBA nexttbtt: %x hw_tu: %x "
+						  "TSF: %llx\n",
+						  sc->nexttbtt,
+						  TSF_TO_TU(tsf),
+						  (unsigned long long) tsf);
 				} else {
 					ath5k_beacon_send(sc);
 				}
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index 1ab57aa..c2de2d9 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -45,7 +45,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int, unsigned int);
-static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int);
 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
@@ -3743,7 +3743,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 /*
  * Initialize a 4-word multirate tx descriptor on 5212
  */
-static bool
+static int
 ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
 	unsigned int tx_rate3, u_int tx_tries3)
@@ -3783,10 +3783,10 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 
 #undef _XTX_TRIES
 
-		return true;
+		return 1;
 	}
 
-	return false;
+	return 0;
 }
 
 /*
diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c
index 60d286e..e7d4aee 100644
--- a/drivers/net/wireless/p54usb.c
+++ b/drivers/net/wireless/p54usb.c
@@ -35,6 +35,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
 	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
 	{USB_DEVICE(0x083a, 0x4501)},	/* Accton 802.11g WN4501 USB */
 	{USB_DEVICE(0x083a, 0x4502)},	/* Siemens Gigaset USB Adapter */
+	{USB_DEVICE(0x083a, 0x5501)},	/* Phillips CPWUA054 */
 	{USB_DEVICE(0x0846, 0x4200)},	/* Netgear WG121 */
 	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
 	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
@@ -62,6 +63,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
 	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */
 	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */
 	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
+	{USB_DEVICE(0x13b1, 0x000a)},	/* Linksys WUSB54G ver 2 */
 	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
 	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
 	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index 27ebd68..5e9a8ac 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -135,13 +135,15 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
 	while (skb_queue_len(&ring->queue)) {
 		struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
 		struct sk_buff *skb;
-		struct ieee80211_tx_status status = { {0} };
+		struct ieee80211_tx_status status;
 		struct ieee80211_tx_control *control;
 		u32 flags = le32_to_cpu(entry->flags);
 
 		if (flags & RTL8180_TX_DESC_FLAG_OWN)
 			return;
 
+		memset(&status, 0, sizeof(status));
+
 		ring->idx = (ring->idx + 1) % ring->entries;
 		skb = __skb_dequeue(&ring->queue);
 		pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 0d71716..f445059 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -113,10 +113,12 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
 
 static void rtl8187_tx_cb(struct urb *urb)
 {
-	struct ieee80211_tx_status status = { {0} };
+	struct ieee80211_tx_status status;
 	struct sk_buff *skb = (struct sk_buff *)urb->context;
 	struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
 
+	memset(&status, 0, sizeof(status));
+
 	usb_free_urb(info->urb);
 	if (info->control)
 		memcpy(&status.control, info->control, sizeof(status.control));
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 49127e4..76ef2d8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -360,11 +360,14 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
 {
 	struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
 	struct sk_buff *skb;
-	struct ieee80211_tx_status status = {{0}};
+	struct ieee80211_tx_status status;
 
 	skb = skb_dequeue(q);
 	if (skb == NULL)
 		return;
+
+	memset(&status, 0, sizeof(status));
+
 	tx_status(hw, skb, &status, 0);
 }
 
@@ -389,7 +392,8 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
 		if (unlikely(error ||
 		    (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
 		{
-			struct ieee80211_tx_status status = {{0}};
+			struct ieee80211_tx_status status;
+			memset(&status, 0, sizeof(status));
 			tx_status(hw, skb, &status, !error);
 		} else {
 			struct sk_buff_head *q =
@@ -603,7 +607,9 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
 		tx_hdr = (struct ieee80211_hdr *)skb->data;
 		if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
 		{
-			struct ieee80211_tx_status status = {{0}};
+			struct ieee80211_tx_status status;
+
+			memset(&status, 0, sizeof(status));
 			status.flags = IEEE80211_TX_STATUS_ACK;
 			status.ack_signal = stats->ssi;
 			__skb_unlink(skb, q);
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index d976660..78fd331 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -105,6 +105,12 @@ config SSB_DRIVER_MIPS
 
 	  If unsure, say N
 
+# Assumption: We are on embedded, if we compile the MIPS core.
+config SSB_EMBEDDED
+	bool
+	depends on SSB_DRIVER_MIPS
+	default y
+
 config SSB_DRIVER_EXTIF
 	bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)"
 	depends on SSB_DRIVER_MIPS && EXPERIMENTAL
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index 7be3975..e235144 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -1,5 +1,6 @@
 # core
 ssb-y					+= main.o scan.o
+ssb-$(CONFIG_SSB_EMBEDDED)		+= embedded.o
 
 # host support
 ssb-$(CONFIG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 6fbf1c5..e586321 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -39,12 +39,14 @@ static inline void chipco_write32(struct ssb_chipcommon *cc,
 	ssb_write32(cc->dev, offset, value);
 }
 
-static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset,
-					 u32 mask, u32 value)
+static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset,
+					u32 mask, u32 value)
 {
 	value &= mask;
 	value |= chipco_read32(cc, offset) & ~mask;
 	chipco_write32(cc, offset, value);
+
+	return value;
 }
 
 void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
@@ -356,14 +358,29 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
 	return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
 }
 
-void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
+u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+}
+
+u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+}
+
+u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
+}
+
+u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
 }
 
-void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
+u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
 }
 
 #ifdef CONFIG_SSB_SERIAL
@@ -376,6 +393,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 	unsigned int irq;
 	u32 baud_base, div;
 	u32 i, n;
+	unsigned int ccrev = cc->dev->id.revision;
 
 	plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
 	irq = ssb_mips_irq(cc->dev);
@@ -387,14 +405,39 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 						chipco_read32(cc, SSB_CHIPCO_CLOCK_M2));
 		div = 1;
 	} else {
-		if (cc->dev->id.revision >= 11) {
+		if (ccrev == 20) {
+			/* BCM5354 uses constant 25MHz clock */
+			baud_base = 25000000;
+			div = 48;
+			/* Set the override bit so we don't divide it */
+			chipco_write32(cc, SSB_CHIPCO_CORECTL,
+				       chipco_read32(cc, SSB_CHIPCO_CORECTL)
+				       | SSB_CHIPCO_CORECTL_UARTCLK0);
+		} else if ((ccrev >= 11) && (ccrev != 15)) {
 			/* Fixed ALP clock */
 			baud_base = 20000000;
+			if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+				/* FIXME: baud_base is different for devices with a PMU */
+				SSB_WARN_ON(1);
+			}
 			div = 1;
+			if (ccrev >= 21) {
+				/* Turn off UART clock before switching clocksource. */
+				chipco_write32(cc, SSB_CHIPCO_CORECTL,
+					       chipco_read32(cc, SSB_CHIPCO_CORECTL)
+					       & ~SSB_CHIPCO_CORECTL_UARTCLKEN);
+			}
 			/* Set the override bit so we don't divide it */
 			chipco_write32(cc, SSB_CHIPCO_CORECTL,
-				       SSB_CHIPCO_CORECTL_UARTCLK0);
-		} else if (cc->dev->id.revision >= 3) {
+				       chipco_read32(cc, SSB_CHIPCO_CORECTL)
+				       | SSB_CHIPCO_CORECTL_UARTCLK0);
+			if (ccrev >= 21) {
+				/* Re-enable the UART clock. */
+				chipco_write32(cc, SSB_CHIPCO_CORECTL,
+					       chipco_read32(cc, SSB_CHIPCO_CORECTL)
+					       | SSB_CHIPCO_CORECTL_UARTCLKEN);
+			}
+		} else if (ccrev >= 3) {
 			/* Internal backplane clock */
 			baud_base = ssb_clockspeed(bus);
 			div = chipco_read32(cc, SSB_CHIPCO_CLKDIV)
@@ -406,7 +449,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 		}
 
 		/* Clock source depends on strapping if UartClkOverride is unset */
-		if ((cc->dev->id.revision > 0) &&
+		if ((ccrev > 0) &&
 		    !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) {
 			if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) ==
 			    SSB_CHIPCO_CAP_UARTCLK_INT) {
@@ -428,7 +471,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 		cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE);
 		uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA;
 		/* Offset changed at after rev 0 */
-		if (cc->dev->id.revision == 0)
+		if (ccrev == 0)
 			uart_regs += (i * 8);
 		else
 			uart_regs += (i * 256);
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index fe55eb8..c3e1d3e 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -27,12 +27,14 @@ static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value)
 	ssb_write32(extif->dev, offset, value);
 }
 
-static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset,
-					u32 mask, u32 value)
+static inline u32 extif_write32_masked(struct ssb_extif *extif, u16 offset,
+				       u32 mask, u32 value)
 {
 	value &= mask;
 	value |= extif_read32(extif, offset) & ~mask;
 	extif_write32(extif, offset, value);
+
+	return value;
 }
 
 #ifdef CONFIG_SSB_SERIAL
@@ -110,20 +112,35 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
 	*m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
 }
 
+void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+				  u32 ticks)
+{
+	extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
+}
+
 u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 {
 	return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
 }
 
-void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
+u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
 {
 	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
 				   mask, value);
 }
 
-void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
+u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
 {
 	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
 				   mask, value);
 }
 
+u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
+{
+	return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
+}
+
+u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
+{
+	return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
+}
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 2faaa90..6d99a98 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -11,6 +11,7 @@
 #include <linux/ssb/ssb.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/ssb/ssb_embedded.h>
 
 #include "ssb_private.h"
 
@@ -27,6 +28,18 @@ void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value)
 	ssb_write32(pc->dev, offset, value);
 }
 
+static inline
+u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset)
+{
+	return ssb_read16(pc->dev, offset);
+}
+
+static inline
+void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value)
+{
+	ssb_write16(pc->dev, offset, value);
+}
+
 /**************************************************
  * Code for hostmode operation.
  **************************************************/
@@ -66,6 +79,7 @@ int pcibios_plat_dev_init(struct pci_dev *d)
 			base = &ssb_pcicore_pcibus_iobase;
 		else
 			base = &ssb_pcicore_pcibus_membase;
+		res->flags |= IORESOURCE_PCI_FIXED;
 		if (res->end) {
 			size = res->end - res->start + 1;
 			if (*base & (size - 1))
@@ -88,10 +102,12 @@ int pcibios_plat_dev_init(struct pci_dev *d)
 
 static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
 {
+	u8 lat;
+
 	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
 		return;
 
-	ssb_printk(KERN_INFO "PCI: fixing up bridge\n");
+	ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
 
 	/* Enable PCI bridge bus mastering and memory space */
 	pci_set_master(dev);
@@ -101,7 +117,10 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
 	pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
 
 	/* Make sure our latency is high enough to handle the devices behind us */
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);
+	lat = 168;
+	ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
+		   pci_name(dev), lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
 
@@ -117,8 +136,10 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
 	u32 addr = 0;
 	u32 tmp;
 
-	if (unlikely(pc->cardbusmode && dev > 1))
+	/* We do only have one cardbus device behind the bridge. */
+	if (pc->cardbusmode && (dev >= 1))
 		goto out;
+
 	if (bus == 0) {
 		/* Type 0 transaction */
 		if (unlikely(dev >= SSB_PCI_SLOT_MAX))
@@ -279,14 +300,14 @@ static struct resource ssb_pcicore_mem_resource = {
 	.name	= "SSB PCIcore external memory",
 	.start	= SSB_PCI_DMA,
 	.end	= SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
-	.flags	= IORESOURCE_MEM,
+	.flags	= IORESOURCE_MEM | IORESOURCE_PCI_FIXED,
 };
 
 static struct resource ssb_pcicore_io_resource = {
 	.name	= "SSB PCIcore external I/O",
 	.start	= 0x100,
 	.end	= 0x7FF,
-	.flags	= IORESOURCE_IO,
+	.flags	= IORESOURCE_IO | IORESOURCE_PCI_FIXED,
 };
 
 static struct pci_controller ssb_pcicore_controller = {
@@ -318,7 +339,16 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
 	udelay(1); /* Assertion time demanded by the PCI standard */
 
-	/*TODO cardbus mode */
+	if (pc->dev->bus->has_cardbus_slot) {
+		ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n");
+		pc->cardbusmode = 1;
+		/* GPIO 1 resets the bridge */
+		ssb_gpio_out(pc->dev->bus, 1, 1);
+		ssb_gpio_outen(pc->dev->bus, 1, 1);
+		pcicore_write16(pc, SSB_PCICORE_SPROM(0),
+				pcicore_read16(pc, SSB_PCICORE_SPROM(0))
+				| 0x0400);
+	}
 
 	/* 64MB I/O window */
 	pcicore_write32(pc, SSB_PCICORE_SBTOPCI0,
@@ -344,7 +374,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	/* Ok, ready to run, register it to the system.
 	 * The following needs change, if we want to port hostmode
 	 * to non-MIPS platform. */
-	set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
+	ssb_pcicore_controller.io_map_base = (unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000);
+	set_io_port_base(ssb_pcicore_controller.io_map_base);
 	/* Give some time to the PCI controller to configure itself with the new
 	 * values. Not waiting at this point causes crashes of the machine. */
 	mdelay(10);
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
new file mode 100644
index 0000000..d3ade82
--- /dev/null
+++ b/drivers/ssb/embedded.c
@@ -0,0 +1,132 @@
+/*
+ * Sonics Silicon Backplane
+ * Embedded systems support code
+ *
+ * Copyright 2005-2008, Broadcom Corporation
+ * Copyright 2006-2008, Michael Buesch <mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_embedded.h>
+
+#include "ssb_private.h"
+
+
+int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
+{
+	if (ssb_chipco_available(&bus->chipco)) {
+		ssb_chipco_watchdog_timer_set(&bus->chipco, ticks);
+		return 0;
+	}
+	if (ssb_extif_available(&bus->extif)) {
+		ssb_extif_watchdog_timer_set(&bus->extif, ticks);
+		return 0;
+	}
+	return -ENODEV;
+}
+
+u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_in(&bus->chipco, mask);
+	else if (ssb_extif_available(&bus->extif))
+		res = ssb_extif_gpio_in(&bus->extif, mask);
+	else
+		SSB_WARN_ON(1);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_in);
+
+u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
+	else if (ssb_extif_available(&bus->extif))
+		res = ssb_extif_gpio_out(&bus->extif, mask, value);
+	else
+		SSB_WARN_ON(1);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_out);
+
+u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
+	else if (ssb_extif_available(&bus->extif))
+		res = ssb_extif_gpio_outen(&bus->extif, mask, value);
+	else
+		SSB_WARN_ON(1);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_outen);
+
+u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_control);
+
+u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
+	else if (ssb_extif_available(&bus->extif))
+		res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
+	else
+		SSB_WARN_ON(1);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_intmask);
+
+u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&bus->gpio_lock, flags);
+	if (ssb_chipco_available(&bus->chipco))
+		res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
+	else if (ssb_extif_available(&bus->extif))
+		res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
+	else
+		SSB_WARN_ON(1);
+	spin_unlock_irqrestore(&bus->gpio_lock, flags);
+
+	return res;
+}
+EXPORT_SYMBOL(ssb_gpio_polarity);
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 9028ed5..bedb2b4 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -557,6 +557,7 @@ static int ssb_fetch_invariants(struct ssb_bus *bus,
 		goto out;
 	memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo));
 	memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom));
+	bus->has_cardbus_slot = iv.has_cardbus_slot;
 out:
 	return err;
 }
@@ -569,6 +570,9 @@ static int ssb_bus_register(struct ssb_bus *bus,
 
 	spin_lock_init(&bus->bar_lock);
 	INIT_LIST_HEAD(&bus->list);
+#ifdef CONFIG_SSB_EMBEDDED
+	spin_lock_init(&bus->gpio_lock);
+#endif
 
 	/* Powerup the bus */
 	err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 9d5da8b..20add65 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -282,6 +282,13 @@ struct ssb_bus {
 	struct ssb_boardinfo boardinfo;
 	/* Contents of the SPROM. */
 	struct ssb_sprom sprom;
+	/* If the board has a cardbus slot, this is set to true. */
+	bool has_cardbus_slot;
+
+#ifdef CONFIG_SSB_EMBEDDED
+	/* Lock for GPIO register access. */
+	spinlock_t gpio_lock;
+#endif /* EMBEDDED */
 
 	/* Internal-only stuff follows. Do not touch. */
 	struct list_head list;
@@ -294,8 +301,13 @@ struct ssb_bus {
 
 /* The initialization-invariants. */
 struct ssb_init_invariants {
+	/* Versioning information about the PCB. */
 	struct ssb_boardinfo boardinfo;
+	/* The SPROM information. That's either stored in an
+	 * EEPROM or NVRAM on the board. */
 	struct ssb_sprom sprom;
+	/* If the board has a cardbus slot, this is set to true. */
+	bool has_cardbus_slot;
 };
 /* Type of function to fetch the invariants. */
 typedef int (*ssb_invariants_func_t)(struct ssb_bus *bus,
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index 4cb9954..536851b 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -51,9 +51,12 @@
 #define  SSB_CHIPCO_CAP_JTAGM		0x00400000	/* JTAG master present */
 #define  SSB_CHIPCO_CAP_BROM		0x00800000	/* Internal boot ROM active */
 #define  SSB_CHIPCO_CAP_64BIT		0x08000000	/* 64-bit Backplane */
+#define  SSB_CHIPCO_CAP_PMU		0x10000000	/* PMU available (rev >= 20) */
+#define  SSB_CHIPCO_CAP_ECI		0x20000000	/* ECI available (rev >= 20) */
 #define SSB_CHIPCO_CORECTL		0x0008
 #define  SSB_CHIPCO_CORECTL_UARTCLK0	0x00000001	/* Drive UART with internal clock */
 #define	 SSB_CHIPCO_CORECTL_SE		0x00000002	/* sync clk out enable (corerev >= 3) */
+#define  SSB_CHIPCO_CORECTL_UARTCLKEN	0x00000008	/* UART clock enable (rev >= 21) */
 #define SSB_CHIPCO_BIST			0x000C
 #define SSB_CHIPCO_OTPS			0x0010		/* OTP status */
 #define	 SSB_CHIPCO_OTPS_PROGFAIL	0x80000000
@@ -357,6 +360,11 @@ struct ssb_chipcommon {
 	u16 fast_pwrup_delay;
 };
 
+static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
+{
+	return (cc->dev != NULL);
+}
+
 extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
 
 #include <linux/pm.h>
@@ -382,11 +390,13 @@ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
 extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
 					  u32 ticks);
 
+/* Chipcommon GPIO pin access. */
 u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
-
-void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
-
-void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
 
 #ifdef CONFIG_SSB_SERIAL
 extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h
index a916435..91161f0 100644
--- a/include/linux/ssb/ssb_driver_extif.h
+++ b/include/linux/ssb/ssb_driver_extif.h
@@ -171,11 +171,15 @@ extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
 extern void ssb_extif_timing_init(struct ssb_extif *extif,
 				  unsigned long ns);
 
-u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
-
-void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value);
+extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+					 u32 ticks);
 
-void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value);
+/* Extif GPIO pin access */
+u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
+u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value);
+u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value);
+u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value);
+u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value);
 
 #ifdef CONFIG_SSB_SERIAL
 extern int ssb_extif_serial_init(struct ssb_extif *extif,
@@ -200,5 +204,11 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
 {
 }
 
+static inline
+void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+				  u32 ticks)
+{
+}
+
 #endif /* CONFIG_SSB_DRIVER_EXTIF */
 #endif /* LINUX_SSB_EXTIFCORE_H_ */
diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h
index 9cfffb7..5e25bac 100644
--- a/include/linux/ssb/ssb_driver_pci.h
+++ b/include/linux/ssb/ssb_driver_pci.h
@@ -51,6 +51,11 @@
 #define  SSB_PCICORE_SBTOPCI1_MASK	0xFC000000
 #define SSB_PCICORE_SBTOPCI2		0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
 #define  SSB_PCICORE_SBTOPCI2_MASK	0xC0000000
+#define SSB_PCICORE_PCICFG0		0x0400	/* PCI config space 0 (rev >= 8) */
+#define SSB_PCICORE_PCICFG1		0x0500	/* PCI config space 1 (rev >= 8) */
+#define SSB_PCICORE_PCICFG2		0x0600	/* PCI config space 2 (rev >= 8) */
+#define SSB_PCICORE_PCICFG3		0x0700	/* PCI config space 3 (rev >= 8) */
+#define SSB_PCICORE_SPROM(wordoffset)	(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
 
 /* SBtoPCIx */
 #define SSB_PCICORE_SBTOPCI_MEM		0x00000000
diff --git a/include/linux/ssb/ssb_embedded.h b/include/linux/ssb/ssb_embedded.h
new file mode 100644
index 0000000..8d8dedf
--- /dev/null
+++ b/include/linux/ssb/ssb_embedded.h
@@ -0,0 +1,18 @@
+#ifndef LINUX_SSB_EMBEDDED_H_
+#define LINUX_SSB_EMBEDDED_H_
+
+#include <linux/types.h>
+#include <linux/ssb/ssb.h>
+
+
+extern int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks);
+
+/* Generic GPIO API */
+u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask);
+u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value);
+u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value);
+u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value);
+u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value);
+u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value);
+
+#endif /* LINUX_SSB_EMBEDDED_H_ */
-- 
John W. Linville
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org

^ permalink raw reply related

* Re: [PATCH 01/04] smc91x: pass along private data
From: Magnus Damm @ 2008-02-21  2:14 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: netdev, lethal, akpm
In-Reply-To: <alpine.LFD.1.00.0802201037070.2732@xanadu.home>

On Thu, Feb 21, 2008 at 12:42 AM, Nicolas Pitre <nico@cam.org> wrote:
> On Wed, 20 Feb 2008, Magnus Damm wrote:
>
>  > Pass a private data pointer to macros and functions. This makes it easy
>  > to later on make run time decisions. This patch does not change any logic.
>  > These changes should be optimized away during compilation.
>  >
>  > Signed-off-by: Magnus Damm <damm@igel.co.jp>
>  > ---
>
> > --- 0001/drivers/net/smc91x.c
>  > +++ work/drivers/net/smc91x.c 2008-02-20 16:52:48.000000000 +0900
>  > @@ -220,23 +220,23 @@ static void PRINT_PKT(u_char *buf, int l
>  >
>  >
>  >  /* this enables an interrupt in the interrupt mask register */
>  > -#define SMC_ENABLE_INT(x) do {                                               \
>  > +#define SMC_ENABLE_INT(priv, x) do {                                 \
>  >       unsigned char mask;                                             \
>  > -     spin_lock_irq(&lp->lock);                                       \
>  > -     mask = SMC_GET_INT_MASK();                                      \
>  > +     spin_lock_irq(&priv->lock);                                     \
>  > +     mask = SMC_GET_INT_MASK(priv);                                  \
>
>  Since "lp" is already used all over the place, could you simply use "lp"
>  for the macro argument name as well instead of "priv"?  This will make
>  the code more uniform and reduce the patch size.

I used the name "priv" instead of "lp" intentionally to make sure I
got compile errors if I missed something. Some variables like "ioaddr"
are today not passed as arguments to the macros but simply assumed to
be present as local variables. I wanted to avoid using the local "lp"
variable by mistake. So the "priv" name is actually a feature. =)

I'd be happy to rewrite the patch to use "lp" though, but I have to
confess that I don't see the point in redoing it. Anyway, please let
me know what you prefer.

Thank you.

/ magnus

^ permalink raw reply

* pull request: wireless-2.6.26 2008-02-20
From: John W. Linville @ 2008-02-21  2:15 UTC (permalink / raw)
  To: davem; +Cc: netdev, linux-wireless

David,

Here are a slew of developments intended for 2.6.26.  The patches are
too diverse to comment upon in this summary... :-)

Please let me know if there are problems!

Thanks,

John

---

Individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6.26/

---

The following changes since commit 1309d4e68497184d2fd87e892ddf14076c2bda98:
  Linus Torvalds (1):
        Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.26.git master

Adam Baker (2):
      rt2x00: don't write past the end when writing short descriptors on rt61
      rt2x00: correct address calc for queue private data

Bruno Randolf (3):
      mac80211: better definition of mactime
      mac80211: move function ieee80211_sta_join_ibss()
      mac80211: enable IBSS merging

Christian Lamparter (1):
      p54: use IEEE 802.11e defaults for initialization

Daniel Drake (1):
      ipw2100/ipw2200: note firmware loading caveat in Kconfig help text

Emmanuel Grumbach (1):
      iwlwifi-2.6: Adds and fixes defines about security

Gertjan van Wingerde (1):
      rt2x00: Fix hw mode registration with mac80211.

Holger Schurig (5):
      libertas: trim overly long debug statement
      libertas: make association debug output nicer
      libertas: make lbs_sync_channel() static
      libertas: make lbs_unset_basic_rate_flags() static
      libertas: rename/document scan_channel

Ivo van Doorn (41):
      rt2x00: Update copyright notice
      rt2x00: Queue handling overhaul
      rt2x00: Fix tx parameter initialization
      rt2x00: Enable master and adhoc mode again
      rt2x00: Driver requiring firmware should select crc algo
      rt2x00: Add per-interface structure
      rt2x00: Remove TX_MGMT queue usage
      rt2x00: Initialize QID from queue->qid
      rt2x00: Move beacon and atim queue defines into rt2x00
      rt2x00: Fix queue index handling
      wireless: Fix WARN_ON() with ieee802.11b
      rt2x00: Rate structure overhaul
      rt2x00: Remove HWMODE_{A,B,G}
      rt2x00: Use ieee80211_channel_to_frequency()
      rt2x00: Make use of MAC80211_LED_TRIGGERS
      rt2x00: Enable LED class support for rt2500usb/rt73usb
      rt2x00: Fix rate initialization
      rt2x00: Release rt2x00 2.1.0
      rt2x00: Fix invalid DMA free
      rt2x00: Make rt2x00 less verbose
      rt2x00: Remove MGMT ring initialization
      rt2x00: Select CONFIG_NEW_LEDS
      rt2x00: make csr_cache and csr_addr an union
      rt2x00: Fix scheduling while atomic errors in usb drivers
      rt2x00: Add queue statistics to debugfs
      rt2x00: Fix typo in debug statement
      rt2x00: Fix skbdesc->data_len initialization
      rt2x00: Fix queue->qid initialization
      rt2x00: Cleanup Makefile
      rt2x00: Kill guardian urb during disable_radio
      rt2x00: Release rt2x00 2.1.1
      rt2x00: Send frames out with configured TX power
      rt2x00: Don't report driver generated frames to tx_status()
      rt2x00: Filter ACK_CTS based on FIF_CONTROL
      rt2x00: Fix Descriptor DMA initialization
      rt2x00: Remove reset_tsf()
      rt2x00: Rename dscape -> mac80211
      rt2x00: Cleanup mode registration
      rt2x00: Remove async vendor request calls from rt2x00usb
      rt2x00: Fix MAC address defines in rt61pci
      rt2x00: Release rt2x00 2.1.2

Javier Cardona (1):
      zd1211rw: Fixed incorrect constant name.

Jiri Slaby (1):
      WDEV: ath5k, typecheck on nonDEBUG

Johannes Berg (23):
      mac80211: allow sending multicast frames through virtual ports
      mac80211: dissolve pre-rx handlers
      cfg80211 API for channels/bitrates, mac80211 and driver conversion
      nl80211: export hardware bitrate/channel capabilities
      mac80211: fix scan band off-by-one error
      mac80211: remove port control enable switch, clean up sta flags
      wireless: fix ERP rate flags
      mac80211: split ieee80211_txrx_result
      mac80211: split RX_DROP
      mac80211: clean up some things in the RX path
      mac80211: remove "dynamic" RX/TX handlers
      mac80211: move some code into ieee80211_invoke_rx_handlers
      mac80211: defer master netdev allocation to ieee80211_register_hw
      mac80211: give burst time in txop rather than 0.1msec units
      mac80211: fix ecw2cw brain-damage
      rtl818x: fix RTS/CTS-less transmit
      b43(legacy): include full timestamp in beacon frames
      mac80211: convert sta_info.pspoll to a flag
      mac80211: invoke set_tim() callback after setting own TIM info
      mac80211: remove sta TIM flag, fix expiry TIM handling
      mac80211: consolidate TIM handling code
      adm8211: fix sparse warnings
      p54: fix sparse warnings

Luis R. Rodriguez (7):
      ath5k: Port to new bitrate/channel API
      ath5k: Cleanup after API changes
      ath5k: ath5k_copy_channels() was not setting the channel band
      ath5k: Use our own Kconfig file, we'll be expanding this shortly
      ath5k: Port debug.c over to the new band API and enable as build option
      ath5k: Use software encryption for now
      ath5k/phy.c: fix negative array index

Marcin Slusarz (1):
      ipw2200: le*_add_cpu conversion

Matthias Kaehlcke (3):
      prism54: Convert acl->sem in a mutex
      prism54: Convert stats_sem in a mutex
      prism54: Convert wpa_sem in a mutex

Michael Buesch (5):
      b43: Fix bandswitch
      mac80211: Extend filter flag documentation about unsupported flags
      b43: Add HostFlags HI support
      zd1211rw: Fix beacon filter flags thinko
      ssb: Add support for 8bit register access

Michael Wu (3):
      nl80211: Add monitor interface configuration flags
      mac80211: Use monitor configuration flags
      mac80211: Add cooked monitor mode support

Mohamed Abbas (2):
      iwlwifi: initialize ieee80211_channel->hw_value
      iwlwifi: set rate_idx correctly from plcp

Randy Dunlap (1):
      wireless: rt2x00: fix driver menu indenting

Reinette Chatre (2):
      iwlwifi: Update iwlwifi version stamp to 1.2.26
      iwlwifi: fix name of function in comment (_rx_card_state_notif)

Roel Kluin (2):
      wireless/iwlwifi/iwl-4965.c: add parentheses
      wireless: Convert to list_for_each_entry_rcu()

Ron Rindjunsky (14):
      mac80211: A-MPDU Tx add session's and low level driver's API
      mac80211: A-MPDU Tx add MLME structures
      mac80211: A-MPDU Tx adding basic functionality
      mac80211: A-MPDU Tx adding qdisc support
      mac80211: A-MPDU Tx MLME data initialization
      mac80211: A-MPDU add debugfs support
      mac80211: A-MPDU Tx change tx_status to support Block Ack data
      mac80211: A-MPDU Tx add delBA from recipient support
      iwlwifi: A-MPDU Tx conform API to mac80211
      iwlwifi: A-MPDU Tx conform flows to mac80211
      iwlwifi: A-MPDU Tx conform block Ack rate scaling to mac80211
      iwlwifi: A-MPDU Tx activation by load measures
      mac80211: adjustable number of bits for qdisc pool
      iwlwifi: remove IWL{4965,3945}_QOS

S.Çağlar Onur (2):
      net/mac80211/: Use time_* macros
      drivers/net/wireless/atmel.c: Use time_* macros

Stefano Brivio (4):
      rc80211-pid: fix rate adjustment
      b43legacy: add definitions for MAC control register
      b43legacy: fix upload of beacon packets to the hardware
      b43legacy: fix B43legacy_WARN_ON macro

Tomas Winkler (7):
      mac80211: set assoc flag to bss_conf
      iwlwifi: enable 802.11n in Kconfig
      iwlwifi: Fix HT compilation breakage caused by cfg80211 API for channels/bitrates patch
      iwlwifi: change iwl->priv iwl_priv * type in iwl-YYY-io.h
      iwlwifi: Add tx_ant_num hw setting variable
      iwlwifi: remove twice defined CSR register
      wireless: update US regulatory domain

 drivers/net/wireless/Kconfig                     |   44 +-
 drivers/net/wireless/adm8211.c                   |   88 +-
 drivers/net/wireless/adm8211.h                   |   65 +--
 drivers/net/wireless/ath5k/Kconfig               |   37 +
 drivers/net/wireless/ath5k/Makefile              |    8 +-
 drivers/net/wireless/ath5k/ath5k.h               |  106 ++--
 drivers/net/wireless/ath5k/base.c                |  409 +++++----
 drivers/net/wireless/ath5k/base.h                |   18 +-
 drivers/net/wireless/ath5k/debug.c               |   55 +-
 drivers/net/wireless/ath5k/debug.h               |   23 +-
 drivers/net/wireless/ath5k/hw.c                  |  170 +---
 drivers/net/wireless/ath5k/initvals.c            |    6 +-
 drivers/net/wireless/ath5k/phy.c                 |   88 +-
 drivers/net/wireless/atmel.c                     |    5 +-
 drivers/net/wireless/b43/b43.h                   |   79 +-
 drivers/net/wireless/b43/main.c                  |  428 ++++++----
 drivers/net/wireless/b43/main.h                  |    4 +-
 drivers/net/wireless/b43/sysfs.c                 |   89 +--
 drivers/net/wireless/b43/xmit.c                  |   95 ++-
 drivers/net/wireless/b43legacy/b43legacy.h       |   46 +-
 drivers/net/wireless/b43legacy/main.c            |  433 +++++-----
 drivers/net/wireless/b43legacy/xmit.c            |   78 +-
 drivers/net/wireless/ipw2200.c                   |    4 +-
 drivers/net/wireless/iwlwifi/Kconfig             |   17 +-
 drivers/net/wireless/iwlwifi/iwl-3945-commands.h |   19 +-
 drivers/net/wireless/iwlwifi/iwl-3945-hw.h       |    1 -
 drivers/net/wireless/iwlwifi/iwl-3945-io.h       |   39 +-
 drivers/net/wireless/iwlwifi/iwl-3945-rs.c       |   90 +--
 drivers/net/wireless/iwlwifi/iwl-3945.c          |   38 +-
 drivers/net/wireless/iwlwifi/iwl-3945.h          |   22 +-
 drivers/net/wireless/iwlwifi/iwl-4965-commands.h |   43 +-
 drivers/net/wireless/iwlwifi/iwl-4965-hw.h       |    1 -
 drivers/net/wireless/iwlwifi/iwl-4965-io.h       |   39 +-
 drivers/net/wireless/iwlwifi/iwl-4965-rs.c       |  371 +++++++--
 drivers/net/wireless/iwlwifi/iwl-4965-rs.h       |   12 +
 drivers/net/wireless/iwlwifi/iwl-4965.c          |  865 ++++++-------------
 drivers/net/wireless/iwlwifi/iwl-4965.h          |  119 +--
 drivers/net/wireless/iwlwifi/iwl3945-base.c      |  469 +++--------
 drivers/net/wireless/iwlwifi/iwl4965-base.c      |  687 +++++-----------
 drivers/net/wireless/libertas/assoc.c            |   20 +-
 drivers/net/wireless/libertas/assoc.h            |    1 -
 drivers/net/wireless/libertas/cmd.c              |   23 +-
 drivers/net/wireless/libertas/cmdresp.c          |    6 +-
 drivers/net/wireless/libertas/debugfs.c          |    2 +-
 drivers/net/wireless/libertas/dev.h              |    4 +-
 drivers/net/wireless/libertas/join.c             |   20 -
 drivers/net/wireless/libertas/join.h             |    2 -
 drivers/net/wireless/libertas/main.c             |   14 +-
 drivers/net/wireless/libertas/scan.c             |   39 +-
 drivers/net/wireless/p54.h                       |    4 -
 drivers/net/wireless/p54common.c                 |   92 ++-
 drivers/net/wireless/p54common.h                 |   75 --
 drivers/net/wireless/prism54/isl_ioctl.c         |   46 +-
 drivers/net/wireless/prism54/islpci_dev.c        |    2 +-
 drivers/net/wireless/prism54/islpci_dev.h        |    6 +-
 drivers/net/wireless/rt2x00/Kconfig              |   62 ++-
 drivers/net/wireless/rt2x00/Makefile             |   37 +-
 drivers/net/wireless/rt2x00/rt2400pci.c          |  436 ++++++----
 drivers/net/wireless/rt2x00/rt2400pci.h          |    8 +-
 drivers/net/wireless/rt2x00/rt2500pci.c          |  442 ++++++----
 drivers/net/wireless/rt2x00/rt2500pci.h          |    6 +-
 drivers/net/wireless/rt2x00/rt2500usb.c          |  512 +++++++-----
 drivers/net/wireless/rt2x00/rt2500usb.h          |    9 +-
 drivers/net/wireless/rt2x00/rt2x00.h             |  339 +++++----
 drivers/net/wireless/rt2x00/rt2x00config.c       |  163 ++--
 drivers/net/wireless/rt2x00/rt2x00debug.c        |  124 ++-
 drivers/net/wireless/rt2x00/rt2x00debug.h        |    2 +-
 drivers/net/wireless/rt2x00/rt2x00dev.c          |  907 +++++++++-----------
 drivers/net/wireless/rt2x00/rt2x00dump.h         |    8 +-
 drivers/net/wireless/rt2x00/rt2x00firmware.c     |   43 +-
 drivers/net/wireless/rt2x00/rt2x00leds.c         |  217 +++++
 drivers/net/wireless/rt2x00/rt2x00leds.h         |   63 ++
 drivers/net/wireless/rt2x00/rt2x00lib.h          |  101 +++-
 drivers/net/wireless/rt2x00/rt2x00mac.c          |  243 ++++--
 drivers/net/wireless/rt2x00/rt2x00pci.c          |  286 ++++---
 drivers/net/wireless/rt2x00/rt2x00pci.h          |   67 ++-
 drivers/net/wireless/rt2x00/rt2x00queue.c        |  299 +++++++
 drivers/net/wireless/rt2x00/rt2x00queue.h        |  457 ++++++++++
 drivers/net/wireless/rt2x00/rt2x00reg.h          |   75 +--
 drivers/net/wireless/rt2x00/rt2x00rfkill.c       |    2 +-
 drivers/net/wireless/rt2x00/rt2x00ring.h         |  290 -------
 drivers/net/wireless/rt2x00/rt2x00usb.c          |  324 ++++---
 drivers/net/wireless/rt2x00/rt2x00usb.h          |  161 +++-
 drivers/net/wireless/rt2x00/rt61pci.c            |  640 +++++++-------
 drivers/net/wireless/rt2x00/rt61pci.h            |   33 +-
 drivers/net/wireless/rt2x00/rt73usb.c            |  521 ++++++------
 drivers/net/wireless/rt2x00/rt73usb.h            |   24 +-
 drivers/net/wireless/rtl8180.h                   |    2 +-
 drivers/net/wireless/rtl8180_dev.c               |  103 ++-
 drivers/net/wireless/rtl8180_grf5101.c           |    5 +-
 drivers/net/wireless/rtl8180_max2820.c           |    5 +-
 drivers/net/wireless/rtl8180_rtl8225.c           |   15 +-
 drivers/net/wireless/rtl8180_sa2400.c            |    5 +-
 drivers/net/wireless/rtl8187.h                   |    2 +-
 drivers/net/wireless/rtl8187_dev.c               |   92 ++-
 drivers/net/wireless/rtl8187_rtl8225.c           |   15 +-
 drivers/net/wireless/rtl818x.h                   |   70 --
 drivers/net/wireless/strip.c                     |    6 +-
 drivers/net/wireless/zd1211rw/zd_chip.c          |   23 +-
 drivers/net/wireless/zd1211rw/zd_chip.h          |    9 +-
 drivers/net/wireless/zd1211rw/zd_ieee80211.c     |   11 +-
 drivers/net/wireless/zd1211rw/zd_mac.c           |  172 ++---
 drivers/net/wireless/zd1211rw/zd_mac.h           |    2 +-
 drivers/ssb/main.c                               |   18 +
 drivers/ssb/pci.c                                |   28 +
 drivers/ssb/pcmcia.c                             |   32 +
 include/linux/nl80211.h                          |   99 +++
 include/linux/ssb/ssb.h                          |   10 +
 include/net/cfg80211.h                           |   24 +-
 include/net/mac80211.h                           |  344 ++++----
 include/net/wireless.h                           |  168 ++++
 net/mac80211/Makefile                            |    1 -
 net/mac80211/cfg.c                               |   30 +-
 net/mac80211/debugfs.c                           |   47 +-
 net/mac80211/debugfs_netdev.c                    |    9 -
 net/mac80211/debugfs_sta.c                       |  136 +++-
 net/mac80211/ieee80211.c                         |  649 +++++++++++----
 net/mac80211/ieee80211_i.h                       |  164 +---
 net/mac80211/ieee80211_iface.c                   |    4 +
 net/mac80211/ieee80211_ioctl.c                   |  127 ++--
 net/mac80211/ieee80211_rate.c                    |   15 +-
 net/mac80211/ieee80211_rate.h                    |   28 +-
 net/mac80211/ieee80211_sta.c                     |  996 ++++++++++++++--------
 net/mac80211/rc80211_pid_algo.c                  |  155 ++--
 net/mac80211/rc80211_simple.c                    |   69 +-
 net/mac80211/regdomain.c                         |  152 ----
 net/mac80211/rx.c                                |  572 +++++++------
 net/mac80211/sta_info.c                          |  138 ++--
 net/mac80211/sta_info.h                          |   96 ++-
 net/mac80211/tx.c                                |  323 ++++---
 net/mac80211/util.c                              |  142 +---
 net/mac80211/wep.c                               |   16 +-
 net/mac80211/wep.h                               |    4 +-
 net/mac80211/wme.c                               |  135 +++-
 net/mac80211/wme.h                               |   23 +-
 net/mac80211/wpa.c                               |   72 +-
 net/mac80211/wpa.h                               |   12 +-
 net/wireless/Makefile                            |    2 +-
 net/wireless/core.c                              |   41 +
 net/wireless/core.h                              |    3 +
 net/wireless/nl80211.c                           |  118 +++-
 net/wireless/reg.c                               |  159 ++++
 net/wireless/util.c                              |   98 +++
 143 files changed, 10183 insertions(+), 8080 deletions(-)
 create mode 100644 drivers/net/wireless/ath5k/Kconfig
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00leds.c
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00leds.h
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.c
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.h
 delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ring.h
 delete mode 100644 net/mac80211/regdomain.c
 create mode 100644 net/wireless/reg.c
 create mode 100644 net/wireless/util.c

Omnibus patch is available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6.26-2008-02-20.patch.bz2

-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* Re: [PATCH 02/04] smc91x: introduce platform data flags
From: Magnus Damm @ 2008-02-21  2:34 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: netdev, lethal, akpm
In-Reply-To: <alpine.LFD.1.00.0802201044270.2732@xanadu.home>

On Thu, Feb 21, 2008 at 12:58 AM, Nicolas Pitre <nico@cam.org> wrote:
> On Wed, 20 Feb 2008, Magnus Damm wrote:
>
>  > This patch introduces struct smc91x_platdata and modifies the driver so
>  > bus width is checked during run time using SMC_nBIT() instead of
>  > SMC_CAN_USE_nBIT.
>  >
>  > Signed-off-by: Magnus Damm <damm@igel.co.jp>
>  > ---
>
>  NAK.
>
>  The SMC91C111 (for example) is often used on devices which have a CPU
>  clock barely higher than the network throughput, hence it is crutial for
>  those devices to have the most efficient access possible to the chip or
>  performance will suffer.  This is the main reason behind the heavily
>  macroized register access so things are always optimized for the data
>  bus capabilities at compile time.

I understand that you want to keep the code as fast as possible. So do
I. But I want to remove the need to modify smc91x.h for each board I
want to support. It is much better in my opinion to have a wide range
of boards supported but a little bit lower throughput compared to only
a few boards supported and excellent performance... People can always
modify the header file by themselves if they want to squeeze out that
extra percent of performance. But maybe that's just me wanting to
support more boards than I have time for. =)

>  This patch introduces a runtimes test on lp->cfg.flags for every
>  register access even on those platforms not using the platform data
>  based bus configuration at all.

Right. It's kind of hard to avoid the check if you want to select the
bus width using platform data though... =) I understand you want to
keep the compile time optimization working well, and this patch is not
so good in that regard.

>  I think you should add a SMC_DYNAMIC_BUS_CONFIG and redefine SMC_nBITS()
>  so they dereference cfg.flags only when it is defined.

Sure, good idea. I'll fix that. Do you mind if I make that the default
behavior? So boards that doesn't have any hard coded configuration in
smc91x.h can use the platform data flags method for configuration
instead.

Thanks for your feedback!

/ magnus

^ permalink raw reply

* Re: [PATCH 04/04] smc91x: add insw/outsw to default config
From: Magnus Damm @ 2008-02-21  2:41 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: netdev, lethal, akpm
In-Reply-To: <alpine.LFD.1.00.0802201059080.2732@xanadu.home>

On Thu, Feb 21, 2008 at 1:00 AM, Nicolas Pitre <nico@cam.org> wrote:
> On Wed, 20 Feb 2008, Magnus Damm wrote:
>
>  > This patch makes sure SMC_insw()/SMC_outsw() are defined for the
>  > default configuration. Without this change BUG()s will be triggered
>  > when using 16-bit only platform data and the default configuration.
>  >
>  > Signed-off-by: Magnus Damm <damm@igel.co.jp>
>
>  You should have introduced this patch as 3/4 instead of 4/4 so to make
>  sure the series won't  create a non functional kernel between 3/4 and
>  4/4.

Yes, you are right. At least in theory. =) In practice this doesn't
matter so much since the boards modified by 3/4 are all in a
half-assed state. I'm working on fixing that up though, and using
platform data flags would be help a lot. =)

Speaking of smc91x and sh-boards, I guess the patch below is too late
for 2.6.25? We have the rest of the board support bits in place
already but no ethernet. I posted the smc91x patch below a bit too
late unfortunately _and_ i forgot to CC you, so my bad.

http://www.mail-archive.com/netdev@vger.kernel.org/msg61390.html

Thanks for your help!

/ magnus

^ permalink raw reply

* Re: [PATCH 00/04] smc91x: request bus width using platform data
From: Magnus Damm @ 2008-02-21  2:46 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: netdev, lethal, akpm
In-Reply-To: <alpine.LFD.1.00.0802201028570.2732@xanadu.home>

On Thu, Feb 21, 2008 at 12:36 AM, Nicolas Pitre <nico@cam.org> wrote:
> On Wed, 20 Feb 2008, Magnus Damm wrote:
>
>  > These patches make it possible to request bus width in the platform data.
>  >
>  > Instead of keep on updating smc91x.h with board specific configuration,
>  > use platform data to pass along bus width and irq flags to the driver.
>  > This change is designed to be backwards-compatible, so all boards configured
>  > in the header file should just work as usual.
>
>  Thank you for doing this work.  I really meant to do it, and commit
>  09779c6df2dbe95483269d194b327d41fe2cc57e was the first step towards that
>  goal, but as you can see we're nearly two years later and I didn't do
>  it.

It's only a lot of boring search and replace work so I don't blame you
for not doing it. =) I'm glad that you like the idea of keeping bus
width flags with the platform data. Hopefully this will make it easier
to support smc91x on a wide range of boards.

>  I have a few comments though.  I will reply to those messages
>  separately.

Great, thanks. Please let me know which way you think is the best and
I'll rework the patches and repost.

Cheers,

/ magnus

^ permalink raw reply

* Re: sungem triggers NAPI warning
From: Benjamin Herrenschmidt @ 2008-02-21  2:54 UTC (permalink / raw)
  To: Johannes Berg; +Cc: netdev
In-Reply-To: <1203457124.3874.2.camel@johannes.berg>


On Tue, 2008-02-19 at 22:38 +0100, Johannes Berg wrote:
> I started getting this warning with recent kernels:

Do that help ?

In gem_poll(), do:

-  work_done += gem_rx(gp, budget);
+  work_done += gem_rx(gp, budget - work_done);

Cheers,
Ben.

> [  773.908927] ------------[ cut here ]------------
> [  773.908954] Badness at net/core/dev.c:2204
> [  773.908958] NIP: c0277960 LR: c0277948 CTR: c02b9948
> [  773.908963] REGS: ee8f1800 TRAP: 0700   Not tainted  (2.6.25-rc2-00261-g54a6132-dirty)
> [  773.908966] MSR: 00029032 <EE,ME,IR,DR>  CR: 84224448  XER: 20000000
> [  773.908976] TASK = eefa0e00[3143] 'Xorg' THREAD: ee8f0000
> [  773.908979] GPR00: 00000001 ee8f18b0 eefa0e00 0000005e ef8d0c30 00000044 00000000 864a0000 
> [  773.908988] GPR08: 00004a86 f2280000 00000000 00000044 00000000 101f85a4 00000000 ee8f1d9c 
> [  773.908997] GPR16: ee8f1da0 ee8f1da4 00000000 ee8f1d94 ee8f1d98 c0620000 c08751a4 0000b994 
> [  773.909006] GPR24: c08750e4 00000000 000000ec 0000005e ee8f0000 00000000 00000040 ef82454c 
> [  773.909016] NIP [c0277960] net_rx_action+0x190/0x218
> [  773.909027] LR [c0277948] net_rx_action+0x178/0x218
> [  773.909032] Call Trace:
> [  773.909035] [ee8f18b0] [c0277948] net_rx_action+0x178/0x218 (unreliable)
> [  773.909041] [ee8f18f0] [c0034d9c] __do_softirq+0x84/0xf8
> [  773.909053] [ee8f1910] [c0006aac] do_softirq+0x58/0x5c
> [  773.909063] [ee8f1920] [c00348d8] irq_exit+0x60/0x80
> [  773.909068] [ee8f1930] [c0006fcc] do_IRQ+0xa8/0xc8
> [  773.909074] [ee8f1940] [c00129d4] ret_from_except+0x0/0x14
> [  773.909086] --- Exception: 501 at _spin_unlock_irqrestore+0x1c/0x54
> [  773.909094]     LR = _spin_unlock_irqrestore+0x18/0x54
> [  773.909098] [ee8f1a20] [c01f39c0] tty_ldisc_try+0x54/0x6c
> [  773.909108] [ee8f1a40] [c01f4d5c] tty_ldisc_ref_wait+0x18/0xb0
> [  773.909114] [ee8f1a80] [c01f4e54] tty_poll+0x60/0xa8
> [  773.909119] [ee8f1aa0] [c00ad734] do_select+0x294/0x4fc
> [  773.909131] [ee8f1d70] [c00adc4c] core_sys_select+0x2b0/0x404
> [  773.909137] [ee8f1ed0] [c00ae510] sys_select+0x140/0x250
> [  773.909142] [ee8f1f10] [c00052ec] ppc_select+0x24/0x150
> [  773.909148] [ee8f1f40] [c0012328] ret_from_syscall+0x0/0x38
> [  773.909153] --- Exception: c01 at 0xfc2b28c
> [  773.909179]     LR = 0x101a4528
> [  773.909181] Instruction dump:
> [  773.909185] 4182ff98 801f0010 7fe3fb78 7fc4f378 7c0903a6 4e800421 7c7b1b78 7f1bf000 
> [  773.909193] 4099ff80 80180204 7c000034 5400d97e <0f000000> 2f800000 419eff68 38000001 
> 
> with a sungem card. I have no idea what to do about it, it doesn't seem
> to be fatal in any way either.
> 
> In order to trigger it, I have to transfer a lot of data. I have
> triggered it now with a full kernel recompilation using -j6 and distcc
> onto a fast machine (with tg3 network, direct cable, gbit), and with
> rsync transferring 26GiB data between the machines.
> 
> johannes


^ permalink raw reply

* [patch 3/6] [POWERPC] pasemi: Add function engine management functions to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-add-fun-alloc --]
[-- Type: text/plain, Size: 2707 bytes --]

Used to allocate functions for crypto/checksum offload.
    
Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -27,6 +27,7 @@
 #define MAX_TXCH 64
 #define MAX_RXCH 64
 #define MAX_FLAGS 64
+#define MAX_FUN 8
 
 static struct pasdma_status *dma_status;
 
@@ -45,6 +46,7 @@ static struct pci_dev *dma_pdev;
 static DECLARE_BITMAP(txch_free, MAX_TXCH);
 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
 static DECLARE_BITMAP(flags_free, MAX_FLAGS);
+static DECLARE_BITMAP(fun_free, MAX_FUN);
 
 /* pasemi_read_iob_reg - read IOB register
  * @reg: Register to read (offset into PCI CFG space)
@@ -440,6 +442,41 @@ void pasemi_dma_clear_flag(int flag)
 }
 EXPORT_SYMBOL(pasemi_dma_clear_flag);
 
+/* pasemi_dma_alloc_fun - Allocate a function engine
+ *
+ * Allocates a function engine to use for crypto/checksum offload
+ * Returns allocated engine (0-8), < 0 on error.
+ */
+int pasemi_dma_alloc_fun(void)
+{
+	int bit;
+
+retry:
+	bit = find_next_bit(fun_free, MAX_FLAGS, 0);
+	if (bit >= MAX_FLAGS)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, fun_free))
+		goto retry;
+
+	return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_fun);
+
+
+/* pasemi_dma_free_fun - Deallocates a function engine
+ * @flag: Engine number to deallocate
+ *
+ * Frees up a function engine so it can be used for other purposes.
+ */
+void pasemi_dma_free_fun(int fun)
+{
+	BUG_ON(test_bit(fun, fun_free));
+	BUG_ON(fun >= MAX_FLAGS);
+	set_bit(fun, fun_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_fun);
+
+
 static void *map_onedev(struct pci_dev *p, int index)
 {
 	struct device_node *dn;
@@ -572,6 +609,9 @@ int pasemi_dma_init(void)
 	for (i = 0; i < MAX_FLAGS; i++)
 		__set_bit(i, flags_free);
 
+	for (i = 0; i < MAX_FUN; i++)
+		__set_bit(i, fun_free);
+
 	/* clear all status flags */
 	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
 	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -472,6 +472,10 @@ extern void pasemi_dma_free_flag(int fla
 extern void pasemi_dma_set_flag(int flag);
 extern void pasemi_dma_clear_flag(int flag);
 
+/* Routines to allocate function engines */
+extern int  pasemi_dma_alloc_fun(void);
+extern void pasemi_dma_free_fun(int fun);
+
 /* Initialize the library, must be called before any other functions */
 extern int pasemi_dma_init(void);
 

-- 


^ permalink raw reply

* [patch 1/6] pasemi_mac: Move RX/TX section enablement to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-move-rx-tx-enable --]
[-- Type: text/plain, Size: 2989 bytes --]

Also stop both rx and tx sections before changing the configuration of
the dma device during init.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -478,6 +478,30 @@ int pasemi_dma_init(void)
 	for (i = 0; i < MAX_RXCH; i++)
 		__set_bit(i, rxch_free);
 
+	i = 1000;
+	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
+	while ((i > 0) && (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1))
+		i--;
+	if (i < 0)
+		printk(KERN_INFO "Warning: Could not disable RX section\n");
+
+	i = 1000;
+	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
+	while ((i > 0) && (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1))
+		i--;
+	if (i < 0)
+		printk(KERN_INFO "Warning: Could not disable TX section\n");
+
+	/* setup resource allocations for the different DMA sections */
+	tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
+	pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
+
+	/* enable tx section */
+	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+
+	/* enable rx section */
+	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+
 	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
 		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
 
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1043,12 +1043,6 @@ static int pasemi_mac_open(struct net_de
 	unsigned int flags;
 	int ret;
 
-	/* enable rx section */
-	write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
-
-	/* enable tx section */
-	write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
-
 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
 		PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 PA Semi, Inc
+ * Copyright (C) 2006-2008 PA Semi, Inc
  *
  * Hardware register layout and descriptor formats for the on-board
  * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
@@ -40,6 +40,11 @@ enum {
 	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
 	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
 	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
+	PAS_DMA_COM_CFG   = 0x114,	/* Common config reg	      */
+	PAS_DMA_TXF_SFLG0 = 0x140,	/* Set flags                  */
+	PAS_DMA_TXF_SFLG1 = 0x144,	/* Set flags                  */
+	PAS_DMA_TXF_CFLG0 = 0x148,	/* Set flags                  */
+	PAS_DMA_TXF_CFLG1 = 0x14c,	/* Set flags                  */
 };
 
 

-- 


^ permalink raw reply

* [patch 0/6] pasemi_mac updates for 2.6.26
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux

Here's a set of updates for pasemi_mac for 2.6.26. Some of them touch
the dma_lib in the platform code as well, but it's easier if it's all
merged through netdev to avoid dependencies.

Major highlights are jumbo frame support and ethtool basics, the rest
is mostly minor plumbing around it.

-- 


^ permalink raw reply

* [patch 2/6] [POWERPC] pasemi: Add flag management functions to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-add-flag-alloc --]
[-- Type: text/plain, Size: 3738 bytes --]

Add functions to manage the channel syncronization flags to dma_lib
    
Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -26,6 +26,7 @@
 
 #define MAX_TXCH 64
 #define MAX_RXCH 64
+#define MAX_FLAGS 64
 
 static struct pasdma_status *dma_status;
 
@@ -43,6 +44,7 @@ static struct pci_dev *dma_pdev;
 
 static DECLARE_BITMAP(txch_free, MAX_TXCH);
 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
+static DECLARE_BITMAP(flags_free, MAX_FLAGS);
 
 /* pasemi_read_iob_reg - read IOB register
  * @reg: Register to read (offset into PCI CFG space)
@@ -373,6 +375,71 @@ void pasemi_dma_free_buf(struct pasemi_d
 }
 EXPORT_SYMBOL(pasemi_dma_free_buf);
 
+/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
+ *
+ * Allocates a flag for use with channel syncronization (event descriptors).
+ * Returns allocated flag (0-63), < 0 on error.
+ */
+int pasemi_dma_alloc_flag(void)
+{
+	int bit;
+
+retry:
+	bit = find_next_bit(flags_free, MAX_FLAGS, 0);
+	if (bit >= MAX_FLAGS)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, flags_free))
+		goto retry;
+
+	return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_flag);
+
+
+/* pasemi_dma_free_flag - Deallocates a flag (event)
+ * @flag: Flag number to deallocate
+ *
+ * Frees up a flag so it can be reused for other purposes.
+ */
+void pasemi_dma_free_flag(int flag)
+{
+	BUG_ON(test_bit(flag, flags_free));
+	BUG_ON(flag >= MAX_FLAGS);
+	set_bit(flag, flags_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_flag);
+
+
+/* pasemi_dma_set_flag - Sets a flag (event) to 1
+ * @flag: Flag number to set active
+ *
+ * Sets the flag provided to 1.
+ */
+void pasemi_dma_set_flag(int flag)
+{
+	BUG_ON(flag >= MAX_FLAGS);
+	if (flag < 32)
+		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
+	else
+		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_set_flag);
+
+/* pasemi_dma_clear_flag - Sets a flag (event) to 0
+ * @flag: Flag number to set inactive
+ *
+ * Sets the flag provided to 0.
+ */
+void pasemi_dma_clear_flag(int flag)
+{
+	BUG_ON(flag >= MAX_FLAGS);
+	if (flag < 32)
+		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
+	else
+		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_clear_flag);
+
 static void *map_onedev(struct pci_dev *p, int index)
 {
 	struct device_node *dn;
@@ -502,6 +569,13 @@ int pasemi_dma_init(void)
 	/* enable rx section */
 	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
 
+	for (i = 0; i < MAX_FLAGS; i++)
+		__set_bit(i, flags_free);
+
+	/* clear all status flags */
+	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
+	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
+
 	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
 		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
 
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -466,6 +466,12 @@ extern void *pasemi_dma_alloc_buf(struct
 extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
 				dma_addr_t *handle);
 
+/* Routines to allocate flags (events) for channel syncronization */
+extern int  pasemi_dma_alloc_flag(void);
+extern void pasemi_dma_free_flag(int flag);
+extern void pasemi_dma_set_flag(int flag);
+extern void pasemi_dma_clear_flag(int flag);
+
 /* Initialize the library, must be called before any other functions */
 extern int pasemi_dma_init(void);
 

-- 


^ permalink raw reply

* [patch 4/6] pasemi_mac: jumbo frame support
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-jumbo-frames --]
[-- Type: text/plain, Size: 18106 bytes --]

First cut at jumbo frame support. To support large MTU, one or several
separate channels must be allocated to calculate the TCP/UDP checksum
separately, since the mac lacks enough buffers to hold a whole packet
while it's being calculated.

Furthermore, it seems that a single function channel is not quite
enough to feed one of the 10Gig links, so allocate two channels for
XAUI interfaces.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.25/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.c
+++ 2.6.25/drivers/net/pasemi_mac.c
@@ -59,11 +59,12 @@
 /* Must be a power of two */
 #define RX_RING_SIZE 2048
 #define TX_RING_SIZE 4096
+#define CS_RING_SIZE (TX_RING_SIZE*2)
 
 #define LRO_MAX_AGGR 64
 
 #define PE_MIN_MTU	64
-#define PE_MAX_MTU	1500
+#define PE_MAX_MTU	9000
 #define PE_DEF_MTU	ETH_DATA_LEN
 
 #define DEFAULT_MSG_ENABLE	  \
@@ -81,6 +82,7 @@
 #define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
 #define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
 #define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
 
 #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
 				 & ((ring)->size - 1))
@@ -322,6 +324,103 @@ static int pasemi_mac_unmap_tx_skb(struc
 	return (nfrags + 3) & ~1;
 }
 
+static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
+{
+	struct pasemi_mac_csring *ring;
+	u32 val;
+	unsigned int cfg;
+	int chno;
+
+	ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
+				       offsetof(struct pasemi_mac_csring, chan));
+
+	if (!ring) {
+		dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
+		goto out_chan;
+	}
+
+	chno = ring->chan.chno;
+
+	ring->size = CS_RING_SIZE;
+	ring->next_to_fill = 0;
+
+	/* Allocate descriptors */
+	if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
+		goto out_ring_desc;
+
+	write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
+		      PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
+	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
+	val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
+
+	write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
+
+	ring->events[0] = pasemi_dma_alloc_flag();
+	ring->events[1] = pasemi_dma_alloc_flag();
+	if (ring->events[0] < 0 || ring->events[1] < 0)
+		goto out_flags;
+
+	pasemi_dma_clear_flag(ring->events[0]);
+	pasemi_dma_clear_flag(ring->events[1]);
+
+	ring->fun = pasemi_dma_alloc_fun();
+	if (ring->fun < 0)
+		goto out_fun;
+
+	cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
+	      PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
+	      PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+	write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
+
+	/* enable channel */
+	pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
+					   PAS_DMA_TXCHAN_TCMDSTA_DB |
+					   PAS_DMA_TXCHAN_TCMDSTA_DE |
+					   PAS_DMA_TXCHAN_TCMDSTA_DA);
+
+	return ring;
+
+out_fun:
+out_flags:
+	if (ring->events[0] >= 0)
+		pasemi_dma_free_flag(ring->events[0]);
+	if (ring->events[1] >= 0)
+		pasemi_dma_free_flag(ring->events[1]);
+	pasemi_dma_free_ring(&ring->chan);
+out_ring_desc:
+	pasemi_dma_free_chan(&ring->chan);
+out_chan:
+
+	return NULL;
+}
+
+static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
+{
+	int i;
+	mac->cs[0] = pasemi_mac_setup_csring(mac);
+	if (mac->type == MAC_TYPE_XAUI)
+		mac->cs[1] = pasemi_mac_setup_csring(mac);
+	else
+		mac->cs[1] = 0;
+
+	for (i = 0; i < MAX_CS; i++)
+		if (mac->cs[i])
+			mac->num_cs++;
+}
+
+static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
+{
+	pasemi_dma_stop_chan(&csring->chan);
+	pasemi_dma_free_flag(csring->events[0]);
+	pasemi_dma_free_flag(csring->events[1]);
+	pasemi_dma_free_ring(&csring->chan);
+	pasemi_dma_free_chan(&csring->chan);
+}
+
 static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
 {
 	struct pasemi_mac_rxring *ring;
@@ -445,7 +544,7 @@ pasemi_mac_setup_tx_resources(const stru
 	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
 	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
 	      PAS_DMA_TXCHAN_CFG_UP |
-	      PAS_DMA_TXCHAN_CFG_WT(2);
+	      PAS_DMA_TXCHAN_CFG_WT(4);
 
 	if (translation_enabled())
 		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
@@ -810,13 +909,21 @@ restart:
 		u64 mactx = TX_DESC(txring, i);
 		struct sk_buff *skb;
 
-		skb = TX_DESC_INFO(txring, i+1).skb;
-		nr_frags = TX_DESC_INFO(txring, i).dma;
-
 		if ((mactx  & XCT_MACTX_E) ||
 		    (*chan->status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
 
+		/* Skip over control descriptors */
+		if (!(mactx & XCT_MACTX_LLEN_M)) {
+			TX_DESC(txring, i) = 0;
+			TX_DESC(txring, i+1) = 0;
+			buf_count = 2;
+			continue;
+		}
+
+		skb = TX_DESC_INFO(txring, i+1).skb;
+		nr_frags = TX_DESC_INFO(txring, i).dma;
+
 		if (unlikely(mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
@@ -1058,6 +1165,12 @@ static int pasemi_mac_open(struct net_de
 	if (!mac->tx)
 		goto out_tx_ring;
 
+	if (dev->mtu > 1500) {
+		pasemi_mac_setup_csrings(mac);
+		if (!mac->num_cs)
+			goto out_tx_ring;
+	}
+
 	/* 0x3ff with 33MHz clock is about 31us */
 	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1241,7 +1354,7 @@ static int pasemi_mac_close(struct net_d
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int sta;
-	int rxch, txch;
+	int rxch, txch, i;
 
 	rxch = rx_ring(mac)->chan.chno;
 	txch = tx_ring(mac)->chan.chno;
@@ -1286,6 +1399,9 @@ static int pasemi_mac_close(struct net_d
 	free_irq(mac->tx->chan.irq, mac->tx);
 	free_irq(mac->rx->chan.irq, mac->rx);
 
+	for (i = 0; i < mac->num_cs; i++)
+		pasemi_mac_free_csring(mac->cs[i]);
+
 	/* Free resources */
 	pasemi_mac_free_rx_resources(mac);
 	pasemi_mac_free_tx_resources(mac);
@@ -1293,35 +1409,113 @@ static int pasemi_mac_close(struct net_d
 	return 0;
 }
 
+static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
+				    const dma_addr_t *map,
+				    const unsigned int *map_size,
+				    struct pasemi_mac_txring *txring,
+				    struct pasemi_mac_csring *csring)
+{
+	u64 fund;
+	dma_addr_t cs_dest;
+	const int nh_off = skb_network_offset(skb);
+	const int nh_len = skb_network_header_len(skb);
+	const int nfrags = skb_shinfo(skb)->nr_frags;
+	int cs_size, i, fill, hdr, cpyhdr, evt;
+	dma_addr_t csdma;
+
+	fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
+	       XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+	       XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
+	       XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
+
+	switch (ip_hdr(skb)->protocol) {
+	case IPPROTO_TCP:
+		fund |= XCT_FUN_SIG_TCP4;
+		/* TCP checksum is 16 bytes into the header */
+		cs_dest = map[0] + skb_transport_offset(skb) + 16;
+		break;
+	case IPPROTO_UDP:
+		fund |= XCT_FUN_SIG_UDP4;
+		/* UDP checksum is 6 bytes into the header */
+		cs_dest = map[0] + skb_transport_offset(skb) + 6;
+		break;
+	default:
+		WARN_ON(1);
+	}
+
+	/* Do the checksum offloaded */
+	fill = csring->next_to_fill;
+	hdr = fill;
+
+	CS_DESC(csring, fill++) = fund;
+	/* Room for 8BRES. Checksum result is really 2 bytes into it */
+	csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
+	CS_DESC(csring, fill++) = 0;
+
+	CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
+	for (i = 1; i <= nfrags; i++)
+		CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+
+	fill += i;
+	if (fill & 1)
+		fill++;
+
+	/* Copy the result into the TCP packet */
+	cpyhdr = fill;
+	CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+				  XCT_FUN_LLEN(2) | XCT_FUN_SE;
+	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
+	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
+	fill++;
+
+	evt = !csring->last_event;
+	csring->last_event = evt;
+
+	/* Event handshaking with MAC TX */
+	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
+	CS_DESC(csring, fill++) = 0;
+	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
+	CS_DESC(csring, fill++) = 0;
+	csring->next_to_fill = fill & (CS_RING_SIZE-1);
+
+	cs_size = fill - hdr;
+	write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
+
+	/* TX-side event handshaking */
+	fill = txring->next_to_fill;
+	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
+	TX_DESC(txring, fill++) = 0;
+	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
+	TX_DESC(txring, fill++) = 0;
+	txring->next_to_fill = fill;
+
+	write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
+
+	return;
+}
+
 static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
-	struct pasemi_mac_txring *txring;
-	u64 dflags, mactx;
+	struct pasemi_mac * const mac = netdev_priv(dev);
+	struct pasemi_mac_txring * const txring = tx_ring(mac);
+	struct pasemi_mac_csring *csring;
+	u64 dflags = 0;
+	u64 mactx;
 	dma_addr_t map[MAX_SKB_FRAGS+1];
 	unsigned int map_size[MAX_SKB_FRAGS+1];
 	unsigned long flags;
 	int i, nfrags;
 	int fill;
+	const int nh_off = skb_network_offset(skb);
+	const int nh_len = skb_network_header_len(skb);
 
-	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
-
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const unsigned char *nh = skb_network_header(skb);
+	prefetch(&txring->ring_info);
 
-		switch (ip_hdr(skb)->protocol) {
-		case IPPROTO_TCP:
-			dflags |= XCT_MACTX_CSUM_TCP;
-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-			dflags |= XCT_MACTX_IPO(nh - skb->data);
-			break;
-		case IPPROTO_UDP:
-			dflags |= XCT_MACTX_CSUM_UDP;
-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-			dflags |= XCT_MACTX_IPO(nh - skb->data);
-			break;
-		}
-	}
+	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
 
 	nfrags = skb_shinfo(skb)->nr_frags;
 
@@ -1344,24 +1538,46 @@ static int pasemi_mac_start_tx(struct sk
 		}
 	}
 
-	mactx = dflags | XCT_MACTX_LLEN(skb->len);
+	if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
+		switch (ip_hdr(skb)->protocol) {
+		case IPPROTO_TCP:
+			dflags |= XCT_MACTX_CSUM_TCP;
+			dflags |= XCT_MACTX_IPH(nh_len >> 2);
+			dflags |= XCT_MACTX_IPO(nh_off);
+			break;
+		case IPPROTO_UDP:
+			dflags |= XCT_MACTX_CSUM_UDP;
+			dflags |= XCT_MACTX_IPH(nh_len >> 2);
+			dflags |= XCT_MACTX_IPO(nh_off);
+			break;
+		default:
+			WARN_ON(1);
+		}
+	}
 
-	txring = tx_ring(mac);
+	mactx = dflags | XCT_MACTX_LLEN(skb->len);
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	fill = txring->next_to_fill;
-
 	/* Avoid stepping on the same cache line that the DMA controller
 	 * is currently about to send, so leave at least 8 words available.
 	 * Total free space needed is mactx + fragments + 8
 	 */
-	if (RING_AVAIL(txring) < nfrags + 10) {
+	if (RING_AVAIL(txring) < nfrags + 14) {
 		/* no room -- stop the queue and wait for tx intr */
 		netif_stop_queue(dev);
 		goto out_err;
 	}
 
+	if (mac->num_cs && skb->len > 1540) {
+		csring = mac->cs[mac->last_cs];
+		mac->last_cs = (mac->last_cs+1) % mac->num_cs;
+
+		/* Queue up checksum + event descriptors, if needed */
+		pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
+	}
+
+	fill = txring->next_to_fill;
 	TX_DESC(txring, fill) = mactx;
 	TX_DESC_INFO(txring, fill).dma = nfrags;
 	fill++;
@@ -1441,6 +1657,7 @@ static int pasemi_mac_change_mtu(struct 
 	unsigned int reg;
 	unsigned int rcmdsta;
 	int running;
+	int ret = 0;
 
 	if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
 		return -EINVAL;
@@ -1462,6 +1679,16 @@ static int pasemi_mac_change_mtu(struct 
 		pasemi_mac_pause_rxint(mac);
 		pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
 		pasemi_mac_free_rx_buffers(mac);
+
+	}
+
+	/* Setup checksum channels if large MTU and none already allocated */
+	if (new_mtu > 1500 && !mac->num_cs) {
+		pasemi_mac_setup_csrings(mac);
+		if (!mac->num_cs) {
+			ret = -ENOMEM;
+			goto out;
+		}
 	}
 
 	/* Change maxf, i.e. what size frames are accepted.
@@ -1476,6 +1703,7 @@ static int pasemi_mac_change_mtu(struct 
 	/* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
 	mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
+out:
 	if (running) {
 		write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
 			      rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
@@ -1488,7 +1716,7 @@ static int pasemi_mac_change_mtu(struct 
 		pasemi_mac_intf_enable(mac);
 	}
 
-	return 0;
+	return ret;
 }
 
 static int __devinit
Index: 2.6.25/drivers/net/pasemi_mac.h
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.h
+++ 2.6.25/drivers/net/pasemi_mac.h
@@ -27,6 +27,7 @@
 #include <linux/phy.h>
 
 #define MAX_LRO_DESCRIPTORS 8
+#define MAX_CS	2
 
 struct pasemi_mac_txring {
 	struct pasemi_dmachan chan; /* Must be first */
@@ -51,6 +52,15 @@ struct pasemi_mac_rxring {
 	struct pasemi_mac *mac;	/* Needed in intr handler */
 };
 
+struct pasemi_mac_csring {
+	struct pasemi_dmachan chan;
+	unsigned int	size;
+	unsigned int	next_to_fill;
+	int		events[2];
+	int		last_event;
+	int		fun;
+};
+
 struct pasemi_mac {
 	struct net_device *netdev;
 	struct pci_dev *pdev;
@@ -60,10 +70,12 @@ struct pasemi_mac {
 	struct napi_struct napi;
 
 	int		bufsz; /* RX ring buffer size */
+	int		last_cs;
+	int		num_cs;
+	u32		dma_if;
 	u8		type;
 #define MAC_TYPE_GMAC	1
 #define MAC_TYPE_XAUI	2
-	u32	dma_if;
 
 	u8		mac_addr[6];
 
@@ -74,6 +86,7 @@ struct pasemi_mac {
 
 	struct pasemi_mac_txring *tx;
 	struct pasemi_mac_rxring *rx;
+	struct pasemi_mac_csring *cs[MAX_CS];
 	char		tx_irq_name[10];		/* "eth%d tx" */
 	char		rx_irq_name[10];		/* "eth%d rx" */
 	int	link;
Index: 2.6.25/include/asm-powerpc/pasemi_dma.h
===================================================================
--- 2.6.25.orig/include/asm-powerpc/pasemi_dma.h
+++ 2.6.25/include/asm-powerpc/pasemi_dma.h
@@ -128,11 +128,16 @@ enum {
 #define    PAS_DMA_TXCHAN_TCMDSTA_DA	0x00000100
 #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
+#define    PAS_DMA_TXCHAN_CFG_TY_COPY	0x00000001	/* Type = copy only */
+#define    PAS_DMA_TXCHAN_CFG_TY_FUNC	0x00000002	/* Type = function */
+#define    PAS_DMA_TXCHAN_CFG_TY_XOR	0x00000003	/* Type = xor only */
 #define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
 #define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
 #define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
 					 PAS_DMA_TXCHAN_CFG_TATTR_M)
-#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
+#define    PAS_DMA_TXCHAN_CFG_LPDQ	0x00000800
+#define    PAS_DMA_TXCHAN_CFG_LPSQ	0x00000400
+#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000003c0
 #define    PAS_DMA_TXCHAN_CFG_WT_S	6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
 					 PAS_DMA_TXCHAN_CFG_WT_M)
@@ -399,11 +404,62 @@ enum {
 				 XCT_COPY_LLEN_M)
 #define XCT_COPY_SE		0x0000000000000001ull
 
+/* Function descriptor fields */
+#define XCT_FUN_T		0x8000000000000000ull
+#define XCT_FUN_ST		0x4000000000000000ull
+#define XCT_FUN_RR_M		0x3000000000000000ull
+#define XCT_FUN_RR_NORES	0x0000000000000000ull
+#define XCT_FUN_RR_8BRES	0x1000000000000000ull
+#define XCT_FUN_RR_24BRES	0x2000000000000000ull
+#define XCT_FUN_RR_40BRES	0x3000000000000000ull
+#define XCT_FUN_I		0x0800000000000000ull
+#define XCT_FUN_O		0x0400000000000000ull
+#define XCT_FUN_E		0x0200000000000000ull
+#define XCT_FUN_FUN_M		0x01c0000000000000ull
+#define XCT_FUN_FUN_S		54
+#define XCT_FUN_FUN(x)		((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
+#define XCT_FUN_CRM_M		0x0038000000000000ull
+#define XCT_FUN_CRM_NOP		0x0000000000000000ull
+#define XCT_FUN_CRM_SIG		0x0008000000000000ull
+#define XCT_FUN_LLEN_M		0x0007ffff00000000ull
+#define XCT_FUN_LLEN_S		32
+#define XCT_FUN_LLEN(x)		((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
+#define XCT_FUN_SHL_M		0x00000000f8000000ull
+#define XCT_FUN_SHL_S		27
+#define XCT_FUN_SHL(x)		((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
+#define XCT_FUN_CHL_M		0x0000000007c00000ull
+#define XCT_FUN_HSZ_M		0x00000000003c0000ull
+#define XCT_FUN_ALG_M		0x0000000000038000ull
+#define XCT_FUN_HP		0x0000000000004000ull
+#define XCT_FUN_BCM_M		0x0000000000003800ull
+#define XCT_FUN_BCP_M		0x0000000000000600ull
+#define XCT_FUN_SIG_M		0x00000000000001f0ull
+#define XCT_FUN_SIG_TCP4	0x0000000000000140ull
+#define XCT_FUN_SIG_TCP6	0x0000000000000150ull
+#define XCT_FUN_SIG_UDP4	0x0000000000000160ull
+#define XCT_FUN_SIG_UDP6	0x0000000000000170ull
+#define XCT_FUN_A		0x0000000000000008ull
+#define XCT_FUN_C		0x0000000000000004ull
+#define XCT_FUN_AL2		0x0000000000000002ull
+#define XCT_FUN_SE		0x0000000000000001ull
+
+/* Function descriptor 8byte result fields */
+#define XCT_FUNRES_8B_CS_M	0x0000ffff00000000ull
+#define XCT_FUNRES_8B_CS_S	32
+#define XCT_FUNRES_8B_CRC_M	0x00000000ffffffffull
+#define XCT_FUNRES_8B_CRC_S	0
+
 /* Control descriptor fields */
 #define CTRL_CMD_T		0x8000000000000000ull
 #define CTRL_CMD_META_EVT	0x2000000000000000ull
 #define CTRL_CMD_O		0x0400000000000000ull
-#define CTRL_CMD_REG_M		0x000000000000000full
+#define CTRL_CMD_ETYPE_M	0x0038000000000000ull
+#define CTRL_CMD_ETYPE_EXT	0x0000000000000000ull
+#define CTRL_CMD_ETYPE_WSET	0x0020000000000000ull
+#define CTRL_CMD_ETYPE_WCLR	0x0028000000000000ull
+#define CTRL_CMD_ETYPE_SET	0x0030000000000000ull
+#define CTRL_CMD_ETYPE_CLR	0x0038000000000000ull
+#define CTRL_CMD_REG_M		0x000000000000007full
 #define CTRL_CMD_REG_S		0
 #define CTRL_CMD_REG(x)		((((long)(x)) << CTRL_CMD_REG_S) & \
 				 CTRL_CMD_REG_M)

-- 


^ permalink raw reply

* [patch 6/6] pasemi_mac: basic ethtool support
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-ethtool --]
[-- Type: text/plain, Size: 9665 bytes --]

First cut at ethtool support, to be completed over time.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.25/drivers/net/Makefile
===================================================================
--- 2.6.25.orig/drivers/net/Makefile
+++ 2.6.25/drivers/net/Makefile
@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
+obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
+pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
 obj-$(CONFIG_MLX4_CORE) += mlx4/
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 
Index: 2.6.25/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.c
+++ 2.6.25/drivers/net/pasemi_mac.c
@@ -55,12 +55,6 @@
  * - Multiqueue RX/TX
  */
 
-
-/* Must be a power of two */
-#define RX_RING_SIZE 2048
-#define TX_RING_SIZE 4096
-#define CS_RING_SIZE (TX_RING_SIZE*2)
-
 #define LRO_MAX_AGGR 64
 
 #define PE_MIN_MTU	64
@@ -77,17 +71,6 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
-#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
-#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
-
-#define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
-				 & ((ring)->size - 1))
-#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
 MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -96,6 +79,8 @@ static int debug = -1;	/* -1 == use DEFA
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
 
+extern const struct ethtool_ops pasemi_mac_ethtool_ops;
+
 static int translation_enabled(void)
 {
 #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
@@ -1148,7 +1133,7 @@ static int pasemi_mac_open(struct net_de
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int flags;
-	int ret;
+	int i, ret;
 
 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
@@ -1171,6 +1156,10 @@ static int pasemi_mac_open(struct net_de
 			goto out_tx_ring;
 	}
 
+	/* Zero out rmon counters */
+	for (i = 0; i < 32; i++)
+		write_mac_reg(mac, PAS_MAC_RMON(i), 0);
+
 	/* 0x3ff with 33MHz clock is about 31us */
 	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1812,6 +1801,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
 	dev->change_mtu = pasemi_mac_change_mtu;
+	dev->ethtool_ops = &pasemi_mac_ethtool_ops;
 
 	if (err)
 		goto out;
Index: 2.6.25/drivers/net/pasemi_mac.h
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.h
+++ 2.6.25/drivers/net/pasemi_mac.h
@@ -26,6 +26,12 @@
 #include <linux/spinlock.h>
 #include <linux/phy.h>
 
+/* Must be a power of two */
+#define RX_RING_SIZE 2048
+#define TX_RING_SIZE 4096
+#define CS_RING_SIZE (TX_RING_SIZE*2)
+
+
 #define MAX_LRO_DESCRIPTORS 8
 #define MAX_CS	2
 
@@ -103,6 +109,16 @@ struct pasemi_mac_buffer {
 	dma_addr_t	dma;
 };
 
+#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
+
+#define RING_USED(ring)	(((ring)->next_to_fill - (ring)->next_to_clean) \
+				& ((ring)->size - 1))
+#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
 
 /* PCI register offsets and formats */
 
@@ -114,6 +130,7 @@ enum {
 	PAS_MAC_CFG_ADR0 = 0x8c,
 	PAS_MAC_CFG_ADR1 = 0x90,
 	PAS_MAC_CFG_TXP = 0x98,
+	PAS_MAC_CFG_RMON = 0x100,
 	PAS_MAC_IPC_CHNL = 0x208,
 };
 
@@ -185,6 +202,8 @@ enum {
 #define PAS_MAC_CFG_TXP_TIFG(x)		(((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
 					 PAS_MAC_CFG_TXP_TIFG_M)
 
+#define PAS_MAC_RMON(r)			(0x100+(r)*4)
+
 #define PAS_MAC_IPC_CHNL_DCHNO_M	0x003f0000
 #define PAS_MAC_IPC_CHNL_DCHNO_S	16
 #define PAS_MAC_IPC_CHNL_DCHNO(x)	(((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
@@ -194,4 +213,5 @@ enum {
 #define PAS_MAC_IPC_CHNL_BCH(x)		(((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
 					 PAS_MAC_IPC_CHNL_BCH_M)
 
+
 #endif /* PASEMI_MAC_H */
Index: 2.6.25/drivers/net/pasemi_mac_ethtool.c
===================================================================
--- /dev/null
+++ 2.6.25/drivers/net/pasemi_mac_ethtool.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2006-2008 PA Semi, Inc
+ *
+ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/inet_lro.h>
+
+#include <asm/pasemi_dma.h>
+#include "pasemi_mac.h"
+
+static struct {
+	const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+	{ "rx-drops" },
+	{ "rx-bytes" },
+	{ "rx-packets" },
+	{ "rx-broadcast-packets" },
+	{ "rx-multicast-packets" },
+	{ "rx-crc-errors" },
+	{ "rx-undersize-errors" },
+	{ "rx-oversize-errors" },
+	{ "rx-short-fragment-errors" },
+	{ "rx-jabber-errors" },
+	{ "rx-64-byte-packets" },
+	{ "rx-65-127-byte-packets" },
+	{ "rx-128-255-byte-packets" },
+	{ "rx-256-511-byte-packets" },
+	{ "rx-512-1023-byte-packets" },
+	{ "rx-1024-1518-byte-packets" },
+	{ "rx-pause-frames" },
+	{ "tx-bytes" },
+	{ "tx-packets" },
+	{ "tx-broadcast-packets" },
+	{ "tx-multicast-packets" },
+	{ "tx-collisions" },
+	{ "tx-late-collisions" },
+	{ "tx-excessive-collisions" },
+	{ "tx-crc-errors" },
+	{ "tx-undersize-errors" },
+	{ "tx-oversize-errors" },
+	{ "tx-64-byte-packets" },
+	{ "tx-65-127-byte-packets" },
+	{ "tx-128-255-byte-packets" },
+	{ "tx-256-511-byte-packets" },
+	{ "tx-512-1023-byte-packets" },
+	{ "tx-1024-1518-byte-packets" },
+};
+
+static int
+pasemi_mac_ethtool_get_settings(struct net_device *netdev,
+			       struct ethtool_cmd *cmd)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	struct phy_device *phydev = mac->phydev;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static void
+pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
+			       struct ethtool_drvinfo *drvinfo)
+{
+	struct pasemi_mac *mac;
+	mac = netdev_priv(netdev);
+
+	/* clear and fill out info */
+	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+	strncpy(drvinfo->driver, "pasemi_mac", 12);
+	strcpy(drvinfo->version, "N/A");
+	strcpy(drvinfo->fw_version, "N/A");
+	strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
+}
+
+static u32
+pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	return mac->msg_enable;
+}
+
+static void
+pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
+				u32 level)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	mac->msg_enable = level;
+}
+
+
+static void
+pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
+				 struct ethtool_ringparam *ering)
+{
+	struct pasemi_mac *mac = netdev->priv;
+
+	ering->tx_max_pending = TX_RING_SIZE/2;
+	ering->tx_pending = RING_USED(mac->tx)/2;
+	ering->rx_max_pending = RX_RING_SIZE/4;
+	ering->rx_pending = RING_USED(mac->rx)/4;
+}
+
+static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(ethtool_stats_keys);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
+		struct ethtool_stats *stats, u64 *data)
+{
+	struct pasemi_mac *mac = netdev->priv;
+	int i;
+
+	data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
+			>> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
+	for (i = 0; i < 32; i++)
+		data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
+}
+
+static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
+				   u8 *data)
+{
+	memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
+}
+
+const struct ethtool_ops pasemi_mac_ethtool_ops = {
+	.get_settings		= pasemi_mac_ethtool_get_settings,
+	.get_drvinfo		= pasemi_mac_ethtool_get_drvinfo,
+	.get_msglevel		= pasemi_mac_ethtool_get_msglevel,
+	.set_msglevel		= pasemi_mac_ethtool_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_ringparam          = pasemi_mac_ethtool_get_ringparam,
+	.get_strings		= pasemi_mac_get_strings,
+	.get_sset_count		= pasemi_mac_get_sset_count,
+	.get_ethtool_stats	= pasemi_mac_get_ethtool_stats,
+};
+

-- 


^ permalink raw reply

* [patch 5/6] pasemi_mac: Enable GSO by default
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev, pasemi-linux
In-Reply-To: <20080221025753.903665000@lixom.net>

[-- Attachment #1: in-progress/pasemi_mac-enable-gso-by-default --]
[-- Type: text/plain, Size: 697 bytes --]

Ethtool support will handle the runtime toggling, but we do quite a bit
better with it on by default so just leave it on for now.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1750,7 +1750,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
 	dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
-			NETIF_F_HIGHDMA;
+			NETIF_F_HIGHDMA | NETIF_F_GSO;
 
 	mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
 	mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;

-- 


^ permalink raw reply

* Re: [PATCH 02/04] smc91x: introduce platform data flags
From: Nicolas Pitre @ 2008-02-21  3:28 UTC (permalink / raw)
  To: Magnus Damm; +Cc: netdev, lethal, akpm
In-Reply-To: <aec7e5c30802201834h7eae8892n7b9434168944eace@mail.gmail.com>

On Thu, 21 Feb 2008, Magnus Damm wrote:

> On Thu, Feb 21, 2008 at 12:58 AM, Nicolas Pitre <nico@cam.org> wrote:
> > On Wed, 20 Feb 2008, Magnus Damm wrote:
> >
> >  > This patch introduces struct smc91x_platdata and modifies the driver so
> >  > bus width is checked during run time using SMC_nBIT() instead of
> >  > SMC_CAN_USE_nBIT.
> >  >
> >  > Signed-off-by: Magnus Damm <damm@igel.co.jp>
> >  > ---
> >
> >  NAK.
> >
> >  The SMC91C111 (for example) is often used on devices which have a CPU
> >  clock barely higher than the network throughput, hence it is crutial for
> >  those devices to have the most efficient access possible to the chip or
> >  performance will suffer.  This is the main reason behind the heavily
> >  macroized register access so things are always optimized for the data
> >  bus capabilities at compile time.
> 
> I understand that you want to keep the code as fast as possible. So do
> I. But I want to remove the need to modify smc91x.h for each board I
> want to support. It is much better in my opinion to have a wide range
> of boards supported but a little bit lower throughput compared to only
> a few boards supported and excellent performance... People can always
> modify the header file by themselves if they want to squeeze out that
> extra percent of performance.

Sure.  That's perfectly fine for new boards.  But existing setups should 
not regress due to this change.

> >  I think you should add a SMC_DYNAMIC_BUS_CONFIG and redefine SMC_nBITS()
> >  so they dereference cfg.flags only when it is defined.
> 
> Sure, good idea. I'll fix that. Do you mind if I make that the default
> behavior? So boards that doesn't have any hard coded configuration in
> smc91x.h can use the platform data flags method for configuration
> instead.

Yes, that's fine.


Nicolas

^ permalink raw reply

* Re: [PATCH 01/04] smc91x: pass along private data
From: Nicolas Pitre @ 2008-02-21  3:35 UTC (permalink / raw)
  To: Magnus Damm; +Cc: netdev, lethal, akpm
In-Reply-To: <aec7e5c30802201814j1f0ab232i60a97c53121fc3b6@mail.gmail.com>

On Thu, 21 Feb 2008, Magnus Damm wrote:

> On Thu, Feb 21, 2008 at 12:42 AM, Nicolas Pitre <nico@cam.org> wrote:
> > On Wed, 20 Feb 2008, Magnus Damm wrote:
> >
> >  > Pass a private data pointer to macros and functions. This makes it easy
> >  > to later on make run time decisions. This patch does not change any logic.
> >  > These changes should be optimized away during compilation.
> >  >
> >  > Signed-off-by: Magnus Damm <damm@igel.co.jp>
> >  > ---
> >
> > > --- 0001/drivers/net/smc91x.c
> >  > +++ work/drivers/net/smc91x.c 2008-02-20 16:52:48.000000000 +0900
> >  > @@ -220,23 +220,23 @@ static void PRINT_PKT(u_char *buf, int l
> >  >
> >  >
> >  >  /* this enables an interrupt in the interrupt mask register */
> >  > -#define SMC_ENABLE_INT(x) do {                                               \
> >  > +#define SMC_ENABLE_INT(priv, x) do {                                 \
> >  >       unsigned char mask;                                             \
> >  > -     spin_lock_irq(&lp->lock);                                       \
> >  > -     mask = SMC_GET_INT_MASK();                                      \
> >  > +     spin_lock_irq(&priv->lock);                                     \
> >  > +     mask = SMC_GET_INT_MASK(priv);                                  \
> >
> >  Since "lp" is already used all over the place, could you simply use "lp"
> >  for the macro argument name as well instead of "priv"?  This will make
> >  the code more uniform and reduce the patch size.
> 
> I used the name "priv" instead of "lp" intentionally to make sure I
> got compile errors if I missed something. Some variables like "ioaddr"
> are today not passed as arguments to the macros but simply assumed to
> be present as local variables. I wanted to avoid using the local "lp"
> variable by mistake. So the "priv" name is actually a feature. =)

Well, you end up using the local lp variable in all cases anyway.

> I'd be happy to rewrite the patch to use "lp" though, but I have to
> confess that I don't see the point in redoing it. Anyway, please let
> me know what you prefer.

I do prefer to have lp everywhere.  But you simply have to search and 
replace "priv" with "lp" in the patch directly.  Then just applying it 
and rediffing will take care of the simplification.


Nicolas

^ permalink raw reply

* Re: [git patches] net driver updates
From: Krishna Kumar2 @ 2008-02-21  3:43 UTC (permalink / raw)
  To: Divy Le Ray; +Cc: David Miller, Jeff Garzik, LKML, netdev
In-Reply-To: <47BCD0DF.1050205@chelsio.com>

Hi Divy,

> > Explain why, so I can include it in the changelog please...
>
> Hi Jeff,
>
> The first part of the patch removes the !netif_queue_stopped(dev).
> It opens the race discussed a while ago between Stephen hemminger and
> David Miller:
> http://marc.info/?l=linux-netdev&m=113383224512427&w=2

I feel this race cannot happen anymore. I think the fix for that race was
to introduce the
__LINK_STATE_QDISC_RUNNING bit thus eliminating any races between CPU's. If
one
CPU has called xmit, the other CPU will enqueue skbs (by holding the
queue_lock) and
exit from qdisc_run since it finds the bit set already.

Thanks,

- KK


^ permalink raw reply

* [PATCH] [NETFILTER]: fix ebtable targets return
From: Joonwoo Park @ 2008-02-21  5:36 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Joonwoo Park, David Miller, netfilter-devel, netdev

The function ebt_do_table doesn't take NF_DROP as a verdict from the targets.

Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
 net/bridge/netfilter/ebt_dnat.c     |    2 +-
 net/bridge/netfilter/ebt_redirect.c |    2 +-
 net/bridge/netfilter/ebt_snat.c     |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index 1ec671d..ca64c1c 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -21,7 +21,7 @@ static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
 	const struct ebt_nat_info *info = data;
 
 	if (!skb_make_writable(skb, 0))
-		return NF_DROP;
+		return EBT_DROP;
 
 	memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN);
 	return info->target;
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index bfb9f74..b8afe85 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -22,7 +22,7 @@ static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr,
 	const struct ebt_redirect_info *info = data;
 
 	if (!skb_make_writable(skb, 0))
-		return NF_DROP;
+		return EBT_DROP;
 
 	if (hooknr != NF_BR_BROUTING)
 		memcpy(eth_hdr(skb)->h_dest,
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 204f996..5425333 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -23,7 +23,7 @@ static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr,
 	const struct ebt_nat_info *info = data;
 
 	if (!skb_make_writable(skb, 0))
-		return NF_DROP;
+		return EBT_DROP;
 
 	memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN);
 	if (!(info->target & NAT_ARP_BIT) &&
-- 
1.5.3.rc5


^ 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