* [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-05-03 5:38 ` David Miller
2010-04-29 23:16 ` [patch 02/13] KSZ8851-SNL: Fix receive interrupt problem Ben Dooks
` (11 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Tristram Ha
[-- Attachment #1: thirdparty/micrel/ks8851-tx-fix.patch --]
[-- Type: text/plain, Size: 3873 bytes --]
From: Tristram Ha <Tristram.Ha@micrel.com>
This fixes a transmit problem of the ks8851 snl network driver.
Under heavy TCP traffic the device will stop transmitting. Turning off
the transmit interrupt avoids this issue. A new workqueue was
implemented to replace the functionality of the transmit interrupt processing.
Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
---
---
drivers/net/ks8851.c | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-20 18:13:58.000000000 +0100
+++ b/drivers/net/ks8851.c 2010-04-20 18:38:18.000000000 +0100
@@ -111,11 +111,13 @@ struct ks8851_net {
struct mii_if_info mii;
struct ks8851_rxctrl rxctrl;
+ struct work_struct tx_check;
struct work_struct tx_work;
struct work_struct irq_work;
struct work_struct rxctrl_work;
struct sk_buff_head txq;
+ int tx_len;
struct spi_message spi_msg1;
struct spi_message spi_msg2;
@@ -573,19 +575,6 @@ static void ks8851_irq_work(struct work_
if (status & IRQ_RXPSI)
handled |= IRQ_RXPSI;
- if (status & IRQ_TXI) {
- handled |= IRQ_TXI;
-
- /* no lock here, tx queue should have been stopped */
-
- /* update our idea of how much tx space is available to the
- * system */
- ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
-
- if (netif_msg_intr(ks))
- ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space);
- }
-
if (status & IRQ_RXI)
handled |= IRQ_RXI;
@@ -623,9 +612,6 @@ static void ks8851_irq_work(struct work_
mutex_unlock(&ks->lock);
- if (status & IRQ_TXI)
- netif_wake_queue(ks->netdev);
-
enable_irq(ks->netdev->irq);
}
@@ -703,6 +689,17 @@ static void ks8851_done_tx(struct ks8851
dev_kfree_skb(txb);
}
+static void ks8851_tx_check(struct work_struct *work)
+{
+ struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_check);
+
+ ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+ if (ks->tx_space > ks->tx_len)
+ netif_wake_queue(ks->netdev);
+ else
+ schedule_work(&ks->tx_check);
+}
+
/**
* ks8851_tx_work - process tx packet(s)
* @work: The work strucutre what was scheduled.
@@ -814,7 +811,6 @@ static int ks8851_net_open(struct net_de
/* clear then enable interrupts */
#define STD_IRQ (IRQ_LCI | /* Link Change */ \
- IRQ_TXI | /* TX done */ \
IRQ_RXI | /* RX done */ \
IRQ_SPIBEI | /* SPI bus error */ \
IRQ_TXPSI | /* TX process stop */ \
@@ -830,6 +826,7 @@ static int ks8851_net_open(struct net_de
ks_dbg(ks, "network device %s up\n", dev->name);
mutex_unlock(&ks->lock);
+ ks8851_write_mac_addr(dev);
return 0;
}
@@ -854,6 +851,7 @@ static int ks8851_net_stop(struct net_de
/* stop any outstanding work */
flush_work(&ks->irq_work);
+ flush_work(&ks->tx_check);
flush_work(&ks->tx_work);
flush_work(&ks->rxctrl_work);
@@ -912,14 +910,16 @@ static netdev_tx_t ks8851_start_xmit(str
if (needed > ks->tx_space) {
netif_stop_queue(dev);
+ ks->tx_len = needed;
+ schedule_work(&ks->tx_check);
ret = NETDEV_TX_BUSY;
} else {
ks->tx_space -= needed;
skb_queue_tail(&ks->txq, skb);
+ schedule_work(&ks->tx_work);
}
spin_unlock(&ks->statelock);
- schedule_work(&ks->tx_work);
return ret;
}
@@ -1227,6 +1227,7 @@ static int __devinit ks8851_probe(struct
mutex_init(&ks->lock);
spin_lock_init(&ks->statelock);
+ INIT_WORK(&ks->tx_check, ks8851_tx_check);
INIT_WORK(&ks->tx_work, ks8851_tx_work);
INIT_WORK(&ks->irq_work, ks8851_irq_work);
INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
@@ -1279,6 +1280,7 @@ static int __devinit ks8851_probe(struct
ks8851_read_selftest(ks);
ks8851_init_mac(ks);
+ ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
ndev->name, ks);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-04-29 23:16 ` [patch 01/13] KS8851: Fix ks8851 snl transmit problem Ben Dooks
@ 2010-05-03 5:38 ` David Miller
2010-05-03 19:06 ` Ha, Tristram
0 siblings, 1 reply; 21+ messages in thread
From: David Miller @ 2010-05-03 5:38 UTC (permalink / raw)
To: ben; +Cc: netdev, tristram.ha, support
From: Ben Dooks <ben@simtec.co.uk>
Date: Fri, 30 Apr 2010 00:16:22 +0100
> From: Tristram Ha <Tristram.Ha@micrel.com>
>
> This fixes a transmit problem of the ks8851 snl network driver.
>
> Under heavy TCP traffic the device will stop transmitting. Turning off
> the transmit interrupt avoids this issue. A new workqueue was
> implemented to replace the functionality of the transmit interrupt processing.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
Please, try to fix this properly. Unless you have a known chip errata
with the TX interrupt that cannot be worked around reasonably, which
would need to be detailed and explained completely in the commit log
message, you should try to figure out what the real problem is.
Otherwise just tossing everything to a workqueue looks like a hack, at
best.
I suspect you have some kind of race between IRQ processing and the
->ndo_start_xmit() handler, so you end up missing a queue wakeup.
Either that or you end up misprogramming the hardware due to the race.
There is no way I'm applying this as-is.
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-05-03 5:38 ` David Miller
@ 2010-05-03 19:06 ` Ha, Tristram
2010-05-03 20:03 ` David Miller
2010-05-03 20:04 ` David Miller
0 siblings, 2 replies; 21+ messages in thread
From: Ha, Tristram @ 2010-05-03 19:06 UTC (permalink / raw)
To: David Miller, ben; +Cc: netdev, support
David Miller wrote:
> From: Ben Dooks <ben@simtec.co.uk>
> Date: Fri, 30 Apr 2010 00:16:22 +0100
>
>> From: Tristram Ha <Tristram.Ha@micrel.com>
>>
>> This fixes a transmit problem of the ks8851 snl network driver.
>>
>> Under heavy TCP traffic the device will stop transmitting. Turning
off
>> the transmit interrupt avoids this issue. A new workqueue was
>> implemented to replace the functionality of the transmit interrupt
processing.
>>
>> Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
>
> Please, try to fix this properly. Unless you have a known chip errata
with the TX interrupt
> that cannot be worked around reasonably, which would need to be
detailed and explained
> completely in the commit log message, you should try to figure out
what the real problem is.
>
> Otherwise just tossing everything to a workqueue looks like a hack, at
best.
>
> I suspect you have some kind of race between IRQ processing and the
> ->ndo_start_xmit() handler, so you end up missing a queue wakeup.
> Either that or you end up misprogramming the hardware due to the race.
>
> There is no way I'm applying this as-is.
As I explained a long time ago (last year), this patch is no longer
considered as a fix but for performance.
The transmit done interrupt in the KSZ8851 chips is not required for
normal operation. Turning it off actually will improve transmit
performance because the system will not be interrupted every time a
packet is sent.
This driver runs on SPI bus. Just reading register requires a workqueue
because it cannot be done under interrupt context. Processing the
transmit interrupt requires scheduling a workqueue anyway.
I tested the driver under the Beagle Zippy2 board with a 24 MHz SPI bus
clock, which limits the throughput to 10 Mbps. On other systems the
transmit performance improvement may be greater, but I do not have that
data to back me up.
If you feel strongly that this workqueue implementation is not
appropriate, then please disregard the patch.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-05-03 19:06 ` Ha, Tristram
@ 2010-05-03 20:03 ` David Miller
2010-05-03 21:11 ` Ha, Tristram
2010-05-03 20:04 ` David Miller
1 sibling, 1 reply; 21+ messages in thread
From: David Miller @ 2010-05-03 20:03 UTC (permalink / raw)
To: Tristram.Ha; +Cc: ben, netdev, support
From: "Ha, Tristram" <Tristram.Ha@Micrel.Com>
Date: Mon, 3 May 2010 12:06:21 -0700
> The transmit done interrupt in the KSZ8851 chips is not required for
> normal operation. Turning it off actually will improve transmit
> performance because the system will not be interrupted every time a
> packet is sent.
But you only trigger this workqueue when you notice in ->ndo_start_xmit()
that you're out of space.
This makes the chip sit idle with no packets to send until the workqueue
executes asynchronously to the initial transmit path which noticed the
queue was full.
That doesn't make any sense to me. If anything you should at least try
to purge the TX queue and make space directly in the ->ndo_start_xmit()
handler. And if that fails trigger an hrtimer to poll the TX state.
Without some kind of timer based polling mechanism, if the workqueue
finds the TX queue is still full, what's going to do more checks
later? You will no longer get ->ndo_start_xmit() calls because the
queue has been marked full, so nothing will trigger the workqueue to
run any more.
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-05-03 20:03 ` David Miller
@ 2010-05-03 21:11 ` Ha, Tristram
2010-05-03 21:13 ` David Miller
0 siblings, 1 reply; 21+ messages in thread
From: Ha, Tristram @ 2010-05-03 21:11 UTC (permalink / raw)
To: David Miller; +Cc: ben, netdev, support
David Miller wrote:
> From: "Ha, Tristram" <Tristram.Ha@Micrel.Com>
> Date: Mon, 3 May 2010 12:06:21 -0700
>
>> The transmit done interrupt in the KSZ8851 chips is not required for
>> normal operation. Turning it off actually will improve transmit
>> performance because the system will not be interrupted every time a
>> packet is sent.
>
> But you only trigger this workqueue when you notice in
->ndo_start_xmit() that you're out of
> space.
>
> This makes the chip sit idle with no packets to send until the
workqueue executes asynchronously
> to the initial transmit path which noticed the queue was full.
>
> That doesn't make any sense to me. If anything you should at least
try to purge the TX queue
> and make space directly in the ->ndo_start_xmit() handler. And if
that fails trigger an hrtimer
> to poll the TX state.
>
> Without some kind of timer based polling mechanism, if the workqueue
finds the TX queue is still
> full, what's going to do more checks later? You will no longer get
->ndo_start_xmit() calls
> because the queue has been marked full, so nothing will trigger the
workqueue to run any more.
I thought the transmit check workqueue reschedules itself when the
buffer available is still not enough, and this is the part you objected.
The buffer has about 8K. Suppose 5 1514-byte packets are sent and the
buffer is not enough to hold the next packet and so the transmit queue
is stopped. A workqueue is scheduled to read the buffer available
register. As previous packets should have been sent the buffer size
read is big enough and so the transmit queue is restarted. This happens
very often as the network bandwidth is only 10 Mbps but the CPU speed is
very fast.
I should also read the buffer available register during receive
interrupt processing so that this situation does not trigger in slow
traffic.
This roundabout way of using workqueue is because the register cannot be
read directly inside ndo_start_xmit().
Actually in other driver with similar transmit buffer available
operation I just return NETDEV_TX_BUSY and let the kernel stack calls
ndo_start_xmit again and again. Supposedly it is bad for the whole
system but the overall transmit throughput is much better than when the
transmit done interrupt is enabled.
There should be a way to trigger the transmit interrupt after certain
number of packets are sent. That will improve the performance and allay
your concern. As I am not the engineer who worked on the Micrel KSZ8851
chip during its development, I am not quite aware of its functions and
limitations. I will try the new code and submit a better patch if
possible.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-05-03 21:11 ` Ha, Tristram
@ 2010-05-03 21:13 ` David Miller
0 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2010-05-03 21:13 UTC (permalink / raw)
To: Tristram.Ha; +Cc: ben, netdev, support
From: "Ha, Tristram" <Tristram.Ha@Micrel.Com>
Date: Mon, 3 May 2010 14:11:41 -0700
> I thought the transmit check workqueue reschedules itself when the
> buffer available is still not enough, and this is the part you objected.
If it reschedules itself, it runs immediately. That will just hog a cpu
endlessly until the TX packets start to be transmitted by the chip. That's
just as bad a polling in a loop.
You need to use an hrtimer or similar.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [patch 01/13] KS8851: Fix ks8851 snl transmit problem
2010-05-03 19:06 ` Ha, Tristram
2010-05-03 20:03 ` David Miller
@ 2010-05-03 20:04 ` David Miller
1 sibling, 0 replies; 21+ messages in thread
From: David Miller @ 2010-05-03 20:04 UTC (permalink / raw)
To: Tristram.Ha; +Cc: ben, netdev, support
And btw, your commit message should have explained all of the things
you're telling me here. Rather than just mention some vague "problem".
Your commit messages should explain everything about why you're
making the change, not just say what changes are being made.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 02/13] KSZ8851-SNL: Fix receive interrupt problem.
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
2010-04-29 23:16 ` [patch 01/13] KS8851: Fix ks8851 snl transmit problem Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 03/13] eeprom_93cx6: Add data direction control Ben Dooks
` (10 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Tristram Ha
[-- Attachment #1: thirdparty/micrel/ks8851-rx-fixeml.txt --]
[-- Type: text/plain, Size: 1438 bytes --]
From: Tristram Ha <Tristram.Ha@micrel.com>
This fixes a receive problem of the ks8851 snl network driver.
Under heavy TCP traffic the device will stop operating correctly. First
the receive interrupt is not triggered anymore. After then the driver
cannot retrieve the correct packets from the device. A workaround for
this problem is to disable the transmit done interrupt.
Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
[ben@simtec.co.uk: cleaned up header]
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.c | 10 ++++++++++
1 file changed, 10 insertions(+)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-28 23:24:20.737026841 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 00:51:12.489525834 +0900
@@ -553,6 +553,13 @@ static void ks8851_irq_work(struct work_
mutex_lock(&ks->lock);
+ /*
+ * Turn off hardware interrupt during receive processing. This fixes
+ * the receive problem under heavy TCP traffic while transmit done
+ * is enabled.
+ */
+ ks8851_wrreg16(ks, KS_IER, 0);
+
status = ks8851_rdreg16(ks, KS_ISR);
if (netif_msg_intr(ks))
@@ -610,6 +617,9 @@ static void ks8851_irq_work(struct work_
ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1);
}
+ /* Re-enable hardware interrupt. */
+ ks8851_wrreg16(ks, KS_IER, ks->rc_ier);
+
mutex_unlock(&ks->lock);
enable_irq(ks->netdev->irq);
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 03/13] eeprom_93cx6: Add data direction control.
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
2010-04-29 23:16 ` [patch 01/13] KS8851: Fix ks8851 snl transmit problem Ben Dooks
2010-04-29 23:16 ` [patch 02/13] KSZ8851-SNL: Fix receive interrupt problem Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-30 11:12 ` Jean Delvare
2010-04-29 23:16 ` [patch 04/13] eeprom_93cx6: Add write support Ben Dooks
` (9 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Wolfram Sang, Jean Delvare, Linux Kernel
[-- Attachment #1: 93c-eeprom-add-direction.patch --]
[-- Type: text/plain, Size: 2336 bytes --]
Some devices need to know if the data is to be output or read, so add a
data direction into the eeprom structure to tell the driver whether the
data line should be driven.
The user in this case is the Micrel KS8851 which has a direction
control for the EEPROM data line and thus needs to know whether
to drive it (writing) or to tristate it for receiving.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Linux Kernel <linux-kernel@vger.kernel.org>
--
drivers/misc/eeprom/eeprom_93cx6.c | 3 +++
include/linux/eeprom_93cx6.h | 2 ++
2 files changed, 5 insertions(+)
Index: b/drivers/misc/eeprom/eeprom_93cx6.c
===================================================================
--- a/drivers/misc/eeprom/eeprom_93cx6.c 2009-10-06 15:35:38.000000000 +0100
+++ b/drivers/misc/eeprom/eeprom_93cx6.c 2009-10-06 15:51:18.000000000 +0100
@@ -70,6 +70,7 @@ static void eeprom_93cx6_startup(struct
eeprom->reg_data_out = 0;
eeprom->reg_data_clock = 0;
eeprom->reg_chip_select = 1;
+ eeprom->drive_data = 1;
eeprom->register_write(eeprom);
/*
@@ -108,6 +109,7 @@ static void eeprom_93cx6_write_bits(stru
*/
eeprom->reg_data_in = 0;
eeprom->reg_data_out = 0;
+ eeprom->drive_data = 1;
/*
* Start writing all bits.
@@ -147,6 +149,7 @@ static void eeprom_93cx6_read_bits(struc
*/
eeprom->reg_data_in = 0;
eeprom->reg_data_out = 0;
+ eeprom->drive_data = 0;
/*
* Start reading all bits.
Index: b/include/linux/eeprom_93cx6.h
===================================================================
--- a/include/linux/eeprom_93cx6.h 2009-10-06 15:35:38.000000000 +0100
+++ b/include/linux/eeprom_93cx6.h 2009-10-06 15:51:18.000000000 +0100
@@ -45,6 +45,7 @@
* @register_write(struct eeprom_93cx6 *eeprom): handler to
* write to the eeprom register by using all reg_* fields.
* @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @drive_data: Set if we're driving the data line.
* @reg_data_in: register field to indicate data input
* @reg_data_out: register field to indicate data output
* @reg_data_clock: register field to set the data clock
@@ -61,6 +62,7 @@ struct eeprom_93cx6 {
int width;
+ char drive_data;
char reg_data_in;
char reg_data_out;
char reg_data_clock;
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [patch 03/13] eeprom_93cx6: Add data direction control.
2010-04-29 23:16 ` [patch 03/13] eeprom_93cx6: Add data direction control Ben Dooks
@ 2010-04-30 11:12 ` Jean Delvare
0 siblings, 0 replies; 21+ messages in thread
From: Jean Delvare @ 2010-04-30 11:12 UTC (permalink / raw)
To: Ben Dooks; +Cc: netdev, tristram.ha, support, Wolfram Sang, Linux Kernel
Hi Ben,
On Fri, 30 Apr 2010 00:16:24 +0100, Ben Dooks wrote:
> Some devices need to know if the data is to be output or read, so add a
> data direction into the eeprom structure to tell the driver whether the
> data line should be driven.
>
> The user in this case is the Micrel KS8851 which has a direction
> control for the EEPROM data line and thus needs to know whether
> to drive it (writing) or to tristate it for receiving.
>
> Signed-off-by: Ben Dooks <ben@simtec.co.uk>
> Cc: Wolfram Sang <w.sang@pengutronix.de>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Linux Kernel <linux-kernel@vger.kernel.org>
I don't know anything about these driver and device, so don't expect
any input from me.
--
Jean Delvare
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 04/13] eeprom_93cx6: Add write support
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (2 preceding siblings ...)
2010-04-29 23:16 ` [patch 03/13] eeprom_93cx6: Add data direction control Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 05/13] KSZ8851-SNL: Add support for EEPROM MAC address Ben Dooks
` (8 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Wolfram Sang, Jean Delvare, Linux Kernel
[-- Attachment #1: 93c-eeprom-add-write.patch --]
[-- Type: text/plain, Size: 3857 bytes --]
Add support for writing data to EEPROM.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Linux Kernel <linux-kernel@vger.kernel.org>
---
drivers/misc/eeprom/eeprom_93cx6.c | 86 +++++++++++++++++++++++++++++++++++++
include/linux/eeprom_93cx6.h | 7 +++
2 files changed, 93 insertions(+)
Index: b/drivers/misc/eeprom/eeprom_93cx6.c
===================================================================
--- a/drivers/misc/eeprom/eeprom_93cx6.c 2009-10-06 15:51:18.000000000 +0100
+++ b/drivers/misc/eeprom/eeprom_93cx6.c 2009-10-06 15:54:36.000000000 +0100
@@ -241,3 +241,89 @@ void eeprom_93cx6_multiread(struct eepro
}
EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
+/**
+ * eeprom_93cx6_wren - set the write enable state
+ * @eeprom: Pointer to eeprom structure
+ * @enable: true to enable writes, otherwise disable writes
+ *
+ * Set the EEPROM write enable state to either allow or deny
+ * writes depending on the @enable value.
+ */
+void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable)
+{
+ u16 command;
+
+ /* start the command */
+ eeprom_93cx6_startup(eeprom);
+
+ /* create command to enable/disable */
+
+ command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE;
+ command <<= (eeprom->width - 2);
+
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_wren);
+
+/**
+ * eeprom_93cx6_write - write data to the EEPROM
+ * @eeprom: Pointer to eeprom structure
+ * @addr: Address to write data to.
+ * @data: The data to write to address @addr.
+ *
+ * Write the @data to the specified @addr in the EEPROM and
+ * waiting for the device to finish writing.
+ *
+ * Note, since we do not expect large number of write operations
+ * we use msleep() to delay in between parts of the operation to
+ * avoid using excessive amounts of CPU time busy waiting.
+ */
+void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data)
+{
+ int timeout = 100;
+ u16 command;
+
+ /* start the command */
+ eeprom_93cx6_startup(eeprom);
+
+ command = PCI_EEPROM_WRITE_OPCODE << eeprom->width;
+ command |= addr;
+
+ /* send write command */
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+ /* send data */
+ eeprom_93cx6_write_bits(eeprom, data, 16);
+
+ /* get ready to check for busy */
+ eeprom->drive_data = 0;
+ eeprom->reg_chip_select = 1;
+ eeprom->register_write(eeprom);
+
+ /* wait at-least 250ns to get DO to be the busy signal */
+ msleep(1);
+
+ /* wait for DO to go high to signify finish */
+
+ while (true) {
+ eeprom->register_read(eeprom);
+
+ if (eeprom->reg_data_out)
+ break;
+
+ msleep(1);
+
+ if (--timeout <= 0) {
+ printk(KERN_ERR "%s: timeout\n", __func__);
+ break;
+ }
+ }
+
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
Index: b/include/linux/eeprom_93cx6.h
===================================================================
--- a/include/linux/eeprom_93cx6.h 2009-10-06 15:51:18.000000000 +0100
+++ b/include/linux/eeprom_93cx6.h 2009-10-06 15:53:16.000000000 +0100
@@ -32,6 +32,7 @@
#define PCI_EEPROM_WIDTH_93C66 8
#define PCI_EEPROM_WIDTH_OPCODE 3
#define PCI_EEPROM_WRITE_OPCODE 0x05
+#define PCI_EEPROM_ERASE_OPCODE 0x07
#define PCI_EEPROM_READ_OPCODE 0x06
#define PCI_EEPROM_EWDS_OPCODE 0x10
#define PCI_EEPROM_EWEN_OPCODE 0x13
@@ -73,3 +74,9 @@ extern void eeprom_93cx6_read(struct eep
const u8 word, u16 *data);
extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
const u8 word, __le16 *data, const u16 words);
+
+extern void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable);
+
+extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom,
+ u8 addr, u16 data);
+
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 05/13] KSZ8851-SNL: Add support for EEPROM MAC address
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (3 preceding siblings ...)
2010-04-29 23:16 ` [patch 04/13] eeprom_93cx6: Add write support Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 06/13] KSZ8851-SNL: Fix MAC address change problem Ben Dooks
` (7 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support
[-- Attachment #1: ks8851-mac-from-eeprom.patch --]
[-- Type: text/plain, Size: 3404 bytes --]
Add support for reading the MAC address from the system registers if there
is an EEPROM present. This involves caching the KS_CCR register for later
use (will also be useful for ETHTOOL support) and adding a print to say
that there is an EEPROM present.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.c | 46 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 39 insertions(+), 7 deletions(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 00:51:12.489525834 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 00:52:02.377026762 +0900
@@ -76,6 +76,7 @@ union ks8851_tx_hdr {
* @msg_enable: The message flags controlling driver output (see ethtool).
* @fid: Incrementing frame id tag.
* @rc_ier: Cached copy of KS_IER.
+ * @rc_ccr: Cached copy of KS_CCR.
* @rc_rxqcr: Cached copy of KS_RXQCR.
*
* The @lock ensures that the chip is protected when certain operations are
@@ -107,6 +108,7 @@ struct ks8851_net {
u16 rc_ier;
u16 rc_rxqcr;
+ u16 rc_ccr;
struct mii_if_info mii;
struct ks8851_rxctrl rxctrl;
@@ -367,21 +369,47 @@ static int ks8851_write_mac_addr(struct
}
/**
+ * ks8851_read_mac_addr - read mac address from device registers
+ * @dev: The network device
+ *
+ * Update our copy of the KS8851 MAC address from the registers of @dev.
+*/
+static void ks8851_read_mac_addr(struct net_device *dev)
+{
+ struct ks8851_net *ks = netdev_priv(dev);
+ int i;
+
+ mutex_lock(&ks->lock);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dev->dev_addr[i] = ks8851_rdreg8(ks, KS_MAR(i));
+
+ mutex_unlock(&ks->lock);
+}
+
+/**
* ks8851_init_mac - initialise the mac address
* @ks: The device structure
*
* Get or create the initial mac address for the device and then set that
- * into the station address register. Currently we assume that the device
- * does not have a valid mac address in it, and so we use random_ether_addr()
+ * into the station address register. If there is an EEPROM present, then
+ * we try that. If no valid mac address is found we use random_ether_addr()
* to create a new one.
- *
- * In future, the driver should check to see if the device has an EEPROM
- * attached and whether that has a valid ethernet address in it.
*/
static void ks8851_init_mac(struct ks8851_net *ks)
{
struct net_device *dev = ks->netdev;
+ /* first, try reading what we've got already */
+ if (ks->rc_ccr & CCR_EEPROM) {
+ ks8851_read_mac_addr(dev);
+ if (is_valid_ether_addr(dev->dev_addr))
+ return;
+
+ ks_err(ks, "invalid mac address read %pM\n",
+ dev->dev_addr);
+ }
+
random_ether_addr(dev->dev_addr);
ks8851_write_mac_addr(dev);
}
@@ -1288,6 +1316,9 @@ static int __devinit ks8851_probe(struct
goto err_id;
}
+ /* cache the contents of the CCR register for EEPROM, etc. */
+ ks->rc_ccr = ks8851_rdreg16(ks, KS_CCR);
+
ks8851_read_selftest(ks);
ks8851_init_mac(ks);
ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
@@ -1305,9 +1336,10 @@ static int __devinit ks8851_probe(struct
goto err_netdev;
}
- dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n",
+ dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
- ndev->dev_addr, ndev->irq);
+ ndev->dev_addr, ndev->irq,
+ ks->rc_ccr & CCR_EEPROM ? "has" : "no");
return 0;
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 06/13] KSZ8851-SNL: Fix MAC address change problem
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (4 preceding siblings ...)
2010-04-29 23:16 ` [patch 05/13] KSZ8851-SNL: Add support for EEPROM MAC address Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 07/13] KSZ8851-SNL: Add ethtool support for EEPROM Ben Dooks
` (6 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Tristram Ha
[-- Attachment #1: thirdparty/micrel/ksz8851-fix-mac.patch --]
[-- Type: text/plain, Size: 2946 bytes --]
From: Tristram Ha <Tristram.Ha@micrel.com>
When device is off it is under power saving mode. Changing the MAC address
in that situation will result in the device not communicating as the first
write to the MAC address register is not executed.
Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
[ben@simtec.co.uk: cleaned up header]
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.c | 30 ++++++++++++++++++++++++++++--
drivers/net/ks8851.h | 2 +-
2 files changed, 29 insertions(+), 3 deletions(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:00:15.519525666 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:01:31.118391091 +0900
@@ -345,6 +345,26 @@ static void ks8851_soft_reset(struct ks8
}
/**
+ * ks8851_set_powermode - set power mode of the device
+ * @ks: The device state
+ * @pwrmode: The power mode value to write to KS_PMECR.
+ *
+ * Change the power mode of the chip.
+ */
+static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode)
+{
+ unsigned pmecr;
+
+ netif_dbg(ks, hw, ks->netdev, "setting power mode %d\n", pwrmode);
+
+ pmecr = ks8851_rdreg16(ks, KS_PMECR);
+ pmecr &= ~PMECR_PM_MASK;
+ pmecr |= pwrmode;
+
+ ks8851_wrreg16(ks, KS_PMECR, pmecr);
+}
+
+/**
* ks8851_write_mac_addr - write mac address to device registers
* @dev: The network device
*
@@ -360,8 +380,15 @@ static int ks8851_write_mac_addr(struct
mutex_lock(&ks->lock);
+ /*
+ * Wake up chip in case it was powered off when stopped; otherwise,
+ * the first write to the MAC address does not take effect.
+ */
+ ks8851_set_powermode(ks, PMECR_PM_NORMAL);
for (i = 0; i < ETH_ALEN; i++)
ks8851_wrreg8(ks, KS_MAR(i), dev->dev_addr[i]);
+ if (!netif_running(dev))
+ ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
mutex_unlock(&ks->lock);
@@ -1260,7 +1287,6 @@ static int __devinit ks8851_probe(struct
ks->netdev = ndev;
ks->spidev = spi;
- ks->tx_space = 6144;
mutex_init(&ks->lock);
spin_lock_init(&ks->statelock);
@@ -1318,10 +1344,10 @@ static int __devinit ks8851_probe(struct
/* cache the contents of the CCR register for EEPROM, etc. */
ks->rc_ccr = ks8851_rdreg16(ks, KS_CCR);
+ ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
ks8851_read_selftest(ks);
ks8851_init_mac(ks);
- ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
ndev->name, ks);
Index: b/drivers/net/ks8851.h
===================================================================
--- a/drivers/net/ks8851.h 2010-04-28 23:24:20.647026644 +0900
+++ b/drivers/net/ks8851.h 2010-04-29 01:00:35.029526937 +0900
@@ -16,7 +16,7 @@
#define CCR_32PIN (1 << 0)
/* MAC address registers */
-#define KS_MAR(_m) 0x15 - (_m)
+#define KS_MAR(_m) (0x15 - (_m))
#define KS_MARL 0x10
#define KS_MARM 0x12
#define KS_MARH 0x14
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 07/13] KSZ8851-SNL: Add ethtool support for EEPROM
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (5 preceding siblings ...)
2010-04-29 23:16 ` [patch 06/13] KSZ8851-SNL: Fix MAC address change problem Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 08/13] KSZ8851-SNL: Fix EEPROM access problem Ben Dooks
` (5 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Simtec Linux Team
[-- Attachment #1: ks8851-add-eeprom-ethtool.patch --]
[-- Type: text/plain, Size: 6382 bytes --]
Add ethtool EEPROM read/write support for the KS8851 driver.
Depends on eeprom_93cx6 driver getting EEPROM write support.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Simtec Linux Team <linux@simtec.co.uk>
---
drivers/net/Kconfig | 1
drivers/net/ks8851.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/ks8851.h | 1
3 files changed, 151 insertions(+)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:01:31.118391091 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:22:42.667052653 +0900
@@ -19,6 +19,7 @@
#include <linux/cache.h>
#include <linux/crc32.h>
#include <linux/mii.h>
+#include <linux/eeprom_93cx6.h>
#include <linux/spi/spi.h>
@@ -78,6 +79,7 @@ union ks8851_tx_hdr {
* @rc_ier: Cached copy of KS_IER.
* @rc_ccr: Cached copy of KS_CCR.
* @rc_rxqcr: Cached copy of KS_RXQCR.
+ * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM.
*
* The @lock ensures that the chip is protected when certain operations are
* in progress. When the read or write packet transfer is in progress, most
@@ -125,6 +127,8 @@ struct ks8851_net {
struct spi_message spi_msg2;
struct spi_transfer spi_xfer1;
struct spi_transfer spi_xfer2[2];
+
+ struct eeprom_93cx6 eeprom;
};
static int msg_enable;
@@ -1149,6 +1153,141 @@ static int ks8851_nway_reset(struct net_
return mii_nway_restart(&ks->mii);
}
+/* EEPROM support */
+
+static void ks8851_eeprom_regread(struct eeprom_93cx6 *ee)
+{
+ struct ks8851_net *ks = ee->data;
+ unsigned val;
+
+ val = ks8851_rdreg16(ks, KS_EEPCR);
+
+ ee->reg_data_out = (val & EEPCR_EESB) ? 1 : 0;
+ ee->reg_data_clock = (val & EEPCR_EESCK) ? 1 : 0;
+ ee->reg_chip_select = (val & EEPCR_EECS) ? 1 : 0;
+}
+
+static void ks8851_eeprom_regwrite(struct eeprom_93cx6 *ee)
+{
+ struct ks8851_net *ks = ee->data;
+ unsigned val = EEPCR_EESA; /* default - eeprom access on */
+
+ if (ee->drive_data)
+ val |= EEPRC_EESRW;
+ if (ee->reg_data_in)
+ val |= EEPCR_EEDO;
+ if (ee->reg_data_clock)
+ val |= EEPCR_EESCK;
+ if (ee->reg_chip_select)
+ val |= EEPCR_EECS;
+
+ printk(KERN_INFO "%s: wr %04x\n", __func__, val);
+ ks8851_wrreg16(ks, KS_EEPCR, val);
+}
+
+/**
+ * ks8851_eeprom_claim - claim device EEPROM and activate the interface
+ * @ks: The network deice state.
+ *
+ * Check for the presence of an EEPROM, and then activate software access
+ * to the device.
+ */
+static int ks8851_eeprom_claim(struct ks8851_net *ks)
+{
+ if (!(ks->rc_ccr & CCR_EEPROM))
+ return -ENOENT;
+
+ /* start with clock low, cs high */
+ ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS);
+ return 0;
+}
+
+/**
+ * ks8851_eeprom_release - release the EEPROM interface
+ * @ks: The device state
+ *
+ * Release the software access to the device EEPROM
+ */
+static void ks8851_eeprom_release(struct ks8851_net *ks)
+{
+ unsigned val = ks8851_rdreg16(ks,KS_EEPCR);
+
+ ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA);
+}
+
+#define KS_EEPROM_MAGIC (0x00008851)
+
+static int ks8851_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ struct ks8851_net *ks = netdev_priv(dev);
+ int offset = ee->offset;
+ int len = ee->len;
+ u16 tmp;
+
+ /* currently only support byte writing */
+ if (len != 1)
+ return -EINVAL;
+
+ if (ee->magic != KS_EEPROM_MAGIC)
+ return -EINVAL;
+
+ if (ks8851_eeprom_claim(ks))
+ return -ENOENT;
+
+ eeprom_93cx6_wren(&ks->eeprom, true);
+
+ /* ethtool currently only supports writing bytes, which means
+ * we have to read/modify/write our 16bit EEPROMs */
+
+ eeprom_93cx6_read(&ks->eeprom, offset/2, &tmp);
+
+ if (offset & 1) {
+ tmp &= 0xff;
+ tmp |= *data << 8;
+ } else {
+ tmp &= 0xff00;
+ tmp |= *data;
+ }
+
+ eeprom_93cx6_write(&ks->eeprom, offset/2, tmp);
+ eeprom_93cx6_wren(&ks->eeprom, false);
+
+ ks8851_eeprom_release(ks);
+
+ return 0;
+}
+
+static int ks8851_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ struct ks8851_net *ks = netdev_priv(dev);
+ int offset = ee->offset;
+ int len = ee->len;
+
+ /* must be 2 byte aligned */
+ if (len & 1 || offset & 1)
+ return -EINVAL;
+
+ if (ks8851_eeprom_claim(ks))
+ return -ENOENT;
+
+ ee->magic = KS_EEPROM_MAGIC;
+
+ eeprom_93cx6_multiread(&ks->eeprom, offset/2, (__le16 *)data, len/2);
+ ks8851_eeprom_release(ks);
+
+ return 0;
+}
+
+static int ks8851_get_eeprom_len(struct net_device *dev)
+{
+ struct ks8851_net *ks = netdev_priv(dev);
+
+ /* currently, we assume it is an 93C46 attached, so return 128 */
+ return ks->rc_ccr & CCR_EEPROM ? 128 : 0;
+}
+
static const struct ethtool_ops ks8851_ethtool_ops = {
.get_drvinfo = ks8851_get_drvinfo,
.get_msglevel = ks8851_get_msglevel,
@@ -1157,6 +1296,9 @@ static const struct ethtool_ops ks8851_e
.set_settings = ks8851_set_settings,
.get_link = ks8851_get_link,
.nway_reset = ks8851_nway_reset,
+ .get_eeprom_len = ks8851_get_eeprom_len,
+ .get_eeprom = ks8851_get_eeprom,
+ .set_eeprom = ks8851_set_eeprom,
};
/* MII interface controls */
@@ -1305,6 +1447,13 @@ static int __devinit ks8851_probe(struct
spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2);
spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2);
+ /* setup EEPROM state */
+
+ ks->eeprom.data = ks;
+ ks->eeprom.width = PCI_EEPROM_WIDTH_93C46;
+ ks->eeprom.register_read = ks8851_eeprom_regread;
+ ks->eeprom.register_write = ks8851_eeprom_regwrite;
+
/* setup mii state */
ks->mii.dev = ndev;
ks->mii.phy_id = 1,
Index: b/drivers/net/Kconfig
===================================================================
--- a/drivers/net/Kconfig 2010-04-28 23:24:20.657052849 +0900
+++ b/drivers/net/Kconfig 2010-04-29 01:22:42.667052653 +0900
@@ -1766,6 +1766,7 @@ config KS8851
depends on SPI
select MII
select CRC32
+ select EEPROM_93CX6
help
SPI driver for Micrel KS8851 SPI attached network chip.
Index: b/drivers/net/ks8851.h
===================================================================
--- a/drivers/net/ks8851.h 2010-04-29 01:00:35.029526937 +0900
+++ b/drivers/net/ks8851.h 2010-04-29 01:22:42.667052653 +0900
@@ -25,6 +25,7 @@
#define OBCR_ODS_16mA (1 << 6)
#define KS_EEPCR 0x22
+#define EEPRC_EESRW (1 << 5)
#define EEPCR_EESA (1 << 4)
#define EEPCR_EESB (1 << 3)
#define EEPCR_EEDO (1 << 2)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 08/13] KSZ8851-SNL: Fix EEPROM access problem
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (6 preceding siblings ...)
2010-04-29 23:16 ` [patch 07/13] KSZ8851-SNL: Add ethtool support for EEPROM Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 09/13] KSZ8851-SNL: Add debugfs export for driver state Ben Dooks
` (4 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Tristram Ha
[-- Attachment #1: thirdparty/micrel/ksz8851-fix-eeprom.patch --]
[-- Type: text/plain, Size: 1304 bytes --]
From: Tristram Ha <Tristram.Ha@micrel.com>
Accessing the EEPROM when the device is receiving sometimes hangs the
system as the hardware is not locked down.
Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com>
[ben@simtec.co.uk: fix description text]
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:22:42.667052653 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:22:47.779528264 +0900
@@ -1181,7 +1181,6 @@ static void ks8851_eeprom_regwrite(struc
if (ee->reg_chip_select)
val |= EEPCR_EECS;
- printk(KERN_INFO "%s: wr %04x\n", __func__, val);
ks8851_wrreg16(ks, KS_EEPCR, val);
}
@@ -1197,6 +1196,8 @@ static int ks8851_eeprom_claim(struct ks
if (!(ks->rc_ccr & CCR_EEPROM))
return -ENOENT;
+ mutex_lock(&ks->lock);
+
/* start with clock low, cs high */
ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS);
return 0;
@@ -1213,6 +1214,7 @@ static void ks8851_eeprom_release(struct
unsigned val = ks8851_rdreg16(ks,KS_EEPCR);
ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA);
+ mutex_unlock(&ks->lock);
}
#define KS_EEPROM_MAGIC (0x00008851)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 09/13] KSZ8851-SNL: Add debugfs export for driver state
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (7 preceding siblings ...)
2010-04-29 23:16 ` [patch 08/13] KSZ8851-SNL: Fix EEPROM access problem Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 10/13] KS8851: ks8851_mll.c: Use the ks8851.h header for device register defines Ben Dooks
` (3 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support
[-- Attachment #1: ks8851-add-debugfs.patch --]
[-- Type: text/plain, Size: 3868 bytes --]
Add the ability to export the state of each network chip via debugfs
to show the cached register state and some of the network device state
information.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/net/ks8851.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:22:47.779528264 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:25:54.217027162 +0900
@@ -21,6 +21,9 @@
#include <linux/mii.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
#include <linux/spi/spi.h>
#include "ks8851.h"
@@ -128,6 +131,9 @@ struct ks8851_net {
struct spi_transfer spi_xfer1;
struct spi_transfer spi_xfer2[2];
+ struct dentry *debug_root;
+ struct dentry *debug_file;
+
struct eeprom_93cx6 eeprom;
};
@@ -1411,6 +1417,91 @@ static int ks8851_read_selftest(struct k
return 0;
}
+/* debugfs code */
+static int state_show(struct seq_file *seq, void *v)
+{
+ struct ks8851_net *ks = seq->private;
+ struct net_device *ndev = ks->netdev;
+
+ seq_printf(seq, "Register cache:\n");
+ seq_printf(seq, "IEQ\t 0x%04x\n", ks->rc_ier);
+ seq_printf(seq, "RXQCR\t 0x%04x\n", ks->rc_rxqcr);
+ seq_printf(seq, "CCR\t 0x%04x\n", ks->rc_ccr);
+ seq_printf(seq, "RXCR1\t 0x%04x\n", ks->rxctrl.rxcr1);
+ seq_printf(seq, "RXCR2\t 0x%04x\n", ks->rxctrl.rxcr2);
+ seq_printf(seq, "MCHASH\t 0=0x%04x, 1=%04x, 2=0x%04x, 3=0x%04x\n",
+ ks->rxctrl.mchash[0], ks->rxctrl.mchash[1],
+ ks->rxctrl.mchash[2], ks->rxctrl.mchash[3]);
+
+ seq_printf(seq, "\n");
+
+ seq_printf(seq, "tx_space = 0x%04x\n", ks->tx_space);
+ seq_printf(seq, "tx fid\t= 0x%02x\n", ks->fid);
+
+ seq_printf(seq, "\n");
+
+ if (ndev->flags & IFF_MULTICAST) {
+ struct dev_mc_list *mcptr = ndev->mc_list;
+ int i;
+
+ seq_printf(seq, "MC list is %d entries\n", ndev->mc_count);
+
+ for (i = 0; i < ndev->mc_count; i++) {
+ seq_printf(seq, "\t%d: %pM\n", i, mcptr->dmi_addr);
+ mcptr = mcptr->next;
+ }
+ } else
+ seq_printf(seq, "No multicast list set\n");
+
+ return 0;
+}
+
+static int state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, state_show, inode->i_private);
+}
+
+static const struct file_operations state_fops = {
+ .owner = THIS_MODULE,
+ .open = state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/**
+ * ks8851_create_debugfs - create debugfs directory and files
+ * @ks: The driver state
+ *
+ * Create the debugfs entries for the specific device.
+ */
+static void __devinit ks8851_create_debugfs(struct ks8851_net *ks)
+{
+ struct dentry *root;
+ char root_name[32];
+
+ snprintf(root_name, sizeof(root_name), "ks8851_%s",
+ dev_name(&ks->spidev->dev));
+
+ root = debugfs_create_dir(root_name, NULL);
+ if (IS_ERR(root)) {
+ ks_err(ks, "cannot create debugfs root\n");
+ return;
+ }
+
+ ks->debug_root = root;
+ ks->debug_file = debugfs_create_file("state", 0444, root,
+ ks, &state_fops);
+ if (IS_ERR(ks->debug_file))
+ ks_err(ks, "cannot create debugfs state file\n");
+}
+
+static void __devexit ks8851_delete_debugfs(struct ks8851_net *ks)
+{
+ debugfs_remove(ks->debug_file);
+ debugfs_remove(ks->debug_root);
+}
+
/* driver bus management functions */
static int __devinit ks8851_probe(struct spi_device *spi)
@@ -1518,6 +1609,8 @@ static int __devinit ks8851_probe(struct
ndev->dev_addr, ndev->irq,
ks->rc_ccr & CCR_EEPROM ? "has" : "no");
+ ks8851_create_debugfs(ks);
+
return 0;
@@ -1537,6 +1630,7 @@ static int __devexit ks8851_remove(struc
if (netif_msg_drv(priv))
dev_info(&spi->dev, "remove");
+ ks8851_delete_debugfs(priv);
unregister_netdev(priv->netdev);
free_irq(spi->irq, priv);
free_netdev(priv->netdev);
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 10/13] KS8851: ks8851_mll.c: Use the ks8851.h header for device register defines
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (8 preceding siblings ...)
2010-04-29 23:16 ` [patch 09/13] KSZ8851-SNL: Add debugfs export for driver state Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 11/13] KS8851: Update ks8851.h header from ks8851_mll.c Ben Dooks
` (2 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support, Ben Dooks
[-- Attachment #1: ks8851-reduce-header-duplication.patch --]
[-- Type: text/plain, Size: 9414 bytes --]
From: Ben Dooks <ben-linux@fluff.org>
The ks8851_mll.c file uses an almost identical copy of ks8851.h included
directly into the source code, baring some identation changes. This patch
removes the commone defines from ks8851_mll.c and includes ks8851.h.
As a note, we did not merge anything that is specific in ks8851_mll.c into
ks8851.h yet.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
---
drivers/net/ks8851_mll.c | 263 -----------------------------------------------
1 file changed, 5 insertions(+), 258 deletions(-)
Index: b/drivers/net/ks8851_mll.c
===================================================================
--- a/drivers/net/ks8851_mll.c 2010-04-28 23:24:20.427026692 +0900
+++ b/drivers/net/ks8851_mll.c 2010-04-29 01:26:00.397035869 +0900
@@ -33,6 +33,8 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include "ks8851.h"
+
#define DRV_NAME "ks8851_mll"
static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 };
@@ -41,165 +43,26 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0
#define TX_BUF_SIZE 2000
#define RX_BUF_SIZE 2000
-#define KS_CCR 0x08
-#define CCR_EEPROM (1 << 9)
-#define CCR_SPI (1 << 8)
#define CCR_8BIT (1 << 7)
#define CCR_16BIT (1 << 6)
#define CCR_32BIT (1 << 5)
#define CCR_SHARED (1 << 4)
-#define CCR_32PIN (1 << 0)
-
-/* MAC address registers */
-#define KS_MARL 0x10
-#define KS_MARM 0x12
-#define KS_MARH 0x14
-#define KS_OBCR 0x20
#define OBCR_ODS_16MA (1 << 6)
-#define KS_EEPCR 0x22
-#define EEPCR_EESA (1 << 4)
-#define EEPCR_EESB (1 << 3)
-#define EEPCR_EEDO (1 << 2)
-#define EEPCR_EESCK (1 << 1)
-#define EEPCR_EECS (1 << 0)
-
-#define KS_MBIR 0x24
-#define MBIR_TXMBF (1 << 12)
-#define MBIR_TXMBFA (1 << 11)
-#define MBIR_RXMBF (1 << 4)
-#define MBIR_RXMBFA (1 << 3)
-
-#define KS_GRR 0x26
-#define GRR_QMU (1 << 1)
-#define GRR_GSR (1 << 0)
-
-#define KS_WFCR 0x2A
-#define WFCR_MPRXE (1 << 7)
-#define WFCR_WF3E (1 << 3)
-#define WFCR_WF2E (1 << 2)
-#define WFCR_WF1E (1 << 1)
-#define WFCR_WF0E (1 << 0)
-
-#define KS_WF0CRC0 0x30
-#define KS_WF0CRC1 0x32
-#define KS_WF0BM0 0x34
-#define KS_WF0BM1 0x36
-#define KS_WF0BM2 0x38
-#define KS_WF0BM3 0x3A
-
-#define KS_WF1CRC0 0x40
-#define KS_WF1CRC1 0x42
-#define KS_WF1BM0 0x44
-#define KS_WF1BM1 0x46
-#define KS_WF1BM2 0x48
-#define KS_WF1BM3 0x4A
-
-#define KS_WF2CRC0 0x50
-#define KS_WF2CRC1 0x52
-#define KS_WF2BM0 0x54
-#define KS_WF2BM1 0x56
-#define KS_WF2BM2 0x58
-#define KS_WF2BM3 0x5A
-
-#define KS_WF3CRC0 0x60
-#define KS_WF3CRC1 0x62
-#define KS_WF3BM0 0x64
-#define KS_WF3BM1 0x66
-#define KS_WF3BM2 0x68
-#define KS_WF3BM3 0x6A
-
-#define KS_TXCR 0x70
-#define TXCR_TCGICMP (1 << 8)
-#define TXCR_TCGUDP (1 << 7)
-#define TXCR_TCGTCP (1 << 6)
-#define TXCR_TCGIP (1 << 5)
-#define TXCR_FTXQ (1 << 4)
-#define TXCR_TXFCE (1 << 3)
-#define TXCR_TXPE (1 << 2)
-#define TXCR_TXCRC (1 << 1)
-#define TXCR_TXE (1 << 0)
-
-#define KS_TXSR 0x72
-#define TXSR_TXLC (1 << 13)
-#define TXSR_TXMC (1 << 12)
-#define TXSR_TXFID_MASK (0x3f << 0)
-#define TXSR_TXFID_SHIFT (0)
-#define TXSR_TXFID_GET(_v) (((_v) >> 0) & 0x3f)
-
-
-#define KS_RXCR1 0x74
-#define RXCR1_FRXQ (1 << 15)
-#define RXCR1_RXUDPFCC (1 << 14)
-#define RXCR1_RXTCPFCC (1 << 13)
-#define RXCR1_RXIPFCC (1 << 12)
-#define RXCR1_RXPAFMA (1 << 11)
-#define RXCR1_RXFCE (1 << 10)
-#define RXCR1_RXEFE (1 << 9)
-#define RXCR1_RXMAFMA (1 << 8)
-#define RXCR1_RXBE (1 << 7)
-#define RXCR1_RXME (1 << 6)
-#define RXCR1_RXUE (1 << 5)
-#define RXCR1_RXAE (1 << 4)
-#define RXCR1_RXINVF (1 << 1)
-#define RXCR1_RXE (1 << 0)
#define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \
RXCR1_RXMAFMA | RXCR1_RXPAFMA)
-#define KS_RXCR2 0x76
-#define RXCR2_SRDBL_MASK (0x7 << 5)
-#define RXCR2_SRDBL_SHIFT (5)
-#define RXCR2_SRDBL_4B (0x0 << 5)
-#define RXCR2_SRDBL_8B (0x1 << 5)
-#define RXCR2_SRDBL_16B (0x2 << 5)
-#define RXCR2_SRDBL_32B (0x3 << 5)
-/* #define RXCR2_SRDBL_FRAME (0x4 << 5) */
-#define RXCR2_IUFFP (1 << 4)
-#define RXCR2_RXIUFCEZ (1 << 3)
-#define RXCR2_UDPLFE (1 << 2)
-#define RXCR2_RXICMPFCC (1 << 1)
-#define RXCR2_RXSAF (1 << 0)
-
-#define KS_TXMIR 0x78
-
-#define KS_RXFHSR 0x7C
-#define RXFSHR_RXFV (1 << 15)
-#define RXFSHR_RXICMPFCS (1 << 13)
-#define RXFSHR_RXIPFCS (1 << 12)
-#define RXFSHR_RXTCPFCS (1 << 11)
-#define RXFSHR_RXUDPFCS (1 << 10)
-#define RXFSHR_RXBF (1 << 7)
-#define RXFSHR_RXMF (1 << 6)
-#define RXFSHR_RXUF (1 << 5)
-#define RXFSHR_RXMR (1 << 4)
-#define RXFSHR_RXFT (1 << 3)
-#define RXFSHR_RXFTL (1 << 2)
-#define RXFSHR_RXRF (1 << 1)
-#define RXFSHR_RXCE (1 << 0)
+#undef RXCR2_SRDBL_FRAME
+
#define RXFSHR_ERR (RXFSHR_RXCE | RXFSHR_RXRF |\
RXFSHR_RXFTL | RXFSHR_RXMR |\
RXFSHR_RXICMPFCS | RXFSHR_RXIPFCS |\
RXFSHR_RXTCPFCS)
+
#define KS_RXFHBCR 0x7E
#define RXFHBCR_CNT_MASK 0x0FFF
-#define KS_TXQCR 0x80
-#define TXQCR_AETFE (1 << 2)
-#define TXQCR_TXQMAM (1 << 1)
-#define TXQCR_METFE (1 << 0)
-
-#define KS_RXQCR 0x82
-#define RXQCR_RXDTTS (1 << 12)
-#define RXQCR_RXDBCTS (1 << 11)
-#define RXQCR_RXFCTS (1 << 10)
-#define RXQCR_RXIPHTOE (1 << 9)
-#define RXQCR_RXDTTE (1 << 7)
-#define RXQCR_RXDBCTE (1 << 6)
-#define RXQCR_RXFCTE (1 << 5)
-#define RXQCR_ADRFE (1 << 4)
-#define RXQCR_SDA (1 << 3)
-#define RXQCR_RRXEF (1 << 0)
#define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE)
#define KS_TXFDPR 0x84
@@ -210,130 +73,14 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0
#define KS_RXFDPR 0x86
#define RXFDPR_RXFPAI (1 << 14)
-#define KS_RXDTTR 0x8C
-#define KS_RXDBCTR 0x8E
-
-#define KS_IER 0x90
-#define KS_ISR 0x92
-#define IRQ_LCI (1 << 15)
-#define IRQ_TXI (1 << 14)
-#define IRQ_RXI (1 << 13)
-#define IRQ_RXOI (1 << 11)
-#define IRQ_TXPSI (1 << 9)
-#define IRQ_RXPSI (1 << 8)
-#define IRQ_TXSAI (1 << 6)
-#define IRQ_RXWFDI (1 << 5)
-#define IRQ_RXMPDI (1 << 4)
-#define IRQ_LDI (1 << 3)
-#define IRQ_EDI (1 << 2)
-#define IRQ_SPIBEI (1 << 1)
-#define IRQ_DEDI (1 << 0)
-
-#define KS_RXFCTR 0x9C
#define RXFCTR_THRESHOLD_MASK 0x00FF
-#define KS_RXFC 0x9D
-#define RXFCTR_RXFC_MASK (0xff << 8)
-#define RXFCTR_RXFC_SHIFT (8)
-#define RXFCTR_RXFC_GET(_v) (((_v) >> 8) & 0xff)
-#define RXFCTR_RXFCT_MASK (0xff << 0)
-#define RXFCTR_RXFCT_SHIFT (0)
-
-#define KS_TXNTFSR 0x9E
-
-#define KS_MAHTR0 0xA0
-#define KS_MAHTR1 0xA2
-#define KS_MAHTR2 0xA4
-#define KS_MAHTR3 0xA6
-
-#define KS_FCLWR 0xB0
-#define KS_FCHWR 0xB2
-#define KS_FCOWR 0xB4
-
-#define KS_CIDER 0xC0
-#define CIDER_ID 0x8870
-#define CIDER_REV_MASK (0x7 << 1)
-#define CIDER_REV_SHIFT (1)
-#define CIDER_REV_GET(_v) (((_v) >> 1) & 0x7)
-
-#define KS_CGCR 0xC6
-#define KS_IACR 0xC8
-#define IACR_RDEN (1 << 12)
-#define IACR_TSEL_MASK (0x3 << 10)
-#define IACR_TSEL_SHIFT (10)
-#define IACR_TSEL_MIB (0x3 << 10)
-#define IACR_ADDR_MASK (0x1f << 0)
-#define IACR_ADDR_SHIFT (0)
-
-#define KS_IADLR 0xD0
-#define KS_IAHDR 0xD2
-
-#define KS_PMECR 0xD4
-#define PMECR_PME_DELAY (1 << 14)
-#define PMECR_PME_POL (1 << 12)
-#define PMECR_WOL_WAKEUP (1 << 11)
-#define PMECR_WOL_MAGICPKT (1 << 10)
-#define PMECR_WOL_LINKUP (1 << 9)
-#define PMECR_WOL_ENERGY (1 << 8)
-#define PMECR_AUTO_WAKE_EN (1 << 7)
-#define PMECR_WAKEUP_NORMAL (1 << 6)
-#define PMECR_WKEVT_MASK (0xf << 2)
-#define PMECR_WKEVT_SHIFT (2)
-#define PMECR_WKEVT_GET(_v) (((_v) >> 2) & 0xf)
-#define PMECR_WKEVT_ENERGY (0x1 << 2)
-#define PMECR_WKEVT_LINK (0x2 << 2)
-#define PMECR_WKEVT_MAGICPKT (0x4 << 2)
-#define PMECR_WKEVT_FRAME (0x8 << 2)
-#define PMECR_PM_MASK (0x3 << 0)
-#define PMECR_PM_SHIFT (0)
-#define PMECR_PM_NORMAL (0x0 << 0)
-#define PMECR_PM_ENERGY (0x1 << 0)
-#define PMECR_PM_SOFTDOWN (0x2 << 0)
-#define PMECR_PM_POWERSAVE (0x3 << 0)
-
-/* Standard MII PHY data */
-#define KS_P1MBCR 0xE4
#define P1MBCR_FORCE_FDX (1 << 8)
-#define KS_P1MBSR 0xE6
#define P1MBSR_AN_COMPLETE (1 << 5)
#define P1MBSR_AN_CAPABLE (1 << 3)
#define P1MBSR_LINK_UP (1 << 2)
-#define KS_PHY1ILR 0xE8
-#define KS_PHY1IHR 0xEA
-#define KS_P1ANAR 0xEC
-#define KS_P1ANLPR 0xEE
-
-#define KS_P1SCLMD 0xF4
-#define P1SCLMD_LEDOFF (1 << 15)
-#define P1SCLMD_TXIDS (1 << 14)
-#define P1SCLMD_RESTARTAN (1 << 13)
-#define P1SCLMD_DISAUTOMDIX (1 << 10)
-#define P1SCLMD_FORCEMDIX (1 << 9)
-#define P1SCLMD_AUTONEGEN (1 << 7)
-#define P1SCLMD_FORCE100 (1 << 6)
-#define P1SCLMD_FORCEFDX (1 << 5)
-#define P1SCLMD_ADV_FLOW (1 << 4)
-#define P1SCLMD_ADV_100BT_FDX (1 << 3)
-#define P1SCLMD_ADV_100BT_HDX (1 << 2)
-#define P1SCLMD_ADV_10BT_FDX (1 << 1)
-#define P1SCLMD_ADV_10BT_HDX (1 << 0)
-
-#define KS_P1CR 0xF6
-#define P1CR_HP_MDIX (1 << 15)
-#define P1CR_REV_POL (1 << 13)
-#define P1CR_OP_100M (1 << 10)
-#define P1CR_OP_FDX (1 << 9)
-#define P1CR_OP_MDI (1 << 7)
-#define P1CR_AN_DONE (1 << 6)
-#define P1CR_LINK_GOOD (1 << 5)
-#define P1CR_PNTR_FLOW (1 << 4)
-#define P1CR_PNTR_100BT_FDX (1 << 3)
-#define P1CR_PNTR_100BT_HDX (1 << 2)
-#define P1CR_PNTR_10BT_FDX (1 << 1)
-#define P1CR_PNTR_10BT_HDX (1 << 0)
-
/* TX Frame control */
#define TXFR_TXIC (1 << 15)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 11/13] KS8851: Update ks8851.h header from ks8851_mll.c
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (9 preceding siblings ...)
2010-04-29 23:16 ` [patch 10/13] KS8851: ks8851_mll.c: Use the ks8851.h header for device register defines Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 12/13] KS8851: Use the ks8851.h header to hold union ks8851_tx_hdr Ben Dooks
2010-04-29 23:16 ` [patch 13/13] KSZ8851-SNL: Add platform data to specific IRQ trigger type Ben Dooks
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support
[-- Attachment #1: ks8851-reduce-header-duplication2.patch --]
[-- Type: text/plain, Size: 4272 bytes --]
Move more useful definitions from ks8851_mll.c into ks8851.h and include
a brief copyright update from the mll source file. Also mop up a few
definitions that got missed in the first patch.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.h | 27 +++++++++++++++++++++++++++
drivers/net/ks8851_mll.c | 40 +---------------------------------------
2 files changed, 28 insertions(+), 39 deletions(-)
Index: b/drivers/net/ks8851.h
===================================================================
--- a/drivers/net/ks8851.h 2010-04-20 18:38:38.000000000 +0100
+++ b/drivers/net/ks8851.h 2010-04-20 18:39:02.000000000 +0100
@@ -3,6 +3,9 @@
* Copyright 2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
+ * portions from drivers/net/ks8851_mll.c,
+ * Copyright (c) 2009 Micrel Inc.
+ *
* KS8851 register definitions
*
* This program is free software; you can redistribute it and/or modify
@@ -13,6 +16,10 @@
#define KS_CCR 0x08
#define CCR_EEPROM (1 << 9)
#define CCR_SPI (1 << 8)
+#define CCR_8BIT (1 << 7)
+#define CCR_16BIT (1 << 6)
+#define CCR_32BIT (1 << 5)
+#define CCR_SHARED (1 << 4)
#define CCR_32PIN (1 << 0)
/* MAC address registers */
@@ -250,7 +257,13 @@
/* Standard MII PHY data */
#define KS_P1MBCR 0xE4
+#define P1MBCR_FORCE_FDX (1 << 8)
+
#define KS_P1MBSR 0xE6
+#define P1MBSR_AN_COMPLETE (1 << 5)
+#define P1MBSR_AN_CAPABLE (1 << 3)
+#define P1MBSR_LINK_UP (1 << 2)
+
#define KS_PHY1ILR 0xE8
#define KS_PHY1IHR 0xEA
#define KS_P1ANAR 0xEC
@@ -285,6 +298,20 @@
#define P1CR_PNTR_10BT_FDX (1 << 1)
#define P1CR_PNTR_10BT_HDX (1 << 0)
+#define KS_P1SR 0xF8
+#define P1SR_HP_MDIX (1 << 15)
+#define P1SR_REV_POL (1 << 13)
+#define P1SR_OP_100M (1 << 10)
+#define P1SR_OP_FDX (1 << 9)
+#define P1SR_OP_MDI (1 << 7)
+#define P1SR_AN_DONE (1 << 6)
+#define P1SR_LINK_GOOD (1 << 5)
+#define P1SR_PNTR_FLOW (1 << 4)
+#define P1SR_PNTR_100BT_FDX (1 << 3)
+#define P1SR_PNTR_100BT_HDX (1 << 2)
+#define P1SR_PNTR_10BT_FDX (1 << 1)
+#define P1SR_PNTR_10BT_HDX (1 << 0)
+
/* TX Frame control */
#define TXFR_TXIC (1 << 15)
Index: b/drivers/net/ks8851_mll.c
===================================================================
--- a/drivers/net/ks8851_mll.c 2010-04-20 18:38:42.000000000 +0100
+++ b/drivers/net/ks8851_mll.c 2010-04-20 18:39:02.000000000 +0100
@@ -43,13 +43,6 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0
#define TX_BUF_SIZE 2000
#define RX_BUF_SIZE 2000
-#define CCR_8BIT (1 << 7)
-#define CCR_16BIT (1 << 6)
-#define CCR_32BIT (1 << 5)
-#define CCR_SHARED (1 << 4)
-
-#define OBCR_ODS_16MA (1 << 6)
-
#define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \
RXCR1_RXMAFMA | RXCR1_RXPAFMA)
@@ -65,41 +58,10 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0
#define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE)
-#define KS_TXFDPR 0x84
-#define TXFDPR_TXFPAI (1 << 14)
-#define TXFDPR_TXFP_MASK (0x7ff << 0)
-#define TXFDPR_TXFP_SHIFT (0)
-
-#define KS_RXFDPR 0x86
-#define RXFDPR_RXFPAI (1 << 14)
-
#define RXFCTR_THRESHOLD_MASK 0x00FF
-#define P1MBCR_FORCE_FDX (1 << 8)
-
-#define P1MBSR_AN_COMPLETE (1 << 5)
-#define P1MBSR_AN_CAPABLE (1 << 3)
-#define P1MBSR_LINK_UP (1 << 2)
-
/* TX Frame control */
-#define TXFR_TXIC (1 << 15)
-#define TXFR_TXFID_MASK (0x3f << 0)
-#define TXFR_TXFID_SHIFT (0)
-
-#define KS_P1SR 0xF8
-#define P1SR_HP_MDIX (1 << 15)
-#define P1SR_REV_POL (1 << 13)
-#define P1SR_OP_100M (1 << 10)
-#define P1SR_OP_FDX (1 << 9)
-#define P1SR_OP_MDI (1 << 7)
-#define P1SR_AN_DONE (1 << 6)
-#define P1SR_LINK_GOOD (1 << 5)
-#define P1SR_PNTR_FLOW (1 << 4)
-#define P1SR_PNTR_100BT_FDX (1 << 3)
-#define P1SR_PNTR_100BT_HDX (1 << 2)
-#define P1SR_PNTR_10BT_FDX (1 << 1)
-#define P1SR_PNTR_10BT_HDX (1 << 0)
#define ENUM_BUS_NONE 0
#define ENUM_BUS_8BIT 1
@@ -1362,7 +1324,7 @@ static int __devinit ks8851_probe(struct
memcpy(netdev->dev_addr, ks->mac_addr, 6);
data = ks_rdreg16(ks, KS_OBCR);
- ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA);
+ ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16mA);
/**
* If you want to use the default MAC addr,
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 12/13] KS8851: Use the ks8851.h header to hold union ks8851_tx_hdr
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (10 preceding siblings ...)
2010-04-29 23:16 ` [patch 11/13] KS8851: Update ks8851.h header from ks8851_mll.c Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
2010-04-29 23:16 ` [patch 13/13] KSZ8851-SNL: Add platform data to specific IRQ trigger type Ben Dooks
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support
[-- Attachment #1: ks8851-reduce-header-duplication3.patch --]
[-- Type: text/plain, Size: 3035 bytes --]
The union ks8851_tx_hdr turns up in both ks8851.c and ks8851_mll.c in two
different formats, thus making a common version in ks8851.h is going to
save source file usage.
The ks8851_mll.c uses the name ks_tx_hdr instead of ks8851_tx_hdr, so
rename this instance.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
---
drivers/net/ks8851.c | 13 -------------
drivers/net/ks8851.h | 14 ++++++++++++++
drivers/net/ks8851_mll.c | 16 +---------------
3 files changed, 15 insertions(+), 28 deletions(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:25:54.217027162 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:28:32.719525804 +0900
@@ -46,19 +46,6 @@ struct ks8851_rxctrl {
u16 rxcr2;
};
-/**
- * union ks8851_tx_hdr - tx header data
- * @txb: The header as bytes
- * @txw: The header as 16bit, little-endian words
- *
- * A dual representation of the tx header data to allow
- * access to individual bytes, and to allow 16bit accesses
- * with 16bit alignment.
- */
-union ks8851_tx_hdr {
- u8 txb[6];
- __le16 txw[3];
-};
/**
* struct ks8851_net - KS8851 driver private data
Index: b/drivers/net/ks8851.h
===================================================================
--- a/drivers/net/ks8851.h 2010-04-29 01:26:03.329527219 +0900
+++ b/drivers/net/ks8851.h 2010-04-29 01:26:04.169526711 +0900
@@ -323,3 +323,17 @@
#define KS_SPIOP_WR (0x40)
#define KS_SPIOP_RXFIFO (0x80)
#define KS_SPIOP_TXFIFO (0xC0)
+
+/**
+ * union ks8851_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks8851_tx_hdr {
+ u8 txb[6];
+ __le16 txw[3];
+};
Index: b/drivers/net/ks8851_mll.c
===================================================================
--- a/drivers/net/ks8851_mll.c 2010-04-29 01:26:03.329527219 +0900
+++ b/drivers/net/ks8851_mll.c 2010-04-29 01:26:04.169526711 +0900
@@ -73,20 +73,6 @@ static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0
#define MAC_ADDR_LEN 6
/**
- * union ks_tx_hdr - tx header data
- * @txb: The header as bytes
- * @txw: The header as 16bit, little-endian words
- *
- * A dual representation of the tx header data to allow
- * access to individual bytes, and to allow 16bit accesses
- * with 16bit alignment.
- */
-union ks_tx_hdr {
- u8 txb[4];
- __le16 txw[2];
-};
-
-/**
* struct ks_net - KS8851 driver private data
* @net_device : The network device we're bound to
* @hw_addr : start address of data register.
@@ -138,7 +124,7 @@ struct ks_net {
struct net_device *netdev;
void __iomem *hw_addr;
void __iomem *hw_addr_cmd;
- union ks_tx_hdr txh ____cacheline_aligned;
+ union ks8851_tx_hdr txh ____cacheline_aligned;
struct mutex lock; /* spinlock to be interrupt safe */
struct platform_device *pdev;
struct mii_if_info mii;
^ permalink raw reply [flat|nested] 21+ messages in thread
* [patch 13/13] KSZ8851-SNL: Add platform data to specific IRQ trigger type.
2010-04-29 23:16 [patch 00/13] Micrel KSZ8851 updates and fixes Ben Dooks
` (11 preceding siblings ...)
2010-04-29 23:16 ` [patch 12/13] KS8851: Use the ks8851.h header to hold union ks8851_tx_hdr Ben Dooks
@ 2010-04-29 23:16 ` Ben Dooks
12 siblings, 0 replies; 21+ messages in thread
From: Ben Dooks @ 2010-04-29 23:16 UTC (permalink / raw)
To: netdev; +Cc: tristram.ha, support
[-- Attachment #1: ks8851-add-platform-data.patch --]
[-- Type: text/plain, Size: 3786 bytes --]
Add platform data to allow the board registering the SPI device to
pass what IRQ trigger type it needs to the driver. The default of
low-level trigger is used if no data is specified, or the field is
zero.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/net/ks8851.c | 27 +++++++++++++++++++++++----
include/linux/ks8851.h | 23 +++++++++++++++++++++++
2 files changed, 46 insertions(+), 4 deletions(-)
Index: b/drivers/net/ks8851.c
===================================================================
--- a/drivers/net/ks8851.c 2010-04-29 01:28:32.719525804 +0900
+++ b/drivers/net/ks8851.c 2010-04-29 01:28:37.229527494 +0900
@@ -20,6 +20,7 @@
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/ks8851.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -70,6 +71,7 @@ struct ks8851_rxctrl {
* @rc_ccr: Cached copy of KS_CCR.
* @rc_rxqcr: Cached copy of KS_RXQCR.
* @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM.
+ * @irq_flags: The IRQ flags passed to request_irq().
*
* The @lock ensures that the chip is protected when certain operations are
* in progress. When the read or write packet transfer is in progress, most
@@ -439,6 +441,15 @@ static void ks8851_init_mac(struct ks885
}
/**
+ * is_level_irq() - return if the given IRQ flags are level triggered
+ * @flags: The flags passed to request_irq().
+*/
+static bool is_level_irq(unsigned flags)
+{
+ return flags & (IRQF_TIRGGER_LOW | IRQF_TRIGGER_HIGH);
+}
+
+/**
* ks8851_irq - device interrupt handler
* @irq: Interrupt number passed from the IRQ hnalder.
* @pw: The private word passed to register_irq(), our struct ks8851_net.
@@ -450,7 +461,9 @@ static irqreturn_t ks8851_irq(int irq, v
{
struct ks8851_net *ks = pw;
- disable_irq_nosync(irq);
+ if (is_level_irq(ks->irq_flags))
+ disable_irq_nosync(irq);
+
schedule_work(&ks->irq_work);
return IRQ_HANDLED;
}
@@ -674,7 +687,8 @@ static void ks8851_irq_work(struct work_
mutex_unlock(&ks->lock);
- enable_irq(ks->netdev->irq);
+ if (is_level_irq(ks->irq_flags))
+ enable_irq(ks->netdev->irq);
}
/**
@@ -1493,6 +1507,7 @@ static void __devexit ks8851_delete_debu
static int __devinit ks8851_probe(struct spi_device *spi)
{
+ struct ks8851_pdata *pd = spi->dev.platform_data;
struct net_device *ndev;
struct ks8851_net *ks;
int ret;
@@ -1578,8 +1593,12 @@ static int __devinit ks8851_probe(struct
ks8851_read_selftest(ks);
ks8851_init_mac(ks);
- ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
- ndev->name, ks);
+ if (pd && pd->irq_flags)
+ ks->irq_flags = pd->irq_flags;
+ else
+ ks->irq_flags = IRQF_TRIGGER_LOW;
+
+ ret = request_irq(spi->irq, ks8851_irq, ks->irq_flags, ndev->name, ks);
if (ret < 0) {
dev_err(&spi->dev, "failed to get irq\n");
goto err_irq;
Index: b/include/linux/ks8851.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/include/linux/ks8851.h 2010-04-29 01:28:37.000000000 +0900
@@ -0,0 +1,23 @@
+/* include/linux/ks8851.h
+ *
+ * Platform specific configuration data for KS8851 driver.
+ *
+ * Copyright 2009 Simtec Electronics
+ * http://www.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * struct ks8851_pdata - platform specific configuration data
+ * @irq_flags: The IRQ trigger flags to pass to request_irq().
+ *
+ * Platform specific configuration to be passed from board support
+ * registering the spi device to the driver.
+ */
+struct ks8851_pdata {
+ unsigned irq_flags;
+};
^ permalink raw reply [flat|nested] 21+ messages in thread