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