Netdev List
 help / color / mirror / Atom feed
* [PATCH 6/18] netfilter: ipt_ULOG: Move away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/netfilter/ipt_ULOG.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index ba5756d..99b3f53 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -196,12 +196,15 @@ static void ipt_ulog_packet(unsigned int hooknum,
 
 	pr_debug("qlen %d, qthreshold %Zu\n", ub->qlen, loginfo->qthreshold);
 
-	/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
-	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
-			sizeof(*pm)+copy_len);
+	nlh = nlmsg_put(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
+			sizeof(*pm)+copy_len, 0);
+	if (!nlh) {
+		pr_debug("error during nlmsg_put\n");
+		goto out_unlock;
+	}
 	ub->qlen++;
 
-	pm = NLMSG_DATA(nlh);
+	pm = nlmsg_data(nlh);
 
 	/* We might not have a timestamp, get one */
 	if (skb->tstamp.tv64 == 0)
@@ -261,13 +264,11 @@ static void ipt_ulog_packet(unsigned int hooknum,
 			nlh->nlmsg_type = NLMSG_DONE;
 		ulog_send(groupnum);
 	}
-
+out_unlock:
 	spin_unlock_bh(&ulog_lock);
 
 	return;
 
-nlmsg_failure:
-	pr_debug("error during NLMSG_PUT\n");
 alloc_failure:
 	pr_debug("Error building netlink message\n");
 	spin_unlock_bh(&ulog_lock);
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 5/18] inet_diag: Move away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too, and remove useless
casts.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/inet_diag.c |   43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 46d1e71..27640e7 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -87,10 +87,14 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 	handler = inet_diag_table[req->sdiag_protocol];
 	BUG_ON(handler == NULL);
 
-	nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r));
+	nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), 0);
+	if (!nlh) {
+		nlmsg_trim(skb, b);
+		return -EMSGSIZE;
+	}
 	nlh->nlmsg_flags = nlmsg_flags;
 
-	r = NLMSG_DATA(nlh);
+	r = nlmsg_data(nlh);
 	BUG_ON(sk->sk_state == TCP_TIME_WAIT);
 
 	if (ext & (1 << (INET_DIAG_MEMINFO - 1)))
@@ -186,7 +190,6 @@ out:
 	return skb->len;
 
 rtattr_failure:
-nlmsg_failure:
 	nlmsg_trim(skb, b);
 	return -EMSGSIZE;
 }
@@ -209,10 +212,15 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 	long tmo;
 	struct inet_diag_msg *r;
 	const unsigned char *previous_tail = skb_tail_pointer(skb);
-	struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq,
-					 unlh->nlmsg_type, sizeof(*r));
+	struct nlmsghdr *nlh = nlmsg_put(skb, pid, seq,
+					 unlh->nlmsg_type, sizeof(*r), 0);
+
+	if (!nlh) {
+		nlmsg_trim(skb, previous_tail);
+		return -EMSGSIZE;
+	}
 
-	r = NLMSG_DATA(nlh);
+	r = nlmsg_data(nlh);
 	BUG_ON(tw->tw_state != TCP_TIME_WAIT);
 
 	nlh->nlmsg_flags = nlmsg_flags;
@@ -247,9 +255,6 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 #endif
 	nlh->nlmsg_len = skb_tail_pointer(skb) - previous_tail;
 	return skb->len;
-nlmsg_failure:
-	nlmsg_trim(skb, previous_tail);
-	return -EMSGSIZE;
 }
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -597,9 +602,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 	struct nlmsghdr *nlh;
 	long tmo;
 
-	nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r));
+	nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), 0);
+	if (!nlh) {
+		nlmsg_trim(skb, b);
+		return -1;
+	}
 	nlh->nlmsg_flags = NLM_F_MULTI;
-	r = NLMSG_DATA(nlh);
+	r = nlmsg_data(nlh);
 
 	r->idiag_family = sk->sk_family;
 	r->idiag_state = TCP_SYN_RECV;
@@ -631,10 +640,6 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 
 	return skb->len;
-
-nlmsg_failure:
-	nlmsg_trim(skb, b);
-	return -1;
 }
 
 static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
@@ -892,7 +897,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	if (nlmsg_attrlen(cb->nlh, hdrlen))
 		bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
 
-	return __inet_diag_dump(skb, cb, (struct inet_diag_req_v2 *)NLMSG_DATA(cb->nlh), bc);
+	return __inet_diag_dump(skb, cb, nlmsg_data(cb->nlh), bc);
 }
 
 static inline int inet_diag_type2proto(int type)
@@ -909,7 +914,7 @@ static inline int inet_diag_type2proto(int type)
 
 static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct inet_diag_req *rc = NLMSG_DATA(cb->nlh);
+	struct inet_diag_req *rc = nlmsg_data(cb->nlh);
 	struct inet_diag_req_v2 req;
 	struct nlattr *bc = NULL;
 	int hdrlen = sizeof(struct inet_diag_req);
@@ -929,7 +934,7 @@ static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *c
 static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
 			       const struct nlmsghdr *nlh)
 {
-	struct inet_diag_req *rc = NLMSG_DATA(nlh);
+	struct inet_diag_req *rc = nlmsg_data(nlh);
 	struct inet_diag_req_v2 req;
 
 	req.sdiag_family = rc->idiag_family;
@@ -996,7 +1001,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 		}
 	}
 
-	return inet_diag_get_exact(skb, h, (struct inet_diag_req_v2 *)NLMSG_DATA(h));
+	return inet_diag_get_exact(skb, h, nlmsg_data(h));
 }
 
 static const struct sock_diag_handler inet_diag_handler = {
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 4/18] decnet: dn_rtmsg: Move away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too.

Also, remove pointless kernel log message.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/decnet/netfilter/dn_rtmsg.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index e6f8862..b8f7f5b 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -42,23 +42,23 @@ static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp)
 	size = NLMSG_SPACE(rt_skb->len);
 	size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
 	skb = alloc_skb(size, GFP_ATOMIC);
-	if (!skb)
-		goto nlmsg_failure;
+	if (!skb) {
+		*errp = -ENOMEM;
+		return NULL;
+	}
 	old_tail = skb->tail;
-	nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh));
+	nlh = nlmsg_put(skb, 0, 0, 0, size - sizeof(*nlh), 0);
+	if (!nlh) {
+		kfree_skb(skb);
+		*errp = -ENOMEM;
+		return NULL;
+	}
 	rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh);
 	rtm->nfdn_ifindex = rt_skb->dev->ifindex;
 	ptr = NFDN_RTMSG(rtm);
 	skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len);
 	nlh->nlmsg_len = skb->tail - old_tail;
 	return skb;
-
-nlmsg_failure:
-	if (skb)
-		kfree_skb(skb);
-	*errp = -ENOMEM;
-	net_err_ratelimited("dn_rtmsg: error creating netlink message\n");
-	return NULL;
 }
 
 static void dnrmg_send_peer(struct sk_buff *skb)
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 3/18] netfilter: ebt_ulog: Move away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too.

Also, free and NULL out skb when nlmsg_put() fails and remove
pointless kernel log message.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/bridge/netfilter/ebt_ulog.c |   23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 5449294..1bd1732 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -145,19 +145,24 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
 
 	if (!ub->skb) {
 		if (!(ub->skb = ulog_alloc_skb(size)))
-			goto alloc_failure;
+			goto unlock;
 	} else if (size > skb_tailroom(ub->skb)) {
 		ulog_send(group);
 
 		if (!(ub->skb = ulog_alloc_skb(size)))
-			goto alloc_failure;
+			goto unlock;
 	}
 
-	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0,
-			size - NLMSG_ALIGN(sizeof(*nlh)));
+	nlh = nlmsg_put(ub->skb, 0, ub->qlen, 0,
+			size - NLMSG_ALIGN(sizeof(*nlh)), 0);
+	if (!nlh) {
+		kfree(ub->skb);
+		ub->skb = NULL;
+		goto unlock;
+	}
 	ub->qlen++;
 
-	pm = NLMSG_DATA(nlh);
+	pm = nlmsg_data(nlh);
 
 	/* Fill in the ulog data */
 	pm->version = EBT_ULOG_VERSION;
@@ -209,14 +214,6 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
 
 unlock:
 	spin_unlock_bh(lock);
-
-	return;
-
-nlmsg_failure:
-	pr_debug("error during NLMSG_PUT. This should "
-		 "not happen, please report to author.\n");
-alloc_failure:
-	goto unlock;
 }
 
 /* this function is registered with the netfilter core */
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 2/18] gdm72xx: Move away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/staging/gdm72xx/netlink_k.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c
index 292af0f..d0cb48a 100644
--- a/drivers/staging/gdm72xx/netlink_k.c
+++ b/drivers/staging/gdm72xx/netlink_k.c
@@ -127,8 +127,12 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
 	}
 
 	seq++;
-	nlh = NLMSG_PUT(skb, 0, seq, type, len);
-	memcpy(NLMSG_DATA(nlh), msg, len);
+	nlh = nlmsg_put(skb, 0, seq, type, len, 0);
+	if (!nlh) {
+		kfree_skb(skb);
+		return -EMSGSIZE;
+	}
+	memcpy(nlmsg_data(nlh), msg, len);
 
 	NETLINK_CB(skb).pid = 0;
 	NETLINK_CB(skb).dst_group = 0;
@@ -144,7 +148,5 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
 		}
 		ret = 0;
 	}
-
-nlmsg_failure:
 	return ret;
 }
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 1/18] connector: Move cn_test.c away from NLMSG_PUT().
From: David Miller @ 2012-06-27  5:02 UTC (permalink / raw)
  To: netdev


And use nlmsg_data() while we're here too.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/connector/cn_test.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
index 7764594..adcca03 100644
--- a/Documentation/connector/cn_test.c
+++ b/Documentation/connector/cn_test.c
@@ -69,9 +69,13 @@ static int cn_test_want_notify(void)
 		return -ENOMEM;
 	}
 
-	nlh = NLMSG_PUT(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh));
+	nlh = nlmsg_put(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh), 0);
+	if (!nlh) {
+		kfree_skb(skb);
+		return -EMSGSIZE;
+	}
 
-	msg = (struct cn_msg *)NLMSG_DATA(nlh);
+	msg = nlmsg_data(nlh);
 
 	memset(msg, 0, size0);
 
@@ -117,11 +121,6 @@ static int cn_test_want_notify(void)
 	pr_info("request was sent: group=0x%x\n", ctl->group);
 
 	return 0;
-
-nlmsg_failure:
-	pr_err("failed to send %u.%u\n", msg->seq, msg->ack);
-	kfree_skb(skb);
-	return -EINVAL;
 }
 #endif
 
-- 
1.7.10.2

^ permalink raw reply related

* [PATCH 0/18] Kill off NLMSG_NEW and NLMSG_PUT
From: David Miller @ 2012-06-27  5:01 UTC (permalink / raw)
  To: netdev


Bad API, embedded gotos, error prone, etc.

Next pass we'll have to deal with the RTA_PUT*() macros
too.

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH v2 -next 4/4] tg3: Add binary sysfs file to export bulk sensor data
From: Michael Chan @ 2012-06-27  5:00 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, nsujir
In-Reply-To: <20120626.210225.1299243479273651339.davem@davemloft.net>

On Tue, 2012-06-26 at 21:02 -0700, David Miller wrote:
> Ben stated merely that a binary attribute existed for sysfs files.  He
> did not, however, say that this is the path down which you should
> implement your feature.

He said that if the data was difficult to parse in the driver, then a
binary sysfs or private ioctl (which we would stay away) would be
appropriate.  There are hundreds of bytes of this data, most of which is
not useful to the user but needed for Lights out management.  It will
greatly bloat the tg3 driver to add code to parse all that data and
export each one separately.
> 
> He, instead, encoraged you to use hwmon and other generic interfaces
> to export this sensor information.

Temperature is useful to the user, defined by hwmon, and easily
extracted so we added this in patch #3.
> 
> I think you were eager to implement things this way because it was the
> least amount of work on your part, and that disappoints me greatly.
> 
Our purpose is not to bloat the tg3 driver unnecessarily. 
> 

^ permalink raw reply

* Re: [PATCH 1/1] connector: use nlmsg_put() instead of NLMSG_PUT() macro.
From: David Miller @ 2012-06-27  4:14 UTC (permalink / raw)
  To: javier.martinez; +Cc: zbr, netdev
In-Reply-To: <1340725284-21698-1-git-send-email-javier.martinez@collabora.co.uk>

From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Date: Tue, 26 Jun 2012 17:41:24 +0200

> The NLMSG_PUT() macro contains a hidden goto which makes the code hard
> to audit and very error prone.
> 
> While been there also use the inline function nlmsg_data() instead of the
> NLMSG_DATA() macro to do explicit type checking.
> 
> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>

Applied, thanks.

I'll work to convert the remaining users, good catch.

^ permalink raw reply

* Re: [PATCH] bridge: Assign rtnl_link_ops to bridge devices created via ioctl (v2)
From: David Miller @ 2012-06-27  4:13 UTC (permalink / raw)
  To: shemminger; +Cc: tgraf, netdev
In-Reply-To: <20120626084845.0578fcb8@nehalam.linuxnetplumber.net>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Tue, 26 Jun 2012 08:48:45 -0700

> This ensures that bridges created with brctl(8) or ioctl(2) directly
> also carry IFLA_LINKINFO when dumped over netlink. This also allows
> to create a bridge with ioctl(2) and delete it with RTM_DELLINK.
> 
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> ---
> v2 - Minor change to Thomas's original patch.
> This is a bug fix, should go to stable as well.

Applied and queued up for -stable, thanks.

^ permalink raw reply

* Re: [patch net-next 0/3] team: couple of fixes
From: David Miller @ 2012-06-27  4:09 UTC (permalink / raw)
  To: jpirko; +Cc: netdev, eric.dumazet, brouer
In-Reply-To: <1340729567-3164-1-git-send-email-jpirko@redhat.com>

From: Jiri Pirko <jpirko@redhat.com>
Date: Tue, 26 Jun 2012 18:52:44 +0200

> Jiri Pirko (3):
>   team: fix team_adjust_ops with regard to enabled ports
>   team: do not allow to map disabled ports
>   team: remove unuset rcu_head field from team_port struct

All looks good, I'll apply this, thanks Jiri.

^ permalink raw reply

* Re: [PATCH v2 net-next 0/7] mac802154: basic wpan class-device support
From: David Miller @ 2012-06-27  4:06 UTC (permalink / raw)
  To: alex.bluesman.smirnov; +Cc: netdev, dbaryshkov
In-Reply-To: <1340702694-24706-1-git-send-email-alex.bluesman.smirnov@gmail.com>

From: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Date: Tue, 26 Jun 2012 13:24:47 +0400

> Cover letter:
> =============
> this patch-set binds the IEEE 802.15.4 Linux stack to the radio
> transceivers. A new device-class called "wpan" is added. It represents
> an interface for the radio device drivers to communicate the information
> with Linux networking stack.
> 
> This is the basic support, only data-packets transmission is supported
> (no MAC-layer specific commands support included here). But this set
> represents a necessary minimum to implement IEEE 802.15.4 standard features
> and test them on real hardware.
> 
> To test/try the wpan device-class the Atmel RF230 transceiver driver
> included in this patch set. The how-to instructions are available in wiki
> at the linux-wsn project site: http://code.google.com/p/linux-wsn/

All applied, thanks.

^ permalink raw reply

* Re: [PATCH] sctp: be mroe restrictive in transport selection on bundled sacks
From: David Miller @ 2012-06-27  4:05 UTC (permalink / raw)
  To: nhorman; +Cc: netdev, vyasevich, linux-sctp
In-Reply-To: <1340742704-2192-1-git-send-email-nhorman@tuxdriver.com>

From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 26 Jun 2012 16:31:44 -0400

> @@ -240,15 +240,20 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
>  	 */
>  	if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
>  	    !pkt->has_cookie_echo) {
> -		struct sctp_association *asoc;
>  		struct timer_list *timer;
> -		asoc = pkt->transport->asoc;
> +		struct sctp_association *asoc = pkt->transport->asoc;
> +		struct sctp_transport *trans;
> +
>  		timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
>  
>  		/* If the SACK timer is running, we have a pending SACK */
>  		if (timer_pending(timer)) {
>  			struct sctp_chunk *sack;
>  			asoc->a_rwnd = asoc->rwnd;
> +
> +			if (chunk->transport && !chunk->transport->moved_ctsn)
> +				return retval;
> +
>  			sack = sctp_make_sack(asoc);
>  			if (sack) {
>  				retval = sctp_packet_append_chunk(pkt, sack);

The new local variable 'trans' seems to be unused.

^ permalink raw reply

* Re: [PATCH v2 -next 4/4] tg3: Add binary sysfs file to export bulk sensor data
From: David Miller @ 2012-06-27  4:02 UTC (permalink / raw)
  To: mchan; +Cc: netdev, nsujir
In-Reply-To: <1340758415-10746-4-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Tue, 26 Jun 2012 17:53:35 -0700

> The bulk of the sensor data is exported as binary data to sysfs for
> userspace access.
> 
> [binary sysfs suggested by Ben Hutchings <bhutchings@solarflare.com>]
> 
> Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
> Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
> Signed-off-by: Michael Chan <mchan@broadcom.com>

Ben stated merely that a binary attribute existed for sysfs files.  He
did not, however, say that this is the path down which you should
implement your feature.

He, instead, encoraged you to use hwmon and other generic interfaces
to export this sensor information.

I think you were eager to implement things this way because it was the
least amount of work on your part, and that disappoints me greatly.

^ permalink raw reply

* Re: [PATCH net-next] udp: Add socket early demux support
From: David Miller @ 2012-06-27  3:59 UTC (permalink / raw)
  To: xiaosuo
  Cc: subramanian.vijay, netdev, shemminger, eric.dumazet,
	alexander.h.duyck
In-Reply-To: <CABa6K_G1+7xvPkveRWEWCpAJcf8gK4=zKwXGtOxJLW2wTCCvMA@mail.gmail.com>

From: Changli Gao <xiaosuo@gmail.com>
Date: Wed, 27 Jun 2012 10:29:19 +0800

> How about implementing the whole early demux infrastructure on
> iptables/netfilter like rpfilter and TPROXY, then users have more
> controls.

Sorry, no.

^ permalink raw reply

* RE: [PATCH] r8169: RxConfig hack for the 8168evl.
From: hayeswang @ 2012-06-27  2:43 UTC (permalink / raw)
  To: 'Francois Romieu'; +Cc: netdev, thomas.pi
In-Reply-To: <20120626092251.GA1854@electric-eye.fr.zoreil.com>

> From: Francois Romieu [mailto:romieu@fr.zoreil.com] 
[...]
> > The definition of the IO 0x44 bit 14 is opposite for new chips.
> > For 8111C, 0 means fetching one Rx descriptor, and 1 means fetching
> > multi-descriptors.
> > For 8111D and the later chips, 0 means fetching 
> multi-descriptors, and 1 means
> > fetching one Rx descriptor.
> 
> Ok. Is there much point fetching one Rx descriptor versus several ?

I just know fetching several Rx descriptor has better performance if the
decsriptors are enough. However, I have no idea about how the hardware
implements it.

> 
> [...]
> > The CFG_METHOD_16 is the internal test chip. We don't have 
> mass production for
> > it. Even it could be removed from driver. I don't think the 
> kernel have to
> > support it.
> 
> Ok.
> 
> There seem to be a few differences for the CFG_METHOD_16 
> chipset between
> the kernel driver and Realtek's own. I have noticed the points below.
> Should some of those be included ?

I think you should reference the CFG_METHOD_17, not CFG_METHOD_16.

[...] 
> - 0x7cf00000 / 0x2c900000 is a Realtek internal, test-only chipset
Should be 0x7cf00000 / 0x2c800000

[...] 
> rtl8169_get_mac_version(struct rtl8169_private *tp,
>  		{ 0x7cf00000, 0x48000000,	RTL_GIGA_MAC_VER_35 },
>  
>  		/* 8168E family. */
> -		{ 0x7c800000, 0x2c800000,	RTL_GIGA_MAC_VER_34 },
> +		{ 0x7cf00000, 0x2c800000,	RTL_GIGA_MAC_VER_34 },

Should be	{ 0x7cf00000, 0x2c900000,	RTL_GIGA_MAC_VER_34 },

[...] 
> @@ -4797,6 +4826,9 @@ static void rtl_hw_start_8168e_2(struct 
> rtl8169_private *tp)
>  
>  	RTL_W8(MaxTxPacketSize, EarlySize);
>  
> +	RTL_W8(0xf2, (RTL_R8(0xf2) & ~0x02) | 0x05);

Please remove this line. We verify it would case kernel panic.

[...] 

 
Best Regards,
Hayes

^ permalink raw reply

* RE: Unknown chipsets from Realtek's 8168 driver
From: hayeswang @ 2012-06-27  2:43 UTC (permalink / raw)
  To: 'Francois Romieu'; +Cc: netdev
In-Reply-To: <20120626102635.GB1854@electric-eye.fr.zoreil.com>

> From: Francois Romieu [mailto:romieu@fr.zoreil.com] 
> 
>   there appears to remain unknown chipsets in Realtek's own driver.
> Namely:
> - CFG_METHOD_21
> - CFG_METHOD_22

I am adding the two now. However, there are many differences for them, so I have
to think how to do.

> - CFG_METHOD_23

The settings for this one are not final yet. Please skip it.
> 
> Should support for some of those be added to the kernel driver ?
> 
> If so it would make sense to plan for those now as there are still a
> couple of weeks ahead before the window for -next closes and 
> everything
> experiences more than 2 months of delay. You will find some incomplete
> stuff below. Feel free to use or ignore it.

Thanks. I would complete it as soon as possible.

 
Best Regards,
Hayes

^ permalink raw reply

* Re: [PATCH net-next] udp: Add socket early demux support
From: Changli Gao @ 2012-06-27  2:29 UTC (permalink / raw)
  To: David Miller
  Cc: subramanian.vijay, netdev, shemminger, eric.dumazet,
	alexander.h.duyck
In-Reply-To: <20120626.143401.445148198931339546.davem@davemloft.net>

On Wed, Jun 27, 2012 at 5:34 AM, David Miller <davem@davemloft.net> wrote:
>
> You can't do this.
>
> If the UDP socket has wildcards, that means the source address of the
> route will not be validated.  This means we will start accepting
> spoofed packets.  It also means the route you are caching is going
> to be the wrong route since the keys are variable.
>
> You can only do an early demux where all the keys are fully specified
> and there are no wildcards.  That why for TCP we only early demux for
> established sockets.

How about implementing the whole early demux infrastructure on
iptables/netfilter like rpfilter and TPROXY, then users have more
controls.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: HSR: How to set IF_OPER_LOWERLAYERDOWN?
From: Arvid Brodin @ 2012-06-27  1:42 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev@vger.kernel.org, Javier Boticario, Bruno Ferreira
In-Reply-To: <20120626153324.455c6081@nehalam.linuxnetplumber.net>

On 2012-06-27 00:33, Stephen Hemminger wrote:
> On Tue, 26 Jun 2012 22:28:51 +0000
> Arvid Brodin <Arvid.Brodin@xdin.com> wrote:
> 
>> Hi,
>>
>> According to Documentation/networking/operstates.txt a network interface have an
>> operational state and an administrative state.
>>
>> If I understand things correctly the administrative state is the desired state set by
>> userspace, and the operational state is the actual state which depends on things like the
>> administrative state, whether a carrier is present, or (for virtual interfaces lite VLAN)
>> whether the lower interface is available.
>>
>>
>> In the driver I'm writing (for the "HSR" redundancy protocol) a hsr (virtual) interface is
>> useable as long as any of its (physical) slaves are useable. I.e. the operstate of a hsr
>> device might be set like this:
>>
>> void hsr_set_operstate()
>> {
>> 	if (!is_admin_up(hsr_dev)) /* Check IFF_UP */ {
>> 		set_operstate(hsr_dev, IF_OPER_DOWN);
>> 		return;
>> 	}
>>
>> 	if (is_operstate_up(slave1) || is_operstate_up(slave2)) /* Check IF_OPER_UP */
>> 		set_operstate(hsr_dev, IF_OPER_UP);
>> 	else
>> 		set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
>> }
> 
> 
> According to 802.1X example in documentation to set it down you need to set IF_OPER_DORMANT
> not IF_OPER_LOWERLAYERDOWN.  Probably a kernel bug in there somwhere.
> 

Hmm... if you're referring to the example in Documentation/networking/operstates.txt it
seems to me that the usage of IF_OPER_DORMANT there is in compliance with RFC2863 - i.e.
the device is waiting for some kind of handshake to finish. I don't think it has anything
to do with taking the device down?

Oh, and I see now that set_operstate() is called from do_setlink() in
net/core/rtnetlink.c, which means this function is used to set operstate from userspace.
The limitations then fits with the description in operstates.txt, and this function is
probably not meant to set an interface's operational state from within the kernel. I wrote
my own hsr_set_operstate that accepts any values, and it seems to work... (?)


Is there a way to get notifications when an interface's operational state change?
NETDEV_CHANGE seems to trigger on carrier change, and NETDEV_UP/DOWN triggers when the
administrative state changes - is there something similar for operational state?

(Unfortunately NETDEV_UP/DOWN triggers before the operational state for the interface in
question changes accordingly, so it's not possible to just check dev->operstate in the
handler for these messages. NETDEV_CHANGE seems to trigger after the interface's
operational state has been changed, though.)

-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Jan Stenbecks Torg 17 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: [PATCH 01/13] netfilter: fix problem with proto register
From: Gao feng @ 2012-06-27  1:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netdev, netfilter-devel
In-Reply-To: <20120626143620.GA11165@1984>

于 2012年06月26日 22:36, Pablo Neira Ayuso 写道:
> On Tue, Jun 26, 2012 at 11:40:14AM +0800, Gao feng wrote:
>> Hi Pablo:
>>
>> 于 2012年06月25日 19:12, Pablo Neira Ayuso 写道:
>>> On Thu, Jun 21, 2012 at 10:36:38PM +0800, Gao feng wrote:
>>>> before commit 2c352f444ccfa966a1aa4fd8e9ee29381c467448
>>>> (netfilter: nf_conntrack: prepare namespace support for
>>>> l4 protocol trackers), we register sysctl before register
>>>> protos, so if sysctl is registered faild, the protos will
>>>> not be registered.
>>>>
>>>> but now, we register protos first, and when register
>>>> sysctl failed, we can use protos too, it's different
>>>> from before.
>>>
>>> No, this has to be an all-or-nothing game. If one fails, everything
>>> else that you've registered has to be unregistered.
>>
>> indeed,this is an all-or-nothing game right now,please look at the ipv4_net_init,
>> when we register nf_conntrack_l3proto_ipv4 failed,we will unregister the already
>> registered l4protoes, and in nf_conntrack_l4proto_unregister,we will call
>> nf_ct_l4proto_unregister_sysctl to free the sysctl table.
> 
> I see proto->init_net allocates in->ctl_table, then
> nf_ct_l3proto_register_sysctl release it if it fails. I got confused
> because I did not see where that memory was being freed. Then, it's
> good.
> 
> Still one more thing:
> 
>>>> so change to register sysctl before register protos.
>>>>
>>>> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
>>>> ---
>>>>  net/netfilter/nf_conntrack_proto.c |   36 +++++++++++++++++++++++-------------
>>>>  1 files changed, 23 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
>>>> index 1ea9194..9bd88aa 100644
>>>> --- a/net/netfilter/nf_conntrack_proto.c
>>>> +++ b/net/netfilter/nf_conntrack_proto.c
>>>> @@ -253,18 +253,23 @@ int nf_conntrack_l3proto_register(struct net *net,
>>>>  {
>>>>  	int ret = 0;
>>>>  
>>>> -	if (net == &init_net)
>>>> -		ret = nf_conntrack_l3proto_register_net(proto);
>>>> +	if (proto->init_net) {
> 
> I think proto->init_net has to be mandatory since all protocol support
> pernet already. We can add BUG_ON at the beginning of the function if
> proto->init_net is not defined.
> 

we can add BUG_ON at nf_conntrack_l4proto_register,because all of the l4protoes
have the init_net function.

BUT nf_conntrack_l3proto_ipv6 doesn't have init_net function,because this proto
doesn't have pernet data, and nf_conntrack_l3proto_ipv4 has pernet data only when
CONFIG_NF_CONNTRACK_PROC_COMPAT is configured.

> I can manually add that to the patch if you see no inconvenience with
> it.
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: [PATCH 04/13] netfilter: regard users as refcount for l4proto's per-net data
From: Gao feng @ 2012-06-27  1:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netdev, netfilter-devel
In-Reply-To: <20120626144708.GB11165@1984>

于 2012年06月26日 22:47, Pablo Neira Ayuso 写道:
> On Tue, Jun 26, 2012 at 11:58:45AM +0800, Gao feng wrote:
>> Hi Pablo:
>> 于 2012年06月25日 19:20, Pablo Neira Ayuso 写道:
>>> On Thu, Jun 21, 2012 at 10:36:41PM +0800, Gao feng wrote:
>>>> Now, nf_proto_net's users is confusing.
>>>> we should regard it as the refcount for l4proto's per-net data,
>>>> because maybe there are two l4protos use the same per-net data.
>>>>
>>>> so increment pn->users when nf_conntrack_l4proto_register
>>>> success, and decrement it for nf_conntrack_l4_unregister case.
>>>>
>>>> because nf_conntrack_l3proto_ipv[4|6] don't use the same per-net
>>>> data,so we don't need to add a refcnt for their per-net data.
>>>>
>>>> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
>>>> ---
>>>>  net/netfilter/nf_conntrack_proto.c |   76 ++++++++++++++++++++++--------------
>>>>  1 files changed, 46 insertions(+), 30 deletions(-)
>>>>
>>>> diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
>>>> index 9d6b6ab..63612e6 100644
>>>> --- a/net/netfilter/nf_conntrack_proto.c
>>>> +++ b/net/netfilter/nf_conntrack_proto.c
>>> [...]
>>>> @@ -458,23 +446,32 @@ int nf_conntrack_l4proto_register(struct net *net,
>>>>  				  struct nf_conntrack_l4proto *l4proto)
>>>>  {
>>>>  	int ret = 0;
>>>> +	struct nf_proto_net *pn = NULL;
>>>>  
>>>>  	if (l4proto->init_net) {
>>>>  		ret = l4proto->init_net(net, l4proto->l3proto);
>>>>  		if (ret < 0)
>>>> -			return ret;
>>>> +			goto out;
>>>>  	}
>>>>  
>>>> -	ret = nf_ct_l4proto_register_sysctl(net, l4proto);
>>>> +	pn = nf_ct_l4proto_net(net, l4proto);
>>>> +	if (pn == NULL)
>>>> +		goto out;
>>>
>>> Same thing here, we're leaking memory allocated by l4proto->init_net.
>>
>> if pn is NULL,init_net can't allocate memory for pn->ctl_table.
>> So I think it's not memory leak here.
> 
> Sorry, I meant to say the line below. But we've already clarified
> this in patch 1/1.
> 
>>>> +	ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto);
>>>>  	if (ret < 0)
>>>> -		return ret;
>>>> +		goto out;
>>>>  
>>>>  	if (net == &init_net) {
>>>>  		ret = nf_conntrack_l4proto_register_net(l4proto);
>>>> -		if (ret < 0)
>>>> -			nf_ct_l4proto_unregister_sysctl(net, l4proto);
>>>> +		if (ret < 0) {
>>>> +			nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
>>>> +			goto out;
>>>
>>> Better replace the two lines above by:
>>>
>>> goto out_register_net;
>>>
>>> and then...
>>>
>>>> +		}
>>>>  	}
>>>>  
>>>> +	pn->users++;
>>>
>>> out_register_net:
>>>         nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
>>>
>>>> +out:
>>>>  	return ret;
>>>
>>> I think that this change is similar to patch 1/1, I think you should
>>> send it as a separated patch.
>>>
>>
>> Yes, It looks better.
>> should I change this and rebase whole patchset or
>> maybe you just apply this patchset and then I send a cleanup patch to do this?
> 
> This patch includes changes that are not included in the description,
> so you have two choices:
> 
> 1) You resend me this patch with appropriate description (including
> the fact that you're fixing the same thing that patch 1/1 does). This
> option still I don't like too much, since making two different things
> in one single patch is nasty, but well if you push me...

Sorry, I don't know which the same thing I fixed in this patch and 1/13 patch.
the 1/13 patch only change the proto's registration order. and this patch doesn't
change the registration order.

This patch is used to try to make variable "users" clear.

> 
> 2) you split the patch in two, with the appropriate descriptions each
> and you'll make me happy.
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 -next 3/4] tg3: Add hwmon support
From: Michael Chan @ 2012-06-27  0:53 UTC (permalink / raw)
  To: davem; +Cc: netdev, nsujir
In-Reply-To: <1340758415-10746-2-git-send-email-mchan@broadcom.com>

Some tg3 devices have management firmware that can export sensor data such
as temperature and other real time diagnostics data.  Export temperature
sensor reading via hwmon sysfs.

[hwmon interface suggested by Ben Hutchings <bhutchings@solarflare.com>]

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c |  189 +++++++++++++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/tg3.h |   63 ++++++++++++
 2 files changed, 252 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 693a584..6b51e3a 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -44,6 +44,10 @@
 #include <linux/prefetch.h>
 #include <linux/dma-mapping.h>
 #include <linux/firmware.h>
+#if IS_ENABLED(CONFIG_HWMON)
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#endif
 
 #include <net/checksum.h>
 #include <net/ip.h>
@@ -9538,6 +9542,182 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 	return tg3_reset_hw(tp, reset_phy);
 }
 
+static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir)
+{
+	int i;
+
+	for (i = 0; i < TG3_SD_NUM_RECS; i++, ocir++) {
+		u32 off = i * TG3_OCIR_LEN, len = TG3_OCIR_LEN;
+
+		tg3_ape_scratchpad_read(tp, (u32 *) ocir, off, len);
+		off += len;
+
+		if (ocir->signature != TG3_OCIR_SIG_MAGIC ||
+		    !(ocir->version_flags & TG3_OCIR_FLAG_ACTIVE))
+			memset(ocir, 0, TG3_OCIR_LEN);
+	}
+}
+
+#if IS_ENABLED(CONFIG_HWMON)
+/* sysfs attributes for hwmon */
+static ssize_t tg3_show_temp(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct tg3 *tp = netdev_priv(netdev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	u32 temperature;
+
+	spin_lock_bh(&tp->lock);
+	tg3_ape_scratchpad_read(tp, &temperature, attr->index,
+				sizeof(temperature));
+	spin_unlock_bh(&tp->lock);
+	return sprintf(buf, "%u\n", temperature);
+}
+
+#define TG3_TEMP_SENSOR_OFFSET 0xd4
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tg3_show_temp, NULL,
+			  TG3_TEMP_SENSOR_OFFSET);
+static struct attribute *tg3_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tg3_group = {
+	.attrs = tg3_attributes,
+};
+
+static void tg3_hwmon_open(struct tg3 *tp)
+{
+	int err;
+	struct tg3_sd *sd = tp->sd;
+	struct pci_dev *pdev = tp->pdev;
+
+	/* Register hwmon sysfs hooks */
+	err = sysfs_create_group(&pdev->dev.kobj, &tg3_group);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n");
+		return;
+	}
+
+	sd->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(sd->hwmon_dev)) {
+		sd->hwmon_dev = NULL;
+		dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n");
+		sysfs_remove_group(&pdev->dev.kobj, &tg3_group);
+	}
+}
+#endif
+
+static int tg3_sd_init(struct tg3 *tp)
+{
+	int i;
+	u32 size = 0;
+	struct tg3_sd *sd;
+	struct tg3_ocir ocirs[TG3_SD_NUM_RECS];
+
+	if (!tg3_flag(tp, ENABLE_APE))
+		return 0;
+
+	tp->sd = kzalloc(sizeof(struct tg3_sd), GFP_KERNEL);
+	if (!tp->sd)
+		return -ENOMEM;
+
+	sd = tp->sd;
+	tg3_sd_scan_scratchpad(tp, ocirs);
+
+	for (i = 0; i < TG3_SD_NUM_RECS; i++) {
+		u32 val = 1;
+		struct tg3_sd_record *rec = &sd->rec[i];
+
+		if (!ocirs[i].src_data_length)
+			continue;
+
+		rec->hdr_len = ocirs[i].src_hdr_length;
+		rec->hdr_off = ocirs[i].src_hdr_offset;
+		rec->data_len = ocirs[i].src_data_length;
+		rec->data_off = ocirs[i].src_data_offset;
+
+		size += ocirs[i].src_hdr_length;
+		size += ocirs[i].src_data_length;
+
+		rec->utmr_off = i * TG3_OCIR_LEN + TG3_OCIR_UPDATE_TMR_OFF;
+		rec->rtmr_off = i * TG3_OCIR_LEN + TG3_OCIR_REFRESH_TMR_OFF;
+		rec->rtmr_int = ocirs[i].refresh_int;
+
+		/* Initialize utmr_off to non-zero so that we read the region
+		 * at least once */
+		if (tg3_ape_scratchpad_write(tp, rec->utmr_off, &val, 4))
+			netdev_err(tp->dev, "write scratchpad error\n");
+
+		ocirs[i].update_tmr = 0;
+	}
+	if (!size) {
+		kfree(sd);
+		tp->sd = NULL;
+		return -ENODEV;
+	}
+
+	size += sizeof(ocirs);
+
+	sd->buf = kzalloc(size, GFP_KERNEL);
+	if (!sd->buf) {
+		kfree(sd);
+		tp->sd = NULL;
+		return -ENOMEM;
+	}
+
+	sd->buf_size = size;
+	memcpy(sd->buf, ocirs, sizeof(ocirs));
+
+	sd->sd_flags_off = 2 * TG3_OCIR_LEN + (tp->pci_fn * sizeof(u32)) +
+				TG3_OCIR_PORT0_FLGS_OFF;
+
+	return 0;
+}
+
+static void tg3_sd_fini(struct tg3 *tp)
+{
+	struct tg3_sd *sd = tp->sd;
+
+	if (!sd)
+		return;
+
+	kfree(sd->buf);
+	kfree(sd);
+	tp->sd = NULL;
+}
+
+static void tg3_sd_close(struct tg3 *tp)
+{
+	struct tg3_sd *sd = tp->sd;
+
+	if (!sd)
+		return;
+
+#if IS_ENABLED(CONFIG_HWMON)
+	if (sd->hwmon_dev) {
+		hwmon_device_unregister(sd->hwmon_dev);
+		sd->hwmon_dev = NULL;
+		sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group);
+	}
+#endif
+}
+
+static int tg3_sd_open(struct tg3 *tp)
+{
+	struct tg3_sd *sd = tp->sd;
+
+	if (!sd)
+		return -ENODEV;
+
+#if IS_ENABLED(CONFIG_HWMON)
+	tg3_hwmon_open(tp);
+#endif
+	return 0;
+}
+
 #define TG3_STAT_ADD32(PSTAT, REG) \
 do {	u32 __val = tr32(REG); \
 	(PSTAT)->low += __val; \
@@ -10246,6 +10426,8 @@ static int tg3_open(struct net_device *dev)
 
 	tg3_phy_start(tp);
 
+	tg3_sd_open(tp);
+
 	tg3_full_lock(tp, 0);
 
 	tg3_timer_start(tp);
@@ -10295,6 +10477,8 @@ static int tg3_close(struct net_device *dev)
 
 	tg3_timer_stop(tp);
 
+	tg3_sd_close(tp);
+
 	tg3_phy_stop(tp);
 
 	tg3_full_lock(tp, 1);
@@ -15945,6 +16129,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
 	tg3_timer_init(tp);
 
+	tg3_sd_init(tp);
+
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Cannot register net device, aborting\n");
@@ -16039,6 +16225,9 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
 		}
 
 		unregister_netdev(dev);
+
+		tg3_sd_fini(tp);
+
 		if (tp->aperegs) {
 			iounmap(tp->aperegs);
 			tp->aperegs = NULL;
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index d167a1c..a3a51c9 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2379,6 +2379,18 @@
 #define TG3_APE_LOCK_PHY3		5
 #define TG3_APE_LOCK_GPIO		7
 
+/* SD flags */
+#define TG3_OCIR_SIG_MAGIC		0x5253434f
+#define TG3_OCIR_FLAG_ACTIVE		0x00000001
+
+#define TG3_OCIR_DRVR_FEAT_CSUM		0x00000001
+#define TG3_OCIR_DRVR_FEAT_TSO		0x00000002
+#define TG3_OCIR_DRVR_FEAT_MASK		0xff
+
+#define TG3_OCIR_REFRESH_TMR_OFF	0x00000008
+#define TG3_OCIR_UPDATE_TMR_OFF		0x0000000c
+#define TG3_OCIR_PORT0_FLGS_OFF		0x0000002c
+
 #define TG3_EEPROM_SB_F1R2_MBA_OFF	0x10
 
 
@@ -2677,6 +2689,55 @@ struct tg3_hw_stats {
 	u8				__reserved4[0xb00-0x9c8];
 };
 
+#define TG3_SD_NUM_RECS			3
+#define TG3_OCIR_LEN			(sizeof(struct tg3_ocir))
+
+
+struct tg3_ocir {
+	u32				signature;
+	u16				version_flags;
+	u16				refresh_int;
+	u32				refresh_tmr;
+	u32				update_tmr;
+	u32				dst_base_addr;
+	u16				src_hdr_offset;
+	u16				src_hdr_length;
+	u16				src_data_offset;
+	u16				src_data_length;
+	u16				dst_hdr_offset;
+	u16				dst_data_offset;
+	u16				dst_reg_upd_offset;
+	u16				dst_sem_offset;
+	u32				reserved1[2];
+	u32				port0_flags;
+	u32				port1_flags;
+	u32				port2_flags;
+	u32				port3_flags;
+	u32				reserved2[1];
+};
+
+struct tg3_sd_record {
+	u16				hdr_off;
+	u16				hdr_len;
+	u16				data_off;
+	u16				data_len;
+	u32				updated_seq;
+	u16				utmr_off;
+	u16				rtmr_off;
+	u32				rtmr_val;
+	u16				rtmr_int;
+};
+
+struct tg3_sd {
+#if IS_ENABLED(CONFIG_HWMON)
+	struct device			*hwmon_dev;
+#endif
+	struct tg3_sd_record		rec[TG3_SD_NUM_RECS];
+	u32				sd_flags_off;
+	int				buf_size;
+	u8				*buf;
+};
+
 /* 'mapping' is superfluous as the chip does not write into
  * the tx/rx post rings so we could just fetch it from there.
  * But the cache behavior is better how we are doing it now.
@@ -3212,6 +3273,8 @@ struct tg3 {
 	const char			*fw_needed;
 	const struct firmware		*fw;
 	u32				fw_len; /* includes BSS */
+
+	struct tg3_sd			*sd;
 };
 
 #endif /* !(_T3_H) */
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 -next 4/4] tg3: Add binary sysfs file to export bulk sensor data
From: Michael Chan @ 2012-06-27  0:53 UTC (permalink / raw)
  To: davem; +Cc: netdev, nsujir
In-Reply-To: <1340758415-10746-3-git-send-email-mchan@broadcom.com>

The bulk of the sensor data is exported as binary data to sysfs for
userspace access.

[binary sysfs suggested by Ben Hutchings <bhutchings@solarflare.com>]

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c |  130 ++++++++++++++++++++++++++++++++++-
 1 files changed, 129 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 6b51e3a..109a7cb 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -9542,6 +9542,48 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 	return tg3_reset_hw(tp, reset_phy);
 }
 
+static void tg3_sd_xfer(struct tg3 *tp, u32 off, u32 size)
+{
+	struct tg3_sd *sd = tp->sd;
+
+	if (!size)
+		return;
+
+	tg3_ape_scratchpad_read(tp, (u32 *) &sd->buf[off], off, size);
+}
+
+static void tg3_sd_update_host(struct tg3 *tp, struct tg3_sd_record *rec)
+{
+	tg3_sd_xfer(tp, rec->data_off, rec->data_len);
+	tg3_sd_xfer(tp, rec->hdr_off, rec->hdr_len);
+}
+
+static void tg3_sd_update_drvflags(struct tg3 *tp, bool unloading)
+{
+	struct tg3_sd *sd = tp->sd;
+	u32 flags;
+
+	if (!sd || !sd->sd_flags_off)
+		return;
+
+	tg3_ape_scratchpad_read(tp, &flags, sd->sd_flags_off, 4);
+
+	flags &= ~TG3_OCIR_DRVR_FEAT_MASK;
+
+	if (!unloading) {
+		u32 mask = NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM;
+
+		if (tp->dev->features & mask)
+			flags |= TG3_OCIR_DRVR_FEAT_CSUM;
+
+		if (tp->dev->features & NETIF_F_ALL_TSO)
+			flags |= TG3_OCIR_DRVR_FEAT_TSO;
+	}
+
+	tg3_ape_scratchpad_write(tp, sd->sd_flags_off, &flags, 4);
+}
+
 static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir)
 {
 	int i;
@@ -9610,6 +9652,32 @@ static void tg3_hwmon_open(struct tg3 *tp)
 }
 #endif
 
+static ssize_t tg3_sd_read(struct file *filep, struct kobject *kobj,
+			   struct bin_attribute *attr, char *buff,
+			   loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct tg3 *tp = netdev_priv(netdev);
+	struct tg3_sd *sd = tp->sd;
+	int len = size < sd->buf_size ? size : sd->buf_size;
+
+	if (offset > sd->buf_size)
+		return 0;
+
+	if (offset + len > sd->buf_size)
+		len = sd->buf_size - offset;
+
+	memcpy(buff, sd->buf + offset, len);
+	return len;
+}
+
+static struct bin_attribute bin_attr_tg3_sd = {
+	.attr = {.name = "tg3_sd", .mode = S_IRUSR},
+	.read = tg3_sd_read,
+};
+
 static int tg3_sd_init(struct tg3 *tp)
 {
 	int i;
@@ -9674,6 +9742,7 @@ static int tg3_sd_init(struct tg3 *tp)
 	sd->sd_flags_off = 2 * TG3_OCIR_LEN + (tp->pci_fn * sizeof(u32)) +
 				TG3_OCIR_PORT0_FLGS_OFF;
 
+	tg3_sd_update_drvflags(tp, false);
 	return 0;
 }
 
@@ -9684,6 +9753,8 @@ static void tg3_sd_fini(struct tg3 *tp)
 	if (!sd)
 		return;
 
+	tg3_sd_update_drvflags(tp, true);
+
 	kfree(sd->buf);
 	kfree(sd);
 	tp->sd = NULL;
@@ -9703,6 +9774,7 @@ static void tg3_sd_close(struct tg3 *tp)
 		sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group);
 	}
 #endif
+	device_remove_bin_file(&tp->pdev->dev, &bin_attr_tg3_sd);
 }
 
 static int tg3_sd_open(struct tg3 *tp)
@@ -9715,7 +9787,7 @@ static int tg3_sd_open(struct tg3 *tp)
 #if IS_ENABLED(CONFIG_HWMON)
 	tg3_hwmon_open(tp);
 #endif
-	return 0;
+	return device_create_bin_file(&tp->pdev->dev, &bin_attr_tg3_sd);
 }
 
 #define TG3_STAT_ADD32(PSTAT, REG) \
@@ -9803,6 +9875,59 @@ static void tg3_chk_missed_msi(struct tg3 *tp)
 	}
 }
 
+
+static void tg3_sd_timer(struct tg3 *tp)
+{
+	int i;
+	u32 val;
+	struct tg3_sd *sd = tp->sd;
+	struct tg3_ocir *ocirp = (struct tg3_ocir *) sd->buf;
+
+	if (!netif_running(tp->dev))
+		return;
+
+	for (i = 0; i < TG3_SD_NUM_RECS; i++, ocirp++) {
+		struct tg3_sd_record *rec = &sd->rec[i];
+
+		if (!rec->data_len)
+			continue;
+
+		tg3_ape_scratchpad_read(tp, &val, rec->utmr_off, 4);
+		/* Check if data has changed */
+		if (val) {
+
+			if (!rec->rtmr_int) {
+				tg3_sd_update_host(tp, rec);
+
+				rec->updated_seq++;
+				ocirp->update_tmr = rec->updated_seq;
+			} else {
+				u32 curr;
+				unsigned long tgt;
+
+				curr = tg3_ape_read32(tp, TG3_APE_STICKY_TMR);
+				tgt = rec->rtmr_val + rec->rtmr_int;
+				if (time_after((unsigned long) curr, tgt)) {
+					tg3_sd_update_host(tp, rec);
+
+					rec->rtmr_val = curr;
+					tg3_ape_scratchpad_write(tp,
+							rec->rtmr_off,
+							&curr, 4);
+
+					rec->updated_seq++;
+					ocirp->update_tmr = rec->updated_seq;
+				}
+			}
+
+			val = 0;
+			if (tg3_ape_scratchpad_write(tp, rec->utmr_off,
+						     &val, 4))
+				netdev_err(tp->dev, "write scratchpad error\n");
+		}
+	}
+}
+
 static void tg3_timer(unsigned long __opaque)
 {
 	struct tg3 *tp = (struct tg3 *) __opaque;
@@ -9841,6 +9966,9 @@ static void tg3_timer(unsigned long __opaque)
 		if (tg3_flag(tp, 5705_PLUS))
 			tg3_periodic_fetch_stats(tp);
 
+		if (tp->sd)
+			tg3_sd_timer(tp);
+
 		if (tp->setlpicnt && !--tp->setlpicnt)
 			tg3_phy_eee_enable(tp);
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 -next 2/4] tg3: Add APE scratchpad read and write functions.
From: Michael Chan @ 2012-06-27  0:53 UTC (permalink / raw)
  To: davem; +Cc: netdev, nsujir
In-Reply-To: <1340758415-10746-1-git-send-email-mchan@broadcom.com>

From: Matt Carlson <mcarlson@broadcom.com>

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c |  137 +++++++++++++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/tg3.h |   10 ++-
 2 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 7c515db..693a584 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -751,6 +751,143 @@ static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)
 	return timeout_us ? 0 : -EBUSY;
 }
 
+static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us)
+{
+	u32 i, apedata;
+
+	for (i = 0; i < timeout_us / 10; i++) {
+		apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+
+		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+			break;
+
+		udelay(10);
+	}
+
+	return i == timeout_us / 10;
+}
+
+int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len)
+{
+	int err;
+	u32 i, bufoff, msgoff, maxlen, apedata;
+
+	if (!tg3_flag(tp, APE_HAS_NCSI))
+		return 0;
+
+	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+	if (apedata != APE_SEG_SIG_MAGIC)
+		return -ENODEV;
+
+	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+	if (!(apedata & APE_FW_STATUS_READY))
+		return -EAGAIN;
+
+	bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) +
+		 TG3_APE_SHMEM_BASE;
+	msgoff = bufoff + 2 * sizeof(u32);
+	maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN);
+
+	while (len) {
+		u32 length;
+
+		/* Cap xfer sizes to scratchpad limits. */
+		length = (len > maxlen) ? maxlen : len;
+		len -= length;
+
+		apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+		if (!(apedata & APE_FW_STATUS_READY))
+			return -EAGAIN;
+
+		/* Wait for up to 1 msec for APE to service previous event. */
+		err = tg3_ape_event_lock(tp, 1000);
+		if (err)
+			return err;
+
+		apedata = APE_EVENT_STATUS_DRIVER_EVNT |
+			  APE_EVENT_STATUS_SCRTCHPD_READ |
+			  APE_EVENT_STATUS_EVENT_PENDING;
+		tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata);
+
+		tg3_ape_write32(tp, bufoff, base_off);
+		tg3_ape_write32(tp, bufoff + sizeof(u32), length);
+
+		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+		tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+
+		base_off += length;
+
+		if (tg3_ape_wait_for_event(tp, 30000))
+			return -EAGAIN;
+
+		for (i = 0; length; i += 4, length -= 4) {
+			u32 val = tg3_ape_read32(tp, msgoff + i);
+			memcpy(data, &val, sizeof(u32));
+			data++;
+		}
+	}
+
+	return 0;
+}
+
+int tg3_ape_scratchpad_write(struct tg3 *tp, u32 dstoff, u32 *data, u32 len)
+{
+	u32 i, bufoff, msgoff, maxlen, apedata;
+
+	if (!tg3_flag(tp, APE_HAS_NCSI))
+		return 0;
+
+	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+	if (apedata != APE_SEG_SIG_MAGIC)
+		return -ENODEV;
+
+	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+	if (!(apedata & APE_FW_STATUS_READY))
+		return -EAGAIN;
+
+	bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) +
+		 TG3_APE_SHMEM_BASE;
+	msgoff = bufoff + 2 * sizeof(u32);
+	maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN);
+
+	while (len) {
+		int err;
+		u32 length;
+
+		/* Cap xfer sizes to scratchpad limits. */
+		length = (len > maxlen) ? maxlen : len;
+		len -= length;
+
+		/* Wait for up to 1 millisecond for
+		 * APE to service previous event.
+		 */
+		err = tg3_ape_event_lock(tp, 1000);
+		if (err)
+			return err;
+
+		tg3_ape_write32(tp, bufoff, dstoff);
+		tg3_ape_write32(tp, bufoff + sizeof(u32), length);
+		apedata = msgoff;
+
+		dstoff += length;
+
+		for (i = 0; length; i += 4, length -= sizeof(u32)) {
+			tg3_ape_write32(tp, apedata, *data++);
+			apedata += sizeof(u32);
+		}
+
+		apedata = APE_EVENT_STATUS_DRIVER_EVNT |
+			  APE_EVENT_STATUS_SCRTCHPD_WRITE |
+			  APE_EVENT_STATUS_EVENT_PENDING;
+		tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata);
+
+		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+		tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+	}
+
+	return 0;
+}
+
 static int tg3_ape_send_event(struct tg3 *tp, u32 event)
 {
 	int err;
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 93865f8..d167a1c 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2311,10 +2311,12 @@
 #define  APE_LOCK_REQ_DRIVER		 0x00001000
 #define TG3_APE_LOCK_GRANT		0x004c
 #define  APE_LOCK_GRANT_DRIVER		 0x00001000
-#define TG3_APE_SEG_SIG			0x4000
-#define  APE_SEG_SIG_MAGIC		 0x41504521
+#define TG3_APE_STICKY_TMR		0x00b0
 
 /* APE shared memory.  Accessible through BAR1 */
+#define TG3_APE_SHMEM_BASE		0x4000
+#define TG3_APE_SEG_SIG			0x4000
+#define  APE_SEG_SIG_MAGIC		 0x41504521
 #define TG3_APE_FW_STATUS		0x400c
 #define  APE_FW_STATUS_READY		 0x00000100
 #define TG3_APE_FW_FEATURES		0x4010
@@ -2327,6 +2329,8 @@
 #define  APE_FW_VERSION_REVMSK		 0x0000ff00
 #define  APE_FW_VERSION_REVSFT		 8
 #define  APE_FW_VERSION_BLDMSK		 0x000000ff
+#define TG3_APE_SEG_MSG_BUF_OFF		0x401c
+#define TG3_APE_SEG_MSG_BUF_LEN		0x4020
 #define TG3_APE_HOST_SEG_SIG		0x4200
 #define  APE_HOST_SEG_SIG_MAGIC		 0x484f5354
 #define TG3_APE_HOST_SEG_LEN		0x4204
@@ -2353,6 +2357,8 @@
 
 #define  APE_EVENT_STATUS_DRIVER_EVNT	 0x00000010
 #define  APE_EVENT_STATUS_STATE_CHNGE	 0x00000500
+#define  APE_EVENT_STATUS_SCRTCHPD_READ	 0x00001600
+#define  APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700
 #define  APE_EVENT_STATUS_STATE_START	 0x00010000
 #define  APE_EVENT_STATUS_STATE_UNLOAD	 0x00020000
 #define  APE_EVENT_STATUS_STATE_WOL	 0x00030000
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 -next 1/4] tg3: Add common function tg3_ape_event_lock()
From: Michael Chan @ 2012-06-27  0:53 UTC (permalink / raw)
  To: davem; +Cc: netdev, nsujir

From: Matt Carlson <mcarlson@broadcom.com>

by refactoring code in tg3_ape_send_event().  The common function will
be used in subsequent patches.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c |   56 ++++++++++++++++++++---------------
 1 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e47ff8b..7c515db 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -730,44 +730,52 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 	tg3_ape_write32(tp, gnt + 4 * locknum, bit);
 }
 
-static void tg3_ape_send_event(struct tg3 *tp, u32 event)
+static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)
 {
-	int i;
 	u32 apedata;
 
-	/* NCSI does not support APE events */
-	if (tg3_flag(tp, APE_HAS_NCSI))
-		return;
+	while (timeout_us) {
+		if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
+			return -EBUSY;
+
+		apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+			break;
+
+		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+
+		udelay(10);
+		timeout_us -= (timeout_us > 10) ? 10 : timeout_us;
+	}
+
+	return timeout_us ? 0 : -EBUSY;
+}
+
+static int tg3_ape_send_event(struct tg3 *tp, u32 event)
+{
+	int err;
+	u32 apedata;
 
 	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
 	if (apedata != APE_SEG_SIG_MAGIC)
-		return;
+		return -EAGAIN;
 
 	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
 	if (!(apedata & APE_FW_STATUS_READY))
-		return;
+		return -EAGAIN;
 
 	/* Wait for up to 1 millisecond for APE to service previous event. */
-	for (i = 0; i < 10; i++) {
-		if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
-			return;
-
-		apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
-
-		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
-			tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
-					event | APE_EVENT_STATUS_EVENT_PENDING);
+	err = tg3_ape_event_lock(tp, 1000);
+	if (err)
+		return err;
 
-		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+	tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
+			event | APE_EVENT_STATUS_EVENT_PENDING);
 
-		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
-			break;
+	tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+	tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
 
-		udelay(100);
-	}
-
-	if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
-		tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+	return 0;
 }
 
 static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
-- 
1.7.1

^ permalink raw reply related


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