174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2baf0fbfeSJeff Kirsher /* 3baf0fbfeSJeff Kirsher * Faraday FTMAC100 10/100 Ethernet 4baf0fbfeSJeff Kirsher * 5baf0fbfeSJeff Kirsher * (C) Copyright 2009-2011 Faraday Technology 6baf0fbfeSJeff Kirsher * Po-Yu Chuang <ratbert@faraday-tech.com> 7baf0fbfeSJeff Kirsher */ 8baf0fbfeSJeff Kirsher 9baf0fbfeSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10baf0fbfeSJeff Kirsher 11baf0fbfeSJeff Kirsher #include <linux/dma-mapping.h> 12baf0fbfeSJeff Kirsher #include <linux/etherdevice.h> 13baf0fbfeSJeff Kirsher #include <linux/ethtool.h> 1437c84890SSergei Antonov #include <linux/if_ether.h> 1530f837b7SVladimir Oltean #include <linux/if_vlan.h> 16baf0fbfeSJeff Kirsher #include <linux/init.h> 1717f1bbcaSThomas Faber #include <linux/interrupt.h> 18baf0fbfeSJeff Kirsher #include <linux/io.h> 19baf0fbfeSJeff Kirsher #include <linux/mii.h> 20baf0fbfeSJeff Kirsher #include <linux/module.h> 21ac316725SRandy Dunlap #include <linux/mod_devicetable.h> 22baf0fbfeSJeff Kirsher #include <linux/netdevice.h> 23baf0fbfeSJeff Kirsher #include <linux/platform_device.h> 24baf0fbfeSJeff Kirsher 25baf0fbfeSJeff Kirsher #include "ftmac100.h" 26baf0fbfeSJeff Kirsher 27baf0fbfeSJeff Kirsher #define DRV_NAME "ftmac100" 28baf0fbfeSJeff Kirsher 29baf0fbfeSJeff Kirsher #define RX_QUEUE_ENTRIES 128 /* must be power of 2 */ 30baf0fbfeSJeff Kirsher #define TX_QUEUE_ENTRIES 16 /* must be power of 2 */ 31baf0fbfeSJeff Kirsher 32baf0fbfeSJeff Kirsher #define RX_BUF_SIZE 2044 /* must be smaller than 0x7ff */ 3337c84890SSergei Antonov #define MAX_PKT_SIZE RX_BUF_SIZE /* multi-segment not supported */ 34baf0fbfeSJeff Kirsher 35baf0fbfeSJeff Kirsher #if MAX_PKT_SIZE > 0x7ff 36baf0fbfeSJeff Kirsher #error invalid MAX_PKT_SIZE 37baf0fbfeSJeff Kirsher #endif 38baf0fbfeSJeff Kirsher 39baf0fbfeSJeff Kirsher #if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE 40baf0fbfeSJeff Kirsher #error invalid RX_BUF_SIZE 41baf0fbfeSJeff Kirsher #endif 42baf0fbfeSJeff Kirsher 43baf0fbfeSJeff Kirsher /****************************************************************************** 44baf0fbfeSJeff Kirsher * private data 45baf0fbfeSJeff Kirsher *****************************************************************************/ 46baf0fbfeSJeff Kirsher struct ftmac100_descs { 47baf0fbfeSJeff Kirsher struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES]; 48baf0fbfeSJeff Kirsher struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES]; 49baf0fbfeSJeff Kirsher }; 50baf0fbfeSJeff Kirsher 51baf0fbfeSJeff Kirsher struct ftmac100 { 52baf0fbfeSJeff Kirsher struct resource *res; 53baf0fbfeSJeff Kirsher void __iomem *base; 54baf0fbfeSJeff Kirsher int irq; 55baf0fbfeSJeff Kirsher 56baf0fbfeSJeff Kirsher struct ftmac100_descs *descs; 57baf0fbfeSJeff Kirsher dma_addr_t descs_dma_addr; 58baf0fbfeSJeff Kirsher 59baf0fbfeSJeff Kirsher unsigned int rx_pointer; 60baf0fbfeSJeff Kirsher unsigned int tx_clean_pointer; 61baf0fbfeSJeff Kirsher unsigned int tx_pointer; 62baf0fbfeSJeff Kirsher unsigned int tx_pending; 63baf0fbfeSJeff Kirsher 64baf0fbfeSJeff Kirsher spinlock_t tx_lock; 65baf0fbfeSJeff Kirsher 66baf0fbfeSJeff Kirsher struct net_device *netdev; 67baf0fbfeSJeff Kirsher struct device *dev; 68baf0fbfeSJeff Kirsher struct napi_struct napi; 69baf0fbfeSJeff Kirsher 70baf0fbfeSJeff Kirsher struct mii_if_info mii; 71baf0fbfeSJeff Kirsher }; 72baf0fbfeSJeff Kirsher 73baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv, 74baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes, gfp_t gfp); 75baf0fbfeSJeff Kirsher 76baf0fbfeSJeff Kirsher /****************************************************************************** 77baf0fbfeSJeff Kirsher * internal functions (hardware register access) 78baf0fbfeSJeff Kirsher *****************************************************************************/ 79baf0fbfeSJeff Kirsher #define INT_MASK_ALL_ENABLED (FTMAC100_INT_RPKT_FINISH | \ 80baf0fbfeSJeff Kirsher FTMAC100_INT_NORXBUF | \ 81baf0fbfeSJeff Kirsher FTMAC100_INT_XPKT_OK | \ 82baf0fbfeSJeff Kirsher FTMAC100_INT_XPKT_LOST | \ 83baf0fbfeSJeff Kirsher FTMAC100_INT_RPKT_LOST | \ 84baf0fbfeSJeff Kirsher FTMAC100_INT_AHB_ERR | \ 85baf0fbfeSJeff Kirsher FTMAC100_INT_PHYSTS_CHG) 86baf0fbfeSJeff Kirsher 87baf0fbfeSJeff Kirsher #define INT_MASK_ALL_DISABLED 0 88baf0fbfeSJeff Kirsher 89baf0fbfeSJeff Kirsher static void ftmac100_enable_all_int(struct ftmac100 *priv) 90baf0fbfeSJeff Kirsher { 91baf0fbfeSJeff Kirsher iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR); 92baf0fbfeSJeff Kirsher } 93baf0fbfeSJeff Kirsher 94baf0fbfeSJeff Kirsher static void ftmac100_disable_all_int(struct ftmac100 *priv) 95baf0fbfeSJeff Kirsher { 96baf0fbfeSJeff Kirsher iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR); 97baf0fbfeSJeff Kirsher } 98baf0fbfeSJeff Kirsher 99baf0fbfeSJeff Kirsher static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr) 100baf0fbfeSJeff Kirsher { 101baf0fbfeSJeff Kirsher iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR); 102baf0fbfeSJeff Kirsher } 103baf0fbfeSJeff Kirsher 104baf0fbfeSJeff Kirsher static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr) 105baf0fbfeSJeff Kirsher { 106baf0fbfeSJeff Kirsher iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR); 107baf0fbfeSJeff Kirsher } 108baf0fbfeSJeff Kirsher 109baf0fbfeSJeff Kirsher static void ftmac100_txdma_start_polling(struct ftmac100 *priv) 110baf0fbfeSJeff Kirsher { 111baf0fbfeSJeff Kirsher iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD); 112baf0fbfeSJeff Kirsher } 113baf0fbfeSJeff Kirsher 114baf0fbfeSJeff Kirsher static int ftmac100_reset(struct ftmac100 *priv) 115baf0fbfeSJeff Kirsher { 116baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 117baf0fbfeSJeff Kirsher int i; 118baf0fbfeSJeff Kirsher 119baf0fbfeSJeff Kirsher /* NOTE: reset clears all registers */ 120baf0fbfeSJeff Kirsher iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR); 121baf0fbfeSJeff Kirsher 122baf0fbfeSJeff Kirsher for (i = 0; i < 5; i++) { 123baf0fbfeSJeff Kirsher unsigned int maccr; 124baf0fbfeSJeff Kirsher 125baf0fbfeSJeff Kirsher maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR); 126baf0fbfeSJeff Kirsher if (!(maccr & FTMAC100_MACCR_SW_RST)) { 127baf0fbfeSJeff Kirsher /* 128baf0fbfeSJeff Kirsher * FTMAC100_MACCR_SW_RST cleared does not indicate 129baf0fbfeSJeff Kirsher * that hardware reset completed (what the f*ck). 130baf0fbfeSJeff Kirsher * We still need to wait for a while. 131baf0fbfeSJeff Kirsher */ 132baf0fbfeSJeff Kirsher udelay(500); 133baf0fbfeSJeff Kirsher return 0; 134baf0fbfeSJeff Kirsher } 135baf0fbfeSJeff Kirsher 136baf0fbfeSJeff Kirsher udelay(1000); 137baf0fbfeSJeff Kirsher } 138baf0fbfeSJeff Kirsher 139baf0fbfeSJeff Kirsher netdev_err(netdev, "software reset failed\n"); 140baf0fbfeSJeff Kirsher return -EIO; 141baf0fbfeSJeff Kirsher } 142baf0fbfeSJeff Kirsher 143baf0fbfeSJeff Kirsher static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac) 144baf0fbfeSJeff Kirsher { 145baf0fbfeSJeff Kirsher unsigned int maddr = mac[0] << 8 | mac[1]; 146baf0fbfeSJeff Kirsher unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; 147baf0fbfeSJeff Kirsher 148baf0fbfeSJeff Kirsher iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR); 149baf0fbfeSJeff Kirsher iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR); 150baf0fbfeSJeff Kirsher } 151baf0fbfeSJeff Kirsher 152baf0fbfeSJeff Kirsher #define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \ 153baf0fbfeSJeff Kirsher FTMAC100_MACCR_RCV_EN | \ 154baf0fbfeSJeff Kirsher FTMAC100_MACCR_XDMA_EN | \ 155baf0fbfeSJeff Kirsher FTMAC100_MACCR_RDMA_EN | \ 156baf0fbfeSJeff Kirsher FTMAC100_MACCR_CRC_APD | \ 157baf0fbfeSJeff Kirsher FTMAC100_MACCR_FULLDUP | \ 158baf0fbfeSJeff Kirsher FTMAC100_MACCR_RX_RUNT | \ 159baf0fbfeSJeff Kirsher FTMAC100_MACCR_RX_BROADPKT) 160baf0fbfeSJeff Kirsher 161baf0fbfeSJeff Kirsher static int ftmac100_start_hw(struct ftmac100 *priv) 162baf0fbfeSJeff Kirsher { 163baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 16437c84890SSergei Antonov unsigned int maccr = MACCR_ENABLE_ALL; 165baf0fbfeSJeff Kirsher 166baf0fbfeSJeff Kirsher if (ftmac100_reset(priv)) 167baf0fbfeSJeff Kirsher return -EIO; 168baf0fbfeSJeff Kirsher 169baf0fbfeSJeff Kirsher /* setup ring buffer base registers */ 170baf0fbfeSJeff Kirsher ftmac100_set_rx_ring_base(priv, 171baf0fbfeSJeff Kirsher priv->descs_dma_addr + 172baf0fbfeSJeff Kirsher offsetof(struct ftmac100_descs, rxdes)); 173baf0fbfeSJeff Kirsher ftmac100_set_tx_ring_base(priv, 174baf0fbfeSJeff Kirsher priv->descs_dma_addr + 175baf0fbfeSJeff Kirsher offsetof(struct ftmac100_descs, txdes)); 176baf0fbfeSJeff Kirsher 177baf0fbfeSJeff Kirsher iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC); 178baf0fbfeSJeff Kirsher 179baf0fbfeSJeff Kirsher ftmac100_set_mac(priv, netdev->dev_addr); 180baf0fbfeSJeff Kirsher 18137c84890SSergei Antonov /* See ftmac100_change_mtu() */ 18237c84890SSergei Antonov if (netdev->mtu > ETH_DATA_LEN) 18337c84890SSergei Antonov maccr |= FTMAC100_MACCR_RX_FTL; 18437c84890SSergei Antonov 185*75943bc9SSergei Antonov /* Add other bits as needed */ 186*75943bc9SSergei Antonov if (netdev->flags & IFF_PROMISC) 187*75943bc9SSergei Antonov maccr |= FTMAC100_MACCR_RCV_ALL; 188*75943bc9SSergei Antonov if (netdev->flags & IFF_ALLMULTI) 189*75943bc9SSergei Antonov maccr |= FTMAC100_MACCR_RX_MULTIPKT; 190*75943bc9SSergei Antonov 19137c84890SSergei Antonov iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); 192baf0fbfeSJeff Kirsher return 0; 193baf0fbfeSJeff Kirsher } 194baf0fbfeSJeff Kirsher 195baf0fbfeSJeff Kirsher static void ftmac100_stop_hw(struct ftmac100 *priv) 196baf0fbfeSJeff Kirsher { 197baf0fbfeSJeff Kirsher iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR); 198baf0fbfeSJeff Kirsher } 199baf0fbfeSJeff Kirsher 200baf0fbfeSJeff Kirsher /****************************************************************************** 201baf0fbfeSJeff Kirsher * internal functions (receive descriptor) 202baf0fbfeSJeff Kirsher *****************************************************************************/ 203baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes) 204baf0fbfeSJeff Kirsher { 205baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS); 206baf0fbfeSJeff Kirsher } 207baf0fbfeSJeff Kirsher 208baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes) 209baf0fbfeSJeff Kirsher { 210baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS); 211baf0fbfeSJeff Kirsher } 212baf0fbfeSJeff Kirsher 213baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes) 214baf0fbfeSJeff Kirsher { 215baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN); 216baf0fbfeSJeff Kirsher } 217baf0fbfeSJeff Kirsher 218baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes) 219baf0fbfeSJeff Kirsher { 220baf0fbfeSJeff Kirsher /* clear status bits */ 221baf0fbfeSJeff Kirsher rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN); 222baf0fbfeSJeff Kirsher } 223baf0fbfeSJeff Kirsher 224baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes) 225baf0fbfeSJeff Kirsher { 226baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR); 227baf0fbfeSJeff Kirsher } 228baf0fbfeSJeff Kirsher 229baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes) 230baf0fbfeSJeff Kirsher { 231baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR); 232baf0fbfeSJeff Kirsher } 233baf0fbfeSJeff Kirsher 234baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes) 235baf0fbfeSJeff Kirsher { 236baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT); 237baf0fbfeSJeff Kirsher } 238baf0fbfeSJeff Kirsher 239baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes) 240baf0fbfeSJeff Kirsher { 241baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB); 242baf0fbfeSJeff Kirsher } 243baf0fbfeSJeff Kirsher 244baf0fbfeSJeff Kirsher static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes) 245baf0fbfeSJeff Kirsher { 246baf0fbfeSJeff Kirsher return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL; 247baf0fbfeSJeff Kirsher } 248baf0fbfeSJeff Kirsher 249baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes) 250baf0fbfeSJeff Kirsher { 251baf0fbfeSJeff Kirsher return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST); 252baf0fbfeSJeff Kirsher } 253baf0fbfeSJeff Kirsher 254baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes, 255baf0fbfeSJeff Kirsher unsigned int size) 256baf0fbfeSJeff Kirsher { 257baf0fbfeSJeff Kirsher rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR); 258baf0fbfeSJeff Kirsher rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size)); 259baf0fbfeSJeff Kirsher } 260baf0fbfeSJeff Kirsher 261baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes) 262baf0fbfeSJeff Kirsher { 263baf0fbfeSJeff Kirsher rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR); 264baf0fbfeSJeff Kirsher } 265baf0fbfeSJeff Kirsher 266baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes, 267baf0fbfeSJeff Kirsher dma_addr_t addr) 268baf0fbfeSJeff Kirsher { 269baf0fbfeSJeff Kirsher rxdes->rxdes2 = cpu_to_le32(addr); 270baf0fbfeSJeff Kirsher } 271baf0fbfeSJeff Kirsher 272baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes) 273baf0fbfeSJeff Kirsher { 274baf0fbfeSJeff Kirsher return le32_to_cpu(rxdes->rxdes2); 275baf0fbfeSJeff Kirsher } 276baf0fbfeSJeff Kirsher 277baf0fbfeSJeff Kirsher /* 278baf0fbfeSJeff Kirsher * rxdes3 is not used by hardware. We use it to keep track of page. 279baf0fbfeSJeff Kirsher * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu(). 280baf0fbfeSJeff Kirsher */ 281baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page) 282baf0fbfeSJeff Kirsher { 283baf0fbfeSJeff Kirsher rxdes->rxdes3 = (unsigned int)page; 284baf0fbfeSJeff Kirsher } 285baf0fbfeSJeff Kirsher 286baf0fbfeSJeff Kirsher static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes) 287baf0fbfeSJeff Kirsher { 288baf0fbfeSJeff Kirsher return (struct page *)rxdes->rxdes3; 289baf0fbfeSJeff Kirsher } 290baf0fbfeSJeff Kirsher 291baf0fbfeSJeff Kirsher /****************************************************************************** 292baf0fbfeSJeff Kirsher * internal functions (receive) 293baf0fbfeSJeff Kirsher *****************************************************************************/ 294baf0fbfeSJeff Kirsher static int ftmac100_next_rx_pointer(int pointer) 295baf0fbfeSJeff Kirsher { 296baf0fbfeSJeff Kirsher return (pointer + 1) & (RX_QUEUE_ENTRIES - 1); 297baf0fbfeSJeff Kirsher } 298baf0fbfeSJeff Kirsher 299baf0fbfeSJeff Kirsher static void ftmac100_rx_pointer_advance(struct ftmac100 *priv) 300baf0fbfeSJeff Kirsher { 301baf0fbfeSJeff Kirsher priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer); 302baf0fbfeSJeff Kirsher } 303baf0fbfeSJeff Kirsher 304baf0fbfeSJeff Kirsher static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv) 305baf0fbfeSJeff Kirsher { 306baf0fbfeSJeff Kirsher return &priv->descs->rxdes[priv->rx_pointer]; 307baf0fbfeSJeff Kirsher } 308baf0fbfeSJeff Kirsher 309baf0fbfeSJeff Kirsher static struct ftmac100_rxdes * 310baf0fbfeSJeff Kirsher ftmac100_rx_locate_first_segment(struct ftmac100 *priv) 311baf0fbfeSJeff Kirsher { 312baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv); 313baf0fbfeSJeff Kirsher 314baf0fbfeSJeff Kirsher while (!ftmac100_rxdes_owned_by_dma(rxdes)) { 315baf0fbfeSJeff Kirsher if (ftmac100_rxdes_first_segment(rxdes)) 316baf0fbfeSJeff Kirsher return rxdes; 317baf0fbfeSJeff Kirsher 318baf0fbfeSJeff Kirsher ftmac100_rxdes_set_dma_own(rxdes); 319baf0fbfeSJeff Kirsher ftmac100_rx_pointer_advance(priv); 320baf0fbfeSJeff Kirsher rxdes = ftmac100_current_rxdes(priv); 321baf0fbfeSJeff Kirsher } 322baf0fbfeSJeff Kirsher 323baf0fbfeSJeff Kirsher return NULL; 324baf0fbfeSJeff Kirsher } 325baf0fbfeSJeff Kirsher 326baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet_error(struct ftmac100 *priv, 327baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes) 328baf0fbfeSJeff Kirsher { 329baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 330baf0fbfeSJeff Kirsher bool error = false; 331baf0fbfeSJeff Kirsher 332baf0fbfeSJeff Kirsher if (unlikely(ftmac100_rxdes_rx_error(rxdes))) { 333baf0fbfeSJeff Kirsher if (net_ratelimit()) 334baf0fbfeSJeff Kirsher netdev_info(netdev, "rx err\n"); 335baf0fbfeSJeff Kirsher 336baf0fbfeSJeff Kirsher netdev->stats.rx_errors++; 337baf0fbfeSJeff Kirsher error = true; 338baf0fbfeSJeff Kirsher } 339baf0fbfeSJeff Kirsher 340baf0fbfeSJeff Kirsher if (unlikely(ftmac100_rxdes_crc_error(rxdes))) { 341baf0fbfeSJeff Kirsher if (net_ratelimit()) 342baf0fbfeSJeff Kirsher netdev_info(netdev, "rx crc err\n"); 343baf0fbfeSJeff Kirsher 344baf0fbfeSJeff Kirsher netdev->stats.rx_crc_errors++; 345baf0fbfeSJeff Kirsher error = true; 346baf0fbfeSJeff Kirsher } 347baf0fbfeSJeff Kirsher 34855f6f3dbSVladimir Oltean if (unlikely(ftmac100_rxdes_runt(rxdes))) { 349baf0fbfeSJeff Kirsher if (net_ratelimit()) 350baf0fbfeSJeff Kirsher netdev_info(netdev, "rx runt\n"); 351baf0fbfeSJeff Kirsher 352baf0fbfeSJeff Kirsher netdev->stats.rx_length_errors++; 353baf0fbfeSJeff Kirsher error = true; 354baf0fbfeSJeff Kirsher } else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) { 355baf0fbfeSJeff Kirsher if (net_ratelimit()) 356baf0fbfeSJeff Kirsher netdev_info(netdev, "rx odd nibble\n"); 357baf0fbfeSJeff Kirsher 358baf0fbfeSJeff Kirsher netdev->stats.rx_length_errors++; 359baf0fbfeSJeff Kirsher error = true; 360baf0fbfeSJeff Kirsher } 36155f6f3dbSVladimir Oltean /* 36255f6f3dbSVladimir Oltean * FTMAC100_RXDES0_FTL is not an error, it just indicates that the 36355f6f3dbSVladimir Oltean * frame is longer than 1518 octets. Receiving these is possible when 36455f6f3dbSVladimir Oltean * we told the hardware not to drop them, via FTMAC100_MACCR_RX_FTL. 36555f6f3dbSVladimir Oltean */ 366baf0fbfeSJeff Kirsher 367baf0fbfeSJeff Kirsher return error; 368baf0fbfeSJeff Kirsher } 369baf0fbfeSJeff Kirsher 370baf0fbfeSJeff Kirsher static void ftmac100_rx_drop_packet(struct ftmac100 *priv) 371baf0fbfeSJeff Kirsher { 372baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 373baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv); 374baf0fbfeSJeff Kirsher bool done = false; 375baf0fbfeSJeff Kirsher 376baf0fbfeSJeff Kirsher if (net_ratelimit()) 377baf0fbfeSJeff Kirsher netdev_dbg(netdev, "drop packet %p\n", rxdes); 378baf0fbfeSJeff Kirsher 379baf0fbfeSJeff Kirsher do { 380baf0fbfeSJeff Kirsher if (ftmac100_rxdes_last_segment(rxdes)) 381baf0fbfeSJeff Kirsher done = true; 382baf0fbfeSJeff Kirsher 383baf0fbfeSJeff Kirsher ftmac100_rxdes_set_dma_own(rxdes); 384baf0fbfeSJeff Kirsher ftmac100_rx_pointer_advance(priv); 385baf0fbfeSJeff Kirsher rxdes = ftmac100_current_rxdes(priv); 386baf0fbfeSJeff Kirsher } while (!done && !ftmac100_rxdes_owned_by_dma(rxdes)); 387baf0fbfeSJeff Kirsher 388baf0fbfeSJeff Kirsher netdev->stats.rx_dropped++; 389baf0fbfeSJeff Kirsher } 390baf0fbfeSJeff Kirsher 391baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed) 392baf0fbfeSJeff Kirsher { 393baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 394baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes; 395baf0fbfeSJeff Kirsher struct sk_buff *skb; 396baf0fbfeSJeff Kirsher struct page *page; 397baf0fbfeSJeff Kirsher dma_addr_t map; 398baf0fbfeSJeff Kirsher int length; 3995bca178eSGustavo A. R. Silva bool ret; 400baf0fbfeSJeff Kirsher 401baf0fbfeSJeff Kirsher rxdes = ftmac100_rx_locate_first_segment(priv); 402baf0fbfeSJeff Kirsher if (!rxdes) 403baf0fbfeSJeff Kirsher return false; 404baf0fbfeSJeff Kirsher 405baf0fbfeSJeff Kirsher if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) { 406baf0fbfeSJeff Kirsher ftmac100_rx_drop_packet(priv); 407baf0fbfeSJeff Kirsher return true; 408baf0fbfeSJeff Kirsher } 409baf0fbfeSJeff Kirsher 41055f6f3dbSVladimir Oltean /* We don't support multi-segment packets for now, so drop them. */ 4115bca178eSGustavo A. R. Silva ret = ftmac100_rxdes_last_segment(rxdes); 41255f6f3dbSVladimir Oltean if (unlikely(!ret)) { 41355f6f3dbSVladimir Oltean netdev->stats.rx_length_errors++; 41455f6f3dbSVladimir Oltean ftmac100_rx_drop_packet(priv); 41555f6f3dbSVladimir Oltean return true; 41655f6f3dbSVladimir Oltean } 417baf0fbfeSJeff Kirsher 418baf0fbfeSJeff Kirsher /* start processing */ 419baf0fbfeSJeff Kirsher skb = netdev_alloc_skb_ip_align(netdev, 128); 420baf0fbfeSJeff Kirsher if (unlikely(!skb)) { 421baf0fbfeSJeff Kirsher if (net_ratelimit()) 422baf0fbfeSJeff Kirsher netdev_err(netdev, "rx skb alloc failed\n"); 423baf0fbfeSJeff Kirsher 424baf0fbfeSJeff Kirsher ftmac100_rx_drop_packet(priv); 425baf0fbfeSJeff Kirsher return true; 426baf0fbfeSJeff Kirsher } 427baf0fbfeSJeff Kirsher 428baf0fbfeSJeff Kirsher if (unlikely(ftmac100_rxdes_multicast(rxdes))) 429baf0fbfeSJeff Kirsher netdev->stats.multicast++; 430baf0fbfeSJeff Kirsher 431baf0fbfeSJeff Kirsher map = ftmac100_rxdes_get_dma_addr(rxdes); 432baf0fbfeSJeff Kirsher dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); 433baf0fbfeSJeff Kirsher 434baf0fbfeSJeff Kirsher length = ftmac100_rxdes_frame_length(rxdes); 435baf0fbfeSJeff Kirsher page = ftmac100_rxdes_get_page(rxdes); 436baf0fbfeSJeff Kirsher skb_fill_page_desc(skb, 0, page, 0, length); 437baf0fbfeSJeff Kirsher skb->len += length; 438baf0fbfeSJeff Kirsher skb->data_len += length; 43996cd8951SEric Dumazet 4406ecd09ddSEric Dumazet if (length > 128) { 44196cd8951SEric Dumazet skb->truesize += PAGE_SIZE; 4426ecd09ddSEric Dumazet /* We pull the minimum amount into linear part */ 4436ecd09ddSEric Dumazet __pskb_pull_tail(skb, ETH_HLEN); 4446ecd09ddSEric Dumazet } else { 4456ecd09ddSEric Dumazet /* Small frames are copied into linear part to free one page */ 4466ecd09ddSEric Dumazet __pskb_pull_tail(skb, length); 4476ecd09ddSEric Dumazet } 448baf0fbfeSJeff Kirsher ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC); 449baf0fbfeSJeff Kirsher 450baf0fbfeSJeff Kirsher ftmac100_rx_pointer_advance(priv); 451baf0fbfeSJeff Kirsher 452baf0fbfeSJeff Kirsher skb->protocol = eth_type_trans(skb, netdev); 453baf0fbfeSJeff Kirsher 454baf0fbfeSJeff Kirsher netdev->stats.rx_packets++; 455baf0fbfeSJeff Kirsher netdev->stats.rx_bytes += skb->len; 456baf0fbfeSJeff Kirsher 457baf0fbfeSJeff Kirsher /* push packet to protocol stack */ 458baf0fbfeSJeff Kirsher netif_receive_skb(skb); 459baf0fbfeSJeff Kirsher 460baf0fbfeSJeff Kirsher (*processed)++; 461baf0fbfeSJeff Kirsher return true; 462baf0fbfeSJeff Kirsher } 463baf0fbfeSJeff Kirsher 464baf0fbfeSJeff Kirsher /****************************************************************************** 465baf0fbfeSJeff Kirsher * internal functions (transmit descriptor) 466baf0fbfeSJeff Kirsher *****************************************************************************/ 467baf0fbfeSJeff Kirsher static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes) 468baf0fbfeSJeff Kirsher { 469baf0fbfeSJeff Kirsher /* clear all except end of ring bit */ 470baf0fbfeSJeff Kirsher txdes->txdes0 = 0; 471baf0fbfeSJeff Kirsher txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR); 472baf0fbfeSJeff Kirsher txdes->txdes2 = 0; 473baf0fbfeSJeff Kirsher txdes->txdes3 = 0; 474baf0fbfeSJeff Kirsher } 475baf0fbfeSJeff Kirsher 476baf0fbfeSJeff Kirsher static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes) 477baf0fbfeSJeff Kirsher { 478baf0fbfeSJeff Kirsher return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN); 479baf0fbfeSJeff Kirsher } 480baf0fbfeSJeff Kirsher 481baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes) 482baf0fbfeSJeff Kirsher { 483baf0fbfeSJeff Kirsher /* 484baf0fbfeSJeff Kirsher * Make sure dma own bit will not be set before any other 485baf0fbfeSJeff Kirsher * descriptor fields. 486baf0fbfeSJeff Kirsher */ 487baf0fbfeSJeff Kirsher wmb(); 488baf0fbfeSJeff Kirsher txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN); 489baf0fbfeSJeff Kirsher } 490baf0fbfeSJeff Kirsher 491baf0fbfeSJeff Kirsher static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes) 492baf0fbfeSJeff Kirsher { 493baf0fbfeSJeff Kirsher return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL); 494baf0fbfeSJeff Kirsher } 495baf0fbfeSJeff Kirsher 496baf0fbfeSJeff Kirsher static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes) 497baf0fbfeSJeff Kirsher { 498baf0fbfeSJeff Kirsher return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL); 499baf0fbfeSJeff Kirsher } 500baf0fbfeSJeff Kirsher 501baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes) 502baf0fbfeSJeff Kirsher { 503baf0fbfeSJeff Kirsher txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR); 504baf0fbfeSJeff Kirsher } 505baf0fbfeSJeff Kirsher 506baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes) 507baf0fbfeSJeff Kirsher { 508baf0fbfeSJeff Kirsher txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS); 509baf0fbfeSJeff Kirsher } 510baf0fbfeSJeff Kirsher 511baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes) 512baf0fbfeSJeff Kirsher { 513baf0fbfeSJeff Kirsher txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS); 514baf0fbfeSJeff Kirsher } 515baf0fbfeSJeff Kirsher 516baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes) 517baf0fbfeSJeff Kirsher { 518baf0fbfeSJeff Kirsher txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC); 519baf0fbfeSJeff Kirsher } 520baf0fbfeSJeff Kirsher 521baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes, 522baf0fbfeSJeff Kirsher unsigned int len) 523baf0fbfeSJeff Kirsher { 524baf0fbfeSJeff Kirsher txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len)); 525baf0fbfeSJeff Kirsher } 526baf0fbfeSJeff Kirsher 527baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes, 528baf0fbfeSJeff Kirsher dma_addr_t addr) 529baf0fbfeSJeff Kirsher { 530baf0fbfeSJeff Kirsher txdes->txdes2 = cpu_to_le32(addr); 531baf0fbfeSJeff Kirsher } 532baf0fbfeSJeff Kirsher 533baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes) 534baf0fbfeSJeff Kirsher { 535baf0fbfeSJeff Kirsher return le32_to_cpu(txdes->txdes2); 536baf0fbfeSJeff Kirsher } 537baf0fbfeSJeff Kirsher 538baf0fbfeSJeff Kirsher /* 539baf0fbfeSJeff Kirsher * txdes3 is not used by hardware. We use it to keep track of socket buffer. 540baf0fbfeSJeff Kirsher * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu(). 541baf0fbfeSJeff Kirsher */ 542baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb) 543baf0fbfeSJeff Kirsher { 544baf0fbfeSJeff Kirsher txdes->txdes3 = (unsigned int)skb; 545baf0fbfeSJeff Kirsher } 546baf0fbfeSJeff Kirsher 547baf0fbfeSJeff Kirsher static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes) 548baf0fbfeSJeff Kirsher { 549baf0fbfeSJeff Kirsher return (struct sk_buff *)txdes->txdes3; 550baf0fbfeSJeff Kirsher } 551baf0fbfeSJeff Kirsher 552baf0fbfeSJeff Kirsher /****************************************************************************** 553baf0fbfeSJeff Kirsher * internal functions (transmit) 554baf0fbfeSJeff Kirsher *****************************************************************************/ 555baf0fbfeSJeff Kirsher static int ftmac100_next_tx_pointer(int pointer) 556baf0fbfeSJeff Kirsher { 557baf0fbfeSJeff Kirsher return (pointer + 1) & (TX_QUEUE_ENTRIES - 1); 558baf0fbfeSJeff Kirsher } 559baf0fbfeSJeff Kirsher 560baf0fbfeSJeff Kirsher static void ftmac100_tx_pointer_advance(struct ftmac100 *priv) 561baf0fbfeSJeff Kirsher { 562baf0fbfeSJeff Kirsher priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer); 563baf0fbfeSJeff Kirsher } 564baf0fbfeSJeff Kirsher 565baf0fbfeSJeff Kirsher static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv) 566baf0fbfeSJeff Kirsher { 567baf0fbfeSJeff Kirsher priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer); 568baf0fbfeSJeff Kirsher } 569baf0fbfeSJeff Kirsher 570baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv) 571baf0fbfeSJeff Kirsher { 572baf0fbfeSJeff Kirsher return &priv->descs->txdes[priv->tx_pointer]; 573baf0fbfeSJeff Kirsher } 574baf0fbfeSJeff Kirsher 575baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv) 576baf0fbfeSJeff Kirsher { 577baf0fbfeSJeff Kirsher return &priv->descs->txdes[priv->tx_clean_pointer]; 578baf0fbfeSJeff Kirsher } 579baf0fbfeSJeff Kirsher 580baf0fbfeSJeff Kirsher static bool ftmac100_tx_complete_packet(struct ftmac100 *priv) 581baf0fbfeSJeff Kirsher { 582baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 583baf0fbfeSJeff Kirsher struct ftmac100_txdes *txdes; 584baf0fbfeSJeff Kirsher struct sk_buff *skb; 585baf0fbfeSJeff Kirsher dma_addr_t map; 586baf0fbfeSJeff Kirsher 587baf0fbfeSJeff Kirsher if (priv->tx_pending == 0) 588baf0fbfeSJeff Kirsher return false; 589baf0fbfeSJeff Kirsher 590baf0fbfeSJeff Kirsher txdes = ftmac100_current_clean_txdes(priv); 591baf0fbfeSJeff Kirsher 592baf0fbfeSJeff Kirsher if (ftmac100_txdes_owned_by_dma(txdes)) 593baf0fbfeSJeff Kirsher return false; 594baf0fbfeSJeff Kirsher 595baf0fbfeSJeff Kirsher skb = ftmac100_txdes_get_skb(txdes); 596baf0fbfeSJeff Kirsher map = ftmac100_txdes_get_dma_addr(txdes); 597baf0fbfeSJeff Kirsher 598baf0fbfeSJeff Kirsher if (unlikely(ftmac100_txdes_excessive_collision(txdes) || 599baf0fbfeSJeff Kirsher ftmac100_txdes_late_collision(txdes))) { 600baf0fbfeSJeff Kirsher /* 601baf0fbfeSJeff Kirsher * packet transmitted to ethernet lost due to late collision 602baf0fbfeSJeff Kirsher * or excessive collision 603baf0fbfeSJeff Kirsher */ 604baf0fbfeSJeff Kirsher netdev->stats.tx_aborted_errors++; 605baf0fbfeSJeff Kirsher } else { 606baf0fbfeSJeff Kirsher netdev->stats.tx_packets++; 607baf0fbfeSJeff Kirsher netdev->stats.tx_bytes += skb->len; 608baf0fbfeSJeff Kirsher } 609baf0fbfeSJeff Kirsher 610baf0fbfeSJeff Kirsher dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE); 611baf0fbfeSJeff Kirsher dev_kfree_skb(skb); 612baf0fbfeSJeff Kirsher 613baf0fbfeSJeff Kirsher ftmac100_txdes_reset(txdes); 614baf0fbfeSJeff Kirsher 615baf0fbfeSJeff Kirsher ftmac100_tx_clean_pointer_advance(priv); 616baf0fbfeSJeff Kirsher 617baf0fbfeSJeff Kirsher spin_lock(&priv->tx_lock); 618baf0fbfeSJeff Kirsher priv->tx_pending--; 619baf0fbfeSJeff Kirsher spin_unlock(&priv->tx_lock); 620baf0fbfeSJeff Kirsher netif_wake_queue(netdev); 621baf0fbfeSJeff Kirsher 622baf0fbfeSJeff Kirsher return true; 623baf0fbfeSJeff Kirsher } 624baf0fbfeSJeff Kirsher 625baf0fbfeSJeff Kirsher static void ftmac100_tx_complete(struct ftmac100 *priv) 626baf0fbfeSJeff Kirsher { 627baf0fbfeSJeff Kirsher while (ftmac100_tx_complete_packet(priv)) 628baf0fbfeSJeff Kirsher ; 629baf0fbfeSJeff Kirsher } 630baf0fbfeSJeff Kirsher 6310a715156SYueHaibing static netdev_tx_t ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb, 632baf0fbfeSJeff Kirsher dma_addr_t map) 633baf0fbfeSJeff Kirsher { 634baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 635baf0fbfeSJeff Kirsher struct ftmac100_txdes *txdes; 636baf0fbfeSJeff Kirsher unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 637baf0fbfeSJeff Kirsher 638baf0fbfeSJeff Kirsher txdes = ftmac100_current_txdes(priv); 639baf0fbfeSJeff Kirsher ftmac100_tx_pointer_advance(priv); 640baf0fbfeSJeff Kirsher 641baf0fbfeSJeff Kirsher /* setup TX descriptor */ 642baf0fbfeSJeff Kirsher ftmac100_txdes_set_skb(txdes, skb); 643baf0fbfeSJeff Kirsher ftmac100_txdes_set_dma_addr(txdes, map); 644baf0fbfeSJeff Kirsher 645baf0fbfeSJeff Kirsher ftmac100_txdes_set_first_segment(txdes); 646baf0fbfeSJeff Kirsher ftmac100_txdes_set_last_segment(txdes); 647baf0fbfeSJeff Kirsher ftmac100_txdes_set_txint(txdes); 648baf0fbfeSJeff Kirsher ftmac100_txdes_set_buffer_size(txdes, len); 649baf0fbfeSJeff Kirsher 650baf0fbfeSJeff Kirsher spin_lock(&priv->tx_lock); 651baf0fbfeSJeff Kirsher priv->tx_pending++; 652baf0fbfeSJeff Kirsher if (priv->tx_pending == TX_QUEUE_ENTRIES) 653baf0fbfeSJeff Kirsher netif_stop_queue(netdev); 654baf0fbfeSJeff Kirsher 655baf0fbfeSJeff Kirsher /* start transmit */ 656baf0fbfeSJeff Kirsher ftmac100_txdes_set_dma_own(txdes); 657baf0fbfeSJeff Kirsher spin_unlock(&priv->tx_lock); 658baf0fbfeSJeff Kirsher 659baf0fbfeSJeff Kirsher ftmac100_txdma_start_polling(priv); 660baf0fbfeSJeff Kirsher return NETDEV_TX_OK; 661baf0fbfeSJeff Kirsher } 662baf0fbfeSJeff Kirsher 663baf0fbfeSJeff Kirsher /****************************************************************************** 664baf0fbfeSJeff Kirsher * internal functions (buffer) 665baf0fbfeSJeff Kirsher *****************************************************************************/ 666baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv, 667baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes, gfp_t gfp) 668baf0fbfeSJeff Kirsher { 669baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 670baf0fbfeSJeff Kirsher struct page *page; 671baf0fbfeSJeff Kirsher dma_addr_t map; 672baf0fbfeSJeff Kirsher 673baf0fbfeSJeff Kirsher page = alloc_page(gfp); 674baf0fbfeSJeff Kirsher if (!page) { 675baf0fbfeSJeff Kirsher if (net_ratelimit()) 676baf0fbfeSJeff Kirsher netdev_err(netdev, "failed to allocate rx page\n"); 677baf0fbfeSJeff Kirsher return -ENOMEM; 678baf0fbfeSJeff Kirsher } 679baf0fbfeSJeff Kirsher 680baf0fbfeSJeff Kirsher map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE); 681baf0fbfeSJeff Kirsher if (unlikely(dma_mapping_error(priv->dev, map))) { 682baf0fbfeSJeff Kirsher if (net_ratelimit()) 683baf0fbfeSJeff Kirsher netdev_err(netdev, "failed to map rx page\n"); 684baf0fbfeSJeff Kirsher __free_page(page); 685baf0fbfeSJeff Kirsher return -ENOMEM; 686baf0fbfeSJeff Kirsher } 687baf0fbfeSJeff Kirsher 688baf0fbfeSJeff Kirsher ftmac100_rxdes_set_page(rxdes, page); 689baf0fbfeSJeff Kirsher ftmac100_rxdes_set_dma_addr(rxdes, map); 690baf0fbfeSJeff Kirsher ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE); 691baf0fbfeSJeff Kirsher ftmac100_rxdes_set_dma_own(rxdes); 692baf0fbfeSJeff Kirsher return 0; 693baf0fbfeSJeff Kirsher } 694baf0fbfeSJeff Kirsher 695baf0fbfeSJeff Kirsher static void ftmac100_free_buffers(struct ftmac100 *priv) 696baf0fbfeSJeff Kirsher { 697baf0fbfeSJeff Kirsher int i; 698baf0fbfeSJeff Kirsher 699baf0fbfeSJeff Kirsher for (i = 0; i < RX_QUEUE_ENTRIES; i++) { 700baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i]; 701baf0fbfeSJeff Kirsher struct page *page = ftmac100_rxdes_get_page(rxdes); 702baf0fbfeSJeff Kirsher dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes); 703baf0fbfeSJeff Kirsher 704baf0fbfeSJeff Kirsher if (!page) 705baf0fbfeSJeff Kirsher continue; 706baf0fbfeSJeff Kirsher 707baf0fbfeSJeff Kirsher dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); 708baf0fbfeSJeff Kirsher __free_page(page); 709baf0fbfeSJeff Kirsher } 710baf0fbfeSJeff Kirsher 711baf0fbfeSJeff Kirsher for (i = 0; i < TX_QUEUE_ENTRIES; i++) { 712baf0fbfeSJeff Kirsher struct ftmac100_txdes *txdes = &priv->descs->txdes[i]; 713baf0fbfeSJeff Kirsher struct sk_buff *skb = ftmac100_txdes_get_skb(txdes); 714baf0fbfeSJeff Kirsher dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes); 715baf0fbfeSJeff Kirsher 716baf0fbfeSJeff Kirsher if (!skb) 717baf0fbfeSJeff Kirsher continue; 718baf0fbfeSJeff Kirsher 719baf0fbfeSJeff Kirsher dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE); 720baf0fbfeSJeff Kirsher dev_kfree_skb(skb); 721baf0fbfeSJeff Kirsher } 722baf0fbfeSJeff Kirsher 723baf0fbfeSJeff Kirsher dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs), 724baf0fbfeSJeff Kirsher priv->descs, priv->descs_dma_addr); 725baf0fbfeSJeff Kirsher } 726baf0fbfeSJeff Kirsher 727baf0fbfeSJeff Kirsher static int ftmac100_alloc_buffers(struct ftmac100 *priv) 728baf0fbfeSJeff Kirsher { 729baf0fbfeSJeff Kirsher int i; 730baf0fbfeSJeff Kirsher 731750afb08SLuis Chamberlain priv->descs = dma_alloc_coherent(priv->dev, 7321f9061d2SJoe Perches sizeof(struct ftmac100_descs), 733750afb08SLuis Chamberlain &priv->descs_dma_addr, GFP_KERNEL); 734baf0fbfeSJeff Kirsher if (!priv->descs) 735baf0fbfeSJeff Kirsher return -ENOMEM; 736baf0fbfeSJeff Kirsher 737baf0fbfeSJeff Kirsher /* initialize RX ring */ 738baf0fbfeSJeff Kirsher ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]); 739baf0fbfeSJeff Kirsher 740baf0fbfeSJeff Kirsher for (i = 0; i < RX_QUEUE_ENTRIES; i++) { 741baf0fbfeSJeff Kirsher struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i]; 742baf0fbfeSJeff Kirsher 743baf0fbfeSJeff Kirsher if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL)) 744baf0fbfeSJeff Kirsher goto err; 745baf0fbfeSJeff Kirsher } 746baf0fbfeSJeff Kirsher 747baf0fbfeSJeff Kirsher /* initialize TX ring */ 748baf0fbfeSJeff Kirsher ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]); 749baf0fbfeSJeff Kirsher return 0; 750baf0fbfeSJeff Kirsher 751baf0fbfeSJeff Kirsher err: 752baf0fbfeSJeff Kirsher ftmac100_free_buffers(priv); 753baf0fbfeSJeff Kirsher return -ENOMEM; 754baf0fbfeSJeff Kirsher } 755baf0fbfeSJeff Kirsher 756baf0fbfeSJeff Kirsher /****************************************************************************** 757baf0fbfeSJeff Kirsher * struct mii_if_info functions 758baf0fbfeSJeff Kirsher *****************************************************************************/ 759baf0fbfeSJeff Kirsher static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg) 760baf0fbfeSJeff Kirsher { 761baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 762baf0fbfeSJeff Kirsher unsigned int phycr; 763baf0fbfeSJeff Kirsher int i; 764baf0fbfeSJeff Kirsher 765baf0fbfeSJeff Kirsher phycr = FTMAC100_PHYCR_PHYAD(phy_id) | 766baf0fbfeSJeff Kirsher FTMAC100_PHYCR_REGAD(reg) | 767baf0fbfeSJeff Kirsher FTMAC100_PHYCR_MIIRD; 768baf0fbfeSJeff Kirsher 769baf0fbfeSJeff Kirsher iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR); 770baf0fbfeSJeff Kirsher 771baf0fbfeSJeff Kirsher for (i = 0; i < 10; i++) { 772baf0fbfeSJeff Kirsher phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR); 773baf0fbfeSJeff Kirsher 774baf0fbfeSJeff Kirsher if ((phycr & FTMAC100_PHYCR_MIIRD) == 0) 775baf0fbfeSJeff Kirsher return phycr & FTMAC100_PHYCR_MIIRDATA; 776baf0fbfeSJeff Kirsher 777baf0fbfeSJeff Kirsher udelay(100); 778baf0fbfeSJeff Kirsher } 779baf0fbfeSJeff Kirsher 780baf0fbfeSJeff Kirsher netdev_err(netdev, "mdio read timed out\n"); 781baf0fbfeSJeff Kirsher return 0; 782baf0fbfeSJeff Kirsher } 783baf0fbfeSJeff Kirsher 784baf0fbfeSJeff Kirsher static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg, 785baf0fbfeSJeff Kirsher int data) 786baf0fbfeSJeff Kirsher { 787baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 788baf0fbfeSJeff Kirsher unsigned int phycr; 789baf0fbfeSJeff Kirsher int i; 790baf0fbfeSJeff Kirsher 791baf0fbfeSJeff Kirsher phycr = FTMAC100_PHYCR_PHYAD(phy_id) | 792baf0fbfeSJeff Kirsher FTMAC100_PHYCR_REGAD(reg) | 793baf0fbfeSJeff Kirsher FTMAC100_PHYCR_MIIWR; 794baf0fbfeSJeff Kirsher 795baf0fbfeSJeff Kirsher data = FTMAC100_PHYWDATA_MIIWDATA(data); 796baf0fbfeSJeff Kirsher 797baf0fbfeSJeff Kirsher iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA); 798baf0fbfeSJeff Kirsher iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR); 799baf0fbfeSJeff Kirsher 800baf0fbfeSJeff Kirsher for (i = 0; i < 10; i++) { 801baf0fbfeSJeff Kirsher phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR); 802baf0fbfeSJeff Kirsher 803baf0fbfeSJeff Kirsher if ((phycr & FTMAC100_PHYCR_MIIWR) == 0) 804baf0fbfeSJeff Kirsher return; 805baf0fbfeSJeff Kirsher 806baf0fbfeSJeff Kirsher udelay(100); 807baf0fbfeSJeff Kirsher } 808baf0fbfeSJeff Kirsher 809baf0fbfeSJeff Kirsher netdev_err(netdev, "mdio write timed out\n"); 810baf0fbfeSJeff Kirsher } 811baf0fbfeSJeff Kirsher 812baf0fbfeSJeff Kirsher /****************************************************************************** 813baf0fbfeSJeff Kirsher * struct ethtool_ops functions 814baf0fbfeSJeff Kirsher *****************************************************************************/ 815baf0fbfeSJeff Kirsher static void ftmac100_get_drvinfo(struct net_device *netdev, 816baf0fbfeSJeff Kirsher struct ethtool_drvinfo *info) 817baf0fbfeSJeff Kirsher { 818f029c781SWolfram Sang strscpy(info->driver, DRV_NAME, sizeof(info->driver)); 819f029c781SWolfram Sang strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info)); 820baf0fbfeSJeff Kirsher } 821baf0fbfeSJeff Kirsher 8229da12b64SPhilippe Reynes static int ftmac100_get_link_ksettings(struct net_device *netdev, 8239da12b64SPhilippe Reynes struct ethtool_link_ksettings *cmd) 824baf0fbfeSJeff Kirsher { 825baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 82682c01a84Syuval.shaia@oracle.com 82782c01a84Syuval.shaia@oracle.com mii_ethtool_get_link_ksettings(&priv->mii, cmd); 82882c01a84Syuval.shaia@oracle.com 82982c01a84Syuval.shaia@oracle.com return 0; 830baf0fbfeSJeff Kirsher } 831baf0fbfeSJeff Kirsher 8329da12b64SPhilippe Reynes static int ftmac100_set_link_ksettings(struct net_device *netdev, 8339da12b64SPhilippe Reynes const struct ethtool_link_ksettings *cmd) 834baf0fbfeSJeff Kirsher { 835baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 8369da12b64SPhilippe Reynes return mii_ethtool_set_link_ksettings(&priv->mii, cmd); 837baf0fbfeSJeff Kirsher } 838baf0fbfeSJeff Kirsher 839baf0fbfeSJeff Kirsher static int ftmac100_nway_reset(struct net_device *netdev) 840baf0fbfeSJeff Kirsher { 841baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 842baf0fbfeSJeff Kirsher return mii_nway_restart(&priv->mii); 843baf0fbfeSJeff Kirsher } 844baf0fbfeSJeff Kirsher 845baf0fbfeSJeff Kirsher static u32 ftmac100_get_link(struct net_device *netdev) 846baf0fbfeSJeff Kirsher { 847baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 848baf0fbfeSJeff Kirsher return mii_link_ok(&priv->mii); 849baf0fbfeSJeff Kirsher } 850baf0fbfeSJeff Kirsher 851baf0fbfeSJeff Kirsher static const struct ethtool_ops ftmac100_ethtool_ops = { 852baf0fbfeSJeff Kirsher .get_drvinfo = ftmac100_get_drvinfo, 853baf0fbfeSJeff Kirsher .nway_reset = ftmac100_nway_reset, 854baf0fbfeSJeff Kirsher .get_link = ftmac100_get_link, 8559da12b64SPhilippe Reynes .get_link_ksettings = ftmac100_get_link_ksettings, 8569da12b64SPhilippe Reynes .set_link_ksettings = ftmac100_set_link_ksettings, 857baf0fbfeSJeff Kirsher }; 858baf0fbfeSJeff Kirsher 859baf0fbfeSJeff Kirsher /****************************************************************************** 860baf0fbfeSJeff Kirsher * interrupt handler 861baf0fbfeSJeff Kirsher *****************************************************************************/ 862baf0fbfeSJeff Kirsher static irqreturn_t ftmac100_interrupt(int irq, void *dev_id) 863baf0fbfeSJeff Kirsher { 864baf0fbfeSJeff Kirsher struct net_device *netdev = dev_id; 865baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 866baf0fbfeSJeff Kirsher 867baf0fbfeSJeff Kirsher /* Disable interrupts for polling */ 868baf0fbfeSJeff Kirsher ftmac100_disable_all_int(priv); 869426a593eSVincent Chen if (likely(netif_running(netdev))) 870baf0fbfeSJeff Kirsher napi_schedule(&priv->napi); 871baf0fbfeSJeff Kirsher 872baf0fbfeSJeff Kirsher return IRQ_HANDLED; 873baf0fbfeSJeff Kirsher } 874baf0fbfeSJeff Kirsher 875baf0fbfeSJeff Kirsher /****************************************************************************** 876baf0fbfeSJeff Kirsher * struct napi_struct functions 877baf0fbfeSJeff Kirsher *****************************************************************************/ 878baf0fbfeSJeff Kirsher static int ftmac100_poll(struct napi_struct *napi, int budget) 879baf0fbfeSJeff Kirsher { 880baf0fbfeSJeff Kirsher struct ftmac100 *priv = container_of(napi, struct ftmac100, napi); 881baf0fbfeSJeff Kirsher struct net_device *netdev = priv->netdev; 882baf0fbfeSJeff Kirsher unsigned int status; 883baf0fbfeSJeff Kirsher bool completed = true; 884baf0fbfeSJeff Kirsher int rx = 0; 885baf0fbfeSJeff Kirsher 886baf0fbfeSJeff Kirsher status = ioread32(priv->base + FTMAC100_OFFSET_ISR); 887baf0fbfeSJeff Kirsher 888baf0fbfeSJeff Kirsher if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) { 889baf0fbfeSJeff Kirsher /* 890baf0fbfeSJeff Kirsher * FTMAC100_INT_RPKT_FINISH: 891baf0fbfeSJeff Kirsher * RX DMA has received packets into RX buffer successfully 892baf0fbfeSJeff Kirsher * 893baf0fbfeSJeff Kirsher * FTMAC100_INT_NORXBUF: 894baf0fbfeSJeff Kirsher * RX buffer unavailable 895baf0fbfeSJeff Kirsher */ 896baf0fbfeSJeff Kirsher bool retry; 897baf0fbfeSJeff Kirsher 898baf0fbfeSJeff Kirsher do { 899baf0fbfeSJeff Kirsher retry = ftmac100_rx_packet(priv, &rx); 900baf0fbfeSJeff Kirsher } while (retry && rx < budget); 901baf0fbfeSJeff Kirsher 902baf0fbfeSJeff Kirsher if (retry && rx == budget) 903baf0fbfeSJeff Kirsher completed = false; 904baf0fbfeSJeff Kirsher } 905baf0fbfeSJeff Kirsher 906baf0fbfeSJeff Kirsher if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) { 907baf0fbfeSJeff Kirsher /* 908baf0fbfeSJeff Kirsher * FTMAC100_INT_XPKT_OK: 909baf0fbfeSJeff Kirsher * packet transmitted to ethernet successfully 910baf0fbfeSJeff Kirsher * 911baf0fbfeSJeff Kirsher * FTMAC100_INT_XPKT_LOST: 912baf0fbfeSJeff Kirsher * packet transmitted to ethernet lost due to late 913baf0fbfeSJeff Kirsher * collision or excessive collision 914baf0fbfeSJeff Kirsher */ 915baf0fbfeSJeff Kirsher ftmac100_tx_complete(priv); 916baf0fbfeSJeff Kirsher } 917baf0fbfeSJeff Kirsher 918baf0fbfeSJeff Kirsher if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST | 919baf0fbfeSJeff Kirsher FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) { 920baf0fbfeSJeff Kirsher if (net_ratelimit()) 921baf0fbfeSJeff Kirsher netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status, 922baf0fbfeSJeff Kirsher status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "", 923baf0fbfeSJeff Kirsher status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "", 924baf0fbfeSJeff Kirsher status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "", 925baf0fbfeSJeff Kirsher status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : ""); 926baf0fbfeSJeff Kirsher 927baf0fbfeSJeff Kirsher if (status & FTMAC100_INT_NORXBUF) { 928baf0fbfeSJeff Kirsher /* RX buffer unavailable */ 929baf0fbfeSJeff Kirsher netdev->stats.rx_over_errors++; 930baf0fbfeSJeff Kirsher } 931baf0fbfeSJeff Kirsher 932baf0fbfeSJeff Kirsher if (status & FTMAC100_INT_RPKT_LOST) { 933baf0fbfeSJeff Kirsher /* received packet lost due to RX FIFO full */ 934baf0fbfeSJeff Kirsher netdev->stats.rx_fifo_errors++; 935baf0fbfeSJeff Kirsher } 936baf0fbfeSJeff Kirsher 937baf0fbfeSJeff Kirsher if (status & FTMAC100_INT_PHYSTS_CHG) { 938baf0fbfeSJeff Kirsher /* PHY link status change */ 939baf0fbfeSJeff Kirsher mii_check_link(&priv->mii); 940baf0fbfeSJeff Kirsher } 941baf0fbfeSJeff Kirsher } 942baf0fbfeSJeff Kirsher 943baf0fbfeSJeff Kirsher if (completed) { 944baf0fbfeSJeff Kirsher /* stop polling */ 945baf0fbfeSJeff Kirsher napi_complete(napi); 946baf0fbfeSJeff Kirsher ftmac100_enable_all_int(priv); 947baf0fbfeSJeff Kirsher } 948baf0fbfeSJeff Kirsher 949baf0fbfeSJeff Kirsher return rx; 950baf0fbfeSJeff Kirsher } 951baf0fbfeSJeff Kirsher 952baf0fbfeSJeff Kirsher /****************************************************************************** 953baf0fbfeSJeff Kirsher * struct net_device_ops functions 954baf0fbfeSJeff Kirsher *****************************************************************************/ 955baf0fbfeSJeff Kirsher static int ftmac100_open(struct net_device *netdev) 956baf0fbfeSJeff Kirsher { 957baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 958baf0fbfeSJeff Kirsher int err; 959baf0fbfeSJeff Kirsher 960baf0fbfeSJeff Kirsher err = ftmac100_alloc_buffers(priv); 961baf0fbfeSJeff Kirsher if (err) { 962baf0fbfeSJeff Kirsher netdev_err(netdev, "failed to allocate buffers\n"); 963baf0fbfeSJeff Kirsher goto err_alloc; 964baf0fbfeSJeff Kirsher } 965baf0fbfeSJeff Kirsher 966baf0fbfeSJeff Kirsher err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev); 967baf0fbfeSJeff Kirsher if (err) { 968baf0fbfeSJeff Kirsher netdev_err(netdev, "failed to request irq %d\n", priv->irq); 969baf0fbfeSJeff Kirsher goto err_irq; 970baf0fbfeSJeff Kirsher } 971baf0fbfeSJeff Kirsher 972baf0fbfeSJeff Kirsher priv->rx_pointer = 0; 973baf0fbfeSJeff Kirsher priv->tx_clean_pointer = 0; 974baf0fbfeSJeff Kirsher priv->tx_pointer = 0; 975baf0fbfeSJeff Kirsher priv->tx_pending = 0; 976baf0fbfeSJeff Kirsher 977baf0fbfeSJeff Kirsher err = ftmac100_start_hw(priv); 978baf0fbfeSJeff Kirsher if (err) 979baf0fbfeSJeff Kirsher goto err_hw; 980baf0fbfeSJeff Kirsher 981baf0fbfeSJeff Kirsher napi_enable(&priv->napi); 982baf0fbfeSJeff Kirsher netif_start_queue(netdev); 983baf0fbfeSJeff Kirsher 984baf0fbfeSJeff Kirsher ftmac100_enable_all_int(priv); 985baf0fbfeSJeff Kirsher 986baf0fbfeSJeff Kirsher return 0; 987baf0fbfeSJeff Kirsher 988baf0fbfeSJeff Kirsher err_hw: 989baf0fbfeSJeff Kirsher free_irq(priv->irq, netdev); 990baf0fbfeSJeff Kirsher err_irq: 991baf0fbfeSJeff Kirsher ftmac100_free_buffers(priv); 992baf0fbfeSJeff Kirsher err_alloc: 993baf0fbfeSJeff Kirsher return err; 994baf0fbfeSJeff Kirsher } 995baf0fbfeSJeff Kirsher 996baf0fbfeSJeff Kirsher static int ftmac100_stop(struct net_device *netdev) 997baf0fbfeSJeff Kirsher { 998baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 999baf0fbfeSJeff Kirsher 1000baf0fbfeSJeff Kirsher ftmac100_disable_all_int(priv); 1001baf0fbfeSJeff Kirsher netif_stop_queue(netdev); 1002baf0fbfeSJeff Kirsher napi_disable(&priv->napi); 1003baf0fbfeSJeff Kirsher ftmac100_stop_hw(priv); 1004baf0fbfeSJeff Kirsher free_irq(priv->irq, netdev); 1005baf0fbfeSJeff Kirsher ftmac100_free_buffers(priv); 1006baf0fbfeSJeff Kirsher 1007baf0fbfeSJeff Kirsher return 0; 1008baf0fbfeSJeff Kirsher } 1009baf0fbfeSJeff Kirsher 10100a715156SYueHaibing static netdev_tx_t 10110a715156SYueHaibing ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) 1012baf0fbfeSJeff Kirsher { 1013baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 1014baf0fbfeSJeff Kirsher dma_addr_t map; 1015baf0fbfeSJeff Kirsher 1016baf0fbfeSJeff Kirsher if (unlikely(skb->len > MAX_PKT_SIZE)) { 1017baf0fbfeSJeff Kirsher if (net_ratelimit()) 1018baf0fbfeSJeff Kirsher netdev_dbg(netdev, "tx packet too big\n"); 1019baf0fbfeSJeff Kirsher 1020baf0fbfeSJeff Kirsher netdev->stats.tx_dropped++; 1021baf0fbfeSJeff Kirsher dev_kfree_skb(skb); 1022baf0fbfeSJeff Kirsher return NETDEV_TX_OK; 1023baf0fbfeSJeff Kirsher } 1024baf0fbfeSJeff Kirsher 1025baf0fbfeSJeff Kirsher map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); 1026baf0fbfeSJeff Kirsher if (unlikely(dma_mapping_error(priv->dev, map))) { 1027baf0fbfeSJeff Kirsher /* drop packet */ 1028baf0fbfeSJeff Kirsher if (net_ratelimit()) 1029baf0fbfeSJeff Kirsher netdev_err(netdev, "map socket buffer failed\n"); 1030baf0fbfeSJeff Kirsher 1031baf0fbfeSJeff Kirsher netdev->stats.tx_dropped++; 1032baf0fbfeSJeff Kirsher dev_kfree_skb(skb); 1033baf0fbfeSJeff Kirsher return NETDEV_TX_OK; 1034baf0fbfeSJeff Kirsher } 1035baf0fbfeSJeff Kirsher 1036baf0fbfeSJeff Kirsher return ftmac100_xmit(priv, skb, map); 1037baf0fbfeSJeff Kirsher } 1038baf0fbfeSJeff Kirsher 1039baf0fbfeSJeff Kirsher /* optional */ 1040baf0fbfeSJeff Kirsher static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 1041baf0fbfeSJeff Kirsher { 1042baf0fbfeSJeff Kirsher struct ftmac100 *priv = netdev_priv(netdev); 1043baf0fbfeSJeff Kirsher struct mii_ioctl_data *data = if_mii(ifr); 1044baf0fbfeSJeff Kirsher 1045baf0fbfeSJeff Kirsher return generic_mii_ioctl(&priv->mii, data, cmd, NULL); 1046baf0fbfeSJeff Kirsher } 1047baf0fbfeSJeff Kirsher 104837c84890SSergei Antonov static int ftmac100_change_mtu(struct net_device *netdev, int mtu) 104937c84890SSergei Antonov { 105037c84890SSergei Antonov struct ftmac100 *priv = netdev_priv(netdev); 105137c84890SSergei Antonov unsigned int maccr; 105237c84890SSergei Antonov 105337c84890SSergei Antonov maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR); 105437c84890SSergei Antonov if (mtu > ETH_DATA_LEN) { 105537c84890SSergei Antonov /* process long packets in the driver */ 105637c84890SSergei Antonov maccr |= FTMAC100_MACCR_RX_FTL; 105737c84890SSergei Antonov } else { 105837c84890SSergei Antonov /* Let the controller drop incoming packets greater 105937c84890SSergei Antonov * than 1518 (that is 1500 + 14 Ethernet + 4 FCS). 106037c84890SSergei Antonov */ 106137c84890SSergei Antonov maccr &= ~FTMAC100_MACCR_RX_FTL; 106237c84890SSergei Antonov } 106337c84890SSergei Antonov iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); 106437c84890SSergei Antonov 106537c84890SSergei Antonov netdev->mtu = mtu; 106637c84890SSergei Antonov 106737c84890SSergei Antonov return 0; 106837c84890SSergei Antonov } 106937c84890SSergei Antonov 1070baf0fbfeSJeff Kirsher static const struct net_device_ops ftmac100_netdev_ops = { 1071baf0fbfeSJeff Kirsher .ndo_open = ftmac100_open, 1072baf0fbfeSJeff Kirsher .ndo_stop = ftmac100_stop, 1073baf0fbfeSJeff Kirsher .ndo_start_xmit = ftmac100_hard_start_xmit, 1074baf0fbfeSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 1075baf0fbfeSJeff Kirsher .ndo_validate_addr = eth_validate_addr, 1076a7605370SArnd Bergmann .ndo_eth_ioctl = ftmac100_do_ioctl, 107737c84890SSergei Antonov .ndo_change_mtu = ftmac100_change_mtu, 1078baf0fbfeSJeff Kirsher }; 1079baf0fbfeSJeff Kirsher 1080baf0fbfeSJeff Kirsher /****************************************************************************** 1081baf0fbfeSJeff Kirsher * struct platform_driver functions 1082baf0fbfeSJeff Kirsher *****************************************************************************/ 1083baf0fbfeSJeff Kirsher static int ftmac100_probe(struct platform_device *pdev) 1084baf0fbfeSJeff Kirsher { 1085baf0fbfeSJeff Kirsher struct resource *res; 1086baf0fbfeSJeff Kirsher int irq; 1087baf0fbfeSJeff Kirsher struct net_device *netdev; 1088baf0fbfeSJeff Kirsher struct ftmac100 *priv; 1089baf0fbfeSJeff Kirsher int err; 1090baf0fbfeSJeff Kirsher 1091baf0fbfeSJeff Kirsher res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1092baf0fbfeSJeff Kirsher if (!res) 1093baf0fbfeSJeff Kirsher return -ENXIO; 1094baf0fbfeSJeff Kirsher 1095baf0fbfeSJeff Kirsher irq = platform_get_irq(pdev, 0); 1096baf0fbfeSJeff Kirsher if (irq < 0) 1097baf0fbfeSJeff Kirsher return irq; 1098baf0fbfeSJeff Kirsher 1099baf0fbfeSJeff Kirsher /* setup net_device */ 1100baf0fbfeSJeff Kirsher netdev = alloc_etherdev(sizeof(*priv)); 1101baf0fbfeSJeff Kirsher if (!netdev) { 1102baf0fbfeSJeff Kirsher err = -ENOMEM; 1103baf0fbfeSJeff Kirsher goto err_alloc_etherdev; 1104baf0fbfeSJeff Kirsher } 1105baf0fbfeSJeff Kirsher 1106baf0fbfeSJeff Kirsher SET_NETDEV_DEV(netdev, &pdev->dev); 11077ad24ea4SWilfried Klaebe netdev->ethtool_ops = &ftmac100_ethtool_ops; 1108baf0fbfeSJeff Kirsher netdev->netdev_ops = &ftmac100_netdev_ops; 110930f837b7SVladimir Oltean netdev->max_mtu = MAX_PKT_SIZE - VLAN_ETH_HLEN; 1110baf0fbfeSJeff Kirsher 1111f7650d82SSergei Antonov err = platform_get_ethdev_address(&pdev->dev, netdev); 1112f7650d82SSergei Antonov if (err == -EPROBE_DEFER) 1113f7650d82SSergei Antonov goto defer_get_mac; 1114f7650d82SSergei Antonov 1115baf0fbfeSJeff Kirsher platform_set_drvdata(pdev, netdev); 1116baf0fbfeSJeff Kirsher 1117baf0fbfeSJeff Kirsher /* setup private data */ 1118baf0fbfeSJeff Kirsher priv = netdev_priv(netdev); 1119baf0fbfeSJeff Kirsher priv->netdev = netdev; 1120baf0fbfeSJeff Kirsher priv->dev = &pdev->dev; 1121baf0fbfeSJeff Kirsher 1122baf0fbfeSJeff Kirsher spin_lock_init(&priv->tx_lock); 1123baf0fbfeSJeff Kirsher 1124baf0fbfeSJeff Kirsher /* initialize NAPI */ 1125b48b89f9SJakub Kicinski netif_napi_add(netdev, &priv->napi, ftmac100_poll); 1126baf0fbfeSJeff Kirsher 1127baf0fbfeSJeff Kirsher /* map io memory */ 1128baf0fbfeSJeff Kirsher priv->res = request_mem_region(res->start, resource_size(res), 1129baf0fbfeSJeff Kirsher dev_name(&pdev->dev)); 1130baf0fbfeSJeff Kirsher if (!priv->res) { 1131baf0fbfeSJeff Kirsher dev_err(&pdev->dev, "Could not reserve memory region\n"); 1132baf0fbfeSJeff Kirsher err = -ENOMEM; 1133baf0fbfeSJeff Kirsher goto err_req_mem; 1134baf0fbfeSJeff Kirsher } 1135baf0fbfeSJeff Kirsher 1136baf0fbfeSJeff Kirsher priv->base = ioremap(res->start, resource_size(res)); 1137baf0fbfeSJeff Kirsher if (!priv->base) { 1138baf0fbfeSJeff Kirsher dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); 1139baf0fbfeSJeff Kirsher err = -EIO; 1140baf0fbfeSJeff Kirsher goto err_ioremap; 1141baf0fbfeSJeff Kirsher } 1142baf0fbfeSJeff Kirsher 1143baf0fbfeSJeff Kirsher priv->irq = irq; 1144baf0fbfeSJeff Kirsher 1145baf0fbfeSJeff Kirsher /* initialize struct mii_if_info */ 1146baf0fbfeSJeff Kirsher priv->mii.phy_id = 0; 1147baf0fbfeSJeff Kirsher priv->mii.phy_id_mask = 0x1f; 1148baf0fbfeSJeff Kirsher priv->mii.reg_num_mask = 0x1f; 1149baf0fbfeSJeff Kirsher priv->mii.dev = netdev; 1150baf0fbfeSJeff Kirsher priv->mii.mdio_read = ftmac100_mdio_read; 1151baf0fbfeSJeff Kirsher priv->mii.mdio_write = ftmac100_mdio_write; 1152baf0fbfeSJeff Kirsher 1153baf0fbfeSJeff Kirsher /* register network device */ 1154baf0fbfeSJeff Kirsher err = register_netdev(netdev); 1155baf0fbfeSJeff Kirsher if (err) { 1156baf0fbfeSJeff Kirsher dev_err(&pdev->dev, "Failed to register netdev\n"); 1157baf0fbfeSJeff Kirsher goto err_register_netdev; 1158baf0fbfeSJeff Kirsher } 1159baf0fbfeSJeff Kirsher 1160baf0fbfeSJeff Kirsher netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base); 1161baf0fbfeSJeff Kirsher 1162baf0fbfeSJeff Kirsher if (!is_valid_ether_addr(netdev->dev_addr)) { 1163f2cedb63SDanny Kukawka eth_hw_addr_random(netdev); 1164baf0fbfeSJeff Kirsher netdev_info(netdev, "generated random MAC address %pM\n", 1165baf0fbfeSJeff Kirsher netdev->dev_addr); 1166baf0fbfeSJeff Kirsher } 1167baf0fbfeSJeff Kirsher 1168baf0fbfeSJeff Kirsher return 0; 1169baf0fbfeSJeff Kirsher 1170baf0fbfeSJeff Kirsher err_register_netdev: 1171baf0fbfeSJeff Kirsher iounmap(priv->base); 1172baf0fbfeSJeff Kirsher err_ioremap: 1173baf0fbfeSJeff Kirsher release_resource(priv->res); 1174baf0fbfeSJeff Kirsher err_req_mem: 1175baf0fbfeSJeff Kirsher netif_napi_del(&priv->napi); 1176f7650d82SSergei Antonov defer_get_mac: 1177baf0fbfeSJeff Kirsher free_netdev(netdev); 1178baf0fbfeSJeff Kirsher err_alloc_etherdev: 1179baf0fbfeSJeff Kirsher return err; 1180baf0fbfeSJeff Kirsher } 1181baf0fbfeSJeff Kirsher 1182be12502eSDmitry Torokhov static int ftmac100_remove(struct platform_device *pdev) 1183baf0fbfeSJeff Kirsher { 1184baf0fbfeSJeff Kirsher struct net_device *netdev; 1185baf0fbfeSJeff Kirsher struct ftmac100 *priv; 1186baf0fbfeSJeff Kirsher 1187baf0fbfeSJeff Kirsher netdev = platform_get_drvdata(pdev); 1188baf0fbfeSJeff Kirsher priv = netdev_priv(netdev); 1189baf0fbfeSJeff Kirsher 1190baf0fbfeSJeff Kirsher unregister_netdev(netdev); 1191baf0fbfeSJeff Kirsher 1192baf0fbfeSJeff Kirsher iounmap(priv->base); 1193baf0fbfeSJeff Kirsher release_resource(priv->res); 1194baf0fbfeSJeff Kirsher 1195baf0fbfeSJeff Kirsher netif_napi_del(&priv->napi); 1196baf0fbfeSJeff Kirsher free_netdev(netdev); 1197baf0fbfeSJeff Kirsher return 0; 1198baf0fbfeSJeff Kirsher } 1199baf0fbfeSJeff Kirsher 120047ab37a1SGreentime Hu static const struct of_device_id ftmac100_of_ids[] = { 120147ab37a1SGreentime Hu { .compatible = "andestech,atmac100" }, 120247ab37a1SGreentime Hu { } 120347ab37a1SGreentime Hu }; 120447ab37a1SGreentime Hu 1205baf0fbfeSJeff Kirsher static struct platform_driver ftmac100_driver = { 1206baf0fbfeSJeff Kirsher .probe = ftmac100_probe, 1207be12502eSDmitry Torokhov .remove = ftmac100_remove, 1208baf0fbfeSJeff Kirsher .driver = { 1209baf0fbfeSJeff Kirsher .name = DRV_NAME, 121047ab37a1SGreentime Hu .of_match_table = ftmac100_of_ids 1211baf0fbfeSJeff Kirsher }, 1212baf0fbfeSJeff Kirsher }; 1213baf0fbfeSJeff Kirsher 1214baf0fbfeSJeff Kirsher /****************************************************************************** 1215baf0fbfeSJeff Kirsher * initialization / finalization 1216baf0fbfeSJeff Kirsher *****************************************************************************/ 1217d280a2c2SZhichao Cai module_platform_driver(ftmac100_driver); 1218baf0fbfeSJeff Kirsher 1219baf0fbfeSJeff Kirsher MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>"); 1220baf0fbfeSJeff Kirsher MODULE_DESCRIPTION("FTMAC100 driver"); 1221baf0fbfeSJeff Kirsher MODULE_LICENSE("GPL"); 122247ab37a1SGreentime Hu MODULE_DEVICE_TABLE(of, ftmac100_of_ids); 1223