* Re: [PATCH] PHYLIB: IRQ event workqueue handling fixes
From: Andrew Morton @ 2007-09-20 23:53 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Andy Fleming, Jeff Garzik, netdev, linux-kernel
In-Reply-To: <Pine.LNX.4.64N.0709171750220.17606@blysk.ds.pg.gda.pl>
On Wed, 19 Sep 2007 15:38:19 +0100 (BST)
"Maciej W. Rozycki" <macro@linux-mips.org> wrote:
> Keep track of disable_irq_nosync() invocations and call enable_irq() the
> right number of times if work has been cancelled that would include them.
>
> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---
> Now that the call to flush_work_keventd() (problematic because of
> rtnl_mutex being held) has been replaced by cancel_work_sync() another
> issue has arisen and been left unresolved. As the MDIO bus cannot be
> accessed from the interrupt context the PHY interrupt handler uses
> disable_irq_nosync() to prevent from looping and schedules some work to be
> done as a softirq, which, apart from handling the state change of the
> originating PHY, is responsible for reenabling the interrupt. Now if the
> interrupt line is shared by another device and a call to the softirq
> handler has been cancelled, that call to enable_irq() never happens and
> the other device cannot use its interrupt anymore as its stuck disabled.
>
> I decided to use a counter rather than a flag because there may be more
> than one call to phy_change() cancelled in the queue -- a real one and a
> fake one triggered by free_irq() if DEBUG_SHIRQ is used, if nothing else.
> Therefore because of its nesting property enable_irq() has to be called
> the right number of times to match the number disable_irq_nosync() was
> called and restore the original state. This DEBUG_SHIRQ feature is also
> the reason why free_irq() has to be called before cancel_work_sync().
>
> While at it I updated the comment about phy_stop_interrupts() being
> called from `keventd' -- this is no longer relevant as the use of
> cancel_work_sync() makes such an approach unnecessary. OTOH a similar
> comment referring to flush_scheduled_work() in phy_stop() still applies as
> using cancel_work_sync() there would be dangerous.
>
> Checked with checkpatch.pl and at the run time (with and without
> DEBUG_SHIRQ).
You always put boring, crappy, insufficient text in the for-the-changelog
section and interesting, useful, sufficient text in the not-for-the-changelog
section.
But you can't fool me! I have an editor and I fix it up.
^ permalink raw reply
* Re: [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Stephen Rothwell @ 2007-09-21 0:08 UTC (permalink / raw)
To: Scott Wood; +Cc: jgarzik, netdev, linuxppc-dev
In-Reply-To: <20070920220121.GF28784@loki.buserror.net>
[-- Attachment #1: Type: text/plain, Size: 1316 bytes --]
On Thu, 20 Sep 2007 17:01:21 -0500 Scott Wood <scottwood@freescale.com> wrote:
>
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -44,12 +44,18 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
Hmm, didn't I already ask you to change this to linux/of_platform.h?
> +++ b/drivers/net/fs_enet/mac-fcc.c
> @@ -42,6 +42,10 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_device.h>
And this to linux/of_device.h
> +++ b/drivers/net/fs_enet/mac-fec.c
> @@ -43,6 +43,10 @@
> #include <asm/commproc.h>
> #endif
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_device.h>
And this?
> +++ b/drivers/net/fs_enet/mac-scc.c
> @@ -43,6 +43,10 @@
> #include <asm/commproc.h>
> #endif
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
And this
> +++ b/drivers/net/fs_enet/mii-fec.c
> @@ -36,6 +36,10 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
And here
Sorry if I missed these last time around.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Scott Wood @ 2007-09-21 0:44 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: jgarzik, netdev, linuxppc-dev
In-Reply-To: <20070921100841.6904f2bc.sfr@canb.auug.org.au>
On Fri, Sep 21, 2007 at 10:08:41AM +1000, Stephen Rothwell wrote:
> On Thu, 20 Sep 2007 17:01:21 -0500 Scott Wood <scottwood@freescale.com> wrote:
> >
> > +++ b/drivers/net/fs_enet/fs_enet-main.c
> > @@ -44,12 +44,18 @@
> > #include <asm/irq.h>
> > #include <asm/uaccess.h>
> >
> > +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> > +#include <asm/of_platform.h>
>
> Hmm, didn't I already ask you to change this to linux/of_platform.h?
Grrr, I thought I'd gotten them all.
-Scott
^ permalink raw reply
* Re: Please pull 'iwlwifi' branch of wireless-2.6
From: Zhu Yi @ 2007-09-21 1:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: John W. Linville, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
jeff-o2qLIJkoznsdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20070919101326.GA32432-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
On Wed, 2007-09-19 at 11:13 +0100, Christoph Hellwig wrote:
> it really needs to be moved into a directory of it's own.
It used to be... John?
> The useless per-file CFLAGS need to go most places can trivially
> be made unconditional anyway.
OK.
> The depends on m for CONFIG_IWL4965 and CONFIG_IWL3945 needs to go,
> we don't put drivers int that need to be modular.
Since we splited the code base for 3945 and 4965 by a simple "fork" of
file iwl-base.c, some non-static functions names remain the same. Make
the two drivers build into vmlinux at the same time will cause conflict.
So to make them depend on m is a current workaround for .24. We will
abstract a common iwl-core.ko and make driver specific iwl3945.ko and
iwl4965.ko depend on it in .25 time frame.
Thanks,
-yi
^ permalink raw reply
* Re: bnx2 dirver's firmware images
From: Michael Chan @ 2007-09-21 2:12 UTC (permalink / raw)
To: Denys Vlasenko; +Cc: David Miller, linux-kernel, netdev
In-Reply-To: <200709201549.08165.vda.linux@googlemail.com>
On Thu, 2007-09-20 at 15:49 +0100, Denys Vlasenko wrote:
>
>
> Please test these two patches.
> I updated them according to your comments.
>
>
I've only tested patch #1. It worked after some minor modifications
below.
>
>
>
>
>
> plain text
> document
> attachment
> (linux-2.6.23-
> rc6.bnx2-1.patch)
>
>
> @@ -2767,89 +2769,44 @@ bnx2_set_rx_mode(struct net_device *dev)
> spin_unlock_bh(&bp->phy_lock);
> }
>
> -#define FW_BUF_SIZE 0x8000
> -
> +/* To be moved to generic lib/ */
> static int
> -bnx2_gunzip_init(struct bnx2 *bp)
> +bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len, void **outbuf)
outbuf is no longer needed.
> + rc = zlib_inflateInit2(strm, -MAX_WBITS);
> + if (rc == Z_OK) {
> + rc = zlib_inflate(strm, Z_FINISH);
> + if (rc == Z_OK)
rc will always be Z_STREAM_END in this case since we provide a big
enough gunzip_buf for the whole blob.
^ permalink raw reply
* Re: Please pull 'iwlwifi' branch of wireless-2.6
From: John W. Linville @ 2007-09-21 1:34 UTC (permalink / raw)
To: Zhu Yi; +Cc: Christoph Hellwig, davem, jeff, netdev, linux-wireless
In-Reply-To: <1190337630.5718.136.camel@debian.sh.intel.com>
On Fri, Sep 21, 2007 at 09:20:30AM +0800, Zhu Yi wrote:
> On Wed, 2007-09-19 at 11:13 +0100, Christoph Hellwig wrote:
> > it really needs to be moved into a directory of it's own.
>
> It used to be... John?
Fine by me -- I guess I misinterpreted the some other statements to
make me think we wanted as flat a directory structure as possible.
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* [PATCH RESEND] 2.6.22.6 networking [ipv4]: fix wrong destination when reply packetes
From: lepton @ 2007-09-21 2:23 UTC (permalink / raw)
To: netdev; +Cc: lkm
Hi,
This is a resend of this patch with more details. I'd
like it can be accepted this time.
The problem: In icmp_reply and ip_send_reply function,
we now use rt->rt_src as destination to send out packets.
For packets received in loopback device, this is wrong
sometimes.
Here is an example (NOTE: eth0 address is set to 10.10.10.1/24):
#tcpdump -n -i lo icmp &
[1] 3155
...
# hping3 --icmp --spoof 10.10.10.3 10.10.10.1
...
09:53:49.508449 IP 10.10.10.3 > 10.10.10.1: icmp 8: echo request seq 0
09:53:49.508482 IP 10.10.10.1 > 10.10.10.1: icmp 8: echo reply seq 0
09:53:50.525560 IP 10.10.10.3 > 10.10.10.1: icmp 8: echo request seq 256
09:53:50.525589 IP 10.10.10.1 > 10.10.10.1: icmp 8: echo reply seq 256
The same thing will happend for tcp:
# hping3 --syn --destport 1234 --spoof 10.10.10.3 10.10.10.1
(NOTE: there is no service to listen on port 1234)
...
10:02:59.395715 IP 10.10.10.3.2787 > 10.10.10.1.1234: S
72057069:72057069(0) win 512 <mss 1414>
10:02:59.395746 IP 10.10.10.1.1234 > 10.10.10.1.2787: R 0:0(0) ack
72057070 win 0
As you can see, all destination address is wrong.
This problem comes from the fact that the route selection for packetes
travle on loopback device only happend once. When we send out packets
from loopback device, the skb->dst is assigned in ip_route_output. It
won't be reassinged in packetes recveive path. So the rt->rt_src don't
equal to ip_hdr(skb)->saddr.
I don't know why we must use rt->rt_src as destionation address. at least
for icmp reply packets, I thin we should use ip_hdr(skb)->saddr as
destionation address. this is according to RFC792:
...
Addresses
The address of the source in an echo message will be the
destination of the echo reply message. To form an echo reply
message, the source and destination addresses are simply reversed,
the type code changed to 0, and the checksum recomputed.
A possible fix is to do ip_route_input in ip_rcv_finish for packtes
received in loopback device. But I think just to use ip_hdr(skb)->saddr
instead of rt->rt_src as destination to reply packetes is a more simple fix.
Thanks Kenan Kalajdzic <kalajdzic@gmail.com> for help me with more details
about this problem.
Signed-off-by: Lepton Wu <ytht.net@gmail.com>
diff -X linux-2.6.22.6/Documentation/dontdiff -pru linux-2.6.22.6/net/ipv4/icmp.c linux-2.6.22.6-lepton/net/ipv4/icmp.c
--- linux-2.6.22.6/net/ipv4/icmp.c 2007-09-14 17:41:18.000000000 +0800
+++ linux-2.6.22.6-lepton/net/ipv4/icmp.c 2007-09-18 09:57:30.000000000 +0800
@@ -382,6 +382,7 @@ static void icmp_reply(struct icmp_bxm *
struct ipcm_cookie ipc;
struct rtable *rt = (struct rtable *)skb->dst;
__be32 daddr;
+ struct iphdr *ip = ip_hdr(skb);
if (ip_options_echo(&icmp_param->replyopts, skb))
return;
@@ -393,7 +394,7 @@ static void icmp_reply(struct icmp_bxm *
icmp_out_count(icmp_param->data.icmph.type);
inet->tos = ip_hdr(skb)->tos;
- daddr = ipc.addr = rt->rt_src;
+ daddr = ipc.addr = ip->saddr;
ipc.opt = NULL;
if (icmp_param->replyopts.optlen) {
ipc.opt = &icmp_param->replyopts;
diff -X linux-2.6.22.6/Documentation/dontdiff -pru linux-2.6.22.6/net/ipv4/ip_output.c linux-2.6.22.6-lepton/net/ipv4/ip_output.c
--- linux-2.6.22.6/net/ipv4/ip_output.c 2007-09-14 17:41:18.000000000 +0800
+++ linux-2.6.22.6-lepton/net/ipv4/ip_output.c 2007-09-18 09:57:13.000000000 +0800
@@ -1337,11 +1337,12 @@ void ip_send_reply(struct sock *sk, stru
struct ipcm_cookie ipc;
__be32 daddr;
struct rtable *rt = (struct rtable*)skb->dst;
+ struct iphdr *ip = ip_hdr(skb);
if (ip_options_echo(&replyopts.opt, skb))
return;
- daddr = ipc.addr = rt->rt_src;
+ daddr = ipc.addr = ip->saddr;
ipc.opt = NULL;
if (replyopts.opt.optlen) {
^ permalink raw reply
* Re: [PATCH 3/3 Rev4] Initialize and fill IPv6 route age
From: Krishna Kumar2 @ 2007-09-21 3:05 UTC (permalink / raw)
To: Varun Chandramohan
Cc: davem, kaber, netdev, shemminger, socketcan, tgraf,
Varun Chandramohan
In-Reply-To: <20070920205903.e40b37af.varunc@linux.vnet.ibm.com>
Varun Chandramohan <varunc@linux.vnet.ibm.com> wrote on 09/20/2007 08:59:03
PM:
> @@ -2123,6 +2131,7 @@ static int rt6_fill_node(struct sk_buff
> {
> struct rtmsg *rtm;
> struct nlmsghdr *nlh;
> + struct timeval tv;
> long expires;
> u32 table;
>
> @@ -2186,6 +2195,11 @@ static int rt6_fill_node(struct sk_buff
> if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
> NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
> }
> +
> + do_gettimeofday(&tv);
> + if (rt->rt6i_age) {
> + NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - rt->rt6i_age));
> + }
Will rt6i_age ever be zero with this new patch? If it can be zero,
the code should really be keeping the "tv" declaration and
do_gettimeofday() inside the "if (rt->rt6i_age)" check.
And from your Patch2/3:
int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
- u32 tb_id, u8 type, u8 scope, __be32 dst, int
dst_len, u8 tos,
+ u32 tb_id, u8 type, u8 scope, __be32 dst, int
dst_len, u8 tos, time_t age,
struct fib_info *fi, unsigned int flags)
{
struct nlmsghdr *nlh;
struct rtmsg *rtm;
+ struct timeval tv;
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
if (nlh == NULL)
@@ -985,6 +987,11 @@ int fib_dump_info(struct sk_buff *skb, u
NLA_PUT_U32(skb, RTA_FLOW,
fi->fib_nh[0].nh_tclassid);
#endif
}
+
+ do_gettimeofday(&tv);
+ if (age) {
+ NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - age));
+ }
Don't you want to return time the first time (and get zero)? Otherwise
RTA_AGE is not returned to user. Something like:
do_gettimeofday(&tv);
NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - age));
Once again, can age ever be zero?
- KK
^ permalink raw reply
* Re: [PATCH 3/3 Rev4] Initialize and fill IPv6 route age
From: Varun Chandramohan @ 2007-09-21 4:30 UTC (permalink / raw)
To: Krishna Kumar2
Cc: davem, kaber, netdev, shemminger, socketcan, tgraf,
Varun Chandramohan
In-Reply-To: <OF5159F66B.5A5F01B8-ON6525735D.000FD530-6525735D.0010F45F@in.ibm.com>
Krishna Kumar2 wrote:
> Varun Chandramohan <varunc@linux.vnet.ibm.com> wrote on 09/20/2007 08:59:03
> PM:
>
>
>> @@ -2123,6 +2131,7 @@ static int rt6_fill_node(struct sk_buff
>> {
>> struct rtmsg *rtm;
>> struct nlmsghdr *nlh;
>> + struct timeval tv;
>> long expires;
>> u32 table;
>>
>> @@ -2186,6 +2195,11 @@ static int rt6_fill_node(struct sk_buff
>> if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
>> NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
>> }
>> +
>> + do_gettimeofday(&tv);
>> + if (rt->rt6i_age) {
>> + NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - rt->rt6i_age));
>> + }
>>
>
> Will rt6i_age ever be zero with this new patch? If it can be zero,
> the code should really be keeping the "tv" declaration and
> do_gettimeofday() inside the "if (rt->rt6i_age)" check.
>
>
No, it will be zero only if some new code added doesnt initialize the
route age. I will update this change in my next patch release.
> And from your Patch2/3:
>
> int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
> - u32 tb_id, u8 type, u8 scope, __be32 dst, int
> dst_len, u8 tos,
> + u32 tb_id, u8 type, u8 scope, __be32 dst, int
> dst_len, u8 tos, time_t age,
> struct fib_info *fi, unsigned int flags)
> {
> struct nlmsghdr *nlh;
> struct rtmsg *rtm;
> + struct timeval tv;
>
> nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
> if (nlh == NULL)
> @@ -985,6 +987,11 @@ int fib_dump_info(struct sk_buff *skb, u
> NLA_PUT_U32(skb, RTA_FLOW,
> fi->fib_nh[0].nh_tclassid);
> #endif
> }
> +
> + do_gettimeofday(&tv);
> + if (age) {
> + NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - age));
> + }
>
> Don't you want to return time the first time (and get zero)? Otherwise
> RTA_AGE is not returned to user. Something like:
>
>
The first time it will be zero.
> do_gettimeofday(&tv);
> NLA_PUT_U32(skb, RTA_AGE, (tv.tv_sec - age));
>
> Once again, can age ever be zero?
>
>
same as above.
> - KK
>
>
^ permalink raw reply
* Re: [PATCH RESEND] 2.6.22.6 networking [ipv4]: fix wrong destination when reply packetes
From: David Stevens @ 2007-09-21 4:35 UTC (permalink / raw)
To: lepton; +Cc: lkm, netdev, netdev-owner
In-Reply-To: <20070921022335.GA2849@router.lepton.home>
I'm not sure why it's using rt_src here, but there are relevant cases that
your description doesn't cover. For example, what happens if the source
is not set in the original packet? Does NAT affect this?
You quote RFC text for ICMP echo and the case where the receiving machine
is the final destination, but you're modifying code that is used for all
ICMP
types and used for ICMP errors generated when acting as an intermediate
router.
In ordinary cases, and certainly with ICMP echo when the source is set in
the original packet and no rewriting is going on (and the address is not
spoofed),
using the original source as the destination is fine. But have you tested
or
considered the other cases?
+-DLS
^ permalink raw reply
* [PATCH] E1000: Do not allow requeue of freed skb
From: Krishna Kumar @ 2007-09-21 5:00 UTC (permalink / raw)
To: auke-jan.h.kok; +Cc: netdev, davem, Krishna Kumar
Returning BUSY will make qdisc_restart enqueue the skb which was already
freed. The bad skb was correctly freed and we should return NETDEV_TX_OK.
Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
---
diff -ruNp a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
--- a/drivers/net/e1000e/netdev.c 2007-09-21 10:23:29.000000000 +0530
+++ b/drivers/net/e1000e/netdev.c 2007-09-21 10:24:20.000000000 +0530
@@ -3531,7 +3531,7 @@ static int e1000_xmit_frame(struct sk_bu
/* handle pci_map_single() error in e1000_tx_map */
dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
- return NETDEV_TX_BUSY;
+ return NETDEV_TX_OK;
}
e1000_tx_queue(adapter, tx_flags, count);
^ permalink raw reply
* bind and O_NONBLOCK
From: Ulrich Drepper @ 2007-09-21 5:59 UTC (permalink / raw)
To: netdev, Alan Cox
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Some time back Alan asked about adding O_NONBLOCK support to bind in the
POSIX spec. I brought this up and the following text will be in the
next revision of the POSIX spec:
=======================
If the socket address cannot be assigned immediately and O_NONBLOCK is
set for the file descriptor for the socket, bind( ) shall fail and set
errno to [EINPROGRESS], but the assignment request shall not be aborted,
and the assignment shall be completed asynchronously. Subsequent calls
to bind() for the same socket, before the assignment is completed, shall
fail and set errno to [EALREADY].
When the assignment has been performed asynchronously, pselect(),
select(), and poll() shall indicate that the file descriptor for the
socket is ready for reading and writing.
=======================
It would be ideal if we'd have such an implementation in the next few
months so that we, in theory, can check whether the text in the
specification makes sense.
- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
iD8DBQFG813Z2ijCOnn/RHQRAsNkAJ9EuDWX3EDez8+o/y3I39A7Axy++ACfZAXi
DRFm1UadrbJ+c7ss0a1vWUI=
=p1bV
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: [PATCH RESEND] 2.6.22.6 networking [ipv4]: fix wrong destination when reply packetes
From: lepton @ 2007-09-21 6:03 UTC (permalink / raw)
To: David Stevens; +Cc: lepton, lkm, netdev, netdev-owner
In-Reply-To: <OFC759A0A2.B923AD69-ON8825735D.0017012F-8825735D.00191D21@us.ibm.com>
Now icmp_reply is only called by icmp_echo and icmp_timestamp
ip_send_reply is only called by tcp_v4_send_reset and tcp_v4_send_ack
I think in all situations the ip_hdr(skb)->saddr is set and should
be the destination of reply packets.
If using rt->rt_src as destination is correct in some situation,
can anyone give me a example?
I think perhaps it is a copy and paste from code like
ip_build_and_send_pkt, but reply packets in these situations
(icmp_echo and icmp_timestamp and tcp_v4_send_ack and tcp_v4_send_reset)
is diffrent, I think we can just use ip_hdr(skb)->saddr as
destination address.
On Thu, Sep 20, 2007 at 09:35:09PM -0700, David Stevens wrote:
> I'm not sure why it's using rt_src here, but there are relevant cases that
> your description doesn't cover. For example, what happens if the source
> is not set in the original packet? Does NAT affect this?
>
> You quote RFC text for ICMP echo and the case where the receiving machine
> is the final destination, but you're modifying code that is used for all
> ICMP
> types and used for ICMP errors generated when acting as an intermediate
> router.
>
> In ordinary cases, and certainly with ICMP echo when the source is set in
> the original packet and no rewriting is going on (and the address is not
> spoofed),
> using the original source as the destination is fine. But have you tested
> or
> considered the other cases?
>
> +-DLS
>
^ permalink raw reply
* Re: Pull request for 'r8169-for-jeff-20070919' branch
From: Francois Romieu @ 2007-09-21 7:08 UTC (permalink / raw)
To: Chuck Ebbert
Cc: Jeff Garzik, netdev, akpm, David Gundersen, Edward Hsu,
Sylvain Le Gall, Roel.Teuwen
In-Reply-To: <46F2E590.1070704@redhat.com>
Chuck Ebbert <cebbert@redhat.com> :
[...]
> Looking again, it may not be r8169's fault, but it is involved. It
Sort of:
[...]
* Hung when moving data off a physical disk in an LVM. Twice during night.
* Hung when adding a disk to a software Raid. Once.
> used to hang and could be restarted by pulling the cable and reinserting
> it,
This is already worked around in 2.6.22-stable.
> but now it just locks solid:
>
> https://bugzilla.redhat.com/show_bug.cgi?id=252955
A part of it look like the usual samba + 816x failure. The most recent
changeset in the patch submitted for inclusion should be applied.
--
Ueimor
^ permalink raw reply
* Re: Please pull 'iwlwifi' branch of wireless-2.6
From: Christoph Hellwig @ 2007-09-21 8:05 UTC (permalink / raw)
To: Zhu Yi
Cc: Christoph Hellwig, John W. Linville, davem, jeff, netdev,
linux-wireless
In-Reply-To: <1190337630.5718.136.camel@debian.sh.intel.com>
On Fri, Sep 21, 2007 at 09:20:30AM +0800, Zhu Yi wrote:
> > The depends on m for CONFIG_IWL4965 and CONFIG_IWL3945 needs to go,
> > we don't put drivers int that need to be modular.
>
> Since we splited the code base for 3945 and 4965 by a simple "fork" of
> file iwl-base.c, some non-static functions names remain the same. Make
> the two drivers build into vmlinux at the same time will cause conflict.
> So to make them depend on m is a current workaround for .24. We will
> abstract a common iwl-core.ko and make driver specific iwl3945.ko and
> iwl4965.ko depend on it in .25 time frame.
This kind of stuff is not what we want to leak into mainline. If you're
too busy to do that 5 minute sed search and replace I'll do it for you.
^ permalink raw reply
* change the way e1000 is handling short VLAN frames
From: Emil Micek @ 2007-09-21 7:31 UTC (permalink / raw)
To: netdev
Hello list,
I'd like to change behaviour of e1000 module when transmiting short
ethernet frames (shorter then 64 bytes) trough VLAN interface.
Current e1000 (according to our observations) first appends 4 bytes of
VLAN tag and then pads the frame to 64 bytes with zeroes if necessary
before transmiting it.
I'd like to change it so it first pads the frame to 64 B and appends the
VLAN tag afterwards, so the resulting VLAN frame would be 68 bytes
minimum.
I want to do it because C3 CMTS from arris, which is connected to our
linux box, has problems handling VLAN frames shorter then 68 bytes.
As i'm quite a newbie concerning linux sources and c programing, i'd
like to ask you if this'd be trivial or complex change and if someone
can point out relevant portions of the sources, where the necessary
changes should be done.
Regards
Emil Micek
^ permalink raw reply
* Re: wrong arp query with policy routing
From: Marco Berizzi @ 2007-09-21 9:08 UTC (permalink / raw)
To: Chuck Ebbert; +Cc: netdev
In-Reply-To: <46F29741.2030505@redhat.com>
Chuck Ebbert wrote:
> > Is there a way to force linux to make an arp
> > probe with the source ip belonging to the
> > same subnet requesting ip?
>
> Umm, arp_filter?
Hello Chuck,
thanks for the reply.
I have tried to 'echo 1 > /proc/sys/net/ipv4/conf/eth0',
but the 'arp whos-has' behaviour doesn't change.
Other hints?
^ permalink raw reply
* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirq network code on SMP
From: John Ye @ 2007-09-21 9:25 UTC (permalink / raw)
To: David Miller; +Cc: netdev, kuznet, pekkas, jmorris, kaber
In-Reply-To: <20070920.104614.58454013.davem@davemloft.net>
David,
Thanks for your reply. I understand it's not worth to do.
I have made it a loadable module to fulfill the function. it mainly for busy
NAT gateway server with SMP to speed up.
John Ye
----- Original Message -----
From: "David Miller" <davem@davemloft.net>
To: <johny@asimco.com.cn>
Cc: <netdev@vger.kernel.org>; <kuznet@ms2.inr.ac.ru>; <pekkas@netcore.fi>;
<jmorris@namei.org>; <kaber@coreworks.de>
Sent: Friday, September 21, 2007 1:46 AM
Subject: Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirq
network code on SMP
>
> The whole reason the queues are per-cpu is so that we do not
> have to touch remote processor state nor use locks of any
> kind whatsoever.
>
> With multi-queue networking cards becoming more and more
> available, which will split up the packet workload in
> hardware across all available cpus, there is less and less
> reason to make a patch like this one.
>
> We've known about this issue for ages, and if we felt it
> was appropriate to make this change, we would have done
> so years ago.
>
^ permalink raw reply
* Re: [PATCH 2/7] CAN: Add PF_CAN core module
From: Urs Thuermann @ 2007-09-21 10:35 UTC (permalink / raw)
To: Joe Perches
Cc: netdev, David Miller, Patrick McHardy, Thomas Gleixner,
Oliver Hartkopp, Oliver Hartkopp
In-Reply-To: <1190318781.26101.148.camel@localhost>
Joe Perches <joe@perches.com> writes:
> On Thu, 2007-09-20 at 20:43 +0200, Urs Thuermann wrote:
> > +#define DBG(...) (debug & 1 ? \
> > + (printk(KERN_DEBUG "can-%s %s: ", \
> > + IDENT, __func__), printk(args)) : 0)
> > +#define DBG_FRAME(args...) (debug & 2 ? can_debug_cframe(args) : 0)
> > +#define DBG_SKB(skb) (debug & 4 ? can_debug_skb(skb) : 0)
> > +#else
> > +#define DBG(args...)
> > +#define DBG_FRAME(args...)
> > +#define DBG_SKB(skb)
> > +#endif
>
> Shouldn't these be like the more common
>
> #define DBG(fmt, args...) \
When I wrote these macros we had one platform where we still used
linux-2.4 and gcc-2.95.3 and with that old gcc your macro def would
mean you can't use DBG with only one argument, like DBG("some string\n");
since gcc-2.95 would leave the , after __func__ followed by the
closing ")". I didn't find a way with gcc-2.95 to make the format
string a separate macro argument (which I also wanted). OK, that's
history now and linux-2.6 needs gcc-3/4 anyway, so I will change this.
> do { \
> if (debug & 1) \
> printk(KERN_DEBUG "can-%s %s: " fmt, IDENT, __func__, ##args); \
> } while (0)
I use "do { ... } while(0)" only for statements, not for expressions.
But I could have used the && instead of ?: operator. I don't think
the "do { ... } while(0)" looks nicer or has any other advantage.
> > void can_debug_cframe(const char *msg, struct can_frame *cf, ...)
>
> This prototype looks backwards to me.
You mean the order or `msg' and `cf'? You want to switch them so that
the variable args follow immediately the format string? Might make
sense, OTOH we wanted to have the message as the first argument.
> I'd prefer something like this, which removes the unnecessary
> kmalloc/kfree pairs or the equivalent conversions to functions.
>
> #define can_debug_cframe(cf, fmt, arg...) \
> do { \
> char buf[20]; \
> int dlc = cf->can_dlc; \
> if (dlc > 8) \
> dlc = 8; \
> if (cf->can_id & CAN_EFF_FLAG) \
> sprintf(buf, "<%08X> [%X] ", cf->can_id & CAN_EFF_MASK, dlc); \
> else \
> sprintf(buf, "<%03X> [%X] ", cf->can_id & CAN_SFF_MASK, dlc); \
> printk(KERN_DEBUG fmt, ##arg); \
> print_hex_dump(buf, DUMP_PREFIX_NONE, cf->data, dlc); \
> } while (0)
Ah, I didn't know print_hex_dump(). That looks nicer. But as Thomas
mentioned, we shouldn't convert these functions into macros.
urs
^ permalink raw reply
* [PATCH 1/2] bnx2: factor out gzip unpacker
From: Denys Vlasenko @ 2007-09-21 11:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Michael Chan, David Miller, linux-kernel, netdev
[-- Attachment #1: Type: text/plain, Size: 477 bytes --]
Hi Jeff,
This patch modifies gzip unpacking code in bnx2 driver so that
it does not depend on bnx2 internals. I will move this code
out of the driver and into zlib in follow-on patch.
It can be useful in other drivers which need to store firmwares
or any other relatively big binary blobs - fonts, cursor bitmaps,
whatever.
Patch is run tested by Michael Chan (driver author).
Michael, can you add your ACK?
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
--
vda
[-- Attachment #2: linux-2.6.23-rc6.bnx2-1.patch --]
[-- Type: text/x-diff, Size: 12509 bytes --]
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2.c linux-2.6.23-rc6.bnx2/drivers/net/bnx2.c
--- linux-2.6.23-rc6/drivers/net/bnx2.c 2007-09-14 00:08:11.000000000 +0100
+++ linux-2.6.23-rc6.bnx2/drivers/net/bnx2.c 2007-09-21 11:44:03.000000000 +0100
@@ -52,6 +52,8 @@
#include "bnx2_fw.h"
#include "bnx2_fw2.h"
+#define FW_BUF_SIZE 0x8000
+
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.6.4"
@@ -2767,89 +2769,45 @@ bnx2_set_rx_mode(struct net_device *dev)
spin_unlock_bh(&bp->phy_lock);
}
-#define FW_BUF_SIZE 0x8000
-
+/* To be moved to generic lib/ */
static int
-bnx2_gunzip_init(struct bnx2 *bp)
+bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len)
{
- if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
- goto gunzip_nomem1;
+ struct z_stream_s *strm;
+ int rc;
- if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
- goto gunzip_nomem2;
+ /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+ * is stripped */
- bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (bp->strm->workspace == NULL)
+ rc = -ENOMEM;
+ strm = kmalloc(sizeof(*strm), GFP_KERNEL);
+ if (strm == NULL)
+ goto gunzip_nomem2;
+ strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+ if (strm->workspace == NULL)
goto gunzip_nomem3;
- return 0;
+ strm->next_in = zbuf;
+ strm->avail_in = len;
+ strm->next_out = gunzip_buf;
+ strm->avail_out = sz;
+
+ rc = zlib_inflateInit2(strm, -MAX_WBITS);
+ if (rc == Z_OK) {
+ rc = zlib_inflate(strm, Z_FINISH);
+ /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
+ if (rc == Z_STREAM_END)
+ rc = sz - strm->avail_out;
+ else
+ rc = -EINVAL;
+ zlib_inflateEnd(strm);
+ } else
+ rc = -EINVAL;
+ kfree(strm->workspace);
gunzip_nomem3:
- kfree(bp->strm);
- bp->strm = NULL;
-
+ kfree(strm);
gunzip_nomem2:
- vfree(bp->gunzip_buf);
- bp->gunzip_buf = NULL;
-
-gunzip_nomem1:
- printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
- "uncompression.\n", bp->dev->name);
- return -ENOMEM;
-}
-
-static void
-bnx2_gunzip_end(struct bnx2 *bp)
-{
- kfree(bp->strm->workspace);
-
- kfree(bp->strm);
- bp->strm = NULL;
-
- if (bp->gunzip_buf) {
- vfree(bp->gunzip_buf);
- bp->gunzip_buf = NULL;
- }
-}
-
-static int
-bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
-{
- int n, rc;
-
- /* check gzip header */
- if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
- return -EINVAL;
-
- n = 10;
-
-#define FNAME 0x8
- if (zbuf[3] & FNAME)
- while ((zbuf[n++] != 0) && (n < len));
-
- bp->strm->next_in = zbuf + n;
- bp->strm->avail_in = len - n;
- bp->strm->next_out = bp->gunzip_buf;
- bp->strm->avail_out = FW_BUF_SIZE;
-
- rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
- if (rc != Z_OK)
- return rc;
-
- rc = zlib_inflate(bp->strm, Z_FINISH);
-
- *outlen = FW_BUF_SIZE - bp->strm->avail_out;
- *outbuf = bp->gunzip_buf;
-
- if ((rc != Z_OK) && (rc != Z_STREAM_END))
- printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
- bp->dev->name, bp->strm->msg);
-
- zlib_inflateEnd(bp->strm);
-
- if (rc == Z_STREAM_END)
- return 0;
-
return rc;
}
@@ -2902,22 +2860,21 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_
/* Load the Text area. */
offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
if (fw->gz_text) {
- u32 text_len;
- void *text;
-
- rc = bnx2_gunzip(bp, fw->gz_text, fw->gz_text_len, &text,
- &text_len);
- if (rc)
- return rc;
-
- fw->text = text;
- }
- if (fw->gz_text) {
+ u32 *text;
int j;
+ text = vmalloc(FW_BUF_SIZE);
+ if (!text)
+ return -ENOMEM;
+ rc = bnx2_gunzip(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
+ if (rc < 0) {
+ vfree(text);
+ return rc;
+ }
for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
- REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
+ REG_WR_IND(bp, offset, cpu_to_le32(text[j]));
}
+ vfree(text);
}
/* Load the Data area. */
@@ -2979,27 +2936,27 @@ bnx2_init_cpus(struct bnx2 *bp)
{
struct cpu_reg cpu_reg;
struct fw_info *fw;
- int rc = 0;
+ int rc;
void *text;
- u32 text_len;
-
- if ((rc = bnx2_gunzip_init(bp)) != 0)
- return rc;
/* Initialize the RV2P processor. */
- rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
- &text_len);
- if (rc)
+ text = vmalloc(FW_BUF_SIZE);
+ if (!text)
+ return -ENOMEM;
+ rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
+ if (rc < 0) {
+ vfree(text);
goto init_cpu_err;
+ }
+ load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
- load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
-
- rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
- &text_len);
- if (rc)
+ rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
+ if (rc < 0) {
+ vfree(text);
goto init_cpu_err;
-
- load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
+ }
+ load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
+ vfree(text);
/* Initialize the RX Processor. */
cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -3115,7 +3072,6 @@ bnx2_init_cpus(struct bnx2 *bp)
goto init_cpu_err;
}
init_cpu_err:
- bnx2_gunzip_end(bp);
return rc;
}
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2.h
--- linux-2.6.23-rc6/drivers/net/bnx2.h 2007-09-14 00:08:11.000000000 +0100
+++ linux-2.6.23-rc6.bnx2/drivers/net/bnx2.h 2007-09-19 10:15:54.000000000 +0100
@@ -6679,9 +6679,6 @@ struct bnx2 {
u32 flash_size;
int status_stats_size;
-
- struct z_stream_s *strm;
- void *gunzip_buf;
};
static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
@@ -6739,7 +6736,7 @@ struct fw_info {
const u32 text_addr;
const u32 text_len;
const u32 text_index;
- u32 *text;
+/* u32 *text;*/
u8 *gz_text;
const u32 gz_text_len;
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2_fw.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw.h
--- linux-2.6.23-rc6/drivers/net/bnx2_fw.h 2007-07-09 00:32:17.000000000 +0100
+++ linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw.h 2007-09-20 15:38:52.000000000 +0100
@@ -15,7 +15,8 @@
*/
static u8 bnx2_COM_b06FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5a,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, */
+ 0xdc, 0x5a,
0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae, 0xc8, 0x15,
0x35, 0xa2, 0xc6, 0xf4, 0x5a, 0xa2, 0xed, 0x5d, 0x72, 0x28, 0x12, 0x96,
0xec, 0x6e, 0x68, 0xda, 0x62, 0x8c, 0x8d, 0xb4, 0xd9, 0xa5, 0x0c, 0xa1,
@@ -1085,8 +1086,9 @@ static struct fw_info bnx2_com_fw_06 = {
};
static u8 bnx2_RXP_b06FwText[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c,
+/* 0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+ 0xec, 0x5c, 0x6f, 0x6c,
0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x4e, 0xd4, 0x91, 0x5c, 0x1e,
0x4f, 0xf4, 0x49, 0x66, 0x94, 0x5d, 0x71, 0x25, 0x5e, 0x2d, 0xc6, 0x5d,
0x31, 0x57, 0x9b, 0x08, 0xce, 0xf1, 0x79, 0xef, 0x64, 0xb1, 0x86, 0x0a,
@@ -1798,8 +1800,9 @@ static struct fw_info bnx2_rxp_fw_06 = {
};
static u8 bnx2_rv2p_proc1[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b,
+/* 0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+ 0xc5, 0x56, 0xcf, 0x6b,
0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b,
0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82,
0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a,
@@ -1877,8 +1880,9 @@ static u8 bnx2_rv2p_proc1[] = {
0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 };
static u8 bnx2_rv2p_proc2[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c,
+/* 0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+ 0xcd, 0x58, 0x5b, 0x6c,
0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2,
0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18,
0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda,
@@ -2057,8 +2061,9 @@ static u8 bnx2_rv2p_proc2[] = {
0x17, 0x00, 0x00, 0x00 };
static u8 bnx2_TPAT_b06FwText[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
+/* 0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+ 0xc5, 0x57, 0x4d, 0x68,
0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d,
0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5,
0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08,
@@ -2290,8 +2295,9 @@ static struct fw_info bnx2_tpat_fw_06 =
};
static u8 bnx2_TXP_b06FwText[] = {
- 0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
- 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
+/* 0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+ 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+ 0xed, 0x5c, 0x6d, 0x6c,
0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2,
0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05,
0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71,
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2_fw2.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw2.h
--- linux-2.6.23-rc6/drivers/net/bnx2_fw2.h 2007-07-09 00:32:17.000000000 +0100
+++ linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw2.h 2007-09-20 15:39:08.000000000 +0100
@@ -15,7 +15,8 @@
*/
static u8 bnx2_COM_b09FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5b,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+ 0xdc, 0x5b,
0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
@@ -1083,7 +1084,8 @@ static struct fw_info bnx2_com_fw_09 = {
};
static u8 bnx2_CP_b09FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xbd, 0x7d,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+ 0xbd, 0x7d,
0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
@@ -2279,7 +2281,8 @@ static struct fw_info bnx2_cp_fw_09 = {
};
static u8 bnx2_RXP_b09FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xec, 0x5c,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+ 0xec, 0x5c,
0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
@@ -2988,7 +2991,8 @@ static struct fw_info bnx2_rxp_fw_09 = {
};
static u8 bnx2_TPAT_b09FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x58,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+ 0xcd, 0x58,
0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
@@ -3279,7 +3283,8 @@ static struct fw_info bnx2_tpat_fw_09 =
};
static u8 bnx2_TXP_b09FwText[] = {
- 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x7c,
+/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+ 0xcd, 0x7c,
0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
[-- Attachment #3: linux-2.6.23-rc6.bnx2-2.patch --]
[-- Type: text/x-diff, Size: 9345 bytes --]
diff -urp linux-2.6.23-rc6.bnx2/drivers/net/bnx2.c linux-2.6.23-rc6.bnx2_2/drivers/net/bnx2.c
--- linux-2.6.23-rc6.bnx2/drivers/net/bnx2.c 2007-09-21 11:44:03.000000000 +0100
+++ linux-2.6.23-rc6.bnx2_2/drivers/net/bnx2.c 2007-09-20 15:35:58.000000000 +0100
@@ -2769,48 +2769,6 @@ bnx2_set_rx_mode(struct net_device *dev)
spin_unlock_bh(&bp->phy_lock);
}
-/* To be moved to generic lib/ */
-static int
-bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len)
-{
- struct z_stream_s *strm;
- int rc;
-
- /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
- * is stripped */
-
- rc = -ENOMEM;
- strm = kmalloc(sizeof(*strm), GFP_KERNEL);
- if (strm == NULL)
- goto gunzip_nomem2;
- strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (strm->workspace == NULL)
- goto gunzip_nomem3;
-
- strm->next_in = zbuf;
- strm->avail_in = len;
- strm->next_out = gunzip_buf;
- strm->avail_out = sz;
-
- rc = zlib_inflateInit2(strm, -MAX_WBITS);
- if (rc == Z_OK) {
- rc = zlib_inflate(strm, Z_FINISH);
- /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
- if (rc == Z_STREAM_END)
- rc = sz - strm->avail_out;
- else
- rc = -EINVAL;
- zlib_inflateEnd(strm);
- } else
- rc = -EINVAL;
-
- kfree(strm->workspace);
-gunzip_nomem3:
- kfree(strm);
-gunzip_nomem2:
- return rc;
-}
-
static void
load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
u32 rv2p_proc)
@@ -2866,7 +2824,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_
text = vmalloc(FW_BUF_SIZE);
if (!text)
return -ENOMEM;
- rc = bnx2_gunzip(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
+ rc = zlib_inflate_blob(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
if (rc < 0) {
vfree(text);
return rc;
@@ -2943,14 +2901,14 @@ bnx2_init_cpus(struct bnx2 *bp)
text = vmalloc(FW_BUF_SIZE);
if (!text)
return -ENOMEM;
- rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
+ rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
if (rc < 0) {
vfree(text);
goto init_cpu_err;
}
load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
- rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
+ rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
if (rc < 0) {
vfree(text);
goto init_cpu_err;
diff -urp linux-2.6.23-rc6.bnx2/include/linux/zlib.h linux-2.6.23-rc6.bnx2_2/include/linux/zlib.h
--- linux-2.6.23-rc6.bnx2/include/linux/zlib.h 2007-07-09 00:32:17.000000000 +0100
+++ linux-2.6.23-rc6.bnx2_2/include/linux/zlib.h 2007-09-20 15:32:50.000000000 +0100
@@ -82,7 +82,7 @@
struct internal_state;
typedef struct z_stream_s {
- Byte *next_in; /* next input byte */
+ const Byte *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
@@ -699,4 +699,8 @@ extern int zlib_inflateInit2(z_streamp s
struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif
+/* Utility function: initialize zlib, unpack binary blob, clean up zlib,
+ * return len or negative error code. */
+extern int zlib_inflate_blob(void *dst, unsigned dst_sz, const void *src, unsigned src_sz);
+
#endif /* _ZLIB_H */
diff -urp linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inffast.c linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inffast.c
--- linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inffast.c 2007-09-19 10:33:08.000000000 +0100
+++ linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inffast.c 2007-09-19 10:47:55.000000000 +0100
@@ -69,22 +69,22 @@
void inflate_fast(z_streamp strm, unsigned start)
{
struct inflate_state *state;
- unsigned char *in; /* local strm->next_in */
- unsigned char *last; /* while in < last, enough input available */
- unsigned char *out; /* local strm->next_out */
- unsigned char *beg; /* inflate()'s initial strm->next_out */
- unsigned char *end; /* while out < end, enough space available */
+ const unsigned char *in; /* local strm->next_in */
+ const unsigned char *last; /* while in < last, enough input available */
+ unsigned char *out; /* local strm->next_out */
+ unsigned char *beg; /* inflate()'s initial strm->next_out */
+ unsigned char *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
- unsigned char *window; /* allocated sliding window, if wsize != 0 */
+ unsigned char *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
- code const *lcode; /* local strm->lencode */
- code const *dcode; /* local strm->distcode */
+ code const *lcode; /* local strm->lencode */
+ code const *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code this; /* retrieved table entry */
@@ -92,7 +92,7 @@ void inflate_fast(z_streamp strm, unsign
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
- unsigned char *from; /* where to copy match from */
+ unsigned char *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state *)strm->state;
diff -urp linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inflate.c linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inflate.c
--- linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inflate.c 2007-09-19 10:33:08.000000000 +0100
+++ linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inflate.c 2007-09-21 11:46:27.000000000 +0100
@@ -332,14 +332,14 @@ static int zlib_inflateSyncPacket(z_stre
int zlib_inflate(z_streamp strm, int flush)
{
struct inflate_state *state;
- unsigned char *next; /* next input */
- unsigned char *put; /* next output */
+ const unsigned char *next; /* next input */
+ unsigned char *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned in, out; /* save starting available input and output */
unsigned copy; /* number of stored or match bytes to copy */
- unsigned char *from; /* where to copy match bytes from */
+ unsigned char *from; /* where to copy match bytes from */
code this; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
@@ -897,7 +897,7 @@ int zlib_inflateIncomp(z_stream *z)
/* Setup some variables to allow misuse of updateWindow */
z->avail_out = 0;
- z->next_out = z->next_in + z->avail_in;
+ z->next_out = (unsigned char*)z->next_in + z->avail_in;
zlib_updatewindow(z, z->avail_in);
@@ -916,3 +916,50 @@ int zlib_inflateIncomp(z_stream *z)
return Z_OK;
}
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+/* Utility function: initialize zlib, unpack binary blob, clean up zlib,
+ * return len or negative error code. */
+int zlib_inflate_blob(void *gunzip_buf, unsigned sz, const void *buf, unsigned len)
+{
+ const u8 *zbuf = buf;
+ struct z_stream_s *strm;
+ int rc;
+
+ rc = -ENOMEM;
+ strm = kmalloc(sizeof(*strm), GFP_KERNEL);
+ if (strm == NULL)
+ goto gunzip_nomem1;
+ strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+ if (strm->workspace == NULL)
+ goto gunzip_nomem2;
+
+ /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+ * expected to be stripped from input */
+
+ strm->next_in = zbuf;
+ strm->avail_in = len;
+ strm->next_out = gunzip_buf;
+ strm->avail_out = sz;
+
+ rc = zlib_inflateInit2(strm, -MAX_WBITS);
+ if (rc == Z_OK) {
+ rc = zlib_inflate(strm, Z_FINISH);
+ /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
+ if (rc == Z_STREAM_END)
+ rc = sz - strm->avail_out;
+ else
+ rc = -EINVAL;
+ zlib_inflateEnd(strm);
+ } else
+ rc = -EINVAL;
+
+ kfree(strm->workspace);
+gunzip_nomem2:
+ kfree(strm);
+gunzip_nomem1:
+ return rc; /* returns Z_OK (0) if successful */
+}
diff -urp linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inflate_syms.c linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inflate_syms.c
--- linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inflate_syms.c 2007-09-19 10:33:08.000000000 +0100
+++ linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inflate_syms.c 2007-09-19 10:34:21.000000000 +0100
@@ -16,4 +16,5 @@ EXPORT_SYMBOL(zlib_inflateInit2);
EXPORT_SYMBOL(zlib_inflateEnd);
EXPORT_SYMBOL(zlib_inflateReset);
EXPORT_SYMBOL(zlib_inflateIncomp);
+EXPORT_SYMBOL(zlib_inflate_blob);
MODULE_LICENSE("GPL");
^ permalink raw reply
* [PATCH 2/2] bnx2: move gzip unpacker to zlib
From: Denys Vlasenko @ 2007-09-21 11:03 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Michael Chan, David Miller, linux-kernel, netdev
In-Reply-To: <200709211201.24475.vda.linux@googlemail.com>
On Friday 21 September 2007 12:01, Denys Vlasenko wrote:
> I will move this code
> out of the driver and into zlib in follow-on patch.
No, I won't. I accidentally attached both patches to first email,
you can find it there. Sorry.
--
vda
^ permalink raw reply
* Re: [LARTC] ifb and ppp
From: jamal @ 2007-09-21 11:23 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Frithjof Hammer, Linux Netdev List
In-Reply-To: <46F2910E.9040900@trash.net>
On Thu, 2007-20-09 at 17:26 +0200, Patrick McHardy wrote:
> I don't see a good solution for this that
> allows to keep the iptables rules, I'd suggest to switch to ematches.
One approach could be to use ipt action:
-------------------
tc filter add dev ppp0 parent ffff: protocol ip u32 match u32/ematch
some match flowid 1:1 action ipt -j mark --set-mark 1
..
...
....
iptables here to use the marks ...
----------------
cheers,
jamal
^ permalink raw reply
* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirq network code on SMP
From: jamal @ 2007-09-21 11:43 UTC (permalink / raw)
To: John Ye; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber
In-Reply-To: <00e601c7fc31$4ed29890$ca8510ac@asimco>
On Fri, 2007-21-09 at 17:25 +0800, John Ye wrote:
> David,
>
> Thanks for your reply. I understand it's not worth to do.
>
> I have made it a loadable module to fulfill the function. it mainly for busy
> NAT gateway server with SMP to speed up.
>
John,
It was a little hard to read your code; however, it does seems to me
like will cause a massive amount of packet reordering to the end hosts
using you as the gateway especially when it is receiving a lot of
packets/second.
You have a queue per CPU that connects your bottom and top half and
several CPUs that may service a single NIC in your bottom half.
one cpu in either bottom/top half has to be slightly loaded and you
loose the ordering where incoming doesnt match outgoing packet order.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirq network code on SMP
From: jamal @ 2007-09-21 11:47 UTC (permalink / raw)
To: John Ye; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber
In-Reply-To: <1190375023.4261.34.camel@localhost>
On Fri, 2007-21-09 at 07:43 -0400, jamal wrote:
> one cpu in either bottom/top half has to be slightly loaded and you
> loose the ordering where incoming doesnt match outgoing packet order.
Actually in your case it gets worse because (if i read that code
correctly) you randomly select the CPUs.
cheers,
jamal
^ permalink raw reply
* [PATCH] sb1250-mac: Driver model & phylib update
From: Maciej W. Rozycki @ 2007-09-21 11:52 UTC (permalink / raw)
To: Andrew Morton, Jeff Garzik; +Cc: netdev, linux-mips, linux-kernel
A driver model and phylib update. It includes the following changes:
1. Removal of unused module options.
2. Phylib support and the resulting removal of generic bits for handling
the PHY.
3. Proper reserving of device resources and using ioremap()ped handles
to access MAC registers rather than platform-specific macros.
4. Handling of the device using the driver model.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
This is a resubmission and this patch has waited for some time now as the
original submission triggered some concerns on the way phylib handled
interrupt-driven PHY units. The issues were resolved a while ago already,
but I was distracted by some other work, mainly in the toolchain area, so
this got postponed this far. For some background information -- as a
reminder -- here is the original long explanation I gave back then:
"Here is a set of patches that update the sb1250-mac driver used for the
onchip Gigabit Ethernet interfaces of the Broadcom SiByte family of SOCs
including the BCM1250 and a couple of other members. These are used,
among others, on various Broadcom evaluation boards together with Broadcom
Gigabit Ethernet PHY chips. Changes include porting the driver to the
driver model as a platform device, support for phylib, including the
BCM54xx PHYs in the interrupt mode, proper resource managment and a couple
of minor clean-ups.
Apart from changes to networking code, there are a few required in the
architecture-specific areas and therefore I am sending these changes to
Ralf and the linux-mips list as well. It might also involve a few more
interested parties in the discussion.
The changes were tested with a Broadcom SWARM board, which includes a
BCM1250 part which has 3 MAC units on chip, of which 2 are usable, with
BCM5421 PHY chips attached (both wired to the same interrupt line, which
made testing whether IRQ sharing works properly in phylib possible).
Link partners included a 1000base and a 100base interface doing
autonegotiation as well as a 10base one doing none.
Other Broadcom boards that I know of may have these or BCM5411 or BCM5461
chips. The lack of documentation or at least actual pieces of hardware
makes the use of interrupts impossible for all but the SWARM, the Sentosa
and the Shorty (with the latter unsupported by Linux)."
All the bits except from the mentioned architecture-specific fix -- the
firmware of the SWARM gets the polarity of the PHY IRQ line wrong, which
has to be reprogrammed in the SOC -- have found their way into Linux
already. The polarity fix is not critical for the update provided here as
the update has been written such that with the current state of affairs
the driver will use the polled mode of phylib operation.
I will provide the architecture-specific fix later on, probably once this
update has propagated back to the linux-mips.org tree (suggestions as to
why I should do otherwise certainly welcome). This way if any problems
are seen due to the switch of the PHY to the interrupt-driven mode, they
can be sorted out independently of this change.
This change applies to the current netdev-2.6.git#upstream tree, on top
of "patch-netdev-2.6.23-rc6-20070920-sb1250-mac-typedef-9" submitted
yesterday.
Please apply.
Maciej
patch-netdev-2.6.23-rc6-20070920-sb1250-mac-29
diff -up --recursive --new-file linux-netdev-2.6.23-rc6-20070920.macro/drivers/net/Kconfig linux-netdev-2.6.23-rc6-20070920/drivers/net/Kconfig
--- linux-netdev-2.6.23-rc6-20070920.macro/drivers/net/Kconfig 2007-09-20 17:55:14.000000000 +0000
+++ linux-netdev-2.6.23-rc6-20070920/drivers/net/Kconfig 2007-09-20 20:31:42.000000000 +0000
@@ -2126,6 +2126,7 @@ config R8169_VLAN
config SB1250_MAC
tristate "SB1250 Gigabit Ethernet support"
depends on SIBYTE_SB1xxx_SOC
+ select PHYLIB
---help---
This driver supports Gigabit Ethernet interfaces based on the
Broadcom SiByte family of System-On-a-Chip parts. They include
diff -up --recursive --new-file linux-netdev-2.6.23-rc6-20070920.macro/drivers/net/sb1250-mac.c linux-netdev-2.6.23-rc6-20070920/drivers/net/sb1250-mac.c
--- linux-netdev-2.6.23-rc6-20070920.macro/drivers/net/sb1250-mac.c 2007-09-20 18:09:18.000000000 +0000
+++ linux-netdev-2.6.23-rc6-20070920/drivers/net/sb1250-mac.c 2007-09-20 21:06:55.000000000 +0000
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003,2004 Broadcom Corporation
+ * Copyright (c) 2006, 2007 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +19,12 @@
*
* This driver is designed for the Broadcom SiByte SOC built-in
* Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp.
+ *
+ * Updated to the driver model and the PHY abstraction layer
+ * by Maciej W. Rozycki.
*/
+
+#include <linux/bug.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -32,9 +38,15 @@
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/bitops.h>
-#include <asm/processor.h> /* Processor type for cache alignment. */
-#include <asm/io.h>
+#include <linux/err.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+
#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/processor.h> /* Processor type for cache alignment. */
/* This is only here until the firmware is ready. In that case,
the firmware leaves the ethernet address in the register for us. */
@@ -48,7 +60,7 @@
/* These identify the driver base version and may not be removed. */
#if 0
-static char version1[] __devinitdata =
+static char version1[] __initdata =
"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n";
#endif
@@ -57,8 +69,6 @@ static char version1[] __devinitdata =
#define CONFIG_SBMAC_COALESCE
-#define MAX_UNITS 4 /* More are supported, limit only on options */
-
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (2*HZ)
@@ -74,26 +84,6 @@ static int debug = 1;
module_param(debug, int, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug messages");
-/* mii status msgs */
-static int noisy_mii = 1;
-module_param(noisy_mii, int, S_IRUGO);
-MODULE_PARM_DESC(noisy_mii, "MII status messages");
-
-/* Used to pass the media type, etc.
- Both 'options[]' and 'full_duplex[]' should exist for driver
- interoperability.
- The media type is usually passed in 'options[]'.
-*/
-#ifdef MODULE
-static int options[MAX_UNITS] = {-1, -1, -1, -1};
-module_param_array(options, int, NULL, S_IRUGO);
-MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS));
-
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1};
-module_param_array(full_duplex, int, NULL, S_IRUGO);
-MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS));
-#endif
-
#ifdef CONFIG_SBMAC_COALESCE
static int int_pktcnt_tx = 255;
module_param(int_pktcnt_tx, int, S_IRUGO);
@@ -112,6 +102,7 @@ module_param(int_timeout_rx, int, S_IRUG
MODULE_PARM_DESC(int_timeout_rx, "RX timeout value");
#endif
+#include <asm/sibyte/board.h>
#include <asm/sibyte/sb1250.h>
#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
#include <asm/sibyte/bcm1480_regs.h>
@@ -135,22 +126,43 @@ MODULE_PARM_DESC(int_timeout_rx, "RX tim
#error invalid SiByte MAC configuation
#endif
+#ifdef K_INT_PHY
+#define SBMAC_PHY_INT K_INT_PHY
+#else
+#define SBMAC_PHY_INT PHY_POLL
+#endif
+
/**********************************************************************
* Simple types
********************************************************************* */
+enum sbmac_speed {
+ sbmac_speed_none = 0,
+ sbmac_speed_10 = SPEED_10,
+ sbmac_speed_100 = SPEED_100,
+ sbmac_speed_1000 = SPEED_1000,
+};
-enum sbmac_speed { sbmac_speed_auto, sbmac_speed_10,
- sbmac_speed_100, sbmac_speed_1000 };
-
-enum sbmac_duplex { sbmac_duplex_auto, sbmac_duplex_half,
- sbmac_duplex_full };
+enum sbmac_duplex {
+ sbmac_duplex_none = -1,
+ sbmac_duplex_half = DUPLEX_HALF,
+ sbmac_duplex_full = DUPLEX_FULL,
+};
-enum sbmac_fc { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
- sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
+enum sbmac_fc {
+ sbmac_fc_none,
+ sbmac_fc_disabled,
+ sbmac_fc_frame,
+ sbmac_fc_collision,
+ sbmac_fc_carrier,
+};
-enum sbmac_state { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
- sbmac_state_broken };
+enum sbmac_state {
+ sbmac_state_uninit,
+ sbmac_state_off,
+ sbmac_state_on,
+ sbmac_state_broken,
+};
/**********************************************************************
@@ -244,18 +256,14 @@ struct sbmac_softc {
*/
struct net_device *sbm_dev; /* pointer to linux device */
struct napi_struct napi;
+ struct phy_device *phy_dev; /* the associated PHY device */
+ struct mii_bus mii_bus; /* the MII bus */
+ int phy_irq[PHY_MAX_ADDR];
spinlock_t sbm_lock; /* spin lock */
- struct timer_list sbm_timer; /* for monitoring MII */
int sbm_devflags; /* current device flags */
- int sbm_phy_oldbmsr;
- int sbm_phy_oldanlpar;
- int sbm_phy_oldk1stsr;
- int sbm_phy_oldlinkstat;
int sbm_buffersize;
- unsigned char sbm_phys[2];
-
/*
* Controller-specific things
*/
@@ -274,6 +282,8 @@ struct sbmac_softc {
enum sbmac_speed sbm_speed; /* current speed */
enum sbmac_duplex sbm_duplex; /* current duplex */
enum sbmac_fc sbm_fc; /* cur. flow control setting */
+ int sbm_pause; /* current pause setting */
+ int sbm_link; /* current link state */
unsigned char sbm_hwaddr[ETHER_ADDR_LEN];
@@ -313,36 +323,37 @@ static uint64_t sbmac_addr2reg(unsigned
static irqreturn_t sbmac_intr(int irq, void *dev_instance);
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
static void sbmac_setmulti(struct sbmac_softc *sc);
-static int sbmac_init(struct net_device *dev, int idx);
+static int sbmac_init(struct platform_device *pldev, long long base);
static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed);
static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex,
enum sbmac_fc fc);
static int sbmac_open(struct net_device *dev);
-static void sbmac_timer(unsigned long data);
static void sbmac_tx_timeout (struct net_device *dev);
static void sbmac_set_rx_mode(struct net_device *dev);
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int sbmac_close(struct net_device *dev);
static int sbmac_poll(struct napi_struct *napi, int budget);
-static int sbmac_mii_poll(struct sbmac_softc *s, int noisy);
+static void sbmac_mii_poll(struct net_device *dev);
static int sbmac_mii_probe(struct net_device *dev);
-static void sbmac_mii_sync(struct sbmac_softc *s);
-static void sbmac_mii_senddata(struct sbmac_softc *s, unsigned int data,
+static void sbmac_mii_sync(void __iomem *sbm_mdio);
+static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
int bitcnt);
-static unsigned int sbmac_mii_read(struct sbmac_softc *s, int phyaddr,
- int regidx);
-static void sbmac_mii_write(struct sbmac_softc *s, int phyaddr, int regidx,
- unsigned int regval);
+static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx);
+static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+ u16 val);
/**********************************************************************
* Globals
********************************************************************* */
-static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
+static char sbmac_string[] = "sb1250-mac";
+static char sbmac_pretty[] = "SB1250 MAC";
+
+static char sbmac_mdio_string[] = "sb1250-mac-mdio";
/**********************************************************************
@@ -354,185 +365,66 @@ static uint64_t sbmac_orig_hwaddr[MAX_UN
#define MII_COMMAND_WRITE 0x01
#define MII_COMMAND_ACK 0x02
-#define BMCR_RESET 0x8000
-#define BMCR_LOOPBACK 0x4000
-#define BMCR_SPEED0 0x2000
-#define BMCR_ANENABLE 0x1000
-#define BMCR_POWERDOWN 0x0800
-#define BMCR_ISOLATE 0x0400
-#define BMCR_RESTARTAN 0x0200
-#define BMCR_DUPLEX 0x0100
-#define BMCR_COLTEST 0x0080
-#define BMCR_SPEED1 0x0040
-#define BMCR_SPEED1000 BMCR_SPEED1
-#define BMCR_SPEED100 BMCR_SPEED0
-#define BMCR_SPEED10 0
-
-#define BMSR_100BT4 0x8000
-#define BMSR_100BT_FDX 0x4000
-#define BMSR_100BT_HDX 0x2000
-#define BMSR_10BT_FDX 0x1000
-#define BMSR_10BT_HDX 0x0800
-#define BMSR_100BT2_FDX 0x0400
-#define BMSR_100BT2_HDX 0x0200
-#define BMSR_1000BT_XSR 0x0100
-#define BMSR_PRESUP 0x0040
-#define BMSR_ANCOMPLT 0x0020
-#define BMSR_REMFAULT 0x0010
-#define BMSR_AUTONEG 0x0008
-#define BMSR_LINKSTAT 0x0004
-#define BMSR_JABDETECT 0x0002
-#define BMSR_EXTCAPAB 0x0001
-
-#define PHYIDR1 0x2000
-#define PHYIDR2 0x5C60
-
-#define ANAR_NP 0x8000
-#define ANAR_RF 0x2000
-#define ANAR_ASYPAUSE 0x0800
-#define ANAR_PAUSE 0x0400
-#define ANAR_T4 0x0200
-#define ANAR_TXFD 0x0100
-#define ANAR_TXHD 0x0080
-#define ANAR_10FD 0x0040
-#define ANAR_10HD 0x0020
-#define ANAR_PSB 0x0001
-
-#define ANLPAR_NP 0x8000
-#define ANLPAR_ACK 0x4000
-#define ANLPAR_RF 0x2000
-#define ANLPAR_ASYPAUSE 0x0800
-#define ANLPAR_PAUSE 0x0400
-#define ANLPAR_T4 0x0200
-#define ANLPAR_TXFD 0x0100
-#define ANLPAR_TXHD 0x0080
-#define ANLPAR_10FD 0x0040
-#define ANLPAR_10HD 0x0020
-#define ANLPAR_PSB 0x0001 /* 802.3 */
-
-#define ANER_PDF 0x0010
-#define ANER_LPNPABLE 0x0008
-#define ANER_NPABLE 0x0004
-#define ANER_PAGERX 0x0002
-#define ANER_LPANABLE 0x0001
-
-#define ANNPTR_NP 0x8000
-#define ANNPTR_MP 0x2000
-#define ANNPTR_ACK2 0x1000
-#define ANNPTR_TOGTX 0x0800
-#define ANNPTR_CODE 0x0008
-
-#define ANNPRR_NP 0x8000
-#define ANNPRR_MP 0x2000
-#define ANNPRR_ACK3 0x1000
-#define ANNPRR_TOGTX 0x0800
-#define ANNPRR_CODE 0x0008
-
-#define K1TCR_TESTMODE 0x0000
-#define K1TCR_MSMCE 0x1000
-#define K1TCR_MSCV 0x0800
-#define K1TCR_RPTR 0x0400
-#define K1TCR_1000BT_FDX 0x200
-#define K1TCR_1000BT_HDX 0x100
-
-#define K1STSR_MSMCFLT 0x8000
-#define K1STSR_MSCFGRES 0x4000
-#define K1STSR_LRSTAT 0x2000
-#define K1STSR_RRSTAT 0x1000
-#define K1STSR_LP1KFD 0x0800
-#define K1STSR_LP1KHD 0x0400
-#define K1STSR_LPASMDIR 0x0200
-
-#define K1SCR_1KX_FDX 0x8000
-#define K1SCR_1KX_HDX 0x4000
-#define K1SCR_1KT_FDX 0x2000
-#define K1SCR_1KT_HDX 0x1000
-
-#define STRAP_PHY1 0x0800
-#define STRAP_NCMODE 0x0400
-#define STRAP_MANMSCFG 0x0200
-#define STRAP_ANENABLE 0x0100
-#define STRAP_MSVAL 0x0080
-#define STRAP_1KHDXADV 0x0010
-#define STRAP_1KFDXADV 0x0008
-#define STRAP_100ADV 0x0004
-#define STRAP_SPEEDSEL 0x0000
-#define STRAP_SPEED100 0x0001
-
-#define PHYSUP_SPEED1000 0x10
-#define PHYSUP_SPEED100 0x08
-#define PHYSUP_SPEED10 0x00
-#define PHYSUP_LINKUP 0x04
-#define PHYSUP_FDX 0x02
-
-#define MII_BMCR 0x00 /* Basic mode control register (rw) */
-#define MII_BMSR 0x01 /* Basic mode status register (ro) */
-#define MII_PHYIDR1 0x02
-#define MII_PHYIDR2 0x03
-
-#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
-#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
-
-
#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */
#define ENABLE 1
#define DISABLE 0
/**********************************************************************
- * SBMAC_MII_SYNC(s)
+ * SBMAC_MII_SYNC(sbm_mdio)
*
* Synchronize with the MII - send a pattern of bits to the MII
* that will guarantee that it is ready to accept a command.
*
* Input parameters:
- * s - sbmac structure
+ * sbm_mdio - address of the MAC's MDIO register
*
* Return value:
* nothing
********************************************************************* */
-static void sbmac_mii_sync(struct sbmac_softc *s)
+static void sbmac_mii_sync(void __iomem *sbm_mdio)
{
int cnt;
uint64_t bits;
int mac_mdio_genc;
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
for (cnt = 0; cnt < 32; cnt++) {
- __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
}
}
/**********************************************************************
- * SBMAC_MII_SENDDATA(s,data,bitcnt)
+ * SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt)
*
* Send some bits to the MII. The bits to be sent are right-
* justified in the 'data' parameter.
*
* Input parameters:
- * s - sbmac structure
- * data - data to send
- * bitcnt - number of bits to send
+ * sbm_mdio - address of the MAC's MDIO register
+ * data - data to send
+ * bitcnt - number of bits to send
********************************************************************* */
-static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt)
+static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
+ int bitcnt)
{
int i;
uint64_t bits;
unsigned int curmask;
int mac_mdio_genc;
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
bits = M_MAC_MDIO_DIR_OUTPUT;
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
curmask = 1 << (bitcnt - 1);
@@ -540,9 +432,9 @@ static void sbmac_mii_senddata(struct sb
if (data & curmask)
bits |= M_MAC_MDIO_OUT;
else bits &= ~M_MAC_MDIO_OUT;
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
curmask >>= 1;
}
}
@@ -550,21 +442,22 @@ static void sbmac_mii_senddata(struct sb
/**********************************************************************
- * SBMAC_MII_READ(s,phyaddr,regidx)
- *
+ * SBMAC_MII_READ(bus, phyaddr, regidx)
* Read a PHY register.
*
* Input parameters:
- * s - sbmac structure
+ * bus - MDIO bus handle
* phyaddr - PHY's address
- * regidx = index of register to read
+ * regnum - index of register to read
*
* Return value:
- * value read, or 0 if an error occurred.
+ * value read, or 0xffff if an error occurred.
********************************************************************* */
-static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
+static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
{
+ struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
+ void __iomem *sbm_mdio = sc->sbm_mdio;
int idx;
int error;
int regval;
@@ -574,8 +467,7 @@ static unsigned int sbmac_mii_read(struc
* Synchronize ourselves so that the PHY knows the next
* thing coming down is a command
*/
-
- sbmac_mii_sync(s);
+ sbmac_mii_sync(sbm_mdio);
/*
* Send the data to the PHY. The sequence is
@@ -584,37 +476,37 @@ static unsigned int sbmac_mii_read(struc
* the PHY addr (5 bits)
* the register index (5 bits)
*/
+ sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
+ sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2);
+ sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
+ sbmac_mii_senddata(sbm_mdio, regidx, 5);
- sbmac_mii_senddata(s,MII_COMMAND_START, 2);
- sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
- sbmac_mii_senddata(s,phyaddr, 5);
- sbmac_mii_senddata(s,regidx, 5);
-
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
/*
* Switch the port around without a clock transition.
*/
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
/*
* Send out a clock pulse to signal we want the status
*/
-
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
+ sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
/*
* If an error occurred, the PHY will signal '1' back
*/
- error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
+ error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN;
/*
* Issue an 'idle' clock pulse, but keep the direction
* the same.
*/
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
+ sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
regval = 0;
@@ -622,55 +514,60 @@ static unsigned int sbmac_mii_read(struc
regval <<= 1;
if (error == 0) {
- if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
+ if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN)
regval |= 1;
}
- __raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
+ sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
}
/* Switch back to output */
- __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
if (error == 0)
return regval;
- return 0;
+ return 0xffff;
}
/**********************************************************************
- * SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
+ * SBMAC_MII_WRITE(bus, phyaddr, regidx, regval)
*
* Write a value to a PHY register.
*
* Input parameters:
- * s - sbmac structure
+ * bus - MDIO bus handle
* phyaddr - PHY to use
- * regidx - register within the PHY
- * regval - data to write to register
+ * regidx - register within the PHY
+ * regval - data to write to register
*
* Return value:
- * nothing
+ * 0 for success
********************************************************************* */
-static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
- unsigned int regval)
+static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+ u16 regval)
{
+ struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
+ void __iomem *sbm_mdio = sc->sbm_mdio;
int mac_mdio_genc;
- sbmac_mii_sync(s);
+ sbmac_mii_sync(sbm_mdio);
- sbmac_mii_senddata(s,MII_COMMAND_START,2);
- sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
- sbmac_mii_senddata(s,phyaddr, 5);
- sbmac_mii_senddata(s,regidx, 5);
- sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
- sbmac_mii_senddata(s,regval,16);
+ sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
+ sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2);
+ sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
+ sbmac_mii_senddata(sbm_mdio, regidx, 5);
+ sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2);
+ sbmac_mii_senddata(sbm_mdio, regval, 16);
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
- __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
+
+ return 0;
}
@@ -713,27 +610,27 @@ static void sbdma_initctx(struct sbmacdm
s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
#endif
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR);
+ __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR);
/*
* initialize register pointers
@@ -953,7 +850,7 @@ static int sbdma_add_rcvbuffer(struct sb
if (sb == NULL) {
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
if (sb_new == NULL) {
- printk(KERN_INFO "%s: sk_buff allocation failed\n",
+ pr_info("%s: sk_buff allocation failed\n",
d->sbdma_eth->sbm_dev->name);
return -ENOBUFS;
}
@@ -1472,14 +1369,6 @@ static int sbmac_initctx(struct sbmac_so
s->sbm_imr = s->sbm_base + R_MAC_INT_MASK;
s->sbm_mdio = s->sbm_base + R_MAC_MDIO;
- s->sbm_phys[0] = 1;
- s->sbm_phys[1] = 0;
-
- s->sbm_phy_oldbmsr = 0;
- s->sbm_phy_oldanlpar = 0;
- s->sbm_phy_oldk1stsr = 0;
- s->sbm_phy_oldlinkstat = 0;
-
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
@@ -1494,14 +1383,6 @@ static int sbmac_initctx(struct sbmac_so
s->sbm_state = sbmac_state_off;
- /*
- * Initial speed is (XXX TEMP) 10MBit/s HDX no FC
- */
-
- s->sbm_speed = sbmac_speed_10;
- s->sbm_duplex = sbmac_duplex_half;
- s->sbm_fc = sbmac_fc_disabled;
-
return 0;
}
@@ -2008,8 +1889,6 @@ static int sbmac_set_speed(struct sbmac_
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;
- case sbmac_speed_auto: /* XXX not implemented */
- /* fall through */
default:
return 0;
}
@@ -2083,8 +1962,6 @@ static int sbmac_set_duplex(struct sbmac
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
break;
- case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
return 0;
@@ -2103,15 +1980,12 @@ static int sbmac_set_duplex(struct sbmac
case sbmac_fc_collision: /* not valid in full duplex */
case sbmac_fc_carrier: /* not valid in full duplex */
- case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
default:
return 0;
}
break;
- case sbmac_duplex_auto:
- /* XXX not implemented */
- break;
+ default:
+ return 0;
}
/*
@@ -2390,7 +2264,7 @@ static int sb1250_change_mtu(struct net_
if (new_mtu > ENET_PACKET_SIZE)
return -EINVAL;
_dev->mtu = new_mtu;
- printk(KERN_INFO "changing the mtu to %d\n", new_mtu);
+ pr_info("changing the mtu to %d\n", new_mtu);
return 0;
}
@@ -2406,20 +2280,17 @@ static int sb1250_change_mtu(struct net_
* status
********************************************************************* */
-static int sbmac_init(struct net_device *dev, int idx)
+static int sbmac_init(struct platform_device *pldev, long long base)
{
- struct sbmac_softc *sc;
+ struct net_device *dev = pldev->dev.driver_data;
+ int idx = pldev->id;
+ struct sbmac_softc *sc = netdev_priv(dev);
unsigned char *eaddr;
uint64_t ea_reg;
int i;
int err;
DECLARE_MAC_BUF(mac);
- sc = netdev_priv(dev);
-
- /* Determine controller base address */
-
- sc->sbm_base = IOADDR(dev->base_addr);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
@@ -2476,43 +2347,55 @@ static int sbmac_init(struct net_device
dev->poll_controller = sbmac_netpoll;
#endif
+ dev->irq = UNIT_INT(idx);
+
/* This is needed for PASS2 for Rx H/W checksum feature */
sbmac_set_iphdr_offset(sc);
err = register_netdev(dev);
- if (err)
- goto out_uninit;
-
- if (sc->rx_hw_checksum == ENABLE) {
- printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
- sc->sbm_dev->name);
+ if (err) {
+ printk(KERN_ERR "%s.%d: unable to register netdev\n",
+ sbmac_string, idx);
+ sbmac_uninitctx(sc);
+ return err;
}
+ pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name);
+
+ if (sc->rx_hw_checksum == ENABLE)
+ pr_info("%s: enabling TCP rcv checksum\n", dev->name);
+
/*
* Display Ethernet address (this is called during the config
* process so we need to finish off the config message that
* was being displayed)
*/
- printk(KERN_INFO
- "%s: SiByte Ethernet at 0x%08lX, address: %s\n",
- dev->name, dev->base_addr, print_mac(mac, eaddr));
+ pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %s\n",
+ dev->name, base, print_mac(mac, eaddr));
- return 0;
+ sc->mii_bus.name = sbmac_mdio_string;
+ sc->mii_bus.id = idx;
+ sc->mii_bus.priv = sc;
+ sc->mii_bus.read = sbmac_mii_read;
+ sc->mii_bus.write = sbmac_mii_write;
+ sc->mii_bus.irq = sc->phy_irq;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ sc->mii_bus.irq[i] = SBMAC_PHY_INT;
-out_uninit:
- sbmac_uninitctx(sc);
+ sc->mii_bus.dev = &pldev->dev;
+ dev_set_drvdata(&pldev->dev, &sc->mii_bus);
- return err;
+ return 0;
}
static int sbmac_open(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
+ int err;
- if (debug > 1) {
- printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
- }
+ if (debug > 1)
+ pr_debug("%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
/*
* map/route interrupt (clear status first, in case something
@@ -2521,25 +2404,35 @@ static int sbmac_open(struct net_device
*/
__raw_readq(sc->sbm_isr);
- if (request_irq(dev->irq, &sbmac_intr, IRQF_SHARED, dev->name, dev))
- return -EBUSY;
+ err = request_irq(dev->irq, &sbmac_intr, IRQF_SHARED, dev->name, dev);
+ if (err) {
+ printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
+ dev->irq);
+ goto out_err;
+ }
/*
- * Probe phy address
+ * Probe PHY address
*/
-
- if(sbmac_mii_probe(dev) == -1) {
- printk("%s: failed to probe PHY.\n", dev->name);
- return -EINVAL;
+ err = mdiobus_register(&sc->mii_bus);
+ if (err) {
+ printk(KERN_ERR "%s: unable to register MDIO bus\n",
+ dev->name);
+ goto out_unirq;
}
- napi_enable(&sc->napi);
+ sc->sbm_speed = sbmac_speed_none;
+ sc->sbm_duplex = sbmac_duplex_none;
+ sc->sbm_fc = sbmac_fc_none;
+ sc->sbm_pause = -1;
+ sc->sbm_link = 0;
/*
- * Configure default speed
+ * Attach to the PHY
*/
-
- sbmac_mii_poll(sc,noisy_mii);
+ err = sbmac_mii_probe(dev);
+ if (err)
+ goto out_unregister;
/*
* Turn on the channel
@@ -2547,200 +2440,133 @@ static int sbmac_open(struct net_device
sbmac_set_channel_state(sc,sbmac_state_on);
- /*
- * XXX Station address is in dev->dev_addr
- */
-
- if (dev->if_port == 0)
- dev->if_port = 0;
-
netif_start_queue(dev);
sbmac_set_rx_mode(dev);
- /* Set the timer to check for link beat. */
- init_timer(&sc->sbm_timer);
- sc->sbm_timer.expires = jiffies + 2 * HZ/100;
- sc->sbm_timer.data = (unsigned long)dev;
- sc->sbm_timer.function = &sbmac_timer;
- add_timer(&sc->sbm_timer);
+ phy_start(sc->phy_dev);
+
+ napi_enable(&sc->napi);
return 0;
+
+out_unregister:
+ mdiobus_unregister(&sc->mii_bus);
+
+out_unirq:
+ free_irq(dev->irq, dev);
+
+out_err:
+ return err;
}
static int sbmac_mii_probe(struct net_device *dev)
{
+ struct sbmac_softc *sc = netdev_priv(dev);
+ struct phy_device *phy_dev;
int i;
- struct sbmac_softc *s = netdev_priv(dev);
- u16 bmsr, id1, id2;
- u32 vendor, device;
-
- for (i=1; i<31; i++) {
- bmsr = sbmac_mii_read(s, i, MII_BMSR);
- if (bmsr != 0) {
- s->sbm_phys[0] = i;
- id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
- id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
- vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
- device = (id2 >> 4) & 0x3f;
-
- printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
- dev->name, i, vendor, device);
- return i;
- }
- }
- return -1;
-}
-
-static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
-{
- int bmsr,bmcr,k1stsr,anlpar;
- int chg;
- char buffer[100];
- char *p = buffer;
-
- /* Read the mode status and mode control registers. */
- bmsr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMSR);
- bmcr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMCR);
-
- /* get the link partner status */
- anlpar = sbmac_mii_read(s,s->sbm_phys[0],MII_ANLPAR);
-
- /* if supported, read the 1000baseT register */
- if (bmsr & BMSR_1000BT_XSR) {
- k1stsr = sbmac_mii_read(s,s->sbm_phys[0],MII_K1STSR);
- }
- else {
- k1stsr = 0;
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ phy_dev = sc->mii_bus.phy_map[i];
+ if (phy_dev)
+ break;
}
+ if (!phy_dev) {
+ printk(KERN_ERR "%s: no PHY found\n", dev->name);
+ return -ENXIO;
+ }
+
+ phy_dev = phy_connect(dev, phy_dev->dev.bus_id, &sbmac_mii_poll, 0,
+ PHY_INTERFACE_MODE_GMII);
+ if (IS_ERR(phy_dev)) {
+ printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+ return PTR_ERR(phy_dev);
+ }
+
+ /* Remove any features not supported by the controller */
+ phy_dev->supported &= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_MII |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause;
+ phy_dev->advertising = phy_dev->supported;
+
+ pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ dev->name, phy_dev->drv->name,
+ phy_dev->dev.bus_id, phy_dev->irq);
- chg = 0;
+ sc->phy_dev = phy_dev;
- if ((bmsr & BMSR_LINKSTAT) == 0) {
- /*
- * If link status is down, clear out old info so that when
- * it comes back up it will force us to reconfigure speed
- */
- s->sbm_phy_oldbmsr = 0;
- s->sbm_phy_oldanlpar = 0;
- s->sbm_phy_oldk1stsr = 0;
return 0;
- }
-
- if ((s->sbm_phy_oldbmsr != bmsr) ||
- (s->sbm_phy_oldanlpar != anlpar) ||
- (s->sbm_phy_oldk1stsr != k1stsr)) {
- if (debug > 1) {
- printk(KERN_DEBUG "%s: bmsr:%x/%x anlpar:%x/%x k1stsr:%x/%x\n",
- s->sbm_dev->name,
- s->sbm_phy_oldbmsr,bmsr,
- s->sbm_phy_oldanlpar,anlpar,
- s->sbm_phy_oldk1stsr,k1stsr);
- }
- s->sbm_phy_oldbmsr = bmsr;
- s->sbm_phy_oldanlpar = anlpar;
- s->sbm_phy_oldk1stsr = k1stsr;
- chg = 1;
- }
-
- if (chg == 0)
- return 0;
-
- p += sprintf(p,"Link speed: ");
-
- if (k1stsr & K1STSR_LP1KFD) {
- s->sbm_speed = sbmac_speed_1000;
- s->sbm_duplex = sbmac_duplex_full;
- s->sbm_fc = sbmac_fc_frame;
- p += sprintf(p,"1000BaseT FDX");
- }
- else if (k1stsr & K1STSR_LP1KHD) {
- s->sbm_speed = sbmac_speed_1000;
- s->sbm_duplex = sbmac_duplex_half;
- s->sbm_fc = sbmac_fc_disabled;
- p += sprintf(p,"1000BaseT HDX");
- }
- else if (anlpar & ANLPAR_TXFD) {
- s->sbm_speed = sbmac_speed_100;
- s->sbm_duplex = sbmac_duplex_full;
- s->sbm_fc = (anlpar & ANLPAR_PAUSE) ? sbmac_fc_frame : sbmac_fc_disabled;
- p += sprintf(p,"100BaseT FDX");
- }
- else if (anlpar & ANLPAR_TXHD) {
- s->sbm_speed = sbmac_speed_100;
- s->sbm_duplex = sbmac_duplex_half;
- s->sbm_fc = sbmac_fc_disabled;
- p += sprintf(p,"100BaseT HDX");
- }
- else if (anlpar & ANLPAR_10FD) {
- s->sbm_speed = sbmac_speed_10;
- s->sbm_duplex = sbmac_duplex_full;
- s->sbm_fc = sbmac_fc_frame;
- p += sprintf(p,"10BaseT FDX");
- }
- else if (anlpar & ANLPAR_10HD) {
- s->sbm_speed = sbmac_speed_10;
- s->sbm_duplex = sbmac_duplex_half;
- s->sbm_fc = sbmac_fc_collision;
- p += sprintf(p,"10BaseT HDX");
- }
- else {
- p += sprintf(p,"Unknown");
- }
-
- if (noisy) {
- printk(KERN_INFO "%s: %s\n",s->sbm_dev->name,buffer);
- }
-
- return 1;
}
-static void sbmac_timer(unsigned long data)
+static void sbmac_mii_poll(struct net_device *dev)
{
- struct net_device *dev = (struct net_device *)data;
struct sbmac_softc *sc = netdev_priv(dev);
- int next_tick = HZ;
- int mii_status;
-
- spin_lock_irq (&sc->sbm_lock);
-
- /* make IFF_RUNNING follow the MII status bit "Link established" */
- mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
+ struct phy_device *phy_dev = sc->phy_dev;
+ unsigned long flags;
+ enum sbmac_fc fc;
+ int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg;
- if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
- sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
- if (mii_status & BMSR_LINKSTAT) {
- netif_carrier_on(dev);
- }
- else {
- netif_carrier_off(dev);
+ link_chg = (sc->sbm_link != phy_dev->link);
+ speed_chg = (sc->sbm_speed != phy_dev->speed);
+ duplex_chg = (sc->sbm_duplex != phy_dev->duplex);
+ pause_chg = (sc->sbm_pause != phy_dev->pause);
+
+ if (!link_chg && !speed_chg && !duplex_chg && !pause_chg)
+ return; /* Hmmm... */
+
+ if (!phy_dev->link) {
+ if (link_chg) {
+ sc->sbm_link = phy_dev->link;
+ sc->sbm_speed = sbmac_speed_none;
+ sc->sbm_duplex = sbmac_duplex_none;
+ sc->sbm_fc = sbmac_fc_disabled;
+ sc->sbm_pause = -1;
+ pr_info("%s: link unavailable\n", dev->name);
}
+ return;
}
- /*
- * Poll the PHY to see what speed we should be running at
- */
+ if (phy_dev->duplex == DUPLEX_FULL) {
+ if (phy_dev->pause)
+ fc = sbmac_fc_frame;
+ else
+ fc = sbmac_fc_disabled;
+ } else
+ fc = sbmac_fc_collision;
+ fc_chg = (sc->sbm_fc != fc);
- if (sbmac_mii_poll(sc,noisy_mii)) {
- if (sc->sbm_state != sbmac_state_off) {
- /*
- * something changed, restart the channel
- */
- if (debug > 1) {
- printk("%s: restarting channel because speed changed\n",
- sc->sbm_dev->name);
- }
- sbmac_channel_stop(sc);
- sbmac_channel_start(sc);
- }
- }
+ pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed,
+ phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H');
- spin_unlock_irq (&sc->sbm_lock);
+ spin_lock_irqsave(&sc->sbm_lock, flags);
+
+ sc->sbm_speed = phy_dev->speed;
+ sc->sbm_duplex = phy_dev->duplex;
+ sc->sbm_fc = fc;
+ sc->sbm_pause = phy_dev->pause;
+ sc->sbm_link = phy_dev->link;
- sc->sbm_timer.expires = jiffies + next_tick;
- add_timer(&sc->sbm_timer);
+ if ((speed_chg || duplex_chg || fc_chg) &&
+ sc->sbm_state != sbmac_state_off) {
+ /*
+ * something changed, restart the channel
+ */
+ if (debug > 1)
+ pr_debug("%s: restarting channel "
+ "because PHY state changed\n", dev->name);
+ sbmac_channel_stop(sc);
+ sbmac_channel_start(sc);
+ }
+
+ spin_unlock_irqrestore(&sc->sbm_lock, flags);
}
@@ -2793,64 +2619,34 @@ static void sbmac_set_rx_mode(struct net
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct sbmac_softc *sc = netdev_priv(dev);
- u16 *data = (u16 *)&rq->ifr_ifru;
- unsigned long flags;
- int retval;
-
- spin_lock_irqsave(&sc->sbm_lock, flags);
- retval = 0;
- switch(cmd) {
- case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
- data[0] = sc->sbm_phys[0] & 0x1f;
- /* Fall Through */
- case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- data[3] = sbmac_mii_read(sc, data[0] & 0x1f, data[1] & 0x1f);
- break;
- case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!capable(CAP_NET_ADMIN)) {
- retval = -EPERM;
- break;
- }
- if (debug > 1) {
- printk(KERN_DEBUG "%s: sbmac_mii_ioctl: write %02X %02X %02X\n",dev->name,
- data[0],data[1],data[2]);
- }
- sbmac_mii_write(sc, data[0] & 0x1f, data[1] & 0x1f, data[2]);
- break;
- default:
- retval = -EOPNOTSUPP;
- }
+ if (!netif_running(dev) || !sc->phy_dev)
+ return -EINVAL;
- spin_unlock_irqrestore(&sc->sbm_lock, flags);
- return retval;
+ return phy_mii_ioctl(sc->phy_dev, if_mii(rq), cmd);
}
static int sbmac_close(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
- unsigned long flags;
- int irq;
napi_disable(&sc->napi);
- sbmac_set_channel_state(sc,sbmac_state_off);
+ phy_stop(sc->phy_dev);
- del_timer_sync(&sc->sbm_timer);
-
- spin_lock_irqsave(&sc->sbm_lock, flags);
+ sbmac_set_channel_state(sc, sbmac_state_off);
netif_stop_queue(dev);
- if (debug > 1) {
- printk(KERN_DEBUG "%s: Shutting down ethercard\n",dev->name);
- }
+ if (debug > 1)
+ pr_debug("%s: Shutting down ethercard\n", dev->name);
- spin_unlock_irqrestore(&sc->sbm_lock, flags);
+ phy_disconnect(sc->phy_dev);
+ sc->phy_dev = NULL;
+
+ mdiobus_unregister(&sc->mii_bus);
- irq = dev->irq;
- synchronize_irq(irq);
- free_irq(irq, dev);
+ free_irq(dev->irq, dev);
sbdma_emptyring(&(sc->sbm_txdma));
sbdma_emptyring(&(sc->sbm_rxdma));
@@ -2883,54 +2679,195 @@ static int sbmac_poll(struct napi_struct
return work_done;
}
+
+static int __init sbmac_probe(struct platform_device *pldev)
+{
+ struct net_device *dev;
+ struct sbmac_softc *sc;
+ void __iomem *sbm_base;
+ struct resource *res;
+ u64 sbmac_orig_hwaddr;
+ int err;
+
+ res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ BUG_ON(!res);
+ sbm_base = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (!sbm_base) {
+ printk(KERN_ERR "%s: unable to map device registers\n",
+ pldev->dev.bus_id);
+ err = -ENOMEM;
+ goto out_out;
+ }
+
+ /*
+ * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
+ * value for us by the firmware if we're going to use this MAC.
+ * If we find a zero, skip this MAC.
+ */
+ sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR);
+ pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", pldev->dev.bus_id,
+ sbmac_orig_hwaddr ? "" : "not ", (long long)res->start);
+ if (sbmac_orig_hwaddr == 0) {
+ err = 0;
+ goto out_unmap;
+ }
+
+ /*
+ * Okay, cool. Initialize this MAC.
+ */
+ dev = alloc_etherdev(sizeof(struct sbmac_softc));
+ if (!dev) {
+ printk(KERN_ERR "%s: unable to allocate etherdev\n",
+ pldev->dev.bus_id);
+ err = -ENOMEM;
+ goto out_unmap;
+ }
+
+ pldev->dev.driver_data = dev;
+ SET_NETDEV_DEV(dev, &pldev->dev);
+
+ sc = netdev_priv(dev);
+ sc->sbm_base = sbm_base;
+
+ err = sbmac_init(pldev, res->start);
+ if (err)
+ goto out_kfree;
+
+ return 0;
+
+out_kfree:
+ free_netdev(dev);
+ __raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR);
+
+out_unmap:
+ iounmap(sbm_base);
+
+out_out:
+ return err;
+}
+
+static int __exit sbmac_remove(struct platform_device *pldev)
+{
+ struct net_device *dev = pldev->dev.driver_data;
+ struct sbmac_softc *sc = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ sbmac_uninitctx(sc);
+ iounmap(sc->sbm_base);
+ free_netdev(dev);
+
+ return 0;
+}
+
+
+static struct platform_device **sbmac_pldev;
+static int sbmac_max_units;
+
#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
-static void
-sbmac_setup_hwaddr(int chan,char *addr)
+static void __init sbmac_setup_hwaddr(int idx, char *addr)
{
+ void __iomem *sbm_base;
+ unsigned long start, end;
uint8_t eaddr[6];
uint64_t val;
- unsigned long port;
- port = A_MAC_CHANNEL_BASE(chan);
- sbmac_parse_hwaddr(addr,eaddr);
+ if (idx >= sbmac_max_units)
+ return;
+
+ start = A_MAC_CHANNEL_BASE(idx);
+ end = A_MAC_CHANNEL_BASE(idx + 1) - 1;
+
+ sbm_base = ioremap_nocache(start, end - start + 1);
+ if (!sbm_base) {
+ printk(KERN_ERR "%s: unable to map device registers\n",
+ sbmac_string);
+ return;
+ }
+
+ sbmac_parse_hwaddr(addr, eaddr);
val = sbmac_addr2reg(eaddr);
- __raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
- val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ __raw_writeq(val, sbm_base + R_MAC_ETHERNET_ADDR);
+ val = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR);
+
+ iounmap(sbm_base);
}
#endif
-static struct net_device *dev_sbmac[MAX_UNITS];
+static int __init sbmac_platform_probe_one(int idx)
+{
+ struct platform_device *pldev;
+ struct {
+ struct resource r;
+ char name[strlen(sbmac_pretty) + 4];
+ } *res;
+ int err;
-static int __init
-sbmac_init_module(void)
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ printk(KERN_ERR "%s.%d: unable to allocate memory\n",
+ sbmac_string, idx);
+ err = -ENOMEM;
+ goto out_err;
+ }
+
+ /*
+ * This is the base address of the MAC.
+ */
+ snprintf(res->name, sizeof(res->name), "%s %d", sbmac_pretty, idx);
+ res->r.name = res->name;
+ res->r.flags = IORESOURCE_MEM;
+ res->r.start = A_MAC_CHANNEL_BASE(idx);
+ res->r.end = A_MAC_CHANNEL_BASE(idx + 1) - 1;
+
+ pldev = platform_device_register_simple(sbmac_string, idx, &res->r, 1);
+ if (IS_ERR(pldev)) {
+ printk(KERN_ERR "%s.%d: unable to register platform device\n",
+ sbmac_string, idx);
+ err = PTR_ERR(pldev);
+ goto out_kfree;
+ }
+
+ if (!pldev->dev.driver) {
+ err = 0; /* No hardware at this address. */
+ goto out_unregister;
+ }
+
+ sbmac_pldev[idx] = pldev;
+ return 0;
+
+out_unregister:
+ platform_device_unregister(pldev);
+
+out_kfree:
+ kfree(res);
+
+out_err:
+ return err;
+}
+
+static void __init sbmac_platform_probe(void)
{
- int idx;
- struct net_device *dev;
- unsigned long port;
- int chip_max_units;
+ int i;
/* Set the number of available units based on the SOC type. */
switch (soc_type) {
case K_SYS_SOC_TYPE_BCM1250:
case K_SYS_SOC_TYPE_BCM1250_ALT:
- chip_max_units = 3;
+ sbmac_max_units = 3;
break;
case K_SYS_SOC_TYPE_BCM1120:
case K_SYS_SOC_TYPE_BCM1125:
case K_SYS_SOC_TYPE_BCM1125H:
- case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
- chip_max_units = 2;
+ case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
+ sbmac_max_units = 2;
break;
case K_SYS_SOC_TYPE_BCM1x55:
case K_SYS_SOC_TYPE_BCM1x80:
- chip_max_units = 4;
+ sbmac_max_units = 4;
break;
default:
- chip_max_units = 0;
- break;
+ return; /* none */
}
- if (chip_max_units > MAX_UNITS)
- chip_max_units = MAX_UNITS;
/*
* For bringup when not using the firmware, we can pre-fill
@@ -2938,89 +2875,71 @@ sbmac_init_module(void)
* specified in this file (or maybe from the config file?)
*/
#ifdef SBMAC_ETH0_HWADDR
- if (chip_max_units > 0)
- sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
+ sbmac_setup_hwaddr(0, SBMAC_ETH0_HWADDR);
#endif
#ifdef SBMAC_ETH1_HWADDR
- if (chip_max_units > 1)
- sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
+ sbmac_setup_hwaddr(1, SBMAC_ETH1_HWADDR);
#endif
#ifdef SBMAC_ETH2_HWADDR
- if (chip_max_units > 2)
- sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
+ sbmac_setup_hwaddr(2, SBMAC_ETH2_HWADDR);
#endif
#ifdef SBMAC_ETH3_HWADDR
- if (chip_max_units > 3)
- sbmac_setup_hwaddr(3,SBMAC_ETH3_HWADDR);
+ sbmac_setup_hwaddr(3, SBMAC_ETH3_HWADDR);
#endif
+ sbmac_pldev = kcalloc(sbmac_max_units, sizeof(*sbmac_pldev),
+ GFP_KERNEL);
+ if (!sbmac_pldev) {
+ printk(KERN_ERR "%s: unable to allocate memory\n",
+ sbmac_string);
+ return;
+ }
+
/*
* Walk through the Ethernet controllers and find
* those who have their MAC addresses set.
*/
- for (idx = 0; idx < chip_max_units; idx++) {
+ for (i = 0; i < sbmac_max_units; i++)
+ if (sbmac_platform_probe_one(i))
+ break;
+}
- /*
- * This is the base address of the MAC.
- */
- port = A_MAC_CHANNEL_BASE(idx);
+static void __exit sbmac_platform_cleanup(void)
+{
+ int i;
- /*
- * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
- * value for us by the firmware if we are going to use this MAC.
- * If we find a zero, skip this MAC.
- */
+ for (i = 0; i < sbmac_max_units; i++)
+ platform_device_unregister(sbmac_pldev[i]);
+ kfree(sbmac_pldev);
+}
- sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
- if (sbmac_orig_hwaddr[idx] == 0) {
- printk(KERN_DEBUG "sbmac: not configuring MAC at "
- "%lx\n", port);
- continue;
- }
- /*
- * Okay, cool. Initialize this MAC.
- */
+static struct platform_driver sbmac_driver = {
+ .probe = sbmac_probe,
+ .remove = __exit_p(sbmac_remove),
+ .driver = {
+ .name = sbmac_string,
+ },
+};
- dev = alloc_etherdev(sizeof(struct sbmac_softc));
- if (!dev)
- return -ENOMEM;
-
- printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
-
- dev->irq = UNIT_INT(idx);
- dev->base_addr = port;
- dev->mem_end = 0;
- if (sbmac_init(dev, idx)) {
- port = A_MAC_CHANNEL_BASE(idx);
- __raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
- free_netdev(dev);
- continue;
- }
- dev_sbmac[idx] = dev;
- }
- return 0;
-}
+static int __init sbmac_init_module(void)
+{
+ int err;
+ err = platform_driver_register(&sbmac_driver);
+ if (err)
+ return err;
-static void __exit
-sbmac_cleanup_module(void)
-{
- struct net_device *dev;
- int idx;
+ sbmac_platform_probe();
- for (idx = 0; idx < MAX_UNITS; idx++) {
- struct sbmac_softc *sc;
- dev = dev_sbmac[idx];
- if (!dev)
- continue;
+ return err;
+}
- sc = netdev_priv(dev);
- unregister_netdev(dev);
- sbmac_uninitctx(sc);
- free_netdev(dev);
- }
+static void __exit sbmac_cleanup_module(void)
+{
+ sbmac_platform_cleanup();
+ platform_driver_unregister(&sbmac_driver);
}
module_init(sbmac_init_module);
^ 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