Dear Jeff: Here is full patch for the JMicron Gigabit Ethernet driver. Supporting JMC250, and JMC260. The patch is also available at: http://cooldavid.org/download/jme.netdev-2.6.20080916.patch Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org> --- diff -uprN -X ./dontdiff netdev-2.6/drivers/net/jme.c linux/drivers/net/jme.c --- netdev-2.6/drivers/net/jme.c 1970-01-01 08:00:00.000000000 +0800 +++ linux/drivers/net/jme.c 2008-09-16 00:54:46.000000000 +0800 @@ -0,0 +1,3019 @@ +/* + * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver + * + * Copyright 2008 JMicron Technology Corporation + * http://www.jmicron.com/ + * + * Author: Guo-Fu Tseng <cooldavid@cooldavid.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/crc32.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <linux/tcp.h> +#include <linux/udp.h> +#include <linux/if_vlan.h> +#include "jme.h" + +static int force_pseudohp = -1; +static int no_pseudohp = -1; +static int no_extplug = -1; +module_param(force_pseudohp, int, ...
Dear Guo-Fu: It works fine, thanks! Acked-and-tested-by: Ethan Hsiao <ethanhsiao@jmicron.com> Regards, > + val = jr
Dear Jeff, David:
This patch:
1. Set bit 5 of GPREG1 to 1 to enable hardware workaround for half-duplex
mode. Which the MAC processor generates CRS/COL by itself instead of
receive it from PHY processor.
2. Set bit 6 of GPREG1 to 1 to enable hardware workaround that masks the
MAC processor working right while calculating IPv6 RSS in 10/100
mode.
3. Group the workaround codes all together.
The patch is also available at:
http://cooldavid.org/download/jme.net-next-2.6.20081009.1.patch
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index f292df5..635f616 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -190,7 +190,7 @@ jme_reset_mac_processor(struct jme_adapter *jme)
else
gpreg0 = GPREG0_DEFAULT;
jwrite32(jme, JME_GPREG0, gpreg0);
- jwrite32(jme, JME_GPREG1, 0);
+ jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
}
static inline void
@@ -365,7 +365,7 @@ static int
jme_check_link(struct net_device *netdev, int testonly)
{
struct jme_adapter *jme = netdev_priv(netdev);
- u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr;
+ u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1;
char linkmsg[64];
int rc = 0;
@@ -437,37 +437,22 @@ jme_check_link(struct net_device *netdev, int testonly)
case PHY_LINK_SPEED_10M:
ghc |= GHC_SPEED_10M;
strcat(linkmsg, "10 Mbps, ");
- if (is_buggy250(jme->pdev->device, jme->chiprev))
- jme_set_phyfifoa(jme);
break;
case PHY_LINK_SPEED_100M:
ghc |= GHC_SPEED_100M;
strcat(linkmsg, "100 Mbps, ");
- if (is_buggy250(jme->pdev->device, jme->chiprev))
- jme_set_phyfifob(jme);
break;
case PHY_LINK_SPEED_1000M:
ghc |= GHC_SPEED_1000M;
strcat(linkmsg, "1000 Mbps, ");
- if (is_buggy250(jme->pdev->device, jme->chiprev))
- jme_set_phyfifoa(jme);
break;
default:
break;
}
- ghc |= (phylink & PHY_LINK_DUPLEX) ? GHC_DPX : ...From: "Guo-Fu Tseng" <cooldavid@cooldavid.org> Applied. --
Dear Jeff, David:
This patch:
Fix IRQ handle bug when interrupt mode.
The driver was incorrectly handled and returned IRQ_HANDLED
while the device is not generating the interrupt.
It happened due to faulty determination of interrupt status register.
The patch is also available at:
http://cooldavid.org/download/jme.net-next-2.6.20081009.2.patch
Found by: "Ethan" <ethanhsiao@jmicron.com>
Fixed by: "akeemting" <akeem@jmicron.com>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 635f616..3ab2442 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -1463,7 +1463,7 @@ jme_intr(int irq, void *dev_id)
/*
* Check if it's really an interrupt for us
*/
- if (unlikely(intrstat == 0))
+ if (unlikely((intrstat & INTR_ENABLE) == 0))
return IRQ_NONE;
/*
--
From: "Guo-Fu Tseng" <cooldavid@cooldavid.org> Applied. --
Dear Jeff, David:
This patch:
Advances the driver version after modification.
The patch is also available at:
http://cooldavid.org/download/jme.net-next-2.6.20081009.3.patch
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index 9fdf20a..f863aee 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -25,7 +25,7 @@
#define __JME_H_INCLUDEE__
#define DRV_NAME "jme"
-#define DRV_VERSION "1.0.2"
+#define DRV_VERSION "1.0.3"
#define PFX DRV_NAME ": "
#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
--
From: "Guo-Fu Tseng" <cooldavid@cooldavid.org> Applied. --
Dear Jeff, David:
Due to the hardware design, except the first chip on the market,
other chips needs to setup the clock source for MAC processor
implicitly through Global Host Control Register(GHC).
(Strange design huh?)
10/100M uses the PCI-E as clock source, and 1G uses GPHY.
And I reordered the code a little, to make it easier to read.
Found-by: "Ethan" <ethanhsiao@jmicron.com>
Fixed-by: "akeemting" <akeem@jmicron.com>
Signed-off-by: "Guo-Fu Tseng" <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 665e70d..49090ba 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -435,15 +435,18 @@ jme_check_link(struct net_device *netdev, int testonly)
GHC_DPX);
switch (phylink & PHY_LINK_SPEED_MASK) {
case PHY_LINK_SPEED_10M:
- ghc |= GHC_SPEED_10M;
+ ghc |= GHC_SPEED_10M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "10 Mbps, ");
break;
case PHY_LINK_SPEED_100M:
- ghc |= GHC_SPEED_100M;
+ ghc |= GHC_SPEED_100M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "100 Mbps, ");
break;
case PHY_LINK_SPEED_1000M:
- ghc |= GHC_SPEED_1000M;
+ ghc |= GHC_SPEED_1000M |
+ GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
strcat(linkmsg, "1000 Mbps, ");
break;
default:
@@ -463,14 +466,6 @@ jme_check_link(struct net_device *netdev, int testonly)
TXTRHD_TXREN |
((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
}
- strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
- "Full-Duplex, " :
- "Half-Duplex, ");
-
- if (phylink & PHY_LINK_MDI_STAT)
- strcat(linkmsg, "MDI-X");
- else
- strcat(linkmsg, "MDI");
gpreg1 = GPREG1_DEFAULT;
if (is_buggy250(jme->pdev->device, jme->chiprev)) {
@@ -492,11 +487,17 @@ jme_check_link(struct net_device *netdev, int testonly)
break;
}
}
- jwrite32(jme, JME_GPREG1, gpreg1);
- jme->reg_ghc = ghc;
+ jwrite32(jme, JME_GPREG1, gpreg1);
jwrite32(jme, JME_GHC, ghc);
+ jme->reg_ghc = ghc;
...patches 1-2 Acked-by: Jeff Garzik <jgarzik@redhat.com> --
From: Jeff Garzik <jgarzik@pobox.com> Both patches applied to net-next-2.6, thanks everyone. --
Dear Jeff, David:
Although the hardware supports the 64bit DMA address in design,
but later found that it actually not working.
This patch reduced the rang to 32bit.
Found-by: "Ethan" <ethanhsiao@jmicron.com>
Signed-off-by: "Guo-Fu Tseng" <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 49090ba..660bb89 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2592,14 +2592,6 @@ static const struct ethtool_ops jme_ethtool_ops = {
static int
jme_pci_dma64(struct pci_dev *pdev)
{
- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
- return 1;
-
- if (!pci_set_dma_mask(pdev, DMA_40BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK))
- return 1;
-
if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
return 0;
--
This patch modifies messages to display correct hardware version.
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 08b3405..60cb997 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2856,7 +2856,11 @@ jme_init_one(struct pci_dev *pdev,
goto err_out_free_shadow;
}
- msg_probe(jme, "JMC250 gigabit%s ver:%x rev:%x macaddr:%pM\n",
+ msg_probe(jme, "%s%s ver:%x rev:%x macaddr:%pM\n",
+ (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ?
+ "JMC250 Gigabit Ethernet" :
+ (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ?
+ "JMC260 Fast Ethernet" : "Unknown",
(jme->fpgaver != 0) ? " (FPGA)" : "",
(jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
jme->rev, netdev->dev_addr);
@@ -3002,7 +3006,7 @@ static struct pci_driver jme_driver = {
static int __init
jme_init_module(void)
{
- printk(KERN_INFO PFX "JMicron JMC250 gigabit ethernet "
+ printk(KERN_INFO PFX "JMicron JMC2XX ethernet "
"driver version %s\n", DRV_VERSION);
return pci_register_driver(&jme_driver);
}
--
We should sync ring descriptor to pci device after modifying it.
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 60cb997..f65a09c 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -1833,7 +1833,7 @@ jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags)
}
static int
-jme_fill_first_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
+jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
{
struct jme_ring *txring = jme->txring;
struct txdesc *txdesc;
@@ -1863,6 +1863,7 @@ jme_fill_first_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags))
jme_tx_csum(jme, skb, &flags);
jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags);
+ jme_map_tx_skb(jme, skb, idx);
txdesc->desc1.flags = flags;
/*
* Set tx buffer info after telling NIC to send
@@ -1932,8 +1933,7 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- jme_map_tx_skb(jme, skb, idx);
- jme_fill_first_tx_desc(jme, skb, idx);
+ jme_fill_tx_desc(jme, skb, idx);
jwrite32(jme, JME_TXCS, jme->reg_txcs |
TXCS_SELECT_QUEUE0 |
--
Clear all modified GHC register flags.
Fixed-by: Ethan Hsiao <ethanhsiao@jmicron.com>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index f65a09c..47dd47f 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -429,10 +429,9 @@ jme_check_link(struct net_device *netdev, int testonly)
jme->phylink = phylink;
- ghc = jme->reg_ghc & ~(GHC_SPEED_10M |
- GHC_SPEED_100M |
- GHC_SPEED_1000M |
- GHC_DPX);
+ ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE |
+ GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY);
switch (phylink & PHY_LINK_SPEED_MASK) {
case PHY_LINK_SPEED_10M:
ghc |= GHC_SPEED_10M |
--
All JMC250 chips have no problem with higher bits support.
Adding it back.
Found-by: Ethan Hsiao <ethanhsiao@jmicron.com>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 47dd47f..4da81a3 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2589,6 +2589,16 @@ static const struct ethtool_ops jme_ethtool_ops = {
static int
jme_pci_dma64(struct pci_dev *pdev)
{
+ if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 &&
+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ return 1;
+
+ if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 &&
+ !pci_set_dma_mask(pdev, DMA_40BIT_MASK))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK))
+ return 1;
+
if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
return 0;
--
Advance version number after previous changes. Sorry for not come along with previous patch series. diff --git a/drivers/net/jme.h b/drivers/net/jme.h index e321c67..0996a06 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -25,7 +25,7 @@ #define __JME_H_INCLUDED__ #define DRV_NAME "jme" -#define DRV_VERSION "1.0.3" +#define DRV_VERSION "1.0.4" #define PFX DRV_NAME ": " #define PCI_DEVICE_ID_JMICRON_JMC250 0x0250 --
From: "Guo-Fu Tseng" <cooldavid@cooldavid.org> Applied, but missing a signoff, please don't forget it next time. --
Going through this driver for net_device_ops makes me wonder why some other things wer not caught during the review process. 1. Obfuscation by macro which looks like some "vendor support older kernels" stuff. See the wrapping of NAPI and NET_STAT 2. 5 tasklets for thing that could be done by NAPI and one tasklet 3. 4 atomic variables for things that should be already covered by locks 4. 3 locks, seems like more than needed. 5. PCI setup of max read request size should be done via pci_set_readrq not by direct manipulation of PCI registers. 6. Not using pci dma allocation which is more standard convention 7. NAPI weight is very large 256 (vs normal 64) --
From: Stephen Hemminger <shemminger@vyatta.com> Using the generic DMA interfaces is actually preferred. There is no effective difference other than using a more generic interface. --
On Thu, 20 Nov 2008 21:36:27 -0800 (PST) Ok, but this??? #define NET_STAT(priv) (priv->dev->stats) #define NETDEV_GET_STATS(netdev, fun_ptr) #define DECLARE_NET_DEVICE_STATS #define DECLARE_NAPI_STRUCT struct napi_struct napi; #define NETIF_NAPI_SET(dev, napis, pollfn, q) \ netif_napi_add(dev, napis, pollfn, q); #define JME_NAPI_HOLDER(holder) struct napi_struct *holder #define JME_NAPI_WEIGHT(w) int w #define JME_NAPI_WEIGHT_VAL(w) w #define JME_NAPI_WEIGHT_SET(w, r) #define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev, napis) #define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi); #define JME_NAPI_DISABLE(priv) \ if (!napi_disable_pending(&priv->napi)) \ napi_disable(&priv->napi); #define JME_RX_SCHEDULE_PREP(priv) \ netif_rx_schedule_prep(priv->dev, &priv->napi) #define JME_RX_SCHEDULE(priv) \ __netif_rx_schedule(priv->dev, &priv->napi); --
From: Stephen Hemminger <shemminger@vyatta.com> Yes, of course, all of those NAPI et al. abstraction macros have to go. I was only commenting about the DMA bits, the rest of your criticism was on target. --
Thank you for point those out. This is my first driver, so I still have many things to learn. I'll work on it. Any suggestion or help is very welcome! Guo-Fu Tseng --
You are right about it. I have another jme.h which can compile for older kernel. It can be removed if it should be. Guo-Fu Tseng --
