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 1748c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leejme_phy_specreg_read(struct jme_adapter *jme, u32 specreg) 1749c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee{ 1750c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee u32 phy_addr; 1751c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1752c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_addr = JM_PHY_SPEC_REG_READ | specreg; 1753c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, 1754c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_addr); 1755c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee return jme_mdio_read(jme->dev, jme->mii_if.phy_id, 1756c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee JM_PHY_SPEC_DATA_REG); 1757c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee} 1758c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1759c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leestatic void 1760c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leejme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data) 1761c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee{ 1762c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee u32 phy_addr; 1763c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1764c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg; 1765c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, 1766c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data); 1767c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, 1768c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_addr); 1769c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee} 1770c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1771c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leestatic int 1772c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leejme_phy_calibration(struct jme_adapter *jme) 1773c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee{ 1774c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee u32 ctrl1000, phy_data; 1775c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1776c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_off(jme); 1777c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_on(jme); 1778c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee /* Enabel PHY test mode 1 */ 1779c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); 1780c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; 1781c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ctrl1000 |= PHY_GAD_TEST_MODE_1; 1782c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); 1783c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1784c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); 1785c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0; 1786c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH | 1787c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee JM_PHY_EXT_COMM_2_CALI_ENABLE; 1788c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); 1789c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee msleep(20); 1790c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); 1791c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE | 1792c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee JM_PHY_EXT_COMM_2_CALI_MODE_0 | 1793c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee JM_PHY_EXT_COMM_2_CALI_LATCH); 1794c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); 1795c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1796c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee /* Disable PHY test mode */ 1797c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); 1798c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; 1799c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); 1800c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee return 0; 1801c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee} 1802c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1803c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leestatic int 1804c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leejme_phy_setEA(struct jme_adapter *jme) 1805c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee{ 1806c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee u32 phy_comm0 = 0, phy_comm1 = 0; 1807c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee u8 nic_ctrl; 1808c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1809c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl); 1810c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) 1811c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee return 0; 1812c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1813c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee switch (jme->pdev->device) { 1814c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee case PCI_DEVICE_ID_JMICRON_JMC250: 1815c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if (((jme->chip_main_rev == 5) && 1816c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) || 1817c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee (jme->chip_sub_rev == 3))) || 1818c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee (jme->chip_main_rev >= 6)) { 1819c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0x008A; 1820c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm1 = 0x4109; 1821c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee } 1822c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if ((jme->chip_main_rev == 3) && 1823c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2))) 1824c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0xE088; 1825c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee break; 1826c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee case PCI_DEVICE_ID_JMICRON_JMC260: 1827c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if (((jme->chip_main_rev == 5) && 1828c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) || 1829c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee (jme->chip_sub_rev == 3))) || 1830c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee (jme->chip_main_rev >= 6)) { 1831c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0x008A; 1832c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm1 = 0x4109; 1833c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee } 1834c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if ((jme->chip_main_rev == 3) && 1835c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2))) 1836c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0xE088; 1837c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0)) 1838c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0x608A; 1839c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2)) 1840c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee phy_comm0 = 0x408A; 1841c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee break; 1842c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee default: 1843c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee return -ENODEV; 1844c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee } 1845c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if (phy_comm0) 1846c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0); 1847c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee if (phy_comm1) 1848c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1); 1849c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1850c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee return 0; 1851c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee} 1852c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee 1853c4860ba2e11261a541632ceee8267ca490d9eb98Aries Leestatic int 185495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_open(struct net_device *netdev) 185595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 185695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 185795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 185895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 185995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_clear_pm(jme); 186095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_NAPI_ENABLE(jme); 186195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 186238ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_enable(&jme->linkch_task); 186395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_enable(&jme->txclean_task); 186495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 186595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 186695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 186795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_request_irq(jme); 186895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) 186995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out; 187095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_irq(jme); 187295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 18734872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_phy_on(jme); 18744872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 187595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 18764872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng else 187795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 1878c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_calibration(jme); 1879c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_setEA(jme); 188095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 188195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 188295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 188395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 188495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out: 188595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 188695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 188795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 188895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 188995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 189095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 189195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_100m_half(struct jme_adapter *jme) 189295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 189395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 bmcr, tmp; 189495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 18951c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_phy_on(jme); 189695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 189795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | 189895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng BMCR_SPEED1000 | BMCR_FULLDPLX); 189995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tmp |= BMCR_SPEED100; 190095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 190195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (bmcr != tmp) 190295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, tmp); 190395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 190495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) 190595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_GHC, GHC_SPEED_100M | GHC_LINK_POLL); 190695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 190795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_GHC, GHC_SPEED_100M); 190895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 190995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 191095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#define JME_WAIT_LINK_TIME 2000 /* 2000ms */ 191195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 191295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_wait_link(struct jme_adapter *jme) 191395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 191495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 phylink, to = JME_WAIT_LINK_TIME; 191595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 191695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(1000); 191795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 191895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while (!(phylink & PHY_LINK_UP) && (to -= 10) > 0) { 191995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(10); 192095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng phylink = jme_linkstat_from_phy(jme); 192195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 192295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 192395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 19241c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengstatic void 19251c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengjme_powersave_phy(struct jme_adapter *jme) 19261c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng{ 19271c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng if (jme->reg_pmcs) { 19281c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_set_100m_half(jme); 19291c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) 19301c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_wait_link(jme); 1931bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng jme_clear_pm(jme); 19321c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng } else { 19331c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_phy_off(jme); 19341c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng } 19351c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng} 19361c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 193795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 193895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_close(struct net_device *netdev) 193995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 194095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 194195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 194395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 194495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_irq(jme); 194695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_irq(jme); 194795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng JME_NAPI_DISABLE(jme); 194995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 195038ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->linkch_task); 195138ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->txclean_task); 195238ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->rxclean_task); 195338ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable(&jme->rxempty_task); 195495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 195595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_rx_engine(jme); 195695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_tx_engine(jme); 195795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 195895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 195995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_tx_resources(jme); 196095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 196195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_off(jme); 196295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 196395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 196495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 196595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 196695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 196795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_alloc_txdesc(struct jme_adapter *jme, 196895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sk_buff *skb) 196995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 1970eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 197195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx, nr_alloc, mask = jme->tx_ring_mask; 197295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng idx = txring->next_to_use; 197495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nr_alloc = skb_shinfo(skb)->nr_frags + 2; 197595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&txring->nr_free) < nr_alloc)) 197795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 197895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_sub(nr_alloc, &txring->nr_free); 198095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txring->next_to_use = (txring->next_to_use + nr_alloc) & mask; 198295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return idx; 198495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 198595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 198795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_fill_tx_map(struct pci_dev *pdev, 198895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc, 198995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi, 199095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct page *page, 199195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 page_offset, 199295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 len, 19933ad9b358e03fd9dbf6705721490c811b666b0fe2MichaÅ‚ MirosÅ‚aw bool hidma) 199495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 199595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_addr_t dmaaddr; 199695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 199795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dmaaddr = pci_map_page(pdev, 199895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng page, 199995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng page_offset, 200095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len, 200195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_TODEVICE); 200295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 200395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_dma_sync_single_for_device(pdev, 200495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dmaaddr, 200595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len, 200695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng PCI_DMA_TODEVICE); 200795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 200895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[0] = 0; 200995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[1] = 0; 201095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.flags = TXFLAG_OWN; 201195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.flags |= (hidma) ? TXFLAG_64BIT : 0; 201295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.datalen = cpu_to_le16(len); 201395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.bufaddrh = cpu_to_le32((__u64)dmaaddr >> 32); 201495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc2.bufaddrl = cpu_to_le32( 201595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (__u64)dmaaddr & 0xFFFFFFFFUL); 201695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 201795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->mapping = dmaaddr; 201895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->len = len; 201995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 202095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 202195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 202295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) 202395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2024eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 202595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc = txring->desc, *ctxdesc; 202695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; 20273ad9b358e03fd9dbf6705721490c811b666b0fe2MichaÅ‚ MirosÅ‚aw bool hidma = jme->dev->features & NETIF_F_HIGHDMA; 202895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, nr_frags = skb_shinfo(skb)->nr_frags; 202995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int mask = jme->tx_ring_mask; 20309e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const struct skb_frag_struct *frag; 203195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 len; 203295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 203395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < nr_frags ; ++i) { 203495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng frag = &skb_shinfo(skb)->frags[i]; 203595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxdesc = txdesc + ((idx + i + 2) & (mask)); 203695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi = txbi + ((idx + i + 2) & (mask)); 203795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2038f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, 2039f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell skb_frag_page(frag), 20409e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet frag->page_offset, skb_frag_size(frag), hidma); 204195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 204295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 204395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; 204495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxdesc = txdesc + ((idx + 1) & (mask)); 204595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ctxbi = txbi + ((idx + 1) & (mask)); 204695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), 204795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng offset_in_page(skb->data), len, hidma); 204895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 204995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 205095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 205195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 205295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) 205395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 205495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(skb_shinfo(skb)->gso_size && 205595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_header_cloned(skb) && 205695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) { 205795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 205895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 205995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 206095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 206195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 206295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 206395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 206495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 206531c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrisonjme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) 206695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 206731c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); 206895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (*mss) { 206995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_LSEN; 207095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (skb->protocol == htons(ETH_P_IP)) { 207295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct iphdr *iph = ip_hdr(skb); 207395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iph->check = 0; 207595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, 207695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iph->daddr, 0, 207795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IPPROTO_TCP, 207895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 0); 207995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 208095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ipv6hdr *ip6h = ipv6_hdr(skb); 208195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tcp_hdr(skb)->check = ~csum_ipv6_magic(&ip6h->saddr, 208395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &ip6h->daddr, 0, 208495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IPPROTO_TCP, 208595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 0); 208695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 208795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 208995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 209095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 209195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 1; 209295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 209395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 209495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 209595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) 209695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 209795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (skb->ip_summed == CHECKSUM_PARTIAL) { 209895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u8 ip_proto; 209995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 210095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (skb->protocol) { 210195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case htons(ETH_P_IP): 210295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = ip_hdr(skb)->protocol; 210395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 210495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case htons(ETH_P_IPV6): 210595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = ipv6_hdr(skb)->nexthdr; 210695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 210795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 210895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ip_proto = 0; 210995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 211095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 211195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 211295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (ip_proto) { 211395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case IPPROTO_TCP: 211495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_TCPCS; 211595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 211695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case IPPROTO_UDP: 211795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_UDPCS; 211895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 211995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 212049d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, tx_err, jme->dev, "Error upper layer protocol\n"); 212195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 212295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 212395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 212495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 212595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 212731c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrisonjme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags) 212895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 212995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (vlan_tx_tag_present(skb)) { 213095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng *flags |= TXFLAG_TAGON; 213131c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison *vlan = cpu_to_le16(vlan_tx_tag_get(skb)); 213295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 213395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 213495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 213595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 21367f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tsengjme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx) 213795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2138eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 213995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct txdesc *txdesc; 214095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi; 214195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u8 flags; 214295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 214395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc = (struct txdesc *)txring->desc + idx; 214495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi = txring->bufinf + idx; 214595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 214695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[0] = 0; 214795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[1] = 0; 214895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[2] = 0; 214995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->dw[3] = 0; 215095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc1.pktsize = cpu_to_le16(skb->len); 215195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 215295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set OWN bit at final. 215395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * When kernel transmit faster than NIC. 215495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * And NIC trying to send this descriptor before we tell 215595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * it to start sending this TX queue. 215695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Other fields are already filled correctly. 215795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 215895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 215995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng flags = TXFLAG_OWN | TXFLAG_INT; 216095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 216195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set checksum flags while not tso 216295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 216395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags)) 216495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_tx_csum(jme, skb, &flags); 216595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags); 21667f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng jme_map_tx_skb(jme, skb, idx); 216795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txdesc->desc1.flags = flags; 216895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 216995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set tx buffer info after telling NIC to send 217095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * For better tx_clean timing 217195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 217295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 217395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->nr_desc = skb_shinfo(skb)->nr_frags + 2; 217495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->skb = skb; 217595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->len = skb->len; 217695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->start_xmit = jiffies; 217795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!txbi->start_xmit) 217895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->start_xmit = (0UL-1); 217995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 218195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 218295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 218495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_stop_queue_if_full(struct jme_adapter *jme) 218595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2186eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng struct jme_ring *txring = &(jme->txring[0]); 218795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_buffer_info *txbi = txring->bufinf; 218895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx = atomic_read(&txring->next_to_clean); 218995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 219095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi += idx; 219195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 219295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smp_wmb(); 219395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) { 219495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(jme->dev); 219549d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, "TX Queue Paused\n"); 219695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng smp_wmb(); 219795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (atomic_read(&txring->nr_free) 219895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng >= (jme->tx_wake_threshold)) { 219995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(jme->dev); 220049d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked\n"); 220195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 220295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 220395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(txbi->start_xmit && 220595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (jiffies - txbi->start_xmit) >= TX_TIMEOUT && 220695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng txbi->skb)) { 220795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(jme->dev); 220849d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_info(jme, tx_queued, jme->dev, 220949d70c4856acfce943fab35fc199b3074961313fJoe Perches "TX Queue Stopped %d@%lu\n", idx, jiffies); 221095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 221195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 221295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 221495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This function is already protected by netif_tx_lock() 221595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 221695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221761357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t 221895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_start_xmit(struct sk_buff *skb, struct net_device *netdev) 221995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 222095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 222195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int idx; 222295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(jme_expand_header(jme, skb))) { 222495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ++(NET_STAT(jme).tx_dropped); 222595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_OK; 222695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 222795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng idx = jme_alloc_txdesc(jme, skb); 222995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (unlikely(idx < 0)) { 223195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 223249d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, tx_err, jme->dev, 223349d70c4856acfce943fab35fc199b3074961313fJoe Perches "BUG! Tx ring full when queue awake!\n"); 223495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_BUSY; 223695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 223795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 22387f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng jme_fill_tx_desc(jme, skb, idx); 223995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXCS, jme->reg_txcs | 224195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_SELECT_QUEUE0 | 224295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_QUEUE0S | 224395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng TXCS_ENABLE); 224495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224549d70c4856acfce943fab35fc199b3074961313fJoe Perches tx_dbg(jme, "xmit: %d+%d@%lu\n", 224649d70c4856acfce943fab35fc199b3074961313fJoe Perches idx, skb_shinfo(skb)->nr_frags + 2, jiffies); 224795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_queue_if_full(jme); 224895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return NETDEV_TX_OK; 225095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 225195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 22528b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tsengstatic void 22538b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tsengjme_set_unicastaddr(struct net_device *netdev) 22548b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng{ 22558b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 22568b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng u32 val; 22578b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 22588b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng val = (netdev->dev_addr[3] & 0xff) << 24 | 22598b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[2] & 0xff) << 16 | 22608b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[1] & 0xff) << 8 | 22618b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[0] & 0xff); 22628b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jwrite32(jme, JME_RXUMA_LO, val); 22638b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng val = (netdev->dev_addr[5] & 0xff) << 8 | 22648b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng (netdev->dev_addr[4] & 0xff); 22658b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jwrite32(jme, JME_RXUMA_HI, val); 22668b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng} 22678b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 226895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 226995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_macaddr(struct net_device *netdev, void *p) 227095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 227195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 227295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct sockaddr *addr = p; 227395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 227495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(netdev)) 227595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EBUSY; 227695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 227795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->macaddr_lock); 227895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 22798b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng jme_set_unicastaddr(netdev); 228095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->macaddr_lock); 228195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 228295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 228395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 228495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 228595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 228695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_multi(struct net_device *netdev) 228795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 228895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 228995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 mc_hash[2] = {}; 229095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 229195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 229295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 229395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_BRDFRAME | RXMCS_UNIFRAME; 229495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 229595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netdev->flags & IFF_PROMISC) { 229695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_ALLFRAME; 229795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (netdev->flags & IFF_ALLMULTI) { 229895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_ALLMULFRAME; 229995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (netdev->flags & IFF_MULTICAST) { 230022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 230195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int bit_nr; 230295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; 230422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, netdev) { 230522bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko bit_nr = ether_crc(ETH_ALEN, ha->addr) & 0x3F; 230695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); 230795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 230895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_LO, mc_hash[0]); 231095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCHT_HI, mc_hash[1]); 231195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 231295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wmb(); 231495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 231595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 231795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 231895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 232095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_change_mtu(struct net_device *netdev, int new_mtu) 232195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 232295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 232395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (new_mtu == jme->old_mtu) 232595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 232695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || 232895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((new_mtu) < IPV6_MIN_MTU)) 232995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 233095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->mtu = new_mtu; 2333d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev_update_features(netdev); 2334d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw 2335ba9adbe67e288823ac1deb7f11576ab5653f833eGuo-Fu Tseng jme_restart_rx_engine(jme); 233695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 233795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 233995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 234095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 234295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_tx_timeout(struct net_device *netdev) 234395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 234495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 234595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 234795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 234895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 234995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 235095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 235295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Force to Reset the link again 235395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 235495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 235595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 235695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2357bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tsengstatic inline void jme_pause_rx(struct jme_adapter *jme) 2358bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng{ 2359bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng atomic_dec(&jme->link_changing); 2360bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2361bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng jme_set_rx_pcc(jme, PCC_OFF); 2362bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 2363bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng JME_NAPI_DISABLE(jme); 2364bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } else { 2365bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_disable(&jme->rxclean_task); 2366bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_disable(&jme->rxempty_task); 2367bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2368bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng} 2369bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2370bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tsengstatic inline void jme_resume_rx(struct jme_adapter *jme) 2371bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng{ 2372bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 2373bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2374bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 2375bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng JME_NAPI_ENABLE(jme); 2376bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } else { 2377bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 2378bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 2379bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2380bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->cur = PCC_P1; 2381bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->attempt = PCC_P1; 2382bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng dpi->cnt = 0; 2383bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 2384bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2385bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng atomic_inc(&jme->link_changing); 2386bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng} 2387bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 238895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 238995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_drvinfo(struct net_device *netdev, 239095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_drvinfo *info) 239195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 239295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 239395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 239423020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 239523020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 239623020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info)); 239795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 239895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 239995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 240095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_regs_len(struct net_device *netdev) 240195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 240295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return JME_REG_LEN; 240395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 240495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 240595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 240695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmmapio_memcpy(struct jme_adapter *jme, u32 *p, u32 reg, int len) 240795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 240895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 240995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 241095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; i += 4) 241195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p[i >> 2] = jread32(jme, reg + i); 241295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 241395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 241495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 241595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmdio_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr) 241695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 241795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 241895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 *p16 = (u16 *)p; 241995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 242095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < reg_nr ; ++i) 242195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p16[i] = jme_mdio_read(jme->dev, jme->mii_if.phy_id, i); 242295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 242395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 242495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 242595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) 242695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 242795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 242895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 *p32 = (u32 *)p; 242995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(p, 0xFF, JME_REG_LEN); 243195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng regs->version = 1; 243395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN); 243495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 243695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_PHY, JME_PHY_LEN); 243795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 243895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 243995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_MISC, JME_MISC_LEN); 244095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 244195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 244295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN); 244395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 244495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng p32 += 0x100 >> 2; 244595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdio_memcpy(jme, p32, JME_PHY_REG_NR); 244695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 244795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 244895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 244995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) 245095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 245195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 245295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 245395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_coalesce_usecs = PCC_TX_TO; 245495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_max_coalesced_frames = PCC_TX_CNT; 245595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 245695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) { 245795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->use_adaptive_rx_coalesce = false; 245895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = 0; 245995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = 0; 246095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 246195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 246295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 246395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->use_adaptive_rx_coalesce = true; 246495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 246595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (jme->dpi.cur) { 246695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P1: 246795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P1_TO; 246895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P1_CNT; 246995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 247095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P2: 247195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P2_TO; 247295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P2_CNT; 247395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 247495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case PCC_P3: 247595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_coalesce_usecs = PCC_P3_TO; 247695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_max_coalesced_frames = PCC_P3_CNT; 247795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 247895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 247995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 248095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 248195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 248295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 248395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 248495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 248595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 248695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) 248795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 248895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 248995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct dynpcc_info *dpi = &(jme->dpi); 249095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 249195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(netdev)) 249295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EBUSY; 249395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 24948e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if (ecmd->use_adaptive_rx_coalesce && 24958e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches test_bit(JME_FLAG_POLL, &jme->flags)) { 249695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng clear_bit(JME_FLAG_POLL, &jme->flags); 249795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_rx; 249895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cur = PCC_P1; 249995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->attempt = PCC_P1; 250095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dpi->cnt = 0; 250195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_rx_pcc(jme, PCC_P1); 250295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 25038e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches } else if (!(ecmd->use_adaptive_rx_coalesce) && 25048e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches !(test_bit(JME_FLAG_POLL, &jme->flags))) { 250595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng set_bit(JME_FLAG_POLL, &jme->flags); 250695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_receive_skb; 250795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_interrupt_mode(jme); 250895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 250995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 251095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 251195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 251295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 251395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 251495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_pauseparam(struct net_device *netdev, 251595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_pauseparam *ecmd) 251695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 251795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 251895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 251995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 252095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->tx_pause = (jme->reg_txpfc & TXPFC_PF_EN) != 0; 252195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->rx_pause = (jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0; 252295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 252395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 252495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); 252595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 252695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 252795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->autoneg = 252895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0; 252995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 253095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 253195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 253295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_pauseparam(struct net_device *netdev, 253395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_pauseparam *ecmd) 253495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 253595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 253695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 253795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 253895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((jme->reg_txpfc & TXPFC_PF_EN) != 0) ^ 253995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->tx_pause != 0)) { 254095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 254195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->tx_pause) 254295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc |= TXPFC_PF_EN; 254395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 254495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc &= ~TXPFC_PF_EN; 254595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 254695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_TXPFC, jme->reg_txpfc); 254795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 254895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 254995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 255095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0) ^ 255195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->rx_pause != 0)) { 255295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 255395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->rx_pause) 255495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_FLOWCTRL; 255595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 255695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs &= ~RXMCS_FLOWCTRL; 255795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 255895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 255995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 256095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 256195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 256295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 256395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); 256495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (((val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0) ^ 256595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (ecmd->autoneg != 0)) { 256695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 256795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ecmd->autoneg) 256895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val |= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); 256995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 257095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); 257195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 257295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 257395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng MII_ADVERTISE, val); 257495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 257595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 257695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 257795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 257895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 257995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 258095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 258195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_wol(struct net_device *netdev, 258295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_wolinfo *wol) 258395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 258495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 258595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 258695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->supported = WAKE_MAGIC | WAKE_PHY; 258795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 258895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts = 0; 258995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 259095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) 259195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts |= WAKE_PHY; 259295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 259395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->reg_pmcs & PMCS_MFEN) 259495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng wol->wolopts |= WAKE_MAGIC; 259595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 259695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 259795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 259895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 259995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_wol(struct net_device *netdev, 260095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_wolinfo *wol) 260195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 260295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 260395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 260495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & (WAKE_MAGICSECURE | 260595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_UCAST | 260695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_MCAST | 260795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_BCAST | 260895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng WAKE_ARP)) 260995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EOPNOTSUPP; 261095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 261195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs = 0; 261295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 261395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & WAKE_PHY) 261495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs |= PMCS_LFEN | PMCS_LREN; 261595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 261695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (wol->wolopts & WAKE_MAGIC) 261795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs |= PMCS_MFEN; 261895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 261995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_PMCS, jme->reg_pmcs); 2620bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); 2621f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 262295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 262395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 262495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 262595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 262695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_settings(struct net_device *netdev, 262795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_cmd *ecmd) 262895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 262995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 263095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc; 263195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 263295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 263395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = mii_ethtool_gset(&(jme->mii_if), ecmd); 263495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 263595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 263695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 263795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 263895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 263995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_settings(struct net_device *netdev, 264095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_cmd *ecmd) 264195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 264295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 264395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc, fdc = 0; 264495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 264525db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny if (ethtool_cmd_speed(ecmd) == SPEED_1000 264625db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny && ecmd->autoneg != AUTONEG_ENABLE) 264795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 264895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 26493ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng /* 26503ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng * Check If user changed duplex only while force_media. 26513ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng * Hardware would not generate link change interrupt. 26523ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng */ 265395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->mii_if.force_media && 265495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ecmd->autoneg != AUTONEG_ENABLE && 265595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (jme->mii_if.full_duplex != ecmd->duplex)) 265695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng fdc = 1; 265795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 265895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->phy_lock); 265995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = mii_ethtool_sset(&(jme->mii_if), ecmd); 266095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 266195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 266295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!rc) { 26633ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng if (fdc) 26643ee94018a9f49ca98e3f77f54a769c784115dbb8Guo-Fu Tseng jme_reset_link(jme); 266595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->old_ecmd = *ecmd; 2666334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng set_bit(JME_FLAG_SSET, &jme->flags); 2667334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng } 2668334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2669334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng return rc; 2670334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng} 2671334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2672334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tsengstatic int 2673334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tsengjme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) 2674334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng{ 2675334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng int rc; 2676334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 2677334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng struct mii_ioctl_data *mii_data = if_mii(rq); 2678334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng unsigned int duplex_chg; 2679334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2680334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (cmd == SIOCSMIIREG) { 2681334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng u16 val = mii_data->val_in; 2682334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (!(val & (BMCR_RESET|BMCR_ANENABLE)) && 2683334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng (val & BMCR_SPEED1000)) 2684334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng return -EINVAL; 2685334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng } 2686334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2687334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng spin_lock_bh(&jme->phy_lock); 2688334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng rc = generic_mii_ioctl(&jme->mii_if, mii_data, cmd, &duplex_chg); 2689334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng spin_unlock_bh(&jme->phy_lock); 2690334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng 2691334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (!rc && (cmd == SIOCSMIIREG)) { 2692334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng if (duplex_chg) 2693334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme_reset_link(jme); 2694334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme_get_settings(netdev, &jme->old_ecmd); 2695334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng set_bit(JME_FLAG_SSET, &jme->flags); 269695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 269795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 269895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 269995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 270095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 270195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u32 270295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_link(struct net_device *netdev) 270395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 270495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 270595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return jread32(jme, JME_PHY_LINK) & PHY_LINK_UP; 270695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 270795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 270895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u32 270995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_msglevel(struct net_device *netdev) 271095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 271195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 271295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return jme->msg_enable; 271395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 271495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 271595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 271695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_msglevel(struct net_device *netdev, u32 value) 271795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 271895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 271995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->msg_enable = value; 272095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 272195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2722c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awstatic netdev_features_t 2723c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awjme_fix_features(struct net_device *netdev, netdev_features_t features) 272495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2725d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (netdev->mtu > 1900) 2726d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM); 2727d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw return features; 272895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 272995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 273095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 2731c8f44affb7244f2ac3e703cab13d55ede27621bbMichaÅ‚ MirosÅ‚awjme_set_features(struct net_device *netdev, netdev_features_t features) 273295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 273395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 273495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 273595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_bh(&jme->rxmcs_lock); 2736d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (features & NETIF_F_RXCSUM) 273795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs |= RXMCS_CHECKSUM; 273895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 273995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs &= ~RXMCS_CHECKSUM; 274095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); 274195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_bh(&jme->rxmcs_lock); 274295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 274395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 274495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 274595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 274695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 274795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_nway_reset(struct net_device *netdev) 274895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 274995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 275095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_restart_an(jme); 275195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 275295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 275395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 275495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic u8 275595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_smb_read(struct jme_adapter *jme, unsigned int addr) 275695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 275795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 275895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int to; 275995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 276095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 276195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 276295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBCSR_BUSY) && --to) { 276395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 276495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 276595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 276695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 276749d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 276895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0xFF; 276995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 277095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 277195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBINTF, 277295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | 277395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWRWN_READ | 277495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWCMD); 277595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 277695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 277795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 277895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBINTF_HWCMD) && --to) { 277995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 278095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 278195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 278295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 278349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 278495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0xFF; 278595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 278695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 278795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return (val & SMBINTF_HWDATR) >> SMBINTF_HWDATR_SHIFT; 278895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 278995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 279095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void 279195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data) 279295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 279395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 279495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int to; 279595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 279695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 279795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 279895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBCSR_BUSY) && --to) { 279995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 280095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 280195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 280295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 280349d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 280495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 280595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 280695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 280795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_SMBINTF, 280895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((data << SMBINTF_HWDATW_SHIFT) & SMBINTF_HWDATW) | 280995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | 281095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWRWN_WRITE | 281195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SMBINTF_HWCMD); 281295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 281395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 281495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng to = JME_SMB_BUSY_TIMEOUT; 281595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((val & SMBINTF_HWCMD) && --to) { 281695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng msleep(1); 281795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBINTF); 281895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 281995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!to) { 282049d70c4856acfce943fab35fc199b3074961313fJoe Perches netif_err(jme, hw, jme->dev, "SMB Bus Busy\n"); 282195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 282295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 282395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 282495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mdelay(2); 282595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 282695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 282795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 282895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_eeprom_len(struct net_device *netdev) 282995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 283095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 283195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 val; 283295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng val = jread32(jme, JME_SMBCSR); 283395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return (val & SMBCSR_EEPROMD) ? JME_SMB_LEN : 0; 283495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 283595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 283695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 283795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_get_eeprom(struct net_device *netdev, 283895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_eeprom *eeprom, u8 *data) 283995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 284095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 284195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, offset = eeprom->offset, len = eeprom->len; 284295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 284395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 284495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * ethtool will check the boundary for us 284595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 284695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng eeprom->magic = JME_EEPROM_MAGIC; 284795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; ++i) 284895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng data[i] = jme_smb_read(jme, i + offset); 284995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 285095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 285195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 285295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 285395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 285495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_set_eeprom(struct net_device *netdev, 285595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct ethtool_eeprom *eeprom, u8 *data) 285695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 285795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 285895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i, offset = eeprom->offset, len = eeprom->len; 285995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 286095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eeprom->magic != JME_EEPROM_MAGIC) 286195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EINVAL; 286295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 286395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 286495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * ethtool will check the boundary for us 286595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 286695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0 ; i < len ; ++i) 286795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_smb_write(jme, i + offset, data[i]); 286895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 286995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 287095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 287195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 287295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic const struct ethtool_ops jme_ethtool_ops = { 287395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_drvinfo = jme_get_drvinfo, 287495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_regs_len = jme_get_regs_len, 287595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_regs = jme_get_regs, 287695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_coalesce = jme_get_coalesce, 287795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_coalesce = jme_set_coalesce, 287895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_pauseparam = jme_get_pauseparam, 287995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_pauseparam = jme_set_pauseparam, 288095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_wol = jme_get_wol, 288195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_wol = jme_set_wol, 288295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_settings = jme_get_settings, 288395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_settings = jme_set_settings, 288495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_link = jme_get_link, 288595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_msglevel = jme_get_msglevel, 288695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_msglevel = jme_set_msglevel, 288795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .nway_reset = jme_nway_reset, 288895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_eeprom_len = jme_get_eeprom_len, 288995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .get_eeprom = jme_get_eeprom, 289095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .set_eeprom = jme_set_eeprom, 289195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 289295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 289395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int 289495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_pci_dma64(struct pci_dev *pdev) 289595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 2896814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && 2897e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) 2898e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) 2899814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng return 1; 2900814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng 2901814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && 2902e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(40))) 2903e930438c42e744ef1f8bfdbb338253c9f384df42Yang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40))) 2904814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng return 1; 2905814c01dc7c533033b4e99981a2e24a6195bfb43cGuo-Fu Tseng 2906284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) 2907284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) 290895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 290995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 291095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 291195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 291295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 291395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 291495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_phy_init(struct jme_adapter *jme) 291595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 291695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 reg26; 291795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 291895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg26 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 26); 291995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_mdio_write(jme->dev, jme->mii_if.phy_id, 26, reg26 | 0x1000); 292095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 292195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 292295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic inline void 292395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_check_hw_ver(struct jme_adapter *jme) 292495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 292595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 chipmode; 292695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 292795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chipmode = jread32(jme, JME_CHIPMODE); 292895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 292995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT; 293095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT; 293119d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->chip_main_rev = jme->chiprev & 0xF; 293219d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF; 293395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 293495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2935e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemmingerstatic const struct net_device_ops jme_netdev_ops = { 2936e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_open = jme_open, 2937e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_stop = jme_close, 2938e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_validate_addr = eth_validate_addr, 2939334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng .ndo_do_ioctl = jme_ioctl, 2940e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_start_xmit = jme_start_xmit, 2941e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_set_mac_address = jme_set_macaddr, 2942afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = jme_set_multi, 2943e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_change_mtu = jme_change_mtu, 2944e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger .ndo_tx_timeout = jme_tx_timeout, 2945d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw .ndo_fix_features = jme_fix_features, 2946d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw .ndo_set_features = jme_set_features, 2947e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger}; 2948e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger 294995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __devinit 295095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_init_one(struct pci_dev *pdev, 295195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng const struct pci_device_id *ent) 295295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 295395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int rc = 0, using_dac, i; 295495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev; 295595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme; 295695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u16 bmcr, bmsr; 295795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng u32 apmc; 295895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 295995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 296095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * set up PCI device basics 296195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 296295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = pci_enable_device(pdev); 296395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 296449d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot enable PCI device\n"); 296595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out; 296695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 296795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 296895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng using_dac = jme_pci_dma64(pdev); 296995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (using_dac < 0) { 297049d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot set PCI DMA Mask\n"); 297195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -EIO; 297295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 297395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 297495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 297595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 297649d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("No PCI resource region found\n"); 297795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 297895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 297995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 298095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 298195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = pci_request_regions(pdev, DRV_NAME); 298295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 298349d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot obtain PCI resource region\n"); 298495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_disable_pdev; 298595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 298695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 298795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_master(pdev); 298895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 298995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 299095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * alloc and init net device 299195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 299295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev = alloc_etherdev(sizeof(*jme)); 299395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!netdev) { 299495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 299595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_release_regions; 299695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 2997e48714baac0e81ed9e19a5785eee52e1eca8f56eStephen Hemminger netdev->netdev_ops = &jme_netdev_ops; 299895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->ethtool_ops = &jme_ethtool_ops; 299995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->watchdog_timeo = TX_TIMEOUT; 3000d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev->hw_features = NETIF_F_IP_CSUM | 3001d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_IPV6_CSUM | 3002d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_SG | 3003d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_TSO | 3004d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_TSO6 | 3005d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw NETIF_F_RXCSUM; 30067903264402546f45f9bac8ad2bfdb00d00eb124aMichaÅ‚ MirosÅ‚aw netdev->features = NETIF_F_IP_CSUM | 30077903264402546f45f9bac8ad2bfdb00d00eb124aMichaÅ‚ MirosÅ‚aw NETIF_F_IPV6_CSUM | 300895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_SG | 300995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_TSO | 301095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_TSO6 | 301195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_HW_VLAN_TX | 301295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_F_HW_VLAN_RX; 301395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (using_dac) 301495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netdev->features |= NETIF_F_HIGHDMA; 301595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 301695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SET_NETDEV_DEV(netdev, &pdev->dev); 301795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, netdev); 301895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 301995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 302095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * init adapter info 302195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 302295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme = netdev_priv(netdev); 302395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->pdev = pdev; 302495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dev = netdev; 302595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->jme_rx = netif_rx; 302695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->old_mtu = netdev->mtu = 1500; 302795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 302895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_ring_size = 1 << 10; 302995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_ring_mask = jme->tx_ring_size - 1; 303095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->tx_wake_threshold = 1 << 9; 303195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->rx_ring_size = 1 << 9; 303295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->rx_ring_mask = jme->rx_ring_size - 1; 303395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->msg_enable = JME_DEF_MSG_ENABLE; 303495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->regs = ioremap(pci_resource_start(pdev, 0), 303595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_resource_len(pdev, 0)); 303695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(jme->regs)) { 303749d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Mapping PCI resource region error\n"); 303895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -ENOMEM; 303995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto err_out_free_netdev; 304095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 304195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 304295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (no_pseudohp) { 304395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC) & ~JME_APMC_PSEUDO_HP_EN; 304495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_APMC, apmc); 304595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (force_pseudohp) { 304695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng apmc = jread32(jme, JME_APMC) | JME_APMC_PSEUDO_HP_EN; 304795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jwrite32(jme, JME_APMC, apmc); 304895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 304995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 305095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, jme->rx_ring_size >> 2) 305195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 305295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->phy_lock); 305395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->macaddr_lock); 305495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&jme->rxmcs_lock); 305595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 305695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->link_changing, 1); 305795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->rx_cleaning, 1); 305895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->tx_cleaning, 1); 305995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_set(&jme->rx_empty, 1); 306095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 306195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->pcc_task, 3062164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_pcc_tasklet, 306395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 306495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->linkch_task, 3065164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_link_change_tasklet, 306695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 306795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->txclean_task, 3068164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_tx_clean_tasklet, 306995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 307095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->rxclean_task, 3071164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_rx_clean_tasklet, 307295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 307395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_init(&jme->rxempty_task, 3074164165dad7e607ec359e64b6fae72abbf3640ea6Joe Perches jme_rx_empty_tasklet, 307595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (unsigned long) jme); 307638ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng tasklet_disable_nosync(&jme->linkch_task); 307795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->txclean_task); 307895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->rxclean_task); 307995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable_nosync(&jme->rxempty_task); 308095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->dpi.cur = PCC_P1; 308195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 308295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_ghc = 0; 308395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxcs = RXCS_DEFAULT; 308495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_rxmcs = RXMCS_DEFAULT; 308595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txpfc = 0; 308695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_pmcs = PMCS_MFEN; 3087854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng jme->reg_gpreg1 = GPREG1_DEFAULT; 3088d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw 3089d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw if (jme->reg_rxmcs & RXMCS_CHECKSUM) 3090d7b576545648e487b2958c220542e111f5ac46f0MichaÅ‚ MirosÅ‚aw netdev->features |= NETIF_F_RXCSUM; 309195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 309295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 309395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Get Max Read Req Size from PCI Config Space 309495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 309595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_read_config_byte(pdev, PCI_DCSR_MRRS, &jme->mrrs); 309695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mrrs &= PCI_DCSR_MRRS_MASK; 309795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (jme->mrrs) { 309895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case MRRS_128B: 309995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_128B; 310095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 310195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case MRRS_256B: 310295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_256B; 310395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 310495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 310595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_512B; 310695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 3107ee289b6440c3b0ccb9459495783e8c299bec6604Joe Perches } 310895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 310995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 311095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Must check before reset_mac_processor 311195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 311295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_check_hw_ver(jme); 311395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.dev = netdev; 311495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (jme->fpgaver) { 311595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = 0; 311695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 1 ; i < 32 ; ++i) { 311795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmcr = jme_mdio_read(netdev, i, MII_BMCR); 311895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bmsr = jme_mdio_read(netdev, i, MII_BMSR); 311995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (bmcr != 0xFFFFU && (bmcr != 0 || bmsr != 0)) { 312095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = i; 312195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 312295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 312395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 312495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 312595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!jme->mii_if.phy_id) { 312695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = -EIO; 312749d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Can not find phy_id\n"); 312849d70c4856acfce943fab35fc199b3074961313fJoe Perches goto err_out_unmap; 312995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 313095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 313195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->reg_ghc |= GHC_LINK_POLL; 313295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 313395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.phy_id = 1; 313495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 313595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) 313695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.supports_gmii = true; 313795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 313895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.supports_gmii = false; 3139334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme->mii_if.phy_id_mask = 0x1F; 3140334fbbb747c978ae9171b9c29dfcea881f4a8d57Guo-Fu Tseng jme->mii_if.reg_num_mask = 0x1F; 314195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.mdio_read = jme_mdio_read; 314295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->mii_if.mdio_write = jme_mdio_write; 314395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 314495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_clear_pm(jme); 3145bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng pci_set_power_state(jme->pdev, PCI_D0); 3146bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng device_set_wakeup_enable(&pdev->dev, true); 3147bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng 314851754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng jme_set_phyfifo_5level(jme); 3149ff938e43d39e926de74b32a3656c190f979ab642Sergei Shtylyov jme->pcirev = pdev->revision; 315095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!jme->fpgaver) 315195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_init(jme); 315295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_phy_off(jme); 315395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 315495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 315595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Reset MAC processor and reload EEPROM for MAC Address 315695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 315795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 315895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = jme_reload_eeprom(jme); 315995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 316049d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Reload eeprom for reading MAC Address error\n"); 3161d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng goto err_out_unmap; 316295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 316395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_load_macaddr(netdev); 316495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 316595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 316695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Tell stack that we are not ready to work until open() 316795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 316895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 316995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 317095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rc = register_netdev(netdev); 317195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (rc) { 317249d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_err("Cannot register net device\n"); 3173d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng goto err_out_unmap; 317495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 317595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 317619d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n", 3177f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? 3178f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches "JMC250 Gigabit Ethernet" : 3179f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? 3180f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches "JMC260 Fast Ethernet" : "Unknown", 3181f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->fpgaver != 0) ? " (FPGA)" : "", 3182f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, 318319d96017d1b5b1c9b709bc21a398ea793256644cGuo-Fu Tseng jme->pcirev, netdev->dev_addr); 318495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 318595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 318695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 318795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_unmap: 318895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iounmap(jme->regs); 318995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_free_netdev: 319095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, NULL); 319195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_netdev(netdev); 319295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_release_regions: 319395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_release_regions(pdev); 319495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out_disable_pdev: 319595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_device(pdev); 319695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengerr_out: 319795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return rc; 319895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 319995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 320095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void __devexit 320195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_remove_one(struct pci_dev *pdev) 320295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 320395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 320495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 320595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 320695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unregister_netdev(netdev); 320795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iounmap(jme->regs); 320895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_set_drvdata(pdev, NULL); 320995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_netdev(netdev); 321095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_release_regions(pdev); 321195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_disable_device(pdev); 321295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 321395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 321495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 32151c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengstatic void 32161c5578194abde100c089855cce72e87c047d8530Guo-Fu Tsengjme_shutdown(struct pci_dev *pdev) 32171c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng{ 32181c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 32191c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 32201c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 32211c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_powersave_phy(jme); 32221c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng pci_pme_active(pdev, true); 32231c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng} 32241c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 3225aab6fb82b1912a312f7547c92ac8d4ecb072e807Guo-Fu Tseng#ifdef CONFIG_PM_SLEEP 3226bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengstatic int 3227bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengjme_suspend(struct device *dev) 322895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 3229f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki struct pci_dev *pdev = to_pci_dev(dev); 323095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 323195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 323295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3233a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher if (!netif_running(netdev)) 3234a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher return 0; 3235a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher 323695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_dec(&jme->link_changing); 323795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 323895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_detach(netdev); 323995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(netdev); 324095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_irq(jme); 324195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 324295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->txclean_task); 324395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxclean_task); 324495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_disable(&jme->rxempty_task); 324595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 324695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_carrier_ok(netdev)) { 324795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (test_bit(JME_FLAG_POLL, &jme->flags)) 324895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_polling_mode(jme); 324995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 325095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_stop_pcc_timer(jme); 325195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_rx_engine(jme); 325295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_disable_tx_engine(jme); 325395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_mac_processor(jme); 325495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_rx_resources(jme); 325595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_free_tx_resources(jme); 325695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_carrier_off(netdev); 325795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme->phylink = 0; 325895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 325995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 326095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_enable(&jme->txclean_task); 326195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxclean_task); 326295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng tasklet_hi_enable(&jme->rxempty_task); 326395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 32641c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng jme_powersave_phy(jme); 326595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 326695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 326795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 326895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3269bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengstatic int 3270bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tsengjme_resume(struct device *dev) 327195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 3272f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki struct pci_dev *pdev = to_pci_dev(dev); 327395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *netdev = pci_get_drvdata(pdev); 327495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct jme_adapter *jme = netdev_priv(netdev); 327595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3276a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher if (!netif_running(netdev)) 3277a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher return 0; 3278a7d5b76d9a7e434e32a5b2815db45489617dcba6Clemens Buchacher 3279bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng jme_clear_pm(jme); 32804872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng jme_phy_on(jme); 32814872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng if (test_bit(JME_FLAG_SSET, &jme->flags)) 328295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_set_settings(netdev, &jme->old_ecmd); 32834872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng else 328495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_phy_processor(jme); 3285c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_calibration(jme); 3286c4860ba2e11261a541632ceee8267ca490d9eb98Aries Lee jme_phy_setEA(jme); 328795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_start_irq(jme); 328895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_attach(netdev); 328995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 329095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng atomic_inc(&jme->link_changing); 329195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 329295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng jme_reset_link(jme); 329395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 329495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 329595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 3296f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3297f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysockistatic SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); 3298f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#define JME_PM_OPS (&jme_pm_ops) 3299f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3300f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#else 3301f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki 3302f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki#define JME_PM_OPS NULL 3303724f88057609c00d6e973c3a7e0eb72f8eec2da9David S. Miller#endif 330495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 3305a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { 330695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, 330795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, 330895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { } 330995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 331095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 331195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct pci_driver jme_driver = { 331295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .name = DRV_NAME, 331395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .id_table = jme_pci_tbl, 331495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .probe = jme_init_one, 331595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .remove = __devexit_p(jme_remove_one), 33161c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng .shutdown = jme_shutdown, 3317f4e5bd4f5784c0608078805f29d4a4897ee482f7Rafael J. Wysocki .driver.pm = JME_PM_OPS, 331895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 331995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 332095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __init 332195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_init_module(void) 332295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 332349d70c4856acfce943fab35fc199b3074961313fJoe Perches pr_info("JMicron JMC2XX ethernet driver version %s\n", DRV_VERSION); 332495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return pci_register_driver(&jme_driver); 332595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 332695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 332795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void __exit 332895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengjme_cleanup_module(void) 332995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 333095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pci_unregister_driver(&jme_driver); 333195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 333295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 333395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_init(jme_init_module); 333495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_exit(jme_cleanup_module); 333595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 333695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_AUTHOR("Guo-Fu Tseng <cooldavid@cooldavid.org>"); 333795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver"); 333895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_LICENSE("GPL"); 333995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_VERSION(DRV_VERSION); 334095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DEVICE_TABLE(pci, jme_pci_tbl); 3341