Re: [PATCH] pcnet32: fix a logic error with pci_set_dma_mask

2015-10-21 Thread Don Fry
On Mon, 2015-10-12 at 05:38 -0700, David Miller wrote:
> From: Geliang Tang <geliangt...@163.com>
> Date: Fri,  9 Oct 2015 03:45:39 -0700
> 
> > pcnet32 can't work on my machine recently. It says "architecture
> > does not support 32bit PCI busmaster DMA". There is a logic error
> > in it: pci_set_dma_mask() return 0 means return successfully.
> > 
> > Signed-off-by: Geliang Tang <geliangt...@163.com>
> 
> This driver doesn't call pci_set_dma_mask() in any of my tree(s).
I failed.  My system with pcnet32 boards was down with a dead power
supply and a visual review was not good enough.  I missed that
pci_dma_supported returns 1 on success and pci_set_dma_mask returns 0 on
success.  The original patch needs to have the ! removed as Geliang Tang
points out.

Acked-by:  Don Fry <pcne...@frontier.com>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 01/15] pcnet32: use pci_set_dma_mask insted of pci_dma_supported

2015-10-05 Thread Don Fry
On Sat, 2015-10-03 at 17:19 +0200, Christoph Hellwig wrote:
> This ensures the dma mask that is supported by the driver is recorded
> in the device structure.
> 
> Signed-off-by: Christoph Hellwig <h...@lst.de>
> ---
>  drivers/net/ethernet/amd/pcnet32.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Acked-by: Don Fry <pcne...@frontier.com>

> diff --git a/drivers/net/ethernet/amd/pcnet32.c 
> b/drivers/net/ethernet/amd/pcnet32.c
> index bc8b04f..e2afabf 100644
> --- a/drivers/net/ethernet/amd/pcnet32.c
> +++ b/drivers/net/ethernet/amd/pcnet32.c
> @@ -1500,7 +1500,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct 
> pci_device_id *ent)
>   return -ENODEV;
>   }
>  
> - if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {
> + if (!pci_set_dma_mask(pdev, PCNET32_DMA_MASK)) {
>   if (pcnet32_debug & NETIF_MSG_PROBE)
>   pr_err("architecture does not support 32bit PCI 
> busmaster DMA\n");
>   return -ENODEV;


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2.6.24] pcnet32: Use print_mac

2008-02-08 Thread Don Fry
Signed-off-by: Joe Perches [EMAIL PROTECTED]
Acked-by:  Don Fry [EMAIL PROTECTED]
---
Originally sent by Joe Dec 14, 2007
Tested by Don on amd_64

--- linux-2.6.24-git13/drivers/net/orig.pcnet32.c   2008-02-04 
10:05:48.0 -0800
+++ linux-2.6.24-git18/drivers/net/pcnet32.c2008-02-04 10:59:08.0 
-0800
@@ -1774,8 +1774,8 @@ pcnet32_probe1(unsigned long ioaddr, int
memset(dev-dev_addr, 0, sizeof(dev-dev_addr));
 
if (pcnet32_debug  NETIF_MSG_PROBE) {
-   for (i = 0; i  6; i++)
-   printk( %2.2x, dev-dev_addr[i]);
+   DECLARE_MAC_BUF(mac);
+   printk( %s, print_mac(mac, dev-dev_addr));
 
/* Version 0x2623 and 0x2624 */
if (((chip_version + 1)  0xfffe) == 0x2624) {


--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2.6.24] pcnet32: use NET_IP_ALIGN instead of 2

2008-02-08 Thread Don Fry
Change hard coded 2 to NET_IP_ALIGN.  Added new #define with comments.
Tested amd_64

Signed-off-by:  Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.24-git13/drivers/net/joe.pcnet32.c2008-02-04 
10:59:08.0 -0800
+++ linux-2.6.24-git18/drivers/net/pcnet32.c2008-02-08 07:20:44.0 
-0800
@@ -174,7 +174,11 @@ static int homepna[MAX_UNITS];
 #define RX_RING_SIZE   (1  (PCNET32_LOG_RX_BUFFERS))
 #define RX_MAX_RING_SIZE   (1  (PCNET32_LOG_MAX_RX_BUFFERS))
 
-#define PKT_BUF_SZ 1544
+#define PKT_BUF_SKB1544
+/* actual buffer length after being aligned */
+#define PKT_BUF_SIZE   (PKT_BUF_SKB - NET_IP_ALIGN)
+/* chip wants twos complement of the (aligned) buffer length */
+#define NEG_BUF_SIZE   (NET_IP_ALIGN - PKT_BUF_SKB)
 
 /* Offsets from base I/O address. */
 #define PCNET32_WIO_RDP0x10
@@ -604,7 +608,7 @@ static void pcnet32_realloc_rx_ring(stru
/* now allocate any new buffers needed */
for (; new  size; new++ ) {
struct sk_buff *rx_skbuff;
-   new_skb_list[new] = dev_alloc_skb(PKT_BUF_SZ);
+   new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB);
if (!(rx_skbuff = new_skb_list[new])) {
/* keep the original lists and buffers */
if (netif_msg_drv(lp))
@@ -613,20 +617,20 @@ static void pcnet32_realloc_rx_ring(stru
   dev-name);
goto free_all_new;
}
-   skb_reserve(rx_skbuff, 2);
+   skb_reserve(rx_skbuff, NET_IP_ALIGN);
 
new_dma_addr_list[new] =
pci_map_single(lp-pci_dev, rx_skbuff-data,
-  PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+  PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]);
-   new_rx_ring[new].buf_length = cpu_to_le16(2 - PKT_BUF_SZ);
+   new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE);
new_rx_ring[new].status = cpu_to_le16(0x8000);
}
/* and free any unneeded buffers */
for (; new  lp-rx_ring_size; new++) {
if (lp-rx_skbuff[new]) {
pci_unmap_single(lp-pci_dev, lp-rx_dma_addr[new],
-PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
dev_kfree_skb(lp-rx_skbuff[new]);
}
}
@@ -651,7 +655,7 @@ static void pcnet32_realloc_rx_ring(stru
for (; --new = lp-rx_ring_size; ) {
if (new_skb_list[new]) {
pci_unmap_single(lp-pci_dev, new_dma_addr_list[new],
-PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
dev_kfree_skb(new_skb_list[new]);
}
}
@@ -678,7 +682,7 @@ static void pcnet32_purge_rx_ring(struct
wmb();  /* Make sure adapter sees owner change */
if (lp-rx_skbuff[i]) {
pci_unmap_single(lp-pci_dev, lp-rx_dma_addr[i],
-PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(lp-rx_skbuff[i]);
}
lp-rx_skbuff[i] = NULL;
@@ -1201,7 +1205,7 @@ static void pcnet32_rx_entry(struct net_
pkt_len = (le32_to_cpu(rxp-msg_length)  0xfff) - 4;
 
/* Discard oversize frames. */
-   if (unlikely(pkt_len  PKT_BUF_SZ - 2)) {
+   if (unlikely(pkt_len  PKT_BUF_SIZE)) {
if (netif_msg_drv(lp))
printk(KERN_ERR %s: Impossible packet size %d!\n,
   dev-name, pkt_len);
@@ -1218,26 +1222,26 @@ static void pcnet32_rx_entry(struct net_
if (pkt_len  rx_copybreak) {
struct sk_buff *newskb;
 
-   if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) {
-   skb_reserve(newskb, 2);
+   if ((newskb = dev_alloc_skb(PKT_BUF_SKB))) {
+   skb_reserve(newskb, NET_IP_ALIGN);
skb = lp-rx_skbuff[entry];
pci_unmap_single(lp-pci_dev,
 lp-rx_dma_addr[entry],
-PKT_BUF_SZ - 2,
+PKT_BUF_SIZE,
 PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_len);
lp-rx_skbuff[entry] = newskb;
lp-rx_dma_addr[entry] =
pci_map_single(lp-pci_dev

Re: [PATCH 5/7]: [NET]: Fix drivers to handle napi_disable() disabling interrupts.

2008-01-08 Thread Don Fry
Tested pcnet32 on x86_64 box and see no problems with the change.
The code is only exercised if doing loopback testing, or changing
the ring size during a receive storm.

Acked-by:  Don Fry [EMAIL PROTECTED]
---

[NET]: Fix drivers to handle napi_disable() disabling interrupts.

When we add the generic napi_disable_pending() breakout
logic to net_rx_action() it means that napi_disable()
can cause NAPI poll interrupt events to be disabled.

And this is exactly what we want.  If a napi_disable()
is pending, and we are looping in the -poll(), we want
-poll() event interrupts to stay disabled and we want
to complete the NAPI poll ASAP.

When -poll() break out during device down was being handled on a
per-driver basis, often these drivers would turn interrupts back on
when '!netif_running()' was detected.

And this would just cause a reschedule of the NAPI -poll() in the
interrupt handler before the napi_disable() could get in there and
grab the NAPI_STATE_SCHED bit.

The vast majority of drivers don't care if napi_disable() might have
the side effect of disabling NAPI -poll() event interrupts.  In all
such cases, when a napi_disable() is performed, the driver just
disabled interrupts or is about to.

However there were three exceptions to this in PCNET32, R8169, and
SKY2.  To fix those cases, at the subsequent napi_enable() points, I
added code to ensure that the -poll() interrupt events are enabled in
the hardware.

Signed-off-by: David S. Miller [EMAIL PROTECTED]
---
 drivers/net/pcnet32.c |5 +
 drivers/net/r8169.c   |2 ++
 drivers/net/sky2.c|3 +++
 3 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ff92aca..90498ff 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -455,9 +455,14 @@ static void pcnet32_netif_start(struct net_device
*dev)
 {
 #ifdef CONFIG_PCNET32_NAPI
struct pcnet32_private *lp = netdev_priv(dev);
+   ulong ioaddr = dev-base_addr;
+   u16 val;
 #endif
netif_wake_queue(dev);
 #ifdef CONFIG_PCNET32_NAPI
+   val = lp-a.read_csr(ioaddr, CSR3);
+   val = 0x00ff;
+   lp-a.write_csr(ioaddr, CSR3, val);
napi_enable(lp-napi);
 #endif
 }
-- 
1.5.4.rc2.38.gd6da3

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html



--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: fix non-napi packet reception

2007-10-17 Thread Don Fry
Recent changes to the driver for the new napi API broke the reception of 
packets when in
non-napi mode.  The initialization of napi.weight was removed for the non-napi 
case
leaving the value zero.

Tested NAPI and non-NAPI on x86_64.

Signed-off-by: Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.23-git7/drivers/net/orig.pcnet32.c2007-10-15 
11:19:17.0 -0700
+++ linux-2.6.23-git7/drivers/net/pcnet32.c 2007-10-17 15:56:15.0 
-0700
@@ -1849,6 +1849,9 @@ pcnet32_probe1(unsigned long ioaddr, int
lp-mii_if.mdio_read = mdio_read;
lp-mii_if.mdio_write = mdio_write;
 
+   /* napi.weight is used in both the napi and non-napi cases */
+   lp-napi.weight = lp-rx_ring_size / 2;
+
 #ifdef CONFIG_PCNET32_NAPI
netif_napi_add(dev, lp-napi, pcnet32_poll, lp-rx_ring_size / 2);
 #endif


-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: remove compile warnings in non-napi mode

2007-10-17 Thread Don Fry
Remove compile warning when in non-napi mode.

Signed-off-by:  Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.23-git7/drivers/net/napi.pcnet32.c2007-10-17 
15:56:15.0 -0700
+++ linux-2.6.23-git7/drivers/net/pcnet32.c 2007-10-17 16:00:44.0 
-0700
@@ -442,7 +442,9 @@ static struct pcnet32_access pcnet32_dwi
 
 static void pcnet32_netif_stop(struct net_device *dev)
 {
+#ifdef CONFIG_PCNET32_NAPI
struct pcnet32_private *lp = netdev_priv(dev);
+#endif
dev-trans_start = jiffies;
 #ifdef CONFIG_PCNET32_NAPI
napi_disable(lp-napi);
@@ -452,7 +454,9 @@ static void pcnet32_netif_stop(struct ne
 
 static void pcnet32_netif_start(struct net_device *dev)
 {
+#ifdef CONFIG_PCNET32_NAPI
struct pcnet32_private *lp = netdev_priv(dev);
+#endif
netif_wake_queue(dev);
 #ifdef CONFIG_PCNET32_NAPI
napi_enable(lp-napi);


-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] pcnet32: fix non-napi packet reception

2007-10-17 Thread Don Fry
In general, we're hoping to remove as many CONFIG_FOO_NAPI as possible,
pushing everybody towards using NAPI.

Any objection to heading in this direction with pcnet32?

Jeff

I have no objections myself.  It has been slowly moving that direction.
First with the napi implementation, default off, labeled experimental.
Then removing experimental and then making the default on.

If any other user of the pcnet32 has objections, now is the time to
speak loudly!

Don

-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: remove private net_device_stats structure

2007-10-17 Thread Don Fry
Remove the statistics from the private structure.
Use the net_device_stats in netn_device structure.

Following Jeff Garzik's massive cleanup Sep 01.
pcnet32 was not low-hanging fruit.

Tested x86_64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.23-git7/drivers/net/cleaner.pcnet32.c 2007-10-17 
16:00:44.0 -0700
+++ linux-2.6.23-git7/drivers/net/pcnet32.c 2007-10-17 16:44:50.0 
-0700
@@ -282,7 +282,6 @@ struct pcnet32_private {
 
struct net_device   *dev;
struct napi_struct  napi;
-   struct net_device_stats stats;
chartx_full;
charphycount;   /* number of phys found */
int options;
@@ -1182,15 +1181,15 @@ static void pcnet32_rx_entry(struct net_
 * buffers, with only the last correctly noting the error.
 */
if (status  0x01)  /* Only count a general error at the */
-   lp-stats.rx_errors++;  /* end of a packet. */
+   dev-stats.rx_errors++; /* end of a packet. */
if (status  0x20)
-   lp-stats.rx_frame_errors++;
+   dev-stats.rx_frame_errors++;
if (status  0x10)
-   lp-stats.rx_over_errors++;
+   dev-stats.rx_over_errors++;
if (status  0x08)
-   lp-stats.rx_crc_errors++;
+   dev-stats.rx_crc_errors++;
if (status  0x04)
-   lp-stats.rx_fifo_errors++;
+   dev-stats.rx_fifo_errors++;
return;
}
 
@@ -1201,13 +1200,13 @@ static void pcnet32_rx_entry(struct net_
if (netif_msg_drv(lp))
printk(KERN_ERR %s: Impossible packet size %d!\n,
   dev-name, pkt_len);
-   lp-stats.rx_errors++;
+   dev-stats.rx_errors++;
return;
}
if (pkt_len  60) {
if (netif_msg_rx_err(lp))
printk(KERN_ERR %s: Runt packet!\n, dev-name);
-   lp-stats.rx_errors++;
+   dev-stats.rx_errors++;
return;
}
 
@@ -1241,7 +1240,7 @@ static void pcnet32_rx_entry(struct net_
printk(KERN_ERR
   %s: Memory squeeze, dropping packet.\n,
   dev-name);
-   lp-stats.rx_dropped++;
+   dev-stats.rx_dropped++;
return;
}
skb-dev = dev;
@@ -1260,7 +1259,7 @@ static void pcnet32_rx_entry(struct net_
   pkt_len,
   PCI_DMA_FROMDEVICE);
}
-   lp-stats.rx_bytes += skb-len;
+   dev-stats.rx_bytes += skb-len;
skb-protocol = eth_type_trans(skb, dev);
 #ifdef CONFIG_PCNET32_NAPI
netif_receive_skb(skb);
@@ -1268,7 +1267,7 @@ static void pcnet32_rx_entry(struct net_
netif_rx(skb);
 #endif
dev-last_rx = jiffies;
-   lp-stats.rx_packets++;
+   dev-stats.rx_packets++;
return;
 }
 
@@ -1316,21 +1315,21 @@ static int pcnet32_tx(struct net_device 
if (status  0x4000) {
/* There was a major error, log it. */
int err_status = le32_to_cpu(lp-tx_ring[entry].misc);
-   lp-stats.tx_errors++;
+   dev-stats.tx_errors++;
if (netif_msg_tx_err(lp))
printk(KERN_ERR
   %s: Tx error status=%04x 
err_status=%08x\n,
   dev-name, status,
   err_status);
if (err_status  0x0400)
-   lp-stats.tx_aborted_errors++;
+   dev-stats.tx_aborted_errors++;
if (err_status  0x0800)
-   lp-stats.tx_carrier_errors++;
+   dev-stats.tx_carrier_errors++;
if (err_status  0x1000)
-   lp-stats.tx_window_errors++;
+   dev-stats.tx_window_errors++;
 #ifndef DO_DXSUFLO
if (err_status  0x4000) {
-   lp-stats.tx_fifo_errors++;
+   dev-stats.tx_fifo_errors++;
/* Ackk!  On FIFO errors the Tx unit is turned 
off! */
/* Remove this verbosity later! */
if (netif_msg_tx_err(lp))
@@ -1341,7 +1340,7 @@ static int pcnet32_tx(struct net_device 
}
 #else
if (err_status  0x4000) {
-   lp

[PATCH] pcnet32: add suspend and resume capability

2007-08-26 Thread Don Fry
Add suspend and resume capability to the driver.
Tested both to ram and to disk on x86_64 platform.

Signed-off-by:  Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.23-rc3/drivers/net/pcnet32.c.orig 2007-08-14 13:52:24.0 
-0700
+++ linux-2.6.23-rc3/drivers/net/pcnet32.c  2007-08-14 14:16:55.0 
-0700
@@ -23,11 +23,11 @@
 
 #define DRV_NAME   pcnet32
 #ifdef CONFIG_PCNET32_NAPI
-#define DRV_VERSION1.33-NAPI
+#define DRV_VERSION1.34-NAPI
 #else
-#define DRV_VERSION1.33
+#define DRV_VERSION1.34
 #endif
-#define DRV_RELDATE27.Jun.2006
+#define DRV_RELDATE14.Aug.2007
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -2943,6 +2943,33 @@ static void pcnet32_watchdog(struct net_
mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
 }
 
+static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+   struct net_device *dev = pci_get_drvdata(pdev);
+
+   if (netif_running(dev)) {
+   netif_device_detach(dev);
+   pcnet32_close(dev);
+   }
+   pci_save_state(pdev);
+   pci_set_power_state(pdev, pci_choose_state(pdev, state));
+   return 0;
+}
+
+static int pcnet32_pm_resume(struct pci_dev *pdev)
+{
+   struct net_device *dev = pci_get_drvdata(pdev);
+
+   pci_set_power_state(pdev, PCI_D0);
+   pci_restore_state(pdev);
+
+   if (netif_running(dev)) {
+   pcnet32_open(dev);
+   netif_device_attach(dev);
+   }
+   return 0;
+}
+
 static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 {
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2966,6 +2993,8 @@ static struct pci_driver pcnet32_driver 
.probe = pcnet32_probe_pci,
.remove = __devexit_p(pcnet32_remove_one),
.id_table = pcnet32_pci_tbl,
+   .suspend = pcnet32_pm_suspend,
+   .resume = pcnet32_pm_resume,
 };
 
 /* An additional parameter that may be passed in... */


-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: add suspend and resume capability

2007-08-14 Thread Don Fry
Add suspend and resume capability to the driver.
Tested both to ram and to disk on x86_64 platform.

Signed-off-by:  Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.23-rc3/drivers/net/pcnet32.c.orig 2007-08-14 13:52:24.0 
-0700
+++ linux-2.6.23-rc3/drivers/net/pcnet32.c  2007-08-14 14:16:55.0 
-0700
@@ -23,11 +23,11 @@
 
 #define DRV_NAME   pcnet32
 #ifdef CONFIG_PCNET32_NAPI
-#define DRV_VERSION1.33-NAPI
+#define DRV_VERSION1.34-NAPI
 #else
-#define DRV_VERSION1.33
+#define DRV_VERSION1.34
 #endif
-#define DRV_RELDATE27.Jun.2006
+#define DRV_RELDATE14.Aug.2007
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -2943,6 +2943,33 @@ static void pcnet32_watchdog(struct net_
mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
 }
 
+static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+   struct net_device *dev = pci_get_drvdata(pdev);
+
+   if (netif_running(dev)) {
+   netif_device_detach(dev);
+   pcnet32_close(dev);
+   }
+   pci_save_state(pdev);
+   pci_set_power_state(pdev, pci_choose_state(pdev, state));
+   return 0;
+}
+
+static int pcnet32_pm_resume(struct pci_dev *pdev)
+{
+   struct net_device *dev = pci_get_drvdata(pdev);
+
+   pci_set_power_state(pdev, PCI_D0);
+   pci_restore_state(pdev);
+
+   if (netif_running(dev)) {
+   pcnet32_open(dev);
+   netif_device_attach(dev);
+   }
+   return 0;
+}
+
 static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 {
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2966,6 +2993,8 @@ static struct pci_driver pcnet32_driver 
.probe = pcnet32_probe_pci,
.remove = __devexit_p(pcnet32_remove_one),
.id_table = pcnet32_pci_tbl,
+   .suspend = pcnet32_pm_suspend,
+   .resume = pcnet32_pm_resume,
 };
 
 /* An additional parameter that may be passed in... */
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Strange soft lockup detected message (looks like spin_lock bug in pcnet32)

2007-05-04 Thread Don Fry
All instances of obtaining the lock in pcnet32 are done as
spin_lock_irqsave except the interrupt handler itself.  The interrupt mask
needs to be saved everywhere else, but the interrupt handler is known not
to need to save the flags.

If the lock is held and the same CPU tries to get the lock again, it will
wait a very long time ;-(.  I believe the locking is fine for a
non-preemptable kernel, but I have little experience with a preemptable
kernel.

When does a preemptable kernel allow interrupts to occur?
Is there a bug in this particular architectures locking code?
From looking at preempt-locking.txt the driver has (1) no per-cpu data,
(2) 'CPU state protection' should be fine,
(3) the 'lock is acquired and released by the same task'.
I don't see a problem unless I am misunderstanding something.

Don
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] pcnet32: only allocate init_block dma consistent

2007-03-06 Thread Don Fry
The change to use netdev_priv can only be done After moving the init
block out of the private structure.  It will break the driver if done
first, which is why they were sent together.

I will separate the changes and resend them.

On Tue, Mar 06, 2007 at 06:13:14AM -0500, Jeff Garzik wrote:
 Don Fry wrote:
 The patch below moves the init_block out of the private struct and
 only allocates init block with pci_alloc_consistent.
 
 This has two effects:
 
 1. Performance increase for non cache coherent machines, because the
CPU only data in the private struct are now cached
 
 2. locks are working now for platforms, which need to have locks
in cached memory
 
 Also use netdev_priv() instead of dev-priv
 
 Signed-off-by: Thomas Bogendoerfer [EMAIL PROTECTED]
 
 please separate the netdev_priv() change into a separate, precursor 
 patch, and resend both
 
 
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] pcnet32: only allocate init_block dma consistent

2007-03-06 Thread Don Fry
The patch below moves the init_block out of the private struct and
only allocates init block with pci_alloc_consistent. 

This has two effects:

1. Performance increase for non cache coherent machines, because the
   CPU only data in the private struct are now cached

2. locks are working now for platforms, which need to have locks
   in cached memory

Signed-off-by: Thomas Bogendoerfer [EMAIL PROTECTED]
Acked-by: Don Fry [EMAIL PROTECTED]
---
 drivers/net/pcnet32.c |   77 ++---
 1 files changed, 34 insertions(+), 43 deletions(-)

diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 36f9d98..04b0c44 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -253,12 +253,12 @@ struct pcnet32_access {
  * so the structure should be allocated using pci_alloc_consistent().
  */
 struct pcnet32_private {
-   struct pcnet32_init_block init_block;
+   struct pcnet32_init_block *init_block;
/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 
32bit mode. */
struct pcnet32_rx_head  *rx_ring;
struct pcnet32_tx_head  *tx_ring;
-   dma_addr_t  dma_addr;/* DMA address of beginning of this
-  object, returned by pci_alloc_consistent */
+   dma_addr_t  init_dma_addr;/* DMA address of beginning of 
the init block,
+  returned by pci_alloc_consistent */
struct pci_dev  *pci_dev;
const char  *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
@@ -1593,7 +1593,6 @@ static int __devinit
 pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 {
struct pcnet32_private *lp;
-   dma_addr_t lp_dma_addr;
int i, media;
int fdx, mii, fset, dxsuflo;
int chip_version;
@@ -1715,7 +1714,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct 
pci_dev *pdev)
dxsuflo = 1;
}
 
-   dev = alloc_etherdev(0);
+   dev = alloc_etherdev(sizeof(*lp));
if (!dev) {
if (pcnet32_debug  NETIF_MSG_PROBE)
printk(KERN_ERR PFX Memory allocation failed.\n);
@@ -1806,25 +1805,22 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct 
pci_dev *pdev)
}
 
dev-base_addr = ioaddr;
+   lp = dev-priv;
/* pci_alloc_consistent returns page-aligned memory, so we do not have 
to check the alignment */
-   if ((lp =
-pci_alloc_consistent(pdev, sizeof(*lp), lp_dma_addr)) == NULL) {
+   if ((lp-init_block =
+pci_alloc_consistent(pdev, sizeof(*lp-init_block), 
lp-init_dma_addr)) == NULL) {
if (pcnet32_debug  NETIF_MSG_PROBE)
printk(KERN_ERR PFX
   Consistent memory allocation failed.\n);
ret = -ENOMEM;
goto err_free_netdev;
}
-
-   memset(lp, 0, sizeof(*lp));
-   lp-dma_addr = lp_dma_addr;
lp-pci_dev = pdev;
 
spin_lock_init(lp-lock);
 
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, pdev-dev);
-   dev-priv = lp;
lp-name = chipname;
lp-shared_irq = shared;
lp-tx_ring_size = TX_RING_SIZE;/* default tx ring size */
@@ -1871,23 +1867,21 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct 
pci_dev *pdev)
 dev-dev_addr[2] == 0x75)
lp-options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
 
-   lp-init_block.mode = le16_to_cpu(0x0003);  /* Disable Rx and Tx. */
-   lp-init_block.tlen_rlen =
+   lp-init_block-mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
+   lp-init_block-tlen_rlen =
le16_to_cpu(lp-tx_len_bits | lp-rx_len_bits);
for (i = 0; i  6; i++)
-   lp-init_block.phys_addr[i] = dev-dev_addr[i];
-   lp-init_block.filter[0] = 0x;
-   lp-init_block.filter[1] = 0x;
-   lp-init_block.rx_ring = (u32) le32_to_cpu(lp-rx_ring_dma_addr);
-   lp-init_block.tx_ring = (u32) le32_to_cpu(lp-tx_ring_dma_addr);
+   lp-init_block-phys_addr[i] = dev-dev_addr[i];
+   lp-init_block-filter[0] = 0x;
+   lp-init_block-filter[1] = 0x;
+   lp-init_block-rx_ring = (u32) le32_to_cpu(lp-rx_ring_dma_addr);
+   lp-init_block-tx_ring = (u32) le32_to_cpu(lp-tx_ring_dma_addr);
 
/* switch pcnet32 to 32bit mode */
a-write_bcr(ioaddr, 20, 2);
 
-   a-write_csr(ioaddr, 1, (lp-dma_addr + offsetof(struct pcnet32_private,
-init_block))  0x);
-   a-write_csr(ioaddr, 2, (lp-dma_addr + offsetof(struct pcnet32_private,
-init_block))  16);
+   a-write_csr(ioaddr, 1, (lp-init_dma_addr  0x));
+   a-write_csr(ioaddr, 2, (lp-init_dma_addr  16

[PATCH 2/2] pcnet32: change to use netdev_priv

2007-03-06 Thread Don Fry
use netdev_priv() instead of dev-priv

Signed-off-by: Thomas Bogendoerfer [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]
---
--- linux-2.6.21-rc2/drivers/net/one.pcnet32.c  2007-03-06 10:48:37.0 
-0800
+++ linux-2.6.21-rc2/drivers/net/pcnet32.c  2007-03-05 18:03:32.0 
-0800
@@ -653,7 +653,7 @@ static void pcnet32_realloc_rx_ring(stru
 
 static void pcnet32_purge_rx_ring(struct net_device *dev)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
int i;
 
/* free all allocated skbuffs */
@@ -681,7 +681,7 @@ static void pcnet32_poll_controller(stru
 
 static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd 
*cmd)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
int r = -EOPNOTSUPP;
 
@@ -696,7 +696,7 @@ static int pcnet32_get_settings(struct n
 
 static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd 
*cmd)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
int r = -EOPNOTSUPP;
 
@@ -711,7 +711,7 @@ static int pcnet32_set_settings(struct n
 static void pcnet32_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
 
strcpy(info-driver, DRV_NAME);
strcpy(info-version, DRV_VERSION);
@@ -723,7 +723,7 @@ static void pcnet32_get_drvinfo(struct n
 
 static u32 pcnet32_get_link(struct net_device *dev)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
int r;
 
@@ -743,19 +743,19 @@ static u32 pcnet32_get_link(struct net_d
 
 static u32 pcnet32_get_msglevel(struct net_device *dev)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
return lp-msg_enable;
 }
 
 static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
lp-msg_enable = value;
 }
 
 static int pcnet32_nway_reset(struct net_device *dev)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
int r = -EOPNOTSUPP;
 
@@ -770,7 +770,7 @@ static int pcnet32_nway_reset(struct net
 static void pcnet32_get_ringparam(struct net_device *dev,
  struct ethtool_ringparam *ering)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
 
ering-tx_max_pending = TX_MAX_RING_SIZE;
ering-tx_pending = lp-tx_ring_size;
@@ -781,7 +781,7 @@ static void pcnet32_get_ringparam(struct
 static int pcnet32_set_ringparam(struct net_device *dev,
 struct ethtool_ringparam *ering)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
unsigned int size;
ulong ioaddr = dev-base_addr;
@@ -847,7 +847,7 @@ static int pcnet32_self_test_count(struc
 static void pcnet32_ethtool_test(struct net_device *dev,
 struct ethtool_test *test, u64 * data)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
int rc;
 
if (test-flags == ETH_TEST_FL_OFFLINE) {
@@ -868,7 +868,7 @@ static void pcnet32_ethtool_test(struct 
 
 static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
struct pcnet32_access *a = lp-a;  /* access to registers */
ulong ioaddr = dev-base_addr;  /* card base I/O address */
struct sk_buff *skb;/* sk buff */
@@ -1047,7 +1047,7 @@ static int pcnet32_loopback_test(struct 
 
 static void pcnet32_led_blink_callback(struct net_device *dev)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
struct pcnet32_access *a = lp-a;
ulong ioaddr = dev-base_addr;
unsigned long flags;
@@ -1064,7 +1064,7 @@ static void pcnet32_led_blink_callback(s
 
 static int pcnet32_phys_id(struct net_device *dev, u32 data)
 {
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv(dev);
struct pcnet32_access *a = lp-a;
ulong ioaddr = dev-base_addr;
unsigned long flags;
@@ -1109,7 +1109,7 @@ static int pcnet32_suspend(struct net_de
int can_sleep)
 {
int csr5;
-   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_private *lp = netdev_priv

[PATCH 0/5] NetXen: 1G/10G Ethernet Driver updates

2006-11-30 Thread Don Fry
The first patch sent by Amit on 29 Nov applied, but the following three
patches did not apply to Jeff's #upstream tree.  Here are the corrected
2nd, 3rd, and 4th patches, with a repeat of the 1st for completeness.
There is a 5th patch which fixes a bug caused by casting a 16-bit
variable into a 32-bit one and using the address.

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] NetXen: Fixed /sys mapping between device and driver

2006-11-30 Thread Don Fry

Signed-off-by: Amit S. Kale [EMAIL PROTECTED]

diff -Nupr netdev-2.6/drivers/net/netxen.orig/netxen_nic_main.c 
netdev-2.6/drivers/net/netxen/netxen_nic_main.c
--- netdev-2.6/drivers/net/netxen.orig/netxen_nic_main.c2006-11-29 
12:13:58.0 -0800
+++ netdev-2.6/drivers/net/netxen/netxen_nic_main.c 2006-11-30 
09:17:51.0 -0800
@@ -273,6 +273,7 @@ netxen_nic_probe(struct pci_dev *pdev, c
}
 
SET_MODULE_OWNER(netdev);
+   SET_NETDEV_DEV(netdev, pdev-dev);
 
port = netdev_priv(netdev);
port-netdev = netdev;
@@ -1043,7 +1044,7 @@ static int netxen_nic_poll(struct net_de
netxen_nic_enable_int(adapter);
}
 
-   return (done ? 0 : 1);
+   return !done;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] NetXen: 64-bit memory fixes and driver cleanup

2006-11-30 Thread Don Fry
NetXen: 1G/10G Ethernet Driver updates
- These fixes take care of driver on machines with 4G memory
- Driver cleanup

Signed-off-by: Amit S. Kale [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

diff -Nupr netdev-2.6/drivers/net/netxen.two/netxen_nic_ethtool.c 
netdev-2.6/drivers/net/netxen/netxen_nic_ethtool.c
--- netdev-2.6/drivers/net/netxen.two/netxen_nic_ethtool.c  2006-11-30 
09:40:47.0 -0800
+++ netdev-2.6/drivers/net/netxen/netxen_nic_ethtool.c  2006-11-30 
09:46:16.0 -0800
@@ -6,12 +6,12 @@
  * 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.
- *
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *   
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
@@ -118,7 +118,7 @@ netxen_nic_get_drvinfo(struct net_device
u32 fw_minor = 0;
u32 fw_build = 0;
 
-   strncpy(drvinfo-driver, netxen_nic, 32);
+   strncpy(drvinfo-driver, netxen_nic_driver_name, 32);
strncpy(drvinfo-version, NETXEN_NIC_LINUX_VERSIONID, 32);
fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
  NETXEN_FW_VERSION_MAJOR));
@@ -211,7 +211,6 @@ netxen_nic_get_settings(struct net_devic
printk(ERROR: Unsupported board model %d\n,
   (netxen_brdtype_t) boardinfo-board_type);
return -EIO;
-
}
 
return 0;
@@ -461,20 +460,22 @@ netxen_nic_get_ringparam(struct net_devi
 {
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port-adapter;
-   int i, j;
+   int i;
 
ring-rx_pending = 0;
+   ring-rx_jumbo_pending = 0;
for (i = 0; i  MAX_RCV_CTX; ++i) {
-   for (j = 0; j  NUM_RCV_DESC_RINGS; j++)
-   ring-rx_pending +=
-   adapter-recv_ctx[i].rcv_desc[j].rcv_pending;
+   ring-rx_pending += adapter-recv_ctx[i].
+   rcv_desc[RCV_DESC_NORMAL_CTXID].rcv_pending;
+   ring-rx_jumbo_pending += adapter-recv_ctx[i].
+   rcv_desc[RCV_DESC_JUMBO_CTXID].rcv_pending;
}
 
ring-rx_max_pending = adapter-max_rx_desc_count;
ring-tx_max_pending = adapter-max_tx_desc_count;
+   ring-rx_jumbo_max_pending = adapter-max_jumbo_rx_desc_count;
ring-rx_mini_max_pending = 0;
ring-rx_mini_pending = 0;
-   ring-rx_jumbo_max_pending = 0;
ring-rx_jumbo_pending = 0;
 }
 
diff -Nupr netdev-2.6/drivers/net/netxen.two/netxen_nic.h 
netdev-2.6/drivers/net/netxen/netxen_nic.h
--- netdev-2.6/drivers/net/netxen.two/netxen_nic.h  2006-11-30 
09:40:47.0 -0800
+++ netdev-2.6/drivers/net/netxen/netxen_nic.h  2006-11-30 09:46:16.0 
-0800
@@ -6,12 +6,12 @@
  * 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.
- *
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *   
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
@@ -89,8 +89,8 @@
  * normalize a 64MB crb address to 32MB PCI window 
  * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1
  */
-#define NETXEN_CRB_NORMAL(reg)\
-   (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST
+#define NETXEN_CRB_NORMAL(reg) \
+   ((reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST)
 
 #define NETXEN_CRB_NORMALIZE(adapter, reg) \
pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg))
@@ -164,7 +164,7 @@ enum {
 
 #define MAX_CMD_DESCRIPTORS1024
 #define MAX_RCV_DESCRIPTORS32768
-#define MAX_JUMBO_RCV_DESCRIPTORS  1024
+#define MAX_JUMBO_RCV_DESCRIPTORS  4096
 #define MAX_RCVSTATUS_DESCRIPTORS  MAX_RCV_DESCRIPTORS
 #define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS
 #define MAX_RCV_DESC   MAX_RCV_DESCRIPTORS
@@ -592,6 +592,16 @@ struct netxen_skb_frag {
u32 length;
 };
 
+/* Bounce buffer index */
+struct bounce_index {
+   /* Index of a buffer

[PATCH 5/5] NetXen: Fix cast error

2006-11-30 Thread Don Fry
Fix for pointer casting error.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

diff -Nupr netdev-2.6/drivers/net/netxen.four/netxen_nic_hw.c 
netdev-2.6/drivers/net/netxen/netxen_nic_hw.c
--- netdev-2.6/drivers/net/netxen.four/netxen_nic_hw.c  2006-11-30 
10:06:24.0 -0800
+++ netdev-2.6/drivers/net/netxen/netxen_nic_hw.c   2006-11-30 
10:31:00.0 -0800
@@ -867,7 +867,7 @@ void netxen_nic_set_link_parameters(stru
 {
struct netxen_adapter *adapter = port-adapter;
__le32 status;
-   u16 autoneg;
+   __le32 autoneg = 0;
__le32 mode;
 
netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, mode);
@@ -907,7 +907,7 @@ void netxen_nic_set_link_parameters(stru
 adapter-
phy_read(adapter, port-portnum,
 
NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-(__le32 *)  autoneg) != 0)
+autoneg) != 0)
port-link_autoneg = autoneg;
} else
goto link_down;
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/5 addendum] NetXen

2006-11-30 Thread Don Fry
The NetXen patches fix many problems in the current #upstream version of
the driver.  It has warts and probably lots of bugs still, but it is
better than what is queued for mainline inclusion at this time.  Please
apply to 2.6.20.

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/5] pcnet32: NAPI implementation (one more try)

2006-09-13 Thread Don Fry
These patches to the pcnet32 driver implement NAPI and respond to some
other suggestions found during NAPI development and testing.

The first patch deletes a couple of unnecessary save/restore operations.
The second patch replaces some magic numbers with hopefully more clear
defines.
The third patch moves the receive and creates a transmit routine.
The fourth patch breaks the receive routine into two pieces to make the
code easier to read and simpler.
The fifth and final patch implements the NAPI changes.

The comments from Francois Romieu regarding using spin_lock instead of
spin_lock_irqsave were investigated, but since interrupts have to be
disabled to prevent the interrupt handler from deadlocking, and since I
would probably forget sometime, it is safer to leave the locking as it
is.  The requested mmiowb calls were added.

Please appply to 2.6.19.

[PATCH 1/5] pcnet32:  remove unnecessary save/restore register accesses.
[PATCH 2/5] pcnet32:  magic number cleanup
[PATCH 3/5] pcnet32:  move/create receive and transmit routines
[PATCH 4/5] pcnet32:  break receive routine into two pieces.
[PATCH 5/5] pcnet32:  NAPI implementation
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] pcnet32: remove unnecessary save/restore register accesses.

2006-09-13 Thread Don Fry
Delete unnecessary save/restore of rap in interrupt handler and statistics.

tested ia32 and ppc64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.orig Fri Sep  8 14:02:12 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Tue Sep 12 10:09:12 2006
@@ -2262,7 +2262,7 @@ pcnet32_interrupt(int irq, void *dev_id,
struct net_device *dev = dev_id;
struct pcnet32_private *lp;
unsigned long ioaddr;
-   u16 csr0, rap;
+   u16 csr0;
int boguscnt = max_interrupt_work;
int must_restart;
 
@@ -2278,7 +2278,6 @@ pcnet32_interrupt(int irq, void *dev_id,
 
spin_lock(lp-lock);
 
-   rap = lp-a.read_rap(ioaddr);
while ((csr0 = lp-a.read_csr(ioaddr, 0))  0x8f00  --boguscnt = 0) {
if (csr0 == 0x) {
break;  /* PCMCIA remove happened */
@@ -2434,7 +2433,6 @@ pcnet32_interrupt(int irq, void *dev_id,
 
/* Set interrupt enable. */
lp-a.write_csr(ioaddr, 0, 0x0040);
-   lp-a.write_rap(ioaddr, rap);
 
if (netif_msg_intr(lp))
printk(KERN_DEBUG %s: exiting interrupt, csr0=%#4.4x.\n,
@@ -2647,13 +2645,10 @@ static struct net_device_stats *pcnet32_
 {
struct pcnet32_private *lp = dev-priv;
unsigned long ioaddr = dev-base_addr;
-   u16 saved_addr;
unsigned long flags;
 
spin_lock_irqsave(lp-lock, flags);
-   saved_addr = lp-a.read_rap(ioaddr);
lp-stats.rx_missed_errors = lp-a.read_csr(ioaddr, 112);
-   lp-a.write_rap(ioaddr, saved_addr);
spin_unlock_irqrestore(lp-lock, flags);
 
return lp-stats;
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] pcnet32: magic number cleanup

2006-09-13 Thread Don Fry
Change some magic numbers to clearer names.  A few whitespace changes.

Tested ia32 and ppc64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.rap  Tue Sep 12 10:09:12 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Tue Sep 12 10:25:09 2006
@@ -207,7 +207,7 @@ static int homepna[MAX_UNITS];
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
-   s16 buf_length;
+   s16 buf_length; /* two`s complement of length */
s16 status;
u32 msg_length;
u32 reserved;
@@ -215,7 +215,7 @@ struct pcnet32_rx_head {
 
 struct pcnet32_tx_head {
u32 base;
-   s16 length;
+   s16 length; /* two`s complement of length */
s16 status;
u32 misc;
u32 reserved;
@@ -804,7 +804,7 @@ static int pcnet32_set_ringparam(struct 
}
if ((1  i) != lp-tx_ring_size)
pcnet32_realloc_tx_ring(dev, lp, i);
-   
+
size = min(ering-rx_pending, (unsigned int)RX_MAX_RING_SIZE);
for (i = 2; i = PCNET32_LOG_MAX_RX_BUFFERS; i++) {
if (size = (1  i))
@@ -812,7 +812,7 @@ static int pcnet32_set_ringparam(struct 
}
if ((1  i) != lp-rx_ring_size)
pcnet32_realloc_rx_ring(dev, lp, i);
-   
+
dev-weight = lp-rx_ring_size / 2;
 
if (netif_running(dev)) {
@@ -892,7 +892,7 @@ static int pcnet32_loopback_test(struct 
 
/* Reset the PCNET32 */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
 
/* switch pcnet32 to 32bit mode */
lp-a.write_bcr(ioaddr, 20, 2);
@@ -1602,7 +1602,7 @@ pcnet32_probe1(unsigned long ioaddr, int
 * boards will work.
 */
/* Trigger an initialization just for the interrupt. */
-   a-write_csr(ioaddr, 0, 0x41);
+   a-write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
mdelay(1);
 
dev-irq = probe_irq_off(irq_mask);
@@ -1965,9 +1965,9 @@ static int pcnet32_open(struct net_devic
 
 #ifdef DO_DXSUFLO
if (lp-dxsuflo) {  /* Disable transmit stop on underflow */
-   val = lp-a.read_csr(ioaddr, 3);
+   val = lp-a.read_csr(ioaddr, CSR3);
val |= 0x40;
-   lp-a.write_csr(ioaddr, 3, val);
+   lp-a.write_csr(ioaddr, CSR3, val);
}
 #endif
 
@@ -1988,8 +1988,8 @@ static int pcnet32_open(struct net_devic
(lp-dma_addr +
 offsetof(struct pcnet32_private, init_block))  16);
 
-   lp-a.write_csr(ioaddr, 4, 0x0915);
-   lp-a.write_csr(ioaddr, 0, 0x0001);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
 
netif_start_queue(dev);
 
@@ -2001,13 +2001,13 @@ static int pcnet32_open(struct net_devic
 
i = 0;
while (i++  100)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_IDON)
break;
/*
 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
 * reports that doing so triggers a bug in the '974.
 */
-   lp-a.write_csr(ioaddr, 0, 0x0042);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_NORMAL);
 
if (netif_msg_ifup(lp))
printk(KERN_DEBUG
@@ -2015,7 +2015,7 @@ static int pcnet32_open(struct net_devic
   dev-name, i,
   (u32) (lp-dma_addr +
  offsetof(struct pcnet32_private, init_block)),
-  lp-a.read_csr(ioaddr, 0));
+  lp-a.read_csr(ioaddr, CSR0));
 
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -2086,7 +2086,7 @@ static int pcnet32_init_ring(struct net_
(rx_skbuff = lp-rx_skbuff[i] =
 dev_alloc_skb(PKT_BUF_SZ))) {
/* there is not much, we can do at this point */
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(KERN_ERR
   %s: pcnet32_init_ring 
dev_alloc_skb failed.\n,
   dev-name);
@@ -2136,7 +2136,7 @@ static void pcnet32_restart(struct net_d
 
/* wait for stop */
for (i = 0; i  100; i++)
-   if (lp-a.read_csr(ioaddr, 0)  0x0004)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_STOP)
break;
 
if (i = 100  netif_msg_drv(lp))
@@ -2149,13 +2149,13 @@ static void pcnet32_restart(struct net_d
return;
 
/* ReInit Ring */
-   lp-a.write_csr(ioaddr, 0, 1);
+   lp

[PATCH 3/5] pcnet32: move/create receive and transmit routines

2006-09-13 Thread Don Fry
Move the receive routine and create the transmit routine.

Tested ia32 and ppc64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.magicTue Sep 12 10:25:20 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Tue Sep 12 11:37:43 2006
@@ -299,7 +299,6 @@ static int pcnet32_probe1(unsigned long,
 static int pcnet32_open(struct net_device *);
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
 static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
 static int pcnet32_close(struct net_device *);
@@ -1125,6 +1124,264 @@ static int pcnet32_suspend(struct net_de
return 1;
 }
 
+
+static int pcnet32_rx(struct net_device *dev)
+{
+   struct pcnet32_private *lp = dev-priv;
+   int entry = lp-cur_rx  lp-rx_mod_mask;
+   int boguscnt = lp-rx_ring_size / 2;
+
+   /* If we own the next entry, it's a new packet. Send it up. */
+   while ((short)le16_to_cpu(lp-rx_ring[entry].status) = 0) {
+   int status = (short)le16_to_cpu(lp-rx_ring[entry].status)  8;
+
+   if (status != 0x03) {   /* There was an error. */
+   /*
+* There is a tricky error noted by John Murphy,
+* [EMAIL PROTECTED] to Russ Nelson: Even with 
full-sized
+* buffers it's possible for a jabber packet to use two
+* buffers, with only the last correctly noting the 
error.
+*/
+   if (status  0x01)  /* Only count a general error 
at the */
+   lp-stats.rx_errors++;  /* end of a packet. */
+   if (status  0x20)
+   lp-stats.rx_frame_errors++;
+   if (status  0x10)
+   lp-stats.rx_over_errors++;
+   if (status  0x08)
+   lp-stats.rx_crc_errors++;
+   if (status  0x04)
+   lp-stats.rx_fifo_errors++;
+   lp-rx_ring[entry].status = le16_to_cpu(0x03ff);
+   } else {
+   /* Malloc up new buffer, compatible with net-2e. */
+   short pkt_len =
+   (le32_to_cpu(lp-rx_ring[entry].msg_length)  0xfff)
+   - 4;
+   struct sk_buff *skb;
+
+   /* Discard oversize frames. */
+   if (unlikely(pkt_len  PKT_BUF_SZ - 2)) {
+   if (netif_msg_drv(lp))
+   printk(KERN_ERR
+  %s: Impossible packet size 
%d!\n,
+  dev-name, pkt_len);
+   lp-stats.rx_errors++;
+   } else if (pkt_len  60) {
+   if (netif_msg_rx_err(lp))
+   printk(KERN_ERR %s: Runt packet!\n,
+  dev-name);
+   lp-stats.rx_errors++;
+   } else {
+   int rx_in_place = 0;
+
+   if (pkt_len  rx_copybreak) {
+   struct sk_buff *newskb;
+
+   if ((newskb =
+dev_alloc_skb(PKT_BUF_SZ))) {
+   skb_reserve(newskb, 2);
+   skb = lp-rx_skbuff[entry];
+   pci_unmap_single(lp-pci_dev,
+lp-
+rx_dma_addr
+[entry],
+PKT_BUF_SZ - 2,
+
PCI_DMA_FROMDEVICE);
+   skb_put(skb, pkt_len);
+   lp-rx_skbuff[entry] = newskb;
+   newskb-dev = dev;
+   lp-rx_dma_addr[entry] =
+   pci_map_single(lp-pci_dev,
+  newskb-data,
+  PKT_BUF_SZ -
+  2,
+  
PCI_DMA_FROMDEVICE

[PATCH 5/5] pcnet32: NAPI implementation

2006-09-13 Thread Don Fry
Implement NAPI changes to pcnet32 driver.  Compile default is off.
Listed as experimental.

Len and Don both worked on a NAPI implementation and have both tested
these changes. 

An e1000 blasting short packets to the pcnet32 will lockup Don's system
until the receive storm stops.  Without NAPI Len's system watchdog would
expire causing the system to reboot.  With NAPI the system will stay
operational.

Tested ia32 and ppc64.  Tested '970A, '971, '972, '973, '975, '976, and
'978.

The Kconfig changes came from Len.  Don is to blame for all the others.

Signed-off-by: Len Sorensen [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/orig.Kconfig Wed Jun 28 10:38:45 2006
+++ linux-2.6.17-git13/drivers/net/Kconfig  Wed Jun 28 15:36:25 2006
@@ -1300,6 +1300,23 @@ config PCNET32
  file:Documentation/networking/net-modules.txt. The module
  will be called pcnet32.
 
+config PCNET32_NAPI
+   bool Use RX polling (NAPI) (EXPERIMENTAL)
+   depends on PCNET32  EXPERIMENTAL
+   help
+ NAPI is a new driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card. It is
+ still somewhat experimental and thus not yet enabled by default.
+
+ If your estimated Rx load is 10kpps or more, or if the card will be
+ deployed on potentially unfriendly networks (e.g. in a firewall),
+ then say Y here.
+
+ See file:Documentation/networking/NAPI_HOWTO.txt for more
+ information.
+
+ If in doubt, say N.
+
 config AMD8111_ETH
tristate AMD 8111 (new PCI lance) support
depends on NET_PCI  PCI
--- linux-2.6.18-rc6/drivers/net/pcnet32.c.splitTue Sep 12 14:21:49 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Tue Sep 12 16:45:01 2006
@@ -21,9 +21,15 @@
  *
  */
 
+#include linux/config.h
+
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.32
-#define DRV_RELDATE18.Mar.2006
+#ifdef CONFIG_PCNET32_NAPI
+#define DRV_VERSION1.33-NAPI
+#else
+#define DRV_VERSION1.33
+#endif
+#define DRV_RELDATE27.Jun.2006
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -882,7 +888,11 @@ static int pcnet32_loopback_test(struct 
rc = 1; /* default to fail */
 
if (netif_running(dev))
+#ifdef CONFIG_PCNET32_NAPI
+   pcnet32_netif_stop(dev);
+#else
pcnet32_close(dev);
+#endif
 
spin_lock_irqsave(lp-lock, flags);
lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* stop the chip */
@@ -1014,6 +1024,16 @@ static int pcnet32_loopback_test(struct 
x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
a-write_bcr(ioaddr, 32, (x  ~0x0002));
 
+#ifdef CONFIG_PCNET32_NAPI
+   if (netif_running(dev)) {
+   pcnet32_netif_start(dev);
+   pcnet32_restart(dev, CSR0_NORMAL);
+   } else {
+   pcnet32_purge_rx_ring(dev);
+   lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+   }
+   spin_unlock_irqrestore(lp-lock, flags);
+#else
if (netif_running(dev)) {
spin_unlock_irqrestore(lp-lock, flags);
pcnet32_open(dev);
@@ -1022,6 +1042,7 @@ static int pcnet32_loopback_test(struct 
lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(lp-lock, flags);
}
+#endif
 
return (rc);
 }  /* end pcnet32_loopback_test  */
@@ -1227,23 +1248,25 @@ static void pcnet32_rx_entry(struct net_
}
lp-stats.rx_bytes += skb-len;
skb-protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_PCNET32_NAPI
+   netif_receive_skb(skb);
+#else
netif_rx(skb);
+#endif
dev-last_rx = jiffies;
lp-stats.rx_packets++;
return;
 }
 
-
-static void pcnet32_rx(struct net_device *dev)
+static int pcnet32_rx(struct net_device *dev, int quota)
 {
struct pcnet32_private *lp = dev-priv;
int entry = lp-cur_rx  lp-rx_mod_mask;
struct pcnet32_rx_head *rxp = lp-rx_ring[entry];
int npackets = 0;
-   int boguscnt = lp-rx_ring_size / 2;
 
/* If we own the next entry, it's a new packet. Send it up. */
-   while (boguscnt  npackets  (short)le16_to_cpu(rxp-status) = 0) {
+   while (quota  npackets  (short)le16_to_cpu(rxp-status) = 0) {
pcnet32_rx_entry(dev, lp, rxp, entry);
npackets += 1;
/*
@@ -1257,10 +1280,10 @@ static void pcnet32_rx(struct net_device
rxp = lp-rx_ring[entry];
}
 
-   return;
+   return npackets;
 }
 
-static int pcnet32_tx(struct net_device *dev, u16 csr0)
+static int pcnet32_tx(struct net_device *dev)
 {
struct pcnet32_private *lp = dev-priv;
unsigned int dirty_tx = lp

[PATCH 4/5] pcnet32: break receive routine into two pieces.

2006-09-13 Thread Don Fry
Breaking the receive frame processing into two routines for greater clarity.  

Tested ia32 and ppc64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.move Tue Sep 12 11:37:43 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Tue Sep 12 14:21:18 2006
@@ -1124,161 +1124,140 @@ static int pcnet32_suspend(struct net_de
return 1;
 }
 
+/*
+ * process one receive descriptor entry
+ */
 
-static int pcnet32_rx(struct net_device *dev)
+static void pcnet32_rx_entry(struct net_device *dev,
+struct pcnet32_private *lp,
+struct pcnet32_rx_head *rxp,
+int entry)
 {
-   struct pcnet32_private *lp = dev-priv;
-   int entry = lp-cur_rx  lp-rx_mod_mask;
-   int boguscnt = lp-rx_ring_size / 2;
+   int status = (short)le16_to_cpu(rxp-status)  8;
+   int rx_in_place = 0;
+   struct sk_buff *skb;
+   short pkt_len;
 
-   /* If we own the next entry, it's a new packet. Send it up. */
-   while ((short)le16_to_cpu(lp-rx_ring[entry].status) = 0) {
-   int status = (short)le16_to_cpu(lp-rx_ring[entry].status)  8;
+   if (status != 0x03) {   /* There was an error. */
+   /*
+* There is a tricky error noted by John Murphy,
+* [EMAIL PROTECTED] to Russ Nelson: Even with full-sized
+* buffers it's possible for a jabber packet to use two
+* buffers, with only the last correctly noting the error.
+*/
+   if (status  0x01)  /* Only count a general error at the */
+   lp-stats.rx_errors++;  /* end of a packet. */
+   if (status  0x20)
+   lp-stats.rx_frame_errors++;
+   if (status  0x10)
+   lp-stats.rx_over_errors++;
+   if (status  0x08)
+   lp-stats.rx_crc_errors++;
+   if (status  0x04)
+   lp-stats.rx_fifo_errors++;
+   return;
+   }
 
-   if (status != 0x03) {   /* There was an error. */
-   /*
-* There is a tricky error noted by John Murphy,
-* [EMAIL PROTECTED] to Russ Nelson: Even with 
full-sized
-* buffers it's possible for a jabber packet to use two
-* buffers, with only the last correctly noting the 
error.
-*/
-   if (status  0x01)  /* Only count a general error 
at the */
-   lp-stats.rx_errors++;  /* end of a packet. */
-   if (status  0x20)
-   lp-stats.rx_frame_errors++;
-   if (status  0x10)
-   lp-stats.rx_over_errors++;
-   if (status  0x08)
-   lp-stats.rx_crc_errors++;
-   if (status  0x04)
-   lp-stats.rx_fifo_errors++;
-   lp-rx_ring[entry].status = le16_to_cpu(0x03ff);
-   } else {
-   /* Malloc up new buffer, compatible with net-2e. */
-   short pkt_len =
-   (le32_to_cpu(lp-rx_ring[entry].msg_length)  0xfff)
-   - 4;
-   struct sk_buff *skb;
+   pkt_len = (le32_to_cpu(rxp-msg_length)  0xfff) - 4;
 
-   /* Discard oversize frames. */
-   if (unlikely(pkt_len  PKT_BUF_SZ - 2)) {
-   if (netif_msg_drv(lp))
-   printk(KERN_ERR
-  %s: Impossible packet size 
%d!\n,
-  dev-name, pkt_len);
-   lp-stats.rx_errors++;
-   } else if (pkt_len  60) {
-   if (netif_msg_rx_err(lp))
-   printk(KERN_ERR %s: Runt packet!\n,
-  dev-name);
-   lp-stats.rx_errors++;
-   } else {
-   int rx_in_place = 0;
+   /* Discard oversize frames. */
+   if (unlikely(pkt_len  PKT_BUF_SZ - 2)) {
+   if (netif_msg_drv(lp))
+   printk(KERN_ERR %s: Impossible packet size %d!\n,
+  dev-name, pkt_len);
+   lp-stats.rx_errors++;
+   return;
+   }
+   if (pkt_len  60) {
+   if (netif_msg_rx_err(lp))
+   printk(KERN_ERR %s: Runt packet!\n, dev-name);
+   lp-stats.rx_errors++;
+   return;
+   }
 
-   if (pkt_len  rx_copybreak

[PATCH 0/3] pcnet32: reorg, NAPI, and cleanup

2006-09-11 Thread Don Fry
These patches to the pcnet32 driver implement NAPI and respond to some
other suggestions found during NAPI development and testing.

The NAPI code change was broken into two pieces, one is
code-reorganization, and the second is the NAPI implementation.  Tested
with and without NAPI ia32 and ppc64 with '970A, '971, '972, and '976.

The comments from Francois Romieu regarding using spin_lock instead of
spin_lock_irqsave were investigated, but since interrupts have to be
disabled to prevent the interrupt handler from deadlocking, and since I
would probably forget sometime, it is safer to leave the locking as it
is.  The requested mmiowb calls were added.

Please appply to 2.6.19.

1/3 Code reorganization to facilitate NAPI.
2/3 NAPI implementation.
3/3 Magic number cleanup.
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] pcnet32: reorganize interrupt, tx, and rx processing

2006-09-11 Thread Don Fry
Reorganize code to facilitate NAPI changes.
Tested ia32 and ppc64.

Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.orig Fri Sep  8 14:02:12 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Mon Sep 11 09:07:13 2006
@@ -299,7 +299,6 @@ static int pcnet32_probe1(unsigned long,
 static int pcnet32_open(struct net_device *);
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
 static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
 static int pcnet32_close(struct net_device *);
@@ -1125,6 +1124,235 @@ static int pcnet32_suspend(struct net_de
return 1;
 }
 
+static int pcnet32_rx_entry(struct net_device *dev,
+   struct pcnet32_private *lp,
+   struct pcnet32_rx_head *rxp,
+   int entry)
+{
+   int status = (short)le16_to_cpu(rxp-status)  8;
+   int rx_in_place = 0;
+   struct sk_buff *skb;
+   short pkt_len;
+
+   if (status != 0x03) {   /* There was an error. */
+   /*
+* There is a tricky error noted by John Murphy,
+* [EMAIL PROTECTED] to Russ Nelson: Even with full-sized
+* buffers it's possible for a jabber packet to use two
+* buffers, with only the last correctly noting the error.
+*/
+   if (status  0x01)  /* Only count a general error at the */
+   lp-stats.rx_errors++;  /* end of a packet. */
+   if (status  0x20)
+   lp-stats.rx_frame_errors++;
+   if (status  0x10)
+   lp-stats.rx_over_errors++;
+   if (status  0x08)
+   lp-stats.rx_crc_errors++;
+   if (status  0x04)
+   lp-stats.rx_fifo_errors++;
+   return 1;
+   }
+
+   pkt_len = (le32_to_cpu(rxp-msg_length)  0xfff) - 4;
+
+   /* Discard oversize frames. */
+   if (unlikely(pkt_len  PKT_BUF_SZ - 2)) {
+   if (netif_msg_drv(lp))
+   printk(KERN_ERR %s: Impossible packet size %d!\n,
+  dev-name, pkt_len);
+   lp-stats.rx_errors++;
+   return 1;
+   }
+   if (pkt_len  60) {
+   if (netif_msg_rx_err(lp))
+   printk(KERN_ERR %s: Runt packet!\n, dev-name);
+   lp-stats.rx_errors++;
+   return 1;
+   }
+
+   if (pkt_len  rx_copybreak) {
+   struct sk_buff *newskb;
+
+   if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) {
+   skb_reserve(newskb, 2);
+   skb = lp-rx_skbuff[entry];
+   pci_unmap_single(lp-pci_dev,
+lp-rx_dma_addr[entry],
+PKT_BUF_SZ - 2,
+PCI_DMA_FROMDEVICE);
+   skb_put(skb, pkt_len);
+   lp-rx_skbuff[entry] = newskb;
+   newskb-dev = dev;
+   lp-rx_dma_addr[entry] =
+   pci_map_single(lp-pci_dev,
+  newskb-data,
+  PKT_BUF_SZ - 2,
+  PCI_DMA_FROMDEVICE);
+   rxp-base = le32_to_cpu(lp-rx_dma_addr[entry]);
+   rx_in_place = 1;
+   } else
+   skb = NULL;
+   } else {
+   skb = dev_alloc_skb(pkt_len + 2);
+   }
+
+   if (skb == NULL) {
+   if (netif_msg_drv(lp))
+   printk(KERN_ERR
+  %s: Memory squeeze, dropping packet.\n,
+  dev-name);
+   lp-stats.rx_dropped++;
+   return 1;
+   }
+   skb-dev = dev;
+   if (!rx_in_place) {
+   skb_reserve(skb, 2);/* 16 byte align */
+   skb_put(skb, pkt_len);  /* Make room */
+   pci_dma_sync_single_for_cpu(lp-pci_dev,
+   lp-rx_dma_addr[entry],
+   PKT_BUF_SZ - 2,
+   PCI_DMA_FROMDEVICE);
+   eth_copy_and_sum(skb,
+(unsigned char *)(lp-rx_skbuff[entry]-data),
+pkt_len, 0);
+   pci_dma_sync_single_for_device(lp-pci_dev,
+  lp-rx_dma_addr[entry],
+  PKT_BUF_SZ - 2,
+  PCI_DMA_FROMDEVICE);
+   }
+   lp-stats.rx_bytes += skb-len;
+   lp

[PATCH 2/3] pcnet32: NAPI implementation

2006-09-11 Thread Don Fry
Implement NAPI changes to pcnet32 driver.  Compile default is off.
Listed as experimental.

Len and Don both worked on a NAPI implementation and have both tested
these changes. 

An e1000 blasting short packets to the pcnet32 will lockup Don's system
until the receive storm stops.  Without NAPI Len's system watchdog would
expire causing the system to reboot.  With NAPI the system will stay
operational.

Tested ia32 and ppc64.  Tested '970A, '971, '972, '973, '975, '976, and
'978.

The Kconfig changes came from Len.  Don is to blame for all the others.

Signed-off-by: Len Sorensen [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/orig.Kconfig Wed Jun 28 10:38:45 2006
+++ linux-2.6.17-git13/drivers/net/Kconfig  Wed Jun 28 15:36:25 2006
@@ -1300,6 +1300,23 @@ config PCNET32
  file:Documentation/networking/net-modules.txt. The module
  will be called pcnet32.
 
+config PCNET32_NAPI
+   bool Use RX polling (NAPI) (EXPERIMENTAL)
+   depends on PCNET32  EXPERIMENTAL
+   help
+ NAPI is a new driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card. It is
+ still somewhat experimental and thus not yet enabled by default.
+
+ If your estimated Rx load is 10kpps or more, or if the card will be
+ deployed on potentially unfriendly networks (e.g. in a firewall),
+ then say Y here.
+
+ See file:Documentation/networking/NAPI_HOWTO.txt for more
+ information.
+
+ If in doubt, say N.
+
 config AMD8111_ETH
tristate AMD 8111 (new PCI lance) support
depends on NET_PCI  PCI
--- linux-2.6.18-rc6/drivers/net/pcnet32.c.breakup  Mon Sep 11 09:07:13 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Fri Sep  8 14:04:47 2006
@@ -21,9 +21,15 @@
  *
  */
 
+#include linux/config.h
+
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.32
-#define DRV_RELDATE18.Mar.2006
+#ifdef CONFIG_PCNET32_NAPI
+#define DRV_VERSION1.33-NAPI
+#else
+#define DRV_VERSION1.33
+#endif
+#define DRV_RELDATE27.Jun.2006
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -882,7 +888,11 @@ static int pcnet32_loopback_test(struct 
rc = 1; /* default to fail */
 
if (netif_running(dev))
+#ifdef CONFIG_PCNET32_NAPI
+   pcnet32_netif_stop(dev);
+#else
pcnet32_close(dev);
+#endif
 
spin_lock_irqsave(lp-lock, flags);
lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* stop the chip */
@@ -1014,6 +1024,16 @@ static int pcnet32_loopback_test(struct 
x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
a-write_bcr(ioaddr, 32, (x  ~0x0002));
 
+#ifdef CONFIG_PCNET32_NAPI
+   if (netif_running(dev)) {
+   pcnet32_netif_start(dev);
+   pcnet32_restart(dev, CSR0_NORMAL);
+   } else {
+   pcnet32_purge_rx_ring(dev);
+   lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+   }
+   spin_unlock_irqrestore(lp-lock, flags);
+#else
if (netif_running(dev)) {
spin_unlock_irqrestore(lp-lock, flags);
pcnet32_open(dev);
@@ -1022,6 +1042,7 @@ static int pcnet32_loopback_test(struct 
lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(lp-lock, flags);
}
+#endif
 
return (rc);
 }  /* end pcnet32_loopback_test  */
@@ -1224,7 +1245,11 @@ static int pcnet32_rx_entry(struct net_d
lp-stats.rx_bytes += skb-len;
lp-stats.rx_packets++;
skb-protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_PCNET32_NAPI
+   netif_receive_skb(skb);
+#else
netif_rx(skb);
+#endif
dev-last_rx = jiffies;
return 1;
 }
@@ -1353,6 +1378,52 @@ static int pcnet32_tx(struct net_device 
return must_restart;
 }
 
+#ifdef CONFIG_PCNET32_NAPI
+static int pcnet32_poll(struct net_device *dev, int *budget)
+{
+   struct pcnet32_private *lp = dev-priv;
+   int quota = min(dev-quota, *budget);
+   unsigned long ioaddr = dev-base_addr;
+   unsigned long flags;
+   u16 val;
+
+   quota = pcnet32_rx(dev, quota);
+
+   spin_lock_irqsave(lp-lock, flags);
+   if (pcnet32_tx(dev)) {
+   /* reset the chip to clear the error condition, then restart */
+   lp-a.reset(ioaddr);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   pcnet32_restart(dev, CSR0_START);
+   netif_wake_queue(dev);
+   }
+   spin_unlock_irqrestore(lp-lock, flags);
+
+   *budget -= quota;
+   dev-quota -= quota;
+
+   if (dev-quota == 0) {
+   return 1;
+   }
+
+   netif_rx_complete(dev);
+
+   spin_lock_irqsave(lp-lock, flags

[PATCH] pcnet32: Magic number cleanup

2006-09-11 Thread Don Fry
Initial magic number cleanup.  Delete one unnecessary read and write.
Tested ia32 and ppc64.

Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.napi Fri Sep  8 14:04:47 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Fri Sep  8 14:05:09 2006
@@ -213,7 +213,7 @@ static int homepna[MAX_UNITS];
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
-   s16 buf_length;
+   s16 buf_length; /* two`s complement of length */
s16 status;
u32 msg_length;
u32 reserved;
@@ -221,7 +221,7 @@ struct pcnet32_rx_head {
 
 struct pcnet32_tx_head {
u32 base;
-   s16 length;
+   s16 length; /* two`s complement of length */
s16 status;
u32 misc;
u32 reserved;
@@ -901,7 +901,7 @@ static int pcnet32_loopback_test(struct 
 
/* Reset the PCNET32 */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
 
/* switch pcnet32 to 32bit mode */
lp-a.write_bcr(ioaddr, 20, 2);
@@ -1393,7 +1393,7 @@ static int pcnet32_poll(struct net_devic
if (pcnet32_tx(dev)) {
/* reset the chip to clear the error condition, then restart */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
pcnet32_restart(dev, CSR0_START);
netif_wake_queue(dev);
}
@@ -1901,7 +1901,7 @@ pcnet32_probe1(unsigned long ioaddr, int
 * boards will work.
 */
/* Trigger an initialization just for the interrupt. */
-   a-write_csr(ioaddr, 0, 0x41);
+   a-write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
mdelay(1);
 
dev-irq = probe_irq_off(irq_mask);
@@ -2268,9 +2268,9 @@ static int pcnet32_open(struct net_devic
 
 #ifdef DO_DXSUFLO
if (lp-dxsuflo) {  /* Disable transmit stop on underflow */
-   val = lp-a.read_csr(ioaddr, 3);
+   val = lp-a.read_csr(ioaddr, CSR3);
val |= 0x40;
-   lp-a.write_csr(ioaddr, 3, val);
+   lp-a.write_csr(ioaddr, CSR3, val);
}
 #endif
 
@@ -2291,8 +2291,8 @@ static int pcnet32_open(struct net_devic
(lp-dma_addr +
 offsetof(struct pcnet32_private, init_block))  16);
 
-   lp-a.write_csr(ioaddr, 4, 0x0915);
-   lp-a.write_csr(ioaddr, 0, 0x0001);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
 
netif_start_queue(dev);
 
@@ -2304,13 +2304,13 @@ static int pcnet32_open(struct net_devic
 
i = 0;
while (i++  100)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_IDON)
break;
/*
 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
 * reports that doing so triggers a bug in the '974.
 */
-   lp-a.write_csr(ioaddr, 0, 0x0042);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_NORMAL);
 
if (netif_msg_ifup(lp))
printk(KERN_DEBUG
@@ -2318,7 +2318,7 @@ static int pcnet32_open(struct net_devic
   dev-name, i,
   (u32) (lp-dma_addr +
  offsetof(struct pcnet32_private, init_block)),
-  lp-a.read_csr(ioaddr, 0));
+  lp-a.read_csr(ioaddr, CSR0));
 
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -2389,7 +2389,7 @@ static int pcnet32_init_ring(struct net_
(rx_skbuff = lp-rx_skbuff[i] =
 dev_alloc_skb(PKT_BUF_SZ))) {
/* there is not much, we can do at this point */
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(KERN_ERR
   %s: pcnet32_init_ring 
dev_alloc_skb failed.\n,
   dev-name);
@@ -2439,7 +2439,7 @@ static void pcnet32_restart(struct net_d
 
/* wait for stop */
for (i = 0; i  100; i++)
-   if (lp-a.read_csr(ioaddr, 0)  0x0004)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_STOP)
break;
 
if (i = 100  netif_msg_drv(lp))
@@ -2452,13 +2452,13 @@ static void pcnet32_restart(struct net_d
return;
 
/* ReInit Ring */
-   lp-a.write_csr(ioaddr, 0, 1);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
i = 0;
while (i++  1000)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp

[PATCH 0/2] pcnet32: NAPI support

2006-09-08 Thread Don Fry
These patches to the pcnet32 driver implement NAPI and respond to some
other suggestions found during NAPI development and testing.

The comments from Francois Romieu regarding using spin_lock instead of
spin_lock_irqsave were investigated, but since interrupts have to be
disabled to prevent the interrupt handler from deadlocking, and since I
would probably forget sometime, it is safer to leave the locking as it
is.  The requested mmiowb calls were added.

Please appply to 2.6.19.

1/2 NAPI implementation.
2/2 Magic number cleanup.
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] pcnet32: NAPI implementation

2006-09-08 Thread Don Fry
Implement NAPI changes to pcnet32 driver.  Compile default is off.
Listed as experimental.

Len and Don both worked on a NAPI implementation and have both tested
these changes. 

An e1000 blasting short packets to the pcnet32 will lockup Don's system
until the receive storm stops.  Without NAPI Len's system watchdog would
expire causing the system to reboot.  With NAPI the system will stay
operational.

Tested ia32 and ppc64.  Tested '970A, '971, '972, '973, '975, '976, and
'978.

The Kconfig changes came from Len.  Don is to blame for all the others.

Signed-off-by: Len Sorensen [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/orig.Kconfig Wed Jun 28 10:38:45 2006
+++ linux-2.6.17-git13/drivers/net/Kconfig  Wed Jun 28 15:36:25 2006
@@ -1300,6 +1300,23 @@ config PCNET32
  file:Documentation/networking/net-modules.txt. The module
  will be called pcnet32.
 
+config PCNET32_NAPI
+   bool Use RX polling (NAPI) (EXPERIMENTAL)
+   depends on PCNET32  EXPERIMENTAL
+   help
+ NAPI is a new driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card. It is
+ still somewhat experimental and thus not yet enabled by default.
+
+ If your estimated Rx load is 10kpps or more, or if the card will be
+ deployed on potentially unfriendly networks (e.g. in a firewall),
+ then say Y here.
+
+ See file:Documentation/networking/NAPI_HOWTO.txt for more
+ information.
+
+ If in doubt, say N.
+
 config AMD8111_ETH
tristate AMD 8111 (new PCI lance) support
depends on NET_PCI  PCI
--- linux-2.6.18-rc6/drivers/net/pcnet32.c.orig Tue Aug 29 11:56:44 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Fri Sep  8 13:50:12 2006
@@ -21,9 +21,15 @@
  *
  */
 
+#include linux/config.h
+
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.32
-#define DRV_RELDATE18.Mar.2006
+#ifdef CONFIG_PCNET32_NAPI
+#define DRV_VERSION1.33-NAPI
+#else
+#define DRV_VERSION1.33
+#endif
+#define DRV_RELDATE27.Jun.2006
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -299,7 +305,6 @@ static int pcnet32_probe1(unsigned long,
 static int pcnet32_open(struct net_device *);
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
 static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
 static int pcnet32_close(struct net_device *);
@@ -883,7 +888,11 @@ static int pcnet32_loopback_test(struct 
rc = 1; /* default to fail */
 
if (netif_running(dev))
+#ifdef CONFIG_PCNET32_NAPI
+   pcnet32_netif_stop(dev);
+#else
pcnet32_close(dev);
+#endif
 
spin_lock_irqsave(lp-lock, flags);
lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* stop the chip */
@@ -1015,6 +1024,16 @@ static int pcnet32_loopback_test(struct 
x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
a-write_bcr(ioaddr, 32, (x  ~0x0002));
 
+#ifdef CONFIG_PCNET32_NAPI
+   if (netif_running(dev)) {
+   pcnet32_netif_start(dev);
+   pcnet32_restart(dev, CSR0_NORMAL);
+   } else {
+   pcnet32_purge_rx_ring(dev);
+   lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+   }
+   spin_unlock_irqrestore(lp-lock, flags);
+#else
if (netif_running(dev)) {
spin_unlock_irqrestore(lp-lock, flags);
pcnet32_open(dev);
@@ -1023,6 +1042,7 @@ static int pcnet32_loopback_test(struct 
lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(lp-lock, flags);
}
+#endif
 
return (rc);
 }  /* end pcnet32_loopback_test  */
@@ -1125,6 +1145,285 @@ static int pcnet32_suspend(struct net_de
return 1;
 }
 
+static int pcnet32_rx_entry(struct net_device *dev,
+   struct pcnet32_private *lp,
+   struct pcnet32_rx_head *rxp,
+   int entry)
+{
+   int status = (short)le16_to_cpu(rxp-status)  8;
+   int rx_in_place = 0;
+   struct sk_buff *skb;
+   short pkt_len;
+
+   if (status != 0x03) {   /* There was an error. */
+   /*
+* There is a tricky error noted by John Murphy,
+* [EMAIL PROTECTED] to Russ Nelson: Even with full-sized
+* buffers it's possible for a jabber packet to use two
+* buffers, with only the last correctly noting the error.
+*/
+   if (status  0x01)  /* Only count a general error

[PATCH 2/2] pcnet32: Magic number cleanup

2006-09-08 Thread Don Fry
Initial magic number cleanup.  Delete one unnecessary read and write.
Tested ia32 and ppc64.

Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc6/drivers/net/pcnet32.c.napi Fri Sep  8 13:19:53 2006
+++ linux-2.6.18-rc6/drivers/net/pcnet32.c  Fri Sep  8 13:57:13 2006
@@ -213,7 +213,7 @@ static int homepna[MAX_UNITS];
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
-   s16 buf_length;
+   s16 buf_length; /* two`s complement of length */
s16 status;
u32 msg_length;
u32 reserved;
@@ -221,7 +221,7 @@ struct pcnet32_rx_head {
 
 struct pcnet32_tx_head {
u32 base;
-   s16 length;
+   s16 length; /* two`s complement of length */
s16 status;
u32 misc;
u32 reserved;
@@ -901,7 +901,7 @@ static int pcnet32_loopback_test(struct 
 
/* Reset the PCNET32 */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
 
/* switch pcnet32 to 32bit mode */
lp-a.write_bcr(ioaddr, 20, 2);
@@ -1393,7 +1393,7 @@ static int pcnet32_poll(struct net_devic
if (pcnet32_tx(dev)) {
/* reset the chip to clear the error condition, then restart */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
pcnet32_restart(dev, CSR0_START);
netif_wake_queue(dev);
}
@@ -1901,7 +1901,7 @@ pcnet32_probe1(unsigned long ioaddr, int
 * boards will work.
 */
/* Trigger an initialization just for the interrupt. */
-   a-write_csr(ioaddr, 0, 0x41);
+   a-write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
mdelay(1);
 
dev-irq = probe_irq_off(irq_mask);
@@ -2268,9 +2268,9 @@ static int pcnet32_open(struct net_devic
 
 #ifdef DO_DXSUFLO
if (lp-dxsuflo) {  /* Disable transmit stop on underflow */
-   val = lp-a.read_csr(ioaddr, 3);
+   val = lp-a.read_csr(ioaddr, CSR3);
val |= 0x40;
-   lp-a.write_csr(ioaddr, 3, val);
+   lp-a.write_csr(ioaddr, CSR3, val);
}
 #endif
 
@@ -2291,8 +2291,8 @@ static int pcnet32_open(struct net_devic
(lp-dma_addr +
 offsetof(struct pcnet32_private, init_block))  16);
 
-   lp-a.write_csr(ioaddr, 4, 0x0915);
-   lp-a.write_csr(ioaddr, 0, 0x0001);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
 
netif_start_queue(dev);
 
@@ -2304,13 +2304,13 @@ static int pcnet32_open(struct net_devic
 
i = 0;
while (i++  100)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_IDON)
break;
/*
 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
 * reports that doing so triggers a bug in the '974.
 */
-   lp-a.write_csr(ioaddr, 0, 0x0042);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_NORMAL);
 
if (netif_msg_ifup(lp))
printk(KERN_DEBUG
@@ -2318,7 +2318,7 @@ static int pcnet32_open(struct net_devic
   dev-name, i,
   (u32) (lp-dma_addr +
  offsetof(struct pcnet32_private, init_block)),
-  lp-a.read_csr(ioaddr, 0));
+  lp-a.read_csr(ioaddr, CSR0));
 
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -2389,7 +2389,7 @@ static int pcnet32_init_ring(struct net_
(rx_skbuff = lp-rx_skbuff[i] =
 dev_alloc_skb(PKT_BUF_SZ))) {
/* there is not much, we can do at this point */
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(KERN_ERR
   %s: pcnet32_init_ring 
dev_alloc_skb failed.\n,
   dev-name);
@@ -2439,7 +2439,7 @@ static void pcnet32_restart(struct net_d
 
/* wait for stop */
for (i = 0; i  100; i++)
-   if (lp-a.read_csr(ioaddr, 0)  0x0004)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_STOP)
break;
 
if (i = 100  netif_msg_drv(lp))
@@ -2452,13 +2452,13 @@ static void pcnet32_restart(struct net_d
return;
 
/* ReInit Ring */
-   lp-a.write_csr(ioaddr, 0, 1);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
i = 0;
while (i++  1000)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp

Re: [PATCH] pcnet32: fix user visible typo

2006-08-29 Thread Don Fry
Alexey,

Your patch is fine.  I had not looked at the if which would prevent zero
cards from even printing.

On Mon, Aug 28, 2006 at 04:51:42PM -0700, Don Fry wrote:
 The cause of #6428 has already been fixed in v1.32 of the pcnet32
 driver.  To be correct, the printk should be:
 
   printk(KERN_INFO PFX %d card%s found\n,
   cards_found, cards_found != 1 ? s : );
 
 So that zero cards also says 'pcnet32: 0 cards found.'
 Why delete the period from the end of the sentence?
 
 On Tue, Aug 29, 2006 at 03:32:49AM +0400, Alexey Dobriyan wrote:
  Also, final dot removed and single form fixed. The cause of #6428 is
  still to be found.
  
  Signed-off-by: Alexey Dobriyan [EMAIL PROTECTED]
  ---
  
   drivers/net/pcnet32.c |3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)
  
  --- a/drivers/net/pcnet32.c
  +++ b/drivers/net/pcnet32.c
  @@ -2986,7 +2986,8 @@ static int __init pcnet32_init_module(vo
  pcnet32_probe_vlbus(pcnet32_portlist);
   
  if (cards_found  (pcnet32_debug  NETIF_MSG_PROBE))
  -   printk(KERN_INFO PFX %d cards_found.\n, cards_found);
  +   printk(KERN_INFO PFX %d card%s found\n,
  +   cards_found, cards_found  1 ? s : );
   
  return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
   }
  
  -
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] pcnet32: fix user visible typo

2006-08-28 Thread Don Fry
The cause of #6428 has already been fixed in v1.32 of the pcnet32
driver.  To be correct, the printk should be:

printk(KERN_INFO PFX %d card%s found\n,
cards_found, cards_found != 1 ? s : );

So that zero cards also says 'pcnet32: 0 cards found.'
Why delete the period from the end of the sentence?

On Tue, Aug 29, 2006 at 03:32:49AM +0400, Alexey Dobriyan wrote:
 Also, final dot removed and single form fixed. The cause of #6428 is
 still to be found.
 
 Signed-off-by: Alexey Dobriyan [EMAIL PROTECTED]
 ---
 
  drivers/net/pcnet32.c |3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 --- a/drivers/net/pcnet32.c
 +++ b/drivers/net/pcnet32.c
 @@ -2986,7 +2986,8 @@ static int __init pcnet32_init_module(vo
   pcnet32_probe_vlbus(pcnet32_portlist);
  
   if (cards_found  (pcnet32_debug  NETIF_MSG_PROBE))
 - printk(KERN_INFO PFX %d cards_found.\n, cards_found);
 + printk(KERN_INFO PFX %d card%s found\n,
 + cards_found, cards_found  1 ? s : );
  
   return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
  }
 
 -
 To unsubscribe from this list: send the line unsubscribe netdev in
 the body of a message to [EMAIL PROTECTED]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2.6.17 0/9] NetXen: 1G/10G Ethernet Driver

2006-08-23 Thread Don Fry
It looks like you have not run the source throught Lindent as previously
requested.  Before you submit the code again, please use the Lindent
script.

I can get the code to ping between two cards.  Will be doing more
testing tomorrow.

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: break in 2.6.18-rc1 identified

2006-08-22 Thread Don Fry
A change I made for 2.6.17 and another for 2.6.18 do not work on older
pcnet32 chips which I do not have access to.  If the chip is a 79C970 or
79C965, do not try and suspend or check the link status.
I have tested with a 79C970A, 79C971, 79C972, 79C973, 79C975, 79C976,
and 79C978.

Please apply to 2.6.18.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.18-rc3-git1/drivers/net/orig.pcnet32.cTue Aug  1 14:47:07 2006
+++ linux-2.6.18-rc3-git1/drivers/net/pcnet32.c Thu Aug  3 08:36:26 2006
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
 #define CSR15  15
 #define PCNET32_MC_FILTER  8
 
+#define PCNET32_79C970A0x2621
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
@@ -289,6 +291,7 @@ struct pcnet32_private {
 
/* each bit indicates an available PHY */
u32 phymask;
+   unsigned short  chip_version;   /* which variant this is */
 };
 
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_d
spin_lock_irqsave(lp-lock, flags);
if (lp-mii) {
r = mii_link_ok(lp-mii_if);
-   } else {
+   } else if (lp-chip_version = PCNET32_79C970A) {
ulong ioaddr = dev-base_addr;  /* card base I/O address */
r = (lp-a.read_bcr(ioaddr, 4) != 0xc0);
+   } else {/* can not detect link on really old chips */
+   r = 1;
}
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_de
ulong ioaddr = dev-base_addr;
int ticks;
 
+   /* really old chips have to be stopped. */
+   if (lp-chip_version  PCNET32_79C970A)
+   return 0;
+
/* set SUSPEND (SPND) - CSR5 bit 0 */
csr5 = a-read_csr(ioaddr, CSR5);
a-write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int
lp-mii_if.reg_num_mask = 0x1f;
lp-dxsuflo = dxsuflo;
lp-mii = mii;
+   lp-chip_version = chip_version;
lp-msg_enable = pcnet32_debug;
if ((cards_found = MAX_UNITS)
|| (options[cards_found]  sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_devic
val |= 2;
} else if (lp-options  PCNET32_PORT_ASEL) {
/* workaround of xSeries250, turn on for 79C975 only */
-   i = ((lp-a.read_csr(ioaddr, 88) |
- (lp-a.
-  read_csr(ioaddr, 89)  16))  12)  0x;
-   if (i == 0x2627)
+   if (lp-chip_version == 0x2627)
val |= 3;
}
lp-a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_devic
 
netif_start_queue(dev);
 
-   /* Print the link status and start the watchdog */
-   pcnet32_check_media(dev, 1);
-   mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+   if (lp-chip_version = PCNET32_79C970A) {
+   /* Print the link status and start the watchdog */
+   pcnet32_check_media(dev, 1);
+   mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+   }
 
i = 0;
while (i++  100)

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] pcnet32: break in 2.6.18-rc1 identified

2006-08-03 Thread Don Fry
A change I made for 2.6.17 and another for 2.6.18 do not work on older
pcnet32 chips which I do not have access to.  Please test this patch if
you have access to a 79C970, 79C974, or 79C965 (VLB) version of the
pcnet32 and let me know if it solves any problems.  I have tested with a
79C970A, 79C971, 79C972, 79C973, 79C975, 79C976, and 79C978 and the
changes work as expected.


--- linux-2.6.18-rc3-git1/drivers/net/orig.pcnet32.cTue Aug  1 14:47:07 2006
+++ linux-2.6.18-rc3-git1/drivers/net/pcnet32.c Thu Aug  3 08:36:26 2006
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
 #define CSR15  15
 #define PCNET32_MC_FILTER  8
 
+#define PCNET32_79C970A0x2621
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
@@ -289,6 +291,7 @@ struct pcnet32_private {
 
/* each bit indicates an available PHY */
u32 phymask;
+   unsigned short  chip_version;   /* which variant this is */
 };
 
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_d
spin_lock_irqsave(lp-lock, flags);
if (lp-mii) {
r = mii_link_ok(lp-mii_if);
-   } else {
+   } else if (lp-chip_version = PCNET32_79C970A) {
ulong ioaddr = dev-base_addr;  /* card base I/O address */
r = (lp-a.read_bcr(ioaddr, 4) != 0xc0);
+   } else {/* can not detect link on really old chips */
+   r = 1;
}
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_de
ulong ioaddr = dev-base_addr;
int ticks;
 
+   /* really old chips have to be stopped. */
+   if (lp-chip_version  PCNET32_79C970A)
+   return 1;
+
/* set SUSPEND (SPND) - CSR5 bit 0 */
csr5 = a-read_csr(ioaddr, CSR5);
a-write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int
lp-mii_if.reg_num_mask = 0x1f;
lp-dxsuflo = dxsuflo;
lp-mii = mii;
+   lp-chip_version = chip_version;
lp-msg_enable = pcnet32_debug;
if ((cards_found = MAX_UNITS)
|| (options[cards_found]  sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_devic
val |= 2;
} else if (lp-options  PCNET32_PORT_ASEL) {
/* workaround of xSeries250, turn on for 79C975 only */
-   i = ((lp-a.read_csr(ioaddr, 88) |
- (lp-a.
-  read_csr(ioaddr, 89)  16))  12)  0x;
-   if (i == 0x2627)
+   if (lp-chip_version == 0x2627)
val |= 3;
}
lp-a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_devic
 
netif_start_queue(dev);
 
-   /* Print the link status and start the watchdog */
-   pcnet32_check_media(dev, 1);
-   mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+   if (lp-chip_version = PCNET32_79C970A) {
+   /* Print the link status and start the watchdog */
+   pcnet32_check_media(dev, 1);
+   mod_timer((lp-watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+   }
 
i = 0;
while (i++  100)

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Simultanious transmits seems to cause hang on pcnet32

2006-07-18 Thread Don Fry
On Tue, Jul 18, 2006 at 11:20:17AM -0400, Lennart Sorensen wrote:
 I am currently doing some testing on my system and managing to totally
 hang the system (so that the watchdog has to come along and reboot it).
 
 The setup is this:
 I have a PLX PCI-PCI bridge with 4 79C972 chips behind it, each running
 100baseTX.  I am transmitting traffic from a smartbits test system from
 port 1 to port 3 and back, and from port 2 to port 4 and back.  I am
 running 500 packets/second with 60 byte packets each way.

I don't know what a 'smartbits test system' is or how it works.  Could
you please briefly explain what it is and does?

 
 If I start the traffic on all 4 ports at the same time, I get less than
 100 packets received back at the smartbits on each port, and then the
 linux kernel is hung.  No response to anything I have tried.  The
 watchdog then reboots the system.
 
 If I start traffic on less than 4 ports, and then add the remaining
 ports a second or so later, then it runs just fine and keeps up with the
 traffic.
 
 I tried making the traffic all flow out eth0 (an rtl8139 port) instead
 of out the pcnet32 ports, and then there is no problem, so I think there
 is some problem when multiple ports try to start transmitting at the
 same time.

Is the rdl8139 on the same PCI bus?

 
 So far it has failed with 2.6.8 and 2.6.16 and with 2.6.17's pcnet32
 with the napi patches applied.

Is there a version of the pcnet32 driver that does work?  Is this a
stock driver or do you have modifications made as well?

 
 I noticed that sometime between 2.6.4 and 2.6.8, the TxDone interrupts
 were removed entirely, where as they used to be sent every once in a
 while.  I am not sure if this is making a difference yet.

The ltint or TxDone interrupt deferral code was removed in May 2004,
2.6.7 timeframe.  Every transmit packet causes an interrupt, rather than
just occasionally.

 
 I tried increasing the ring sizes to their maximum setting of 9/9 rather
 than the current default of 4/5, and that didn't make any difference
 either.

Does reducing the ring size make any difference?  Or tx large/rx small,
or vice-versa?

 
 Does anyone have a suggestion for how to go about debuging this issue?
 So far I am very confused.

Is there any way to see what is happening on the PCI bus where the
pcnet32 devices are connected?  Or see what is happening on the master
side of the pci-to-pci bridge?  Do the chips share any interrupt lines
or do they all have dedicated irq's?

Is this an SMP or UP system?

 
 I tried turning on lots of debuging in pcnet32, but that seems to slow
 the system down enough (printing debug messages on the serial console)
 that it only manages to transmit 10 packets per port per second, at
 which point it doesn't lock up.  Reducing the test setting from 500
 60byte packets/second to 100 makes the problem disappear as well.
 
 So I am open for suggestions to try.  I really don't know where to go
 about debuging this when it makes the kernel lock up.  It makes me think
 it is getting stuck somewhere with interrupts disabled, but I can't see
 anything in the transmit code that looks like that could happen.
 
 --
 Len Sorensen
 -
 To unsubscribe from this list: send the line unsubscribe netdev in
 the body of a message to [EMAIL PROTECTED]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] pcnet32: Use kcalloc instead of kmalloc and memset

2006-06-29 Thread Don Fry

On 2006-03-08 Eric Sesterhenn wrote:
converts drivers/net to kzalloc usage.

Don Fry modified it to use netif_msg_drv.  Tested ia32 and ppc64.

Signed-off-by: Eric Sesterhenn [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/get.pcnet32.cWed Jun 28 11:17:09 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cWed Jun 28 11:55:52 2006
@@ -1432,7 +1432,7 @@ static int pcnet32_alloc_ring(struct net
   lp-tx_ring_size,
   lp-tx_ring_dma_addr);
if (lp-tx_ring == NULL) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Consistent memory allocation failed.\n,
   name);
@@ -1444,52 +1444,48 @@ static int pcnet32_alloc_ring(struct net
   lp-rx_ring_size,
   lp-rx_ring_dma_addr);
if (lp-rx_ring == NULL) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Consistent memory allocation failed.\n,
   name);
return -ENOMEM;
}
 
-   lp-tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp-tx_ring_size,
+   lp-tx_dma_addr = kcalloc(lp-tx_ring_size, sizeof(dma_addr_t),
  GFP_ATOMIC);
if (!lp-tx_dma_addr) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Memory allocation failed.\n, name);
return -ENOMEM;
}
-   memset(lp-tx_dma_addr, 0, sizeof(dma_addr_t) * lp-tx_ring_size);
 
-   lp-rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp-rx_ring_size,
+   lp-rx_dma_addr = kcalloc(lp-rx_ring_size, sizeof(dma_addr_t),
  GFP_ATOMIC);
if (!lp-rx_dma_addr) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Memory allocation failed.\n, name);
return -ENOMEM;
}
-   memset(lp-rx_dma_addr, 0, sizeof(dma_addr_t) * lp-rx_ring_size);
 
-   lp-tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp-tx_ring_size,
+   lp-tx_skbuff = kcalloc(lp-tx_ring_size, sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!lp-tx_skbuff) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Memory allocation failed.\n, name);
return -ENOMEM;
}
-   memset(lp-tx_skbuff, 0, sizeof(struct sk_buff *) * lp-tx_ring_size);
 
-   lp-rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp-rx_ring_size,
+   lp-rx_skbuff = kcalloc(lp-rx_ring_size, sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!lp-rx_skbuff) {
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(\n KERN_ERR PFX
   %s: Memory allocation failed.\n, name);
return -ENOMEM;
}
-   memset(lp-rx_skbuff, 0, sizeof(struct sk_buff *) * lp-rx_ring_size);
 
return 0;
 }
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/9] pcnet32: Fix off-by-one in get_ringparam

2006-06-29 Thread Don Fry

Fix off-by-one in pcnet32_get_ringparam

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/device.pcnet32.c Wed Jun 28 11:12:22 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cWed Jun 28 11:16:15 2006
@@ -515,10 +515,10 @@ static void pcnet32_get_ringparam(struct
 {
struct pcnet32_private *lp = dev-priv;
 
-   ering-tx_max_pending = TX_MAX_RING_SIZE - 1;
-   ering-tx_pending = lp-tx_ring_size - 1;
-   ering-rx_max_pending = RX_MAX_RING_SIZE - 1;
-   ering-rx_pending = lp-rx_ring_size - 1;
+   ering-tx_max_pending = TX_MAX_RING_SIZE;
+   ering-tx_pending = lp-tx_ring_size;
+   ering-rx_max_pending = RX_MAX_RING_SIZE;
+   ering-rx_pending = lp-rx_ring_size;
 }
 
 static int pcnet32_set_ringparam(struct net_device *dev,
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/9] pcnet32: Use PCI_DEVICE macro

2006-06-29 Thread Don Fry
Jon Mason wrote on Thu, 12 Jan 2006 17:07:49 -0600:
This patch adds the PCI_DEVICE macro to the pcnet32 driver.

This has been tested on my opteron with my trident adapter.

Don Fry modified it slightly and tested on ia32 and ppc64.

Signed-off-by: Jon Mason [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/mismatch.pcnet32.c   Wed Jun 28 11:03:38 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cWed Jun 28 11:11:37 2006
@@ -58,18 +58,15 @@ static const char *const version =
  * PCI device identifiers for new style Linux PCI Device Drivers
  */
 static struct pci_device_id pcnet32_pci_tbl[] = {
-   { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-   { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+   { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
+   { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
 
/*
 * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
 * the incorrect vendor id.
 */
-   { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_NETWORK_ETHERNET  8, 0x00, 0},
+   { PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
+ .class = (PCI_CLASS_NETWORK_ETHERNET  8), .class_mask = 0x00, },
 
{ } /* terminate list */
 };
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/9] pcnet32: NAPI support

2006-06-29 Thread Don Fry
These patches to the pcnet32 driver implement NAPI and fix some other
errors found during NAPI development and testing.  Please apply to
2.6.18.

1/9 Fix Section mismatch error
2/9 Use PCI_DEVICE macro
3/9 Fix off-by-one in get_ringparam
4/9 Use kcalloc instead of kmalloc and memset
5/9 Handle memory allocation failures cleanly when resizing tx/rx rings
6/9 Suspend the chip rather than restart when changing multicast/promisc
7/9 Cleanup rx buffers after loopback test.
8/9 NAPI implementation.
9/9 Magic number cleanup.
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] pcnet32: Suspend the chip rather than restart when changing multicast/promisc

2006-06-29 Thread Don Fry

Suspend the chip if possible rather than stop and discard all tx and rx
frames, when changing the mcast list or entering/leaving promiscuous
mode.  Created common pcnet32_suspend routine.

Tested ia32 and ppc64

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/set.pcnet32.cWed Jun 28 13:13:52 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cWed Jun 28 15:16:58 2006
@@ -1062,6 +1062,43 @@ static int pcnet32_phys_id(struct net_de
return 0;
 }
 
+/*
+ * lp-lock must be held.
+ */
+static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
+   int can_sleep)
+{
+   int csr5;
+   struct pcnet32_private *lp = dev-priv;
+   struct pcnet32_access *a = lp-a;
+   ulong ioaddr = dev-base_addr;
+   int ticks;
+
+   /* set SUSPEND (SPND) - CSR5 bit 0 */
+   csr5 = a-read_csr(ioaddr, CSR5);
+   a-write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
+
+   /* poll waiting for bit to be set */
+   ticks = 0;
+   while (!(a-read_csr(ioaddr, CSR5)  CSR5_SUSPEND)) {
+   spin_unlock_irqrestore(lp-lock, *flags);
+   if (can_sleep)
+   msleep(1);
+   else
+   mdelay(1);
+   spin_lock_irqsave(lp-lock, *flags);
+   ticks++;
+   if (ticks  200) {
+   if (netif_msg_hw(lp))
+   printk(KERN_DEBUG
+  %s: Error getting into suspend!\n,
+  dev-name);
+   return 0;
+   }
+   }
+   return 1;
+}
+
 #define PCNET32_REGS_PER_PHY   32
 #define PCNET32_MAX_PHYS   32
 static int pcnet32_get_regs_len(struct net_device *dev)
@@ -1080,32 +1117,13 @@ static void pcnet32_get_regs(struct net_
struct pcnet32_private *lp = dev-priv;
struct pcnet32_access *a = lp-a;
ulong ioaddr = dev-base_addr;
-   int ticks;
unsigned long flags;
 
spin_lock_irqsave(lp-lock, flags);
 
-   csr0 = a-read_csr(ioaddr, 0);
-   if (!(csr0  0x0004)) { /* If not stopped */
-   /* set SUSPEND (SPND) - CSR5 bit 0 */
-   a-write_csr(ioaddr, 5, 0x0001);
-
-   /* poll waiting for bit to be set */
-   ticks = 0;
-   while (!(a-read_csr(ioaddr, 5)  0x0001)) {
-   spin_unlock_irqrestore(lp-lock, flags);
-   mdelay(1);
-   spin_lock_irqsave(lp-lock, flags);
-   ticks++;
-   if (ticks  200) {
-   if (netif_msg_hw(lp))
-   printk(KERN_DEBUG
-  %s: Error getting into 
suspend!\n,
-  dev-name);
-   break;
-   }
-   }
-   }
+   csr0 = a-read_csr(ioaddr, CSR0);
+   if (!(csr0  CSR0_STOP))/* If not stopped */
+   pcnet32_suspend(dev, flags, 1);
 
/* read address PROM */
for (i = 0; i  16; i += 2)
@@ -1142,9 +1160,12 @@ static void pcnet32_get_regs(struct net_
}
}
 
-   if (!(csr0  0x0004)) { /* If not stopped */
+   if (!(csr0  CSR0_STOP)) {  /* If not stopped */
+   int csr5;
+
/* clear SUSPEND (SPND) - CSR5 bit 0 */
-   a-write_csr(ioaddr, 5, 0x);
+   csr5 = a-read_csr(ioaddr, CSR5);
+   a-write_csr(ioaddr, CSR5, csr5  (~CSR5_SUSPEND));
}
 
spin_unlock_irqrestore(lp-lock, flags);
@@ -2652,6 +2673,7 @@ static void pcnet32_load_multicast(struc
volatile struct pcnet32_init_block *ib = lp-init_block;
volatile u16 *mcast_table = (u16 *)  ib-filter;
struct dev_mc_list *dmi = dev-mc_list;
+   unsigned long ioaddr = dev-base_addr;
char *addrs;
int i;
u32 crc;
@@ -2660,6 +2682,10 @@ static void pcnet32_load_multicast(struc
if (dev-flags  IFF_ALLMULTI) {
ib-filter[0] = 0x;
ib-filter[1] = 0x;
+   lp-a.write_csr(ioaddr, PCNET32_MC_FILTER, 0x);
+   lp-a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0x);
+   lp-a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0x);
+   lp-a.write_csr(ioaddr, PCNET32_MC_FILTER+3, 0x);
return;
}
/* clear the multicast filter */
@@ -2681,6 +2707,9 @@ static void pcnet32_load_multicast(struc
le16_to_cpu(le16_to_cpu(mcast_table[crc  4]) |
(1  (crc  0xf)));
}
+   for (i = 0; i  4; i++)
+   lp-a.write_csr(ioaddr, PCNET32_MC_FILTER + i,
+   le16_to_cpu(mcast_table[i]));
return;
 }
 
@@ -2691,8 +2720,11 @@ static void

[PATCH 7/9] pcnet32: Cleanup rx buffers after loopback test.

2006-06-29 Thread Don Fry

More cleanup to pcnet32_loopback_test to release receive buffers if
device is not up.  Created common routine to free rx buffers.

Tested ia32 and ppc64

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/mcast.pcnet32.c  Wed Jun 28 15:16:58 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cThu Jun 29 13:09:40 2006
@@ -645,6 +645,25 @@ static void pcnet32_realloc_rx_ring(stru
return;
 }
 
+static void pcnet32_purge_rx_ring(struct net_device *dev)
+{
+   struct pcnet32_private *lp = dev-priv;
+   int i;
+
+   /* free all allocated skbuffs */
+   for (i = 0; i  lp-rx_ring_size; i++) {
+   lp-rx_ring[i].status = 0;  /* CPU owns buffer */
+   wmb();  /* Make sure adapter sees owner change */
+   if (lp-rx_skbuff[i]) {
+   pci_unmap_single(lp-pci_dev, lp-rx_dma_addr[i],
+PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+   dev_kfree_skb_any(lp-rx_skbuff[i]);
+   }
+   lp-rx_skbuff[i] = NULL;
+   lp-rx_dma_addr[i] = 0;
+   }
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void pcnet32_poll_controller(struct net_device *dev)
 {
@@ -856,29 +875,27 @@ static int pcnet32_loopback_test(struct 
unsigned long flags;
unsigned long ticks;
 
-   *data1 = 1; /* status of test, default to fail */
rc = 1; /* default to fail */
 
if (netif_running(dev))
pcnet32_close(dev);
 
spin_lock_irqsave(lp-lock, flags);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* stop the chip */
+
+   numbuffs = min(numbuffs, (int)min(lp-rx_ring_size, lp-tx_ring_size));
 
/* Reset the PCNET32 */
lp-a.reset(ioaddr);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);
 
/* switch pcnet32 to 32bit mode */
lp-a.write_bcr(ioaddr, 20, 2);
 
-   lp-init_block.mode =
-   le16_to_cpu((lp-options  PCNET32_PORT_PORTSEL)  7);
-   lp-init_block.filter[0] = 0;
-   lp-init_block.filter[1] = 0;
-
/* purge  init rings but don't actually restart */
pcnet32_restart(dev, 0x);
 
-   lp-a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* Set STOP bit */
 
/* Initialize Transmit buffers. */
size = data_len + 15;
@@ -920,14 +937,15 @@ static int pcnet32_loopback_test(struct 
}
}
 
-   x = a-read_bcr(ioaddr, 32);/* set internal loopback in BSR32 */
-   x = x | 0x0002;
-   a-write_bcr(ioaddr, 32, x);
+   x = a-read_bcr(ioaddr, 32);/* set internal loopback in BCR32 */
+   a-write_bcr(ioaddr, 32, x | 0x0002);
 
-   lp-a.write_csr(ioaddr, 15, 0x0044);/* set int loopback in CSR15 */
+   /* set int loopback in CSR15 */
+   x = a-read_csr(ioaddr, CSR15)  0xfffc;
+   lp-a.write_csr(ioaddr, CSR15, x | 0x0044);
 
teststatus = le16_to_cpu(0x8000);
-   lp-a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_START);  /* Set STRT bit */
 
/* Check status of descriptors */
for (x = 0; x  numbuffs; x++) {
@@ -935,7 +953,7 @@ static int pcnet32_loopback_test(struct 
rmb();
while ((lp-rx_ring[x].status  teststatus)  (ticks  200)) {
spin_unlock_irqrestore(lp-lock, flags);
-   mdelay(1);
+   msleep(1);
spin_lock_irqsave(lp-lock, flags);
rmb();
ticks++;
@@ -948,7 +966,7 @@ static int pcnet32_loopback_test(struct 
}
}
 
-   lp-a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* Set STOP bit */
wmb();
if (netif_msg_hw(lp)  netif_msg_pktdata(lp)) {
printk(KERN_DEBUG %s: RX loopback packets:\n, dev-name);
@@ -981,25 +999,24 @@ static int pcnet32_loopback_test(struct 
}
x++;
}
-   if (!rc) {
-   *data1 = 0;
-   }
 
   clean_up:
+   *data1 = rc;
pcnet32_purge_tx_ring(dev);
-   x = a-read_csr(ioaddr, 15)  0x;
-   a-write_csr(ioaddr, 15, (x  ~0x0044));/* reset bits 6 and 2 */
 
-   x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
-   x = x  ~0x0002;
-   a-write_bcr(ioaddr, 32, x);
+   x = a-read_csr(ioaddr, CSR15);
+   a-write_csr(ioaddr, CSR15, (x  ~0x0044)); /* reset bits 6 and 2 */
 
-   spin_unlock_irqrestore(lp-lock, flags);
+   x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
+   a-write_bcr(ioaddr, 32, (x  ~0x0002));
 
if (netif_running(dev)) {
+   spin_unlock_irqrestore(lp-lock, flags);
pcnet32_open(dev);
} else

[PATCH 8/9] pcnet32: NAPI implementation.

2006-06-29 Thread Don Fry

Implement NAPI changes to pcnet32 driver.  Compile default is off.
Listed as experimental.

Len and Don both worked on a NAPI implementation and have both tested
these changes. 

An e1000 blasting short packets to the pcnet32 will lockup Don's system
until the receive storm stops.  Without NAPI Len's system watchdog would
expire causing the system to reboot.  With NAPI the system will stay
operational.

Tested ia32 and ppc64.  Tested '970A, '971, '972, '973, '975, '976, and
'978.

The Kconfig changes came from Len.  Don is to blame for all the others.

Signed-off-by: Len Sorensen [EMAIL PROTECTED]
Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/orig.Kconfig Wed Jun 28 10:38:45 2006
+++ linux-2.6.17-git13/drivers/net/Kconfig  Wed Jun 28 15:36:25 2006
@@ -1300,6 +1300,23 @@ config PCNET32
  file:Documentation/networking/net-modules.txt. The module
  will be called pcnet32.
 
+config PCNET32_NAPI
+   bool Use RX polling (NAPI) (EXPERIMENTAL)
+   depends on PCNET32  EXPERIMENTAL
+   help
+ NAPI is a new driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card. It is
+ still somewhat experimental and thus not yet enabled by default.
+
+ If your estimated Rx load is 10kpps or more, or if the card will be
+ deployed on potentially unfriendly networks (e.g. in a firewall),
+ then say Y here.
+
+ See file:Documentation/networking/NAPI_HOWTO.txt for more
+ information.
+
+ If in doubt, say N.
+
 config AMD8111_ETH
tristate AMD 8111 (new PCI lance) support
depends on NET_PCI  PCI
--- linux-2.6.17-git13/drivers/net/purge.pcnet32.c  Thu Jun 29 13:28:24 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cThu Jun 29 13:28:31 2006
@@ -21,9 +21,15 @@
  *
  */
 
+#include linux/config.h
+
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.32
-#define DRV_RELDATE18.Mar.2006
+#ifdef CONFIG_PCNET32_NAPI
+#define DRV_VERSION1.33-NAPI
+#else
+#define DRV_VERSION1.33
+#endif
+#define DRV_RELDATE27.Jun.2006
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -296,7 +302,6 @@ static int pcnet32_probe1(unsigned long,
 static int pcnet32_open(struct net_device *);
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
 static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
 static int pcnet32_close(struct net_device *);
@@ -878,7 +883,11 @@ static int pcnet32_loopback_test(struct 
rc = 1; /* default to fail */
 
if (netif_running(dev))
+#ifdef CONFIG_PCNET32_NAPI
+   pcnet32_netif_stop(dev);
+#else
pcnet32_close(dev);
+#endif
 
spin_lock_irqsave(lp-lock, flags);
lp-a.write_csr(ioaddr, CSR0, CSR0_STOP);   /* stop the chip */
@@ -1010,6 +1019,16 @@ static int pcnet32_loopback_test(struct 
x = a-read_bcr(ioaddr, 32);/* reset internal loopback */
a-write_bcr(ioaddr, 32, (x  ~0x0002));
 
+#ifdef CONFIG_PCNET32_NAPI
+   if (netif_running(dev)) {
+   pcnet32_netif_start(dev);
+   pcnet32_restart(dev, CSR0_NORMAL);
+   } else {
+   pcnet32_purge_rx_ring(dev);
+   lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+   }
+   spin_unlock_irqrestore(lp-lock, flags);
+#else
if (netif_running(dev)) {
spin_unlock_irqrestore(lp-lock, flags);
pcnet32_open(dev);
@@ -1018,6 +1037,7 @@ static int pcnet32_loopback_test(struct 
lp-a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(lp-lock, flags);
}
+#endif
 
return (rc);
 }  /* end pcnet32_loopback_test  */
@@ -1116,6 +1136,285 @@ static int pcnet32_suspend(struct net_de
return 1;
 }
 
+static int pcnet32_rx_entry(struct net_device *dev,
+   struct pcnet32_private *lp,
+   struct pcnet32_rx_head *rxp,
+   int entry)
+{
+   int status = (short)le16_to_cpu(rxp-status)  8;
+   int rx_in_place = 0;
+   struct sk_buff *skb;
+   short pkt_len;
+
+   if (status != 0x03) {   /* There was an error. */
+   /*
+* There is a tricky error noted by John Murphy,
+* [EMAIL PROTECTED] to Russ Nelson: Even with full-sized
+* buffers it's possible for a jabber packet to use two
+* buffers, with only the last correctly noting the error.
+*/
+   if (status  0x01)  /* Only count a general error

[PATCH 9/9] pcnet32: Magic number cleanup.

2006-06-29 Thread Don Fry

Initial magic number cleanup.  Delete one unnecessary read and write.
Tested ia32 and ppc64.

Signed-off-by: Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/napi.pcnet32.c   Thu Jun 29 13:25:50 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cThu Jun 29 13:30:46 2006
@@ -211,7 +211,7 @@ static int homepna[MAX_UNITS];
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
-   s16 buf_length;
+   s16 buf_length; /* two`s complement of length */
s16 status;
u32 msg_length;
u32 reserved;
@@ -219,7 +219,7 @@ struct pcnet32_rx_head {
 
 struct pcnet32_tx_head {
u32 base;
-   s16 length;
+   s16 length; /* two`s complement of length */
s16 status;
u32 misc;
u32 reserved;
@@ -896,7 +896,7 @@ static int pcnet32_loopback_test(struct 
 
/* Reset the PCNET32 */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
 
/* switch pcnet32 to 32bit mode */
lp-a.write_bcr(ioaddr, 20, 2);
@@ -1384,7 +1384,7 @@ static int pcnet32_poll(struct net_devic
if (pcnet32_tx(dev)) {
/* reset the chip to clear the error condition, then restart */
lp-a.reset(ioaddr);
-   lp-a.write_csr(ioaddr, CSR4, 0x0915);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
pcnet32_restart(dev, CSR0_START);
netif_wake_queue(dev);
}
@@ -1891,7 +1891,7 @@ pcnet32_probe1(unsigned long ioaddr, int
 * boards will work.
 */
/* Trigger an initialization just for the interrupt. */
-   a-write_csr(ioaddr, 0, 0x41);
+   a-write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
mdelay(1);
 
dev-irq = probe_irq_off(irq_mask);
@@ -2261,9 +2261,9 @@ static int pcnet32_open(struct net_devic
 
 #ifdef DO_DXSUFLO
if (lp-dxsuflo) {  /* Disable transmit stop on underflow */
-   val = lp-a.read_csr(ioaddr, 3);
+   val = lp-a.read_csr(ioaddr, CSR3);
val |= 0x40;
-   lp-a.write_csr(ioaddr, 3, val);
+   lp-a.write_csr(ioaddr, CSR3, val);
}
 #endif
 
@@ -2284,8 +2284,8 @@ static int pcnet32_open(struct net_devic
(lp-dma_addr +
 offsetof(struct pcnet32_private, init_block))  16);
 
-   lp-a.write_csr(ioaddr, 4, 0x0915);
-   lp-a.write_csr(ioaddr, 0, 0x0001);
+   lp-a.write_csr(ioaddr, CSR4, 0x0915);  /* auto tx pad */
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
 
netif_start_queue(dev);
 
@@ -2295,13 +2295,13 @@ static int pcnet32_open(struct net_devic
 
i = 0;
while (i++  100)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_IDON)
break;
/*
 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
 * reports that doing so triggers a bug in the '974.
 */
-   lp-a.write_csr(ioaddr, 0, 0x0042);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_NORMAL);
 
if (netif_msg_ifup(lp))
printk(KERN_DEBUG
@@ -2309,7 +2309,7 @@ static int pcnet32_open(struct net_devic
   dev-name, i,
   (u32) (lp-dma_addr +
  offsetof(struct pcnet32_private, init_block)),
-  lp-a.read_csr(ioaddr, 0));
+  lp-a.read_csr(ioaddr, CSR0));
 
spin_unlock_irqrestore(lp-lock, flags);
 
@@ -2380,7 +2380,7 @@ static int pcnet32_init_ring(struct net_
(rx_skbuff = lp-rx_skbuff[i] =
 dev_alloc_skb(PKT_BUF_SZ))) {
/* there is not much, we can do at this point */
-   if (pcnet32_debug  NETIF_MSG_DRV)
+   if (netif_msg_drv(lp))
printk(KERN_ERR
   %s: pcnet32_init_ring 
dev_alloc_skb failed.\n,
   dev-name);
@@ -2430,7 +2430,7 @@ static void pcnet32_restart(struct net_d
 
/* wait for stop */
for (i = 0; i  100; i++)
-   if (lp-a.read_csr(ioaddr, 0)  0x0004)
+   if (lp-a.read_csr(ioaddr, CSR0)  CSR0_STOP)
break;
 
if (i = 100  netif_msg_drv(lp))
@@ -2443,13 +2443,13 @@ static void pcnet32_restart(struct net_d
return;
 
/* ReInit Ring */
-   lp-a.write_csr(ioaddr, 0, 1);
+   lp-a.write_csr(ioaddr, CSR0, CSR0_INIT);
i = 0;
while (i++  1000)
-   if (lp-a.read_csr(ioaddr, 0)  0x0100

[PATCH 5/9] pcnet32: Handle memory allocation failures cleanly when resizing tx/rx rings

2006-06-29 Thread Don Fry

Fix pcnet32_set_ringparam to handle memory allocation errors without
leaving the adapter in an inoperative state and null pointers waiting to
be dereferenced.

Tested ia32 and ppc64.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-git13/drivers/net/calloc.pcnet32.c Wed Jun 28 11:55:52 2006
+++ linux-2.6.17-git13/drivers/net/pcnet32.cWed Jun 28 13:13:52 2006
@@ -185,6 +185,23 @@ static int homepna[MAX_UNITS];
 
 #define PCNET32_TOTAL_SIZE 0x20
 
+#define CSR0   0
+#define CSR0_INIT  0x1
+#define CSR0_START 0x2
+#define CSR0_STOP  0x4
+#define CSR0_TXPOLL0x8
+#define CSR0_INTEN 0x40
+#define CSR0_IDON  0x0100
+#define CSR0_NORMAL(CSR0_START | CSR0_INTEN)
+#define PCNET32_INIT_LOW   1
+#define PCNET32_INIT_HIGH  2
+#define CSR3   3
+#define CSR4   4
+#define CSR5   5
+#define CSR5_SUSPEND   0x0001
+#define CSR15  15
+#define PCNET32_MC_FILTER  8
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
u32 base;
@@ -415,6 +432,219 @@ static struct pcnet32_access pcnet32_dwi
.reset = pcnet32_dwio_reset
 };
 
+static void pcnet32_netif_stop(struct net_device *dev)
+{
+   dev-trans_start = jiffies;
+   netif_poll_disable(dev);
+   netif_tx_disable(dev);
+}
+
+static void pcnet32_netif_start(struct net_device *dev)
+{
+   netif_wake_queue(dev);
+   netif_poll_enable(dev);
+}
+
+/*
+ * Allocate space for the new sized tx ring.
+ * Free old resources
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp-lock held.
+ */
+static void pcnet32_realloc_tx_ring(struct net_device *dev,
+   struct pcnet32_private *lp,
+   unsigned int size)
+{
+   dma_addr_t new_ring_dma_addr;
+   dma_addr_t *new_dma_addr_list;
+   struct pcnet32_tx_head *new_tx_ring;
+   struct sk_buff **new_skb_list;
+
+   pcnet32_purge_tx_ring(dev);
+
+   new_tx_ring = pci_alloc_consistent(lp-pci_dev,
+  sizeof(struct pcnet32_tx_head) *
+  (1  size),
+  new_ring_dma_addr);
+   if (new_tx_ring == NULL) {
+   if (netif_msg_drv(lp))
+   printk(\n KERN_ERR
+  %s: Consistent memory allocation failed.\n,
+  dev-name);
+   return;
+   }
+   memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1  size));
+
+   new_dma_addr_list = kcalloc((1  size), sizeof(dma_addr_t),
+   GFP_ATOMIC);
+   if (!new_dma_addr_list) {
+   if (netif_msg_drv(lp))
+   printk(\n KERN_ERR
+  %s: Memory allocation failed.\n, dev-name);
+   goto free_new_tx_ring;
+   }
+
+   new_skb_list = kcalloc((1  size), sizeof(struct sk_buff *),
+   GFP_ATOMIC);
+   if (!new_skb_list) {
+   if (netif_msg_drv(lp))
+   printk(\n KERN_ERR
+  %s: Memory allocation failed.\n, dev-name);
+   goto free_new_lists;
+   }
+
+   kfree(lp-tx_skbuff);
+   kfree(lp-tx_dma_addr);
+   pci_free_consistent(lp-pci_dev,
+   sizeof(struct pcnet32_tx_head) *
+   lp-tx_ring_size, lp-tx_ring,
+   lp-tx_ring_dma_addr);
+
+   lp-tx_ring_size = (1  size);
+   lp-tx_mod_mask = lp-tx_ring_size - 1;
+   lp-tx_len_bits = (size  12);
+   lp-tx_ring = new_tx_ring;
+   lp-tx_ring_dma_addr = new_ring_dma_addr;
+   lp-tx_dma_addr = new_dma_addr_list;
+   lp-tx_skbuff = new_skb_list;
+   return;
+
+free_new_lists:
+   kfree(new_dma_addr_list);
+free_new_tx_ring:
+   pci_free_consistent(lp-pci_dev,
+   sizeof(struct pcnet32_tx_head) *
+   (1  size),
+   new_tx_ring,
+   new_ring_dma_addr);
+   return;
+}
+
+/*
+ * Allocate space for the new sized rx ring.
+ * Re-use old receive buffers.
+ *   alloc extra buffers
+ *   free unneeded buffers
+ *   free unneeded buffers
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp-lock held.
+ */
+static void pcnet32_realloc_rx_ring(struct net_device *dev,
+   struct pcnet32_private *lp,
+   unsigned int size)
+{
+   dma_addr_t new_ring_dma_addr;
+   dma_addr_t *new_dma_addr_list;
+   struct pcnet32_rx_head *new_rx_ring;
+   struct sk_buff **new_skb_list;
+   int new, overlap;
+
+   new_rx_ring = pci_alloc_consistent(lp-pci_dev,
+  sizeof(struct pcnet32_rx_head

Re: [PATCH 8/9] pcnet32: NAPI implementation.

2006-06-29 Thread Don Fry
On Fri, Jun 30, 2006 at 12:24:38AM +0200, Francois Romieu wrote:
 Nit below.
 
 Don Fry [EMAIL PROTECTED] :
 [...]
  --- linux-2.6.17-git13/drivers/net/purge.pcnet32.c  Thu Jun 29 13:28:24 2006
  +++ linux-2.6.17-git13/drivers/net/pcnet32.cThu Jun 29 13:28:31 2006
 [...]
  +#ifdef CONFIG_PCNET32_NAPI
  +static int pcnet32_poll(struct net_device *dev, int *budget)
  +{
 [...]
  +   netif_rx_complete(dev);
  +
  +   spin_lock_irqsave(lp-lock, flags);
 
 No need to save/restore (it's true in pcnet32_{get_regs/suspend} too).

This lock is taken by the interrupt handler and my reading of
spinlocks.txt says I do need to use spin_lock_irqsave unless I
misunderstand.  The only spin_lock() is in the interrupt handler itself,
all others are spin_lock_irqsave.

 
  +
  +   /* clear interrupt masks */
  +   val = lp-a.read_csr(ioaddr, CSR3);
  +   val = 0x00ff;
  +   lp-a.write_csr(ioaddr, CSR3, val);
  +
  +   /* Set interrupt enable. */
  +   lp-a.write_csr(ioaddr, CSR0, CSR0_INTEN);
 
 Insert mmiowb():

Is this required in addition to the two outw() in write_csr?  There are
rmb() and wmb() in the places that need them, but no mmiowb() anywhere.
What are the factors for when mmiowb needs to be inserted?

 
  +
  +   spin_unlock_irqrestore(lp-lock, flags);
 
 [...]
  @@ -2413,183 +2608,41 @@ pcnet32_interrupt(int irq, void *dev_id,
 dev-name, csr0);
  /* unlike for the lance, there is no restart needed */
  }
  -
  -   if (must_restart) {
  +#ifdef CONFIG_PCNET32_NAPI
  +   if (netif_rx_schedule_prep(dev)) {
  +   u16 val;
  +   /* set interrupt masks */
  +   val = lp-a.read_csr(ioaddr, CSR3);
  +   val |= 0x5f00;
  +   lp-a.write_csr(ioaddr, CSR3, val);
 
 Insert mmiowb();
 
 -- 
 Ueimor

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFT PATCH] pcnet32: NAPI support

2006-06-28 Thread Don Fry
On Wed, Jun 28, 2006 at 10:40:10AM -0400, Lennart Sorensen wrote:
 On Fri, Jun 23, 2006 at 02:32:12PM -0700, Don Fry wrote:
  This set of changes combines the work done by Len Sorensen and myself to
  add compile time support for NAPI for the pcnet32 driver.  I have tested
  it on ia32 and ppc64 hardware with various versions of the pcnet32
  adapter.  I have also made a few changes requested by Jon Mason, but the
  substitution of the many magic numbers in the driver is not yet done.
  
  If no-one encounters any problems when testing this, I will break up the
  several changes, into proper patches and submit them next week.
 
 Well so far this is working for me.  It is a somewhat different layout
 of the interrupt handler so it took me a bit of work to get the features
 I need patched in, but in the end I ended up with simpler code as a
 reesult, so I am quite happy with the new layout.  The driver works on
 everything I have to try it on so far.
 

snip

Yes, I saw the debug statements when creating the email and was too lazy
to remove them and create a new patch.  The patch needs to be broken up
into functional pieces anyway, so since it has passed all of my testing
as well, I will start on that...

 
 So yep, looks pretty good to me.  Those two debug statements are my only
 comments on it.
 
 Len Sorensen

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFT] pcnet32 NAPI changes

2006-06-16 Thread Don Fry
This patch is a collection of changes to pcnet32 which does the
following: 

- Fix section mismatch warning.
- fix set_ringparam to correctly handle memory allocation failures
- fix off-by-one in get_ringparam.
- cleanup at end of loopback_test when not up.
- Add NAPI to driver, fixing set_ringparam and loopback_test to work
  correctly with poll.
- for multicast, do not reset the chip unless cannot enter suspend mode
  to avoid race with poll.

The set_ringparam code is larger than I would prefer, but it will not
leave null pointers around for the code to stumble over when memory
allocation fails.  If anyone has a better idea, please let me know.

Some complexity could be avoided by allocating memory for the maximum
number of tx and rx buffers at probe time.  Requiring 14k for the tx
ring and arrays, and another 14k for rx; instead of about 10k total for
the default sizes.

It is NAPI only, unlike Len Sorensen's version which allows for compile
time selection.  Some drivers are NAPI only, others have compile
options.  Which is preferred?

I have tested these changes with a 79C971, 973, 976, and 978 on a ppc64
machine, and 970A, 972, 973, 975, and 976 on an x86 machine.

I have not tested these changes with VMware or Xen.



--- linux-2.6.17-rc6/drivers/net/orig.pcnet32.c 2006-06-15 11:49:39.0 
-0700
+++ linux-2.6.17-rc6/drivers/net/pcnet32.c  2006-06-16 11:30:45.0 
-0700
@@ -22,8 +22,8 @@
  */
 
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.32
-#define DRV_RELDATE18.Mar.2006
+#define DRV_VERSION1.33-NAPI
+#define DRV_RELDATE16.Jun.2006
 #define PFXDRV_NAME : 
 
 static const char *const version =
@@ -277,13 +277,12 @@ struct pcnet32_private {
u32 phymask;
 };
 
-static void pcnet32_probe_vlbus(void);
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
 static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
 static int pcnet32_open(struct net_device *);
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
+static int pcnet32_poll(struct net_device *dev, int *budget);
 static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
 static int pcnet32_close(struct net_device *);
@@ -425,6 +424,215 @@ static struct pcnet32_access pcnet32_dwi
.reset = pcnet32_dwio_reset
 };
 
+static void pcnet32_netif_stop(struct net_device *dev)
+{
+   dev-trans_start = jiffies;
+   netif_poll_disable(dev);
+   netif_tx_disable(dev);
+}
+
+static void pcnet32_netif_start(struct net_device *dev)
+{
+   netif_wake_queue(dev);
+   netif_poll_enable(dev);
+}
+
+/*
+ * Allocate space for the new sized tx ring.
+ * Free old resources
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp-lock held.
+ */
+static void pcnet32_realloc_tx_ring(struct net_device *dev,
+   struct pcnet32_private *lp,
+   unsigned int size)
+{
+   dma_addr_t new_ring_dma_addr;
+   dma_addr_t *new_dma_addr_list;
+   struct pcnet32_tx_head *new_tx_ring;
+   struct sk_buff **new_skb_list;
+
+   pcnet32_purge_tx_ring(dev);
+
+   new_tx_ring = pci_alloc_consistent(lp-pci_dev,
+  sizeof(struct pcnet32_tx_head) *
+  (1  size),
+  new_ring_dma_addr);
+   if (new_tx_ring == NULL) {
+   if (pcnet32_debug  NETIF_MSG_DRV)
+   printk(\n KERN_ERR PFX
+  %s: Consistent memory allocation failed.\n,
+  dev-name);
+   return;
+   }
+   memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1  size));
+
+   new_dma_addr_list = kcalloc(sizeof(dma_addr_t), (1  size), 
GFP_ATOMIC);
+   if (!new_dma_addr_list) {
+   if (pcnet32_debug  NETIF_MSG_DRV)
+   printk(\n KERN_ERR PFX
+  %s: Memory allocation failed.\n, dev-name);
+   goto free_new_tx_ring;
+   }
+
+   new_skb_list = kcalloc(sizeof(struct sk_buff *), (1  size), 
GFP_ATOMIC);
+   if (!new_skb_list) {
+   if (pcnet32_debug  NETIF_MSG_DRV)
+   printk(\n KERN_ERR PFX
+  %s: Memory allocation failed.\n, dev-name);
+   goto free_new_lists;
+   }
+
+   kfree(lp-tx_skbuff);
+   kfree(lp-tx_dma_addr);
+   pci_free_consistent(lp-pci_dev,
+   sizeof(struct pcnet32_tx_head) *
+   lp-tx_ring_size, lp-tx_ring,
+   lp-tx_ring_dma_addr);
+
+   

Re: [PATCH] pcnet32 driver NAPI support

2006-06-07 Thread Don Fry
On Wed, Jun 07, 2006 at 03:34:56PM -0400, Lennart Sorensen wrote:
 On Wed, Jun 07, 2006 at 11:20:40AM -0700, Don Fry wrote:
 
  Some areas of concern that you may have addressed already, I have not
  scanned your changes yet, are what happens if the ring size is changed
  without bringing down the interface (via ethtool), or if the loopback
  test is run in a similar fashion, or a tx timeout occurs.
 
 The same thing as if it was done before enabling napi.  From a few
 messages I have seen, it doesn't work right now, and it won't work any
 better with my changes.  I have never tried changing the ring size on
 the fly, so I don't know.

Today without your NAPI changes the device can be up and operational,
and change the ring size without hanging or causing a panic or causing
problems with the driver.  The same can be said for running the loopback
test, or when a tx timeout occurs.

It does not look like the same can be said for your NAPI changes, yet.
Try changing the ring size a dozen times during a receive storm and see
what happens.

 
 It appears that the port is stopped before the ring size change is done,
 although I can't really tell how it handles things if the queue is not
 empty when it stops the port.  Does it try to handle anything left in
 the ring first or does it just toss those packets? (That I would
 consider wrong).
 
  The lp-lock MUST be held whenever accessing the csr or bcr registers as
  this is a multi-step process, and has been the source of problems in the
  past.  Even on UP systems.
 
 Hmm, I just followed what appeared to be in pcnet32_rx and how tulip and
 a few other drivers had done their napi conversions.  It certainly works
 for me the way I did it.  Haven't seen any lockups yet.  I do see that I
 am not holding the lock when I acknowledge IRQs in pcnet32_poll, which
 pcnet32_rx doesn't need to worry about since it is called from the
 interrupt handler which already holds the lock.  That should be fixed
 then.

Yes, that is the minimum that needs to be changed.
There have been a lot of changes made to the driver, by myself included,
that seem to work just fine, but later the timing changes and you lose
the race, resulting in problems.  Changing one part of the driver
without understanding the whole thing is very risky.

 
 So I can do:
 // Clear RX interrupts
 spin_lock(lp-lock);
 lp-a.write_csr (ioaddr, 0, 0x1400);
 spin_unlock(lp-lock);
 That part seems simple enough to protect.
 
 Is this safe without holding the lock?
 } while(lp-a.read_csr (ioaddr, 0)  0x1400);

No, see below.

 Not sure how to wrap a lock around that one without holding the lock for
 way too long.
 
 perhaps:
 spin_lock(lp-lock);
   state=lp-a.read_csr (ioaddr, 0)  0x1400;
 spin_unlock(lp-lock);
 } while(state);
 Does that seem more reasonable?

The lock must be held during ANY read or write to a csr or bcr.

The problem is that accessing a csr/bcr takes two steps.  One is to
write the address register indicating which register to read or write,
and second, read or write the register.  The problem is that without the
lock, entity A writes to the rap to access register X, then before it
can access that register entity B writes the rap to access register Y,
At that point entity A will read, or worse write, the contents of the
wrong register.

This problem is even worse when reading/writing a PHY register because
it entails writing bcr 33 and reading/writing bcr 34, without being
interrupted by something that might change bcr 33.  Not likely, but not
something that can be ignored.  It may not happen often, but it will
happen eventually.

 
 Len Sorensen

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] pcnet32 driver NAPI support

2006-06-07 Thread Don Fry
One other problem I ran into.  I applied the patch but it will not
compile because rl_active is never defined.  I have worked around it but
...


-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2.6.17-rc5] pcnet32: remove incorrect pcnet32_free_ring

2006-05-25 Thread Don Fry
During a code scan for another change I discovered that this call to
pcnet32_free_ring must be removed.  If the open fails due to a lack of
memory all the ring structures are removed via the call to free_ring
and a subsequent call to open will dereference a null pointer in
pcnet32_init_ring.

Please apply to 2.6.17.

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.17-rc5/drivers/net/orig.pcnet32.c 2006-05-25 15:59:12.0 
-0700
+++ linux-2.6.17-rc5/drivers/net/pcnet32.c  2006-05-25 16:09:40.0 
-0700
@@ -1774,8 +1774,6 @@ static int pcnet32_open(struct net_devic
lp-rx_dma_addr[i] = 0;
}
 
-   pcnet32_free_ring(dev);
-
/*
 * Switch back to 16bit mode to avoid problems with dumb
 * DOS packet driver after a warm reboot

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] pcnet32.c: modify RX ring size through module parameter

2006-05-15 Thread Don Fry
I have several problems with this patch.  First, it assumes you only have
one device or you want all devices to operate with the same receive ring
size.  (use module_param_array like full_duplex or options).

Second, the mininum number of descriptors should be 4 not 2, or the
loopback test will look past the end of the receive ring looking for
status to change, and then try and pick up an skb pointer past the end of
the array and try to dereference it.

Either fix the loopback test to work with the minimum number of tx and rx
descriptors instead of the hard coded 4, or make the minimum rx ring
size be 4.  numbuffs = min(4 , min(lp-tx_ring_size, lp-rx_ring_size));

Another nit is the description says it is the RX Ring Buffer Size which
might be misunderstood as the size of the receive buffer, not the size of
the receive descriptor ring.  (RX Ring Size would be better).

Lastly, the patch also will not apply against pcnet32.c in mainline
2.6.17-rc4 due to whitespace changes.

On Mon, May 15, 2006 at 11:32:14AM +0800, Wen Hsin Chang wrote:
 This patch is created from pcnet32.c v1.32. it will allow users to 
 specify RX ring size upon module
 insertion via module parameter 'rx_log_size'. This is needed in some 
 cases where too small the rx ring
 size will cause RX errors upon remote installation via pcnet32 NIC card.
 
 Signed-off-by: Wen Hsin Chang [EMAIL PROTECTED]

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2.6.16-git1] pcnet32: support boards with multiple phys

2006-03-20 Thread Don Fry
Boards with multiple PHYs were not being handled properly by the pcnet32
driver.  This patch by Thomas Bogendoerfer with changes by me will allow
Allied Telesyn 2700FTX and 2701FTX boards to use either the copper or
the fiber interfaces.  It has been tested on ia32 and ppc64 hardware.
Philippe Seewer also tested and improved the patch.
ethtool for pcnet32 already supports multiple phys.

See also bugzilla bug 4219.

Please apply to 2.6.16

Signed-off-by:  Don Fry [EMAIL PROTECTED]

--- linux-2.6.16-git1/drivers/net/pcnet32.c.origMon Mar 20 13:53:17 2006
+++ linux-2.6.16-git1/drivers/net/pcnet32.c Mon Mar 20 14:26:15 2006
@@ -22,8 +22,8 @@
  */
 
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.31c
-#define DRV_RELDATE01.Nov.2005
+#define DRV_VERSION1.32
+#define DRV_RELDATE18.Mar.2006
 #define PFXDRV_NAME : 
 
 static const char * const version =
@@ -133,7 +133,7 @@ static const char pcnet32_gstrings_test[
 };
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
-#define PCNET32_NUM_REGS 168
+#define PCNET32_NUM_REGS 136
 
 #define MAX_UNITS 8/* More are supported, limit only on options */
 static int options[MAX_UNITS];
@@ -265,6 +265,9 @@ static int homepna[MAX_UNITS];
  * v1.31c  01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only.
  *Force 100Mbit FD if Auto (ASEL) is selected.
  *See Bugzilla 2669 and 4551.
+ * v1.32   18 Mar2006 Thomas Bogendoerfer and Don Fry added Multi-Phy
+ *handling for supporting AT-270x FTX cards with FX and Tx PHYs.
+ *Philippe Seewer assisted with auto negotiation and testing.
  */
 
 
@@ -375,6 +378,7 @@ struct pcnet32_private {
 unsigned int   dirty_rx, dirty_tx; /* The ring entries to be free()ed. 
*/
 struct net_device_stats stats;
 char   tx_full;
+char   phycount;   /* number of phys found */
 intoptions;
 unsigned int   shared_irq:1,   /* shared irq possible */
dxsuflo:1,  /* disable transmit stop on uflo */
@@ -384,6 +388,9 @@ struct pcnet32_private {
 struct timer_list  watchdog_timer;
 struct timer_list  blink_timer;
 u32msg_enable; /* debug message level */
+
+/* each bit indicates an available PHY */
+u32phymask;
 };
 
 static void pcnet32_probe_vlbus(void);
@@ -415,6 +422,7 @@ static void pcnet32_get_regs(struct net_
 static void pcnet32_purge_tx_ring(struct net_device *dev);
 static int pcnet32_alloc_ring(struct net_device *dev, char *name);
 static void pcnet32_free_ring(struct net_device *dev);
+static void pcnet32_check_media(struct net_device *dev, int verbose);
 
 
 enum pci_flags_bit {
@@ -936,9 +944,14 @@ static int pcnet32_phys_id(struct net_de
 return 0;
 }
 
+#define PCNET32_REGS_PER_PHY   32
+#define PCNET32_MAX_PHYS   32
 static int pcnet32_get_regs_len(struct net_device *dev)
 {
-return(PCNET32_NUM_REGS * sizeof(u16));
+struct pcnet32_private *lp = dev-priv;
+int j = lp-phycount * PCNET32_REGS_PER_PHY;
+
+return((PCNET32_NUM_REGS + j) * sizeof(u16));
 }
 
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
@@ -998,9 +1011,14 @@ static void pcnet32_get_regs(struct net_
 
 /* read mii phy registers */
 if (lp-mii) {
-   for (i=0; i32; i++) {
-   lp-a.write_bcr(ioaddr, 33, ((lp-mii_if.phy_id)  5) | i);
-   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   int j;
+   for (j=0; jPCNET32_MAX_PHYS; j++) {
+   if (lp-phymask  (1  j)) {
+   for (i=0; iPCNET32_REGS_PER_PHY; i++) {
+   lp-a.write_bcr(ioaddr, 33, (j  5) | i);
+   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   }
+   }
}
 }
 
@@ -1009,10 +1027,6 @@ static void pcnet32_get_regs(struct net_
a-write_csr(ioaddr, 5, 0x);
 }
 
-i = buff - (u16 *)ptr;
-for (; i  PCNET32_NUM_REGS; i++)
-   *buff++ = 0;
-
 spin_unlock_irqrestore(lp-lock, flags);
 }
 
@@ -1185,7 +1199,7 @@ pcnet32_probe1(unsigned long ioaddr, int
if (cards_found  MAX_UNITS  homepna[cards_found])
media |= 1; /* switch to home wiring mode */
if (pcnet32_debug  NETIF_MSG_PROBE)
-   printk(KERN_DEBUG PFX media set to %sMbit mode.\n, 
+   printk(KERN_DEBUG PFX media set to %sMbit mode.\n,
(media  1) ? 1 : 10);
a-write_bcr(ioaddr, 49, media);
break;
@@ -1401,8 +1415,34 @@ pcnet32_probe1(unsigned long ioaddr, int
 }
 
 /* Set the mii phy_id so that we can query the link state */
-if (lp-mii)
+if (lp-mii) {
+   /* lp-phycount and lp-phymask are set to 0 by memset above */
+
lp-mii_if.phy_id = ((lp-a.read_bcr (ioaddr, 33))  5)  0x1f;
+   /* scan for PHYs */
+   for (i=0

Re: [PATCH 1/2] pcnet32: Introduce basic AT 2700/01 FTX support

2006-03-17 Thread Don Fry
On Fri, Mar 17, 2006 at 05:13:24PM +0100, Seewer Philippe wrote:
 
 OK. applied it to 2.6.16-rc6. applies and works flawless. The new 
 check_media function is subjectively slower than the older code without 
 it but thats all I found.
 
 Tested with AT 2700FTX and 2701FTX. Both work and can be reconfigured 
 with ethtool. Supplying default options like 100full work as well.
 
 I fiddled with the code a bit and got AUTONEG running. With this 
 extension our AT FTX cards will work fine. All cards will be configured 
 by default to use fibre at 100full and the module will use autoneg. 

Is this selection of 100Full done with the AT diag routine?

 Since the fibre phy ignores settings for autoneg, 100full is not 
 overridden and works. But copper the phy will do autoneg. Tested and 
 works (un-/plugging and switching too of course).

If I understand correctly, your suggestion is to always have Autoneg
selected (options = 0) but the hardware is set by default to use 100Full
Fiber.

Is that a correct understanding?

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] pcnet32: Introduce basic AT 2700/01 FTX support

2006-03-08 Thread Don Fry
On Mon, Feb 27, 2006 at 11:45:51AM +0100, Seewer Philippe wrote:
 OK, found it.
 
 The code in pcnet32_open assigns XCVR_INTERNAL to ecmd.port instead of 
 ecmd.transceiver, making mii_ethtool_sset fail and leaving all phys 
 configured to defaults.
 
 On the Allied Telesyn FTX cards this means to use autoneg on tp when 
 default is fiber and 10/half on fiber when tp is default. Thats why the 
 fiber port didn't work, because it only supports 100Mbit. Overriding the 
 speed/duplex with ethtool makes it work though.
 
 Assigning XCRV_INTERNAL to the correct attribute introduces a new 
 problem: Since all options are ignored the code forces all phys to 
 10/half, so ethtool is needed again to reconfigure the settings.
 
 Changing the option override in probe1 to |= works and configures all 
 phy's with the correct options (except for autoneg of course, which is 
 still specifically ignored).
 
 I don't know whether it was the intention of the patch to force usage of 
 ethtool or not... Any suggestions?
 
 Regards
 Philippe Seewer

I get the same results in my testing.  Good catch on the coding error
for ecmd.transciever.  Without adding some more specific code to support
the Allied Telesyn cards I don`t know how to get things to work without
using ethtool.

Maybe someone else has a better idea.

Here is my current patch for you to review.  I would like to submit it
for 2.6.17.

--- linux-2.6.16-rc5/drivers/net/pcnet32.c.orig Mon Jan  2 19:21:10 2006
+++ linux-2.6.16-rc5/drivers/net/pcnet32.c  Wed Mar  8 15:38:01 2006
@@ -22,8 +22,8 @@
  */
 
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.31c
-#define DRV_RELDATE01.Nov.2005
+#define DRV_VERSION1.32
+#define DRV_RELDATE08.Mar.2006
 #define PFXDRV_NAME : 
 
 static const char *version =
@@ -133,7 +133,7 @@ static const char pcnet32_gstrings_test[
 };
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
-#define PCNET32_NUM_REGS 168
+#define PCNET32_NUM_REGS 136
 
 #define MAX_UNITS 8/* More are supported, limit only on options */
 static int options[MAX_UNITS];
@@ -265,6 +265,8 @@ static int homepna[MAX_UNITS];
  * v1.31c  01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only.
  *Force 100Mbit FD if Auto (ASEL) is selected.
  *See Bugzilla 2669 and 4551.
+ * v1.32   08 Mar20065 Thomas Bogendoerfer and Don Fry added Multi-Phy
+ *handling for supporting AT-270x FTX cards with FX and Tx PHYs
  */
 
 
@@ -375,6 +377,7 @@ struct pcnet32_private {
 unsigned int   dirty_rx, dirty_tx; /* The ring entries to be free()ed. 
*/
 struct net_device_stats stats;
 char   tx_full;
+char   phycount;   /* number of phys found */
 intoptions;
 unsigned int   shared_irq:1,   /* shared irq possible */
dxsuflo:1,  /* disable transmit stop on uflo */
@@ -384,6 +387,9 @@ struct pcnet32_private {
 struct timer_list  watchdog_timer;
 struct timer_list  blink_timer;
 u32msg_enable; /* debug message level */
+
+/* each bit indicates an available PHY */
+u32phymask;
 };
 
 static void pcnet32_probe_vlbus(void);
@@ -415,6 +421,7 @@ static void pcnet32_get_regs(struct net_
 static void pcnet32_purge_tx_ring(struct net_device *dev);
 static int pcnet32_alloc_ring(struct net_device *dev, char *name);
 static void pcnet32_free_ring(struct net_device *dev);
+static void pcnet32_check_media(struct net_device *dev, int verbose);
 
 
 enum pci_flags_bit {
@@ -936,9 +943,14 @@ static int pcnet32_phys_id(struct net_de
 return 0;
 }
 
+#define PCNET32_REGS_PER_PHY   32
+#define PCNET32_MAX_PHYS   32
 static int pcnet32_get_regs_len(struct net_device *dev)
 {
-return(PCNET32_NUM_REGS * sizeof(u16));
+struct pcnet32_private *lp = dev-priv;
+int j = lp-phycount * PCNET32_REGS_PER_PHY;
+
+return((PCNET32_NUM_REGS + j) * sizeof(u16));
 }
 
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
@@ -998,9 +1010,14 @@ static void pcnet32_get_regs(struct net_
 
 /* read mii phy registers */
 if (lp-mii) {
-   for (i=0; i32; i++) {
-   lp-a.write_bcr(ioaddr, 33, ((lp-mii_if.phy_id)  5) | i);
-   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   int j;
+   for (j=0; jPCNET32_MAX_PHYS; j++) {
+   if (lp-phymask  (1  j)) {
+   for (i=0; iPCNET32_REGS_PER_PHY; i++) {
+   lp-a.write_bcr(ioaddr, 33, (j  5) | i);
+   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   }
+   }
}
 }
 
@@ -1009,10 +1026,6 @@ static void pcnet32_get_regs(struct net_
a-write_csr(ioaddr, 5, 0x);
 }
 
-i = buff - (u16 *)ptr;
-for (; i  PCNET32_NUM_REGS; i++)
-   *buff++ = 0;
-
 spin_unlock_irqrestore(lp-lock

Re: [PATCH 1/2] pcnet32: Introduce basic AT 2700/01 FTX support

2006-02-20 Thread Don Fry
On Mon, Feb 20, 2006 at 04:30:22PM +0100, Seewer Philippe wrote:
 
 Basic result: Works perfectly (exceptions see below) out of the box
 
 Problem 1: During probe1, lp-options is silently overwritten with 
 PCNET32_PORT_MII. Even setting the statement to lp-options |= doesn't 
 help mutch, the eeprom defaults of the card are used always.
 

The options are ignored for multi-phy cards.  The option might be valid
for the fiber port, but not what you want for the copper port, for
example.  If you have a better suggestion I would be very interrested.

 Problem 2: Switching only works if the cards eeprom is programmed to use 
 the fiber port as default. Otherwise the fiber port is seen (output says 
 yes, i've got two phys) but not used.

I am very ignorant of the eeprom settings, so I probably  missed many
things in my testing.  When I was playing around with the interfaces, I
would bring up the interface, unplug one cable and plug in the other.

I also used ethtool to force full and half duplex and speed, to see how
the interface would behave.

What do you use to display/change the eeprom settings of a card?
If the fiber card was just seen but not used, what did the registers of
the card contain?
ethtool has been enhanced to support the pcnet32 better (at least for
me).

 
 Regards,
 Philippe Seewer
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] pcnet32: Introduce basic AT 2700/01 FTX support

2006-02-17 Thread Don Fry
Philippe,

On a purely mechanical note, the patches do not apply cleanly because
of whitespace changes.  Possibly your mailer changed tabs to spaces,
which causes the patch not to apply, and also causes your patch to have
different spacing than the rest of the file.  The driver does not
conform to the 8-space indentation guideline/rule, but it is consistent
in 4-space indentation.

I am looking over this change and the following one, to try and
understand what and why you made your changes.

The change made by Thomas Bogendoerfer and modified by myself is much
more flexible than your changes, in that they are not specific just to
the Allied Telesyn boards with multiple Phys.  They also allow dynamic
changing of cabling without requiring the driver to be removed/installed
or the card power cycled.  I also see little value in the module
parameters, when it can be determined dynamically. Also, maxphy might be
thought to the the maximum number of phys, rather than the maximum phy
number supported.  If static selection of the phy to use is passed in as
a module parameter, why also include a maxphy?

As I review your patches I will follow up to the mailing list.

On Fri, Feb 17, 2006 at 05:14:39PM +0100, Seewer Philippe wrote:
 
 This patch extends Don Fry's last patch for AT 2700/01 FX to set the
 speed/fdx options for the FTX variants of these cards as well.
 
 Additionally the option override has been moved from pcnet32_open to
 pcnet32_probe1 because it's only necessary to override the options once.
 
 Tested and works.
 
 Patch applies to 2.6.16-rc3
 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] pcnet32: Introduce basic AT 2700/01 FTX support

2006-02-17 Thread Don Fry
I am removing linux-kernel from the mailing list, as this thread is more
appropriate to netdev, and there is a lot more traffic on linux-kernel.

On Fri, Feb 17, 2006 at 09:12:52PM +0100, Seewer Philippe wrote:
 
 Don Fry wrote:
  Philippe,
  
  On a purely mechanical note, the patches do not apply cleanly because
  of whitespace changes.  Possibly your mailer changed tabs to spaces,
  which causes the patch not to apply, and also causes your patch to have
  different spacing than the rest of the file.  The driver does not
  conform to the 8-space indentation guideline/rule, but it is consistent
  in 4-space indentation.
 uhhh did i forget to run Lindent..? Or was it that i just
 selected-middle clicked them into thunderbird?
 what's the recommended procedure oh how to append patches to
 mails? (Documentation just says included not attached...)

I use mutt and just ':r filename' to include the patch file(s).  When I
forget and middle click the changes I get a gentle reminder that I have
messed up again ;-)

  
  I am looking over this change and the following one, to try and
  understand what and why you made your changes.
  
  The change made by Thomas Bogendoerfer and modified by myself is much
  more flexible than your changes, in that they are not specific just to
  the Allied Telesyn boards with multiple Phys.
 I'm not sure what you are talking about. I didn't see any PHY switching
 code in the driver... And the specs specifically say that when more than

I sent out a patch for testing on November 8 to netdev which is
available on the archives, with a patch to support boards with multiple
phys.  I have received few comments on the code.  Maybe you could test
that code and see if it does what you need.  I was waiting until 2.6.16
is final before resubmitting the enhancements to go into 2.6.17.

search for [RFT] pcnet32: support for boards with multiple phys

 one PHY is connected control should revert to software.
 
  They also allow dynamic
  changing of cabling without requiring the driver to be removed/installed
  or the card power cycled.  I also see little value in the module
  parameters, when it can be determined dynamically. Also, maxphy might be
  thought to the the maximum number of phys, rather than the maximum phy
  number supported.  If static selection of the phy to use is passed in as
  a module parameter, why also include a maxphy?
 maxphy is supposed to be how many PHYs are actually connected to the chip.
 I didn't want to introduce a generic PHY scanner (which is possible)
 because that would have haa impact on all cards not only cards that actually
 have more than one phy.

If maxphy is just the number of phys, and the vendor used phy 3 and 7,
instead of 1 and 2, your code would not work, asis.

 
 I really tried to put this into pcnet32_open. But i just didn't work...
 
  
  As I review your patches I will follow up to the mailing list.
  
  On Fri, Feb 17, 2006 at 05:14:39PM +0100, Seewer Philippe wrote:
  
 This patch extends Don Fry's last patch for AT 2700/01 FX to set the
 speed/fdx options for the FTX variants of these cards as well.
 
 Additionally the option override has been moved from pcnet32_open to
 pcnet32_probe1 because it's only necessary to override the options once.
 
 Tested and works.
 
 Patch applies to 2.6.16-rc3
 
  
  Don Fry
  [EMAIL PROTECTED]
 

-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] is_valid_ether_addr() returns true for FF:FF:FF:FF:FF:FF

2005-12-13 Thread Don Fry
I'm (easily) confused.

Unless the specs have changed recently, the broadcast address of all 1's
is just a special type of multicast adddress, that all stations shall be
able to recognize.

In looking at the code in etherdevice.h it looks like the test of
is_multicast_ether_addr() is broken, because it will return false for
the value ff:00:00:00:00:00 (for example), which is a valid multicast
address.  Or at least it used to be.

If the definition of a multicast address has changed, then maybe the
code is correct, but it should be documented better.

On Tue, Dec 13, 2005 at 09:45:55AM -0800, Stephen Hemminger wrote:
 On Mon, 12 Dec 2005 18:56:49 -0600
 Michael Ellerman [EMAIL PROTECTED] wrote:
 
  Since a5fe736eaf9bae1b45317313de04b564441b94f2 (2.6.13-rc1 ish),
  is_valid_ether_addr() has been broken, because its assumption that
  FF:FF:FF:FF:FF:FF is a multicast address is wrong. Ouch.
  
  Signed-off-by: Michael Ellerman [EMAIL PROTECTED]
  ---
  
   include/linux/etherdevice.h |6 +++---
   1 files changed, 3 insertions(+), 3 deletions(-)
  
  Index: linux/include/linux/etherdevice.h
  ===
  --- linux.orig/include/linux/etherdevice.h
  +++ linux/include/linux/etherdevice.h
  @@ -91,9 +91,9 @@ static inline int is_broadcast_ether_add
*/
   static inline int is_valid_ether_addr(const u8 *addr)
   {
  -   /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
  -* explicitly check for it here. */
  -   return !is_multicast_ether_addr(addr)  !is_zero_ether_addr(addr);
  +   return  !is_broadcast_ether_addr(addr) 
  +   !is_multicast_ether_addr(addr) 
  +   !is_zero_ether_addr(addr);
   }
   
 
 why not
   return !(addr[0]  1)  !is_zero_ether_addr(addr);
 
 -- 
 Stephen Hemminger [EMAIL PROTECTED]
 OSDL http://developer.osdl.org/~shemminger
 -
-- 
Don Fry
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFT] pcnet32: support for boards with multiple phys

2005-11-08 Thread Don Fry
This patch contains code from Thomas Bogendoerfer which I have modified
somewhat.  It works fine for me in my testing, but I would like
additional exposure to this code before submitting to mainline.
It should fix bugzilla bug #4219 as well.

The patch is based on 2.6.14-git11. The ethtool version at
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/ethtool.git
supports the multiple phys (ethtool -d ethX).  The ethtool version 3
will also work, just not as 'pretty'.

Please let me know if it works or not for you. 
Especially if it breaks something.

Thanks.

--- linux-2.6.14-git11/drivers/net/pcnet32.c.orig   Tue Nov  8 09:31:20 2005
+++ linux-2.6.14-git11/drivers/net/pcnet32.cTue Nov  8 09:56:30 2005
@@ -22,8 +22,8 @@
  */
 
 #define DRV_NAME   pcnet32
-#define DRV_VERSION1.31c
-#define DRV_RELDATE01.Nov.2005
+#define DRV_VERSION1.32
+#define DRV_RELDATE02.Nov.2005
 #define PFXDRV_NAME : 
 
 static const char *version =
@@ -133,7 +133,7 @@ static const char pcnet32_gstrings_test[
 };
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
-#define PCNET32_NUM_REGS 168
+#define PCNET32_NUM_REGS 136
 
 #define MAX_UNITS 8/* More are supported, limit only on options */
 static int options[MAX_UNITS];
@@ -265,6 +265,8 @@ static int homepna[MAX_UNITS];
  * v1.31c  01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only.
  *Force 100Mbit FD if Auto (ASEL) is selected.
  *See Bugzilla 2669 and 4551.
+ * v1.32   02 Nov 2005 Thomas Bogendoerfer and Don Fry added Multi-Phy
+ *handling for supporting AT-270x FTX cards with FX and Tx PHYs
  */
 
 
@@ -384,6 +386,9 @@ struct pcnet32_private {
 struct timer_list  watchdog_timer;
 struct timer_list  blink_timer;
 u32msg_enable; /* debug message level */
+
+/* each bit indicates an available PHY, only valid with more than 1 PHY */
+u32multiphymask;
 };
 
 static void pcnet32_probe_vlbus(void);
@@ -936,9 +941,23 @@ static int pcnet32_phys_id(struct net_de
 return 0;
 }
 
+#define PCNET32_REGS_PER_PHY   32
+#define PCNET32_MAX_PHYS   32
 static int pcnet32_get_regs_len(struct net_device *dev)
 {
-return(PCNET32_NUM_REGS * sizeof(u16));
+struct pcnet32_private *lp = dev-priv;
+int j = 0;
+
+if (lp-multiphymask) {
+   int i;
+
+   for (i=0; iPCNET32_MAX_PHYS; i++)
+   if (lp-multiphymask  (1  i))
+   j += PCNET32_REGS_PER_PHY;
+} else if (lp-mii) {
+   j = PCNET32_REGS_PER_PHY;
+}
+return((PCNET32_NUM_REGS + j) * sizeof(u16));
 }
 
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
@@ -998,9 +1017,21 @@ static void pcnet32_get_regs(struct net_
 
 /* read mii phy registers */
 if (lp-mii) {
-   for (i=0; i32; i++) {
-   lp-a.write_bcr(ioaddr, 33, ((lp-mii_if.phy_id)  5) | i);
-   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   if (lp-multiphymask) {
+   int j;
+   for (j=0; jPCNET32_MAX_PHYS; j++) {
+   if (lp-multiphymask  (1  j)) {
+   for (i=0; iPCNET32_REGS_PER_PHY; i++) {
+   lp-a.write_bcr(ioaddr, 33, (j  5) | i);
+   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   }
+   }
+   }
+   } else {
+   for (i=0; iPCNET32_REGS_PER_PHY; i++) {
+   lp-a.write_bcr(ioaddr, 33, ((lp-mii_if.phy_id)  5) | i);
+   *buff++ = lp-a.read_bcr(ioaddr, 34);
+   }
}
 }
 
@@ -1009,10 +1040,6 @@ static void pcnet32_get_regs(struct net_
a-write_csr(ioaddr, 5, 0x);
 }
 
-i = buff - (u16 *)ptr;
-for (; i  PCNET32_NUM_REGS; i++)
-   *buff++ = 0;
-
 spin_unlock_irqrestore(lp-lock, flags);
 }
 
@@ -1185,7 +1212,7 @@ pcnet32_probe1(unsigned long ioaddr, int
if (cards_found  MAX_UNITS  homepna[cards_found])
media |= 1; /* switch to home wiring mode */
if (pcnet32_debug  NETIF_MSG_PROBE)
-   printk(KERN_DEBUG PFX media set to %sMbit mode.\n, 
+   printk(KERN_DEBUG PFX media set to %sMbit mode.\n,
(media  1) ? 1 : 10);
a-write_bcr(ioaddr, 49, media);
break;
@@ -1406,8 +1433,38 @@ pcnet32_probe1(unsigned long ioaddr, int
 }
 
 /* Set the mii phy_id so that we can query the link state */
-if (lp-mii)
+if (lp-mii) {
+   int cnt = 0;
+   u32 phymask = 0;
+
lp-mii_if.phy_id = ((lp-a.read_bcr (ioaddr, 33))  5)  0x1f;
+   /* scan for PHYs */
+   for (i=0; iPCNET32_MAX_PHYS; i++) {
+   unsigned short id1, id2;
+
+   id1 = mdio_read(dev, i, MII_PHYSID1);
+   if (id1 == 0x)
+   continue;
+   id2 = mdio_read(dev, i, MII_PHYSID2);
+   if (id2 == 0x