14796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok/* 24796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Dave DNET Ethernet Controller driver 34796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * 44796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Copyright (C) 2008 Dave S.r.l. <www.dave.eu> 54796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> 64796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * 74796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * This program is free software; you can redistribute it and/or modify 84796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * it under the terms of the GNU General Public License version 2 as 94796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * published by the Free Software Foundation. 104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 11142071b83426674ef2dab98cf2a6627328d0988eGeert Uytterhoeven#include <linux/io.h> 124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/module.h> 134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/moduleparam.h> 144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/kernel.h> 154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/types.h> 164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/slab.h> 174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/delay.h> 184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/init.h> 19a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h> 204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/netdevice.h> 214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/etherdevice.h> 224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/dma-mapping.h> 234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/platform_device.h> 244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include <linux/phy.h> 254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#include "dnet.h" 274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#undef DEBUG 294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok/* function for reading internal MAC register */ 3135f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrisonstatic u16 dnet_readw_mac(struct dnet *bp, u16 reg) 324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 data_read; 344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* issue a read */ 364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, reg, MACREG_ADDR); 374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* since a read/write op to the MAC is very slow, 394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * we must wait before reading the data */ 404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ndelay(500); 414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* read data read from the MAC register */ 434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok data_read = dnet_readl(bp, MACREG_DATA); 444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* all done */ 464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return data_read; 474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok/* function for writing internal MAC register */ 5035f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrisonstatic void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) 514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* load data to write */ 534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, val, MACREG_DATA); 544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* issue a write */ 564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR); 574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* since a read/write op to the MAC is very slow, 594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * we must wait before exiting */ 604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ndelay(500); 614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void __dnet_set_hwaddr(struct dnet *bp) 644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 tmp; 664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6735f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr); 684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); 6935f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2)); 704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); 7135f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4)); 724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); 734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void __devinit dnet_get_hwaddr(struct dnet *bp) 764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 tmp; 784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u8 addr[6]; 794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * from MAC docs: 824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * "Note that the MAC address is stored in the registers in Hexadecimal 834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * form. For example, to set the MAC Address to: AC-DE-48-00-00-80 844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * would require writing 0xAC (octet 0) to address 0x0B (high byte of 854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of 864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of 874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of 884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of 894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of 904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * Mac_addr[15:0]). 914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG); 9335f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison *((__be16 *)addr) = cpu_to_be16(tmp); 944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG); 9535f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison *((__be16 *)(addr + 2)) = cpu_to_be16(tmp); 964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG); 9735f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrison *((__be16 *)(addr + 4)) = cpu_to_be16(tmp); 984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (is_valid_ether_addr(addr)) 1004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok memcpy(bp->dev->dev_addr, addr, sizeof(addr)); 1014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 1024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 1044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 1054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = bus->priv; 1064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 value; 1074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) 1094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok & DNET_INTERNAL_GMII_MNG_CMD_FIN)) 1104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok cpu_relax(); 1114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* only 5 bits allowed for phy-addr and reg_offset */ 1134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mii_id &= 0x1f; 1144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok regnum &= 0x1f; 1154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* prepare reg_value for a read */ 1174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok value = (mii_id << 8); 1184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok value |= regnum; 1194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* write control word */ 1214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value); 1224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* wait for end of transfer */ 1244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) 1254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok & DNET_INTERNAL_GMII_MNG_CMD_FIN)) 1264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok cpu_relax(); 1274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG); 1294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value); 1314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return value; 1334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 1344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, 1364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 value) 1374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 1384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = bus->priv; 1394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u16 tmp; 1404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value); 1424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) 1444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok & DNET_INTERNAL_GMII_MNG_CMD_FIN)) 1454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok cpu_relax(); 1464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* prepare for a write operation */ 1484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp = (1 << 13); 1494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* only 5 bits allowed for phy-addr and reg_offset */ 1514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mii_id &= 0x1f; 1524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok regnum &= 0x1f; 1534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* only 16 bits on data */ 1554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok value &= 0xffff; 1564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* prepare reg_value for a write */ 1584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp |= (mii_id << 8); 1594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tmp |= regnum; 1604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* write data to write first */ 1624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value); 1634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* write control word */ 1654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp); 1664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) 1684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok & DNET_INTERNAL_GMII_MNG_CMD_FIN)) 1694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok cpu_relax(); 1704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 1724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 1734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_mdio_reset(struct mii_bus *bus) 1754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 1764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 1774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 1784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void dnet_handle_link_change(struct net_device *dev) 1804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 1814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 1824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev = bp->phy_dev; 1834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned long flags; 1844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 mode_reg, ctl_reg; 1854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int status_change = 0; 1874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_lock_irqsave(&bp->lock, flags); 1894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG); 1914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); 1924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 1934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (phydev->link) { 1944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->duplex != phydev->duplex) { 1954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (phydev->duplex) 1964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ctl_reg &= 1974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP); 1984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok else 1994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ctl_reg |= 2004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP; 2014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->duplex = phydev->duplex; 2034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok status_change = 1; 2044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->speed != phydev->speed) { 2074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok status_change = 1; 2084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok switch (phydev->speed) { 2094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok case 1000: 2104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mode_reg |= DNET_INTERNAL_MODE_GBITEN; 2114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok break; 2124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok case 100: 2134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok case 10: 2144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mode_reg &= ~DNET_INTERNAL_MODE_GBITEN; 2154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok break; 2164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok default: 2174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_WARNING 2184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "%s: Ack! Speed (%d) is not " 2194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "10/100/1000!\n", dev->name, 2204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev->speed); 2214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok break; 2224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->speed = phydev->speed; 2244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (phydev->link != bp->link) { 2284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (phydev->link) { 2294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mode_reg |= 2304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN); 2314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } else { 2324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mode_reg &= 2334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ~(DNET_INTERNAL_MODE_RXEN | 2344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTERNAL_MODE_TXEN); 2354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->speed = 0; 2364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->duplex = -1; 2374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->link = phydev->link; 2394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok status_change = 1; 2414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (status_change) { 2444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg); 2454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg); 2464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_unlock_irqrestore(&bp->lock, flags); 2494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (status_change) { 2514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (phydev->link) 2524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_INFO "%s: link up (%d/%s)\n", 2534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->name, phydev->speed, 2544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); 2554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok else 2564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_INFO "%s: link down\n", dev->name); 2574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 2594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_mii_probe(struct net_device *dev) 2614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 2624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 2634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev = NULL; 2644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int phy_addr; 2654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* find the first phy */ 2674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { 2684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->mii_bus->phy_map[phy_addr]) { 2694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev = bp->mii_bus->phy_map[phy_addr]; 2704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok break; 2714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!phydev) { 2754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_ERR "%s: no PHY found\n", dev->name); 2764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -ENODEV; 2774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* TODO : add pin_irq */ 2804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* attach the mac to the phy */ 2824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->capabilities & DNET_HAS_RMII) { 2836580f57d485f70851218813fa053d971915f61fbStephen Rothwell phydev = phy_connect(dev, dev_name(&phydev->dev), 2844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok &dnet_handle_link_change, 0, 2854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok PHY_INTERFACE_MODE_RMII); 2864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } else { 2876580f57d485f70851218813fa053d971915f61fbStephen Rothwell phydev = phy_connect(dev, dev_name(&phydev->dev), 2884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok &dnet_handle_link_change, 0, 2894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok PHY_INTERFACE_MODE_MII); 2904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (IS_ERR(phydev)) { 2934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); 2944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return PTR_ERR(phydev); 2954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 2964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 2974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* mask with MAC supported features */ 2984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->capabilities & DNET_HAS_GIGABIT) 2994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev->supported &= PHY_GBIT_FEATURES; 3004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok else 3014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev->supported &= PHY_BASIC_FEATURES; 3024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause; 3044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev->advertising = phydev->supported; 3064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->link = 0; 3084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->speed = 0; 3094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->duplex = -1; 3104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->phy_dev = phydev; 3114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 3134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 3144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_mii_init(struct dnet *bp) 3164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 3174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int err, i; 3184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus = mdiobus_alloc(); 3204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->mii_bus == NULL) 3214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -ENOMEM; 3224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->name = "dnet_mii_bus"; 3244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->read = &dnet_mdio_read; 3254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->write = &dnet_mdio_write; 3264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->reset = &dnet_mdio_reset; 3274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 32863f678301fb952c2d758d9ded4ed88c1da6c0c50Florian Fainelli snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 32963f678301fb952c2d758d9ded4ed88c1da6c0c50Florian Fainelli bp->pdev->name, bp->pdev->id); 3304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->priv = bp; 3324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 3344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!bp->mii_bus->irq) { 3354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -ENOMEM; 3364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out; 3374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 3384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (i = 0; i < PHY_MAX_ADDR; i++) 3404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->mii_bus->irq[i] = PHY_POLL; 3414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (mdiobus_register(bp->mii_bus)) { 3434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -ENXIO; 3444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_free_mdio_irq; 3454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 3464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (dnet_mii_probe(bp->dev) != 0) { 3484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -ENXIO; 3494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_unregister_bus; 3504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 3514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 3534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_unregister_bus: 3554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mdiobus_unregister(bp->mii_bus); 3564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_free_mdio_irq: 3574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok kfree(bp->mii_bus->irq); 3584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out: 3594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mdiobus_free(bp->mii_bus); 3604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return err; 3614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 3624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok/* For Neptune board: LINK1000 as Link LED and TX as activity LED */ 36435f2516f0a1f9dddb339849c7a07e089322c18c3Harvey Harrisonstatic int dnet_phy_marvell_fixup(struct phy_device *phydev) 3654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 3664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return phy_write(phydev, 0x18, 0x4148); 3674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 3684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void dnet_update_stats(struct dnet *bp) 3704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 3714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT; 3724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 *p = &bp->hw_stats.rx_pkt_ignr; 3734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 *end = &bp->hw_stats.rx_byte + 1; 3744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok WARN_ON((unsigned long)(end - p - 1) != 3764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4); 3774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (; p < end; p++, reg++) 3794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok *p += readl(reg); 3804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok reg = bp->regs + DNET_TX_UNICAST_CNT; 3824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok p = &bp->hw_stats.tx_unicast; 3834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok end = &bp->hw_stats.tx_byte + 1; 3844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok WARN_ON((unsigned long)(end - p - 1) != 3864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4); 3874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (; p < end; p++, reg++) 3894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok *p += readl(reg); 3904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 3914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 3924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_poll(struct napi_struct *napi, int budget) 3934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 3944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = container_of(napi, struct dnet, napi); 3954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct net_device *dev = bp->dev; 3964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int npackets = 0; 3974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int pkt_len; 3984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct sk_buff *skb; 3994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int *data_ptr; 4004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 int_enable; 4014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 cmd_word; 4024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int i; 4034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok while (npackets < budget) { 4054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 4064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * break out of while loop if there are no more 4074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * packets waiting 4084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 4094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { 4109fae6c3f648e38f023b99b5f5a5280907b2e796eIlya Yanok napi_complete(napi); 4114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable = dnet_readl(bp, INTR_ENB); 4124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; 4134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, int_enable, INTR_ENB); 4144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 4154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 4164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok cmd_word = dnet_readl(bp, RX_LEN_FIFO); 4184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pkt_len = cmd_word & 0xFFFF; 4194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (cmd_word & 0xDF180000) 4214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_ERR "%s packet receive error %x\n", 4224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok __func__, cmd_word); 4234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 42421a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi skb = netdev_alloc_skb(dev, pkt_len + 5); 4254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (skb != NULL) { 4264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* Align IP on 16 byte boundaries */ 4274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok skb_reserve(skb, 2); 4284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 4294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * 'skb_put()' points to the start of sk_buff 4304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * data area. 4314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 4324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok data_ptr = (unsigned int *)skb_put(skb, pkt_len); 4334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (i = 0; i < (pkt_len + 3) >> 2; i++) 4344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok *data_ptr++ = dnet_readl(bp, RX_DATA_FIFO); 4354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok skb->protocol = eth_type_trans(skb, dev); 4364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_receive_skb(skb); 4374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok npackets++; 4384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } else 4394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_NOTICE 4404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "%s: No memory to allocate a sk_buff of " 4414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "size %u.\n", dev->name, pkt_len); 4424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 4434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok budget -= npackets; 4454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (npackets < budget) { 4474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* We processed all packets available. Tell NAPI it can 4484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * stop polling then re-enable rx interrupts */ 4499fae6c3f648e38f023b99b5f5a5280907b2e796eIlya Yanok napi_complete(napi); 4504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable = dnet_readl(bp, INTR_ENB); 4514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; 4524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, int_enable, INTR_ENB); 4534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 4544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 4554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* There are still packets waiting */ 4574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 1; 4584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 4594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic irqreturn_t dnet_interrupt(int irq, void *dev_id) 4614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 4624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct net_device *dev = dev_id; 4634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 4644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 int_src, int_enable, int_current; 4654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned long flags; 4664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int handled = 0; 4674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_lock_irqsave(&bp->lock, flags); 4694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* read and clear the DNET irq (clear on read) */ 4714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_src = dnet_readl(bp, INTR_SRC); 4724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable = dnet_readl(bp, INTR_ENB); 4734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_current = int_src & int_enable; 4744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* restart the queue if we had stopped it for TX fifo almost full */ 4764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (int_current & DNET_INTR_SRC_TX_FIFOAE) { 4774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable = dnet_readl(bp, INTR_ENB); 4784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable &= ~DNET_INTR_ENB_TX_FIFOAE; 4794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, int_enable, INTR_ENB); 4804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_wake_queue(dev); 4814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok handled = 1; 4824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 4834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* RX FIFO error checking */ 4854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (int_current & 4864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) { 4874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__, 4884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_readl(bp, RX_STATUS), int_current); 4894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* we can only flush the RX FIFOs */ 4904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL); 4914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ndelay(500); 4924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, 0, SYS_CTL); 4934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok handled = 1; 4944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 4954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 4964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* TX FIFO error checking */ 4974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (int_current & 4984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) { 4994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__, 5004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_readl(bp, TX_STATUS), int_current); 5014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* we can only flush the TX FIFOs */ 5024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL); 5034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok ndelay(500); 5044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, 0, SYS_CTL); 5054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok handled = 1; 5064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 5074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { 5099fae6c3f648e38f023b99b5f5a5280907b2e796eIlya Yanok if (napi_schedule_prep(&bp->napi)) { 5104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 5114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * There's no point taking any more interrupts 5124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * until we have processed the buffers 5134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 5144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* Disable Rx interrupts and schedule NAPI poll */ 5154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable = dnet_readl(bp, INTR_ENB); 5164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; 5174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, int_enable, INTR_ENB); 5189fae6c3f648e38f023b99b5f5a5280907b2e796eIlya Yanok __napi_schedule(&bp->napi); 5194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 5204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok handled = 1; 5214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 5224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!handled) 5244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("%s: irq %x remains\n", __func__, int_current); 5254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_unlock_irqrestore(&bp->lock, flags); 5274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return IRQ_RETVAL(handled); 5294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 5304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#ifdef DEBUG 5324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic inline void dnet_print_skb(struct sk_buff *skb) 5334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 5344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int k; 5354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(KERN_DEBUG PFX "data:"); 5364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (k = 0; k < skb->len; k++) 5374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk(" %02x", (unsigned int)skb->data[k]); 5384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok printk("\n"); 5394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 5404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#else 5414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#define dnet_print_skb(skb) do {} while (0) 5424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok#endif 5434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 54461357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) 5454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 5464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 5484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 tx_status, irq_enable; 5494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int len, i, tx_cmd, wrsz; 5504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned long flags; 5514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int *bufp; 5524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tx_status = dnet_readl(bp, TX_STATUS); 5544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5552c5849ea38fdad477d72dcf1c8c4842db4b33aaeDavid S. Miller pr_debug("start_xmit: len %u head %p data %p\n", 5562c5849ea38fdad477d72dcf1c8c4842db4b33aaeDavid S. Miller skb->len, skb->head, skb->data); 5574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_print_skb(skb); 5584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* frame size (words) */ 5604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok len = (skb->len + 3) >> 2; 5614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_lock_irqsave(&bp->lock, flags); 5634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tx_status = dnet_readl(bp, TX_STATUS); 5654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5662c5849ea38fdad477d72dcf1c8c4842db4b33aaeDavid S. Miller bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL); 5674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok wrsz = (u32) skb->len + 3; 5682c5849ea38fdad477d72dcf1c8c4842db4b33aaeDavid S. Miller wrsz += ((unsigned long) skb->data) & 0x3; 5694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok wrsz >>= 2; 5702c5849ea38fdad477d72dcf1c8c4842db4b33aaeDavid S. Miller tx_cmd = ((((unsigned long)(skb->data)) & 0x03) << 16) | (u32) skb->len; 5714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* check if there is enough room for the current frame */ 5734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { 5744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok for (i = 0; i < wrsz; i++) 5754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, *bufp++, TX_DATA_FIFO); 5764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 5784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * inform MAC that a packet's written and ready to be 5794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * shipped out 5804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 5814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, tx_cmd, TX_LEN_FIFO); 5824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 5834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) { 5854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_stop_queue(dev); 5864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok tx_status = dnet_readl(bp, INTR_SRC); 5874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok irq_enable = dnet_readl(bp, INTR_ENB); 5884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok irq_enable |= DNET_INTR_ENB_TX_FIFOAE; 5894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, irq_enable, INTR_ENB); 5904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 5914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 592ff9b3078b918480a471b065c36133a144a531038Richard Cochran skb_tx_timestamp(skb); 593ff9b3078b918480a471b065c36133a144a531038Richard Cochran 5944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* free the buffer */ 5954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_kfree_skb(skb); 5964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_unlock_irqrestore(&bp->lock, flags); 5984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 5996ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 6004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 6014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void dnet_reset_hw(struct dnet *bp) 6034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 6044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* put ts_mac in IDLE state i.e. disable rx/tx */ 6054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN); 6064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 6084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * RX FIFO almost full threshold: only cmd FIFO almost full is 6094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * implemented for RX side 6104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 6114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH); 6124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* 6134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * TX FIFO almost empty threshold: only data FIFO almost empty 6144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok * is implemented for TX side 6154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok */ 6164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH); 6174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* flush rx/tx fifos */ 6194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH, 6204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok SYS_CTL); 6214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok msleep(1); 6224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, 0, SYS_CTL); 6234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 6244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void dnet_init_hw(struct dnet *bp) 6264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 6274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok u32 config; 6284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_reset_hw(bp); 6304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok __dnet_set_hwaddr(bp); 6314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); 6334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->dev->flags & IFF_PROMISC) 6354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* Copy All Frames */ 6364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC; 6374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!(bp->dev->flags & IFF_BROADCAST)) 6384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* No BroadCast */ 6394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST; 6404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE | 6424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST | 6434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL | 6444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS; 6454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config); 6474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* clear irq before enabling them */ 6494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok config = dnet_readl(bp, INTR_SRC); 6504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* enable RX/TX interrupt, recv packet ready interrupt */ 6524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY | 6534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR | 6544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL | 6554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM | 6564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok DNET_INTR_ENB_RX_PKTRDY, INTR_ENB); 6574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 6584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_open(struct net_device *dev) 6604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 6614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 6624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* if the phy is not yet register, retry later */ 6644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!bp->phy_dev) 6654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -EAGAIN; 6664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!is_valid_ether_addr(dev->dev_addr)) 6684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -EADDRNOTAVAIL; 6694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok napi_enable(&bp->napi); 6714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_init_hw(bp); 6724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phy_start_aneg(bp->phy_dev); 6744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* schedule a link state check */ 6764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phy_start(bp->phy_dev); 6774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_start_queue(dev); 6794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 6814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 6824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_close(struct net_device *dev) 6844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 6854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 6864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_stop_queue(dev); 6884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok napi_disable(&bp->napi); 6894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->phy_dev) 6914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phy_stop(bp->phy_dev); 6924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_reset_hw(bp); 6944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_carrier_off(dev); 6954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 6974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 6984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 6994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat) 7004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 7014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("%s\n", __func__); 7024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("----------------------------- RX statistics " 7034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "-------------------------------\n"); 7044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr); 7054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err); 7064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm); 7074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm); 7084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol); 7094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err); 7104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt); 7114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm); 7124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm); 7134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast); 7144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast); 7154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag); 7164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink); 7174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib); 7184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd); 7194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte); 7204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("----------------------------- TX statistics " 7214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "-------------------------------\n"); 7224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast); 7234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm); 7244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast); 7254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast); 7264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag); 7274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs); 7284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo); 7294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte); 7304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 7314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic struct net_device_stats *dnet_get_stats(struct net_device *dev) 7334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 7344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 7364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct net_device_stats *nstat = &dev->stats; 7374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet_stats *hwstat = &bp->hw_stats; 7384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* read stats from hardware */ 7404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_update_stats(bp); 7414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* Convert HW stats into netdevice stats */ 7434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_errors = (hwstat->rx_len_chk_err + 7444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_lng_frm + hwstat->rx_shrt_frm + 7454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* ignore IGP violation error 7464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_ipg_viol + */ 7474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_crc_err + 7484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_pre_shrink + 7494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_drib_nib + hwstat->rx_unsup_opcd); 7504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->tx_errors = hwstat->tx_bad_fcs; 7514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_length_errors = (hwstat->rx_len_chk_err + 7524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_lng_frm + 7534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->rx_shrt_frm + hwstat->rx_pre_shrink); 7544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_crc_errors = hwstat->rx_crc_err; 7554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib; 7564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_packets = hwstat->rx_ok_pkt; 7574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->tx_packets = (hwstat->tx_unicast + 7584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok hwstat->tx_multicast + hwstat->tx_brdcast); 7594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_bytes = hwstat->rx_byte; 7604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->tx_bytes = hwstat->tx_byte; 7614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->multicast = hwstat->rx_multicast; 7624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok nstat->rx_missed_errors = hwstat->rx_pkt_ignr; 7634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_print_pretty_hwstats(hwstat); 7654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return nstat; 7674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 7684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 7704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 7714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 7724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev = bp->phy_dev; 7734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!phydev) 7754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -ENODEV; 7764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return phy_ethtool_gset(phydev, cmd); 7784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 7794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 7814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 7824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 7834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev = bp->phy_dev; 7844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!phydev) 7864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -ENODEV; 7874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return phy_ethtool_sset(phydev, cmd); 7894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 7904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 7924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 7934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp = netdev_priv(dev); 7944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev = bp->phy_dev; 7954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!netif_running(dev)) 7974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -EINVAL; 7984796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 7994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!phydev) 8004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return -ENODEV; 8014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 80228b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran return phy_mii_ioctl(phydev, rq, cmd); 8034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 8044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic void dnet_get_drvinfo(struct net_device *dev, 8064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct ethtool_drvinfo *info) 8074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 80868aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 80968aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 81068aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->bus_info, "0", sizeof(info->bus_info)); 8114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 8124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic const struct ethtool_ops dnet_ethtool_ops = { 8144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .get_settings = dnet_get_settings, 8154796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .set_settings = dnet_set_settings, 8164796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .get_drvinfo = dnet_get_drvinfo, 8174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .get_link = ethtool_op_get_link, 8184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok}; 8194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic const struct net_device_ops dnet_netdev_ops = { 8214796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_open = dnet_open, 8224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_stop = dnet_close, 8234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_get_stats = dnet_get_stats, 8244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_start_xmit = dnet_start_xmit, 8254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_do_ioctl = dnet_ioctl, 8264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_set_mac_address = eth_mac_addr, 8274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_validate_addr = eth_validate_addr, 8284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .ndo_change_mtu = eth_change_mtu, 8294796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok}; 8304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int __devinit dnet_probe(struct platform_device *pdev) 8324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 8334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct resource *res; 8344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct net_device *dev; 8354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp; 8364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct phy_device *phydev; 8374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok int err = -ENXIO; 8384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unsigned int mem_base, mem_size, irq; 8394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8414796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!res) { 8424796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_err(&pdev->dev, "no mmio resource defined\n"); 8434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out; 8444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 8454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mem_base = res->start; 8464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mem_size = resource_size(res); 8474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok irq = platform_get_irq(pdev, 0); 8484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!request_mem_region(mem_base, mem_size, DRV_NAME)) { 8504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_err(&pdev->dev, "no memory region available\n"); 8514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -EBUSY; 8524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out; 8534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 8544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -ENOMEM; 8564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev = alloc_etherdev(sizeof(*bp)); 85741de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1Joe Perches if (!dev) 858de140b0d511ad86a5dd0888c9095ae030ada2e86Dan Carpenter goto err_out_release_mem; 8594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* TODO: Actually, we have some interesting features... */ 8614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->features |= 0; 8624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp = netdev_priv(dev); 8644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->dev = dev; 8654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 866b093dd96844186cd03318aaf0cd96f91db3970efIlya Yanok platform_set_drvdata(pdev, dev); 8674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok SET_NETDEV_DEV(dev, &pdev->dev); 8684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok spin_lock_init(&bp->lock); 8704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->regs = ioremap(mem_base, mem_size); 8724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!bp->regs) { 8734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_err(&pdev->dev, "failed to map registers, aborting.\n"); 8744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = -ENOMEM; 8754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_free_dev; 8764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 8774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->irq = irq; 8794796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev); 8804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (err) { 8814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", 8824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok irq, err); 8834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_iounmap; 8844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 8854796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8864796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->netdev_ops = &dnet_netdev_ops; 8874796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok netif_napi_add(dev, &bp->napi, dnet_poll, 64); 8884796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->ethtool_ops = &dnet_ethtool_ops; 8894796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8904796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev->base_addr = (unsigned long)bp->regs; 8914796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8924796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK; 8934796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8944796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_get_hwaddr(bp); 8954796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 8964796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (!is_valid_ether_addr(dev->dev_addr)) { 8974796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* choose a random ethernet address */ 898f2cedb63df14342ad40a8b5b324fc5d94a60b665Danny Kukawka eth_hw_addr_random(dev); 8994796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok __dnet_set_hwaddr(bp); 9004796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 9014796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9024796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = register_netdev(dev); 9034796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (err) { 9044796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); 9054796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_free_irq; 9064796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 9074796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9084796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* register the PHY board fixup (for Marvell 88E1111) */ 9094796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0, 9104796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dnet_phy_marvell_fixup); 9114796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok /* we can live without it, so just issue a warning */ 9124796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (err) 9134796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n"); 9144796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 915de140b0d511ad86a5dd0888c9095ae030ada2e86Dan Carpenter err = dnet_mii_init(bp); 916de140b0d511ad86a5dd0888c9095ae030ada2e86Dan Carpenter if (err) 9174796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok goto err_out_unregister_netdev; 9184796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9194796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n", 9204796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp->regs, mem_base, dev->irq, dev->dev_addr); 9212381a55c88453d3f29fe62d235579a05fc20b7b3Frans Pop dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma\n", 9224796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ", 9234796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ", 9244796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ", 9254796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok (bp->capabilities & DNET_HAS_DMA) ? "" : "no "); 9264796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phydev = bp->phy_dev; 9274796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev_info(&pdev->dev, "attached PHY driver [%s] " 9284796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "(mii_bus:phy_addr=%s, irq=%d)\n", 9296580f57d485f70851218813fa053d971915f61fbStephen Rothwell phydev->drv->name, dev_name(&phydev->dev), phydev->irq); 9304796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9314796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 9324796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9334796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_unregister_netdev: 9344796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unregister_netdev(dev); 9354796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_free_irq: 9364796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok free_irq(dev->irq, dev); 9374796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_iounmap: 9384796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok iounmap(bp->regs); 9394796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out_free_dev: 9404796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok free_netdev(dev); 941de140b0d511ad86a5dd0888c9095ae030ada2e86Dan Carpentererr_out_release_mem: 942de140b0d511ad86a5dd0888c9095ae030ada2e86Dan Carpenter release_mem_region(mem_base, mem_size); 9434796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokerr_out: 9444796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return err; 9454796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 9464796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9474796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic int __devexit dnet_remove(struct platform_device *pdev) 9484796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok{ 9494796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9504796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct net_device *dev; 9514796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok struct dnet *bp; 9524796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9534796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok dev = platform_get_drvdata(pdev); 9544796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9554796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (dev) { 9564796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok bp = netdev_priv(dev); 9574796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok if (bp->phy_dev) 9584796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok phy_disconnect(bp->phy_dev); 9594796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mdiobus_unregister(bp->mii_bus); 9604796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok kfree(bp->mii_bus->irq); 9614796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok mdiobus_free(bp->mii_bus); 9624796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok unregister_netdev(dev); 9634796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok free_irq(dev->irq, dev); 9644796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok iounmap(bp->regs); 9654796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok free_netdev(dev); 9664796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok } 9674796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9684796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok return 0; 9694796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok} 9704796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9714796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanokstatic struct platform_driver dnet_driver = { 9724796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .probe = dnet_probe, 9734796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .remove = __devexit_p(dnet_remove), 9744796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .driver = { 9754796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok .name = "dnet", 9764796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok }, 9774796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok}; 9784796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 979db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(dnet_driver); 9804796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok 9814796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya YanokMODULE_LICENSE("GPL"); 9824796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya YanokMODULE_DESCRIPTION("Dave DNET Ethernet driver"); 9834796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya YanokMODULE_AUTHOR("Ilya Yanok <yanok@emcraft.com>, " 9844796417417a62e2ae83d92cb92e1ecf9ec67b5f5Ilya Yanok "Matteo Vit <matteo.vit@dave.eu>"); 985