Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 1/3] {IPv4,xfrm} Add Extended Sequence Number (ESN) support for AH egress part
From: Fan Du @ 2014-01-08  8:53 UTC (permalink / raw)
  To: steffen.klassert; +Cc: davem, netdev
In-Reply-To: <1389171192-28091-1-git-send-email-fan.du@windriver.com>

This patch add esn support for AH output stage by attaching upper 32bits
sequence number right after packet payload as specified by RFC 4302.

Then the ICV value will guard upper 32bits sequence number as well when
packet going out.

Signed-off-by: Fan Du <fan.du@windriver.com>
---
 net/ipv4/ah4.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 7179026..a7fac03 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -12,6 +12,7 @@
 #include <linux/scatterlist.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
+#include <crypto/scatterwalk.h>
 
 struct ah_skb_cb {
 	struct xfrm_skb_cb xfrm;
@@ -155,6 +156,10 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 	struct iphdr *iph, *top_iph;
 	struct ip_auth_hdr *ah;
 	struct ah_data *ahp;
+	int seqhi_len = 0;
+	__be32 *seqhi;
+	int sglists = 0;
+	struct scatterlist *seqhisg;
 
 	ahp = x->data;
 	ahash = ahp->ahash;
@@ -167,14 +172,19 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 	ah = ip_auth_hdr(skb);
 	ihl = ip_hdrlen(skb);
 
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists = 1;
+		seqhi_len = sizeof(*seqhi);
+	}
 	err = -ENOMEM;
-	iph = ah_alloc_tmp(ahash, nfrags, ihl);
+	iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + seqhi_len);
 	if (!iph)
 		goto out;
-
-	icv = ah_tmp_icv(ahash, iph, ihl);
+	seqhi = (__be32 *)((char *)iph + ihl);
+	icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
 	req = ah_tmp_req(ahash, icv);
 	sg = ah_req_sg(ahash, req);
+	seqhisg = sg + nfrags;
 
 	memset(ah->auth_data, 0, ahp->icv_trunc_len);
 
@@ -213,7 +223,14 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, 0, skb->len);
 
-	ahash_request_set_crypt(req, sg, icv, skb->len);
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_unmark_end(&sg[nfrags - 1]);
+		/* Attach seqhi sg right after packet payload */
+		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+		sg_init_table(seqhisg, sglists);
+		sg_set_buf(seqhisg, seqhi, seqhi_len);
+	}
+	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah_output_done, skb);
 
 	AH_SKB_CB(skb)->tmp = iph;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 2/3] {IPv4,xfrm} Add Extended Sequence Number (ESN) support for AH ingress part
From: Fan Du @ 2014-01-08  8:53 UTC (permalink / raw)
  To: steffen.klassert; +Cc: davem, netdev
In-Reply-To: <1389171192-28091-1-git-send-email-fan.du@windriver.com>

This patch add esn support for AH input stage by attaching upper 32bits
sequence number right after packet payload as specified by RFC 4302.

Then the ICV value will guard upper 32bits sequence number as well when
packet getting in.

Signed-off-by: Fan Du <fan.du@windriver.com>
---
 net/ipv4/ah4.c |   24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index a7fac03..169d9a5 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -312,6 +312,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 	struct ip_auth_hdr *ah;
 	struct ah_data *ahp;
 	int err = -ENOMEM;
+	int seqhi_len = 0;
+	__be32 *seqhi;
+	int sglists = 0;
+	struct scatterlist *seqhisg;
 
 	if (!pskb_may_pull(skb, sizeof(*ah)))
 		goto out;
@@ -352,14 +356,21 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 	iph = ip_hdr(skb);
 	ihl = ip_hdrlen(skb);
 
-	work_iph = ah_alloc_tmp(ahash, nfrags, ihl + ahp->icv_trunc_len);
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists = 1;
+		seqhi_len = sizeof(*seqhi);
+	}
+
+	work_iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + ahp->icv_trunc_len + seqhi_len);
 	if (!work_iph)
 		goto out;
 
-	auth_data = ah_tmp_auth(work_iph, ihl);
+	seqhi = (__be32 *)((char *)work_iph + ihl);
+	auth_data = ah_tmp_auth(seqhi, seqhi_len);
 	icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
 	req = ah_tmp_req(ahash, icv);
 	sg = ah_req_sg(ahash, req);
+	seqhisg = sg + nfrags;
 
 	memcpy(work_iph, iph, ihl);
 	memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -381,7 +392,14 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, 0, skb->len);
 
-	ahash_request_set_crypt(req, sg, icv, skb->len);
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_unmark_end(&sg[nfrags - 1]);
+		/* Attach seqhi sg right after packet payload */
+		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+		sg_init_table(seqhisg, sglists);
+		sg_set_buf(seqhisg, seqhi, seqhi_len);
+	}
+	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah_input_done, skb);
 
 	AH_SKB_CB(skb)->tmp = work_iph;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 0/3] {IPv4,xfrm} Add ESN support for AH
From: Fan Du @ 2014-01-08  8:53 UTC (permalink / raw)
  To: steffen.klassert; +Cc: davem, netdev

Hi,

This is initial Extended Sequence Number support for AH based on IPv4.
The rationale is totally by the RFC 4302, which states:

3.3.3.2.2.  Implicit Packet Padding and ESN

   If the ESN option is elected for an SA, then the high-order 32 bits
   of the ESN must be included in the ICV computation.  For purposes of
   ICV computation, these bits are appended (implicitly) immediately
   after the end of the payload, and before any implicit packet padding.

So we attach the high-order 32bits as a scatterlist right after the packet
payload to compute ICV value. 

Test:
I add a knob in iproute2/ip/xfrm_state.c to enable esn when setting SA,
which make it possible to test with-esn and without-esn scenarios, both
cases works ok with ping using packetsize(-s) from default to 32768.  

Fan Du (3):
  {IPv4,xfrm} Add Extended Sequence Number support for AH egress part
  {IPv4,xfrm} Add Extended Sequence Number support for AH ingress part
  xfrm: Don't prohibit AH from using ESN feature

 net/ipv4/ah4.c       |   49 ++++++++++++++++++++++++++++++++++++++++++-------
 net/xfrm/xfrm_user.c |    4 ----
 2 files changed, 42 insertions(+), 11 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* Re: [net-next 3/7] ixgbe: Use static inlines instead of macros
From: Scott Feldman @ 2014-01-08  8:47 UTC (permalink / raw)
  To: Aaron Brown; +Cc: David Miller, Mark Rustad, Netdev, gospo, sassmann
In-Reply-To: <1389166847-3780-4-git-send-email-aaron.f.brown@intel.com>


On Jan 7, 2014, at 11:40 PM, Aaron Brown <aaron.f.brown@intel.com> wrote:

> From: Mark Rustad <mark.d.rustad@intel.com>
> 
> -#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
> +static inline void IXGBE_WRITE_REG(struct ixgbe_hw *hw, u32 reg, u32 value)

Bummer, now you have a all-caps func name.

^ permalink raw reply

* Re: [PATCH] ipv6: don't call addrconf_dst_alloc again when enable lo
From: Gao feng @ 2014-01-08  8:42 UTC (permalink / raw)
  To: chenweilong, David Miller, kumaran.4353, netdev
In-Reply-To: <20140108080528.GD9007@order.stressinduktion.org>

On 01/08/2014 04:05 PM, Hannes Frederic Sowa wrote:
> On Wed, Jan 08, 2014 at 03:50:09PM +0800, Gao feng wrote:
>> On 01/03/2014 02:53 PM, Hannes Frederic Sowa wrote:
>>> On Thu, Jan 02, 2014 at 05:33:15PM +0800, chenweilong wrote:
>>>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>>>> index 62d1799..d2f8c0a 100644
>>>> --- a/net/ipv6/addrconf.c
>>>> +++ b/net/ipv6/addrconf.c
>>>> @@ -2422,8 +2422,9 @@ static void init_loopback(struct net_device *dev)
>>>>  			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
>>>>  				continue;
>>>>
>>>> -			if (sp_ifa->rt)
>>>> -				continue;
>>>> +			if (sp_ifa->rt && sp_ifa->rt->dst.dev == dev) {
>>>> +				ip6_del_rt(sp_ifa->rt);
>>>> +			}
>>>>
>>>>  			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
>>>>
>>>
>>> Maybe this change would not be that bad after all, as those ifa attached dsts
>>> are already dead and queued up for gc and should not get inserted back.
>>
>> I like this idea, maybe the below patch is better. we only need to delete this
>> route when it has been added to garbage list.
>>
>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>> index 1a341f7..4dca886 100644
>> --- a/net/ipv6/addrconf.c
>> +++ b/net/ipv6/addrconf.c
>> @@ -2610,8 +2610,16 @@ static void init_loopback(struct net_device *dev)
>>                         if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
>>                                 continue;
>>
>> -                       if (sp_ifa->rt)
>> -                               continue;
>> +                       if (sp_ifa->rt) {
>> +                               /* This dst has been added to garbage list when
>> +                                * lo device down, delete this obsolete dst and
>> +                                * reallocate new router for ifa. */
>> +                               if (sp_ifa->rt->dst.obsolete > 0) {
>> +                                       ip6_del_rt(sp_ifa->rt);
>> +                                       sp_ifa->rt = NULL;
>> +                               } else
>> +                                       continue;
>> +                       }
>>
>>                         sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
> 
> It looks like it can work but I don't know if we should just fix this the
> clean way (see below).
> 
>>> I'll try to just disable routes without removing them at all when we set an
>>> interface to down at the weekend.
>>>
>>
>> How do you decide which route should be disabled?  use rt6_flags? I don't know
>> if your way will cause miscarriage.
> 
> What I did so far is that I added a new function next to rt6_ifdown that
> only gets called if interface gets shutdown but not unregistered (from
> addrconf_ifdown).
> 

rt6_ifdown has alreay put this device related routes to the garbage list.

> fib6_clean_all then iterates over the whole routing table with a new predicate
> function which checks in the same way like fib6_ifdown, if it is a matching route
> (the interfaces match up) and if so, toggles a new "DEAD" flag in rt6i_flags.
> 
> When bringing up the interface I distinguish between up and register and just
> clear this death flag from the routes on bringing it up.
> 
> fib lookup code then does not honour those routes.
> 
> I had no time to test this thoroughly at the weekend and still have some code
> paths were I am unsure. Do you see any problems with this so far? We could
> then delete the special cases on loopback interface init.

So you add a special case in the general network interface down logic. I think this
is more complex...

Thanks!

^ permalink raw reply

* Re: [net-next 2/7] ixgbe: Indicate removal state explicitly
From: Scott Feldman @ 2014-01-08  8:37 UTC (permalink / raw)
  To: Aaron Brown; +Cc: David Miller, Mark Rustad, Netdev, gospo, sassmann
In-Reply-To: <1389166847-3780-3-git-send-email-aaron.f.brown@intel.com>


On Jan 7, 2014, at 11:40 PM, Aaron Brown <aaron.f.brown@intel.com> wrote:

> From: Mark Rustad <mark.d.rustad@intel.com>
> 
> Add a bit, __IXGBE_REMOVE, to indicate that the module is being
> removed. The __IXGBE_DOWN bit had been overloaded for this purpose,
> but that leads to trouble. A few places now check both __IXGBE_DOWN
> and __IXGBE_REMOVE. Notably, setting either bit will prevent service
> task execution.
> 
> Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
> Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
> ---
> drivers/net/ethernet/intel/ixgbe/ixgbe.h      |  1 +
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 12 ++++++++----
> 2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> index 49531cd..8da263a 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> @@ -798,6 +798,7 @@ enum ixgbe_state_t {
> 	__IXGBE_TESTING,
> 	__IXGBE_RESETTING,
> 	__IXGBE_DOWN,
> +	__IXGBE_REMOVE,

__IXGBE_REMOVING?  More consistent with _TESTING, _RESETTING, etc.

^ permalink raw reply

* Re: [PATCH net 1/2] bonding: ensure that the TSO being set on bond master
From: Veaceslav Falico @ 2014-01-08  8:33 UTC (permalink / raw)
  To: Ding Tianhong; +Cc: Jay Vosburgh, Eric Dumazet, David S. Miller, Netdev
In-Reply-To: <52CCFE18.7040606@huawei.com>

On Wed, Jan 08, 2014 at 03:28:24PM +0800, Ding Tianhong wrote:
>The commit b0ce3508(bonding: allow TSO being set on bonding master)
>has make the TSO being set for bond dev, but in some situation, if
>the slave did not have the NETIF_F_SG features, the bond master will
>miss the TSO features in netdev_fix_features because the TSO is
>depended on SG. So I have to add SG and TSO features on bond master
>together.

Do you know why TSO depends on SG? And what will happen if bonding supports
SG, but one of its slaves doesn't?

>
>The netdev_add_tso_features() was only used for bonding, so I think no
>need to export it to netdevice.h.
>
>Cc: Eric Dumazet <edumazet@google.com>
>Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>---
> drivers/net/bonding/bond_main.c | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index e06c445..8ce67ed 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c
>@@ -1045,6 +1045,20 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
>
> /*---------------------------------- IOCTL ----------------------------------*/
>
>+/* Allow TSO being used on stacked device:
>+ * Performing the GSO segmentation before last device
>+ * is a performance improvement.
>+ * The TSO is depended on SG, so add SG and TSO together,
>+ * otherwise the netdev_fix_features() may clean the TSO.
>+ */
>+static netdev_features_t bond_add_tso_features(netdev_features_t features,
>+					       netdev_features_t mask)
>+{
>+	return netdev_increment_features(features,
>+					 NETIF_F_ALL_TSO | NETIF_F_SG,
>+					 mask);
>+}
>+
> static netdev_features_t bond_fix_features(struct net_device *dev,
> 					   netdev_features_t features)
> {
>@@ -1068,7 +1082,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
> 						     slave->dev->features,
> 						     mask);
> 	}
>-	features = netdev_add_tso_features(features, mask);
>+	features = bond_add_tso_features(features, mask);
>
> 	return features;
> }
>-- 
>1.8.0
>
>
>

^ permalink raw reply

* Re: [net-next 5/7] ixgbe: Check register reads for adapter removal
From: Scott Feldman @ 2014-01-08  8:35 UTC (permalink / raw)
  To: Aaron Brown; +Cc: David Miller, Mark Rustad, Netdev, gospo, sassmann
In-Reply-To: <1389166847-3780-6-git-send-email-aaron.f.brown@intel.com>

On Jan 7, 2014, at 11:40 PM, Aaron Brown <aaron.f.brown@intel.com> wrote:

> From: Mark Rustad <mark.d.rustad@intel.com>
> 
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
> index 5e157ac..480c5c1 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
> @@ -124,6 +124,11 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
> s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
> s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
> 
> +#define IXGBE_FAILED_READ_REG 0xffffffffU
> +
> +void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg);
> +#define IXGBE_REMOVED(a) unlikely(!(a))

IXGBE_REMOVED seems pretty closely tied to hw->hw_addr, but the macro turns any input into !input.  Maybe an inline that takes a *hw?

> +
> static inline void IXGBE_WRITE_REG(struct ixgbe_hw *hw, u32 reg, u32 value)
> {
> 	writel(value, hw->hw_addr + reg);
> @@ -144,7 +149,15 @@ static inline void IXGBE_WRITE_REG64(struct ixgbe_hw *hw, u32 reg, u64 value)
> 
> static inline u32 IXGBE_READ_REG(struct ixgbe_hw *hw, u32 reg)
> {
> -	return readl(hw->hw_addr + reg);
> +	u8 __iomem *reg_addr = ACCESS_ONCE(hw->hw_addr);
> +	u32 value;
> +
> +	if (IXGBE_REMOVED(reg_addr))
> +		return IXGBE_FAILED_READ_REG;
> +	value = readl(reg_addr + reg);
> +	if (unlikely(value == IXGBE_FAILED_READ_REG))
> +		ixgbe_check_remove(hw, reg);
> +	return value;
> }
> 
> #define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) \
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 4d71277..896a8b0 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -283,6 +283,35 @@ static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
> 		schedule_work(&adapter->service_task);
> }
> 
> +static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
> +{
> +	struct ixgbe_adapter *adapter = hw->back;
> +
> +	if (!hw->hw_addr)
> +		return;
> +	hw->hw_addr = NULL;
> +	e_dev_err("Adapter removed\n");
> +}
> +
> +void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
> +{
> +	u32 value;
> +
> +	/* The following check not only optimizes a bit by not
> +	 * performing a read on the status register when the
> +	 * register just read was a status register read that
> +	 * returned IXGBE_FAILED_READ_REG. It also blocks any
> +	 * potential recursion.
> +	 */
> +	if (reg == IXGBE_STATUS) {
> +		ixgbe_remove_adapter(hw);
> +		return;
> +	}
> +	value = IXGBE_READ_REG(hw, IXGBE_STATUS);
> +	if (value == IXGBE_FAILED_READ_REG)
> +		ixgbe_remove_adapter(hw);
> +}
> +
> static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter)
> {
> 	BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state));
> @@ -2970,7 +2999,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
> 			ring->count * sizeof(union ixgbe_adv_tx_desc));
> 	IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0);
> 	IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
> -	ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx);
> +	ring->tail = adapter->io_addr + IXGBE_TDT(reg_idx);

How is this related to the commit msg about register reads?  Seems like two patches.

> 
> 	/*
> 	 * set WTHRESH to encourage burst writeback, it should not be set
> @@ -3373,7 +3402,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
> 			ring->count * sizeof(union ixgbe_adv_rx_desc));
> 	IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0);
> 	IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0);
> -	ring->tail = hw->hw_addr + IXGBE_RDT(reg_idx);
> +	ring->tail = adapter->io_addr + IXGBE_RDT(reg_idx);
> 
> 	ixgbe_configure_srrctl(adapter, ring);
> 	ixgbe_configure_rscctl(adapter, ring);
> @@ -7887,6 +7916,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> 
> 	hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
> 			      pci_resource_len(pdev, 0));
> +	adapter->io_addr = hw->hw_addr;
> 	if (!hw->hw_addr) {
> 		err = -EIO;
> 		goto err_ioremap;
> @@ -8195,7 +8225,7 @@ err_register:
> err_sw_init:
> 	ixgbe_disable_sriov(adapter);
> 	adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
> -	iounmap(hw->hw_addr);
> +	iounmap(adapter->io_addr);
> err_ioremap:
> 	free_netdev(netdev);
> err_alloc_etherdev:
> @@ -8262,7 +8292,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
> 	kfree(adapter->ixgbe_ieee_ets);
> 
> #endif
> -	iounmap(adapter->hw.hw_addr);
> +	iounmap(adapter->io_addr);
> 	pci_release_selected_regions(pdev, pci_select_bars(pdev,
> 				     IORESOURCE_MEM));
> 
> -- 
> 1.8.5.GIT
> 
> --
> 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

* Re: [PATCH net-next v5] IPv6: add the option to use anycast addresses as source addresses in echo reply
From: Hannes Frederic Sowa @ 2014-01-08  8:22 UTC (permalink / raw)
  To: François-Xavier Le Bail
  Cc: netdev, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki Yoshifuji, Patrick McHardy
In-Reply-To: <1389169066.26962.YahooMailBasic@web125506.mail.ne1.yahoo.com>

On Wed, Jan 08, 2014 at 12:17:46AM -0800, François-Xavier Le Bail wrote:
> On Tue, 1/7/14, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:
> 
> > On Tue, Jan 07, 2014 at 02:57:27PM +0100, Francois-Xavier Le Bail wrote:
> > > --- a/include/net/netns/ipv6.h
> > > +++ b/include/net/netns/ipv6.h
> > > @@ -73,6 +73,7 @@ struct netns_ipv6 {
> > >  #endif
> > >  	atomic_t		dev_addr_genid;
> > >  	atomic_t		rt_genid;
> > > +	int			anycast_src_echo_reply;
> > >  };
> 
> > Sorry, I missed that on first review and you could also do that as a
> > follow-up:
> 
> > Could you move anycast_src_echo_reply to netns_sysctl_ipv6?
> 
> I can do that, but please explain what this change is needed.

I think it is just a matter of style so that the ipv6 knobs are kept
together.

Greetings,

  Hannes

^ permalink raw reply

* Re: [PATCH net-next v5] IPv6: add the option to use anycast addresses as source addresses in echo reply
From: François-Xavier Le Bail @ 2014-01-08  8:17 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: netdev, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki Yoshifuji, Patrick McHardy
In-Reply-To: <20140107205101.GJ30393@order.stressinduktion.org>

On Tue, 1/7/14, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:

> On Tue, Jan 07, 2014 at 02:57:27PM +0100, Francois-Xavier Le Bail wrote:
> > --- a/include/net/netns/ipv6.h
> > +++ b/include/net/netns/ipv6.h
> > @@ -73,6 +73,7 @@ struct netns_ipv6 {
> >  #endif
> >  	atomic_t		dev_addr_genid;
> >  	atomic_t		rt_genid;
> > +	int			anycast_src_echo_reply;
> >  };

> Sorry, I missed that on first review and you could also do that as a
> follow-up:

> Could you move anycast_src_echo_reply to netns_sysctl_ipv6?

I can do that, but please explain what this change is needed.

BR
François-Xavier

^ permalink raw reply

* Re: [PATCH net-next v5] IPv6: add the option to use anycast addresses as source addresses in echo reply
From: François-Xavier Le Bail @ 2014-01-08  8:06 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: netdev, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki Yoshifuji, Patrick McHardy
In-Reply-To: <20140107191436.GE30393@order.stressinduktion.org>

On Tue, 1/7/14, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:

> On Tue, Jan 07, 2014 at 02:57:27PM +0100, Francois-Xavier Le Bail wrote:
> > This change allows to follow a recommandation of RFC4942.
> > 
> > - Add "anycast_src_echo_reply" sysctl to control the use of anycast addresses
> >   as source addresses for ICMPv6 echo reply. This sysctl is false by default
> >   to preserve existing behavior.
> > - Add inline check ipv6_anycast_destination().
> > - Use them in icmpv6_echo_reply().
 
> Works and best solution IMHO.

Yes. Thank you for testing.

BR
François-Xavier
 

^ permalink raw reply

* Re: [PATCH] ipv6: don't call addrconf_dst_alloc again when enable lo
From: Hannes Frederic Sowa @ 2014-01-08  8:05 UTC (permalink / raw)
  To: Gao feng; +Cc: chenweilong, David Miller, kumaran.4353, netdev
In-Reply-To: <52CD0331.8040204@cn.fujitsu.com>

On Wed, Jan 08, 2014 at 03:50:09PM +0800, Gao feng wrote:
> On 01/03/2014 02:53 PM, Hannes Frederic Sowa wrote:
> > On Thu, Jan 02, 2014 at 05:33:15PM +0800, chenweilong wrote:
> >> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> >> index 62d1799..d2f8c0a 100644
> >> --- a/net/ipv6/addrconf.c
> >> +++ b/net/ipv6/addrconf.c
> >> @@ -2422,8 +2422,9 @@ static void init_loopback(struct net_device *dev)
> >>  			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
> >>  				continue;
> >>
> >> -			if (sp_ifa->rt)
> >> -				continue;
> >> +			if (sp_ifa->rt && sp_ifa->rt->dst.dev == dev) {
> >> +				ip6_del_rt(sp_ifa->rt);
> >> +			}
> >>
> >>  			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
> >>
> > 
> > Maybe this change would not be that bad after all, as those ifa attached dsts
> > are already dead and queued up for gc and should not get inserted back.
> 
> I like this idea, maybe the below patch is better. we only need to delete this
> route when it has been added to garbage list.
> 
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 1a341f7..4dca886 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -2610,8 +2610,16 @@ static void init_loopback(struct net_device *dev)
>                         if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
>                                 continue;
> 
> -                       if (sp_ifa->rt)
> -                               continue;
> +                       if (sp_ifa->rt) {
> +                               /* This dst has been added to garbage list when
> +                                * lo device down, delete this obsolete dst and
> +                                * reallocate new router for ifa. */
> +                               if (sp_ifa->rt->dst.obsolete > 0) {
> +                                       ip6_del_rt(sp_ifa->rt);
> +                                       sp_ifa->rt = NULL;
> +                               } else
> +                                       continue;
> +                       }
> 
>                         sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);

It looks like it can work but I don't know if we should just fix this the
clean way (see below).

> > I'll try to just disable routes without removing them at all when we set an
> > interface to down at the weekend.
> > 
> 
> How do you decide which route should be disabled?  use rt6_flags? I don't know
> if your way will cause miscarriage.

What I did so far is that I added a new function next to rt6_ifdown that
only gets called if interface gets shutdown but not unregistered (from
addrconf_ifdown).

fib6_clean_all then iterates over the whole routing table with a new predicate
function which checks in the same way like fib6_ifdown, if it is a matching route
(the interfaces match up) and if so, toggles a new "DEAD" flag in rt6i_flags.

When bringing up the interface I distinguish between up and register and just
clear this death flag from the routes on bringing it up.

fib lookup code then does not honour those routes.

I had no time to test this thoroughly at the weekend and still have some code
paths were I am unsure. Do you see any problems with this so far? We could
then delete the special cases on loopback interface init.

Thanks,

  Hannes

^ permalink raw reply

* Re: [PATCH net-next V2 1/3] net: Add GRO support for UDP encapsulating protocols
From: Or Gerlitz @ 2014-01-08  8:04 UTC (permalink / raw)
  To: Eric Dumazet, Or Gerlitz
  Cc: Jerry Chu, Eric Dumazet, Herbert Xu, netdev@vger.kernel.org,
	David Miller, Yan Burman, Shlomo Pongratz
In-Reply-To: <1389130693.26646.72.camel@edumazet-glaptop2.roam.corp.google.com>

On 07/01/2014 23:38, Eric Dumazet wrote:
> On Tue, 2014-01-07 at 22:37 +0200, Or Gerlitz wrote:
>
>> So here's the thing, per my understanding we want to GRO only received
>> **encapsulated** packets whose checksum status is != CHECKSUM_NONE
>> which means the NIC has some support for doing RX checksum of
>> encapsulated packets. Per the current convension, in that case the NIC
>> RX code has to set skb->encapsulation see 6a674e9c75b17 "net: Add
>> support for hardware-offloaded encapsulation" this convension is
>> implemented in the current drivers that have HW offloads for
>> encapsulated packets (bnx2x, i40e and mlx4)
> I do not think its true.
>
> Some drivers set CHECKSUM_COMPLETE even for regular UDP frames...
>
> git grep -n CHECKSUM_COMPLETE -- drivers/net
>
>
>
Eric, the point I was trying to make is that as long as the driver set a 
value which is different from CHECKSUM_NONE
for an skb who carry encapsulated packet, we want skb->encapsulation to 
be set, per the architecture dictated by the above commit.

^ permalink raw reply

* Re: [PATCH net-next V2 1/3] net: Add GRO support for UDP encapsulating protocols
From: Or Gerlitz @ 2014-01-08  8:02 UTC (permalink / raw)
  To: Jerry Chu, Or Gerlitz
  Cc: Eric Dumazet, Eric Dumazet, Herbert Xu, netdev@vger.kernel.org,
	David Miller, Yan Burman, Shlomo Pongratz
In-Reply-To: <CAPshTCiFf=vpsw7D_pX5c=NTpg04+fi5u6M9byfQiszOU+qRzw@mail.gmail.com>

On 08/01/2014 00:11, Jerry Chu wrote:
> On Tue, Jan 7, 2014 at 12:37 PM, Or Gerlitz <or.gerlitz@gmail.com> wrote:
>> On Tue, Jan 7, 2014 at 10:32 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>>> On Tue, 2014-01-07 at 22:19 +0200, Or Gerlitz wrote:
>>>> On Tue, Jan 7, 2014 at 6:33 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>>>>> On Tue, 2014-01-07 at 17:29 +0200, Or Gerlitz wrote:
>>>>>> +
>>>>>> +#define MAX_UDP_PORT (1 << 16)
>>>>>> +extern const struct net_offload __rcu *udp_offloads[MAX_UDP_PORT];
>>>>> Thats 512 KB of memory.
>>>>> This will greatly impact forwarding performance of UDP packets with
>>>>> random ports, and will increase kernel memory size for embedded devices.
>>>> Re forwarding, are you referring to the case where the forwarded
>>>> packets are encapsulated? packets which are not encapusalted will be
>>>> flushed in the gro receive handler (this went out by mistake in V2 but
>>>> exists in V1)  if skb->encapsulation isn't set.
>>>>
>>> How do you know encapsulation must be tried for a given incoming
>>> packet ? NIC do not magically sets skb->encapsulation I think...
>> So here's the thing, per my understanding we want to GRO only received
>> **encapsulated** packets whose checksum status is != CHECKSUM_NONE
> What's wrong with GRO'ing pkts whose csum == CHECKSUM_NONE?

I am not sure, intuitively it sounds a bit wrong to me, empirically, it 
doesn't work for udp encapsulated  / vxlan
traffic, I got drops from the tcp stack in tcp_rcv_established() -- if  
GRO-ed packets carry CHECKSUM_NONE
we arrive to the csum_error label, which means that 
tcp_checksum_complete_user() failed for them


> Also "udp_offload" is a little misleading - you are not trying to GRO UDP
> pkts where UDP is the real transport. You are only trying to GRO UDP encapped TCP pkts.

Indeed -- however, I just plugged into what was there for GSO, e.g stack 
will not do GSO for plain UDP
packets, only for those who encapsulate something the code that does 
this is udp_offloads.c -- any suggestion
how to phrase/frame the change you envision?


>

^ permalink raw reply

* [PATCH v4 net-next 2/4] sh_eth: Add support for r7s72100
From: Simon Horman @ 2014-01-08  8:02 UTC (permalink / raw)
  To: David S. Miller, netdev, linux-sh
  Cc: linux-arm-kernel, Magnus Damm, Sergei Shtylyov, Simon Horman
In-Reply-To: <1389168152-9434-1-git-send-email-horms+renesas@verge.net.au>

This is a fast ethernet controller.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

---

Dave,

please consider this for net-next.

v4
* As requested by David Miller
  - Use a boolean for the return value of sh_eth_is_rz_fast_ether()
  - Correct coding style in sh_eth_get_stats()

v3
* No change

v2
* As suggested by Magnus Damm and Sergei Shtylyov
  - r7s72100 ethernet is not gigabit so do not refer to it as such

* As suggested by Magnus Damm
  - As RZ specific register layout rather than using the gigabit layout
    which includes registers that do not exist on this chip.

As suggested by Sergei Shtylyov
  - Do not use sh_eth_chip_reset_r8a7740 as it accesses non-existent
    RMII registers. Instead use sh_eth_chip_reset.
  - Do not use sh_eth_set_rate_gether as it accesses non-existent registers.
  - Do not use reserved LCHNG bit of ECSR
  - Do not use reserved LCHNGIP bit of ECSIPR
  - Document that R8A779x also needs a 16 bit shift of the RFS bits
  - Do not document that the R7S72100 has GECMR, it does not
---
 drivers/net/ethernet/renesas/sh_eth.c | 118 ++++++++++++++++++++++++++++++++--
 drivers/net/ethernet/renesas/sh_eth.h |   4 +-
 2 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 4b38533..cc6d4af 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -190,6 +190,59 @@ static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
 	[TRIMD]		= 0x027c,
 };
 
+static const u16 sh_eth_offset_fast_rz[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[EDSR]		= 0x0000,
+	[EDMR]		= 0x0400,
+	[EDTRR]		= 0x0408,
+	[EDRRR]		= 0x0410,
+	[EESR]		= 0x0428,
+	[EESIPR]	= 0x0430,
+	[TDLAR]		= 0x0010,
+	[TDFAR]		= 0x0014,
+	[TDFXR]		= 0x0018,
+	[TDFFR]		= 0x001c,
+	[RDLAR]		= 0x0030,
+	[RDFAR]		= 0x0034,
+	[RDFXR]		= 0x0038,
+	[RDFFR]		= 0x003c,
+	[TRSCER]	= 0x0438,
+	[RMFCR]		= 0x0440,
+	[TFTR]		= 0x0448,
+	[FDR]		= 0x0450,
+	[RMCR]		= 0x0458,
+	[RPADIR]	= 0x0460,
+	[FCFTR]		= 0x0468,
+	[CSMR]		= 0x04E4,
+
+	[ECMR]		= 0x0500,
+	[ECSR]		= 0x0510,
+	[ECSIPR]	= 0x0518,
+	[PIR]		= 0x0520,
+	[APR]		= 0x0554,
+	[MPR]		= 0x0558,
+	[PFTCR]		= 0x055c,
+	[PFRCR]		= 0x0560,
+	[TPAUSER]	= 0x0564,
+	[MAHR]		= 0x05c0,
+	[MALR]		= 0x05c8,
+	[CEFCR]		= 0x0740,
+	[FRECR]		= 0x0748,
+	[TSFRCR]	= 0x0750,
+	[TLFRCR]	= 0x0758,
+	[RFCR]		= 0x0760,
+	[MAFCR]		= 0x0778,
+
+	[ARSTR]		= 0x0000,
+	[TSU_CTRST]	= 0x0004,
+	[TSU_VTAG0]	= 0x0058,
+	[TSU_ADSBSY]	= 0x0060,
+	[TSU_TEN]	= 0x0064,
+	[TSU_ADRH0]	= 0x0100,
+	[TSU_ADRL0]	= 0x0104,
+	[TSU_ADRH31]	= 0x01f8,
+	[TSU_ADRL31]	= 0x01fc,
+};
+
 static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
 	[ECMR]		= 0x0100,
 	[RFLR]		= 0x0108,
@@ -318,6 +371,14 @@ static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 		return false;
 }
 
+static bool sh_eth_is_rz_fast_ether(struct sh_eth_private *mdp)
+{
+	if (mdp->reg_offset == sh_eth_offset_fast_rz)
+		return true;
+	else
+		return false;
+}
+
 static void sh_eth_select_mii(struct net_device *ndev)
 {
 	u32 value = 0x0;
@@ -701,6 +762,35 @@ static struct sh_eth_cpu_data r8a7740_data = {
 	.shift_rd0	= 1,
 };
 
+/* R7S72100 */
+static struct sh_eth_cpu_data r7s72100_data = {
+	.chip_reset	= sh_eth_chip_reset,
+	.set_duplex	= sh_eth_set_duplex,
+
+	.register_type	= SH_ETH_REG_FAST_RZ,
+
+	.ecsr_value	= ECSR_ICD,
+	.ecsipr_value	= ECSIPR_ICDIP,
+	.eesipr_value	= 0xff7f009f,
+
+	.tx_check	= EESR_TC1 | EESR_FTC,
+	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
+			  EESR_TDE | EESR_ECI,
+	.fdr_value	= 0x0000070f,
+	.rmcr_value	= RMCR_RNC,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.hw_swap	= 1,
+	.rpadir		= 1,
+	.rpadir_value   = 2 << 16,
+	.no_trimd	= 1,
+	.tsu		= 1,
+	.shift_rd0	= 1,
+};
+
 static struct sh_eth_cpu_data sh7619_data = {
 	.register_type	= SH_ETH_REG_FAST_SH3_SH2,
 
@@ -767,7 +857,7 @@ static int sh_eth_reset(struct net_device *ndev)
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	int ret = 0;
 
-	if (sh_eth_is_gether(mdp)) {
+	if (sh_eth_is_gether(mdp) || sh_eth_is_rz_fast_ether(mdp)) {
 		sh_eth_write(ndev, EDSR_ENALL, EDSR);
 		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
 			     EDMR);
@@ -880,6 +970,8 @@ static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
 {
 	if (sh_eth_is_gether(mdp))
 		return EDTRR_TRNS_GETHER;
+	else if (sh_eth_is_rz_fast_ether(mdp))
+		return EDTRR_TRNS_RZ_ETHER;
 	else
 		return EDTRR_TRNS_ETHER;
 }
@@ -1041,7 +1133,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
 		/* Rx descriptor address set */
 		if (i == 0) {
 			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
-			if (sh_eth_is_gether(mdp))
+			if (sh_eth_is_gether(mdp) ||
+			    sh_eth_is_rz_fast_ether(mdp))
 				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
 		}
 	}
@@ -1062,7 +1155,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
 		if (i == 0) {
 			/* Tx descriptor address set */
 			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
-			if (sh_eth_is_gether(mdp))
+			if (sh_eth_is_gether(mdp) ||
+			    sh_eth_is_rz_fast_ether(mdp))
 				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
 		}
 	}
@@ -1309,9 +1403,9 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
 
 		/* In case of almost all GETHER/ETHERs, the Receive Frame State
 		 * (RFS) bits in the Receive Descriptor 0 are from bit 9 to
-		 * bit 0. However, in case of the R8A7740's GETHER, the RFS
-		 * bits are from bit 25 to bit 16. So, the driver needs right
-		 * shifting by 16.
+		 * bit 0. However, in case of the R8A7740, R8A779x and
+		 * R7S72100 the RFS bits are from bit 25 to bit 16. So, the
+		 * driver needs right shifting by 16.
 		 */
 		if (mdp->cd->shift_rd0)
 			desc_status >>= 16;
@@ -2061,6 +2155,9 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 
+	if (sh_eth_is_rz_fast_ether(mdp))
+		return &ndev->stats;
+
 	pm_runtime_get_sync(&mdp->pdev->dev);
 
 	ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
@@ -2442,6 +2539,11 @@ static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev,
 /* SuperH's TSU register init function */
 static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 {
+	if (sh_eth_is_rz_fast_ether(mdp)) {
+		sh_eth_tsu_write(mdp, 0, TSU_TEN); /* Disable all CAM entry */
+		return;
+	}
+
 	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
 	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
 	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
@@ -2564,6 +2666,9 @@ static const u16 *sh_eth_get_register_offset(int register_type)
 	case SH_ETH_REG_FAST_RCAR:
 		reg_offset = sh_eth_offset_fast_rcar;
 		break;
+	case SH_ETH_REG_FAST_RZ:
+		reg_offset = sh_eth_offset_fast_rz;
+		break;
 	case SH_ETH_REG_FAST_SH4:
 		reg_offset = sh_eth_offset_fast_sh4;
 		break;
@@ -2799,6 +2904,7 @@ static struct platform_device_id sh_eth_id_table[] = {
 	{ "sh7757-ether", (kernel_ulong_t)&sh7757_data },
 	{ "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga },
 	{ "sh7763-gether", (kernel_ulong_t)&sh7763_data },
+	{ "r7s72100-ether", (kernel_ulong_t)&r7s72100_data },
 	{ "r8a7740-gether", (kernel_ulong_t)&r8a7740_data },
 	{ "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
 	{ "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 0fe35b7..0bcde90 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -156,6 +156,7 @@ enum {
 enum {
 	SH_ETH_REG_GIGABIT,
 	SH_ETH_REG_FAST_RCAR,
+	SH_ETH_REG_FAST_RZ,
 	SH_ETH_REG_FAST_SH4,
 	SH_ETH_REG_FAST_SH3_SH2
 };
@@ -169,7 +170,7 @@ enum {
 
 /* Register's bits
  */
-/* EDSR : sh7734, sh7757, sh7763, and r8a7740 only */
+/* EDSR : sh7734, sh7757, sh7763, r8a7740 and r7s72100 only */
 enum EDSR_BIT {
 	EDSR_ENT = 0x01, EDSR_ENR = 0x02,
 };
@@ -191,6 +192,7 @@ enum DMAC_M_BIT {
 /* EDTRR */
 enum DMAC_T_BIT {
 	EDTRR_TRNS_GETHER = 0x03,
+	EDTRR_TRNS_RZ_ETHER = 0x03,
 	EDTRR_TRNS_ETHER = 0x01,
 };
 
-- 
1.8.4

^ permalink raw reply related

* [PATCH v4 0/4] Add ethernet support for r7s72100
From: Simon Horman @ 2014-01-08  8:02 UTC (permalink / raw)
  To: David S. Miller, netdev, linux-sh
  Cc: linux-arm-kernel, Magnus Damm, Sergei Shtylyov, Simon Horman

Hi,

this series adds ethernet support to sh-pfc for the r7s72100 SoC.

This series is based on a merge of:
* The topic/r7s72100-v3.13-rc7-20140107 tag in my renesas tree
* net-next
  - Head revision: 80077935cad223b29
    ("Merge branch 'master' of
      git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next")

The first two patches, targeted at net-next, also applies cleanly there.

Changes since v3
* Use bool as return type of sh_eth_is_gether()
  and sh_eth_is_rz_fast_ether()
* Correct coding style in sh_eth_get_stats()

Changes since v2
* Trivial rebase
* Dropped "RFC" from subject

Changes since v1 are noted in the changelog of each patch.

Simon Horman (4):
  sh_eth: Use bool as return type of sh_eth_is_gether()
  sh_eth: Add support for r7s72100
  ARM: shmobile: r7s72100: Add clock for r7s72100-ether
  ARM: shmobile: genmai: Enable r7s72100-ether

 arch/arm/mach-shmobile/board-genmai.c   |  21 ++++++
 arch/arm/mach-shmobile/clock-r7s72100.c |   4 ++
 drivers/net/ethernet/renesas/sh_eth.c   | 124 +++++++++++++++++++++++++++++---
 drivers/net/ethernet/renesas/sh_eth.h   |   4 +-
 4 files changed, 143 insertions(+), 10 deletions(-)

-- 
1.8.4

^ permalink raw reply

* [PATCH v4 4/4] ARM: shmobile: genmai: Enable r7s72100-ether
From: Simon Horman @ 2014-01-08  8:02 UTC (permalink / raw)
  To: David S. Miller, netdev, linux-sh
  Cc: linux-arm-kernel, Magnus Damm, Sergei Shtylyov, Simon Horman,
	Simon Horman
In-Reply-To: <1389168152-9434-1-git-send-email-horms+renesas@verge.net.au>

Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---

Dave,

I plan to take this change through my tree.

v3 - v4
* No change

v2
* As suggested by Magnus Damm and Sergei Shtylyov
  - r7s72100 ethernet is not gigabit so do not refer to it as such

* As suggested by Sergei Shtylyov
  - set no_ether_link as there is no LINK signal documented
    in the manual
---
 arch/arm/mach-shmobile/board-genmai.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/mach-shmobile/board-genmai.c b/arch/arm/mach-shmobile/board-genmai.c
index 3e92e3c..a1f6fe1 100644
--- a/arch/arm/mach-shmobile/board-genmai.c
+++ b/arch/arm/mach-shmobile/board-genmai.c
@@ -20,15 +20,36 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/sh_eth.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/r7s72100.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+/* Ether */
+static const struct sh_eth_plat_data ether_pdata __initconst = {
+	.phy			= 0x00, /* PD60610 */
+	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
+	.phy_interface		= PHY_INTERFACE_MODE_MII,
+	.no_ether_link		= 1
+};
+
+static const struct resource ether_resources[] __initconst = {
+	DEFINE_RES_MEM(0xe8203000, 0x800),
+	DEFINE_RES_MEM(0xe8204800, 0x200),
+	DEFINE_RES_IRQ(gic_iid(359)),
+};
+
 static void __init genmai_add_standard_devices(void)
 {
 	r7s72100_clock_init();
 	r7s72100_add_dt_devices();
+
+	platform_device_register_resndata(&platform_bus, "r7s72100-ether", -1,
+					  ether_resources,
+					  ARRAY_SIZE(ether_resources),
+					  &ether_pdata, sizeof(ether_pdata));
 }
 
 static const char * const genmai_boards_compat_dt[] __initconst = {
-- 
1.8.4


^ permalink raw reply related

* [PATCH v4 3/4] ARM: shmobile: r7s72100: Add clock for r7s72100-ether
From: Simon Horman @ 2014-01-08  8:02 UTC (permalink / raw)
  To: David S. Miller, netdev, linux-sh
  Cc: linux-arm-kernel, Magnus Damm, Sergei Shtylyov, Simon Horman
In-Reply-To: <1389168152-9434-1-git-send-email-horms+renesas@verge.net.au>

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

---

Dave,

I plan to take this change through my tree.

v3 - v4
* No change

v2
* As suggested by Sergei Shtylyov
  - Add MSTP74 to beginning of enum on a line by itself
* As suggested by Magnus Damm
  - r7s72100 ethernet is not gigabit so do not refer to it as such
---
 arch/arm/mach-shmobile/clock-r7s72100.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c
index e6ab0cd..c4ba651 100644
--- a/arch/arm/mach-shmobile/clock-r7s72100.c
+++ b/arch/arm/mach-shmobile/clock-r7s72100.c
@@ -27,6 +27,7 @@
 #define FRQCR2		0xfcfe0014
 #define STBCR3		0xfcfe0420
 #define STBCR4		0xfcfe0424
+#define STBCR7		0xfcfe0430
 #define STBCR9		0xfcfe0438
 
 #define PLL_RATE 30
@@ -146,6 +147,7 @@ struct clk div4_clks[DIV4_NR] = {
 };
 
 enum {	MSTP97, MSTP96, MSTP95, MSTP94,
+	MSTP74,
 	MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
 	MSTP33,	MSTP_NR };
 
@@ -154,6 +156,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP96] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 6, 0), /* RIIC1 */
 	[MSTP95] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 5, 0), /* RIIC2 */
 	[MSTP94] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 4, 0), /* RIIC3 */
+	[MSTP74] = SH_CLK_MSTP8(&peripheral1_clk, STBCR7, 4, 0), /* Ether */
 	[MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
 	[MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
 	[MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
@@ -176,6 +179,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
 	/* MSTP clocks */
+	CLKDEV_DEV_ID("r7s72100-ether", &mstp_clks[MSTP74]),
 	CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]),
 
 	/* ICK */
-- 
1.8.4


^ permalink raw reply related

* [PATCH v4 net-next 1/4] sh_eth: Use bool as return type of sh_eth_is_gether()
From: Simon Horman @ 2014-01-08  8:02 UTC (permalink / raw)
  To: David S. Miller, netdev, linux-sh
  Cc: linux-arm-kernel, Magnus Damm, Sergei Shtylyov, Simon Horman
In-Reply-To: <1389168152-9434-1-git-send-email-horms+renesas@verge.net.au>

Return a boolean and use true and false.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

---

Dave,

please consider this for net-next.

v4
* First post
---
 drivers/net/ethernet/renesas/sh_eth.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 8884107..4b38533 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -310,12 +310,12 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
 	[TSU_ADRL31]	= 0x01fc,
 };
 
-static int sh_eth_is_gether(struct sh_eth_private *mdp)
+static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 {
 	if (mdp->reg_offset == sh_eth_offset_gigabit)
-		return 1;
+		return true;
 	else
-		return 0;
+		return false;
 }
 
 static void sh_eth_select_mii(struct net_device *ndev)
-- 
1.8.4


^ permalink raw reply related

* Re: [PATCH] ipv6: don't call addrconf_dst_alloc again when enable lo
From: Gao feng @ 2014-01-08  7:50 UTC (permalink / raw)
  To: chenweilong, David Miller, kumaran.4353, netdev
In-Reply-To: <20140103065349.GK22494@order.stressinduktion.org>

On 01/03/2014 02:53 PM, Hannes Frederic Sowa wrote:
> On Thu, Jan 02, 2014 at 05:33:15PM +0800, chenweilong wrote:
>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>> index 62d1799..d2f8c0a 100644
>> --- a/net/ipv6/addrconf.c
>> +++ b/net/ipv6/addrconf.c
>> @@ -2422,8 +2422,9 @@ static void init_loopback(struct net_device *dev)
>>  			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
>>  				continue;
>>
>> -			if (sp_ifa->rt)
>> -				continue;
>> +			if (sp_ifa->rt && sp_ifa->rt->dst.dev == dev) {
>> +				ip6_del_rt(sp_ifa->rt);
>> +			}
>>
>>  			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
>>
> 
> Maybe this change would not be that bad after all, as those ifa attached dsts
> are already dead and queued up for gc and should not get inserted back.

I like this idea, maybe the below patch is better. we only need to delete this
route when it has been added to garbage list.

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1a341f7..4dca886 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2610,8 +2610,16 @@ static void init_loopback(struct net_device *dev)
                        if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
                                continue;

-                       if (sp_ifa->rt)
-                               continue;
+                       if (sp_ifa->rt) {
+                               /* This dst has been added to garbage list when
+                                * lo device down, delete this obsolete dst and
+                                * reallocate new router for ifa. */
+                               if (sp_ifa->rt->dst.obsolete > 0) {
+                                       ip6_del_rt(sp_ifa->rt);
+                                       sp_ifa->rt = NULL;
+                               } else
+                                       continue;
+                       }

                        sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);



> 
> I'll try to just disable routes without removing them at all when we set an
> interface to down at the weekend.
> 

How do you decide which route should be disabled?  use rt6_flags? I don't know
if your way will cause miscarriage.

^ permalink raw reply related

* [net-next 7/7] ixgbe: Additional adapter removal checks
From: Aaron Brown @ 2014-01-08  7:40 UTC (permalink / raw)
  To: davem; +Cc: Mark Rustad, netdev, gospo, sassmann, Aaron Brown
In-Reply-To: <1389166847-3780-1-git-send-email-aaron.f.brown@intel.com>

From: Mark Rustad <mark.d.rustad@intel.com>

Additional checks are needed for a detected removal not to cause
problems. Some involve simply avoiding a lot of stuff that can't
do anything good, and also cases where the phony return value can
cause problems. In addition, down the adapter when the removal is
sensed.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 22 ++++++++++++++++++++++
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c    | 16 ++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 412cb1a..0899b1d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1342,6 +1342,10 @@ static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg,
 	static const u32 test_pattern[] = {
 		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 
+	if (IXGBE_REMOVED(adapter->hw.hw_addr)) {
+		*data = 1;
+		return 1;
+	}
 	for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
 		before = IXGBE_READ_REG(&adapter->hw, reg);
 		IXGBE_WRITE_REG(&adapter->hw, reg, test_pattern[pat] & write);
@@ -1364,6 +1368,10 @@ static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg,
 {
 	u32 val, before;
 
+	if (IXGBE_REMOVED(adapter->hw.hw_addr)) {
+		*data = 1;
+		return 1;
+	}
 	before = IXGBE_READ_REG(&adapter->hw, reg);
 	IXGBE_WRITE_REG(&adapter->hw, reg, write & mask);
 	val = IXGBE_READ_REG(&adapter->hw, reg);
@@ -1384,6 +1392,11 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
 	u32 value, before, after;
 	u32 i, toggle;
 
+	if (IXGBE_REMOVED(adapter->hw.hw_addr)) {
+		e_err(drv, "Adapter removed - register test blocked\n");
+		*data = 1;
+		return 1;
+	}
 	switch (adapter->hw.mac.type) {
 	case ixgbe_mac_82598EB:
 		toggle = 0x7FFFF3FF;
@@ -1950,6 +1963,15 @@ static void ixgbe_diag_test(struct net_device *netdev,
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	bool if_running = netif_running(netdev);
 
+	if (IXGBE_REMOVED(adapter->hw.hw_addr)) {
+		e_err(hw, "Adapter removed - test blocked\n");
+		data[0] = 1;
+		data[1] = 1;
+		data[2] = 1;
+		data[3] = 1;
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		return;
+	}
 	set_bit(__IXGBE_TESTING, &adapter->state);
 	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		struct ixgbe_hw *hw = &adapter->hw;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 896a8b0..364df2c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -291,6 +291,7 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
 		return;
 	hw->hw_addr = NULL;
 	e_dev_err("Adapter removed\n");
+	ixgbe_service_event_schedule(adapter);
 }
 
 void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
@@ -3338,6 +3339,8 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
 	u32 rxdctl;
 	u8 reg_idx = ring->reg_idx;
 
+	if (IXGBE_REMOVED(hw->hw_addr))
+		return;
 	/* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
 	if (hw->mac.type == ixgbe_mac_82598EB &&
 	    !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
@@ -3362,6 +3365,8 @@ void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
 	u32 rxdctl;
 	u8 reg_idx = ring->reg_idx;
 
+	if (IXGBE_REMOVED(hw->hw_addr))
+		return;
 	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
 	rxdctl &= ~IXGBE_RXDCTL_ENABLE;
 
@@ -4687,6 +4692,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
 	struct ixgbe_hw *hw = &adapter->hw;
 	int err;
 
+	if (IXGBE_REMOVED(hw->hw_addr))
+		return;
 	/* lock SFP init bit to prevent race conditions with the watchdog */
 	while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
 		usleep_range(1000, 2000);
@@ -6397,6 +6404,15 @@ static void ixgbe_service_task(struct work_struct *work)
 	struct ixgbe_adapter *adapter = container_of(work,
 						     struct ixgbe_adapter,
 						     service_task);
+	if (IXGBE_REMOVED(adapter->hw.hw_addr)) {
+		if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+			rtnl_lock();
+			ixgbe_down(adapter);
+			rtnl_unlock();
+		}
+		ixgbe_service_event_complete(adapter);
+		return;
+	}
 	ixgbe_reset_subtask(adapter);
 	ixgbe_sfp_detection_subtask(adapter);
 	ixgbe_sfp_link_config_subtask(adapter);
-- 
1.8.5.GIT

^ permalink raw reply related

* [net-next 6/7] ixgbe: Check for adapter removal on register writes
From: Aaron Brown @ 2014-01-08  7:40 UTC (permalink / raw)
  To: davem; +Cc: Mark Rustad, netdev, gospo, sassmann, Aaron Brown
In-Reply-To: <1389166847-3780-1-git-send-email-aaron.f.brown@intel.com>

From: Mark Rustad <mark.d.rustad@intel.com>

Prevent writes to an adapter that has been detected as removed
by a previous failing read. This also fixes some include file
ordering confusion that this patch revealed.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 12 ++++++++++--
 drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c    |  3 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c    |  2 +-
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 480c5c1..5320586 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -131,7 +131,11 @@ void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg);
 
 static inline void IXGBE_WRITE_REG(struct ixgbe_hw *hw, u32 reg, u32 value)
 {
-	writel(value, hw->hw_addr + reg);
+	u8 __iomem *reg_addr = ACCESS_ONCE(hw->hw_addr);
+
+	if (IXGBE_REMOVED(reg_addr))
+		return;
+	writel(value, reg_addr + reg);
 }
 
 #ifndef writeq
@@ -144,7 +148,11 @@ static inline void writeq(u64 val, void __iomem *addr)
 
 static inline void IXGBE_WRITE_REG64(struct ixgbe_hw *hw, u32 reg, u64 value)
 {
-	writeq(value, hw->hw_addr + reg);
+	u8 __iomem *reg_addr = ACCESS_ONCE(hw->hw_addr);
+
+	if (IXGBE_REMOVED(reg_addr))
+		return;
+	writeq(value, reg_addr + reg);
 }
 
 static inline u32 IXGBE_READ_REG(struct ixgbe_hw *hw, u32 reg)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
index d4a64e6..cc3101a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -27,8 +27,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include "ixgbe_type.h"
-#include "ixgbe_common.h"
+#include "ixgbe.h"
 #include "ixgbe_mbx.h"
 
 /**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 39217e5..132557c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 
-#include "ixgbe_common.h"
+#include "ixgbe.h"
 #include "ixgbe_phy.h"
 
 static void ixgbe_i2c_start(struct ixgbe_hw *hw);
-- 
1.8.5.GIT

^ permalink raw reply related

* [net-next 5/7] ixgbe: Check register reads for adapter removal
From: Aaron Brown @ 2014-01-08  7:40 UTC (permalink / raw)
  To: davem; +Cc: Mark Rustad, netdev, gospo, sassmann, Aaron Brown
In-Reply-To: <1389166847-3780-1-git-send-email-aaron.f.brown@intel.com>

From: Mark Rustad <mark.d.rustad@intel.com>

Check all register reads for adapter removal by checking the status
register after any register read that returns 0xFFFFFFFF. Since the
status register will never return 0xFFFFFFFF unless the adapter is
removed, such a value from a status register read confirms the
removal.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h        |  1 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 15 +++++++++-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c   | 38 ++++++++++++++++++++++---
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 199cf74..002c9e2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -747,6 +747,7 @@ struct ixgbe_adapter {
 #ifdef IXGBE_FCOE
 	struct ixgbe_fcoe fcoe;
 #endif /* IXGBE_FCOE */
+	u8 __iomem *io_addr; /* Mainly for iounmap use */
 	u32 wol;
 
 	u16 bd_number;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 5e157ac..480c5c1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -124,6 +124,11 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
 s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
 
+#define IXGBE_FAILED_READ_REG 0xffffffffU
+
+void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg);
+#define IXGBE_REMOVED(a) unlikely(!(a))
+
 static inline void IXGBE_WRITE_REG(struct ixgbe_hw *hw, u32 reg, u32 value)
 {
 	writel(value, hw->hw_addr + reg);
@@ -144,7 +149,15 @@ static inline void IXGBE_WRITE_REG64(struct ixgbe_hw *hw, u32 reg, u64 value)
 
 static inline u32 IXGBE_READ_REG(struct ixgbe_hw *hw, u32 reg)
 {
-	return readl(hw->hw_addr + reg);
+	u8 __iomem *reg_addr = ACCESS_ONCE(hw->hw_addr);
+	u32 value;
+
+	if (IXGBE_REMOVED(reg_addr))
+		return IXGBE_FAILED_READ_REG;
+	value = readl(reg_addr + reg);
+	if (unlikely(value == IXGBE_FAILED_READ_REG))
+		ixgbe_check_remove(hw, reg);
+	return value;
 }
 
 #define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) \
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 4d71277..896a8b0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -283,6 +283,35 @@ static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
 		schedule_work(&adapter->service_task);
 }
 
+static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+
+	if (!hw->hw_addr)
+		return;
+	hw->hw_addr = NULL;
+	e_dev_err("Adapter removed\n");
+}
+
+void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
+{
+	u32 value;
+
+	/* The following check not only optimizes a bit by not
+	 * performing a read on the status register when the
+	 * register just read was a status register read that
+	 * returned IXGBE_FAILED_READ_REG. It also blocks any
+	 * potential recursion.
+	 */
+	if (reg == IXGBE_STATUS) {
+		ixgbe_remove_adapter(hw);
+		return;
+	}
+	value = IXGBE_READ_REG(hw, IXGBE_STATUS);
+	if (value == IXGBE_FAILED_READ_REG)
+		ixgbe_remove_adapter(hw);
+}
+
 static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter)
 {
 	BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state));
@@ -2970,7 +2999,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
 			ring->count * sizeof(union ixgbe_adv_tx_desc));
 	IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
-	ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx);
+	ring->tail = adapter->io_addr + IXGBE_TDT(reg_idx);
 
 	/*
 	 * set WTHRESH to encourage burst writeback, it should not be set
@@ -3373,7 +3402,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 			ring->count * sizeof(union ixgbe_adv_rx_desc));
 	IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0);
-	ring->tail = hw->hw_addr + IXGBE_RDT(reg_idx);
+	ring->tail = adapter->io_addr + IXGBE_RDT(reg_idx);
 
 	ixgbe_configure_srrctl(adapter, ring);
 	ixgbe_configure_rscctl(adapter, ring);
@@ -7887,6 +7916,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
 			      pci_resource_len(pdev, 0));
+	adapter->io_addr = hw->hw_addr;
 	if (!hw->hw_addr) {
 		err = -EIO;
 		goto err_ioremap;
@@ -8195,7 +8225,7 @@ err_register:
 err_sw_init:
 	ixgbe_disable_sriov(adapter);
 	adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
-	iounmap(hw->hw_addr);
+	iounmap(adapter->io_addr);
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
@@ -8262,7 +8292,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
 	kfree(adapter->ixgbe_ieee_ets);
 
 #endif
-	iounmap(adapter->hw.hw_addr);
+	iounmap(adapter->io_addr);
 	pci_release_selected_regions(pdev, pci_select_bars(pdev,
 				     IORESOURCE_MEM));
 
-- 
1.8.5.GIT

^ permalink raw reply related

* [net-next 4/7] ixgbe: Make ethtool register test use accessors
From: Aaron Brown @ 2014-01-08  7:40 UTC (permalink / raw)
  To: davem; +Cc: Mark Rustad, netdev, gospo, sassmann, Aaron Brown
In-Reply-To: <1389166847-3780-1-git-send-email-aaron.f.brown@intel.com>

From: Mark Rustad <mark.d.rustad@intel.com>

Make the ethtool register test use the normal register accessor
functions. Also eliminate macros used for calling register test
functions to make error exits clearer. Use boolean values for
boolean returns instead of 0 and 1.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 88 +++++++++++-------------
 1 file changed, 42 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 4e7c9b0..412cb1a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1343,54 +1343,41 @@ static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg,
 		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 
 	for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
-		before = readl(adapter->hw.hw_addr + reg);
-		writel((test_pattern[pat] & write),
-		       (adapter->hw.hw_addr + reg));
-		val = readl(adapter->hw.hw_addr + reg);
+		before = IXGBE_READ_REG(&adapter->hw, reg);
+		IXGBE_WRITE_REG(&adapter->hw, reg, test_pattern[pat] & write);
+		val = IXGBE_READ_REG(&adapter->hw, reg);
 		if (val != (test_pattern[pat] & write & mask)) {
 			e_err(drv, "pattern test reg %04X failed: got "
 			      "0x%08X expected 0x%08X\n",
 			      reg, val, (test_pattern[pat] & write & mask));
 			*data = reg;
-			writel(before, adapter->hw.hw_addr + reg);
-			return 1;
+			IXGBE_WRITE_REG(&adapter->hw, reg, before);
+			return true;
 		}
-		writel(before, adapter->hw.hw_addr + reg);
+		IXGBE_WRITE_REG(&adapter->hw, reg, before);
 	}
-	return 0;
+	return false;
 }
 
 static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg,
 			      u32 mask, u32 write)
 {
 	u32 val, before;
-	before = readl(adapter->hw.hw_addr + reg);
-	writel((write & mask), (adapter->hw.hw_addr + reg));
-	val = readl(adapter->hw.hw_addr + reg);
+
+	before = IXGBE_READ_REG(&adapter->hw, reg);
+	IXGBE_WRITE_REG(&adapter->hw, reg, write & mask);
+	val = IXGBE_READ_REG(&adapter->hw, reg);
 	if ((write & mask) != (val & mask)) {
 		e_err(drv, "set/check reg %04X test failed: got 0x%08X "
 		      "expected 0x%08X\n", reg, (val & mask), (write & mask));
 		*data = reg;
-		writel(before, (adapter->hw.hw_addr + reg));
-		return 1;
+		IXGBE_WRITE_REG(&adapter->hw, reg, before);
+		return true;
 	}
-	writel(before, (adapter->hw.hw_addr + reg));
-	return 0;
+	IXGBE_WRITE_REG(&adapter->hw, reg, before);
+	return false;
 }
 
-#define REG_PATTERN_TEST(reg, mask, write)				      \
-	do {								      \
-		if (reg_pattern_test(adapter, data, reg, mask, write))	      \
-			return 1;					      \
-	} while (0)							      \
-
-
-#define REG_SET_AND_CHECK(reg, mask, write)				      \
-	do {								      \
-		if (reg_set_and_check(adapter, data, reg, mask, write))	      \
-			return 1;					      \
-	} while (0)							      \
-
 static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
 {
 	const struct ixgbe_reg_test *test;
@@ -1438,38 +1425,47 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
 	 */
 	while (test->reg) {
 		for (i = 0; i < test->array_len; i++) {
+			bool b = false;
+
 			switch (test->test_type) {
 			case PATTERN_TEST:
-				REG_PATTERN_TEST(test->reg + (i * 0x40),
-						 test->mask,
-						 test->write);
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 0x40),
+						     test->mask,
+						     test->write);
 				break;
 			case SET_READ_TEST:
-				REG_SET_AND_CHECK(test->reg + (i * 0x40),
-						  test->mask,
-						  test->write);
+				b = reg_set_and_check(adapter, data,
+						      test->reg + (i * 0x40),
+						      test->mask,
+						      test->write);
 				break;
 			case WRITE_NO_TEST:
-				writel(test->write,
-				       (adapter->hw.hw_addr + test->reg)
-				       + (i * 0x40));
+				IXGBE_WRITE_REG(&adapter->hw,
+						test->reg + (i * 0x40),
+						test->write);
 				break;
 			case TABLE32_TEST:
-				REG_PATTERN_TEST(test->reg + (i * 4),
-						 test->mask,
-						 test->write);
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 4),
+						     test->mask,
+						     test->write);
 				break;
 			case TABLE64_TEST_LO:
-				REG_PATTERN_TEST(test->reg + (i * 8),
-						 test->mask,
-						 test->write);
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 8),
+						     test->mask,
+						     test->write);
 				break;
 			case TABLE64_TEST_HI:
-				REG_PATTERN_TEST((test->reg + 4) + (i * 8),
-						 test->mask,
-						 test->write);
+				b = reg_pattern_test(adapter, data,
+						     (test->reg + 4) + (i * 8),
+						     test->mask,
+						     test->write);
 				break;
 			}
+			if (b)
+				return 1;
 		}
 		test++;
 	}
-- 
1.8.5.GIT

^ permalink raw reply related

* [net-next 3/7] ixgbe: Use static inlines instead of macros
From: Aaron Brown @ 2014-01-08  7:40 UTC (permalink / raw)
  To: davem; +Cc: Mark Rustad, netdev, gospo, sassmann, Aaron Brown
In-Reply-To: <1389166847-3780-1-git-send-email-aaron.f.brown@intel.com>

From: Mark Rustad <mark.d.rustad@intel.com>

Kernel coding standard prefers static inline functions instead
of macros, so use them for register accessors. This is to prepare
for adding LER, Live Error Recovery, checks to those accessors.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h        |  5 +++++
 drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 30 +++++++++++++++++--------
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c   |  4 ++--
 3 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 8da263a..199cf74 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -585,6 +585,11 @@ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
 	return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
 }
 
+static inline void ixgbe_write_tail(struct ixgbe_ring *ring, u32 value)
+{
+	writel(value, ring->tail);
+}
+
 #define IXGBE_RX_DESC(R, i)	    \
 	(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
 #define IXGBE_TX_DESC(R, i)	    \
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index d259dc7..5e157ac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -124,22 +124,34 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
 s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
 
-#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
+static inline void IXGBE_WRITE_REG(struct ixgbe_hw *hw, u32 reg, u32 value)
+{
+	writel(value, hw->hw_addr + reg);
+}
 
 #ifndef writeq
-#define writeq(val, addr) writel((u32) (val), addr); \
-    writel((u32) (val >> 32), (addr + 4));
+static inline void writeq(u64 val, void __iomem *addr)
+{
+	writel((u32)val, addr);
+	writel((u32)(val >> 32), addr + 4);
+}
 #endif
 
-#define IXGBE_WRITE_REG64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
+static inline void IXGBE_WRITE_REG64(struct ixgbe_hw *hw, u32 reg, u64 value)
+{
+	writeq(value, hw->hw_addr + reg);
+}
 
-#define IXGBE_READ_REG(a, reg) readl((a)->hw_addr + (reg))
+static inline u32 IXGBE_READ_REG(struct ixgbe_hw *hw, u32 reg)
+{
+	return readl(hw->hw_addr + reg);
+}
 
-#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) (\
-    writel((value), ((a)->hw_addr + (reg) + ((offset) << 2))))
+#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) \
+		IXGBE_WRITE_REG((a), (reg) + ((offset) << 2), (value))
 
-#define IXGBE_READ_REG_ARRAY(a, reg, offset) (\
-    readl((a)->hw_addr + (reg) + ((offset) << 2)))
+#define IXGBE_READ_REG_ARRAY(a, reg, offset) \
+		IXGBE_READ_REG((a), (reg) + ((offset) << 2))
 
 #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 923b0fa..4d71277 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1315,7 +1315,7 @@ static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val)
 	 * such as IA-64).
 	 */
 	wmb();
-	writel(val, rx_ring->tail);
+	ixgbe_write_tail(rx_ring, val);
 }
 
 static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
@@ -6699,7 +6699,7 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
 	tx_ring->next_to_use = i;
 
 	/* notify HW of packet */
-	writel(i, tx_ring->tail);
+	ixgbe_write_tail(tx_ring, i);
 
 	return;
 dma_error:
-- 
1.8.5.GIT

^ 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