* dccp-test-tree [PATCH 9/10] Userspace support for modifying the ECN bits of Data/DataAck packets
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-9-git-send-email-gerrit@erg.abdn.ac.uk>
This allows to pass ECN bits as cmsg ancillary data with a cmsg_type of
DCCP_SCM_ECN_BITS for Data/DataAck packets.
The scope of this patch is for developing user-space applications that work
with, modify, or control the use of ECN bits on data packets.
RFC: This is an AF-independent alternative to using IP_TOS/IPV6_TCLASS for
modifying the ECN bits.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
Documentation/networking/dccp.txt | 12 ++++++++++--
include/linux/dccp.h | 1 +
net/dccp/output.c | 10 +++++++---
net/dccp/proto.c | 20 ++++++++++++++++++++
4 files changed, 38 insertions(+), 5 deletions(-)
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -32,8 +32,16 @@ is at http://www.ietf.org/html.charters/dccp-charter.html
ECN Support
===========
By default, all outgoing packets are sent with ECT(0) as per RFC 3168, sec. 5.
-This can be disabled by setting the `ecn_local' sysctl to 0 (see below). The
-ECN Nonce (RFC 3540) is not supported.
+This can be disabled by setting the `ecn_local' sysctl to 0 (see below).
+
+For Data/DataAck packets, the ECN bits can be modified by passing an appropriate
+cmsg(3) value as ancillary data to sendmsg(2). The argument is an uint8_t value
+between 0..3 (corresponding to Not-ECT, ECT(1), ECT(0), and CE). Values greater
+than 3 are not accepted. Values need to be wrapped into a cmsg(3) header:
+ cmsg->cmsg_level = SOL_DCCP;
+ cmsg->cmsg_type = DCCP_SCM_ECN_BITS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(uint8_t)); /* or CMSG_LEN(1) */
+
Missing features
================
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -202,6 +202,7 @@ enum dccp_cmsg_type {
DCCP_SCM_PRIORITY = 1,
DCCP_SCM_QPOLICY_MAX = 0xFFFF,
/* ^-- Up to here reserved exclusively for qpolicy parameters */
+ DCCP_SCM_ECN_BITS,
DCCP_SCM_MAX
};
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -53,7 +53,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
const u32 dccp_header_size = sizeof(*dh) +
sizeof(struct dccp_hdr_ext) +
dccp_packet_hdr_len(dcb->dccpd_type);
- int err, set_ack = 1;
+ int err, set_ack = 1, ecn_bits = INET_ECN_ECT_0;
u64 ackno = dp->dccps_gsr;
/*
* Increment GSS here already in case the option code needs it.
@@ -66,6 +66,8 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
set_ack = 0;
/* fall through */
case DCCP_PKT_DATAACK:
+ /* ECN bits of Data/DataAck are set in dccp_sendmsg() */
+ ecn_bits = DCCP_SKB_CB(skb)->dccpd_ecn;
case DCCP_PKT_RESET:
break;
@@ -130,8 +132,10 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
break;
}
- if (dp->dccps_r_ecn_ok)
- INET_ECN_xmit(sk);
+ if (dp->dccps_r_ecn_ok) {
+ inet_sk(sk)->tos &= ~INET_ECN_MASK;
+ inet_sk(sk)->tos |= ecn_bits & INET_ECN_MASK;
+ }
icsk->icsk_af_ops->send_check(sk, 0, skb);
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -707,7 +707,17 @@ EXPORT_SYMBOL_GPL(compat_dccp_getsockopt);
static int dccp_msghdr_parse(struct msghdr *msg, struct sk_buff *skb)
{
+ const struct dccp_sock *dp = dccp_sk(skb->sk);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+ u8 val;
+
+ /*
+ * Setting ECN bits via DCCP_SCM_ECN_BITS: Data/DataAck only.
+ * See dccp_transmit_skb() where further processing takes place.
+ * By default, when no cmsg bits are supplied and when ECN is not
+ * disabled, ECT(0) is used for all outgoing packets (RFC 3168, 5.).
+ */
+ DCCP_SKB_CB(skb)->dccpd_ecn = INET_ECN_ECT_0;
/*
* Assign an (opaque) qpolicy priority value to skb->priority.
@@ -739,6 +749,16 @@ static int dccp_msghdr_parse(struct msghdr *msg, struct sk_buff *skb)
return -EINVAL;
skb->priority = *(__u32 *)CMSG_DATA(cmsg);
break;
+ case DCCP_SCM_ECN_BITS:
+ if (!dp->dccps_r_ecn_ok)
+ return -EINVAL;
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(__u8)))
+ return -EINVAL;
+ val = *(__u8 *)CMSG_DATA(cmsg);
+ if (val > INET_ECN_MASK)
+ return -EINVAL;
+ DCCP_SKB_CB(skb)->dccpd_ecn = val;
+ break;
default:
return -EINVAL;
}
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 1/10]: Put the ECN bits into the dccp_skb_cb
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-1-git-send-email-gerrit@erg.abdn.ac.uk>
This adds the two bits from the IPv4 TOS or IPv6 Traffic Class field into the
dccp_skb_cb.
To make the required room, dccp_opt_len is curtailed to 10 bits, since the
DCCP option length can not exceed 1020 < 2^10-1.
Further changes:
----------------
* added code to copy the TOS/traffic class field contents,
* supplied a utility function that checks for CE,
* deleted duplicate inclusion of headers.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/dccp.h | 10 +++++++++-
net/dccp/ipv4.c | 5 ++---
net/dccp/ipv6.c | 15 ++++++++-------
3 files changed, 19 insertions(+), 11 deletions(-)
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -14,6 +14,7 @@
#include <linux/dccp.h>
#include <linux/ktime.h>
+#include <net/inet_ecn.h>
#include <net/snmp.h>
#include <net/sock.h>
#include <net/tcp.h>
@@ -355,6 +356,7 @@ static inline int dccp_bad_service_code(const struct sock *sk,
* dccp_skb_cb - DCCP per-packet control information
* @dccpd_type: one of %dccp_pkt_type (or unknown)
* @dccpd_ccval: CCVal field (5.1), see e.g. RFC 4342, 8.1
+ * @dccpd_ecn: ECN bits read from the IPv4 TOS / IPv6 Traffic Class field
* @dccpd_reset_code: one of %dccp_reset_codes
* @dccpd_reset_data: Data1..3 fields (depend on @dccpd_reset_code)
* @dccpd_opt_len: total length of all options (5.8) in the packet
@@ -371,15 +373,21 @@ struct dccp_skb_cb {
} header;
__u8 dccpd_type:4;
__u8 dccpd_ccval:4;
+ __u8 dccpd_ecn:2;
__u8 dccpd_reset_code,
dccpd_reset_data[3];
- __u16 dccpd_opt_len;
+ __u16 dccpd_opt_len:10;
__u64 dccpd_seq;
__u64 dccpd_ack_seq;
};
#define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
+static inline bool dccp_skb_is_ecn_ce(const struct sk_buff *skb)
+{
+ return (DCCP_SKB_CB(skb)->dccpd_ecn & INET_ECN_MASK) == INET_ECN_CE;
+}
+
/* RFC 4340, sec. 7.7 */
static inline int dccp_non_data_packet(const struct sk_buff *skb)
{
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -10,16 +10,13 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/dccp.h>
#include <linux/icmp.h>
#include <linux/module.h>
-#include <linux/skbuff.h>
#include <linux/random.h>
#include <net/icmp.h>
#include <net/inet_common.h>
#include <net/inet_hashtables.h>
-#include <net/inet_sock.h>
#include <net/protocol.h>
#include <net/sock.h>
#include <net/timewait_sock.h>
@@ -783,6 +780,8 @@ static int dccp_v4_rcv(struct sk_buff *skb)
goto discard_it;
iph = ip_hdr(skb);
+ DCCP_SKB_CB(skb)->dccpd_ecn = iph->tos & INET_ECN_MASK;
+
/* Step 1: If header checksum is incorrect, drop packet and return */
if (dccp_v4_csum_finish(skb, iph->saddr, iph->daddr)) {
DCCP_WARN("dropped packet with invalid checksum\n");
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -19,7 +19,6 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_hashtables.h>
-#include <net/inet_sock.h>
#include <net/inet6_connection_sock.h>
#include <net/inet6_hashtables.h>
#include <net/ip6_route.h>
@@ -783,6 +782,7 @@ discard:
static int dccp_v6_rcv(struct sk_buff *skb)
{
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
const struct dccp_hdr *dh;
struct sock *sk;
int min_cov;
@@ -792,6 +792,8 @@ static int dccp_v6_rcv(struct sk_buff *skb)
if (dccp_invalid_packet(skb))
goto discard_it;
+ dcb->dccpd_ecn = ipv6_get_dsfield(ipv6_hdr(skb)) & INET_ECN_MASK;
+
/* Step 1: If header checksum is incorrect, drop packet and return. */
if (dccp_v6_csum_finish(skb, &ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr)) {
@@ -801,13 +803,13 @@ static int dccp_v6_rcv(struct sk_buff *skb)
dh = dccp_hdr(skb);
- DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
- DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
+ dcb->dccpd_seq = dccp_hdr_seq(dh);
+ dcb->dccpd_type = dh->dccph_type;
if (dccp_packet_without_ack(skb))
- DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
+ dcb->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
else
- DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
+ dcb->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
/* Step 2:
* Look up flow ID in table and get corresponding socket */
@@ -863,8 +865,7 @@ no_dccp_socket:
* Drop packet and return
*/
if (dh->dccph_type != DCCP_PKT_RESET) {
- DCCP_SKB_CB(skb)->dccpd_reset_code =
- DCCP_RESET_CODE_NO_CONNECTION;
+ dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
dccp_v6_ctl_send_reset(sk, skb);
}
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 3/10] Add feature-negotiation handler for ECN-Incapable feature
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-3-git-send-email-gerrit@erg.abdn.ac.uk>
This completes the feature-negotiation support for ECN in DCCP:
* a socket field to indicate whether this end is ECN-incapable,
* a socket field to record whether the remote end is ECN-capable,
* a feature-negotiation handler to activate the local/remote features.
When local ECN support is disabled, the ECN bits are erased before passing
the skb on to the CCIDs (which perform the actual ECN processing). If the
remote end is ECN-capable, dccp_transmit_skb() sets the ECT(0) codepoint.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
include/linux/dccp.h | 4 ++++
net/dccp/feat.c | 13 ++++++++++++-
net/dccp/input.c | 13 +++++++++++++
net/dccp/output.c | 3 +++
4 files changed, 32 insertions(+), 1 deletions(-)
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -467,6 +467,8 @@ struct dccp_ackvec;
* @dccps_r_ack_ratio - feature-remote Ack Ratio
* @dccps_l_seq_win - local Sequence Window (influences ack number validity)
* @dccps_r_seq_win - remote Sequence Window (influences seq number validity)
+ * @dccps_l_ecn_ok - this host understands ECN bits (RFC 4340, 12.1)
+ * @dccps_r_ecn_ok - the remote end understands ECN bits
* @dccps_pcslen - sender partial checksum coverage (via sockopt)
* @dccps_pcrlen - receiver partial checksum coverage (via sockopt)
* @dccps_send_ndp_count - local Send NDP Count feature (7.7.2)
@@ -512,6 +514,8 @@ struct dccp_sock {
__u16 dccps_r_ack_ratio;
__u64 dccps_l_seq_win:48;
__u64 dccps_r_seq_win:48;
+ bool dccps_l_ecn_ok:1,
+ dccps_r_ecn_ok:1;
__u8 dccps_pcslen:4;
__u8 dccps_pcrlen:4;
__u8 dccps_send_ndp_count:1;
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -72,6 +72,17 @@ static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)
return 0;
}
+static int dccp_hdlr_ecn(struct sock *sk, u64 ecn_incapable, bool rx)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ if (rx)
+ dp->dccps_l_ecn_ok = (ecn_incapable == 0);
+ else
+ dp->dccps_r_ecn_ok = (ecn_incapable == 0);
+ return 0;
+}
+
static int dccp_hdlr_ack_ratio(struct sock *sk, u64 ratio, bool rx)
{
#ifndef __CCID2_COPES_GRACEFULLY_WITH_DYNAMIC_ACK_RATIO_UPDATES__
@@ -170,7 +181,7 @@ static const struct {
{ DCCPF_CCID, FEAT_AT_TX, FEAT_SP, 2, dccp_hdlr_ccid },
{ DCCPF_SHORT_SEQNOS, FEAT_AT_TX, FEAT_SP, 0, NULL },
{ DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100, dccp_hdlr_seq_win },
- { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0, NULL },
+ { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_ecn },
{ DCCPF_ACK_RATIO, FEAT_AT_TX, FEAT_NN, 2, dccp_hdlr_ack_ratio},
{ DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_ackvec },
{ DCCPF_SEND_NDP_COUNT, FEAT_AT_TX, FEAT_SP, 0, dccp_hdlr_ndp },
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -159,6 +159,17 @@ static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
}
+static void dccp_handle_ecn_codepoints(struct sock *sk, struct sk_buff *skb)
+{
+ /*
+ * When locally disabled, erase ECN codepoints (a peer conforming to
+ * RFC 4340, 12.2 should set these to zero anyway).
+ */
+ if (!dccp_sk(sk)->dccps_l_ecn_ok)
+ DCCP_SKB_CB(skb)->dccpd_ecn = INET_ECN_NOT_ECT;
+
+}
+
static void dccp_handle_ackvec_processing(struct sock *sk, struct sk_buff *skb)
{
struct dccp_ackvec *av = dccp_sk(sk)->dccps_hc_rx_ackvec;
@@ -372,6 +383,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
if (dccp_parse_options(sk, NULL, skb))
return 1;
+ dccp_handle_ecn_codepoints(sk, skb);
dccp_handle_ackvec_processing(sk, skb);
dccp_deliver_input_to_ccids(sk, skb);
@@ -665,6 +677,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
case DCCP_PARTOPEN:
/* Step 8: if using Ack Vectors, mark packet acknowledgeable */
+ dccp_handle_ecn_codepoints(sk, skb);
dccp_handle_ackvec_processing(sk, skb);
dccp_deliver_input_to_ccids(sk, skb);
/* fall through */
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -130,6 +130,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
break;
}
+ if (dp->dccps_r_ecn_ok)
+ INET_ECN_xmit(sk);
+
icsk->icsk_af_ops->send_check(sk, 0, skb);
if (set_ack)
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 7/10] Extend the packet-history code to support ECN-marked-CE events
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-7-git-send-email-gerrit@erg.abdn.ac.uk>
This extends the main accounting routine, tfrc_rx_congestion_event, to
also consider ECN-marks.
Loss and ECN-marks are treated separately: when there is already a loss
event, it is not necessary to also check for ECN marks (there will be at
most one new congestion event anyway).
Conversely, if there is an ECN-event, tracking a pending loss is disabled.
This is due to the fact that considering every possible combination of
loss_count with/-out ECN-marks creates a lot of complexity which does not
seem warranted -- comments added to point this out.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/ccids/lib/packet_history.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -360,6 +360,27 @@ bool tfrc_rx_congestion_event(struct tfrc_rx_hist *h,
*/
new_event = tfrc_lh_interval_add(lh, h, first_li, sk);
__three_after_loss(h);
+
+ } else if (dccp_data_packet(skb) && dccp_skb_is_ecn_ce(skb)) {
+ /*
+ * We only test for ECN marks on data packets. This is the way
+ * the RFC considers ECN marks - a future implementation may
+ * find it useful to also check ECN marks on non-data packets.
+ */
+ new_event = tfrc_lh_interval_add(lh, h, first_li, sk);
+ /*
+ * Also combinations of loss and ECN-marks (as per the warning)
+ * are not supported. The permutations of loss combined with or
+ * without ECN-marks create a lot of complexity, which does not
+ * seem warranted: ECN-marked packets immediately trigger con-
+ * gestion events.
+ * Testing is needed to see whether ignoring the loss_count in
+ * light of an ECN-marked-CE event really has any disadvantages.
+ */
+ if (new_event && h->loss_count) {
+ DCCP_WARN("Ignoring loss count due to ECN\n");
+ tfrc_rx_hist_resume_rtt_sampling(h);
+ }
}
/*
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 5/10] net: Mask out ECN bits when setting TOS/TCLASS
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-5-git-send-email-gerrit@erg.abdn.ac.uk>
This patch is needed by the AF-independent approach to provide DCCPv4/6
ECN support. Since this approach handles ECN at in the module, the patch
disables user-side manipulation of ECN bits via TOS/TCLASS.
However, it also fixes a bug occurring in SCTPv6: when passing values that
contain 0x1 in the ECN bits, the internal value of ECT(0) gets turned into
0x3 = CE, i.e. it suggests to the other side that congestion was experienced.
I am working on these issues and would greatly appreciate feedback/suggestions.
(NB - not touched datagram_send_ctl(), since it is used only by udpv6/rawv6).
An alternative for modifying ECN bits in user space is in a subsequent patch.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/ipv4/ip_sockglue.c | 7 ++++---
net/ipv6/ipv6_sockglue.c | 2 ++
2 files changed, 6 insertions(+), 3 deletions(-)
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -27,6 +27,7 @@
#include <net/ip.h>
#include <net/icmp.h>
#include <net/tcp_states.h>
+#include <net/inet_ecn.h>
#include <linux/udp.h>
#include <linux/igmp.h>
#include <linux/netfilter.h>
@@ -550,9 +551,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
break;
case IP_TOS: /* This sets both TOS and Precedence */
- if (sk->sk_type == SOCK_STREAM) {
- val &= ~3;
- val |= inet->tos & 3;
+ if (sk->sk_type != SOCK_RAW) {
+ val &= ~INET_ECN_MASK;
+ val |= inet->tos & INET_ECN_MASK;
}
if (inet->tos != val) {
inet->tos = val;
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -318,6 +318,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
/* RFC 3542, 6.5: default traffic class of 0x0 */
if (val == -1)
val = 0;
+ if (sk->sk_type != SOCK_RAW)
+ val &= ~INET_ECN_MASK;
np->tclass = val;
retv = 0;
break;
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 4/10] net: Hack to enable IPv6 ECN support
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-4-git-send-email-gerrit@erg.abdn.ac.uk>
ECN is not currently supported on inet6 sockets.
This is a hack to copy over the ECN bits when ECN-capable transport
has been enabled on the inet_sk socket.
This allows to support DCCPv6 ECN support, but needs to be revised:
* the inet_sock already has an u8 `tos' field for the DSCP/ECN bits;
* the same field is present as u8 `tclass' field in ipv6_pinfo;
* the DS field (RFC 2474) and the ECN bits (RFC 3168) are AF-independent,
so TOS/Traffic Class could be made AF-independent;
* sockets that include ipv6_pinfo also include struct inet_sock.
Ideally there should be one field, e.g. `inet->dsfield', but doing
this requires some more careful analysis, since inet_sk(sk)->tos and
inet6_sk(sk)->tclass are referenced all over the source code.
Leaving this for the moment, to be completed later.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
include/net/inet_ecn.h | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -46,9 +46,13 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
(label) &= ~htonl(INET_ECN_MASK << 20); \
} while (0)
+/*
+ * XXX Hack: copy over the ECN bits from inet_sk to inet6_sk.
+ * This should be replaced by a single `dsfield' in inet
+ */
#define IP6_ECN_flow_xmit(sk, label) do { \
- if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \
- (label) |= htonl(INET_ECN_ECT_0 << 20); \
+ IP6_ECN_flow_init(label); \
+ (label) |= htonl((inet_sk(sk)->tos & INET_ECN_MASK) << 20); \
} while (0)
static inline int IP_ECN_set_ce(struct iphdr *iph)
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 10/10] Userspace support for reading ECN bits
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-10-git-send-email-gerrit@erg.abdn.ac.uk>
This adds support to read the ECN bits of incoming DCCP packets.
RFC: This is an AF-independent alternative to IP_RECVTOS/IPV6_RECVTCLASS.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
Documentation/networking/dccp.txt | 6 ++++++
include/linux/dccp.h | 5 ++++-
net/dccp/proto.c | 15 +++++++++++++++
3 files changed, 25 insertions(+), 1 deletions(-)
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -41,6 +41,8 @@ than 3 are not accepted. Values need to be wrapped into a cmsg(3) header:
cmsg->cmsg_level = SOL_DCCP;
cmsg->cmsg_type = DCCP_SCM_ECN_BITS;
cmsg->cmsg_len = CMSG_LEN(sizeof(uint8_t)); /* or CMSG_LEN(1) */
+The process can be reversed for recvmsg(2) when the DCCP_SOCKOPT_GET_ECN_BITS
+socket option is enabled (see below), using the same cmsg encapsulation.
Missing features
@@ -131,6 +133,10 @@ DCCP_SOCKOPT_RECV_CSCOV is for the receiver and has a different meaning: it
restrictive this setting (see [RFC 4340, sec. 9.2.1]). Partial coverage
settings are inherited to the child socket after accept().
+DCCP_SOCKOPT_GET_ECN_BITS takes a boolean int value and enables the delivery
+ of ECN bits as ancillary data to recvmsg(2). The data is received as
+ uint8_t value at SOL_DCCP level and cmsg_type of DCCP_SCM_ECN_BITS.
+
The following two options apply to CCID 3 exclusively and are getsockopt()-only.
In either case, a TFRC info struct (defined in <linux/tfrc.h>) is returned.
DCCP_SOCKOPT_CCID_RX_INFO
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -228,6 +228,7 @@ enum dccp_packet_dequeueing_policy {
#define DCCP_SOCKOPT_RX_CCID 15
#define DCCP_SOCKOPT_QPOLICY_ID 16
#define DCCP_SOCKOPT_QPOLICY_TXQLEN 17
+#define DCCP_SOCKOPT_GET_ECN_BITS 18
#define DCCP_SOCKOPT_CCID_RX_INFO 128
#define DCCP_SOCKOPT_CCID_TX_INFO 192
@@ -470,6 +471,7 @@ struct dccp_ackvec;
* @dccps_r_seq_win - remote Sequence Window (influences seq number validity)
* @dccps_l_ecn_ok - this host understands ECN bits (RFC 4340, 12.1)
* @dccps_r_ecn_ok - the remote end understands ECN bits
+ * @dccps_get_ecn_bits - this host requests ECN bits as recvmsg() ancillary data
* @dccps_pcslen - sender partial checksum coverage (via sockopt)
* @dccps_pcrlen - receiver partial checksum coverage (via sockopt)
* @dccps_send_ndp_count - local Send NDP Count feature (7.7.2)
@@ -516,7 +518,8 @@ struct dccp_sock {
__u64 dccps_l_seq_win:48;
__u64 dccps_r_seq_win:48;
bool dccps_l_ecn_ok:1,
- dccps_r_ecn_ok:1;
+ dccps_r_ecn_ok:1,
+ dccps_get_ecn_bits:1;
__u8 dccps_pcslen:4;
__u8 dccps_pcrlen:4;
__u8 dccps_send_ndp_count:1;
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -550,6 +550,9 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
else
dp->dccps_tx_qlen = val;
break;
+ case DCCP_SOCKOPT_GET_ECN_BITS:
+ dp->dccps_get_ecn_bits = (val != 0);
+ break;
default:
err = -ENOPROTOOPT;
break;
@@ -663,6 +666,9 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
case DCCP_SOCKOPT_QPOLICY_TXQLEN:
val = dp->dccps_tx_qlen;
break;
+ case DCCP_SOCKOPT_GET_ECN_BITS:
+ val = dp->dccps_get_ecn_bits;
+ break;
case 128 ... 191:
return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
len, (u32 __user *)optval, optlen);
@@ -825,6 +831,13 @@ out_discard:
EXPORT_SYMBOL_GPL(dccp_sendmsg);
+static void dccp_cmsg_recv_ecn_bits(struct msghdr *msg, struct sk_buff *skb)
+{
+ u8 val = DCCP_SKB_CB(skb)->dccpd_ecn;
+
+ put_cmsg(msg, SOL_DCCP, DCCP_SCM_ECN_BITS, sizeof(val), &val);
+}
+
int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len, int nonblock, int flags, int *addr_len)
{
@@ -919,6 +932,8 @@ verify_sock_status:
len = -EFAULT;
break;
}
+ if (dccp_sk(sk)->dccps_get_ecn_bits)
+ dccp_cmsg_recv_ecn_bits(msg, skb);
found_fin_ok:
if (!(flags & MSG_PEEK))
sk_eat_skb(sk, skb, 0);
--
1.6.0.rc2
^ permalink raw reply
* dccp-test-tree [PATCH 8/10] ccid-2: Ack Vector ECN support
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249847327-6792-8-git-send-email-gerrit@erg.abdn.ac.uk>
This adds Ack Vector support for registering ECN packets marked as
congestion-experienced (CE), and a FIXME to look after the Ack
Vector Nonce Sum (RFC 4340, 12.2 and RFC 3450, 3.).
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/ackvec.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -250,6 +250,16 @@ void dccp_ackvec_input(struct dccp_ackvec *av, struct sk_buff *skb)
u64 seqno = DCCP_SKB_CB(skb)->dccpd_seq;
enum dccp_ackvec_states state = DCCPAV_RECEIVED;
+ if (DCCP_SKB_CB(skb)->dccpd_ecn == INET_ECN_CE)
+ state = DCCPAV_ECN_MARKED;
+ else if (DCCP_SKB_CB(skb)->dccpd_ecn == INET_ECN_ECT_1)
+ /*
+ * FIXME: As long as we get ECT(0), the nonce sum is 0 as per
+ * RFC 3540, sec. 3. Supporting ECT(1) requires more work, as
+ * e.g. older Ack Vector cells must then be summed over again.
+ */
+ DCCP_WARN("Ack Vector Nonce sum does not yet support ECT(1)\n");
+
if (dccp_ackvec_is_empty(av)) {
dccp_ackvec_add_new(av, 1, seqno, state);
av->av_tail_ackno = seqno;
--
1.6.0.rc2
^ permalink raw reply
* [PATCH 0/10]: DCCPv4/6 support for ECN/ECT(0)
From: Gerrit Renker @ 2009-08-09 19:48 UTC (permalink / raw)
To: dccp; +Cc: netdev
In-Reply-To: <dccp_test_tree_sending_ecn_for_review>
This extends DCCP with ECN/ECT(0) capability, requesting review and comments.
In particular,
* following RFC 2474 and RFC 3168, the set takes an AF-independent approach,
* the kernel still takes an AF-dependent approach (inet->tos, inet6->tclass),
so it would be good to have input what the general trend is,
* some of the patches touch on general issues and hence need discussion.
Patch #1: Adds the ECN bits into the CB, for processing by DCCP and its CCIDs.
Patch #2: Adds a sysctl to for dccpv4/6 ECN support (similar to tcp_ecn sysctl).
Patch #3: Adds feature-negotiation handler for DCCP ECN support.
Patch #4: Is a hack to add ECN support. It is _not_ meant for consideration. I'd
appreciate any suggestions of doing this better. Currently there is no
full IPv6 ECN support: only TCPv4 uses ECN, SCTPv6 uses a workaround.
If you are reviewing this, please also check the next one.
Patch #5: Disables userspace modification of ECN bits via IP_TOS/IPV6_TCLASS,
since this will corrupt the internal ECN values. It is needed by this
approach for DCCP, but also by SCTPv6, since it is otherwise possible
to modify the ECN bits of np->tclass in userspace.
Patch #6: Extends the TFRC loss interval code of DCCP to support ECN.
Patch #7: Complements patch #6 by adding support for ECN-CE congestion events.
Patch #8: Adds Ack Vector ECN support to CCID-2.
Patch #9: AF-independent modification of DCCP ECN bits (compare #5).
Patch #10: AF-independent reading of DCCP-ECN bits; complements #9.
All patches (apart from #5) have been tested for approximately one year and
are now integrated into the DCCP test tree available at
git://eden-feed.erg.abdn.ac.uk/dccp_exp [subtree 'dccp']
http://eden-feed.erg.abdn.ac.uk [web view]
http://eden-feed.erg.abdn.ac.uk/latest-dccp-test-tree.tar.bz2
Before doing this, I compile-tested the tree again and ran a quick iperf test to
ensure that ECT(0) is now working (DCCPv6 tested via ::1 loopback).
^ permalink raw reply
* Reading Route-Metric
From: Tim Schneider @ 2009-08-09 19:14 UTC (permalink / raw)
To: netdev
Hello,
I've been trying for some time now to find a solution to my problem.
Since I a new to the kernel I was hoping that someone with more
experience could help me by giving me a hint on how to solve my problem.
I am writing a Kernel Module and I need to read out the Route-Metric-
Value of a socket. I want to do this from within TCP, so I can access
the structs "socket" and "sock" of the socket. As of now, I haven't
found a way to find out the wanted value with the data I have given. I
would be grateful, if somebody could give me a hint on how to
accomplish that task.
Thank you for you Help
Tim Schneider
^ permalink raw reply
* [Resent][PATCH 1/2] inet6: Conversion from u8 to int
From: Gerrit Renker @ 2009-08-09 18:12 UTC (permalink / raw)
To: davem; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249841569-23706-1-git-send-email-gerrit@erg.abdn.ac.uk>
This replaces assignments of the type "int on LHS" = "u8 on RHS" with
simpler code. The LHS can express all of the unsigned right hand side
values, hence the assigned value can not be negative.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/ipv6/icmp.c | 17 ++++-------------
net/ipv6/ip6_output.c | 15 +++++----------
net/ipv6/ipv6_sockglue.c | 2 --
net/ipv6/raw.c | 5 +----
net/ipv6/udp.c | 5 +----
5 files changed, 11 insertions(+), 33 deletions(-)
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1037,8 +1037,6 @@ static int do_ipv6_getsockopt(struct soc
case IPV6_TCLASS:
val = np->tclass;
- if (val < 0)
- val = 0;
break;
case IPV6_RECVTCLASS:
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -877,11 +877,8 @@ static int rawv6_sendmsg(struct kiocb *i
hlimit = ip6_dst_hoplimit(dst);
}
- if (tclass < 0) {
+ if (tclass < 0)
tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
- }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -900,11 +900,8 @@ do_udp_sendmsg:
hlimit = ip6_dst_hoplimit(dst);
}
- if (tclass < 0) {
+ if (tclass < 0)
tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
- }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -323,7 +323,7 @@ void icmpv6_send(struct sk_buff *skb, u8
int iif = 0;
int addr_type = 0;
int len;
- int hlimit, tclass;
+ int hlimit;
int err = 0;
if ((u8 *)hdr < skb->head ||
@@ -469,10 +469,6 @@ route_done:
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
msg.skb = skb;
msg.offset = skb_network_offset(skb);
msg.type = type;
@@ -488,8 +484,8 @@ route_done:
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr),
- hlimit, tclass, NULL, &fl, (struct rt6_info*)dst,
+ sizeof(struct icmp6hdr), hlimit,
+ np->tclass, NULL, &fl, (struct rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -522,7 +518,6 @@ static void icmpv6_echo_reply(struct sk_
struct dst_entry *dst;
int err = 0;
int hlimit;
- int tclass;
saddr = &ipv6_hdr(skb)->daddr;
@@ -562,10 +557,6 @@ static void icmpv6_echo_reply(struct sk_
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
idev = in6_dev_get(skb->dev);
msg.skb = skb;
@@ -573,7 +564,7 @@ static void icmpv6_echo_reply(struct sk_
msg.type = ICMPV6_ECHO_REPLY;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl,
+ sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
(struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -206,7 +206,8 @@ int ip6_xmit(struct sock *sk, struct sk_
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit, tclass;
+ int hlimit = -1;
+ int tclass = 0;
u32 mtu;
if (opt) {
@@ -249,19 +250,13 @@ int ip6_xmit(struct sock *sk, struct sk_
/*
* Fill in the IPv6 header
*/
-
- hlimit = -1;
- if (np)
+ if (np) {
+ tclass = np->tclass;
hlimit = np->hop_limit;
+ }
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = -1;
- if (np)
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
hdr->payload_len = htons(seg_len);
^ permalink raw reply
* [PATCH 2/2] inet6: Set default traffic class
From: Gerrit Renker @ 2009-08-09 18:12 UTC (permalink / raw)
To: davem; +Cc: netdev, Gerrit Renker
In-Reply-To: <1249841569-23706-2-git-send-email-gerrit@erg.abdn.ac.uk>
This patch addresses:
* assigning -1 to np->tclass as it is currently done is not very meaningful,
since it turns into 0xff;
* RFC 3542, 6.5 allows -1 for clearing the sticky IPV6_TCLASS option
and specifies -1 to mean "use kernel default":
- RFC 2460, 7. requires that the default traffic class must be zero for
all 8 bits,
- this is consistent with RFC 2474, 4.1 which recommends a default PHB of 0,
in combination with a value of the ECN field of "non-ECT" (RFC 3168, 5.).
This patch changes the meaning of -1 from assigning 255 to mean the RFC 2460
default, which at the same time allows to satisfy clearing the sticky TCLASS
option as per RFC 3542, 6.5.
(When passing -1 as ancillary data, the fallback remains np->tclass, which
has either been set via socket options, or contains the default value.)
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/ipv6/ipv6_sockglue.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -315,6 +315,9 @@ static int do_ipv6_setsockopt(struct soc
goto e_inval;
if (val < -1 || val > 0xff)
goto e_inval;
+ /* RFC 3542, 6.5: default traffic class of 0x0 */
+ if (val == -1)
+ val = 0;
np->tclass = val;
retv = 0;
break;
^ permalink raw reply
* [PATCH 0/2] inet6: resolve IPV6_TCLASS conversion problems
From: Gerrit Renker @ 2009-08-09 18:12 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <resolve_IPV6_TCLASS>
These are two patches dealing with the IPV6_TCLASS sticky socket option. They
belong together, the second patch is a follow-up and fixes the remainder.
Patch #1: Removes unnecessary conversions (tclass being u8)
This is a resent, an OK was given in the reply of
http://marc.info/?l=linux-netdev&m=124820628409987&w=2
Patch #2: Solves the remaining problem of passing the socket option,
fixing a bug (-1 became a non-default traffic class of 0xff).
^ permalink raw reply
* Re: [RFC PATCH v2 19/19] virtio: add a vbus transport
From: Anthony Liguori @ 2009-08-09 16:40 UTC (permalink / raw)
To: Gregory Haskins
Cc: linux-kernel, agraf, pmullaney, pmorreale, rusty, netdev, kvm,
avi, bhutchings, andi, gregkh, herber, chrisw, shemminger,
Michael S. Tsirkin
In-Reply-To: <20090409163221.32740.38373.stgit@dev.haskins.net>
Gregory Haskins wrote:
> We add a new virtio transport for accessing backends located on vbus. This
> complements the existing transports for virtio-pci, virtio-s390, and
> virtio-lguest that already exist.
>
> Signed-off-by: Gregory Haskins <ghaskins@novell.com>
Very interesting...
I'm somewhat confused by what you're advocating vbus as. I'm trying to
figure out how we converge vbus and virtio and become one big happy
family :-)
What parts of it do you think are better than virtio? Should we forget
about venet and just focus on virtio-net on top of virtio-vbus assuming
that we can prove venet-tap/virtio-vbus/virtio-net is just as good as
venet-tap/vbus/venet?
If we can prove that an in-kernel virtio-net
backend/virtio-pci/virtio-net does just as well as
venet-tap/virtio-vbus/virtio-net does that mean that vbus is no longer
needed?
If you concede that the transport mechanisms can be identical, are you
really advocating the discovering and configuration mechanisms in vbus?
Is that what we should be focusing on? Do you care only about the host
mechanisms or do you also require the guest infrastructure to be present?
I think two paravirtual I/O frameworks for KVM is a bad thing. It
duplicates a ton of code and will very likely lead to user unhappiness.
Regards,
Anthony Liguori
^ permalink raw reply
* [PATCH] zorro8390: Fix read buffer overflow in zorro8390_init_one()
From: Roel Kluin @ 2009-08-09 14:00 UTC (permalink / raw)
To: David S. Miller, netdev, Andrew Morton
Prevent read from cards[-1] when no card was found.
Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
is ENODEV appropriate here?
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 37c84e3..55502e1 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -120,6 +120,9 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
if (z->id == cards[i].id)
break;
+ if (i < 0)
+ return -ENODEV;
+
board = z->resource.start;
ioaddr = board+cards[i].offset;
dev = alloc_ei_netdev();
^ permalink raw reply related
* (unknown),
From: Pavan Tumati @ 2009-08-09 13:29 UTC (permalink / raw)
To: netdev
subscribe netdev
^ permalink raw reply
* [PATCH] net: include/linux/icmpv6: includecheck fix for icmpv6.h
From: Jaswinder Singh Rajput @ 2009-08-09 13:27 UTC (permalink / raw)
To: David Miller, netdev
fix the following 'make includecheck' warning:
include/linux/icmpv6.h: linux/skbuff.h is included more than once.
Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com>
---
include/linux/icmpv6.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index b6a8518..c0d8357 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -171,8 +171,6 @@ struct icmp6_filter {
#ifdef __KERNEL__
#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-
extern void icmpv6_send(struct sk_buff *skb,
u8 type, u8 code,
--
1.6.0.6
^ permalink raw reply related
* [PATCH] net: smc911x: includecheck fix for smc911x.h
From: Jaswinder Singh Rajput @ 2009-08-09 13:12 UTC (permalink / raw)
To: David Miller, nico, netdev, dustin
fix the following 'make includecheck' warning:
drivers/net/smc911x.h: mach/dma.h is included more than once.
Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com>
---
drivers/net/smc911x.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index 8140f7c..05adb6a 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -236,7 +236,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
* Use a DMA for RX and TX packets.
*/
#include <linux/dma-mapping.h>
-#include <mach/dma.h>
static dma_addr_t rx_dmabuf, tx_dmabuf;
static int rx_dmalen, tx_dmalen;
--
1.6.0.6
^ permalink raw reply related
* [PATCH] net: pcmcia/axnet_cs: includecheck fix axnet_cs.c
From: Jaswinder Singh Rajput @ 2009-08-09 13:05 UTC (permalink / raw)
To: David Miller, netdev, David Hinds
fix the following 'make includecheck' warning:
drivers/net/pcmcia/axnet_cs.c: linux/etherdevice.h is included more than once.
Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com>
---
drivers/net/pcmcia/axnet_cs.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index b5cfac7..1e87d63 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -893,8 +893,6 @@ static const char version_8390[] = KERN_INFO \
#include <linux/in.h>
#include <linux/interrupt.h>
-#include <linux/etherdevice.h>
-
#define BUG_83C690
/* These are the operational function interfaces to board-specific
--
1.6.0.6
^ permalink raw reply related
* [PATCH v3] Add support for w90p910 mac driver
From: Wan ZongShun @ 2009-08-09 13:06 UTC (permalink / raw)
To: David S. Miller, Russell King; +Cc: linux-arm-kernel, linux-netdev
Dear David,
I fixed up my mac driver, which relatives to previous
mac driver actually in the tree.
Thanks a lot for your help!
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
---
drivers/net/arm/w90p910_ether.c | 206 +++++++++++++++++++++------------------
1 files changed, 112 insertions(+), 94 deletions(-)
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 616fb79..890716f 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -143,16 +143,17 @@ struct recv_pdesc {
struct tran_pdesc {
struct w90p910_txbd desclist[TX_DESC_SIZE];
- char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+ char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
};
struct w90p910_ether {
struct recv_pdesc *rdesc;
- struct recv_pdesc *rdesc_phys;
struct tran_pdesc *tdesc;
- struct tran_pdesc *tdesc_phys;
+ dma_addr_t rdesc_phys;
+ dma_addr_t tdesc_phys;
struct net_device_stats stats;
struct platform_device *pdev;
+ struct resource *res;
struct sk_buff *skb;
struct clk *clk;
struct clk *rmiiclk;
@@ -169,7 +170,6 @@ struct w90p910_ether {
unsigned int start_tx_ptr;
unsigned int start_rx_ptr;
unsigned int linkflag;
- spinlock_t lock;
};
static void update_linkspeed_register(struct net_device *dev,
@@ -275,59 +275,75 @@ static void w90p910_write_cam(struct net_device *dev,
__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
}
-static void w90p910_init_desc(struct net_device *dev)
+static int w90p910_init_desc(struct net_device *dev)
{
struct w90p910_ether *ether;
- struct w90p910_txbd *tdesc, *tdesc_phys;
- struct w90p910_rxbd *rdesc, *rdesc_phys;
- unsigned int i, j;
+ struct w90p910_txbd *tdesc;
+ struct w90p910_rxbd *rdesc;
+ struct platform_device *pdev;
+ unsigned int i;
ether = netdev_priv(dev);
+ pdev = ether->pdev;
ether->tdesc = (struct tran_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
- (dma_addr_t *) ðer->tdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ðer->tdesc_phys, GFP_KERNEL);
+
+ if (!ether->tdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
+ return -ENOMEM;
+ }
ether->rdesc = (struct recv_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
- (dma_addr_t *) ðer->rdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ ðer->rdesc_phys, GFP_KERNEL);
+
+ if (!ether->rdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
+ return -ENOMEM;
+ }
for (i = 0; i < TX_DESC_SIZE; i++) {
- tdesc = &(ether->tdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / TX_DESC_SIZE);
+ tdesc = &(ether->tdesc->desclist[i]);
- if (j != 0) {
- tdesc_phys = &(ether->tdesc_phys->desclist[0]);
- ether->start_tx_ptr = (unsigned int)tdesc_phys;
- tdesc->next = (unsigned int)ether->start_tx_ptr;
- } else {
- tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
- tdesc->next = (unsigned int)tdesc_phys;
- }
+ if (i == TX_DESC_SIZE - 1)
+ offset = offsetof(struct tran_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct tran_pdesc, desclist[i + 1]);
- tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+ tdesc->next = ether->tdesc_phys + offset;
+ tdesc->buffer = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, tran_buf[i]);
tdesc->sl = 0;
tdesc->mode = 0;
}
+ ether->start_tx_ptr = ether->tdesc_phys;
+
for (i = 0; i < RX_DESC_SIZE; i++) {
- rdesc = &(ether->rdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / RX_DESC_SIZE);
+ rdesc = &(ether->rdesc->desclist[i]);
- if (j != 0) {
- rdesc_phys = &(ether->rdesc_phys->desclist[0]);
- ether->start_rx_ptr = (unsigned int)rdesc_phys;
- rdesc->next = (unsigned int)ether->start_rx_ptr;
- } else {
- rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
- rdesc->next = (unsigned int)rdesc_phys;
- }
+ if (i == RX_DESC_SIZE - 1)
+ offset = offsetof(struct recv_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct recv_pdesc, desclist[i + 1]);
+ rdesc->next = ether->rdesc_phys + offset;
rdesc->sl = RX_OWEN_DMA;
- rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+ rdesc->buffer = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, recv_buf[i]);
}
+
+ ether->start_rx_ptr = ether->rdesc_phys;
+
+ return 0;
}
static void w90p910_set_fifo_threshold(struct net_device *dev)
@@ -456,8 +472,6 @@ static void w90p910_reset_mac(struct net_device *dev)
{
struct w90p910_ether *ether = netdev_priv(dev);
- spin_lock(ðer->lock);
-
w90p910_enable_tx(dev, 0);
w90p910_enable_rx(dev, 0);
w90p910_set_fifo_threshold(dev);
@@ -486,8 +500,6 @@ static void w90p910_reset_mac(struct net_device *dev)
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
-
- spin_unlock(ðer->lock);
}
static void w90p910_mdio_write(struct net_device *dev,
@@ -541,7 +553,7 @@ static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
return data;
}
-static int set_mac_address(struct net_device *dev, void *addr)
+static int w90p910_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *address = addr;
@@ -557,11 +569,14 @@ static int set_mac_address(struct net_device *dev, void *addr)
static int w90p910_ether_close(struct net_device *dev)
{
struct w90p910_ether *ether = netdev_priv(dev);
+ struct platform_device *pdev;
- dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
- ether->rdesc, (dma_addr_t)ether->rdesc_phys);
- dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
- ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+ pdev = ether->pdev;
+
+ dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ ether->rdesc, ether->rdesc_phys);
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
netif_stop_queue(dev);
@@ -597,6 +612,7 @@ static int w90p910_send_frame(struct net_device *dev,
txbd = ðer->tdesc->desclist[ether->cur_tx];
buffer = ether->tdesc->tran_buf[ether->cur_tx];
+
if (length > 1514) {
dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
length = 1514;
@@ -612,7 +628,9 @@ static int w90p910_send_frame(struct net_device *dev,
w90p910_trigger_tx(dev);
- ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+ if (++ether->cur_tx >= TX_DESC_SIZE)
+ ether->cur_tx = 0;
+
txbd = ðer->tdesc->desclist[ether->cur_tx];
dev->trans_start = jiffies;
@@ -632,7 +650,7 @@ static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_irq(skb);
return 0;
}
- return -1;
+ return -EAGAIN;
}
static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
@@ -640,27 +658,25 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
struct w90p910_ether *ether;
struct w90p910_txbd *txbd;
struct platform_device *pdev;
- struct tran_pdesc *tran_pdesc;
struct net_device *dev;
unsigned int cur_entry, entry, status;
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
ether = netdev_priv(dev);
pdev = ether->pdev;
- spin_lock(ðer->lock);
-
w90p910_get_and_clear_int(dev, &status);
cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
- tran_pdesc = ether->tdesc_phys;
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
while (entry != cur_entry) {
txbd = ðer->tdesc->desclist[ether->finish_tx];
- ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+ if (++ether->finish_tx >= TX_DESC_SIZE)
+ ether->finish_tx = 0;
if (txbd->sl & TXDS_TXCP) {
ether->stats.tx_packets++;
@@ -675,20 +691,19 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
}
if (status & MISTA_EXDEF) {
dev_err(&pdev->dev, "emc defer exceed interrupt\n");
} else if (status & MISTA_TXBERR) {
- dev_err(&pdev->dev, "emc bus error interrupt\n");
- w90p910_reset_mac(dev);
- } else if (status & MISTA_TDU) {
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
- }
-
- spin_unlock(ðer->lock);
+ dev_err(&pdev->dev, "emc bus error interrupt\n");
+ w90p910_reset_mac(dev);
+ } else if (status & MISTA_TDU) {
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
return IRQ_HANDLED;
}
@@ -698,20 +713,20 @@ static void netdev_rx(struct net_device *dev)
struct w90p910_ether *ether;
struct w90p910_rxbd *rxbd;
struct platform_device *pdev;
- struct recv_pdesc *rdesc_phys;
struct sk_buff *skb;
unsigned char *data;
unsigned int length, status, val, entry;
ether = netdev_priv(dev);
pdev = ether->pdev;
- rdesc_phys = ether->rdesc_phys;
rxbd = ðer->rdesc->desclist[ether->cur_rx];
do {
val = __raw_readl(ether->reg + REG_CRXDSA);
- entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+ entry = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
if (val == entry)
break;
@@ -743,22 +758,23 @@ static void netdev_rx(struct net_device *dev)
dev_err(&pdev->dev, "rx runt err\n");
ether->stats.rx_length_errors++;
} else if (status & RXDS_CRCE) {
- dev_err(&pdev->dev, "rx crc err\n");
- ether->stats.rx_crc_errors++;
- }
-
- if (status & RXDS_ALIE) {
+ dev_err(&pdev->dev, "rx crc err\n");
+ ether->stats.rx_crc_errors++;
+ } else if (status & RXDS_ALIE) {
dev_err(&pdev->dev, "rx aligment err\n");
ether->stats.rx_frame_errors++;
} else if (status & RXDS_PTLE) {
- dev_err(&pdev->dev, "rx longer err\n");
- ether->stats.rx_over_errors++;
- }
+ dev_err(&pdev->dev, "rx longer err\n");
+ ether->stats.rx_over_errors++;
}
+ }
rxbd->sl = RX_OWEN_DMA;
rxbd->reserved = 0x0;
- ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+
+ if (++ether->cur_rx >= RX_DESC_SIZE)
+ ether->cur_rx = 0;
+
rxbd = ðer->rdesc->desclist[ether->cur_rx];
dev->last_rx = jiffies;
@@ -772,28 +788,23 @@ static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
struct platform_device *pdev;
unsigned int status;
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
ether = netdev_priv(dev);
pdev = ether->pdev;
- spin_lock(ðer->lock);
-
w90p910_get_and_clear_int(dev, &status);
if (status & MISTA_RDU) {
netdev_rx(dev);
-
w90p910_trigger_rx(dev);
- spin_unlock(ðer->lock);
return IRQ_HANDLED;
} else if (status & MISTA_RXBERR) {
- dev_err(&pdev->dev, "emc rx bus error\n");
- w90p910_reset_mac(dev);
- }
+ dev_err(&pdev->dev, "emc rx bus error\n");
+ w90p910_reset_mac(dev);
+ }
netdev_rx(dev);
- spin_unlock(ðer->lock);
return IRQ_HANDLED;
}
@@ -826,6 +837,7 @@ static int w90p910_ether_open(struct net_device *dev)
if (request_irq(ether->rxirq, w90p910_rx_interrupt,
0x0, pdev->name, dev)) {
dev_err(&pdev->dev, "register irq rx failed\n");
+ free_irq(ether->txirq, dev);
return -EAGAIN;
}
@@ -908,7 +920,7 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
.ndo_start_xmit = w90p910_ether_start_xmit,
.ndo_get_stats = w90p910_ether_stats,
.ndo_set_multicast_list = w90p910_ether_set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
+ .ndo_set_mac_address = w90p910_set_mac_address,
.ndo_do_ioctl = w90p910_ether_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
@@ -949,8 +961,6 @@ static int w90p910_ether_setup(struct net_device *dev)
get_mac_address(dev);
- spin_lock_init(ðer->lock);
-
ether->cur_tx = 0x0;
ether->cur_rx = 0x0;
ether->finish_tx = 0x0;
@@ -972,30 +982,29 @@ static int __devinit w90p910_ether_probe(struct platform_device *pdev)
{
struct w90p910_ether *ether;
struct net_device *dev;
- struct resource *res;
int error;
dev = alloc_etherdev(sizeof(struct w90p910_ether));
if (!dev)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
+ ether = netdev_priv(dev);
+
+ ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (ether->res == NULL) {
dev_err(&pdev->dev, "failed to get I/O memory\n");
error = -ENXIO;
goto failed_free;
}
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
+ if (!request_mem_region(ether->res->start,
+ resource_size(ether->res), pdev->name)) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
error = -EBUSY;
goto failed_free;
}
- ether = netdev_priv(dev);
-
- ether->reg = ioremap(res->start, resource_size(res));
+ ether->reg = ioremap(ether->res->start, resource_size(ether->res));
if (ether->reg == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -ENXIO;
@@ -1056,7 +1065,7 @@ failed_free_txirq:
failed_free_io:
iounmap(ether->reg);
failed_free_mem:
- release_mem_region(res->start, resource_size(res));
+ release_mem_region(ether->res->start, resource_size(ether->res));
failed_free:
free_netdev(dev);
return error;
@@ -1068,10 +1077,19 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
struct w90p910_ether *ether = netdev_priv(dev);
unregister_netdev(dev);
+
clk_put(ether->rmiiclk);
clk_put(ether->clk);
+
+ iounmap(ether->reg);
+ release_mem_region(ether->res->start, resource_size(ether->res));
+
+ free_irq(ether->txirq, dev);
+ free_irq(ether->rxirq, dev);
+
del_timer_sync(ðer->check_timer);
platform_set_drvdata(pdev, NULL);
+
free_netdev(dev);
return 0;
}
--
1.5.6.3
^ permalink raw reply related
* [PATCH] net: cs89x0: includecheck fix for cs89x0.c
From: Jaswinder Singh Rajput @ 2009-08-09 12:59 UTC (permalink / raw)
To: David Miller, netdev, Russwll Nelson, Andrew Morton, mcruse
fix the following 'make includecheck' warning:
drivers/net/cs89x0.c: asm/irq.h is included more than once.
Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com>
---
drivers/net/cs89x0.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index ecf88ab..839cac5 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -177,13 +177,10 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0};
#elif defined(CONFIG_MACH_IXDP2351)
static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
-#include <asm/irq.h>
#elif defined(CONFIG_ARCH_IXDP2X01)
-#include <asm/irq.h>
static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
#elif defined(CONFIG_ARCH_PNX010X)
-#include <asm/irq.h>
#include <mach/gpio.h>
#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
--
1.6.0.6
^ permalink raw reply related
* [PATCH] sky2: Create buffer alloc and free helpers
From: Mike McCormack @ 2009-08-09 11:40 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Refactor similar two sections of code that free buffers into one.
As a side effect, only call tx_init() in sky2_up() if all buffer
allocations succeed.
Signed-off-by: Mike McCormack <mikem@ring3k.org>
---
drivers/net/sky2.c | 111 +++++++++++++++++++++++++++------------------------
1 files changed, 59 insertions(+), 52 deletions(-)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 824a319..fab51bb 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1396,6 +1396,62 @@ nomem:
return -ENOMEM;
}
+static int sky2_alloc_buffers(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+
+ /* must be power of 2 */
+ sky2->tx_le = pci_alloc_consistent(hw->pdev,
+ TX_RING_SIZE *
+ sizeof(struct sky2_tx_le),
+ &sky2->tx_le_map);
+ if (!sky2->tx_le)
+ goto err;
+
+ sky2->tx_ring = kcalloc(TX_RING_SIZE, sizeof(struct tx_ring_info),
+ GFP_KERNEL);
+ if (!sky2->tx_ring)
+ goto err;
+
+ sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
+ &sky2->rx_le_map);
+ if (!sky2->rx_le)
+ goto err;
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+ sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
+ GFP_KERNEL);
+ if (!sky2->rx_ring)
+ goto err;
+
+ return 0;
+
+err:
+ return -1;
+}
+
+static void sky2_free_buffers(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+
+ if (sky2->rx_le) {
+ pci_free_consistent(hw->pdev, RX_LE_BYTES,
+ sky2->rx_le, sky2->rx_le_map);
+ sky2->rx_le = NULL;
+ }
+ if (sky2->tx_le) {
+ pci_free_consistent(hw->pdev,
+ TX_RING_SIZE * sizeof(struct sky2_tx_le),
+ sky2->tx_le, sky2->tx_le_map);
+ sky2->tx_le = NULL;
+ }
+ kfree(sky2->tx_ring);
+ kfree(sky2->rx_ring);
+
+ sky2->tx_ring = NULL;
+ sky2->rx_ring = NULL;
+}
+
/* Bring up network interface. */
static int sky2_up(struct net_device *dev)
{
@@ -1422,32 +1478,11 @@ static int sky2_up(struct net_device *dev)
netif_carrier_off(dev);
- /* must be power of 2 */
- sky2->tx_le = pci_alloc_consistent(hw->pdev,
- TX_RING_SIZE *
- sizeof(struct sky2_tx_le),
- &sky2->tx_le_map);
- if (!sky2->tx_le)
- goto err_out;
-
- sky2->tx_ring = kcalloc(TX_RING_SIZE, sizeof(struct tx_ring_info),
- GFP_KERNEL);
- if (!sky2->tx_ring)
+ if (0 > sky2_alloc_buffers(sky2))
goto err_out;
tx_init(sky2);
- sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
- &sky2->rx_le_map);
- if (!sky2->rx_le)
- goto err_out;
- memset(sky2->rx_le, 0, RX_LE_BYTES);
-
- sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
- GFP_KERNEL);
- if (!sky2->rx_ring)
- goto err_out;
-
napi_disable(&hw->napi);
sky2_mac_init(hw, port);
napi_enable(&hw->napi);
@@ -1507,22 +1542,7 @@ static int sky2_up(struct net_device *dev)
return 0;
err_out:
- if (sky2->rx_le) {
- pci_free_consistent(hw->pdev, RX_LE_BYTES,
- sky2->rx_le, sky2->rx_le_map);
- sky2->rx_le = NULL;
- }
- if (sky2->tx_le) {
- pci_free_consistent(hw->pdev,
- TX_RING_SIZE * sizeof(struct sky2_tx_le),
- sky2->tx_le, sky2->tx_le_map);
- sky2->tx_le = NULL;
- }
- kfree(sky2->tx_ring);
- kfree(sky2->rx_ring);
-
- sky2->tx_ring = NULL;
- sky2->rx_ring = NULL;
+ sky2_free_buffers(sky2);
return err;
}
@@ -1900,20 +1920,7 @@ static int sky2_down(struct net_device *dev)
sky2_tx_clean(dev);
sky2_rx_clean(sky2);
- pci_free_consistent(hw->pdev, RX_LE_BYTES,
- sky2->rx_le, sky2->rx_le_map);
- kfree(sky2->rx_ring);
-
- pci_free_consistent(hw->pdev,
- TX_RING_SIZE * sizeof(struct sky2_tx_le),
- sky2->tx_le, sky2->tx_le_map);
- kfree(sky2->tx_ring);
-
- sky2->tx_le = NULL;
- sky2->rx_le = NULL;
-
- sky2->rx_ring = NULL;
- sky2->tx_ring = NULL;
+ sky2_free_buffers(sky2);
return 0;
}
--
1.5.6.5
^ permalink raw reply related
* [PATCH] sky2: Serialize access to PCI config space
From: Mike McCormack @ 2009-08-09 11:37 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Disable NAPI when powering up or down the phy, as sky2_err_intr
may also access the PCI config space.
Signed-off-by: Mike McCormack <mikem@ring3k.org>
---
drivers/net/sky2.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 8e05d29..824a319 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1448,7 +1448,9 @@ static int sky2_up(struct net_device *dev)
if (!sky2->rx_ring)
goto err_out;
+ napi_disable(&hw->napi);
sky2_mac_init(hw, port);
+ napi_enable(&hw->napi);
/* Register is number of 4K blocks on internal RAM buffer. */
ramsize = sky2_read8(hw, B2_E_0) * 4;
@@ -1880,13 +1882,16 @@ static int sky2_down(struct net_device *dev)
sky2_write32(hw, B0_IMSK, imask);
sky2_read32(hw, B0_IMSK);
+ /* after this, there should be no more interrupts for this port */
synchronize_irq(hw->pdev->irq);
- napi_synchronize(&hw->napi);
+ napi_disable(&hw->napi);
spin_lock_bh(&sky2->phy_lock);
sky2_phy_power_down(hw, port);
spin_unlock_bh(&sky2->phy_lock);
+ napi_enable(&hw->napi);
+
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
--
1.5.6.5
^ permalink raw reply related
* Re: [evb] RE: [PATCH][RFC] net/bridge: add basic VEPA support
From: Or Gerlitz @ 2009-08-09 11:19 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Paul Congdon (UC Davis), arnd, anna.fischer, netdev, bridge,
davem, adobriyan, virtualization, evb@yahoogroups.com
In-Reply-To: <20090807143652.1659ac57@nehalam>
Stephen Hemminger wrote:
> I have a patch that forwards all multicast packets, and another that does proper forwarding. It should have worked that way in original macvlan, the current behavior is really a bug.
>
Looking in macvlan_set_multicast_list() it acts in a similar manner to
macvlan_set_mac_address() in the sense that it calls dev_mc_sync(). I
assume what's left is to add macvlan_hash_xxx multicast logic to
map/unmap multicast groups to what macvlan devices want to receive them
and this way the flooding can be removed, correct?
Or.
^ permalink raw reply
* [Fwd: Re: [PATCH] Fix userland build failure in linux/if_tunnel.h]
From: Sergei Poselenov @ 2009-08-09 9:41 UTC (permalink / raw)
To: netdev; +Cc: wd@denx.de >> Wolfgang Denk
Hello all,
As suggested, reposting the message in this list. Could someone please
comment?
Original message here:
http://lkml.org/lkml/2009/6/18/223
Thanks in advance,
Sergei
-------- Original Message --------
Subject: Re: [PATCH] Fix userland build failure in linux/if_tunnel.h
Date: Fri, 7 Aug 2009 15:31:06 +0400
From: Sergei Poselenov <sposelenov@emcraft.com>
Organisation: Emcraft Systems
To: linux-kernel@vger.kernel.org
CC: wd@denx.de
References: <20090618183738.662f7ef1@emcraft.com>
Hello all,
Unfortunately, received no replies, but the problem still persists.
Probably, I was unclear describing the issue. It is not the busybox
build problem - any application including exported linux/if_tunnel.h
could fail the linkage because of unresolved __cpu_to_be16().
Here is a reduced testcase program:
#include <netinet/ip.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <asm/types.h>
#include <linux/if_tunnel.h>
void foo(void);
void foo(void)
{
int a = GRE_CSUM;
}
How to reproduce:
bash> arm-linux-gcc -c t.c
bash> nm -n t.o
U __cpu_to_be16
00000000 t $a
00000000 T foo
As you see, __cpu_to_be16 is undefined, so linking will fail.
Adding <asm/byteorder.h> to if_tunnel.h, as I suggested, fixes the
problem.
Thanks for any comments,
Sergei
On Thu, 18 Jun 2009 18:37:38 +0400
Sergei Poselenov <sposelenov@emcraft.com> wrote:
> Hello all,
>
> The last commit to linux/if_tunnel.h broke the busybox
> application build.
> When linking the final image linker complains:
> networking/libiproute/lib.a(iptunnel.o): In function `parse_args':
> /work/psl/e/arm-aa/target_rpms/busybox/BUILD/busybox-1.7.1/networking/libiproute/iptunnel.c:189:
> undefined reference to
> `__cpu_to_be16' /work/psl/e/arm-aa/target_rpms/busybox/BUILD/busybox-1.7.1/networking/libiproute/iptunnel.c:190:
> undefined reference to
> `__cpu_to_be16' /work/psl/e/arm-aa/target_rpms/busybox/BUILD/busybox-1.7.1/networking/libiproute/iptunnel.c:202:
> undefined reference to `__cpu_to_be16'
> ...
>
> Please review the following patch, which fixes the build error.
>
> Subject: [PATCH] The busybox application build failed in linking
> complaining to unresolved __cpu_to_be16 (ARM target). This patch
> fixes this.
>
> Signed-off-by: Sergei Poselenov <sposelenov@emcraft.com>
> ---
> include/linux/if_tunnel.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
> index 5a9aae4..137130b 100644
> --- a/include/linux/if_tunnel.h
> +++ b/include/linux/if_tunnel.h
> @@ -2,6 +2,7 @@
> #define _IF_TUNNEL_H_
>
> #include <linux/types.h>
> +#include <asm/byteorder.h>
>
> #ifdef __KERNEL__
> #include <linux/ip.h>
^ permalink raw reply
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