Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next-2.6] IB/{nes,ipoib}: Pass supported flags to ethtool_op_set_flags()
From: David Miller @ 2010-07-04 18:48 UTC (permalink / raw)
  To: rdreier
  Cc: bhutchings, rolandd, randy.dunlap, netdev, linux-net-drivers,
	sgruszka, amit.salecha, amwang, anirban.chakraborty, dm, scofeldm,
	vkolluri, roprabhu, e1000-devel, buytenh, gallatin, brice,
	shemminger, jgarzik, faisal.latif, chien.tin.tung, linux-rdma
In-Reply-To: <adask40nxaa.fsf@roland-alpha.cisco.com>

From: Roland Dreier <rdreier@cisco.com>
Date: Sat, 03 Jul 2010 13:08:29 -0700

>  > Following commit 1437ce3983bcbc0447a0dedcd644c14fe833d266 "ethtool:
>  > Change ethtool_op_set_flags to validate flags", ethtool_op_set_flags
>  > takes a third parameter and cannot be used directly as an
>  > implementation of ethtool_ops::set_flags.
> 
> Acked-by: Roland Dreier <rolandd@cisco.com>

Applied, thanks guys.

^ permalink raw reply

* Re: bnx2/5709: Strange interrupts spread
From: Christophe Ngo Van Duc @ 2010-07-04 20:36 UTC (permalink / raw)
  To: netdev@vger.kernel.org
In-Reply-To: <AANLkTimTcqANb3HQuC1W6VHWTh0ixO1lXAmVrmP6OZy2@mail.gmail.com>

Is it a requirement that the interface has an IP address for the TX
and RX hash to work?

Christophe.

On Fri, Jul 2, 2010 at 7:12 PM, Christophe Ngo Van Duc
<cngovanduc@gmail.com> wrote:
> Hi
>
> Well that's the strange thing: it is IP traffic. The only difference
> with eth0 and eth1 is that eth2 and eth3 belongs to a bridge (br0).
>
> Best Regards,
> Christophe.
>
> On 7/2/10, Michael Chan <mchan@broadcom.com> wrote:
>>
>> On Fri, 2010-07-02 at 13:33 -0700, Christophe Ngo Van Duc wrote:
>>> On eth2 (external card) all interrupts goes to CPU0
>>>
>>>
>>>            CPU0       CPU1       CPU2       CPU3       CPU4       CPU5
>>>   CPU6       CPU7
>>>   80:   46973077          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-0
>>>   81:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-1
>>>   82:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-2
>>>   83:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-3
>>>   84:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-4
>>>   85:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-5
>>>   86:          0          0       2445          0         37          0
>>>    8463         13   PCI-MSI-edge      eth2-6
>>>   87:          0          0          0          0          0          0
>>>       0          0   PCI-MSI-edge      eth2-7
>>
>> Reformatted your output
>>
>>> If I understand correctly the RSS hash is used to dispatch the packets
>>> into the different queues running on the different CPU.
>>
>> It looks like most interrupts go to eth2-0, a few go to eth2-6.  The rx
>> ring for eth2-0 is for non-IP packets.  The RSS hash will hash IP
>> packets and place them on eth2-1 to eth2-7.  eth2-0 also handles tx
>> interrupts for TX ring 0.  TX traffic is hashed by the stack.
>>
>> What kind of traffic is passing through eth2?
>>
>> Thanks.
>>
>>
>>
>
> --
> Sent from my mobile device
>

^ permalink raw reply

* RE: [REGRESSION] e1000e stopped working [MANUALLY BISECTED]
From: Maxim Levitsky @ 2010-07-04 22:48 UTC (permalink / raw)
  To: Tantilov, Emil S
  Cc: netdev@vger.kernel.org, Allan, Bruce W, Pieper, Jeffrey E
In-Reply-To: <1278204106.21020.0.camel@localhost.localdomain>

Did few guesses, and now I see that reverting the below commit fixes the
problem.

"e1000e: Fix/cleanup PHY reset code for ICHx/PCHx"
e98cac447cc1cc418dff1d610a5c79c4f2bdec7f.


Best regards,
	Maxim Levitsky


^ permalink raw reply

* [PATCH] ks8842: Replace usage of dev_dbg with netdev_dbg
From: Richard Röjfors @ 2010-07-04 23:26 UTC (permalink / raw)
  To: netdev; +Cc: davem

This patch replaces all usage of dev_dbg with netdev_dbg.

A side effect is that the pointer to the platform device in the adapter
struct can be removed.

Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com>
---
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index f852ab3..d47bba9 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -119,7 +119,6 @@ struct ks8842_adapter {
 	int		irq;
 	struct tasklet_struct	tasklet;
 	spinlock_t	lock; /* spinlock to be interrupt safe */
-	struct platform_device *pdev;
 };
 
 static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
@@ -331,8 +330,7 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
 	u32 *ptr = (u32 *)skb->data;
 	u32 ctrl;
 
-	dev_dbg(&adapter->pdev->dev,
-		"%s: len %u head %p data %p tail %p end %p\n",
+	netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n",
 		__func__, skb->len, skb->head, skb->data,
 		skb_tail_pointer(skb), skb_end_pointer(skb));
 
@@ -369,15 +367,13 @@ static void ks8842_rx_frame(struct net_device *netdev,
 
 	status &= 0xffff;
 
-	dev_dbg(&adapter->pdev->dev, "%s - rx_data: status: %x\n",
-		__func__, status);
+	netdev_dbg(netdev, "%s - rx_data: status: %x\n", __func__, status);
 
 	/* check the status */
 	if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
 		struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len);
 
-		dev_dbg(&adapter->pdev->dev, "%s, got package, len: %d\n",
-			__func__, len);
+		netdev_dbg(netdev, "%s, got package, len: %d\n", __func__, len);
 		if (skb) {
 			u32 *data;
 
@@ -400,7 +396,7 @@ static void ks8842_rx_frame(struct net_device *netdev,
 		} else
 			netdev->stats.rx_dropped++;
 	} else {
-		dev_dbg(&adapter->pdev->dev, "RX error, status: %x\n", status);
+		netdev_dbg(netdev, "RX error, status: %x\n", status);
 		netdev->stats.rx_errors++;
 		if (status & RXSR_TOO_LONG)
 			netdev->stats.rx_length_errors++;
@@ -423,8 +419,7 @@ static void ks8842_rx_frame(struct net_device *netdev,
 void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
 {
 	u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
-	dev_dbg(&adapter->pdev->dev, "%s Entry - rx_data: %d\n",
-		__func__, rx_data);
+	netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data);
 	while (rx_data) {
 		ks8842_rx_frame(netdev, adapter);
 		rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
@@ -434,7 +429,7 @@ void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
 void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
 {
 	u16 sr = ks8842_read16(adapter, 16, REG_TXSR);
-	dev_dbg(&adapter->pdev->dev, "%s - entry, sr: %x\n", __func__, sr);
+	netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr);
 	netdev->stats.tx_packets++;
 	if (netif_queue_stopped(netdev))
 		netif_wake_queue(netdev);
@@ -443,7 +438,7 @@ void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
 void ks8842_handle_rx_overrun(struct net_device *netdev,
 	struct ks8842_adapter *adapter)
 {
-	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+	netdev_dbg(netdev, "%s: entry\n", __func__);
 	netdev->stats.rx_errors++;
 	netdev->stats.rx_fifo_errors++;
 }
@@ -462,7 +457,7 @@ void ks8842_tasklet(unsigned long arg)
 	spin_unlock_irqrestore(&adapter->lock, flags);
 
 	isr = ks8842_read16(adapter, 18, REG_ISR);
-	dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr);
+	netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
 
 	/* Ack */
 	ks8842_write16(adapter, 18, isr, REG_ISR);
@@ -501,13 +496,14 @@ void ks8842_tasklet(unsigned long arg)
 
 static irqreturn_t ks8842_irq(int irq, void *devid)
 {
-	struct ks8842_adapter *adapter = devid;
+	struct net_device *netdev = devid;
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
 	u16 isr;
 	u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
 	irqreturn_t ret = IRQ_NONE;
 
 	isr = ks8842_read16(adapter, 18, REG_ISR);
-	dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr);
+	netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
 
 	if (isr) {
 		/* disable IRQ */
@@ -532,7 +528,7 @@ static int ks8842_open(struct net_device *netdev)
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
 	int err;
 
-	dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__);
+	netdev_dbg(netdev, "%s - entry\n", __func__);
 
 	/* reset the HW */
 	ks8842_reset_hw(adapter);
@@ -542,7 +538,7 @@ static int ks8842_open(struct net_device *netdev)
 	ks8842_update_link_status(netdev, adapter);
 
 	err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME,
-		adapter);
+		netdev);
 	if (err) {
 		pr_err("Failed to request IRQ: %d: %d\n", adapter->irq, err);
 		return err;
@@ -555,10 +551,10 @@ static int ks8842_close(struct net_device *netdev)
 {
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
 
-	dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__);
+	netdev_dbg(netdev, "%s - entry\n", __func__);
 
 	/* free the irq */
-	free_irq(adapter->irq, adapter);
+	free_irq(adapter->irq, netdev);
 
 	/* disable the switch */
 	ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE);
@@ -572,7 +568,7 @@ static netdev_tx_t ks8842_xmit_frame(struct sk_buff *skb,
 	int ret;
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
 
-	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+	netdev_dbg(netdev, "%s: entry\n", __func__);
 
 	ret = ks8842_tx_frame(skb, netdev);
 
@@ -588,7 +584,7 @@ static int ks8842_set_mac(struct net_device *netdev, void *p)
 	struct sockaddr *addr = p;
 	char *mac = (u8 *)addr->sa_data;
 
-	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+	netdev_dbg(netdev, "%s: entry\n", __func__);
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
@@ -604,7 +600,7 @@ static void ks8842_tx_timeout(struct net_device *netdev)
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
 
-	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+	netdev_dbg(netdev, "%s: entry\n", __func__);
 
 	spin_lock_irqsave(&adapter->lock, flags);
 	/* disable interrupts */
@@ -663,8 +659,6 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
 		goto err_get_irq;
 	}
 
-	adapter->pdev = pdev;
-
 	tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev);
 	spin_lock_init(&adapter->lock);
 


^ permalink raw reply related

* Re: [PATCH net-next-2.6] ipv6: adding ip_nonlocal_bind option from ipv4
From: Simon Horman @ 2010-07-05  2:03 UTC (permalink / raw)
  To: Michal Humpula; +Cc: netdev
In-Reply-To: <201007032238.28344.michal.humpula@web4u.cz>

On Sat, Jul 03, 2010 at 10:38:28PM +0200, Michal Humpula wrote:
> Adds ability to bind non-local IPv6 address the same way as for IPv4
> 
> Signed-off-by: Michal Humpula <michal.humpula@web4u.cz>
> 
> diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
> index f350c69..27fa09a 100644
> --- a/Documentation/networking/ip-sysctl.txt
> +++ b/Documentation/networking/ip-sysctl.txt
> @@ -962,6 +962,10 @@ bindv6only - BOOLEAN
>  		FALSE: enable IPv4-mapped address feature
>  
>  	Default: FALSE (as specified in RFC2553bis)

I think a blank line here would be nice.

> +ipv6_nonlocal_bind - BOOLEAN
> +	If set, allows processes to bind() to non-local IPv6 addresses,
> +	which can be quite useful - but may break some applications.
> +	Default: 0
>  
>  IPv6 Fragmentation:
>  
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index 7bb5cb6..8957ead 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -528,6 +528,7 @@ enum {
>  	NET_IPV6_IP6FRAG_TIME=23,
>  	NET_IPV6_IP6FRAG_SECRET_INTERVAL=24,
>  	NET_IPV6_MLD_MAX_MSF=25,
> +	NET_IPV6_NONLOCAL_BIND=26
>  };
>  
>  enum {
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 1f84124..f459fcb 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -641,6 +641,8 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
>  #endif
>  
>  #ifdef CONFIG_SYSCTL
> +extern int sysctl_ipv6_nonlocal_bind;
> +
>  extern ctl_table ipv6_route_table_template[];
>  extern ctl_table ipv6_icmp_table_template[];
>  
> diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
> index 1357c57..525edae 100644
> --- a/kernel/sysctl_binary.c
> +++ b/kernel/sysctl_binary.c
> @@ -559,6 +559,7 @@ static const struct bin_table bin_net_ipv6_table[] = {
>  	{ CTL_DIR,	NET_IPV6_ROUTE,		"route",	bin_net_ipv6_route_table },
>  	{ CTL_DIR,	NET_IPV6_ICMP,		"icmp",		bin_net_ipv6_icmp_table },
>  	{ CTL_INT,	NET_IPV6_BINDV6ONLY,		"bindv6only" },
> +	{ CTL_INT,	NET_IPV6_NONLOCAL_BIND,		"ipv6_nonlocal_bind" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_HIGH_THRESH,	"ip6frag_high_thresh" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_LOW_THRESH,	"ip6frag_low_thresh" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_TIME,		"ip6frag_time" },
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index e830cd4..55b3552 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -252,6 +252,8 @@ out_rcu_unlock:
>  	goto out;
>  }
>  
> +int sysctl_ipv6_nonlocal_bind __read_mostly;
> +EXPORT_SYMBOL(sysctl_ipv6_nonlocal_bind);
>  
>  /* bind for INET6 API */
>  int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> @@ -345,8 +347,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>  			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
>  				if (!ipv6_chk_addr(net, &addr->sin6_addr,
>  						   dev, 0)) {
> -					err = -EADDRNOTAVAIL;
> -					goto out_unlock;
> +					if (!sysctl_ipv6_nonlocal_bind) {
> +						err = -EADDRNOTAVAIL;
> +						goto out_unlock;
> +					}
>  				}
>  			}
>  			rcu_read_unlock();

Perhaps the inner two if statements could be combined to remove
unnecessary nesting? And perhaps check for sysctl_ipv6_nonlocal_bind first,
as presumably its a cheaper, though less likely to succeed check.

			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
				if (!sysctl_ipv6_nonlocal_bind &&
				    !ipv6_chk_addr(net, &addr->sin6_addr,
						   dev, 0)) {
					err = -EADDRNOTAVAIL;
					goto out_unlock;
				}
			}

Actually, I wonder if all three if statements could be combined.

			if (!(addr_type & IPV6_ADDR_MULTICAST) &&
		            !sysctl_ipv6_nonlocal_bind &&
			    !ipv6_chk_addr(net, &addr->sin6_addr, dev, 0)) {
				err = -EADDRNOTAVAIL;
				goto out_unlock;
			}

> diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
> index fa1d8f4..56bfe76 100644
> --- a/net/ipv6/sysctl_net_ipv6.c
> +++ b/net/ipv6/sysctl_net_ipv6.c
> @@ -35,6 +35,13 @@ static ctl_table ipv6_table_template[] = {
>  		.mode		= 0644,
>  		.proc_handler	= proc_dointvec
>  	},
> +	{
> +		.procname = "ipv6_nonlocal_bind",
> +		.data   = &sysctl_ipv6_nonlocal_bind,
> +		.maxlen   = sizeof(int),
> +		.mode   = 0644,
> +		.proc_handler = proc_dointvec
> +	},
>  	{ }
>  };
>  
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 0/4] Extend Time Stamping
From: Richard Cochran @ 2010-07-05  5:30 UTC (permalink / raw)
  To: netdev

This patch set extends the packet time stamping capabilites of the
network stack in two ways.

1. The first patch presents a work-around for the TX software time
   stamping fallback problem cited in cd4d8fdad1f1. The idea is to add
   two inline functions into each MAC driver. The functions will act
   as hooks for current (and possible future) time stamping needs,
   once they are placed correctly within each MAC driver.

2. The other patches prepare the way for PHY drivers to offer time
   stamping.

I am preparing a new round of patches for PTP support, but it will
require the changes in this patch set in order to function. Thus I
would like to have this patch set reviewed (and hopefully merged) in
order to go forward.

Thanks,
Richard

* Patch ChangeLog
** v2
   Removed the CONFIG option for the driver hooks.


Richard Cochran (4):
  net: add driver hooks for time stamping.
  phylib: add a way to make PHY time stamps possible.
  phylib: preserve ifreq parameter when calling generic phy_mii_ioctl()
  phylib: Allow reading and writing a mii bus from atomic context.

 drivers/net/arm/ixp4xx_eth.c           |    3 +-
 drivers/net/au1000_eth.c               |    2 +-
 drivers/net/bcm63xx_enet.c             |    2 +-
 drivers/net/cpmac.c                    |    5 +--
 drivers/net/dnet.c                     |    2 +-
 drivers/net/ethoc.c                    |    2 +-
 drivers/net/fec.c                      |    2 +-
 drivers/net/fec_mpc52xx.c              |    2 +-
 drivers/net/fs_enet/fs_enet-main.c     |    3 +-
 drivers/net/fsl_pq_mdio.c              |    4 +-
 drivers/net/gianfar.c                  |    2 +-
 drivers/net/macb.c                     |    2 +-
 drivers/net/mv643xx_eth.c              |    2 +-
 drivers/net/octeon/octeon_mgmt.c       |    2 +-
 drivers/net/phy/mdio_bus.c             |   45 ++++++++++++++++++---
 drivers/net/phy/phy.c                  |    8 +++-
 drivers/net/sb1250-mac.c               |    2 +-
 drivers/net/sh_eth.c                   |    2 +-
 drivers/net/smsc911x.c                 |    2 +-
 drivers/net/smsc9420.c                 |    2 +-
 drivers/net/stmmac/stmmac_main.c       |   22 ++++-------
 drivers/net/tc35815.c                  |    2 +-
 drivers/net/tg3.c                      |    2 +-
 drivers/net/ucc_geth.c                 |    2 +-
 drivers/staging/octeon/ethernet-mdio.c |    2 +-
 include/linux/phy.h                    |   24 ++++++++++-
 include/linux/skbuff.h                 |   65 ++++++++++++++++++++++++++++++++
 net/Kconfig                            |   11 +++++
 net/dsa/slave.c                        |    3 +-
 29 files changed, 175 insertions(+), 54 deletions(-)


^ permalink raw reply

* [PATCH 1/4] net: add driver hooks for time stamping.
From: Richard Cochran @ 2010-07-05  5:31 UTC (permalink / raw)
  To: netdev
In-Reply-To: <cover.1278307573.git.richard.cochran@omicron.at>

This patch adds hooks for transmit and receive time stamps. The
transmit hook allows a software fallback for transmit time stamps,
for MACs lacking time stamping hardware. The receive hook does not yet
have any effect, but it prepares the way for hardware time stamping
in PHY devices. Using the hooks will still require adding two inline
function calls to each MAC driver.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 include/linux/skbuff.h |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ac74ee0..75323fe 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -29,6 +29,7 @@
 #include <linux/rcupdate.h>
 #include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
+#include <linux/phy.h>
 
 /* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
@@ -1947,6 +1948,41 @@ static inline ktime_t net_invalid_timestamp(void)
 extern void skb_tstamp_tx(struct sk_buff *orig_skb,
 			struct skb_shared_hwtstamps *hwtstamps);
 
+static inline void sw_tx_timestamp(struct sk_buff *skb)
+{
+	union skb_shared_tx *shtx = skb_tx(skb);
+	if (shtx->software && !shtx->in_progress)
+		skb_tstamp_tx(skb, NULL);
+}
+
+/**
+ * skb_tx_timestamp() - Driver hook for transmit timestamping
+ *
+ * Ethernet MAC Drivers should call this function in their hard_xmit()
+ * function as soon as possible after giving the sk_buff to the MAC
+ * hardware, but before freeing the sk_buff.
+ *
+ * @phy: The port's phy_device. Pass NULL if this is not available.
+ * @skb: A socket buffer.
+ */
+static inline void skb_tx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+	sw_tx_timestamp(skb);
+}
+
+/**
+ * skb_rx_timestamp() - Driver hook for receive timestamping
+ *
+ * Ethernet MAC Drivers should call this function in their NAPI poll()
+ * function immediately before calling eth_type_trans().
+ *
+ * @phy: The port's phy_device. Pass NULL if this is not available.
+ * @skb: A socket buffer.
+ */
+static inline void skb_rx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+}
+
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/4] phylib: add a way to make PHY time stamps possible.
From: Richard Cochran @ 2010-07-05  5:32 UTC (permalink / raw)
  To: netdev
In-Reply-To: <cover.1278307573.git.richard.cochran@omicron.at>

This patch adds a new networking option to allow hardware time stamps
from PHY devices. Using PHY time stamps will still require adding two
inline function calls to each MAC driver. The CONFIG option makes
these calls safe to add, since the calls become NOOPs when the option
is disabled.

The patch also adds phylib driver methods for the SIOCSHWTSTAMP ioctl
and callbacks for transmit and receive time stamping. Drivers may
optionally implement these functions.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 include/linux/phy.h    |    7 +++++++
 include/linux/skbuff.h |   29 +++++++++++++++++++++++++++++
 net/Kconfig            |   11 +++++++++++
 3 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 987e111..3566bde 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -234,6 +234,8 @@ enum phy_state {
 	PHY_RESUMING
 };
 
+struct sk_buff;
+
 /* phy_device: An instance of a PHY
  *
  * drv: Pointer to the driver for this PHY instance
@@ -402,6 +404,11 @@ struct phy_driver {
 	/* Clears up any memory if needed */
 	void (*remove)(struct phy_device *phydev);
 
+	/* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */
+	int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr);
+	int (*rxtstamp)(struct phy_device *phydev, struct sk_buff *skb);
+	int (*txtstamp)(struct phy_device *phydev, struct sk_buff *skb);
+
 	struct device_driver driver;
 };
 #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 75323fe..8905508 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1955,6 +1955,33 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
 		skb_tstamp_tx(skb, NULL);
 }
 
+#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
+
+static inline void phy_tx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+	union skb_shared_tx *shtx = skb_tx(skb);
+	if (shtx->hardware && phy && phy->drv->txtstamp)
+		phy->drv->txtstamp(phy, skb);
+}
+
+static inline void phy_rx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+	if (phy && phy->drv->rxtstamp)
+		phy->drv->rxtstamp(phy, skb);
+}
+
+#else /* CONFIG_NETWORK_PHY_TIMESTAMPING */
+
+static inline void phy_tx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+}
+
+static inline void phy_rx_timestamp(struct phy_device *phy, struct sk_buff *skb)
+{
+}
+
+#endif /* !CONFIG_NETWORK_PHY_TIMESTAMPING */
+
 /**
  * skb_tx_timestamp() - Driver hook for transmit timestamping
  *
@@ -1967,6 +1994,7 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  */
 static inline void skb_tx_timestamp(struct phy_device *phy, struct sk_buff *skb)
 {
+	phy_tx_timestamp(phy, skb);
 	sw_tx_timestamp(skb);
 }
 
@@ -1981,6 +2009,7 @@ static inline void skb_tx_timestamp(struct phy_device *phy, struct sk_buff *skb)
  */
 static inline void skb_rx_timestamp(struct phy_device *phy, struct sk_buff *skb)
 {
+	phy_rx_timestamp(phy, skb);
 }
 
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
diff --git a/net/Kconfig b/net/Kconfig
index 0d68b40..3fa7ae3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -86,6 +86,17 @@ config NETWORK_SECMARK
 	  to nfmark, but designated for security purposes.
 	  If you are unsure how to answer this question, answer N.
 
+config NETWORK_PHY_TIMESTAMPING
+	bool "Timestamping in PHY devices"
+	depends on EXPERIMENTAL
+	help
+	  This allows timestamping of network packets by PHYs with
+	  hardware timestamping capabilities. This option adds some
+	  overhead in the transmit and receive paths. Note that this
+	  option also requires support in the MAC driver.
+
+	  If you are unsure how to answer this question, answer N.
+
 menuconfig NETFILTER
 	bool "Network packet filtering framework (Netfilter)"
 	---help---
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 3/4] phylib: preserve ifreq parameter when calling generic phy_mii_ioctl()
From: Richard Cochran @ 2010-07-05  5:33 UTC (permalink / raw)
  To: netdev
In-Reply-To: <cover.1278307573.git.richard.cochran@omicron.at>

The phy_mii_ioctl() function unnecessarily throws away the original ifreq.
We need access to the ifreq in order to support PHYs that can perform
hardware time stamping.

Two maverick drivers filter the ioctl commands passed to phy_mii_ioctl().
This is unnecessary since phylib will check the command in any case.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 drivers/net/arm/ixp4xx_eth.c           |    3 ++-
 drivers/net/au1000_eth.c               |    2 +-
 drivers/net/bcm63xx_enet.c             |    2 +-
 drivers/net/cpmac.c                    |    5 +----
 drivers/net/dnet.c                     |    2 +-
 drivers/net/ethoc.c                    |    2 +-
 drivers/net/fec.c                      |    2 +-
 drivers/net/fec_mpc52xx.c              |    2 +-
 drivers/net/fs_enet/fs_enet-main.c     |    3 +--
 drivers/net/gianfar.c                  |    2 +-
 drivers/net/macb.c                     |    2 +-
 drivers/net/mv643xx_eth.c              |    2 +-
 drivers/net/octeon/octeon_mgmt.c       |    2 +-
 drivers/net/phy/phy.c                  |    8 +++++++-
 drivers/net/sb1250-mac.c               |    2 +-
 drivers/net/sh_eth.c                   |    2 +-
 drivers/net/smsc911x.c                 |    2 +-
 drivers/net/smsc9420.c                 |    2 +-
 drivers/net/stmmac/stmmac_main.c       |   22 ++++++++--------------
 drivers/net/tc35815.c                  |    2 +-
 drivers/net/tg3.c                      |    2 +-
 drivers/net/ucc_geth.c                 |    2 +-
 drivers/staging/octeon/ethernet-mdio.c |    2 +-
 include/linux/phy.h                    |    2 +-
 net/dsa/slave.c                        |    3 +--
 25 files changed, 39 insertions(+), 43 deletions(-)

diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index ee2f842..4f1cc71 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -782,7 +782,8 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 
 	if (!netif_running(dev))
 		return -EINVAL;
-	return phy_mii_ioctl(port->phydev, if_mii(req), cmd);
+
+	return phy_mii_ioctl(port->phydev, req, cmd);
 }
 
 /* ethtool support */
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index ece6128..386d4fe 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -978,7 +978,7 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!aup->phy_dev)
 		return -EINVAL; /* PHY not controllable */
 
-	return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd);
+	return phy_mii_ioctl(aup->phy_dev, rq, cmd);
 }
 
 static const struct net_device_ops au1000_netdev_ops = {
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index faf5add..0d2c5da 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -1496,7 +1496,7 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (priv->has_phy) {
 		if (!priv->phydev)
 			return -ENODEV;
-		return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+		return phy_mii_ioctl(priv->phydev, rq, cmd);
 	} else {
 		struct mii_if_info mii;
 
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 1756d28..cdb05bb 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -846,11 +846,8 @@ static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		return -EINVAL;
 	if (!priv->phy)
 		return -EINVAL;
-	if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) ||
-	    (cmd == SIOCSMIIREG))
-		return phy_mii_ioctl(priv->phy, if_mii(ifr), cmd);
 
-	return -EOPNOTSUPP;
+	return phy_mii_ioctl(priv->phy, ifr, cmd);
 }
 
 static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 8b0f50b..4ea7141 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -797,7 +797,7 @@ static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
 static void dnet_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 37ce8ac..d9f3106 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -732,7 +732,7 @@ static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		phy = priv->phy;
 	}
 
-	return phy_mii_ioctl(phy, mdio, cmd);
+	return phy_mii_ioctl(phy, ifr, cmd);
 }
 
 static int ethoc_config(struct net_device *dev, struct ifmap *map)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index b4afd7a..1670866 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -828,7 +828,7 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
 static void fec_enet_free_buffers(struct net_device *dev)
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 25e6cc6..fdbf148 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -826,7 +826,7 @@ static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!priv->phydev)
 		return -ENOTSUPP;
 
-	return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(priv->phydev, rq, cmd);
 }
 
 static const struct net_device_ops mpc52xx_fec_netdev_ops = {
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 309a0ea..f08cff9 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -963,12 +963,11 @@ static const struct ethtool_ops fs_ethtool_ops = {
 static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	return phy_mii_ioctl(fep->phydev, mii, cmd);
+	return phy_mii_ioctl(fep->phydev, rq, cmd);
 }
 
 extern int fs_mii_connect(struct net_device *dev);
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index fccb7a3..1d16d51 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -847,7 +847,7 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!priv->phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(priv->phydev, rq, cmd);
 }
 
 static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 40797fb..ff2f158 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -1082,7 +1082,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
 static const struct net_device_ops macb_netdev_ops = {
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 82b720f..0561425 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2457,7 +2457,7 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 
 	if (mp->phy != NULL)
-		return phy_mii_ioctl(mp->phy, if_mii(ifr), cmd);
+		return phy_mii_ioctl(mp->phy, ifr, cmd);
 
 	return -EOPNOTSUPP;
 }
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index f4a0f08..b264f0f 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -620,7 +620,7 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
 	if (!p->phydev)
 		return -EINVAL;
 
-	return phy_mii_ioctl(p->phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(p->phydev, rq, cmd);
 }
 
 static void octeon_mgmt_adjust_link(struct net_device *netdev)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 64be466..5130db8 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -309,8 +309,9 @@ EXPORT_SYMBOL(phy_ethtool_gset);
  * current state.  Use at own risk.
  */
 int phy_mii_ioctl(struct phy_device *phydev,
-		struct mii_ioctl_data *mii_data, int cmd)
+		struct ifreq *ifr, int cmd)
 {
+	struct mii_ioctl_data *mii_data = if_mii(ifr);
 	u16 val = mii_data->val_in;
 
 	switch (cmd) {
@@ -360,6 +361,11 @@ int phy_mii_ioctl(struct phy_device *phydev,
 		}
 		break;
 
+	case SIOCSHWTSTAMP:
+		if (phydev->drv->hwtstamp)
+			return phydev->drv->hwtstamp(phydev, ifr);
+		/* fall through */
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 1f3acc3..e585c3f 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2532,7 +2532,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!netif_running(dev) || !sc->phy_dev)
 		return -EINVAL;
 
-	return phy_mii_ioctl(sc->phy_dev, if_mii(rq), cmd);
+	return phy_mii_ioctl(sc->phy_dev, rq, cmd);
 }
 
 static int sbmac_close(struct net_device *dev)
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 501a55f..8279f8e 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1233,7 +1233,7 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
 	if (!phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
 #if defined(SH_ETH_HAS_TSU)
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index cc55974..56dc2ff 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -1538,7 +1538,7 @@ static int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	if (!netif_running(dev) || !pdata->phy_dev)
 		return -EINVAL;
 
-	return phy_mii_ioctl(pdata->phy_dev, if_mii(ifr), cmd);
+	return phy_mii_ioctl(pdata->phy_dev, ifr, cmd);
 }
 
 static int
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 6cdee6a..b09ee1c 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -245,7 +245,7 @@ static int smsc9420_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	if (!netif_running(dev) || !pd->phy_dev)
 		return -EINVAL;
 
-	return phy_mii_ioctl(pd->phy_dev, if_mii(ifr), cmd);
+	return phy_mii_ioctl(pd->phy_dev, ifr, cmd);
 }
 
 static int smsc9420_ethtool_get_settings(struct net_device *dev,
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index a31d580..acf0616 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -1437,24 +1437,18 @@ static void stmmac_poll_controller(struct net_device *dev)
 static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	int ret = -EOPNOTSUPP;
+	int ret;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		if (!priv->phydev)
-			return -EINVAL;
-
-		spin_lock(&priv->lock);
-		ret = phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
-		spin_unlock(&priv->lock);
-	default:
-		break;
-	}
+	if (!priv->phydev)
+		return -EINVAL;
+
+	spin_lock(&priv->lock);
+	ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+	spin_unlock(&priv->lock);
+
 	return ret;
 }
 
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index be08b75..99e423a 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -2066,7 +2066,7 @@ static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		return -EINVAL;
 	if (!lp->phy_dev)
 		return -ENODEV;
-	return phy_mii_ioctl(lp->phy_dev, if_mii(rq), cmd);
+	return phy_mii_ioctl(lp->phy_dev, rq, cmd);
 }
 
 static void tc35815_chip_reset(struct net_device *dev)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 289cdc5..d4163f2 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10954,7 +10954,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
 			return -EAGAIN;
 		phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
-		return phy_mii_ioctl(phydev, data, cmd);
+		return phy_mii_ioctl(phydev, ifr, cmd);
 	}
 
 	switch (cmd) {
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index dc32a62..e17dd74 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3714,7 +3714,7 @@ static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!ugeth->phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(ugeth->phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(ugeth->phydev, rq, cmd);
 }
 
 static const struct net_device_ops ucc_geth_netdev_ops = {
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 7e0be8d..10a82ef 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -113,7 +113,7 @@ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!priv->phydev)
 		return -EINVAL;
 
-	return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+	return phy_mii_ioctl(priv->phydev, rq, cmd);
 }
 
 static void cvm_oct_adjust_link(struct net_device *dev)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 3566bde..7a8caac 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -505,7 +505,7 @@ void phy_stop_machine(struct phy_device *phydev);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_mii_ioctl(struct phy_device *phydev,
-		struct mii_ioctl_data *mii_data, int cmd);
+		struct ifreq *ifr, int cmd);
 int phy_start_interrupts(struct phy_device *phydev);
 void phy_print_status(struct phy_device *phydev);
 struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8fdca56..64ca2a6 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -164,10 +164,9 @@ out:
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct mii_ioctl_data *mii_data = if_mii(ifr);
 
 	if (p->phy != NULL)
-		return phy_mii_ioctl(p->phy, mii_data, cmd);
+		return phy_mii_ioctl(p->phy, ifr, cmd);
 
 	return -EOPNOTSUPP;
 }
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/4] phylib: Allow reading and writing a mii bus from atomic context.
From: Richard Cochran @ 2010-07-05  5:33 UTC (permalink / raw)
  To: netdev
In-Reply-To: <cover.1278307573.git.richard.cochran@omicron.at>

In order to support hardware time stamping from a PHY, it is necessary to
read from the PHY while running in_interrupt(). This patch allows a mii
bus to operate in an atomic context. An mii_bus driver may declare itself
capable for this mode. Drivers which do not do this will remain with the
default that bus operations may sleep.

Before commit 35b5f6b1a82b5c586e0b24c711dc6ba944e88ef1 mii bus
operations were protected with spin locks. That commit replaced the
locks with mutexs in order to accommodate i2c buses that need to
sleep. Thus, this patch restores the original behavior as a run time
option.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 drivers/net/fsl_pq_mdio.c  |    4 +-
 drivers/net/phy/mdio_bus.c |   45 +++++++++++++++++++++++++++++++++++++------
 include/linux/phy.h        |   15 ++++++++++++-
 3 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index b4c41d7..0b34f50 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -145,7 +145,7 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
 	struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
 	int timeout = PHY_INIT_TIMEOUT;
 
-	mutex_lock(&bus->mdio_lock);
+	mdiobus_lock(bus);
 
 	/* Reset the management interface */
 	out_be32(&regs->miimcfg, MIIMCFG_RESET);
@@ -157,7 +157,7 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
 	while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
 		cpu_relax();
 
-	mutex_unlock(&bus->mdio_lock);
+	mdiobus_unlock(bus);
 
 	if (timeout < 0) {
 		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 6a6b819..ad6bed8 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -37,6 +37,32 @@
 #include <asm/uaccess.h>
 
 /**
+ * mdiobus_lock - locks a given bus for read or write operations.
+ * @bus: target mii_bus
+ */
+void mdiobus_lock(struct mii_bus *bus)
+{
+	if (MDIOBUS_SLEEPS_RW == bus->locktype)
+		mutex_lock(&bus->lock.m);
+	else
+		spin_lock(&bus->lock.s);
+}
+EXPORT_SYMBOL(mdiobus_lock);
+
+/**
+ * mdiobus_unlock - unlocks a given bus for read or write operations.
+ * @bus: target mii_bus
+ */
+void mdiobus_unlock(struct mii_bus *bus)
+{
+	if (MDIOBUS_SLEEPS_RW == bus->locktype)
+		mutex_unlock(&bus->lock.m);
+	else
+		spin_unlock(&bus->lock.s);
+}
+EXPORT_SYMBOL(mdiobus_unlock);
+
+/**
  * mdiobus_alloc - allocate a mii_bus structure
  *
  * Description: called by a bus driver to allocate an mii_bus
@@ -107,7 +133,10 @@ int mdiobus_register(struct mii_bus *bus)
 		return -EINVAL;
 	}
 
-	mutex_init(&bus->mdio_lock);
+	if (MDIOBUS_SLEEPS_RW == bus->locktype)
+		mutex_init(&bus->lock.m);
+	else
+		spin_lock_init(&bus->lock.s);
 
 	if (bus->reset)
 		bus->reset(bus);
@@ -212,11 +241,12 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
 {
 	int retval;
 
-	BUG_ON(in_interrupt());
+	if (MDIOBUS_SLEEPS_RW == bus->locktype)
+		BUG_ON(in_interrupt());
 
-	mutex_lock(&bus->mdio_lock);
+	mdiobus_lock(bus);
 	retval = bus->read(bus, addr, regnum);
-	mutex_unlock(&bus->mdio_lock);
+	mdiobus_unlock(bus);
 
 	return retval;
 }
@@ -237,11 +267,12 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
 {
 	int err;
 
-	BUG_ON(in_interrupt());
+	if (MDIOBUS_SLEEPS_RW == bus->locktype)
+		BUG_ON(in_interrupt());
 
-	mutex_lock(&bus->mdio_lock);
+	mdiobus_lock(bus);
 	err = bus->write(bus, addr, regnum, val);
-	mutex_unlock(&bus->mdio_lock);
+	mdiobus_unlock(bus);
 
 	return err;
 }
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7a8caac..93ea55f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -98,11 +98,20 @@ struct mii_bus {
 	int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
 	int (*reset)(struct mii_bus *bus);
 
+	/* Indicates whether bus may be used from an atomic context. */
+	enum {
+		MDIOBUS_SLEEPS_RW,
+		MDIOBUS_ATOMIC_RW
+	} locktype;
+
 	/*
-	 * A lock to ensure that only one thing can read/write
+	 * A lock or mutex to ensure that only one thing can read/write
 	 * the MDIO bus at a time
 	 */
-	struct mutex mdio_lock;
+	union {
+		struct mutex m;
+		spinlock_t s;
+	} lock;
 
 	struct device *parent;
 	enum {
@@ -127,6 +136,8 @@ struct mii_bus {
 };
 #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
 
+void mdiobus_lock(struct mii_bus *bus);
+void mdiobus_unlock(struct mii_bus *bus);
 struct mii_bus *mdiobus_alloc(void);
 int mdiobus_register(struct mii_bus *bus);
 void mdiobus_unregister(struct mii_bus *bus);
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH 3/3] pm_qos: get rid of the allocation in pm_qos_add_request()
From: Takashi Iwai @ 2010-07-05  6:41 UTC (permalink / raw)
  To: James Bottomley; +Cc: Linux PM, markgross, netdev
In-Reply-To: <1277747088.10879.201.camel@mulgrave.site>

Hi,

sorry for the late reply, as I've been on vacation in the last week
(and shut off mails intentionally :)

At Mon, 28 Jun 2010 12:44:48 -0500,
James Bottomley wrote:
> 
> Since every caller has to squirrel away the returned pointer anyway,
> they might as well supply the memory area.  This fixes a bug in a few of
> the call sites where the returned pointer was dereferenced without
> checking it for NULL (which gets returned if the kzalloc failed).
> 
> I'd like to hear how sound and netdev feels about this: it will add
> about two more pointers worth of data to struct netdev and struct
> snd_pcm_substream .. but I think it's worth it.  If you're OK, I'll add
> your acks and send through the pm tree.
> 
> This also looks to me like an android independent clean up (even though
> it renders the request_add atomically callable).  I also added include
> guards to include/linux/pm_qos_params.h

I like the patch very well, too.
But, just wondering...

> @@ -262,6 +260,11 @@ void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
>  	if (!pm_qos_req) /*guard against callers passing in null */
>  		return;
>  
> +	if (pm_qos_request_active(pm_qos_req)) {
> +		WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n");
> +		return;
> +	}
> +

Is this correct...?  Shouldn't it be a negative check?


thanks,

Takashi

^ permalink raw reply

* Re: IGB driver upgrade
From: sbs @ 2010-07-05  6:45 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: netdev@vger.kernel.org, e1000-devel@lists.sourceforge.net
In-Reply-To: <4C2A1C3C.3040403@intel.com>

I have tested 2.0.6 and 2.1.9 modules for 4 days and there were no any
issues detected :)


On Tue, Jun 29, 2010 at 8:15 PM, Alexander Duyck
<alexander.h.duyck@intel.com> wrote:
> sbs wrote:
>>
>> We're running 2.6.33.2 kernel version.
>> I have compiled and installed 2.0.6 and 2.1.9 modules on two our servers.
>>
>> Strange freezes usually appears in several (1 or 2) days.
>> So I'll let you know when it happen and what module version will be
>> responsible for that
>
> Since the issue is being seen with the in-kernel driver and not the
> standalone module one other possibility is that this could be an issue that
> is specific to multi-queue.  You can test for this by setting the RSS
> parameter to 0 for the standalone module to enable multiple queues on the
> 2.2.9 driver.

Thank you, I'll install 2.6.35-rc4 today on several servers with both
standalone(with RSS=0) and static driver and let you know after.

>
> One other thing you might want to try would be to test the latest release
> candidate kernel from kernel.org.  This would help to tell us if this is
> still an issue in the current kernel, or an issue that is present in just
> 2.6.33.
>
> Thanks,
>
> Alex
>

^ permalink raw reply

* Re: [PATCH net-next-2.6] ipv6: adding ip_nonlocal_bind option from ipv4
From: Michal Humpula @ 2010-07-05  6:56 UTC (permalink / raw)
  To: Simon Horman; +Cc: netdev
In-Reply-To: <20100705020333.GA14260@verge.net.au>

On Monday 05 of July 2010 04:03:36 Simon Horman wrote:
> On Sat, Jul 03, 2010 at 10:38:28PM +0200, Michal Humpula wrote:
> > Adds ability to bind non-local IPv6 address the same way as for IPv4
> > 
> > Signed-off-by: Michal Humpula <michal.humpula@web4u.cz>
> > 
> > diff --git a/Documentation/networking/ip-sysctl.txt
> > b/Documentation/networking/ip-sysctl.txt index f350c69..27fa09a 100644
> > --- a/Documentation/networking/ip-sysctl.txt
> > +++ b/Documentation/networking/ip-sysctl.txt
> > @@ -962,6 +962,10 @@ bindv6only - BOOLEAN
> > 
> >  		FALSE: enable IPv4-mapped address feature
> >  	
> >  	Default: FALSE (as specified in RFC2553bis)
> 
> I think a blank line here would be nice.
> 
> > +ipv6_nonlocal_bind - BOOLEAN
> > +	If set, allows processes to bind() to non-local IPv6 addresses,
> > +	which can be quite useful - but may break some applications.
> > +	Default: 0
> > 
> >  IPv6 Fragmentation:
> > 
> > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > index e830cd4..55b3552 100644
> > --- a/net/ipv6/af_inet6.c
> > +++ b/net/ipv6/af_inet6.c
> > 
> > @@ -345,8 +347,10 @@ int inet6_bind(struct socket *sock, struct sockaddr
> > *uaddr, int addr_len)
> > 
> >  			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
> >  			
> >  				if (!ipv6_chk_addr(net, &addr->sin6_addr,
> >  				
> >  						   dev, 0)) {
> > 
> > -					err = -EADDRNOTAVAIL;
> > -					goto out_unlock;
> > +					if (!sysctl_ipv6_nonlocal_bind) {
> > +						err = -EADDRNOTAVAIL;
> > +						goto out_unlock;
> > +					}
> > 
> >  				}
> >  			
> >  			}
> >  			rcu_read_unlock();
> 
> Perhaps the inner two if statements could be combined to remove
> unnecessary nesting? And perhaps check for sysctl_ipv6_nonlocal_bind first,
> as presumably its a cheaper, though less likely to succeed check.
> 
> 			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
> 				if (!sysctl_ipv6_nonlocal_bind &&
> 				    !ipv6_chk_addr(net, &addr->sin6_addr,
> 						   dev, 0)) {
> 					err = -EADDRNOTAVAIL;
> 					goto out_unlock;
> 				}
> 			}
> 
> Actually, I wonder if all three if statements could be combined.
> 
> 			if (!(addr_type & IPV6_ADDR_MULTICAST) &&
> 		            !sysctl_ipv6_nonlocal_bind &&
> 			    !ipv6_chk_addr(net, &addr->sin6_addr, dev, 0)) {
> 				err = -EADDRNOTAVAIL;
> 				goto out_unlock;
> 			}
> 

Thanks you for review, I agree with the objections. I'll send a corrected version.

^ permalink raw reply

* [PATCH v2] ipt_REJECT: can't work with bridges
From: Changli Gao @ 2010-07-05  7:16 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: David S. Miller, Alexey Kuznetsov, Pekka Savola (ipv6),
	James Morris, Hideaki YOSHIFUJI, netfilter-devel, netdev,
	Changli Gao

ipt_REJECT: can't work with bridges

ip_route_me_harder can't create the route cache when the outdev is the same with
the indev for the skbs whichout a valid protocol set.

__mkroute_input functions has this check:
1998         if (skb->protocol != htons(ETH_P_IP)) {
1999                 /* Not IP (i.e. ARP). Do not create route, if it is
2000                  * invalid for proxy arp. DNAT routes are always valid.
2001                  *
2002                  * Proxy arp feature have been extended to allow, ARP
2003                  * replies back to the same interface, to support
2004                  * Private VLAN switch technologies. See arp.c.
2005                  */
2006                 if (out_dev == in_dev &&
2007                     IN_DEV_PROXY_ARP_PVLAN(in_dev) == 0) {
2008                         err = -EINVAL;
2009                         goto cleanup;
2010                 }
2011         }

This patch gives the new skb a valid protocol to bypass this check. In order to
make ipt_REJECT work with bridges, you also need to enable ip_forward.

This patch also fixes a regression. When we used skb_copy_expand(), we didn't
have this issue stated above, as the protocol was properly set. In fact, the
regression also affects TC classification and packet sockets.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
 net/ipv4/netfilter/ipt_REJECT.c |    1 +
 1 file changed, 1 insertion(+)
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index bbbd273..60b8832 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -111,6 +111,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 	/* ip_route_me_harder expects skb->dst to be set */
 	skb_dst_set_noref(nskb, skb_dst(oldskb));
 
+	nskb->protocol = htons(ETH_P_IP);
 	if (ip_route_me_harder(nskb, addr_type))
 		goto free_nskb;
 

^ permalink raw reply related

* Re: [REGRESSION] e1000e stopped working [MANUALLY BISECTED]
From: Jeff Kirsher @ 2010-07-05  8:13 UTC (permalink / raw)
  To: Maxim Levitsky
  Cc: Tantilov, Emil S, netdev@vger.kernel.org, Allan, Bruce W,
	Pieper, Jeffrey E
In-Reply-To: <1278283714.3444.1.camel@localhost.localdomain>

On Sun, Jul 4, 2010 at 15:48, Maxim Levitsky <maximlevitsky@gmail.com> wrote:
> Did few guesses, and now I see that reverting the below commit fixes the
> problem.
>
> "e1000e: Fix/cleanup PHY reset code for ICHx/PCHx"
> e98cac447cc1cc418dff1d610a5c79c4f2bdec7f.
>
>
> Best regards,
>        Maxim Levitsky
>
> --

Can you give us till Tuesday to respond?  I know that there are some
additional e1000e patches in my queue, which may resolve the issue,
but this weekend the power is down to do some infrastructure upgrades
which prevents us from doing any investigation.debugging until
Tuesday.

-- 
Cheers,
Jeff

^ permalink raw reply

* Re: [PATCH] nf_conntrack_reasm: add fast path for in-order fragments
From: Patrick McHardy @ 2010-07-05  8:37 UTC (permalink / raw)
  To: Changli Gao
  Cc: David S. Miller, Alexey Kuznetsov, Pekka Savola (ipv6),
	James Morris, Hideaki YOSHIFUJI, Eric Dumazet, netfilter-devel,
	netdev, Mitchell Erblich
In-Reply-To: <1277956710-22313-1-git-send-email-xiaosuo@gmail.com>

Changli Gao wrote:
> nf_conntrack_reasm: add fast path for in-order fragments
>
> As the fragments are sent in order in most of OSes, such as Windows, Darwin and
> FreeBSD, it is likely the new fragments are at the end of the inet_frag_queue.
> In the fast path, we check if the skb at the end of the inet_frag_queue is the
> prev we expect.

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] netfilter: postpone the checksum calculation
From: Patrick McHardy @ 2010-07-05  8:39 UTC (permalink / raw)
  To: Changli Gao; +Cc: David S. Miller, netfilter-devel, netdev
In-Reply-To: <1278050577-3358-1-git-send-email-xiaosuo@gmail.com>

Changli Gao wrote:
> netfilter: postpone the checksum calculation.
>
> postpone the checksum calculation, then if the output NIC supports checksum
> offloading, we can utlize it. And though the output NIC doesn't support
> checksum offloading, but we'll mangle this packet, this can free us from
> updating the checksum, as the checksum calculation occurs later.

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] ipvs: Kconfig cleanup
From: Patrick McHardy @ 2010-07-05  8:43 UTC (permalink / raw)
  To: Simon Horman
  Cc: Michal Marek, lvs-devel, netdev, Julian Anastasov, Wensong Zhang,
	linux-kernel
In-Reply-To: <20100704071347.GB9437@verge.net.au>

Simon Horman wrote:
> [ Added Patrick McHardy to CC ]
>
> On Sun, Jul 04, 2010 at 04:05:16PM +0900, Simon Horman wrote:
>   
>> On Fri, Jul 02, 2010 at 10:32:08PM +0200, Michal Marek wrote:
>>     
>>> IP_VS_PROTO_AH_ESP should be set iff either of IP_VS_PROTO_{AH,ESP} is
>>> selected. Express this with standard kconfig syntax.
>>>
>>> Signed-off-by: Michal Marek <mmarek@suse.cz>
>>>       
>> Acked-by: Simon Horman <horms@verge.net.au>

Applied, thanks.

^ permalink raw reply

* [PATCH v2 0/9]  atm:  propagate atm_dev signal carrier to LOWER_UP of netdevice
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto

Changes from v1:
Use atm_dev notifier chain  instead of callback function pointer in struct vcc.
In drivers/usb/atm call atm_dev_signal_change().

In userspace it's helpfull to know if a network device has a carrier signal. 
Often it is monitored via netlink.  This patchset allows a way for the 
struct atm_dev drivers to pass carrier on/off to the netdevice.

For DSL, carrier is on when the line has reached showtime state.

Currently this patchset only propagates the changes to br2684 vccs,
as this is the only type of hardware I have to test.

If you prefer git you can pull from:
git://github.com/karlhiramoto/linux-2.6.git atm-v2



Karl Hiramoto (9):
  atm: propagate signal changes via notifier
  atm/br2684: register notifier event for carrier signal changes.
  atm/adummy: add syfs DEVICE_ATTR to change signal
  atm/idt77105.c: call atm_dev_signal_change() when signal changes.
  atm/solos-pci: call atm_dev_signal_change() when signal changes.
  atm/suni.c: call atm_dev_signal_change() when signal changes.
  usb/atm/cxacru.c: call atm_dev_signal_change() when signal changes.
  usb/atm/speedtch.c: call atm_dev_signal_change() when signal changes.
  usb/atm/ueagle-atm.c: call atm_dev_signal_change() when signal
    changes.

 drivers/atm/adummy.c         |   39 ++++++++++++++++++++++++
 drivers/atm/idt77105.c       |   11 ++++---
 drivers/atm/solos-pci.c      |    6 ++--
 drivers/atm/suni.c           |    5 ++-
 drivers/usb/atm/cxacru.c     |   18 ++++++------
 drivers/usb/atm/speedtch.c   |   10 +++---
 drivers/usb/atm/ueagle-atm.c |   13 ++++++--
 include/linux/atmdev.h       |   12 +++++++
 net/atm/br2684.c             |   66 ++++++++++++++++++++++++++++++++++++++++-
 net/atm/common.c             |   31 +++++++++++++++++++
 10 files changed, 182 insertions(+), 29 deletions(-)


^ permalink raw reply

* [PATCH v2 1/9] atm: propagate signal changes via notifier
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

Add notifier chain for changes in atm_dev.

Clients like br2684 will call register_atmdevice_notifier() to be notified of
changes. Drivers will call atm_dev_signal_change() to notify clients like
br2684 of the change.

On DSL and ATM devices it's usefull to have a know if you have a carrier
signal. netdevice LOWER_UP changes can be propagated to userspace via netlink
monitor.

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 include/linux/atmdev.h |   12 ++++++++++++
 net/atm/common.c       |   31 +++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 817b237..30890bc 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -431,6 +431,10 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
     int number,unsigned long *flags); /* number == -1: pick first available */
 struct atm_dev *atm_dev_lookup(int number);
 void atm_dev_deregister(struct atm_dev *dev);
+/**
+* Propagate lower layer signal change in atm_dev->signal to netdevice.
+*/
+void atm_dev_signal_change(struct atm_dev *dev, char signal);
 void vcc_insert_socket(struct sock *sk);
 
 
@@ -510,6 +514,14 @@ void register_atm_ioctl(struct atm_ioctl *);
  */
 void deregister_atm_ioctl(struct atm_ioctl *);
 
+
+/**
+* register_atmdevice_notifier - register atm_dev notify events
+* Currently we notify of signal found/lost
+*/
+int register_atmdevice_notifier(struct notifier_block *nb);
+void unregister_atmdevice_notifier(struct notifier_block *nb);
+
 #endif /* __KERNEL__ */
 
 #endif
diff --git a/net/atm/common.c b/net/atm/common.c
index b43feb1..cfa342e 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -37,6 +37,8 @@ EXPORT_SYMBOL(vcc_hash);
 DEFINE_RWLOCK(vcc_sklist_lock);
 EXPORT_SYMBOL(vcc_sklist_lock);
 
+static BLOCKING_NOTIFIER_HEAD(atm_dev_notify_chain);
+
 static void __vcc_insert_socket(struct sock *sk)
 {
 	struct atm_vcc *vcc = atm_sk(sk);
@@ -212,6 +214,23 @@ void vcc_release_async(struct atm_vcc *vcc, int reply)
 }
 EXPORT_SYMBOL(vcc_release_async);
 
+void atm_dev_signal_change(struct atm_dev *dev, char signal)
+{
+	int i;
+	pr_debug("%s signal=%d dev=%p number=%d dev->signal=%d\n",
+		__func__, signal, dev, dev->number, dev->signal);
+
+	/* atm driver sending invalid signal */
+	WARN_ON(signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND);
+
+	if (dev->signal == signal)
+		return; /* no change */
+
+	dev->signal = signal;
+
+	blocking_notifier_call_chain(&atm_dev_notify_chain, signal, dev);
+}
+EXPORT_SYMBOL(atm_dev_signal_change);
 
 void atm_dev_release_vccs(struct atm_dev *dev)
 {
@@ -781,6 +800,18 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,
 	return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
 }
 
+int register_atmdevice_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&atm_dev_notify_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_atmdevice_notifier);
+
+void unregister_atmdevice_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&atm_dev_notify_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_atmdevice_notifier);
+
 static int __init atm_init(void)
 {
 	int error;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 3/9] atm/adummy: add syfs DEVICE_ATTR to change signal
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 drivers/atm/adummy.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c
index 6d44f07..46b9476 100644
--- a/drivers/atm/adummy.c
+++ b/drivers/atm/adummy.c
@@ -40,6 +40,42 @@ struct adummy_dev {
 
 static LIST_HEAD(adummy_devs);
 
+static ssize_t __set_signal(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
+	int signal;
+
+	if (sscanf(buf, "%d", &signal) == 1) {
+
+		if (signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND)
+			signal = ATM_PHY_SIG_UNKNOWN;
+
+		atm_dev_signal_change(atm_dev, signal);
+		return 1;
+	}
+	return -EINVAL;
+}
+
+static ssize_t __show_signal(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
+	return sprintf(buf, "%d\n", atm_dev->signal);
+}
+static DEVICE_ATTR(signal, 0644, __show_signal, __set_signal);
+
+static struct attribute *adummy_attrs[] = {
+	&dev_attr_signal.attr,
+	NULL
+};
+
+static struct attribute_group adummy_group_attrs = {
+	.name = NULL, /* We want them in dev's root folder */
+	.attrs = adummy_attrs
+};
+
 static int __init
 adummy_start(struct atm_dev *dev)
 {
@@ -128,6 +164,9 @@ static int __init adummy_init(void)
 	adummy_dev->atm_dev = atm_dev;
 	atm_dev->dev_data = adummy_dev;
 
+	if (sysfs_create_group(&atm_dev->class_dev.kobj, &adummy_group_attrs))
+		dev_err(&atm_dev->class_dev, "Could not register attrs for adummy\n");
+
 	if (adummy_start(atm_dev)) {
 		printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n");
 		err = -ENODEV;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 2/9] atm/br2684: register notifier event for carrier signal changes.
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

When a signal change event occurs call netif_carrier_on/off.

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 net/atm/br2684.c |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 6719af6..5afa512 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -139,6 +139,42 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
 	return NULL;
 }
 
+static int atm_dev_event(struct notifier_block *this, unsigned long event,
+		 void *arg)
+{
+	struct atm_dev *atm_dev = arg;
+	struct list_head *lh;
+	struct net_device *net_dev;
+	struct br2684_vcc *brvcc;
+	struct atm_vcc *atm_vcc;
+
+	pr_debug("event=%ld dev=%p\n", event, atm_dev);
+
+	read_lock(&devs_lock);
+	list_for_each(lh, &br2684_devs) {
+		net_dev = list_entry_brdev(lh);
+
+		list_for_each_entry(brvcc, &BRPRIV(net_dev)->brvccs, brvccs) {
+			atm_vcc = brvcc->atmvcc;
+			if (atm_vcc && brvcc->atmvcc->dev == atm_dev) {
+
+				if (atm_vcc->dev->signal == ATM_PHY_SIG_LOST)
+					netif_carrier_off(net_dev);
+				else
+					netif_carrier_on(net_dev);
+
+			}
+		}
+	}
+	read_unlock(&devs_lock);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block atm_dev_notifier = {
+	.notifier_call = atm_dev_event,
+};
+
 /* chained vcc->pop function.  Check if we should wake the netif_queue */
 static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
@@ -362,6 +398,12 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
 			unregister_netdev(net_dev);
 			free_netdev(net_dev);
 		}
+		read_lock_irq(&devs_lock);
+		if (list_empty(&br2684_devs)) {
+			/* last br2684 device */
+			unregister_atmdevice_notifier(&atm_dev_notifier);
+		}
+		read_unlock_irq(&devs_lock);
 		return;
 	}
 
@@ -530,6 +572,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 
 		br2684_push(atmvcc, skb);
 	}
+
+	/* initialize netdev carrier state */
+	if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
+		netif_carrier_off(net_dev);
+	else
+		netif_carrier_on(net_dev);
+
 	__module_get(THIS_MODULE);
 	return 0;
 
@@ -620,9 +669,16 @@ static int br2684_create(void __user *arg)
 	}
 
 	write_lock_irq(&devs_lock);
+
 	brdev->payload = payload;
-	brdev->number = list_empty(&br2684_devs) ? 1 :
-	    BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
+
+	if (list_empty(&br2684_devs)) {
+		/* 1st br2684 device */
+		register_atmdevice_notifier(&atm_dev_notifier);
+		brdev->number = 1;
+	} else
+		brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
+
 	list_add_tail(&brdev->br2684_devs, &br2684_devs);
 	write_unlock_irq(&devs_lock);
 	return 0;
@@ -758,6 +814,7 @@ static int __init br2684_init(void)
 		return -ENOMEM;
 #endif
 	register_atm_ioctl(&br2684_ioctl_ops);
+
 	return 0;
 }
 
@@ -772,6 +829,11 @@ static void __exit br2684_exit(void)
 	remove_proc_entry("br2684", atm_proc_root);
 #endif
 
+
+	/* if not already empty */
+	if (!list_empty(&br2684_devs))
+		unregister_atmdevice_notifier(&atm_dev_notifier);
+
 	while (!list_empty(&br2684_devs)) {
 		net_dev = list_entry_brdev(br2684_devs.next);
 		brdev = BRPRIV(net_dev);
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 4/9] atm/idt77105.c: call atm_dev_signal_change() when signal changes.
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

Propagate changes to upper atm layer.

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 drivers/atm/idt77105.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index dab5cf5..bca9cb8 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -126,7 +126,7 @@ static void idt77105_restart_timer_func(unsigned long dummy)
                 istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
                 if (istat & IDT77105_ISTAT_GOODSIG) {
                     /* Found signal again */
-                    dev->signal = ATM_PHY_SIG_FOUND;
+                    atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
 	            printk(KERN_NOTICE "%s(itf %d): signal detected again\n",
                         dev->type,dev->number);
                     /* flush the receive FIFO */
@@ -222,7 +222,7 @@ static void idt77105_int(struct atm_dev *dev)
             /* Rx Signal Condition Change - line went up or down */
             if (istat & IDT77105_ISTAT_GOODSIG) {   /* signal detected again */
                 /* This should not happen (restart timer does it) but JIC */
-                dev->signal = ATM_PHY_SIG_FOUND;
+		atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
             } else {    /* signal lost */
                 /*
                  * Disable interrupts and stop all transmission and
@@ -235,7 +235,7 @@ static void idt77105_int(struct atm_dev *dev)
                     IDT77105_MCR_DRIC|
                     IDT77105_MCR_HALTTX
                     ) & ~IDT77105_MCR_EIP, MCR);
-                dev->signal = ATM_PHY_SIG_LOST;
+		atm_dev_signal_change(dev, ATM_PHY_SIG_LOST);
 	        printk(KERN_NOTICE "%s(itf %d): signal lost\n",
                     dev->type,dev->number);
             }
@@ -272,8 +272,9 @@ static int idt77105_start(struct atm_dev *dev)
 	memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
         
         /* initialise dev->signal from Good Signal Bit */
-        dev->signal = GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? ATM_PHY_SIG_FOUND :
-	  ATM_PHY_SIG_LOST;
+	atm_dev_signal_change(dev,
+		GET(ISTAT) & IDT77105_ISTAT_GOODSIG ?
+		ATM_PHY_SIG_FOUND : ATM_PHY_SIG_LOST);
 	if (dev->signal == ATM_PHY_SIG_LOST)
 		printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
 		    dev->number);
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 6/9] atm/suni.c: call atm_dev_signal_change() when signal changes.
From: Karl Hiramoto @ 2010-07-05  8:45 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

Propagate changes to upper atm layer.

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 drivers/atm/suni.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index da4b91f..41c56ea 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -291,8 +291,9 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
 
 static void poll_los(struct atm_dev *dev)
 {
-	dev->signal = GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? ATM_PHY_SIG_LOST :
-	  ATM_PHY_SIG_FOUND;
+	atm_dev_signal_change(dev,
+		GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ?
+		ATM_PHY_SIG_LOST : ATM_PHY_SIG_FOUND);
 }
 
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 9/9] usb/atm/ueagle-atm.c: call atm_dev_signal_change() when signal changes.
From: Karl Hiramoto @ 2010-07-05  8:46 UTC (permalink / raw)
  To: linux-atm-general, netdev, chas; +Cc: nathan, Karl Hiramoto
In-Reply-To: <1278319561-23548-1-git-send-email-karl@hiramoto.org>

Propagate signal changes to upper atm layer.

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 drivers/usb/atm/ueagle-atm.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e213d3f..ebae944 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -575,6 +575,13 @@ MODULE_PARM_DESC(annex,
 			sc->usbatm->atm_dev->type = val; \
 	} while (0)
 
+#define UPDATE_ATM_SIGNAL(val) \
+	do { \
+		if (sc->usbatm->atm_dev) \
+			atm_dev_signal_change(sc->usbatm->atm_dev, val); \
+	} while (0)
+
+
 /* Firmware loading */
 #define LOAD_INTERNAL     0xA0
 #define F8051_USBCS       0x7f92
@@ -1359,7 +1366,7 @@ static int uea_stat_e1(struct uea_softc *sc)
 	/* always update it as atm layer could not be init when we switch to
 	 * operational state
 	 */
-	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);
+	UPDATE_ATM_SIGNAL(ATM_PHY_SIG_FOUND);
 
 	/* wake up processes waiting for synchronization */
 	wake_up(&sc->sync_q);
@@ -1498,7 +1505,7 @@ static int uea_stat_e4(struct uea_softc *sc)
 	/* always update it as atm layer could not be init when we switch to
 	 * operational state
 	 */
-	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);
+	UPDATE_ATM_SIGNAL(ATM_PHY_SIG_FOUND);
 
 	/* wake up processes waiting for synchronization */
 	wake_up(&sc->sync_q);
@@ -1825,7 +1832,7 @@ static int uea_start_reset(struct uea_softc *sc)
 	 * So we will failed to wait Ready CMV.
 	 */
 	sc->cmv_ack = 0;
-	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
+	UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST);
 
 	/* reset statistics */
 	memset(&sc->stats, 0, sizeof(struct uea_stats));
-- 
1.7.1


^ 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