* Re: [PATCH] netlink: change presentation of portid in procfs to unsigned
From: David Miller @ 2012-12-18 4:51 UTC (permalink / raw)
To: hannes; +Cc: netdev
In-Reply-To: <20121216010919.GA1528@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Sun, 16 Dec 2012 02:09:19 +0100
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied.
^ permalink raw reply
* Re: [PATCH] netlink: validate addr_len on bind
From: David Miller @ 2012-12-18 4:52 UTC (permalink / raw)
To: hannes; +Cc: netdev
In-Reply-To: <20121216014219.GB1528@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Sun, 16 Dec 2012 02:42:19 +0100
> Otherwise an out of bounds read could happen.
>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied.
^ permalink raw reply
* Re: [PATCH] atm: use scnprintf() instead of sprintf()
From: David Miller @ 2012-12-18 4:52 UTC (permalink / raw)
To: chas; +Cc: netdev, gang.chen
In-Reply-To: <20121217110001.3eaf3ac5@thirdoffive.cmf.nrl.navy.mil>
From: chas williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Date: Mon, 17 Dec 2012 11:00:01 -0500
>
> As reported by Chen Gang <gang.chen@asianux.com>, we should ensure there
> is enough space when formatting the sysfs buffers.
>
> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Applied.
^ permalink raw reply
* Re: [PATCH 1/2 v2] qmi_wwan/cdc_ether: add Dell Wireless 5800 (Novatel E362) USB IDs
From: David Miller @ 2012-12-18 4:52 UTC (permalink / raw)
To: dcbw; +Cc: bjorn, aleksander, netdev
In-Reply-To: <1355768261.1424.50.camel@dcbw.foobar.com>
From: Dan Williams <dcbw@redhat.com>
Date: Mon, 17 Dec 2012 12:17:41 -0600
> Signed-off-by: Dan Williams <dcbw@redhat.com>
Applied.
^ permalink raw reply
* Re: [PATCH 2/2 v2] cdc_ether: cleanup: use USB_DEVICE_AND_INTERFACE_INFO for Novatel 551/E362
From: David Miller @ 2012-12-18 4:52 UTC (permalink / raw)
To: dcbw; +Cc: bjorn, aleksander, netdev
In-Reply-To: <1355768386.1424.52.camel@dcbw.foobar.com>
From: Dan Williams <dcbw@redhat.com>
Date: Mon, 17 Dec 2012 12:19:46 -0600
> Signed-off-by: Dan Williams <dcbw@redhat.com>
Applied.
^ permalink raw reply
* [RFC][PATCH] ipv6 multicast forwarding: Remove threshold checking and some trivial bugs
From: Ang Way Chuang @ 2012-12-18 4:57 UTC (permalink / raw)
To: netdev; +Cc: yoshfuji
This patch fixes trivial bugs for IPv6 multicast forwarding code and remove
threshold checking for multicast forwarding cache.
1. Threshold checking in IPv6 multicast forwarding cache (MFC) was not properly implemented.
syscall to setsockopt(... MRT6_ADD_MIF,...) doesn't affect the TTL because it is never used.
In fact, all MFC will always have ttl of 1 as set by ip6mr_mfc_add. From my limited knowledge of
multicast routing, threshold setting on interface is only used by DVMRP which doesn't support
IPv6. FreeBSD's struct mif6ctl doesn't have vifc_threshold. This patch removes the ttl cruft
within kernel. Userspace ABI for backward compatibility. Can someone knowledgable in multicast
routing please verify whether my understanding is correct?
2. Don't allow addition of MFC with non-existent multicast interface index.
3. Don't allow addition of MFC where incoming interface is part of oif list. This does not make
sense. Why would we want to send a multicast back to the interface where it originates from.
4. setsockopt(....MRT6_ADD_MIF, ) allows a "physical" interface to be registered as multicast
interface multiple times. This doesn't make sense. Don't allow registration duplicate
registration of the same "physical" interface.
This patch has been tested, albeit minimally using a simple program. Is this patch okay for
inclusion? Will sign off if it is okay.
---
include/linux/mroute6.h | 3 +-
net/ipv6/ip6mr.c | 79 +++++++++++++++++++++++++----------------------
2 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index a223561..88a79d8 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -66,7 +66,6 @@ struct mif_device {
unsigned long bytes_in,bytes_out;
unsigned long pkt_in,pkt_out; /* Statistics */
unsigned long rate_limit; /* Traffic shaping (NI) */
- unsigned char threshold; /* TTL threshold */
unsigned short flags; /* Control flags */
int link; /* Physical interface index */
};
@@ -92,7 +91,7 @@ struct mfc6_cache {
unsigned long bytes;
unsigned long pkt;
unsigned long wrong_if;
- unsigned char ttls[MAXMIFS]; /* TTL thresholds */
+ struct if_set mf6c_ifset; /* Where it is going */
} res;
} mfc_un;
};
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 26dcdec..0a12fe4 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -122,6 +122,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb,
struct netlink_callback *cb);
static void mroute_clean_tables(struct mr6_table *mrt);
static void ipmr_expire_process(unsigned long arg);
+static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev);
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
#define ip6mr_for_each_table(mrt, net) \
@@ -574,10 +575,10 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
for (n = mfc->mfc_un.res.minvif;
n < mfc->mfc_un.res.maxvif; n++) {
if (MIF_EXISTS(mrt, n) &&
- mfc->mfc_un.res.ttls[n] < 255)
+ IF_ISSET(n, &mfc->mfc_un.res.mf6c_ifset))
seq_printf(seq,
" %2d:%-3d",
- n, mfc->mfc_un.res.ttls[n]);
+ n, 1);
}
} else {
/* unresolved mfc_caches don't contain
@@ -895,28 +896,6 @@ static void ipmr_expire_process(unsigned long arg)
spin_unlock(&mfc_unres_lock);
}
-/* Fill oifs list. It is called under write locked mrt_lock. */
-
-static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache,
- unsigned char *ttls)
-{
- int vifi;
-
- cache->mfc_un.res.minvif = MAXMIFS;
- cache->mfc_un.res.maxvif = 0;
- memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
-
- for (vifi = 0; vifi < mrt->maxvif; vifi++) {
- if (MIF_EXISTS(mrt, vifi) &&
- ttls[vifi] && ttls[vifi] < 255) {
- cache->mfc_un.res.ttls[vifi] = ttls[vifi];
- if (cache->mfc_un.res.minvif > vifi)
- cache->mfc_un.res.minvif = vifi;
- if (cache->mfc_un.res.maxvif <= vifi)
- cache->mfc_un.res.maxvif = vifi + 1;
- }
- }
-}
static int mif6_add(struct net *net, struct mr6_table *mrt,
struct mif6ctl *vifc, int mrtsock)
@@ -955,6 +934,12 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
dev = dev_get_by_index(net, vifc->mif6c_pifi);
if (!dev)
return -EADDRNOTAVAIL;
+
+ if (ip6mr_find_vif(mrt, dev) >= 0) {
+ dev_put(dev);
+ return -EADDRINUSE;
+ }
+
err = dev_set_allmulti(dev, 1);
if (err) {
dev_put(dev);
@@ -980,7 +965,6 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
v->flags = vifc->mif6c_flags;
if (!mrtsock)
v->flags |= VIFF_STATIC;
- v->threshold = vifc->vifc_threshold;
v->bytes_in = 0;
v->bytes_out = 0;
v->pkt_in = 0;
@@ -1393,22 +1377,37 @@ void ip6_mr_cleanup(void)
static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
struct mf6cctl *mfc, int mrtsock)
{
+ int minvif = MAXMIFS;
+ int maxvif = 0;
bool found = false;
int line;
struct mfc6_cache *uc, *c;
- unsigned char ttls[MAXMIFS];
int i;
- if (mfc->mf6cc_parent >= MAXMIFS)
+ if (mfc->mf6cc_parent >= MAXMIFS || !MIF_EXISTS(mrt, mfc->mf6cc_parent))
return -ENFILE;
- memset(ttls, 255, MAXMIFS);
- for (i = 0; i < MAXMIFS; i++) {
- if (IF_ISSET(i, &mfc->mf6cc_ifset))
- ttls[i] = 1;
+ /* incoming interface should not be part of outgoing interfaces, doing so
+ * will cause duplicate
+ */
+ if (IF_ISSET(mfc->mf6cc_parent, &mfc->mf6cc_ifset))
+ return -EINVAL;
+ for (i = 0; i < MAXMIFS; i++) {
+ if (IF_ISSET(i, &mfc->mf6cc_ifset)) {
+ if (!MIF_EXISTS(mrt, i))
+ return -ENFILE;
+
+ if (minvif > i)
+ minvif = i;
+ if (maxvif <= i)
+ maxvif = i + 1;
+ }
}
+ if (maxvif <= minvif) /* mf6cc_ifset is basically empty */
+ return -EINVAL;
+
line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
@@ -1422,7 +1421,10 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
if (found) {
write_lock_bh(&mrt_lock);
c->mf6c_parent = mfc->mf6cc_parent;
- ip6mr_update_thresholds(mrt, c, ttls);
+ c->mfc_un.res.mf6c_ifset = mfc->mf6cc_ifset;
+ c->mfc_un.res.minvif = minvif;
+ c->mfc_un.res.maxvif = maxvif;
+
if (!mrtsock)
c->mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock);
@@ -1440,7 +1442,10 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
c->mf6c_parent = mfc->mf6cc_parent;
- ip6mr_update_thresholds(mrt, c, ttls);
+ c->mfc_un.res.mf6c_ifset = mfc->mf6cc_ifset;
+ c->mfc_un.res.minvif = minvif;
+ c->mfc_un.res.maxvif = maxvif;
+
if (!mrtsock)
c->mfc_flags |= MFC_STATIC;
@@ -2036,7 +2041,7 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
large chunk of pimd to kernel. Ough... --ANK
*/
(mrt->mroute_do_pim ||
- cache->mfc_un.res.ttls[true_vifi] < 255) &&
+ IF_ISSET(true_vifi, &cache->mfc_un.res.mf6c_ifset)) &&
time_after(jiffies,
cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
cache->mfc_un.res.last_assert = jiffies;
@@ -2052,7 +2057,7 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
* Forward the frame
*/
for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
- if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
+ if (IF_ISSET(ct, &cache->mfc_un.res.mf6c_ifset)) {
if (psend != -1) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2)
@@ -2143,7 +2148,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
return -EMSGSIZE;
for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
- if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
+ if (MIF_EXISTS(mrt, ct) && IF_ISSET(ct, &c->mfc_un.res.mf6c_ifset)) {
nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
if (nhp == NULL) {
nla_nest_cancel(skb, mp_attr);
@@ -2151,7 +2156,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
}
nhp->rtnh_flags = 0;
- nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
+ nhp->rtnh_hops = 1; /* this is broken as IPv6 does not use TTL threshold */
nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
nhp->rtnh_len = sizeof(*nhp);
}
^ permalink raw reply related
* Re: [RFC][PATCH] ipv6 multicast forwarding: Remove threshold checking and some trivial bugs
From: David Miller @ 2012-12-18 5:03 UTC (permalink / raw)
To: wcang; +Cc: netdev, yoshfuji
In-Reply-To: <50CFF7A7.1070508@sfc.wide.ad.jp>
From: Ang Way Chuang <wcang@sfc.wide.ad.jp>
Date: Tue, 18 Dec 2012 12:57:11 +0800
> This patch fixes trivial bugs for IPv6 multicast forwarding code and remove
> threshold checking for multicast forwarding cache.
>
> 1. Threshold checking in IPv6 multicast forwarding cache (MFC) was not properly implemented.
> syscall to setsockopt(... MRT6_ADD_MIF,...) doesn't affect the TTL because it is never used.
> In fact, all MFC will always have ttl of 1 as set by ip6mr_mfc_add. From my limited knowledge of
> multicast routing, threshold setting on interface is only used by DVMRP which doesn't support
> IPv6. FreeBSD's struct mif6ctl doesn't have vifc_threshold. This patch removes the ttl cruft
> within kernel. Userspace ABI for backward compatibility. Can someone knowledgable in multicast
> routing please verify whether my understanding is correct?
> 2. Don't allow addition of MFC with non-existent multicast interface index.
> 3. Don't allow addition of MFC where incoming interface is part of oif list. This does not make
> sense. Why would we want to send a multicast back to the interface where it originates from.
> 4. setsockopt(....MRT6_ADD_MIF, ) allows a "physical" interface to be registered as multicast
> interface multiple times. This doesn't make sense. Don't allow registration duplicate
> registration of the same "physical" interface.
>
> This patch has been tested, albeit minimally using a simple program. Is this patch okay for
> inclusion? Will sign off if it is okay.
How about we don't mix together a set of bug fixes, with a semantic
change (the removal of the threshold checking)?
I also don't see what the point is of not signing off on this change
when you submit it.
If you delay the signoff until after review, you're just causing it to
take longer to have your changes integrated. It also makes it look
like you didn't believe fully in your change, so you probably should
have sent it as an RFC and listed your doubts in the email instead.
Overall I would rate this as an extremely poor patch submission,
sorry.
^ permalink raw reply
* Re: [RFC][PATCH] ipv6 multicast forwarding: Remove threshold checking and some trivial bugs
From: Ang Way Chuang @ 2012-12-18 5:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev, yoshfuji
In-Reply-To: <20121217.210333.1952508082741483861.davem@davemloft.net>
Oops, sorry. You're right. I am not very confident with this modification. It may break some multicast
routing daemon. Let's drop this for now.
On 18/12/2012 13:03, David Miller wrote:
> From: Ang Way Chuang <wcang@sfc.wide.ad.jp>
> Date: Tue, 18 Dec 2012 12:57:11 +0800
>
>> This patch fixes trivial bugs for IPv6 multicast forwarding code and remove
>> threshold checking for multicast forwarding cache.
>>
>> 1. Threshold checking in IPv6 multicast forwarding cache (MFC) was not properly implemented.
>> syscall to setsockopt(... MRT6_ADD_MIF,...) doesn't affect the TTL because it is never used.
>> In fact, all MFC will always have ttl of 1 as set by ip6mr_mfc_add. From my limited knowledge of
>> multicast routing, threshold setting on interface is only used by DVMRP which doesn't support
>> IPv6. FreeBSD's struct mif6ctl doesn't have vifc_threshold. This patch removes the ttl cruft
>> within kernel. Userspace ABI for backward compatibility. Can someone knowledgable in multicast
>> routing please verify whether my understanding is correct?
>> 2. Don't allow addition of MFC with non-existent multicast interface index.
>> 3. Don't allow addition of MFC where incoming interface is part of oif list. This does not make
>> sense. Why would we want to send a multicast back to the interface where it originates from.
>> 4. setsockopt(....MRT6_ADD_MIF, ) allows a "physical" interface to be registered as multicast
>> interface multiple times. This doesn't make sense. Don't allow registration duplicate
>> registration of the same "physical" interface.
>>
>> This patch has been tested, albeit minimally using a simple program. Is this patch okay for
>> inclusion? Will sign off if it is okay.
>
> How about we don't mix together a set of bug fixes, with a semantic
> change (the removal of the threshold checking)?
>
> I also don't see what the point is of not signing off on this change
> when you submit it.
>
> If you delay the signoff until after review, you're just causing it to
> take longer to have your changes integrated. It also makes it look
> like you didn't believe fully in your change, so you probably should
> have sent it as an RFC and listed your doubts in the email instead.
>
> Overall I would rate this as an extremely poor patch submission,
> sorry.
> --
> 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 1/2] be2net: fix be_close() to ensure all events are ack'ed
From: Sathya Perla @ 2012-12-18 5:38 UTC (permalink / raw)
To: netdev; +Cc: Sathya Perla
In be_close(), be_eq_clean() must be called after all RX/TX/MCC queues
have been cleaned to ensure that any events caused while cleaning up
completions are notified/acked. Not clearing all events can cause
upredictable behaviour when RX rings are re-created in the subsequent
be_open().
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be_cmds.c | 5 +++++
drivers/net/ethernet/emulex/benet/be_main.c | 21 ++++++++++++---------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index f2875aa..8a250c3 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -298,7 +298,12 @@ void be_async_mcc_enable(struct be_adapter *adapter)
void be_async_mcc_disable(struct be_adapter *adapter)
{
+ spin_lock_bh(&adapter->mcc_cq_lock);
+
adapter->mcc_obj.rearm_cq = false;
+ be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
+
+ spin_unlock_bh(&adapter->mcc_cq_lock);
}
int be_process_mcc(struct be_adapter *adapter)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index f95612b..bf50e73 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2398,13 +2398,22 @@ static int be_close(struct net_device *netdev)
be_roce_dev_close(adapter);
- be_async_mcc_disable(adapter);
-
if (!lancer_chip(adapter))
be_intr_set(adapter, false);
- for_all_evt_queues(adapter, eqo, i) {
+ for_all_evt_queues(adapter, eqo, i)
napi_disable(&eqo->napi);
+
+ be_async_mcc_disable(adapter);
+
+ /* Wait for all pending tx completions to arrive so that
+ * all tx skbs are freed.
+ */
+ be_tx_compl_clean(adapter);
+
+ be_rx_qs_destroy(adapter);
+
+ for_all_evt_queues(adapter, eqo, i) {
if (msix_enabled(adapter))
synchronize_irq(be_msix_vec_get(adapter, eqo));
else
@@ -2414,12 +2423,6 @@ static int be_close(struct net_device *netdev)
be_irq_unregister(adapter);
- /* Wait for all pending tx completions to arrive so that
- * all tx skbs are freed.
- */
- be_tx_compl_clean(adapter);
-
- be_rx_qs_destroy(adapter);
return 0;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] be2net: fix wrong frag_idx reported by RX CQ
From: Sathya Perla @ 2012-12-18 5:38 UTC (permalink / raw)
To: netdev; +Cc: Sathya Perla
In-Reply-To: <1355809131-8924-1-git-send-email-sathya.perla@emulex.com>
The RX CQ can report completions with invalid frag_idx when the RXQ that
was *previously* using it, was not cleaned up properly. This hits
a BUG_ON() in be2net.
When completion coalescing is enabled on a CQ, an explicit CQ-notify
(with rearm) is needed for each compl, to flush partially coalesced CQ
entries that are pending DMA.
In be_close(), this fix now notifies CQ for each compl, waits explicitly
for the flush compl to arrive and complains if it doesn't arrive.
Also renaming be_crit_error() to be_hw_error() as it's the more
appropriate name and to convey that we don't wait for the flush compl
only when a HW error has occurred.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be.h | 2 +-
drivers/net/ethernet/emulex/benet/be_main.c | 38 ++++++++++++++++++++++----
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index abf26c7..3bc1912 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -616,7 +616,7 @@ static inline bool be_error(struct be_adapter *adapter)
return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout;
}
-static inline bool be_crit_error(struct be_adapter *adapter)
+static inline bool be_hw_error(struct be_adapter *adapter)
{
return adapter->eeh_error || adapter->hw_error;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index bf50e73..9dca22b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1689,15 +1689,41 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
struct be_queue_info *rxq = &rxo->q;
struct be_queue_info *rx_cq = &rxo->cq;
struct be_rx_compl_info *rxcp;
+ struct be_adapter *adapter = rxo->adapter;
+ int flush_wait = 0;
u16 tail;
- /* First cleanup pending rx completions */
- while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
- be_rx_compl_discard(rxo, rxcp);
- be_cq_notify(rxo->adapter, rx_cq->id, false, 1);
+ /* Consume pending rx completions.
+ * Wait for the flush completion (identified by zero num_rcvd)
+ * to arrive. Notify CQ even when there are no more CQ entries
+ * for HW to flush partially coalesced CQ entries.
+ * In Lancer, there is no need to wait for flush compl.
+ */
+ for (;;) {
+ rxcp = be_rx_compl_get(rxo);
+ if (rxcp == NULL) {
+ if (lancer_chip(adapter))
+ break;
+
+ if (flush_wait++ > 10 || be_hw_error(adapter)) {
+ dev_warn(&adapter->pdev->dev,
+ "did not receive flush compl\n");
+ break;
+ }
+ be_cq_notify(adapter, rx_cq->id, true, 0);
+ mdelay(1);
+ } else {
+ be_rx_compl_discard(rxo, rxcp);
+ be_cq_notify(adapter, rx_cq->id, true, 1);
+ if (rxcp->num_rcvd == 0)
+ break;
+ }
}
- /* Then free posted rx buffer that were not used */
+ /* After cleanup, leave the CQ in unarmed state */
+ be_cq_notify(adapter, rx_cq->id, false, 0);
+
+ /* Then free posted rx buffers that were not used */
tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
page_info = get_rx_page_info(rxo, tail);
@@ -2157,7 +2183,7 @@ void be_detect_error(struct be_adapter *adapter)
u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
u32 i;
- if (be_crit_error(adapter))
+ if (be_hw_error(adapter))
return;
if (lancer_chip(adapter)) {
--
1.7.1
^ permalink raw reply related
* Re: [patch net-next 0/4] net: allow to change carrier from userspace
From: Stephen Hemminger @ 2012-12-18 6:49 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, bhutchings, mirqus, greearb, fbl
In-Reply-To: <20121216105451.GA1546@minipsycho.orion>
On Sun, 16 Dec 2012 11:54:51 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
>
> I see that the patchset is in state "Rejected" in patchwork.
> Stephen convinced me for a moment that the problem can be handled by operstate.
> As it turned out (in last 3-4 emails in thread) operstate use would not
> be an option.
>
> So how should I proceed? Should I repost the patchset? Anyone has any other
> comments?
>
> thanks.
Don't take my comments so far as negative. Devices to need to be more controllable
from userspace. But I have concerns about introducing a new way to change state causing
more races. For example, changing carrier state should cause netlink events to fire and
these should post to routing daemons etc. Also, what happens if some confused developer
mixes operstate and direct carrier control.
The root cause of all this confusion is that their are three ways of expressing
the same state, and they are controlled through different paths:
a. Old BSD style flag bit IFF_RUNNING
b. LINK_STATE bit in kernel (netif_carrier_ok)
c. RFC2863 operational state
The operstate stuff is the most complete, but is the weakest in implementation:
a. kernel drivers check netif_carrier_ok when they should be using netif_dormant
(bridge is one example). But what will break if this changes?
b. lower device state is not tracked correctly by tunnels and a few other layered devices
c. dormant from kernel space was never used by much.
The good news is that the old BSD style IFF_RUNNING bit is the most commonly
used bit by applications and it works correctly in either carrier or operstate mode.
^ permalink raw reply
* Re: [PATCH 4/4] FEC: Add time stamping code and a PTP hardware clock
From: Richard Cochran @ 2012-12-18 7:04 UTC (permalink / raw)
To: Sascha Hauer
Cc: Frank Li, netdev, lznua, Frank Li, Shawn Guo, davem,
linux-arm-kernel
In-Reply-To: <20121217200232.GS26326@pengutronix.de>
On Mon, Dec 17, 2012 at 09:02:32PM +0100, Sascha Hauer wrote:
> This leaves an option in the tree which can be used to break FEC on
> i.MX3/5.
>
> depends on !SOC_IMX31 && !SOC_IMX35 && !SOC_IMX5
>
> might be an option, but given that this patch seems to have bypassed any
> review I feel more like reverting it.
Instead of reverting, I suggest finding a solution (Frank) to let the
code work when it can work and to prevent it when it cannot. This
could be kconfig, DT, or run time probing of silicon revisions, but I
don't have access to this hardware, and so I can't really say how to
fix it.
Just for the record, I did in fact review this patch, and I commented
on exactly this point. Frank said we would address this point, and he
did so. Not knowing the imx family very well, I took his word for it.
After all, Frank has a Freescale address, and I would expect a
Freescale employee to know how to provide the right fix.
Thanks,
Richard
^ permalink raw reply
* [PATCH net-next] xfrm: removes a superfluous check and add a statistic
From: roy.qing.li @ 2012-12-18 8:39 UTC (permalink / raw)
To: netdev
From: Li RongQing <roy.qing.li@gmail.com>
Remove the check if x->km.state equal to XFRM_STATE_VALID in
xfrm_state_check_expire(), which will be done before call
xfrm_state_check_expire().
add a LINUX_MIB_XFRMOUTSTATEINVALID statistic to record the
outbound error due to invalid xfrm state.
Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
---
include/uapi/linux/snmp.h | 1 +
net/xfrm/xfrm_output.c | 6 ++++++
net/xfrm/xfrm_proc.c | 1 +
net/xfrm/xfrm_state.c | 3 ---
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index fdfba23..93b24ce 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -274,6 +274,7 @@ enum
LINUX_MIB_XFRMOUTSTATEMODEERROR, /* XfrmOutStateModeError */
LINUX_MIB_XFRMOUTSTATESEQERROR, /* XfrmOutStateSeqError */
LINUX_MIB_XFRMOUTSTATEEXPIRED, /* XfrmOutStateExpired */
+ LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */
LINUX_MIB_XFRMOUTPOLBLOCK, /* XfrmOutPolBlock */
LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */
LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 95a338c..3670526 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -61,6 +61,12 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
}
spin_lock_bh(&x->lock);
+
+ if (unlikely(x->km.state != XFRM_STATE_VALID)) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID);
+ goto error_nolock;
+ }
+
err = xfrm_state_check_expire(x);
if (err) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED);
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c
index d0a1af8..e4cd441 100644
--- a/net/xfrm/xfrm_proc.c
+++ b/net/xfrm/xfrm_proc.c
@@ -39,6 +39,7 @@ static const struct snmp_mib xfrm_mib_list[] = {
SNMP_MIB_ITEM("XfrmOutStateModeError", LINUX_MIB_XFRMOUTSTATEMODEERROR),
SNMP_MIB_ITEM("XfrmOutStateSeqError", LINUX_MIB_XFRMOUTSTATESEQERROR),
SNMP_MIB_ITEM("XfrmOutStateExpired", LINUX_MIB_XFRMOUTSTATEEXPIRED),
+ SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID),
SNMP_MIB_ITEM("XfrmOutPolBlock", LINUX_MIB_XFRMOUTPOLBLOCK),
SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD),
SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR),
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3459692..05db236 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1370,9 +1370,6 @@ int xfrm_state_check_expire(struct xfrm_state *x)
if (!x->curlft.use_time)
x->curlft.use_time = get_seconds();
- if (x->km.state != XFRM_STATE_VALID)
- return -EINVAL;
-
if (x->curlft.bytes >= x->lft.hard_byte_limit ||
x->curlft.packets >= x->lft.hard_packet_limit) {
x->km.state = XFRM_STATE_EXPIRED;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 4/4] FEC: Add time stamping code and a PTP hardware clock
From: Frank Li @ 2012-12-18 8:51 UTC (permalink / raw)
To: Richard Cochran
Cc: Sascha Hauer, Shawn Guo, Frank Li, lznua, linux-arm-kernel,
netdev, davem
In-Reply-To: <20121218070420.GA2946@netboy.at.omicron.at>
>>
>> might be an option, but given that this patch seems to have bypassed any
>> review I feel more like reverting it.
>
> Instead of reverting, I suggest finding a solution (Frank) to let the
> code work when it can work and to prevent it when it cannot. This
> could be kconfig, DT, or run time probing of silicon revisions, but I
> don't have access to this hardware, and so I can't really say how to
> fix it.
I am traveling in this week. I will try to find out the solution after
come back office
in next week. But quick solution is shawn's patch, which resolve mx3
and mx5 problem at least in short term.
>
> Just for the record, I did in fact review this patch, and I commented
> on exactly this point. Frank said we would address this point, and he
> did so. Not knowing the imx family very well, I took his word for it.
> After all, Frank has a Freescale address, and I would expect a
> Freescale employee to know how to provide the right fix.
>
> Thanks,
> Richard
^ permalink raw reply
* RE: [PATCH v2] netlink: align attributes on 64-bits
From: David Laight @ 2012-12-18 9:19 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: bhutchings, tgraf, netdev, davem
In-Reply-To: <50CF57DC.5050804@6wind.com>
> Le 17/12/2012 18:06, David Laight a écrit :
> >> int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
> >> {
> >> - if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
> >> + int align = IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8) ? 0 : 4;
> >
> > I've just realised where you are adding this!
> > You only want to add pad if the attribute is a single 64bit item,
> > not whenever the destination is misaligned.
> As said in the commit log, I want to align all attributes. An attribute can be
> like this:
>
> struct foo {
> __u32 bar1;
> __u32 bar2;
> __u64 bar3;
> }
>
> nla_put() don't know what is contained in the attribute.
Put there is no need to 8-byte align something whose size isn't a
multiple of 8 bytes.
> > ...
> >> + if (align) {
> >> + /* Goal is to add an attribute with size 4. We know that
> >> + * NLA_HDRLEN is 4, hence payload is 0.
> >> + */
> >> + __nla_reserve(skb, 0, 0);
> >
> > One of those zeros should be 'align - 4', then the comment
> > can be more descriptive.
> I thought if you were to research why we use 0, you would know that the first 0
> is the type and the second is the payload size...
I can tell that one is the type and the other the size, you've
implied that the 'type+size' actually total 4 bytes.
I don't need to find out which is which!
Now you've told me I'd have written:
_nla_reserve(skb, 0, align - NLA_HDRLEN);
The compiler could well have tracked the value - so know it is 4.
OTOH you might want to generate the size of 'align' without
using a conditional.
David
^ permalink raw reply
* Re: [patch net-next 0/4] net: allow to change carrier from userspace
From: Jiri Pirko @ 2012-12-18 9:31 UTC (permalink / raw)
To: Stephen Hemminger
Cc: netdev, davem, edumazet, bhutchings, mirqus, greearb, fbl
In-Reply-To: <20121217224957.70775f99@nehalam.linuxnetplumber.net>
Tue, Dec 18, 2012 at 07:49:57AM CET, shemminger@vyatta.com wrote:
>On Sun, 16 Dec 2012 11:54:51 +0100
>Jiri Pirko <jiri@resnulli.us> wrote:
>
>>
>> I see that the patchset is in state "Rejected" in patchwork.
>> Stephen convinced me for a moment that the problem can be handled by operstate.
>> As it turned out (in last 3-4 emails in thread) operstate use would not
>> be an option.
>>
>> So how should I proceed? Should I repost the patchset? Anyone has any other
>> comments?
>>
>> thanks.
>
>Don't take my comments so far as negative. Devices to need to be more controllable
>from userspace. But I have concerns about introducing a new way to change state causing
>more races. For example, changing carrier state should cause netlink events to fire and
>these should post to routing daemons etc. Also, what happens if some confused developer
>mixes operstate and direct carrier control.
I do not think that the race you are describing is of any concern. The
same can happen now for any device. My patchset only adds a possibility
for "soft devices" to change the carrier as well.
Developer will not be likely confused. As the possibility of carrier
change from userspace will be limited to small set of devices, for other
devices the attempt will lead to -EOPNOTSUPP (in contrast with operstate
which is available for all devices).
I can add a comments/notes to code and operstates.txt stating the
purpose of this iface.
>
>The root cause of all this confusion is that their are three ways of expressing
>the same state, and they are controlled through different paths:
> a. Old BSD style flag bit IFF_RUNNING
> b. LINK_STATE bit in kernel (netif_carrier_ok)
> c. RFC2863 operational state
I do not think so. Yes, for a) and c), these are strictly connected,
expressing the same thing. But b) is not the same. It's on lower level
than a) and c). What b) can be compared to is IFF_LOWER_UP.
>
>The operstate stuff is the most complete, but is the weakest in implementation:
> a. kernel drivers check netif_carrier_ok when they should be using netif_dormant
> (bridge is one example). But what will break if this changes?
I agree, that should be changed.
> b. lower device state is not tracked correctly by tunnels and a few other layered devices
> c. dormant from kernel space was never used by much.
>
>The good news is that the old BSD style IFF_RUNNING bit is the most commonly
>used bit by applications and it works correctly in either carrier or operstate mode.
That is indeed a good thing.
^ permalink raw reply
* [PATCH] ethtool: add register dump support for SMSC LAN9420
From: Steve Glendinning @ 2012-12-18 9:34 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, Steve Glendinning
This patch adds support for SMSC's LAN9420 PCI ethernet controller
to ethtool's dump registers (-d) command.
This patch is for use with the smsc9420 driver.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
Makefile.am | 2 +-
ethtool.c | 2 ++
internal.h | 3 ++
smsc9420.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 smsc9420.c
diff --git a/Makefile.am b/Makefile.am
index ba1faa6..728be0a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@ ethtool_SOURCES = ethtool.c ethtool-copy.h internal.h net_tstamp-copy.h \
fec_8xx.c ibm_emac.c ixgb.c ixgbe.c natsemi.c \
pcnet32.c realtek.c tg3.c marvell.c vioc.c \
smsc911x.c at76c50x-usb.c sfc.c stmmac.c \
- rxclass.c sfpid.c sfpdiag.c
+ rxclass.c sfpid.c sfpdiag.c smsc9420.c
TESTS = test-cmdline test-features
check_PROGRAMS = test-cmdline test-features
diff --git a/ethtool.c b/ethtool.c
index 345c21c..97c3d76 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -15,6 +15,7 @@
* amd8111e support by Reeja John <reeja.john@amd.com>
* long arguments by Andi Kleen.
* SMSC LAN911x support by Steve Glendinning <steve.glendinning@smsc.com>
+ * SMSC LAN9420 support by Steve Glendinning <steve.glendinning@shawell.net>
* Rx Network Flow Control configuration support <santwona.behera@sun.com>
* Various features by Ben Hutchings <bhutchings@solarflare.com>;
* Copyright 2009, 2010 Solarflare Communications
@@ -884,6 +885,7 @@ static const struct {
{ "sky2", sky2_dump_regs },
{ "vioc", vioc_dump_regs },
{ "smsc911x", smsc911x_dump_regs },
+ { "smsc9420", smsc9420_dump_regs },
{ "at76c50x-usb", at76c50x_usb_dump_regs },
{ "sfc", sfc_dump_regs },
{ "st_mac100", st_mac100_dump_regs },
diff --git a/internal.h b/internal.h
index e977a81..8873cd1 100644
--- a/internal.h
+++ b/internal.h
@@ -228,6 +228,9 @@ int vioc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
/* SMSC LAN911x/LAN921x embedded ethernet controller */
int smsc911x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+/* SMSC LAN9420 PCI ethernet controller */
+int smsc9420_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+
int at76c50x_usb_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
/* Solarflare Solarstorm controllers */
diff --git a/smsc9420.c b/smsc9420.c
new file mode 100644
index 0000000..b6a24a0
--- /dev/null
+++ b/smsc9420.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <string.h>
+#include "internal.h"
+
+int smsc9420_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+{
+ unsigned int *smsc_reg = (unsigned int *)regs->data;
+
+ fprintf(stdout, "LAN9420 DMAC Control & Status Registers\n");
+ fprintf(stdout, "offset 0x00, BUS_MODE = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x04, TX_POLL_DEMAND = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x08, TX_POLL_DEMAND = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x0C, RX_BASE_ADDR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x10, TX_BASE_ADDR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x14, DMAC_STATUS = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x18, DMAC_CONTROL = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x1C, DMAC_INTR_ENA = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x20, MISS_FRAME_CNT = 0x%08X\n",*smsc_reg++);
+ smsc_reg += 11; /* 0x24 - 0x4C RESERVED */
+ fprintf(stdout, "offset 0x50, CUR_TX_BUF_ADDR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x54, CUR_RX_BUF_ADDR = 0x%08X\n",*smsc_reg++);
+ smsc_reg += 10; /* 0x58 - 0x7C RESERVED */
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "LAN9420 MAC Control & Status Registers\n");
+ fprintf(stdout, "offset 0x80, MAC_CR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x84, ADDRH = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x88, ADDRL = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x8C, HASHH = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x90, HASHL = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x94, MIIADDR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x98, MIIDATA = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0x9C, FLOW = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xA0, VLAN1 = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xA4, VLAN2 = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xA8, WUFF = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xAC, WUCSR = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xB0, COE_CR = 0x%08X\n",*smsc_reg++);
+ smsc_reg += 3; /* 0xB4 - 0xBC RESERVED */
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "LAN9420 System Control & Status Registers\n");
+ fprintf(stdout, "offset 0xC0, ID_REV = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xC4, INT_CTL = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xC8, INT_STS = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xCC, INT_CFG = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xD0, GPIO_CFG = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xD4, GPT_CFG = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xD8, GPT_CNT = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xDC, BUS_CFG = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xE0, PMT_CTRL = 0x%08X\n",*smsc_reg++);
+ smsc_reg += 4; /* 0xE4 - 0xF0 RESERVED */
+ fprintf(stdout, "offset 0xF4, FREE_RUN = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xF8, E2P_CMD = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "offset 0xFC, E2P_DATA = 0x%08X\n",*smsc_reg++);
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "PHY Registers\n");
+ fprintf(stdout, "index 0, Basic Control Reg = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 1, Basic Status Reg = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 2, PHY identifier 1 = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 3, PHY identifier 2 = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 4, Auto Negotiation Advertisement Reg = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 5, Auto Negotiation Link Partner Ability Reg = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 6, Auto Negotiation Expansion Register = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 7, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 8, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 9, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 10, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 11, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 12, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 13, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 14, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 15, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 16, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 17, Mode Control/Status Reg = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 18, Special Modes = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 19, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 20, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 21, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 22, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 23, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 24, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 25, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 26, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 27, Control/Status Indication = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 28, Reserved = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 29, Interrupt Source Register = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 30, Interrupt Mask Register = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "index 31, PHY Special Control/Status Register = 0x%04X\n",*smsc_reg++);
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/2] smsc95xx enhancements
From: Steve Glendinning @ 2012-12-18 10:46 UTC (permalink / raw)
To: netdev; +Cc: ming.lei, oneukum, gregkh, Steve Glendinning
Two driver enhancements for net-next. There's ongoing discussion around
the best way to improve autosuspend moving forwards but in the meantime
the second patch in this set enables autosuspend for supported parts in
most situations.
Steve Glendinning (2):
smsc95xx: eliminate duplicate warnings on io failure
smsc95xx: enable dynamic autosuspend
drivers/net/usb/smsc95xx.c | 435 ++++++++++++++++++++++----------------------
1 file changed, 217 insertions(+), 218 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH 1/2] smsc95xx: eliminate duplicate warnings on io failure
From: Steve Glendinning @ 2012-12-18 10:46 UTC (permalink / raw)
To: netdev; +Cc: ming.lei, oneukum, gregkh, Steve Glendinning, Joe Perches
In-Reply-To: <1355827574-15164-1-git-send-email-steve.glendinning@shawell.net>
The register read/write functions already log a warning if
an access fails, so this patch removes the additional warnings
logged by callers that don't add any more information.
This patch makes the resulting driver smaller by not containing
as many warning strings.
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc95xx.c | 284 +++++++++++---------------------------------
1 file changed, 67 insertions(+), 217 deletions(-)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 9b73670..124e67f 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -513,10 +513,8 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
u32 flow, afc_cfg = 0;
int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading AFC_CFG\n");
+ if (ret < 0)
return ret;
- }
if (duplex == DUPLEX_FULL) {
u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
@@ -541,16 +539,10 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
}
ret = smsc95xx_write_reg(dev, FLOW, flow);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing FLOW\n");
- return ret;
- }
-
- ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
if (ret < 0)
- netdev_warn(dev->net, "Error writing AFC_CFG\n");
+ return ret;
- return ret;
+ return smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
}
static int smsc95xx_link_reset(struct usbnet *dev)
@@ -564,16 +556,12 @@ static int smsc95xx_link_reset(struct usbnet *dev)
/* clear interrupt status */
ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing INT_STS\n");
+ if (ret < 0)
return ret;
- }
mii_check_media(mii, 1, 1);
mii_ethtool_gset(&dev->mii, &ecmd);
@@ -595,10 +583,8 @@ static int smsc95xx_link_reset(struct usbnet *dev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing MAC_CR\n");
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
if (ret < 0)
@@ -638,10 +624,8 @@ static int smsc95xx_set_features(struct net_device *netdev,
int ret;
ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret);
+ if (ret < 0)
return ret;
- }
if (features & NETIF_F_HW_CSUM)
read_buf |= Tx_COE_EN_;
@@ -654,10 +638,8 @@ static int smsc95xx_set_features(struct net_device *netdev,
read_buf &= ~Rx_COE_EN_;
ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
return 0;
@@ -800,16 +782,10 @@ static int smsc95xx_set_mac_address(struct usbnet *dev)
int ret;
ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);
- return ret;
- }
-
- ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
if (ret < 0)
- netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret);
+ return ret;
- return ret;
+ return smsc95xx_write_reg(dev, ADDRH, addr_hi);
}
/* starts the TX path */
@@ -825,17 +801,11 @@ static int smsc95xx_start_tx_path(struct usbnet *dev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* Enable Tx at SCSRs */
- ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
- if (ret < 0)
- netdev_warn(dev->net, "Failed to write TX_CFG: %d\n", ret);
-
- return ret;
+ return smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
}
/* Starts the Receive path */
@@ -843,17 +813,12 @@ static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
unsigned long flags;
- int ret;
spin_lock_irqsave(&pdata->mac_cr_lock, flags);
pdata->mac_cr |= MAC_CR_RXEN_;
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
- ret = __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
- if (ret < 0)
- netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
-
- return ret;
+ return __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
}
static int smsc95xx_phy_initialize(struct usbnet *dev)
@@ -910,19 +875,15 @@ static int smsc95xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
+ if (ret < 0)
return ret;
- }
timeout = 0;
do {
msleep(10);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
timeout++;
} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
@@ -932,19 +893,15 @@ static int smsc95xx_reset(struct usbnet *dev)
}
ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret);
+ if (ret < 0)
return ret;
- }
timeout = 0;
do {
msleep(10);
ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret);
+ if (ret < 0)
return ret;
- }
timeout++;
} while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
@@ -961,10 +918,8 @@ static int smsc95xx_reset(struct usbnet *dev)
dev->net->dev_addr);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
read_buf);
@@ -972,16 +927,12 @@ static int smsc95xx_reset(struct usbnet *dev)
read_buf |= HW_CFG_BIR_;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
@@ -1002,42 +953,32 @@ static int smsc95xx_reset(struct usbnet *dev)
(ulong)dev->rx_urb_size);
ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net,
"Read Value from BURST_CAP after writing: 0x%08x\n",
read_buf);
ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net,
"Read Value from BULK_IN_DLY after writing: 0x%08x\n",
read_buf);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n",
read_buf);
@@ -1051,69 +992,51 @@ static int smsc95xx_reset(struct usbnet *dev)
read_buf |= NET_IP_ALIGN << 9;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+ if (ret < 0)
return ret;
- }
netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
/* Configure GPIO pins as LED outputs */
write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
LED_GPIO_CFG_FDX_LED;
ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* Init Tx */
ret = smsc95xx_write_reg(dev, FLOW, 0);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* Don't need mac_cr_lock during initialisation */
ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* Init Rx */
/* Set Vlan */
ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write VLAN1: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* Enable or disable checksum offload engines */
ret = smsc95xx_set_features(dev->net, dev->net->features);
@@ -1131,19 +1054,15 @@ static int smsc95xx_reset(struct usbnet *dev)
}
ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
+ if (ret < 0)
return ret;
- }
/* enable PHY interrupts */
read_buf |= INT_EP_CTL_PHY_INT_;
ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_start_tx_path(dev);
if (ret < 0) {
@@ -1213,10 +1132,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
/* detect device revision as different features may be available */
ret = smsc95xx_read_reg(dev, ID_REV, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+ if (ret < 0)
return ret;
- }
val >>= 16;
if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
@@ -1261,17 +1178,13 @@ static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
/* read to clear */
ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ if (ret < 0)
return ret;
- }
/* enable interrupt source */
ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
+ if (ret < 0)
return ret;
- }
ret |= mask;
@@ -1287,16 +1200,12 @@ static int smsc95xx_link_ok_nopm(struct usbnet *dev)
/* first, a dummy read, needed to latch some MII phys */
ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ if (ret < 0)
return ret;
- }
return !!(ret & BMSR_LSTATUS);
}
@@ -1308,19 +1217,15 @@ static int smsc95xx_enter_suspend0(struct usbnet *dev)
int ret;
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
val |= PM_CTL_SUS_MODE_0;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
/* clear wol status */
val &= ~PM_CTL_WUPS_;
@@ -1331,15 +1236,11 @@ static int smsc95xx_enter_suspend0(struct usbnet *dev)
val |= PM_CTL_WUPS_ED_;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
/* read back PM_CTRL */
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0)
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
return ret;
}
@@ -1360,10 +1261,8 @@ static int smsc95xx_enter_suspend1(struct usbnet *dev)
/* enable energy detect power-down mode */
ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
+ if (ret < 0)
return ret;
- }
ret |= MODE_CTRL_STS_EDPWRDOWN_;
@@ -1371,27 +1270,21 @@ static int smsc95xx_enter_suspend1(struct usbnet *dev)
/* enter SUSPEND1 mode */
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
val |= PM_CTL_SUS_MODE_1;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
/* clear wol status, enable energy detection */
val &= ~PM_CTL_WUPS_;
val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0)
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
return ret;
}
@@ -1402,17 +1295,13 @@ static int smsc95xx_enter_suspend2(struct usbnet *dev)
int ret;
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
val |= PM_CTL_SUS_MODE_2;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0)
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
return ret;
}
@@ -1442,32 +1331,24 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
/* disable energy detect (link up) & wake up events */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading WUCSR\n");
+ if (ret < 0)
goto done;
- }
val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUCSR\n");
+ if (ret < 0)
goto done;
- }
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
goto done;
- }
val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
goto done;
- }
ret = smsc95xx_enter_suspend2(dev);
goto done;
@@ -1565,7 +1446,6 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
for (i = 0; i < (wuff_filter_count * 4); i++) {
ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUFF\n");
kfree(filter_mask);
goto done;
}
@@ -1574,67 +1454,51 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
for (i = 0; i < (wuff_filter_count / 4); i++) {
ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUFF\n");
+ if (ret < 0)
goto done;
- }
}
for (i = 0; i < (wuff_filter_count / 4); i++) {
ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUFF\n");
+ if (ret < 0)
goto done;
- }
}
for (i = 0; i < (wuff_filter_count / 2); i++) {
ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUFF\n");
+ if (ret < 0)
goto done;
- }
}
/* clear any pending pattern match packet status */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading WUCSR\n");
+ if (ret < 0)
goto done;
- }
val |= WUCSR_WUFR_;
ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUCSR\n");
+ if (ret < 0)
goto done;
- }
}
if (pdata->wolopts & WAKE_MAGIC) {
/* clear any pending magic packet status */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading WUCSR\n");
+ if (ret < 0)
goto done;
- }
val |= WUCSR_MPR_;
ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUCSR\n");
+ if (ret < 0)
goto done;
- }
}
/* enable/disable wakeup sources */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading WUCSR\n");
+ if (ret < 0)
goto done;
- }
if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
netdev_info(dev->net, "enabling pattern match wakeup\n");
@@ -1653,17 +1517,13 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
}
ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUCSR\n");
+ if (ret < 0)
goto done;
- }
/* enable wol wakeup source */
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
goto done;
- }
val |= PM_CTL_WOL_EN_;
@@ -1672,10 +1532,8 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
val |= PM_CTL_ED_EN_;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
goto done;
- }
/* enable receiver to enable frame reception */
smsc95xx_start_rx_path(dev, 1);
@@ -1702,34 +1560,26 @@ static int smsc95xx_resume(struct usb_interface *intf)
if (pdata->wolopts) {
/* clear wake-up sources */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading WUCSR\n");
+ if (ret < 0)
return ret;
- }
val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing WUCSR\n");
+ if (ret < 0)
return ret;
- }
/* clear wake-up status */
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
val &= ~PM_CTL_WOL_EN_;
val |= PM_CTL_WUPS_;
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
- if (ret < 0) {
- netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ if (ret < 0)
return ret;
- }
}
ret = usbnet_resume(intf);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3 2/2] smsc95xx: enable dynamic autosuspend
From: Steve Glendinning @ 2012-12-18 10:46 UTC (permalink / raw)
To: netdev; +Cc: ming.lei, oneukum, gregkh, Steve Glendinning
In-Reply-To: <1355827574-15164-1-git-send-email-steve.glendinning@shawell.net>
This patch enables USB dynamic autosuspend for LAN9500A. This
saves very little power in itself, but it allows power saving
in upstream hubs/hosts.
The earlier devices in this family (LAN9500/9512/9514) do not
support this feature.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc95xx.c | 151 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 150 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 124e67f..6a74a68 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -55,6 +55,13 @@
#define FEATURE_PHY_NLP_CROSSOVER (0x02)
#define FEATURE_AUTOSUSPEND (0x04)
+#define SUSPEND_SUSPEND0 (0x01)
+#define SUSPEND_SUSPEND1 (0x02)
+#define SUSPEND_SUSPEND2 (0x04)
+#define SUSPEND_SUSPEND3 (0x08)
+#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
+
struct smsc95xx_priv {
u32 mac_cr;
u32 hash_hi;
@@ -62,6 +69,7 @@ struct smsc95xx_priv {
u32 wolopts;
spinlock_t mac_cr_lock;
u8 features;
+ u8 suspend_flags;
};
static bool turbo_mode = true;
@@ -1242,6 +1250,8 @@ static int smsc95xx_enter_suspend0(struct usbnet *dev)
/* read back PM_CTRL */
ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ pdata->suspend_flags |= SUSPEND_SUSPEND0;
+
return ret;
}
@@ -1286,11 +1296,14 @@ static int smsc95xx_enter_suspend1(struct usbnet *dev)
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ pdata->suspend_flags |= SUSPEND_SUSPEND1;
+
return ret;
}
static int smsc95xx_enter_suspend2(struct usbnet *dev)
{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
u32 val;
int ret;
@@ -1303,9 +1316,97 @@ static int smsc95xx_enter_suspend2(struct usbnet *dev)
ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ pdata->suspend_flags |= SUSPEND_SUSPEND2;
+
return ret;
}
+static int smsc95xx_enter_suspend3(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc95xx_read_reg_nopm(dev, RX_FIFO_INF, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val & 0xFFFF) {
+ netdev_info(dev->net, "rx fifo not empty in autosuspend\n");
+ return -EBUSY;
+ }
+
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0)
+ return ret;
+
+ val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+ val |= PM_CTL_SUS_MODE_3 | PM_CTL_RES_CLR_WKP_STS;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0)
+ return ret;
+
+ /* clear wol status */
+ val &= ~PM_CTL_WUPS_;
+ val |= PM_CTL_WUPS_WOL_;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0)
+ return ret;
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND3;
+
+ return 0;
+}
+
+static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ int ret;
+
+ if (!netif_running(dev->net)) {
+ /* interface is ifconfig down so fully power down hw */
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
+ return smsc95xx_enter_suspend2(dev);
+ }
+
+ if (!link_up) {
+ /* link is down so enter EDPD mode, but only if device can
+ * reliably resume from it. This check should be redundant
+ * as current FEATURE_AUTOSUSPEND parts also support
+ * FEATURE_PHY_NLP_CROSSOVER but it's included for clarity */
+ if (!(pdata->features & FEATURE_PHY_NLP_CROSSOVER)) {
+ netdev_warn(dev->net, "EDPD not supported\n");
+ return -EBUSY;
+ }
+
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+
+ /* enable PHY wakeup events for if cable is attached */
+ ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_ANEG_COMP_);
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ return ret;
+ }
+
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+ return smsc95xx_enter_suspend1(dev);
+ }
+
+ /* enable PHY wakeup events so we remote wakeup if cable is pulled */
+ ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_LINK_DOWN_);
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ return ret;
+ }
+
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+ return smsc95xx_enter_suspend3(dev);
+}
+
static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -1313,15 +1414,35 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
u32 val, link_up;
int ret;
+ /* TODO: don't indicate this feature to usb framework if
+ * our current hardware doesn't have the capability
+ */
+ if ((message.event == PM_EVENT_AUTO_SUSPEND) &&
+ (!(pdata->features & FEATURE_AUTOSUSPEND))) {
+ netdev_warn(dev->net, "autosuspend not supported\n");
+ return -EBUSY;
+ }
+
ret = usbnet_suspend(intf, message);
if (ret < 0) {
netdev_warn(dev->net, "usbnet_suspend error\n");
return ret;
}
+ if (pdata->suspend_flags) {
+ netdev_warn(dev->net, "error during last resume\n");
+ pdata->suspend_flags = 0;
+ }
+
/* determine if link is up using only _nopm functions */
link_up = smsc95xx_link_ok_nopm(dev);
+ if (message.event == PM_EVENT_AUTO_SUSPEND) {
+ ret = smsc95xx_autosuspend(dev, link_up);
+ goto done;
+ }
+
+ /* if we get this far we're not autosuspending */
/* if no wol options set, or if link is down and we're not waking on
* PHY activity, enter lowest power SUSPEND2 mode
*/
@@ -1552,12 +1673,18 @@ static int smsc95xx_resume(struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u8 suspend_flags = pdata->suspend_flags;
int ret;
u32 val;
BUG_ON(!dev);
- if (pdata->wolopts) {
+ netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
+
+ /* do this first to ensure it's cleared even in error case */
+ pdata->suspend_flags = 0;
+
+ if (suspend_flags & SUSPEND_ALLMODES) {
/* clear wake-up sources */
ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
if (ret < 0)
@@ -1741,6 +1868,26 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
return skb;
}
+static int smsc95xx_manage_power(struct usbnet *dev, int on)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ dev->intf->needs_remote_wakeup = on;
+
+ if (pdata->features & FEATURE_AUTOSUSPEND)
+ return 0;
+
+ /* this chip revision doesn't support autosuspend */
+ netdev_info(dev->net, "hardware doesn't support USB autosuspend\n");
+
+ if (on)
+ usb_autopm_get_interface_no_resume(dev->intf);
+ else
+ usb_autopm_put_interface(dev->intf);
+
+ return 0;
+}
+
static const struct driver_info smsc95xx_info = {
.description = "smsc95xx USB 2.0 Ethernet",
.bind = smsc95xx_bind,
@@ -1750,6 +1897,7 @@ static const struct driver_info smsc95xx_info = {
.rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status,
+ .manage_power = smsc95xx_manage_power,
.flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
@@ -1857,6 +2005,7 @@ static struct usb_driver smsc95xx_driver = {
.reset_resume = smsc95xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
+ .supports_autosuspend = 1,
};
module_usb_driver(smsc95xx_driver);
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v2] netlink: align attributes on 64-bits
From: Nicolas Dichtel @ 2012-12-18 10:18 UTC (permalink / raw)
To: David Laight; +Cc: bhutchings, tgraf, netdev, davem
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B70F2@saturn3.aculab.com>
Le 18/12/2012 10:19, David Laight a écrit :
>> Le 17/12/2012 18:06, David Laight a écrit :
>>>> int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
>>>> {
>>>> - if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
>>>> + int align = IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8) ? 0 : 4;
>>>
>>> I've just realised where you are adding this!
>>> You only want to add pad if the attribute is a single 64bit item,
>>> not whenever the destination is misaligned.
>> As said in the commit log, I want to align all attributes. An attribute can be
>> like this:
>>
>> struct foo {
>> __u32 bar1;
>> __u32 bar2;
>> __u64 bar3;
>> }
>>
>> nla_put() don't know what is contained in the attribute.
>
> Put there is no need to 8-byte align something whose size isn't a
> multiple of 8 bytes.
Even if you cast the structure in a buffer and read bar3 (without any memcpy
before)?
>
>>> ...
>>>> + if (align) {
>>>> + /* Goal is to add an attribute with size 4. We know that
>>>> + * NLA_HDRLEN is 4, hence payload is 0.
>>>> + */
>>>> + __nla_reserve(skb, 0, 0);
>>>
>>> One of those zeros should be 'align - 4', then the comment
>>> can be more descriptive.
>
>> I thought if you were to research why we use 0, you would know that the first 0
>> is the type and the second is the payload size...
>
> I can tell that one is the type and the other the size, you've
> implied that the 'type+size' actually total 4 bytes.
> I don't need to find out which is which!
> Now you've told me I'd have written:
> _nla_reserve(skb, 0, align - NLA_HDRLEN);
>
> The compiler could well have tracked the value - so know it is 4.
> OTOH you might want to generate the size of 'align' without
> using a conditional.
Yes, it is the goal ;-)
^ permalink raw reply
* [GIT PULL net-next 01/17] ndisc: Fix size calculation for headers.
From: YOSHIFUJI Hideaki @ 2012-12-18 10:52 UTC (permalink / raw)
To: davem, netdev; +Cc: yoshfuji
In-Reply-To: <50CF84A5.7030706@linux-ipv6.org>
We used to allocate MAX_HEADER bytes more than needed but
reserved hlen only (not MAX_HEADER + hlen) and the MAX_HEADER
was left behind.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
net/ipv6/ndisc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f2a007b..a1d2a45 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -395,8 +395,7 @@ static struct sk_buff *ndisc_build_skb(struct net_device *dev,
len += ndisc_opt_addr_space(dev);
skb = sock_alloc_send_skb(sk,
- (MAX_HEADER + sizeof(struct ipv6hdr) +
- len + hlen + tlen),
+ hlen + sizeof(struct ipv6hdr) + len + tlen,
1, &err);
if (!skb) {
ND_PRINTK(0, err, "ND: %s failed to allocate an skb, err=%d\n",
@@ -1422,8 +1421,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
hlen = LL_RESERVED_SPACE(dev);
tlen = dev->needed_tailroom;
buff = sock_alloc_send_skb(sk,
- (MAX_HEADER + sizeof(struct ipv6hdr) +
- len + hlen + tlen),
+ hlen + sizeof(struct ipv6hdr) + len + tlen,
1, &err);
if (buff == NULL) {
ND_PRINTK(0, err,
--
1.7.9.5
^ permalink raw reply related
* [GIT PULL net-next 02/17] ipv6: Introduce __ip6_hdr() for setting IPv6 header.
From: YOSHIFUJI Hideaki @ 2012-12-18 10:52 UTC (permalink / raw)
To: davem, netdev; +Cc: yoshfuji
In-Reply-To: <50CF84A5.7030706@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/net/ipv6.h | 15 +++++++++++++++
net/ipv6/ip6_gre.c | 18 ++++++------------
net/ipv6/ip6_output.c | 26 +++++---------------------
net/ipv6/ip6_tunnel.c | 12 +++++-------
4 files changed, 31 insertions(+), 40 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5af66b2..710bf2b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -622,6 +622,21 @@ extern int ip6_mc_input(struct sk_buff *skb);
extern int __ip6_local_out(struct sk_buff *skb);
extern int ip6_local_out(struct sk_buff *skb);
+static inline void __ip6_hdr(struct ipv6hdr *hdr,
+ unsigned int tclass,
+ __be32 flowlabel,
+ unsigned int proto,
+ unsigned int hoplimit,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr)
+{
+ *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel;
+ hdr->nexthdr = proto;
+ hdr->hop_limit = hoplimit;
+ hdr->saddr = *saddr;
+ hdr->daddr = *daddr;
+}
+
/*
* Extension header (options) processing
*/
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 867466c..d91deaa 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -773,13 +773,10 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
* Push down and install the IP header.
*/
ipv6h = ipv6_hdr(skb);
- *(__be32 *)ipv6h = fl6->flowlabel | htonl(0x60000000);
- dsfield = INET_ECN_encapsulate(0, dsfield);
- ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
- ipv6h->hop_limit = tunnel->parms.hop_limit;
- ipv6h->nexthdr = proto;
- ipv6h->saddr = fl6->saddr;
- ipv6h->daddr = fl6->daddr;
+
+ __ip6_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
+ fl6->flowlabel, proto, tunnel->parms.hop_limit,
+ &fl6->saddr, &fl6->daddr);
((__be16 *)(ipv6h + 1))[0] = tunnel->parms.o_flags;
((__be16 *)(ipv6h + 1))[1] = (dev->type == ARPHRD_ETHER) ?
@@ -1241,11 +1238,8 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen);
__be16 *p = (__be16 *)(ipv6h+1);
- *(__be32 *)ipv6h = t->fl.u.ip6.flowlabel | htonl(0x60000000);
- ipv6h->hop_limit = t->parms.hop_limit;
- ipv6h->nexthdr = NEXTHDR_GRE;
- ipv6h->saddr = t->parms.laddr;
- ipv6h->daddr = t->parms.raddr;
+ __ip6_hdr(ipv6h, 0, t->fl.u.ip6.flowlabel, NEXTHDR_GRE,
+ t->parms.hop_limit, &t->parms.laddr, &t->parms.raddr);
p[0] = t->parms.o_flags;
p[1] = htons(type);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5552d13..8c597b3 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -216,14 +216,9 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel;
-
+ __ip6_hdr(hdr, tclass, fl6->flowlabel, proto, hlimit,
+ &fl6->saddr, first_hop);
hdr->payload_len = htons(seg_len);
- hdr->nexthdr = proto;
- hdr->hop_limit = hlimit;
-
- hdr->saddr = fl6->saddr;
- hdr->daddr = *first_hop;
skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark;
@@ -267,14 +262,8 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
skb_put(skb, sizeof(struct ipv6hdr));
hdr = ipv6_hdr(skb);
- *(__be32*)hdr = htonl(0x60000000);
-
+ __ip6_hdr(hdr, 0, 0, proto, np->hop_limit, saddr, daddr);
hdr->payload_len = htons(len);
- hdr->nexthdr = proto;
- hdr->hop_limit = np->hop_limit;
-
- hdr->saddr = *saddr;
- hdr->daddr = *daddr;
return 0;
}
@@ -1548,13 +1537,8 @@ int ip6_push_pending_frames(struct sock *sk)
skb_reset_network_header(skb);
hdr = ipv6_hdr(skb);
- *(__be32*)hdr = fl6->flowlabel |
- htonl(0x60000000 | ((int)np->cork.tclass << 20));
-
- hdr->hop_limit = np->cork.hop_limit;
- hdr->nexthdr = proto;
- hdr->saddr = fl6->saddr;
- hdr->daddr = *final_dst;
+ __ip6_hdr(hdr, np->cork.tclass, fl6->flowlabel, proto,
+ np->cork.hop_limit, &fl6->saddr, final_dst);
skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a14f28b..28e4bf0 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1030,13 +1030,11 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
ipv6h = ipv6_hdr(skb);
- *(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000);
- dsfield = INET_ECN_encapsulate(0, dsfield);
- ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
- ipv6h->hop_limit = t->parms.hop_limit;
- ipv6h->nexthdr = proto;
- ipv6h->saddr = fl6->saddr;
- ipv6h->daddr = fl6->daddr;
+
+ __ip6_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
+ fl6->flowlabel, proto, t->parms.hop_limit,
+ &fl6->saddr, &fl6->daddr);
+
nf_reset(skb);
pkt_len = skb->len;
err = ip6_local_out(skb);
--
1.7.9.5
^ permalink raw reply related
* [GIT PULL net-next 03/17] ndisc: Introduce struct red_msg for redirect message.
From: YOSHIFUJI Hideaki @ 2012-12-18 10:53 UTC (permalink / raw)
To: davem, netdev; +Cc: yoshfuji
In-Reply-To: <50CF84A5.7030706@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/net/ndisc.h | 7 +++++++
net/ipv6/ndisc.c | 25 +++++++++++--------------
net/ipv6/route.c | 24 ++++++++++--------------
3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 7af1ea8..a7df01d 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -78,6 +78,13 @@ struct ra_msg {
__be32 retrans_timer;
};
+struct red_msg {
+ struct icmp6hdr icmph;
+ struct in6_addr target;
+ struct in6_addr dest;
+ __u8 opt[0];
+};
+
struct nd_opt_hdr {
__u8 nd_opt_type;
__u8 nd_opt_len;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a1d2a45..a181113 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1337,12 +1337,11 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
struct net_device *dev = skb->dev;
struct net *net = dev_net(dev);
struct sock *sk = net->ipv6.ndisc_sk;
- int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
+ int len = sizeof(struct red_msg);
struct inet_peer *peer;
struct sk_buff *buff;
- struct icmp6hdr *icmph;
+ struct red_msg *msg;
struct in6_addr saddr_buf;
- struct in6_addr *addrp;
struct rt6_info *rt;
struct dst_entry *dst;
struct inet6_dev *idev;
@@ -1436,21 +1435,19 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data);
skb_put(buff, len);
- icmph = icmp6_hdr(buff);
+ msg = (struct red_msg *)icmp6_hdr(buff);
- memset(icmph, 0, sizeof(struct icmp6hdr));
- icmph->icmp6_type = NDISC_REDIRECT;
+ memset(&msg->icmph, 0, sizeof(struct icmp6hdr));
+ msg->icmph.icmp6_type = NDISC_REDIRECT;
/*
* copy target and destination addresses
*/
- addrp = (struct in6_addr *)(icmph + 1);
- *addrp = *target;
- addrp++;
- *addrp = ipv6_hdr(skb)->daddr;
+ msg->target = *target;
+ msg->dest = ipv6_hdr(skb)->daddr;
- opt = (u8*) (addrp + 1);
+ opt = msg->opt;
/*
* include target_address option
@@ -1471,9 +1468,9 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
memcpy(opt, ipv6_hdr(skb), rd_len - 8);
- icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
- len, IPPROTO_ICMPV6,
- csum_partial(icmph, len, 0));
+ msg->icmph.icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
+ len, IPPROTO_ICMPV6,
+ csum_partial(msg, len, 0));
skb_dst_set(buff, dst);
rcu_read_lock();
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e229a3b..ec31862 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1705,37 +1705,33 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
struct net *net = dev_net(skb->dev);
struct netevent_redirect netevent;
struct rt6_info *rt, *nrt = NULL;
- const struct in6_addr *target;
struct ndisc_options ndopts;
- const struct in6_addr *dest;
struct neighbour *old_neigh;
struct inet6_dev *in6_dev;
struct neighbour *neigh;
- struct icmp6hdr *icmph;
+ struct red_msg *msg;
int optlen, on_link;
u8 *lladdr;
optlen = skb->tail - skb->transport_header;
- optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
+ optlen -= sizeof(*msg);
if (optlen < 0) {
net_dbg_ratelimited("rt6_do_redirect: packet too short\n");
return;
}
- icmph = icmp6_hdr(skb);
- target = (const struct in6_addr *) (icmph + 1);
- dest = target + 1;
+ msg = (struct red_msg *)icmp6_hdr(skb);
- if (ipv6_addr_is_multicast(dest)) {
+ if (ipv6_addr_is_multicast(&msg->dest)) {
net_dbg_ratelimited("rt6_do_redirect: destination address is multicast\n");
return;
}
on_link = 0;
- if (ipv6_addr_equal(dest, target)) {
+ if (ipv6_addr_equal(&msg->dest, &msg->target)) {
on_link = 1;
- } else if (ipv6_addr_type(target) !=
+ } else if (ipv6_addr_type(&msg->target) !=
(IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n");
return;
@@ -1752,7 +1748,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
* first-hop router for the specified ICMP Destination Address.
*/
- if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
+ if (!ndisc_parse_options(msg->opt, optlen, &ndopts)) {
net_dbg_ratelimited("rt6_redirect: invalid ND options\n");
return;
}
@@ -1779,7 +1775,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
*/
dst_confirm(&rt->dst);
- neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
+ neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
if (!neigh)
return;
@@ -1799,7 +1795,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
NEIGH_UPDATE_F_ISROUTER))
);
- nrt = ip6_rt_copy(rt, dest);
+ nrt = ip6_rt_copy(rt, &msg->dest);
if (!nrt)
goto out;
@@ -1817,7 +1813,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
netevent.old_neigh = old_neigh;
netevent.new = &nrt->dst;
netevent.new_neigh = neigh;
- netevent.daddr = dest;
+ netevent.daddr = &msg->dest;
call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
if (rt->rt6i_flags & RTF_CACHE) {
--
1.7.9.5
^ permalink raw reply related
* [GIT PULL net-next 04/17] ndisc: Introduce ndisc_fill_redirect_hdr_option().
From: YOSHIFUJI Hideaki @ 2012-12-18 10:54 UTC (permalink / raw)
To: davem, netdev; +Cc: yoshfuji
In-Reply-To: <50CF84A5.7030706@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
net/ipv6/ndisc.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a181113..0a4f3a9 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1332,6 +1332,19 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
}
+static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb,
+ int rd_len)
+{
+ memset(opt, 0, 8);
+ *(opt++) = ND_OPT_REDIRECT_HDR;
+ *(opt++) = (rd_len >> 3);
+ opt += 6;
+
+ memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
+
+ return opt;
+}
+
void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
{
struct net_device *dev = skb->dev;
@@ -1461,12 +1474,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
* build redirect option and copy skb over to the new packet.
*/
- memset(opt, 0, 8);
- *(opt++) = ND_OPT_REDIRECT_HDR;
- *(opt++) = (rd_len >> 3);
- opt += 6;
-
- memcpy(opt, ipv6_hdr(skb), rd_len - 8);
+ if (rd_len)
+ opt = ndisc_fill_redirect_hdr_option(opt, skb, rd_len);
msg->icmph.icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
len, IPPROTO_ICMPV6,
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox