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