Netdev List
 help / color / mirror / Atom feed
* Re: [v3 RFC PATCH 0/4] Implement multiqueue virtio-net
From: Simon Horman @ 2011-02-22  7:47 UTC (permalink / raw)
  To: Krishna Kumar
  Cc: rusty, davem, mst, arnd, eric.dumazet, netdev, avi, anthony, kvm
In-Reply-To: <20101020085452.15579.76002.sendpatchset@krkumar2.in.ibm.com>

On Wed, Oct 20, 2010 at 02:24:52PM +0530, Krishna Kumar wrote:
> Following set of patches implement transmit MQ in virtio-net.  Also
> included is the user qemu changes.  MQ is disabled by default unless
> qemu specifies it.

Hi Krishna,

I have a few questions about the results below:

1. Are the (%) comparisons between non-mq and mq virtio?
2. Was UDP or TCP used?
3. What was the transmit size (-m option to netperf)?

Also, I'm interested to know what the status of these patches is.
Are you planing a fresh series?

> 
>                   Changes from rev2:
>                   ------------------
> 1. Define (in virtio_net.h) the maximum send txqs; and use in
>    virtio-net and vhost-net.
> 2. vi->sq[i] is allocated individually, resulting in cache line
>    aligned sq[0] to sq[n].  Another option was to define
>    'send_queue' as:
>        struct send_queue {
>                struct virtqueue *svq;
>                struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
>        } ____cacheline_aligned_in_smp;
>    and to statically allocate 'VIRTIO_MAX_SQ' of those.  I hope
>    the submitted method is preferable.
> 3. Changed vhost model such that vhost[0] handles RX and vhost[1-MAX]
>    handles TX[0-n].
> 4. Further change TX handling such that vhost[0] handles both RX/TX
>    for single stream case.
> 
>                   Enabling MQ on virtio:
>                   -----------------------
> When following options are passed to qemu:
>         - smp > 1
>         - vhost=on
>         - mq=on (new option, default:off)
> then #txqueues = #cpus.  The #txqueues can be changed by using an
> optional 'numtxqs' option.  e.g. for a smp=4 guest:
>         vhost=on                   ->   #txqueues = 1
>         vhost=on,mq=on             ->   #txqueues = 4
>         vhost=on,mq=on,numtxqs=2   ->   #txqueues = 2
>         vhost=on,mq=on,numtxqs=8   ->   #txqueues = 8
> 
> 
>                    Performance (guest -> local host):
>                    -----------------------------------
> System configuration:
>         Host:  8 Intel Xeon, 8 GB memory
>         Guest: 4 cpus, 2 GB memory
> Test: Each test case runs for 60 secs, sum over three runs (except
> when number of netperf sessions is 1, which has 10 runs of 12 secs
> each).  No tuning (default netperf) other than taskset vhost's to
> cpus 0-3.  numtxqs=32 gave the best results though the guest had
> only 4 vcpus (I haven't tried beyond that).
> 
> ______________ numtxqs=2, vhosts=3  ____________________
> #sessions  BW%      CPU%    RCPU%    SD%      RSD%
> ________________________________________________________
> 1          4.46    -1.96     .19     -12.50   -6.06
> 2          4.93    -1.16    2.10      0       -2.38
> 4          46.17    64.77   33.72     19.51   -2.48
> 8          47.89    70.00   36.23     41.46    13.35
> 16         48.97    80.44   40.67     21.11   -5.46
> 24         49.03    78.78   41.22     20.51   -4.78
> 32         51.11    77.15   42.42     15.81   -6.87
> 40         51.60    71.65   42.43     9.75    -8.94
> 48         50.10    69.55   42.85     11.80   -5.81
> 64         46.24    68.42   42.67     14.18   -3.28
> 80         46.37    63.13   41.62     7.43    -6.73
> 96         46.40    63.31   42.20     9.36    -4.78
> 128        50.43    62.79   42.16     13.11   -1.23
> ________________________________________________________
> BW: 37.2%,  CPU/RCPU: 66.3%,41.6%,  SD/RSD: 11.5%,-3.7%
> 
> ______________ numtxqs=8, vhosts=5  ____________________
> #sessions   BW%      CPU%     RCPU%     SD%      RSD%
> ________________________________________________________
> 1           -.76    -1.56     2.33      0        3.03
> 2           17.41    11.11    11.41     0       -4.76
> 4           42.12    55.11    30.20     19.51    .62
> 8           54.69    80.00    39.22     24.39    -3.88
> 16          54.77    81.62    40.89     20.34    -6.58
> 24          54.66    79.68    41.57     15.49    -8.99
> 32          54.92    76.82    41.79     17.59    -5.70
> 40          51.79    68.56    40.53     15.31    -3.87
> 48          51.72    66.40    40.84     9.72     -7.13
> 64          51.11    63.94    41.10     5.93     -8.82
> 80          46.51    59.50    39.80     9.33     -4.18
> 96          47.72    57.75    39.84     4.20     -7.62
> 128         54.35    58.95    40.66     3.24     -8.63
> ________________________________________________________
> BW: 38.9%,  CPU/RCPU: 63.0%,40.1%,  SD/RSD: 6.0%,-7.4%
> 
> ______________ numtxqs=16, vhosts=5  ___________________
> #sessions   BW%      CPU%     RCPU%     SD%      RSD%
> ________________________________________________________
> 1           -1.43    -3.52    1.55      0          3.03
> 2           33.09     21.63   20.12    -10.00     -9.52
> 4           67.17     94.60   44.28     19.51     -11.80
> 8           75.72     108.14  49.15     25.00     -10.71
> 16          80.34     101.77  52.94     25.93     -4.49
> 24          70.84     93.12   43.62     27.63     -5.03
> 32          69.01     94.16   47.33     29.68     -1.51
> 40          58.56     63.47   25.91    -3.92      -25.85
> 48          61.16     74.70   34.88     .89       -22.08
> 64          54.37     69.09   26.80    -6.68      -30.04
> 80          36.22     22.73   -2.97    -8.25      -27.23
> 96          41.51     50.59   13.24     9.84      -16.77
> 128         48.98     38.15   6.41     -.33       -22.80
> ________________________________________________________
> BW: 46.2%,  CPU/RCPU: 55.2%,18.8%,  SD/RSD: 1.2%,-22.0%
> 
> ______________ numtxqs=32, vhosts=5  ___________________
> #            BW%       CPU%    RCPU%    SD%     RSD%
> ________________________________________________________
> 1            7.62     -38.03   -26.26  -50.00   -33.33
> 2            28.95     20.46    21.62   0       -7.14
> 4            84.05     60.79    45.74  -2.43    -12.42
> 8            86.43     79.57    50.32   15.85   -3.10
> 16           88.63     99.48    58.17   9.47    -13.10
> 24           74.65     80.87    41.99  -1.81    -22.89
> 32           63.86     59.21    23.58  -18.13   -36.37
> 40           64.79     60.53    22.23  -15.77   -35.84
> 48           49.68     26.93    .51    -36.40   -49.61
> 64           54.69     36.50    5.41   -26.59   -43.23
> 80           45.06     12.72   -13.25  -37.79   -52.08
> 96           40.21    -3.16    -24.53  -39.92   -52.97
> 128          36.33    -33.19   -43.66  -5.68    -20.49
> ________________________________________________________
> BW: 49.3%,  CPU/RCPU: 15.5%,-8.2%,  SD/RSD: -22.2%,-37.0%
> 
> 
> Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
> ---
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: [PATCH 3/5] r8169: fix the wrong parameter of point address
From: Francois Romieu @ 2011-02-22  8:00 UTC (permalink / raw)
  To: Hayes Wang; +Cc: netdev, linux-kernel
In-Reply-To: <1298356917-486-3-git-send-email-hayeswang@realtek.com>

Hayes Wang <hayeswang@realtek.com> :
> Correct the parameter of rtl8168_oob_notify. It results in the
> wrong point address and influences RTL8168DP.

Please send this one separately as a patch against current kernel
tree as it is clearly a bugfix. The remaining patches are probably
more -next material.

-- 
Ueimor

^ permalink raw reply

* Re: [PATCH 3/5] r8169: fix the wrong parameter of point address
From: Francois Romieu @ 2011-02-22  8:21 UTC (permalink / raw)
  To: Hayes Wang; +Cc: netdev, linux-kernel
In-Reply-To: <20110222080017.GA12453@electric-eye.fr.zoreil.com>

Francois Romieu <romieu@fr.zoreil.com> :
> Hayes Wang <hayeswang@realtek.com> :
> > Correct the parameter of rtl8168_oob_notify. It results in the
> > wrong point address and influences RTL8168DP.
> 
> Please send this one separately as a patch against current kernel
> tree as it is clearly a bugfix. The remaining patches are probably
> more -next material.

Correct me if I am wrong:
- #3 and #1 are bugfixes
- can you specify if #4 and #5 are either bugfixes, optimizations or cleanups ?
- #2 adds support for a new chipset

-- 
Ueimor

^ permalink raw reply

* [PATCH] ipvs: fix dst_lock locking on dest update
From: Julian Anastasov @ 2011-02-22  8:40 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, lvs-devel, Simon Horman


 	Fix dst_lock usage in __ip_vs_update_dest. We need
_bh locking because destination is updated in user context.
Can cause lockups on frequent destination updates.
Problem reported by Simon Kirby. Bug was introduced
in 2.6.37 from the "ipvs: changes for local real server"
change.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
---

 	Dave, please apply to net-2.6.
Patch is for 2.6.37+ and applies to 2.6.38-rc6. There is
little fuzz when applying to net-next, let me know if
I should provide patch for other trees.

--- linux-2.6.37/net/netfilter/ipvs/ip_vs_ctl.c	2011-01-06 00:01:23.600069161 +0200
+++ linux/net/netfilter/ipvs/ip_vs_ctl.c	2011-02-19 23:14:44.463250743 +0200
@@ -810,9 +810,9 @@ __ip_vs_update_dest(struct ip_vs_service
  	dest->u_threshold = udest->u_threshold;
  	dest->l_threshold = udest->l_threshold;

-	spin_lock(&dest->dst_lock);
+	spin_lock_bh(&dest->dst_lock);
  	ip_vs_dst_reset(dest);
-	spin_unlock(&dest->dst_lock);
+	spin_unlock_bh(&dest->dst_lock);

  	if (add)
  		ip_vs_new_estimator(&dest->stats);

^ permalink raw reply

* RE: [PATCH 3/5] r8169: fix the wrong parameter of point address
From: hayeswang @ 2011-02-22  8:46 UTC (permalink / raw)
  To: 'Francois Romieu'; +Cc: netdev, linux-kernel
In-Reply-To: <20110222082153.GA12463@electric-eye.fr.zoreil.com>

 

> -----Original Message-----
> From: Francois Romieu [mailto:romieu@fr.zoreil.com] 
> Sent: Tuesday, February 22, 2011 4:22 PM
> To: Hayeswang
> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 3/5] r8169: fix the wrong parameter of 
> point address
> 
> Francois Romieu <romieu@fr.zoreil.com> :
> > Hayes Wang <hayeswang@realtek.com> :
> > > Correct the parameter of rtl8168_oob_notify. It results 
> in the wrong 
> > > point address and influences RTL8168DP.
> > 
> > Please send this one separately as a patch against current 
> kernel tree 
> > as it is clearly a bugfix. The remaining patches are probably more 
> > -next material.
> 
> Correct me if I am wrong:
> - #3 and #1 are bugfixes
> - can you specify if #4 and #5 are either bugfixes, 
> optimizations or cleanups ?
> - #2 adds support for a new chipset

#1, #3, #4 are bugfixes.
#2 adds support for a new chipset
#5 is cleanup.

I would separate them and send the patches again.

 
Best Regards,
Hayes

^ permalink raw reply

* Re: [PATCH] ipvs: fix dst_lock locking on dest update
From: Hans Schillstrom @ 2011-02-22  9:11 UTC (permalink / raw)
  To: Julian Anastasov; +Cc: David S. Miller, netdev, lvs-devel, Simon Horman

>---- Original Message ----
>From: Julian Anastasov <ja@ssi.bg>
>To: "David S. Miller" <davem@davemloft.net>
>Cc: netdev@vger.kernel.org, lvs-devel@vger.kernel.org, "Simon Horman" <horms@verge.net.au>
>Sent: Tue, Feb 22, 2011, 9:36 AM
>Subject: [PATCH] ipvs: fix dst_lock locking on dest update
>
>Fix dst_lock usage in __ip_vs_update_dest. We need
>_bh locking because destination is updated in user context.
>Can cause lockups on frequent destination updates.
>Problem reported by Simon Kirby. Bug was introduced
>in 2.6.37 from the "ipvs: changes for local real server"
>change.
>
>Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>

>---
>
> 	Dave, please apply to net-2.6.
>Patch is for 2.6.37+ and applies to 2.6.38-rc6. There is
>little fuzz when applying to net-next, let me know if
>I should provide patch for other trees.

The patch seems to be OK in 2.6.38 expcept for line number.
All my thest runs without any problems.

>
>--- linux-2.6.37/net/netfilter/ipvs/ip_vs_ctl.c	2011-01-06 00:01:23.600069161 +0200
>+++ linux/net/netfilter/ipvs/ip_vs_ctl.c	2011-02-19 23:14:44.463250743 +0200
>@@ -810,9 +810,9 @@ __ip_vs_update_dest(struct ip_vs_service
>  	dest->u_threshold = udest->u_threshold;
>  	dest->l_threshold = udest->l_threshold;
>
>-	spin_lock(&dest->dst_lock);
>+	spin_lock_bh(&dest->dst_lock);
>  	ip_vs_dst_reset(dest);
>-	spin_unlock(&dest->dst_lock);
>+	spin_unlock_bh(&dest->dst_lock);
>
>  	if (add)
>  		ip_vs_new_estimator(&dest->stats);
>--


Hans Schillstrom <hans@schillstrom.com>



^ permalink raw reply

* [PATCH 1/2] net/r8169: adjust rtl8169_set_speed_xmii function
From: Hayes Wang @ 2011-02-22  9:26 UTC (permalink / raw)
  To: romieu; +Cc: netdev, linux-kernel, Hayes Wang

Adjust code of rtl8169_set_speed_xmii function and remove part
codes which have done in rtl_pll_power_up function.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/r8169.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 469ab0b..de94489 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1124,6 +1124,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int giga_ctrl, bmcr;
 
+	rtl_writephy(tp, 0x1f, 0x0000);
+
 	if (autoneg == AUTONEG_ENABLE) {
 		int auto_nego;
 
@@ -1152,18 +1154,6 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 
 		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
 
-		if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
-		    (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
-		    (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
-			/*
-			 * Wake up the PHY.
-			 * Vendor specific (0x1f) and reserved (0x0e) MII
-			 * registers.
-			 */
-			rtl_writephy(tp, 0x1f, 0x0000);
-			rtl_writephy(tp, 0x0e, 0x0000);
-		}
-
 		rtl_writephy(tp, MII_ADVERTISE, auto_nego);
 		rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
 	} else {
@@ -1178,8 +1168,6 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 
 		if (duplex == DUPLEX_FULL)
 			bmcr |= BMCR_FULLDPLX;
-
-		rtl_writephy(tp, 0x1f, 0x0000);
 	}
 
 	tp->phy_1000_ctrl_reg = giga_ctrl;
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 1/3] net/r8169: Correct settings of rtl8102e
From: Hayes Wang @ 2011-02-22  9:26 UTC (permalink / raw)
  To: romieu; +Cc: netdev, linux-kernel, Hayes Wang
In-Reply-To: <1298366782-1508-1-git-send-email-hayeswang@realtek.com>

Adjust and remove certain settings of RTL8102E which are for previous chips.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/r8169.c |   20 ++++++--------------
 1 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 469ab0b..3630dd7 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -3042,7 +3042,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_mwi_2;
 	}
 
-	tp->cp_cmd = PCIMulRW | RxChkSum;
+	tp->cp_cmd = RxChkSum;
 
 	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
@@ -3847,8 +3847,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
 	Cxpl_dbg_sel | \
 	ASF | \
 	PktCntrDisable | \
-	PCIDAC | \
-	PCIMulRW)
+	Mac_dbgo_sel)
 
 static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
@@ -3878,8 +3877,6 @@ static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 	if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
 		RTL_W8(Config1, cfg1 & ~LEDS0);
 
-	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
-
 	rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
 }
 
@@ -3891,8 +3888,6 @@ static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
 
 	RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
 	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
-
-	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
 }
 
 static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
@@ -3918,6 +3913,8 @@ static void rtl_hw_start_8101(struct net_device *dev)
 		}
 	}
 
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_07:
 		rtl_hw_start_8102e_1(ioaddr, pdev);
@@ -3932,14 +3929,13 @@ static void rtl_hw_start_8101(struct net_device *dev)
 		break;
 	}
 
-	RTL_W8(Cfg9346, Cfg9346_Unlock);
+	RTL_W8(Cfg9346, Cfg9346_Lock);
 
 	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
-	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
-
+	tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
 	RTL_W16(IntrMitigate, 0x0000);
@@ -3949,14 +3945,10 @@ static void rtl_hw_start_8101(struct net_device *dev)
 	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
 	rtl_set_rx_tx_config_registers(tp);
 
-	RTL_W8(Cfg9346, Cfg9346_Lock);
-
 	RTL_R8(IntrMask);
 
 	rtl_set_rx_mode(dev);
 
-	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-
 	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
 
 	RTL_W16(IntrMask, tp->intr_event);
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 2/2] net/r8169: Support RTL8105E
From: Hayes Wang @ 2011-02-22  9:26 UTC (permalink / raw)
  To: romieu; +Cc: netdev, linux-kernel, Hayes Wang
In-Reply-To: <1298366782-1508-1-git-send-email-hayeswang@realtek.com>

Support the new chips for RTL8105E

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/r8169.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index de94489..2543edd 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -36,6 +36,7 @@
 
 #define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
 #define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
+#define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
 
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
@@ -123,6 +124,8 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
 	RTL_GIGA_MAC_VER_27 = 0x1b, // 8168DP
 	RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP
+	RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E
+	RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -160,7 +163,9 @@ static const struct {
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
 	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E
-	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880)  // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_30, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -267,9 +272,15 @@ enum rtl8168_8101_registers {
 #define	EPHYAR_REG_MASK			0x1f
 #define	EPHYAR_REG_SHIFT		16
 #define	EPHYAR_DATA_MASK		0xffff
+	DLLPR			= 0xd0,
+#define	PM_SWITCH			(1 << 6)
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
+	TWSI			= 0xd2,
+	MCU			= 0xd3,
+#define	EN_NDP				(1 << 3)
+#define	EN_OOB_RESET			(1 << 2)
 	EFUSEAR			= 0xdc,
 #define	EFUSEAR_FLAG			0x80000000
 #define	EFUSEAR_WRITE_CMD		0x80000000
@@ -568,6 +579,7 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
+MODULE_FIRMWARE(FIRMWARE_8105E_1);
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -1145,7 +1157,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 		    (tp->mac_version != RTL_GIGA_MAC_VER_13) &&
 		    (tp->mac_version != RTL_GIGA_MAC_VER_14) &&
 		    (tp->mac_version != RTL_GIGA_MAC_VER_15) &&
-		    (tp->mac_version != RTL_GIGA_MAC_VER_16)) {
+		    (tp->mac_version != RTL_GIGA_MAC_VER_16) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_29) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_30)) {
 			giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
 		} else {
 			netif_info(tp, link, dev,
@@ -1547,6 +1561,9 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		{ 0x7c800000, 0x30000000,	RTL_GIGA_MAC_VER_11 },
 
 		/* 8101 family. */
+		{ 0x7cf00000, 0x40a00000,	RTL_GIGA_MAC_VER_30 },
+		{ 0x7cf00000, 0x40900000,	RTL_GIGA_MAC_VER_29 },
+		{ 0x7c800000, 0x40800000,	RTL_GIGA_MAC_VER_30 },
 		{ 0x7cf00000, 0x34a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x24a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x34900000,	RTL_GIGA_MAC_VER_08 },
@@ -2423,6 +2440,33 @@ static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
+static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0005 },
+		{ 0x1a, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0004 },
+		{ 0x1c, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x15, 0x7701 },
+		{ 0x1f, 0x0000 }
+	};
+
+	/* Disable ALDPS before ram code */
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x18, 0x0310);
+	msleep(100);
+
+	if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0)
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
 static void rtl_hw_phy_config(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -2490,6 +2534,10 @@ static void rtl_hw_phy_config(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_28:
 		rtl8168d_4_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
+		rtl8105e_hw_phy_config(tp);
+		break;
 
 	default:
 		break;
@@ -2928,6 +2976,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_09:
 	case RTL_GIGA_MAC_VER_10:
 	case RTL_GIGA_MAC_VER_16:
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
 		ops->down	= r810x_pll_power_down;
 		ops->up		= r810x_pll_power_up;
 		break;
@@ -3890,6 +3940,37 @@ static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
 	rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
 }
 
+static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8105e_1[] = {
+		{ 0x07,	0, 0x4000 },
+		{ 0x19,	0, 0x0200 },
+		{ 0x19,	0, 0x0020 },
+		{ 0x1e,	0, 0x2000 },
+		{ 0x03,	0, 0x0001 },
+		{ 0x19,	0, 0x0100 },
+		{ 0x19,	0, 0x0004 },
+		{ 0x0a,	0, 0x0020 }
+	};
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idel */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
+
+	/* disable Early Tally Counter */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
+
+	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PM_SWITCH);
+
+	rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
+}
+
+static void rtl_hw_start_8105e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	rtl_hw_start_8105e_1(ioaddr, pdev);
+	rtl_ephy_write(ioaddr, 0x1e, rtl_ephy_read(ioaddr, 0x1e) | 0x8000);
+}
+
 static void rtl_hw_start_8101(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3918,6 +3999,13 @@ static void rtl_hw_start_8101(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_09:
 		rtl_hw_start_8102e_2(ioaddr, pdev);
 		break;
+
+	case RTL_GIGA_MAC_VER_29:
+		rtl_hw_start_8105e_1(ioaddr, pdev);
+		break;
+	case RTL_GIGA_MAC_VER_30:
+		rtl_hw_start_8105e_2(ioaddr, pdev);
+		break;
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 3/3] net/r8169: fix RTL8168DP issue
From: Hayes Wang @ 2011-02-22  9:26 UTC (permalink / raw)
  To: romieu; +Cc: netdev, linux-kernel, Hayes Wang
In-Reply-To: <1298366782-1508-1-git-send-email-hayeswang@realtek.com>

Fix the RTL8111DP turn off the power when DASH is enabled.
Fix RTL_GIGA_MAC_VER_27 don't wait tx finish before reset.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/r8169.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 336ba94..ef2133b 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -2869,8 +2869,11 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
 
-	if (tp->mac_version == RTL_GIGA_MAC_VER_27)
+	if (((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	     (tp->mac_version == RTL_GIGA_MAC_VER_28)) &&
+	    (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) {
 		return;
+	}
 
 	if (((tp->mac_version == RTL_GIGA_MAC_VER_23) ||
 	     (tp->mac_version == RTL_GIGA_MAC_VER_24)) &&
@@ -2892,6 +2895,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_25:
 	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
 		RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
 		break;
 	}
@@ -2901,12 +2906,17 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
 
-	if (tp->mac_version == RTL_GIGA_MAC_VER_27)
+	if (((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	     (tp->mac_version == RTL_GIGA_MAC_VER_28)) &&
+	    (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) {
 		return;
+	}
 
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_25:
 	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
 		RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
 		break;
 	}
@@ -3319,7 +3329,8 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 	/* Disable interrupts */
 	rtl8169_irq_mask_and_ack(ioaddr);
 
-	if (tp->mac_version == RTL_GIGA_MAC_VER_28) {
+	if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_28) {
 		while (RTL_R8(TxPoll) & NPQ)
 			udelay(20);
 
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 2/3] net/r8169: fix the wrong parameter of point address
From: Hayes Wang @ 2011-02-22  9:26 UTC (permalink / raw)
  To: romieu; +Cc: netdev, linux-kernel, Hayes Wang
In-Reply-To: <1298366782-1508-1-git-send-email-hayeswang@realtek.com>

Correct the parameter of rtl8168_oob_notify. It results in the
wrong point address and influences RTL8168DP.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/r8169.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 3630dd7..336ba94 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -617,8 +617,9 @@ static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
 	}
 }
 
-static void rtl8168_oob_notify(void __iomem *ioaddr, u8 cmd)
+static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
 {
+	void __iomem *ioaddr = tp->mmio_addr;
 	int i;
 
 	RTL_W8(ERIDR, cmd);
@@ -630,7 +631,7 @@ static void rtl8168_oob_notify(void __iomem *ioaddr, u8 cmd)
 			break;
 	}
 
-	ocp_write(ioaddr, 0x1, 0x30, 0x00000001);
+	ocp_write(tp, 0x1, 0x30, 0x00000001);
 }
 
 #define OOB_CMD_RESET		0x00
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 0/4] simple generic timer infrastructure and stmmac example
From: Peppe CAVALLARO @ 2011-02-22 10:17 UTC (permalink / raw)
  To: linux-sh@vger.kernel.org, netdev@vger.kernel.org
  Cc: Stuart MENEFY, Peppe CAVALLARO

Many devices targeted at the embedded market provide a number of
generic timers which are capable of generating interrupts at a
requested rate. These can then be used in the implementation of drivers
for other peripherals which require a timer interrupt, without having
to provide an additional timer as part of that peripheral.

A code provides a simple abstraction layer which allows a timer to be
registered, and for a driver to request a timer.
Currently this doesn't provide any of the additional information, such
as precision or position in clock framework which might be required
for a fully featured driver.

This patches also updates the stmmac Network device driver to use
the generic timer infrastructure The timer is used for mitigating
the number of the interrupts. This helps many people to save the
CPU on STM platforms with MAC10/100 and GMAC device without an
embedded timer.

Welcome comments and review.

Giuseppe Cavallaro (3):
  sh_timer: add the support to use the generic timer
  stmmac: switch to use the new generic timer interface
  stmmac: rework and improvement the stmmac timer

Stuart Menefy (1):
  clksource: Generic timer infrastructure

 drivers/clocksource/Makefile       |    1 +
 drivers/clocksource/generictimer.c |   60 +++++++++++++++++++++
 drivers/clocksource/sh_tmu.c       |   72 +++++++++++++++++++++++++
 drivers/net/stmmac/Kconfig         |   19 ++++---
 drivers/net/stmmac/Makefile        |    2 +-
 drivers/net/stmmac/common.h        |    6 ++
 drivers/net/stmmac/stmmac.h        |    5 +-
 drivers/net/stmmac/stmmac_main.c   |   66 ++++++++++++-----------
 drivers/net/stmmac/stmmac_timer.c  |  103 +++++++++++++++++++++---------------
 drivers/net/stmmac/stmmac_timer.h  |   12 ++---
 include/linux/generictimer.h       |   41 ++++++++++++++
 11 files changed, 295 insertions(+), 92 deletions(-)
 create mode 100644 drivers/clocksource/generictimer.c
 create mode 100644 include/linux/generictimer.h

-- 
1.7.4

^ permalink raw reply

* [PATCH (sh-2.6) 1/4] clksource: Generic timer infrastructure
From: Peppe CAVALLARO @ 2011-02-22 10:17 UTC (permalink / raw)
  To: linux-sh@vger.kernel.org, netdev@vger.kernel.org; +Cc: Stuart MENEFY
In-Reply-To: <1298369864-24429-1-git-send-email-peppe.cavallaro@st.com>

From: Stuart Menefy <stuart.menefy@st.com>

Many devices targeted at the embedded market provide a number of
generic timers which are capable of generating interrupts at a
requested rate. These can then be used in the implementation of drivers
for other peripherals which require a timer interrupt, without having
to provide an additional timer as part of that peripheral.

A code provides a simple abstraction layer which allows a timer to be
registered, and for a driver to request a timer.

Currently this doesn't provide any of the additional information, such
as precision or position in clock framework which might be required
for a fully featured driver.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/clocksource/Makefile       |    1 +
 drivers/clocksource/generictimer.c |   60 ++++++++++++++++++++++++++++++++++++
 include/linux/generictimer.h       |   41 ++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clocksource/generictimer.c
 create mode 100644 include/linux/generictimer.h

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index be61ece..b0be293 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-y				+= generictimer.o
diff --git a/drivers/clocksource/generictimer.c b/drivers/clocksource/generictimer.c
new file mode 100644
index 0000000..a74a87a
--- /dev/null
+++ b/drivers/clocksource/generictimer.c
@@ -0,0 +1,60 @@
+/*
+ * Simple generic hardware timer interface
+ *
+ * Copyright (C) 2010 STMicroelectronics Limited
+ * Authors: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ *          Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/generictimer.h>
+
+static DEFINE_MUTEX(gt_mutex);
+static LIST_HEAD(gt_list);
+
+void generic_timer_register_device(struct generic_timer *gt)
+{
+	mutex_lock(&gt_mutex);
+	list_add(&gt->list, &gt_list);
+	mutex_unlock(&gt_mutex);
+}
+
+struct generic_timer *generic_timer_claim(void (*handler) (void *), void *data)
+{
+	struct generic_timer *gt = NULL;
+
+	if (!handler) {
+		pr_err("%s: invalid handler\n", __func__);
+		return NULL;
+	}
+
+	mutex_lock(&gt_mutex);
+	if (!list_empty(&gt_list)) {
+		struct list_head *list = gt_list.next;
+		list_del(list);
+		gt = container_of(list, struct generic_timer, list);
+	}
+	mutex_unlock(&gt_mutex);
+
+	if (!gt)
+		return NULL;
+
+	/* Prepare the new handler */
+	gt->priv_handler = handler;
+	gt->data = data;
+
+	return gt;
+}
+
+void generic_timer_release(struct generic_timer *gt)
+{
+	/* Just in case... */
+	generic_timer_stop(gt);
+
+	generic_timer_register_device(gt);
+}
diff --git a/include/linux/generictimer.h b/include/linux/generictimer.h
new file mode 100644
index 0000000..87fb656
--- /dev/null
+++ b/include/linux/generictimer.h
@@ -0,0 +1,41 @@
+#ifndef __STM_GENERIC_TIMER_H
+#define __STM_GENERIC_TIMER_H
+
+#include <linux/list.h>
+
+/* Generic timer device intrface */
+
+struct generic_timer {
+	char *name;
+	struct list_head list;
+	void (*priv_handler)(void *data);
+	void *data;
+	void (*timer_start)(struct generic_timer *gt);
+	void (*timer_stop)(struct generic_timer *gt);
+	void (*set_rate)(struct generic_timer *gt, unsigned long rate);
+};
+
+void generic_timer_register_device(struct generic_timer *gt);
+
+/* Driver interface */
+
+struct generic_timer *generic_timer_claim(void (*handler)(void *), void *data);
+void generic_timer_release(struct generic_timer *gt);
+
+static inline void generic_timer_start(struct generic_timer *gt)
+{
+	gt->timer_start(gt);
+}
+
+static inline void generic_timer_stop(struct generic_timer *gt)
+{
+	gt->timer_stop(gt);
+}
+
+static inline void generic_timer_set_rate(struct generic_timer *gt,
+		unsigned long rate)
+{
+	gt->set_rate(gt, rate);
+}
+
+#endif /* __STM_GENERIC_TIMER_H */
-- 
1.7.4

^ permalink raw reply related

* [PATCH (sh-2.6) 2/4] sh_timer: add the support to use the generic timer
From: Peppe CAVALLARO @ 2011-02-22 10:17 UTC (permalink / raw)
  To: linux-sh@vger.kernel.org, netdev@vger.kernel.org
  Cc: Stuart MENEFY, Peppe CAVALLARO
In-Reply-To: <1298369864-24429-1-git-send-email-peppe.cavallaro@st.com>

Add the support to register and use a TMU channel as
generic timer. For example the stmmac network device
driver, on STM platforms, uses the TMU channel 2 for
mitigating the number of interrupts.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
---
 drivers/clocksource/sh_tmu.c |   72 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 36aba99..8199556 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -29,6 +29,7 @@
 #include <linux/err.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/generictimer.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 
@@ -41,6 +42,7 @@ struct sh_tmu_priv {
 	unsigned long periodic;
 	struct clock_event_device ced;
 	struct clocksource cs;
+	struct generic_timer gt;
 };
 
 static DEFINE_SPINLOCK(sh_tmu_lock);
@@ -184,6 +186,74 @@ static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static struct sh_tmu_priv *gt_to_sh_tmu(struct generic_timer *gt)
+{
+	return container_of(gt, struct sh_tmu_priv, gt);
+}
+
+static void sh_tmu_generic_timer_start(struct generic_timer *gt)
+{
+	struct sh_tmu_priv *p = gt_to_sh_tmu(gt);
+
+	sh_tmu_write(p, TCR, 0x0020);
+	sh_tmu_start_stop_ch(p, 1);
+}
+
+static void sh_tmu_generic_timer_stop(struct generic_timer *gt)
+{
+	struct sh_tmu_priv *p = gt_to_sh_tmu(gt);
+
+	sh_tmu_start_stop_ch(p, 0);
+	sh_tmu_write(p, TCR, 0x0000);
+}
+
+static void sh_tmu_generic_timer_set_rate(struct generic_timer *gt,
+					  unsigned long rate)
+{
+	struct sh_tmu_priv *p = gt_to_sh_tmu(gt);
+
+	sh_tmu_enable(p);
+	p->periodic = p->rate / rate;
+	sh_tmu_set_next(p, p->periodic, 1);
+}
+
+static irqreturn_t sh_tmu_generic_timer_interrupt(int irq, void *dev_id)
+{
+	struct sh_tmu_priv *p = dev_id;
+
+	sh_tmu_write(p, TCR, 0x0020);
+
+	p->gt.priv_handler(p->gt.data);
+	return IRQ_HANDLED;
+}
+
+static void sh_tmu_register_generic_timer(struct sh_tmu_priv *p, char *name)
+{
+	struct generic_timer *gt = &p->gt;
+	int ret;
+
+	gt->name = name;
+	gt->timer_start = sh_tmu_generic_timer_start;
+	gt->timer_stop = sh_tmu_generic_timer_stop;
+	gt->set_rate = sh_tmu_generic_timer_set_rate;
+
+	p->irqaction.handler = sh_tmu_generic_timer_interrupt;
+
+	ret = setup_irq(p->irqaction.irq, &p->irqaction);
+	if (unlikely(ret)) {
+		dev_err(&p->pdev->dev, "failed to request irq %d\n",
+			p->irqaction.irq);
+		return;
+	}
+
+	sh_tmu_generic_timer_stop(gt);
+	sh_tmu_write(p, TCOR, 0xffffffff);
+	sh_tmu_write(p, TCNT, 0xffffffff);
+
+	dev_info(&p->pdev->dev, "used for generic timer\n");
+	generic_timer_register_device(gt);
+}
+
 static struct sh_tmu_priv *cs_to_sh_tmu(struct clocksource *cs)
 {
 	return container_of(cs, struct sh_tmu_priv, cs);
@@ -342,6 +412,8 @@ static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
 		sh_tmu_register_clockevent(p, name, clockevent_rating);
 	else if (clocksource_rating)
 		sh_tmu_register_clocksource(p, name, clocksource_rating);
+	else
+		sh_tmu_register_generic_timer(p, name);
 
 	return 0;
 }
-- 
1.7.4

^ permalink raw reply related

* [PATCH (net-2.6) 3/4] stmmac: switch to use the new generic timer interface
From: Peppe CAVALLARO @ 2011-02-22 10:17 UTC (permalink / raw)
  To: linux-sh@vger.kernel.org, netdev@vger.kernel.org
  Cc: Stuart MENEFY, Peppe CAVALLARO
In-Reply-To: <1298369864-24429-1-git-send-email-peppe.cavallaro@st.com>

The stmmac can use an external timer for mitigating
the number of interrupts.
On SH4 platforms based this can be done by using the
TMU channel 2 interrupt.
This actually helps many people to save the CPU usage
on platforms with MAC10/100 and GMAC devices without
an embedded timer.

This patch removes the old code (obsoleted and only
valid for old STM Kernels) and uses the new generic
timer interface.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/Kconfig        |    1 -
 drivers/net/stmmac/stmmac_main.c  |   21 ++++----
 drivers/net/stmmac/stmmac_timer.c |  101 +++++++++++++++++++++---------------
 drivers/net/stmmac/stmmac_timer.h |   11 ++---
 4 files changed, 74 insertions(+), 60 deletions(-)

diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index 7df7df4..b74e79b 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -32,7 +32,6 @@ config STMMAC_DUAL_MAC
 config STMMAC_TIMER
 	bool "STMMAC Timer optimisation"
 	default n
-	depends on RTC_HCTOSYS_DEVICE
 	help
 	  Use an external timer for mitigating the number of network
 	  interrupts. Currently, for SH architectures, it is possible
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 34a0af3..26714b4 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -652,7 +652,7 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv)
 {
 #ifdef CONFIG_STMMAC_TIMER
 	if (likely(priv->tm->enable))
-		priv->tm->timer_start(tmrate);
+		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 	else
 #endif
 		priv->hw->dma->enable_dma_irq(priv->ioaddr);
@@ -662,7 +662,7 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv)
 {
 #ifdef CONFIG_STMMAC_TIMER
 	if (likely(priv->tm->enable))
-		priv->tm->timer_stop();
+		priv->tm->timer_stop(priv->tm->timer_callb);
 	else
 #endif
 		priv->hw->dma->disable_dma_irq(priv->ioaddr);
@@ -703,11 +703,11 @@ void stmmac_schedule(struct net_device *dev)
 	_stmmac_schedule(priv);
 }
 
-static void stmmac_no_timer_started(unsigned int x)
+static void stmmac_no_timer_started(void *t, unsigned int x)
 {;
 };
 
-static void stmmac_no_timer_stopped(void)
+static void stmmac_no_timer_stopped(void *t)
 {;
 };
 #endif
@@ -720,7 +720,6 @@ static void stmmac_no_timer_stopped(void)
  */
 static void stmmac_tx_err(struct stmmac_priv *priv)
 {
-
 	netif_stop_queue(priv->dev);
 
 	priv->hw->dma->stop_tx(priv->ioaddr);
@@ -807,7 +806,8 @@ static int stmmac_open(struct net_device *dev)
 	/* Test if the external timer can be actually used.
 	 * In case of failure continue without timer. */
 	if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
-		pr_warning("stmmaceth: cannot attach the external timer.\n");
+		pr_warning("stmmac (%s): cannot attach the external timer.\n",
+			   dev->name);
 		priv->tm->freq = 0;
 		priv->tm->timer_start = stmmac_no_timer_started;
 		priv->tm->timer_stop = stmmac_no_timer_stopped;
@@ -864,7 +864,8 @@ static int stmmac_open(struct net_device *dev)
 	priv->hw->dma->start_rx(priv->ioaddr);
 
 #ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_start(tmrate);
+	if (likely(priv->tm->enable))
+		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 #endif
 	/* Dump DMA/MAC registers */
 	if (netif_msg_hw(priv)) {
@@ -902,7 +903,7 @@ static int stmmac_release(struct net_device *dev)
 
 #ifdef CONFIG_STMMAC_TIMER
 	/* Stop and release the timer */
-	stmmac_close_ext_timer();
+	stmmac_close_ext_timer(priv->tm->timer_callb);
 	if (priv->tm != NULL)
 		kfree(priv->tm);
 #endif
@@ -1815,7 +1816,7 @@ static int stmmac_suspend(struct device *dev)
 		phy_stop(priv->phydev);
 
 #ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_stop();
+	priv->tm->timer_stop(priv->tm->timer_callb);
 	if (likely(priv->tm->enable))
 		dis_ic = 1;
 #endif
@@ -1866,7 +1867,7 @@ static int stmmac_resume(struct device *dev)
 
 #ifdef CONFIG_STMMAC_TIMER
 	if (likely(priv->tm->enable))
-		priv->tm->timer_start(tmrate);
+		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 #endif
 	napi_enable(&priv->napi);
 
diff --git a/drivers/net/stmmac/stmmac_timer.c b/drivers/net/stmmac/stmmac_timer.c
index 2a0e1ab..2481daa 100644
--- a/drivers/net/stmmac/stmmac_timer.c
+++ b/drivers/net/stmmac/stmmac_timer.c
@@ -33,102 +33,119 @@ static void stmmac_timer_handler(void *data)
 	stmmac_schedule(dev);
 }
 
-#define STMMAC_TIMER_MSG(timer, freq) \
-printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
+#define STMMAC_TIMER_MSG(dev_name, timer, freq) \
+printk(KERN_INFO "stmmac_timer: (%s) %s Timer (freq %dHz)\n", \
+		 dev_name, timer, freq);
 
 #if defined(CONFIG_STMMAC_RTC_TIMER)
 #include <linux/rtc.h>
-static struct rtc_device *stmmac_rtc;
-static rtc_task_t stmmac_task;
 
-static void stmmac_rtc_start(unsigned int new_freq)
+static void stmmac_rtc_start(void *timer, unsigned int new_freq)
 {
-	rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq);
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1);
+	struct rtc_device *rtc = timer;
+
+	rtc_irq_set_freq(rtc, rtc->irq_task, new_freq);
+	rtc_irq_set_state(rtc, rtc->irq_task, 1);
+	return;
 }
 
-static void stmmac_rtc_stop(void)
+static void stmmac_rtc_stop(void *timer)
 {
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
+	struct rtc_device *rtc = timer;
+
+	rtc_irq_set_state(rtc, rtc->irq_task, 0);
+	return;
 }
 
 int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 {
-	stmmac_task.private_data = dev;
-	stmmac_task.func = stmmac_timer_handler;
+	struct rtc_device *rtc;
+	rtc_task_t rtc_task;
+
+	rtc_task.private_data = dev;
+	rtc_task.func = stmmac_timer_handler;
 
-	stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
-	if (stmmac_rtc == NULL) {
+	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+	if (rtc == NULL) {
 		pr_err("open rtc device failed\n");
 		return -ENODEV;
 	}
 
-	rtc_irq_register(stmmac_rtc, &stmmac_task);
+	rtc_irq_register(rtc, &rtc_task);
 
 	/* Periodic mode is not supported */
-	if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
+	if ((rtc_irq_set_freq(rtc, &rtc_task, tm->freq) < 0)) {
 		pr_err("set periodic failed\n");
-		rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-		rtc_class_close(stmmac_rtc);
+		rtc_irq_unregister(rtc, &rtc_task);
+		rtc_class_close(rtc);
 		return -1;
 	}
 
-	STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
+	STMMAC_TIMER_MSG(dev->name, CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
 
+	rtc->irq_task = &rtc_task;
+	tm->timer_callb = rtc;
 	tm->timer_start = stmmac_rtc_start;
 	tm->timer_stop = stmmac_rtc_stop;
 
 	return 0;
 }
 
-int stmmac_close_ext_timer(void)
+int stmmac_close_ext_timer(void *timer)
 {
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-	rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-	rtc_class_close(stmmac_rtc);
+	struct rtc_device *rtc = timer;
+
+	rtc_irq_set_state(rtc, rtc->irq_task, 0);
+	rtc_irq_unregister(rtc, rtc->irq_task);
+	rtc_class_close(rtc);
+
 	return 0;
 }
 
 #elif defined(CONFIG_STMMAC_TMU_TIMER)
-#include <linux/clk.h>
-#define TMU_CHANNEL "tmu2_clk"
-static struct clk *timer_clock;
+#include <linux/generictimer.h>
 
-static void stmmac_tmu_start(unsigned int new_freq)
+/* Set rate and start the timer */
+static void stmmac_tmu_set_rate(void *timer_callb, unsigned int new_freq)
 {
-	clk_set_rate(timer_clock, new_freq);
-	clk_enable(timer_clock);
+	struct generic_timer *timer = timer_callb;
+
+	generic_timer_start(timer);
+	generic_timer_set_rate(timer, new_freq);
+	return;
 }
 
-static void stmmac_tmu_stop(void)
+static void stmmac_tmu_stop(void *timer_callb)
 {
-	clk_disable(timer_clock);
+	struct generic_timer *timer = timer_callb;
+
+	generic_timer_stop(timer);
+	return;
 }
 
 int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 {
-	timer_clock = clk_get(NULL, TMU_CHANNEL);
+	struct generic_timer *timer;
+	timer = generic_timer_claim(stmmac_timer_handler,  dev);
 
-	if (timer_clock == NULL)
+	if (timer == NULL)
 		return -1;
 
-	if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
-		timer_clock = NULL;
-		return -1;
-	}
+	STMMAC_TIMER_MSG(dev->name, "sh_tmu", tm->freq);
 
-	STMMAC_TIMER_MSG("TMU2", tm->freq);
-	tm->timer_start = stmmac_tmu_start;
+	tm->timer_callb = timer;
+	tm->timer_start = stmmac_tmu_set_rate;
 	tm->timer_stop = stmmac_tmu_stop;
 
 	return 0;
 }
 
-int stmmac_close_ext_timer(void)
+int stmmac_close_ext_timer(void *timer_callb)
 {
-	clk_disable(timer_clock);
-	tmu2_unregister_user();
-	clk_put(timer_clock);
+	struct generic_timer *timer = timer_callb;
+
+	stmmac_tmu_stop(timer_callb);
+	generic_timer_release(timer);
 	return 0;
 }
 #endif
diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h
index 6863590..250f5cb 100644
--- a/drivers/net/stmmac/stmmac_timer.h
+++ b/drivers/net/stmmac/stmmac_timer.h
@@ -23,20 +23,17 @@
 *******************************************************************************/
 
 struct stmmac_timer {
-	void (*timer_start) (unsigned int new_freq);
-	void (*timer_stop) (void);
+	void (*timer_start) (void *timer, unsigned int new_freq);
+	void (*timer_stop) (void *timer);
 	unsigned int freq;
 	unsigned int enable;
+	void *timer_callb;
 };
 
 /* Open the HW timer device and return 0 in case of success */
 int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm);
 /* Stop the timer and release it */
-int stmmac_close_ext_timer(void);
+int stmmac_close_ext_timer(void *priv);
 /* Function used for scheduling task within the stmmac */
 void stmmac_schedule(struct net_device *dev);
 
-#if defined(CONFIG_STMMAC_TMU_TIMER)
-extern int tmu2_register_user(void *fnt, void *data);
-extern void tmu2_unregister_user(void);
-#endif
-- 
1.7.4

^ permalink raw reply related

* Re: sysctls below net.ipv[46].conf.all not working as expected
From: Uwe Kleine-König @ 2011-02-22  9:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Marco d'Itri
In-Reply-To: <20101230204319.GE14221@pengutronix.de>

Hello David,

On Thu, Dec 30, 2010 at 09:43:19PM +0100, Uwe Kleine-König wrote:
> On Thu, Dec 30, 2010 at 12:30:23PM -0800, David Miller wrote:
> > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > Date: Wed, 29 Dec 2010 17:06:07 +0100
> > 
> > > I did the following:
> > > 
> > > 	cassiopeia:~# sysctl net.ipv6.conf.all.use_tempaddr
> > > 	net.ipv6.conf.all.use_tempaddr = 0
> > > 
> > > 	cassiopeia:~# sysctl net.ipv6.conf.eth0.use_tempaddr
> > > 	net.ipv6.conf.eth0.use_tempaddr = 0
> > > 
> > > 	cassiopeia:~# sysctl -w net.ipv6.conf.all.use_tempaddr=1
> > > 	net.ipv6.conf.all.use_tempaddr = 1
> > > 
> > > 	cassiopeia:~# sysctl net.ipv6.conf.all.use_tempaddr
> > > 	net.ipv6.conf.all.use_tempaddr = 1
> > > 
> > > 	cassiopeia:~# sysctl net.ipv6.conf.eth0.use_tempaddr
> > > 	net.ipv6.conf.eth0.use_tempaddr = 0
> > > 
> > > Here I would have expected that eth0's use_tempaddr is 1, too.  The
> > > problem is not that this entry isn't writeable:
> > 
> > The "all" value is propagated at the first moment that the ipv6 device
> > private is created, usually that is when the device is first brought up
> > which means it can happen as early as the exact moment the device is
> > registered.
> > 
> > Therefore, if you want "all" to apply to "eth0", you must make sure
> > the sysctl is set properly before the device is registered.
> I thought this is what "default" was used for?!
I took the time now to dig into the source for ipv4/{all,default}.

Unless I'm mistaken I found:

 - inetdev_init copies dev_net(dev)->ipv4.devconf_dflt to &in_dev->cnf
   That's called from inetdev_event if there is no in_dev.

 - devinet_copy_dflt_conf copies to all devices that have !test_bit(i,
   in_dev->cnf.state)
   devinet_copy_dflt_conf is called when /proc/sys/net/ipv4/conf/default
   is written to.  I didn't found where the in_dev->cnf.state bits are
   set.

 - net->ipv4.devconf_all is never propagated to the devices.

 - The data behind /proc/sys/net/ipv4/conf/all is used in registering
   net->ipv4.forw_hdr and seems only have to do with ip_forward

So I think that it's really "default" that propagates to a new device as
I expected and the documentation suggests.

So IMHO a better name for "all" would be "global" ...

> If you are really right, the documentation is (IMHO) misleading.  e.g.
> Documentation/networking/ip-sysctl.txt tells:
> 
> 	conf/default/*:
> 		Change the interface-specific default settings.
> 
> 	conf/all/*:
> 		Change all the interface-specific settings.
... and this is misleading.  I wonder if it would be considered OK, to
create a new config directory called "global" that acts like "all" now
and let "all" propagate all changes to all devices, "default" and
"global".  If not the documentation needs clearification.

I guess for ipv6 it's similar, though I didn't check that.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH (net-2.6) 4/4] stmmac: rework and improvement the stmmac timer
From: Peppe CAVALLARO @ 2011-02-22 10:17 UTC (permalink / raw)
  To: linux-sh@vger.kernel.org, netdev@vger.kernel.org
  Cc: Stuart MENEFY, Peppe CAVALLARO
In-Reply-To: <1298369864-24429-1-git-send-email-peppe.cavallaro@st.com>

This patch prepares the stmmac to use the
embedded watchdog timer included in the new
mac generations. The STMMAC_TIMER option becomes
STMMAC_EXT_TIMER. The patch also tidies-up the code
and improvements the Kconfig information.

The driver can use the external timer and in case
of problems, i.e. while registering the timer,
it'll continue to work with NAPI and interrupts.

Currently, the STMMAC_EXT_TIMER can be turned on
SUPERH only and it depends on SH_TIMER_TMU: I mean
on platforms where I performed all my tests.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/Kconfig        |   18 ++++++++----
 drivers/net/stmmac/Makefile       |    2 +-
 drivers/net/stmmac/common.h       |    6 ++++
 drivers/net/stmmac/stmmac.h       |    5 ++-
 drivers/net/stmmac/stmmac_main.c  |   51 +++++++++++++++++++-----------------
 drivers/net/stmmac/stmmac_timer.c |    4 +-
 drivers/net/stmmac/stmmac_timer.h |    1 -
 7 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index b74e79b..cdbe5a8 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -29,22 +29,28 @@ config STMMAC_DUAL_MAC
 	  Ethernet Controllers. This option turns on the second Ethernet
 	  device on this kind of platforms.
 
-config STMMAC_TIMER
+config STMMAC_EXT_TIMER
 	bool "STMMAC Timer optimisation"
 	default n
 	help
 	  Use an external timer for mitigating the number of network
 	  interrupts. Currently, for SH architectures, it is possible
-	  to use the TMU channel 2 and the SH-RTC device.
+	  to use the TMU channel 2 (via Generic Timer) and the SH-RTC
+	  device. If the timer registration fails during the interface
+	  initialisation then the driver will work without any
+	  mitigation schema.
 
 choice
         prompt "Select Timer device"
-        depends on STMMAC_TIMER
+        depends on STMMAC_EXT_TIMER
 
-config STMMAC_TMU_TIMER
-        bool "TMU channel 2"
-        depends on CPU_SH4
+config STMMAC_GEN_TIMER
+        bool "Generic External Timer"
+        depends on SH_TIMER_TMU
 	help
+	  Use the Generic timer for mitigating the interrupts.
+	  For example, in case of SUPERH the TMU channel 2
+	  is used for that.
 
 config STMMAC_RTC_TIMER
         bool "Real time clock"
diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile
index 9691733..05d84b2 100644
--- a/drivers/net/stmmac/Makefile
+++ b/drivers/net/stmmac/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
-stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
+stmmac-$(CONFIG_STMMAC_EXT_TIMER) += stmmac_timer.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o	\
 	      dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o	\
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o $(stmmac-y)
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 375ea19..4bd9d01 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -43,6 +43,12 @@
 #undef FRAME_FILTER_DEBUG
 /* #define FRAME_FILTER_DEBUG */
 
+enum mitigation_timer {
+	no_timer = 0,
+	external = 1,
+	embedded = 2,
+};
+
 struct stmmac_extra_stats {
 	/* Transmit errors */
 	unsigned long tx_underflow ____cacheline_aligned;
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 5f06c47..1b76977 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -25,7 +25,7 @@
 #include <linux/stmmac.h>
 
 #include "common.h"
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 #include "stmmac_timer.h"
 #endif
 
@@ -77,9 +77,10 @@ struct stmmac_priv {
 	spinlock_t lock;
 	int wolopts;
 	int wolenabled;
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 	struct stmmac_timer *tm;
 #endif
+	unsigned int timer;
 #ifdef STMMAC_VLAN_TAG_USED
 	struct vlan_group *vlgrp;
 #endif
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 26714b4..53a7086 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -122,7 +122,7 @@ MODULE_PARM_DESC(tc, "DMA threshold control value");
 /* Pay attention to tune this parameter; take care of both
  * hardware capability and network stabitily/performance impact.
  * Many tests showed that ~4ms latency seems to be good enough. */
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 #define DEFAULT_PERIODIC_RATE	256
 static int tmrate = DEFAULT_PERIODIC_RATE;
 module_param(tmrate, int, S_IRUGO | S_IWUSR);
@@ -415,9 +415,9 @@ static void init_dma_desc_rings(struct net_device *dev)
 	else
 		bfsize = DMA_BUFFER_SIZE;
 
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 	/* Disable interrupts on completion for the reception if timer is on */
-	if (likely(priv->tm->enable))
+	if (likely(priv->timer == external))
 		dis_ic = 1;
 #endif
 	/* If the MTU exceeds 8k so use the second buffer in the chain */
@@ -650,8 +650,8 @@ static void stmmac_tx(struct stmmac_priv *priv)
 
 static inline void stmmac_enable_irq(struct stmmac_priv *priv)
 {
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	if (likely(priv->timer == external))
 		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 	else
 #endif
@@ -660,8 +660,8 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv)
 
 static inline void stmmac_disable_irq(struct stmmac_priv *priv)
 {
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	if (likely(priv->timer == external))
 		priv->tm->timer_stop(priv->tm->timer_callb);
 	else
 #endif
@@ -693,7 +693,7 @@ static inline void _stmmac_schedule(struct stmmac_priv *priv)
 	}
 }
 
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 void stmmac_schedule(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
@@ -795,7 +795,7 @@ static int stmmac_open(struct net_device *dev)
 		return ret;
 	}
 
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 	priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
 	if (unlikely(priv->tm == NULL)) {
 		pr_err("%s: ERROR: timer memory alloc failed\n", __func__);
@@ -812,7 +812,7 @@ static int stmmac_open(struct net_device *dev)
 		priv->tm->timer_start = stmmac_no_timer_started;
 		priv->tm->timer_stop = stmmac_no_timer_stopped;
 	} else
-		priv->tm->enable = 1;
+		priv->timer = external;
 #endif
 
 	/* Create and initialize the TX/RX descriptors chains. */
@@ -863,8 +863,8 @@ static int stmmac_open(struct net_device *dev)
 	priv->hw->dma->start_tx(priv->ioaddr);
 	priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	if (likely(priv->timer == external))
 		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 #endif
 	/* Dump DMA/MAC registers */
@@ -901,11 +901,13 @@ static int stmmac_release(struct net_device *dev)
 
 	netif_stop_queue(dev);
 
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 	/* Stop and release the timer */
-	stmmac_close_ext_timer(priv->tm->timer_callb);
-	if (priv->tm != NULL)
+	if (priv->tm != NULL) {
+		if (likely(priv->timer == external))
+			stmmac_close_ext_timer(priv->tm->timer_callb);
 		kfree(priv->tm);
+	}
 #endif
 	napi_disable(&priv->napi);
 	skb_queue_purge(&priv->rx_recycle);
@@ -1096,9 +1098,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Interrupt on completition only for the latest segment */
 	priv->hw->desc->close_tx_desc(desc);
 
-#ifdef CONFIG_STMMAC_TIMER
-	/* Clean IC while using timer */
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	/* Clean IC while using ext timer */
+	if (likely(priv->timer == external))
 		priv->hw->desc->clear_tx_ic(desc);
 #endif
 	/* To avoid raise condition */
@@ -1815,10 +1817,11 @@ static int stmmac_suspend(struct device *dev)
 	if (priv->phydev)
 		phy_stop(priv->phydev);
 
-#ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_stop(priv->tm->timer_callb);
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	if (likely(priv->timer == external)) {
+		priv->tm->timer_stop(priv->tm->timer_callb);
 		dis_ic = 1;
+	}
 #endif
 	napi_disable(&priv->napi);
 
@@ -1865,8 +1868,8 @@ static int stmmac_resume(struct device *dev)
 	priv->hw->dma->start_tx(priv->ioaddr);
 	priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
+#ifdef CONFIG_STMMAC_EXT_TIMER
+	if (likely(priv->timer == external))
 		priv->tm->timer_start(priv->tm->timer_callb, tmrate);
 #endif
 	napi_enable(&priv->napi);
@@ -1977,7 +1980,7 @@ static int __init stmmac_cmdline_opt(char *str)
 				       (unsigned long *)&flow_ctrl);
 		else if (!strncmp(opt, "pause:", 6))
 			strict_strtoul(opt + 6, 0, (unsigned long *)&pause);
-#ifdef CONFIG_STMMAC_TIMER
+#ifdef CONFIG_STMMAC_EXT_TIMER
 		else if (!strncmp(opt, "tmrate:", 7))
 			strict_strtoul(opt + 7, 0, (unsigned long *)&tmrate);
 #endif
diff --git a/drivers/net/stmmac/stmmac_timer.c b/drivers/net/stmmac/stmmac_timer.c
index 2481daa..e64db59 100644
--- a/drivers/net/stmmac/stmmac_timer.c
+++ b/drivers/net/stmmac/stmmac_timer.c
@@ -102,7 +102,7 @@ int stmmac_close_ext_timer(void *timer)
 	return 0;
 }
 
-#elif defined(CONFIG_STMMAC_TMU_TIMER)
+#elif defined(CONFIG_STMMAC_GEN_TIMER)
 #include <linux/generictimer.h>
 
 /* Set rate and start the timer */
@@ -131,7 +131,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 	if (timer == NULL)
 		return -1;
 
-	STMMAC_TIMER_MSG(dev->name, "sh_tmu", tm->freq);
+	STMMAC_TIMER_MSG(dev->name, "Generic", tm->freq);
 
 	tm->timer_callb = timer;
 	tm->timer_start = stmmac_tmu_set_rate;
diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h
index 250f5cb..d719bd5 100644
--- a/drivers/net/stmmac/stmmac_timer.h
+++ b/drivers/net/stmmac/stmmac_timer.h
@@ -26,7 +26,6 @@ struct stmmac_timer {
 	void (*timer_start) (void *timer, unsigned int new_freq);
 	void (*timer_stop) (void *timer);
 	unsigned int freq;
-	unsigned int enable;
 	void *timer_callb;
 };
 
-- 
1.7.4

^ permalink raw reply related

* [PATCH] llc: avoid skb_clone() if there is only one handler
From: Changli Gao @ 2011-02-22 11:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: David S. Miller, netdev, Changli Gao

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
---
 net/llc/llc_input.c |   25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index f996874..058f1e9 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -181,25 +181,26 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 	 * LLC functionality
 	 */
 	rcv = rcu_dereference(sap->rcv_func);
-	if (rcv) {
-		struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
-		if (cskb)
-			rcv(cskb, dev, pt, orig_dev);
-	}
 	dest = llc_pdu_type(skb);
-	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
-		goto drop_put;
-	llc_type_handlers[dest - 1](sap, skb);
-out_put:
+	if (unlikely(!dest || !llc_type_handlers[dest - 1])) {
+		if (rcv)
+			rcv(skb, dev, pt, orig_dev);
+		else
+			kfree_skb(skb);
+	} else {
+		if (rcv) {
+			struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+			if (cskb)
+				rcv(cskb, dev, pt, orig_dev);
+		}
+		llc_type_handlers[dest - 1](sap, skb);
+	}
 	llc_sap_put(sap);
 out:
 	return 0;
 drop:
 	kfree_skb(skb);
 	goto out;
-drop_put:
-	kfree_skb(skb);
-	goto out_put;
 handle_station:
 	if (!llc_station_handler)
 		goto drop;

^ permalink raw reply related

* [PATCH] r8169: disable ASPM
From: Stanislaw Gruszka @ 2011-02-22 12:00 UTC (permalink / raw)
  To: netdev; +Cc: Francois Romieu, stable

r8169: disable ASPM

For some time is known that ASPM is causing troubles on r8169, i.e. make
device randomly stop working without any errors in dmesg.

Currently Tomi Leppikangas reports that system with r8169 device hangs
with MCE errors when ASPM is enabled:
https://bugzilla.redhat.com/show_bug.cgi?id=642861#c4

Lets disable ASPM for r8169 devices at all, to avoid problems with
r8169 PCIe devices at least for some users.

Reported-by: Tomi Leppikangas <tomi.leppikangas@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
I have to add (with shame on us) that we selfishly carry this patch
in RHEL6 for some time now.

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 469ab0b..ae40c0e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/firmware.h>
+#include <linux/pci-aspm.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -3009,6 +3010,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	mii->reg_num_mask = 0x1f;
 	mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
 
+	/* disable ASPM completely as that cause random device stop working
+	 * problems as well as full system hangs for some PCIe devices users */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				     PCIE_LINK_STATE_CLKPM);
+
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
 	rc = pci_enable_device(pdev);
 	if (rc < 0) {

^ permalink raw reply related

* Re: [PATCH ethtool 5/5] ethtool: Add --version option
From: Ben Hutchings @ 2011-02-22 12:37 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <1561212236.5138.1298355384916.JavaMail.root@tahiti.vyatta.com>

On Mon, 2011-02-21 at 22:16 -0800, Stephen Hemminger wrote:
[...]
> The standard convention is to use -V for short form of version option.

This is not anywhere near standard.

$ cp -V
cp: invalid option -- 'V'
Try `cp --help' for more information.
$ bash -V
bash: -V: invalid option
[...]
$ emacs -V
[opens window]
$ vim -V
chdir(/usr/share/vim)
fchdir() to previous dir
sourcing "$VIM/vimrc"
[...looks like that meant 'verbose'...]

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH 2/2] DM9000B: Fix PHY power for network down/up
From: Sergei Shtylyov @ 2011-02-22 12:36 UTC (permalink / raw)
  To: Henry Nestler; +Cc: Sergei Shtylyov, netdev, akpm, linux-arm-kernel, tori
In-Reply-To: <4D62D323.7010403@henry.nestler.mail.gmail.com>

Hello.

On 22-02-2011 0:03, Henry Nestler wrote:

>>> DM9000 revision B needs 1 ms delay after PHY power on (see spec), and PHY
>>> power must on in register

>>      Couldn't parse that.

    You seem to have missed a word in your patch description.

> This can read in manual DM900B-12-DS-F02 from September 2 2010, Page 14:
> "If this Register 1FH bit 0 is updated from '1' to '0', the all
> Registers can not be accessed within 1ms."

    That I've understood.

> The example driver code waits 2 ms.

>>> diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
>>> index 2d4c4fc..5925569 100644
>>> --- a/drivers/net/dm9000.c
>>> +++ b/drivers/net/dm9000.c
>> [...]
>>> @@ -1194,6 +1191,10 @@ dm9000_open(struct net_device *dev)
>>>    	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
>>>    		return -EAGAIN;
>>>
>>> +	/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
>>> +	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
>>> +	udelay(1000); /* delay needs by DM9000B */

>>      Why not mdelay(1)?

> Because udelay is the base of mdelay.
> See include/linux/delay.h:31

> #define mdelay(n) ... udelay((n)*1000)

    And?

WBR, Sergei

^ permalink raw reply

* Re: why all packets have same queue no when rps enabled?
From: Ben Hutchings @ 2011-02-22 12:45 UTC (permalink / raw)
  To: Jon Zhou; +Cc: netdev@vger.kernel.org
In-Reply-To: <4A6A2125329CFD4D8CC40C9E8ABCAB9F24D3DE6D0C@MILEXCH2.ds.jdsu.net>

On Mon, 2011-02-21 at 20:07 -0800, Jon Zhou wrote:
> Hi
> 
> I expect each incoming packet will have a different queue no. when I
> enabled RPS on kernel 2.6.36.4
[...]
> Looks almost all packets fall at same queue?
> Will RPS allocate queue no for each packet? and what hash algorithm
> rps used? (is it Toeplitz hash algorithm?)

The queue number identifies a hardware queue.  RPS therefore does not
update this number when queueing packets for processing on other CPUs.

If the hardware/driver provides a receive hash (probably Toeplitz) then
this is used for RPS.  Otherwise a much cheaper hash is used.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: why all packets have same queue no when rps enabled?
From: Eric Dumazet @ 2011-02-22 13:01 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Jon Zhou, netdev@vger.kernel.org
In-Reply-To: <1298378756.2211.478.camel@localhost>

Le mardi 22 février 2011 à 12:45 +0000, Ben Hutchings a écrit :

> The queue number identifies a hardware queue.  RPS therefore does not
> update this number when queueing packets for processing on other CPUs.
> 
> If the hardware/driver provides a receive hash (probably Toeplitz) then
> this is used for RPS.  Otherwise a much cheaper hash is used.

The default is/should be : rxhash generated in network stack.

ethtool -k eth0 | grep hash
receive-hashing: off

To use the device/harwdare provided rxhash, you need to ask for it.

ethtool -K eth0 rxhash on



BTW, I am not sure what you mean by "much cheaper hash is used"...

I presume hardware provided hash is less expensive (for our cpu) than
computing our rxhash...




^ permalink raw reply

* Re: [PATCH ethtool 5/5] ethtool: Add --version option
From: Eric Dumazet @ 2011-02-22 13:05 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Stephen Hemminger, netdev
In-Reply-To: <1298378228.2211.472.camel@localhost>

Le mardi 22 février 2011 à 12:37 +0000, Ben Hutchings a écrit :
> On Mon, 2011-02-21 at 22:16 -0800, Stephen Hemminger wrote:
> [...]
> > The standard convention is to use -V for short form of version option.
> 
> This is not anywhere near standard.
> 
> $ cp -V
> cp: invalid option -- 'V'
> Try `cp --help' for more information.
> $ bash -V
> bash: -V: invalid option
> [...]
> $ emacs -V
> [opens window]
> $ vim -V
> chdir(/usr/share/vim)
> fchdir() to previous dir
> sourcing "$VIM/vimrc"
> [...looks like that meant 'verbose'...]

Now try with networking tools, many use -V

(As a matter of fact, ethtool -h already is used to display help)

# ping -V
ping utility, iputils-sss20071127
# tc -V
tc utility, iproute2-ss100823
# ssh -V
OpenSSH_5.1p1 Debian-5, OpenSSL 0.9.8g 19 Oct 2007




^ permalink raw reply

* Re: why all packets have same queue no when rps enabled?
From: Ben Hutchings @ 2011-02-22 13:09 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Jon Zhou, netdev@vger.kernel.org
In-Reply-To: <1298379718.2861.3.camel@edumazet-laptop>

On Tue, 2011-02-22 at 14:01 +0100, Eric Dumazet wrote:
> Le mardi 22 février 2011 à 12:45 +0000, Ben Hutchings a écrit :
> 
> > The queue number identifies a hardware queue.  RPS therefore does not
> > update this number when queueing packets for processing on other CPUs.
> > 
> > If the hardware/driver provides a receive hash (probably Toeplitz) then
> > this is used for RPS.  Otherwise a much cheaper hash is used.
> 
> The default is/should be : rxhash generated in network stack.
> 
> ethtool -k eth0 | grep hash
> receive-hashing: off
> 
> To use the device/harwdare provided rxhash, you need to ask for it.
> 
> ethtool -K eth0 rxhash on

Whether this is enabled by default depends on the driver.

> BTW, I am not sure what you mean by "much cheaper hash is used"...
> 
> I presume hardware provided hash is less expensive (for our cpu) than
> computing our rxhash...

I mean the hash function we use is much cheaper than Toeplitz.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply


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