Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v6] net: batch skb dequeueing from softnet input_pkt_queue
From: Eric Dumazet @ 2010-04-23 10:26 UTC (permalink / raw)
  To: Changli Gao
  Cc: David S. Miller, jamal, Tom Herbert, Stephen Hemminger, netdev
In-Reply-To: <1272010378-2955-1-git-send-email-xiaosuo@gmail.com>

Le vendredi 23 avril 2010 à 16:12 +0800, Changli Gao a écrit :
> batch skb dequeueing from softnet input_pkt_queue.
> 
> batch skb dequeueing from softnet input_pkt_queue to reduce potential lock
> contention when RPS is enabled.
> 
> Note: in the worst case, the number of packets in a softnet_data may be double
> of netdev_max_backlog.
> 
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ----

Oops, reading it again, I found process_backlog() was still taking the
lock twice, if only one packet is waiting in input_pkt_queue.

Possible fix, on top of your patch :

diff --git a/net/core/dev.c b/net/core/dev.c
index 0eddd23..0569be7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3296,8 +3296,9 @@ static int process_backlog(struct napi_struct *napi, int quota)
 #endif
 	napi->weight = weight_p;
 	local_irq_disable();
-	while (1) {
+	while (work < quota) {
 		struct sk_buff *skb;
+		unsigned int qlen;
 
 		while ((skb = __skb_dequeue(&sd->process_queue))) {
 			local_irq_enable();
@@ -3308,13 +3309,15 @@ static int process_backlog(struct napi_struct *napi, int quota)
 		}
 
 		rps_lock(sd);
-		input_queue_head_add(sd, skb_queue_len(&sd->input_pkt_queue));
-		skb_queue_splice_tail_init(&sd->input_pkt_queue,
-					   &sd->process_queue);
-		if (skb_queue_empty(&sd->process_queue)) {
+		qlen = skb_queue_len(&sd->input_pkt_queue);
+		if (qlen) {
+			input_queue_head_add(sd, qlen);
+			skb_queue_splice_tail_init(&sd->input_pkt_queue,
+						   &sd->process_queue);
+		}
+		if (qlen < quota - work) {
 			__napi_complete(napi);
-			rps_unlock(sd);
-			break;
+			quota = work + qlen;
 		}
 		rps_unlock(sd);
 	}



^ permalink raw reply related

* Re: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 10:35 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: Changli Gao, Eric Dumazet, Linux Kernel Network Hackers,
	netfilter-devel, Paul E McKenney
In-Reply-To: <1271943066.14501.194.camel@jdb-workstation>

Jesper Dangaard Brouer wrote:
> I have added a stats counter to prove my case, which I think we should add to the kernel (to detect the case in the future).
> The DDoS attack has disappeared, so I guess I'll try to see if I can reproduce the problem in my testlab.
> 
> 
> 
> [PATCH] net: netfilter conntrack extended with extra stat counter.
> 
> From: Jesper Dangaard Brouer <hawk@comx.dk>
> 
> I suspect an unfortunatly series of events occuring under a DDoS
> attack, in function __nf_conntrack_find() nf_contrack_core.c.
> 
> Adding a stats counter to see if the search is restarted too often.

Applied, thanks Jesper.

^ permalink raw reply

* Re: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 10:36 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Jesper Dangaard Brouer, paulmck, Changli Gao, hawk,
	Linux Kernel Network Hackers, Netfilter Developers
In-Reply-To: <1271970893.7895.6507.camel@edumazet-laptop>

Eric Dumazet wrote:
> Le jeudi 22 avril 2010 à 23:03 +0200, Eric Dumazet a écrit :
>>> Guess I have to reproduce the DoS attack in a testlab (I will first have 
>>> time Tuesday).  So we can determine if its bad hashing or restart of the 
>>> search loop.
>>>
> 
> Or very long chains, if attacker managed to find a jhash flaw.

That should be visible in the "searched" statistic.

> You could add a lookup_restart counter :

I've applied Jespers equivalent patch.
--
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 net-next-2.6] l2tp: fix memory allocation
From: Jiri Pirko @ 2010-04-23 10:53 UTC (permalink / raw)
  To: netdev; +Cc: davem, kleptog, jchapman

Since .size is set properly in "struct pernet_operations l2tp_net_ops",
allocating space for "struct l2tp_net" by hand is not correct, even causes
memory leakage.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index ecc7aea..1712af1 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1617,14 +1617,9 @@ EXPORT_SYMBOL_GPL(l2tp_session_create);
 
 static __net_init int l2tp_init_net(struct net *net)
 {
-	struct l2tp_net *pn;
-	int err;
+	struct l2tp_net *pn = net_generic(net, l2tp_net_id);
 	int hash;
 
-	pn = kzalloc(sizeof(*pn), GFP_KERNEL);
-	if (!pn)
-		return -ENOMEM;
-
 	INIT_LIST_HEAD(&pn->l2tp_tunnel_list);
 	spin_lock_init(&pn->l2tp_tunnel_list_lock);
 
@@ -1633,33 +1628,11 @@ static __net_init int l2tp_init_net(struct net *net)
 
 	spin_lock_init(&pn->l2tp_session_hlist_lock);
 
-	err = net_assign_generic(net, l2tp_net_id, pn);
-	if (err)
-		goto out;
-
 	return 0;
-
-out:
-	kfree(pn);
-	return err;
-}
-
-static __net_exit void l2tp_exit_net(struct net *net)
-{
-	struct l2tp_net *pn;
-
-	pn = net_generic(net, l2tp_net_id);
-	/*
-	 * if someone has cached our net then
-	 * further net_generic call will return NULL
-	 */
-	net_assign_generic(net, l2tp_net_id, NULL);
-	kfree(pn);
 }
 
 static struct pernet_operations l2tp_net_ops = {
 	.init = l2tp_init_net,
-	.exit = l2tp_exit_net,
 	.id   = &l2tp_net_id,
 	.size = sizeof(struct l2tp_net),
 };

^ permalink raw reply related

* Re: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 10:55 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Jesper Dangaard Brouer, paulmck, Changli Gao, hawk,
	Linux Kernel Network Hackers, Netfilter Developers
In-Reply-To: <1271970199.7895.6482.camel@edumazet-laptop>

Eric Dumazet wrote:
> Le jeudi 22 avril 2010 à 22:38 +0200, Jesper Dangaard Brouer a écrit :
>> On Thu, 22 Apr 2010, Eric Dumazet wrote:
>>
>>> Le jeudi 22 avril 2010 à 08:51 -0700, Paul E. McKenney a écrit :
>>>> On Thu, Apr 22, 2010 at 04:53:49PM +0200, Eric Dumazet wrote:
>>>>> Le jeudi 22 avril 2010 à 16:36 +0200, Eric Dumazet a écrit :
>>>>>
>>>>> If we can do the 'retry' a 10 times, it means the attacker was really
>>>>> clever enough to inject new packets (new conntracks) at the right
>>>>> moment, in the right hash chain, and this sounds so higly incredible
>>>>> that I cannot believe it at all :)
>>>> Or maybe the DoS attack is injecting so many new conntracks that a large
>>>> fraction of the hash chains are being modified at any given time?
>>>>
>> I think its plausable, there is a lot of modification going on.
>> Approx 40.000 deletes/sec and 40.000 inserts/sec.
>> The hash bucket size is 300032, and with 80000 modifications/sec, we are 
>> (potentially) changing 26.6% of the hash chains each second.
>>
> 
> OK but a lookup last a fraction of a micro second, unless interrupted by
> hard irq.
> 
> Probability of a change during a lookup should be very very small.
> 
> Note that the scenario for a restart is :
> 
> The lookup go through the chain.
> While it is examining one object, this object is deleted.
> The object is re-allocated by another cpu and inserted to a new chain.

I think another scenario that seems a bit more likely would be
that a new entry is added to the chain after it was fully searched.
Perhaps we could continue searching at the last position if the
last entry is not a nulls entry to improve this.
--
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: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 10:56 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Changli Gao, hawk, Linux Kernel Network Hackers, netfilter-devel,
	Paul E McKenney
In-Reply-To: <1271946961.7895.5665.camel@edumazet-laptop>

Eric Dumazet wrote:
> Le jeudi 22 avril 2010 à 15:17 +0200, Patrick McHardy a écrit :
>> Changli Gao wrote:
>>>> struct nf_conntrack_tuple_hash *
>>>> __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple)
>>>> ...
>>> We should add a retry limit there.
>> We can't do that since that would allow false negatives.
> 
> If one hash slot is under attack, then there is a bug somewhere.
> 
> If we cannot avoid this, we can fallback to a secure mode at the second
> retry, and take the spinlock.
> 
> Tis way, most of lookups stay lockless (one pass), and some might take
> the slot lock to avoid the possibility of a loop.

That sounds like a good idea. But lets what for Jesper's test results
before we start fixing this problem :)
--
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 net-next-2.6] l2tp_eth: fix memory allocation
From: Jiri Pirko @ 2010-04-23 11:01 UTC (permalink / raw)
  To: netdev; +Cc: davem, kleptog, jchapman

Since .size is set properly in "struct pernet_operations l2tp_eth_net_ops",
allocating space for "struct l2tp_eth_net" by hand is not correct, even causes
memory leakage.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>

diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index ca1164a..58c6c4c 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -276,43 +276,16 @@ out:
 
 static __net_init int l2tp_eth_init_net(struct net *net)
 {
-	struct l2tp_eth_net *pn;
-	int err;
-
-	pn = kzalloc(sizeof(*pn), GFP_KERNEL);
-	if (!pn)
-		return -ENOMEM;
+	struct l2tp_eth_net *pn = net_generic(net, l2tp_eth_net_id);
 
 	INIT_LIST_HEAD(&pn->l2tp_eth_dev_list);
 	spin_lock_init(&pn->l2tp_eth_lock);
 
-	err = net_assign_generic(net, l2tp_eth_net_id, pn);
-	if (err)
-		goto out;
-
 	return 0;
-
-out:
-	kfree(pn);
-	return err;
-}
-
-static __net_exit void l2tp_eth_exit_net(struct net *net)
-{
-	struct l2tp_eth_net *pn;
-
-	pn = net_generic(net, l2tp_eth_net_id);
-	/*
-	 * if someone has cached our net then
-	 * further net_generic call will return NULL
-	 */
-	net_assign_generic(net, l2tp_eth_net_id, NULL);
-	kfree(pn);
 }
 
 static __net_initdata struct pernet_operations l2tp_eth_net_ops = {
 	.init = l2tp_eth_init_net,
-	.exit = l2tp_eth_exit_net,
 	.id   = &l2tp_eth_net_id,
 	.size = sizeof(struct l2tp_eth_net),
 };

^ permalink raw reply related

* Re: DDoS attack causing bad effect on conntrack searches
From: Eric Dumazet @ 2010-04-23 11:05 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Jesper Dangaard Brouer, paulmck, Changli Gao, hawk,
	Linux Kernel Network Hackers, Netfilter Developers
In-Reply-To: <4BD17CAA.4090708@trash.net>

Le vendredi 23 avril 2010 à 12:55 +0200, Patrick McHardy a écrit :
> Eric Dumazet wrote:
> > 
> > OK but a lookup last a fraction of a micro second, unless interrupted by
> > hard irq.
> > 
> > Probability of a change during a lookup should be very very small.
> > 
> > Note that the scenario for a restart is :
> > 
> > The lookup go through the chain.
> > While it is examining one object, this object is deleted.
> > The object is re-allocated by another cpu and inserted to a new chain.
> 
> I think another scenario that seems a bit more likely would be
> that a new entry is added to the chain after it was fully searched.
> Perhaps we could continue searching at the last position if the
> last entry is not a nulls entry to improve this.

But the last entry is always a nulls entry, what do you mean exactly ?

When an unsert (of a fresh object, not a reused one) is done, this
doesnt affect lookups in any way, since its done at the head of list.




^ permalink raw reply

* Re: DDoS attack causing bad effect on conntrack searches
From: Eric Dumazet @ 2010-04-23 11:06 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Jesper Dangaard Brouer, paulmck, Changli Gao, hawk,
	Linux Kernel Network Hackers, Netfilter Developers
In-Reply-To: <4BD1784A.6010306@trash.net>

Le vendredi 23 avril 2010 à 12:36 +0200, Patrick McHardy a écrit :
> Eric Dumazet wrote:
> > Le jeudi 22 avril 2010 à 23:03 +0200, Eric Dumazet a écrit :
> >>> Guess I have to reproduce the DoS attack in a testlab (I will first have 
> >>> time Tuesday).  So we can determine if its bad hashing or restart of the 
> >>> search loop.
> >>>
> > 
> > Or very long chains, if attacker managed to find a jhash flaw.
> 
> That should be visible in the "searched" statistic.
> 
> > You could add a lookup_restart counter :
> 
> I've applied Jespers equivalent patch.

Yes of course, I missed it or I would not have cooked it ;)

Thanks


--
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: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 11:06 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Jesper Dangaard Brouer, paulmck, Changli Gao, hawk,
	Linux Kernel Network Hackers, Netfilter Developers
In-Reply-To: <1272020717.7895.7974.camel@edumazet-laptop>

Eric Dumazet wrote:
> Le vendredi 23 avril 2010 à 12:55 +0200, Patrick McHardy a écrit :
>> Eric Dumazet wrote:
>>> OK but a lookup last a fraction of a micro second, unless interrupted by
>>> hard irq.
>>>
>>> Probability of a change during a lookup should be very very small.
>>>
>>> Note that the scenario for a restart is :
>>>
>>> The lookup go through the chain.
>>> While it is examining one object, this object is deleted.
>>> The object is re-allocated by another cpu and inserted to a new chain.
>> I think another scenario that seems a bit more likely would be
>> that a new entry is added to the chain after it was fully searched.
>> Perhaps we could continue searching at the last position if the
>> last entry is not a nulls entry to improve this.
> 
> But the last entry is always a nulls entry, what do you mean exactly ?
> 
> When an unsert (of a fresh object, not a reused one) is done, this
> doesnt affect lookups in any way, since its done at the head of list.

Right, I missed that :)
--
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/RFC Resubmission] cdc_ether: Identify MBM devices by GUID in MDLM descriptor
From: Jonas Sjoquist @ 2010-04-23 11:07 UTC (permalink / raw)
  To: oneukum, davem; +Cc: netdev

From: Jonas Sjöquist <jonas.sjoquist@ericsson.com>

This patch removes vid/pid for Ericsson MBM devices from the whitelist set of
devices. The MBM devices are instead identified by GUID.

In order for cdc_ether to handle these devices the GUID in the MDLM descriptor
is tested. All MBM devices currently handled by cdc_ether as well as future
CDC Ethernet MBM devices can be identified by the GUID.

This is the same solution used in Carl Nordbeck's mbm driver,
http://kerneltrap.org/mailarchive/linux-usb/2008/11/17/4141384/thread

I post this as RFC to get feedback on however cdc_ether is the correct place to
do the binding, or if it should be done in a separate driver, e.g. zaurus.

Signed-off-by: Jonas Sjöquist <jonas.sjoquist@ericsson.com>
---
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index c8cdb7f..811b2dc 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -64,6 +64,11 @@ static int is_wireless_rndis(struct usb_interface_descriptor *desc)
 
 #endif
 
+static const u8 mbm_guid[16] = {
+	0xa3, 0x17, 0xa8, 0x8b, 0x04, 0x5e, 0x4f, 0x01,
+	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
+};
+
 /*
  * probes control interface, claims data interface, collects the bulk
  * endpoints, activates data interface (if needed), maybe sets MTU.
@@ -79,6 +84,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 	int				status;
 	int				rndis;
 	struct usb_driver		*driver = driver_of(intf);
+	struct usb_cdc_mdlm_desc	*desc = NULL;
+	struct usb_cdc_mdlm_detail_desc *detail = NULL;
 
 	if (sizeof dev->data < sizeof *info)
 		return -EDOM;
@@ -229,6 +236,34 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 			 * side link address we were given.
 			 */
 			break;
+		case USB_CDC_MDLM_TYPE:
+			if (desc) {
+				dev_dbg(&intf->dev, "extra MDLM descriptor\n");
+				goto bad_desc;
+			}
+
+			desc = (void *)buf;
+
+			if (desc->bLength != sizeof(*desc))
+				goto bad_desc;
+
+			if (memcmp(&desc->bGUID, mbm_guid, 16))
+				goto bad_desc;
+			break;
+		case USB_CDC_MDLM_DETAIL_TYPE:
+			if (detail) {
+				dev_dbg(&intf->dev, "extra MDLM detail descriptor\n");
+				goto bad_desc;
+			}
+
+			detail = (void *)buf;
+
+			if (detail->bGuidDescriptorType == 0) {
+				if (detail->bLength < (sizeof(*detail) + 1))
+					goto bad_desc;
+			} else
+				goto bad_desc;
+			break;
 		}
 next_desc:
 		len -= buf [0];	/* bLength */
@@ -542,80 +577,10 @@ static const struct usb_device_id	products [] = {
 			USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
 }, {
-	/* Ericsson F3507g */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3507g ver. 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1902, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3607gw */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1904, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3607gw ver 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1905, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3607gw ver 3 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3307 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190a, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson F3307 ver 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1909, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson C3607w */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1049, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Ericsson C3607w ver 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190b, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Toshiba F3507g */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Toshiba F3607gw */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130c, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Toshiba F3607gw ver 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x1311, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Dell F3507g */
-	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Dell F3607gw */
-	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8183, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
-}, {
-	/* Dell F3607gw ver 2 */
-	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8184, USB_CLASS_COMM,
-			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &mbm_info,
+	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
+			USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long)&mbm_info,
+
 },
 	{ },		// END
 };


^ permalink raw reply related

* [PATCH net-next-2.6] net: disallow to use net_assign_generic externally
From: Jiri Pirko @ 2010-04-23 11:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, ebiederm

Now there's no need to use this fuction directly because it's handled by
register_pernet_device. So to make this simple and easy to understand,
make this static to do not tempt potentional users.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>

diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
index ff4982a..81a31c0 100644
--- a/include/net/netns/generic.h
+++ b/include/net/netns/generic.h
@@ -14,11 +14,8 @@
  * The rules are simple:
  * 1. set pernet_operations->id.  After register_pernet_device you
  *    will have the id of your private pointer.
- * 2. Either set pernet_operations->size (to have the code allocate and
- *    free a private structure pointed to from struct net ) or 
- *    call net_assign_generic() to put the private data on the struct
- *    net (most preferably this should be done in the ->init callback
- *    of the ops registered);
+ * 2. set pernet_operations->size to have the code allocate and free
+ *    a private structure pointed to from struct net.
  * 3. do not change this pointer while the net is alive;
  * 4. do not try to have any private reference on the net_generic object.
  *
@@ -46,6 +43,4 @@ static inline void *net_generic(struct net *net, int id)
 
 	return ptr;
 }
-
-extern int net_assign_generic(struct net *net, int id, void *data);
 #endif
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index bd8c471..777477c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -27,6 +27,51 @@ EXPORT_SYMBOL(init_net);
 
 #define INITIAL_NET_GEN_PTRS	13 /* +1 for len +2 for rcu_head */
 
+static void net_generic_release(struct rcu_head *rcu)
+{
+	struct net_generic *ng;
+
+	ng = container_of(rcu, struct net_generic, rcu);
+	kfree(ng);
+}
+
+static int net_assign_generic(struct net *net, int id, void *data)
+{
+	struct net_generic *ng, *old_ng;
+
+	BUG_ON(!mutex_is_locked(&net_mutex));
+	BUG_ON(id == 0);
+
+	ng = old_ng = net->gen;
+	if (old_ng->len >= id)
+		goto assign;
+
+	ng = kzalloc(sizeof(struct net_generic) +
+			id * sizeof(void *), GFP_KERNEL);
+	if (ng == NULL)
+		return -ENOMEM;
+
+	/*
+	 * Some synchronisation notes:
+	 *
+	 * The net_generic explores the net->gen array inside rcu
+	 * read section. Besides once set the net->gen->ptr[x]
+	 * pointer never changes (see rules in netns/generic.h).
+	 *
+	 * That said, we simply duplicate this array and schedule
+	 * the old copy for kfree after a grace period.
+	 */
+
+	ng->len = id;
+	memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
+
+	rcu_assign_pointer(net->gen, ng);
+	call_rcu(&old_ng->rcu, net_generic_release);
+assign:
+	ng->ptr[id - 1] = data;
+	return 0;
+}
+
 static int ops_init(const struct pernet_operations *ops, struct net *net)
 {
 	int err;
@@ -526,49 +571,3 @@ void unregister_pernet_device(struct pernet_operations *ops)
 	mutex_unlock(&net_mutex);
 }
 EXPORT_SYMBOL_GPL(unregister_pernet_device);
-
-static void net_generic_release(struct rcu_head *rcu)
-{
-	struct net_generic *ng;
-
-	ng = container_of(rcu, struct net_generic, rcu);
-	kfree(ng);
-}
-
-int net_assign_generic(struct net *net, int id, void *data)
-{
-	struct net_generic *ng, *old_ng;
-
-	BUG_ON(!mutex_is_locked(&net_mutex));
-	BUG_ON(id == 0);
-
-	ng = old_ng = net->gen;
-	if (old_ng->len >= id)
-		goto assign;
-
-	ng = kzalloc(sizeof(struct net_generic) +
-			id * sizeof(void *), GFP_KERNEL);
-	if (ng == NULL)
-		return -ENOMEM;
-
-	/*
-	 * Some synchronisation notes:
-	 *
-	 * The net_generic explores the net->gen array inside rcu
-	 * read section. Besides once set the net->gen->ptr[x]
-	 * pointer never changes (see rules in netns/generic.h).
-	 *
-	 * That said, we simply duplicate this array and schedule
-	 * the old copy for kfree after a grace period.
-	 */
-
-	ng->len = id;
-	memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
-
-	rcu_assign_pointer(net->gen, ng);
-	call_rcu(&old_ng->rcu, net_generic_release);
-assign:
-	ng->ptr[id - 1] = data;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(net_assign_generic);

^ permalink raw reply related

* [patch] sctp: cleanup: remove unneeded null check
From: Dan Carpenter @ 2010-04-23 11:59 UTC (permalink / raw)
  To: Vlad Yasevich
  Cc: Sridhar Samudrala, David S. Miller, Wei Yongjun, Chris Dischino,
	linux-sctp, netdev, kernel-janitors

"chunk" can never be null here.  We dereferenced it earlier in the
function and also at the start of the function we passed it to 
sctp_pack_cookie() which dereferences it.

This code has been around since the dawn of git history so if "chunk"
were ever null someone would have complained about it.

Signed-off-by: Dan Carpenter <error27@gmail.com>

diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 17cb400..52352fc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -470,8 +470,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
 	 *
 	 * [INIT ACK back to where the INIT came from.]
 	 */
-	if (chunk)
-		retval->transport = chunk->transport;
+	retval->transport = chunk->transport;
 
 nomem_chunk:
 	kfree(cookie);

^ permalink raw reply related

* nfs41: potential null deref in xprt_reserve_xprt()?
From: Dan Carpenter @ 2010-04-23 12:00 UTC (permalink / raw)
  To: iyer-HgOvQuBEEgTQT0dZR+AlfA
  Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA

I'm going through some Smatch results and had a question.  

Until commit 343952fa5a: "nfs41: Get the rpc_xprt * from the rpc_rqst 
instead of the rpc_clnt." we assumed that "task->tk_rqstp" can be NULL.  
But that patch dereferences it unconditionally.

diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 0eea2bf..c144611 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -195,8 +195,8 @@ EXPORT_SYMBOL_GPL(xprt_load_transport);
  */
 int xprt_reserve_xprt(struct rpc_task *task)
 {
-       struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
	                        ^^^^^^^^^^^^^

Can "req" be null here?  The patch is a year old, so presumably it
isn't null very often.

If you would like, I can remove the checks for null from the rest of the
function.

regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/7] Topcliff GbE: Add The Main code [3/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 18536 bytes --]

^ permalink raw reply

* [PATCH 1/7] Topcliff GbE: Add The Main code [1/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 39156 bytes --]

^ permalink raw reply

* [PATCH 1/7] Topcliff GbE: Add The Main code [2/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 39085 bytes --]

^ permalink raw reply

* [PATCH 3/7] Topcliff GbE: Add The Ethtool code [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 7634 bytes --]

^ permalink raw reply

* [PATCH 2/7] Topcliff GbE: Add The Parameter check code
From: Masayuki Ohtake @ 2010-04-23 11:59 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Andrew, Intel OTC

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

This patch adds the Parameter check code of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/net/pch_gbe/pch_gbe_param.c        | 594 ++
+++++++++++++++++++++++++++++++ 1 files changed, 594 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c 2010-04-13
18:18:01.000000000 +0900
@@ -0,0 +1,594 @@
+/*!
+ * @file pch_gbe_param.c
+ * @brief Linux PCH Gigabit Ethernet Driver parameter check source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define PCH_GBE_MAX_NIC 1
+
+#define OPTION_UNSET   -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+
+#define PCH_GBE_PARAM_INIT { [0 ... PCH_GBE_MAX_NIC] = OPTION_UNSET }
+#ifdef PCH_GBE_QAC
+#define PCH_GBE_PARAM(X, desc)
+#else
+#define PCH_GBE_PARAM(X, desc) \
+ static int X[PCH_GBE_MAX_NIC+1] = PCH_GBE_PARAM_INIT; \
+ static int num_##X; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
+ MODULE_PARM_DESC(X, desc);
+#endif
+
+/*
+ * Transmit Descriptor Count
+ *    Valid Range:   PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
+ *    Default Value: PCH_GBE_DEFAULT_TXD
+ */
+PCH_GBE_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+/*
+ * Receive Descriptor Count
+ *    Valid Range:   PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
+ *    Default Value: PCH_GBE_DEFAULT_RXD
+ */
+PCH_GBE_PARAM(RxDescriptors, "Number of receive descriptors");
+
+/* User Specified Speed Override
+ *
+ * Valid Range: 0, 10, 100, 1000
+ *  - 0    - auto-negotiate at all supported speeds
+ *  - 10   - only link at 10 Mbps
+ *  - 100  - only link at 100 Mbps
+ *  - 1000 - only link at 1000 Mbps
+ *
+ * Default Value: 0
+ */
+PCH_GBE_PARAM(Speed, "Speed setting");
+
+/* User Specified Duplex Override
+ *
+ * Valid Range: 0-2
+ *  - 0 - auto-negotiate for duplex
+ *  - 1 - only link at half duplex
+ *  - 2 - only link at full duplex
+ *
+ * Default Value: 0
+ */
+PCH_GBE_PARAM(Duplex, "Duplex setting");
+
+/*
+ * Auto-negotiation Advertisement Override
+ *    Valid Range: 0x01-0x0F, 0x20-0x2F
+ *
+ *       The AutoNeg value is a bit mask describing which speed and duplex
+ *       combinations should be advertised during auto-negotiation.
+ *       The supported speed and duplex modes are listed below
+ *
+ *       Bit           7     6     5      4      3     2     1      0
+ *       Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
+ *       Duplex                    Full          Full  Half  Full   Half
+ *
+ *    Default Value: 0x2F (copper)
+ */
+PCH_GBE_PARAM(AutoNeg, "Advertised auto-negotiation setting");
+#define AUTONEG_ADV_DEFAULT  0x2F
+
+/*
+ * User Specified Flow Control Override
+ *    Valid Range: 0-3
+ *     - 0 - No Flow Control
+ *     - 1 - Rx only, respond to PAUSE frames but do not generate them
+ *     - 2 - Tx only, generate PAUSE frames but ignore them on receive
+ *     - 3 - Full Flow Control Support
+ *    Default Value: Read flow control settings from the EEPROM
+ */
+PCH_GBE_PARAM(FlowControl, "Flow Control setting");
+
+/*
+ * XsumRX - Receive Checksum Offload Enable/Disable
+ *    Valid Range: 0, 1
+ *     - 0 - disables all checksum offload
+ *     - 1 - enables receive IP/TCP/UDP checksum offload
+ *    Default Value: PCH_GBE_DEFAULT_RX_CSUM
+ */
+PCH_GBE_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
+
+/*
+ * XsumTX - Transmit Checksum Offload Enable/Disable
+ *    Valid Range: 0, 1
+ *     - 0 - disables all checksum offload
+ *     - 1 - enables transmit IP/TCP/UDP checksum offload
+ *    Default Value: PCH_GBE_DEFAULT_TX_CSUM
+ */
+PCH_GBE_PARAM(XsumTX, "Disable or enable Transmit Checksum offload");
+
+struct pch_gbe_option {
+ enum { enable_option, range_option, list_option } type;
+ signed char *name;
+ signed char *err;
+ int  def;
+ union {
+  struct { /* range_option info */
+   int min;
+   int max;
+  } r;
+  struct { /* list_option info */
+   int nr;
+   struct pch_gbe_opt_list { int i; signed char *str; } *p;
+  } l;
+ } arg;
+};
+
+/* ------------------------------------------------------------------------
----
+ Function prototype
+---------------------------------------------------------------------------
- */
+static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter);
+static int pch_gbe_validate_option(int *value,
+     struct pch_gbe_option *opt,
+     struct pch_gbe_adapter *adapter);
+
+/* ------------------------------------------------------------------------
----
+ Function
+---------------------------------------------------------------------------
- */
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn      static int pch_gbe_validate_option(int *value,
+ *                                             struct pch_gbe_option *opt,
+ *                                             struct pch_gbe_adapter
*adapter)
+ * @brief   Validate option
+ * @param   value   [IN] value
+ * @param   opt     [IN] option
+ * @param   adapter [IN] Board private structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:   Failed
+ */
+static int
+pch_gbe_validate_option(int *value, struct pch_gbe_option *opt,
+  struct pch_gbe_adapter *adapter)
+{
+ if (*value == OPTION_UNSET) {
+  *value = opt->def;
+  return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+  switch (*value) {
+  case OPTION_ENABLED:
+   DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name);
+   return 0;
+  case OPTION_DISABLED:
+   DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name);
+   return 0;
+  }
+  break;
+ case range_option:
+  if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+   DPRINTK(PROBE, INFO,
+     "%s set to %i\n", opt->name, *value);
+   return 0;
+  }
+  break;
+ case list_option: {
+  int i;
+  struct pch_gbe_opt_list *ent;
+
+  for (i = 0; i < opt->arg.l.nr; i++) {
+   ent = &opt->arg.l.p[i];
+   if (*value == ent->i) {
+    if (ent->str[0] != '\0')
+     DPRINTK(PROBE, INFO, "%s\n", ent->str);
+    return 0;
+   }
+  }
+ }
+  break;
+ default:
+  BUG();
+ }
+
+ DPRINTK(PROBE, INFO, "Invalid %s value specified (%i) %s\n",
+   opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn      void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+ * @brief   Range Checking for Command Line Parameters
+ * @param   adapter  [IN] Board private structure
+ * @return  None
+ * @remarks
+ *  This routine checks all command line parameters for valid user
+ *  input.  If an invalid value is given, or if no user specified
+ *  value exists, a default value is used.  The final value is stored
+ *  in a variable in the adapter structure.
+ */
+void
+pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int bd = adapter->bd_number;
+
+ PCH_DEBUG("pch_gbe_check_options\n");
+
+ if (bd >= PCH_GBE_MAX_NIC) {
+  DPRINTK(PROBE, NOTICE,
+         "Warning: no configuration for board #%i\n", bd);
+  DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
+ }
+
+ { /* Transmit Descriptor Count */
+  struct pch_gbe_option opt = {
+   .type = range_option,
+   .name = "Transmit Descriptors",
+   .err  = "using default of "
+    __MODULE_STRING(PCH_GBE_DEFAULT_TXD),
+   .def  = PCH_GBE_DEFAULT_TXD,
+   .arg  = { .r = { .min = PCH_GBE_MIN_TXD } },
+   .arg  = { .r = { .max = PCH_GBE_MAX_TXD } }
+  };
+  struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+  if (num_TxDescriptors > bd) {
+   tx_ring->count = TxDescriptors[bd];
+   pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
+   PCH_GBE_ROUNDUP(tx_ring->count,
+     PCH_GBE_TX_DESC_MULTIPLE);
+  } else {
+   tx_ring->count = opt.def;
+  }
+ }
+ { /* Receive Descriptor Count */
+  struct pch_gbe_option opt = {
+   .type = range_option,
+   .name = "Receive Descriptors",
+   .err  = "using default of "
+    __MODULE_STRING(PCH_GBE_DEFAULT_RXD),
+   .def  = PCH_GBE_DEFAULT_RXD,
+   .arg  = { .r = { .min = PCH_GBE_MIN_RXD } },
+   .arg  = { .r = { .max = PCH_GBE_MAX_RXD } }
+  };
+  struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+  if (num_RxDescriptors > bd) {
+   rx_ring->count = RxDescriptors[bd];
+   pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
+   PCH_GBE_ROUNDUP(rx_ring->count,
+     PCH_GBE_RX_DESC_MULTIPLE);
+  } else {
+   rx_ring->count = opt.def;
+  }
+ }
+ { /* Checksum Offload Enable/Disable */
+  struct pch_gbe_option opt = {
+   .type = enable_option,
+   .name = "Checksum Offload",
+   .err  = "defaulting to Enabled",
+   .def  = PCH_GBE_DEFAULT_RX_CSUM
+  };
+
+  if (num_XsumRX > bd) {
+   adapter->rx_csum = XsumRX[bd];
+   pch_gbe_validate_option((int *)(&adapter->rx_csum),
+      &opt, adapter);
+  } else {
+   adapter->rx_csum = opt.def;
+  }
+ }
+ { /* Checksum Offload Enable/Disable */
+  struct pch_gbe_option opt = {
+   .type = enable_option,
+   .name = "Checksum Offload",
+   .err  = "defaulting to Enabled",
+   .def  = PCH_GBE_DEFAULT_TX_CSUM
+  };
+
+  if (num_XsumTX > bd) {
+   adapter->tx_csum = XsumTX[bd];
+   pch_gbe_validate_option((int *)(&adapter->tx_csum),
+      &opt, adapter);
+  } else {
+   adapter->tx_csum = opt.def;
+  }
+ }
+ { /* Flow Control */
+
+  struct pch_gbe_opt_list fc_list[] = {
+   {pch_gbe_fc_none, "Flow Control Disabled"},
+   {pch_gbe_fc_rx_pause, "Flow Control Receive Only"},
+   {pch_gbe_fc_tx_pause, "Flow Control Transmit Only"},
+   {pch_gbe_fc_full, "Flow Control Enabled"} };
+
+  struct pch_gbe_option opt = {
+   .type = list_option,
+   .name = "Flow Control",
+   .err  = "reading default settings from EEPROM",
+   .def  = PCH_GBE_FC_DEFAULT,
+   .arg  = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
+      .p = fc_list } }
+  };
+
+  if (num_FlowControl > bd) {
+   hw->mac.fc = FlowControl[bd];
+   pch_gbe_validate_option((int *)(&hw->mac.fc),
+       &opt, adapter);
+  } else {
+   hw->mac.fc = opt.def;
+  }
+ }
+
+ pch_gbe_check_copper_options(adapter);
+}
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn      static void pch_gbe_check_copper_options(
+ *                      struct pch_gbe_adapter *adapter)
+ * @brief   Range Checking for Link Options, Copper Version
+ * @param   adapter  [IN] Board private structure
+ * @return  None
+ * @remarks
+ *  Handles speed and duplex options on copper adapters
+ */
+static void
+pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int speed, dplx;
+ int bd = adapter->bd_number;
+
+ { /* Speed */
+  struct pch_gbe_opt_list speed_list[] = {
+    {0, "" },
+    {SPEED_10, ""},
+    {SPEED_100, ""},
+    {SPEED_1000, ""} };
+
+  struct pch_gbe_option opt = {
+   .type = list_option,
+   .name = "Speed",
+   .err  = "parameter ignored",
+   .def  = 0,
+   .arg  = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
+      .p = speed_list } }
+  };
+
+  if (num_Speed > bd) {
+   speed = Speed[bd];
+   pch_gbe_validate_option(&speed, &opt, adapter);
+  } else {
+   speed = opt.def;
+  }
+ }
+ { /* Duplex */
+  struct pch_gbe_opt_list dplx_list[] = {
+    {0, ""},
+    {PHY_HALF_DUPLEX, ""},
+    {PHY_FULL_DUPLEX, ""} };
+
+  struct pch_gbe_option opt = {
+   .type = list_option,
+   .name = "Duplex",
+   .err  = "parameter ignored",
+   .def  = 0,
+   .arg  = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
+      .p = dplx_list } }
+  };
+
+  if (num_Duplex > bd) {
+   dplx = Duplex[bd];
+   pch_gbe_validate_option(&dplx, &opt, adapter);
+  } else {
+   dplx = opt.def;
+  }
+ }
+
+ { /* Autoneg */
+  struct pch_gbe_opt_list an_list[] =
+   #define AA "AutoNeg advertising "
+   {{ 0x01, AA "10/HD" },
+    { 0x02, AA "10/FD" },
+    { 0x03, AA "10/FD, 10/HD" },
+    { 0x04, AA "100/HD" },
+    { 0x05, AA "100/HD, 10/HD" },
+    { 0x06, AA "100/HD, 10/FD" },
+    { 0x07, AA "100/HD, 10/FD, 10/HD" },
+    { 0x08, AA "100/FD" },
+    { 0x09, AA "100/FD, 10/HD" },
+    { 0x0a, AA "100/FD, 10/FD" },
+    { 0x0b, AA "100/FD, 10/FD, 10/HD" },
+    { 0x0c, AA "100/FD, 100/HD" },
+    { 0x0d, AA "100/FD, 100/HD, 10/HD" },
+    { 0x0e, AA "100/FD, 100/HD, 10/FD" },
+    { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
+    { 0x20, AA "1000/FD" },
+    { 0x21, AA "1000/FD, 10/HD" },
+    { 0x22, AA "1000/FD, 10/FD" },
+    { 0x23, AA "1000/FD, 10/FD, 10/HD" },
+    { 0x24, AA "1000/FD, 100/HD" },
+    { 0x25, AA "1000/FD, 100/HD, 10/HD" },
+    { 0x26, AA "1000/FD, 100/HD, 10/FD" },
+    { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
+    { 0x28, AA "1000/FD, 100/FD" },
+    { 0x29, AA "1000/FD, 100/FD, 10/HD" },
+    { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
+    { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
+    { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
+    { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
+    { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
+    { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" } };
+
+  struct pch_gbe_option opt = {
+   .type = list_option,
+   .name = "AutoNeg",
+   .err  = "parameter ignored",
+   .def  = AUTONEG_ADV_DEFAULT,
+   .arg  = { .l = { .nr = (int)ARRAY_SIZE(an_list),
+      .p = an_list} }
+  };
+
+  if (num_AutoNeg > bd) {
+   if (speed != 0 || dplx != 0) {
+    DPRINTK(PROBE, INFO,
+    "AutoNeg specified along with Speed or Duplex, "
+    "parameter ignored\n");
+    hw->phy.autoneg_advertised = opt.def;
+   } else {
+    hw->phy.autoneg_advertised = AutoNeg[bd];
+    pch_gbe_validate_option(
+     (int *)(&hw->phy.autoneg_advertised),
+     &opt, adapter);
+   }
+  } else {
+   hw->phy.autoneg_advertised = opt.def;
+  }
+ }
+
+ switch (speed + dplx) {
+ case 0:
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  if ((num_Speed > bd) && (speed != 0 || dplx != 0))
+   DPRINTK(PROBE, INFO,
+    "Speed and duplex autonegotiation enabled\n");
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_HALF_DUPLEX:
+  DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n");
+  DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+   "Half Duplex only\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+      PHY_ADVERTISE_100_HALF;
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_FULL_DUPLEX:
+  DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n");
+  DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+   "Full Duplex only\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
+      PHY_ADVERTISE_100_FULL |
+      PHY_ADVERTISE_1000_FULL;
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_FULL;
+  break;
+ case PHY_SPEED_10:
+  DPRINTK(PROBE, INFO, "10 Mbps Speed specified "
+   "without Duplex\n");
+  DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+      PHY_ADVERTISE_10_FULL;
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_SPEED_10 + PHY_HALF_DUPLEX:
+  DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Half Duplex\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+  hw->phy.autoneg_advertised = 0;
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_SPEED_10 + PHY_FULL_DUPLEX:
+  DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Full Duplex\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+  hw->phy.autoneg_advertised = 0;
+  hw->mac.link_speed = SPEED_10;
+  hw->mac.link_duplex = DUPLEX_FULL;
+  break;
+ case PHY_SPEED_100:
+  DPRINTK(PROBE, INFO, "100 Mbps Speed specified "
+   "without Duplex\n");
+  DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+   "100 Mbps only\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
+      PHY_ADVERTISE_100_FULL;
+  hw->mac.link_speed = SPEED_100;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_SPEED_100 + PHY_HALF_DUPLEX:
+  DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Half Duplex\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+  hw->phy.autoneg_advertised = 0;
+  hw->mac.link_speed = SPEED_100;
+  hw->mac.link_duplex = DUPLEX_HALF;
+  break;
+ case PHY_SPEED_100 + PHY_FULL_DUPLEX:
+  DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Full Duplex\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+  hw->phy.autoneg_advertised = 0;
+  hw->mac.link_speed = SPEED_100;
+  hw->mac.link_duplex = DUPLEX_FULL;
+  break;
+ case PHY_SPEED_1000:
+  DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without "
+   "Duplex\n");
+  goto full_duplex_only;
+ case PHY_SPEED_1000 + PHY_HALF_DUPLEX:
+  DPRINTK(PROBE, INFO,
+   "Half Duplex is not supported at 1000 Mbps\n");
+  /* fall through */
+ case PHY_SPEED_1000 + PHY_FULL_DUPLEX:
+full_duplex_only:
+  DPRINTK(PROBE, INFO,
+         "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+  hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+  hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
+  hw->mac.link_speed = SPEED_1000;
+  hw->mac.link_duplex = DUPLEX_FULL;
+  break;
+ default:
+  BUG();
+ }
+}
+



^ permalink raw reply

* [PATCH 4/7] Topcliff GbE: Add The Hardware layer I/F code
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

This patch adds the Hardware layer I/F code of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/net/pch_gbe/pch_gbe_api.c          | 648 ++
 drivers/net/pch_gbe/pch_gbe_api.h          | 251
 drivers/net/pch_gbe/pch_gbe_plat.c         | 175
+++++++++++++++++++++++++++++++ 3 files changed, 1074 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c 2010-04-13
19:23:50.000000000 +0900
@@ -0,0 +1,648 @@
+/*!
+ * @file pch_gbe_api.c
+ * @brief Linux PCH Gigabit Ethernet Driver HAL API source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe_mac.h"
+#include "pch_gbe_api.h"
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+ * @brief   Sets MAC type
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks This function sets the mac type of the adapter based on the
+ *          device ID stored in the hw structure.
+ *          MUST BE FIRST FUNCTION CALLED (explicitly or through
+ *          pch_gbe_hal_setup_init_funcs()).
+ */
+s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ s32 ret_val = PCH_GBE_SUCCESS;
+
+ PCH_DEBUG("pch_gbe_hal_set_mac_type\n");
+
+ switch ((u16) hw->device_id) {
+ case PCI_DEVICE_ID_INTEL_IOH1_GBE:
+  mac->type = PCH_GBE_MAC_TYPE_PCH1;
+  break;
+ default:
+  /* Should never have loaded on this device */
+  mac->type = PCH_GBE_MAC_TYPE_UNDEFINED;
+  ret_val = -PCH_GBE_ERR_MAC_INIT;
+  break;
+ }
+ PCH_DEBUG("mac->type:0x%x  ret_val:0x%x\n", mac->type, ret_val);
+ return ret_val;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+ * @brief   Initializes function pointers
+ * @param   hw [INOUT] pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks This function must be called by a driver in order to use the
rest
+ *          of the 'shared' code files. Called by drivers only.
+ */
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+{
+ s32 ret_val;
+
+ PCH_DEBUG("pch_gbe_hal_setup_init_funcs\n");
+
+ /* Can't do much good without knowing the MAC type.
+  */
+ ret_val = pch_gbe_hal_set_mac_type(hw);
+ if (ret_val) {
+  PCH_LOG(KERN_ERR,
+   "ERROR: MAC type could not be set properly.\n");
+  goto out;
+ }
+
+ if (!hw->hw_addr) {
+  PCH_LOG(KERN_ERR, "ERROR: Registers not mapped\n");
+  ret_val = -PCH_GBE_ERR_CONFIG;
+  goto out;
+ }
+
+ /* Set up the init function pointers. These are functions within the
+  * adapter family file that sets up function pointers for the rest of
+  * the functions in that family.
+  */
+ switch (hw->mac.type) {
+ case PCH_GBE_MAC_TYPE_PCH1:
+ case PCH_GBE_MAC_TYPE_PCH2:
+  pch_gbe_plat_init_function_pointers(hw);
+  break;
+ default:
+  PCH_LOG(KERN_ERR, "Hardware not supported\n");
+  ret_val = -PCH_GBE_ERR_CONFIG;
+  break;
+ }
+out:
+ PCH_DEBUG("ret_val:0x%x\n", ret_val);
+ return ret_val;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief   Obtain bus information for adapter
+ * @param   hw [INOUT] pointer to the HW structure
+ * @return  None
+ * @remarks This will obtain information about the HW bus for which the
+ *          adaper is attached and stores it in the hw structure. This is a
+ *          function pointer entry point called by drivers.
+ */
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_get_bus_info\n");
+
+ if (hw->func.get_bus_info != NULL)
+  hw->func.get_bus_info(hw);
+ else
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ *               u8 *mc_addr_list, u32 mc_addr_count,
+ *               u32 mar_used_count, u32 mar_count)
+ * @brief   Update Multicast addresses
+ * @param   hw        [INOUT] Pointer to the HW structure
+ * @param   mc_addr_list   [IN]Array of multicast addresses to program
+ * @param   mc_addr_count  [IN]Number of multicast addresses to program
+ * @param   mar_used_count [IN]The first MAC Address register free to
program
+ * @param   mar_count [IN]Total number of supported MAC Address Registers
+ * @return  None
+ * @remarks
+ *  Updates the MAC Address Registers and Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ *  The parameter mar_count will usually be hw->mac.mar_entry_count
+ *  unless there are workarounds that change this.  Currently no func
pointer
+ *  exists and all implementations are handled in the generic version of
this
+ *  function.
+ */
+void
+pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+    u8 *mc_addr_list,
+    u32 mc_addr_count,
+    u32 mar_used_count, u32 mar_count)
+{
+ PCH_DEBUG("pch_gbe_hal_mc_addr_list_update\n");
+
+ if (hw->func.mc_addr_list_update != NULL) {
+  hw->func.mc_addr_list_update(hw,
+          mc_addr_list,
+          mc_addr_count,
+          mar_used_count, mar_count);
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+ * @brief   Force MAC flow control
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Force the MAC's flow control settings. Currently no func pointer exists
+ *  and all implementations are handled in the generic version of this
+ *  function.
+ */
+s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_force_mac_fc\n");
+
+ return pch_gbe_mac_force_mac_fc(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+ * @brief   Reset hardware
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This resets the hardware into a known state. This is a function pointer
+ *  entry point called by drivers.
+ */
+s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_reset_hw\n");
+
+ if (hw->func.reset_hw != NULL) {
+  hw->func.reset_hw(hw);
+  return PCH_GBE_SUCCESS;
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+ * @brief   Initialize hardware
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This inits the hardware readying it for operation. This is a function
+ *  pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_init_hw\n");
+
+ if (hw->func.init_hw != NULL) {
+  return hw->func.init_hw(hw);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+ * @brief   Configures link and flow control
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This configures link and flow control settings for the adapter. This
+ *  is a function pointer entry point called by drivers. While modules can
+ *  also call this, they probably call their own version of this function.
+ */
+s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_setup_link\n");
+
+ if (hw->func.setup_link != NULL) {
+  return hw->func.setup_link(hw);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+ * @brief   Configures SW controllable LED
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This prepares the SW controllable LED for use and saves the current
state
+ *  of the LED so it can be later restored. This is a function pointer
entry
+ *  point called by drivers.
+ */
+s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_setup_led\n");
+
+ if (hw->func.setup_led != NULL)
+  return hw->func.setup_led(hw);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+ * @brief   Restores SW controllable LED
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This restores the SW controllable LED to the value saved off by
+ *  pch_gbe_hal_setup_led.
+ *  This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_cleanup_led\n");
+
+ if (hw->func.cleanup_led != NULL)
+  return hw->func.cleanup_led(hw);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+ * @brief   Turn on SW controllable LED
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Turns the SW defined LED on. This is a function pointer entry point
+ *  called by drivers.
+ */
+s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_led_on\n");
+
+ if (hw->func.led_on != NULL)
+  return hw->func.led_on(hw);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+ * @brief   Turn off SW controllable LED
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Turns the SW defined LED off. This is a function pointer entry point
+ *  called by drivers.
+ */
+s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_led_off\n");
+
+ if (hw->func.led_off != NULL)
+  return hw->func.led_off(hw);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32
index)
+ * @brief   Sets a MAC address register
+ * @param   hw    [INOUT] Pointer to the HW structure
+ * @param   addr  [IN] Address to set the RAR to
+ * @param   index [IN] The RAR to set
+ * @return  None
+ * @remarks
+ *  Sets a MAC Address Register (RAR) to the specified address.
+ *  Currently no func pointer exists and all implementations are
+ *  handled in the generic version of this function.
+ */
+void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32 index)
+{
+ PCH_DEBUG("pch_gbe_hal_mar_set\n");
+
+ pch_gbe_mac_mar_set(hw, addr, index);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw,
+ *                                       u32 offset, u16 *data)
+ * @brief   Reads PHY register
+ * @param   hw     [INOUT] Pointer to the HW structure
+ * @param   offset [IN] The register to read
+ * @param   data   [IN] The buffer to store the 16-bit read.
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Reads the PHY register and returns the value in data.
+ *  This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_read_phy_reg\n");
+
+ if (hw->func.read_phy_reg != NULL)
+  return hw->func.read_phy_reg(hw, offset, data);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw,
+ *                                        u32 offset, u16 data)
+ * @brief   Writes PHY register
+ * @param   hw     [INOUT] Pointer to the HW structure
+ * @param   offset [IN] The register to write
+ * @param   data   [IN] The value to write.
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Writes the PHY register at offset with the value in data.
+ *  This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data)
+{
+ PCH_DEBUG("pch_gbe_hal_write_phy_reg\n");
+
+ if (hw->func.write_phy_reg != NULL)
+  return hw->func.write_phy_reg(hw, offset, data);
+ else
+  return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+ * @brief   Hard PHY reset
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  None
+ * @remarks
+ *  Performs a hard PHY reset. This is a function pointer entry point
called
+ *  by drivers.
+ */
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_phy_hw_reset\n");
+
+ if (hw->func.reset_phy != NULL)
+  hw->func.reset_phy(hw);
+ else
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+ * @brief   Soft PHY reset
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  None
+ * @remarks
+ *  Performs a soft PHY reset on those that apply. This is a function
pointer
+ *  entry point called by drivers.
+ */
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_phy_sw_reset\n");
+
+ if (hw->func.sw_reset_phy != NULL)
+  hw->func.sw_reset_phy(hw);
+ else
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+ * @brief   Reads MAC address
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Reads the MAC address out of the adapter and stores it in the HW
structure.
+ *  Currently no func pointer exists and all implementations are handled in
the
+ *  generic version of this function.
+ */
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_read_mac_addr\n");
+
+ if (hw->func.read_mac_addr != NULL) {
+  return hw->func.read_mac_addr(hw);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+#ifdef CONFIG_PCH_PHUB
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+ * @brief   Verifies NVM (EEPROM) checksum
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Validates the NVM checksum is correct. This is a function pointer entry
+ *  point called by drivers.
+ */
+s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_validate_nvm_checksum\n");
+
+ if (hw->func.validate_nvm != NULL) {
+  return hw->func.validate_nvm(hw);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw,
+ *                                   u32 offset, u8 *data)
+ * @brief   Reads NVM (EEPROM)
+ * @param   hw     [INOUT] Pointer to the HW structure
+ * @param   offset [IN] The word offset to read
+ * @param   data   [IN] Pointer to the properly sized buffer for the data.
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_read_nvm\n");
+
+ if (hw->func.read_nvm != NULL) {
+  return hw->func.read_nvm(hw, offset, data);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw,
+ *                                    u32 offset, u8 *data)
+ * @brief   Writes to NVM (EEPROM)
+ * @param   hw     [INOUT] Pointer to the HW structure
+ * @param   offset [IN] The word offset to read
+ * @param   data   [IN] Pointer to the properly sized buffer for the data.
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_write_nvm\n");
+
+ if (hw->func.write_nvm != NULL)
+  return hw->func.write_nvm(hw, offset, data);
+ else
+  return PCH_GBE_SUCCESS;
+}
+#endif /* CONFIG_PCH_PHUB */
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32
wu_evt)
+ * @brief   Set wake-on-lan event
+ * @param   hw     [INOUT] Pointer to the HW structure
+ * @param   wu_evt [IN] Wake up event
+ * @return  None
+ */
+void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt)
+{
+ PCH_DEBUG("pch_gbe_hal_set_wol_event\n");
+
+ pch_gbe_mac_set_wol_event(hw, wu_evt);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+ * @brief   Power up PHY
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  None
+ */
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_power_up_phy\n");
+
+ if (hw->func.power_up_phy != NULL)
+  hw->func.power_up_phy(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+ * @brief   Power down PHY
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  None
+ */
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_power_down_phy\n");
+
+ if (hw->func.power_down_phy != NULL)
+  hw->func.power_down_phy(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw,
+ *                                    u32 addr, u32 dir, u32 reg, u16 data)
+ * @brief   Control MII Management IF
+ * @param   hw   [INOUT] Pointer to the HW structure
+ * @param   addr [IN] Address of PHY
+ * @param   dir  [IN] Operetion. (Write or Read)
+ * @param   reg  [IN] Access register of PHY
+ * @param   data [IN] Write data
+ * @return  None
+ */
+u16
+pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg,
+        u16 data)
+{
+#ifdef DEBUG_TEST
+ PCH_DEBUG("pch_gbe_hal_ctrl_miim\n");
+#endif
+ if (hw->func.ctrl_miim != NULL) {
+  return hw->func.ctrl_miim(hw, addr, dir, reg, data);
+ } else {
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+  return PCH_GBE_SUCCESS;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+ * @brief   Set pause packet
+ * @param   hw [INOUT] Pointer to the HW structure
+ * @return  None
+ */
+void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_set_pause_packet\n");
+
+ if (hw->func.pause_packet != NULL)
+  hw->func.pause_packet(hw);
+ else
+  PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h 2010-04-13
19:25:22.000000000 +0900
@@ -0,0 +1,251 @@
+/*!
+ * @file pch_gbe_api.h
+ * @brief Linux PCH Gigabit Ethernet Driver HAL API header file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#ifndef _PCH_GBE_API_H_
+#define _PCH_GBE_API_H_
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+ * @brief   Sets MAC type
+ */
+s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+ * @brief   Initializes function pointers
+ */
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief   Obtain bus information for adapter
+ */
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ *               u8 *mc_addr_list, u32 mc_addr_count,
+ *               u32 mar_used_count, u32 mar_count)
+ * @brief   Update Multicast addresses
+ */
+void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+     u8 *mc_addr_list, u32 mc_addr_count,
+     u32 mar_used_count, u32 mar_count);
+
+/*
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+ * @brief   Force MAC flow control
+ */
+s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+ * @brief   Reset hardware
+ */
+s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+ * @brief   Initialize hardware
+ */
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+ * @brief   Configures link and flow control
+ */
+s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+ * @brief   Configures SW controllable LED
+ */
+s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+ * @brief   Restores SW controllable LED
+ */
+s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+ * @brief   Turn on SW controllable LED
+ */
+s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+ * @brief   Turn off SW controllable LED
+ */
+s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32
index)
+ * @brief   Sets a MAC address register
+ */
+void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32 index);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw,
+ *      u32 offset, u16 *data)
+ * @brief   Reads PHY register
+ */
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw,
+ *      u32 offset, u16 data)
+ * @brief   Writes PHY register
+ */
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+ * @brief   Hard PHY reset
+ */
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+ * @brief   Soft PHY reset
+ */
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+ * @brief   Reads MAC address
+ */
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw);
+
+#ifdef CONFIG_PCH_PHUB
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+ * @brief   Verifies NVM (EEPROM) checksum
+ */
+s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw,
+ *     u32 offset, u8 *data)
+ * @brief   Reads NVM (EEPROM)
+ */
+s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw,
+ *     u32 offset, u8 *data)
+ * @brief   Writes to NVM (EEPROM)
+ */
+s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data);
+#endif /* CONFIG_PCH_PHUB */
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32
wu_evt)
+ * @brief   Set wake-on-lan event
+ */
+void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+ * @brief   Power up PHY
+ */
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+ * @brief   Power down PHY
+ */
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw,
+ *                                    u32 addr, u32 dir, u32 reg, u16 data)
+ * @brief   Control MII Management IF
+ */
+u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32
reg,
+     u16 data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn      void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+ * @brief   Set pause packet
+ */
+void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup  HAL API Layer
+ * @def      PCH_GBE_HAL_MIIM_READ
+ * @brief    Read operation is done through MII Management IF
+ */
+#define PCH_GBE_HAL_MIIM_READ          ((u32)0x00000000)
+
+/*!
+ * @ingroup  HAL API Layer
+ * @def      PCH_GBE_HAL_MIIM_WRITE
+ * @brief    Write operation is done through MII Management IF
+ */
+#define PCH_GBE_HAL_MIIM_WRITE         ((u32)0x04000000)
+
+/* pch_gbe_plat.c */
+/*!
+ * @ingroup HAL internal functions
+ * @fn      void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+ * @brief   Init func ptrs.
+ */
+void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw);
+
+#endif
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c 2010-04-13
19:25:07.000000000 +0900
@@ -0,0 +1,175 @@
+/*!
+ * @file pch_gbe_plat.c
+ * @brief Linux PCH Gigabit Ethernet Driver HAL internal function
(platform) source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe_mac.h"
+#include "pch_gbe_nvm.h"
+#include "pch_gbe_phy.h"
+#include "pch_gbe_api.h"
+
+
+static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw);
+static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw);
+
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn      void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+ * @brief   Init func ptrs.
+ * @param   hw  [OUT] Pointer to the HW structure
+ * @return  None
+ * @remarks
+ *  The only function explicitly called by the api module to initialize
+ *  all function pointers and parameters.
+ */
+void
+pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ struct pch_gbe_phy_info *phy = &hw->phy;
+ struct pch_gbe_nvm_info *nvm = &hw->nvm;
+ struct pch_gbe_functions *func = &hw->func;
+
+ PCH_DEBUG("pch_gbe_plat_init_function_pointers\n");
+
+ /* Set MAC address registers entry count */
+ mac->mar_entry_count    = PCH_GBE_MAR_ENTRIES;
+ /* Set PHY parameter */
+ phy->reset_delay_us     = PCH_GBE_PHY_RESET_DELAY_US;
+ /* Set NVM parameter */
+ nvm->word_size          = PCH_GBE_NVM_WORD_SIZE;
+
+ /* Set function pointers */
+ func->get_bus_info             = pch_gbe_plat_get_bus_info;
+ func->reset_hw                 = pch_gbe_mac_reset_hw;
+ func->init_hw                  = pch_gbe_plat_init_hw;
+ func->setup_link               = pch_gbe_mac_setup_link;
+ func->setup_physical_interface = pch_gbe_phy_setup_link_fpga;
+ func->mc_addr_list_update      = pch_gbe_mac_mc_addr_list_update;
+ func->setup_led                = pch_gbe_phy_led_setup;
+ func->cleanup_led              = pch_gbe_phy_led_cleanup;
+ func->led_on                   = pch_gbe_phy_led_on;
+ func->led_off                  = pch_gbe_phy_led_off;
+ func->read_phy_reg             = pch_gbe_phy_read_reg_miic;
+ func->write_phy_reg            = pch_gbe_phy_write_reg_miic;
+ func->reset_phy                = pch_gbe_phy_hw_reset;
+ func->sw_reset_phy             = pch_gbe_phy_sw_reset;
+ func->power_up_phy             = pch_gbe_phy_power_up;
+ func->power_down_phy           = pch_gbe_phy_power_down;
+#ifdef CONFIG_PCH_PHUB
+ func->read_nvm                 = pch_gbe_nvm_read_mem;
+ func->write_nvm                = pch_gbe_nvm_write_mem;
+ func->validate_nvm             = pch_gbe_nvm_validate_checksum;
+ func->read_mac_addr            = pch_gbe_nvm_read_mac_addr;
+#else
+ func->read_mac_addr            = pch_gbe_mac_read_mac_addr;
+#endif
+ func->ctrl_miim                = pch_gbe_mac_ctrl_miim;
+ func->pause_packet             = pch_gbe_mac_set_pause_packet;
+
+#ifdef DEBUG_TEST
+ PCH_DEBUG("[MAC]mar_entry_count:%d /[PHY] reset_delay_us:%d\n",
+   mac->mar_entry_count, phy->reset_delay_us);
+ PCH_DEBUG("[NVM] word_size:0x%08x\n", nvm->word_size);
+#endif
+}
+
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn      static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief   Obtain bus information for adapter
+ * @param   hw  [OUT] Pointer to the HW structure
+ * @return  None
+ * @remarks
+ *  This will obtain information about the HW bus for which the
+ *  adaper is attached and stores it in the hw structure.  This is a
function
+ *  pointer entry point called by the api module.
+ */
+static void
+pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_plat_get_bus_info\n");
+
+ hw->bus.type  = pch_gbe_bus_type_pci_express;
+ hw->bus.speed = pch_gbe_bus_speed_2500;
+ hw->bus.width = pch_gbe_bus_width_pcie_x1;
+
+#ifdef DEBUG_TEST
+ PCH_DEBUG("[BUS] type:0x%08x  speed:0x%08x  width:0x%08x\n",
+   hw->bus.type, hw->bus.speed, hw->bus.width);
+#endif
+}
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn      static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+ * @brief   Initialize hardware
+ * @param   hw  [INOUT] Pointer to the HW structure
+ * @return  PCH_GBE_SUCCESS:  Successfully
+ * @return  Negative value:  Failed
+ * @remarks
+ *  This inits the hardware readying it for operation.  This is a
+ *  function pointer entry point called by the api module.
+ */
+static s32
+pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ s32 ret_val;
+
+ PCH_DEBUG("pch_gbe_plat_init_hw\n");
+
+ /* Setup the receive address. */
+ pch_gbe_mac_init_rx_addrs(hw, mac->mar_entry_count);
+
+ ret_val = pch_gbe_phy_get_id(hw);
+ if (ret_val) {
+  PCH_LOG(KERN_ERR, "pch_gbe_phy_get_id error\n");
+  return ret_val;
+ }
+ pch_gbe_phy_init_setting(hw);
+ /* Setup Mac interface option RGMII */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+ pch_gbe_phy_set_rgmii(hw);
+#endif
+ /* Setup link and flow control */
+ ret_val = pch_gbe_hal_setup_link(hw);
+#ifdef DEBUG_TEST
+ if (ret_val)
+  PCH_LOG(KERN_ERR, "pch_gbe_phy_get_id error\n");
+#endif
+ return ret_val;
+}
+


^ permalink raw reply

* [PATCH 3/7] Topcliff GbE: Add The Ethtool code [1/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 39196 bytes --]

^ permalink raw reply

* [PATCH 5/7] Topcliff GbE: Add The Hardware layer codes [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 9627 bytes --]

^ permalink raw reply

* [PATCH 5/7] Topcliff GbE: Add The Hardware layer codes [1/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 39112 bytes --]

^ permalink raw reply

* [PATCH 6/7] Topcliff GbE: Add The common header files [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:01 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

[-- Attachment #1: Type: message/partial, Size: 15960 bytes --]

^ permalink raw reply

* [PATCH 7/7] Topcliff GbE: Change The Kconfig and Makefile
From: Masayuki Ohtake @ 2010-04-23 12:01 UTC (permalink / raw)
  To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

This patch change the Kconfig and Makefile of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/net/Kconfig                        | 5 ++
 drivers/net/Makefile                       | 1
 drivers/net/pch_gbe/Makefile               | 6
+++++++++++++++++++++++++++++++ 3 files changed, 12 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/Kconfig
topcliff-2.6.33.1/drivers/net/Kconfig
--- linux-2.6.33.1/drivers/net/Kconfig 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/Kconfig 2010-04-13 00:55:22.000000000
+0900
@@ -1977,6 +1977,11 @@
    If you say N, all options in this submenu will be skipped and disabled.

 if NETDEV_1000
+config PCH_GBE
+        tristate "PCH Gigabit Ethernet"
+        ---help---
+          This is an gigabit ethernet driver for PCH.
+          resources.

 config ACENIC
  tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
diff -urN linux-2.6.33.1/drivers/net/Makefile
topcliff-2.6.33.1/drivers/net/Makefile
--- linux-2.6.33.1/drivers/net/Makefile 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/Makefile 2010-04-13 00:55:22.000000000
+0900
@@ -287,3 +287,4 @@
 obj-$(CONFIG_WIMAX) += wimax/

 obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/Makefile
topcliff-2.6.33.1/drivers/net/pch_gbe/Makefile
--- linux-2.6.33.1/drivers/net/pch_gbe/Makefile 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/Makefile 2010-04-13
00:55:22.000000000 +0900
@@ -0,0 +1,6 @@
+ifeq ($(CONFIG_PCH_GBE_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_GBE) += pch_gbe.o
+pch_gbe-objs := pch_gbe_mac.o pch_gbe_phy.o pch_gbe_nvm.o pch_gbe_ethtool.o
pch_gbe_plat.o pch_gbe_param.o pch_gbe_api.o pch_gbe_main.o


^ permalink raw reply


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