jme.c revision c8f44affb7244f2ac3e703cab13d55ede27621bb
195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver 395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Copyright 2008 JMicron Technology Corporation 595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * http://www.jmicron.com/ 6e47dfcd81edb7c6065fd2219c818b3b526bd624dGuo-Fu Tseng * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org> 795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Author: Guo-Fu Tseng <cooldavid@cooldavid.org> 995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 1095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This program is free software; you can redistribute it and/or modify 1195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * it under the terms of the GNU General Public License as published by 1295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the Free Software Foundation; either version 2 of the License. 1395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 1495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This program is distributed in the hope that it will be useful, 1595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * but WITHOUT ANY WARRANTY; without even the implied warranty of 1695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * GNU General Public License for more details. 1895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 1995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * You should have received a copy of the GNU General Public License 2095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * along with this program; if not, write to the Free Software 2195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 2395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 2495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2549d70c4856acfce943fab35fc199b3074961313fJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2649d70c4856acfce943fab35fc199b3074961313fJoe Perches 2795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/module.h> 2895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/kernel.h> 2995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/pci.h> 3095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/netdevice.h> 3195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/etherdevice.h> 3295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/ethtool.h> 3395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/mii.h> 3495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/crc32.h> 3595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/delay.h> 3695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/spinlock.h> 3795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/in.h> 3895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/ip.h> 3995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/ipv6.h> 4095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/tcp.h> 4195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/udp.h> 4295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/if_vlan.h> 435a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 44b7c6bfb710cfd6552c3186cb8ce1ac9eef7a0e3dKamalesh Babulal#include <net/ip6_checksum.h> 4595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include "jme.h" 4695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 4795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int force_pseudohp = -1; 4895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int no_pseudohp = -1; 4995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int no_extplug = -1; 5095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param(force_pseudohp, int, 0); 5195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(force_pseudohp, 5295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Enable pseudo hot-plug feature manually by driver instead of BIOS."); 5395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param(no_pseudohp, int, 0); 5495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(no_pseudohp, "Disable pseudo hot-plug feature."); 5595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param(no_extplug, int, 0); 5695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(no_extplug, 5795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Do not use external plug signal for pseudo hot-plug."); 5895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 5995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 6095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_mdio_read(struct net_device *netdev, int phy, int reg) 6195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 6295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 6395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, val, again = (reg == MII_BMSR) ? 1 : 0; 6495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 6595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengread_again: 6695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMI, SMI_OP_REQ | 6795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smi_phy_addr(phy) | 6895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smi_reg_addr(reg)); 6995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 7095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 7195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) { 7295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng udelay(20); 7395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMI); 7495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((val & SMI_OP_REQ) == 0) 7595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 7695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 7795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 7895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (i == 0) { 7949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("phy(%d) read timeout : %d\n", phy, reg); 8095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 8195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 8295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 8395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (again--) 8495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto read_again; 8595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 8695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return (val & SMI_DATA_MASK) >> SMI_DATA_SHIFT; 8795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 8895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 8995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 9095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_mdio_write(struct net_device *netdev, 9195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int phy, int reg, int val) 9295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 9395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 9495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 9595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 9695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMI, SMI_OP_WRITE | SMI_OP_REQ | 9795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((val << SMI_DATA_SHIFT) & SMI_DATA_MASK) | 9895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smi_phy_addr(phy) | smi_reg_addr(reg)); 9995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 10095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 10195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) { 10295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng udelay(20); 10395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((jread32(jme, JME_SMI) & SMI_OP_REQ) == 0) 10495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 10595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 10695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 10795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (i == 0) 10849d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("phy(%d) write timeout : %d\n", phy, reg); 10995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 11095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 11195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 11295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_reset_phy_processor(struct jme_adapter *jme) 11395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 11495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 11595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 11695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, 11795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id, 11895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_ADVERTISE, ADVERTISE_ALL | 11995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); 12095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 12195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) 12295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, 12395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id, 12495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_CTRL1000, 12595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ADVERTISE_1000FULL | ADVERTISE_1000HALF); 12695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 12795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jme_mdio_read(jme->dev, 12895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id, 12995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_BMCR); 13095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 13195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, 13295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id, 13395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_BMCR, val | BMCR_RESET); 13495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 13595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 13695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 13795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_setup_wakeup_frame(struct jme_adapter *jme, 138b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches const u32 *mask, u32 crc, int fnr) 13995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 14095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 14195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 14295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 14395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup CRC pattern 14495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 14595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_WFOI, WFOI_CRC_SEL | (fnr & WFOI_FRAME_SEL)); 14695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 14795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_WFODP, crc); 14895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 14995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 15095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 15195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup Mask 15295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 15395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < WAKEUP_FRAME_MASK_DWNR ; ++i) { 15495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_WFOI, 15595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((i << WFOI_MASK_SHIFT) & WFOI_MASK_SEL) | 15695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (fnr & WFOI_FRAME_SEL)); 15795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 15895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_WFODP, mask[i]); 15995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 16095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 16195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 16295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 16395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 164854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_mac_rxclk_off(struct jme_adapter *jme) 165854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 166854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 |= GPREG1_RXCLKOFF; 167854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); 168854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 169854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 170854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 171854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_mac_rxclk_on(struct jme_adapter *jme) 172854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 173854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF; 174854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); 175854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 176854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 177854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 178854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_mac_txclk_off(struct jme_adapter *jme) 179854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 180854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC); 181854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GHC, jme->reg_ghc); 182854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 183854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 184854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 185854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_mac_txclk_on(struct jme_adapter *jme) 186854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 187854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng u32 speed = jme->reg_ghc & GHC_SPEED; 188854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (speed == GHC_SPEED_1000M) 189854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY; 190854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng else 191854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; 192854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GHC, jme->reg_ghc); 193854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 194854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 195854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 196854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_reset_ghc_speed(struct jme_adapter *jme) 197854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 198854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX); 199854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GHC, jme->reg_ghc); 200854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 201854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 202854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 203854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_reset_250A2_workaround(struct jme_adapter *jme) 204854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 205854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | 206854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng GPREG1_RSSPATCH); 207854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); 208854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 209854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 210854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 211854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_assert_ghc_reset(struct jme_adapter *jme) 212854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 213854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_SWRST; 214854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GHC, jme->reg_ghc); 215854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 216854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 217854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 218854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengjme_clear_ghc_reset(struct jme_adapter *jme) 219854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 220854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc &= ~GHC_SWRST; 221854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_GHC, jme->reg_ghc); 222854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 223854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 224854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic inline void 22595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_reset_mac_processor(struct jme_adapter *jme) 22695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 227b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0}; 22895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 crc = 0xCDCDCDCD; 22995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 gpreg0; 23095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 23195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_reset_ghc_speed(jme); 233854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_reset_250A2_workaround(jme); 234854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 235854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_on(jme); 236854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_on(jme); 237854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng udelay(1); 238854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_assert_ghc_reset(jme); 239854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng udelay(1); 240854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_off(jme); 241854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_off(jme); 242854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng udelay(1); 243854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_clear_ghc_reset(jme); 244854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng udelay(1); 245854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_on(jme); 246854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_on(jme); 247854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng udelay(1); 248854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_off(jme); 249854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_off(jme); 25095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 25195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXDBA_LO, 0x00000000); 25295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXDBA_HI, 0x00000000); 25395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXQDC, 0x00000000); 25495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXNDA, 0x00000000); 25595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXDBA_LO, 0x00000000); 25695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXDBA_HI, 0x00000000); 25795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXQDC, 0x00000000); 25895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXNDA, 0x00000000); 25995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 26095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_LO, 0x00000000); 26195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_HI, 0x00000000); 26295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < WAKEUP_FRAME_NR ; ++i) 26395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_setup_wakeup_frame(jme, mask, crc, i); 26495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) 26595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng gpreg0 = GPREG0_DEFAULT | GPREG0_LNKINTPOLL; 26695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 26795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng gpreg0 = GPREG0_DEFAULT; 26895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_GPREG0, gpreg0); 26995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 27095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 27195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 27295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_clear_pm(struct jme_adapter *jme) 27395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 274bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs); 27595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 27695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 27795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 27895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_reload_eeprom(struct jme_adapter *jme) 27995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 28095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 28195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 28295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 28395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 28495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 28595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (val & SMBCSR_EEPROMD) { 28695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val |= SMBCSR_CNACK; 28795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBCSR, val); 28895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val |= SMBCSR_RELOAD; 28995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBCSR, val); 29095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(12); 29195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 29295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = JME_EEPROM_RELOAD_TIMEOUT; i > 0; --i) { 29395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(1); 29495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((jread32(jme, JME_SMBCSR) & SMBCSR_RELOAD) == 0) 29595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 29695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 29795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 29895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (i == 0) { 29949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("eeprom reload timeout\n"); 30095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EIO; 30195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 30295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 30395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 30495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 30595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 30695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 30795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 30895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_load_macaddr(struct net_device *netdev) 30995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 31095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 31195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unsigned char macaddr[6]; 31295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 31395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->macaddr_lock); 31595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_RXUMA_LO); 31695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[0] = (val >> 0) & 0xFF; 31795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[1] = (val >> 8) & 0xFF; 31895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[2] = (val >> 16) & 0xFF; 31995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[3] = (val >> 24) & 0xFF; 32095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_RXUMA_HI); 32195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[4] = (val >> 0) & 0xFF; 32295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng macaddr[5] = (val >> 8) & 0xFF; 32395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(netdev->dev_addr, macaddr, 6); 32495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->macaddr_lock); 32595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 32695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 32795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 32895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_rx_pcc(struct jme_adapter *jme, int p) 32995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 33095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (p) { 33195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_OFF: 33295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PCCRX0, 33395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_OFF_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | 33495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_OFF_CNT << PCCRX_SHIFT) & PCCRX_MASK)); 33595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 33695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P1: 33795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PCCRX0, 33895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P1_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | 33995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P1_CNT << PCCRX_SHIFT) & PCCRX_MASK)); 34095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 34195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P2: 34295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PCCRX0, 34395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P2_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | 34495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P2_CNT << PCCRX_SHIFT) & PCCRX_MASK)); 34595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 34695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P3: 34795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PCCRX0, 34895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P3_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | 34995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_P3_CNT << PCCRX_SHIFT) & PCCRX_MASK)); 35095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 35195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 35295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 35395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 35495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 35595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 35695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(test_bit(JME_FLAG_POLL, &jme->flags))) 357f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches netif_info(jme, rx_status, jme->dev, "Switched to PCC_P%d\n", p); 35895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 35995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 36095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 36195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_start_irq(struct jme_adapter *jme) 36295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 36395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng register struct dynpcc_info *dpi = &(jme->dpi); 36495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 36595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 36695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cur = PCC_P1; 36795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->attempt = PCC_P1; 36895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 36995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 37095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PCCTX, 37195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_TX_TO << PCCTXTO_SHIFT) & PCCTXTO_MASK) | 37295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((PCC_TX_CNT << PCCTX_SHIFT) & PCCTX_MASK) | 37395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCCTXQ0_EN 37495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ); 37595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 37695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 37795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Enable Interrupts 37895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 37995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_IENS, INTR_ENABLE); 38095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 38195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 38295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 38395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_stop_irq(struct jme_adapter *jme) 38495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 38595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 38695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Disable Interrupts 38795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 38895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_IENC, INTR_ENABLE); 38995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 39095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 39195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u32 39295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_linkstat_from_phy(struct jme_adapter *jme) 39395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 39495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 phylink, bmsr; 39595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 39695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 17); 39795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmsr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMSR); 39895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (bmsr & BMSR_ANCOMP) 39995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink |= PHY_LINK_AUTONEG_COMPLETE; 40095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 40195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return phylink; 40295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 40395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 40495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 40551754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tsengjme_set_phyfifo_5level(struct jme_adapter *jme) 40695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 40795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004); 40895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 40995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 41095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 41151754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tsengjme_set_phyfifo_8level(struct jme_adapter *jme) 41295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 41395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000); 41495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 41595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 41695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 41795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_check_link(struct net_device *netdev, int testonly) 41895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 41995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 420854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr; 42195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng char linkmsg[64]; 42295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc = 0; 42395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 42495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng linkmsg[0] = '\0'; 42595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 42695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) 42795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 42895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 42995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jread32(jme, JME_PHY_LINK); 43095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 43195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (phylink & PHY_LINK_UP) { 43295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(phylink & PHY_LINK_AUTONEG_COMPLETE)) { 43395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 43495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * If we did not enable AN 43595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Speed/Duplex Info should be obtained from SMI 43695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 43795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = PHY_LINK_UP; 43895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 43995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(jme->dev, 44095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id, 44195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_BMCR); 44295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 44395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink |= ((bmcr & BMCR_SPEED1000) && 44495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (bmcr & BMCR_SPEED100) == 0) ? 44595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PHY_LINK_SPEED_1000M : 44695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (bmcr & BMCR_SPEED100) ? 44795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PHY_LINK_SPEED_100M : 44895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PHY_LINK_SPEED_10M; 44995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 45095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink |= (bmcr & BMCR_FULLDPLX) ? 45195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PHY_LINK_DUPLEX : 0; 45295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 45395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng strcat(linkmsg, "Forced: "); 45495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 45595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 45695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Keep polling for speed/duplex resolve complete 45795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 45895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (!(phylink & PHY_LINK_SPEEDDPU_RESOLVED) && 45995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng --cnt) { 46095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 46195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng udelay(1); 46295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 46395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) 46495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 46595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 46695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jread32(jme, JME_PHY_LINK); 46795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 46895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!cnt) 46949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Waiting speed resolve timeout\n"); 47095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 47195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng strcat(linkmsg, "ANed: "); 47295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 47395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 47495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->phylink == phylink) { 47595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = 1; 47695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 47795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 47895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (testonly) 47995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 48095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 48195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = phylink; 48295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 483854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 484854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * The speed/duplex setting of jme->reg_ghc already cleared 485854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * by jme_reset_mac_processor() 486854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 48795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (phylink & PHY_LINK_SPEED_MASK) { 48895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PHY_LINK_SPEED_10M: 489854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_SPEED_10M; 49095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng strcat(linkmsg, "10 Mbps, "); 49195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 49295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PHY_LINK_SPEED_100M: 493854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_SPEED_100M; 49495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng strcat(linkmsg, "100 Mbps, "); 49595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 49695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PHY_LINK_SPEED_1000M: 497854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_SPEED_1000M; 49895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng strcat(linkmsg, "1000 Mbps, "); 49995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 50095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 50195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 50295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 50395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 50495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (phylink & PHY_LINK_DUPLEX) { 50595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); 5063903c023570446303a10f152cfc120dcbf9a4ccfGuo-Fu Tseng jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX); 507854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_ghc |= GHC_DPX; 50895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 50995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | 51095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXMCS_BACKOFF | 51195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXMCS_CARRIERSENSE | 51295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXMCS_COLLISION); 5133903c023570446303a10f152cfc120dcbf9a4ccfGuo-Fu Tseng jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX); 51495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 515a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng 516854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32(jme, JME_GHC, jme->reg_ghc); 517854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 518a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng if (is_buggy250(jme->pdev->device, jme->chiprev)) { 519854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | 520854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng GPREG1_RSSPATCH); 521a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng if (!(phylink & PHY_LINK_DUPLEX)) 522854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH; 523a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng switch (phylink & PHY_LINK_SPEED_MASK) { 524a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng case PHY_LINK_SPEED_10M: 52551754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng jme_set_phyfifo_8level(jme); 526854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 |= GPREG1_RSSPATCH; 527a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng break; 528a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng case PHY_LINK_SPEED_100M: 52951754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng jme_set_phyfifo_5level(jme); 530854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 |= GPREG1_RSSPATCH; 531a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng break; 532a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng case PHY_LINK_SPEED_1000M: 53351754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng jme_set_phyfifo_8level(jme); 534a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng break; 535a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng default: 536a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng break; 537a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng } 538a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng } 539854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); 54095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 5414f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? 5424f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting "Full-Duplex, " : 5434f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting "Half-Duplex, "); 5444f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting strcat(linkmsg, (phylink & PHY_LINK_MDI_STAT) ? 5454f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting "MDI-X" : 5464f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting "MDI"); 54749d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, link, jme->dev, "Link is up at %s\n", linkmsg); 54895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_on(netdev); 54995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 55095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (testonly) 55195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 55295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 55349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, link, jme->dev, "Link is down\n"); 55495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 55595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 55695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 55795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 55895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout: 55995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 56095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 56195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 56295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 56395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_setup_tx_resources(struct jme_adapter *jme) 56495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 56595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 56695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 56795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->alloc = dma_alloc_coherent(&(jme->pdev->dev), 56895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TX_RING_ALLOC_SIZE(jme->tx_ring_size), 56995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &(txring->dmaalloc), 57095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng GFP_ATOMIC); 57195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 57247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (!txring->alloc) 57347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng goto err_set_null; 57495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 57595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 57695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 16 Bytes align 57795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 57895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->desc = (void *)ALIGN((unsigned long)(txring->alloc), 57995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RING_DESC_ALIGN); 58095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->dma = ALIGN(txring->dmaalloc, RING_DESC_ALIGN); 58195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->next_to_use = 0; 58295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&txring->next_to_clean, 0); 58395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&txring->nr_free, jme->tx_ring_size); 58495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 58547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->bufinf = kmalloc(sizeof(struct jme_buffer_info) * 58647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng jme->tx_ring_size, GFP_ATOMIC); 58747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (unlikely(!(txring->bufinf))) 58847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng goto err_free_txring; 58947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 59095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 59195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Initialize Transmit Descriptors 59295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 59395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(txring->alloc, 0, TX_RING_ALLOC_SIZE(jme->tx_ring_size)); 59495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(txring->bufinf, 0, 59595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng sizeof(struct jme_buffer_info) * jme->tx_ring_size); 59695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 59795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 59847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 59947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengerr_free_txring: 60047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng dma_free_coherent(&(jme->pdev->dev), 60147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng TX_RING_ALLOC_SIZE(jme->tx_ring_size), 60247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->alloc, 60347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->dmaalloc); 60447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 60547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengerr_set_null: 60647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->desc = NULL; 60747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->dmaalloc = 0; 60847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->dma = 0; 60947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->bufinf = NULL; 61047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 61147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng return -ENOMEM; 61295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 61395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 61495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 61595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_free_tx_resources(struct jme_adapter *jme) 61695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 61795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 61895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 619eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_buffer_info *txbi; 62095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 62195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (txring->alloc) { 62247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (txring->bufinf) { 62347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng for (i = 0 ; i < jme->tx_ring_size ; ++i) { 62447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi = txring->bufinf + i; 62547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (txbi->skb) { 62647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng dev_kfree_skb(txbi->skb); 62747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi->skb = NULL; 62847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng } 62947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi->mapping = 0; 63047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi->len = 0; 63147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi->nr_desc = 0; 63247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txbi->start_xmit = 0; 63395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 63447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng kfree(txring->bufinf); 63595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 63695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 63795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_free_coherent(&(jme->pdev->dev), 63895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TX_RING_ALLOC_SIZE(jme->tx_ring_size), 63995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->alloc, 64095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->dmaalloc); 64195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 64295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->alloc = NULL; 64395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->desc = NULL; 64495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->dmaalloc = 0; 64595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->dma = 0; 64647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng txring->bufinf = NULL; 64795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 64895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->next_to_use = 0; 64995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&txring->next_to_clean, 0); 65095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&txring->nr_free, 0); 65195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 65295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 65395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 65495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_enable_tx_engine(struct jme_adapter *jme) 65595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 65695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 65795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Select Queue 0 65895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 65995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXCS, TXCS_DEFAULT | TXCS_SELECT_QUEUE0); 66095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 66195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 66295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 66395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup TX Queue 0 DMA Bass Address 66495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 66595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXDBA_LO, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL); 66695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXDBA_HI, (__u64)(jme->txring[0].dma) >> 32); 66795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXNDA, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL); 66895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 66995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 67095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup TX Descptor Count 67195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 67295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXQDC, jme->tx_ring_size); 67395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 67495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 67595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Enable TX Engine 67695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 67795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 678854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_TXCS, jme->reg_txcs | 67995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_SELECT_QUEUE0 | 68095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_ENABLE); 68195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 682854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 683854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Start clock for TX MAC Processor 684854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 685854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_on(jme); 68695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 68795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 68895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 68995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_restart_tx_engine(struct jme_adapter *jme) 69095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 69195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 69295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Restart TX Engine 69395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 69495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXCS, jme->reg_txcs | 69595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_SELECT_QUEUE0 | 69695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_ENABLE); 69795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 69895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 69995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 70095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_disable_tx_engine(struct jme_adapter *jme) 70195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 70295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 70395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 70495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 70595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 70695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Disable TX Engine 70795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 70895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0); 70995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 71095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 71195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_TXCS); 71295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = JME_TX_DISABLE_TIMEOUT ; (val & TXCS_ENABLE) && i > 0 ; --i) { 71395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(1); 71495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_TXCS); 71595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rmb(); 71695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 71795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 71895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!i) 71949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Disable TX engine timeout\n"); 720854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 721854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 722854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Stop clock for TX MAC Processor 723854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 724854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_txclk_off(jme); 72595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 72695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 72795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 72895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_clean_rxdesc(struct jme_adapter *jme, int i) 72995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 730eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 73195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng register struct rxdesc *rxdesc = rxring->desc; 73295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *rxbi = rxring->bufinf; 73395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc += i; 73495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi += i; 73595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 73695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->dw[0] = 0; 73795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->dw[1] = 0; 73895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->desc1.bufaddrh = cpu_to_le32((__u64)rxbi->mapping >> 32); 73995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->desc1.bufaddrl = cpu_to_le32( 74095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (__u64)rxbi->mapping & 0xFFFFFFFFUL); 74195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->desc1.datalen = cpu_to_le16(rxbi->len); 74295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->dev->features & NETIF_F_HIGHDMA) 74395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->desc1.flags = RXFLAG_64BIT; 74495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 74595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->desc1.flags |= RXFLAG_OWN | RXFLAG_INT; 74695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 74795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 74895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 74995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_make_new_rx_buf(struct jme_adapter *jme, int i) 75095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 75195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 75295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *rxbi = rxring->bufinf + i; 75395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sk_buff *skb; 75494c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng dma_addr_t mapping; 75595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 75695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb = netdev_alloc_skb(jme->dev, 75795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dev->mtu + RX_EXTRA_LEN); 75895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!skb)) 75995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -ENOMEM; 76095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 76194c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng mapping = pci_map_page(jme->pdev, virt_to_page(skb->data), 76294c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng offset_in_page(skb->data), skb_tailroom(skb), 76394c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng PCI_DMA_FROMDEVICE); 76494c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng if (unlikely(pci_dma_mapping_error(jme->pdev, mapping))) { 76594c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng dev_kfree_skb(skb); 76694c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng return -ENOMEM; 76794c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng } 76894c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng 76994c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng if (likely(rxbi->mapping)) 77094c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng pci_unmap_page(jme->pdev, rxbi->mapping, 77194c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng rxbi->len, PCI_DMA_FROMDEVICE); 77294c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng 77395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->skb = skb; 77495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->len = skb_tailroom(skb); 77594c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng rxbi->mapping = mapping; 77695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 77795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 77895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 77995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 78095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_free_rx_buf(struct jme_adapter *jme, int i) 78195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 78295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 78395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *rxbi = rxring->bufinf; 78495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi += i; 78595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 78695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rxbi->skb) { 78795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_unmap_page(jme->pdev, 78895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->mapping, 78995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->len, 79095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_FROMDEVICE); 79195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(rxbi->skb); 79295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->skb = NULL; 79395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->mapping = 0; 79495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->len = 0; 79595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 79695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 79795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 79895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 79995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_free_rx_resources(struct jme_adapter *jme) 80095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 80195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 80295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 80395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 80495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rxring->alloc) { 80547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (rxring->bufinf) { 80647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng for (i = 0 ; i < jme->rx_ring_size ; ++i) 80747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng jme_free_rx_buf(jme, i); 80847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng kfree(rxring->bufinf); 80947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng } 81095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 81195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_free_coherent(&(jme->pdev->dev), 81295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RX_RING_ALLOC_SIZE(jme->rx_ring_size), 81395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->alloc, 81495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->dmaalloc); 81595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->alloc = NULL; 81695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->desc = NULL; 81795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->dmaalloc = 0; 81895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->dma = 0; 81947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->bufinf = NULL; 82095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 82195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->next_to_use = 0; 82295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&rxring->next_to_clean, 0); 82395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 82495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 82595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 82695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_setup_rx_resources(struct jme_adapter *jme) 82795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 82895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 82995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 83095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 83195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->alloc = dma_alloc_coherent(&(jme->pdev->dev), 83295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RX_RING_ALLOC_SIZE(jme->rx_ring_size), 83395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &(rxring->dmaalloc), 83495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng GFP_ATOMIC); 83547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (!rxring->alloc) 83647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng goto err_set_null; 83795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 83895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 83995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 16 Bytes align 84095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 84195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->desc = (void *)ALIGN((unsigned long)(rxring->alloc), 84295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RING_DESC_ALIGN); 84395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->dma = ALIGN(rxring->dmaalloc, RING_DESC_ALIGN); 84495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxring->next_to_use = 0; 84595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&rxring->next_to_clean, 0); 84695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 84747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->bufinf = kmalloc(sizeof(struct jme_buffer_info) * 84847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng jme->rx_ring_size, GFP_ATOMIC); 84947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng if (unlikely(!(rxring->bufinf))) 85047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng goto err_free_rxring; 85147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 85295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 85395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Initiallize Receive Descriptors 85495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 85547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng memset(rxring->bufinf, 0, 85647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng sizeof(struct jme_buffer_info) * jme->rx_ring_size); 85795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < jme->rx_ring_size ; ++i) { 85895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(jme_make_new_rx_buf(jme, i))) { 85995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 86095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -ENOMEM; 86195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 86295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 86395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_clean_rxdesc(jme, i); 86495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 86595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 86695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 86747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 86847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengerr_free_rxring: 86947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng dma_free_coherent(&(jme->pdev->dev), 87047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng RX_RING_ALLOC_SIZE(jme->rx_ring_size), 87147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->alloc, 87247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->dmaalloc); 87347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengerr_set_null: 87447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->desc = NULL; 87547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->dmaalloc = 0; 87647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->dma = 0; 87747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng rxring->bufinf = NULL; 87847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 87947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng return -ENOMEM; 88095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 88195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 88295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 88395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_enable_rx_engine(struct jme_adapter *jme) 88495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 88595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 88695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Select Queue 0 88795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 88895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXCS, jme->reg_rxcs | 88995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_QUEUESEL_Q0); 89095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 89195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 89295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 89395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup RX DMA Bass Address 89495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 895eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng jwrite32(jme, JME_RXDBA_LO, (__u64)(jme->rxring[0].dma) & 0xFFFFFFFFUL); 89695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXDBA_HI, (__u64)(jme->rxring[0].dma) >> 32); 897eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng jwrite32(jme, JME_RXNDA, (__u64)(jme->rxring[0].dma) & 0xFFFFFFFFUL); 89895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 89995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 90095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup RX Descriptor Count 90195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 90295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXQDC, jme->rx_ring_size); 90395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 90495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 90595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Setup Unicast Filter 90695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 9078b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jme_set_unicastaddr(jme->dev); 90895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_multi(jme->dev); 90995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 91095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 91195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Enable RX Engine 91295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 91395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 914854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jwrite32f(jme, JME_RXCS, jme->reg_rxcs | 91595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_QUEUESEL_Q0 | 91695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_ENABLE | 91795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_QST); 918854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 919854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 920854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Start clock for RX MAC Processor 921854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 922854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_on(jme); 92395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 92495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 92595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 92695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_restart_rx_engine(struct jme_adapter *jme) 92795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 92895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 92995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Start RX Engine 93095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 93195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXCS, jme->reg_rxcs | 93295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_QUEUESEL_Q0 | 93395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_ENABLE | 93495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng RXCS_QST); 93595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 93695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 93795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 93895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_disable_rx_engine(struct jme_adapter *jme) 93995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 94095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 94195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 94295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 94395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 94495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Disable RX Engine 94595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 94695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXCS, jme->reg_rxcs); 94795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 94895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 94995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_RXCS); 95095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = JME_RX_DISABLE_TIMEOUT ; (val & RXCS_ENABLE) && i > 0 ; --i) { 95195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(1); 95295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_RXCS); 95395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rmb(); 95495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 95595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 95695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!i) 95749d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Disable RX engine timeout\n"); 95895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 959854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 960854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Stop clock for RX MAC Processor 961854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 962854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme_mac_rxclk_off(jme); 96395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 96495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 965c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tsengstatic u16 966c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tsengjme_udpsum(struct sk_buff *skb) 967c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng{ 968c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng u16 csum = 0xFFFFu; 969c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 970c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) 971c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng return csum; 972c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng if (skb->protocol != htons(ETH_P_IP)) 973c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng return csum; 974c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng skb_set_network_header(skb, ETH_HLEN); 975c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || 976c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng (skb->len < (ETH_HLEN + 977c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng (ip_hdr(skb)->ihl << 2) + 978c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng sizeof(struct udphdr)))) { 979c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng skb_reset_network_header(skb); 980c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng return csum; 981c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng } 982c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng skb_set_transport_header(skb, 983c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng ETH_HLEN + (ip_hdr(skb)->ihl << 2)); 984c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng csum = udp_hdr(skb)->check; 985c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng skb_reset_transport_header(skb); 986c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng skb_reset_network_header(skb); 987c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 988c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng return csum; 989c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng} 990c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 99195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 992c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tsengjme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb) 99395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 99495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) 99595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return false; 99695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 997ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_TCPON | RXWBFLAG_TCPCS)) 998ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng == RXWBFLAG_TCPON)) { 999ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng if (flags & RXWBFLAG_IPV4) 1000f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches netif_err(jme, rx_err, jme->dev, "TCP Checksum error\n"); 1001ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng return false; 100295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 100395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1004ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) 1005c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng == RXWBFLAG_UDPON) && jme_udpsum(skb)) { 1006ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng if (flags & RXWBFLAG_IPV4) 100749d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); 1008ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng return false; 100995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 101095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1011ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng if (unlikely((flags & (RXWBFLAG_IPV4 | RXWBFLAG_IPCS)) 1012ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng == RXWBFLAG_IPV4)) { 101349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error\n"); 1014ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng return false; 101595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 101695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 101795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return true; 101895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 101995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 102095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 102195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) 102295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 102395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 102495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct rxdesc *rxdesc = rxring->desc; 102595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *rxbi = rxring->bufinf; 102695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sk_buff *skb; 102795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int framesize; 102895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 102995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc += idx; 103095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi += idx; 103195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 103295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb = rxbi->skb; 103395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_dma_sync_single_for_cpu(jme->pdev, 103495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->mapping, 103595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->len, 103695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_FROMDEVICE); 103795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 103895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(jme_make_new_rx_buf(jme, idx))) { 103995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_dma_sync_single_for_device(jme->pdev, 104095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->mapping, 104195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxbi->len, 104295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_FROMDEVICE); 104395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 104495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_dropped); 104595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 104695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng framesize = le16_to_cpu(rxdesc->descwb.framesize) 104795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng - RX_PREPAD_SIZE; 104895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 104995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_reserve(skb, RX_PREPAD_SIZE); 105095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_put(skb, framesize); 105195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->protocol = eth_type_trans(skb, jme->dev); 105295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1053c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) 105495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->ip_summed = CHECKSUM_UNNECESSARY; 105595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 1056bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet skb_checksum_none_assert(skb); 105795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 105831c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { 10595043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko u16 vid = le16_to_cpu(rxdesc->descwb.vlan); 10605043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko 10615043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko __vlan_hwaccel_put_tag(skb, vid); 10625043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko NET_STAT(jme).rx_bytes += 4; 106395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 10645043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko jme->jme_rx(skb); 106595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 106631c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) == 106731c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison cpu_to_le16(RXWBFLAG_DEST_MUL)) 106895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).multicast); 106995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 107095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NET_STAT(jme).rx_bytes += framesize; 107195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_packets); 107295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 107395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 107495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_clean_rxdesc(jme, idx); 107595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 107695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 107795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 107895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 107995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_process_receive(struct jme_adapter *jme, int limit) 108095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 108195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *rxring = &(jme->rxring[0]); 108295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct rxdesc *rxdesc = rxring->desc; 108395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, j, ccnt, desccnt, mask = jme->rx_ring_mask; 108495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 108595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!atomic_dec_and_test(&jme->rx_cleaning))) 108695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_inc; 108795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 108895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&jme->link_changing) != 1)) 108995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_inc; 109095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 109195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!netif_carrier_ok(jme->dev))) 109295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_inc; 109395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 109495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng i = atomic_read(&rxring->next_to_clean); 1095858b9ced6e73a0f087294c398a1ae70a7eeed94fRoel Kluin while (limit > 0) { 109695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc = rxring->desc; 109795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc += i; 109895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 109931c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) || 110095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL)) 110195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 1102858b9ced6e73a0f087294c398a1ae70a7eeed94fRoel Kluin --limit; 110395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1104ea192aa89c3b26d56113e70c72238f6951d4097fGuo-Fu Tseng rmb(); 110595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT; 110695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 110795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(desccnt > 1 || 110895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rxdesc->descwb.errstat & RXWBERR_ALLERR)) { 110995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 111095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rxdesc->descwb.errstat & RXWBERR_CRCERR) 111195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_crc_errors); 111295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else if (rxdesc->descwb.errstat & RXWBERR_OVERUN) 111395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_fifo_errors); 111495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 111595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_errors); 111695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 111795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (desccnt > 1) 111895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng limit -= desccnt - 1; 111995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 112095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (j = i, ccnt = desccnt ; ccnt-- ; ) { 112195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_clean_rxdesc(jme, j); 112295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng j = (j + 1) & (mask); 112395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 112495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 112595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 112695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_alloc_and_feed_skb(jme, i); 112795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 112895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 112995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng i = (i + desccnt) & (mask); 113095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 113195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout: 113395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&rxring->next_to_clean, i); 113495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout_inc: 113695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->rx_cleaning); 113795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return limit > 0 ? limit : 0; 113995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 114095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 114195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 114295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 114395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_attempt_pcc(struct dynpcc_info *dpi, int atmp) 114495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 114595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (likely(atmp == dpi->cur)) { 114695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 114795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 114895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 114995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 115095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (dpi->attempt == atmp) { 115195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(dpi->cnt); 115295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 115395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->attempt = atmp; 115495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 115595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 115695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 115795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 115895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 115995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 116095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_dynamic_pcc(struct jme_adapter *jme) 116195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 116295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng register struct dynpcc_info *dpi = &(jme->dpi); 116395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 116495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((NET_STAT(jme).rx_bytes - dpi->last_bytes) > PCC_P3_THRESHOLD) 116595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_attempt_pcc(dpi, PCC_P3); 11668e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches else if ((NET_STAT(jme).rx_packets - dpi->last_pkts) > PCC_P2_THRESHOLD || 11678e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches dpi->intr_cnt > PCC_INTR_THRESHOLD) 116895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_attempt_pcc(dpi, PCC_P2); 116995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 117095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_attempt_pcc(dpi, PCC_P1); 117195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 117295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(dpi->attempt != dpi->cur && dpi->cnt > 5)) { 117395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (dpi->attempt < dpi->cur) 117495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_schedule(&jme->rxclean_task); 117595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, dpi->attempt); 117695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cur = dpi->attempt; 117795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 117895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 117995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 118095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 118195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 118295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_start_pcc_timer(struct jme_adapter *jme) 118395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 118495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 118595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->last_bytes = NET_STAT(jme).rx_bytes; 118695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->last_pkts = NET_STAT(jme).rx_packets; 118795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->intr_cnt = 0; 118895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TMCSR, 118995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TMCSR_EN | ((0xFFFFFF - PCC_INTERVAL_US) & TMCSR_CNT)); 119095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 119195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 119295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 119395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_stop_pcc_timer(struct jme_adapter *jme) 119495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 119595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TMCSR, 0); 119695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 119795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 119895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 119995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_shutdown_nic(struct jme_adapter *jme) 120095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 120195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 phylink; 120295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 120395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 120495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 120595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(phylink & PHY_LINK_UP)) { 120695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 120795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Disable all interrupt before issue timer 120895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 120995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_irq(jme); 121095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TIMER2, TMCSR_EN | 0xFFFFFE); 121195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 121295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 121395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 121495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 121595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_pcc_tasklet(unsigned long arg) 121695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 121795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = (struct jme_adapter *)arg; 121895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = jme->dev; 121995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 122095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(test_bit(JME_FLAG_SHUTDOWN, &jme->flags))) { 122195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_shutdown_nic(jme); 122295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 122395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 122495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 122595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!netif_carrier_ok(netdev) || 122695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (atomic_read(&jme->link_changing) != 1) 122795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng )) { 122895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_pcc_timer(jme); 122995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 123095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 123195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(test_bit(JME_FLAG_POLL, &jme->flags))) 123395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_dynamic_pcc(jme); 123495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_pcc_timer(jme); 123695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 123795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 123995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_polling_mode(struct jme_adapter *jme) 124095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 124195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, PCC_OFF); 124295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 124395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 124495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 124595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_interrupt_mode(struct jme_adapter *jme) 124695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 124795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 124895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 124995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 125095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline int 125195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_pseudo_hotplug_enabled(struct jme_adapter *jme) 125295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 125395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 apmc; 125495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC); 125595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return apmc & JME_APMC_PSEUDO_HP_EN; 125695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 125795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 125895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 125995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_start_shutdown_timer(struct jme_adapter *jme) 126095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 126195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 apmc; 126295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 126395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC) | JME_APMC_PCIE_SD_EN; 126495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc &= ~JME_APMC_EPIEN_CTRL; 126595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!no_extplug) { 126695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_EN); 126795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 126895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 126995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_APMC, apmc); 127095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 127195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_TIMER2, 0); 127295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng set_bit(JME_FLAG_SHUTDOWN, &jme->flags); 127395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TMCSR, 127495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TMCSR_EN | ((0xFFFFFF - APMC_PHP_SHUTDOWN_DELAY) & TMCSR_CNT)); 127595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 127695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 127795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 127895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_stop_shutdown_timer(struct jme_adapter *jme) 127995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 128095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 apmc; 128195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 128295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_TMCSR, 0); 128395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_TIMER2, 0); 128495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng clear_bit(JME_FLAG_SHUTDOWN, &jme->flags); 128595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 128695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC); 128795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc &= ~(JME_APMC_PCIE_SD_EN | JME_APMC_EPIEN_CTRL); 128895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_DIS); 128995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 129095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_APMC, apmc); 129195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 129295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 129395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 129495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_link_change_tasklet(unsigned long arg) 129595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 129695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = (struct jme_adapter *)arg; 129795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = jme->dev; 129895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 129995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 130095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (!atomic_dec_and_test(&jme->link_changing)) { 130195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->link_changing); 130249d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, intr, jme->dev, "Get link change lock failed\n"); 130395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (atomic_read(&jme->link_changing) != 1) 130449d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, intr, jme->dev, "Waiting link change lock\n"); 130595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 130695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 130795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) 130895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 130995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 131095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->old_mtu = netdev->mtu; 131195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 131295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme_pseudo_hotplug_enabled(jme)) 131395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_shutdown_timer(jme); 131495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 131595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_pcc_timer(jme); 131695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->txclean_task); 131795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxclean_task); 131895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxempty_task); 131995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 132095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_carrier_ok(netdev)) { 132195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_rx_engine(jme); 132295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_tx_engine(jme); 132395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 132495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 132595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_tx_resources(jme); 132695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 132795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) 132895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_polling_mode(jme); 132995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 133095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 133195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 133295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 133395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_check_link(netdev, 0); 133495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_carrier_ok(netdev)) { 133595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_setup_rx_resources(jme); 133695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 133749d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Allocating resources for RX error, Device STOPPED!\n"); 133895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_enable_tasklet; 133995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 134095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 134195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_setup_tx_resources(jme); 134295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 134349d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Allocating resources for TX error, Device STOPPED!\n"); 134495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_free_rx_resources; 134595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 134695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 134795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_enable_rx_engine(jme); 134895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_enable_tx_engine(jme); 134995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 135095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_start_queue(netdev); 135195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 135295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) 135395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 135495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 135595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_pcc_timer(jme); 135695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (jme_pseudo_hotplug_enabled(jme)) { 135795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_shutdown_timer(jme); 135895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 135995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 136095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_enable_tasklet; 136195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 136295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_free_rx_resources: 136395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 136495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout_enable_tasklet: 136595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_enable(&jme->txclean_task); 136695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 136795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 136895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout: 136995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->link_changing); 137095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 137195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 137295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 137395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_rx_clean_tasklet(unsigned long arg) 137495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 137595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = (struct jme_adapter *)arg; 137695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 137795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 137895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_process_receive(jme, jme->rx_ring_size); 137995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(dpi->intr_cnt); 138095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 138295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 138495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget)) 138595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 138695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = jme_napi_priv(holder); 138795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rest; 138895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget)); 139095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 139195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (atomic_read(&jme->rx_empty) > 0) { 139295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_dec(&jme->rx_empty); 139395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_dropped); 139495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_rx_engine(jme); 139595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 139695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->rx_empty); 139795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 139895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rest) { 139995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_RX_COMPLETE(netdev, holder); 140095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 140195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 140295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 140395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_NAPI_WEIGHT_SET(budget, rest); 140495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return JME_NAPI_WEIGHT_VAL(budget) - rest; 140595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 140695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 140795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 140895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_rx_empty_tasklet(unsigned long arg) 140995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 141095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = (struct jme_adapter *)arg; 141195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 141295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&jme->link_changing) != 1)) 141395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 141495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 141595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!netif_carrier_ok(jme->dev))) 141695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 141795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1418f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches netif_info(jme, rx_status, jme->dev, "RX Queue Full!\n"); 141995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 142095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_rx_clean_tasklet(arg); 142195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 142295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (atomic_read(&jme->rx_empty) > 0) { 142395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_dec(&jme->rx_empty); 142495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).rx_dropped); 142595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_rx_engine(jme); 142695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 142795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->rx_empty); 142895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 142995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 143095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 143195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_wake_queue_if_stopped(struct jme_adapter *jme) 143295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 1433eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 143495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 143595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smp_wmb(); 143695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(netif_queue_stopped(jme->dev) && 143795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) { 143849d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_done, jme->dev, "TX Queue Waked\n"); 143995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(jme->dev); 144095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 144195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 144295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 144395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 144495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 144595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_tx_clean_tasklet(unsigned long arg) 144695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 144795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = (struct jme_adapter *)arg; 144895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 144995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc = txring->desc; 145095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi; 145195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, j, cnt = 0, max, err, mask; 145295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 145349d70c4856acfce943fab35fc199b3074961313fJoe Perches tx_dbg(jme, "Into txclean\n"); 145495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 145595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!atomic_dec_and_test(&jme->tx_cleaning))) 145695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 145795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 145895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&jme->link_changing) != 1)) 145995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 146095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(!netif_carrier_ok(jme->dev))) 146295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 146395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng max = jme->tx_ring_size - atomic_read(&txring->nr_free); 146595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mask = jme->tx_ring_mask; 146695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = atomic_read(&txring->next_to_clean) ; cnt < max ; ) { 146895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi = txbi + i; 147095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 147195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (likely(ctxbi->skb && 147295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng !(txdesc[i].descwb.flags & TXWBFLAG_OWN))) { 147395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 147495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tx_dbg(jme, "txclean: %d+%d@%lu\n", 147549d70c4856acfce943fab35fc199b3074961313fJoe Perches i, ctxbi->nr_desc, jiffies); 147695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 147795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR; 147895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 147995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (j = 1 ; j < ctxbi->nr_desc ; ++j) { 148095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ttxbi = txbi + ((i + j) & (mask)); 148195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc[(i + j) & (mask)].dw[0] = 0; 148295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 148395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_unmap_page(jme->pdev, 148495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ttxbi->mapping, 148595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ttxbi->len, 148695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_TODEVICE); 148795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 148895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ttxbi->mapping = 0; 148995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ttxbi->len = 0; 149095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 149195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 149295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(ctxbi->skb); 149395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 149495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng cnt += ctxbi->nr_desc; 149595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 149695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(err)) { 149795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).tx_carrier_errors); 149895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 149995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).tx_packets); 150095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NET_STAT(jme).tx_bytes += ctxbi->len; 150195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 150295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 150395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi->skb = NULL; 150495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi->len = 0; 150595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi->start_xmit = 0; 150695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 150795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 150895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 150995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 151095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 151195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng i = (i + ctxbi->nr_desc) & mask; 151295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 151395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi->nr_desc = 0; 151495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 151595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 151649d70c4856acfce943fab35fc199b3074961313fJoe Perches tx_dbg(jme, "txclean: done %d@%lu\n", i, jiffies); 151795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&txring->next_to_clean, i); 151895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_add(cnt, &txring->nr_free); 151995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 152095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_wake_queue_if_stopped(jme); 152195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 152295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout: 152395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->tx_cleaning); 152495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 152595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 152695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 152795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_intr_msi(struct jme_adapter *jme, u32 intrstat) 152895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 152995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 153095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Disable interrupt 153195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 153295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_IENC, INTR_ENABLE); 153395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 153495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (intrstat & (INTR_LINKCH | INTR_SWINTR)) { 153595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 153695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Link change event is critical 153795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * all other events are ignored 153895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 153995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_IEVE, intrstat); 154095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_schedule(&jme->linkch_task); 154195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out_reenable; 154295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 154395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 154495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (intrstat & INTR_TMINTR) { 154595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_IEVE, INTR_TMINTR); 154695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_schedule(&jme->pcc_task); 154795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 154895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 154995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (intrstat & (INTR_PCCTXTO | INTR_PCCTX)) { 155095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_IEVE, INTR_PCCTXTO | INTR_PCCTX | INTR_TX0); 155195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_schedule(&jme->txclean_task); 155295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 155395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 155495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) { 155595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_IEVE, (intrstat & (INTR_PCCRX0TO | 155695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng INTR_PCCRX0 | 155795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng INTR_RX0EMP)) | 155895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng INTR_RX0); 155995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 156095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 156195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 156295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (intrstat & INTR_RX0EMP) 156395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->rx_empty); 156495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 156595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) { 156695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (likely(JME_RX_SCHEDULE_PREP(jme))) { 156795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_polling_mode(jme); 156895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_RX_SCHEDULE(jme); 156995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 157095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 157195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 157295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (intrstat & INTR_RX0EMP) { 157395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->rx_empty); 157495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_schedule(&jme->rxempty_task); 157595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (intrstat & (INTR_PCCRX0TO | INTR_PCCRX0)) { 157695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_schedule(&jme->rxclean_task); 157795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 157895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 157995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 158095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengout_reenable: 158195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 158295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Re-enable interrupt 158395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 158495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32f(jme, JME_IENS, INTR_ENABLE); 158595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 158695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 158795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic irqreturn_t 158895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_intr(int irq, void *dev_id) 158995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 159095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = dev_id; 159195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 159295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 intrstat; 159395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 159495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng intrstat = jread32(jme, JME_IEVE); 159595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 159695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 159795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Check if it's really an interrupt for us 159895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 1599576b5223e2caa0f19afb8ac17455759c214370ceakeemting if (unlikely((intrstat & INTR_ENABLE) == 0)) 160095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return IRQ_NONE; 160195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 160295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 160395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Check if the device still exist 160495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 160595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(intrstat == ~((typeof(intrstat))0))) 160695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return IRQ_NONE; 160795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 160895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_intr_msi(jme, intrstat); 160995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 161095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return IRQ_HANDLED; 161195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 161295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 161395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic irqreturn_t 161495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_msi(int irq, void *dev_id) 161595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 161695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = dev_id; 161795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 161895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 intrstat; 161995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1620d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng intrstat = jread32(jme, JME_IEVE); 162195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 162295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_intr_msi(jme, intrstat); 162395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 162495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return IRQ_HANDLED; 162595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 162695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 162795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 162895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_reset_link(struct jme_adapter *jme) 162995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 163095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TMCSR, TMCSR_SWIT); 163195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 163295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 163495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_restart_an(struct jme_adapter *jme) 163595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 163695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 bmcr; 163795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 163995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 164095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 164195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 164295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 164395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 164495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 164595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 164695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_request_irq(struct jme_adapter *jme) 164795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 164895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 164995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = jme->dev; 165095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irq_handler_t handler = jme_intr; 165195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int irq_flags = IRQF_SHARED; 165295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 165395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!pci_enable_msi(jme->pdev)) { 165495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng set_bit(JME_FLAG_MSI, &jme->flags); 165595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng handler = jme_msi; 165695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irq_flags = 0; 165795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 165895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 165995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = request_irq(jme->pdev->irq, handler, irq_flags, netdev->name, 166095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev); 166195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 166249d70c4856acfce943fab35fc199b3074961313fJoe Perches netdev_err(netdev, 166349d70c4856acfce943fab35fc199b3074961313fJoe Perches "Unable to request %s interrupt (return: %d)\n", 166449d70c4856acfce943fab35fc199b3074961313fJoe Perches test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx", 166549d70c4856acfce943fab35fc199b3074961313fJoe Perches rc); 166695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 166795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_MSI, &jme->flags)) { 166895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_msi(jme->pdev); 166995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng clear_bit(JME_FLAG_MSI, &jme->flags); 167095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 167195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 167295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->irq = jme->pdev->irq; 167395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 167495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 167595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 167695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 167795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 167895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 167995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_free_irq(struct jme_adapter *jme) 168095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 168195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_irq(jme->pdev->irq, jme->dev); 168295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_MSI, &jme->flags)) { 168395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_msi(jme->pdev); 168495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng clear_bit(JME_FLAG_MSI, &jme->flags); 168595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dev->irq = jme->pdev->irq; 168695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 168795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 168895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1689c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tsengstatic inline void 16904872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengjme_new_phy_on(struct jme_adapter *jme) 16914872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng{ 16924872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng u32 reg; 16934872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 16944872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg = jread32(jme, JME_PHY_PWR); 16954872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg &= ~(PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW | 16964872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng PHY_PWR_DWN2 | PHY_PWR_CLKSEL); 16974872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jwrite32(jme, JME_PHY_PWR, reg); 16984872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 16994872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®); 17004872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg &= ~PE1_GPREG0_PBG; 17014872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg |= PE1_GPREG0_ENBG; 17024872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg); 17034872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng} 17044872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17054872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengstatic inline void 17064872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengjme_new_phy_off(struct jme_adapter *jme) 17074872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng{ 17084872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng u32 reg; 17094872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17104872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg = jread32(jme, JME_PHY_PWR); 17114872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg |= PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW | 17124872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng PHY_PWR_DWN2 | PHY_PWR_CLKSEL; 17134872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jwrite32(jme, JME_PHY_PWR, reg); 17144872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17154872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®); 17164872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg &= ~PE1_GPREG0_PBG; 17174872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng reg |= PE1_GPREG0_PDD3COLD; 17184872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg); 17194872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng} 17204872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17214872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengstatic inline void 1722c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tsengjme_phy_on(struct jme_adapter *jme) 1723c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng{ 1724c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng u32 bmcr; 1725c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng 1726c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 1727c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng bmcr &= ~BMCR_PDOWN; 1728c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 17294872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17304872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (new_phy_power_ctrl(jme->chip_main_rev)) 17314872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_new_phy_on(jme); 17324872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng} 17334872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17344872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengstatic inline void 17354872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengjme_phy_off(struct jme_adapter *jme) 17364872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng{ 17374872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng u32 bmcr; 17384872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17394872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 17404872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng bmcr |= BMCR_PDOWN; 17414872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 17424872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17434872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (new_phy_power_ctrl(jme->chip_main_rev)) 17444872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_new_phy_off(jme); 1745c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng} 1746c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng 174795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 174895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_open(struct net_device *netdev) 174995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 175095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 175195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 175295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 175395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_clear_pm(jme); 175495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_NAPI_ENABLE(jme); 175595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 175638ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_enable(&jme->linkch_task); 175795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_enable(&jme->txclean_task); 175895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 175995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 176095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 176195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_request_irq(jme); 176295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) 176395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out; 176495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 176595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_irq(jme); 176695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 17674872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_phy_on(jme); 17684872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 176995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 17704872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng else 177195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 177295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 177395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 177495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 177595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 177695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 177795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out: 177895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 177995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 178095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 178195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 178295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 178395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 178495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_100m_half(struct jme_adapter *jme) 178595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 178695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 bmcr, tmp; 178795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 17881c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_phy_on(jme); 178995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 179095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | 179195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng BMCR_SPEED1000 | BMCR_FULLDPLX); 179295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tmp |= BMCR_SPEED100; 179395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 179495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (bmcr != tmp) 179595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, tmp); 179695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 179795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) 179895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_GHC, GHC_SPEED_100M | GHC_LINK_POLL); 179995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 180095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_GHC, GHC_SPEED_100M); 180195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 180295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 180395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#define JME_WAIT_LINK_TIME 2000 /* 2000ms */ 180495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 180595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_wait_link(struct jme_adapter *jme) 180695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 180795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 phylink, to = JME_WAIT_LINK_TIME; 180895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 180995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(1000); 181095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 181195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (!(phylink & PHY_LINK_UP) && (to -= 10) > 0) { 181295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(10); 181395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 181495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 181595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 181695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 18171c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengstatic void 18181c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengjme_powersave_phy(struct jme_adapter *jme) 18191c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng{ 18201c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng if (jme->reg_pmcs) { 18211c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_set_100m_half(jme); 18221c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) 18231c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_wait_link(jme); 1824bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng jme_clear_pm(jme); 18251c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng } else { 18261c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_phy_off(jme); 18271c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng } 18281c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng} 18291c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 183095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 183195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_close(struct net_device *netdev) 183295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 183395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 183495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 183595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 183695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 183795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 183895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_irq(jme); 183995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_irq(jme); 184095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 184195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_NAPI_DISABLE(jme); 184295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 184338ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->linkch_task); 184438ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->txclean_task); 184538ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->rxclean_task); 184638ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->rxempty_task); 184795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 184895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_rx_engine(jme); 184995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_tx_engine(jme); 185095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 185195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 185295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_tx_resources(jme); 185395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 185495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_off(jme); 185595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 185695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 185795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 185895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 185995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 186095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_alloc_txdesc(struct jme_adapter *jme, 186195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sk_buff *skb) 186295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 1863eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 186495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx, nr_alloc, mask = jme->tx_ring_mask; 186595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 186695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng idx = txring->next_to_use; 186795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nr_alloc = skb_shinfo(skb)->nr_frags + 2; 186895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 186995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&txring->nr_free) < nr_alloc)) 187095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 187195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_sub(nr_alloc, &txring->nr_free); 187395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->next_to_use = (txring->next_to_use + nr_alloc) & mask; 187595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return idx; 187795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 187895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 188095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_fill_tx_map(struct pci_dev *pdev, 188195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc, 188295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi, 188395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct page *page, 188495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 page_offset, 188595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 len, 188695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u8 hidma) 188795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 188895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_addr_t dmaaddr; 188995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 189095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dmaaddr = pci_map_page(pdev, 189195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng page, 189295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng page_offset, 189395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len, 189495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_TODEVICE); 189595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 189695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_dma_sync_single_for_device(pdev, 189795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dmaaddr, 189895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len, 189995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_TODEVICE); 190095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 190195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[0] = 0; 190295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[1] = 0; 190395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.flags = TXFLAG_OWN; 190495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.flags |= (hidma) ? TXFLAG_64BIT : 0; 190595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.datalen = cpu_to_le16(len); 190695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.bufaddrh = cpu_to_le32((__u64)dmaaddr >> 32); 190795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.bufaddrl = cpu_to_le32( 190895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (__u64)dmaaddr & 0xFFFFFFFFUL); 190995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 191095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->mapping = dmaaddr; 191195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->len = len; 191295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 191395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 191495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 191595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) 191695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 1917eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 191895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc = txring->desc, *ctxdesc; 191995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; 1920c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚aw u8 hidma = !!(jme->dev->features & NETIF_F_HIGHDMA); 192195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, nr_frags = skb_shinfo(skb)->nr_frags; 192295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int mask = jme->tx_ring_mask; 19239e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const struct skb_frag_struct *frag; 192495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 len; 192595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 192695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < nr_frags ; ++i) { 192795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng frag = &skb_shinfo(skb)->frags[i]; 192895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxdesc = txdesc + ((idx + i + 2) & (mask)); 192995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi = txbi + ((idx + i + 2) & (mask)); 193095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1931f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, 1932f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell skb_frag_page(frag), 19339e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet frag->page_offset, skb_frag_size(frag), hidma); 193495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 193595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 193695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; 193795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxdesc = txdesc + ((idx + 1) & (mask)); 193895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi = txbi + ((idx + 1) & (mask)); 193995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), 194095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng offset_in_page(skb->data), len, hidma); 194195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 194395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 194595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) 194695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 194795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(skb_shinfo(skb)->gso_size && 194895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_header_cloned(skb) && 194995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) { 195095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 195195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 195295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 195395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 195495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 195595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 195695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 195795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 195831c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrisonjme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) 195995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 196031c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); 196195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (*mss) { 196295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_LSEN; 196395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 196495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (skb->protocol == htons(ETH_P_IP)) { 196595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct iphdr *iph = ip_hdr(skb); 196695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 196795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iph->check = 0; 196895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, 196995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iph->daddr, 0, 197095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IPPROTO_TCP, 197195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 0); 197295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 197395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ipv6hdr *ip6h = ipv6_hdr(skb); 197495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tcp_hdr(skb)->check = ~csum_ipv6_magic(&ip6h->saddr, 197695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &ip6h->daddr, 0, 197795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IPPROTO_TCP, 197895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 0); 197995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 198095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 198295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 198395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 1; 198595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 198695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 198895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) 198995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 199095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (skb->ip_summed == CHECKSUM_PARTIAL) { 199195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u8 ip_proto; 199295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 199395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (skb->protocol) { 199495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case htons(ETH_P_IP): 199595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = ip_hdr(skb)->protocol; 199695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 199795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case htons(ETH_P_IPV6): 199895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = ipv6_hdr(skb)->nexthdr; 199995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 200095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 200195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = 0; 200295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 200395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 200495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 200595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (ip_proto) { 200695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case IPPROTO_TCP: 200795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_TCPCS; 200895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 200995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case IPPROTO_UDP: 201095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_UDPCS; 201195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 201295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 201349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, tx_err, jme->dev, "Error upper layer protocol\n"); 201495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 201595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 201695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 201795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 201895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 201995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 202031c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrisonjme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags) 202195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 202295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (vlan_tx_tag_present(skb)) { 202395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_TAGON; 202431c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison *vlan = cpu_to_le16(vlan_tx_tag_get(skb)); 202595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 202695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 202795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 202895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 20297f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tsengjme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx) 203095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2031eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 203295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc; 203395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi; 203495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u8 flags; 203595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 203695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc = (struct txdesc *)txring->desc + idx; 203795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi = txring->bufinf + idx; 203895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 203995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[0] = 0; 204095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[1] = 0; 204195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[2] = 0; 204295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[3] = 0; 204395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc1.pktsize = cpu_to_le16(skb->len); 204495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 204595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set OWN bit at final. 204695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * When kernel transmit faster than NIC. 204795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * And NIC trying to send this descriptor before we tell 204895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * it to start sending this TX queue. 204995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Other fields are already filled correctly. 205095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 205195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 205295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng flags = TXFLAG_OWN | TXFLAG_INT; 205395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 205495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set checksum flags while not tso 205595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 205695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags)) 205795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_tx_csum(jme, skb, &flags); 205895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags); 20597f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng jme_map_tx_skb(jme, skb, idx); 206095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc1.flags = flags; 206195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 206295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set tx buffer info after telling NIC to send 206395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * For better tx_clean timing 206495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 206595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 206695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->nr_desc = skb_shinfo(skb)->nr_frags + 2; 206795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->skb = skb; 206895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->len = skb->len; 206995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->start_xmit = jiffies; 207095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!txbi->start_xmit) 207195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->start_xmit = (0UL-1); 207295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 207495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 207595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 207795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_stop_queue_if_full(struct jme_adapter *jme) 207895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2079eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 208095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi = txring->bufinf; 208195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx = atomic_read(&txring->next_to_clean); 208295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi += idx; 208495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smp_wmb(); 208695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) { 208795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(jme->dev); 208849d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, "TX Queue Paused\n"); 208995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smp_wmb(); 209095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (atomic_read(&txring->nr_free) 209195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng >= (jme->tx_wake_threshold)) { 209295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(jme->dev); 209349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked\n"); 209495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 209595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 209695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 209795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(txbi->start_xmit && 209895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (jiffies - txbi->start_xmit) >= TX_TIMEOUT && 209995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->skb)) { 210095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(jme->dev); 210149d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, 210249d70c4856acfce943fab35fc199b3074961313fJoe Perches "TX Queue Stopped %d@%lu\n", idx, jiffies); 210395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 210495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 210595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 210695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 210795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This function is already protected by netif_tx_lock() 210895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 210995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 211061357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t 211195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_start_xmit(struct sk_buff *skb, struct net_device *netdev) 211295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 211395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 211495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx; 211595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 211695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(jme_expand_header(jme, skb))) { 211795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).tx_dropped); 211895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_OK; 211995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 212095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng idx = jme_alloc_txdesc(jme, skb); 212295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(idx < 0)) { 212495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 212549d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, tx_err, jme->dev, 212649d70c4856acfce943fab35fc199b3074961313fJoe Perches "BUG! Tx ring full when queue awake!\n"); 212795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_BUSY; 212995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 213095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 21317f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng jme_fill_tx_desc(jme, skb, idx); 213295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 213395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXCS, jme->reg_txcs | 213495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_SELECT_QUEUE0 | 213595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_QUEUE0S | 213695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_ENABLE); 213795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 213849d70c4856acfce943fab35fc199b3074961313fJoe Perches tx_dbg(jme, "xmit: %d+%d@%lu\n", 213949d70c4856acfce943fab35fc199b3074961313fJoe Perches idx, skb_shinfo(skb)->nr_frags + 2, jiffies); 214095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_queue_if_full(jme); 214195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 214295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_OK; 214395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 214495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 21458b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tsengstatic void 21468b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tsengjme_set_unicastaddr(struct net_device *netdev) 21478b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng{ 21488b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 21498b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng u32 val; 21508b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 21518b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng val = (netdev->dev_addr[3] & 0xff) << 24 | 21528b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[2] & 0xff) << 16 | 21538b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[1] & 0xff) << 8 | 21548b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[0] & 0xff); 21558b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jwrite32(jme, JME_RXUMA_LO, val); 21568b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng val = (netdev->dev_addr[5] & 0xff) << 8 | 21578b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[4] & 0xff); 21588b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jwrite32(jme, JME_RXUMA_HI, val); 21598b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng} 21608b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 216195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 216295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_macaddr(struct net_device *netdev, void *p) 216395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 216495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 216595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sockaddr *addr = p; 216695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 216795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(netdev)) 216895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EBUSY; 216995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 217095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->macaddr_lock); 217195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 21728b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jme_set_unicastaddr(netdev); 217395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->macaddr_lock); 217495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 217595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 217695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 217795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 217895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 217995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_multi(struct net_device *netdev) 218095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 218195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 218295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 mc_hash[2] = {}; 218395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 218595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_BRDFRAME | RXMCS_UNIFRAME; 218795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netdev->flags & IFF_PROMISC) { 218995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_ALLFRAME; 219095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (netdev->flags & IFF_ALLMULTI) { 219195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_ALLMULFRAME; 219295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (netdev->flags & IFF_MULTICAST) { 219322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 219495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int bit_nr; 219595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 219695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; 219722bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, netdev) { 219822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko bit_nr = ether_crc(ETH_ALEN, ha->addr) & 0x3F; 219995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); 220095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 220195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_LO, mc_hash[0]); 220395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_HI, mc_hash[1]); 220495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 220595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 220795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 220895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 221095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 221195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 221395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_change_mtu(struct net_device *netdev, int new_mtu) 221495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 221595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 221695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (new_mtu == jme->old_mtu) 221895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 221995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || 222195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((new_mtu) < IPV6_MIN_MTU)) 222295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 222395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (new_mtu > 4000) { 222595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs &= ~RXCS_FIFOTHNP; 222695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs |= RXCS_FIFOTHNP_64QW; 222795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_rx_engine(jme); 222895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 222995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs &= ~RXCS_FIFOTHNP; 223095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs |= RXCS_FIFOTHNP_128QW; 223195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_rx_engine(jme); 223295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 223395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->mtu = new_mtu; 2235d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev_update_features(netdev); 2236d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw 223795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 223895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 224095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 224195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 224395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_tx_timeout(struct net_device *netdev) 224495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 224595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 224695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 224895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 224995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 225095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 225195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 225295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 225395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Force to Reset the link again 225495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 225595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 225695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 225795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2258bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tsengstatic inline void jme_pause_rx(struct jme_adapter *jme) 2259bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng{ 2260bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng atomic_dec(&jme->link_changing); 2261bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2262bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng jme_set_rx_pcc(jme, PCC_OFF); 2263bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 2264bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng JME_NAPI_DISABLE(jme); 2265bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } else { 2266bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_disable(&jme->rxclean_task); 2267bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_disable(&jme->rxempty_task); 2268bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2269bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng} 2270bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2271bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tsengstatic inline void jme_resume_rx(struct jme_adapter *jme) 2272bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng{ 2273bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 2274bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2275bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 2276bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng JME_NAPI_ENABLE(jme); 2277bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } else { 2278bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 2279bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 2280bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2281bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->cur = PCC_P1; 2282bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->attempt = PCC_P1; 2283bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->cnt = 0; 2284bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 2285bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2286bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng atomic_inc(&jme->link_changing); 2287bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng} 2288bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 228995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 229095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_drvinfo(struct net_device *netdev, 229195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_drvinfo *info) 229295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 229395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 229495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 229523020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 229623020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 229723020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info)); 229895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 229995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 230195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_regs_len(struct net_device *netdev) 230295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 230395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return JME_REG_LEN; 230495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 230595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 230795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmmapio_memcpy(struct jme_adapter *jme, u32 *p, u32 reg, int len) 230895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 230995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 231095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; i += 4) 231295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p[i >> 2] = jread32(jme, reg + i); 231395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 231495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 231695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmdio_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr) 231795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 231895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 231995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 *p16 = (u16 *)p; 232095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < reg_nr ; ++i) 232295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p16[i] = jme_mdio_read(jme->dev, jme->mii_if.phy_id, i); 232395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 232495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 232695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) 232795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 232895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 232995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 *p32 = (u32 *)p; 233095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(p, 0xFF, JME_REG_LEN); 233295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng regs->version = 1; 233495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN); 233595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 233795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_PHY, JME_PHY_LEN); 233895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 234095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_MISC, JME_MISC_LEN); 234195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 234395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN); 234495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 234695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdio_memcpy(jme, p32, JME_PHY_REG_NR); 234795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 234895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 235095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) 235195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 235295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 235395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_coalesce_usecs = PCC_TX_TO; 235595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_max_coalesced_frames = PCC_TX_CNT; 235695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 235895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->use_adaptive_rx_coalesce = false; 235995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = 0; 236095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = 0; 236195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 236295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 236395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 236495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->use_adaptive_rx_coalesce = true; 236595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 236695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (jme->dpi.cur) { 236795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P1: 236895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P1_TO; 236995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P1_CNT; 237095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 237195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P2: 237295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P2_TO; 237395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P2_CNT; 237495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 237595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P3: 237695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P3_TO; 237795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P3_CNT; 237895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 237995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 238095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 238195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 238295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 238395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 238495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 238595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 238695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 238795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) 238895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 238995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 239095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 239195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 239295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(netdev)) 239395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EBUSY; 239495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 23958e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if (ecmd->use_adaptive_rx_coalesce && 23968e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches test_bit(JME_FLAG_POLL, &jme->flags)) { 239795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng clear_bit(JME_FLAG_POLL, &jme->flags); 239895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_rx; 239995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cur = PCC_P1; 240095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->attempt = PCC_P1; 240195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 240295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 240395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 24048e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches } else if (!(ecmd->use_adaptive_rx_coalesce) && 24058e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches !(test_bit(JME_FLAG_POLL, &jme->flags))) { 240695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng set_bit(JME_FLAG_POLL, &jme->flags); 240795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_receive_skb; 240895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 240995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 241095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 241195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 241295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 241395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 241495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 241595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_pauseparam(struct net_device *netdev, 241695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_pauseparam *ecmd) 241795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 241895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 241995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 242095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 242195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_pause = (jme->reg_txpfc & TXPFC_PF_EN) != 0; 242295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_pause = (jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0; 242395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 242495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 242595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); 242695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 242795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 242895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->autoneg = 242995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0; 243095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 243195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 243395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_pauseparam(struct net_device *netdev, 243495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_pauseparam *ecmd) 243595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 243695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 243795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 243895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((jme->reg_txpfc & TXPFC_PF_EN) != 0) ^ 244095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->tx_pause != 0)) { 244195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 244295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->tx_pause) 244395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc |= TXPFC_PF_EN; 244495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 244595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc &= ~TXPFC_PF_EN; 244695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 244795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXPFC, jme->reg_txpfc); 244895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 244995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 245095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 245195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0) ^ 245295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->rx_pause != 0)) { 245395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 245495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->rx_pause) 245595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_FLOWCTRL; 245695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 245795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs &= ~RXMCS_FLOWCTRL; 245895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 245995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 246095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 246195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 246295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 246395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 246495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); 246595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0) ^ 246695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->autoneg != 0)) { 246795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 246895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->autoneg) 246995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val |= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); 247095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 247195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); 247295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 247395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 247495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_ADVERTISE, val); 247595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 247695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 247795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 247895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 247995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 248095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 248195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 248295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_wol(struct net_device *netdev, 248395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_wolinfo *wol) 248495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 248595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 248695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 248795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->supported = WAKE_MAGIC | WAKE_PHY; 248895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 248995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts = 0; 249095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 249195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) 249295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts |= WAKE_PHY; 249395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 249495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->reg_pmcs & PMCS_MFEN) 249595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts |= WAKE_MAGIC; 249695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 249795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 249895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 249995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 250095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_wol(struct net_device *netdev, 250195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_wolinfo *wol) 250295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 250395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 250495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 250595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & (WAKE_MAGICSECURE | 250695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_UCAST | 250795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_MCAST | 250895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_BCAST | 250995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_ARP)) 251095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EOPNOTSUPP; 251195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 251295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs = 0; 251395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 251495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & WAKE_PHY) 251595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs |= PMCS_LFEN | PMCS_LREN; 251695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 251795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & WAKE_MAGIC) 251895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs |= PMCS_MFEN; 251995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 252095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PMCS, jme->reg_pmcs); 2521bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); 2522f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 252395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 252495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 252595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 252695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 252795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_settings(struct net_device *netdev, 252895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_cmd *ecmd) 252995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 253095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 253195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 253295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 253395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 253495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = mii_ethtool_gset(&(jme->mii_if), ecmd); 253595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 253695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 253795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 253895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 253995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 254095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_settings(struct net_device *netdev, 254195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_cmd *ecmd) 254295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 254395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 254495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc, fdc = 0; 254595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 254625db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny if (ethtool_cmd_speed(ecmd) == SPEED_1000 254725db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny && ecmd->autoneg != AUTONEG_ENABLE) 254895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 254995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 25503ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng /* 25513ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng * Check If user changed duplex only while force_media. 25523ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng * Hardware would not generate link change interrupt. 25533ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng */ 255495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->mii_if.force_media && 255595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->autoneg != AUTONEG_ENABLE && 255695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (jme->mii_if.full_duplex != ecmd->duplex)) 255795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng fdc = 1; 255895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 255995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 256095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = mii_ethtool_sset(&(jme->mii_if), ecmd); 256195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 256295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 256395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!rc) { 25643ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng if (fdc) 25653ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng jme_reset_link(jme); 256695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->old_ecmd = *ecmd; 2567334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng set_bit(JME_FLAG_SSET, &jme->flags); 2568334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng } 2569334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2570334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng return rc; 2571334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng} 2572334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2573334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tsengstatic int 2574334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tsengjme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) 2575334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng{ 2576334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng int rc; 2577334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 2578334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng struct mii_ioctl_data *mii_data = if_mii(rq); 2579334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng unsigned int duplex_chg; 2580334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2581334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (cmd == SIOCSMIIREG) { 2582334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng u16 val = mii_data->val_in; 2583334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (!(val & (BMCR_RESET|BMCR_ANENABLE)) && 2584334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng (val & BMCR_SPEED1000)) 2585334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng return -EINVAL; 2586334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng } 2587334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2588334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng spin_lock_bh(&jme->phy_lock); 2589334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng rc = generic_mii_ioctl(&jme->mii_if, mii_data, cmd, &duplex_chg); 2590334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 2591334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2592334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (!rc && (cmd == SIOCSMIIREG)) { 2593334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (duplex_chg) 2594334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme_reset_link(jme); 2595334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme_get_settings(netdev, &jme->old_ecmd); 2596334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng set_bit(JME_FLAG_SSET, &jme->flags); 259795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 259895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 259995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 260095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 260195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 260295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u32 260395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_link(struct net_device *netdev) 260495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 260595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 260695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return jread32(jme, JME_PHY_LINK) & PHY_LINK_UP; 260795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 260895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 260995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u32 261095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_msglevel(struct net_device *netdev) 261195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 261295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 261395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return jme->msg_enable; 261495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 261595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 261695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 261795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_msglevel(struct net_device *netdev, u32 value) 261895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 261995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 262095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->msg_enable = value; 262195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 262295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2623c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awstatic netdev_features_t 2624c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awjme_fix_features(struct net_device *netdev, netdev_features_t features) 262595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2626d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (netdev->mtu > 1900) 2627d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM); 2628d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw return features; 262995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 263095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 263195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 2632c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awjme_set_features(struct net_device *netdev, netdev_features_t features) 263395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 263495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 263595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 263695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 2637d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (features & NETIF_F_RXCSUM) 263895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_CHECKSUM; 263995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 264095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs &= ~RXMCS_CHECKSUM; 264195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 264295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 264395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 264495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 264595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 264695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 264795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 264895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_nway_reset(struct net_device *netdev) 264995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 265095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 265195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_an(jme); 265295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 265395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 265495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 265595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u8 265695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_smb_read(struct jme_adapter *jme, unsigned int addr) 265795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 265895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 265995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int to; 266095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 266195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 266295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 266395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBCSR_BUSY) && --to) { 266495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 266595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 266695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 266795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 266849d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 266995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0xFF; 267095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 267195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 267295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBINTF, 267395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | 267495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWRWN_READ | 267595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWCMD); 267695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 267795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 267895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 267995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBINTF_HWCMD) && --to) { 268095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 268195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 268295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 268395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 268449d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 268595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0xFF; 268695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 268795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 268895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return (val & SMBINTF_HWDATR) >> SMBINTF_HWDATR_SHIFT; 268995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 269095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 269195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 269295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data) 269395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 269495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 269595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int to; 269695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 269795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 269895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 269995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBCSR_BUSY) && --to) { 270095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 270195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 270295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 270395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 270449d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 270595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 270695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 270795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 270895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBINTF, 270995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((data << SMBINTF_HWDATW_SHIFT) & SMBINTF_HWDATW) | 271095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | 271195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWRWN_WRITE | 271295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWCMD); 271395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 271495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 271595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 271695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBINTF_HWCMD) && --to) { 271795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 271895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 271995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 272095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 272149d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 272295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 272395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 272495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 272595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(2); 272695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 272795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 272895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 272995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_eeprom_len(struct net_device *netdev) 273095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 273195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 273295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 273395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 273495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return (val & SMBCSR_EEPROMD) ? JME_SMB_LEN : 0; 273595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 273695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 273795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 273895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_eeprom(struct net_device *netdev, 273995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_eeprom *eeprom, u8 *data) 274095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 274195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 274295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, offset = eeprom->offset, len = eeprom->len; 274395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 274495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 274595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * ethtool will check the boundary for us 274695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 274795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng eeprom->magic = JME_EEPROM_MAGIC; 274895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; ++i) 274995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng data[i] = jme_smb_read(jme, i + offset); 275095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 275195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 275295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 275395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 275495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 275595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_eeprom(struct net_device *netdev, 275695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_eeprom *eeprom, u8 *data) 275795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 275895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 275995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, offset = eeprom->offset, len = eeprom->len; 276095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 276195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eeprom->magic != JME_EEPROM_MAGIC) 276295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 276395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 276495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 276595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * ethtool will check the boundary for us 276695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 276795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; ++i) 276895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_smb_write(jme, i + offset, data[i]); 276995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 277095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 277195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 277295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 277395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic const struct ethtool_ops jme_ethtool_ops = { 277495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_drvinfo = jme_get_drvinfo, 277595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_regs_len = jme_get_regs_len, 277695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_regs = jme_get_regs, 277795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_coalesce = jme_get_coalesce, 277895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_coalesce = jme_set_coalesce, 277995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_pauseparam = jme_get_pauseparam, 278095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_pauseparam = jme_set_pauseparam, 278195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_wol = jme_get_wol, 278295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_wol = jme_set_wol, 278395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_settings = jme_get_settings, 278495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_settings = jme_set_settings, 278595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_link = jme_get_link, 278695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_msglevel = jme_get_msglevel, 278795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_msglevel = jme_set_msglevel, 278895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .nway_reset = jme_nway_reset, 278995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_eeprom_len = jme_get_eeprom_len, 279095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_eeprom = jme_get_eeprom, 279195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_eeprom = jme_set_eeprom, 279295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 279395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 279495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 279595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_pci_dma64(struct pci_dev *pdev) 279695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2797814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && 2798e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) 2799e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) 2800814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng return 1; 2801814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng 2802814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && 2803e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(40))) 2804e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40))) 2805814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng return 1; 2806814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng 2807284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) 2808284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) 280995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 281095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 281195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 281295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 281395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 281495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 281595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_phy_init(struct jme_adapter *jme) 281695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 281795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 reg26; 281895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 281995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg26 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 26); 282095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 26, reg26 | 0x1000); 282195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 282295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 282395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 282495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_check_hw_ver(struct jme_adapter *jme) 282595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 282695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 chipmode; 282795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 282895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chipmode = jread32(jme, JME_CHIPMODE); 282995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 283095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT; 283195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT; 283219d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->chip_main_rev = jme->chiprev & 0xF; 283319d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF; 283495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 283595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2836e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemmingerstatic const struct net_device_ops jme_netdev_ops = { 2837e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_open = jme_open, 2838e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_stop = jme_close, 2839e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_validate_addr = eth_validate_addr, 2840334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng .ndo_do_ioctl = jme_ioctl, 2841e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_start_xmit = jme_start_xmit, 2842e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_set_mac_address = jme_set_macaddr, 2843afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = jme_set_multi, 2844e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_change_mtu = jme_change_mtu, 2845e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_tx_timeout = jme_tx_timeout, 2846d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw .ndo_fix_features = jme_fix_features, 2847d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw .ndo_set_features = jme_set_features, 2848e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger}; 2849e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger 285095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __devinit 285195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_init_one(struct pci_dev *pdev, 285295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng const struct pci_device_id *ent) 285395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 285495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc = 0, using_dac, i; 285595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev; 285695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme; 285795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 bmcr, bmsr; 285895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 apmc; 285995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 286095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 286195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * set up PCI device basics 286295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 286395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = pci_enable_device(pdev); 286495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 286549d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot enable PCI device\n"); 286695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out; 286795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 286895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 286995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng using_dac = jme_pci_dma64(pdev); 287095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (using_dac < 0) { 287149d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot set PCI DMA Mask\n"); 287295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -EIO; 287395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 287495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 287595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 287695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 287749d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("No PCI resource region found\n"); 287895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 287995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 288095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 288195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 288295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = pci_request_regions(pdev, DRV_NAME); 288395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 288449d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot obtain PCI resource region\n"); 288595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 288695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 288795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 288895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_master(pdev); 288995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 289095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 289195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * alloc and init net device 289295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 289395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev = alloc_etherdev(sizeof(*jme)); 289495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!netdev) { 289549d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot allocate netdev structure\n"); 289695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 289795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_release_regions; 289895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 2899e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger netdev->netdev_ops = &jme_netdev_ops; 290095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->ethtool_ops = &jme_ethtool_ops; 290195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->watchdog_timeo = TX_TIMEOUT; 2902d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev->hw_features = NETIF_F_IP_CSUM | 2903d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_IPV6_CSUM | 2904d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_SG | 2905d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_TSO | 2906d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_TSO6 | 2907d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_RXCSUM; 29087903264402546f45f9bac8ad2bfdb00d00eb124aMichaÅ‚ MirosÅ‚aw netdev->features = NETIF_F_IP_CSUM | 29097903264402546f45f9bac8ad2bfdb00d00eb124aMichaÅ‚ MirosÅ‚aw NETIF_F_IPV6_CSUM | 291095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_SG | 291195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_TSO | 291295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_TSO6 | 291395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_HW_VLAN_TX | 291495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_HW_VLAN_RX; 291595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (using_dac) 291695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->features |= NETIF_F_HIGHDMA; 291795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 291895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SET_NETDEV_DEV(netdev, &pdev->dev); 291995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, netdev); 292095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 292195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 292295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * init adapter info 292395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 292495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme = netdev_priv(netdev); 292595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->pdev = pdev; 292695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dev = netdev; 292795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_rx; 292895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->old_mtu = netdev->mtu = 1500; 292995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 293095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_ring_size = 1 << 10; 293195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_ring_mask = jme->tx_ring_size - 1; 293295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_wake_threshold = 1 << 9; 293395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->rx_ring_size = 1 << 9; 293495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->rx_ring_mask = jme->rx_ring_size - 1; 293595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->msg_enable = JME_DEF_MSG_ENABLE; 293695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->regs = ioremap(pci_resource_start(pdev, 0), 293795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_resource_len(pdev, 0)); 293895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(jme->regs)) { 293949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Mapping PCI resource region error\n"); 294095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 294195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_free_netdev; 294295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 294395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 294495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (no_pseudohp) { 294595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC) & ~JME_APMC_PSEUDO_HP_EN; 294695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_APMC, apmc); 294795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (force_pseudohp) { 294895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC) | JME_APMC_PSEUDO_HP_EN; 294995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_APMC, apmc); 295095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 295195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 295295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, jme->rx_ring_size >> 2) 295395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 295495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->phy_lock); 295595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->macaddr_lock); 295695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->rxmcs_lock); 295795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 295895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->link_changing, 1); 295995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->rx_cleaning, 1); 296095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->tx_cleaning, 1); 296195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->rx_empty, 1); 296295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 296395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->pcc_task, 2964164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_pcc_tasklet, 296595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 296695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->linkch_task, 2967164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_link_change_tasklet, 296895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 296995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->txclean_task, 2970164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_tx_clean_tasklet, 297195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 297295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->rxclean_task, 2973164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_rx_clean_tasklet, 297495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 297595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->rxempty_task, 2976164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_rx_empty_tasklet, 297795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 297838ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable_nosync(&jme->linkch_task); 297995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->txclean_task); 298095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->rxclean_task); 298195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->rxempty_task); 298295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dpi.cur = PCC_P1; 298395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 298495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_ghc = 0; 298595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs = RXCS_DEFAULT; 298695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs = RXMCS_DEFAULT; 298795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc = 0; 298895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs = PMCS_MFEN; 2989854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 = GPREG1_DEFAULT; 2990d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw 2991d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (jme->reg_rxmcs & RXMCS_CHECKSUM) 2992d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev->features |= NETIF_F_RXCSUM; 299395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 299495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 299595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Get Max Read Req Size from PCI Config Space 299695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 299795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_read_config_byte(pdev, PCI_DCSR_MRRS, &jme->mrrs); 299895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mrrs &= PCI_DCSR_MRRS_MASK; 299995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (jme->mrrs) { 300095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case MRRS_128B: 300195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_128B; 300295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 300395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case MRRS_256B: 300495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_256B; 300595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 300695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 300795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_512B; 300895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 3009ee289b6440c3b0ccb9459495783e8c299bec6604Joe Perches } 301095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 301195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 301295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Must check before reset_mac_processor 301395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 301495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_check_hw_ver(jme); 301595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.dev = netdev; 301695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) { 301795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = 0; 301895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 1 ; i < 32 ; ++i) { 301995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(netdev, i, MII_BMCR); 302095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmsr = jme_mdio_read(netdev, i, MII_BMSR); 302195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (bmcr != 0xFFFFU && (bmcr != 0 || bmsr != 0)) { 302295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = i; 302395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 302495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 302595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 302695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 302795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!jme->mii_if.phy_id) { 302895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -EIO; 302949d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Can not find phy_id\n"); 303049d70c4856acfce943fab35fc199b3074961313fJoe Perches goto err_out_unmap; 303195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 303295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 303395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_ghc |= GHC_LINK_POLL; 303495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 303595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = 1; 303695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 303795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) 303895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.supports_gmii = true; 303995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 304095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.supports_gmii = false; 3041334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme->mii_if.phy_id_mask = 0x1F; 3042334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme->mii_if.reg_num_mask = 0x1F; 304395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.mdio_read = jme_mdio_read; 304495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.mdio_write = jme_mdio_write; 304595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 304695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_clear_pm(jme); 3047bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng pci_set_power_state(jme->pdev, PCI_D0); 3048bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng device_set_wakeup_enable(&pdev->dev, true); 3049bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng 305051754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng jme_set_phyfifo_5level(jme); 3051ff938e43d39e926de74b32a3656c190f979ab642Sergei Shtylyov jme->pcirev = pdev->revision; 305295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!jme->fpgaver) 305395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_init(jme); 305495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_off(jme); 305595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 305695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 305795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Reset MAC processor and reload EEPROM for MAC Address 305895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 305995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 306095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_reload_eeprom(jme); 306195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 306249d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Reload eeprom for reading MAC Address error\n"); 3063d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng goto err_out_unmap; 306495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 306595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_load_macaddr(netdev); 306695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 306795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 306895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Tell stack that we are not ready to work until open() 306995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 307095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 307195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 307295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = register_netdev(netdev); 307395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 307449d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot register net device\n"); 3075d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng goto err_out_unmap; 307695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 307795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 307819d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n", 3079f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? 3080f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches "JMC250 Gigabit Ethernet" : 3081f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? 3082f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches "JMC260 Fast Ethernet" : "Unknown", 3083f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->fpgaver != 0) ? " (FPGA)" : "", 3084f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, 308519d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->pcirev, netdev->dev_addr); 308695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 308795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 308895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 308995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_unmap: 309095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iounmap(jme->regs); 309195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_free_netdev: 309295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, NULL); 309395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_netdev(netdev); 309495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_release_regions: 309595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_release_regions(pdev); 309695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_disable_pdev: 309795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_device(pdev); 309895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out: 309995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 310095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 310195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 310295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void __devexit 310395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_remove_one(struct pci_dev *pdev) 310495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 310595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 310695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 310795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 310895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unregister_netdev(netdev); 310995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iounmap(jme->regs); 311095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, NULL); 311195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_netdev(netdev); 311295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_release_regions(pdev); 311395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_device(pdev); 311495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 311595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 311695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31171c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengstatic void 31181c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengjme_shutdown(struct pci_dev *pdev) 31191c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng{ 31201c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 31211c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 31221c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 31231c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_powersave_phy(jme); 31241c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng pci_pme_active(pdev, true); 31251c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng} 31261c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 3127aab6fb82b1912a312f7547c92ac8d4ecb072e807Guo-Fu Tseng#ifdef CONFIG_PM_SLEEP 3128bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengstatic int 3129bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengjme_suspend(struct device *dev) 313095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 3131f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki struct pci_dev *pdev = to_pci_dev(dev); 313295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 313395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 313495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3135a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher if (!netif_running(netdev)) 3136a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher return 0; 3137a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher 313895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_dec(&jme->link_changing); 313995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 314095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_detach(netdev); 314195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 314295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_irq(jme); 314395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 314495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->txclean_task); 314595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxclean_task); 314695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxempty_task); 314795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 314895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_carrier_ok(netdev)) { 314995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) 315095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_polling_mode(jme); 315195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 315295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_pcc_timer(jme); 315395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_rx_engine(jme); 315495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_tx_engine(jme); 315595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 315695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 315795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_tx_resources(jme); 315895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 315995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 316095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 316195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 316295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_enable(&jme->txclean_task); 316395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 316495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 316595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31661c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_powersave_phy(jme); 316795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 316895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 316995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 317095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3171bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengstatic int 3172bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengjme_resume(struct device *dev) 317395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 3174f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki struct pci_dev *pdev = to_pci_dev(dev); 317595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 317695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 317795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3178a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher if (!netif_running(netdev)) 3179a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher return 0; 3180a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher 3181bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng jme_clear_pm(jme); 31824872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_phy_on(jme); 31834872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 318495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 31854872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng else 318695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 318795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 318895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_irq(jme); 318995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_attach(netdev); 319095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 319195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->link_changing); 319295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 319395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 319495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 319595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 319695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 3197f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3198f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysockistatic SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); 3199f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#define JME_PM_OPS (&jme_pm_ops) 3200f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3201f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#else 3202f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3203f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#define JME_PM_OPS NULL 3204724f88057609c00d6e973c3a7e0eb72f8eec2da9David S. Miller#endif 320595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3206a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { 320795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, 320895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, 320995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { } 321095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 321195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 321295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct pci_driver jme_driver = { 321395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .name = DRV_NAME, 321495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .id_table = jme_pci_tbl, 321595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .probe = jme_init_one, 321695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .remove = __devexit_p(jme_remove_one), 32171c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng .shutdown = jme_shutdown, 3218f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki .driver.pm = JME_PM_OPS, 321995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 322095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 322195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __init 322295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_init_module(void) 322395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 322449d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_info("JMicron JMC2XX ethernet driver version %s\n", DRV_VERSION); 322595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return pci_register_driver(&jme_driver); 322695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 322795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 322895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void __exit 322995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_cleanup_module(void) 323095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 323195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_unregister_driver(&jme_driver); 323295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 323395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 323495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_init(jme_init_module); 323595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_exit(jme_cleanup_module); 323695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 323795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_AUTHOR("Guo-Fu Tseng <cooldavid@cooldavid.org>"); 323895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver"); 323995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_LICENSE("GPL"); 324095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_VERSION(DRV_VERSION); 324195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DEVICE_TABLE(pci, jme_pci_tbl); 324295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3243