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