* Re: [PATCH] bridge: mask forwarding of IEEE 802 local multicast groups
From: Stephen Hemminger @ 2011-08-15 18:25 UTC (permalink / raw)
To: Nick Carter; +Cc: David Lamparter, netdev, Michał Mirosław, davem
In-Reply-To: <CAEJpZP3PHC32i8m74-ML6DDGii8ojJ6v12CqQ+v2MKEMSDU=7A@mail.gmail.com>
On Mon, 15 Aug 2011 17:27:12 +0100
Nick Carter <ncarter100@gmail.com> wrote:
> On 28 July 2011 16:41, Stephen Hemminger
> <shemminger@linux-foundation.org> wrote:
> > On Wed, 27 Jul 2011 13:17:15 +0200
> > David Lamparter <equinox@diac24.net> wrote:
> >
> >> On Fri, Jul 15, 2011 at 06:33:45PM +0200, David Lamparter wrote:
> >> > On Fri, Jul 15, 2011 at 06:03:57PM +0200, David Lamparter wrote:
> >> > > On Fri, Jul 15, 2011 at 04:44:50PM +0100, Nick Carter wrote:
> >> > > > On 12 July 2011 12:36, David Lamparter <equinox@diac24.net> wrote:
> >> > > > > On Mon, Jul 11, 2011 at 08:27:55AM -0700, Stephen Hemminger wrote:
> >> > > > >> I am still undecided on this. Understand the need, but don't like idea
> >> > > > >> of bridge behaving in non-conforming manner. Will see if IEEE 802 committee
> >> > > > >> has any input.
> >> > > > >
> >> > > > > The patch doesn't make the bridge behave nonconformant. The default mask
> >> > > > > is 0, which just keeps the old behaviour.
> >> >
> >> > P.S.: I'd like to once more stress this. In my opinion the patch should
> >> > be merged because it provides desireable functionality at a small cost
> >> > (one test, one knob) and __does not change any default behaviour__.
> >>
> >> Stephen, anything new on this?
> >
> > No.
> > Don't like adding yet another hack user visible API which will have
> > to be maintained for too long. But on the other hand I don't have
> > a better solution at my finger tips. If better idea doesn't come
> > along, then we can go with yours.
> >
> I have not noticed any other proposals and this thread has been open
> for quite a while. Have we waited long enough ? If so can this patch
> be taken ?
>
I am testing an alternative. The problem with your proposal is that
it relies on the multicast address. It turns out there are people using
other addresses for the STP group address, so using that as a identifier
is incorrect.
^ permalink raw reply
* [PATCH] net: netdev-features.txt update to Documentation/networking/00-INDEX
From: Willem de Bruijn @ 2011-08-15 18:27 UTC (permalink / raw)
To: netdev; +Cc: mircus, davem
Update netdev-features.txt entry in 00-INDEX to incorporate
feedback by Michał Mirosław. A trivial update to my previous
patch, but I was too late with preparing a v2. Will try to
avoid having to send patches to my own patches in the future.
willem
Signed-off-by: Willem de Bruijn <willemb@gmail.com>
---
Documentation/networking/00-INDEX | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 811252b..bbce121 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -135,7 +135,7 @@ multiqueue.txt
netconsole.txt
- The network console module netconsole.ko: configuration and notes.
netdev-features.txt
- - Network interface "feature mess and how to get out from it alive".
+ - Network interface features API description.
netdevices.txt
- info on network device driver functions exported to the kernel.
netif-msg.txt
--
1.7.3.1
^ permalink raw reply related
* Re: [RFC PATCH v2 9/9] sfc: Support for byte queue limits
From: Ben Hutchings @ 2011-08-15 18:36 UTC (permalink / raw)
To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.2.00.1108072151500.13386@pokey.mtv.corp.google.com>
On Sun, 2011-08-07 at 21:53 -0700, Tom Herbert wrote:
> Changes to sfc to use byte queue limits.
>
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> drivers/net/sfc/tx.c | 27 +++++++++++++++++++++------
> 1 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
> index 84eb99e..9aa4339 100644
> --- a/drivers/net/sfc/tx.c
> +++ b/drivers/net/sfc/tx.c
> @@ -31,7 +31,9 @@
> #define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u)
>
> static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
> - struct efx_tx_buffer *buffer)
> + struct efx_tx_buffer *buffer,
> + unsigned int *pkts_compl,
> + unsigned int *bytes_compl)
> {
> if (buffer->unmap_len) {
> struct pci_dev *pci_dev = tx_queue->efx->pci_dev;
> @@ -48,6 +50,8 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
> }
>
> if (buffer->skb) {
> + (*pkts_compl)++;
> + (*bytes_compl) += buffer->skb->len;
We avoid using *buffer->skb on the completion path, as it is liklely to
be cache-cold. I would prefer to add and subtract fragment lengths
(buffer->len) instead. (This will also result in a slightly more
accurate estimate of the queue length when TSO is used.)
> dev_kfree_skb_any((struct sk_buff *) buffer->skb);
> buffer->skb = NULL;
> netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev,
> @@ -254,6 +258,8 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
> buffer->skb = skb;
> buffer->continuation = false;
>
> + netdev_tx_sent_queue(tx_queue->core_txq, 1, skb->len);
> +
> /* Pass off to hardware */
> efx_nic_push_buffers(tx_queue);
>
> @@ -271,10 +277,11 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
> unwind:
> /* Work backwards until we hit the original insert pointer value */
> while (tx_queue->insert_count != tx_queue->write_count) {
> + unsigned int pkts_compl = 0, bytes_compl = 0;
> --tx_queue->insert_count;
> insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
> buffer = &tx_queue->buffer[insert_ptr];
> - efx_dequeue_buffer(tx_queue, buffer);
> + efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
> buffer->len = 0;
> }
>
> @@ -297,7 +304,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
> * specified index.
> */
> static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
> - unsigned int index)
> + unsigned int index,
> + unsigned int *pkts_compl,
> + unsigned int *bytes_compl)
> {
> struct efx_nic *efx = tx_queue->efx;
> unsigned int stop_index, read_ptr;
> @@ -315,7 +324,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
> return;
> }
>
> - efx_dequeue_buffer(tx_queue, buffer);
> + efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl);
[...]
Since efx_deqeueue_buffers() is the only caller of efx_dequeue_buffer()
that actually wants to count the completed packets & bytes, the counting
should be done here.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH] bnx2x: suppress repeated error messages about Max BW
From: Eilon Greenstein @ 2011-08-15 18:47 UTC (permalink / raw)
To: Michal Schmidt
Cc: netdev@vger.kernel.org, Dmitry Kravkov, Vladislav Zolotarov
In-Reply-To: <4E493798.7010405@redhat.com>
On Mon, 2011-08-15 at 08:13 -0700, Michal Schmidt wrote:
> On 08/15/2011 02:33 PM, Eilon Greenstein wrote:
> > On Mon, 2011-08-15 at 04:59 -0700, Michal Schmidt wrote:
> >> and bnx2x_init_vn_minmax() calls bnx2x_extract_max_cfg() on the given
> >> VN, so it seems that the warning can be produced for a non-current VN.
> >
> > You are right, only one function (the PMF) will call this code for all
> > functions. But I suspect that if you have zero values, you will have
> > them for all VNs - is that the case?
>
> A tester reported getting only these 4 messages with the patch applied:
>
> [bnx2x_extract_max_cfg:1074(eth4)]Illegal configuration detected for Max
> BW on vn 2 - using 100 instead
> [bnx2x_extract_max_cfg:1074(eth5)]Illegal configuration detected for Max
> BW on vn 2 - using 100 instead
> [bnx2x_extract_max_cfg:1074(eth6)]Illegal configuration detected for Max
> BW on vn 3 - using 100 instead
> [bnx2x_extract_max_cfg:1074(eth7)]Illegal configuration detected for Max
> BW on vn 3 - using 100 instead
>
> This suggests that VNs 0 and 1 had non-zero Max BW configuration.
Michal - this is a great point of data! It helped me finding a bug in
that code - the code is not suitable for 4 port devices, it always
assumes 4 VN per PCI function, while in 4 port devices there are only 2
VN per PCI function. I assume that you are seeing this problem on a
57800 with 2x10G + 2x1G - and the 1G devices are in single function mode
and therefore you are seeing this error message. I will send a patch to
fix the problem on 4 port devices soon (after testing it for a while) -
please confirm that you are seeing this issue on 2x10G+2x1G 57800
device.
Now it all makes sense to me - it’s not just misconfigured board
workaround, this is a real issue :)
Thanks for helping in identifying it!
Eilon
^ permalink raw reply
* Re: invalid requirement from ethtool?
From: David Miller @ 2011-08-15 20:49 UTC (permalink / raw)
To: bhutchings; +Cc: eli, netdev
In-Reply-To: <1313429040.2731.17.camel@bwh-desktop>
From: Ben Hutchings <bhutchings@solarflare.com>
Date: Mon, 15 Aug 2011 18:24:00 +0100
> David, I know you maintained tg3 for some time so I assume you have a
> hardware reference. Can you confirm whether a value of 1 in
> HOSTCC_{RX,TX}MAX_FRAMES results in an interrupt after 1 completion or
> after 2 completions?
A value of 1 results in an interrupt after 1 completion.
If you put a zero there, the packet count comparison never triggers.
^ permalink raw reply
* Task blocked on a ext4 partition
From: Felipe Wilhelms Damasio - Taghos @ 2011-08-15 20:51 UTC (permalink / raw)
To: netdev
Hi All,
I'm using a mmap-based file sharing system on an ext4 partition with
epoll on an ISP.
Last night the system got a significant slow down, and dmesg showed a
lot of these:
INFO: task fshare:23798 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
fshare D 0000000000000007 0 23798 17719 0x00000000
ffff88018af29648 0000000000000082 0000000000012500 ffff88018af29fd8
ffff88018af29fd8 ffff88042d371a40 0000000000012500 0000000000012500
0000000000012500 ffff88042d371a40 ffff88042e0d5550 ffff88042d371ce8
Call Trace:
[<ffffffff8102e155>] ? enqueue_entity+0x11f/0x127
[<ffffffff8151c9c7>] schedule_timeout+0x22/0xda
[<ffffffff81035288>] ? get_parent_ip+0x11/0x41
[<ffffffff8103541e>] ? sub_preempt_count+0x92/0xa5
[<ffffffff8151c0fc>] wait_for_common+0xca/0x140
[<ffffffff81037bd1>] ? default_wake_function+0x0/0xf
[<ffffffff8151c20c>] wait_for_completion+0x18/0x1a
[<ffffffff810df950>] writeback_inodes_sb+0xb4/0xbf
[<ffffffff810dfe60>] writeback_inodes_sb_if_idle+0x37/0x4b
[<ffffffff81124b34>] ext4_da_write_begin+0xa5/0x1e6
[<ffffffff8108fdab>] ? find_lock_page+0x1e/0x5d
[<ffffffff8111e263>] ext4_page_mkwrite+0x117/0x168
[<ffffffff810a316b>] __do_fault+0x125/0x388
[<ffffffff81035288>] ? get_parent_ip+0x11/0x41
[<ffffffff810a52d6>] handle_mm_fault+0x429/0x838
[<ffffffff8102211e>] do_page_fault+0x222/0x239
[<ffffffff8151e44f>] page_fault+0x1f/0x30
[<ffffffff8122e1ed>] ? copy_user_generic_string+0x2d/0x40
[<ffffffff81457020>] ? memcpy_toiovec+0x37/0x66
[<ffffffff814578ee>] skb_copy_datagram_iovec+0x4b/0x1cf
[<ffffffff81035288>] ? get_parent_ip+0x11/0x41
[<ffffffff81494fb9>] tcp_recvmsg+0x746/0xa62
[<ffffffff814b09ed>] inet_recvmsg+0x5a/0x78
[<ffffffff8144d89a>] __sock_recvmsg+0x7b/0x87
[<ffffffff8144db5b>] sock_recvmsg+0xa6/0xbf
[<ffffffff814922e2>] ? tcp_poll+0x2b/0x180
[<ffffffff810c584c>] ? fget_light+0x93/0xa9
[<ffffffff8144dcd9>] ? sockfd_lookup_light+0x1b/0x53
[<ffffffff8144f291>] sys_recvfrom+0xb0/0xfe
[<ffffffff810f11c5>] ? sys_epoll_wait+0x28f/0x2a7
[<ffffffff81002a2b>] system_call_fastpath+0x16/0x1b
Do you have any idea what could cause this?
The kernel I'm using is 2.6.35.13. Is there any other info I can provide
to help track this down?
Cheers,
--
Felipe Wilhelms Damasio
TAGHOS - Tecnologia
Rua Prof. Alvaro Alvim, 211
Porto Alegre - RS - (51) 3239-3180
www.taghos.com.br
^ permalink raw reply
* Re: 3.1-rc1-git9: Reported regressions 2.6.39 -> 3.0
From: Bernd Schubert @ 2011-08-15 21:22 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux Kernel Mailing List, Maciej Rutecki, Florian Mickler,
Kernel Testers List, Network Development
In-Reply-To: <xuTC4jRtHbB.A.l4H.gMCSOB@chimera>
On 08/14/2011 09:02 PM, Rafael J. Wysocki wrote:
> Please let the tracking team know if there are any Bugzilla entries that
> should be added to the list in there.
>
Could you please add
Bug-Entry : https://bugzilla.kernel.org/show_bug.cgi?id=41212
Subject : ipoib causes kernel panic (NULL pointer dereference)
Submitter : Bernd Schubert <bernd.schubert-97jfqw80gc6171pxa8y+qA@public.gmane.org>
Date : 2011-08-15 15:40
Patch : https://bugzilla.kernel.org/attachment.cgi?id=68942
Thanks,
Bernd
^ permalink raw reply
* [RFC] bridge: allow passing link-local multicast
From: Stephen Hemminger @ 2011-08-15 22:05 UTC (permalink / raw)
To: Ed Swierk; +Cc: netdev, Nick Carter, David Lamparter, bridge
In-Reply-To: <CAF5U64B_fb2tFMLHmK+zw3n6gmq+bYDyFnXhLE0ayssK5m+THA@mail.gmail.com>
Several users have wanted to forward 802.1x EAP multicast
packets through a bridge. And there has been a couple of
attempts at allowing some form of this in the past.
If a bridge does not have spanning tree turned on, then it should
act like a pure hub and forward all traffic. This makes it fully
transparent, and if there is another bridge using spanning tree
the STP packets will still work for detecting loops in the network.
If bridge has STP enabled, then the default behavior is to
process all link-local multicasts locally. The expectation is
that if 802.1x or other protocol using link-local multicasts
that a service (or proxy) for that protocol will be used.
Optionally, a sysctl value can be set to allow non STP packets
to still be forwarded. I chose sysctl for this because it is
where such modifications exist when doing IP or netfilter.
There are other filtering/configuration options that are needed
and this is a better way to enable them.
Thanks to David Lamparter, and others for bringing this up.
Users who need this facility should provide feedback, is this
a usable solution?
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
Patch against net-next
Documentation/networking/ip-sysctl.txt | 4 ++
net/bridge/Makefile | 2 -
net/bridge/br.c | 12 ++++++
net/bridge/br_input.c | 30 ++++++++++++++++-
net/bridge/br_private.h | 5 ++
net/bridge/br_sysctl.c | 57 +++++++++++++++++++++++++++++++++
6 files changed, 107 insertions(+), 3 deletions(-)
--- a/Documentation/networking/ip-sysctl.txt 2011-08-15 10:58:36.451532115 -0700
+++ b/Documentation/networking/ip-sysctl.txt 2011-08-15 11:39:57.719438766 -0700
@@ -1289,6 +1289,10 @@ bridge-nf-filter-pppoe-tagged - BOOLEAN
0 : disable this.
Default: 1
+bridge-forward-link-local - BOOLEAN
+ 1 : pass link-local multicasts through bridge in STP mode
+ 0 : disable this.
+ Default: 0
proc/sys/net/sctp/* Variables:
--- a/net/bridge/Makefile 2011-08-15 10:30:25.203595742 -0700
+++ b/net/bridge/Makefile 2011-08-15 11:22:38.139477877 -0700
@@ -9,7 +9,7 @@ bridge-y := br.o br_device.o br_fdb.o br
br_stp_if.o br_stp_timer.o br_netlink.o
bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
-
+bridge-$(CONFIG_SYSCTL) += br_sysctl.o
bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o
--- a/net/bridge/br.c 2011-08-15 10:30:48.755594855 -0700
+++ b/net/bridge/br.c 2011-08-15 10:33:07.215589647 -0700
@@ -60,6 +60,12 @@ static int __init br_init(void)
if (err)
goto err_out4;
+#ifdef CONFIG_SYSCTL
+ err = br_sysctl_init();
+ if (err)
+ goto err_out5;
+#endif
+
brioctl_set(br_ioctl_deviceless_stub);
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
@@ -67,6 +73,9 @@ static int __init br_init(void)
#endif
return 0;
+
+err_out5:
+ br_netlink_fini();
err_out4:
unregister_netdevice_notifier(&br_device_notifier);
err_out3:
@@ -84,6 +93,9 @@ static void __exit br_deinit(void)
{
stp_proto_unregister(&br_stp_proto);
+#ifdef CONFIG_SYSCTL
+ br_sysctl_fini();
+#endif
br_netlink_fini();
unregister_netdevice_notifier(&br_device_notifier);
brioctl_set(NULL);
--- a/net/bridge/br_input.c 2011-08-15 10:40:21.435573311 -0700
+++ b/net/bridge/br_input.c 2011-08-15 11:39:57.719438766 -0700
@@ -16,11 +16,18 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/netfilter_bridge.h>
+#include <linux/llc.h>
+#include <net/llc.h>
+#include <net/llc_pdu.h>
+
#include "br_private.h"
/* Bridge group multicast address 802.1d (pg 51). */
const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+/* Should link-local packets be forwarded (in STP mode) */
+int br_forward_link_local;
+
/* Hook for brouter */
br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
EXPORT_SYMBOL(br_should_route_hook);
@@ -138,6 +145,17 @@ static inline int is_link_local(const un
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
}
+/* Identify Spanning Tree packets based on header */
+static bool is_stp_bpdu(struct sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ return skb->protocol == htons(ETH_P_802_2) &&
+ pdu->ctrl_1 == LLC_PDU_TYPE_U &&
+ pdu->dsap == LLC_SAP_BSPAN &&
+ pdu->ssap == LLC_SAP_BSPAN;
+}
+
/*
* Return NULL if skb is handled
* note: already called with rcu_read_lock
@@ -166,8 +184,16 @@ rx_handler_result_t br_handle_frame(stru
if (skb->protocol == htons(ETH_P_PAUSE))
goto drop;
- /* If STP is turned off, then forward */
- if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
+ /* If STP is turned off, then in hub mode */
+ if (p->br->stp_enabled == BR_NO_STP)
+ goto forward;
+
+ /*
+ * If STP is on
+ * then Always handle STP packets locally,
+ * other packets can be forwarded if sysctl is enabled.
+ */
+ if (!is_stp_bpdu(skb) && br_forward_link_local)
goto forward;
if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
--- a/net/bridge/br_private.h 2011-08-15 10:38:35.587577293 -0700
+++ b/net/bridge/br_private.h 2011-08-15 10:57:36.983534352 -0700
@@ -284,6 +284,7 @@ struct br_input_skb_cb {
pr_debug("%s: " format, (br)->dev->name, ##args)
extern struct notifier_block br_device_notifier;
+extern int br_forward_link_local;
extern const u8 br_group_address[ETH_ALEN];
/* called under bridge lock */
@@ -546,6 +547,10 @@ extern int br_sysfs_renameif(struct net_
extern int br_sysfs_addbr(struct net_device *dev);
extern void br_sysfs_delbr(struct net_device *dev);
+/* br_sysctl.c */
+extern int br_sysctl_init(void);
+extern void br_sysctl_fini(void);
+
#else
#define br_sysfs_addif(p) (0)
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/net/bridge/br_sysctl.c 2011-08-15 11:41:00.819436393 -0700
@@ -0,0 +1,57 @@
+/*
+ * Sysctl settings for bridge
+ *
+ * Authors:
+ * Stephen Hemminger <shemminger@osdl.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
+#include <linux/sysctl.h>
+
+#include "br_private.h"
+
+static struct ctl_table bridge_table[] = {
+ {
+ .procname = "bridge-forward-link-local",
+ .data = &br_forward_link_local,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+};
+
+static struct ctl_path bridge_ctl_path[] = {
+ { .procname = "net", },
+ { .procname = "bridge", },
+ { },
+};
+
+static struct ctl_table_header *br_sysctl;
+
+int __init br_sysctl_init(void)
+{
+ br_sysctl = register_sysctl_paths(bridge_ctl_path, bridge_table);
+ if (br_sysctl == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void __exit br_sysctl_fini(void)
+{
+ unregister_net_sysctl_table(br_sysctl);
+}
^ permalink raw reply
* Re: [PATCH] virtio-net: Read MAC only after initializing MSI-X
From: Sasha Levin @ 2011-08-15 22:17 UTC (permalink / raw)
To: Rusty Russell
Cc: linux-kernel, Michael S. Tsirkin, virtualization, netdev, kvm
In-Reply-To: <87vctz7c7d.fsf@rustcorp.com.au>
On Mon, 2011-08-15 at 09:55 +0930, Rusty Russell wrote:
> On Sun, 14 Aug 2011 16:57:32 +0300, Sasha Levin <levinsasha928@gmail.com> wrote:
> > On Sun, 2011-08-14 at 12:23 +0930, Rusty Russell wrote:
> > > On Sat, 13 Aug 2011 11:51:01 +0300, Sasha Levin <levinsasha928@gmail.com> wrote:
> > > > The MAC of a virtio-net device is located at the first field of the device
> > > > specific header. This header is located at offset 20 if the device doesn't
> > > > support MSI-X or offset 24 if it does.
> > >
> > > Erk. This means, in general, we have to do virtio_find_single_vq or
> > > config->find_vqs before we examine any config options.
> > >
> > > Look at virtio_blk, which has the same error.
> > >
> > > Solutions in order of best to worst:
> > > (1) Enable MSI-X before calling device probe. This means reserving two
> > > vectors in virtio_pci_probe to ensure we *can* do this, I think. Michael?
> >
> > Do you mean reserving the vectors even before we probed the device for
> > MSI-X support? Wouldn't we need 3 vectors then? (config, input, output).
>
> We want three, but *need* two: see vp_find_vqs(). Also, the generic
> code doesn't know how many virtqueues we have on the device.
We can just pci_enable_msix() and see if we can get 2 vectors, if we can
- we assume the device has msix on, right?
--
Sasha.
^ permalink raw reply
* [PATCH net-next 1/5] ethtool: Reformat struct ethtool_coalesce comments into kernel-doc format
From: Ben Hutchings @ 2011-08-16 0:06 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Eli Cohen
This reorders and duplicates some wording, but should make no
substantive changes.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
include/linux/ethtool.h | 135 ++++++++++++++++++++++-------------------------
1 files changed, 64 insertions(+), 71 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c6e427a..be32dd0 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -117,99 +117,92 @@ struct ethtool_eeprom {
__u8 data[0];
};
-/* for configuring coalescing parameters of chip */
+/**
+ * struct ethtool_coalesce - coalescing parameters of chip
+ * @cmd: ETHTOOL_{G,S}COALESCE
+ * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
+ * a packet arrives. If 0, only @rx_max_coalesced_frames is used.
+ * @rx_max_coalesced_frames: How many packets to delay an RX interrupt
+ * after a packet arrives. If 0, only @rx_coalesce_usecs is used.
+ * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
+ * this value applies while an IRQ is being serviced by the host.
+ * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
+ * except that this value applies while an IRQ is being serviced
+ * by the host.
+ * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
+ * a packet is sent. If 0, only @tx_max_coalesced_frames
+ * is used.
+ * @tx_max_coalesced_frames: How many packets to delay a TX interrupt
+ * after a packet is sent. If 0, only @tx_coalesce_usecs is
+ * used.
+ * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
+ * this value applies while an IRQ is being serviced by the host.
+ * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
+ * except that this value applies while an IRQ is being serviced
+ * by the host.
+ * @stats_block_coalesce_usecs: How many usecs to delay in-memory
+ * statistics block updates. Some drivers do not have an
+ * in-memory statistic block, and in such cases this value is
+ * ignored. This value must not be zero.
+ * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing.
+ * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing.
+ * @pkt_rate_low: Threshold for low packet rate (packets per second).
+ * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after
+ * a packet arrives, when the packet rate is below @pkt_rate_low.
+ * @rx_max_coalesced_frames_low: How many packets to delay an RX interrupt
+ * after a packet arrives, when the packet rate is below @pkt_rate_low.
+ * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after
+ * a packet is sent, when the packet rate is below @pkt_rate_low.
+ * @tx_max_coalesced_frames_low: How many packets to delay a TX interrupt
+ * after a packet is sent, when the packet rate is below @pkt_rate_low.
+ * @pkt_rate_high: Threshold for high packet rate (packets per second).
+ * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after
+ * a packet arrives, when the packet rate is above @pkt_rate_high.
+ * @rx_max_coalesced_frames_high: How many packets to delay an RX interrupt
+ * after a packet arrives, when the packet rate is above @pkt_rate_high.
+ * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after
+ * a packet is sent, when the packet rate is above @pkt_rate_high.
+ * @tx_max_coalesced_frames_high: How many packets to delay a TX interrupt
+ * after a packet is sent, when the packet rate is above @pkt_rate_high.
+ * @rate_sample_interval: How often to do adaptive coalescing packet rate
+ * sampling, measured in seconds. Must not be zero.
+ *
+ * It is illegal to set both usecs and max frames to zero as this
+ * would cause interrupts to never be generated.
+ *
+ * Adaptive RX/TX coalescing is an algorithm implemented by some
+ * drivers to improve latency under low packet rates and improve
+ * throughput under high packet rates. Some drivers only implement
+ * one of RX or TX adaptive coalescing. Anything not implemented by
+ * the driver causes these values to be silently ignored.
+ *
+ * When the packet rate is below @pkt_rate_high but above
+ * @pkt_rate_low (both measured in packets per second) the
+ * normal {rx,tx}_* coalescing parameters are used.
+ */
struct ethtool_coalesce {
- __u32 cmd; /* ETHTOOL_{G,S}COALESCE */
-
- /* How many usecs to delay an RX interrupt after
- * a packet arrives. If 0, only rx_max_coalesced_frames
- * is used.
- */
+ __u32 cmd;
__u32 rx_coalesce_usecs;
-
- /* How many packets to delay an RX interrupt after
- * a packet arrives. If 0, only rx_coalesce_usecs is
- * used. It is illegal to set both usecs and max frames
- * to zero as this would cause RX interrupts to never be
- * generated.
- */
__u32 rx_max_coalesced_frames;
-
- /* Same as above two parameters, except that these values
- * apply while an IRQ is being serviced by the host. Not
- * all cards support this feature and the values are ignored
- * in that case.
- */
__u32 rx_coalesce_usecs_irq;
__u32 rx_max_coalesced_frames_irq;
-
- /* How many usecs to delay a TX interrupt after
- * a packet is sent. If 0, only tx_max_coalesced_frames
- * is used.
- */
__u32 tx_coalesce_usecs;
-
- /* How many packets to delay a TX interrupt after
- * a packet is sent. If 0, only tx_coalesce_usecs is
- * used. It is illegal to set both usecs and max frames
- * to zero as this would cause TX interrupts to never be
- * generated.
- */
__u32 tx_max_coalesced_frames;
-
- /* Same as above two parameters, except that these values
- * apply while an IRQ is being serviced by the host. Not
- * all cards support this feature and the values are ignored
- * in that case.
- */
__u32 tx_coalesce_usecs_irq;
__u32 tx_max_coalesced_frames_irq;
-
- /* How many usecs to delay in-memory statistics
- * block updates. Some drivers do not have an in-memory
- * statistic block, and in such cases this value is ignored.
- * This value must not be zero.
- */
__u32 stats_block_coalesce_usecs;
-
- /* Adaptive RX/TX coalescing is an algorithm implemented by
- * some drivers to improve latency under low packet rates and
- * improve throughput under high packet rates. Some drivers
- * only implement one of RX or TX adaptive coalescing. Anything
- * not implemented by the driver causes these values to be
- * silently ignored.
- */
__u32 use_adaptive_rx_coalesce;
__u32 use_adaptive_tx_coalesce;
-
- /* When the packet rate (measured in packets per second)
- * is below pkt_rate_low, the {rx,tx}_*_low parameters are
- * used.
- */
__u32 pkt_rate_low;
__u32 rx_coalesce_usecs_low;
__u32 rx_max_coalesced_frames_low;
__u32 tx_coalesce_usecs_low;
__u32 tx_max_coalesced_frames_low;
-
- /* When the packet rate is below pkt_rate_high but above
- * pkt_rate_low (both measured in packets per second) the
- * normal {rx,tx}_* coalescing parameters are used.
- */
-
- /* When the packet rate is (measured in packets per second)
- * is above pkt_rate_high, the {rx,tx}_*_high parameters are
- * used.
- */
__u32 pkt_rate_high;
__u32 rx_coalesce_usecs_high;
__u32 rx_max_coalesced_frames_high;
__u32 tx_coalesce_usecs_high;
__u32 tx_max_coalesced_frames_high;
-
- /* How often to do adaptive coalescing packet rate sampling,
- * measured in seconds. Must not be zero.
- */
__u32 rate_sample_interval;
};
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 2/5] ethtool: Specify what kind of coalescing struct ethtool_coalesce covers
From: Ben Hutchings @ 2011-08-16 0:07 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
include/linux/ethtool.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index be32dd0..71d45a1 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -118,7 +118,7 @@ struct ethtool_eeprom {
};
/**
- * struct ethtool_coalesce - coalescing parameters of chip
+ * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
* @cmd: ETHTOOL_{G,S}COALESCE
* @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
* a packet arrives. If 0, only @rx_max_coalesced_frames is used.
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 3/5] ethtool: Correct description of 'max_coalesced_frames' fields
From: Ben Hutchings @ 2011-08-16 0:07 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>
The current descriptions state that these fields specify 'How many
packets to delay ... after a packet ...' which implies that the
hardware should wait for (max_coalesced_frames + 1) completions before
generating an interrupt. It is also stated that setting both this
field and the corresponding 'coalesce_usecs' field to 0 is invalid.
Together, this implies that the hardware must always be configured
to delay a completion IRQ for at least 1 usec or 1 more completion.
I believe that the addition of 1 is not intended, and David Miller
confirms that the original implementation (in tg3) does not do this.
Clarify the descriptions of these fields to avoid this interpretation.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
include/linux/ethtool.h | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 71d45a1..18059ca 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -122,8 +122,8 @@ struct ethtool_eeprom {
* @cmd: ETHTOOL_{G,S}COALESCE
* @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
* a packet arrives. If 0, only @rx_max_coalesced_frames is used.
- * @rx_max_coalesced_frames: How many packets to delay an RX interrupt
- * after a packet arrives. If 0, only @rx_coalesce_usecs is used.
+ * @rx_max_coalesced_frames: Maximum number of packets to receive
+ * before an RX interrupt. If 0, only @rx_coalesce_usecs is used.
* @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
* this value applies while an IRQ is being serviced by the host.
* @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
@@ -132,9 +132,9 @@ struct ethtool_eeprom {
* @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
* a packet is sent. If 0, only @tx_max_coalesced_frames
* is used.
- * @tx_max_coalesced_frames: How many packets to delay a TX interrupt
- * after a packet is sent. If 0, only @tx_coalesce_usecs is
- * used.
+ * @tx_max_coalesced_frames: Maximum number of packets to be sent
+ * before a TX interrupt. If 0, only @tx_coalesce_usecs is
+ * used.
* @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
* this value applies while an IRQ is being serviced by the host.
* @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
@@ -149,21 +149,21 @@ struct ethtool_eeprom {
* @pkt_rate_low: Threshold for low packet rate (packets per second).
* @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after
* a packet arrives, when the packet rate is below @pkt_rate_low.
- * @rx_max_coalesced_frames_low: How many packets to delay an RX interrupt
- * after a packet arrives, when the packet rate is below @pkt_rate_low.
+ * @rx_max_coalesced_frames_low: Maximum number of packets to be received
+ * before an RX interrupt, when the packet rate is below @pkt_rate_low.
* @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after
* a packet is sent, when the packet rate is below @pkt_rate_low.
- * @tx_max_coalesced_frames_low: How many packets to delay a TX interrupt
- * after a packet is sent, when the packet rate is below @pkt_rate_low.
+ * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before
+ * a TX interrupt, when the packet rate is below @pkt_rate_low.
* @pkt_rate_high: Threshold for high packet rate (packets per second).
* @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after
* a packet arrives, when the packet rate is above @pkt_rate_high.
- * @rx_max_coalesced_frames_high: How many packets to delay an RX interrupt
- * after a packet arrives, when the packet rate is above @pkt_rate_high.
+ * @rx_max_coalesced_frames_high: Maximum number of packets to be received
+ * before an RX interrupt, when the packet rate is above @pkt_rate_high.
* @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after
* a packet is sent, when the packet rate is above @pkt_rate_high.
- * @tx_max_coalesced_frames_high: How many packets to delay a TX interrupt
- * after a packet is sent, when the packet rate is above @pkt_rate_high.
+ * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before
+ * a TX interrupt, when the packet rate is above @pkt_rate_high.
* @rate_sample_interval: How often to do adaptive coalescing packet rate
* sampling, measured in seconds. Must not be zero.
*
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 4/5] ethtool: Explicitly state the exit condition for interrupt coalescing
From: Ben Hutchings @ 2011-08-16 0:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>
Also explicitly state how to disable interrupt coalescing.
Remove the now-redundant text from field descriptions.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
include/linux/ethtool.h | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 18059ca..42378b3 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -121,20 +121,18 @@ struct ethtool_eeprom {
* struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
* @cmd: ETHTOOL_{G,S}COALESCE
* @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
- * a packet arrives. If 0, only @rx_max_coalesced_frames is used.
+ * a packet arrives.
* @rx_max_coalesced_frames: Maximum number of packets to receive
- * before an RX interrupt. If 0, only @rx_coalesce_usecs is used.
+ * before an RX interrupt.
* @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
* this value applies while an IRQ is being serviced by the host.
* @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
* except that this value applies while an IRQ is being serviced
* by the host.
* @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
- * a packet is sent. If 0, only @tx_max_coalesced_frames
- * is used.
+ * a packet is sent.
* @tx_max_coalesced_frames: Maximum number of packets to be sent
- * before a TX interrupt. If 0, only @tx_coalesce_usecs is
- * used.
+ * before a TX interrupt.
* @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
* this value applies while an IRQ is being serviced by the host.
* @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
@@ -167,8 +165,13 @@ struct ethtool_eeprom {
* @rate_sample_interval: How often to do adaptive coalescing packet rate
* sampling, measured in seconds. Must not be zero.
*
- * It is illegal to set both usecs and max frames to zero as this
- * would cause interrupts to never be generated.
+ * Each pair of (usecs, max_frames) fields specifies this exit
+ * condition for interrupt coalescing:
+ * (usecs > 0 && time_since_first_completion >= usecs) ||
+ * (max_frames > 0 && completed_frames >= max_frames)
+ * It is illegal to set both usecs and max_frames to zero as this
+ * would cause interrupts to never be generated. To disable
+ * coalescing, set usecs = 0 and max_frames = 1.
*
* Adaptive RX/TX coalescing is an algorithm implemented by some
* drivers to improve latency under low packet rates and improve
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 5/5] ethtool: Note common alternate exit condition for interrupt coalescing
From: Ben Hutchings @ 2011-08-16 0:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>
Many implementations ignore the value of max_frames and do not
treat usecs == 0 as special. Document this as deprecated.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
include/linux/ethtool.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 42378b3..3829712 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -173,6 +173,12 @@ struct ethtool_eeprom {
* would cause interrupts to never be generated. To disable
* coalescing, set usecs = 0 and max_frames = 1.
*
+ * Some implementations ignore the value of max_frames and use the
+ * condition:
+ * time_since_first_completion >= usecs
+ * This is deprecated. Drivers for hardware that does not support
+ * counting completions should validate that max_frames == !rx_usecs.
+ *
* Adaptive RX/TX coalescing is an algorithm implemented by some
* drivers to improve latency under low packet rates and improve
* throughput under high packet rates. Some drivers only implement
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-2.6 V2] bonding:reset backup and inactive flag of slave
From: Weiping Pan @ 2011-08-16 1:57 UTC (permalink / raw)
To: netdev; +Cc: Weiping Pan
In-Reply-To: <j2bgs2$pf5$1@dough.gmane.org>
Eduard Sinelnikov (eduard.sinelnikov@gmail.com) found that if we change
bonding mode from active backup to round robin, some slaves are still keeping
"backup", and won't transmit packets.
As Jay Vosburgh(fubar@us.ibm.com) pointed out that we can work around that by
removing the bond_is_active_slave() check, because the "backup" flag is only
meaningful for active backup mode.
But if we just simply ignore the bond_is_active_slave() check,
the transmission will work fine, but we can't maintain the correct value of
"backup" flag for each slaves, though it is meaningless for other mode than
active backup.
I'd like to reset "backup" and "inactive" flag in bond_open,
thus we can keep the correct value of them.
As for bond_is_active_slave(), I'd like to prepare another patch to handle it.
V2:
Use C style comment.
Move read_lock(&bond->curr_slave_lock).
Replace restore with reset, for active backup mode, it means "restore",
but for other modes, it means "reset".
Signed-off-by: Weiping Pan <panweiping3@gmail.com>
---
drivers/net/bonding/bond_main.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 38a83ac..43f2ea5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3419,9 +3419,27 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ int i;
bond->kill_timers = 0;
+ /* reset slave->backup and slave->inactive */
+ read_lock(&bond->lock);
+ if (bond->slave_cnt > 0) {
+ read_lock(&bond->curr_slave_lock);
+ bond_for_each_slave(bond, slave, i) {
+ if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ && (slave != bond->curr_active_slave)) {
+ bond_set_slave_inactive_flags(slave);
+ } else {
+ bond_set_slave_active_flags(slave);
+ }
+ }
+ read_unlock(&bond->curr_slave_lock);
+ }
+ read_unlock(&bond->lock);
+
INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
if (bond_is_lb(bond)) {
--
1.7.4.4
^ permalink raw reply related
* linux-next: build failure after merge of the net tree
From: Stephen Rothwell @ 2011-08-16 3:26 UTC (permalink / raw)
To: David Miller, netdev; +Cc: linux-next, linux-kernel
Hi all,
After merging the net tree, today's linux-next build (x86_64 allmodconfig)
failed like this:
drivers/net/ethernet/sun/sungem_phy.c:36:24: fatal error: sungem_phy.h: No such file or directory
Caused by commit 2bb698412d8a ("net: Move sungem_phy.h under
include/linux").
I applied this patch for today:
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 13:22:24 +1000
Subject: [PATCH] sungem: sungem_phy.h moved
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
drivers/net/ethernet/sun/sungem_phy.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/sun/sungem_phy.c b/drivers/net/ethernet/sun/sungem_phy.c
index d16880d..db99c22 100644
--- a/drivers/net/ethernet/sun/sungem_phy.c
+++ b/drivers/net/ethernet/sun/sungem_phy.c
@@ -33,7 +33,7 @@
#include <asm/prom.h>
#endif
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
/* Link modes of the BCM5400 PHY */
static const int phy_BCM5400_link_table[8][3] = {
--
1.7.5.4
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
^ permalink raw reply related
* Re: linux-next: build failure after merge of the net tree
From: David Miller @ 2011-08-16 4:03 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-next, linux-kernel
In-Reply-To: <20110816132659.7719837bd136aa520c5814ac@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 13:26:59 +1000
> I applied this patch for today:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 16 Aug 2011 13:22:24 +1000
> Subject: [PATCH] sungem: sungem_phy.h moved
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Sigh, applied, sorry about this.
^ permalink raw reply
* Re: linux-next: build failure after merge of the final tree (net tree related)
From: Stephen Rothwell @ 2011-08-16 5:28 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110814.225610.2264854100578866902.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 467 bytes --]
Hi Dave,
On Sun, 14 Aug 2011 22:56:10 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>
> This should fix the include problem, but I suspect this thing won't
> link.
Yep, indeed, today I get:
make[5]: *** No rule to make target `drivers/net/ethernet/toshiba/ethernet/sun/sungem_phy.o', needed by `drivers/net/ethernet/toshiba/built-in.o'.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: linux-next: build failure after merge of the final tree (net tree related)
From: David Miller @ 2011-08-16 6:11 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110816152815.911f15937efa2ebf58a2795d@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 15:28:15 +1000
> Hi Dave,
>
> On Sun, 14 Aug 2011 22:56:10 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>>
>> This should fix the include problem, but I suspect this thing won't
>> link.
>
> Yep, indeed, today I get:
>
> make[5]: *** No rule to make target `drivers/net/ethernet/toshiba/ethernet/sun/sungem_phy.o', needed by `drivers/net/ethernet/toshiba/built-in.o'.
Please test this patch:
--------------------
net: Fix sungem_phy sharing.
Since sungem_phy is used by multiple, unrelated, drivers make it
build as a real module under drivers/net.
depmod will pick up the symbol dependency and make sure sungem_phy.ko
gets loaded any time sungem.ko or spider_net.ko is loaded.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/Kconfig | 3 +
drivers/net/Makefile | 2 +
drivers/net/ethernet/sun/Makefile | 1 -
drivers/net/ethernet/sun/sungem.c | 2 +-
drivers/net/ethernet/sun/sungem_phy.c | 1200 -----------------------------
drivers/net/ethernet/toshiba/Makefile | 2 +-
drivers/net/ethernet/toshiba/spider_net.c | 4 +-
drivers/net/sungem_phy.c | 1199 ++++++++++++++++++++++++++++
include/linux/sungem_phy.h | 2 +-
9 files changed, 1209 insertions(+), 1206 deletions(-)
delete mode 100644 drivers/net/ethernet/sun/sungem_phy.c
create mode 100644 drivers/net/sungem_phy.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 31d8792..ef6b6be 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -186,6 +186,9 @@ config MII
source "drivers/net/phy/Kconfig"
+config SUNGEM_PHY
+ tristate
+
#
# Ethernet
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 9cb47bb..c33009b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -75,3 +75,5 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_WIMAX) += wimax/
obj-$(CONFIG_CAIF) += caif/
+
+obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
diff --git a/drivers/net/ethernet/sun/Makefile b/drivers/net/ethernet/sun/Makefile
index 6e25dad..1e620ff 100644
--- a/drivers/net/ethernet/sun/Makefile
+++ b/drivers/net/ethernet/sun/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
obj-$(CONFIG_SUNQE) += sunqe.o
obj-$(CONFIG_SUNBMAC) += sunbmac.o
obj-$(CONFIG_SUNGEM) += sungem.o
-obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
obj-$(CONFIG_CASSINI) += cassini.o
obj-$(CONFIG_SUNVNET) += sunvnet.o
obj-$(CONFIG_NIU) += niu.o
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 0f13c5d..fb9885d 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -1721,7 +1721,7 @@ static void gem_init_phy(struct gem *gp)
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
/* Reset and detect MII PHY */
- mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
+ sungem_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
/* Init PHY */
if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
diff --git a/drivers/net/ethernet/sun/sungem_phy.c b/drivers/net/ethernet/sun/sungem_phy.c
deleted file mode 100644
index db99c22..0000000
--- a/drivers/net/ethernet/sun/sungem_phy.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-/*
- * PHY drivers for the sungem ethernet driver.
- *
- * This file could be shared with other drivers.
- *
- * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
- *
- * TODO:
- * - Add support for PHYs that provide an IRQ line
- * - Eventually moved the entire polling state machine in
- * there (out of the eth driver), so that it can easily be
- * skipped on PHYs that implement it in hardware.
- * - On LXT971 & BCM5201, Apple uses some chip specific regs
- * to read the link status. Figure out why and if it makes
- * sense to do the same (magic aneg ?)
- * - Apple has some additional power management code for some
- * Broadcom PHYs that they "hide" from the OpenSource version
- * of darwin, still need to reverse engineer that
- */
-
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/prom.h>
-#endif
-
-#include <linux/sungem_phy.h>
-
-/* Link modes of the BCM5400 PHY */
-static const int phy_BCM5400_link_table[8][3] = {
- { 0, 0, 0 }, /* No link */
- { 0, 0, 0 }, /* 10BT Half Duplex */
- { 1, 0, 0 }, /* 10BT Full Duplex */
- { 0, 1, 0 }, /* 100BT Half Duplex */
- { 0, 1, 0 }, /* 100BT Half Duplex */
- { 1, 1, 0 }, /* 100BT Full Duplex*/
- { 1, 0, 1 }, /* 1000BT */
- { 1, 0, 1 }, /* 1000BT */
-};
-
-static inline int __phy_read(struct mii_phy* phy, int id, int reg)
-{
- return phy->mdio_read(phy->dev, id, reg);
-}
-
-static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
-{
- phy->mdio_write(phy->dev, id, reg, val);
-}
-
-static inline int phy_read(struct mii_phy* phy, int reg)
-{
- return phy->mdio_read(phy->dev, phy->mii_id, reg);
-}
-
-static inline void phy_write(struct mii_phy* phy, int reg, int val)
-{
- phy->mdio_write(phy->dev, phy->mii_id, reg, val);
-}
-
-static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
-{
- u16 val;
- int limit = 10000;
-
- val = __phy_read(phy, phy_id, MII_BMCR);
- val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
- val |= BMCR_RESET;
- __phy_write(phy, phy_id, MII_BMCR, val);
-
- udelay(100);
-
- while (--limit) {
- val = __phy_read(phy, phy_id, MII_BMCR);
- if ((val & BMCR_RESET) == 0)
- break;
- udelay(10);
- }
- if ((val & BMCR_ISOLATE) && limit > 0)
- __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
-
- return limit <= 0;
-}
-
-static int bcm5201_init(struct mii_phy* phy)
-{
- u16 data;
-
- data = phy_read(phy, MII_BCM5201_MULTIPHY);
- data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
- phy_write(phy, MII_BCM5201_MULTIPHY, data);
-
- phy_write(phy, MII_BCM5201_INTERRUPT, 0);
-
- return 0;
-}
-
-static int bcm5201_suspend(struct mii_phy* phy)
-{
- phy_write(phy, MII_BCM5201_INTERRUPT, 0);
- phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
-
- return 0;
-}
-
-static int bcm5221_init(struct mii_phy* phy)
-{
- u16 data;
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
- data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
- data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- return 0;
-}
-
-static int bcm5221_suspend(struct mii_phy* phy)
-{
- u16 data;
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
- data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
-
- return 0;
-}
-
-static int bcm5241_init(struct mii_phy* phy)
-{
- u16 data;
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
- data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
- data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- return 0;
-}
-
-static int bcm5241_suspend(struct mii_phy* phy)
-{
- u16 data;
-
- data = phy_read(phy, MII_BCM5221_TEST);
- phy_write(phy, MII_BCM5221_TEST,
- data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
- data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
- phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
- data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
-
- return 0;
-}
-
-static int bcm5400_init(struct mii_phy* phy)
-{
- u16 data;
-
- /* Configure for gigabit full duplex */
- data = phy_read(phy, MII_BCM5400_AUXCONTROL);
- data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
- phy_write(phy, MII_BCM5400_AUXCONTROL, data);
-
- data = phy_read(phy, MII_BCM5400_GB_CONTROL);
- data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
- phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
- udelay(100);
-
- /* Reset and configure cascaded 10/100 PHY */
- (void)reset_one_mii_phy(phy, 0x1f);
-
- data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
- data |= MII_BCM5201_MULTIPHY_SERIALMODE;
- __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
-
- data = phy_read(phy, MII_BCM5400_AUXCONTROL);
- data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
- phy_write(phy, MII_BCM5400_AUXCONTROL, data);
-
- return 0;
-}
-
-static int bcm5400_suspend(struct mii_phy* phy)
-{
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
- phy_write(phy, MII_BMCR, BMCR_PDOWN);
-#endif
- return 0;
-}
-
-static int bcm5401_init(struct mii_phy* phy)
-{
- u16 data;
- int rev;
-
- rev = phy_read(phy, MII_PHYSID2) & 0x000f;
- if (rev == 0 || rev == 3) {
- /* Some revisions of 5401 appear to need this
- * initialisation sequence to disable, according
- * to OF, "tap power management"
- *
- * WARNING ! OF and Darwin don't agree on the
- * register addresses. OF seem to interpret the
- * register numbers below as decimal
- *
- * Note: This should (and does) match tg3_init_5401phy_dsp
- * in the tg3.c driver. -DaveM
- */
- phy_write(phy, 0x18, 0x0c20);
- phy_write(phy, 0x17, 0x0012);
- phy_write(phy, 0x15, 0x1804);
- phy_write(phy, 0x17, 0x0013);
- phy_write(phy, 0x15, 0x1204);
- phy_write(phy, 0x17, 0x8006);
- phy_write(phy, 0x15, 0x0132);
- phy_write(phy, 0x17, 0x8006);
- phy_write(phy, 0x15, 0x0232);
- phy_write(phy, 0x17, 0x201f);
- phy_write(phy, 0x15, 0x0a20);
- }
-
- /* Configure for gigabit full duplex */
- data = phy_read(phy, MII_BCM5400_GB_CONTROL);
- data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
- phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
- udelay(10);
-
- /* Reset and configure cascaded 10/100 PHY */
- (void)reset_one_mii_phy(phy, 0x1f);
-
- data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
- data |= MII_BCM5201_MULTIPHY_SERIALMODE;
- __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
-
- return 0;
-}
-
-static int bcm5401_suspend(struct mii_phy* phy)
-{
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
- phy_write(phy, MII_BMCR, BMCR_PDOWN);
-#endif
- return 0;
-}
-
-static int bcm5411_init(struct mii_phy* phy)
-{
- u16 data;
-
- /* Here's some more Apple black magic to setup
- * some voltage stuffs.
- */
- phy_write(phy, 0x1c, 0x8c23);
- phy_write(phy, 0x1c, 0x8ca3);
- phy_write(phy, 0x1c, 0x8c23);
-
- /* Here, Apple seems to want to reset it, do
- * it as well
- */
- phy_write(phy, MII_BMCR, BMCR_RESET);
- phy_write(phy, MII_BMCR, 0x1340);
-
- data = phy_read(phy, MII_BCM5400_GB_CONTROL);
- data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
- phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
- udelay(10);
-
- /* Reset and configure cascaded 10/100 PHY */
- (void)reset_one_mii_phy(phy, 0x1f);
-
- return 0;
-}
-
-static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
- u16 ctl, adv;
-
- phy->autoneg = 1;
- phy->speed = SPEED_10;
- phy->duplex = DUPLEX_HALF;
- phy->pause = 0;
- phy->advertising = advertise;
-
- /* Setup standard advertise */
- adv = phy_read(phy, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- phy_write(phy, MII_ADVERTISE, adv);
-
- /* Start/Restart aneg */
- ctl = phy_read(phy, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
- u16 ctl;
-
- phy->autoneg = 0;
- phy->speed = speed;
- phy->duplex = fd;
- phy->pause = 0;
-
- ctl = phy_read(phy, MII_BMCR);
- ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
-
- /* First reset the PHY */
- phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
- /* Select speed & duplex */
- switch(speed) {
- case SPEED_10:
- break;
- case SPEED_100:
- ctl |= BMCR_SPEED100;
- break;
- case SPEED_1000:
- default:
- return -EINVAL;
- }
- if (fd == DUPLEX_FULL)
- ctl |= BMCR_FULLDPLX;
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int genmii_poll_link(struct mii_phy *phy)
-{
- u16 status;
-
- (void)phy_read(phy, MII_BMSR);
- status = phy_read(phy, MII_BMSR);
- if ((status & BMSR_LSTATUS) == 0)
- return 0;
- if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
- return 0;
- return 1;
-}
-
-static int genmii_read_link(struct mii_phy *phy)
-{
- u16 lpa;
-
- if (phy->autoneg) {
- lpa = phy_read(phy, MII_LPA);
-
- if (lpa & (LPA_10FULL | LPA_100FULL))
- phy->duplex = DUPLEX_FULL;
- else
- phy->duplex = DUPLEX_HALF;
- if (lpa & (LPA_100FULL | LPA_100HALF))
- phy->speed = SPEED_100;
- else
- phy->speed = SPEED_10;
- phy->pause = 0;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-
-static int generic_suspend(struct mii_phy* phy)
-{
- phy_write(phy, MII_BMCR, BMCR_PDOWN);
-
- return 0;
-}
-
-static int bcm5421_init(struct mii_phy* phy)
-{
- u16 data;
- unsigned int id;
-
- id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
-
- /* Revision 0 of 5421 needs some fixups */
- if (id == 0x002060e0) {
- /* This is borrowed from MacOS
- */
- phy_write(phy, 0x18, 0x1007);
- data = phy_read(phy, 0x18);
- phy_write(phy, 0x18, data | 0x0400);
- phy_write(phy, 0x18, 0x0007);
- data = phy_read(phy, 0x18);
- phy_write(phy, 0x18, data | 0x0800);
- phy_write(phy, 0x17, 0x000a);
- data = phy_read(phy, 0x15);
- phy_write(phy, 0x15, data | 0x0200);
- }
-
- /* Pick up some init code from OF for K2 version */
- if ((id & 0xfffffff0) == 0x002062e0) {
- phy_write(phy, 4, 0x01e1);
- phy_write(phy, 9, 0x0300);
- }
-
- /* Check if we can enable automatic low power */
-#ifdef CONFIG_PPC_PMAC
- if (phy->platform_data) {
- struct device_node *np = of_get_parent(phy->platform_data);
- int can_low_power = 1;
- if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
- can_low_power = 0;
- if (can_low_power) {
- /* Enable automatic low-power */
- phy_write(phy, 0x1c, 0x9002);
- phy_write(phy, 0x1c, 0xa821);
- phy_write(phy, 0x1c, 0x941d);
- }
- }
-#endif /* CONFIG_PPC_PMAC */
-
- return 0;
-}
-
-static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
- u16 ctl, adv;
-
- phy->autoneg = 1;
- phy->speed = SPEED_10;
- phy->duplex = DUPLEX_HALF;
- phy->pause = 0;
- phy->advertising = advertise;
-
- /* Setup standard advertise */
- adv = phy_read(phy, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- if (advertise & ADVERTISED_Pause)
- adv |= ADVERTISE_PAUSE_CAP;
- if (advertise & ADVERTISED_Asym_Pause)
- adv |= ADVERTISE_PAUSE_ASYM;
- phy_write(phy, MII_ADVERTISE, adv);
-
- /* Setup 1000BT advertise */
- adv = phy_read(phy, MII_1000BASETCONTROL);
- adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (advertise & SUPPORTED_1000baseT_Half)
- adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
- if (advertise & SUPPORTED_1000baseT_Full)
- adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(phy, MII_1000BASETCONTROL, adv);
-
- /* Start/Restart aneg */
- ctl = phy_read(phy, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
- u16 ctl;
-
- phy->autoneg = 0;
- phy->speed = speed;
- phy->duplex = fd;
- phy->pause = 0;
-
- ctl = phy_read(phy, MII_BMCR);
- ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
-
- /* First reset the PHY */
- phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
- /* Select speed & duplex */
- switch(speed) {
- case SPEED_10:
- break;
- case SPEED_100:
- ctl |= BMCR_SPEED100;
- break;
- case SPEED_1000:
- ctl |= BMCR_SPD2;
- }
- if (fd == DUPLEX_FULL)
- ctl |= BMCR_FULLDPLX;
-
- // XXX Should we set the sungem to GII now on 1000BT ?
-
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int bcm54xx_read_link(struct mii_phy *phy)
-{
- int link_mode;
- u16 val;
-
- if (phy->autoneg) {
- val = phy_read(phy, MII_BCM5400_AUXSTATUS);
- link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
- MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
- phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
- DUPLEX_FULL : DUPLEX_HALF;
- phy->speed = phy_BCM5400_link_table[link_mode][2] ?
- SPEED_1000 :
- (phy_BCM5400_link_table[link_mode][1] ?
- SPEED_100 : SPEED_10);
- val = phy_read(phy, MII_LPA);
- phy->pause = (phy->duplex == DUPLEX_FULL) &&
- ((val & LPA_PAUSE) != 0);
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-
-static int marvell88e1111_init(struct mii_phy* phy)
-{
- u16 rev;
-
- /* magic init sequence for rev 0 */
- rev = phy_read(phy, MII_PHYSID2) & 0x000f;
- if (rev == 0) {
- phy_write(phy, 0x1d, 0x000a);
- phy_write(phy, 0x1e, 0x0821);
-
- phy_write(phy, 0x1d, 0x0006);
- phy_write(phy, 0x1e, 0x8600);
-
- phy_write(phy, 0x1d, 0x000b);
- phy_write(phy, 0x1e, 0x0100);
-
- phy_write(phy, 0x1d, 0x0004);
- phy_write(phy, 0x1e, 0x4850);
- }
- return 0;
-}
-
-#define BCM5421_MODE_MASK (1 << 5)
-
-static int bcm5421_poll_link(struct mii_phy* phy)
-{
- u32 phy_reg;
- int mode;
-
- /* find out in what mode we are */
- phy_write(phy, MII_NCONFIG, 0x1000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
-
- if ( mode == BCM54XX_COPPER)
- return genmii_poll_link(phy);
-
- /* try to find out wether we have a link */
- phy_write(phy, MII_NCONFIG, 0x2000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- if (phy_reg & 0x0020)
- return 0;
- else
- return 1;
-}
-
-static int bcm5421_read_link(struct mii_phy* phy)
-{
- u32 phy_reg;
- int mode;
-
- /* find out in what mode we are */
- phy_write(phy, MII_NCONFIG, 0x1000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
-
- if ( mode == BCM54XX_COPPER)
- return bcm54xx_read_link(phy);
-
- phy->speed = SPEED_1000;
-
- /* find out wether we are running half- or full duplex */
- phy_write(phy, MII_NCONFIG, 0x2000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- if ( (phy_reg & 0x0080) >> 7)
- phy->duplex |= DUPLEX_HALF;
- else
- phy->duplex |= DUPLEX_FULL;
-
- return 0;
-}
-
-static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
-{
- /* enable fiber mode */
- phy_write(phy, MII_NCONFIG, 0x9020);
- /* LEDs active in both modes, autosense prio = fiber */
- phy_write(phy, MII_NCONFIG, 0x945f);
-
- if (!autoneg) {
- /* switch off fibre autoneg */
- phy_write(phy, MII_NCONFIG, 0xfc01);
- phy_write(phy, 0x0b, 0x0004);
- }
-
- phy->autoneg = autoneg;
-
- return 0;
-}
-
-#define BCM5461_FIBER_LINK (1 << 2)
-#define BCM5461_MODE_MASK (3 << 1)
-
-static int bcm5461_poll_link(struct mii_phy* phy)
-{
- u32 phy_reg;
- int mode;
-
- /* find out in what mode we are */
- phy_write(phy, MII_NCONFIG, 0x7c00);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
-
- if ( mode == BCM54XX_COPPER)
- return genmii_poll_link(phy);
-
- /* find out wether we have a link */
- phy_write(phy, MII_NCONFIG, 0x7000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- if (phy_reg & BCM5461_FIBER_LINK)
- return 1;
- else
- return 0;
-}
-
-#define BCM5461_FIBER_DUPLEX (1 << 3)
-
-static int bcm5461_read_link(struct mii_phy* phy)
-{
- u32 phy_reg;
- int mode;
-
- /* find out in what mode we are */
- phy_write(phy, MII_NCONFIG, 0x7c00);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
-
- if ( mode == BCM54XX_COPPER) {
- return bcm54xx_read_link(phy);
- }
-
- phy->speed = SPEED_1000;
-
- /* find out wether we are running half- or full duplex */
- phy_write(phy, MII_NCONFIG, 0x7000);
- phy_reg = phy_read(phy, MII_NCONFIG);
-
- if (phy_reg & BCM5461_FIBER_DUPLEX)
- phy->duplex |= DUPLEX_FULL;
- else
- phy->duplex |= DUPLEX_HALF;
-
- return 0;
-}
-
-static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
-{
- /* select fiber mode, enable 1000 base-X registers */
- phy_write(phy, MII_NCONFIG, 0xfc0b);
-
- if (autoneg) {
- /* enable fiber with no autonegotiation */
- phy_write(phy, MII_ADVERTISE, 0x01e0);
- phy_write(phy, MII_BMCR, 0x1140);
- } else {
- /* enable fiber with autonegotiation */
- phy_write(phy, MII_BMCR, 0x0140);
- }
-
- phy->autoneg = autoneg;
-
- return 0;
-}
-
-static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
- u16 ctl, adv;
-
- phy->autoneg = 1;
- phy->speed = SPEED_10;
- phy->duplex = DUPLEX_HALF;
- phy->pause = 0;
- phy->advertising = advertise;
-
- /* Setup standard advertise */
- adv = phy_read(phy, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- if (advertise & ADVERTISED_Pause)
- adv |= ADVERTISE_PAUSE_CAP;
- if (advertise & ADVERTISED_Asym_Pause)
- adv |= ADVERTISE_PAUSE_ASYM;
- phy_write(phy, MII_ADVERTISE, adv);
-
- /* Setup 1000BT advertise & enable crossover detect
- * XXX How do we advertise 1000BT ? Darwin source is
- * confusing here, they read from specific control and
- * write to control... Someone has specs for those
- * beasts ?
- */
- adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
- adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
- adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
- MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (advertise & SUPPORTED_1000baseT_Half)
- adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
- if (advertise & SUPPORTED_1000baseT_Full)
- adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(phy, MII_1000BASETCONTROL, adv);
-
- /* Start/Restart aneg */
- ctl = phy_read(phy, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
- u16 ctl, ctl2;
-
- phy->autoneg = 0;
- phy->speed = speed;
- phy->duplex = fd;
- phy->pause = 0;
-
- ctl = phy_read(phy, MII_BMCR);
- ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
- ctl |= BMCR_RESET;
-
- /* Select speed & duplex */
- switch(speed) {
- case SPEED_10:
- break;
- case SPEED_100:
- ctl |= BMCR_SPEED100;
- break;
- /* I'm not sure about the one below, again, Darwin source is
- * quite confusing and I lack chip specs
- */
- case SPEED_1000:
- ctl |= BMCR_SPD2;
- }
- if (fd == DUPLEX_FULL)
- ctl |= BMCR_FULLDPLX;
-
- /* Disable crossover. Again, the way Apple does it is strange,
- * though I don't assume they are wrong ;)
- */
- ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
- ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
- MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
- MII_1000BASETCONTROL_FULLDUPLEXCAP |
- MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (speed == SPEED_1000)
- ctl2 |= (fd == DUPLEX_FULL) ?
- MII_1000BASETCONTROL_FULLDUPLEXCAP :
- MII_1000BASETCONTROL_HALFDUPLEXCAP;
- phy_write(phy, MII_1000BASETCONTROL, ctl2);
-
- // XXX Should we set the sungem to GII now on 1000BT ?
-
- phy_write(phy, MII_BMCR, ctl);
-
- return 0;
-}
-
-static int marvell_read_link(struct mii_phy *phy)
-{
- u16 status, pmask;
-
- if (phy->autoneg) {
- status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
- if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
- return -EAGAIN;
- if (status & MII_M1011_PHY_SPEC_STATUS_1000)
- phy->speed = SPEED_1000;
- else if (status & MII_M1011_PHY_SPEC_STATUS_100)
- phy->speed = SPEED_100;
- else
- phy->speed = SPEED_10;
- if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
- phy->duplex = DUPLEX_FULL;
- else
- phy->duplex = DUPLEX_HALF;
- pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
- MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
- phy->pause = (status & pmask) == pmask;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-
-#define MII_BASIC_FEATURES \
- (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | \
- SUPPORTED_Pause)
-
-/* On gigabit capable PHYs, we advertise Pause support but not asym pause
- * support for now as I'm not sure it's supported and Darwin doesn't do
- * it neither. --BenH.
- */
-#define MII_GBIT_FEATURES \
- (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
-
-/* Broadcom BCM 5201 */
-static struct mii_phy_ops bcm5201_phy_ops = {
- .init = bcm5201_init,
- .suspend = bcm5201_suspend,
- .setup_aneg = genmii_setup_aneg,
- .setup_forced = genmii_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = genmii_read_link,
-};
-
-static struct mii_phy_def bcm5201_phy_def = {
- .phy_id = 0x00406210,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5201",
- .features = MII_BASIC_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5201_phy_ops
-};
-
-/* Broadcom BCM 5221 */
-static struct mii_phy_ops bcm5221_phy_ops = {
- .suspend = bcm5221_suspend,
- .init = bcm5221_init,
- .setup_aneg = genmii_setup_aneg,
- .setup_forced = genmii_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = genmii_read_link,
-};
-
-static struct mii_phy_def bcm5221_phy_def = {
- .phy_id = 0x004061e0,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5221",
- .features = MII_BASIC_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5221_phy_ops
-};
-
-/* Broadcom BCM 5241 */
-static struct mii_phy_ops bcm5241_phy_ops = {
- .suspend = bcm5241_suspend,
- .init = bcm5241_init,
- .setup_aneg = genmii_setup_aneg,
- .setup_forced = genmii_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = genmii_read_link,
-};
-static struct mii_phy_def bcm5241_phy_def = {
- .phy_id = 0x0143bc30,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5241",
- .features = MII_BASIC_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5241_phy_ops
-};
-
-/* Broadcom BCM 5400 */
-static struct mii_phy_ops bcm5400_phy_ops = {
- .init = bcm5400_init,
- .suspend = bcm5400_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5400_phy_def = {
- .phy_id = 0x00206040,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5400",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5400_phy_ops
-};
-
-/* Broadcom BCM 5401 */
-static struct mii_phy_ops bcm5401_phy_ops = {
- .init = bcm5401_init,
- .suspend = bcm5401_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5401_phy_def = {
- .phy_id = 0x00206050,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5401",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5401_phy_ops
-};
-
-/* Broadcom BCM 5411 */
-static struct mii_phy_ops bcm5411_phy_ops = {
- .init = bcm5411_init,
- .suspend = generic_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5411_phy_def = {
- .phy_id = 0x00206070,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5411",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5411_phy_ops
-};
-
-/* Broadcom BCM 5421 */
-static struct mii_phy_ops bcm5421_phy_ops = {
- .init = bcm5421_init,
- .suspend = generic_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = bcm5421_poll_link,
- .read_link = bcm5421_read_link,
- .enable_fiber = bcm5421_enable_fiber,
-};
-
-static struct mii_phy_def bcm5421_phy_def = {
- .phy_id = 0x002060e0,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5421",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5421_phy_ops
-};
-
-/* Broadcom BCM 5421 built-in K2 */
-static struct mii_phy_ops bcm5421k2_phy_ops = {
- .init = bcm5421_init,
- .suspend = generic_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5421k2_phy_def = {
- .phy_id = 0x002062e0,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5421-K2",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5421k2_phy_ops
-};
-
-static struct mii_phy_ops bcm5461_phy_ops = {
- .init = bcm5421_init,
- .suspend = generic_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = bcm5461_poll_link,
- .read_link = bcm5461_read_link,
- .enable_fiber = bcm5461_enable_fiber,
-};
-
-static struct mii_phy_def bcm5461_phy_def = {
- .phy_id = 0x002060c0,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5461",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5461_phy_ops
-};
-
-/* Broadcom BCM 5462 built-in Vesta */
-static struct mii_phy_ops bcm5462V_phy_ops = {
- .init = bcm5421_init,
- .suspend = generic_suspend,
- .setup_aneg = bcm54xx_setup_aneg,
- .setup_forced = bcm54xx_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5462V_phy_def = {
- .phy_id = 0x002060d0,
- .phy_id_mask = 0xfffffff0,
- .name = "BCM5462-Vesta",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &bcm5462V_phy_ops
-};
-
-/* Marvell 88E1101 amd 88E1111 */
-static struct mii_phy_ops marvell88e1101_phy_ops = {
- .suspend = generic_suspend,
- .setup_aneg = marvell_setup_aneg,
- .setup_forced = marvell_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = marvell_read_link
-};
-
-static struct mii_phy_ops marvell88e1111_phy_ops = {
- .init = marvell88e1111_init,
- .suspend = generic_suspend,
- .setup_aneg = marvell_setup_aneg,
- .setup_forced = marvell_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = marvell_read_link
-};
-
-/* two revs in darwin for the 88e1101 ... I could use a datasheet
- * to get the proper names...
- */
-static struct mii_phy_def marvell88e1101v1_phy_def = {
- .phy_id = 0x01410c20,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1101v1",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &marvell88e1101_phy_ops
-};
-static struct mii_phy_def marvell88e1101v2_phy_def = {
- .phy_id = 0x01410c60,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1101v2",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &marvell88e1101_phy_ops
-};
-static struct mii_phy_def marvell88e1111_phy_def = {
- .phy_id = 0x01410cc0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1111",
- .features = MII_GBIT_FEATURES,
- .magic_aneg = 1,
- .ops = &marvell88e1111_phy_ops
-};
-
-/* Generic implementation for most 10/100 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
- .setup_aneg = genmii_setup_aneg,
- .setup_forced = genmii_setup_forced,
- .poll_link = genmii_poll_link,
- .read_link = genmii_read_link
-};
-
-static struct mii_phy_def genmii_phy_def = {
- .phy_id = 0x00000000,
- .phy_id_mask = 0x00000000,
- .name = "Generic MII",
- .features = MII_BASIC_FEATURES,
- .magic_aneg = 0,
- .ops = &generic_phy_ops
-};
-
-static struct mii_phy_def* mii_phy_table[] = {
- &bcm5201_phy_def,
- &bcm5221_phy_def,
- &bcm5241_phy_def,
- &bcm5400_phy_def,
- &bcm5401_phy_def,
- &bcm5411_phy_def,
- &bcm5421_phy_def,
- &bcm5421k2_phy_def,
- &bcm5461_phy_def,
- &bcm5462V_phy_def,
- &marvell88e1101v1_phy_def,
- &marvell88e1101v2_phy_def,
- &marvell88e1111_phy_def,
- &genmii_phy_def,
- NULL
-};
-
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
-{
- int rc;
- u32 id;
- struct mii_phy_def* def;
- int i;
-
- /* We do not reset the mii_phy structure as the driver
- * may re-probe the PHY regulary
- */
- phy->mii_id = mii_id;
-
- /* Take PHY out of isloate mode and reset it. */
- rc = reset_one_mii_phy(phy, mii_id);
- if (rc)
- goto fail;
-
- /* Read ID and find matching entry */
- id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
- printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
- id, mii_id);
- for (i=0; (def = mii_phy_table[i]) != NULL; i++)
- if ((id & def->phy_id_mask) == def->phy_id)
- break;
- /* Should never be NULL (we have a generic entry), but... */
- if (def == NULL)
- goto fail;
-
- phy->def = def;
-
- return 0;
-fail:
- phy->speed = 0;
- phy->duplex = 0;
- phy->pause = 0;
- phy->advertising = 0;
- return -ENODEV;
-}
-
-EXPORT_SYMBOL(mii_phy_probe);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/ethernet/toshiba/Makefile b/drivers/net/ethernet/toshiba/Makefile
index 71d861f..a506900 100644
--- a/drivers/net/ethernet/toshiba/Makefile
+++ b/drivers/net/ethernet/toshiba/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
spidernet-y += spider_net.o spider_net_ethtool.o
-obj-$(CONFIG_SPIDER_NET) += spidernet.o ethernet/sun/sungem_phy.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
obj-$(CONFIG_TC35815) += tc35815.o
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 1ff3491c..af345db 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -196,7 +196,7 @@ spider_net_setup_aneg(struct spider_net_card *card)
if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
advertise |= SUPPORTED_1000baseT_Half;
- mii_phy_probe(phy, phy->mii_id);
+ sungem_phy_probe(phy, phy->mii_id);
phy->def->ops->setup_aneg(phy, advertise);
}
@@ -2120,7 +2120,7 @@ spider_net_setup_phy(struct spider_net_card *card)
unsigned short id;
id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
if (id != 0x0000 && id != 0xffff) {
- if (!mii_phy_probe(phy, phy->mii_id)) {
+ if (!sungem_phy_probe(phy, phy->mii_id)) {
pr_info("Found %s.\n", phy->def->name);
break;
}
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
new file mode 100644
index 0000000..58f13ad
--- /dev/null
+++ b/drivers/net/sungem_phy.c
@@ -0,0 +1,1199 @@
+/*
+ * PHY drivers for the sungem ethernet driver.
+ *
+ * This file could be shared with other drivers.
+ *
+ * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ *
+ * TODO:
+ * - Add support for PHYs that provide an IRQ line
+ * - Eventually moved the entire polling state machine in
+ * there (out of the eth driver), so that it can easily be
+ * skipped on PHYs that implement it in hardware.
+ * - On LXT971 & BCM5201, Apple uses some chip specific regs
+ * to read the link status. Figure out why and if it makes
+ * sense to do the same (magic aneg ?)
+ * - Apple has some additional power management code for some
+ * Broadcom PHYs that they "hide" from the OpenSource version
+ * of darwin, still need to reverse engineer that
+ */
+
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/prom.h>
+#endif
+
+#include <linux/sungem_phy.h>
+
+/* Link modes of the BCM5400 PHY */
+static const int phy_BCM5400_link_table[8][3] = {
+ { 0, 0, 0 }, /* No link */
+ { 0, 0, 0 }, /* 10BT Half Duplex */
+ { 1, 0, 0 }, /* 10BT Full Duplex */
+ { 0, 1, 0 }, /* 100BT Half Duplex */
+ { 0, 1, 0 }, /* 100BT Half Duplex */
+ { 1, 1, 0 }, /* 100BT Full Duplex*/
+ { 1, 0, 1 }, /* 1000BT */
+ { 1, 0, 1 }, /* 1000BT */
+};
+
+static inline int __phy_read(struct mii_phy* phy, int id, int reg)
+{
+ return phy->mdio_read(phy->dev, id, reg);
+}
+
+static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
+{
+ phy->mdio_write(phy->dev, id, reg, val);
+}
+
+static inline int phy_read(struct mii_phy* phy, int reg)
+{
+ return phy->mdio_read(phy->dev, phy->mii_id, reg);
+}
+
+static inline void phy_write(struct mii_phy* phy, int reg, int val)
+{
+ phy->mdio_write(phy->dev, phy->mii_id, reg, val);
+}
+
+static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
+{
+ u16 val;
+ int limit = 10000;
+
+ val = __phy_read(phy, phy_id, MII_BMCR);
+ val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
+ val |= BMCR_RESET;
+ __phy_write(phy, phy_id, MII_BMCR, val);
+
+ udelay(100);
+
+ while (--limit) {
+ val = __phy_read(phy, phy_id, MII_BMCR);
+ if ((val & BMCR_RESET) == 0)
+ break;
+ udelay(10);
+ }
+ if ((val & BMCR_ISOLATE) && limit > 0)
+ __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
+
+ return limit <= 0;
+}
+
+static int bcm5201_init(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5201_MULTIPHY);
+ data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
+ phy_write(phy, MII_BCM5201_MULTIPHY, data);
+
+ phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+
+ return 0;
+}
+
+static int bcm5201_suspend(struct mii_phy* phy)
+{
+ phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+ phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
+
+ return 0;
+}
+
+static int bcm5221_init(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+ data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ return 0;
+}
+
+static int bcm5221_suspend(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
+
+ return 0;
+}
+
+static int bcm5241_init(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+ data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ return 0;
+}
+
+static int bcm5241_suspend(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+ return 0;
+}
+
+static int bcm5400_init(struct mii_phy* phy)
+{
+ u16 data;
+
+ /* Configure for gigabit full duplex */
+ data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+ data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
+ phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+
+ data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+ data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+ phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+ udelay(100);
+
+ /* Reset and configure cascaded 10/100 PHY */
+ (void)reset_one_mii_phy(phy, 0x1f);
+
+ data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+ data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+ __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+ data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+ data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
+ phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+
+ return 0;
+}
+
+static int bcm5400_suspend(struct mii_phy* phy)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+ phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+ return 0;
+}
+
+static int bcm5401_init(struct mii_phy* phy)
+{
+ u16 data;
+ int rev;
+
+ rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+ if (rev == 0 || rev == 3) {
+ /* Some revisions of 5401 appear to need this
+ * initialisation sequence to disable, according
+ * to OF, "tap power management"
+ *
+ * WARNING ! OF and Darwin don't agree on the
+ * register addresses. OF seem to interpret the
+ * register numbers below as decimal
+ *
+ * Note: This should (and does) match tg3_init_5401phy_dsp
+ * in the tg3.c driver. -DaveM
+ */
+ phy_write(phy, 0x18, 0x0c20);
+ phy_write(phy, 0x17, 0x0012);
+ phy_write(phy, 0x15, 0x1804);
+ phy_write(phy, 0x17, 0x0013);
+ phy_write(phy, 0x15, 0x1204);
+ phy_write(phy, 0x17, 0x8006);
+ phy_write(phy, 0x15, 0x0132);
+ phy_write(phy, 0x17, 0x8006);
+ phy_write(phy, 0x15, 0x0232);
+ phy_write(phy, 0x17, 0x201f);
+ phy_write(phy, 0x15, 0x0a20);
+ }
+
+ /* Configure for gigabit full duplex */
+ data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+ data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+ phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+ udelay(10);
+
+ /* Reset and configure cascaded 10/100 PHY */
+ (void)reset_one_mii_phy(phy, 0x1f);
+
+ data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+ data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+ __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+ return 0;
+}
+
+static int bcm5401_suspend(struct mii_phy* phy)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+ phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+ return 0;
+}
+
+static int bcm5411_init(struct mii_phy* phy)
+{
+ u16 data;
+
+ /* Here's some more Apple black magic to setup
+ * some voltage stuffs.
+ */
+ phy_write(phy, 0x1c, 0x8c23);
+ phy_write(phy, 0x1c, 0x8ca3);
+ phy_write(phy, 0x1c, 0x8c23);
+
+ /* Here, Apple seems to want to reset it, do
+ * it as well
+ */
+ phy_write(phy, MII_BMCR, BMCR_RESET);
+ phy_write(phy, MII_BMCR, 0x1340);
+
+ data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+ data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+ phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+ udelay(10);
+
+ /* Reset and configure cascaded 10/100 PHY */
+ (void)reset_one_mii_phy(phy, 0x1f);
+
+ return 0;
+}
+
+static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+ u16 ctl, adv;
+
+ phy->autoneg = 1;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+ phy->pause = 0;
+ phy->advertising = advertise;
+
+ /* Setup standard advertise */
+ adv = phy_read(phy, MII_ADVERTISE);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ phy_write(phy, MII_ADVERTISE, adv);
+
+ /* Start/Restart aneg */
+ ctl = phy_read(phy, MII_BMCR);
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+ u16 ctl;
+
+ phy->autoneg = 0;
+ phy->speed = speed;
+ phy->duplex = fd;
+ phy->pause = 0;
+
+ ctl = phy_read(phy, MII_BMCR);
+ ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
+
+ /* First reset the PHY */
+ phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+ /* Select speed & duplex */
+ switch(speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ ctl |= BMCR_SPEED100;
+ break;
+ case SPEED_1000:
+ default:
+ return -EINVAL;
+ }
+ if (fd == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int genmii_poll_link(struct mii_phy *phy)
+{
+ u16 status;
+
+ (void)phy_read(phy, MII_BMSR);
+ status = phy_read(phy, MII_BMSR);
+ if ((status & BMSR_LSTATUS) == 0)
+ return 0;
+ if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
+ return 0;
+ return 1;
+}
+
+static int genmii_read_link(struct mii_phy *phy)
+{
+ u16 lpa;
+
+ if (phy->autoneg) {
+ lpa = phy_read(phy, MII_LPA);
+
+ if (lpa & (LPA_10FULL | LPA_100FULL))
+ phy->duplex = DUPLEX_FULL;
+ else
+ phy->duplex = DUPLEX_HALF;
+ if (lpa & (LPA_100FULL | LPA_100HALF))
+ phy->speed = SPEED_100;
+ else
+ phy->speed = SPEED_10;
+ phy->pause = 0;
+ }
+ /* On non-aneg, we assume what we put in BMCR is the speed,
+ * though magic-aneg shouldn't prevent this case from occurring
+ */
+
+ return 0;
+}
+
+static int generic_suspend(struct mii_phy* phy)
+{
+ phy_write(phy, MII_BMCR, BMCR_PDOWN);
+
+ return 0;
+}
+
+static int bcm5421_init(struct mii_phy* phy)
+{
+ u16 data;
+ unsigned int id;
+
+ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+
+ /* Revision 0 of 5421 needs some fixups */
+ if (id == 0x002060e0) {
+ /* This is borrowed from MacOS
+ */
+ phy_write(phy, 0x18, 0x1007);
+ data = phy_read(phy, 0x18);
+ phy_write(phy, 0x18, data | 0x0400);
+ phy_write(phy, 0x18, 0x0007);
+ data = phy_read(phy, 0x18);
+ phy_write(phy, 0x18, data | 0x0800);
+ phy_write(phy, 0x17, 0x000a);
+ data = phy_read(phy, 0x15);
+ phy_write(phy, 0x15, data | 0x0200);
+ }
+
+ /* Pick up some init code from OF for K2 version */
+ if ((id & 0xfffffff0) == 0x002062e0) {
+ phy_write(phy, 4, 0x01e1);
+ phy_write(phy, 9, 0x0300);
+ }
+
+ /* Check if we can enable automatic low power */
+#ifdef CONFIG_PPC_PMAC
+ if (phy->platform_data) {
+ struct device_node *np = of_get_parent(phy->platform_data);
+ int can_low_power = 1;
+ if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
+ can_low_power = 0;
+ if (can_low_power) {
+ /* Enable automatic low-power */
+ phy_write(phy, 0x1c, 0x9002);
+ phy_write(phy, 0x1c, 0xa821);
+ phy_write(phy, 0x1c, 0x941d);
+ }
+ }
+#endif /* CONFIG_PPC_PMAC */
+
+ return 0;
+}
+
+static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+ u16 ctl, adv;
+
+ phy->autoneg = 1;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+ phy->pause = 0;
+ phy->advertising = advertise;
+
+ /* Setup standard advertise */
+ adv = phy_read(phy, MII_ADVERTISE);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
+ phy_write(phy, MII_ADVERTISE, adv);
+
+ /* Setup 1000BT advertise */
+ adv = phy_read(phy, MII_1000BASETCONTROL);
+ adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
+ if (advertise & SUPPORTED_1000baseT_Half)
+ adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+ if (advertise & SUPPORTED_1000baseT_Full)
+ adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+ phy_write(phy, MII_1000BASETCONTROL, adv);
+
+ /* Start/Restart aneg */
+ ctl = phy_read(phy, MII_BMCR);
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+ u16 ctl;
+
+ phy->autoneg = 0;
+ phy->speed = speed;
+ phy->duplex = fd;
+ phy->pause = 0;
+
+ ctl = phy_read(phy, MII_BMCR);
+ ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+
+ /* First reset the PHY */
+ phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+ /* Select speed & duplex */
+ switch(speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ ctl |= BMCR_SPEED100;
+ break;
+ case SPEED_1000:
+ ctl |= BMCR_SPD2;
+ }
+ if (fd == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+
+ // XXX Should we set the sungem to GII now on 1000BT ?
+
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int bcm54xx_read_link(struct mii_phy *phy)
+{
+ int link_mode;
+ u16 val;
+
+ if (phy->autoneg) {
+ val = phy_read(phy, MII_BCM5400_AUXSTATUS);
+ link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
+ MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
+ phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ phy->speed = phy_BCM5400_link_table[link_mode][2] ?
+ SPEED_1000 :
+ (phy_BCM5400_link_table[link_mode][1] ?
+ SPEED_100 : SPEED_10);
+ val = phy_read(phy, MII_LPA);
+ phy->pause = (phy->duplex == DUPLEX_FULL) &&
+ ((val & LPA_PAUSE) != 0);
+ }
+ /* On non-aneg, we assume what we put in BMCR is the speed,
+ * though magic-aneg shouldn't prevent this case from occurring
+ */
+
+ return 0;
+}
+
+static int marvell88e1111_init(struct mii_phy* phy)
+{
+ u16 rev;
+
+ /* magic init sequence for rev 0 */
+ rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+ if (rev == 0) {
+ phy_write(phy, 0x1d, 0x000a);
+ phy_write(phy, 0x1e, 0x0821);
+
+ phy_write(phy, 0x1d, 0x0006);
+ phy_write(phy, 0x1e, 0x8600);
+
+ phy_write(phy, 0x1d, 0x000b);
+ phy_write(phy, 0x1e, 0x0100);
+
+ phy_write(phy, 0x1d, 0x0004);
+ phy_write(phy, 0x1e, 0x4850);
+ }
+ return 0;
+}
+
+#define BCM5421_MODE_MASK (1 << 5)
+
+static int bcm5421_poll_link(struct mii_phy* phy)
+{
+ u32 phy_reg;
+ int mode;
+
+ /* find out in what mode we are */
+ phy_write(phy, MII_NCONFIG, 0x1000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
+
+ if ( mode == BCM54XX_COPPER)
+ return genmii_poll_link(phy);
+
+ /* try to find out wether we have a link */
+ phy_write(phy, MII_NCONFIG, 0x2000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ if (phy_reg & 0x0020)
+ return 0;
+ else
+ return 1;
+}
+
+static int bcm5421_read_link(struct mii_phy* phy)
+{
+ u32 phy_reg;
+ int mode;
+
+ /* find out in what mode we are */
+ phy_write(phy, MII_NCONFIG, 0x1000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
+
+ if ( mode == BCM54XX_COPPER)
+ return bcm54xx_read_link(phy);
+
+ phy->speed = SPEED_1000;
+
+ /* find out wether we are running half- or full duplex */
+ phy_write(phy, MII_NCONFIG, 0x2000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ if ( (phy_reg & 0x0080) >> 7)
+ phy->duplex |= DUPLEX_HALF;
+ else
+ phy->duplex |= DUPLEX_FULL;
+
+ return 0;
+}
+
+static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+ /* enable fiber mode */
+ phy_write(phy, MII_NCONFIG, 0x9020);
+ /* LEDs active in both modes, autosense prio = fiber */
+ phy_write(phy, MII_NCONFIG, 0x945f);
+
+ if (!autoneg) {
+ /* switch off fibre autoneg */
+ phy_write(phy, MII_NCONFIG, 0xfc01);
+ phy_write(phy, 0x0b, 0x0004);
+ }
+
+ phy->autoneg = autoneg;
+
+ return 0;
+}
+
+#define BCM5461_FIBER_LINK (1 << 2)
+#define BCM5461_MODE_MASK (3 << 1)
+
+static int bcm5461_poll_link(struct mii_phy* phy)
+{
+ u32 phy_reg;
+ int mode;
+
+ /* find out in what mode we are */
+ phy_write(phy, MII_NCONFIG, 0x7c00);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+ if ( mode == BCM54XX_COPPER)
+ return genmii_poll_link(phy);
+
+ /* find out wether we have a link */
+ phy_write(phy, MII_NCONFIG, 0x7000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ if (phy_reg & BCM5461_FIBER_LINK)
+ return 1;
+ else
+ return 0;
+}
+
+#define BCM5461_FIBER_DUPLEX (1 << 3)
+
+static int bcm5461_read_link(struct mii_phy* phy)
+{
+ u32 phy_reg;
+ int mode;
+
+ /* find out in what mode we are */
+ phy_write(phy, MII_NCONFIG, 0x7c00);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+ if ( mode == BCM54XX_COPPER) {
+ return bcm54xx_read_link(phy);
+ }
+
+ phy->speed = SPEED_1000;
+
+ /* find out wether we are running half- or full duplex */
+ phy_write(phy, MII_NCONFIG, 0x7000);
+ phy_reg = phy_read(phy, MII_NCONFIG);
+
+ if (phy_reg & BCM5461_FIBER_DUPLEX)
+ phy->duplex |= DUPLEX_FULL;
+ else
+ phy->duplex |= DUPLEX_HALF;
+
+ return 0;
+}
+
+static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+ /* select fiber mode, enable 1000 base-X registers */
+ phy_write(phy, MII_NCONFIG, 0xfc0b);
+
+ if (autoneg) {
+ /* enable fiber with no autonegotiation */
+ phy_write(phy, MII_ADVERTISE, 0x01e0);
+ phy_write(phy, MII_BMCR, 0x1140);
+ } else {
+ /* enable fiber with autonegotiation */
+ phy_write(phy, MII_BMCR, 0x0140);
+ }
+
+ phy->autoneg = autoneg;
+
+ return 0;
+}
+
+static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+ u16 ctl, adv;
+
+ phy->autoneg = 1;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+ phy->pause = 0;
+ phy->advertising = advertise;
+
+ /* Setup standard advertise */
+ adv = phy_read(phy, MII_ADVERTISE);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
+ phy_write(phy, MII_ADVERTISE, adv);
+
+ /* Setup 1000BT advertise & enable crossover detect
+ * XXX How do we advertise 1000BT ? Darwin source is
+ * confusing here, they read from specific control and
+ * write to control... Someone has specs for those
+ * beasts ?
+ */
+ adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+ adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
+ adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+ MII_1000BASETCONTROL_HALFDUPLEXCAP);
+ if (advertise & SUPPORTED_1000baseT_Half)
+ adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+ if (advertise & SUPPORTED_1000baseT_Full)
+ adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+ phy_write(phy, MII_1000BASETCONTROL, adv);
+
+ /* Start/Restart aneg */
+ ctl = phy_read(phy, MII_BMCR);
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+ u16 ctl, ctl2;
+
+ phy->autoneg = 0;
+ phy->speed = speed;
+ phy->duplex = fd;
+ phy->pause = 0;
+
+ ctl = phy_read(phy, MII_BMCR);
+ ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+ ctl |= BMCR_RESET;
+
+ /* Select speed & duplex */
+ switch(speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ ctl |= BMCR_SPEED100;
+ break;
+ /* I'm not sure about the one below, again, Darwin source is
+ * quite confusing and I lack chip specs
+ */
+ case SPEED_1000:
+ ctl |= BMCR_SPD2;
+ }
+ if (fd == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+
+ /* Disable crossover. Again, the way Apple does it is strange,
+ * though I don't assume they are wrong ;)
+ */
+ ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+ ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
+ MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
+ MII_1000BASETCONTROL_FULLDUPLEXCAP |
+ MII_1000BASETCONTROL_HALFDUPLEXCAP);
+ if (speed == SPEED_1000)
+ ctl2 |= (fd == DUPLEX_FULL) ?
+ MII_1000BASETCONTROL_FULLDUPLEXCAP :
+ MII_1000BASETCONTROL_HALFDUPLEXCAP;
+ phy_write(phy, MII_1000BASETCONTROL, ctl2);
+
+ // XXX Should we set the sungem to GII now on 1000BT ?
+
+ phy_write(phy, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int marvell_read_link(struct mii_phy *phy)
+{
+ u16 status, pmask;
+
+ if (phy->autoneg) {
+ status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
+ if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+ return -EAGAIN;
+ if (status & MII_M1011_PHY_SPEC_STATUS_1000)
+ phy->speed = SPEED_1000;
+ else if (status & MII_M1011_PHY_SPEC_STATUS_100)
+ phy->speed = SPEED_100;
+ else
+ phy->speed = SPEED_10;
+ if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+ phy->duplex = DUPLEX_FULL;
+ else
+ phy->duplex = DUPLEX_HALF;
+ pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
+ MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
+ phy->pause = (status & pmask) == pmask;
+ }
+ /* On non-aneg, we assume what we put in BMCR is the speed,
+ * though magic-aneg shouldn't prevent this case from occurring
+ */
+
+ return 0;
+}
+
+#define MII_BASIC_FEATURES \
+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | \
+ SUPPORTED_Pause)
+
+/* On gigabit capable PHYs, we advertise Pause support but not asym pause
+ * support for now as I'm not sure it's supported and Darwin doesn't do
+ * it neither. --BenH.
+ */
+#define MII_GBIT_FEATURES \
+ (MII_BASIC_FEATURES | \
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+
+/* Broadcom BCM 5201 */
+static struct mii_phy_ops bcm5201_phy_ops = {
+ .init = bcm5201_init,
+ .suspend = bcm5201_suspend,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link,
+};
+
+static struct mii_phy_def bcm5201_phy_def = {
+ .phy_id = 0x00406210,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5201",
+ .features = MII_BASIC_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5201_phy_ops
+};
+
+/* Broadcom BCM 5221 */
+static struct mii_phy_ops bcm5221_phy_ops = {
+ .suspend = bcm5221_suspend,
+ .init = bcm5221_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link,
+};
+
+static struct mii_phy_def bcm5221_phy_def = {
+ .phy_id = 0x004061e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5221",
+ .features = MII_BASIC_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5221_phy_ops
+};
+
+/* Broadcom BCM 5241 */
+static struct mii_phy_ops bcm5241_phy_ops = {
+ .suspend = bcm5241_suspend,
+ .init = bcm5241_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link,
+};
+static struct mii_phy_def bcm5241_phy_def = {
+ .phy_id = 0x0143bc30,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5241",
+ .features = MII_BASIC_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5241_phy_ops
+};
+
+/* Broadcom BCM 5400 */
+static struct mii_phy_ops bcm5400_phy_ops = {
+ .init = bcm5400_init,
+ .suspend = bcm5400_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5400_phy_def = {
+ .phy_id = 0x00206040,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5400",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5400_phy_ops
+};
+
+/* Broadcom BCM 5401 */
+static struct mii_phy_ops bcm5401_phy_ops = {
+ .init = bcm5401_init,
+ .suspend = bcm5401_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5401_phy_def = {
+ .phy_id = 0x00206050,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5401",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5401_phy_ops
+};
+
+/* Broadcom BCM 5411 */
+static struct mii_phy_ops bcm5411_phy_ops = {
+ .init = bcm5411_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5411_phy_def = {
+ .phy_id = 0x00206070,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5411",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5411_phy_ops
+};
+
+/* Broadcom BCM 5421 */
+static struct mii_phy_ops bcm5421_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = bcm5421_poll_link,
+ .read_link = bcm5421_read_link,
+ .enable_fiber = bcm5421_enable_fiber,
+};
+
+static struct mii_phy_def bcm5421_phy_def = {
+ .phy_id = 0x002060e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5421",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5421_phy_ops
+};
+
+/* Broadcom BCM 5421 built-in K2 */
+static struct mii_phy_ops bcm5421k2_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5421k2_phy_def = {
+ .phy_id = 0x002062e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5421-K2",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5421k2_phy_ops
+};
+
+static struct mii_phy_ops bcm5461_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = bcm5461_poll_link,
+ .read_link = bcm5461_read_link,
+ .enable_fiber = bcm5461_enable_fiber,
+};
+
+static struct mii_phy_def bcm5461_phy_def = {
+ .phy_id = 0x002060c0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5461",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5461_phy_ops
+};
+
+/* Broadcom BCM 5462 built-in Vesta */
+static struct mii_phy_ops bcm5462V_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5462V_phy_def = {
+ .phy_id = 0x002060d0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5462-Vesta",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5462V_phy_ops
+};
+
+/* Marvell 88E1101 amd 88E1111 */
+static struct mii_phy_ops marvell88e1101_phy_ops = {
+ .suspend = generic_suspend,
+ .setup_aneg = marvell_setup_aneg,
+ .setup_forced = marvell_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = marvell_read_link
+};
+
+static struct mii_phy_ops marvell88e1111_phy_ops = {
+ .init = marvell88e1111_init,
+ .suspend = generic_suspend,
+ .setup_aneg = marvell_setup_aneg,
+ .setup_forced = marvell_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = marvell_read_link
+};
+
+/* two revs in darwin for the 88e1101 ... I could use a datasheet
+ * to get the proper names...
+ */
+static struct mii_phy_def marvell88e1101v1_phy_def = {
+ .phy_id = 0x01410c20,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101v1",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1101v2_phy_def = {
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101v2",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1111_phy_def = {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &marvell88e1111_phy_ops
+};
+
+/* Generic implementation for most 10/100 PHYs */
+static struct mii_phy_ops generic_phy_ops = {
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def genmii_phy_def = {
+ .phy_id = 0x00000000,
+ .phy_id_mask = 0x00000000,
+ .name = "Generic MII",
+ .features = MII_BASIC_FEATURES,
+ .magic_aneg = 0,
+ .ops = &generic_phy_ops
+};
+
+static struct mii_phy_def* mii_phy_table[] = {
+ &bcm5201_phy_def,
+ &bcm5221_phy_def,
+ &bcm5241_phy_def,
+ &bcm5400_phy_def,
+ &bcm5401_phy_def,
+ &bcm5411_phy_def,
+ &bcm5421_phy_def,
+ &bcm5421k2_phy_def,
+ &bcm5461_phy_def,
+ &bcm5462V_phy_def,
+ &marvell88e1101v1_phy_def,
+ &marvell88e1101v2_phy_def,
+ &marvell88e1111_phy_def,
+ &genmii_phy_def,
+ NULL
+};
+
+int sungem_phy_probe(struct mii_phy *phy, int mii_id)
+{
+ int rc;
+ u32 id;
+ struct mii_phy_def* def;
+ int i;
+
+ /* We do not reset the mii_phy structure as the driver
+ * may re-probe the PHY regulary
+ */
+ phy->mii_id = mii_id;
+
+ /* Take PHY out of isloate mode and reset it. */
+ rc = reset_one_mii_phy(phy, mii_id);
+ if (rc)
+ goto fail;
+
+ /* Read ID and find matching entry */
+ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+ printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
+ id, mii_id);
+ for (i=0; (def = mii_phy_table[i]) != NULL; i++)
+ if ((id & def->phy_id_mask) == def->phy_id)
+ break;
+ /* Should never be NULL (we have a generic entry), but... */
+ if (def == NULL)
+ goto fail;
+
+ phy->def = def;
+
+ return 0;
+fail:
+ phy->speed = 0;
+ phy->duplex = 0;
+ phy->pause = 0;
+ phy->advertising = 0;
+ return -ENODEV;
+}
+
+EXPORT_SYMBOL(sungem_phy_probe);
+MODULE_LICENSE("GPL");
diff --git a/include/linux/sungem_phy.h b/include/linux/sungem_phy.h
index af02f94..bd9be9f 100644
--- a/include/linux/sungem_phy.h
+++ b/include/linux/sungem_phy.h
@@ -61,7 +61,7 @@ struct mii_phy
/* Pass in a struct mii_phy with dev, mdio_read and mdio_write
* filled, the remaining fields will be filled on return
*/
-extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
+extern int sungem_phy_probe(struct mii_phy *phy, int mii_id);
/* MII definitions missing from mii.h */
--
1.7.6
^ permalink raw reply related
* Re: linux-next: build failure after merge of the final tree (net tree related)
From: Stephen Rothwell @ 2011-08-16 6:57 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110815.231116.1728582609642497613.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 428 bytes --]
Hi Dave,
On Mon, 15 Aug 2011 23:11:16 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>
> Please test this patch:
>
> --------------------
> net: Fix sungem_phy sharing.
This fixes my allyesconfig build (and doesn't break any of the others :-)).
Tested-by: Stephen Rothwell <sfr@canb.auug.org.au>
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: linux-next: build failure after merge of the final tree (net tree related)
From: David Miller @ 2011-08-16 7:17 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110816165744.5c069b0c9f2e329e48ecd7d0@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 16:57:44 +1000
> Hi Dave,
>
> On Mon, 15 Aug 2011 23:11:16 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>>
>> Please test this patch:
>>
>> --------------------
>> net: Fix sungem_phy sharing.
>
> This fixes my allyesconfig build (and doesn't break any of the others :-)).
>
> Tested-by: Stephen Rothwell <sfr@canb.auug.org.au>
Thanks a lot for testing.
^ permalink raw reply
* [patch net-2.6] via-velocity: remove non-tagged packet filtering
From: Jiri Pirko @ 2011-08-16 8:33 UTC (permalink / raw)
To: netdev; +Cc: davem, shemminger, romieu, stephan.baerwolf
It's undesired to filter untagged packets at any time. So simply remove this.
Reported-by: Stephan Bärwolf <stephan.baerwolf@tu-ilmenau.de>
Tested-by: Stephan Bärwolf <stephan.baerwolf@tu-ilmenau.de>
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/via-velocity.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index deb1eca..7c5336c 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -515,10 +515,6 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
mac_set_cam_mask(regs, vptr->mCAMmask);
/* Enable VCAMs */
-
- if (test_bit(0, vptr->active_vlans))
- WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG);
-
for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
mac_set_vlan_cam(regs, i, (u8 *) &vid);
vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
--
1.7.6
^ permalink raw reply related
* get_random_int() should use hash[1]
From: George Spelvin @ 2011-08-16 9:07 UTC (permalink / raw)
To: davem; +Cc: linux, netdev
Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
As long as you're using MD5, you should know that each round only
modifies one word of the state. The order is [0], [3], [2], [1],
repeating 64 times. Thus, on output, word [1] is the "most hashed"
word. If you really wanted word [0], you could just skip the last
3 rounds.
It's not really critical, but as long as you're performing the
rounds, you might as well use them...
--- drivers/char/random.c.1 2011-08-16 05:02:09.000000000 -0400
+++ drivers/char/random.c.2 2011-08-16 05:02:43.000000000 -0400
@@ -1323,7 +1323,7 @@
hash[0] += current->pid + jiffies + get_cycles();
md5_transform(hash, random_int_secret);
- ret = hash[0];
+ ret = hash[1];
put_cpu_var(get_random_int_hash);
return ret;
Me, I'd also put jiffies and get_cycles into different words
just on general principles, but that's up to you:
- hash[0] += current->pid + jiffies + get_cycles();
+ hash[1] += current->pid + jiffies;
+ hash[2] += get_cycles();
^ permalink raw reply
* Re: get_random_int() should use hash[1]
From: David Miller @ 2011-08-16 9:09 UTC (permalink / raw)
To: linux; +Cc: netdev
In-Reply-To: <20110816090723.18492.qmail@science.horizon.com>
From: "George Spelvin" <linux@horizon.com>
Date: 16 Aug 2011 05:07:23 -0400
> Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
>
> As long as you're using MD5, you should know that each round only
> modifies one word of the state. The order is [0], [3], [2], [1],
> repeating 64 times. Thus, on output, word [1] is the "most hashed"
> word. If you really wanted word [0], you could just skip the last
> 3 rounds.
>
> It's not really critical, but as long as you're performing the
> rounds, you might as well use them...
Please provide a proper signoff with your change and properly
"-p1" base your patch.
Thanks.
^ permalink raw reply
* Re: get_random_int() should use hash[1]
From: David Miller @ 2011-08-16 9:10 UTC (permalink / raw)
To: linux; +Cc: netdev
In-Reply-To: <20110816.020935.717525957035990843.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Tue, 16 Aug 2011 02:09:35 -0700 (PDT)
> From: "George Spelvin" <linux@horizon.com>
> Date: 16 Aug 2011 05:07:23 -0400
>
>> Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
>>
>> As long as you're using MD5, you should know that each round only
>> modifies one word of the state. The order is [0], [3], [2], [1],
>> repeating 64 times. Thus, on output, word [1] is the "most hashed"
>> word. If you really wanted word [0], you could just skip the last
>> 3 rounds.
>>
>> It's not really critical, but as long as you're performing the
>> rounds, you might as well use them...
>
> Please provide a proper signoff with your change and properly
> "-p1" base your patch.
>
> Thanks.
Also this change is of interest to, and effects, folks outside of
networking. So probably want to CC: linux-kernel when you respin
this.
^ 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