summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-13 18:27:40 -0600
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-13 18:27:40 -0600
commitf0094b28f3038936c1985be64dbe83f0e950b671 (patch)
treec3a61d5583cc2b39f65ef3b01e6660696b359656 /drivers/net/ethernet
parent13b102bf48d39d84d87bee31544f4588502649b6 (diff)
parent61dac43ee6bedd8507294c7af8959157b686c221 (diff)
downloadtalos-obmc-linux-f0094b28f3038936c1985be64dbe83f0e950b671.tar.gz
talos-obmc-linux-f0094b28f3038936c1985be64dbe83f0e950b671.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Several networking final fixes and tidies for the merge window: 1) Changes during the merge window unintentionally took away the ability to build bluetooth modular, fix from Geert Uytterhoeven. 2) Several phy_node reference count bug fixes from Uwe Kleine-König. 3) Fix ucc_geth build failures, also from Uwe Kleine-König. 4) Fix klog false positivies when netlink messages go to network taps, by properly resetting the network header. Fix from Daniel Borkmann. 5) Sizing estimate of VF netlink messages is too small, from Jiri Benc. 6) New APM X-Gene SoC ethernet driver, from Iyappan Subramanian. 7) VLAN untagging is erroneously dependent upon whether the VLAN module is loaded or not, but there are generic dependencies that matter wrt what can be expected as the SKB enters the stack. Make the basic untagging generic code, and do it unconditionally. From Vlad Yasevich. 8) xen-netfront only has so many slots in it's transmit queue so linearize packets that have too many frags. From Zoltan Kiss. 9) Fix suspend/resume PHY handling in bcmgenet driver, from Florian Fainelli" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (55 commits) net: bcmgenet: correctly resume adapter from Wake-on-LAN net: bcmgenet: update UMAC_CMD only when link is detected net: bcmgenet: correctly suspend and resume PHY device net: bcmgenet: request and enable main clock earlier net: ethernet: myricom: myri10ge: myri10ge.c: Cleaning up missing null-terminate after strncpy call xen-netfront: Fix handling packets on compound pages with skb_linearize net: fec: Support phys probed from devicetree and fixed-link smsc: replace WARN_ON() with WARN_ON_SMP() xen-netback: Don't deschedule NAPI when carrier off net: ethernet: qlogic: qlcnic: Remove duplicate object file from Makefile wan: wanxl: Remove typedefs from struct names m68k/atari: EtherNEC - ethernet support (ne) net: ethernet: ti: cpmac.c: Cleaning up missing null-terminate after strncpy call hdlc: Remove typedefs from struct names airo_cs: Remove typedef local_info_t atmel: Remove typedef atmel_priv_ioctl com20020_cs: Remove typedef com20020_dev_t ethernet: amd: Remove typedef local_info_t net: Always untag vlan-tagged traffic on input. drivers: net: Add APM X-Gene SoC ethernet driver support. ...
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/8390/Kconfig3
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c26
-rw-r--r--drivers/net/ethernet/8390/ne.c2
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c68
-rw-r--r--drivers/net/ethernet/Kconfig1
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c1
-rw-r--r--drivers/net/ethernet/apm/Kconfig1
-rw-r--r--drivers/net/ethernet/apm/Makefile5
-rw-r--r--drivers/net/ethernet/apm/xgene/Kconfig9
-rw-r--r--drivers/net/ethernet/apm/xgene/Makefile6
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c125
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c728
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h337
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c951
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h135
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c37
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h11
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c260
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h10
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h12
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c92
-rw-r--r--drivers/net/ethernet/freescale/fec.h1
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c76
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c3
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c16
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c24
-rw-r--r--drivers/net/ethernet/fujitsu/fmvj18x_cs.c34
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c9
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/Makefile2
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.h2
-rw-r--r--drivers/net/ethernet/ti/cpmac.c1
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c3
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c3
-rw-r--r--drivers/net/ethernet/xircom/xirc2ps_cs.c40
39 files changed, 2778 insertions, 276 deletions
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index 0988811f4e40..2d89bd00de61 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -91,7 +91,8 @@ config MCF8390
config NE2000
tristate "NE2000/NE1000 support"
- depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+ depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX || \
+ ATARI_ETHERNEC)
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 73c57a4a7b9e..7769c05543f1 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -108,7 +108,7 @@ static u32 axnet_msg_enable;
/*====================================================================*/
-typedef struct axnet_dev_t {
+struct axnet_dev {
struct pcmcia_device *p_dev;
caddr_t base;
struct timer_list watchdog;
@@ -118,9 +118,9 @@ typedef struct axnet_dev_t {
int phy_id;
int flags;
int active_low;
-} axnet_dev_t;
+};
-static inline axnet_dev_t *PRIV(struct net_device *dev)
+static inline struct axnet_dev *PRIV(struct net_device *dev)
{
void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
return p;
@@ -141,13 +141,13 @@ static const struct net_device_ops axnet_netdev_ops = {
static int axnet_probe(struct pcmcia_device *link)
{
- axnet_dev_t *info;
+ struct axnet_dev *info;
struct net_device *dev;
struct ei_device *ei_local;
dev_dbg(&link->dev, "axnet_attach()\n");
- dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
+ dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(struct axnet_dev));
if (!dev)
return -ENOMEM;
@@ -274,7 +274,7 @@ static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
static int axnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
int i, j, j2, ret;
dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
@@ -389,7 +389,7 @@ static int axnet_suspend(struct pcmcia_device *link)
static int axnet_resume(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
if (link->open) {
if (info->active_low == 1)
@@ -467,7 +467,7 @@ static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
int ret;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
unsigned int nic_base = dev->base_addr;
@@ -497,7 +497,7 @@ static int axnet_open(struct net_device *dev)
static int axnet_close(struct net_device *dev)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
@@ -554,7 +554,7 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
static void ei_watchdog(u_long arg)
{
struct net_device *dev = (struct net_device *)(arg);
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
unsigned int nic_base = dev->base_addr;
unsigned int mii_addr = nic_base + AXNET_MII_EEP;
u_short link;
@@ -610,7 +610,7 @@ reschedule:
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct mii_ioctl_data *data = if_mii(rq);
unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
switch (cmd) {
@@ -1452,7 +1452,7 @@ static void ei_receive(struct net_device *dev)
static void ei_rx_overrun(struct net_device *dev)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
long e8390_base = dev->base_addr;
unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = netdev_priv(dev);
@@ -1624,7 +1624,7 @@ static void set_multicast_list(struct net_device *dev)
static void AX88190_init(struct net_device *dev, int startp)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
long e8390_base = dev->base_addr;
struct ei_device *ei_local = netdev_priv(dev);
int i;
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index 58eaa8f34942..de566fb6e0f7 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -169,6 +169,8 @@ bad_clone_list[] __initdata = {
#elif defined(CONFIG_PLAT_OAKS32R) || \
defined(CONFIG_MACH_TX49XX)
# define DCR_VAL 0x48 /* 8-bit mode */
+#elif defined(CONFIG_ATARI) /* 8-bit mode on Atari, normal on Q40 */
+# define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49)
#else
# define DCR_VAL 0x49
#endif
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index ca3c2b921cf6..9fb7b9d4fd6c 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -111,11 +111,11 @@ static void pcnet_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
-typedef struct hw_info_t {
+struct hw_info {
u_int offset;
u_char a0, a1, a2;
u_int flags;
-} hw_info_t;
+};
#define DELAY_OUTPUT 0x01
#define HAS_MISC_REG 0x02
@@ -132,7 +132,7 @@ typedef struct hw_info_t {
#define MII_PHYID_REG1 0x02
#define MII_PHYID_REG2 0x03
-static hw_info_t hw_info[] = {
+static struct hw_info hw_info[] = {
{ /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
{ /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
{ /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
@@ -196,11 +196,11 @@ static hw_info_t hw_info[] = {
#define NR_INFO ARRAY_SIZE(hw_info)
-static hw_info_t default_info = { 0, 0, 0, 0, 0 };
-static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
-static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
+static struct hw_info default_info = { 0, 0, 0, 0, 0 };
+static struct hw_info dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
+static struct hw_info dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
-typedef struct pcnet_dev_t {
+struct pcnet_dev {
struct pcmcia_device *p_dev;
u_int flags;
void __iomem *base;
@@ -210,12 +210,12 @@ typedef struct pcnet_dev_t {
u_char eth_phy, pna_phy;
u_short link_status;
u_long mii_reset;
-} pcnet_dev_t;
+};
-static inline pcnet_dev_t *PRIV(struct net_device *dev)
+static inline struct pcnet_dev *PRIV(struct net_device *dev)
{
char *p = netdev_priv(dev);
- return (pcnet_dev_t *)(p + sizeof(struct ei_device));
+ return (struct pcnet_dev *)(p + sizeof(struct ei_device));
}
static const struct net_device_ops pcnet_netdev_ops = {
@@ -237,13 +237,13 @@ static const struct net_device_ops pcnet_netdev_ops = {
static int pcnet_probe(struct pcmcia_device *link)
{
- pcnet_dev_t *info;
+ struct pcnet_dev *info;
struct net_device *dev;
dev_dbg(&link->dev, "pcnet_attach()\n");
/* Create new ethernet device */
- dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
+ dev = __alloc_ei_netdev(sizeof(struct pcnet_dev));
if (!dev) return -ENOMEM;
info = PRIV(dev);
info->p_dev = link;
@@ -276,7 +276,7 @@ static void pcnet_detach(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+static struct hw_info *get_hwinfo(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
u_char __iomem *base, *virt;
@@ -317,7 +317,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_prom(struct pcmcia_device *link)
+static struct hw_info *get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
unsigned int ioaddr = dev->base_addr;
@@ -371,7 +371,7 @@ static hw_info_t *get_prom(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_dl10019(struct pcmcia_device *link)
+static struct hw_info *get_dl10019(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -393,7 +393,7 @@ static hw_info_t *get_dl10019(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_ax88190(struct pcmcia_device *link)
+static struct hw_info *get_ax88190(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
unsigned int ioaddr = dev->base_addr;
@@ -424,7 +424,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_hwired(struct pcmcia_device *link)
+static struct hw_info *get_hwired(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -489,12 +489,12 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
return try_io_port(p_dev);
}
-static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
- int *has_shmem, int try)
+static struct hw_info *pcnet_try_config(struct pcmcia_device *link,
+ int *has_shmem, int try)
{
struct net_device *dev = link->priv;
- hw_info_t *local_hw_info;
- pcnet_dev_t *info = PRIV(dev);
+ struct hw_info *local_hw_info;
+ struct pcnet_dev *info = PRIV(dev);
int priv = try;
int ret;
@@ -553,10 +553,10 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
static int pcnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
int start_pg, stop_pg, cm_offset;
int has_shmem = 0;
- hw_info_t *local_hw_info;
+ struct hw_info *local_hw_info;
struct ei_device *ei_local;
dev_dbg(&link->dev, "pcnet_config\n");
@@ -639,7 +639,7 @@ failed:
static void pcnet_release(struct pcmcia_device *link)
{
- pcnet_dev_t *info = PRIV(link->priv);
+ struct pcnet_dev *info = PRIV(link->priv);
dev_dbg(&link->dev, "pcnet_release\n");
@@ -836,7 +836,7 @@ static void write_asic(unsigned int ioaddr, int location, short asic_data)
static void set_misc_reg(struct net_device *dev)
{
unsigned int nic_base = dev->base_addr;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
u_char tmp;
if (info->flags & HAS_MISC_REG) {
@@ -873,7 +873,7 @@ static void set_misc_reg(struct net_device *dev)
static void mii_phy_probe(struct net_device *dev)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
int i;
u_int tmp, phyid;
@@ -898,7 +898,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
int ret;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
unsigned int nic_base = dev->base_addr;
@@ -931,7 +931,7 @@ static int pcnet_open(struct net_device *dev)
static int pcnet_close(struct net_device *dev)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
@@ -982,7 +982,7 @@ static void pcnet_reset_8390(struct net_device *dev)
static int set_config(struct net_device *dev, struct ifmap *map)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
if (!(info->flags & HAS_MISC_REG))
return -EOPNOTSUPP;
@@ -1000,7 +1000,7 @@ static int set_config(struct net_device *dev, struct ifmap *map)
static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- pcnet_dev_t *info;
+ struct pcnet_dev *info;
irqreturn_t ret = ei_interrupt(irq, dev_id);
if (ret == IRQ_HANDLED) {
@@ -1013,7 +1013,7 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
static void ei_watchdog(u_long arg)
{
struct net_device *dev = (struct net_device *)arg;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
unsigned int nic_base = dev->base_addr;
unsigned int mii_addr = nic_base + DLINK_GPIO;
u_short link;
@@ -1101,7 +1101,7 @@ reschedule:
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct mii_ioctl_data *data = if_mii(rq);
unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
@@ -1214,7 +1214,7 @@ static void dma_block_output(struct net_device *dev, int count,
const u_char *buf, const int start_page)
{
unsigned int nic_base = dev->base_addr;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
#ifdef PCMCIA_DEBUG
int retries = 0;
struct ei_device *ei_local = netdev_priv(dev);
@@ -1403,7 +1403,7 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset)
{
struct net_device *dev = link->priv;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
int i, window_size, offset, ret;
window_size = (stop_pg - start_pg) << 8;
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index edb718661850..dc7406c81c45 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
source "drivers/net/ethernet/altera/Kconfig"
source "drivers/net/ethernet/amd/Kconfig"
+source "drivers/net/ethernet/apm/Kconfig"
source "drivers/net/ethernet/apple/Kconfig"
source "drivers/net/ethernet/arc/Kconfig"
source "drivers/net/ethernet/atheros/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 58de3339ab3c..224a01877149 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
obj-$(CONFIG_ALTERA_TSE) += altera/
obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_XGENE) += apm/
obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
obj-$(CONFIG_NET_VENDOR_ARC) += arc/
obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 1f5487f4888c..dc84f7193c2d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -117,7 +117,6 @@
#include <linux/spinlock.h>
#include <linux/tcp.h>
#include <linux/if_vlan.h>
-#include <linux/phy.h>
#include <net/busy_poll.h>
#include <linux/clk.h>
#include <linux/if_ether.h>
diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
new file mode 100644
index 000000000000..ec63d706d464
--- /dev/null
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -0,0 +1 @@
+source "drivers/net/ethernet/apm/xgene/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile b/drivers/net/ethernet/apm/Makefile
new file mode 100644
index 000000000000..65ce32ad1b2c
--- /dev/null
+++ b/drivers/net/ethernet/apm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for APM X-GENE Ethernet driver.
+#
+
+obj-$(CONFIG_NET_XGENE) += xgene/
diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
new file mode 100644
index 000000000000..616dff6d3f5f
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Kconfig
@@ -0,0 +1,9 @@
+config NET_XGENE
+ tristate "APM X-Gene SoC Ethernet Driver"
+ select PHYLIB
+ help
+ This is the Ethernet driver for the on-chip ethernet interface on the
+ APM X-Gene SoC.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene_enet.
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
new file mode 100644
index 000000000000..c643e8a0a0dc
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet Driver.
+#
+
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
+obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
new file mode 100644
index 000000000000..63f2aa54a594
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -0,0 +1,125 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/ethtool.h>
+#include "xgene_enet_main.h"
+
+struct xgene_gstrings_stats {
+ char name[ETH_GSTRING_LEN];
+ int offset;
+};
+
+#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
+
+static const struct xgene_gstrings_stats gstrings_stats[] = {
+ XGENE_STAT(rx_packets),
+ XGENE_STAT(tx_packets),
+ XGENE_STAT(rx_bytes),
+ XGENE_STAT(tx_bytes),
+ XGENE_STAT(rx_errors),
+ XGENE_STAT(tx_errors),
+ XGENE_STAT(rx_length_errors),
+ XGENE_STAT(rx_crc_errors),
+ XGENE_STAT(rx_frame_errors),
+ XGENE_STAT(rx_fifo_errors)
+};
+
+#define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats)
+
+static void xgene_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct platform_device *pdev = pdata->pdev;
+
+ strcpy(info->driver, "xgene_enet");
+ strcpy(info->version, XGENE_DRV_VERSION);
+ snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
+ sprintf(info->bus_info, "%s", pdev->name);
+}
+
+static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_gset(phydev, cmd);
+}
+
+static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+}
+
+static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ int i;
+ u8 *p = data;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < XGENE_STATS_LEN; i++) {
+ memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+}
+
+static int xgene_get_sset_count(struct net_device *ndev, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return -EINVAL;
+
+ return XGENE_STATS_LEN;
+}
+
+static void xgene_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *dummy,
+ u64 *data)
+{
+ void *pdata = netdev_priv(ndev);
+ int i;
+
+ for (i = 0; i < XGENE_STATS_LEN; i++)
+ *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+}
+
+static const struct ethtool_ops xgene_ethtool_ops = {
+ .get_drvinfo = xgene_get_drvinfo,
+ .get_settings = xgene_get_settings,
+ .set_settings = xgene_set_settings,
+ .get_link = ethtool_op_get_link,
+ .get_strings = xgene_get_strings,
+ .get_sset_count = xgene_get_sset_count,
+ .get_ethtool_stats = xgene_get_ethtool_stats
+};
+
+void xgene_enet_set_ethtool_ops(struct net_device *ndev)
+{
+ ndev->ethtool_ops = &xgene_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
new file mode 100644
index 000000000000..812d8d65159b
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -0,0 +1,728 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+ u64 addr = ring->dma;
+ enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize;
+
+ ring_cfg[4] |= (1 << SELTHRSH_POS) &
+ CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN);
+ ring_cfg[3] |= ACCEPTLERR;
+ ring_cfg[2] |= QCOHERENT;
+
+ addr >>= 8;
+ ring_cfg[2] |= (addr << RINGADDRL_POS) &
+ CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN);
+ addr >>= RINGADDRL_LEN;
+ ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN);
+ ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) &
+ CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN);
+}
+
+static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+ bool is_bufpool;
+ u32 val;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR;
+ ring_cfg[4] |= (val << RINGTYPE_POS) &
+ CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN);
+
+ if (is_bufpool) {
+ ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) &
+ CREATE_MASK(RINGMODE_POS, RINGMODE_LEN);
+ }
+}
+
+static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+
+ ring_cfg[3] |= RECOMBBUF;
+ ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) &
+ CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN);
+ ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN);
+}
+
+static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring,
+ u32 offset, u32 data)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ iowrite32(data, pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
+ u32 offset, u32 *data)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ *data = ioread32(pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ int i;
+
+ xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
+ for (i = 0; i < NUM_RING_CONFIG; i++) {
+ xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
+ ring->state[i]);
+ }
+}
+
+static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG);
+ xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ xgene_enet_ring_set_type(ring);
+
+ if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
+ xgene_enet_ring_set_recombbuf(ring);
+
+ xgene_enet_ring_init(ring);
+ xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
+{
+ u32 ring_id_val, ring_id_buf;
+ bool is_bufpool;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+
+ ring_id_val = ring->id & GENMASK(9, 0);
+ ring_id_val |= OVERWRITE;
+
+ ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
+ ring_id_buf |= PREFETCH_BUF_EN;
+ if (is_bufpool)
+ ring_id_buf |= IS_BUFFER_POOL;
+
+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val);
+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf);
+}
+
+static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
+{
+ u32 ring_id;
+
+ ring_id = ring->id | OVERWRITE;
+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id);
+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+ struct xgene_enet_desc_ring *ring)
+{
+ u32 size = ring->size;
+ u32 i, data;
+ bool is_bufpool;
+
+ xgene_enet_clr_ring_state(ring);
+ xgene_enet_set_ring_state(ring);
+ xgene_enet_set_ring_id(ring);
+
+ ring->slots = xgene_enet_get_numslots(ring->id, size);
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+ return ring;
+
+ for (i = 0; i < ring->slots; i++)
+ xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]);
+
+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+ data |= BIT(31 - xgene_enet_ring_bufnum(ring->id));
+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+ return ring;
+}
+
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
+{
+ u32 data;
+ bool is_bufpool;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+ goto out;
+
+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+ data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id));
+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+out:
+ xgene_enet_clr_desc_ring_id(ring);
+ xgene_enet_clr_ring_state(ring);
+}
+
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status)
+{
+ struct rtnl_link_stats64 *stats = &pdata->stats;
+
+ switch (status) {
+ case INGRESS_CRC:
+ stats->rx_crc_errors++;
+ break;
+ case INGRESS_CHECKSUM:
+ case INGRESS_CHECKSUM_COMPUTE:
+ stats->rx_errors++;
+ break;
+ case INGRESS_TRUNC_FRAME:
+ stats->rx_frame_errors++;
+ break;
+ case INGRESS_PKT_LEN:
+ stats->rx_length_errors++;
+ break;
+ case INGRESS_PKT_UNDER:
+ stats->rx_frame_errors++;
+ break;
+ case INGRESS_FIFO_OVERRUN:
+ stats->rx_fifo_errors++;
+ break;
+ default:
+ break;
+ }
+}
+
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_ring_if_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 wr_addr, u32 wr_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(wr_addr, addr);
+ iowrite32(wr_data, wr);
+ iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+ /* wait for write command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
+ u32 wr_addr, u32 wr_data)
+{
+ void __iomem *addr, *wr, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+ netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
+ wr_addr);
+}
+
+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 rd_addr, u32 *rd_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(rd_addr, addr);
+ iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+ /* wait for read command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ *rd_data = ioread32(rd);
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
+ u32 rd_addr, u32 *rd_data)
+{
+ void __iomem *addr, *rd, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+ netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
+ rd_addr);
+}
+
+static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id,
+ u32 reg, u16 data)
+{
+ u32 addr = 0, wr_data = 0;
+ u32 done;
+ u8 wait = 10;
+
+ PHY_ADDR_SET(&addr, phy_id);
+ REG_ADDR_SET(&addr, reg);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+
+ PHY_CONTROL_SET(&wr_data, data);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data);
+ do {
+ usleep_range(5, 10);
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+ } while ((done & BUSY_MASK) && wait--);
+
+ if (done & BUSY_MASK) {
+ netdev_err(pdata->ndev, "MII_MGMT write failed\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
+ u8 phy_id, u32 reg)
+{
+ u32 addr = 0;
+ u32 data, done;
+ u8 wait = 10;
+
+ PHY_ADDR_SET(&addr, phy_id);
+ REG_ADDR_SET(&addr, reg);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+ do {
+ usleep_range(5, 10);
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+ } while ((done & BUSY_MASK) && wait--);
+
+ if (done & BUSY_MASK) {
+ netdev_err(pdata->ndev, "MII_MGMT read failed\n");
+ return -EBUSY;
+ }
+
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
+
+ return data;
+}
+
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+{
+ u32 addr0, addr1;
+ u8 *dev_addr = pdata->ndev->dev_addr;
+
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+ addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+ addr1 |= pdata->phy_addr & 0xFFFF;
+
+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ u32 data;
+ u8 wait = 10;
+
+ xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+ do {
+ usleep_range(100, 110);
+ xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
+ } while ((data != 0xffffffff) && wait--);
+
+ if (data != 0xffffffff) {
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
+{
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
+}
+
+void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
+{
+ u32 value, mc2;
+ u32 intf_ctl, rgmii;
+ u32 icm0, icm2;
+
+ xgene_gmac_reset(pdata);
+
+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
+ xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
+ xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
+
+ switch (speed) {
+ case SPEED_10:
+ ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ CFG_MACMODE_SET(&icm0, 0);
+ CFG_WAITASYNCRD_SET(&icm2, 500);
+ rgmii &= ~CFG_SPEED_1250;
+ break;
+ case SPEED_100:
+ ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ intf_ctl |= ENET_LHD_MODE;
+ CFG_MACMODE_SET(&icm0, 1);
+ CFG_WAITASYNCRD_SET(&icm2, 80);
+ rgmii &= ~CFG_SPEED_1250;
+ break;
+ default:
+ ENET_INTERFACE_MODE2_SET(&mc2, 2);
+ intf_ctl |= ENET_GHD_MODE;
+ CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
+ xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
+ value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+ xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
+ break;
+ }
+
+ mc2 |= FULL_DUPLEX2;
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
+ xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
+
+ xgene_gmac_set_mac_addr(pdata);
+
+ /* Adjust MDC clock frequency */
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
+ MGMT_CLOCK_SEL_SET(&value, 7);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
+
+ /* Enable drop if bufpool not available */
+ xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
+ value |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+ xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value);
+
+ /* Rtype should be copied from FP */
+ xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
+ xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+
+ /* Rx-Tx traffic resume */
+ xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
+
+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
+
+ xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
+ value &= ~TX_DV_GATE_EN0;
+ value &= ~RX_DV_GATE_EN0;
+ value |= RESUME_RX0;
+ xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value);
+
+ xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
+}
+
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
+{
+ u32 val = 0xffffffff;
+
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
+}
+
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id)
+{
+ u32 cb;
+ u32 fpsel;
+
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+
+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
+ cb |= CFG_CLE_BYPASS_EN0;
+ CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
+
+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
+ CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
+ CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
+}
+
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
+}
+
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
+}
+
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
+}
+
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
+}
+
+void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+{
+ u32 val;
+
+ clk_prepare_enable(pdata->clk);
+ clk_disable_unprepare(pdata->clk);
+ clk_prepare_enable(pdata->clk);
+ xgene_enet_ecc_init(pdata);
+ xgene_enet_config_ring_if_assoc(pdata);
+
+ /* Enable auto-incr for scanning */
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
+ val |= SCAN_AUTO_INCR;
+ MGMT_CLOCK_SEL_SET(&val, 1);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
+}
+
+void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
+{
+ clk_disable_unprepare(pdata->clk);
+}
+
+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct xgene_enet_pdata *pdata = bus->priv;
+ u32 val;
+
+ val = xgene_mii_phy_read(pdata, mii_id, regnum);
+ netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n",
+ mii_id, regnum, val);
+
+ return val;
+}
+
+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 val)
+{
+ struct xgene_enet_pdata *pdata = bus->priv;
+
+ netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n",
+ mii_id, regnum, val);
+ return xgene_mii_phy_write(pdata, mii_id, regnum, val);
+}
+
+static void xgene_enet_adjust_link(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev->link) {
+ if (pdata->phy_speed != phydev->speed) {
+ xgene_gmac_init(pdata, phydev->speed);
+ xgene_gmac_rx_enable(pdata);
+ xgene_gmac_tx_enable(pdata);
+ pdata->phy_speed = phydev->speed;
+ phy_print_status(phydev);
+ }
+ } else {
+ xgene_gmac_rx_disable(pdata);
+ xgene_gmac_tx_disable(pdata);
+ pdata->phy_speed = SPEED_UNKNOWN;
+ phy_print_status(phydev);
+ }
+}
+
+static int xgene_enet_phy_connect(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device_node *phy_np;
+ struct phy_device *phy_dev;
+ struct device *dev = &pdata->pdev->dev;
+
+ phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
+ if (!phy_np) {
+ netdev_dbg(ndev, "No phy-handle found\n");
+ return -ENODEV;
+ }
+
+ phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+ 0, pdata->phy_mode);
+ if (!phy_dev) {
+ netdev_err(ndev, "Could not connect to PHY\n");
+ return -ENODEV;
+ }
+
+ pdata->phy_speed = SPEED_UNKNOWN;
+ phy_dev->supported &= ~SUPPORTED_10baseT_Half &
+ ~SUPPORTED_100baseT_Half &
+ ~SUPPORTED_1000baseT_Half;
+ phy_dev->advertising = phy_dev->supported;
+ pdata->phy_dev = phy_dev;
+
+ return 0;
+}
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ struct device *dev = &pdata->pdev->dev;
+ struct device_node *child_np;
+ struct device_node *mdio_np = NULL;
+ struct mii_bus *mdio_bus;
+ int ret;
+
+ for_each_child_of_node(dev->of_node, child_np) {
+ if (of_device_is_compatible(child_np, "apm,xgene-mdio")) {
+ mdio_np = child_np;
+ break;
+ }
+ }
+
+ if (!mdio_np) {
+ netdev_dbg(ndev, "No mdio node in the dts\n");
+ return -ENXIO;
+ }
+
+ mdio_bus = mdiobus_alloc();
+ if (!mdio_bus)
+ return -ENOMEM;
+
+ mdio_bus->name = "APM X-Gene MDIO bus";
+ mdio_bus->read = xgene_enet_mdio_read;
+ mdio_bus->write = xgene_enet_mdio_write;
+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii",
+ ndev->name);
+
+ mdio_bus->priv = pdata;
+ mdio_bus->parent = &ndev->dev;
+
+ ret = of_mdiobus_register(mdio_bus, mdio_np);
+ if (ret) {
+ netdev_err(ndev, "Failed to register MDIO bus\n");
+ mdiobus_free(mdio_bus);
+ return ret;
+ }
+ pdata->mdio_bus = mdio_bus;
+
+ ret = xgene_enet_phy_connect(ndev);
+ if (ret)
+ xgene_enet_mdio_remove(pdata);
+
+ return ret;
+}
+
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
+{
+ mdiobus_unregister(pdata->mdio_bus);
+ mdiobus_free(pdata->mdio_bus);
+ pdata->mdio_bus = NULL;
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
new file mode 100644
index 000000000000..371e7a5b2507
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -0,0 +1,337 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_HW_H__
+#define __XGENE_ENET_HW_H__
+
+#include "xgene_enet_main.h"
+
+struct xgene_enet_pdata;
+struct xgene_enet_stats;
+
+/* clears and then set bits */
+static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len)
+{
+ u32 end = start + len - 1;
+ u32 mask = GENMASK(end, start);
+
+ *dst &= ~mask;
+ *dst |= (val << start) & mask;
+}
+
+static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
+{
+ return (val & GENMASK(end, start)) >> start;
+}
+
+#define CSR_RING_ID 0x0008
+#define OVERWRITE BIT(31)
+#define IS_BUFFER_POOL BIT(20)
+#define PREFETCH_BUF_EN BIT(21)
+#define CSR_RING_ID_BUF 0x000c
+#define CSR_RING_NE_INT_MODE 0x017c
+#define CSR_RING_CONFIG 0x006c
+#define CSR_RING_WR_BASE 0x0070
+#define NUM_RING_CONFIG 5
+#define BUFPOOL_MODE 3
+#define RM3 3
+#define INC_DEC_CMD_ADDR 0x002c
+#define UDP_HDR_SIZE 2
+#define BUF_LEN_CODE_2K 0x5000
+
+#define CREATE_MASK(pos, len) GENMASK((pos)+(len)-1, (pos))
+#define CREATE_MASK_ULL(pos, len) GENMASK_ULL((pos)+(len)-1, (pos))
+
+/* Empty slot soft signature */
+#define EMPTY_SLOT_INDEX 1
+#define EMPTY_SLOT ~0ULL
+
+#define WORK_DESC_SIZE 32
+#define BUFPOOL_DESC_SIZE 16
+
+#define RING_OWNER_MASK GENMASK(9, 6)
+#define RING_BUFNUM_MASK GENMASK(5, 0)
+
+#define SELTHRSH_POS 3
+#define SELTHRSH_LEN 3
+#define RINGADDRL_POS 5
+#define RINGADDRL_LEN 27
+#define RINGADDRH_POS 0
+#define RINGADDRH_LEN 6
+#define RINGSIZE_POS 23
+#define RINGSIZE_LEN 3
+#define RINGTYPE_POS 19
+#define RINGTYPE_LEN 2
+#define RINGMODE_POS 20
+#define RINGMODE_LEN 3
+#define RECOMTIMEOUTL_POS 28
+#define RECOMTIMEOUTL_LEN 3
+#define RECOMTIMEOUTH_POS 0
+#define RECOMTIMEOUTH_LEN 2
+#define NUMMSGSINQ_POS 1
+#define NUMMSGSINQ_LEN 16
+#define ACCEPTLERR BIT(19)
+#define QCOHERENT BIT(4)
+#define RECOMBBUF BIT(27)
+
+#define BLOCK_ETH_CSR_OFFSET 0x2000
+#define BLOCK_ETH_RING_IF_OFFSET 0x9000
+#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000
+#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
+
+#define BLOCK_ETH_MAC_OFFSET 0x0000
+#define BLOCK_ETH_STATS_OFFSET 0x0014
+#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
+
+#define MAC_ADDR_REG_OFFSET 0x00
+#define MAC_COMMAND_REG_OFFSET 0x04
+#define MAC_WRITE_REG_OFFSET 0x08
+#define MAC_READ_REG_OFFSET 0x0c
+#define MAC_COMMAND_DONE_REG_OFFSET 0x10
+
+#define STAT_ADDR_REG_OFFSET 0x00
+#define STAT_COMMAND_REG_OFFSET 0x04
+#define STAT_WRITE_REG_OFFSET 0x08
+#define STAT_READ_REG_OFFSET 0x0c
+#define STAT_COMMAND_DONE_REG_OFFSET 0x10
+
+#define MII_MGMT_CONFIG_ADDR 0x20
+#define MII_MGMT_COMMAND_ADDR 0x24
+#define MII_MGMT_ADDRESS_ADDR 0x28
+#define MII_MGMT_CONTROL_ADDR 0x2c
+#define MII_MGMT_STATUS_ADDR 0x30
+#define MII_MGMT_INDICATORS_ADDR 0x34
+
+#define BUSY_MASK BIT(0)
+#define READ_CYCLE_MASK BIT(0)
+#define PHY_CONTROL_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
+
+#define ENET_SPARE_CFG_REG_ADDR 0x0750
+#define RSIF_CONFIG_REG_ADDR 0x0010
+#define RSIF_RAM_DBG_REG0_ADDR 0x0048
+#define RGMII_REG_0_ADDR 0x07e0
+#define CFG_LINK_AGGR_RESUME_0_ADDR 0x07c8
+#define DEBUG_REG_ADDR 0x0700
+#define CFG_BYPASS_ADDR 0x0294
+#define CLE_BYPASS_REG0_0_ADDR 0x0490
+#define CLE_BYPASS_REG1_0_ADDR 0x0494
+#define CFG_RSIF_FPBUFF_TIMEOUT_EN BIT(31)
+#define RESUME_TX BIT(0)
+#define CFG_SPEED_1250 BIT(24)
+#define TX_PORT0 BIT(0)
+#define CFG_BYPASS_UNISEC_TX BIT(2)
+#define CFG_BYPASS_UNISEC_RX BIT(1)
+#define CFG_CLE_BYPASS_EN0 BIT(31)
+#define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3)
+
+#define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
+#define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12)
+#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
+#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2)
+#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
+#define ICM_CONFIG0_REG_0_ADDR 0x0400
+#define ICM_CONFIG2_REG_0_ADDR 0x0410
+#define RX_DV_GATE_REG_0_ADDR 0x05fc
+#define TX_DV_GATE_EN0 BIT(2)
+#define RX_DV_GATE_EN0 BIT(1)
+#define RESUME_RX0 BIT(0)
+#define ENET_CFGSSQMIWQASSOC_ADDR 0xe0
+#define ENET_CFGSSQMIFPQASSOC_ADDR 0xdc
+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR 0xf0
+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR 0xf4
+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR 0x70
+#define ENET_BLOCK_MEM_RDY_ADDR 0x74
+#define MAC_CONFIG_1_ADDR 0x00
+#define MAC_CONFIG_2_ADDR 0x04
+#define MAX_FRAME_LEN_ADDR 0x10
+#define INTERFACE_CONTROL_ADDR 0x38
+#define STATION_ADDR0_ADDR 0x40
+#define STATION_ADDR1_ADDR 0x44
+#define PHY_ADDR_SET(dst, val) xgene_set_bits(dst, val, 8, 5)
+#define REG_ADDR_SET(dst, val) xgene_set_bits(dst, val, 0, 5)
+#define ENET_INTERFACE_MODE2_SET(dst, val) xgene_set_bits(dst, val, 8, 2)
+#define MGMT_CLOCK_SEL_SET(dst, val) xgene_set_bits(dst, val, 0, 3)
+#define SOFT_RESET1 BIT(31)
+#define TX_EN BIT(0)
+#define RX_EN BIT(2)
+#define ENET_LHD_MODE BIT(25)
+#define ENET_GHD_MODE BIT(26)
+#define FULL_DUPLEX2 BIT(0)
+#define SCAN_AUTO_INCR BIT(5)
+#define TBYT_ADDR 0x38
+#define TPKT_ADDR 0x39
+#define TDRP_ADDR 0x45
+#define TFCS_ADDR 0x47
+#define TUND_ADDR 0x4a
+
+#define TSO_IPPROTO_TCP 1
+#define FULL_DUPLEX 2
+
+#define USERINFO_POS 0
+#define USERINFO_LEN 32
+#define FPQNUM_POS 32
+#define FPQNUM_LEN 12
+#define LERR_POS 60
+#define LERR_LEN 3
+#define STASH_POS 52
+#define STASH_LEN 2
+#define BUFDATALEN_POS 48
+#define BUFDATALEN_LEN 12
+#define DATAADDR_POS 0
+#define DATAADDR_LEN 42
+#define COHERENT_POS 63
+#define HENQNUM_POS 48
+#define HENQNUM_LEN 12
+#define TYPESEL_POS 44
+#define TYPESEL_LEN 4
+#define ETHHDR_POS 12
+#define ETHHDR_LEN 8
+#define IC_POS 35 /* Insert CRC */
+#define TCPHDR_POS 0
+#define TCPHDR_LEN 6
+#define IPHDR_POS 6
+#define IPHDR_LEN 6
+#define EC_POS 22 /* Enable checksum */
+#define EC_LEN 1
+#define IS_POS 24 /* IP protocol select */
+#define IS_LEN 1
+#define TYPE_ETH_WORK_MESSAGE_POS 44
+
+struct xgene_enet_raw_desc {
+ __le64 m0;
+ __le64 m1;
+ __le64 m2;
+ __le64 m3;
+};
+
+struct xgene_enet_raw_desc16 {
+ __le64 m0;
+ __le64 m1;
+};
+
+static inline void xgene_enet_mark_desc_slot_empty(void *desc_slot_ptr)
+{
+ __le64 *desc_slot = desc_slot_ptr;
+
+ desc_slot[EMPTY_SLOT_INDEX] = cpu_to_le64(EMPTY_SLOT);
+}
+
+static inline bool xgene_enet_is_desc_slot_empty(void *desc_slot_ptr)
+{
+ __le64 *desc_slot = desc_slot_ptr;
+
+ return (desc_slot[EMPTY_SLOT_INDEX] == cpu_to_le64(EMPTY_SLOT));
+}
+
+enum xgene_enet_ring_cfgsize {
+ RING_CFGSIZE_512B,
+ RING_CFGSIZE_2KB,
+ RING_CFGSIZE_16KB,
+ RING_CFGSIZE_64KB,
+ RING_CFGSIZE_512KB,
+ RING_CFGSIZE_INVALID
+};
+
+enum xgene_enet_ring_type {
+ RING_DISABLED,
+ RING_REGULAR,
+ RING_BUFPOOL
+};
+
+enum xgene_ring_owner {
+ RING_OWNER_ETH0,
+ RING_OWNER_CPU = 15,
+ RING_OWNER_INVALID
+};
+
+enum xgene_enet_ring_bufnum {
+ RING_BUFNUM_REGULAR = 0x0,
+ RING_BUFNUM_BUFPOOL = 0x20,
+ RING_BUFNUM_INVALID
+};
+
+enum xgene_enet_cmd {
+ XGENE_ENET_WR_CMD = BIT(31),
+ XGENE_ENET_RD_CMD = BIT(30)
+};
+
+enum xgene_enet_err_code {
+ HBF_READ_DATA = 3,
+ HBF_LL_READ = 4,
+ BAD_WORK_MSG = 6,
+ BUFPOOL_TIMEOUT = 15,
+ INGRESS_CRC = 16,
+ INGRESS_CHECKSUM = 17,
+ INGRESS_TRUNC_FRAME = 18,
+ INGRESS_PKT_LEN = 19,
+ INGRESS_PKT_UNDER = 20,
+ INGRESS_FIFO_OVERRUN = 21,
+ INGRESS_CHECKSUM_COMPUTE = 26,
+ ERR_CODE_INVALID
+};
+
+static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id)
+{
+ return (id & RING_OWNER_MASK) >> 6;
+}
+
+static inline u8 xgene_enet_ring_bufnum(u16 id)
+{
+ return id & RING_BUFNUM_MASK;
+}
+
+static inline bool xgene_enet_is_bufpool(u16 id)
+{
+ return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
+}
+
+static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
+{
+ bool is_bufpool = xgene_enet_is_bufpool(id);
+
+ return (is_bufpool) ? size / BUFPOOL_DESC_SIZE :
+ size / WORK_DESC_SIZE;
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+ struct xgene_enet_desc_ring *ring);
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring);
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status);
+
+void xgene_enet_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id);
+void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
+void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+
+#endif /* __XGENE_ENET_HW_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
new file mode 100644
index 000000000000..af7c40ac1455
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -0,0 +1,951 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ int i;
+
+ for (i = 0; i < buf_pool->slots; i++) {
+ raw_desc = &buf_pool->raw_desc16[i];
+
+ /* Hardware expects descriptor in little endian format */
+ raw_desc->m0 = cpu_to_le64(i |
+ SET_VAL(FPQNUM, buf_pool->dst_ring_num) |
+ SET_VAL(STASH, 3));
+ }
+}
+
+static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
+ u32 nbuf)
+{
+ struct sk_buff *skb;
+ struct xgene_enet_raw_desc16 *raw_desc;
+ struct net_device *ndev;
+ struct device *dev;
+ dma_addr_t dma_addr;
+ u32 tail = buf_pool->tail;
+ u32 slots = buf_pool->slots - 1;
+ u16 bufdatalen, len;
+ int i;
+
+ ndev = buf_pool->ndev;
+ dev = ndev_to_dev(buf_pool->ndev);
+ bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
+ len = XGENE_ENET_MAX_MTU;
+
+ for (i = 0; i < nbuf; i++) {
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ skb = netdev_alloc_skb_ip_align(ndev, len);
+ if (unlikely(!skb))
+ return -ENOMEM;
+ buf_pool->rx_skb[tail] = skb;
+
+ dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma_addr)) {
+ netdev_err(ndev, "DMA mapping error\n");
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, bufdatalen) |
+ SET_BIT(COHERENT));
+ tail = (tail + 1) & slots;
+ }
+
+ iowrite32(nbuf, buf_pool->cmd);
+ buf_pool->tail = tail;
+
+ return 0;
+}
+
+static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ return ((u16)pdata->rm << 10) | ring->num;
+}
+
+static u8 xgene_enet_hdr_len(const void *data)
+{
+ const struct ethhdr *eth = data;
+
+ return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+{
+ u32 __iomem *cmd_base = ring->cmd_base;
+ u32 ring_state, num_msgs;
+
+ ring_state = ioread32(&cmd_base[1]);
+ num_msgs = ring_state & CREATE_MASK(NUMMSGSINQ_POS, NUMMSGSINQ_LEN);
+
+ return num_msgs >> NUMMSGSINQ_POS;
+}
+
+static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ u32 slots = buf_pool->slots - 1;
+ u32 tail = buf_pool->tail;
+ u32 userinfo;
+ int i, len;
+
+ len = xgene_enet_ring_len(buf_pool);
+ for (i = 0; i < len; i++) {
+ tail = (tail - 1) & slots;
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ /* Hardware stores descriptor in little endian format */
+ userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
+ }
+
+ iowrite32(-len, buf_pool->cmd);
+ buf_pool->tail = tail;
+}
+
+static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
+{
+ struct xgene_enet_desc_ring *rx_ring = data;
+
+ if (napi_schedule_prep(&rx_ring->napi)) {
+ disable_irq_nosync(irq);
+ __napi_schedule(&rx_ring->napi);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ struct xgene_enet_raw_desc *raw_desc)
+{
+ struct sk_buff *skb;
+ struct device *dev;
+ u16 skb_index;
+ u8 status;
+ int ret = 0;
+
+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ skb = cp_ring->cp_skb[skb_index];
+
+ dev = ndev_to_dev(cp_ring->ndev);
+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+ GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)),
+ DMA_TO_DEVICE);
+
+ /* Checking for error */
+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+ if (unlikely(status > 2)) {
+ xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
+ status);
+ ret = -EIO;
+ }
+
+ if (likely(skb)) {
+ dev_kfree_skb_any(skb);
+ } else {
+ netdev_err(cp_ring->ndev, "completion skb is NULL\n");
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static u64 xgene_enet_work_msg(struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ u8 l3hlen, l4hlen = 0;
+ u8 csum_enable = 0;
+ u8 proto = 0;
+ u8 ethhdr;
+ u64 hopinfo;
+
+ if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
+ unlikely(skb->protocol != htons(ETH_P_8021Q)))
+ goto out;
+
+ if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM)))
+ goto out;
+
+ iph = ip_hdr(skb);
+ if (unlikely(ip_is_fragment(iph)))
+ goto out;
+
+ if (likely(iph->protocol == IPPROTO_TCP)) {
+ l4hlen = tcp_hdrlen(skb) >> 2;
+ csum_enable = 1;
+ proto = TSO_IPPROTO_TCP;
+ } else if (iph->protocol == IPPROTO_UDP) {
+ l4hlen = UDP_HDR_SIZE;
+ csum_enable = 1;
+ }
+out:
+ l3hlen = ip_hdrlen(skb) >> 2;
+ ethhdr = xgene_enet_hdr_len(skb->data);
+ hopinfo = SET_VAL(TCPHDR, l4hlen) |
+ SET_VAL(IPHDR, l3hlen) |
+ SET_VAL(ETHHDR, ethhdr) |
+ SET_VAL(EC, csum_enable) |
+ SET_VAL(IS, proto) |
+ SET_BIT(IC) |
+ SET_BIT(TYPE_ETH_WORK_MESSAGE);
+
+ return hopinfo;
+}
+
+static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
+ struct sk_buff *skb)
+{
+ struct device *dev = ndev_to_dev(tx_ring->ndev);
+ struct xgene_enet_raw_desc *raw_desc;
+ dma_addr_t dma_addr;
+ u16 tail = tx_ring->tail;
+ u64 hopinfo;
+
+ raw_desc = &tx_ring->raw_desc[tail];
+ memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
+
+ dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma_addr)) {
+ netdev_err(tx_ring->ndev, "DMA mapping error\n");
+ return -EINVAL;
+ }
+
+ /* Hardware expects descriptor in little endian format */
+ raw_desc->m0 = cpu_to_le64(tail);
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, skb->len) |
+ SET_BIT(COHERENT));
+ hopinfo = xgene_enet_work_msg(skb);
+ raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
+ hopinfo);
+ tx_ring->cp_ring->cp_skb[tail] = skb;
+
+ return 0;
+}
+
+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+ struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
+ struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
+ u32 tx_level, cq_level;
+
+ tx_level = xgene_enet_ring_len(tx_ring);
+ cq_level = xgene_enet_ring_len(cp_ring);
+ if (unlikely(tx_level > pdata->tx_qcnt_hi ||
+ cq_level > pdata->cp_qcnt_hi)) {
+ netif_stop_queue(ndev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (xgene_enet_setup_tx_desc(tx_ring, skb)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ iowrite32(1, tx_ring->cmd);
+ skb_tx_timestamp(skb);
+ tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1);
+
+ pdata->stats.tx_packets++;
+ pdata->stats.tx_bytes += skb->len;
+
+ return NETDEV_TX_OK;
+}
+
+static void xgene_enet_skip_csum(struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ if (!ip_is_fragment(iph) ||
+ (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+}
+
+static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
+ struct xgene_enet_raw_desc *raw_desc)
+{
+ struct net_device *ndev;
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u32 datalen, skb_index;
+ struct sk_buff *skb;
+ u8 status;
+ int ret = 0;
+
+ ndev = rx_ring->ndev;
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(rx_ring->ndev);
+ buf_pool = rx_ring->buf_pool;
+
+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+ XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ skb = buf_pool->rx_skb[skb_index];
+
+ /* checking for error */
+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+ if (unlikely(status > 2)) {
+ dev_kfree_skb_any(skb);
+ xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
+ status);
+ pdata->stats.rx_dropped++;
+ ret = -EIO;
+ goto out;
+ }
+
+ /* strip off CRC as HW isn't doing this */
+ datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
+ datalen -= 4;
+ prefetch(skb->data - NET_IP_ALIGN);
+ skb_put(skb, datalen);
+
+ skb_checksum_none_assert(skb);
+ skb->protocol = eth_type_trans(skb, ndev);
+ if (likely((ndev->features & NETIF_F_IP_CSUM) &&
+ skb->protocol == htons(ETH_P_IP))) {
+ xgene_enet_skip_csum(skb);
+ }
+
+ pdata->stats.rx_packets++;
+ pdata->stats.rx_bytes += datalen;
+ napi_gro_receive(&rx_ring->napi, skb);
+out:
+ if (--rx_ring->nbufpool == 0) {
+ ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
+ rx_ring->nbufpool = NUM_BUFPOOL;
+ }
+
+ return ret;
+}
+
+static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc)
+{
+ return GET_VAL(FPQNUM, le64_to_cpu(raw_desc->m0)) ? true : false;
+}
+
+static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+ int budget)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+ struct xgene_enet_raw_desc *raw_desc;
+ u16 head = ring->head;
+ u16 slots = ring->slots - 1;
+ int ret, count = 0;
+
+ do {
+ raw_desc = &ring->raw_desc[head];
+ if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
+ break;
+
+ if (is_rx_desc(raw_desc))
+ ret = xgene_enet_rx_frame(ring, raw_desc);
+ else
+ ret = xgene_enet_tx_completion(ring, raw_desc);
+ xgene_enet_mark_desc_slot_empty(raw_desc);
+
+ head = (head + 1) & slots;
+ count++;
+
+ if (ret)
+ break;
+ } while (--budget);
+
+ if (likely(count)) {
+ iowrite32(-count, ring->cmd);
+ ring->head = head;
+
+ if (netif_queue_stopped(ring->ndev)) {
+ if (xgene_enet_ring_len(ring) < pdata->cp_qcnt_low)
+ netif_wake_queue(ring->ndev);
+ }
+ }
+
+ return budget;
+}
+
+static int xgene_enet_napi(struct napi_struct *napi, const int budget)
+{
+ struct xgene_enet_desc_ring *ring;
+ int processed;
+
+ ring = container_of(napi, struct xgene_enet_desc_ring, napi);
+ processed = xgene_enet_process_ring(ring, budget);
+
+ if (processed != budget) {
+ napi_complete(napi);
+ enable_irq(ring->irq);
+ }
+
+ return processed;
+}
+
+static void xgene_enet_timeout(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+ xgene_gmac_reset(pdata);
+}
+
+static int xgene_enet_register_irq(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ int ret;
+
+ ret = devm_request_irq(dev, pdata->rx_ring->irq, xgene_enet_rx_irq,
+ IRQF_SHARED, ndev->name, pdata->rx_ring);
+ if (ret) {
+ netdev_err(ndev, "rx%d interrupt request failed\n",
+ pdata->rx_ring->irq);
+ }
+
+ return ret;
+}
+
+static void xgene_enet_free_irq(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+ devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
+}
+
+static int xgene_enet_open(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int ret;
+
+ xgene_gmac_tx_enable(pdata);
+ xgene_gmac_rx_enable(pdata);
+
+ ret = xgene_enet_register_irq(ndev);
+ if (ret)
+ return ret;
+ napi_enable(&pdata->rx_ring->napi);
+
+ if (pdata->phy_dev)
+ phy_start(pdata->phy_dev);
+
+ netif_start_queue(ndev);
+
+ return ret;
+}
+
+static int xgene_enet_close(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+
+ if (pdata->phy_dev)
+ phy_stop(pdata->phy_dev);
+
+ napi_disable(&pdata->rx_ring->napi);
+ xgene_enet_free_irq(ndev);
+ xgene_enet_process_ring(pdata->rx_ring, -1);
+
+ xgene_gmac_tx_disable(pdata);
+ xgene_gmac_rx_disable(pdata);
+
+ return 0;
+}
+
+static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
+{
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+
+ pdata = netdev_priv(ring->ndev);
+ dev = ndev_to_dev(ring->ndev);
+
+ xgene_enet_clear_ring(ring);
+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+}
+
+static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
+{
+ struct xgene_enet_desc_ring *buf_pool;
+
+ if (pdata->tx_ring) {
+ xgene_enet_delete_ring(pdata->tx_ring);
+ pdata->tx_ring = NULL;
+ }
+
+ if (pdata->rx_ring) {
+ buf_pool = pdata->rx_ring->buf_pool;
+ xgene_enet_delete_bufpool(buf_pool);
+ xgene_enet_delete_ring(buf_pool);
+ xgene_enet_delete_ring(pdata->rx_ring);
+ pdata->rx_ring = NULL;
+ }
+}
+
+static int xgene_enet_get_ring_size(struct device *dev,
+ enum xgene_enet_ring_cfgsize cfgsize)
+{
+ int size = -EINVAL;
+
+ switch (cfgsize) {
+ case RING_CFGSIZE_512B:
+ size = 0x200;
+ break;
+ case RING_CFGSIZE_2KB:
+ size = 0x800;
+ break;
+ case RING_CFGSIZE_16KB:
+ size = 0x4000;
+ break;
+ case RING_CFGSIZE_64KB:
+ size = 0x10000;
+ break;
+ case RING_CFGSIZE_512KB:
+ size = 0x80000;
+ break;
+ default:
+ dev_err(dev, "Unsupported cfg ring size %d\n", cfgsize);
+ break;
+ }
+
+ return size;
+}
+
+static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
+{
+ struct device *dev;
+
+ if (!ring)
+ return;
+
+ dev = ndev_to_dev(ring->ndev);
+
+ if (ring->desc_addr) {
+ xgene_enet_clear_ring(ring);
+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+ }
+ devm_kfree(dev, ring);
+}
+
+static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+ struct xgene_enet_desc_ring *ring;
+
+ ring = pdata->tx_ring;
+ if (ring && ring->cp_ring && ring->cp_ring->cp_skb)
+ devm_kfree(dev, ring->cp_ring->cp_skb);
+ xgene_enet_free_desc_ring(ring);
+
+ ring = pdata->rx_ring;
+ if (ring && ring->buf_pool && ring->buf_pool->rx_skb)
+ devm_kfree(dev, ring->buf_pool->rx_skb);
+ xgene_enet_free_desc_ring(ring->buf_pool);
+ xgene_enet_free_desc_ring(ring);
+}
+
+static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
+ struct net_device *ndev, u32 ring_num,
+ enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
+{
+ struct xgene_enet_desc_ring *ring;
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ u32 size;
+
+ ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring),
+ GFP_KERNEL);
+ if (!ring)
+ return NULL;
+
+ ring->ndev = ndev;
+ ring->num = ring_num;
+ ring->cfgsize = cfgsize;
+ ring->id = ring_id;
+
+ size = xgene_enet_get_ring_size(dev, cfgsize);
+ ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
+ GFP_KERNEL);
+ if (!ring->desc_addr) {
+ devm_kfree(dev, ring);
+ return NULL;
+ }
+ ring->size = size;
+
+ ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
+ ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
+ pdata->rm = RM3;
+ ring = xgene_enet_setup_ring(ring);
+ netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n",
+ ring->num, ring->size, ring->id, ring->slots);
+
+ return ring;
+}
+
+static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum)
+{
+ return (owner << 6) | (bufnum & GENMASK(5, 0));
+}
+
+static int xgene_enet_create_desc_rings(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
+ struct xgene_enet_desc_ring *buf_pool = NULL;
+ u8 cpu_bufnum = 0, eth_bufnum = 0;
+ u8 bp_bufnum = 0x20;
+ u16 ring_id, ring_num = 0;
+ int ret;
+
+ /* allocate rx descriptor ring */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
+ rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB, ring_id);
+ if (!rx_ring) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* allocate buffer pool for receiving packets */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++);
+ buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_2KB, ring_id);
+ if (!buf_pool) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ rx_ring->nbufpool = NUM_BUFPOOL;
+ rx_ring->buf_pool = buf_pool;
+ rx_ring->irq = pdata->rx_irq;
+ buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
+ sizeof(struct sk_buff *), GFP_KERNEL);
+ if (!buf_pool->rx_skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
+ rx_ring->buf_pool = buf_pool;
+ pdata->rx_ring = rx_ring;
+
+ /* allocate tx descriptor ring */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++);
+ tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB, ring_id);
+ if (!tx_ring) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ pdata->tx_ring = tx_ring;
+
+ cp_ring = pdata->rx_ring;
+ cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
+ sizeof(struct sk_buff *), GFP_KERNEL);
+ if (!cp_ring->cp_skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ pdata->tx_ring->cp_ring = cp_ring;
+ pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
+
+ pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
+ pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
+ pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
+
+ return 0;
+
+err:
+ xgene_enet_free_desc_rings(pdata);
+ return ret;
+}
+
+static struct rtnl_link_stats64 *xgene_enet_get_stats64(
+ struct net_device *ndev,
+ struct rtnl_link_stats64 *storage)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct rtnl_link_stats64 *stats = &pdata->stats;
+
+ stats->rx_errors += stats->rx_length_errors +
+ stats->rx_crc_errors +
+ stats->rx_frame_errors +
+ stats->rx_fifo_errors;
+ memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
+
+ return storage;
+}
+
+static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int ret;
+
+ ret = eth_mac_addr(ndev, addr);
+ if (ret)
+ return ret;
+ xgene_gmac_set_mac_addr(pdata);
+
+ return ret;
+}
+
+static const struct net_device_ops xgene_ndev_ops = {
+ .ndo_open = xgene_enet_open,
+ .ndo_stop = xgene_enet_close,
+ .ndo_start_xmit = xgene_enet_start_xmit,
+ .ndo_tx_timeout = xgene_enet_timeout,
+ .ndo_get_stats64 = xgene_enet_get_stats64,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = xgene_enet_set_mac_address,
+};
+
+static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+{
+ struct platform_device *pdev;
+ struct net_device *ndev;
+ struct device *dev;
+ struct resource *res;
+ void __iomem *base_addr;
+ const char *mac;
+ int ret;
+
+ pdev = pdata->pdev;
+ dev = &pdev->dev;
+ ndev = pdata->ndev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
+ if (!res) {
+ dev_err(dev, "Resource enet_csr not defined\n");
+ return -ENODEV;
+ }
+ pdata->base_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->base_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+ return PTR_ERR(pdata->base_addr);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
+ if (!res) {
+ dev_err(dev, "Resource ring_csr not defined\n");
+ return -ENODEV;
+ }
+ pdata->ring_csr_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->ring_csr_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Ring CSR region\n");
+ return PTR_ERR(pdata->ring_csr_addr);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
+ if (!res) {
+ dev_err(dev, "Resource ring_cmd not defined\n");
+ return -ENODEV;
+ }
+ pdata->ring_cmd_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->ring_cmd_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Ring command region\n");
+ return PTR_ERR(pdata->ring_cmd_addr);
+ }
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_err(dev, "Unable to get ENET Rx IRQ\n");
+ ret = ret ? : -ENXIO;
+ return ret;
+ }
+ pdata->rx_irq = ret;
+
+ mac = of_get_mac_address(dev->of_node);
+ if (mac)
+ memcpy(ndev->dev_addr, mac, ndev->addr_len);
+ else
+ eth_hw_addr_random(ndev);
+ memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+ pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+ if (pdata->phy_mode < 0) {
+ dev_err(dev, "Incorrect phy-connection-type in DTS\n");
+ return -EINVAL;
+ }
+
+ pdata->clk = devm_clk_get(&pdev->dev, NULL);
+ ret = IS_ERR(pdata->clk);
+ if (IS_ERR(pdata->clk)) {
+ dev_err(&pdev->dev, "can't get clock\n");
+ ret = PTR_ERR(pdata->clk);
+ return ret;
+ }
+
+ base_addr = pdata->base_addr;
+ pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
+ pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
+ pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
+ pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
+ pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
+ pdata->rx_buff_cnt = NUM_PKT_BUF;
+
+ return ret;
+}
+
+static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u16 dst_ring_num;
+ int ret;
+
+ xgene_gmac_tx_disable(pdata);
+ xgene_gmac_rx_disable(pdata);
+
+ ret = xgene_enet_create_desc_rings(ndev);
+ if (ret) {
+ netdev_err(ndev, "Error in ring configuration\n");
+ return ret;
+ }
+
+ /* setup buffer pool */
+ buf_pool = pdata->rx_ring->buf_pool;
+ xgene_enet_init_bufpool(buf_pool);
+ ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+ if (ret) {
+ xgene_enet_delete_desc_rings(pdata);
+ return ret;
+ }
+
+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
+ xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
+
+ return ret;
+}
+
+static int xgene_enet_probe(struct platform_device *pdev)
+{
+ struct net_device *ndev;
+ struct xgene_enet_pdata *pdata;
+ struct device *dev = &pdev->dev;
+ struct napi_struct *napi;
+ int ret;
+
+ ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
+ if (!ndev)
+ return -ENOMEM;
+
+ pdata = netdev_priv(ndev);
+
+ pdata->pdev = pdev;
+ pdata->ndev = ndev;
+ SET_NETDEV_DEV(ndev, dev);
+ platform_set_drvdata(pdev, pdata);
+ ndev->netdev_ops = &xgene_ndev_ops;
+ xgene_enet_set_ethtool_ops(ndev);
+ ndev->features |= NETIF_F_IP_CSUM |
+ NETIF_F_GSO |
+ NETIF_F_GRO;
+
+ ret = xgene_enet_get_resources(pdata);
+ if (ret)
+ goto err;
+
+ xgene_enet_reset(pdata);
+ xgene_gmac_init(pdata, SPEED_1000);
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ netdev_err(ndev, "Failed to register netdev\n");
+ goto err;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (ret) {
+ netdev_err(ndev, "No usable DMA configuration\n");
+ goto err;
+ }
+
+ ret = xgene_enet_init_hw(pdata);
+ if (ret)
+ goto err;
+
+ napi = &pdata->rx_ring->napi;
+ netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
+ ret = xgene_enet_mdio_config(pdata);
+
+ return ret;
+err:
+ free_netdev(ndev);
+ return ret;
+}
+
+static int xgene_enet_remove(struct platform_device *pdev)
+{
+ struct xgene_enet_pdata *pdata;
+ struct net_device *ndev;
+
+ pdata = platform_get_drvdata(pdev);
+ ndev = pdata->ndev;
+
+ xgene_gmac_rx_disable(pdata);
+ xgene_gmac_tx_disable(pdata);
+
+ netif_napi_del(&pdata->rx_ring->napi);
+ xgene_enet_mdio_remove(pdata);
+ xgene_enet_delete_desc_rings(pdata);
+ unregister_netdev(ndev);
+ xgene_gport_shutdown(pdata);
+ free_netdev(ndev);
+
+ return 0;
+}
+
+static struct of_device_id xgene_enet_match[] = {
+ {.compatible = "apm,xgene-enet",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_enet_match);
+
+static struct platform_driver xgene_enet_driver = {
+ .driver = {
+ .name = "xgene-enet",
+ .of_match_table = xgene_enet_match,
+ },
+ .probe = xgene_enet_probe,
+ .remove = xgene_enet_remove,
+};
+
+module_platform_driver(xgene_enet_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
+MODULE_VERSION(XGENE_DRV_VERSION);
+MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
new file mode 100644
index 000000000000..0815866986b0
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -0,0 +1,135 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_MAIN_H__
+#define __XGENE_ENET_MAIN_H__
+
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/prefetch.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include "xgene_enet_hw.h"
+
+#define XGENE_DRV_VERSION "v1.0"
+#define XGENE_ENET_MAX_MTU 1536
+#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
+#define NUM_PKT_BUF 64
+#define NUM_BUFPOOL 32
+
+/* software context of a descriptor ring */
+struct xgene_enet_desc_ring {
+ struct net_device *ndev;
+ u16 id;
+ u16 num;
+ u16 head;
+ u16 tail;
+ u16 slots;
+ u16 irq;
+ u32 size;
+ u32 state[NUM_RING_CONFIG];
+ void __iomem *cmd_base;
+ void __iomem *cmd;
+ dma_addr_t dma;
+ u16 dst_ring_num;
+ u8 nbufpool;
+ struct sk_buff *(*rx_skb);
+ struct sk_buff *(*cp_skb);
+ enum xgene_enet_ring_cfgsize cfgsize;
+ struct xgene_enet_desc_ring *cp_ring;
+ struct xgene_enet_desc_ring *buf_pool;
+ struct napi_struct napi;
+ union {
+ void *desc_addr;
+ struct xgene_enet_raw_desc *raw_desc;
+ struct xgene_enet_raw_desc16 *raw_desc16;
+ };
+};
+
+/* ethernet private data */
+struct xgene_enet_pdata {
+ struct net_device *ndev;
+ struct mii_bus *mdio_bus;
+ struct phy_device *phy_dev;
+ int phy_speed;
+ struct clk *clk;
+ struct platform_device *pdev;
+ struct xgene_enet_desc_ring *tx_ring;
+ struct xgene_enet_desc_ring *rx_ring;
+ char *dev_name;
+ u32 rx_buff_cnt;
+ u32 tx_qcnt_hi;
+ u32 cp_qcnt_hi;
+ u32 cp_qcnt_low;
+ u32 rx_irq;
+ void __iomem *eth_csr_addr;
+ void __iomem *eth_ring_if_addr;
+ void __iomem *eth_diag_csr_addr;
+ void __iomem *mcx_mac_addr;
+ void __iomem *mcx_stats_addr;
+ void __iomem *mcx_mac_csr_addr;
+ void __iomem *base_addr;
+ void __iomem *ring_csr_addr;
+ void __iomem *ring_cmd_addr;
+ u32 phy_addr;
+ int phy_mode;
+ u32 speed;
+ u16 rm;
+ struct rtnl_link_stats64 stats;
+};
+
+/* Set the specified value into a bit-field defined by its starting position
+ * and length within a single u64.
+ */
+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
+{
+ return (val & ((1ULL << len) - 1)) << pos;
+}
+
+#define SET_VAL(field, val) \
+ xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
+
+#define SET_BIT(field) \
+ xgene_enet_set_field_value(field ## _POS, 1, 1)
+
+/* Get the value from a bit-field defined by its starting position
+ * and length within the specified u64.
+ */
+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
+{
+ return (src >> pos) & ((1ULL << len) - 1);
+}
+
+#define GET_VAL(field, src) \
+ xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
+
+static inline struct device *ndev_to_dev(struct net_device *ndev)
+{
+ return ndev->dev.parent;
+}
+
+void xgene_enet_set_ethtool_ops(struct net_device *netdev);
+
+#endif /* __XGENE_ENET_MAIN_H__ */
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index ce455aed5a2f..3f9d4de8173c 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -739,7 +739,6 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv,
case GENET_POWER_PASSIVE:
/* Power down LED */
- bcmgenet_mii_reset(priv->dev);
if (priv->hw_params->flags & GENET_HAS_EXT) {
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= (EXT_PWR_DOWN_PHY |
@@ -779,7 +778,9 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
}
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
- bcmgenet_mii_reset(priv->dev);
+
+ if (mode == GENET_POWER_PASSIVE)
+ bcmgenet_mii_reset(priv->dev);
}
/* ioctl handle special commands that are not present in ethtool. */
@@ -1961,7 +1962,8 @@ static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
static int bcmgenet_wol_resume(struct bcmgenet_priv *priv)
{
/* From WOL-enabled suspend, switch to regular clock */
- clk_disable_unprepare(priv->clk_wol);
+ if (priv->wolopts)
+ clk_disable_unprepare(priv->clk_wol);
phy_init_hw(priv->phydev);
/* Speed settings must be restored */
@@ -2164,6 +2166,10 @@ static void bcmgenet_netif_stop(struct net_device *dev)
* disabled no new work will be scheduled.
*/
cancel_work_sync(&priv->bcmgenet_irq_work);
+
+ priv->old_pause = -1;
+ priv->old_link = -1;
+ priv->old_duplex = -1;
}
static int bcmgenet_close(struct net_device *dev)
@@ -2533,6 +2539,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv->pdev = pdev;
priv->version = (enum bcmgenet_version)of_id->data;
+ priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
+ if (IS_ERR(priv->clk))
+ dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
+
+ if (!IS_ERR(priv->clk))
+ clk_prepare_enable(priv->clk);
+
bcmgenet_set_hw_params(priv);
/* Mii wait queue */
@@ -2541,17 +2554,10 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv->rx_buf_len = RX_BUF_LENGTH;
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
- priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
- if (IS_ERR(priv->clk))
- dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
-
priv->clk_wol = devm_clk_get(&priv->pdev->dev, "enet-wol");
if (IS_ERR(priv->clk_wol))
dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
- if (!IS_ERR(priv->clk))
- clk_prepare_enable(priv->clk);
-
err = reset_umac(priv);
if (err)
goto err_clk_disable;
@@ -2611,6 +2617,8 @@ static int bcmgenet_suspend(struct device *d)
bcmgenet_netif_stop(dev);
+ phy_suspend(priv->phydev);
+
netif_device_detach(dev);
/* Disable MAC receive */
@@ -2661,9 +2669,7 @@ static int bcmgenet_resume(struct device *d)
if (ret)
goto out_clk_disable;
- if (priv->wolopts)
- ret = bcmgenet_wol_resume(priv);
-
+ ret = bcmgenet_wol_resume(priv);
if (ret)
goto out_clk_disable;
@@ -2678,6 +2684,9 @@ static int bcmgenet_resume(struct device *d)
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
}
+ if (priv->wolopts)
+ bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+
/* Disable RX/TX DMA and flush TX queues */
dma_ctrl = bcmgenet_dma_disable(priv);
@@ -2693,6 +2702,8 @@ static int bcmgenet_resume(struct device *d)
netif_device_attach(dev);
+ phy_resume(priv->phydev);
+
bcmgenet_netif_start(dev);
return 0;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 18961613d385..c88f7ae99636 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -129,7 +129,10 @@ static void bcmgenet_mii_setup(struct net_device *dev)
cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
}
- if (status_changed) {
+ if (!status_changed)
+ return;
+
+ if (phydev->link) {
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
CMD_HD_EN |
@@ -137,8 +140,9 @@ static void bcmgenet_mii_setup(struct net_device *dev)
reg |= cmd_bits;
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
- phy_print_status(phydev);
}
+
+ phy_print_status(phydev);
}
void bcmgenet_mii_reset(struct net_device *dev)
@@ -303,12 +307,12 @@ static int bcmgenet_mii_probe(struct net_device *dev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(dn)) {
+ if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
ret = of_phy_register_fixed_link(dn);
if (ret)
return ret;
- priv->phy_dn = dn;
+ priv->phy_dn = of_node_get(dn);
}
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0,
@@ -444,6 +448,7 @@ int bcmgenet_mii_init(struct net_device *dev)
return 0;
out:
+ of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus);
out_free:
kfree(priv->mii_bus->irq);
@@ -455,6 +460,7 @@ void bcmgenet_mii_exit(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
+ of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus);
kfree(priv->mii_bus->irq);
mdiobus_free(priv->mii_bus);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index c9b922cc3e67..d57282172ea5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -50,13 +50,13 @@
#include "cxgb4_uld.h"
#define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x09
-#define T4FW_VERSION_MICRO 0x17
+#define T4FW_VERSION_MINOR 0x0B
+#define T4FW_VERSION_MICRO 0x1B
#define T4FW_VERSION_BUILD 0x00
#define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x09
-#define T5FW_VERSION_MICRO 0x17
+#define T5FW_VERSION_MINOR 0x0B
+#define T5FW_VERSION_MICRO 0x1B
#define T5FW_VERSION_BUILD 0x00
#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@ -522,6 +522,9 @@ struct sge_txq {
struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
struct sge_txq q;
struct netdev_queue *txq; /* associated netdev TX queue */
+#ifdef CONFIG_CHELSIO_T4_DCB
+ u8 dcb_prio; /* DCB Priority bound to queue */
+#endif
unsigned long tso; /* # of TSO requests */
unsigned long tx_cso; /* # of Tx checksum offloads */
unsigned long vlan_ins; /* # of Tx VLAN insertions */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
index 0d3a9df5be36..8edf0f5bd679 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
@@ -20,6 +20,17 @@
#include "cxgb4.h"
+/* DCBx version control
+ */
+char *dcb_ver_array[] = {
+ "Unknown",
+ "DCBx-CIN",
+ "DCBx-CEE 1.01",
+ "DCBx-IEEE",
+ "", "", "",
+ "Auto Negotiated"
+};
+
/* Initialize a port's Data Center Bridging state. Typically used after a
* Link Down event.
*/
@@ -27,25 +38,45 @@ void cxgb4_dcb_state_init(struct net_device *dev)
{
struct port_info *pi = netdev2pinfo(dev);
struct port_dcb_info *dcb = &pi->dcb;
+ int version_temp = dcb->dcb_version;
memset(dcb, 0, sizeof(struct port_dcb_info));
dcb->state = CXGB4_DCB_STATE_START;
+ if (version_temp)
+ dcb->dcb_version = version_temp;
+
+ netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
+ __func__, pi->port_id);
+}
+
+void cxgb4_dcb_version_init(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+
+ /* Any writes here are only done on kernels that exlicitly need
+ * a specific version, say < 2.6.38 which only support CEE
+ */
+ dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
}
/* Finite State machine for Data Center Bridging.
*/
void cxgb4_dcb_state_fsm(struct net_device *dev,
- enum cxgb4_dcb_state_input input)
+ enum cxgb4_dcb_state_input transition_to)
{
struct port_info *pi = netdev2pinfo(dev);
struct port_dcb_info *dcb = &pi->dcb;
struct adapter *adap = pi->adapter;
+ enum cxgb4_dcb_state current_state = dcb->state;
- switch (input) {
- case CXGB4_DCB_INPUT_FW_DISABLED: {
- /* Firmware tells us it's not doing DCB */
- switch (dcb->state) {
- case CXGB4_DCB_STATE_START: {
+ netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
+ __func__, dcb->state, transition_to, dev->name);
+
+ switch (current_state) {
+ case CXGB4_DCB_STATE_START: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_DISABLED: {
/* we're going to use Host DCB */
dcb->state = CXGB4_DCB_STATE_HOST;
dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
@@ -53,48 +84,62 @@ void cxgb4_dcb_state_fsm(struct net_device *dev,
break;
}
- case CXGB4_DCB_STATE_HOST: {
- /* we're alreaady in Host DCB mode */
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're going to use Firmware DCB */
+ dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
+ dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+ /* expected transition */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
break;
}
default:
- goto bad_state_transition;
+ goto bad_state_input;
}
break;
}
- case CXGB4_DCB_INPUT_FW_ENABLED: {
- /* Firmware tells us that it is doing DCB */
- switch (dcb->state) {
- case CXGB4_DCB_STATE_START: {
- /* we're going to use Firmware DCB */
- dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
- dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+ case CXGB4_DCB_STATE_FW_INCOMPLETE: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're alreaady in firmware DCB mode */
break;
}
- case CXGB4_DCB_STATE_FW_INCOMPLETE:
- case CXGB4_DCB_STATE_FW_ALLSYNCED: {
- /* we're alreaady in firmware DCB mode */
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+ /* we're already incomplete */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+ dcb->enabled = 1;
+ linkwatch_fire_event(dev);
break;
}
default:
- goto bad_state_transition;
+ goto bad_state_input;
}
break;
}
- case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
- /* Firmware tells us that its DCB state is incomplete */
- switch (dcb->state) {
- case CXGB4_DCB_STATE_FW_INCOMPLETE: {
- /* we're already incomplete */
+ case CXGB4_DCB_STATE_FW_ALLSYNCED: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're alreaady in firmware DCB mode */
break;
}
- case CXGB4_DCB_STATE_FW_ALLSYNCED: {
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
/* We were successfully running with firmware DCB but
* now it's telling us that it's in an "incomplete
* state. We need to reset back to a ground state
@@ -107,46 +152,48 @@ void cxgb4_dcb_state_fsm(struct net_device *dev,
break;
}
- default:
- goto bad_state_transition;
- }
- break;
- }
-
- case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
- /* Firmware tells us that its DCB state is complete */
- switch (dcb->state) {
- case CXGB4_DCB_STATE_FW_INCOMPLETE: {
- dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ /* we're already all sync'ed
+ * this is only applicable for IEEE or
+ * when another VI already completed negotiaton
+ */
dcb->enabled = 1;
linkwatch_fire_event(dev);
break;
}
- case CXGB4_DCB_STATE_FW_ALLSYNCED: {
- /* we're already all sync'ed */
+ default:
+ goto bad_state_input;
+ }
+ break;
+ }
+
+ case CXGB4_DCB_STATE_HOST: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_DISABLED: {
+ /* we're alreaady in Host DCB mode */
break;
}
default:
- goto bad_state_transition;
+ goto bad_state_input;
}
break;
}
default:
- goto bad_state_input;
+ goto bad_state_transition;
}
return;
bad_state_input:
dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
- input);
+ transition_to);
return;
bad_state_transition:
dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
- dcb->state, input);
+ current_state, transition_to);
}
/* Handle a DCB/DCBX update message from the firmware.
@@ -160,6 +207,7 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap,
struct port_info *pi = netdev_priv(dev);
struct port_dcb_info *dcb = &pi->dcb;
int dcb_type = pcmd->u.dcb.pgid.type;
+ int dcb_running_version;
/* Handle Firmware DCB Control messages separately since they drive
* our state machine.
@@ -171,6 +219,25 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap,
? CXGB4_DCB_STATE_FW_ALLSYNCED
: CXGB4_DCB_STATE_FW_INCOMPLETE);
+ if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
+ dcb_running_version = FW_PORT_CMD_DCB_VERSION_GET(
+ be16_to_cpu(
+ pcmd->u.dcb.control.dcb_version_to_app_state));
+ if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
+ dcb_running_version == FW_PORT_DCB_VER_IEEE) {
+ dcb->dcb_version = dcb_running_version;
+ dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
+ dev->name,
+ dcb_ver_array[dcb->dcb_version]);
+ } else {
+ dev_warn(adap->pdev_dev,
+ "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
+ dcb_ver_array[dcb->dcb_version],
+ dcb_ver_array[dcb_running_version]);
+ dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
+ }
+ }
+
cxgb4_dcb_state_fsm(dev, input);
return;
}
@@ -199,7 +266,11 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap,
dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
sizeof(dcb->pgrate));
+ memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
+ sizeof(dcb->tsa));
dcb->msgs |= CXGB4_DCB_FW_PGRATE;
+ if (dcb->msgs & CXGB4_DCB_FW_PGID)
+ IEEE_FAUX_SYNC(dev, dcb);
break;
case FW_PORT_DCB_TYPE_PRIORATE:
@@ -212,6 +283,7 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap,
dcb->pfcen = fwdcb->pfc.pfcen;
dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
dcb->msgs |= CXGB4_DCB_FW_PFC;
+ IEEE_FAUX_SYNC(dev, dcb);
break;
case FW_PORT_DCB_TYPE_APP_ID: {
@@ -220,13 +292,25 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap,
struct app_priority *ap = &dcb->app_priority[idx];
struct dcb_app app = {
- .selector = fwap->sel_field,
.protocol = be16_to_cpu(fwap->protocolid),
- .priority = fwap->user_prio_map,
};
int err;
- err = dcb_setapp(dev, &app);
+ /* Convert from firmware format to relevant format
+ * when using app selector
+ */
+ if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
+ app.selector = (fwap->sel_field + 1);
+ app.priority = ffs(fwap->user_prio_map) - 1;
+ err = dcb_ieee_setapp(dev, &app);
+ IEEE_FAUX_SYNC(dev, dcb);
+ } else {
+ /* Default is CEE */
+ app.selector = !!(fwap->sel_field);
+ app.priority = fwap->user_prio_map;
+ err = dcb_setapp(dev, &app);
+ }
+
if (err)
dev_err(adap->pdev_dev,
"Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
@@ -408,9 +492,10 @@ static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
if (err != FW_PORT_DCB_CFG_SUCCESS) {
dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
-err);
- } else {
- *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
+ return;
}
+
+ *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
}
static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
@@ -637,7 +722,8 @@ static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
return err;
}
if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
- return pcmd.u.dcb.app_priority.user_prio_map;
+ if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
+ return pcmd.u.dcb.app_priority.user_prio_map;
/* exhausted app list */
if (!pcmd.u.dcb.app_priority.protocolid)
@@ -657,8 +743,8 @@ static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
/* Write a new Application User Priority Map for the specified Application ID
*/
-static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
- u8 app_prio)
+static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+ u8 app_prio)
{
struct fw_port_cmd pcmd;
struct port_info *pi = netdev2pinfo(dev);
@@ -673,10 +759,6 @@ static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
if (!netif_carrier_ok(dev))
return -ENOLINK;
- if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
- app_idtype != DCB_APP_IDTYPE_PORTNUM)
- return -EINVAL;
-
for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
@@ -725,6 +807,30 @@ static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
return 0;
}
+/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
+static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+ u8 app_prio)
+{
+ int ret;
+ struct dcb_app app = {
+ .selector = app_idtype,
+ .protocol = app_id,
+ .priority = app_prio,
+ };
+
+ if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
+ app_idtype != DCB_APP_IDTYPE_PORTNUM)
+ return -EINVAL;
+
+ /* Convert app_idtype to a format that firmware understands */
+ ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
+ app_idtype : 3, app_id, app_prio);
+ if (ret)
+ return ret;
+
+ return dcb_setapp(dev, &app);
+}
+
/* Return whether IEEE Data Center Bridging has been negotiated.
*/
static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
@@ -738,6 +844,7 @@ static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
/* Fill in the Application User Priority Map associated with the
* specified Application.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
*/
static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
{
@@ -748,28 +855,39 @@ static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
if (!(app->selector && app->protocol))
return -EINVAL;
- prio = dcb_getapp(dev, app);
- if (prio == 0) {
- /* If app doesn't exist in dcb_app table, try firmware
- * directly.
- */
- prio = __cxgb4_getapp(dev, app->selector, app->protocol, 0);
- }
+ /* Try querying firmware first, use firmware format */
+ prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
+
+ if (prio < 0)
+ prio = dcb_ieee_getapp_mask(dev, app);
- app->priority = prio;
+ app->priority = ffs(prio) - 1;
return 0;
}
-/* Write a new Application User Priority Map for the specified App id. */
+/* Write a new Application User Priority Map for the specified Application ID.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
+ */
static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
{
+ int ret;
+
if (!cxgb4_ieee_negotiation_complete(dev))
return -EINVAL;
- if (!(app->selector && app->protocol && app->priority))
+ if (!(app->selector && app->protocol))
+ return -EINVAL;
+
+ if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->selector < IEEE_8021QAZ_APP_SEL_ANY))
return -EINVAL;
- cxgb4_setapp(dev, app->selector, app->protocol, app->priority);
- return dcb_setapp(dev, app);
+ /* change selector to a format that firmware understands */
+ ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
+ (1 << app->priority));
+ if (ret)
+ return ret;
+
+ return dcb_ieee_setapp(dev, app);
}
/* Return our DCBX parameters.
@@ -794,8 +912,9 @@ static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
!= dcb_request)
return 1;
- /* Can't set DCBX capabilities if DCBX isn't enabled. */
- if (!pi->dcb.state)
+ /* Can't enable DCB if we haven't successfully negotiated it.
+ */
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
return 1;
/* There's currently no mechanism to allow for the firmware DCBX
@@ -874,7 +993,8 @@ static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
table[i].selector = pcmd.u.dcb.app_priority.sel_field;
table[i].protocol =
be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
- table[i].priority = pcmd.u.dcb.app_priority.user_prio_map;
+ table[i].priority =
+ ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
}
return err;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
index 1ec1d834e257..2a6aa88984f4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
@@ -63,6 +63,13 @@
#define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \
INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG)
+#define IEEE_FAUX_SYNC(__dev, __dcb) \
+ do { \
+ if ((__dcb)->dcb_version == FW_PORT_DCB_VER_IEEE) \
+ cxgb4_dcb_state_fsm((__dev), \
+ CXGB4_DCB_STATE_FW_ALLSYNCED); \
+ } while (0)
+
/* States we can be in for a port's Data Center Bridging.
*/
enum cxgb4_dcb_state {
@@ -108,11 +115,13 @@ struct port_dcb_info {
* Native Endian format).
*/
u32 pgid; /* Priority Group[0..7] */
+ u8 dcb_version; /* Running DCBx version */
u8 pfcen; /* Priority Flow Control[0..7] */
u8 pg_num_tcs_supported; /* max PG Traffic Classes */
u8 pfc_num_tcs_supported; /* max PFC Traffic Classes */
u8 pgrate[8]; /* Priority Group Rate[0..7] */
u8 priorate[8]; /* Priority Rate[0..7] */
+ u8 tsa[8]; /* TSA Algorithm[0..7] */
struct app_priority { /* Application Information */
u8 user_prio_map; /* Priority Map bitfield */
u8 sel_field; /* Protocol ID interpretation */
@@ -121,6 +130,7 @@ struct port_dcb_info {
};
void cxgb4_dcb_state_init(struct net_device *);
+void cxgb4_dcb_version_init(struct net_device *);
void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input);
void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *);
void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 1a162d21d8ac..a62d3f468c52 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -522,6 +522,8 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
dev_err(adap->pdev_dev,
"Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n",
enable ? "set" : "unset", pi->port_id, i, -err);
+ else
+ txq->dcb_prio = value;
}
}
#endif /* CONFIG_CHELSIO_T4_DCB */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index ff709e3b3e7e..0549170d7e2e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1629,6 +1629,14 @@ enum fw_port_l2cfg_ctlbf {
FW_PORT_L2_CTLBF_TXIPG = 0x20
};
+enum fw_port_dcb_versions {
+ FW_PORT_DCB_VER_UNKNOWN,
+ FW_PORT_DCB_VER_CEE1D0,
+ FW_PORT_DCB_VER_CEE1D01,
+ FW_PORT_DCB_VER_IEEE,
+ FW_PORT_DCB_VER_AUTO = 7
+};
+
enum fw_port_dcb_cfg {
FW_PORT_DCB_CFG_PG = 0x01,
FW_PORT_DCB_CFG_PFC = 0x02,
@@ -1709,6 +1717,7 @@ struct fw_port_cmd {
__u8 r10_lo[5];
__u8 num_tcs_supported;
__u8 pgrate[8];
+ __u8 tsa[8];
} pgrate;
struct fw_port_dcb_priorate {
__u8 type;
@@ -1735,7 +1744,7 @@ struct fw_port_cmd {
struct fw_port_dcb_control {
__u8 type;
__u8 all_syncd_pkd;
- __be16 pfc_state_to_app_state;
+ __be16 dcb_version_to_app_state;
__be32 r11;
__be64 r12;
} control;
@@ -1778,6 +1787,7 @@ struct fw_port_cmd {
#define FW_PORT_CMD_DCBXDIS (1U << 7)
#define FW_PORT_CMD_APPLY (1U << 7)
#define FW_PORT_CMD_ALL_SYNCD (1U << 7)
+#define FW_PORT_CMD_DCB_VERSION_GET(x) (((x) >> 8) & 0xf)
#define FW_PORT_CMD_PPPEN(x) ((x) << 31)
#define FW_PORT_CMD_TPSRC(x) ((x) << 28)
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 23084fb2090e..9b33057a9477 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -93,7 +93,7 @@ enum dm9000_type {
};
/* Structure/enum declaration ------------------------------- */
-typedef struct board_info {
+struct board_info {
void __iomem *io_addr; /* Register I/O base address */
void __iomem *io_data; /* Data I/O address */
@@ -141,7 +141,7 @@ typedef struct board_info {
u32 wake_state;
int ip_summed;
-} board_info_t;
+};
/* debug code */
@@ -151,7 +151,7 @@ typedef struct board_info {
} \
} while (0)
-static inline board_info_t *to_dm9000_board(struct net_device *dev)
+static inline struct board_info *to_dm9000_board(struct net_device *dev)
{
return netdev_priv(dev);
}
@@ -162,7 +162,7 @@ static inline board_info_t *to_dm9000_board(struct net_device *dev)
* Read a byte from I/O port
*/
static u8
-ior(board_info_t *db, int reg)
+ior(struct board_info *db, int reg)
{
writeb(reg, db->io_addr);
return readb(db->io_data);
@@ -173,14 +173,14 @@ ior(board_info_t *db, int reg)
*/
static void
-iow(board_info_t *db, int reg, int value)
+iow(struct board_info *db, int reg, int value)
{
writeb(reg, db->io_addr);
writeb(value, db->io_data);
}
static void
-dm9000_reset(board_info_t *db)
+dm9000_reset(struct board_info *db)
{
dev_dbg(db->dev, "resetting device\n");
@@ -272,7 +272,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
* Sleep, either by using msleep() or if we are suspending, then
* use mdelay() to sleep.
*/
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
+static void dm9000_msleep(struct board_info *db, unsigned int ms)
{
if (db->in_suspend || db->in_timeout)
mdelay(ms);
@@ -284,7 +284,7 @@ static void dm9000_msleep(board_info_t *db, unsigned int ms)
static int
dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned int reg_save;
int ret;
@@ -330,7 +330,7 @@ static void
dm9000_phy_write(struct net_device *dev,
int phyaddr_unused, int reg, int value)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned long reg_save;
@@ -408,7 +408,7 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
}
}
-static void dm9000_schedule_poll(board_info_t *db)
+static void dm9000_schedule_poll(struct board_info *db)
{
if (db->type == TYPE_DM9000E)
schedule_delayed_work(&db->phy_poll, HZ * 2);
@@ -416,7 +416,7 @@ static void dm9000_schedule_poll(board_info_t *db)
static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
if (!netif_running(dev))
return -EINVAL;
@@ -425,7 +425,7 @@ static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
}
static unsigned int
-dm9000_read_locked(board_info_t *db, int reg)
+dm9000_read_locked(struct board_info *db, int reg)
{
unsigned long flags;
unsigned int ret;
@@ -437,7 +437,7 @@ dm9000_read_locked(board_info_t *db, int reg)
return ret;
}
-static int dm9000_wait_eeprom(board_info_t *db)
+static int dm9000_wait_eeprom(struct board_info *db)
{
unsigned int status;
int timeout = 8; /* wait max 8msec */
@@ -474,7 +474,7 @@ static int dm9000_wait_eeprom(board_info_t *db)
* Read a word data from EEPROM
*/
static void
-dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
+dm9000_read_eeprom(struct board_info *db, int offset, u8 *to)
{
unsigned long flags;
@@ -514,7 +514,7 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
* Write a word data to SROM
*/
static void
-dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
+dm9000_write_eeprom(struct board_info *db, int offset, u8 *data)
{
unsigned long flags;
@@ -546,7 +546,7 @@ dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
static void dm9000_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
strlcpy(info->driver, CARDNAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
@@ -556,21 +556,21 @@ static void dm9000_get_drvinfo(struct net_device *dev,
static u32 dm9000_get_msglevel(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return dm->msg_enable;
}
static void dm9000_set_msglevel(struct net_device *dev, u32 value)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
dm->msg_enable = value;
}
static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
mii_ethtool_gset(&dm->mii, cmd);
return 0;
@@ -578,21 +578,21 @@ static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return mii_ethtool_sset(&dm->mii, cmd);
}
static int dm9000_nway_reset(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return mii_nway_restart(&dm->mii);
}
static int dm9000_set_features(struct net_device *dev,
netdev_features_t features)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
netdev_features_t changed = dev->features ^ features;
unsigned long flags;
@@ -608,7 +608,7 @@ static int dm9000_set_features(struct net_device *dev,
static u32 dm9000_get_link(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
u32 ret;
if (dm->flags & DM9000_PLATF_EXT_PHY)
@@ -629,7 +629,7 @@ static int dm9000_get_eeprom_len(struct net_device *dev)
static int dm9000_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int i;
@@ -653,7 +653,7 @@ static int dm9000_get_eeprom(struct net_device *dev,
static int dm9000_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int done;
@@ -691,7 +691,7 @@ static int dm9000_set_eeprom(struct net_device *dev,
static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
memset(w, 0, sizeof(struct ethtool_wolinfo));
@@ -702,7 +702,7 @@ static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
unsigned long flags;
u32 opts = w->wolopts;
u32 wcr = 0;
@@ -752,7 +752,7 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
.set_eeprom = dm9000_set_eeprom,
};
-static void dm9000_show_carrier(board_info_t *db,
+static void dm9000_show_carrier(struct board_info *db,
unsigned carrier, unsigned nsr)
{
int lpa;
@@ -775,7 +775,7 @@ static void
dm9000_poll_work(struct work_struct *w)
{
struct delayed_work *dw = to_delayed_work(w);
- board_info_t *db = container_of(dw, board_info_t, phy_poll);
+ struct board_info *db = container_of(dw, struct board_info, phy_poll);
struct net_device *ndev = db->ndev;
if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
@@ -843,7 +843,7 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type)
static void
dm9000_hash_table_unlocked(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
struct netdev_hw_addr *ha;
int i, oft;
u32 hash_val;
@@ -879,7 +879,7 @@ dm9000_hash_table_unlocked(struct net_device *dev)
static void
dm9000_hash_table(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&db->lock, flags);
@@ -888,13 +888,13 @@ dm9000_hash_table(struct net_device *dev)
}
static void
-dm9000_mask_interrupts(board_info_t *db)
+dm9000_mask_interrupts(struct board_info *db)
{
iow(db, DM9000_IMR, IMR_PAR);
}
static void
-dm9000_unmask_interrupts(board_info_t *db)
+dm9000_unmask_interrupts(struct board_info *db)
{
iow(db, DM9000_IMR, db->imr_all);
}
@@ -905,7 +905,7 @@ dm9000_unmask_interrupts(board_info_t *db)
static void
dm9000_init_dm9000(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned int imr;
unsigned int ncr;
@@ -970,7 +970,7 @@ dm9000_init_dm9000(struct net_device *dev)
/* Our watchdog timed out. Called by the networking layer */
static void dm9000_timeout(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
u8 reg_save;
unsigned long flags;
@@ -996,7 +996,7 @@ static void dm9000_send_packet(struct net_device *dev,
int ip_summed,
u16 pkt_len)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
/* The DM9000 is not smart enough to leave fragmented packets alone. */
if (dm->ip_summed != ip_summed) {
@@ -1023,7 +1023,7 @@ static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
dm9000_dbg(db, 3, "%s:\n", __func__);
@@ -1062,7 +1062,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
* receive the packet to upper layer, free the transmitted packet
*/
-static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
+static void dm9000_tx_done(struct net_device *dev, struct board_info *db)
{
int tx_status = ior(db, DM9000_NSR); /* Got TX status */
@@ -1094,7 +1094,7 @@ struct dm9000_rxhdr {
static void
dm9000_rx(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
@@ -1196,7 +1196,7 @@ dm9000_rx(struct net_device *dev)
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;
@@ -1246,7 +1246,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned nsr, wcr;
@@ -1296,7 +1296,7 @@ static void dm9000_poll_controller(struct net_device *dev)
static int
dm9000_open(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
@@ -1342,7 +1342,7 @@ dm9000_open(struct net_device *dev)
static void
dm9000_shutdown(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
@@ -1358,7 +1358,7 @@ dm9000_shutdown(struct net_device *dev)
static int
dm9000_stop(struct net_device *ndev)
{
- board_info_t *db = netdev_priv(ndev);
+ struct board_info *db = netdev_priv(ndev);
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -1681,7 +1681,7 @@ dm9000_drv_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
- board_info_t *db;
+ struct board_info *db;
if (ndev) {
db = netdev_priv(ndev);
@@ -1704,7 +1704,7 @@ dm9000_drv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
- board_info_t *db = netdev_priv(ndev);
+ struct board_info *db = netdev_priv(ndev);
if (ndev) {
if (netif_running(ndev)) {
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index bd53caf1c1eb..9f7fa644a397 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -310,6 +310,7 @@ struct fec_enet_private {
int mii_timeout;
uint phy_speed;
phy_interface_t phy_interface;
+ struct device_node *phy_node;
int link;
int full_duplex;
int speed;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 66fe1f672499..4f87dffcb9b2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -52,6 +52,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/regulator/consumer.h>
#include <linux/if_vlan.h>
@@ -1648,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev)
fep->phy_dev = NULL;
- /* check for attached phy */
- for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
- if ((fep->mii_bus->phy_mask & (1 << phy_id)))
- continue;
- if (fep->mii_bus->phy_map[phy_id] == NULL)
- continue;
- if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
- continue;
- if (dev_id--)
- continue;
- strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
- break;
- }
+ if (fep->phy_node) {
+ phy_dev = of_phy_connect(ndev, fep->phy_node,
+ &fec_enet_adjust_link, 0,
+ fep->phy_interface);
+ } else {
+ /* check for attached phy */
+ for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+ if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+ continue;
+ if (fep->mii_bus->phy_map[phy_id] == NULL)
+ continue;
+ if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+ continue;
+ if (dev_id--)
+ continue;
+ strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+ break;
+ }
- if (phy_id >= PHY_MAX_ADDR) {
- netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
- strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
- phy_id = 0;
+ if (phy_id >= PHY_MAX_ADDR) {
+ netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
+ strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+ phy_id = 0;
+ }
+
+ snprintf(phy_name, sizeof(phy_name),
+ PHY_ID_FMT, mdio_bus_id, phy_id);
+ phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
+ fep->phy_interface);
}
- snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
- phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
- fep->phy_interface);
if (IS_ERR(phy_dev)) {
netdev_err(ndev, "could not attach to PHY\n");
return PTR_ERR(phy_dev);
@@ -1707,6 +1716,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
+ struct device_node *node;
int err = -ENXIO, i;
/*
@@ -1774,7 +1784,15 @@ static int fec_enet_mii_init(struct platform_device *pdev)
for (i = 0; i < PHY_MAX_ADDR; i++)
fep->mii_bus->irq[i] = PHY_POLL;
- if (mdiobus_register(fep->mii_bus))
+ node = of_get_child_by_name(pdev->dev.of_node, "mdio");
+ if (node) {
+ err = of_mdiobus_register(fep->mii_bus, node);
+ of_node_put(node);
+ } else {
+ err = mdiobus_register(fep->mii_bus);
+ }
+
+ if (err)
goto err_out_free_mdio_irq;
mii_cnt++;
@@ -2527,6 +2545,7 @@ fec_probe(struct platform_device *pdev)
struct resource *r;
const struct of_device_id *of_id;
static int dev_id;
+ struct device_node *np = pdev->dev.of_node, *phy_node;
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
@@ -2566,6 +2585,18 @@ fec_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
+ phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (!phy_node && of_phy_is_fixed_link(np)) {
+ ret = of_phy_register_fixed_link(np);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "broken fixed-link specification\n");
+ goto failed_phy;
+ }
+ phy_node = of_node_get(np);
+ }
+ fep->phy_node = phy_node;
+
ret = of_get_phy_mode(pdev->dev.of_node);
if (ret < 0) {
pdata = dev_get_platdata(&pdev->dev);
@@ -2670,6 +2701,8 @@ failed_init:
failed_regulator:
fec_enet_clk_enable(ndev, false);
failed_clk:
+failed_phy:
+ of_node_put(phy_node);
failed_ioremap:
free_netdev(ndev);
@@ -2691,6 +2724,7 @@ fec_drv_remove(struct platform_device *pdev)
if (fep->ptp_clock)
ptp_clock_unregister(fep->ptp_clock);
fec_enet_clk_enable(ndev, false);
+ of_node_put(fep->phy_node);
free_netdev(ndev);
return 0;
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 9947765e90c5..ff55fbb20a75 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -1015,8 +1015,7 @@ mpc52xx_fec_remove(struct platform_device *op)
unregister_netdev(ndev);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
+ of_node_put(priv->phy_node);
priv->phy_node = NULL;
irq_dispose_mapping(ndev->irq);
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index cfaf17b70f3f..748fd24d3d9e 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1033,7 +1033,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- fpi->phy_node = ofdev->dev.of_node;
+ fpi->phy_node = of_node_get(ofdev->dev.of_node);
}
if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index a6cf40e62f3a..fb29d049f4e1 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -892,12 +892,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(np)) {
+ if (!priv->phy_node && of_phy_is_fixed_link(np)) {
err = of_phy_register_fixed_link(np);
if (err)
goto err_grp_init;
- priv->phy_node = np;
+ priv->phy_node = of_node_get(np);
}
/* Find the TBI PHY. If it's not there, we don't support SGMII */
@@ -1435,10 +1435,8 @@ register_fail:
unmap_group_regs(priv);
gfar_free_rx_queues(priv);
gfar_free_tx_queues(priv);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
- if (priv->tbi_node)
- of_node_put(priv->tbi_node);
+ of_node_put(priv->phy_node);
+ of_node_put(priv->tbi_node);
free_gfar_dev(priv);
return err;
}
@@ -1447,10 +1445,8 @@ static int gfar_remove(struct platform_device *ofdev)
{
struct gfar_private *priv = platform_get_drvdata(ofdev);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
- if (priv->tbi_node)
- of_node_put(priv->tbi_node);
+ of_node_put(priv->phy_node);
+ of_node_put(priv->tbi_node);
unregister_netdev(priv->ndev);
unmap_group_regs(priv);
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 8ceaf7a2660c..3cf0478b3728 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -3785,16 +3785,15 @@ static int ucc_geth_probe(struct platform_device* ofdev)
ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
- if (!ug_info->phy_node) {
- /* In the case of a fixed PHY, the DT node associated
+ if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
+ /*
+ * In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(np)) {
- err = of_phy_register_fixed_link(np);
- if (err)
- return err;
- }
- ug_info->phy_node = np;
+ err = of_phy_register_fixed_link(np);
+ if (err)
+ return err;
+ ug_info->phy_node = of_node_get(np);
}
/* Find the TBI PHY node. If it's not there, we don't support SGMII */
@@ -3862,8 +3861,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof(*ugeth));
- if (dev == NULL)
+ if (dev == NULL) {
+ of_node_put(ug_info->tbi_node);
+ of_node_put(ug_info->phy_node);
return -ENOMEM;
+ }
ugeth = netdev_priv(dev);
spin_lock_init(&ugeth->lock);
@@ -3897,6 +3899,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
pr_err("%s: Cannot register net device, aborting\n",
dev->name);
free_netdev(dev);
+ of_node_put(ug_info->tbi_node);
+ of_node_put(ug_info->phy_node);
return err;
}
@@ -3920,6 +3924,8 @@ static int ucc_geth_remove(struct platform_device* ofdev)
unregister_netdev(dev);
free_netdev(dev);
ucc_geth_memclean(ugeth);
+ of_node_put(ugeth->ug_info->tbi_node);
+ of_node_put(ugeth->ug_info->phy_node);
return 0;
}
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index cfe7a7431730..a7139f588ad2 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -99,23 +99,23 @@ static const struct ethtool_ops netdev_ethtool_ops;
/*
card type
*/
-typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
+enum cardtype { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
XXX10304, NEC, KME
-} cardtype_t;
+};
/*
driver specific data structure
*/
-typedef struct local_info_t {
+struct local_info {
struct pcmcia_device *p_dev;
long open_time;
uint tx_started:1;
uint tx_queue;
u_short tx_queue_len;
- cardtype_t cardtype;
+ enum cardtype cardtype;
u_short sent;
u_char __iomem *base;
-} local_info_t;
+};
#define MC_FILTERBREAK 64
@@ -232,13 +232,13 @@ static const struct net_device_ops fjn_netdev_ops = {
static int fmvj18x_probe(struct pcmcia_device *link)
{
- local_info_t *lp;
+ struct local_info *lp;
struct net_device *dev;
dev_dbg(&link->dev, "fmvj18x_attach()\n");
/* Make up a FMVJ18x specific data structure */
- dev = alloc_etherdev(sizeof(local_info_t));
+ dev = alloc_etherdev(sizeof(struct local_info));
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
@@ -327,10 +327,10 @@ static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
static int fmvj18x_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
int i, ret;
unsigned int ioaddr;
- cardtype_t cardtype;
+ enum cardtype cardtype;
char *card_name = "unknown";
u8 *buf;
size_t len;
@@ -584,7 +584,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
int i;
struct net_device *dev = link->priv;
unsigned int ioaddr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
/* Allocate a small memory window */
link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,7 +626,7 @@ static void fmvj18x_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
u_char __iomem *tmp;
dev_dbg(&link->dev, "fmvj18x_release\n");
@@ -711,7 +711,7 @@ module_pcmcia_driver(fmvj18x_cs_driver);
static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
{
struct net_device *dev = dev_id;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr;
unsigned short tx_stat, rx_stat;
@@ -772,7 +772,7 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
static void fjn_tx_timeout(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
@@ -802,7 +802,7 @@ static void fjn_tx_timeout(struct net_device *dev)
static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
short length = skb->len;
@@ -874,7 +874,7 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
static void fjn_reset(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
int i;
@@ -1058,7 +1058,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){
static int fjn_open(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
pr_debug("fjn_open('%s').\n", dev->name);
@@ -1083,7 +1083,7 @@ static int fjn_open(struct net_device *dev)
static int fjn_close(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
unsigned int ioaddr = dev->base_addr;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index dadd9a5f6323..c9f1d1b7ef37 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2969,14 +2969,14 @@ static int mvneta_probe(struct platform_device *pdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- phy_node = dn;
+ phy_node = of_node_get(dn);
}
phy_mode = of_get_phy_mode(dn);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy-mode\n");
err = -EINVAL;
- goto err_free_irq;
+ goto err_put_phy_node;
}
dev->tx_queue_len = MVNETA_MAX_TXD;
@@ -2992,7 +2992,7 @@ static int mvneta_probe(struct platform_device *pdev)
pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
err = PTR_ERR(pp->clk);
- goto err_free_irq;
+ goto err_put_phy_node;
}
clk_prepare_enable(pp->clk);
@@ -3071,6 +3071,8 @@ err_free_stats:
free_percpu(pp->stats);
err_clk:
clk_disable_unprepare(pp->clk);
+err_put_phy_node:
+ of_node_put(phy_node);
err_free_irq:
irq_dispose_mapping(dev->irq);
err_free_netdev:
@@ -3088,6 +3090,7 @@ static int mvneta_remove(struct platform_device *pdev)
clk_disable_unprepare(pp->clk);
free_percpu(pp->stats);
irq_dispose_mapping(dev->irq);
+ of_node_put(pp->phy_node);
free_netdev(dev);
return 0;
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index f3d5d79f1cd1..69c26f04d8ce 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -574,6 +574,7 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp,
/* save firmware version for ethtool */
strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+ mgp->fw_version[sizeof(mgp->fw_version) - 1] = '\0';
sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
&mgp->fw_ver_minor, &mgp->fw_ver_tiny);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index a848d2979722..3c2c2c7c1559 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -8,7 +8,7 @@ qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
qlcnic_83xx_init.o qlcnic_83xx_vnic.o \
- qlcnic_minidump.o qlcnic_sriov_common.o
+ qlcnic_sriov_common.o
qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o
diff --git a/drivers/net/ethernet/smsc/smsc911x.h b/drivers/net/ethernet/smsc/smsc911x.h
index 23953957fed8..54d648920a1b 100644
--- a/drivers/net/ethernet/smsc/smsc911x.h
+++ b/drivers/net/ethernet/smsc/smsc911x.h
@@ -51,7 +51,7 @@
#ifdef CONFIG_DEBUG_SPINLOCK
#define SMSC_ASSERT_MAC_LOCK(pdata) \
- WARN_ON(!spin_is_locked(&pdata->mac_lock))
+ WARN_ON_SMP(!spin_is_locked(&pdata->mac_lock))
#else
#define SMSC_ASSERT_MAC_LOCK(pdata) do {} while (0)
#endif /* CONFIG_DEBUG_SPINLOCK */
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 3809f4ec2820..f9bcf7aa88ca 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1130,6 +1130,7 @@ static int cpmac_probe(struct platform_device *pdev)
strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
}
+ mdio_bus_id[sizeof(mdio_bus_id) - 1] = '\0';
dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
if (!dev)
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 8a6e5c2d6f95..36f4459520c3 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1148,8 +1148,7 @@ static int temac_of_remove(struct platform_device *op)
temac_mdio_teardown(lp);
unregister_netdev(ndev);
sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
lp->phy_node = NULL;
iounmap(lp->regs);
if (lp->sdma_regs)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 7b0a73556264..30e8608ff050 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1630,8 +1630,7 @@ static int axienet_of_remove(struct platform_device *op)
axienet_mdio_teardown(lp);
unregister_netdev(ndev);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
lp->phy_node = NULL;
iounmap(lp->regs);
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index 7c81ffb861e8..d56f8693202b 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -266,7 +266,7 @@ static void xirc2ps_detach(struct pcmcia_device *p_dev);
static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
-typedef struct local_info_t {
+struct local_info {
struct net_device *dev;
struct pcmcia_device *p_dev;
@@ -281,7 +281,7 @@ typedef struct local_info_t {
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
struct work_struct tx_timeout_task;
-} local_info_t;
+};
/****************
* Some more prototypes
@@ -475,12 +475,12 @@ static int
xirc2ps_probe(struct pcmcia_device *link)
{
struct net_device *dev;
- local_info_t *local;
+ struct local_info *local;
dev_dbg(&link->dev, "attach()\n");
/* Allocate the device structure */
- dev = alloc_etherdev(sizeof(local_info_t));
+ dev = alloc_etherdev(sizeof(struct local_info));
if (!dev)
return -ENOMEM;
local = netdev_priv(dev);
@@ -536,7 +536,7 @@ static int
set_card_type(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
u8 *buf;
unsigned int cisrev, mediaid, prodid;
size_t len;
@@ -690,7 +690,7 @@ static int
xirc2ps_config(struct pcmcia_device * link)
{
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr;
int err;
u8 *buf;
@@ -931,7 +931,7 @@ xirc2ps_release(struct pcmcia_device *link)
if (link->resource[2]->end) {
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
if (local->dingo)
iounmap(local->dingo_ccr - 0x0800);
}
@@ -975,7 +975,7 @@ static irqreturn_t
xirc2ps_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr;
u_char saved_page;
unsigned bytes_rcvd;
@@ -1194,8 +1194,8 @@ xirc2ps_interrupt(int irq, void *dev_id)
static void
xirc2ps_tx_timeout_task(struct work_struct *work)
{
- local_info_t *local =
- container_of(work, local_info_t, tx_timeout_task);
+ struct local_info *local =
+ container_of(work, struct local_info, tx_timeout_task);
struct net_device *dev = local->dev;
/* reset the card */
do_reset(dev,1);
@@ -1206,7 +1206,7 @@ xirc2ps_tx_timeout_task(struct work_struct *work)
static void
xirc_tx_timeout(struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
dev->stats.tx_errors++;
netdev_notice(dev, "transmit timed out\n");
schedule_work(&lp->tx_timeout_task);
@@ -1215,7 +1215,7 @@ xirc_tx_timeout(struct net_device *dev)
static netdev_tx_t
do_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
int okay;
unsigned freespace;
@@ -1300,7 +1300,7 @@ static void set_address(struct set_address_info *sa_info, char *addr)
static void set_addresses(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
struct set_address_info sa_info;
int i;
@@ -1362,7 +1362,7 @@ set_multicast_list(struct net_device *dev)
static int
do_config(struct net_device *dev, struct ifmap *map)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
pr_debug("do_config(%p)\n", dev);
if (map->port != 255 && map->port != dev->if_port) {
@@ -1387,7 +1387,7 @@ do_config(struct net_device *dev, struct ifmap *map)
static int
do_open(struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
dev_dbg(&link->dev, "do_open(%p)\n", dev);
@@ -1421,7 +1421,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static int
do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
struct mii_ioctl_data *data = if_mii(rq);
@@ -1453,7 +1453,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static void
hardreset(struct net_device *dev)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
SelectPage(4);
@@ -1470,7 +1470,7 @@ hardreset(struct net_device *dev)
static void
do_reset(struct net_device *dev, int full)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
unsigned value;
@@ -1631,7 +1631,7 @@ do_reset(struct net_device *dev, int full)
static int
init_mii(struct net_device *dev)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
unsigned control, status, linkpartner;
int i;
@@ -1715,7 +1715,7 @@ static int
do_stop(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
dev_dbg(&link->dev, "do_stop(%p)\n", dev);
OpenPOWER on IntegriCloud