* 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox