From: Linus Torvalds Date: Tue, 25 Oct 2011 11:25:22 +0000 (+0200) Subject: Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8a9ea3237e7e;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git Merge git://git./linux/kernel/git/davem/net-next * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1745 commits) dp83640: free packet queues on remove dp83640: use proper function to free transmit time stamping packets ipv6: Do not use routes from locally generated RAs |PATCH net-next] tg3: add tx_dropped counter be2net: don't create multiple RX/TX rings in multi channel mode be2net: don't create multiple TXQs in BE2 be2net: refactor VF setup/teardown code into be_vf_setup/clear() be2net: add vlan/rx-mode/flow-control config to be_setup() net_sched: cls_flow: use skb_header_pointer() ipv4: avoid useless call of the function check_peer_pmtu TCP: remove TCP_DEBUG net: Fix driver name for mdio-gpio.c ipv4: tcp: fix TOS value in ACK messages sent from TIME_WAIT rtnetlink: Add missing manual netlink notification in dev_change_net_namespaces ipv4: fix ipsec forward performance regression jme: fix irq storm after suspend/resume route: fix ICMP redirect validation net: hold sock reference while processing tx timestamps tcp: md5: add more const attributes Add ethtool -g support to virtio_net ... Fix up conflicts in: - drivers/net/Kconfig: The split-up generated a trivial conflict with removal of a stale reference to Documentation/networking/net-modules.txt. Remove it from the new location instead. - fs/sysfs/dir.c: Fairly nasty conflicts with the sysfs rb-tree usage, conflicting with Eric Biederman's changes for tagged directories. --- 8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 diff --cc drivers/net/ethernet/atheros/atlx/atl1.c index 000000000000,0405261efb5c..33a4e35f5ee8 mode 000000,100644..100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@@ -1,0 -1,3668 +1,3668 @@@ + /* + * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. + * Copyright(c) 2006 - 2007 Chris Snook + * Copyright(c) 2006 - 2008 Jay Cliburn + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + * + * Contact Information: + * Xiong Huang + * Jie Yang + * Chris Snook + * Jay Cliburn + * + * This version is adapted from the Attansic reference driver. + * + * TODO: + * Add more ethtool functions. + * Fix abstruse irq enable/disable condition described here: + * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 + * + * NEEDS TESTING: + * VLAN + * multicast + * promiscuous mode + * interrupt coalescing + * SMP torture testing + */ + + #include + #include + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #include "atl1.h" + + #define ATLX_DRIVER_VERSION "2.1.3" + MODULE_AUTHOR("Xiong Huang , " + "Chris Snook , " + "Jay Cliburn "); + MODULE_LICENSE("GPL"); + MODULE_VERSION(ATLX_DRIVER_VERSION); + + /* Temporary hack for merging atl1 and atl2 */ + #include "atlx.c" + + static const struct ethtool_ops atl1_ethtool_ops; + + /* + * This is the only thing that needs to be changed to adjust the + * maximum number of ports that the driver can manage. + */ + #define ATL1_MAX_NIC 4 + + #define OPTION_UNSET -1 + #define OPTION_DISABLED 0 + #define OPTION_ENABLED 1 + + #define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET } + + /* + * Interrupt Moderate Timer in units of 2 us + * + * Valid Range: 10-65535 + * + * Default Value: 100 (200us) + */ + static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; + static unsigned int num_int_mod_timer; + module_param_array_named(int_mod_timer, int_mod_timer, int, + &num_int_mod_timer, 0); + MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer"); + + #define DEFAULT_INT_MOD_CNT 100 /* 200us */ + #define MAX_INT_MOD_CNT 65000 + #define MIN_INT_MOD_CNT 50 + + struct atl1_option { + enum { enable_option, range_option, list_option } type; + char *name; + char *err; + int def; + union { + struct { /* range_option info */ + int min; + int max; + } r; + struct { /* list_option info */ + int nr; + struct atl1_opt_list { + int i; + char *str; + } *p; + } l; + } arg; + }; + + static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, + struct pci_dev *pdev) + { + if (*value == OPTION_UNSET) { + *value = opt->def; + return 0; + } + + switch (opt->type) { + case enable_option: + switch (*value) { + case OPTION_ENABLED: + dev_info(&pdev->dev, "%s enabled\n", opt->name); + return 0; + case OPTION_DISABLED: + dev_info(&pdev->dev, "%s disabled\n", opt->name); + return 0; + } + break; + case range_option: + if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { + dev_info(&pdev->dev, "%s set to %i\n", opt->name, + *value); + return 0; + } + break; + case list_option:{ + int i; + struct atl1_opt_list *ent; + + for (i = 0; i < opt->arg.l.nr; i++) { + ent = &opt->arg.l.p[i]; + if (*value == ent->i) { + if (ent->str[0] != '\0') + dev_info(&pdev->dev, "%s\n", + ent->str); + return 0; + } + } + } + break; + + default: + break; + } + + dev_info(&pdev->dev, "invalid %s specified (%i) %s\n", + opt->name, *value, opt->err); + *value = opt->def; + return -1; + } + + /* + * atl1_check_options - Range Checking for Command Line Parameters + * @adapter: board private structure + * + * This routine checks all command line parameters for valid user + * input. If an invalid value is given, or if no user specified + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + */ + static void __devinit atl1_check_options(struct atl1_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + int bd = adapter->bd_number; + if (bd >= ATL1_MAX_NIC) { + dev_notice(&pdev->dev, "no configuration for board#%i\n", bd); + dev_notice(&pdev->dev, "using defaults for all values\n"); + } + { /* Interrupt Moderate Timer */ + struct atl1_option opt = { + .type = range_option, + .name = "Interrupt Moderator Timer", + .err = "using default of " + __MODULE_STRING(DEFAULT_INT_MOD_CNT), + .def = DEFAULT_INT_MOD_CNT, + .arg = {.r = {.min = MIN_INT_MOD_CNT, + .max = MAX_INT_MOD_CNT} } + }; + int val; + if (num_int_mod_timer > bd) { + val = int_mod_timer[bd]; + atl1_validate_option(&val, &opt, pdev); + adapter->imt = (u16) val; + } else + adapter->imt = (u16) (opt.def); + } + } + + /* + * atl1_pci_tbl - PCI Device ID Table + */ + static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = { + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)}, + /* required last entry */ + {0,} + }; + MODULE_DEVICE_TABLE(pci, atl1_pci_tbl); + + static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | + NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; + + static int debug = -1; + module_param(debug, int, 0); + MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)"); + + /* + * Reset the transmit and receive units; mask and clear all interrupts. + * hw - Struct containing variables accessed by shared code + * return : 0 or idle status (if error) + */ + static s32 atl1_reset_hw(struct atl1_hw *hw) + { + struct pci_dev *pdev = hw->back->pdev; + struct atl1_adapter *adapter = hw->back; + u32 icr; + int i; + + /* + * Clear Interrupt mask to stop board from generating + * interrupts & Clear any pending interrupt events + */ + /* + * iowrite32(0, hw->hw_addr + REG_IMR); + * iowrite32(0xffffffff, hw->hw_addr + REG_ISR); + */ + + /* + * Issue Soft Reset to the MAC. This will reset the chip's + * transmit, receive, DMA. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL); + ioread32(hw->hw_addr + REG_MASTER_CTRL); + + iowrite16(1, hw->hw_addr + REG_PHY_ENABLE); + ioread16(hw->hw_addr + REG_PHY_ENABLE); + + /* delay about 1ms */ + msleep(1); + + /* Wait at least 10ms for All module to be Idle */ + for (i = 0; i < 10; i++) { + icr = ioread32(hw->hw_addr + REG_IDLE_STATUS); + if (!icr) + break; + /* delay 1 ms */ + msleep(1); + /* FIXME: still the right way to do this? */ + cpu_relax(); + } + + if (icr) { + if (netif_msg_hw(adapter)) + dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr); + return icr; + } + + return 0; + } + + /* function about EEPROM + * + * check_eeprom_exist + * return 0 if eeprom exist + */ + static int atl1_check_eeprom_exist(struct atl1_hw *hw) + { + u32 value; + value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL); + if (value & SPI_FLASH_CTRL_EN_VPD) { + value &= ~SPI_FLASH_CTRL_EN_VPD; + iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL); + } + + value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST); + return ((value & 0xFF00) == 0x6C00) ? 0 : 1; + } + + static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value) + { + int i; + u32 control; + + if (offset & 3) + /* address do not align */ + return false; + + iowrite32(0, hw->hw_addr + REG_VPD_DATA); + control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; + iowrite32(control, hw->hw_addr + REG_VPD_CAP); + ioread32(hw->hw_addr + REG_VPD_CAP); + + for (i = 0; i < 10; i++) { + msleep(2); + control = ioread32(hw->hw_addr + REG_VPD_CAP); + if (control & VPD_CAP_VPD_FLAG) + break; + } + if (control & VPD_CAP_VPD_FLAG) { + *p_value = ioread32(hw->hw_addr + REG_VPD_DATA); + return true; + } + /* timeout */ + return false; + } + + /* + * Reads the value from a PHY register + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to read + */ + static s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data) + { + u32 val; + int i; + + val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | + MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 << + MDIO_CLK_SEL_SHIFT; + iowrite32(val, hw->hw_addr + REG_MDIO_CTRL); + ioread32(hw->hw_addr + REG_MDIO_CTRL); + + for (i = 0; i < MDIO_WAIT_TIMES; i++) { + udelay(2); + val = ioread32(hw->hw_addr + REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + } + if (!(val & (MDIO_START | MDIO_BUSY))) { + *phy_data = (u16) val; + return 0; + } + return ATLX_ERR_PHY; + } + + #define CUSTOM_SPI_CS_SETUP 2 + #define CUSTOM_SPI_CLK_HI 2 + #define CUSTOM_SPI_CLK_LO 2 + #define CUSTOM_SPI_CS_HOLD 2 + #define CUSTOM_SPI_CS_HI 3 + + static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf) + { + int i; + u32 value; + + iowrite32(0, hw->hw_addr + REG_SPI_DATA); + iowrite32(addr, hw->hw_addr + REG_SPI_ADDR); + + value = SPI_FLASH_CTRL_WAIT_READY | + (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) << + SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI & + SPI_FLASH_CTRL_CLK_HI_MASK) << + SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO & + SPI_FLASH_CTRL_CLK_LO_MASK) << + SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD & + SPI_FLASH_CTRL_CS_HOLD_MASK) << + SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI & + SPI_FLASH_CTRL_CS_HI_MASK) << + SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) << + SPI_FLASH_CTRL_INS_SHIFT; + + iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL); + + value |= SPI_FLASH_CTRL_START; + iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL); + ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL); + + for (i = 0; i < 10; i++) { + msleep(1); + value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL); + if (!(value & SPI_FLASH_CTRL_START)) + break; + } + + if (value & SPI_FLASH_CTRL_START) + return false; + + *buf = ioread32(hw->hw_addr + REG_SPI_DATA); + + return true; + } + + /* + * get_permanent_address + * return 0 if get valid mac address, + */ + static int atl1_get_permanent_address(struct atl1_hw *hw) + { + u32 addr[2]; + u32 i, control; + u16 reg; + u8 eth_addr[ETH_ALEN]; + bool key_valid; + + if (is_valid_ether_addr(hw->perm_mac_addr)) + return 0; + + /* init */ + addr[0] = addr[1] = 0; + + if (!atl1_check_eeprom_exist(hw)) { + reg = 0; + key_valid = false; + /* Read out all EEPROM content */ + i = 0; + while (1) { + if (atl1_read_eeprom(hw, i + 0x100, &control)) { + if (key_valid) { + if (reg == REG_MAC_STA_ADDR) + addr[0] = control; + else if (reg == (REG_MAC_STA_ADDR + 4)) + addr[1] = control; + key_valid = false; + } else if ((control & 0xff) == 0x5A) { + key_valid = true; + reg = (u16) (control >> 16); + } else + break; + } else + /* read error */ + break; + i += 4; + } + + *(u32 *) ð_addr[2] = swab32(addr[0]); + *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]); + if (is_valid_ether_addr(eth_addr)) { + memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); + return 0; + } + } + + /* see if SPI FLAGS exist ? */ + addr[0] = addr[1] = 0; + reg = 0; + key_valid = false; + i = 0; + while (1) { + if (atl1_spi_read(hw, i + 0x1f000, &control)) { + if (key_valid) { + if (reg == REG_MAC_STA_ADDR) + addr[0] = control; + else if (reg == (REG_MAC_STA_ADDR + 4)) + addr[1] = control; + key_valid = false; + } else if ((control & 0xff) == 0x5A) { + key_valid = true; + reg = (u16) (control >> 16); + } else + /* data end */ + break; + } else + /* read error */ + break; + i += 4; + } + + *(u32 *) ð_addr[2] = swab32(addr[0]); + *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]); + if (is_valid_ether_addr(eth_addr)) { + memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); + return 0; + } + + /* + * On some motherboards, the MAC address is written by the + * BIOS directly to the MAC register during POST, and is + * not stored in eeprom. If all else thus far has failed + * to fetch the permanent MAC address, try reading it directly. + */ + addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR); + addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4)); + *(u32 *) ð_addr[2] = swab32(addr[0]); + *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]); + if (is_valid_ether_addr(eth_addr)) { + memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); + return 0; + } + + return 1; + } + + /* + * Reads the adapter's MAC address from the EEPROM + * hw - Struct containing variables accessed by shared code + */ + static s32 atl1_read_mac_addr(struct atl1_hw *hw) + { + u16 i; + + if (atl1_get_permanent_address(hw)) + random_ether_addr(hw->perm_mac_addr); + + for (i = 0; i < ETH_ALEN; i++) + hw->mac_addr[i] = hw->perm_mac_addr[i]; + return 0; + } + + /* + * Hashes an address to determine its location in the multicast table + * hw - Struct containing variables accessed by shared code + * mc_addr - the multicast address to hash + * + * atl1_hash_mc_addr + * purpose + * set hash value for a multicast address + * hash calcu processing : + * 1. calcu 32bit CRC for multicast address + * 2. reverse crc with MSB to LSB + */ + static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) + { + u32 crc32, value = 0; + int i; + + crc32 = ether_crc_le(6, mc_addr); + for (i = 0; i < 32; i++) + value |= (((crc32 >> i) & 1) << (31 - i)); + + return value; + } + + /* + * Sets the bit in the multicast table corresponding to the hash value. + * hw - Struct containing variables accessed by shared code + * hash_value - Multicast address hash value + */ + static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value) + { + u32 hash_bit, hash_reg; + u32 mta; + + /* + * The HASH Table is a register array of 2 32-bit registers. + * It is treated like an array of 64 bits. We want to set + * bit BitArray[hash_value]. So we figure out what register + * the bit is in, read it, OR in the new bit, then write + * back the new value. The register is determined by the + * upper 7 bits of the hash value and the bit within that + * register are determined by the lower 5 bits of the value. + */ + hash_reg = (hash_value >> 31) & 0x1; + hash_bit = (hash_value >> 26) & 0x1F; + mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2)); + mta |= (1 << hash_bit); + iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2)); + } + + /* + * Writes a value to a PHY register + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to write + * data - data to write to the PHY + */ + static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data) + { + int i; + u32 val; + + val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | + (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | + MDIO_SUP_PREAMBLE | + MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; + iowrite32(val, hw->hw_addr + REG_MDIO_CTRL); + ioread32(hw->hw_addr + REG_MDIO_CTRL); + + for (i = 0; i < MDIO_WAIT_TIMES; i++) { + udelay(2); + val = ioread32(hw->hw_addr + REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + } + + if (!(val & (MDIO_START | MDIO_BUSY))) + return 0; + + return ATLX_ERR_PHY; + } + + /* + * Make L001's PHY out of Power Saving State (bug) + * hw - Struct containing variables accessed by shared code + * when power on, L001's PHY always on Power saving State + * (Gigabit Link forbidden) + */ + static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) + { + s32 ret; + ret = atl1_write_phy_reg(hw, 29, 0x0029); + if (ret) + return ret; + return atl1_write_phy_reg(hw, 30, 0); + } + + /* + * Resets the PHY and make all config validate + * hw - Struct containing variables accessed by shared code + * + * Sets bit 15 and 12 of the MII Control regiser (for F001 bug) + */ + static s32 atl1_phy_reset(struct atl1_hw *hw) + { + struct pci_dev *pdev = hw->back->pdev; + struct atl1_adapter *adapter = hw->back; + s32 ret_val; + u16 phy_data; + + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN; + else { + switch (hw->media_type) { + case MEDIA_TYPE_100M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 | + MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET; + break; + default: + /* MEDIA_TYPE_10M_HALF: */ + phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + break; + } + } + + ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data); + if (ret_val) { + u32 val; + int i; + /* pcie serdes link may be down! */ + if (netif_msg_hw(adapter)) + dev_dbg(&pdev->dev, "pcie phy link down\n"); + + for (i = 0; i < 25; i++) { + msleep(1); + val = ioread32(hw->hw_addr + REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + } + + if ((val & (MDIO_START | MDIO_BUSY)) != 0) { + if (netif_msg_hw(adapter)) + dev_warn(&pdev->dev, + "pcie link down at least 25ms\n"); + return ret_val; + } + } + return 0; + } + + /* + * Configures PHY autoneg and flow control advertisement settings + * hw - Struct containing variables accessed by shared code + */ + static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw) + { + s32 ret_val; + s16 mii_autoneg_adv_reg; + s16 mii_1000t_ctrl_reg; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ + mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; + + /* Read the MII 1000Base-T Control Register (Address 9). */ + mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK; + + /* + * First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ + mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK; + mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK; + + /* + * Need to parse media_type and set up + * the appropriate PHY registers. + */ + switch (hw->media_type) { + case MEDIA_TYPE_AUTO_SENSOR: + mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS | + MII_AR_10T_FD_CAPS | + MII_AR_100TX_HD_CAPS | + MII_AR_100TX_FD_CAPS); + mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS; + break; + + case MEDIA_TYPE_1000M_FULL: + mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS; + break; + + case MEDIA_TYPE_100M_FULL: + mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS; + break; + + case MEDIA_TYPE_100M_HALF: + mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS; + break; + + case MEDIA_TYPE_10M_FULL: + mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS; + break; + + default: + mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS; + break; + } + + /* flow control fixed to enable all */ + mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE); + + hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; + hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg; + + ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); + if (ret_val) + return ret_val; + + ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg); + if (ret_val) + return ret_val; + + return 0; + } + + /* + * Configures link settings. + * hw - Struct containing variables accessed by shared code + * Assumes the hardware has previously been reset and the + * transmitter and receiver are not enabled. + */ + static s32 atl1_setup_link(struct atl1_hw *hw) + { + struct pci_dev *pdev = hw->back->pdev; + struct atl1_adapter *adapter = hw->back; + s32 ret_val; + + /* + * Options: + * PHY will advertise value(s) parsed from + * autoneg_advertised and fc + * no matter what autoneg is , We will not wait link result. + */ + ret_val = atl1_phy_setup_autoneg_adv(hw); + if (ret_val) { + if (netif_msg_link(adapter)) + dev_dbg(&pdev->dev, + "error setting up autonegotiation\n"); + return ret_val; + } + /* SW.Reset , En-Auto-Neg if needed */ + ret_val = atl1_phy_reset(hw); + if (ret_val) { + if (netif_msg_link(adapter)) + dev_dbg(&pdev->dev, "error resetting phy\n"); + return ret_val; + } + hw->phy_configured = true; + return ret_val; + } + + static void atl1_init_flash_opcode(struct atl1_hw *hw) + { + if (hw->flash_vendor >= ARRAY_SIZE(flash_table)) + /* Atmel */ + hw->flash_vendor = 0; + + /* Init OP table */ + iowrite8(flash_table[hw->flash_vendor].cmd_program, + hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM); + iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase, + hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE); + iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase, + hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE); + iowrite8(flash_table[hw->flash_vendor].cmd_rdid, + hw->hw_addr + REG_SPI_FLASH_OP_RDID); + iowrite8(flash_table[hw->flash_vendor].cmd_wren, + hw->hw_addr + REG_SPI_FLASH_OP_WREN); + iowrite8(flash_table[hw->flash_vendor].cmd_rdsr, + hw->hw_addr + REG_SPI_FLASH_OP_RDSR); + iowrite8(flash_table[hw->flash_vendor].cmd_wrsr, + hw->hw_addr + REG_SPI_FLASH_OP_WRSR); + iowrite8(flash_table[hw->flash_vendor].cmd_read, + hw->hw_addr + REG_SPI_FLASH_OP_READ); + } + + /* + * Performs basic configuration of the adapter. + * hw - Struct containing variables accessed by shared code + * Assumes that the controller has previously been reset and is in a + * post-reset uninitialized state. Initializes multicast table, + * and Calls routines to setup link + * Leaves the transmit and receive units disabled and uninitialized. + */ + static s32 atl1_init_hw(struct atl1_hw *hw) + { + u32 ret_val = 0; + + /* Zero out the Multicast HASH table */ + iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); + /* clear the old settings from the multicast hash table */ + iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); + + atl1_init_flash_opcode(hw); + + if (!hw->phy_configured) { - /* enable GPHY LinkChange Interrrupt */ ++ /* enable GPHY LinkChange Interrupt */ + ret_val = atl1_write_phy_reg(hw, 18, 0xC00); + if (ret_val) + return ret_val; + /* make PHY out of power-saving state */ + ret_val = atl1_phy_leave_power_saving(hw); + if (ret_val) + return ret_val; + /* Call a subroutine to configure the link */ + ret_val = atl1_setup_link(hw); + } + return ret_val; + } + + /* + * Detects the current speed and duplex settings of the hardware. + * hw - Struct containing variables accessed by shared code + * speed - Speed of the connection + * duplex - Duplex setting of the connection + */ + static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex) + { + struct pci_dev *pdev = hw->back->pdev; + struct atl1_adapter *adapter = hw->back; + s32 ret_val; + u16 phy_data; + + /* ; --- Read PHY Specific Status Register (17) */ + ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data); + if (ret_val) + return ret_val; + + if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED)) + return ATLX_ERR_PHY_RES; + + switch (phy_data & MII_ATLX_PSSR_SPEED) { + case MII_ATLX_PSSR_1000MBS: + *speed = SPEED_1000; + break; + case MII_ATLX_PSSR_100MBS: + *speed = SPEED_100; + break; + case MII_ATLX_PSSR_10MBS: + *speed = SPEED_10; + break; + default: + if (netif_msg_hw(adapter)) + dev_dbg(&pdev->dev, "error getting speed\n"); + return ATLX_ERR_PHY_SPEED; + break; + } + if (phy_data & MII_ATLX_PSSR_DPLX) + *duplex = FULL_DUPLEX; + else + *duplex = HALF_DUPLEX; + + return 0; + } + + static void atl1_set_mac_addr(struct atl1_hw *hw) + { + u32 value; + /* + * 00-0B-6A-F6-00-DC + * 0: 6AF600DC 1: 000B + * low dword + */ + value = (((u32) hw->mac_addr[2]) << 24) | + (((u32) hw->mac_addr[3]) << 16) | + (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5])); + iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR); + /* high dword */ + value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1])); + iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2)); + } + + /* + * atl1_sw_init - Initialize general software structures (struct atl1_adapter) + * @adapter: board private structure to initialize + * + * atl1_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + */ + static int __devinit atl1_sw_init(struct atl1_adapter *adapter) + { + struct atl1_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + + hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + + adapter->wol = 0; + device_set_wakeup_enable(&adapter->pdev->dev, false); + adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7; + adapter->ict = 50000; /* 100ms */ + adapter->link_speed = SPEED_0; /* hardware init */ + adapter->link_duplex = FULL_DUPLEX; + + hw->phy_configured = false; + hw->preamble_len = 7; + hw->ipgt = 0x60; + hw->min_ifg = 0x50; + hw->ipgr1 = 0x40; + hw->ipgr2 = 0x60; + hw->max_retry = 0xf; + hw->lcol = 0x37; + hw->jam_ipg = 7; + hw->rfd_burst = 8; + hw->rrd_burst = 8; + hw->rfd_fetch_gap = 1; + hw->rx_jumbo_th = adapter->rx_buffer_len / 8; + hw->rx_jumbo_lkah = 1; + hw->rrd_ret_timer = 16; + hw->tpd_burst = 4; + hw->tpd_fetch_th = 16; + hw->txf_burst = 0x100; + hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3; + hw->tpd_fetch_gap = 1; + hw->rcb_value = atl1_rcb_64; + hw->dma_ord = atl1_dma_ord_enh; + hw->dmar_block = atl1_dma_req_256; + hw->dmaw_block = atl1_dma_req_256; + hw->cmb_rrd = 4; + hw->cmb_tpd = 4; + hw->cmb_rx_timer = 1; /* about 2us */ + hw->cmb_tx_timer = 1; /* about 2us */ + hw->smb_timer = 100000; /* about 200ms */ + + spin_lock_init(&adapter->lock); + spin_lock_init(&adapter->mb_lock); + + return 0; + } + + static int mdio_read(struct net_device *netdev, int phy_id, int reg_num) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + u16 result; + + atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result); + + return result; + } + + static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, + int val) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + + atl1_write_phy_reg(&adapter->hw, reg_num, val); + } + + /* + * atl1_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ + static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + int retval; + + if (!netif_running(netdev)) + return -EINVAL; + + spin_lock_irqsave(&adapter->lock, flags); + retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); + spin_unlock_irqrestore(&adapter->lock, flags); + + return retval; + } + + /* + * atl1_setup_mem_resources - allocate Tx / RX descriptor resources + * @adapter: board private structure + * + * Return 0 on success, negative on failure + */ + static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_ring_header *ring_header = &adapter->ring_header; + struct pci_dev *pdev = adapter->pdev; + int size; + u8 offset = 0; + + size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count); + tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); + if (unlikely(!tpd_ring->buffer_info)) { + if (netif_msg_drv(adapter)) + dev_err(&pdev->dev, "kzalloc failed , size = D%d\n", + size); + goto err_nomem; + } + rfd_ring->buffer_info = + (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count); + + /* + * real ring DMA buffer + * each ring/block may need up to 8 bytes for alignment, hence the + * additional 40 bytes tacked onto the end. + */ + ring_header->size = size = + sizeof(struct tx_packet_desc) * tpd_ring->count + + sizeof(struct rx_free_desc) * rfd_ring->count + + sizeof(struct rx_return_desc) * rrd_ring->count + + sizeof(struct coals_msg_block) + + sizeof(struct stats_msg_block) + + 40; + + ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, + &ring_header->dma); + if (unlikely(!ring_header->desc)) { + if (netif_msg_drv(adapter)) + dev_err(&pdev->dev, "pci_alloc_consistent failed\n"); + goto err_nomem; + } + + memset(ring_header->desc, 0, ring_header->size); + + /* init TPD ring */ + tpd_ring->dma = ring_header->dma; + offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0; + tpd_ring->dma += offset; + tpd_ring->desc = (u8 *) ring_header->desc + offset; + tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count; + + /* init RFD ring */ + rfd_ring->dma = tpd_ring->dma + tpd_ring->size; + offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0; + rfd_ring->dma += offset; + rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset); + rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count; + + + /* init RRD ring */ + rrd_ring->dma = rfd_ring->dma + rfd_ring->size; + offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0; + rrd_ring->dma += offset; + rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset); + rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count; + + + /* init CMB */ + adapter->cmb.dma = rrd_ring->dma + rrd_ring->size; + offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0; + adapter->cmb.dma += offset; + adapter->cmb.cmb = (struct coals_msg_block *) + ((u8 *) rrd_ring->desc + (rrd_ring->size + offset)); + + /* init SMB */ + adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block); + offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0; + adapter->smb.dma += offset; + adapter->smb.smb = (struct stats_msg_block *) + ((u8 *) adapter->cmb.cmb + + (sizeof(struct coals_msg_block) + offset)); + + return 0; + + err_nomem: + kfree(tpd_ring->buffer_info); + return -ENOMEM; + } + + static void atl1_init_ring_ptrs(struct atl1_adapter *adapter) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); + + rfd_ring->next_to_clean = 0; + atomic_set(&rfd_ring->next_to_use, 0); + + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); + } + + /* + * atl1_clean_rx_ring - Free RFD Buffers + * @adapter: board private structure + */ + static void atl1_clean_rx_ring(struct atl1_adapter *adapter) + { + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; + + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rfd_ring->count; i++) { + buffer_info = &rfd_ring->buffer_info[i]; + if (buffer_info->dma) { + pci_unmap_page(pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + } + if (buffer_info->skb) { + dev_kfree_skb(buffer_info->skb); + buffer_info->skb = NULL; + } + } + + size = sizeof(struct atl1_buffer) * rfd_ring->count; + memset(rfd_ring->buffer_info, 0, size); + + /* Zero out the descriptor ring */ + memset(rfd_ring->desc, 0, rfd_ring->size); + + rfd_ring->next_to_clean = 0; + atomic_set(&rfd_ring->next_to_use, 0); + + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); + } + + /* + * atl1_clean_tx_ring - Free Tx Buffers + * @adapter: board private structure + */ + static void atl1_clean_tx_ring(struct atl1_adapter *adapter) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; + + /* Free all the Tx ring sk_buffs */ + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; + if (buffer_info->dma) { + pci_unmap_page(pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + } + + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; + if (buffer_info->skb) { + dev_kfree_skb_any(buffer_info->skb); + buffer_info->skb = NULL; + } + } + + size = sizeof(struct atl1_buffer) * tpd_ring->count; + memset(tpd_ring->buffer_info, 0, size); + + /* Zero out the descriptor ring */ + memset(tpd_ring->desc, 0, tpd_ring->size); + + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); + } + + /* + * atl1_free_ring_resources - Free Tx / RX descriptor Resources + * @adapter: board private structure + * + * Free all transmit software resources + */ + static void atl1_free_ring_resources(struct atl1_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_ring_header *ring_header = &adapter->ring_header; + + atl1_clean_tx_ring(adapter); + atl1_clean_rx_ring(adapter); + + kfree(tpd_ring->buffer_info); + pci_free_consistent(pdev, ring_header->size, ring_header->desc, + ring_header->dma); + + tpd_ring->buffer_info = NULL; + tpd_ring->desc = NULL; + tpd_ring->dma = 0; + + rfd_ring->buffer_info = NULL; + rfd_ring->desc = NULL; + rfd_ring->dma = 0; + + rrd_ring->desc = NULL; + rrd_ring->dma = 0; + + adapter->cmb.dma = 0; + adapter->cmb.cmb = NULL; + + adapter->smb.dma = 0; + adapter->smb.smb = NULL; + } + + static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) + { + u32 value; + struct atl1_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + /* Config MAC CTRL Register */ + value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; + /* duplex */ + if (FULL_DUPLEX == adapter->link_duplex) + value |= MAC_CTRL_DUPLX; + /* speed */ + value |= ((u32) ((SPEED_1000 == adapter->link_speed) ? + MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) << + MAC_CTRL_SPEED_SHIFT); + /* flow control */ + value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); + /* PAD & CRC */ + value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + /* preamble length */ + value |= (((u32) adapter->hw.preamble_len + & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + /* vlan */ + __atlx_vlan_mode(netdev->features, &value); + /* rx checksum + if (adapter->rx_csum) + value |= MAC_CTRL_RX_CHKSUM_EN; + */ + /* filter mode */ + value |= MAC_CTRL_BC_EN; + if (netdev->flags & IFF_PROMISC) + value |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) + value |= MAC_CTRL_MC_ALL_EN; + /* value |= MAC_CTRL_LOOPBACK; */ + iowrite32(value, hw->hw_addr + REG_MAC_CTRL); + } + + static u32 atl1_check_link(struct atl1_adapter *adapter) + { + struct atl1_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + u32 ret_val; + u16 speed, duplex, phy_data; + int reconfig = 0; + + /* MII_BMSR must read twice */ + atl1_read_phy_reg(hw, MII_BMSR, &phy_data); + atl1_read_phy_reg(hw, MII_BMSR, &phy_data); + if (!(phy_data & BMSR_LSTATUS)) { + /* link down */ + if (netif_carrier_ok(netdev)) { + /* old link state: Up */ + if (netif_msg_link(adapter)) + dev_info(&adapter->pdev->dev, "link is down\n"); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + } + return 0; + } + + /* Link Up */ + ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) + return ret_val; + + switch (hw->media_type) { + case MEDIA_TYPE_1000M_FULL: + if (speed != SPEED_1000 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_FULL: + if (speed != SPEED_100 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_HALF: + if (speed != SPEED_100 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_FULL: + if (speed != SPEED_10 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_HALF: + if (speed != SPEED_10 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + } + + /* link result is our setting */ + if (!reconfig) { + if (adapter->link_speed != speed || + adapter->link_duplex != duplex) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; + atl1_setup_mac_ctrl(adapter); + if (netif_msg_link(adapter)) + dev_info(&adapter->pdev->dev, + "%s link is up %d Mbps %s\n", + netdev->name, adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "full duplex" : "half duplex"); + } + if (!netif_carrier_ok(netdev)) { + /* Link down -> Up */ + netif_carrier_on(netdev); + } + return 0; + } + + /* change original link status */ + if (netif_carrier_ok(netdev)) { + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + + if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR && + hw->media_type != MEDIA_TYPE_1000M_FULL) { + switch (hw->media_type) { + case MEDIA_TYPE_100M_FULL: + phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 | + MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET; + break; + default: + /* MEDIA_TYPE_10M_HALF: */ + phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + break; + } + atl1_write_phy_reg(hw, MII_BMCR, phy_data); + return 0; + } + + /* auto-neg, insert timer to re-config phy */ + if (!adapter->phy_timer_pending) { + adapter->phy_timer_pending = true; + mod_timer(&adapter->phy_config_timer, + round_jiffies(jiffies + 3 * HZ)); + } + + return 0; + } + + static void set_flow_ctrl_old(struct atl1_adapter *adapter) + { + u32 hi, lo, value; + + /* RFD Flow Control */ + value = adapter->rfd_ring.count; + hi = value / 16; + if (hi < 2) + hi = 2; + lo = value * 7 / 8; + + value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH); + + /* RRD Flow Control */ + value = adapter->rrd_ring.count; + lo = value / 16; + hi = value * 7 / 8; + if (lo < 2) + lo = 2; + value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH); + } + + static void set_flow_ctrl_new(struct atl1_hw *hw) + { + u32 hi, lo, value; + + /* RXF Flow Control */ + value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN); + lo = value / 16; + if (lo < 192) + lo = 192; + hi = value * 7 / 8; + if (hi < lo) + hi = lo + 16; + value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH); + + /* RRD Flow Control */ + value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN); + lo = value / 8; + hi = value * 7 / 8; + if (lo < 2) + lo = 2; + if (hi < lo) + hi = lo + 3; + value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH); + } + + /* + * atl1_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + */ + static u32 atl1_configure(struct atl1_adapter *adapter) + { + struct atl1_hw *hw = &adapter->hw; + u32 value; + + /* clear interrupt status */ + iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR); + + /* set MAC Address */ + value = (((u32) hw->mac_addr[2]) << 24) | + (((u32) hw->mac_addr[3]) << 16) | + (((u32) hw->mac_addr[4]) << 8) | + (((u32) hw->mac_addr[5])); + iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR); + value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1])); + iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4)); + + /* tx / rx ring */ + + /* HI base address */ + iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32), + hw->hw_addr + REG_DESC_BASE_ADDR_HI); + /* LO base address */ + iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_RFD_ADDR_LO); + iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_RRD_ADDR_LO); + iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_TPD_ADDR_LO); + iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_CMB_ADDR_LO); + iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_SMB_ADDR_LO); + + /* element count */ + value = adapter->rrd_ring.count; + value <<= 16; + value += adapter->rfd_ring.count; + iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE); + iowrite32(adapter->tpd_ring.count, hw->hw_addr + + REG_DESC_TPD_RING_SIZE); + + /* Load Ptr */ + iowrite32(1, hw->hw_addr + REG_LOAD_PTR); + + /* config Mailbox */ + value = ((atomic_read(&adapter->tpd_ring.next_to_use) + & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) | + ((atomic_read(&adapter->rrd_ring.next_to_clean) + & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) | + ((atomic_read(&adapter->rfd_ring.next_to_use) + & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAILBOX); + + /* config IPG/IFG */ + value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK) + << MAC_IPG_IFG_IPGT_SHIFT) | + (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) + << MAC_IPG_IFG_MIFG_SHIFT) | + (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) + << MAC_IPG_IFG_IPGR1_SHIFT) | + (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) + << MAC_IPG_IFG_IPGR2_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG); + + /* config Half-Duplex Control */ + value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | + (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) + << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | + MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | + (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | + (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) + << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL); + + /* set Interrupt Moderator Timer */ + iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT); + iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL); + + /* set Interrupt Clear Timer */ + iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER); + + /* set max frame size hw will accept */ + iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU); + + /* jumbo size & rrd retirement timer */ + value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) + << RXQ_JMBOSZ_TH_SHIFT) | + (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK) + << RXQ_JMBO_LKAH_SHIFT) | + (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK) + << RXQ_RRD_TIMER_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM); + + /* Flow Control */ + switch (hw->dev_rev) { + case 0x8001: + case 0x9001: + case 0x9002: + case 0x9003: + set_flow_ctrl_old(adapter); + break; + default: + set_flow_ctrl_new(hw); + break; + } + + /* config TXQ */ + value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK) + << TXQ_CTRL_TPD_BURST_NUM_SHIFT) | + (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK) + << TXQ_CTRL_TXF_BURST_NUM_SHIFT) | + (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK) + << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | + TXQ_CTRL_EN; + iowrite32(value, hw->hw_addr + REG_TXQ_CTRL); + + /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */ + value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK) + << TX_JUMBO_TASK_TH_SHIFT) | + (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK) + << TX_TPD_MIN_IPG_SHIFT); + iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG); + + /* config RXQ */ + value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK) + << RXQ_CTRL_RFD_BURST_NUM_SHIFT) | + (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK) + << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) | + (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK) + << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN | + RXQ_CTRL_EN; + iowrite32(value, hw->hw_addr + REG_RXQ_CTRL); + + /* config DMA Engine */ + value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) + << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | + ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) + << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN | + DMA_CTRL_DMAW_EN; + value |= (u32) hw->dma_ord; + if (atl1_rcb_128 == hw->rcb_value) + value |= DMA_CTRL_RCB_VALUE; + iowrite32(value, hw->hw_addr + REG_DMA_CTRL); + + /* config CMB / SMB */ + value = (hw->cmb_tpd > adapter->tpd_ring.count) ? + hw->cmb_tpd : adapter->tpd_ring.count; + value <<= 16; + value |= hw->cmb_rrd; + iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH); + value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16); + iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER); + iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER); + + /* --- enable CMB / SMB */ + value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN; + iowrite32(value, hw->hw_addr + REG_CSMB_CTRL); + + value = ioread32(adapter->hw.hw_addr + REG_ISR); + if (unlikely((value & ISR_PHY_LINKDOWN) != 0)) + value = 1; /* config failed */ + else + value = 0; + + /* clear all interrupt status */ + iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR); + iowrite32(0, adapter->hw.hw_addr + REG_ISR); + return value; + } + + /* + * atl1_pcie_patch - Patch for PCIE module + */ + static void atl1_pcie_patch(struct atl1_adapter *adapter) + { + u32 value; + + /* much vendor magic here */ + value = 0x6500; + iowrite32(value, adapter->hw.hw_addr + 0x12FC); + /* pcie flow control mode change */ + value = ioread32(adapter->hw.hw_addr + 0x1008); + value |= 0x8000; + iowrite32(value, adapter->hw.hw_addr + 0x1008); + } + + /* + * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 + * on PCI Command register is disable. + * The function enable this bit. + * Brackett, 2006/03/15 + */ + static void atl1_via_workaround(struct atl1_adapter *adapter) + { + unsigned long value; + + value = ioread16(adapter->hw.hw_addr + PCI_COMMAND); + if (value & PCI_COMMAND_INTX_DISABLE) + value &= ~PCI_COMMAND_INTX_DISABLE; + iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND); + } + + static void atl1_inc_smb(struct atl1_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + struct stats_msg_block *smb = adapter->smb.smb; + + /* Fill out the OS statistics structure */ + adapter->soft_stats.rx_packets += smb->rx_ok; + adapter->soft_stats.tx_packets += smb->tx_ok; + adapter->soft_stats.rx_bytes += smb->rx_byte_cnt; + adapter->soft_stats.tx_bytes += smb->tx_byte_cnt; + adapter->soft_stats.multicast += smb->rx_mcast; + adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 + + smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry); + + /* Rx Errors */ + adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err + + smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov + + smb->rx_rrd_ov + smb->rx_align_err); + adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov; + adapter->soft_stats.rx_length_errors += smb->rx_len_err; + adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err; + adapter->soft_stats.rx_frame_errors += smb->rx_align_err; + adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + + smb->rx_rxf_ov); + + adapter->soft_stats.rx_pause += smb->rx_pause; + adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov; + adapter->soft_stats.rx_trunc += smb->rx_sz_ov; + + /* Tx Errors */ + adapter->soft_stats.tx_errors += (smb->tx_late_col + + smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc); + adapter->soft_stats.tx_fifo_errors += smb->tx_underrun; + adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col; + adapter->soft_stats.tx_window_errors += smb->tx_late_col; + + adapter->soft_stats.excecol += smb->tx_abort_col; + adapter->soft_stats.deffer += smb->tx_defer; + adapter->soft_stats.scc += smb->tx_1_col; + adapter->soft_stats.mcc += smb->tx_2_col; + adapter->soft_stats.latecol += smb->tx_late_col; + adapter->soft_stats.tx_underun += smb->tx_underrun; + adapter->soft_stats.tx_trunc += smb->tx_trunc; + adapter->soft_stats.tx_pause += smb->tx_pause; + + netdev->stats.rx_packets = adapter->soft_stats.rx_packets; + netdev->stats.tx_packets = adapter->soft_stats.tx_packets; + netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes; + netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes; + netdev->stats.multicast = adapter->soft_stats.multicast; + netdev->stats.collisions = adapter->soft_stats.collisions; + netdev->stats.rx_errors = adapter->soft_stats.rx_errors; + netdev->stats.rx_over_errors = + adapter->soft_stats.rx_missed_errors; + netdev->stats.rx_length_errors = + adapter->soft_stats.rx_length_errors; + netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors; + netdev->stats.rx_frame_errors = + adapter->soft_stats.rx_frame_errors; + netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; + netdev->stats.rx_missed_errors = + adapter->soft_stats.rx_missed_errors; + netdev->stats.tx_errors = adapter->soft_stats.tx_errors; + netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors; + netdev->stats.tx_aborted_errors = + adapter->soft_stats.tx_aborted_errors; + netdev->stats.tx_window_errors = + adapter->soft_stats.tx_window_errors; + netdev->stats.tx_carrier_errors = + adapter->soft_stats.tx_carrier_errors; + } + + static void atl1_update_mailbox(struct atl1_adapter *adapter) + { + unsigned long flags; + u32 tpd_next_to_use; + u32 rfd_next_to_use; + u32 rrd_next_to_clean; + u32 value; + + spin_lock_irqsave(&adapter->mb_lock, flags); + + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean); + + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + + spin_unlock_irqrestore(&adapter->mb_lock, flags); + } + + static void atl1_clean_alloc_flag(struct atl1_adapter *adapter, + struct rx_return_desc *rrd, u16 offset) + { + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + + while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) { + rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; + if (++rfd_ring->next_to_clean == rfd_ring->count) { + rfd_ring->next_to_clean = 0; + } + } + } + + static void atl1_update_rfd_index(struct atl1_adapter *adapter, + struct rx_return_desc *rrd) + { + u16 num_buf; + + num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) / + adapter->rx_buffer_len; + if (rrd->num_buf == num_buf) + /* clean alloc flag for bad rrd */ + atl1_clean_alloc_flag(adapter, rrd, num_buf); + } + + static void atl1_rx_checksum(struct atl1_adapter *adapter, + struct rx_return_desc *rrd, struct sk_buff *skb) + { + struct pci_dev *pdev = adapter->pdev; + + /* + * The L1 hardware contains a bug that erroneously sets the + * PACKET_FLAG_ERR and ERR_FLAG_L4_CHKSUM bits whenever a + * fragmented IP packet is received, even though the packet + * is perfectly valid and its checksum is correct. There's + * no way to distinguish between one of these good packets + * and a packet that actually contains a TCP/UDP checksum + * error, so all we can do is allow it to be handed up to + * the higher layers and let it be sorted out there. + */ + + skb_checksum_none_assert(skb); + + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC | + ERR_FLAG_CODE | ERR_FLAG_OV)) { + adapter->hw_csum_err++; + if (netif_msg_rx_err(adapter)) + dev_printk(KERN_DEBUG, &pdev->dev, + "rx checksum error\n"); + return; + } + } + + /* not IPv4 */ + if (!(rrd->pkt_flg & PACKET_FLAG_IPV4)) + /* checksum is invalid, but it's not an IPv4 pkt, so ok */ + return; + + /* IPv4 packet */ + if (likely(!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_good++; + return; + } + } + + /* + * atl1_alloc_rx_buffers - Replace used receive buffers + * @adapter: address of board private structure + */ + static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) + { + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct pci_dev *pdev = adapter->pdev; + struct page *page; + unsigned long offset; + struct atl1_buffer *buffer_info, *next_info; + struct sk_buff *skb; + u16 num_alloc = 0; + u16 rfd_next_to_use, next_next; + struct rx_free_desc *rfd_desc; + + next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use); + if (++next_next == rfd_ring->count) + next_next = 0; + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; + + while (!buffer_info->alloced && !next_info->alloced) { + if (buffer_info->skb) { + buffer_info->alloced = 1; + goto next; + } + + rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use); + + skb = netdev_alloc_skb_ip_align(adapter->netdev, + adapter->rx_buffer_len); + if (unlikely(!skb)) { + /* Better luck next round */ + adapter->netdev->stats.rx_dropped++; + break; + } + + buffer_info->alloced = 1; + buffer_info->skb = skb; + buffer_info->length = (u16) adapter->rx_buffer_len; + page = virt_to_page(skb->data); + offset = (unsigned long)skb->data & ~PAGE_MASK; + buffer_info->dma = pci_map_page(pdev, page, offset, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); + rfd_desc->coalese = 0; + + next: + rfd_next_to_use = next_next; + if (unlikely(++next_next == rfd_ring->count)) + next_next = 0; + + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; + num_alloc++; + } + + if (num_alloc) { + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use); + } + return num_alloc; + } + + static void atl1_intr_rx(struct atl1_adapter *adapter) + { + int i, count; + u16 length; + u16 rrd_next_to_clean; + u32 value; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_buffer *buffer_info; + struct rx_return_desc *rrd; + struct sk_buff *skb; + + count = 0; + + rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); + + while (1) { + rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); + i = 1; + if (likely(rrd->xsz.valid)) { /* packet valid */ + chk_rrd: + /* check rrd status */ + if (likely(rrd->num_buf == 1)) + goto rrd_ok; + else if (netif_msg_rx_err(adapter)) { + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "unexpected RRD buffer count\n"); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "rx_buf_len = %d\n", + adapter->rx_buffer_len); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "RRD num_buf = %d\n", + rrd->num_buf); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "RRD pkt_len = %d\n", + rrd->xsz.xsum_sz.pkt_size); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "RRD pkt_flg = 0x%08X\n", + rrd->pkt_flg); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "RRD err_flg = 0x%08X\n", + rrd->err_flg); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "RRD vlan_tag = 0x%08X\n", + rrd->vlan_tag); + } + + /* rrd seems to be bad */ + if (unlikely(i-- > 0)) { + /* rrd may not be DMAed completely */ + udelay(1); + goto chk_rrd; + } + /* bad rrd */ + if (netif_msg_rx_err(adapter)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "bad RRD\n"); + /* see if update RFD index */ + if (rrd->num_buf > 1) + atl1_update_rfd_index(adapter, rrd); + + /* update rrd */ + rrd->xsz.valid = 0; + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; + continue; + } else { /* current rrd still not be updated */ + + break; + } + rrd_ok: + /* clean alloc flag for bad rrd */ + atl1_clean_alloc_flag(adapter, rrd, 0); + + buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; + if (++rfd_ring->next_to_clean == rfd_ring->count) + rfd_ring->next_to_clean = 0; + + /* update rrd next to clean */ + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; + + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM + | ERR_FLAG_LEN))) { + /* packet error, don't need upstream */ + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + continue; + } + } + + /* Good Receive */ + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + skb = buffer_info->skb; + length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); + + skb_put(skb, length - ETH_FCS_LEN); + + /* Receive Checksum Offload */ + atl1_rx_checksum(adapter, rrd, skb); + skb->protocol = eth_type_trans(skb, adapter->netdev); + + if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) { + u16 vlan_tag = (rrd->vlan_tag >> 4) | + ((rrd->vlan_tag & 7) << 13) | + ((rrd->vlan_tag & 8) << 9); + + __vlan_hwaccel_put_tag(skb, vlan_tag); + } + netif_rx(skb); + + /* let protocol layer free skb */ + buffer_info->skb = NULL; + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + } + + atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); + + atl1_alloc_rx_buffers(adapter); + + /* update mailbox ? */ + if (count) { + u32 tpd_next_to_use; + u32 rfd_next_to_use; + + spin_lock(&adapter->mb_lock); + + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = + atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = + atomic_read(&adapter->rrd_ring.next_to_clean); + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + spin_unlock(&adapter->mb_lock); + } + } + + static void atl1_intr_tx(struct atl1_adapter *adapter) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + u16 sw_tpd_next_to_clean; + u16 cmb_tpd_next_to_clean; + + sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); + cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); + + while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { + buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; + if (buffer_info->dma) { + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + + if (buffer_info->skb) { + dev_kfree_skb_irq(buffer_info->skb); + buffer_info->skb = NULL; + } + + if (++sw_tpd_next_to_clean == tpd_ring->count) + sw_tpd_next_to_clean = 0; + } + atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean); + + if (netif_queue_stopped(adapter->netdev) && + netif_carrier_ok(adapter->netdev)) + netif_wake_queue(adapter->netdev); + } + + static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring) + { + u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); + u16 next_to_use = atomic_read(&tpd_ring->next_to_use); + return (next_to_clean > next_to_use) ? + next_to_clean - next_to_use - 1 : + tpd_ring->count + next_to_clean - next_to_use - 1; + } + + static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, + struct tx_packet_desc *ptpd) + { + u8 hdr_len, ip_off; + u32 real_len; + int err; + + if (skb_shinfo(skb)->gso_size) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (unlikely(err)) + return -1; + } + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + + real_len = (((unsigned char *)iph - skb->data) + + ntohs(iph->tot_len)); + if (real_len < skb->len) + pskb_trim(skb, real_len); + hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); + if (skb->len == hdr_len) { + iph->check = 0; + tcp_hdr(skb)->check = + ~csum_tcpudp_magic(iph->saddr, + iph->daddr, tcp_hdrlen(skb), + IPPROTO_TCP, 0); + ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) << + TPD_IPHL_SHIFT; + ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) & + TPD_TCPHDRLEN_MASK) << + TPD_TCPHDRLEN_SHIFT; + ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT; + ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT; + return 1; + } + + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, IPPROTO_TCP, 0); + ip_off = (unsigned char *)iph - + (unsigned char *) skb_network_header(skb); + if (ip_off == 8) /* 802.3-SNAP frame */ + ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; + else if (ip_off != 0) + return -2; + + ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) << + TPD_IPHL_SHIFT; + ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) & + TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT; + ptpd->word3 |= (skb_shinfo(skb)->gso_size & + TPD_MSS_MASK) << TPD_MSS_SHIFT; + ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT; + return 3; + } + } + return false; + } + + static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, + struct tx_packet_desc *ptpd) + { + u8 css, cso; + + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { + css = skb_checksum_start_offset(skb); + cso = css + (u8) skb->csum_offset; + if (unlikely(css & 0x1)) { + /* L1 hardware requires an even number here */ + if (netif_msg_tx_err(adapter)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "payload offset not an even number\n"); + return -1; + } + ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) << + TPD_PLOADOFFSET_SHIFT; + ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) << + TPD_CCSUMOFFSET_SHIFT; + ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT; + return true; + } + return 0; + } + + static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + struct tx_packet_desc *ptpd) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + u16 buf_len = skb->len; + struct page *page; + unsigned long offset; + unsigned int nr_frags; + unsigned int f; + int retval; + u16 next_to_use; + u16 data_len; + u8 hdr_len; + + buf_len -= skb->data_len; + nr_frags = skb_shinfo(skb)->nr_frags; + next_to_use = atomic_read(&tpd_ring->next_to_use); + buffer_info = &tpd_ring->buffer_info[next_to_use]; + BUG_ON(buffer_info->skb); + /* put skb in last TPD */ + buffer_info->skb = NULL; + + retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; + if (retval) { + /* TSO */ + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + buffer_info->length = hdr_len; + page = virt_to_page(skb->data); + offset = (unsigned long)skb->data & ~PAGE_MASK; + buffer_info->dma = pci_map_page(adapter->pdev, page, + offset, hdr_len, + PCI_DMA_TODEVICE); + + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + + if (buf_len > hdr_len) { + int i, nseg; + + data_len = buf_len - hdr_len; + nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; + for (i = 0; i < nseg; i++) { + buffer_info = + &tpd_ring->buffer_info[next_to_use]; + buffer_info->skb = NULL; + buffer_info->length = + (ATL1_MAX_TX_BUF_LEN >= + data_len) ? ATL1_MAX_TX_BUF_LEN : data_len; + data_len -= buffer_info->length; + page = virt_to_page(skb->data + + (hdr_len + i * ATL1_MAX_TX_BUF_LEN)); + offset = (unsigned long)(skb->data + + (hdr_len + i * ATL1_MAX_TX_BUF_LEN)) & + ~PAGE_MASK; + buffer_info->dma = pci_map_page(adapter->pdev, + page, offset, buffer_info->length, + PCI_DMA_TODEVICE); + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } + } + } else { + /* not TSO */ + buffer_info->length = buf_len; + page = virt_to_page(skb->data); + offset = (unsigned long)skb->data & ~PAGE_MASK; + buffer_info->dma = pci_map_page(adapter->pdev, page, + offset, buf_len, PCI_DMA_TODEVICE); + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } + + for (f = 0; f < nr_frags; f++) { + const struct skb_frag_struct *frag; + u16 i, nseg; + + frag = &skb_shinfo(skb)->frags[f]; + buf_len = skb_frag_size(frag); + + nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; + for (i = 0; i < nseg; i++) { + buffer_info = &tpd_ring->buffer_info[next_to_use]; + BUG_ON(buffer_info->skb); + + buffer_info->skb = NULL; + buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ? + ATL1_MAX_TX_BUF_LEN : buf_len; + buf_len -= buffer_info->length; + buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, + frag, i * ATL1_MAX_TX_BUF_LEN, + buffer_info->length, DMA_TO_DEVICE); + + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } + } + + /* last tpd's buffer-info */ + buffer_info->skb = skb; + } + + static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, + struct tx_packet_desc *ptpd) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + struct tx_packet_desc *tpd; + u16 j; + u32 val; + u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use); + + for (j = 0; j < count; j++) { + buffer_info = &tpd_ring->buffer_info[next_to_use]; + tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use); + if (tpd != ptpd) + memcpy(tpd, ptpd, sizeof(struct tx_packet_desc)); + tpd->buffer_addr = cpu_to_le64(buffer_info->dma); + tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT); + tpd->word2 |= (cpu_to_le16(buffer_info->length) & + TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT; + + /* + * if this is the first packet in a TSO chain, set + * TPD_HDRFLAG, otherwise, clear it. + */ + val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & + TPD_SEGMENT_EN_MASK; + if (val) { + if (!j) + tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT; + else + tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT); + } + + if (j == (count - 1)) + tpd->word3 |= 1 << TPD_EOP_SHIFT; + + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + + atomic_set(&tpd_ring->next_to_use, next_to_use); + } + + static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + struct net_device *netdev) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + int len; + int tso; + int count = 1; + int ret_val; + struct tx_packet_desc *ptpd; + u16 vlan_tag; + unsigned int nr_frags = 0; + unsigned int mss = 0; + unsigned int f; + unsigned int proto_hdr_len; + + len = skb_headlen(skb); + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + nr_frags = skb_shinfo(skb)->nr_frags; + for (f = 0; f < nr_frags; f++) { + unsigned int f_size = skb_frag_size(&skb_shinfo(skb)->frags[f]); + count += (f_size + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; + } + + mss = skb_shinfo(skb)->gso_size; + if (mss) { + if (skb->protocol == htons(ETH_P_IP)) { + proto_hdr_len = (skb_transport_offset(skb) + + tcp_hdrlen(skb)); + if (unlikely(proto_hdr_len > len)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + /* need additional TPD ? */ + if (proto_hdr_len != len) + count += (len - proto_hdr_len + + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; + } + } + + if (atl1_tpd_avail(&adapter->tpd_ring) < count) { + /* not enough descriptors */ + netif_stop_queue(netdev); + if (netif_msg_tx_queued(adapter)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "tx busy\n"); + return NETDEV_TX_BUSY; + } + + ptpd = ATL1_TPD_DESC(tpd_ring, + (u16) atomic_read(&tpd_ring->next_to_use)); + memset(ptpd, 0, sizeof(struct tx_packet_desc)); + + if (vlan_tx_tag_present(skb)) { + vlan_tag = vlan_tx_tag_get(skb); + vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | + ((vlan_tag >> 9) & 0x8); + ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; + ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) << + TPD_VLANTAG_SHIFT; + } + + tso = atl1_tso(adapter, skb, ptpd); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (!tso) { + ret_val = atl1_tx_csum(adapter, skb, ptpd); + if (ret_val < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + } + + atl1_tx_map(adapter, skb, ptpd); + atl1_tx_queue(adapter, count, ptpd); + atl1_update_mailbox(adapter); + mmiowb(); + return NETDEV_TX_OK; + } + + /* + * atl1_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure + */ + static irqreturn_t atl1_intr(int irq, void *data) + { + struct atl1_adapter *adapter = netdev_priv(data); + u32 status; + int max_ints = 10; + + status = adapter->cmb.cmb->int_stats; + if (!status) + return IRQ_NONE; + + do { + /* clear CMB interrupt status at once */ + adapter->cmb.cmb->int_stats = 0; + + if (status & ISR_GPHY) /* clear phy status */ + atlx_clear_phy_int(adapter); + + /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ + iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR); + + /* check if SMB intr */ + if (status & ISR_SMB) + atl1_inc_smb(adapter); + + /* check if PCIE PHY Link down */ + if (status & ISR_PHY_LINKDOWN) { + if (netif_msg_intr(adapter)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "pcie phy link down %x\n", status); + if (netif_running(adapter->netdev)) { /* reset MAC */ + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; + } + } + + /* check if DMA read/write error ? */ + if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { + if (netif_msg_intr(adapter)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "pcie DMA r/w error (status = 0x%x)\n", + status); + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; + } + + /* link event */ + if (status & ISR_GPHY) { + adapter->soft_stats.tx_carrier_errors++; + atl1_check_for_link(adapter); + } + + /* transmit event */ + if (status & ISR_CMB_TX) + atl1_intr_tx(adapter); + + /* rx exception */ + if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV | ISR_CMB_RX))) { + if (status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV)) + if (netif_msg_intr(adapter)) + dev_printk(KERN_DEBUG, + &adapter->pdev->dev, + "rx exception, ISR = 0x%x\n", + status); + atl1_intr_rx(adapter); + } + + if (--max_ints < 0) + break; + + } while ((status = adapter->cmb.cmb->int_stats)); + + /* re-enable Interrupt */ + iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); + return IRQ_HANDLED; + } + + + /* + * atl1_phy_config - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ + static void atl1_phy_config(unsigned long data) + { + struct atl1_adapter *adapter = (struct atl1_adapter *)data; + struct atl1_hw *hw = &adapter->hw; + unsigned long flags; + + spin_lock_irqsave(&adapter->lock, flags); + adapter->phy_timer_pending = false; + atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); + atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg); + atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN); + spin_unlock_irqrestore(&adapter->lock, flags); + } + + /* + * Orphaned vendor comment left intact here: + * + * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT + * will assert. We do soft reset <0x1400=1> according + * with the SPEC. BUT, it seemes that PCIE or DMA + * state-machine will not be reset. DMAR_TO_INT will + * assert again and again. + * + */ + + static int atl1_reset(struct atl1_adapter *adapter) + { + int ret; + ret = atl1_reset_hw(&adapter->hw); + if (ret) + return ret; + return atl1_init_hw(&adapter->hw); + } + + static s32 atl1_up(struct atl1_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + int err; + int irq_flags = 0; + + /* hardware has been reset, we need to reload some things */ + atlx_set_multi(netdev); + atl1_init_ring_ptrs(adapter); + atlx_restore_vlan(adapter); + err = atl1_alloc_rx_buffers(adapter); + if (unlikely(!err)) + /* no RX BUFFER allocated */ + return -ENOMEM; + + if (unlikely(atl1_configure(adapter))) { + err = -EIO; + goto err_up; + } + + err = pci_enable_msi(adapter->pdev); + if (err) { + if (netif_msg_ifup(adapter)) + dev_info(&adapter->pdev->dev, + "Unable to enable MSI: %d\n", err); + irq_flags |= IRQF_SHARED; + } + + err = request_irq(adapter->pdev->irq, atl1_intr, irq_flags, + netdev->name, netdev); + if (unlikely(err)) + goto err_up; + + atlx_irq_enable(adapter); + atl1_check_link(adapter); + netif_start_queue(netdev); + return 0; + + err_up: + pci_disable_msi(adapter->pdev); + /* free rx_buffers */ + atl1_clean_rx_ring(adapter); + return err; + } + + static void atl1_down(struct atl1_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + + netif_stop_queue(netdev); + del_timer_sync(&adapter->phy_config_timer); + adapter->phy_timer_pending = false; + + atlx_irq_disable(adapter); + free_irq(adapter->pdev->irq, netdev); + pci_disable_msi(adapter->pdev); + atl1_reset_hw(&adapter->hw); + adapter->cmb.cmb->int_stats = 0; + + adapter->link_speed = SPEED_0; + adapter->link_duplex = -1; + netif_carrier_off(netdev); + + atl1_clean_tx_ring(adapter); + atl1_clean_rx_ring(adapter); + } + + static void atl1_tx_timeout_task(struct work_struct *work) + { + struct atl1_adapter *adapter = + container_of(work, struct atl1_adapter, tx_timeout_task); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + atl1_down(adapter); + atl1_up(adapter); + netif_device_attach(netdev); + } + + /* + * atl1_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + */ + static int atl1_change_mtu(struct net_device *netdev, int new_mtu) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + int old_mtu = netdev->mtu; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + + if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || + (max_frame > MAX_JUMBO_FRAME_SIZE)) { + if (netif_msg_link(adapter)) + dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + return -EINVAL; + } + + adapter->hw.max_frame_size = max_frame; + adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; + adapter->rx_buffer_len = (max_frame + 7) & ~7; + adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; + + netdev->mtu = new_mtu; + if ((old_mtu != new_mtu) && netif_running(netdev)) { + atl1_down(adapter); + atl1_up(adapter); + } + + return 0; + } + + /* + * atl1_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + */ + static int atl1_open(struct net_device *netdev) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + int err; + + netif_carrier_off(netdev); + + /* allocate transmit descriptors */ + err = atl1_setup_ring_resources(adapter); + if (err) + return err; + + err = atl1_up(adapter); + if (err) + goto err_up; + + return 0; + + err_up: + atl1_reset(adapter); + return err; + } + + /* + * atl1_close - Disables a network interface + * @netdev: network interface device structure + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + */ + static int atl1_close(struct net_device *netdev) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + atl1_down(adapter); + atl1_free_ring_resources(adapter); + return 0; + } + + #ifdef CONFIG_PM + static int atl1_suspend(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + u32 ctrl = 0; + u32 wufc = adapter->wol; + u32 val; + u16 speed; + u16 duplex; + + netif_device_detach(netdev); + if (netif_running(netdev)) + atl1_down(adapter); + + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + val = ctrl & BMSR_LSTATUS; + if (val) + wufc &= ~ATLX_WUFC_LNKC; + if (!wufc) + goto disable_wol; + + if (val) { + val = atl1_get_speed_and_duplex(hw, &speed, &duplex); + if (val) { + if (netif_msg_ifdown(adapter)) + dev_printk(KERN_DEBUG, &pdev->dev, + "error getting speed/duplex\n"); + goto disable_wol; + } + + ctrl = 0; + + /* enable magic packet WOL */ + if (wufc & ATLX_WUFC_MAG) + ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); + iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); + ioread32(hw->hw_addr + REG_WOL_CTRL); + + /* configure the mac */ + ctrl = MAC_CTRL_RX_EN; + ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 : + MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT); + if (duplex == FULL_DUPLEX) + ctrl |= MAC_CTRL_DUPLX; + ctrl |= (((u32)adapter->hw.preamble_len & + MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + __atlx_vlan_mode(netdev->features, &ctrl); + if (wufc & ATLX_WUFC_MAG) + ctrl |= MAC_CTRL_BC_EN; + iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); + ioread32(hw->hw_addr + REG_MAC_CTRL); + + /* poke the PHY */ + ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); + ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + } else { + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); + ioread32(hw->hw_addr + REG_WOL_CTRL); + iowrite32(0, hw->hw_addr + REG_MAC_CTRL); + ioread32(hw->hw_addr + REG_MAC_CTRL); + hw->phy_configured = false; + } + + return 0; + + disable_wol: + iowrite32(0, hw->hw_addr + REG_WOL_CTRL); + ioread32(hw->hw_addr + REG_WOL_CTRL); + ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); + ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + hw->phy_configured = false; + + return 0; + } + + static int atl1_resume(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + + iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); + + atl1_reset_hw(&adapter->hw); + + if (netif_running(netdev)) { + adapter->cmb.cmb->int_stats = 0; + atl1_up(adapter); + } + netif_device_attach(netdev); + + return 0; + } + + static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume); + #define ATL1_PM_OPS (&atl1_pm_ops) + + #else + + static int atl1_suspend(struct device *dev) { return 0; } + + #define ATL1_PM_OPS NULL + #endif + + static void atl1_shutdown(struct pci_dev *pdev) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + + atl1_suspend(&pdev->dev); + pci_wake_from_d3(pdev, adapter->wol); + pci_set_power_state(pdev, PCI_D3hot); + } + + #ifdef CONFIG_NET_POLL_CONTROLLER + static void atl1_poll_controller(struct net_device *netdev) + { + disable_irq(netdev->irq); + atl1_intr(netdev->irq, netdev); + enable_irq(netdev->irq); + } + #endif + + static const struct net_device_ops atl1_netdev_ops = { + .ndo_open = atl1_open, + .ndo_stop = atl1_close, + .ndo_start_xmit = atl1_xmit_frame, + .ndo_set_rx_mode = atlx_set_multi, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = atl1_set_mac, + .ndo_change_mtu = atl1_change_mtu, + .ndo_fix_features = atlx_fix_features, + .ndo_set_features = atlx_set_features, + .ndo_do_ioctl = atlx_ioctl, + .ndo_tx_timeout = atlx_tx_timeout, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = atl1_poll_controller, + #endif + }; + + /* + * atl1_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in atl1_pci_tbl + * + * Returns 0 on success, negative on failure + * + * atl1_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + */ + static int __devinit atl1_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + struct net_device *netdev; + struct atl1_adapter *adapter; + static int cards_found = 0; + int err; + + err = pci_enable_device(pdev); + if (err) + return err; + + /* + * The atl1 chip can DMA to 64-bit addresses, but it uses a single + * shared register for the high 32 bits, so only a single, aligned, + * 4 GB physical address range can be used at a time. + * + * Supporting 64-bit DMA on this hardware is more trouble than it's + * worth. It is far easier to limit to 32-bit DMA than update + * various kernel subsystems to support the mechanics required by a + * fixed-high-32-bit system. + */ + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, "no usable DMA configuration\n"); + goto err_dma; + } + /* + * Mark all PCI regions associated with PCI device + * pdev as being reserved by owner atl1_driver_name + */ + err = pci_request_regions(pdev, ATLX_DRIVER_NAME); + if (err) + goto err_request_regions; + + /* + * Enables bus-mastering on the device and calls + * pcibios_set_master to do the needed arch specific settings + */ + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct atl1_adapter)); + if (!netdev) { + err = -ENOMEM; + goto err_alloc_etherdev; + } + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; + adapter->hw.back = adapter; + adapter->msg_enable = netif_msg_init(debug, atl1_default_msg); + + adapter->hw.hw_addr = pci_iomap(pdev, 0, 0); + if (!adapter->hw.hw_addr) { + err = -EIO; + goto err_pci_iomap; + } + /* get device revision number */ + adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + + (REG_MASTER_CTRL + 2)); + if (netif_msg_probe(adapter)) + dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION); + + /* set default ring resource counts */ + adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD; + adapter->tpd_ring.count = ATL1_DEFAULT_TPD; + + adapter->mii.dev = netdev; + adapter->mii.mdio_read = mdio_read; + adapter->mii.mdio_write = mdio_write; + adapter->mii.phy_id_mask = 0x1f; + adapter->mii.reg_num_mask = 0x1f; + + netdev->netdev_ops = &atl1_netdev_ops; + netdev->watchdog_timeo = 5 * HZ; + + netdev->ethtool_ops = &atl1_ethtool_ops; + adapter->bd_number = cards_found; + + /* setup the private structure */ + err = atl1_sw_init(adapter); + if (err) + goto err_common; + + netdev->features = NETIF_F_HW_CSUM; + netdev->features |= NETIF_F_SG; + netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); + + netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO | + NETIF_F_HW_VLAN_RX; + + /* is this valid? see atl1_setup_mac_ctrl() */ + netdev->features |= NETIF_F_RXCSUM; + + /* + * patch for some L1 of old version, + * the final version of L1 may not need these + * patches + */ + /* atl1_pcie_patch(adapter); */ + + /* really reset GPHY core */ + iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE); + + /* + * reset the controller to + * put the device in a known good starting state + */ + if (atl1_reset_hw(&adapter->hw)) { + err = -EIO; + goto err_common; + } + + /* copy the MAC address out of the EEPROM */ + atl1_read_mac_addr(&adapter->hw); + memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->dev_addr)) { + err = -EIO; + goto err_common; + } + + atl1_check_options(adapter); + + /* pre-init the MAC, and setup link */ + err = atl1_init_hw(&adapter->hw); + if (err) { + err = -EIO; + goto err_common; + } + + atl1_pcie_patch(adapter); + /* assume we have no link for now */ + netif_carrier_off(netdev); + + setup_timer(&adapter->phy_config_timer, atl1_phy_config, + (unsigned long)adapter); + adapter->phy_timer_pending = false; + + INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task); + + INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task); + + INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task); + + err = register_netdev(netdev); + if (err) + goto err_common; + + cards_found++; + atl1_via_workaround(adapter); + return 0; + + err_common: + pci_iounmap(pdev, adapter->hw.hw_addr); + err_pci_iomap: + free_netdev(netdev); + err_alloc_etherdev: + pci_release_regions(pdev); + err_dma: + err_request_regions: + pci_disable_device(pdev); + return err; + } + + /* + * atl1_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * atl1_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. The could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + */ + static void __devexit atl1_remove(struct pci_dev *pdev) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter; + /* Device not available. Return. */ + if (!netdev) + return; + + adapter = netdev_priv(netdev); + + /* + * Some atl1 boards lack persistent storage for their MAC, and get it + * from the BIOS during POST. If we've been messing with the MAC + * address, we need to save the permanent one. + */ + if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { + memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, + ETH_ALEN); + atl1_set_mac_addr(&adapter->hw); + } + + iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE); + unregister_netdev(netdev); + pci_iounmap(pdev, adapter->hw.hw_addr); + pci_release_regions(pdev); + free_netdev(netdev); + pci_disable_device(pdev); + } + + static struct pci_driver atl1_driver = { + .name = ATLX_DRIVER_NAME, + .id_table = atl1_pci_tbl, + .probe = atl1_probe, + .remove = __devexit_p(atl1_remove), + .shutdown = atl1_shutdown, + .driver.pm = ATL1_PM_OPS, + }; + + /* + * atl1_exit_module - Driver Exit Cleanup Routine + * + * atl1_exit_module is called just before the driver is removed + * from memory. + */ + static void __exit atl1_exit_module(void) + { + pci_unregister_driver(&atl1_driver); + } + + /* + * atl1_init_module - Driver Registration Routine + * + * atl1_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + */ + static int __init atl1_init_module(void) + { + return pci_register_driver(&atl1_driver); + } + + module_init(atl1_init_module); + module_exit(atl1_exit_module); + + struct atl1_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; + }; + + #define ATL1_STAT(m) \ + sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m) + + static struct atl1_stats atl1_gstrings_stats[] = { + {"rx_packets", ATL1_STAT(soft_stats.rx_packets)}, + {"tx_packets", ATL1_STAT(soft_stats.tx_packets)}, + {"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)}, + {"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)}, + {"rx_errors", ATL1_STAT(soft_stats.rx_errors)}, + {"tx_errors", ATL1_STAT(soft_stats.tx_errors)}, + {"multicast", ATL1_STAT(soft_stats.multicast)}, + {"collisions", ATL1_STAT(soft_stats.collisions)}, + {"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)}, + {"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)}, + {"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)}, + {"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)}, + {"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)}, + {"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)}, + {"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)}, + {"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)}, + {"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)}, + {"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)}, + {"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)}, + {"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)}, + {"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)}, + {"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)}, + {"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)}, + {"tx_underun", ATL1_STAT(soft_stats.tx_underun)}, + {"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)}, + {"tx_pause", ATL1_STAT(soft_stats.tx_pause)}, + {"rx_pause", ATL1_STAT(soft_stats.rx_pause)}, + {"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)}, + {"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)} + }; + + static void atl1_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + int i; + char *p; + + for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) { + p = (char *)adapter+atl1_gstrings_stats[i].stat_offset; + data[i] = (atl1_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + + } + + static int atl1_get_sset_count(struct net_device *netdev, int sset) + { + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(atl1_gstrings_stats); + default: + return -EOPNOTSUPP; + } + } + + static int atl1_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP); + ecmd->advertising = ADVERTISED_TP; + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) { + ecmd->advertising |= ADVERTISED_Autoneg; + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->advertising |= + (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full); + } else + ecmd->advertising |= (ADVERTISED_1000baseT_Full); + } + ecmd->port = PORT_TP; + ecmd->phy_address = 0; + ecmd->transceiver = XCVR_INTERNAL; + + if (netif_carrier_ok(adapter->netdev)) { + u16 link_speed, link_duplex; + atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex); + ethtool_cmd_speed_set(ecmd, link_speed); + if (link_duplex == FULL_DUPLEX) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } else { + ethtool_cmd_speed_set(ecmd, -1); + ecmd->duplex = -1; + } + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) + ecmd->autoneg = AUTONEG_ENABLE; + else + ecmd->autoneg = AUTONEG_DISABLE; + + return 0; + } + + static int atl1_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + u16 phy_data; + int ret_val = 0; + u16 old_media_type = hw->media_type; + + if (netif_running(adapter->netdev)) { + if (netif_msg_link(adapter)) + dev_dbg(&adapter->pdev->dev, + "ethtool shutting down adapter\n"); + atl1_down(adapter); + } + + if (ecmd->autoneg == AUTONEG_ENABLE) + hw->media_type = MEDIA_TYPE_AUTO_SENSOR; + else { + u32 speed = ethtool_cmd_speed(ecmd); + if (speed == SPEED_1000) { + if (ecmd->duplex != DUPLEX_FULL) { + if (netif_msg_link(adapter)) + dev_warn(&adapter->pdev->dev, + "1000M half is invalid\n"); + ret_val = -EINVAL; + goto exit_sset; + } + hw->media_type = MEDIA_TYPE_1000M_FULL; + } else if (speed == SPEED_100) { + if (ecmd->duplex == DUPLEX_FULL) + hw->media_type = MEDIA_TYPE_100M_FULL; + else + hw->media_type = MEDIA_TYPE_100M_HALF; + } else { + if (ecmd->duplex == DUPLEX_FULL) + hw->media_type = MEDIA_TYPE_10M_FULL; + else + hw->media_type = MEDIA_TYPE_10M_HALF; + } + } + switch (hw->media_type) { + case MEDIA_TYPE_AUTO_SENSOR: + ecmd->advertising = + ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_Autoneg | ADVERTISED_TP; + break; + case MEDIA_TYPE_1000M_FULL: + ecmd->advertising = + ADVERTISED_1000baseT_Full | + ADVERTISED_Autoneg | ADVERTISED_TP; + break; + default: + ecmd->advertising = 0; + break; + } + if (atl1_phy_setup_autoneg_adv(hw)) { + ret_val = -EINVAL; + if (netif_msg_link(adapter)) + dev_warn(&adapter->pdev->dev, + "invalid ethtool speed/duplex setting\n"); + goto exit_sset; + } + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN; + else { + switch (hw->media_type) { + case MEDIA_TYPE_100M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 | + MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET; + break; + default: + /* MEDIA_TYPE_10M_HALF: */ + phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + break; + } + } + atl1_write_phy_reg(hw, MII_BMCR, phy_data); + exit_sset: + if (ret_val) + hw->media_type = old_media_type; + + if (netif_running(adapter->netdev)) { + if (netif_msg_link(adapter)) + dev_dbg(&adapter->pdev->dev, + "ethtool starting adapter\n"); + atl1_up(adapter); + } else if (!ret_val) { + if (netif_msg_link(adapter)) + dev_dbg(&adapter->pdev->dev, + "ethtool resetting adapter\n"); + atl1_reset(adapter); + } + return ret_val; + } + + static void atl1_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + + strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, ATLX_DRIVER_VERSION, + sizeof(drvinfo->version)); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), + sizeof(drvinfo->bus_info)); + drvinfo->eedump_len = ATL1_EEDUMP_LEN; + } + + static void atl1_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + if (adapter->wol & ATLX_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + } + + static int atl1_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | + WAKE_ARP | WAKE_MAGICSECURE)) + return -EOPNOTSUPP; + adapter->wol = 0; + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= ATLX_WUFC_MAG; + + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + + return 0; + } + + static u32 atl1_get_msglevel(struct net_device *netdev) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + return adapter->msg_enable; + } + + static void atl1_set_msglevel(struct net_device *netdev, u32 value) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + adapter->msg_enable = value; + } + + static int atl1_get_regs_len(struct net_device *netdev) + { + return ATL1_REG_COUNT * sizeof(u32); + } + + static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs, + void *p) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + unsigned int i; + u32 *regbuf = p; + + for (i = 0; i < ATL1_REG_COUNT; i++) { + /* + * This switch statement avoids reserved regions + * of register space. + */ + switch (i) { + case 6 ... 9: + case 14: + case 29 ... 31: + case 34 ... 63: + case 75 ... 127: + case 136 ... 1023: + case 1027 ... 1087: + case 1091 ... 1151: + case 1194 ... 1195: + case 1200 ... 1201: + case 1206 ... 1213: + case 1216 ... 1279: + case 1290 ... 1311: + case 1323 ... 1343: + case 1358 ... 1359: + case 1368 ... 1375: + case 1378 ... 1383: + case 1388 ... 1391: + case 1393 ... 1395: + case 1402 ... 1403: + case 1410 ... 1471: + case 1522 ... 1535: + /* reserved region; don't read it */ + regbuf[i] = 0; + break; + default: + /* unreserved region */ + regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32))); + } + } + } + + static void atl1_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_tpd_ring *txdr = &adapter->tpd_ring; + struct atl1_rfd_ring *rxdr = &adapter->rfd_ring; + + ring->rx_max_pending = ATL1_MAX_RFD; + ring->tx_max_pending = ATL1_MAX_TPD; + ring->rx_pending = rxdr->count; + ring->tx_pending = txdr->count; + } + + static int atl1_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_tpd_ring *tpdr = &adapter->tpd_ring; + struct atl1_rrd_ring *rrdr = &adapter->rrd_ring; + struct atl1_rfd_ring *rfdr = &adapter->rfd_ring; + + struct atl1_tpd_ring tpd_old, tpd_new; + struct atl1_rfd_ring rfd_old, rfd_new; + struct atl1_rrd_ring rrd_old, rrd_new; + struct atl1_ring_header rhdr_old, rhdr_new; + struct atl1_smb smb; + struct atl1_cmb cmb; + int err; + + tpd_old = adapter->tpd_ring; + rfd_old = adapter->rfd_ring; + rrd_old = adapter->rrd_ring; + rhdr_old = adapter->ring_header; + + if (netif_running(adapter->netdev)) + atl1_down(adapter); + + rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD); + rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD : + rfdr->count; + rfdr->count = (rfdr->count + 3) & ~3; + rrdr->count = rfdr->count; + + tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD); + tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD : + tpdr->count; + tpdr->count = (tpdr->count + 3) & ~3; + + if (netif_running(adapter->netdev)) { + /* try to get new resources before deleting old */ + err = atl1_setup_ring_resources(adapter); + if (err) + goto err_setup_ring; + + /* + * save the new, restore the old in order to free it, + * then restore the new back again + */ + + rfd_new = adapter->rfd_ring; + rrd_new = adapter->rrd_ring; + tpd_new = adapter->tpd_ring; + rhdr_new = adapter->ring_header; + adapter->rfd_ring = rfd_old; + adapter->rrd_ring = rrd_old; + adapter->tpd_ring = tpd_old; + adapter->ring_header = rhdr_old; + /* + * Save SMB and CMB, since atl1_free_ring_resources + * will clear them. + */ + smb = adapter->smb; + cmb = adapter->cmb; + atl1_free_ring_resources(adapter); + adapter->rfd_ring = rfd_new; + adapter->rrd_ring = rrd_new; + adapter->tpd_ring = tpd_new; + adapter->ring_header = rhdr_new; + adapter->smb = smb; + adapter->cmb = cmb; + + err = atl1_up(adapter); + if (err) + return err; + } + return 0; + + err_setup_ring: + adapter->rfd_ring = rfd_old; + adapter->rrd_ring = rrd_old; + adapter->tpd_ring = tpd_old; + adapter->ring_header = rhdr_old; + atl1_up(adapter); + return err; + } + + static void atl1_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *epause) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) { + epause->autoneg = AUTONEG_ENABLE; + } else { + epause->autoneg = AUTONEG_DISABLE; + } + epause->rx_pause = 1; + epause->tx_pause = 1; + } + + static int atl1_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *epause) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) { + epause->autoneg = AUTONEG_ENABLE; + } else { + epause->autoneg = AUTONEG_DISABLE; + } + + epause->rx_pause = 1; + epause->tx_pause = 1; + + return 0; + } + + static void atl1_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) + { + u8 *p = data; + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) { + memcpy(p, atl1_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + break; + } + } + + static int atl1_nway_reset(struct net_device *netdev) + { + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + + if (netif_running(netdev)) { + u16 phy_data; + atl1_down(adapter); + + if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || + hw->media_type == MEDIA_TYPE_1000M_FULL) { + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN; + } else { + switch (hw->media_type) { + case MEDIA_TYPE_100M_FULL: + phy_data = MII_CR_FULL_DUPLEX | + MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = MII_CR_FULL_DUPLEX | + MII_CR_SPEED_10 | MII_CR_RESET; + break; + default: + /* MEDIA_TYPE_10M_HALF */ + phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + } + } + atl1_write_phy_reg(hw, MII_BMCR, phy_data); + atl1_up(adapter); + } + return 0; + } + + static const struct ethtool_ops atl1_ethtool_ops = { + .get_settings = atl1_get_settings, + .set_settings = atl1_set_settings, + .get_drvinfo = atl1_get_drvinfo, + .get_wol = atl1_get_wol, + .set_wol = atl1_set_wol, + .get_msglevel = atl1_get_msglevel, + .set_msglevel = atl1_set_msglevel, + .get_regs_len = atl1_get_regs_len, + .get_regs = atl1_get_regs, + .get_ringparam = atl1_get_ringparam, + .set_ringparam = atl1_set_ringparam, + .get_pauseparam = atl1_get_pauseparam, + .set_pauseparam = atl1_set_pauseparam, + .get_link = ethtool_op_get_link, + .get_strings = atl1_get_strings, + .nway_reset = atl1_nway_reset, + .get_ethtool_stats = atl1_get_ethtool_stats, + .get_sset_count = atl1_get_sset_count, + }; diff --cc drivers/net/ethernet/broadcom/bnx2.h index 000000000000,fc50d4267df8..99d31a7d6aaa mode 000000,100644..100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@@ -1,0 -1,7388 +1,7388 @@@ + /* bnx2.h: Broadcom NX2 network driver. + * + * Copyright (c) 2004-2011 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Written by: Michael Chan (mchan@broadcom.com) + */ + + + #ifndef BNX2_H + #define BNX2_H + + /* Hardware data structures and register definitions automatically + * generated from RTL code. Do not modify. + */ + + /* + * tx_bd definition + */ + struct tx_bd { + u32 tx_bd_haddr_hi; + u32 tx_bd_haddr_lo; + u32 tx_bd_mss_nbytes; + #define TX_BD_TCP6_OFF2_SHL (14) + u32 tx_bd_vlan_tag_flags; + #define TX_BD_FLAGS_CONN_FAULT (1<<0) + #define TX_BD_FLAGS_TCP6_OFF0_MSK (3<<1) + #define TX_BD_FLAGS_TCP6_OFF0_SHL (1) + #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1) + #define TX_BD_FLAGS_IP_CKSUM (1<<2) + #define TX_BD_FLAGS_VLAN_TAG (1<<3) + #define TX_BD_FLAGS_COAL_NOW (1<<4) + #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5) + #define TX_BD_FLAGS_END (1<<6) + #define TX_BD_FLAGS_START (1<<7) + #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8) + #define TX_BD_FLAGS_TCP6_OFF4_SHL (12) + #define TX_BD_FLAGS_SW_FLAGS (1<<13) + #define TX_BD_FLAGS_SW_SNAP (1<<14) + #define TX_BD_FLAGS_SW_LSO (1<<15) + + }; + + + /* + * rx_bd definition + */ + struct rx_bd { + u32 rx_bd_haddr_hi; + u32 rx_bd_haddr_lo; + u32 rx_bd_len; + u32 rx_bd_flags; + #define RX_BD_FLAGS_NOPUSH (1<<0) + #define RX_BD_FLAGS_DUMMY (1<<1) + #define RX_BD_FLAGS_END (1<<2) + #define RX_BD_FLAGS_START (1<<3) + + }; + + #define BNX2_RX_ALIGN 16 + + /* + * status_block definition + */ + struct status_block { + u32 status_attn_bits; + #define STATUS_ATTN_BITS_LINK_STATE (1L<<0) + #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1) + #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2) + #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3) + #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4) + #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5) + #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6) + #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7) + #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8) + #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9) + #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10) + #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11) + #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12) + #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13) + #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14) + #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15) + #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16) + #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17) + #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18) + #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19) + #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20) + #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21) + #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22) + #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23) + #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24) + #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25) + #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26) + #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27) + #define STATUS_ATTN_BITS_EPB_ERROR (1L<<30) + #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31) + + u32 status_attn_bits_ack; + #if defined(__BIG_ENDIAN) + u16 status_tx_quick_consumer_index0; + u16 status_tx_quick_consumer_index1; + u16 status_tx_quick_consumer_index2; + u16 status_tx_quick_consumer_index3; + u16 status_rx_quick_consumer_index0; + u16 status_rx_quick_consumer_index1; + u16 status_rx_quick_consumer_index2; + u16 status_rx_quick_consumer_index3; + u16 status_rx_quick_consumer_index4; + u16 status_rx_quick_consumer_index5; + u16 status_rx_quick_consumer_index6; + u16 status_rx_quick_consumer_index7; + u16 status_rx_quick_consumer_index8; + u16 status_rx_quick_consumer_index9; + u16 status_rx_quick_consumer_index10; + u16 status_rx_quick_consumer_index11; + u16 status_rx_quick_consumer_index12; + u16 status_rx_quick_consumer_index13; + u16 status_rx_quick_consumer_index14; + u16 status_rx_quick_consumer_index15; + u16 status_completion_producer_index; + u16 status_cmd_consumer_index; + u16 status_idx; + u8 status_unused; + u8 status_blk_num; + #elif defined(__LITTLE_ENDIAN) + u16 status_tx_quick_consumer_index1; + u16 status_tx_quick_consumer_index0; + u16 status_tx_quick_consumer_index3; + u16 status_tx_quick_consumer_index2; + u16 status_rx_quick_consumer_index1; + u16 status_rx_quick_consumer_index0; + u16 status_rx_quick_consumer_index3; + u16 status_rx_quick_consumer_index2; + u16 status_rx_quick_consumer_index5; + u16 status_rx_quick_consumer_index4; + u16 status_rx_quick_consumer_index7; + u16 status_rx_quick_consumer_index6; + u16 status_rx_quick_consumer_index9; + u16 status_rx_quick_consumer_index8; + u16 status_rx_quick_consumer_index11; + u16 status_rx_quick_consumer_index10; + u16 status_rx_quick_consumer_index13; + u16 status_rx_quick_consumer_index12; + u16 status_rx_quick_consumer_index15; + u16 status_rx_quick_consumer_index14; + u16 status_cmd_consumer_index; + u16 status_completion_producer_index; + u8 status_blk_num; + u8 status_unused; + u16 status_idx; + #endif + }; + + /* + * status_block definition + */ + struct status_block_msix { + #if defined(__BIG_ENDIAN) + u16 status_tx_quick_consumer_index; + u16 status_rx_quick_consumer_index; + u16 status_completion_producer_index; + u16 status_cmd_consumer_index; + u32 status_unused; + u16 status_idx; + u8 status_unused2; + u8 status_blk_num; + #elif defined(__LITTLE_ENDIAN) + u16 status_rx_quick_consumer_index; + u16 status_tx_quick_consumer_index; + u16 status_cmd_consumer_index; + u16 status_completion_producer_index; + u32 status_unused; + u8 status_blk_num; + u8 status_unused2; + u16 status_idx; + #endif + }; + + #define BNX2_SBLK_MSIX_ALIGN_SIZE 128 + + + /* + * statistics_block definition + */ + struct statistics_block { + u32 stat_IfHCInOctets_hi; + u32 stat_IfHCInOctets_lo; + u32 stat_IfHCInBadOctets_hi; + u32 stat_IfHCInBadOctets_lo; + u32 stat_IfHCOutOctets_hi; + u32 stat_IfHCOutOctets_lo; + u32 stat_IfHCOutBadOctets_hi; + u32 stat_IfHCOutBadOctets_lo; + u32 stat_IfHCInUcastPkts_hi; + u32 stat_IfHCInUcastPkts_lo; + u32 stat_IfHCInMulticastPkts_hi; + u32 stat_IfHCInMulticastPkts_lo; + u32 stat_IfHCInBroadcastPkts_hi; + u32 stat_IfHCInBroadcastPkts_lo; + u32 stat_IfHCOutUcastPkts_hi; + u32 stat_IfHCOutUcastPkts_lo; + u32 stat_IfHCOutMulticastPkts_hi; + u32 stat_IfHCOutMulticastPkts_lo; + u32 stat_IfHCOutBroadcastPkts_hi; + u32 stat_IfHCOutBroadcastPkts_lo; + u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; + u32 stat_Dot3StatsCarrierSenseErrors; + u32 stat_Dot3StatsFCSErrors; + u32 stat_Dot3StatsAlignmentErrors; + u32 stat_Dot3StatsSingleCollisionFrames; + u32 stat_Dot3StatsMultipleCollisionFrames; + u32 stat_Dot3StatsDeferredTransmissions; + u32 stat_Dot3StatsExcessiveCollisions; + u32 stat_Dot3StatsLateCollisions; + u32 stat_EtherStatsCollisions; + u32 stat_EtherStatsFragments; + u32 stat_EtherStatsJabbers; + u32 stat_EtherStatsUndersizePkts; + u32 stat_EtherStatsOverrsizePkts; + u32 stat_EtherStatsPktsRx64Octets; + u32 stat_EtherStatsPktsRx65Octetsto127Octets; + u32 stat_EtherStatsPktsRx128Octetsto255Octets; + u32 stat_EtherStatsPktsRx256Octetsto511Octets; + u32 stat_EtherStatsPktsRx512Octetsto1023Octets; + u32 stat_EtherStatsPktsRx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsRx1523Octetsto9022Octets; + u32 stat_EtherStatsPktsTx64Octets; + u32 stat_EtherStatsPktsTx65Octetsto127Octets; + u32 stat_EtherStatsPktsTx128Octetsto255Octets; + u32 stat_EtherStatsPktsTx256Octetsto511Octets; + u32 stat_EtherStatsPktsTx512Octetsto1023Octets; + u32 stat_EtherStatsPktsTx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsTx1523Octetsto9022Octets; + u32 stat_XonPauseFramesReceived; + u32 stat_XoffPauseFramesReceived; + u32 stat_OutXonSent; + u32 stat_OutXoffSent; + u32 stat_FlowControlDone; + u32 stat_MacControlFramesReceived; + u32 stat_XoffStateEntered; + u32 stat_IfInFramesL2FilterDiscards; + u32 stat_IfInRuleCheckerDiscards; + u32 stat_IfInFTQDiscards; + u32 stat_IfInMBUFDiscards; + u32 stat_IfInRuleCheckerP4Hit; + u32 stat_CatchupInRuleCheckerDiscards; + u32 stat_CatchupInFTQDiscards; + u32 stat_CatchupInMBUFDiscards; + u32 stat_CatchupInRuleCheckerP4Hit; + u32 stat_GenStat00; + u32 stat_GenStat01; + u32 stat_GenStat02; + u32 stat_GenStat03; + u32 stat_GenStat04; + u32 stat_GenStat05; + u32 stat_GenStat06; + u32 stat_GenStat07; + u32 stat_GenStat08; + u32 stat_GenStat09; + u32 stat_GenStat10; + u32 stat_GenStat11; + u32 stat_GenStat12; + u32 stat_GenStat13; + u32 stat_GenStat14; + u32 stat_GenStat15; + u32 stat_FwRxDrop; + }; + + + /* + * l2_fhdr definition + */ + struct l2_fhdr { + u32 l2_fhdr_status; + #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0) + #define L2_FHDR_STATUS_RULE_P2 (1<<3) + #define L2_FHDR_STATUS_RULE_P3 (1<<4) + #define L2_FHDR_STATUS_RULE_P4 (1<<5) + #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6) + #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7) + #define L2_FHDR_STATUS_RSS_HASH (1<<8) + #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13) + #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14) + #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15) + + #define L2_FHDR_STATUS_SPLIT (1<<16) + #define L2_FHDR_ERRORS_BAD_CRC (1<<17) + #define L2_FHDR_ERRORS_PHY_DECODE (1<<18) + #define L2_FHDR_ERRORS_ALIGNMENT (1<<19) + #define L2_FHDR_ERRORS_TOO_SHORT (1<<20) + #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21) + #define L2_FHDR_ERRORS_TCP_XSUM (1<<28) + #define L2_FHDR_ERRORS_UDP_XSUM (1<<31) + + #define L2_FHDR_STATUS_USE_RXHASH \ + (L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_RSS_HASH) + + u32 l2_fhdr_hash; + #if defined(__BIG_ENDIAN) + u16 l2_fhdr_pkt_len; + u16 l2_fhdr_vlan_tag; + u16 l2_fhdr_ip_xsum; + u16 l2_fhdr_tcp_udp_xsum; + #elif defined(__LITTLE_ENDIAN) + u16 l2_fhdr_vlan_tag; + u16 l2_fhdr_pkt_len; + u16 l2_fhdr_tcp_udp_xsum; + u16 l2_fhdr_ip_xsum; + #endif + }; + + #define BNX2_RX_OFFSET (sizeof(struct l2_fhdr) + 2) + + /* + * l2_context definition + */ + #define BNX2_L2CTX_TYPE 0x00000000 + #define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16) + #define BNX2_L2CTX_TYPE_TYPE (0xf<<28) + #define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28) + #define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28) + + #define BNX2_L2CTX_TX_HOST_BIDX 0x00000088 + #define BNX2_L2CTX_EST_NBD 0x00000088 + #define BNX2_L2CTX_CMD_TYPE 0x00000088 + #define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24) + #define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24) + #define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24) + + #define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090 + #define BNX2_L2CTX_TSCH_BSEQ 0x00000094 + #define BNX2_L2CTX_TBDR_BSEQ 0x00000098 + #define BNX2_L2CTX_TBDR_BOFF 0x0000009c + #define BNX2_L2CTX_TBDR_BIDX 0x0000009c + #define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0 + #define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4 + #define BNX2_L2CTX_TXP_BOFF 0x000000a8 + #define BNX2_L2CTX_TXP_BIDX 0x000000a8 + #define BNX2_L2CTX_TXP_BSEQ 0x000000ac + + #define BNX2_L2CTX_TYPE_XI 0x00000080 + #define BNX2_L2CTX_CMD_TYPE_XI 0x00000240 + #define BNX2_L2CTX_TBDR_BHADDR_HI_XI 0x00000258 + #define BNX2_L2CTX_TBDR_BHADDR_LO_XI 0x0000025c + + /* + * l2_bd_chain_context definition + */ + #define BNX2_L2CTX_BD_PRE_READ 0x00000000 + #define BNX2_L2CTX_CTX_SIZE 0x00000000 + #define BNX2_L2CTX_CTX_TYPE 0x00000000 + #define BNX2_L2CTX_FLOW_CTRL_ENABLE 0x000000ff + #define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16) + #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28) + #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28) + #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28) + + #define BNX2_L2CTX_HOST_BDIDX 0x00000004 + #define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT 16 + #define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT 24 + #define BNX2_L2CTX_L5_STATUSB_NUM(sb_id) \ + (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0) + #define BNX2_L2CTX_L2_STATUSB_NUM(sb_id) \ + (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0) + #define BNX2_L2CTX_HOST_BSEQ 0x00000008 + #define BNX2_L2CTX_NX_BSEQ 0x0000000c + #define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010 + #define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014 + #define BNX2_L2CTX_NX_BDIDX 0x00000018 + + #define BNX2_L2CTX_HOST_PG_BDIDX 0x00000044 + #define BNX2_L2CTX_PG_BUF_SIZE 0x00000048 + #define BNX2_L2CTX_RBDC_KEY 0x0000004c + #define BNX2_L2CTX_RBDC_JUMBO_KEY 0x3ffe + #define BNX2_L2CTX_NX_PG_BDHADDR_HI 0x00000050 + #define BNX2_L2CTX_NX_PG_BDHADDR_LO 0x00000054 + + /* + * pci_config_l definition + * offset: 0000 + */ + #define BNX2_PCICFG_MSI_CONTROL 0x00000058 + #define BNX2_PCICFG_MSI_CONTROL_ENABLE (1L<<16) + + #define BNX2_PCICFG_MISC_CONFIG 0x00000068 + #define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2) + #define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3) + #define BNX2_PCICFG_MISC_CONFIG_RESERVED1 (1L<<4) + #define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5) + #define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6) + #define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7) + #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8) + #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9) + #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN1_SWAP_EN (1L<<10) + #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN2_SWAP_EN (1L<<11) + #define BNX2_PCICFG_MISC_CONFIG_GRC_WIN3_SWAP_EN (1L<<12) + #define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16) + #define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24) + #define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28) + + #define BNX2_PCICFG_MISC_STATUS 0x0000006c + #define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0) + #define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1) + #define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2) + #define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3) + #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4) + #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4) + #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4) + #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4) + #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4) + #define BNX2_PCICFG_MISC_STATUS_BAD_MEM_WRITE_BE (1L<<8) + + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070 + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_17 (1L<<17) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_19 (1L<<19) + #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20) + + #define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078 + #define BNX2_PCICFG_REG_WINDOW_ADDRESS_VAL (0xfffffL<<2) + + #define BNX2_PCICFG_REG_WINDOW 0x00000080 + #define BNX2_PCICFG_INT_ACK_CMD 0x00000084 + #define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0) + #define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16) + #define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17) + #define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18) + #define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM (0xfL<<24) + #define BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT 24 + + #define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088 + #define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c + #define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090 + #define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094 + + #define BNX2_PCICFG_DEVICE_CONTROL 0x000000b4 + #define BNX2_PCICFG_DEVICE_STATUS_NO_PEND ((1L<<5)<<16) + + /* + * pci_reg definition + * offset: 0x400 + */ + #define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400 + #define BNX2_PCI_GRC_WINDOW_ADDR_VALUE (0x1ffL<<13) + #define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN (1L<<31) + + #define BNX2_PCI_GRC_WINDOW2_BASE 0xc000 + #define BNX2_PCI_GRC_WINDOW3_BASE 0xe000 + + #define BNX2_PCI_CONFIG_1 0x00000404 + #define BNX2_PCI_CONFIG_1_RESERVED0 (0xffL<<0) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8) + #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11) + #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11) + #define BNX2_PCI_CONFIG_1_RESERVED1 (0x3ffffL<<14) + + #define BNX2_PCI_CONFIG_2 0x00000408 + #define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0) + #define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4) + #define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5) + #define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6) + #define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8) + #define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8) + #define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16) + #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21) + #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21) + #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21) + #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21) + #define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21) + #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23) + #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24) + #define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25) + #define BNX2_PCI_CONFIG_2_RESERVED0 (0x3fL<<26) + #define BNX2_PCI_CONFIG_2_BAR_PREFETCH_XI (1L<<16) + #define BNX2_PCI_CONFIG_2_RESERVED0_XI (0x7fffL<<17) + + #define BNX2_PCI_CONFIG_3 0x0000040c + #define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0) + #define BNX2_PCI_CONFIG_3_REG_STICKY_BYTE (0xffL<<8) + #define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24) + #define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25) + #define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26) + #define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27) + #define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30) + #define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31) + + #define BNX2_PCI_PM_DATA_A 0x00000410 + #define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0) + #define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8) + #define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16) + #define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24) + + #define BNX2_PCI_PM_DATA_B 0x00000414 + #define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0) + #define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8) + #define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16) + #define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24) + + #define BNX2_PCI_SWAP_DIAG0 0x00000418 + #define BNX2_PCI_SWAP_DIAG1 0x0000041c + #define BNX2_PCI_EXP_ROM_ADDR 0x00000420 + #define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2) + #define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31) + + #define BNX2_PCI_EXP_ROM_DATA 0x00000424 + #define BNX2_PCI_VPD_INTF 0x00000428 + #define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0) + + #define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c + #define BNX2_PCI_VPD_ADDR_FLAG_MSK 0x0000ffff + #define BNX2_PCI_VPD_ADDR_FLAG_SL 0L + #define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fffL<<2) + #define BNX2_PCI_VPD_ADDR_FLAG_WR (1L<<15) + + #define BNX2_PCI_VPD_DATA 0x00000430 + #define BNX2_PCI_ID_VAL1 0x00000434 + #define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0) + #define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16) + + #define BNX2_PCI_ID_VAL2 0x00000438 + #define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0) + #define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16) + + #define BNX2_PCI_ID_VAL3 0x0000043c + #define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0) + #define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24) + + #define BNX2_PCI_ID_VAL4 0x00000440 + #define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0) + #define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0) + #define BNX2_PCI_ID_VAL4_RESERVED0 (0x3L<<4) + #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6) + #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6) + #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6) + #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6) + #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6) + #define BNX2_PCI_ID_VAL4_MSI_PV_MASK_CAP (1L<<8) + #define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9) + #define BNX2_PCI_ID_VAL4_MULTI_MSG_CAP (0x7L<<12) + #define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15) + #define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16) + #define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17) + #define BNX2_PCI_ID_VAL4_RESERVED2 (0x7L<<18) + #define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B21 (0x3L<<21) + #define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B21 (0x3L<<23) + #define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B0 (1L<<25) + #define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE_B10 (0x3L<<26) + #define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B0 (1L<<28) + #define BNX2_PCI_ID_VAL4_RESERVED3 (0x7L<<29) + #define BNX2_PCI_ID_VAL4_RESERVED3_XI (0xffffL<<16) + + #define BNX2_PCI_ID_VAL5 0x00000444 + #define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0) + #define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1) + #define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2) + #define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3) + #define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4) + #define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5) + #define BNX2_PCI_ID_VAL5_RESERVED0_TE (0x3ffffffL<<6) + #define BNX2_PCI_ID_VAL5_PM_VERSION_XI (0x7L<<6) + #define BNX2_PCI_ID_VAL5_NO_SOFT_RESET_XI (1L<<9) + #define BNX2_PCI_ID_VAL5_RESERVED0_XI (0x3fffffL<<10) + + #define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448 + #define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8) + #define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9) + #define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16) + #define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24) + + #define BNX2_PCI_ID_VAL6 0x0000044c + #define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0) + #define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8) + #define BNX2_PCI_ID_VAL6_BIST (0xffL<<16) + #define BNX2_PCI_ID_VAL6_RESERVED0 (0xffL<<24) + + #define BNX2_PCI_MSI_DATA 0x00000450 + #define BNX2_PCI_MSI_DATA_MSI_DATA (0xffffL<<0) + + #define BNX2_PCI_MSI_ADDR_H 0x00000454 + #define BNX2_PCI_MSI_ADDR_L 0x00000458 + #define BNX2_PCI_MSI_ADDR_L_VAL (0x3fffffffL<<2) + + #define BNX2_PCI_CFG_ACCESS_CMD 0x0000045c + #define BNX2_PCI_CFG_ACCESS_CMD_ADR (0x3fL<<2) + #define BNX2_PCI_CFG_ACCESS_CMD_RD_REQ (1L<<27) + #define BNX2_PCI_CFG_ACCESS_CMD_WR_REQ (0xfL<<28) + + #define BNX2_PCI_CFG_ACCESS_DATA 0x00000460 + #define BNX2_PCI_MSI_MASK 0x00000464 + #define BNX2_PCI_MSI_MASK_MSI_MASK (0xffffffffL<<0) + + #define BNX2_PCI_MSI_PEND 0x00000468 + #define BNX2_PCI_MSI_PEND_MSI_PEND (0xffffffffL<<0) + + #define BNX2_PCI_PM_DATA_C 0x0000046c + #define BNX2_PCI_PM_DATA_C_PM_DATA_8_PRG (0xffL<<0) + #define BNX2_PCI_PM_DATA_C_RESERVED0 (0xffffffL<<8) + + #define BNX2_PCI_MSIX_CONTROL 0x000004c0 + #define BNX2_PCI_MSIX_CONTROL_MSIX_TBL_SIZ (0x7ffL<<0) + #define BNX2_PCI_MSIX_CONTROL_RESERVED0 (0x1fffffL<<11) + + #define BNX2_PCI_MSIX_TBL_OFF_BIR 0x000004c4 + #define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_BIR (0x7L<<0) + #define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_OFF (0x1fffffffL<<3) + + #define BNX2_PCI_MSIX_PBA_OFF_BIT 0x000004c8 + #define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_BIR (0x7L<<0) + #define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_OFF (0x1fffffffL<<3) + + #define BNX2_PCI_PCIE_CAPABILITY 0x000004d0 + #define BNX2_PCI_PCIE_CAPABILITY_INTERRUPT_MSG_NUM (0x1fL<<0) + #define BNX2_PCI_PCIE_CAPABILITY_COMPLY_PCIE_1_1 (1L<<5) + + #define BNX2_PCI_DEVICE_CAPABILITY 0x000004d4 + #define BNX2_PCI_DEVICE_CAPABILITY_MAX_PL_SIZ_SUPPORTED (0x7L<<0) + #define BNX2_PCI_DEVICE_CAPABILITY_EXTENDED_TAG_SUPPORT (1L<<5) + #define BNX2_PCI_DEVICE_CAPABILITY_L0S_ACCEPTABLE_LATENCY (0x7L<<6) + #define BNX2_PCI_DEVICE_CAPABILITY_L1_ACCEPTABLE_LATENCY (0x7L<<9) + #define BNX2_PCI_DEVICE_CAPABILITY_ROLE_BASED_ERR_RPT (1L<<15) + + #define BNX2_PCI_LINK_CAPABILITY 0x000004dc + #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED (0xfL<<0) + #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0001 (1L<<0) + #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0010 (1L<<0) + #define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_WIDTH (0x1fL<<4) + #define BNX2_PCI_LINK_CAPABILITY_CLK_POWER_MGMT (1L<<9) + #define BNX2_PCI_LINK_CAPABILITY_ASPM_SUPPORT (0x3L<<10) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT (0x7L<<12) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_101 (5L<<12) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_110 (6L<<12) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT (0x7L<<15) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_001 (1L<<15) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_010 (2L<<15) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT (0x7L<<18) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_101 (5L<<18) + #define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_110 (6L<<18) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT (0x7L<<21) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_001 (1L<<21) + #define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_010 (2L<<21) + #define BNX2_PCI_LINK_CAPABILITY_PORT_NUM (0xffL<<24) + + #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2 0x000004e4 + #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_RANGE_SUPP (0xfL<<0) + #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_DISABL_SUPP (1L<<4) + #define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_RESERVED (0x7ffffffL<<5) + + #define BNX2_PCI_PCIE_LINK_CAPABILITY_2 0x000004e8 + #define BNX2_PCI_PCIE_LINK_CAPABILITY_2_RESERVED (0xffffffffL<<0) + + #define BNX2_PCI_GRC_WINDOW1_ADDR 0x00000610 + #define BNX2_PCI_GRC_WINDOW1_ADDR_VALUE (0x1ffL<<13) + + #define BNX2_PCI_GRC_WINDOW2_ADDR 0x00000614 + #define BNX2_PCI_GRC_WINDOW2_ADDR_VALUE (0x1ffL<<13) + + #define BNX2_PCI_GRC_WINDOW3_ADDR 0x00000618 + #define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE (0x1ffL<<13) + + #define BNX2_MSIX_TABLE_ADDR 0x318000 + #define BNX2_MSIX_PBA_ADDR 0x31c000 + + /* + * misc_reg definition + * offset: 0x800 + */ + #define BNX2_MISC_COMMAND 0x00000800 + #define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0) + #define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1) + #define BNX2_MISC_COMMAND_SW_RESET (1L<<4) + #define BNX2_MISC_COMMAND_POR_RESET (1L<<5) + #define BNX2_MISC_COMMAND_HD_RESET (1L<<6) + #define BNX2_MISC_COMMAND_CMN_SW_RESET (1L<<7) + #define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8) + #define BNX2_MISC_COMMAND_CS16_ERR (1L<<9) + #define BNX2_MISC_COMMAND_CS16_ERR_LOC (0xfL<<12) + #define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16) + #define BNX2_MISC_COMMAND_POWERDOWN_EVENT (1L<<23) + #define BNX2_MISC_COMMAND_SW_SHUTDOWN (1L<<24) + #define BNX2_MISC_COMMAND_SHUTDOWN_EN (1L<<25) + #define BNX2_MISC_COMMAND_DINTEG_ATTN_EN (1L<<26) + #define BNX2_MISC_COMMAND_PCIE_LINK_IN_L23 (1L<<27) + #define BNX2_MISC_COMMAND_PCIE_DIS (1L<<28) + + #define BNX2_MISC_CFG 0x00000804 + #define BNX2_MISC_CFG_GRC_TMOUT (1L<<0) + #define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1) + #define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1) + #define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1) + #define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1) + #define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1) + #define BNX2_MISC_CFG_BIST_EN (1L<<3) + #define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4) + #define BNX2_MISC_CFG_RESERVED5_TE (1L<<5) + #define BNX2_MISC_CFG_RESERVED6_TE (1L<<6) + #define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7) + #define BNX2_MISC_CFG_LEDMODE (0x7L<<8) + #define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY1_TE (1L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY2_TE (2L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY3_TE (3L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY4_TE (4L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY5_TE (5L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY6_TE (6L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY7_TE (7L<<8) + #define BNX2_MISC_CFG_MCP_GRC_TMOUT_TE (1L<<11) + #define BNX2_MISC_CFG_DBU_GRC_TMOUT_TE (1L<<12) + #define BNX2_MISC_CFG_LEDMODE_XI (0xfL<<8) + #define BNX2_MISC_CFG_LEDMODE_MAC_XI (0L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY1_XI (1L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY2_XI (2L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY3_XI (3L<<8) + #define BNX2_MISC_CFG_LEDMODE_MAC2_XI (4L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY4_XI (5L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY5_XI (6L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY6_XI (7L<<8) + #define BNX2_MISC_CFG_LEDMODE_MAC3_XI (8L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY7_XI (9L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY8_XI (10L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY9_XI (11L<<8) + #define BNX2_MISC_CFG_LEDMODE_MAC4_XI (12L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY10_XI (13L<<8) + #define BNX2_MISC_CFG_LEDMODE_PHY11_XI (14L<<8) + #define BNX2_MISC_CFG_LEDMODE_UNUSED_XI (15L<<8) + #define BNX2_MISC_CFG_PORT_SELECT_XI (1L<<13) + #define BNX2_MISC_CFG_PARITY_MODE_XI (1L<<14) + + #define BNX2_MISC_ID 0x00000808 + #define BNX2_MISC_ID_BOND_ID (0xfL<<0) + #define BNX2_MISC_ID_BOND_ID_X (0L<<0) + #define BNX2_MISC_ID_BOND_ID_C (3L<<0) + #define BNX2_MISC_ID_BOND_ID_S (12L<<0) + #define BNX2_MISC_ID_CHIP_METAL (0xffL<<4) + #define BNX2_MISC_ID_CHIP_REV (0xfL<<12) + #define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16) + + #define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7) + #define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8) + #define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16) + #define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17) + #define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18) + #define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19) + #define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) + #define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21) + #define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22) + #define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23) + #define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) + #define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25) + #define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26) + #define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27) + #define BNX2_MISC_ENABLE_STATUS_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) + #define BNX2_MISC_ENABLE_STATUS_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) + + #define BNX2_MISC_ENABLE_SET_BITS 0x00000810 + #define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0) + #define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1) + #define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2) + #define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3) + #define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4) + #define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5) + #define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) + #define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7) + #define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8) + #define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9) + #define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10) + #define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) + #define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12) + #define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13) + #define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14) + #define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15) + #define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16) + #define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17) + #define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18) + #define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19) + #define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) + #define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21) + #define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22) + #define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23) + #define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) + #define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25) + #define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26) + #define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27) + #define BNX2_MISC_ENABLE_SET_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) + #define BNX2_MISC_ENABLE_SET_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) + + #define BNX2_MISC_ENABLE_CLR_BITS 0x00000814 + #define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7) + #define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8) + #define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16) + #define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17) + #define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18) + #define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19) + #define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) + #define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21) + #define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22) + #define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23) + #define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) + #define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25) + #define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26) + #define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27) + #define BNX2_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) + #define BNX2_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) + + #define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818 + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED0_XI (0x7L<<8) + #define BNX2_MISC_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED1_XI (0xfL<<12) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_17_TE (1L<<17) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18_TE (1L<<18) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_19_TE (1L<<19) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_TE (0xfffL<<20) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_MGMT_XI (1L<<17) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED2_XI (0x3fL<<18) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_VCO_XI (0x7L<<24) + #define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED3_XI (1L<<27) + #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_XI (0xfL<<28) + + #define BNX2_MISC_SPIO 0x0000081c + #define BNX2_MISC_SPIO_VALUE (0xffL<<0) + #define BNX2_MISC_SPIO_SET (0xffL<<8) + #define BNX2_MISC_SPIO_CLR (0xffL<<16) + #define BNX2_MISC_SPIO_FLOAT (0xffL<<24) + + #define BNX2_MISC_SPIO_INT 0x00000820 + #define BNX2_MISC_SPIO_INT_INT_STATE_TE (0xfL<<0) + #define BNX2_MISC_SPIO_INT_OLD_VALUE_TE (0xfL<<8) + #define BNX2_MISC_SPIO_INT_OLD_SET_TE (0xfL<<16) + #define BNX2_MISC_SPIO_INT_OLD_CLR_TE (0xfL<<24) + #define BNX2_MISC_SPIO_INT_INT_STATE_XI (0xffL<<0) + #define BNX2_MISC_SPIO_INT_OLD_VALUE_XI (0xffL<<8) + #define BNX2_MISC_SPIO_INT_OLD_SET_XI (0xffL<<16) + #define BNX2_MISC_SPIO_INT_OLD_CLR_XI (0xffL<<24) + + #define BNX2_MISC_CONFIG_LFSR 0x00000824 + #define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0) + + #define BNX2_MISC_LFSR_MASK_BITS 0x00000828 + #define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0) + #define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1) + #define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2) + #define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3) + #define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4) + #define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5) + #define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) + #define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7) + #define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8) + #define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9) + #define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10) + #define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) + #define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12) + #define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13) + #define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14) + #define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15) + #define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16) + #define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17) + #define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18) + #define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19) + #define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) + #define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21) + #define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22) + #define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23) + #define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) + #define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25) + #define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26) + #define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27) + #define BNX2_MISC_LFSR_MASK_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) + #define BNX2_MISC_LFSR_MASK_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) + + #define BNX2_MISC_ARB_REQ0 0x0000082c + #define BNX2_MISC_ARB_REQ1 0x00000830 + #define BNX2_MISC_ARB_REQ2 0x00000834 + #define BNX2_MISC_ARB_REQ3 0x00000838 + #define BNX2_MISC_ARB_REQ4 0x0000083c + #define BNX2_MISC_ARB_FREE0 0x00000840 + #define BNX2_MISC_ARB_FREE1 0x00000844 + #define BNX2_MISC_ARB_FREE2 0x00000848 + #define BNX2_MISC_ARB_FREE3 0x0000084c + #define BNX2_MISC_ARB_FREE4 0x00000850 + #define BNX2_MISC_ARB_REQ_STATUS0 0x00000854 + #define BNX2_MISC_ARB_REQ_STATUS1 0x00000858 + #define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c + #define BNX2_MISC_ARB_REQ_STATUS3 0x00000860 + #define BNX2_MISC_ARB_REQ_STATUS4 0x00000864 + #define BNX2_MISC_ARB_GNT0 0x00000868 + #define BNX2_MISC_ARB_GNT0_0 (0x7L<<0) + #define BNX2_MISC_ARB_GNT0_1 (0x7L<<4) + #define BNX2_MISC_ARB_GNT0_2 (0x7L<<8) + #define BNX2_MISC_ARB_GNT0_3 (0x7L<<12) + #define BNX2_MISC_ARB_GNT0_4 (0x7L<<16) + #define BNX2_MISC_ARB_GNT0_5 (0x7L<<20) + #define BNX2_MISC_ARB_GNT0_6 (0x7L<<24) + #define BNX2_MISC_ARB_GNT0_7 (0x7L<<28) + + #define BNX2_MISC_ARB_GNT1 0x0000086c + #define BNX2_MISC_ARB_GNT1_8 (0x7L<<0) + #define BNX2_MISC_ARB_GNT1_9 (0x7L<<4) + #define BNX2_MISC_ARB_GNT1_10 (0x7L<<8) + #define BNX2_MISC_ARB_GNT1_11 (0x7L<<12) + #define BNX2_MISC_ARB_GNT1_12 (0x7L<<16) + #define BNX2_MISC_ARB_GNT1_13 (0x7L<<20) + #define BNX2_MISC_ARB_GNT1_14 (0x7L<<24) + #define BNX2_MISC_ARB_GNT1_15 (0x7L<<28) + + #define BNX2_MISC_ARB_GNT2 0x00000870 + #define BNX2_MISC_ARB_GNT2_16 (0x7L<<0) + #define BNX2_MISC_ARB_GNT2_17 (0x7L<<4) + #define BNX2_MISC_ARB_GNT2_18 (0x7L<<8) + #define BNX2_MISC_ARB_GNT2_19 (0x7L<<12) + #define BNX2_MISC_ARB_GNT2_20 (0x7L<<16) + #define BNX2_MISC_ARB_GNT2_21 (0x7L<<20) + #define BNX2_MISC_ARB_GNT2_22 (0x7L<<24) + #define BNX2_MISC_ARB_GNT2_23 (0x7L<<28) + + #define BNX2_MISC_ARB_GNT3 0x00000874 + #define BNX2_MISC_ARB_GNT3_24 (0x7L<<0) + #define BNX2_MISC_ARB_GNT3_25 (0x7L<<4) + #define BNX2_MISC_ARB_GNT3_26 (0x7L<<8) + #define BNX2_MISC_ARB_GNT3_27 (0x7L<<12) + #define BNX2_MISC_ARB_GNT3_28 (0x7L<<16) + #define BNX2_MISC_ARB_GNT3_29 (0x7L<<20) + #define BNX2_MISC_ARB_GNT3_30 (0x7L<<24) + #define BNX2_MISC_ARB_GNT3_31 (0x7L<<28) + + #define BNX2_MISC_RESERVED1 0x00000878 + #define BNX2_MISC_RESERVED1_MISC_RESERVED1_VALUE (0x3fL<<0) + + #define BNX2_MISC_RESERVED2 0x0000087c + #define BNX2_MISC_RESERVED2_PCIE_DIS (1L<<0) + #define BNX2_MISC_RESERVED2_LINK_IN_L23 (1L<<1) + + #define BNX2_MISC_SM_ASF_CONTROL 0x00000880 + #define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0) + #define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1) + #define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2) + #define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3) + #define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4) + #define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5) + #define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7) + #define BNX2_MISC_SM_ASF_CONTROL_STRETCH_EN (1L<<8) + #define BNX2_MISC_SM_ASF_CONTROL_STRETCH_PULSE (1L<<9) + #define BNX2_MISC_SM_ASF_CONTROL_RES (0x3L<<10) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15) + #define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x7fL<<16) + #define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x7fL<<23) + #define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30) + #define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31) + + #define BNX2_MISC_SMB_IN 0x00000884 + #define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0) + #define BNX2_MISC_SMB_IN_RDY (1L<<8) + #define BNX2_MISC_SMB_IN_DONE (1L<<9) + #define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10) + #define BNX2_MISC_SMB_IN_STATUS (0x7L<<11) + #define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11) + #define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11) + #define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11) + #define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11) + #define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11) + + #define BNX2_MISC_SMB_OUT 0x00000888 + #define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0) + #define BNX2_MISC_SMB_OUT_RDY (1L<<8) + #define BNX2_MISC_SMB_OUT_START (1L<<9) + #define BNX2_MISC_SMB_OUT_LAST (1L<<10) + #define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11) + #define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12) + #define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13) + #define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (6L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20) + #define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24) + #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25) + #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26) + #define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27) + #define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28) + + #define BNX2_MISC_SMB_WATCHDOG 0x0000088c + #define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0) + + #define BNX2_MISC_SMB_HEARTBEAT 0x00000890 + #define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0) + + #define BNX2_MISC_SMB_POLL_ASF 0x00000894 + #define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0) + + #define BNX2_MISC_SMB_POLL_LEGACY 0x00000898 + #define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0) + + #define BNX2_MISC_SMB_RETRAN 0x0000089c + #define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0) + + #define BNX2_MISC_SMB_TIMESTAMP 0x000008a0 + #define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0) + + #define BNX2_MISC_PERR_ENA0 0x000008a4 + #define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0) + #define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1) + #define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2) + #define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3) + #define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4) + #define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5) + #define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12) + #define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20) + #define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21) + #define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22) + #define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23) + #define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24) + #define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25) + #define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26) + #define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27) + #define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28) + #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29) + #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30) + #define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31) + #define BNX2_MISC_PERR_ENA0_COM_DMAE_PERR_EN_XI (1L<<0) + #define BNX2_MISC_PERR_ENA0_CP_DMAE_PERR_EN_XI (1L<<1) + #define BNX2_MISC_PERR_ENA0_RPM_ACPIBEMEM_PERR_EN_XI (1L<<2) + #define BNX2_MISC_PERR_ENA0_CTX_USAGE_CNT_PERR_EN_XI (1L<<3) + #define BNX2_MISC_PERR_ENA0_CTX_PGTBL_PERR_EN_XI (1L<<4) + #define BNX2_MISC_PERR_ENA0_CTX_CACHE_PERR_EN_XI (1L<<5) + #define BNX2_MISC_PERR_ENA0_CTX_MIRROR_PERR_EN_XI (1L<<6) + #define BNX2_MISC_PERR_ENA0_COM_CTXC_PERR_EN_XI (1L<<7) + #define BNX2_MISC_PERR_ENA0_COM_SCPAD_PERR_EN_XI (1L<<8) + #define BNX2_MISC_PERR_ENA0_CP_CTXC_PERR_EN_XI (1L<<9) + #define BNX2_MISC_PERR_ENA0_CP_SCPAD_PERR_EN_XI (1L<<10) + #define BNX2_MISC_PERR_ENA0_RXP_RBUFC_PERR_EN_XI (1L<<11) + #define BNX2_MISC_PERR_ENA0_RXP_CTXC_PERR_EN_XI (1L<<12) + #define BNX2_MISC_PERR_ENA0_RXP_SCPAD_PERR_EN_XI (1L<<13) + #define BNX2_MISC_PERR_ENA0_TPAT_SCPAD_PERR_EN_XI (1L<<14) + #define BNX2_MISC_PERR_ENA0_TXP_CTXC_PERR_EN_XI (1L<<15) + #define BNX2_MISC_PERR_ENA0_TXP_SCPAD_PERR_EN_XI (1L<<16) + #define BNX2_MISC_PERR_ENA0_CS_TMEM_PERR_EN_XI (1L<<17) + #define BNX2_MISC_PERR_ENA0_MQ_CTX_PERR_EN_XI (1L<<18) + #define BNX2_MISC_PERR_ENA0_RPM_DFIFOMEM_PERR_EN_XI (1L<<19) + #define BNX2_MISC_PERR_ENA0_RPC_DFIFOMEM_PERR_EN_XI (1L<<20) + #define BNX2_MISC_PERR_ENA0_RBUF_PTRMEM_PERR_EN_XI (1L<<21) + #define BNX2_MISC_PERR_ENA0_RBUF_DATAMEM_PERR_EN_XI (1L<<22) + #define BNX2_MISC_PERR_ENA0_RV2P_P2IRAM_PERR_EN_XI (1L<<23) + #define BNX2_MISC_PERR_ENA0_RV2P_P1IRAM_PERR_EN_XI (1L<<24) + #define BNX2_MISC_PERR_ENA0_RV2P_CB1REGS_PERR_EN_XI (1L<<25) + #define BNX2_MISC_PERR_ENA0_RV2P_CB0REGS_PERR_EN_XI (1L<<26) + #define BNX2_MISC_PERR_ENA0_TPBUF_PERR_EN_XI (1L<<27) + #define BNX2_MISC_PERR_ENA0_THBUF_PERR_EN_XI (1L<<28) + #define BNX2_MISC_PERR_ENA0_TDMA_PERR_EN_XI (1L<<29) + #define BNX2_MISC_PERR_ENA0_TBDC_PERR_EN_XI (1L<<30) + #define BNX2_MISC_PERR_ENA0_TSCH_LR_PERR_EN_XI (1L<<31) + + #define BNX2_MISC_PERR_ENA1 0x000008a8 + #define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0) + #define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1) + #define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2) + #define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3) + #define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4) + #define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5) + #define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6) + #define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7) + #define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8) + #define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9) + #define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10) + #define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11) + #define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12) + #define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13) + #define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14) + #define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15) + #define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16) + #define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17) + #define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18) + #define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19) + #define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20) + #define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21) + #define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22) + #define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23) + #define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24) + #define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25) + #define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26) + #define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27) + #define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28) + #define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29) + #define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30) + #define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31) + #define BNX2_MISC_PERR_ENA1_RBDC_PERR_EN_XI (1L<<0) + #define BNX2_MISC_PERR_ENA1_RDMA_DFIFO_PERR_EN_XI (1L<<2) + #define BNX2_MISC_PERR_ENA1_HC_STATS_PERR_EN_XI (1L<<3) + #define BNX2_MISC_PERR_ENA1_HC_MSIX_PERR_EN_XI (1L<<4) + #define BNX2_MISC_PERR_ENA1_HC_PRODUCSTB_PERR_EN_XI (1L<<5) + #define BNX2_MISC_PERR_ENA1_HC_CONSUMSTB_PERR_EN_XI (1L<<6) + #define BNX2_MISC_PERR_ENA1_TPATQ_PERR_EN_XI (1L<<7) + #define BNX2_MISC_PERR_ENA1_MCPQ_PERR_EN_XI (1L<<8) + #define BNX2_MISC_PERR_ENA1_TDMAQ_PERR_EN_XI (1L<<9) + #define BNX2_MISC_PERR_ENA1_TXPQ_PERR_EN_XI (1L<<10) + #define BNX2_MISC_PERR_ENA1_COMTQ_PERR_EN_XI (1L<<11) + #define BNX2_MISC_PERR_ENA1_COMQ_PERR_EN_XI (1L<<12) + #define BNX2_MISC_PERR_ENA1_RLUPQ_PERR_EN_XI (1L<<13) + #define BNX2_MISC_PERR_ENA1_RXPQ_PERR_EN_XI (1L<<14) + #define BNX2_MISC_PERR_ENA1_RV2PPQ_PERR_EN_XI (1L<<15) + #define BNX2_MISC_PERR_ENA1_RDMAQ_PERR_EN_XI (1L<<16) + #define BNX2_MISC_PERR_ENA1_TASQ_PERR_EN_XI (1L<<17) + #define BNX2_MISC_PERR_ENA1_TBDRQ_PERR_EN_XI (1L<<18) + #define BNX2_MISC_PERR_ENA1_TSCHQ_PERR_EN_XI (1L<<19) + #define BNX2_MISC_PERR_ENA1_COMXQ_PERR_EN_XI (1L<<20) + #define BNX2_MISC_PERR_ENA1_RXPCQ_PERR_EN_XI (1L<<21) + #define BNX2_MISC_PERR_ENA1_RV2PTQ_PERR_EN_XI (1L<<22) + #define BNX2_MISC_PERR_ENA1_RV2PMQ_PERR_EN_XI (1L<<23) + #define BNX2_MISC_PERR_ENA1_CPQ_PERR_EN_XI (1L<<24) + #define BNX2_MISC_PERR_ENA1_CSQ_PERR_EN_XI (1L<<25) + #define BNX2_MISC_PERR_ENA1_RLUP_CID_PERR_EN_XI (1L<<26) + #define BNX2_MISC_PERR_ENA1_RV2PCS_TMEM_PERR_EN_XI (1L<<27) + #define BNX2_MISC_PERR_ENA1_RV2PCSQ_PERR_EN_XI (1L<<28) + #define BNX2_MISC_PERR_ENA1_MQ_IDX_PERR_EN_XI (1L<<29) + + #define BNX2_MISC_PERR_ENA2 0x000008ac + #define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0) + #define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1) + #define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2) + #define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3) + #define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4) + #define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5) + #define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6) + #define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7) + #define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8) + #define BNX2_MISC_PERR_ENA2_TGT_FIFO_PERR_EN_XI (1L<<0) + #define BNX2_MISC_PERR_ENA2_UMP_TX_PERR_EN_XI (1L<<1) + #define BNX2_MISC_PERR_ENA2_UMP_RX_PERR_EN_XI (1L<<2) + #define BNX2_MISC_PERR_ENA2_MCP_ROM_PERR_EN_XI (1L<<3) + #define BNX2_MISC_PERR_ENA2_MCP_SCPAD_PERR_EN_XI (1L<<4) + #define BNX2_MISC_PERR_ENA2_HB_MEM_PERR_EN_XI (1L<<5) + #define BNX2_MISC_PERR_ENA2_PCIE_REPLAY_PERR_EN_XI (1L<<6) + + #define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0 + #define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0) + #define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12) + #define BNX2_MISC_DEBUG_VECTOR_SEL_1_XI (0xfffL<<15) + + #define BNX2_MISC_VREG_CONTROL 0x000008b4 + #define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_XI (0xfL<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS14_XI (0L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS12_XI (1L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS10_XI (2L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS8_XI (3L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS6_XI (4L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS4_XI (5L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS2_XI (6L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_NOM_XI (7L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS2_XI (8L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS4_XI (9L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS6_XI (10L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS8_XI (11L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS10_XI (12L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS12_XI (13L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS14_XI (14L<<0) + #define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS16_XI (15L<<0) + #define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS14 (0L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS12 (1L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS10 (2L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS8 (3L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS6 (4L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS4 (5L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_PLUS2 (6L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_NOM (7L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS2 (8L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS4 (9L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS6 (10L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS8 (11L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS10 (12L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS12 (13L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS14 (14L<<4) + #define BNX2_MISC_VREG_CONTROL_2_5_MINUS16 (15L<<4) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT (0xfL<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS14 (0L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS12 (1L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS10 (2L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS8 (3L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS6 (4L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS4 (5L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS2 (6L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_NOM (7L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS2 (8L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS4 (9L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS6 (10L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS8 (11L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS10 (12L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS12 (13L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS14 (14L<<8) + #define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS16 (15L<<8) + + #define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8 + #define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6) + + #define BNX2_MISC_GP_HW_CTL0 0x000008bc + #define BNX2_MISC_GP_HW_CTL0_TX_DRIVE (1L<<0) + #define BNX2_MISC_GP_HW_CTL0_RMII_MODE (1L<<1) + #define BNX2_MISC_GP_HW_CTL0_RMII_CRSDV_SEL (1L<<2) + #define BNX2_MISC_GP_HW_CTL0_RVMII_MODE (1L<<3) + #define BNX2_MISC_GP_HW_CTL0_FLASH_SAMP_SCLK_NEGEDGE_TE (1L<<4) + #define BNX2_MISC_GP_HW_CTL0_HIDDEN_REVISION_ID_TE (1L<<5) + #define BNX2_MISC_GP_HW_CTL0_HC_CNTL_TMOUT_CTR_RST_TE (1L<<6) + #define BNX2_MISC_GP_HW_CTL0_RESERVED1_XI (0x7L<<4) + #define BNX2_MISC_GP_HW_CTL0_ENA_CORE_RST_ON_MAIN_PWR_GOING_AWAY (1L<<7) + #define BNX2_MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE (1L<<8) + #define BNX2_MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE (1L<<9) + #define BNX2_MISC_GP_HW_CTL0_LED_ACT_SEL_TE (1L<<10) + #define BNX2_MISC_GP_HW_CTL0_RESERVED2_XI (0x7L<<8) + #define BNX2_MISC_GP_HW_CTL0_UP1_DEF0 (1L<<11) + #define BNX2_MISC_GP_HW_CTL0_FIBER_MODE_DIS_DEF (1L<<12) + #define BNX2_MISC_GP_HW_CTL0_FORCE2500_DEF (1L<<13) + #define BNX2_MISC_GP_HW_CTL0_AUTODETECT_DIS_DEF (1L<<14) + #define BNX2_MISC_GP_HW_CTL0_PARALLEL_DETECT_DEF (1L<<15) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI (0xfL<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_3MA (0L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P5MA (1L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P0MA (3L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P5MA (5L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P0MA (7L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_PWRDN (15L<<16) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE2DIS (1L<<20) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE1DIS (1L<<21) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT (0x3L<<22) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M6P (0L<<22) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M0P (1L<<22) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P0P (2L<<22) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P6P (3L<<22) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT (0x3L<<24) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M6P (0L<<24) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M0P (1L<<24) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P0P (2L<<24) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P6P (3L<<24) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ (0x3L<<26) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_240UA (0L<<26) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_160UA (1L<<26) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_400UA (2L<<26) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_320UA (3L<<26) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ (0x3L<<28) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_240UA (0L<<28) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_160UA (1L<<28) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_400UA (2L<<28) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_320UA (3L<<28) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ (0x3L<<30) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P57 (0L<<30) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P45 (1L<<30) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P62 (2L<<30) + #define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P66 (3L<<30) + + #define BNX2_MISC_GP_HW_CTL1 0x000008c0 + #define BNX2_MISC_GP_HW_CTL1_1_ATTN_BTN_PRSNT_TE (1L<<0) + #define BNX2_MISC_GP_HW_CTL1_1_ATTN_IND_PRSNT_TE (1L<<1) + #define BNX2_MISC_GP_HW_CTL1_1_PWR_IND_PRSNT_TE (1L<<2) + #define BNX2_MISC_GP_HW_CTL1_0_PCIE_LOOPBACK_TE (1L<<3) + #define BNX2_MISC_GP_HW_CTL1_RESERVED_SOFT_XI (0xffffL<<0) + #define BNX2_MISC_GP_HW_CTL1_RESERVED_HARD_XI (0xffffL<<16) + + #define BNX2_MISC_NEW_HW_CTL 0x000008c4 + #define BNX2_MISC_NEW_HW_CTL_MAIN_POR_BYPASS (1L<<0) + #define BNX2_MISC_NEW_HW_CTL_RINGOSC_ENABLE (1L<<1) + #define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL0 (1L<<2) + #define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL1 (1L<<3) + #define BNX2_MISC_NEW_HW_CTL_RESERVED_SHARED (0xfffL<<4) + #define BNX2_MISC_NEW_HW_CTL_RESERVED_SPLIT (0xffffL<<16) + + #define BNX2_MISC_NEW_CORE_CTL 0x000008c8 + #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0) + #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1) + #define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16) + #define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2) + #define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16) + + #define BNX2_MISC_ECO_HW_CTL 0x000008cc + #define BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN (1L<<0) + #define BNX2_MISC_ECO_HW_CTL_RESERVED_SOFT (0x7fffL<<1) + #define BNX2_MISC_ECO_HW_CTL_RESERVED_HARD (0xffffL<<16) + + #define BNX2_MISC_ECO_CORE_CTL 0x000008d0 + #define BNX2_MISC_ECO_CORE_CTL_RESERVED_SOFT (0xffffL<<0) + #define BNX2_MISC_ECO_CORE_CTL_RESERVED_HARD (0xffffL<<16) + + #define BNX2_MISC_PPIO 0x000008d4 + #define BNX2_MISC_PPIO_VALUE (0xfL<<0) + #define BNX2_MISC_PPIO_SET (0xfL<<8) + #define BNX2_MISC_PPIO_CLR (0xfL<<16) + #define BNX2_MISC_PPIO_FLOAT (0xfL<<24) + + #define BNX2_MISC_PPIO_INT 0x000008d8 + #define BNX2_MISC_PPIO_INT_INT_STATE (0xfL<<0) + #define BNX2_MISC_PPIO_INT_OLD_VALUE (0xfL<<8) + #define BNX2_MISC_PPIO_INT_OLD_SET (0xfL<<16) + #define BNX2_MISC_PPIO_INT_OLD_CLR (0xfL<<24) + + #define BNX2_MISC_RESET_NUMS 0x000008dc + #define BNX2_MISC_RESET_NUMS_NUM_HARD_RESETS (0x7L<<0) + #define BNX2_MISC_RESET_NUMS_NUM_PCIE_RESETS (0x7L<<4) + #define BNX2_MISC_RESET_NUMS_NUM_PERSTB_RESETS (0x7L<<8) + #define BNX2_MISC_RESET_NUMS_NUM_CMN_RESETS (0x7L<<12) + #define BNX2_MISC_RESET_NUMS_NUM_PORT_RESETS (0x7L<<16) + + #define BNX2_MISC_CS16_ERR 0x000008e0 + #define BNX2_MISC_CS16_ERR_ENA_PCI (1L<<0) + #define BNX2_MISC_CS16_ERR_ENA_RDMA (1L<<1) + #define BNX2_MISC_CS16_ERR_ENA_TDMA (1L<<2) + #define BNX2_MISC_CS16_ERR_ENA_EMAC (1L<<3) + #define BNX2_MISC_CS16_ERR_ENA_CTX (1L<<4) + #define BNX2_MISC_CS16_ERR_ENA_TBDR (1L<<5) + #define BNX2_MISC_CS16_ERR_ENA_RBDC (1L<<6) + #define BNX2_MISC_CS16_ERR_ENA_COM (1L<<7) + #define BNX2_MISC_CS16_ERR_ENA_CP (1L<<8) + #define BNX2_MISC_CS16_ERR_STA_PCI (1L<<16) + #define BNX2_MISC_CS16_ERR_STA_RDMA (1L<<17) + #define BNX2_MISC_CS16_ERR_STA_TDMA (1L<<18) + #define BNX2_MISC_CS16_ERR_STA_EMAC (1L<<19) + #define BNX2_MISC_CS16_ERR_STA_CTX (1L<<20) + #define BNX2_MISC_CS16_ERR_STA_TBDR (1L<<21) + #define BNX2_MISC_CS16_ERR_STA_RBDC (1L<<22) + #define BNX2_MISC_CS16_ERR_STA_COM (1L<<23) + #define BNX2_MISC_CS16_ERR_STA_CP (1L<<24) + + #define BNX2_MISC_SPIO_EVENT 0x000008e4 + #define BNX2_MISC_SPIO_EVENT_ENABLE (0xffL<<0) + + #define BNX2_MISC_PPIO_EVENT 0x000008e8 + #define BNX2_MISC_PPIO_EVENT_ENABLE (0xfL<<0) + + #define BNX2_MISC_DUAL_MEDIA_CTRL 0x000008ec + #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID (0xffL<<0) + #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_X (0L<<0) + #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C (3L<<0) + #define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S (12L<<0) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP (0x7L<<8) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN (1L<<11) + #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_SIGDET (1L<<12) + #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_SIGDET (1L<<13) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_SIGDET (1L<<14) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_SIGDET (1L<<15) + #define BNX2_MISC_DUAL_MEDIA_CTRL_LCPLL_RST (1L<<16) + #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_RST (1L<<17) + #define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_RST (1L<<18) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_RST (1L<<19) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_RST (1L<<20) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL (0x7L<<21) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP (1L<<24) + #define BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE (1L<<25) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ (0xfL<<26) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER1_IDDQ (1L<<26) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER0_IDDQ (2L<<26) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY1_IDDQ (4L<<26) + #define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY0_IDDQ (8L<<26) + + #define BNX2_MISC_OTP_CMD1 0x000008f0 + #define BNX2_MISC_OTP_CMD1_FMODE (0x7L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_IDLE (0L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_WRITE (1L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_INIT (2L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_SET (3L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_RST (4L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_VERIFY (5L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_RESERVED0 (6L<<0) + #define BNX2_MISC_OTP_CMD1_FMODE_RESERVED1 (7L<<0) + #define BNX2_MISC_OTP_CMD1_USEPINS (1L<<8) + #define BNX2_MISC_OTP_CMD1_PROGSEL (1L<<9) + #define BNX2_MISC_OTP_CMD1_PROGSTART (1L<<10) + #define BNX2_MISC_OTP_CMD1_PCOUNT (0x7L<<16) + #define BNX2_MISC_OTP_CMD1_PBYP (1L<<19) + #define BNX2_MISC_OTP_CMD1_VSEL (0xfL<<20) + #define BNX2_MISC_OTP_CMD1_TM (0x7L<<27) + #define BNX2_MISC_OTP_CMD1_SADBYP (1L<<30) + #define BNX2_MISC_OTP_CMD1_DEBUG (1L<<31) + + #define BNX2_MISC_OTP_CMD2 0x000008f4 + #define BNX2_MISC_OTP_CMD2_OTP_ROM_ADDR (0x3ffL<<0) + #define BNX2_MISC_OTP_CMD2_DOSEL (0x7fL<<16) + #define BNX2_MISC_OTP_CMD2_DOSEL_0 (0L<<16) + #define BNX2_MISC_OTP_CMD2_DOSEL_1 (1L<<16) + #define BNX2_MISC_OTP_CMD2_DOSEL_127 (127L<<16) + + #define BNX2_MISC_OTP_STATUS 0x000008f8 + #define BNX2_MISC_OTP_STATUS_DATA (0xffL<<0) + #define BNX2_MISC_OTP_STATUS_VALID (1L<<8) + #define BNX2_MISC_OTP_STATUS_BUSY (1L<<9) + #define BNX2_MISC_OTP_STATUS_BUSYSM (1L<<10) + #define BNX2_MISC_OTP_STATUS_DONE (1L<<11) + + #define BNX2_MISC_OTP_SHIFT1_CMD 0x000008fc + #define BNX2_MISC_OTP_SHIFT1_CMD_RESET_MODE_N (1L<<0) + #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_DONE (1L<<1) + #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_START (1L<<2) + #define BNX2_MISC_OTP_SHIFT1_CMD_LOAD_DATA (1L<<3) + #define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_SELECT (0x1fL<<8) + + #define BNX2_MISC_OTP_SHIFT1_DATA 0x00000900 + #define BNX2_MISC_OTP_SHIFT2_CMD 0x00000904 + #define BNX2_MISC_OTP_SHIFT2_CMD_RESET_MODE_N (1L<<0) + #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_DONE (1L<<1) + #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_START (1L<<2) + #define BNX2_MISC_OTP_SHIFT2_CMD_LOAD_DATA (1L<<3) + #define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_SELECT (0x1fL<<8) + + #define BNX2_MISC_OTP_SHIFT2_DATA 0x00000908 + #define BNX2_MISC_BIST_CS0 0x0000090c + #define BNX2_MISC_BIST_CS0_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS0_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS0_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS0_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS0_MBIST_GO (1L<<9) + #define BNX2_MISC_BIST_CS0_BIST_OVERRIDE (1L<<31) + + #define BNX2_MISC_BIST_MEMSTATUS0 0x00000910 + #define BNX2_MISC_BIST_CS1 0x00000914 + #define BNX2_MISC_BIST_CS1_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS1_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS1_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS1_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS1_MBIST_GO (1L<<9) + + #define BNX2_MISC_BIST_MEMSTATUS1 0x00000918 + #define BNX2_MISC_BIST_CS2 0x0000091c + #define BNX2_MISC_BIST_CS2_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS2_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS2_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS2_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS2_MBIST_GO (1L<<9) + + #define BNX2_MISC_BIST_MEMSTATUS2 0x00000920 + #define BNX2_MISC_BIST_CS3 0x00000924 + #define BNX2_MISC_BIST_CS3_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS3_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS3_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS3_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS3_MBIST_GO (1L<<9) + + #define BNX2_MISC_BIST_MEMSTATUS3 0x00000928 + #define BNX2_MISC_BIST_CS4 0x0000092c + #define BNX2_MISC_BIST_CS4_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS4_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS4_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS4_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS4_MBIST_GO (1L<<9) + + #define BNX2_MISC_BIST_MEMSTATUS4 0x00000930 + #define BNX2_MISC_BIST_CS5 0x00000934 + #define BNX2_MISC_BIST_CS5_MBIST_EN (1L<<0) + #define BNX2_MISC_BIST_CS5_BIST_SETUP (0x3L<<1) + #define BNX2_MISC_BIST_CS5_MBIST_ASYNC_RESET (1L<<3) + #define BNX2_MISC_BIST_CS5_MBIST_DONE (1L<<8) + #define BNX2_MISC_BIST_CS5_MBIST_GO (1L<<9) + + #define BNX2_MISC_BIST_MEMSTATUS5 0x00000938 + #define BNX2_MISC_MEM_TM0 0x0000093c + #define BNX2_MISC_MEM_TM0_PCIE_REPLAY_TM (0xfL<<0) + #define BNX2_MISC_MEM_TM0_MCP_SCPAD (0xfL<<8) + #define BNX2_MISC_MEM_TM0_UMP_TM (0xffL<<16) + #define BNX2_MISC_MEM_TM0_HB_MEM_TM (0xfL<<24) + + #define BNX2_MISC_USPLL_CTRL 0x00000940 + #define BNX2_MISC_USPLL_CTRL_PH_DET_DIS (1L<<0) + #define BNX2_MISC_USPLL_CTRL_FREQ_DET_DIS (1L<<1) + #define BNX2_MISC_USPLL_CTRL_LCPX (0x3fL<<2) + #define BNX2_MISC_USPLL_CTRL_RX (0x3L<<8) + #define BNX2_MISC_USPLL_CTRL_VC_EN (1L<<10) + #define BNX2_MISC_USPLL_CTRL_VCO_MG (0x3L<<11) + #define BNX2_MISC_USPLL_CTRL_KVCO_XF (0x7L<<13) + #define BNX2_MISC_USPLL_CTRL_KVCO_XS (0x7L<<16) + #define BNX2_MISC_USPLL_CTRL_TESTD_EN (1L<<19) + #define BNX2_MISC_USPLL_CTRL_TESTD_SEL (0x7L<<20) + #define BNX2_MISC_USPLL_CTRL_TESTA_EN (1L<<23) + #define BNX2_MISC_USPLL_CTRL_TESTA_SEL (0x3L<<24) + #define BNX2_MISC_USPLL_CTRL_ATTEN_FREF (1L<<26) + #define BNX2_MISC_USPLL_CTRL_DIGITAL_RST (1L<<27) + #define BNX2_MISC_USPLL_CTRL_ANALOG_RST (1L<<28) + #define BNX2_MISC_USPLL_CTRL_LOCK (1L<<29) + + #define BNX2_MISC_PERR_STATUS0 0x00000944 + #define BNX2_MISC_PERR_STATUS0_COM_DMAE_PERR (1L<<0) + #define BNX2_MISC_PERR_STATUS0_CP_DMAE_PERR (1L<<1) + #define BNX2_MISC_PERR_STATUS0_RPM_ACPIBEMEM_PERR (1L<<2) + #define BNX2_MISC_PERR_STATUS0_CTX_USAGE_CNT_PERR (1L<<3) + #define BNX2_MISC_PERR_STATUS0_CTX_PGTBL_PERR (1L<<4) + #define BNX2_MISC_PERR_STATUS0_CTX_CACHE_PERR (1L<<5) + #define BNX2_MISC_PERR_STATUS0_CTX_MIRROR_PERR (1L<<6) + #define BNX2_MISC_PERR_STATUS0_COM_CTXC_PERR (1L<<7) + #define BNX2_MISC_PERR_STATUS0_COM_SCPAD_PERR (1L<<8) + #define BNX2_MISC_PERR_STATUS0_CP_CTXC_PERR (1L<<9) + #define BNX2_MISC_PERR_STATUS0_CP_SCPAD_PERR (1L<<10) + #define BNX2_MISC_PERR_STATUS0_RXP_RBUFC_PERR (1L<<11) + #define BNX2_MISC_PERR_STATUS0_RXP_CTXC_PERR (1L<<12) + #define BNX2_MISC_PERR_STATUS0_RXP_SCPAD_PERR (1L<<13) + #define BNX2_MISC_PERR_STATUS0_TPAT_SCPAD_PERR (1L<<14) + #define BNX2_MISC_PERR_STATUS0_TXP_CTXC_PERR (1L<<15) + #define BNX2_MISC_PERR_STATUS0_TXP_SCPAD_PERR (1L<<16) + #define BNX2_MISC_PERR_STATUS0_CS_TMEM_PERR (1L<<17) + #define BNX2_MISC_PERR_STATUS0_MQ_CTX_PERR (1L<<18) + #define BNX2_MISC_PERR_STATUS0_RPM_DFIFOMEM_PERR (1L<<19) + #define BNX2_MISC_PERR_STATUS0_RPC_DFIFOMEM_PERR (1L<<20) + #define BNX2_MISC_PERR_STATUS0_RBUF_PTRMEM_PERR (1L<<21) + #define BNX2_MISC_PERR_STATUS0_RBUF_DATAMEM_PERR (1L<<22) + #define BNX2_MISC_PERR_STATUS0_RV2P_P2IRAM_PERR (1L<<23) + #define BNX2_MISC_PERR_STATUS0_RV2P_P1IRAM_PERR (1L<<24) + #define BNX2_MISC_PERR_STATUS0_RV2P_CB1REGS_PERR (1L<<25) + #define BNX2_MISC_PERR_STATUS0_RV2P_CB0REGS_PERR (1L<<26) + #define BNX2_MISC_PERR_STATUS0_TPBUF_PERR (1L<<27) + #define BNX2_MISC_PERR_STATUS0_THBUF_PERR (1L<<28) + #define BNX2_MISC_PERR_STATUS0_TDMA_PERR (1L<<29) + #define BNX2_MISC_PERR_STATUS0_TBDC_PERR (1L<<30) + #define BNX2_MISC_PERR_STATUS0_TSCH_LR_PERR (1L<<31) + + #define BNX2_MISC_PERR_STATUS1 0x00000948 + #define BNX2_MISC_PERR_STATUS1_RBDC_PERR (1L<<0) + #define BNX2_MISC_PERR_STATUS1_RDMA_DFIFO_PERR (1L<<2) + #define BNX2_MISC_PERR_STATUS1_HC_STATS_PERR (1L<<3) + #define BNX2_MISC_PERR_STATUS1_HC_MSIX_PERR (1L<<4) + #define BNX2_MISC_PERR_STATUS1_HC_PRODUCSTB_PERR (1L<<5) + #define BNX2_MISC_PERR_STATUS1_HC_CONSUMSTB_PERR (1L<<6) + #define BNX2_MISC_PERR_STATUS1_TPATQ_PERR (1L<<7) + #define BNX2_MISC_PERR_STATUS1_MCPQ_PERR (1L<<8) + #define BNX2_MISC_PERR_STATUS1_TDMAQ_PERR (1L<<9) + #define BNX2_MISC_PERR_STATUS1_TXPQ_PERR (1L<<10) + #define BNX2_MISC_PERR_STATUS1_COMTQ_PERR (1L<<11) + #define BNX2_MISC_PERR_STATUS1_COMQ_PERR (1L<<12) + #define BNX2_MISC_PERR_STATUS1_RLUPQ_PERR (1L<<13) + #define BNX2_MISC_PERR_STATUS1_RXPQ_PERR (1L<<14) + #define BNX2_MISC_PERR_STATUS1_RV2PPQ_PERR (1L<<15) + #define BNX2_MISC_PERR_STATUS1_RDMAQ_PERR (1L<<16) + #define BNX2_MISC_PERR_STATUS1_TASQ_PERR (1L<<17) + #define BNX2_MISC_PERR_STATUS1_TBDRQ_PERR (1L<<18) + #define BNX2_MISC_PERR_STATUS1_TSCHQ_PERR (1L<<19) + #define BNX2_MISC_PERR_STATUS1_COMXQ_PERR (1L<<20) + #define BNX2_MISC_PERR_STATUS1_RXPCQ_PERR (1L<<21) + #define BNX2_MISC_PERR_STATUS1_RV2PTQ_PERR (1L<<22) + #define BNX2_MISC_PERR_STATUS1_RV2PMQ_PERR (1L<<23) + #define BNX2_MISC_PERR_STATUS1_CPQ_PERR (1L<<24) + #define BNX2_MISC_PERR_STATUS1_CSQ_PERR (1L<<25) + #define BNX2_MISC_PERR_STATUS1_RLUP_CID_PERR (1L<<26) + #define BNX2_MISC_PERR_STATUS1_RV2PCS_TMEM_PERR (1L<<27) + #define BNX2_MISC_PERR_STATUS1_RV2PCSQ_PERR (1L<<28) + #define BNX2_MISC_PERR_STATUS1_MQ_IDX_PERR (1L<<29) + + #define BNX2_MISC_PERR_STATUS2 0x0000094c + #define BNX2_MISC_PERR_STATUS2_TGT_FIFO_PERR (1L<<0) + #define BNX2_MISC_PERR_STATUS2_UMP_TX_PERR (1L<<1) + #define BNX2_MISC_PERR_STATUS2_UMP_RX_PERR (1L<<2) + #define BNX2_MISC_PERR_STATUS2_MCP_ROM_PERR (1L<<3) + #define BNX2_MISC_PERR_STATUS2_MCP_SCPAD_PERR (1L<<4) + #define BNX2_MISC_PERR_STATUS2_HB_MEM_PERR (1L<<5) + #define BNX2_MISC_PERR_STATUS2_PCIE_REPLAY_PERR (1L<<6) + + #define BNX2_MISC_LCPLL_CTRL0 0x00000950 + #define BNX2_MISC_LCPLL_CTRL0_OAC (0x7L<<0) + #define BNX2_MISC_LCPLL_CTRL0_OAC_NEGTWENTY (0L<<0) + #define BNX2_MISC_LCPLL_CTRL0_OAC_ZERO (1L<<0) + #define BNX2_MISC_LCPLL_CTRL0_OAC_TWENTY (3L<<0) + #define BNX2_MISC_LCPLL_CTRL0_OAC_FORTY (7L<<0) + #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL (0x7L<<3) + #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_360 (0L<<3) + #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_480 (1L<<3) + #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_600 (3L<<3) + #define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_720 (7L<<3) + #define BNX2_MISC_LCPLL_CTRL0_BIAS_CTRL (0x3L<<6) + #define BNX2_MISC_LCPLL_CTRL0_PLL_OBSERVE (0x7L<<8) + #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL (0x3L<<11) + #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_0 (0L<<11) + #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_1 (1L<<11) + #define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_2 (2L<<11) + #define BNX2_MISC_LCPLL_CTRL0_PLLSEQSTART (1L<<13) + #define BNX2_MISC_LCPLL_CTRL0_RESERVED (1L<<14) + #define BNX2_MISC_LCPLL_CTRL0_CAPRETRY_EN (1L<<15) + #define BNX2_MISC_LCPLL_CTRL0_FREQMONITOR_EN (1L<<16) + #define BNX2_MISC_LCPLL_CTRL0_FREQDETRESTART_EN (1L<<17) + #define BNX2_MISC_LCPLL_CTRL0_FREQDETRETRY_EN (1L<<18) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE_EN (1L<<19) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE (1L<<20) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFPASS (1L<<21) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE_EN (1L<<22) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE (1L<<23) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS_EN (1L<<24) + #define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS (1L<<25) + #define BNX2_MISC_LCPLL_CTRL0_CAPRESTART (1L<<26) + #define BNX2_MISC_LCPLL_CTRL0_CAPSELECTM_EN (1L<<27) + + #define BNX2_MISC_LCPLL_CTRL1 0x00000954 + #define BNX2_MISC_LCPLL_CTRL1_CAPSELECTM (0x1fL<<0) + #define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN_EN (1L<<5) + #define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN (1L<<6) + #define BNX2_MISC_LCPLL_CTRL1_SLOWDN_XOR (1L<<7) + + #define BNX2_MISC_LCPLL_STATUS 0x00000958 + #define BNX2_MISC_LCPLL_STATUS_FREQDONE_SM (1L<<0) + #define BNX2_MISC_LCPLL_STATUS_FREQPASS_SM (1L<<1) + #define BNX2_MISC_LCPLL_STATUS_PLLSEQDONE (1L<<2) + #define BNX2_MISC_LCPLL_STATUS_PLLSEQPASS (1L<<3) + #define BNX2_MISC_LCPLL_STATUS_PLLSTATE (0x7L<<4) + #define BNX2_MISC_LCPLL_STATUS_CAPSTATE (0x7L<<7) + #define BNX2_MISC_LCPLL_STATUS_CAPSELECT (0x1fL<<10) + #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR (1L<<15) + #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_0 (0L<<15) + #define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_1 (1L<<15) + + #define BNX2_MISC_OSCFUNDS_CTRL 0x0000095c + #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON (1L<<5) + #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_OFF (0L<<5) + #define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_ON (1L<<5) + #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM (0x3L<<6) + #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_0 (0L<<6) + #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_1 (1L<<6) + #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_2 (2L<<6) + #define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_3 (3L<<6) + #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ (0x3L<<8) + #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_0 (0L<<8) + #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_1 (1L<<8) + #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_2 (2L<<8) + #define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_3 (3L<<8) + #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ (0x3L<<10) + #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_0 (0L<<10) + #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_1 (1L<<10) + #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_2 (2L<<10) + #define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_3 (3L<<10) + + + /* + * nvm_reg definition + * offset: 0x6400 + */ + #define BNX2_NVM_COMMAND 0x00006400 + #define BNX2_NVM_COMMAND_RST (1L<<0) + #define BNX2_NVM_COMMAND_DONE (1L<<3) + #define BNX2_NVM_COMMAND_DOIT (1L<<4) + #define BNX2_NVM_COMMAND_WR (1L<<5) + #define BNX2_NVM_COMMAND_ERASE (1L<<6) + #define BNX2_NVM_COMMAND_FIRST (1L<<7) + #define BNX2_NVM_COMMAND_LAST (1L<<8) + #define BNX2_NVM_COMMAND_WREN (1L<<16) + #define BNX2_NVM_COMMAND_WRDI (1L<<17) + #define BNX2_NVM_COMMAND_EWSR (1L<<18) + #define BNX2_NVM_COMMAND_WRSR (1L<<19) + #define BNX2_NVM_COMMAND_RD_ID (1L<<20) + #define BNX2_NVM_COMMAND_RD_STATUS (1L<<21) + #define BNX2_NVM_COMMAND_MODE_256 (1L<<22) + + #define BNX2_NVM_STATUS 0x00006404 + #define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0) + #define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4) + #define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_XI (0x1fL<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_IDLE_XI (0L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD0_XI (1L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD1_XI (2L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH0_XI (3L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH1_XI (4L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ADDR0_XI (5L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA0_XI (6L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA1_XI (7L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA2_XI (8L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA0_XI (9L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA1_XI (10L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA2_XI (11L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID0_XI (12L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID1_XI (13L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID2_XI (14L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID3_XI (15L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID4_XI (16L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CHECK_BUSY0_XI (17L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ST_WREN_XI (18L<<0) + #define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WAIT_XI (19L<<0) + + #define BNX2_NVM_WRITE 0x00006408 + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI_XI (1L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO_XI (2L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B_XI (4L<<0) + #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK_XI (8L<<0) + + #define BNX2_NVM_ADDR 0x0000640c + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI_XI (1L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO_XI (2L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B_XI (4L<<0) + #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK_XI (8L<<0) + + #define BNX2_NVM_READ 0x00006410 + #define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SI_XI (1L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SO_XI (2L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_CS_B_XI (4L<<0) + #define BNX2_NVM_READ_NVM_READ_VALUE_SCLK_XI (8L<<0) + + #define BNX2_NVM_CFG1 0x00006414 + #define BNX2_NVM_CFG1_FLASH_MODE (1L<<0) + #define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1) + #define BNX2_NVM_CFG1_PASS_MODE (1L<<2) + #define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3) + #define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4) + #define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4) + #define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4) + #define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7) + #define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11) + #define BNX2_NVM_CFG1_STRAP_CONTROL_0 (1L<<23) + #define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24) + #define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25) + #define BNX2_NVM_CFG1_FW_USTRAP_1 (1L<<26) + #define BNX2_NVM_CFG1_FW_USTRAP_0 (1L<<27) + #define BNX2_NVM_CFG1_FW_USTRAP_2 (1L<<28) + #define BNX2_NVM_CFG1_FW_USTRAP_3 (1L<<29) + #define BNX2_NVM_CFG1_FW_FLASH_TYPE_EN (1L<<30) + #define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31) + + #define BNX2_NVM_CFG2 0x00006418 + #define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0) + #define BNX2_NVM_CFG2_DUMMY (0xffL<<8) + #define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16) + #define BNX2_NVM_CFG2_READ_ID (0xffL<<24) + + #define BNX2_NVM_CFG3 0x0000641c + #define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0) + #define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8) + #define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16) + #define BNX2_NVM_CFG3_READ_CMD (0xffL<<24) + + #define BNX2_NVM_SW_ARB 0x00006420 + #define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0) + #define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1) + #define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2) + #define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3) + #define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4) + #define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5) + #define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6) + #define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7) + #define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8) + #define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9) + #define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10) + #define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11) + #define BNX2_NVM_SW_ARB_REQ0 (1L<<12) + #define BNX2_NVM_SW_ARB_REQ1 (1L<<13) + #define BNX2_NVM_SW_ARB_REQ2 (1L<<14) + #define BNX2_NVM_SW_ARB_REQ3 (1L<<15) + + #define BNX2_NVM_ACCESS_ENABLE 0x00006424 + #define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0) + #define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1) + + #define BNX2_NVM_WRITE1 0x00006428 + #define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0) + #define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8) + #define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16) + + #define BNX2_NVM_CFG4 0x0000642c + #define BNX2_NVM_CFG4_FLASH_SIZE (0x7L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_1MBIT (0L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_2MBIT (1L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_4MBIT (2L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_8MBIT (3L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_16MBIT (4L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_32MBIT (5L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_64MBIT (6L<<0) + #define BNX2_NVM_CFG4_FLASH_SIZE_128MBIT (7L<<0) + #define BNX2_NVM_CFG4_FLASH_VENDOR (1L<<3) + #define BNX2_NVM_CFG4_FLASH_VENDOR_ST (0L<<3) + #define BNX2_NVM_CFG4_FLASH_VENDOR_ATMEL (1L<<3) + #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC (0x3L<<4) + #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT8 (0L<<4) + #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT9 (1L<<4) + #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT10 (2L<<4) + #define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT11 (3L<<4) + #define BNX2_NVM_CFG4_STATUS_BIT_POLARITY (1L<<6) + #define BNX2_NVM_CFG4_RESERVED (0x1ffffffL<<7) + + #define BNX2_NVM_RECONFIG 0x00006430 + #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE (0xfL<<0) + #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ST (0L<<0) + #define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ATMEL (1L<<0) + #define BNX2_NVM_RECONFIG_RECONFIG_STRAP_VALUE (0xfL<<4) + #define BNX2_NVM_RECONFIG_RESERVED (0x7fffffL<<8) + #define BNX2_NVM_RECONFIG_RECONFIG_DONE (1L<<31) + + + + /* + * dma_reg definition + * offset: 0xc00 + */ + #define BNX2_DMA_COMMAND 0x00000c00 + #define BNX2_DMA_COMMAND_ENABLE (1L<<0) + + #define BNX2_DMA_STATUS 0x00000c04 + #define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0) + #define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16) + #define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17) + #define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18) + #define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19) + #define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20) + #define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21) + #define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22) + #define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23) + #define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24) + #define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25) + #define BNX2_DMA_STATUS_GLOBAL_ERR_XI (1L<<0) + #define BNX2_DMA_STATUS_BME_XI (1L<<4) + + #define BNX2_DMA_CONFIG 0x00000c08 + #define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0) + #define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1) + #define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4) + #define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5) + #define BNX2_DMA_CONFIG_ONE_DMA (1L<<6) + #define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7) + #define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8) + #define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10) + #define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11) + #define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12) + #define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16) + #define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20) + #define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23) + #define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24) + #define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24) + #define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24) + #define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24) + #define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24) + #define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24) + #define BNX2_DMA_CONFIG_DAT_WBSWAP_MODE_XI (0x3L<<0) + #define BNX2_DMA_CONFIG_CTL_WBSWAP_MODE_XI (0x3L<<4) + #define BNX2_DMA_CONFIG_MAX_PL_XI (0x7L<<12) + #define BNX2_DMA_CONFIG_MAX_PL_128B_XI (0L<<12) + #define BNX2_DMA_CONFIG_MAX_PL_256B_XI (1L<<12) + #define BNX2_DMA_CONFIG_MAX_PL_512B_XI (2L<<12) + #define BNX2_DMA_CONFIG_MAX_PL_EN_XI (1L<<15) + #define BNX2_DMA_CONFIG_MAX_RRS_XI (0x7L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_128B_XI (0L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_256B_XI (1L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_512B_XI (2L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_1024B_XI (3L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_2048B_XI (4L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_4096B_XI (5L<<16) + #define BNX2_DMA_CONFIG_MAX_RRS_EN_XI (1L<<19) + #define BNX2_DMA_CONFIG_NO_64SWAP_EN_XI (1L<<31) + + #define BNX2_DMA_BLACKOUT 0x00000c0c + #define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0) + #define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8) + #define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16) + + #define BNX2_DMA_READ_MASTER_SETTING_0 0x00000c10 + #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_NO_SNOOP (1L<<0) + #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_RELAX_ORDER (1L<<1) + #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PRIORITY (1L<<2) + #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_TRAFFIC_CLASS (0x7L<<4) + #define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PARAM_EN (1L<<7) + #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_NO_SNOOP (1L<<8) + #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_RELAX_ORDER (1L<<9) + #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PRIORITY (1L<<10) + #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_TRAFFIC_CLASS (0x7L<<12) + #define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PARAM_EN (1L<<15) + #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_NO_SNOOP (1L<<16) + #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_RELAX_ORDER (1L<<17) + #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PRIORITY (1L<<18) + #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_TRAFFIC_CLASS (0x7L<<20) + #define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PARAM_EN (1L<<23) + #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24) + #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25) + #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PRIORITY (1L<<26) + #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28) + #define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31) + + #define BNX2_DMA_READ_MASTER_SETTING_1 0x00000c14 + #define BNX2_DMA_READ_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0) + #define BNX2_DMA_READ_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1) + #define BNX2_DMA_READ_MASTER_SETTING_1_COM_PRIORITY (1L<<2) + #define BNX2_DMA_READ_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4) + #define BNX2_DMA_READ_MASTER_SETTING_1_COM_PARAM_EN (1L<<7) + #define BNX2_DMA_READ_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8) + #define BNX2_DMA_READ_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9) + #define BNX2_DMA_READ_MASTER_SETTING_1_CP_PRIORITY (1L<<10) + #define BNX2_DMA_READ_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12) + #define BNX2_DMA_READ_MASTER_SETTING_1_CP_PARAM_EN (1L<<15) + + #define BNX2_DMA_WRITE_MASTER_SETTING_0 0x00000c18 + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_NO_SNOOP (1L<<0) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_RELAX_ORDER (1L<<1) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PRIORITY (1L<<2) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_CS_VLD (1L<<3) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_TRAFFIC_CLASS (0x7L<<4) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PARAM_EN (1L<<7) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_NO_SNOOP (1L<<8) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_RELAX_ORDER (1L<<9) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PRIORITY (1L<<10) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_CS_VLD (1L<<11) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_TRAFFIC_CLASS (0x7L<<12) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PARAM_EN (1L<<15) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PRIORITY (1L<<26) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_CS_VLD (1L<<27) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28) + #define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31) + + #define BNX2_DMA_WRITE_MASTER_SETTING_1 0x00000c1c + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PRIORITY (1L<<2) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_CS_VLD (1L<<3) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PARAM_EN (1L<<7) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PRIORITY (1L<<10) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_CS_VLD (1L<<11) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12) + #define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PARAM_EN (1L<<15) + + #define BNX2_DMA_ARBITER 0x00000c20 + #define BNX2_DMA_ARBITER_NUM_READS (0x7L<<0) + #define BNX2_DMA_ARBITER_WR_ARB_MODE (1L<<4) + #define BNX2_DMA_ARBITER_WR_ARB_MODE_STRICT (0L<<4) + #define BNX2_DMA_ARBITER_WR_ARB_MODE_RND_RBN (1L<<4) + #define BNX2_DMA_ARBITER_RD_ARB_MODE (0x3L<<5) + #define BNX2_DMA_ARBITER_RD_ARB_MODE_STRICT (0L<<5) + #define BNX2_DMA_ARBITER_RD_ARB_MODE_RND_RBN (1L<<5) + #define BNX2_DMA_ARBITER_RD_ARB_MODE_WGT_RND_RBN (2L<<5) + #define BNX2_DMA_ARBITER_ALT_MODE_EN (1L<<8) + #define BNX2_DMA_ARBITER_RR_MODE (1L<<9) + #define BNX2_DMA_ARBITER_TIMER_MODE (1L<<10) + #define BNX2_DMA_ARBITER_OUSTD_READ_REQ (0xfL<<12) + + #define BNX2_DMA_ARB_TIMERS 0x00000c24 + #define BNX2_DMA_ARB_TIMERS_RD_DRR_WAIT_TIME (0xffL<<0) + #define BNX2_DMA_ARB_TIMERS_TM_MIN_TIMEOUT (0xffL<<12) + #define BNX2_DMA_ARB_TIMERS_TM_MAX_TIMEOUT (0xfffL<<20) + + #define BNX2_DMA_DEBUG_VECT_PEEK 0x00000c2c + #define BNX2_DMA_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_DMA_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_DMA_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_DMA_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_DMA_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_DMA_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_DMA_TAG_RAM_00 0x00000c30 + #define BNX2_DMA_TAG_RAM_00_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_00_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_00_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_00_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_00_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_00_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_00_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_00_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_00_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_01 0x00000c34 + #define BNX2_DMA_TAG_RAM_01_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_01_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_01_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_01_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_01_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_01_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_01_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_01_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_01_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_02 0x00000c38 + #define BNX2_DMA_TAG_RAM_02_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_02_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_02_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_02_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_02_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_02_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_02_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_02_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_02_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_03 0x00000c3c + #define BNX2_DMA_TAG_RAM_03_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_03_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_03_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_03_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_03_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_03_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_03_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_03_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_03_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_04 0x00000c40 + #define BNX2_DMA_TAG_RAM_04_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_04_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_04_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_04_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_04_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_04_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_04_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_04_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_04_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_05 0x00000c44 + #define BNX2_DMA_TAG_RAM_05_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_05_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_05_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_05_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_05_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_05_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_05_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_05_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_05_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_06 0x00000c48 + #define BNX2_DMA_TAG_RAM_06_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_06_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_06_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_06_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_06_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_06_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_06_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_06_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_06_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_07 0x00000c4c + #define BNX2_DMA_TAG_RAM_07_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_07_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_07_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_07_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_07_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_07_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_07_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_07_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_07_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_08 0x00000c50 + #define BNX2_DMA_TAG_RAM_08_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_08_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_08_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_08_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_08_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_08_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_08_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_08_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_08_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_09 0x00000c54 + #define BNX2_DMA_TAG_RAM_09_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_09_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_09_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_09_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_09_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_09_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_09_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_09_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_09_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_10 0x00000c58 + #define BNX2_DMA_TAG_RAM_10_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_10_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_10_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_10_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_10_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_10_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_10_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_10_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_10_VALID (1L<<10) + + #define BNX2_DMA_TAG_RAM_11 0x00000c5c + #define BNX2_DMA_TAG_RAM_11_CHANNEL (0xfL<<0) + #define BNX2_DMA_TAG_RAM_11_MASTER (0x7L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_CTX (0L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_RBDC (1L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_TBDC (2L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_COM (3L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_CP (4L<<4) + #define BNX2_DMA_TAG_RAM_11_MASTER_TDMA (5L<<4) + #define BNX2_DMA_TAG_RAM_11_SWAP (0x3L<<7) + #define BNX2_DMA_TAG_RAM_11_SWAP_CONFIG (0L<<7) + #define BNX2_DMA_TAG_RAM_11_SWAP_DATA (1L<<7) + #define BNX2_DMA_TAG_RAM_11_SWAP_CONTROL (2L<<7) + #define BNX2_DMA_TAG_RAM_11_FUNCTION (1L<<9) + #define BNX2_DMA_TAG_RAM_11_VALID (1L<<10) + + #define BNX2_DMA_RCHAN_STAT_22 0x00000c60 + #define BNX2_DMA_RCHAN_STAT_30 0x00000c64 + #define BNX2_DMA_RCHAN_STAT_31 0x00000c68 + #define BNX2_DMA_RCHAN_STAT_32 0x00000c6c + #define BNX2_DMA_RCHAN_STAT_40 0x00000c70 + #define BNX2_DMA_RCHAN_STAT_41 0x00000c74 + #define BNX2_DMA_RCHAN_STAT_42 0x00000c78 + #define BNX2_DMA_RCHAN_STAT_50 0x00000c7c + #define BNX2_DMA_RCHAN_STAT_51 0x00000c80 + #define BNX2_DMA_RCHAN_STAT_52 0x00000c84 + #define BNX2_DMA_RCHAN_STAT_60 0x00000c88 + #define BNX2_DMA_RCHAN_STAT_61 0x00000c8c + #define BNX2_DMA_RCHAN_STAT_62 0x00000c90 + #define BNX2_DMA_RCHAN_STAT_70 0x00000c94 + #define BNX2_DMA_RCHAN_STAT_71 0x00000c98 + #define BNX2_DMA_RCHAN_STAT_72 0x00000c9c + #define BNX2_DMA_WCHAN_STAT_00 0x00000ca0 + #define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0) + + #define BNX2_DMA_WCHAN_STAT_01 0x00000ca4 + #define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0) + + #define BNX2_DMA_WCHAN_STAT_02 0x00000ca8 + #define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0) + #define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16) + #define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17) + #define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18) + + #define BNX2_DMA_WCHAN_STAT_10 0x00000cac + #define BNX2_DMA_WCHAN_STAT_11 0x00000cb0 + #define BNX2_DMA_WCHAN_STAT_12 0x00000cb4 + #define BNX2_DMA_WCHAN_STAT_20 0x00000cb8 + #define BNX2_DMA_WCHAN_STAT_21 0x00000cbc + #define BNX2_DMA_WCHAN_STAT_22 0x00000cc0 + #define BNX2_DMA_WCHAN_STAT_30 0x00000cc4 + #define BNX2_DMA_WCHAN_STAT_31 0x00000cc8 + #define BNX2_DMA_WCHAN_STAT_32 0x00000ccc + #define BNX2_DMA_WCHAN_STAT_40 0x00000cd0 + #define BNX2_DMA_WCHAN_STAT_41 0x00000cd4 + #define BNX2_DMA_WCHAN_STAT_42 0x00000cd8 + #define BNX2_DMA_WCHAN_STAT_50 0x00000cdc + #define BNX2_DMA_WCHAN_STAT_51 0x00000ce0 + #define BNX2_DMA_WCHAN_STAT_52 0x00000ce4 + #define BNX2_DMA_WCHAN_STAT_60 0x00000ce8 + #define BNX2_DMA_WCHAN_STAT_61 0x00000cec + #define BNX2_DMA_WCHAN_STAT_62 0x00000cf0 + #define BNX2_DMA_WCHAN_STAT_70 0x00000cf4 + #define BNX2_DMA_WCHAN_STAT_71 0x00000cf8 + #define BNX2_DMA_WCHAN_STAT_72 0x00000cfc + #define BNX2_DMA_ARB_STAT_00 0x00000d00 + #define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0) + #define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16) + #define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24) + + #define BNX2_DMA_ARB_STAT_01 0x00000d04 + #define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0) + #define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4) + #define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8) + #define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12) + #define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16) + #define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20) + #define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24) + #define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28) + + #define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00 + #define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0) + #define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1) + #define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2) + #define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3) + #define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8) + + #define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04 + #define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08 + #define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0) + #define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1) + #define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2) + #define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3) + #define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8) + + #define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c + #define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10 + #define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0) + #define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1) + #define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2) + #define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3) + #define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8) + + #define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14 + + + /* + * context_reg definition + * offset: 0x1000 + */ + #define BNX2_CTX_COMMAND 0x00001000 + #define BNX2_CTX_COMMAND_ENABLED (1L<<0) + #define BNX2_CTX_COMMAND_DISABLE_USAGE_CNT (1L<<1) + #define BNX2_CTX_COMMAND_DISABLE_PLRU (1L<<2) + #define BNX2_CTX_COMMAND_DISABLE_COMBINE_READ (1L<<3) + #define BNX2_CTX_COMMAND_FLUSH_AHEAD (0x1fL<<8) + #define BNX2_CTX_COMMAND_MEM_INIT (1L<<13) + #define BNX2_CTX_COMMAND_PAGE_SIZE (0xfL<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_256 (0L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_512 (1L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_1K (2L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_2K (3L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_4K (4L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_8K (5L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_16K (6L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_32K (7L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_64K (8L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_128K (9L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_256K (10L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_512K (11L<<16) + #define BNX2_CTX_COMMAND_PAGE_SIZE_1M (12L<<16) + + #define BNX2_CTX_STATUS 0x00001004 + #define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0) + #define BNX2_CTX_STATUS_READ_STAT (1L<<16) + #define BNX2_CTX_STATUS_WRITE_STAT (1L<<17) + #define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18) + #define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19) + #define BNX2_CTX_STATUS_EXT_READ_STAT (1L<<20) + #define BNX2_CTX_STATUS_EXT_WRITE_STAT (1L<<21) + #define BNX2_CTX_STATUS_MISS_STAT (1L<<22) + #define BNX2_CTX_STATUS_HIT_STAT (1L<<23) + #define BNX2_CTX_STATUS_DEAD_LOCK (1L<<24) + #define BNX2_CTX_STATUS_USAGE_CNT_ERR (1L<<25) + #define BNX2_CTX_STATUS_INVALID_PAGE (1L<<26) + + #define BNX2_CTX_VIRT_ADDR 0x00001008 + #define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6) + + #define BNX2_CTX_PAGE_TBL 0x0000100c + #define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6) + + #define BNX2_CTX_DATA_ADR 0x00001010 + #define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2) + + #define BNX2_CTX_DATA 0x00001014 + #define BNX2_CTX_LOCK 0x00001018 + #define BNX2_CTX_LOCK_TYPE (0x7L<<0) + #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0) + #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0) + #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0) + #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0) + #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0) + #define BNX2_CTX_LOCK_TYPE_VOID_XI (0L<<0) + #define BNX2_CTX_LOCK_TYPE_PROTOCOL_XI (1L<<0) + #define BNX2_CTX_LOCK_TYPE_TX_XI (2L<<0) + #define BNX2_CTX_LOCK_TYPE_TIMER_XI (4L<<0) + #define BNX2_CTX_LOCK_TYPE_COMPLETE_XI (7L<<0) + #define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7) + #define BNX2_CTX_LOCK_GRANTED (1L<<26) + #define BNX2_CTX_LOCK_MODE (0x7L<<27) + #define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27) + #define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27) + #define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27) + #define BNX2_CTX_LOCK_STATUS (1L<<30) + #define BNX2_CTX_LOCK_REQ (1L<<31) + + #define BNX2_CTX_CTX_CTRL 0x0000101c + #define BNX2_CTX_CTX_CTRL_CTX_ADDR (0x7ffffL<<2) + #define BNX2_CTX_CTX_CTRL_MOD_USAGE_CNT (0x3L<<21) + #define BNX2_CTX_CTX_CTRL_NO_RAM_ACC (1L<<23) + #define BNX2_CTX_CTX_CTRL_PREFETCH_SIZE (0x3L<<24) + #define BNX2_CTX_CTX_CTRL_ATTR (1L<<26) + #define BNX2_CTX_CTX_CTRL_WRITE_REQ (1L<<30) + #define BNX2_CTX_CTX_CTRL_READ_REQ (1L<<31) + + #define BNX2_CTX_CTX_DATA 0x00001020 + #define BNX2_CTX_ACCESS_STATUS 0x00001040 + #define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0) + #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10) + #define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12) + #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14) + #define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17) + #define BNX2_CTX_ACCESS_STATUS_CAMMASTERENCODED_XI (0x1fL<<0) + #define BNX2_CTX_ACCESS_STATUS_CACHEMASTERENCODED_XI (0x1fL<<5) + #define BNX2_CTX_ACCESS_STATUS_REQUEST_XI (0x3fffffL<<10) + + #define BNX2_CTX_DBG_LOCK_STATUS 0x00001044 + #define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0) + #define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22) + + #define BNX2_CTX_CACHE_CTRL_STATUS 0x00001048 + #define BNX2_CTX_CACHE_CTRL_STATUS_RFIFO_OVERFLOW (1L<<0) + #define BNX2_CTX_CACHE_CTRL_STATUS_INVALID_READ_COMP (1L<<1) + #define BNX2_CTX_CACHE_CTRL_STATUS_FLUSH_START (1L<<6) + #define BNX2_CTX_CACHE_CTRL_STATUS_FREE_ENTRY_CNT (0x3fL<<7) + #define BNX2_CTX_CACHE_CTRL_STATUS_CACHE_ENTRY_NEEDED (0x3fL<<13) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN0_ACTIVE (1L<<19) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN1_ACTIVE (1L<<20) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN2_ACTIVE (1L<<21) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN3_ACTIVE (1L<<22) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN4_ACTIVE (1L<<23) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN5_ACTIVE (1L<<24) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN6_ACTIVE (1L<<25) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN7_ACTIVE (1L<<26) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN8_ACTIVE (1L<<27) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN9_ACTIVE (1L<<28) + #define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN10_ACTIVE (1L<<29) + + #define BNX2_CTX_CACHE_CTRL_SM_STATUS 0x0000104c + #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_DWC (0x7L<<0) + #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_WFIFOC (0x7L<<3) + #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RTAGC (0x7L<<6) + #define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RFIFOC (0x7L<<9) + #define BNX2_CTX_CACHE_CTRL_SM_STATUS_INVALID_BLK_ADDR (0x7fffL<<16) + + #define BNX2_CTX_CACHE_STATUS 0x00001050 + #define BNX2_CTX_CACHE_STATUS_HELD_ENTRIES (0x3ffL<<0) + #define BNX2_CTX_CACHE_STATUS_MAX_HELD_ENTRIES (0x3ffL<<16) + + #define BNX2_CTX_DMA_STATUS 0x00001054 + #define BNX2_CTX_DMA_STATUS_RD_CHAN0_STATUS (0x3L<<0) + #define BNX2_CTX_DMA_STATUS_RD_CHAN1_STATUS (0x3L<<2) + #define BNX2_CTX_DMA_STATUS_RD_CHAN2_STATUS (0x3L<<4) + #define BNX2_CTX_DMA_STATUS_RD_CHAN3_STATUS (0x3L<<6) + #define BNX2_CTX_DMA_STATUS_RD_CHAN4_STATUS (0x3L<<8) + #define BNX2_CTX_DMA_STATUS_RD_CHAN5_STATUS (0x3L<<10) + #define BNX2_CTX_DMA_STATUS_RD_CHAN6_STATUS (0x3L<<12) + #define BNX2_CTX_DMA_STATUS_RD_CHAN7_STATUS (0x3L<<14) + #define BNX2_CTX_DMA_STATUS_RD_CHAN8_STATUS (0x3L<<16) + #define BNX2_CTX_DMA_STATUS_RD_CHAN9_STATUS (0x3L<<18) + #define BNX2_CTX_DMA_STATUS_RD_CHAN10_STATUS (0x3L<<20) + + #define BNX2_CTX_REP_STATUS 0x00001058 + #define BNX2_CTX_REP_STATUS_ERROR_ENTRY (0x3ffL<<0) + #define BNX2_CTX_REP_STATUS_ERROR_CLIENT_ID (0x1fL<<10) + #define BNX2_CTX_REP_STATUS_USAGE_CNT_MAX_ERR (1L<<16) + #define BNX2_CTX_REP_STATUS_USAGE_CNT_MIN_ERR (1L<<17) + #define BNX2_CTX_REP_STATUS_USAGE_CNT_MISS_ERR (1L<<18) + + #define BNX2_CTX_CKSUM_ERROR_STATUS 0x0000105c + #define BNX2_CTX_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) + #define BNX2_CTX_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + + #define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080 + #define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0) + #define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14) + #define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16) + #define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE_XI (1L<<14) + #define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE_XI (0x7L<<15) + + #define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084 + #define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088 + #define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c + #define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090 + #define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094 + #define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098 + #define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c + #define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0 + #define BNX2_CTX_CHNL_LOCK_STATUS_9 0x000010a4 + + #define BNX2_CTX_CACHE_DATA 0x000010c4 + #define BNX2_CTX_HOST_PAGE_TBL_CTRL 0x000010c8 + #define BNX2_CTX_HOST_PAGE_TBL_CTRL_PAGE_TBL_ADDR (0x1ffL<<0) + #define BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ (1L<<30) + #define BNX2_CTX_HOST_PAGE_TBL_CTRL_READ_REQ (1L<<31) + + #define BNX2_CTX_HOST_PAGE_TBL_DATA0 0x000010cc + #define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID (1L<<0) + #define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALUE (0xffffffL<<8) + + #define BNX2_CTX_HOST_PAGE_TBL_DATA1 0x000010d0 + #define BNX2_CTX_CAM_CTRL 0x000010d4 + #define BNX2_CTX_CAM_CTRL_CAM_ADDR (0x3ffL<<0) + #define BNX2_CTX_CAM_CTRL_RESET (1L<<27) + #define BNX2_CTX_CAM_CTRL_INVALIDATE (1L<<28) + #define BNX2_CTX_CAM_CTRL_SEARCH (1L<<29) + #define BNX2_CTX_CAM_CTRL_WRITE_REQ (1L<<30) + #define BNX2_CTX_CAM_CTRL_READ_REQ (1L<<31) + + + /* + * emac_reg definition + * offset: 0x1400 + */ + #define BNX2_EMAC_MODE 0x00001400 + #define BNX2_EMAC_MODE_RESET (1L<<0) + #define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1) + #define BNX2_EMAC_MODE_PORT (0x3L<<2) + #define BNX2_EMAC_MODE_PORT_NONE (0L<<2) + #define BNX2_EMAC_MODE_PORT_MII (1L<<2) + #define BNX2_EMAC_MODE_PORT_GMII (2L<<2) + #define BNX2_EMAC_MODE_PORT_MII_10M (3L<<2) + #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) + #define BNX2_EMAC_MODE_25G_MODE (1L<<5) + #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) + #define BNX2_EMAC_MODE_TX_BURST (1L<<8) + #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) + #define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10) + #define BNX2_EMAC_MODE_FORCE_LINK (1L<<11) + #define BNX2_EMAC_MODE_SERDES_MODE (1L<<12) + #define BNX2_EMAC_MODE_BOND_OVRD (1L<<13) + #define BNX2_EMAC_MODE_MPKT (1L<<18) + #define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19) + #define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20) + + #define BNX2_EMAC_STATUS 0x00001404 + #define BNX2_EMAC_STATUS_LINK (1L<<11) + #define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12) + #define BNX2_EMAC_STATUS_SERDES_AUTONEG_COMPLETE (1L<<13) + #define BNX2_EMAC_STATUS_SERDES_AUTONEG_CHANGE (1L<<14) + #define BNX2_EMAC_STATUS_SERDES_NXT_PG_CHANGE (1L<<16) + #define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0 (1L<<17) + #define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18) + #define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22) + #define BNX2_EMAC_STATUS_MI_INT (1L<<23) + #define BNX2_EMAC_STATUS_AP_ERROR (1L<<24) + #define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31) + + #define BNX2_EMAC_ATTENTION_ENA 0x00001408 + #define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11) + #define BNX2_EMAC_ATTENTION_ENA_AUTONEG_CHANGE (1L<<14) + #define BNX2_EMAC_ATTENTION_ENA_NXT_PG_CHANGE (1L<<16) + #define BNX2_EMAC_ATTENTION_ENA_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18) + #define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22) + #define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23) + #define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24) + + #define BNX2_EMAC_LED 0x0000140c + #define BNX2_EMAC_LED_OVERRIDE (1L<<0) + #define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1) + #define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2) + #define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3) + #define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4) + #define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5) + #define BNX2_EMAC_LED_TRAFFIC (1L<<6) + #define BNX2_EMAC_LED_1000MB (1L<<7) + #define BNX2_EMAC_LED_100MB (1L<<8) + #define BNX2_EMAC_LED_10MB (1L<<9) + #define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10) + #define BNX2_EMAC_LED_2500MB (1L<<11) + #define BNX2_EMAC_LED_2500MB_OVERRIDE (1L<<12) + #define BNX2_EMAC_LED_ACTIVITY_SEL (0x3L<<17) + #define BNX2_EMAC_LED_ACTIVITY_SEL_0 (0L<<17) + #define BNX2_EMAC_LED_ACTIVITY_SEL_1 (1L<<17) + #define BNX2_EMAC_LED_ACTIVITY_SEL_2 (2L<<17) + #define BNX2_EMAC_LED_ACTIVITY_SEL_3 (3L<<17) + #define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19) + #define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31) + + #define BNX2_EMAC_MAC_MATCH0 0x00001410 + #define BNX2_EMAC_MAC_MATCH1 0x00001414 + #define BNX2_EMAC_MAC_MATCH2 0x00001418 + #define BNX2_EMAC_MAC_MATCH3 0x0000141c + #define BNX2_EMAC_MAC_MATCH4 0x00001420 + #define BNX2_EMAC_MAC_MATCH5 0x00001424 + #define BNX2_EMAC_MAC_MATCH6 0x00001428 + #define BNX2_EMAC_MAC_MATCH7 0x0000142c + #define BNX2_EMAC_MAC_MATCH8 0x00001430 + #define BNX2_EMAC_MAC_MATCH9 0x00001434 + #define BNX2_EMAC_MAC_MATCH10 0x00001438 + #define BNX2_EMAC_MAC_MATCH11 0x0000143c + #define BNX2_EMAC_MAC_MATCH12 0x00001440 + #define BNX2_EMAC_MAC_MATCH13 0x00001444 + #define BNX2_EMAC_MAC_MATCH14 0x00001448 + #define BNX2_EMAC_MAC_MATCH15 0x0000144c + #define BNX2_EMAC_MAC_MATCH16 0x00001450 + #define BNX2_EMAC_MAC_MATCH17 0x00001454 + #define BNX2_EMAC_MAC_MATCH18 0x00001458 + #define BNX2_EMAC_MAC_MATCH19 0x0000145c + #define BNX2_EMAC_MAC_MATCH20 0x00001460 + #define BNX2_EMAC_MAC_MATCH21 0x00001464 + #define BNX2_EMAC_MAC_MATCH22 0x00001468 + #define BNX2_EMAC_MAC_MATCH23 0x0000146c + #define BNX2_EMAC_MAC_MATCH24 0x00001470 + #define BNX2_EMAC_MAC_MATCH25 0x00001474 + #define BNX2_EMAC_MAC_MATCH26 0x00001478 + #define BNX2_EMAC_MAC_MATCH27 0x0000147c + #define BNX2_EMAC_MAC_MATCH28 0x00001480 + #define BNX2_EMAC_MAC_MATCH29 0x00001484 + #define BNX2_EMAC_MAC_MATCH30 0x00001488 + #define BNX2_EMAC_MAC_MATCH31 0x0000148c + #define BNX2_EMAC_BACKOFF_SEED 0x00001498 + #define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0) + + #define BNX2_EMAC_RX_MTU_SIZE 0x0000149c + #define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0) + #define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) + + #define BNX2_EMAC_SERDES_CNTL 0x000014a4 + #define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0) + #define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3) + #define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6) + #define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7) + #define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10) + #define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11) + #define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12) + #define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13) + #define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14) + #define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15) + #define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16) + #define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17) + #define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18) + #define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19) + #define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20) + #define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22) + + #define BNX2_EMAC_SERDES_STATUS 0x000014a8 + #define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0) + #define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8) + + #define BNX2_EMAC_MDIO_COMM 0x000014ac + #define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0) + #define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16) + #define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21) + #define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_22_XI (1L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_45_XI (1L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_22_XI (2L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_INC_45_XI (2L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26) + #define BNX2_EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26) + #define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28) + #define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29) + #define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30) + + #define BNX2_EMAC_MDIO_STATUS 0x000014b0 + #define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0) + #define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1) + + #define BNX2_EMAC_MDIO_MODE 0x000014b4 + #define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1) + #define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4) + #define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8) + #define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9) + #define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10) + #define BNX2_EMAC_MDIO_MODE_MDC (1L<<11) + #define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12) + #define BNX2_EMAC_MDIO_MODE_EXT_MDINT (1L<<13) + #define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16) + #define BNX2_EMAC_MDIO_MODE_CLOCK_CNT_XI (0x3fL<<16) + #define BNX2_EMAC_MDIO_MODE_CLAUSE_45_XI (1L<<31) + + #define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8 + #define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0) + + #define BNX2_EMAC_TX_MODE 0x000014bc + #define BNX2_EMAC_TX_MODE_RESET (1L<<0) + #define BNX2_EMAC_TX_MODE_CS16_TEST (1L<<2) + #define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) + #define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4) + #define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5) + #define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6) + #define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7) + + #define BNX2_EMAC_TX_STATUS 0x000014c0 + #define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0) + #define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1) + #define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2) + #define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3) + #define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4) + #define BNX2_EMAC_TX_STATUS_CS16_ERROR (1L<<5) + + #define BNX2_EMAC_TX_LENGTHS 0x000014c4 + #define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0) + #define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8) + #define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12) + + #define BNX2_EMAC_RX_MODE 0x000014c8 + #define BNX2_EMAC_RX_MODE_RESET (1L<<0) + #define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2) + #define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3) + #define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4) + #define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5) + #define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6) + #define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7) + #define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8) + #define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9) + #define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10) + #define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11) + #define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12) + + #define BNX2_EMAC_RX_STATUS 0x000014cc + #define BNX2_EMAC_RX_STATUS_FFED (1L<<0) + #define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1) + #define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2) + + #define BNX2_EMAC_MULTICAST_HASH0 0x000014d0 + #define BNX2_EMAC_MULTICAST_HASH1 0x000014d4 + #define BNX2_EMAC_MULTICAST_HASH2 0x000014d8 + #define BNX2_EMAC_MULTICAST_HASH3 0x000014dc + #define BNX2_EMAC_MULTICAST_HASH4 0x000014e0 + #define BNX2_EMAC_MULTICAST_HASH5 0x000014e4 + #define BNX2_EMAC_MULTICAST_HASH6 0x000014e8 + #define BNX2_EMAC_MULTICAST_HASH7 0x000014ec + #define BNX2_EMAC_CKSUM_ERROR_STATUS 0x000014f0 + #define BNX2_EMAC_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) + #define BNX2_EMAC_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + + #define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500 + #define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504 + #define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508 + #define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c + #define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510 + #define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514 + #define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518 + #define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c + #define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520 + #define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524 + #define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528 + #define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c + #define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530 + #define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534 + #define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538 + #define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540 + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544 + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548 + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550 + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554 + #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001558 + #define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c + #define BNX2_EMAC_RXMAC_DEBUG1 0x00001560 + #define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0) + #define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1) + #define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2) + #define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3) + #define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4) + #define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5) + #define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6) + #define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7) + #define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23) + + #define BNX2_EMAC_RXMAC_DEBUG2 0x00001564 + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3) + #define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7) + #define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15) + #define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16) + #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18) + #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18) + #define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18) + #define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19) + #define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23) + + #define BNX2_EMAC_RXMAC_DEBUG3 0x00001568 + #define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0) + #define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16) + + #define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c + #define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16) + #define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22) + #define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23) + #define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24) + #define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25) + #define BNX2_EMAC_RXMAC_DEBUG4_SFD_FOUND (1L<<26) + #define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27) + #define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28) + + #define BNX2_EMAC_RXMAC_DEBUG5 0x00001570 + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4) + #define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7) + #define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8) + #define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11) + #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12) + #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13) + #define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14) + #define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15) + #define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16) + #define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19) + #define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20) + + #define BNX2_EMAC_RX_STAT_FALSECARRIERERRORS 0x00001574 + #define BNX2_EMAC_RX_STAT_AC0 0x00001580 + #define BNX2_EMAC_RX_STAT_AC1 0x00001584 + #define BNX2_EMAC_RX_STAT_AC2 0x00001588 + #define BNX2_EMAC_RX_STAT_AC3 0x0000158c + #define BNX2_EMAC_RX_STAT_AC4 0x00001590 + #define BNX2_EMAC_RX_STAT_AC5 0x00001594 + #define BNX2_EMAC_RX_STAT_AC6 0x00001598 + #define BNX2_EMAC_RX_STAT_AC7 0x0000159c + #define BNX2_EMAC_RX_STAT_AC8 0x000015a0 + #define BNX2_EMAC_RX_STAT_AC9 0x000015a4 + #define BNX2_EMAC_RX_STAT_AC10 0x000015a8 + #define BNX2_EMAC_RX_STAT_AC11 0x000015ac + #define BNX2_EMAC_RX_STAT_AC12 0x000015b0 + #define BNX2_EMAC_RX_STAT_AC13 0x000015b4 + #define BNX2_EMAC_RX_STAT_AC14 0x000015b8 + #define BNX2_EMAC_RX_STAT_AC15 0x000015bc + #define BNX2_EMAC_RX_STAT_AC16 0x000015c0 + #define BNX2_EMAC_RX_STAT_AC17 0x000015c4 + #define BNX2_EMAC_RX_STAT_AC18 0x000015c8 + #define BNX2_EMAC_RX_STAT_AC19 0x000015cc + #define BNX2_EMAC_RX_STAT_AC20 0x000015d0 + #define BNX2_EMAC_RX_STAT_AC21 0x000015d4 + #define BNX2_EMAC_RX_STAT_AC22 0x000015d8 + #define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc + #define BNX2_EMAC_RX_STAT_AC_28 0x000015f4 + #define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600 + #define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604 + #define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608 + #define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c + #define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610 + #define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614 + #define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618 + #define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c + #define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620 + #define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624 + #define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628 + #define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c + #define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630 + #define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634 + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638 + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640 + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644 + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648 + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c + #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001650 + #define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654 + #define BNX2_EMAC_TXMAC_DEBUG0 0x00001658 + #define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0) + #define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4) + #define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5) + #define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6) + #define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10) + #define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11) + #define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12) + #define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13) + #define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14) + #define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15) + #define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19) + + #define BNX2_EMAC_TXMAC_DEBUG2 0x00001660 + #define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0) + #define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10) + #define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26) + #define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31) + + #define BNX2_EMAC_TXMAC_DEBUG3 0x00001664 + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4) + #define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7) + #define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8) + #define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9) + #define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13) + + #define BNX2_EMAC_TXMAC_DEBUG4 0x00001668 + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16) + #define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20) + #define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21) + #define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22) + #define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23) + #define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24) + #define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25) + #define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26) + #define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27) + #define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28) + #define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29) + #define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30) + #define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31) + + #define BNX2_EMAC_TX_STAT_AC0 0x00001680 + #define BNX2_EMAC_TX_STAT_AC1 0x00001684 + #define BNX2_EMAC_TX_STAT_AC2 0x00001688 + #define BNX2_EMAC_TX_STAT_AC3 0x0000168c + #define BNX2_EMAC_TX_STAT_AC4 0x00001690 + #define BNX2_EMAC_TX_STAT_AC5 0x00001694 + #define BNX2_EMAC_TX_STAT_AC6 0x00001698 + #define BNX2_EMAC_TX_STAT_AC7 0x0000169c + #define BNX2_EMAC_TX_STAT_AC8 0x000016a0 + #define BNX2_EMAC_TX_STAT_AC9 0x000016a4 + #define BNX2_EMAC_TX_STAT_AC10 0x000016a8 + #define BNX2_EMAC_TX_STAT_AC11 0x000016ac + #define BNX2_EMAC_TX_STAT_AC12 0x000016b0 + #define BNX2_EMAC_TX_STAT_AC13 0x000016b4 + #define BNX2_EMAC_TX_STAT_AC14 0x000016b8 + #define BNX2_EMAC_TX_STAT_AC15 0x000016bc + #define BNX2_EMAC_TX_STAT_AC16 0x000016c0 + #define BNX2_EMAC_TX_STAT_AC17 0x000016c4 + #define BNX2_EMAC_TX_STAT_AC18 0x000016c8 + #define BNX2_EMAC_TX_STAT_AC19 0x000016cc + #define BNX2_EMAC_TX_STAT_AC20 0x000016d0 + #define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8 + #define BNX2_EMAC_TX_RATE_LIMIT_CTRL 0x000016fc + #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_INC (0x7fL<<0) + #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_NUM (0x7fL<<16) + #define BNX2_EMAC_TX_RATE_LIMIT_CTRL_RATE_LIMITER_EN (1L<<31) + + + /* + * rpm_reg definition + * offset: 0x1800 + */ + #define BNX2_RPM_COMMAND 0x00001800 + #define BNX2_RPM_COMMAND_ENABLED (1L<<0) + #define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4) + + #define BNX2_RPM_STATUS 0x00001804 + #define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0) + #define BNX2_RPM_STATUS_FREE_WAIT (1L<<1) + + #define BNX2_RPM_CONFIG 0x00001808 + #define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0) + #define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1) + #define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2) + #define BNX2_RPM_CONFIG_MP_KEEP (1L<<3) + #define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4) + #define BNX2_RPM_CONFIG_DISABLE_WOL_ASSERT (1L<<30) + #define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31) + + #define BNX2_RPM_MGMT_PKT_CTRL 0x0000180c + #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_SORT (0xfL<<0) + #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_RULE (0xfL<<4) + #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_DISCARD_EN (1L<<30) + #define BNX2_RPM_MGMT_PKT_CTRL_MGMT_EN (1L<<31) + + #define BNX2_RPM_VLAN_MATCH0 0x00001810 + #define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0) + + #define BNX2_RPM_VLAN_MATCH1 0x00001814 + #define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0) + + #define BNX2_RPM_VLAN_MATCH2 0x00001818 + #define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0) + + #define BNX2_RPM_VLAN_MATCH3 0x0000181c + #define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0) + + #define BNX2_RPM_SORT_USER0 0x00001820 + #define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0) + #define BNX2_RPM_SORT_USER0_BC_EN (1L<<16) + #define BNX2_RPM_SORT_USER0_MC_EN (1L<<17) + #define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18) + #define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19) + #define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20) + #define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24) + #define BNX2_RPM_SORT_USER0_VLAN_NOTMATCH (1L<<25) + #define BNX2_RPM_SORT_USER0_ENA (1L<<31) + + #define BNX2_RPM_SORT_USER1 0x00001824 + #define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0) + #define BNX2_RPM_SORT_USER1_BC_EN (1L<<16) + #define BNX2_RPM_SORT_USER1_MC_EN (1L<<17) + #define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18) + #define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19) + #define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20) + #define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24) + #define BNX2_RPM_SORT_USER1_ENA (1L<<31) + + #define BNX2_RPM_SORT_USER2 0x00001828 + #define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0) + #define BNX2_RPM_SORT_USER2_BC_EN (1L<<16) + #define BNX2_RPM_SORT_USER2_MC_EN (1L<<17) + #define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18) + #define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19) + #define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20) + #define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24) + #define BNX2_RPM_SORT_USER2_ENA (1L<<31) + + #define BNX2_RPM_SORT_USER3 0x0000182c + #define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0) + #define BNX2_RPM_SORT_USER3_BC_EN (1L<<16) + #define BNX2_RPM_SORT_USER3_MC_EN (1L<<17) + #define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18) + #define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19) + #define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20) + #define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24) + #define BNX2_RPM_SORT_USER3_ENA (1L<<31) + + #define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840 + #define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844 + #define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848 + #define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c + #define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0 0x00001854 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1 0x00001858 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2 0x0000185c + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3 0x00001860 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4 0x00001864 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5 0x00001868 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6 0x0000186c + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7 0x00001870 + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN (0xffL<<0) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER (0xffL<<16) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN_TYPE (1L<<30) + #define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_EN (1L<<31) + + #define BNX2_RPM_STAT_AC0 0x00001880 + #define BNX2_RPM_STAT_AC1 0x00001884 + #define BNX2_RPM_STAT_AC2 0x00001888 + #define BNX2_RPM_STAT_AC3 0x0000188c + #define BNX2_RPM_STAT_AC4 0x00001890 + #define BNX2_RPM_RC_CNTL_16 0x000018e0 + #define BNX2_RPM_RC_CNTL_16_OFFSET (0xffL<<0) + #define BNX2_RPM_RC_CNTL_16_CLASS (0x7L<<8) + #define BNX2_RPM_RC_CNTL_16_PRIORITY (1L<<11) + #define BNX2_RPM_RC_CNTL_16_P4 (1L<<12) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE (0x7L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_START (0L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_IP (1L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP (2L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_UDP (3L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_DATA (4L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP_UDP (5L<<13) + #define BNX2_RPM_RC_CNTL_16_HDR_TYPE_ICMPV6 (6L<<13) + #define BNX2_RPM_RC_CNTL_16_COMP (0x3L<<16) + #define BNX2_RPM_RC_CNTL_16_COMP_EQUAL (0L<<16) + #define BNX2_RPM_RC_CNTL_16_COMP_NEQUAL (1L<<16) + #define BNX2_RPM_RC_CNTL_16_COMP_GREATER (2L<<16) + #define BNX2_RPM_RC_CNTL_16_COMP_LESS (3L<<16) + #define BNX2_RPM_RC_CNTL_16_MAP (1L<<18) + #define BNX2_RPM_RC_CNTL_16_SBIT (1L<<19) + #define BNX2_RPM_RC_CNTL_16_CMDSEL (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_16_DISCARD (1L<<25) + #define BNX2_RPM_RC_CNTL_16_MASK (1L<<26) + #define BNX2_RPM_RC_CNTL_16_P1 (1L<<27) + #define BNX2_RPM_RC_CNTL_16_P2 (1L<<28) + #define BNX2_RPM_RC_CNTL_16_P3 (1L<<29) + #define BNX2_RPM_RC_CNTL_16_NBIT (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_16 0x000018e4 + #define BNX2_RPM_RC_VALUE_MASK_16_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_16_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_17 0x000018e8 + #define BNX2_RPM_RC_CNTL_17_OFFSET (0xffL<<0) + #define BNX2_RPM_RC_CNTL_17_CLASS (0x7L<<8) + #define BNX2_RPM_RC_CNTL_17_PRIORITY (1L<<11) + #define BNX2_RPM_RC_CNTL_17_P4 (1L<<12) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE (0x7L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_START (0L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_IP (1L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP (2L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_UDP (3L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_DATA (4L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP_UDP (5L<<13) + #define BNX2_RPM_RC_CNTL_17_HDR_TYPE_ICMPV6 (6L<<13) + #define BNX2_RPM_RC_CNTL_17_COMP (0x3L<<16) + #define BNX2_RPM_RC_CNTL_17_COMP_EQUAL (0L<<16) + #define BNX2_RPM_RC_CNTL_17_COMP_NEQUAL (1L<<16) + #define BNX2_RPM_RC_CNTL_17_COMP_GREATER (2L<<16) + #define BNX2_RPM_RC_CNTL_17_COMP_LESS (3L<<16) + #define BNX2_RPM_RC_CNTL_17_MAP (1L<<18) + #define BNX2_RPM_RC_CNTL_17_SBIT (1L<<19) + #define BNX2_RPM_RC_CNTL_17_CMDSEL (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_17_DISCARD (1L<<25) + #define BNX2_RPM_RC_CNTL_17_MASK (1L<<26) + #define BNX2_RPM_RC_CNTL_17_P1 (1L<<27) + #define BNX2_RPM_RC_CNTL_17_P2 (1L<<28) + #define BNX2_RPM_RC_CNTL_17_P3 (1L<<29) + #define BNX2_RPM_RC_CNTL_17_NBIT (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_17 0x000018ec + #define BNX2_RPM_RC_VALUE_MASK_17_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_17_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_18 0x000018f0 + #define BNX2_RPM_RC_CNTL_18_OFFSET (0xffL<<0) + #define BNX2_RPM_RC_CNTL_18_CLASS (0x7L<<8) + #define BNX2_RPM_RC_CNTL_18_PRIORITY (1L<<11) + #define BNX2_RPM_RC_CNTL_18_P4 (1L<<12) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE (0x7L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_START (0L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_IP (1L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP (2L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_UDP (3L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_DATA (4L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP_UDP (5L<<13) + #define BNX2_RPM_RC_CNTL_18_HDR_TYPE_ICMPV6 (6L<<13) + #define BNX2_RPM_RC_CNTL_18_COMP (0x3L<<16) + #define BNX2_RPM_RC_CNTL_18_COMP_EQUAL (0L<<16) + #define BNX2_RPM_RC_CNTL_18_COMP_NEQUAL (1L<<16) + #define BNX2_RPM_RC_CNTL_18_COMP_GREATER (2L<<16) + #define BNX2_RPM_RC_CNTL_18_COMP_LESS (3L<<16) + #define BNX2_RPM_RC_CNTL_18_MAP (1L<<18) + #define BNX2_RPM_RC_CNTL_18_SBIT (1L<<19) + #define BNX2_RPM_RC_CNTL_18_CMDSEL (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_18_DISCARD (1L<<25) + #define BNX2_RPM_RC_CNTL_18_MASK (1L<<26) + #define BNX2_RPM_RC_CNTL_18_P1 (1L<<27) + #define BNX2_RPM_RC_CNTL_18_P2 (1L<<28) + #define BNX2_RPM_RC_CNTL_18_P3 (1L<<29) + #define BNX2_RPM_RC_CNTL_18_NBIT (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_18 0x000018f4 + #define BNX2_RPM_RC_VALUE_MASK_18_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_18_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_19 0x000018f8 + #define BNX2_RPM_RC_CNTL_19_OFFSET (0xffL<<0) + #define BNX2_RPM_RC_CNTL_19_CLASS (0x7L<<8) + #define BNX2_RPM_RC_CNTL_19_PRIORITY (1L<<11) + #define BNX2_RPM_RC_CNTL_19_P4 (1L<<12) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE (0x7L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_START (0L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_IP (1L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP (2L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_UDP (3L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_DATA (4L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP_UDP (5L<<13) + #define BNX2_RPM_RC_CNTL_19_HDR_TYPE_ICMPV6 (6L<<13) + #define BNX2_RPM_RC_CNTL_19_COMP (0x3L<<16) + #define BNX2_RPM_RC_CNTL_19_COMP_EQUAL (0L<<16) + #define BNX2_RPM_RC_CNTL_19_COMP_NEQUAL (1L<<16) + #define BNX2_RPM_RC_CNTL_19_COMP_GREATER (2L<<16) + #define BNX2_RPM_RC_CNTL_19_COMP_LESS (3L<<16) + #define BNX2_RPM_RC_CNTL_19_MAP (1L<<18) + #define BNX2_RPM_RC_CNTL_19_SBIT (1L<<19) + #define BNX2_RPM_RC_CNTL_19_CMDSEL (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_19_DISCARD (1L<<25) + #define BNX2_RPM_RC_CNTL_19_MASK (1L<<26) + #define BNX2_RPM_RC_CNTL_19_P1 (1L<<27) + #define BNX2_RPM_RC_CNTL_19_P2 (1L<<28) + #define BNX2_RPM_RC_CNTL_19_P3 (1L<<29) + #define BNX2_RPM_RC_CNTL_19_NBIT (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_19 0x000018fc + #define BNX2_RPM_RC_VALUE_MASK_19_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_19_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_0 0x00001900 + #define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0) + #define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8) + #define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11) + #define BNX2_RPM_RC_CNTL_0_P4 (1L<<12) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP_UDP (5L<<13) + #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_ICMPV6 (6L<<13) + #define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16) + #define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16) + #define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16) + #define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16) + #define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16) + #define BNX2_RPM_RC_CNTL_0_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19) + #define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20) + #define BNX2_RPM_RC_CNTL_0_MAP (1L<<24) + #define BNX2_RPM_RC_CNTL_0_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25) + #define BNX2_RPM_RC_CNTL_0_MASK (1L<<26) + #define BNX2_RPM_RC_CNTL_0_P1 (1L<<27) + #define BNX2_RPM_RC_CNTL_0_P2 (1L<<28) + #define BNX2_RPM_RC_CNTL_0_P3 (1L<<29) + #define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_0 0x00001904 + #define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_1 0x00001908 + #define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_1_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_1_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_1_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_1_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_1_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_1_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_1_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_1_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_1_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_1_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_1_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_1_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_1_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_1_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_1_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_1_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_1_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_1_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_1_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c + #define BNX2_RPM_RC_VALUE_MASK_1_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_1_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_2 0x00001910 + #define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_2_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_2_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_2_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_2_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_2_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_2_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_2_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_2_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_2_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_2_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_2_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_2_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_2_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_2_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_2_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_2_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_2_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_2_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_2_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_2 0x00001914 + #define BNX2_RPM_RC_VALUE_MASK_2_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_2_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_3 0x00001918 + #define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_3_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_3_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_3_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_3_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_3_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_3_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_3_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_3_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_3_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_3_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_3_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_3_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_3_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_3_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_3_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_3_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_3_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_3_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_3_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c + #define BNX2_RPM_RC_VALUE_MASK_3_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_3_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_4 0x00001920 + #define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_4_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_4_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_4_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_4_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_4_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_4_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_4_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_4_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_4_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_4_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_4_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_4_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_4_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_4_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_4_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_4_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_4_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_4_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_4_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_4 0x00001924 + #define BNX2_RPM_RC_VALUE_MASK_4_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_4_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_5 0x00001928 + #define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_5_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_5_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_5_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_5_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_5_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_5_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_5_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_5_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_5_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_5_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_5_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_5_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_5_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_5_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_5_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_5_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_5_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_5_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_5_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c + #define BNX2_RPM_RC_VALUE_MASK_5_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_5_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_6 0x00001930 + #define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_6_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_6_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_6_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_6_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_6_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_6_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_6_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_6_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_6_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_6_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_6_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_6_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_6_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_6_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_6_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_6_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_6_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_6_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_6_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_6 0x00001934 + #define BNX2_RPM_RC_VALUE_MASK_6_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_6_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_7 0x00001938 + #define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_7_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_7_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_7_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_7_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_7_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_7_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_7_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_7_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_7_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_7_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_7_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_7_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_7_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_7_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_7_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_7_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_7_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_7_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_7_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c + #define BNX2_RPM_RC_VALUE_MASK_7_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_7_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_8 0x00001940 + #define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_8_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_8_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_8_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_8_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_8_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_8_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_8_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_8_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_8_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_8_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_8_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_8_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_8_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_8_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_8_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_8_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_8_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_8_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_8_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_8 0x00001944 + #define BNX2_RPM_RC_VALUE_MASK_8_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_8_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_9 0x00001948 + #define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_9_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_9_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_9_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_9_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_9_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_9_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_9_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_9_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_9_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_9_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_9_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_9_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_9_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_9_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_9_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_9_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_9_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_9_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_9_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c + #define BNX2_RPM_RC_VALUE_MASK_9_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_9_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_10 0x00001950 + #define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_10_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_10_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_10_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_10_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_10_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_10_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_10_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_10_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_10_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_10_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_10_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_10_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_10_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_10_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_10_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_10_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_10_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_10_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_10_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_10 0x00001954 + #define BNX2_RPM_RC_VALUE_MASK_10_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_10_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_11 0x00001958 + #define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_11_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_11_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_11_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_11_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_11_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_11_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_11_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_11_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_11_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_11_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_11_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_11_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_11_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_11_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_11_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_11_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_11_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_11_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_11_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c + #define BNX2_RPM_RC_VALUE_MASK_11_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_11_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_12 0x00001960 + #define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_12_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_12_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_12_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_12_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_12_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_12_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_12_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_12_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_12_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_12_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_12_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_12_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_12_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_12_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_12_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_12_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_12_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_12_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_12_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_12 0x00001964 + #define BNX2_RPM_RC_VALUE_MASK_12_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_12_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_13 0x00001968 + #define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_13_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_13_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_13_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_13_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_13_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_13_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_13_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_13_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_13_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_13_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_13_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_13_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_13_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_13_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_13_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_13_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_13_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_13_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_13_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c + #define BNX2_RPM_RC_VALUE_MASK_13_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_13_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_14 0x00001970 + #define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_14_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_14_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_14_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_14_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_14_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_14_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_14_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_14_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_14_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_14_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_14_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_14_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_14_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_14_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_14_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_14_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_14_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_14_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_14_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_14 0x00001974 + #define BNX2_RPM_RC_VALUE_MASK_14_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_14_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CNTL_15 0x00001978 + #define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0) + #define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19) + #define BNX2_RPM_RC_CNTL_15_OFFSET_XI (0xffL<<0) + #define BNX2_RPM_RC_CNTL_15_CLASS_XI (0x7L<<8) + #define BNX2_RPM_RC_CNTL_15_PRIORITY_XI (1L<<11) + #define BNX2_RPM_RC_CNTL_15_P4_XI (1L<<12) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_XI (0x7L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_START_XI (0L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_IP_XI (1L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_XI (2L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_UDP_XI (3L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_DATA_XI (4L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_UDP_XI (5L<<13) + #define BNX2_RPM_RC_CNTL_15_HDR_TYPE_ICMPV6_XI (6L<<13) + #define BNX2_RPM_RC_CNTL_15_COMP_XI (0x3L<<16) + #define BNX2_RPM_RC_CNTL_15_COMP_EQUAL_XI (0L<<16) + #define BNX2_RPM_RC_CNTL_15_COMP_NEQUAL_XI (1L<<16) + #define BNX2_RPM_RC_CNTL_15_COMP_GREATER_XI (2L<<16) + #define BNX2_RPM_RC_CNTL_15_COMP_LESS_XI (3L<<16) + #define BNX2_RPM_RC_CNTL_15_MAP_XI (1L<<18) + #define BNX2_RPM_RC_CNTL_15_SBIT_XI (1L<<19) + #define BNX2_RPM_RC_CNTL_15_CMDSEL_XI (0x1fL<<20) + #define BNX2_RPM_RC_CNTL_15_DISCARD_XI (1L<<25) + #define BNX2_RPM_RC_CNTL_15_MASK_XI (1L<<26) + #define BNX2_RPM_RC_CNTL_15_P1_XI (1L<<27) + #define BNX2_RPM_RC_CNTL_15_P2_XI (1L<<28) + #define BNX2_RPM_RC_CNTL_15_P3_XI (1L<<29) + #define BNX2_RPM_RC_CNTL_15_NBIT_XI (1L<<30) + + #define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c + #define BNX2_RPM_RC_VALUE_MASK_15_VALUE (0xffffL<<0) + #define BNX2_RPM_RC_VALUE_MASK_15_MASK (0xffffL<<16) + + #define BNX2_RPM_RC_CONFIG 0x00001980 + #define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0) + #define BNX2_RPM_RC_CONFIG_RULE_ENABLE_XI (0xfffffL<<0) + #define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24) + #define BNX2_RPM_RC_CONFIG_KNUM_OVERWRITE (1L<<31) + + #define BNX2_RPM_DEBUG0 0x00001984 + #define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0) + #define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16) + #define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17) + #define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18) + #define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19) + #define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20) + #define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21) + #define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22) + #define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23) + #define BNX2_RPM_DEBUG0_DONE (1L<<24) + #define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25) + #define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26) + #define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27) + #define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28) + #define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31) + + #define BNX2_RPM_DEBUG1 0x00001988 + #define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0) + #define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0) + #define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16) + #define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28) + #define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29) + #define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30) + #define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31) + + #define BNX2_RPM_DEBUG2 0x0000198c + #define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0) + #define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16) + #define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24) + #define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25) + #define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26) + #define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27) + #define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28) + #define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29) + #define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30) + #define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31) + + #define BNX2_RPM_DEBUG3 0x00001990 + #define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0) + #define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9) + #define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10) + #define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11) + #define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12) + #define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13) + #define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14) + #define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15) + #define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16) + #define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21) + #define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22) + #define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23) + #define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24) + #define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24) + #define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24) + #define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26) + #define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26) + #define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29) + #define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29) + #define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29) + #define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30) + #define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30) + #define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30) + #define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31) + + #define BNX2_RPM_DEBUG4 0x00001994 + #define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0) + #define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25) + #define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28) + #define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31) + + #define BNX2_RPM_DEBUG5 0x00001998 + #define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0) + #define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5) + #define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10) + #define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15) + #define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20) + #define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21) + #define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22) + #define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23) + #define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24) + #define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25) + #define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26) + #define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27) + #define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28) + #define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29) + #define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30) + #define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31) + + #define BNX2_RPM_DEBUG6 0x0000199c + #define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0) + #define BNX2_RPM_DEBUG6_VEC (0xffffL<<16) + + #define BNX2_RPM_DEBUG7 0x000019a0 + #define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0) + + #define BNX2_RPM_DEBUG8 0x000019a4 + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0) + #define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0) + #define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4) + #define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5) + #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6) + #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7) + #define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8) + #define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9) + #define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10) + #define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11) + #define BNX2_RPM_DEBUG8_EOF_DET (1L<<12) + #define BNX2_RPM_DEBUG8_SOF_DET (1L<<13) + #define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14) + #define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15) + #define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16) + #define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24) + + #define BNX2_RPM_DEBUG9 0x000019a8 + #define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0) + #define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3) + #define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4) + #define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28) + #define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29) + #define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30) + #define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31) + #define BNX2_RPM_DEBUG9_BEMEM_R_XI (0x1fL<<0) + #define BNX2_RPM_DEBUG9_EO_XI (1L<<5) + #define BNX2_RPM_DEBUG9_AEOF_DE_XI (1L<<6) + #define BNX2_RPM_DEBUG9_SO_XI (1L<<7) + #define BNX2_RPM_DEBUG9_WD64_CT_XI (0x1fL<<8) + #define BNX2_RPM_DEBUG9_EOF_VLDBYTE_XI (0x7L<<13) + #define BNX2_RPM_DEBUG9_ACPI_RDE_PAT_ID_XI (0xfL<<16) + #define BNX2_RPM_DEBUG9_CALCRC_RESULT_XI (0x3ffL<<20) + #define BNX2_RPM_DEBUG9_DATA_IN_VL_XI (1L<<30) + #define BNX2_RPM_DEBUG9_CALCRC_BUFFER_VLD_XI (1L<<31) + + #define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0 + #define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4 + #define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8 + #define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc + #define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0 + #define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4 + #define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8 + #define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc + #define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0 + #define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4 + #define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8 + #define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec + #define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0 + #define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4 + #define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8 + #define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL 0x00001a00 + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_BYTE_ADDRESS (0xffffL<<0) + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_DEBUGRD (1L<<28) + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_MODE (1L<<29) + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_INIT (1L<<30) + #define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_WR (1L<<31) + + #define BNX2_RPM_ACPI_PATTERN_CTRL 0x00001a04 + #define BNX2_RPM_ACPI_PATTERN_CTRL_PATTERN_ID (0xfL<<0) + #define BNX2_RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR (1L<<30) + #define BNX2_RPM_ACPI_PATTERN_CTRL_WR (1L<<31) + + #define BNX2_RPM_ACPI_DATA 0x00001a08 + #define BNX2_RPM_ACPI_DATA_PATTERN_BE (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_LEN0 0x00001a0c + #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN3 (0xffL<<0) + #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN2 (0xffL<<8) + #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN1 (0xffL<<16) + #define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN0 (0xffL<<24) + + #define BNX2_RPM_ACPI_PATTERN_LEN1 0x00001a10 + #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN7 (0xffL<<0) + #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN6 (0xffL<<8) + #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN5 (0xffL<<16) + #define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN4 (0xffL<<24) + + #define BNX2_RPM_ACPI_PATTERN_CRC0 0x00001a18 + #define BNX2_RPM_ACPI_PATTERN_CRC0_PATTERN_CRC0 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC1 0x00001a1c + #define BNX2_RPM_ACPI_PATTERN_CRC1_PATTERN_CRC1 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC2 0x00001a20 + #define BNX2_RPM_ACPI_PATTERN_CRC2_PATTERN_CRC2 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC3 0x00001a24 + #define BNX2_RPM_ACPI_PATTERN_CRC3_PATTERN_CRC3 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC4 0x00001a28 + #define BNX2_RPM_ACPI_PATTERN_CRC4_PATTERN_CRC4 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC5 0x00001a2c + #define BNX2_RPM_ACPI_PATTERN_CRC5_PATTERN_CRC5 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC6 0x00001a30 + #define BNX2_RPM_ACPI_PATTERN_CRC6_PATTERN_CRC6 (0xffffffffL<<0) + + #define BNX2_RPM_ACPI_PATTERN_CRC7 0x00001a34 + #define BNX2_RPM_ACPI_PATTERN_CRC7_PATTERN_CRC7 (0xffffffffL<<0) + + + /* + * rlup_reg definition + * offset: 0x2000 + */ + #define BNX2_RLUP_RSS_CONFIG 0x0000201c + #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_XI (0x3L<<0) + #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI (0L<<0) + #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI (1L<<0) + #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_IP_ONLY_XI (2L<<0) + #define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_RES_XI (3L<<0) + #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_XI (0x3L<<2) + #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI (0L<<2) + #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI (1L<<2) + #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI (2L<<2) + #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI (3L<<2) + + #define BNX2_RLUP_RSS_COMMAND 0x00002048 + #define BNX2_RLUP_RSS_COMMAND_RSS_IND_TABLE_ADDR (0xfUL<<0) + #define BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK (0xffUL<<4) + #define BNX2_RLUP_RSS_COMMAND_WRITE (1UL<<12) + #define BNX2_RLUP_RSS_COMMAND_READ (1UL<<13) + #define BNX2_RLUP_RSS_COMMAND_HASH_MASK (0x7UL<<14) + + #define BNX2_RLUP_RSS_DATA 0x0000204c + + + /* + * rbuf_reg definition + * offset: 0x200000 + */ + #define BNX2_RBUF_COMMAND 0x00200000 + #define BNX2_RBUF_COMMAND_ENABLED (1L<<0) + #define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1) + #define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2) + #define BNX2_RBUF_COMMAND_PKT_OFFSET_OVFL (1L<<3) + #define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4) + #define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5) + #define BNX2_RBUF_COMMAND_EN_PRI_CHNGE_TE (1L<<6) + #define BNX2_RBUF_COMMAND_CU_ISOLATE_XI (1L<<5) + #define BNX2_RBUF_COMMAND_EN_PRI_CHANGE_XI (1L<<6) + #define BNX2_RBUF_COMMAND_GRC_ENDIAN_CONV_DIS_XI (1L<<7) + + #define BNX2_RBUF_STATUS1 0x00200004 + #define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0) + + #define BNX2_RBUF_STATUS2 0x00200008 + #define BNX2_RBUF_STATUS2_FREE_TAIL (0x1ffL<<0) + #define BNX2_RBUF_STATUS2_FREE_HEAD (0x1ffL<<16) + + #define BNX2_RBUF_CONFIG 0x0020000c + #define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0) + #define BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 31 / 1000) + 54) + #define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16) + #define BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 39 / 1000) + 66) + #define BNX2_RBUF_CONFIG_VAL(mtu) \ + (BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) | \ + (BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) << 16)) + + #define BNX2_RBUF_FW_BUF_ALLOC 0x00200010 + #define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7) + #define BNX2_RBUF_FW_BUF_ALLOC_TYPE (1L<<16) + #define BNX2_RBUF_FW_BUF_ALLOC_ALLOC_REQ (1L<<31) + + #define BNX2_RBUF_FW_BUF_FREE 0x00200014 + #define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0) + #define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7) + #define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16) + #define BNX2_RBUF_FW_BUF_FREE_TYPE (1L<<25) + #define BNX2_RBUF_FW_BUF_FREE_FREE_REQ (1L<<31) + + #define BNX2_RBUF_FW_BUF_SEL 0x00200018 + #define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0) + #define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7) + #define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16) + #define BNX2_RBUF_FW_BUF_SEL_SEL_REQ (1L<<31) + + #define BNX2_RBUF_CONFIG2 0x0020001c + #define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0) + #define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 4 / 1000) + 5) + #define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16) + #define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 2 / 100) + 30) + #define BNX2_RBUF_CONFIG2_VAL(mtu) \ + (BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) | \ + (BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) << 16)) + + #define BNX2_RBUF_CONFIG3 0x00200020 + #define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0) + #define BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 12 / 1000) + 18) + #define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16) + #define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) \ + ((((mtu) - 1500) * 2 / 100) + 30) + #define BNX2_RBUF_CONFIG3_VAL(mtu) \ + (BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) | \ + (BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) << 16)) + + #define BNX2_RBUF_PKT_DATA 0x00208000 + #define BNX2_RBUF_CLIST_DATA 0x00210000 + #define BNX2_RBUF_BUF_DATA 0x00220000 + + + /* + * rv2p_reg definition + * offset: 0x2800 + */ + #define BNX2_RV2P_COMMAND 0x00002800 + #define BNX2_RV2P_COMMAND_ENABLED (1L<<0) + #define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1) + #define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2) + #define BNX2_RV2P_COMMAND_ABORT0 (1L<<4) + #define BNX2_RV2P_COMMAND_ABORT1 (1L<<5) + #define BNX2_RV2P_COMMAND_ABORT2 (1L<<6) + #define BNX2_RV2P_COMMAND_ABORT3 (1L<<7) + #define BNX2_RV2P_COMMAND_ABORT4 (1L<<8) + #define BNX2_RV2P_COMMAND_ABORT5 (1L<<9) + #define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16) + #define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17) + #define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18) + + #define BNX2_RV2P_STATUS 0x00002804 + #define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12) + #define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13) + + #define BNX2_RV2P_CONFIG 0x00002808 + #define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0) + #define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12) + #define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20) + #define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21) + #define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24) + #define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24) + + #define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810 + #define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16) + + #define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814 + #define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16) + + #define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818 + #define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16) + + #define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c + #define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16) + + #define BNX2_RV2P_INSTR_HIGH 0x00002830 + #define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0) + + #define BNX2_RV2P_INSTR_LOW 0x00002834 + #define BNX2_RV2P_INSTR_LOW_LOW (0xffffffffL<<0) + + #define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838 + #define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0) + #define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31) + + #define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c + #define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0) + #define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31) + + #define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840 + #define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844 + #define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848 + #define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c + #define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_RV2P_MPFE_PFE_CTL 0x00002afc + #define BNX2_RV2P_MPFE_PFE_CTL_INC_USAGE_CNT (1L<<0) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE (0xfL<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_0 (0L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_1 (1L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_2 (2L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_3 (3L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_4 (4L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_5 (5L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_6 (6L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_7 (7L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_8 (8L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_9 (9L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_10 (10L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_11 (11L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_12 (12L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_13 (13L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_14 (14L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_15 (15L<<4) + #define BNX2_RV2P_MPFE_PFE_CTL_PFE_COUNT (0xfL<<12) + #define BNX2_RV2P_MPFE_PFE_CTL_OFFSET (0x1ffL<<16) + + #define BNX2_RV2P_RV2PPQ 0x00002b40 + #define BNX2_RV2P_PFTQ_CMD 0x00002b78 + #define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10) + #define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26) + #define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_RV2P_PFTQ_CMD_POP (1L<<30) + #define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31) + + #define BNX2_RV2P_PFTQ_CTL 0x00002b7c + #define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0) + #define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_RV2P_RV2PTQ 0x00002b80 + #define BNX2_RV2P_TFTQ_CMD 0x00002bb8 + #define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10) + #define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26) + #define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_RV2P_TFTQ_CMD_POP (1L<<30) + #define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31) + + #define BNX2_RV2P_TFTQ_CTL 0x00002bbc + #define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0) + #define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_RV2P_RV2PMQ 0x00002bc0 + #define BNX2_RV2P_MFTQ_CMD 0x00002bf8 + #define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10) + #define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26) + #define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_RV2P_MFTQ_CMD_POP (1L<<30) + #define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31) + + #define BNX2_RV2P_MFTQ_CTL 0x00002bfc + #define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0) + #define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + + /* + * mq_reg definition + * offset: 0x3c00 + */ + #define BNX2_MQ_COMMAND 0x00003c00 + #define BNX2_MQ_COMMAND_ENABLED (1L<<0) + #define BNX2_MQ_COMMAND_INIT (1L<<1) + #define BNX2_MQ_COMMAND_OVERFLOW (1L<<4) + #define BNX2_MQ_COMMAND_WR_ERROR (1L<<5) + #define BNX2_MQ_COMMAND_RD_ERROR (1L<<6) + #define BNX2_MQ_COMMAND_IDB_CFG_ERROR (1L<<7) + #define BNX2_MQ_COMMAND_IDB_OVERFLOW (1L<<10) + #define BNX2_MQ_COMMAND_NO_BIN_ERROR (1L<<11) + #define BNX2_MQ_COMMAND_NO_MAP_ERROR (1L<<12) + + #define BNX2_MQ_STATUS 0x00003c04 + #define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16) + #define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17) + #define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18) + #define BNX2_MQ_STATUS_IDB_OFLOW_STAT (1L<<19) + + #define BNX2_MQ_CONFIG 0x00003c08 + #define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0) + #define BNX2_MQ_CONFIG_HALT_DIS (1L<<1) + #define BNX2_MQ_CONFIG_BIN_MQ_MODE (1L<<2) + #define BNX2_MQ_CONFIG_DIS_IDB_DROP (1L<<3) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4) + #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4) + #define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8) + #define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20) + + #define BNX2_MQ_ENQUEUE1 0x00003c0c + #define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2) + #define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8) + #define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24) + #define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28) + + #define BNX2_MQ_ENQUEUE2 0x00003c10 + #define BNX2_MQ_BAD_WR_ADDR 0x00003c14 + #define BNX2_MQ_BAD_RD_ADDR 0x00003c18 + #define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c + #define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12) + + #define BNX2_MQ_KNL_WIND_END 0x00003c20 + #define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8) + + #define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24 + #define BNX2_MQ_KNL_TX_MASK1 0x00003c28 + #define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c + #define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30 + #define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34 + #define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38 + #define BNX2_MQ_KNL_TX_MASK2 0x00003c3c + #define BNX2_MQ_KNL_CMD_MASK2 0x00003c40 + #define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44 + #define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48 + #define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c + #define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50 + #define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54 + #define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58 + #define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c + #define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60 + #define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64 + #define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68 + #define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c + #define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70 + #define BNX2_MQ_MEM_WR_ADDR 0x00003c74 + #define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0) + + #define BNX2_MQ_MEM_WR_DATA0 0x00003c78 + #define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0) + + #define BNX2_MQ_MEM_WR_DATA1 0x00003c7c + #define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0) + + #define BNX2_MQ_MEM_WR_DATA2 0x00003c80 + #define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0) + #define BNX2_MQ_MEM_WR_DATA2_VALUE_XI (0x7fffffffL<<0) + + #define BNX2_MQ_MEM_RD_ADDR 0x00003c84 + #define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0) + + #define BNX2_MQ_MEM_RD_DATA0 0x00003c88 + #define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0) + + #define BNX2_MQ_MEM_RD_DATA1 0x00003c8c + #define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0) + + #define BNX2_MQ_MEM_RD_DATA2 0x00003c90 + #define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0) + #define BNX2_MQ_MEM_RD_DATA2_VALUE_XI (0x7fffffffL<<0) + + #define BNX2_MQ_MAP_L2_3 0x00003d2c + #define BNX2_MQ_MAP_L2_3_MQ_OFFSET (0xffL<<0) + #define BNX2_MQ_MAP_L2_3_SZ (0x3L<<8) + #define BNX2_MQ_MAP_L2_3_CTX_OFFSET (0x2ffL<<10) + #define BNX2_MQ_MAP_L2_3_BIN_OFFSET (0x7L<<23) + #define BNX2_MQ_MAP_L2_3_ARM (0x3L<<26) + #define BNX2_MQ_MAP_L2_3_ENA (0x1L<<31) + #define BNX2_MQ_MAP_L2_3_DEFAULT 0x82004646 + + #define BNX2_MQ_MAP_L2_5 0x00003d34 + #define BNX2_MQ_MAP_L2_5_ARM (0x3L<<26) + + /* + * tsch_reg definition + * offset: 0x4c00 + */ + #define BNX2_TSCH_TSS_CFG 0x00004c1c + #define BNX2_TSCH_TSS_CFG_TSS_START_CID (0x7ffL<<8) + #define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON (0xfL<<24) + + + + /* + * tbdr_reg definition + * offset: 0x5000 + */ + #define BNX2_TBDR_COMMAND 0x00005000 + #define BNX2_TBDR_COMMAND_ENABLE (1L<<0) + #define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1) + #define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4) + + #define BNX2_TBDR_STATUS 0x00005004 + #define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0) + #define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1) + #define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2) + #define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3) + #define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4) + #define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5) + #define BNX2_TBDR_STATUS_BURST_CNT (1L<<6) + + #define BNX2_TBDR_CONFIG 0x00005008 + #define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0) + #define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8) + #define BNX2_TBDR_CONFIG_PRIORITY (1L<<9) + #define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10) + #define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24) + #define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24) + + #define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c + #define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_TBDR_CKSUM_ERROR_STATUS 0x00005010 + #define BNX2_TBDR_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) + #define BNX2_TBDR_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + + #define BNX2_TBDR_TBDRQ 0x000053c0 + #define BNX2_TBDR_FTQ_CMD 0x000053f8 + #define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_TBDR_FTQ_CMD_POP (1L<<30) + #define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_TBDR_FTQ_CTL 0x000053fc + #define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + + /* + * tdma_reg definition + * offset: 0x5c00 + */ + #define BNX2_TDMA_COMMAND 0x00005c00 + #define BNX2_TDMA_COMMAND_ENABLED (1L<<0) + #define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4) + #define BNX2_TDMA_COMMAND_CS16_ERR (1L<<5) + #define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7) + #define BNX2_TDMA_COMMAND_MASK_CS1 (1L<<20) + #define BNX2_TDMA_COMMAND_MASK_CS2 (1L<<21) + #define BNX2_TDMA_COMMAND_MASK_CS3 (1L<<22) + #define BNX2_TDMA_COMMAND_MASK_CS4 (1L<<23) + #define BNX2_TDMA_COMMAND_FORCE_ILOCK_CKERR (1L<<24) + #define BNX2_TDMA_COMMAND_OFIFO_CLR (1L<<30) + #define BNX2_TDMA_COMMAND_IFIFO_CLR (1L<<31) + + #define BNX2_TDMA_STATUS 0x00005c04 + #define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0) + #define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1) + #define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2) + #define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3) + #define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16) + #define BNX2_TDMA_STATUS_BURST_CNT (1L<<17) + #define BNX2_TDMA_STATUS_MAX_IFIFO_DEPTH (0x3fL<<20) + #define BNX2_TDMA_STATUS_OFIFO_OVERFLOW (1L<<30) + #define BNX2_TDMA_STATUS_IFIFO_OVERFLOW (1L<<31) + + #define BNX2_TDMA_CONFIG 0x00005c08 + #define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0) + #define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1) + #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN (0x3L<<2) + #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_0 (0L<<2) + #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_1 (1L<<2) + #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_2 (2L<<2) + #define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_3 (3L<<2) + #define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4) + #define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4) + #define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4) + #define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4) + #define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4) + #define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8) + #define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8) + #define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8) + #define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8) + #define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8) + #define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15) + #define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16) + #define BNX2_TDMA_CONFIG_CMPL_ENTRY (1L<<17) + #define BNX2_TDMA_CONFIG_OFIFO_CMP (1L<<19) + #define BNX2_TDMA_CONFIG_OFIFO_CMP_3 (0L<<19) + #define BNX2_TDMA_CONFIG_OFIFO_CMP_2 (1L<<19) + #define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_XI (0x7L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_0_XI (0L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_4_XI (1L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_8_XI (2L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_16_XI (3L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_32_XI (4L<<20) + #define BNX2_TDMA_CONFIG_IFIFO_DEPTH_64_XI (5L<<20) + #define BNX2_TDMA_CONFIG_FIFO_CMP_EN_XI (1L<<23) + #define BNX2_TDMA_CONFIG_BYTES_OST_XI (0x7L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_512_XI (0L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_1024_XI (1L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_2048_XI (2L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_4096_XI (3L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_8192_XI (4L<<24) + #define BNX2_TDMA_CONFIG_BYTES_OST_16384_XI (5L<<24) + #define BNX2_TDMA_CONFIG_HC_BYPASS_XI (1L<<27) + #define BNX2_TDMA_CONFIG_LCL_MRRS_XI (0x7L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_128_XI (0L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_256_XI (1L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_512_XI (2L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_1024_XI (3L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_2048_XI (4L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_4096_XI (5L<<28) + #define BNX2_TDMA_CONFIG_LCL_MRRS_EN_XI (1L<<31) + + #define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c + #define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3) + + #define BNX2_TDMA_DBG_WATCHDOG 0x00005c10 + #define BNX2_TDMA_DBG_TRIGGER 0x00005c14 + #define BNX2_TDMA_DMAD_FSM 0x00005c80 + #define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0) + #define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4) + #define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8) + #define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12) + #define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16) + #define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20) + #define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24) + + #define BNX2_TDMA_DMAD_STATUS 0x00005c84 + #define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0) + #define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4) + #define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8) + #define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12) + + #define BNX2_TDMA_DR_INTF_FSM 0x00005c88 + #define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0) + #define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4) + #define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8) + #define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12) + #define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16) + + #define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c + #define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0) + #define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4) + #define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8) + #define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12) + #define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16) + + #define BNX2_TDMA_PUSH_FSM 0x00005c90 + #define BNX2_TDMA_BD_IF_DEBUG 0x00005c94 + #define BNX2_TDMA_DMAD_IF_DEBUG 0x00005c98 + #define BNX2_TDMA_CTX_IF_DEBUG 0x00005c9c + #define BNX2_TDMA_TPBUF_IF_DEBUG 0x00005ca0 + #define BNX2_TDMA_DR_IF_DEBUG 0x00005ca4 + #define BNX2_TDMA_TPATQ_IF_DEBUG 0x00005ca8 + #define BNX2_TDMA_TDMA_ILOCK_CKSUM 0x00005cac + #define BNX2_TDMA_TDMA_ILOCK_CKSUM_CALCULATED (0xffffL<<0) + #define BNX2_TDMA_TDMA_ILOCK_CKSUM_EXPECTED (0xffffL<<16) + + #define BNX2_TDMA_TDMA_PCIE_CKSUM 0x00005cb0 + #define BNX2_TDMA_TDMA_PCIE_CKSUM_CALCULATED (0xffffL<<0) + #define BNX2_TDMA_TDMA_PCIE_CKSUM_EXPECTED (0xffffL<<16) + + #define BNX2_TDMA_TDMAQ 0x00005fc0 + #define BNX2_TDMA_FTQ_CMD 0x00005ff8 + #define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_TDMA_FTQ_CMD_POP (1L<<30) + #define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_TDMA_FTQ_CTL 0x00005ffc + #define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + + /* + * hc_reg definition + * offset: 0x6800 + */ + #define BNX2_HC_COMMAND 0x00006800 + #define BNX2_HC_COMMAND_ENABLE (1L<<0) + #define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4) + #define BNX2_HC_COMMAND_COAL_NOW (1L<<16) + #define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17) + #define BNX2_HC_COMMAND_STATS_NOW (1L<<18) + #define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19) + #define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19) + #define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19) + #define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19) + #define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19) + #define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21) + #define BNX2_HC_COMMAND_MAIN_PWR_INT (1L<<22) + #define BNX2_HC_COMMAND_COAL_ON_NEXT_EVENT (1L<<27) + + #define BNX2_HC_STATUS 0x00006804 + #define BNX2_HC_STATUS_MASTER_ABORT (1L<<0) + #define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1) + #define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16) + #define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17) + #define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18) + #define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19) + #define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20) + #define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23) + #define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24) + #define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25) + + #define BNX2_HC_CONFIG 0x00006808 + #define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0) + #define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1) + #define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2) + #define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3) + #define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5) + #define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6) + #define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8) + #define BNX2_HC_CONFIG_PER_MODE (1L<<16) + #define BNX2_HC_CONFIG_ONE_SHOT (1L<<17) + #define BNX2_HC_CONFIG_USE_INT_PARAM (1L<<18) + #define BNX2_HC_CONFIG_SET_MASK_AT_RD (1L<<19) + #define BNX2_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20) + #define BNX2_HC_CONFIG_SB_ADDR_INC (0x7L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_64B (0L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_128B (1L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_256B (2L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_512B (3L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24) + #define BNX2_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24) + #define BNX2_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29) + #define BNX2_HC_CONFIG_UNMASK_ALL (1L<<30) + #define BNX2_HC_CONFIG_TX_SEL (1L<<31) + + #define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c + #define BNX2_HC_STATUS_ADDR_L 0x00006810 + #define BNX2_HC_STATUS_ADDR_H 0x00006814 + #define BNX2_HC_STATISTICS_ADDR_L 0x00006818 + #define BNX2_HC_STATISTICS_ADDR_H 0x0000681c + #define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820 + #define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP 0x00006824 + #define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828 + #define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS 0x0000682c + #define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS 0x00006830 + #define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS 0x00006834 + #define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS 0x00006838 + #define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS 0x0000683c + #define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_STAT_COLLECT_TICKS 0x00006840 + #define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4) + + #define BNX2_HC_STATS_TICKS 0x00006844 + #define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8) + + #define BNX2_HC_STATS_INTERRUPT_STATUS 0x00006848 + #define BNX2_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0) + #define BNX2_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16) + + #define BNX2_HC_STAT_MEM_DATA 0x0000684c + #define BNX2_HC_STAT_GEN_SEL_0 0x00006850 + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_XI (0xffL<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UMP_RX_FRAME_DROP_XI (52L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S0_XI (57L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S1_XI (58L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S2_XI (85L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S3_XI (86L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S4_XI (87L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S5_XI (88L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S6_XI (89L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S7_XI (90L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S8_XI (91L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S9_XI (92L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S10_XI (93L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MQ_IDB_OFLOW_XI (94L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_RD_CNT_XI (123L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_WR_CNT_XI (124L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_HITS_XI (125L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_MISSES_XI (126L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC1_XI (128L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC1_XI (129L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC1_XI (130L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC1_XI (131L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC1_XI (132L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC1_XI (133L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC2_XI (134L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC2_XI (135L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC2_XI (136L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC2_XI (137L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC2_XI (138L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC2_XI (139L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC3_XI (140L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC3_XI (141L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC3_XI (142L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC3_XI (143L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC3_XI (144L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC3_XI (145L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC4_XI (146L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC4_XI (147L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC4_XI (148L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC4_XI (149L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC4_XI (150L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC4_XI (151L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC5_XI (152L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC5_XI (153L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC5_XI (154L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC5_XI (155L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC5_XI (156L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC5_XI (157L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC6_XI (158L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC6_XI (159L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC6_XI (160L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC6_XI (161L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC6_XI (162L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC6_XI (163L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC7_XI (164L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC7_XI (165L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC7_XI (166L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC7_XI (167L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC7_XI (168L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC7_XI (169L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC8_XI (170L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC8_XI (171L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC8_XI (172L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC8_XI (173L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC8_XI (174L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC8_XI (175L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_CMD_CNT_XI (176L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_SLOT_CNT_XI (177L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI (178L<<0) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1_XI (0xffL<<8) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2_XI (0xffL<<16) + #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3_XI (0xffL<<24) + + #define BNX2_HC_STAT_GEN_SEL_1 0x00006854 + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4_XI (0xffL<<0) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5_XI (0xffL<<8) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6_XI (0xffL<<16) + #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7_XI (0xffL<<24) + + #define BNX2_HC_STAT_GEN_SEL_2 0x00006858 + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8_XI (0xffL<<0) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9_XI (0xffL<<8) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10_XI (0xffL<<16) + #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11_XI (0xffL<<24) + + #define BNX2_HC_STAT_GEN_SEL_3 0x0000685c + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12_XI (0xffL<<0) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13_XI (0xffL<<8) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14_XI (0xffL<<16) + #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15_XI (0xffL<<24) + + #define BNX2_HC_STAT_GEN_STAT0 0x00006888 + #define BNX2_HC_STAT_GEN_STAT1 0x0000688c + #define BNX2_HC_STAT_GEN_STAT2 0x00006890 + #define BNX2_HC_STAT_GEN_STAT3 0x00006894 + #define BNX2_HC_STAT_GEN_STAT4 0x00006898 + #define BNX2_HC_STAT_GEN_STAT5 0x0000689c + #define BNX2_HC_STAT_GEN_STAT6 0x000068a0 + #define BNX2_HC_STAT_GEN_STAT7 0x000068a4 + #define BNX2_HC_STAT_GEN_STAT8 0x000068a8 + #define BNX2_HC_STAT_GEN_STAT9 0x000068ac + #define BNX2_HC_STAT_GEN_STAT10 0x000068b0 + #define BNX2_HC_STAT_GEN_STAT11 0x000068b4 + #define BNX2_HC_STAT_GEN_STAT12 0x000068b8 + #define BNX2_HC_STAT_GEN_STAT13 0x000068bc + #define BNX2_HC_STAT_GEN_STAT14 0x000068c0 + #define BNX2_HC_STAT_GEN_STAT15 0x000068c4 + #define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8 + #define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc + #define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0 + #define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4 + #define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8 + #define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc + #define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0 + #define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4 + #define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8 + #define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec + #define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0 + #define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4 + #define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8 + #define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc + #define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900 + #define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904 + #define BNX2_HC_STAT_GEN_STAT_AC 0x000068c8 + #define BNX2_HC_VIS 0x00006908 + #define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0) + #define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0) + #define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8) + #define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8) + #define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12) + #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15) + #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15) + #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15) + #define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15) + + #define BNX2_HC_VIS_1 0x0000690c + #define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4) + #define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4) + #define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4) + #define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5) + #define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5) + #define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5) + #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6) + #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6) + #define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6) + #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7) + #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7) + #define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17) + #define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17) + #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21) + #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21) + #define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21) + #define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23) + #define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23) + #define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23) + #define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24) + #define BNX2_HC_VIS_1_INT_B (1L<<27) + + #define BNX2_HC_DEBUG_VECT_PEEK 0x00006910 + #define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_HC_COALESCE_NOW 0x00006914 + #define BNX2_HC_COALESCE_NOW_COAL_NOW (0x1ffL<<1) + #define BNX2_HC_COALESCE_NOW_COAL_NOW_WO_INT (0x1ffL<<11) + #define BNX2_HC_COALESCE_NOW_COAL_ON_NXT_EVENT (0x1ffL<<21) + + #define BNX2_HC_MSIX_BIT_VECTOR 0x00006918 + #define BNX2_HC_MSIX_BIT_VECTOR_VAL (0x1ffL<<0) + + #define BNX2_HC_SB_CONFIG_1 0x00006a00 + #define BNX2_HC_SB_CONFIG_1_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_1_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_1_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_1_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_1_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_1_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_1_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_1_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_1 0x00006a04 + #define BNX2_HC_TX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_1_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_1 0x00006a08 + #define BNX2_HC_COMP_PROD_TRIP_1_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_1_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_1 0x00006a0c + #define BNX2_HC_RX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_1_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_1 0x00006a10 + #define BNX2_HC_RX_TICKS_1_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_1_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_1 0x00006a14 + #define BNX2_HC_TX_TICKS_1_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_1_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_1 0x00006a18 + #define BNX2_HC_COM_TICKS_1_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_1_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_1 0x00006a1c + #define BNX2_HC_CMD_TICKS_1_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_1_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_1 0x00006a20 + #define BNX2_HC_PERIODIC_TICKS_1_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_1_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_2 0x00006a24 + #define BNX2_HC_SB_CONFIG_2_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_2_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_2_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_2_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_2_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_2_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_2_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_2_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_2 0x00006a28 + #define BNX2_HC_TX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_2_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_2 0x00006a2c + #define BNX2_HC_COMP_PROD_TRIP_2_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_2_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_2 0x00006a30 + #define BNX2_HC_RX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_2_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_2 0x00006a34 + #define BNX2_HC_RX_TICKS_2_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_2_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_2 0x00006a38 + #define BNX2_HC_TX_TICKS_2_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_2_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_2 0x00006a3c + #define BNX2_HC_COM_TICKS_2_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_2_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_2 0x00006a40 + #define BNX2_HC_CMD_TICKS_2_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_2_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_2 0x00006a44 + #define BNX2_HC_PERIODIC_TICKS_2_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_2_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_3 0x00006a48 + #define BNX2_HC_SB_CONFIG_3_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_3_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_3_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_3_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_3_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_3_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_3_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_3_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_3 0x00006a4c + #define BNX2_HC_TX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_3_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_3 0x00006a50 + #define BNX2_HC_COMP_PROD_TRIP_3_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_3_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_3 0x00006a54 + #define BNX2_HC_RX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_3_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_3 0x00006a58 + #define BNX2_HC_RX_TICKS_3_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_3_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_3 0x00006a5c + #define BNX2_HC_TX_TICKS_3_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_3_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_3 0x00006a60 + #define BNX2_HC_COM_TICKS_3_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_3_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_3 0x00006a64 + #define BNX2_HC_CMD_TICKS_3_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_3_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_3 0x00006a68 + #define BNX2_HC_PERIODIC_TICKS_3_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_3_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_4 0x00006a6c + #define BNX2_HC_SB_CONFIG_4_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_4_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_4_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_4_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_4_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_4_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_4_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_4_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_4 0x00006a70 + #define BNX2_HC_TX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_4_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_4 0x00006a74 + #define BNX2_HC_COMP_PROD_TRIP_4_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_4_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_4 0x00006a78 + #define BNX2_HC_RX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_4_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_4 0x00006a7c + #define BNX2_HC_RX_TICKS_4_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_4_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_4 0x00006a80 + #define BNX2_HC_TX_TICKS_4_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_4_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_4 0x00006a84 + #define BNX2_HC_COM_TICKS_4_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_4_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_4 0x00006a88 + #define BNX2_HC_CMD_TICKS_4_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_4_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_4 0x00006a8c + #define BNX2_HC_PERIODIC_TICKS_4_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_4_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_5 0x00006a90 + #define BNX2_HC_SB_CONFIG_5_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_5_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_5_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_5_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_5_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_5_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_5_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_5_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_5 0x00006a94 + #define BNX2_HC_TX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_5_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_5 0x00006a98 + #define BNX2_HC_COMP_PROD_TRIP_5_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_5_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_5 0x00006a9c + #define BNX2_HC_RX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_5_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_5 0x00006aa0 + #define BNX2_HC_RX_TICKS_5_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_5_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_5 0x00006aa4 + #define BNX2_HC_TX_TICKS_5_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_5_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_5 0x00006aa8 + #define BNX2_HC_COM_TICKS_5_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_5_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_5 0x00006aac + #define BNX2_HC_CMD_TICKS_5_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_5_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_5 0x00006ab0 + #define BNX2_HC_PERIODIC_TICKS_5_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_5_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_6 0x00006ab4 + #define BNX2_HC_SB_CONFIG_6_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_6_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_6_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_6_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_6_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_6_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_6_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_6_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_6 0x00006ab8 + #define BNX2_HC_TX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_6_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_6 0x00006abc + #define BNX2_HC_COMP_PROD_TRIP_6_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_6_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_6 0x00006ac0 + #define BNX2_HC_RX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_6_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_6 0x00006ac4 + #define BNX2_HC_RX_TICKS_6_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_6_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_6 0x00006ac8 + #define BNX2_HC_TX_TICKS_6_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_6_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_6 0x00006acc + #define BNX2_HC_COM_TICKS_6_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_6_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_6 0x00006ad0 + #define BNX2_HC_CMD_TICKS_6_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_6_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_6 0x00006ad4 + #define BNX2_HC_PERIODIC_TICKS_6_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_6_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_7 0x00006ad8 + #define BNX2_HC_SB_CONFIG_7_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_7_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_7_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_7_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_7_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_7_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_7_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_7_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_7 0x00006adc + #define BNX2_HC_TX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_7_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_7 0x00006ae0 + #define BNX2_HC_COMP_PROD_TRIP_7_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_7_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_7 0x00006ae4 + #define BNX2_HC_RX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_7_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_7 0x00006ae8 + #define BNX2_HC_RX_TICKS_7_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_7_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_7 0x00006aec + #define BNX2_HC_TX_TICKS_7_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_7_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_7 0x00006af0 + #define BNX2_HC_COM_TICKS_7_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_7_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_7 0x00006af4 + #define BNX2_HC_CMD_TICKS_7_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_7_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_7 0x00006af8 + #define BNX2_HC_PERIODIC_TICKS_7_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_7_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_8 0x00006afc + #define BNX2_HC_SB_CONFIG_8_RX_TMR_MODE (1L<<1) + #define BNX2_HC_SB_CONFIG_8_TX_TMR_MODE (1L<<2) + #define BNX2_HC_SB_CONFIG_8_COM_TMR_MODE (1L<<3) + #define BNX2_HC_SB_CONFIG_8_CMD_TMR_MODE (1L<<4) + #define BNX2_HC_SB_CONFIG_8_PER_MODE (1L<<16) + #define BNX2_HC_SB_CONFIG_8_ONE_SHOT (1L<<17) + #define BNX2_HC_SB_CONFIG_8_USE_INT_PARAM (1L<<18) + #define BNX2_HC_SB_CONFIG_8_PER_COLLECT_LIMIT (0xfL<<20) + + #define BNX2_HC_TX_QUICK_CONS_TRIP_8 0x00006b00 + #define BNX2_HC_TX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0) + #define BNX2_HC_TX_QUICK_CONS_TRIP_8_INT (0xffL<<16) + + #define BNX2_HC_COMP_PROD_TRIP_8 0x00006b04 + #define BNX2_HC_COMP_PROD_TRIP_8_VALUE (0xffL<<0) + #define BNX2_HC_COMP_PROD_TRIP_8_INT (0xffL<<16) + + #define BNX2_HC_RX_QUICK_CONS_TRIP_8 0x00006b08 + #define BNX2_HC_RX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0) + #define BNX2_HC_RX_QUICK_CONS_TRIP_8_INT (0xffL<<16) + + #define BNX2_HC_RX_TICKS_8 0x00006b0c + #define BNX2_HC_RX_TICKS_8_VALUE (0x3ffL<<0) + #define BNX2_HC_RX_TICKS_8_INT (0x3ffL<<16) + + #define BNX2_HC_TX_TICKS_8 0x00006b10 + #define BNX2_HC_TX_TICKS_8_VALUE (0x3ffL<<0) + #define BNX2_HC_TX_TICKS_8_INT (0x3ffL<<16) + + #define BNX2_HC_COM_TICKS_8 0x00006b14 + #define BNX2_HC_COM_TICKS_8_VALUE (0x3ffL<<0) + #define BNX2_HC_COM_TICKS_8_INT (0x3ffL<<16) + + #define BNX2_HC_CMD_TICKS_8 0x00006b18 + #define BNX2_HC_CMD_TICKS_8_VALUE (0x3ffL<<0) + #define BNX2_HC_CMD_TICKS_8_INT (0x3ffL<<16) + + #define BNX2_HC_PERIODIC_TICKS_8 0x00006b1c + #define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS (0xffffL<<0) + #define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS (0xffffL<<16) + + #define BNX2_HC_SB_CONFIG_SIZE (BNX2_HC_SB_CONFIG_2 - BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_COMP_PROD_TRIP_OFF (BNX2_HC_COMP_PROD_TRIP_1 - \ + BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_COM_TICKS_OFF (BNX2_HC_COM_TICKS_1 - BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_CMD_TICKS_OFF (BNX2_HC_CMD_TICKS_1 - BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_TX_QUICK_CONS_TRIP_OFF (BNX2_HC_TX_QUICK_CONS_TRIP_1 - \ + BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_TX_TICKS_OFF (BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_RX_QUICK_CONS_TRIP_OFF (BNX2_HC_RX_QUICK_CONS_TRIP_1 - \ + BNX2_HC_SB_CONFIG_1) + #define BNX2_HC_RX_TICKS_OFF (BNX2_HC_RX_TICKS_1 - BNX2_HC_SB_CONFIG_1) + + + /* + * txp_reg definition + * offset: 0x40000 + */ + #define BNX2_TXP_CPU_MODE 0x00045000 + #define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_TXP_CPU_STATE 0x00045004 + #define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_TXP_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_TXP_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_TXP_CPU_EVENT_MASK 0x00045008 + #define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c + #define BNX2_TXP_CPU_INSTRUCTION 0x00045020 + #define BNX2_TXP_CPU_DATA_ACCESS 0x00045024 + #define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028 + #define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c + #define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030 + #define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034 + #define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038 + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048 + #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_TXP_CPU_REG_FILE 0x00045200 + #define BNX2_TXP_TXPQ 0x000453c0 + #define BNX2_TXP_FTQ_CMD 0x000453f8 + #define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_TXP_FTQ_CMD_POP (1L<<30) + #define BNX2_TXP_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_TXP_FTQ_CTL 0x000453fc + #define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_TXP_SCRATCH 0x00060000 + + + /* + * tpat_reg definition + * offset: 0x80000 + */ + #define BNX2_TPAT_CPU_MODE 0x00085000 + #define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_TPAT_CPU_STATE 0x00085004 + #define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_TPAT_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_TPAT_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_TPAT_CPU_EVENT_MASK 0x00085008 + #define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c + #define BNX2_TPAT_CPU_INSTRUCTION 0x00085020 + #define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024 + #define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028 + #define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c + #define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030 + #define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034 + #define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038 + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048 + #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_TPAT_CPU_REG_FILE 0x00085200 + #define BNX2_TPAT_TPATQ 0x000853c0 + #define BNX2_TPAT_FTQ_CMD 0x000853f8 + #define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_TPAT_FTQ_CMD_POP (1L<<30) + #define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_TPAT_FTQ_CTL 0x000853fc + #define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_TPAT_SCRATCH 0x000a0000 + + + /* + * rxp_reg definition + * offset: 0xc0000 + */ + #define BNX2_RXP_CPU_MODE 0x000c5000 + #define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_RXP_CPU_STATE 0x000c5004 + #define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_RXP_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_RXP_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_RXP_CPU_EVENT_MASK 0x000c5008 + #define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c + #define BNX2_RXP_CPU_INSTRUCTION 0x000c5020 + #define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024 + #define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028 + #define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c + #define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030 + #define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034 + #define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038 + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048 + #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_RXP_CPU_REG_FILE 0x000c5200 + #define BNX2_RXP_PFE_PFE_CTL 0x000c537c + #define BNX2_RXP_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) + #define BNX2_RXP_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) + #define BNX2_RXP_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + + #define BNX2_RXP_RXPCQ 0x000c5380 + #define BNX2_RXP_CFTQ_CMD 0x000c53b8 + #define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10) + #define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26) + #define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_RXP_CFTQ_CMD_POP (1L<<30) + #define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31) + + #define BNX2_RXP_CFTQ_CTL 0x000c53bc + #define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0) + #define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_RXP_RXPQ 0x000c53c0 + #define BNX2_RXP_FTQ_CMD 0x000c53f8 + #define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_RXP_FTQ_CMD_POP (1L<<30) + #define BNX2_RXP_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_RXP_FTQ_CTL 0x000c53fc + #define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_RXP_SCRATCH 0x000e0000 + #define BNX2_RXP_SCRATCH_RXP_FLOOD 0x000e0024 + #define BNX2_RXP_SCRATCH_RSS_TBL_SZ 0x000e0038 + #define BNX2_RXP_SCRATCH_RSS_TBL 0x000e003c + #define BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES 128 + + + /* + * com_reg definition + * offset: 0x100000 + */ + #define BNX2_COM_CKSUM_ERROR_STATUS 0x00100000 + #define BNX2_COM_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) + #define BNX2_COM_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + + #define BNX2_COM_CPU_MODE 0x00105000 + #define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_COM_CPU_STATE 0x00105004 + #define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_COM_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_COM_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_COM_CPU_EVENT_MASK 0x00105008 + #define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c + #define BNX2_COM_CPU_INSTRUCTION 0x00105020 + #define BNX2_COM_CPU_DATA_ACCESS 0x00105024 + #define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028 + #define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c + #define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030 + #define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034 + #define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038 + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048 + #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_COM_CPU_REG_FILE 0x00105200 + #define BNX2_COM_COMTQ_PFE_PFE_CTL 0x001052bc + #define BNX2_COM_COMTQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) + #define BNX2_COM_COMTQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + + #define BNX2_COM_COMXQ 0x00105340 + #define BNX2_COM_COMXQ_FTQ_CMD 0x00105378 + #define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30) + #define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c + #define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_COM_COMTQ 0x00105380 + #define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8 + #define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30) + #define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc + #define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_COM_COMQ 0x001053c0 + #define BNX2_COM_COMQ_FTQ_CMD 0x001053f8 + #define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30) + #define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_COM_COMQ_FTQ_CTL 0x001053fc + #define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_COM_SCRATCH 0x00120000 + + #define BNX2_FW_RX_LOW_LATENCY 0x00120058 + #define BNX2_FW_RX_DROP_COUNT 0x00120084 + + + /* + * cp_reg definition + * offset: 0x180000 + */ + #define BNX2_CP_CKSUM_ERROR_STATUS 0x00180000 + #define BNX2_CP_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) + #define BNX2_CP_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + + #define BNX2_CP_CPU_MODE 0x00185000 + #define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_CP_CPU_STATE 0x00185004 + #define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_CP_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_CP_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_CP_CPU_EVENT_MASK 0x00185008 + #define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c + #define BNX2_CP_CPU_INSTRUCTION 0x00185020 + #define BNX2_CP_CPU_DATA_ACCESS 0x00185024 + #define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028 + #define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c + #define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030 + #define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034 + #define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038 + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048 + #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_CP_CPU_REG_FILE 0x00185200 + #define BNX2_CP_CPQ_PFE_PFE_CTL 0x001853bc + #define BNX2_CP_CPQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) + #define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) + #define BNX2_CP_CPQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + + #define BNX2_CP_CPQ 0x001853c0 + #define BNX2_CP_CPQ_FTQ_CMD 0x001853f8 + #define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30) + #define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_CP_CPQ_FTQ_CTL 0x001853fc + #define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_CP_SCRATCH 0x001a0000 + + #define BNX2_FW_MAX_ISCSI_CONN 0x001a0080 + + + /* + * mcp_reg definition + * offset: 0x140000 + */ + #define BNX2_MCP_MCP_CONTROL 0x00140080 + #define BNX2_MCP_MCP_CONTROL_SMBUS_SEL (1L<<30) + #define BNX2_MCP_MCP_CONTROL_MCP_ISOLATE (1L<<31) + + #define BNX2_MCP_MCP_ATTENTION_STATUS 0x00140084 + #define BNX2_MCP_MCP_ATTENTION_STATUS_DRV_DOORBELL (1L<<29) + #define BNX2_MCP_MCP_ATTENTION_STATUS_WATCHDOG_TIMEOUT (1L<<30) + #define BNX2_MCP_MCP_ATTENTION_STATUS_CPU_EVENT (1L<<31) + + #define BNX2_MCP_MCP_HEARTBEAT_CONTROL 0x00140088 + #define BNX2_MCP_MCP_HEARTBEAT_CONTROL_MCP_HEARTBEAT_ENABLE (1L<<31) + + #define BNX2_MCP_MCP_HEARTBEAT_STATUS 0x0014008c + #define BNX2_MCP_MCP_HEARTBEAT_STATUS_MCP_HEARTBEAT_PERIOD (0x7ffL<<0) + #define BNX2_MCP_MCP_HEARTBEAT_STATUS_VALID (1L<<31) + + #define BNX2_MCP_MCP_HEARTBEAT 0x00140090 + #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_COUNT (0x3fffffffL<<0) + #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_INC (1L<<30) + #define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_RESET (1L<<31) + + #define BNX2_MCP_WATCHDOG_RESET 0x00140094 + #define BNX2_MCP_WATCHDOG_RESET_WATCHDOG_RESET (1L<<31) + + #define BNX2_MCP_WATCHDOG_CONTROL 0x00140098 + #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_TIMEOUT (0xfffffffL<<0) + #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ATTN (1L<<29) + #define BNX2_MCP_WATCHDOG_CONTROL_MCP_RST_ENABLE (1L<<30) + #define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ENABLE (1L<<31) + + #define BNX2_MCP_ACCESS_LOCK 0x0014009c + #define BNX2_MCP_ACCESS_LOCK_LOCK (1L<<31) + + #define BNX2_MCP_TOE_ID 0x001400a0 + #define BNX2_MCP_TOE_ID_FUNCTION_ID (1L<<31) + + #define BNX2_MCP_MAILBOX_CFG 0x001400a4 + #define BNX2_MCP_MAILBOX_CFG_MAILBOX_OFFSET (0x3fffL<<0) + #define BNX2_MCP_MAILBOX_CFG_MAILBOX_SIZE (0xfffL<<20) + + #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC 0x001400a8 + #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_OFFSET (0x3fffL<<0) + #define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_SIZE (0xfffL<<20) + + #define BNX2_MCP_MCP_DOORBELL 0x001400ac + #define BNX2_MCP_MCP_DOORBELL_MCP_DOORBELL (1L<<31) + + #define BNX2_MCP_DRIVER_DOORBELL 0x001400b0 + #define BNX2_MCP_DRIVER_DOORBELL_DRIVER_DOORBELL (1L<<31) + + #define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC 0x001400b4 + #define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC_DRIVER_DOORBELL (1L<<31) + + #define BNX2_MCP_CPU_MODE 0x00145000 + #define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0) + #define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1) + #define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) + #define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) + #define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6) + #define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7) + #define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10) + #define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) + #define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) + #define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) + #define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + + #define BNX2_MCP_CPU_STATE 0x00145004 + #define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0) + #define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2) + #define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) + #define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) + #define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) + #define BNX2_MCP_CPU_STATE_BAD_PC_HALTED (1L<<6) + #define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7) + #define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) + #define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10) + #define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) -#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12) ++#define BNX2_MCP_CPU_STATE_INTERRUPT (1L<<12) + #define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) + #define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15) + #define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31) + + #define BNX2_MCP_CPU_EVENT_MASK 0x00145008 + #define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) + #define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) + #define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) + #define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) + #define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) + #define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) + #define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) + #define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) + #define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) + #define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) + #define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + + #define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c + #define BNX2_MCP_CPU_INSTRUCTION 0x00145020 + #define BNX2_MCP_CPU_DATA_ACCESS 0x00145024 + #define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028 + #define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c + #define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030 + #define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034 + #define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) + #define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038 + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) + #define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + #define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048 + #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) + #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) + #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) + #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + + #define BNX2_MCP_CPU_REG_FILE 0x00145200 + #define BNX2_MCP_MCPQ 0x001453c0 + #define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8 + #define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0) + #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10) + #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10) + #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10) + #define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25) + #define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26) + #define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27) + #define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28) + #define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29) + #define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30) + #define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31) + + #define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc + #define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0) + #define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1) + #define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) + #define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) + #define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + #define BNX2_MCP_ROM 0x00150000 + #define BNX2_MCP_SCRATCH 0x00160000 + #define BNX2_MCP_STATE_P1 0x0016f9c8 + #define BNX2_MCP_STATE_P0 0x0016fdc8 + #define BNX2_MCP_STATE_P1_5708 0x001699c8 + #define BNX2_MCP_STATE_P0_5708 0x00169dc8 + + #define BNX2_SHM_HDR_SIGNATURE BNX2_MCP_SCRATCH + #define BNX2_SHM_HDR_SIGNATURE_SIG_MASK 0xffff0000 + #define BNX2_SHM_HDR_SIGNATURE_SIG 0x53530000 + #define BNX2_SHM_HDR_SIGNATURE_VER_MASK 0x000000ff + #define BNX2_SHM_HDR_SIGNATURE_VER_ONE 0x00000001 + + #define BNX2_SHM_HDR_ADDR_0 BNX2_MCP_SCRATCH + 4 + #define BNX2_SHM_HDR_ADDR_1 BNX2_MCP_SCRATCH + 8 + + + #define NUM_MC_HASH_REGISTERS 8 + + + /* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */ + #define PHY_BCM5706_PHY_ID 0x00206160 + + #define PHY_ID(id) ((id) & 0xfffffff0) + #define PHY_REV_ID(id) ((id) & 0xf) + + /* 5708 Serdes PHY registers */ + + #define BCM5708S_BMCR_FORCE_2500 0x20 + + #define BCM5708S_UP1 0xb + + #define BCM5708S_UP1_2G5 0x1 + + #define BCM5708S_BLK_ADDR 0x1f + + #define BCM5708S_BLK_ADDR_DIG 0x0000 + #define BCM5708S_BLK_ADDR_DIG3 0x0002 + #define BCM5708S_BLK_ADDR_TX_MISC 0x0005 + + /* Digital Block */ + #define BCM5708S_1000X_CTL1 0x10 + + #define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001 + #define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010 + + #define BCM5708S_1000X_CTL2 0x11 + + #define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001 + + #define BCM5708S_1000X_STAT1 0x14 + + #define BCM5708S_1000X_STAT1_SGMII 0x0001 + #define BCM5708S_1000X_STAT1_LINK 0x0002 + #define BCM5708S_1000X_STAT1_FD 0x0004 + #define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018 + #define BCM5708S_1000X_STAT1_SPEED_10 0x0000 + #define BCM5708S_1000X_STAT1_SPEED_100 0x0008 + #define BCM5708S_1000X_STAT1_SPEED_1G 0x0010 + #define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018 + #define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020 + #define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040 + + /* Digital3 Block */ + #define BCM5708S_DIG_3_0 0x10 + + #define BCM5708S_DIG_3_0_USE_IEEE 0x0001 + + /* Tx/Misc Block */ + #define BCM5708S_TX_ACTL1 0x15 + + #define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30 + + #define BCM5708S_TX_ACTL3 0x17 + + #define MII_BNX2_DSP_RW_PORT 0x15 + #define MII_BNX2_DSP_ADDRESS 0x17 + #define MII_BNX2_DSP_EXPAND_REG 0x0f00 + #define MII_EXPAND_REG1 (MII_BNX2_DSP_EXPAND_REG | 1) + #define MII_EXPAND_REG1_RUDI_C 0x20 + #define MII_EXPAND_SERDES_CTL (MII_BNX2_DSP_EXPAND_REG | 3) + + #define MII_BNX2_MISC_SHADOW 0x1c + #define MISC_SHDW_AN_DBG 0x6800 + #define MISC_SHDW_AN_DBG_NOSYNC 0x0002 + #define MISC_SHDW_AN_DBG_RUDI_INVALID 0x0100 + #define MISC_SHDW_MODE_CTL 0x7c00 + #define MISC_SHDW_MODE_CTL_SIG_DET 0x0010 + + #define MII_BNX2_BLK_ADDR 0x1f + #define MII_BNX2_BLK_ADDR_IEEE0 0x0000 + #define MII_BNX2_BLK_ADDR_GP_STATUS 0x8120 + #define MII_BNX2_GP_TOP_AN_STATUS1 0x1b + #define MII_BNX2_GP_TOP_AN_SPEED_MSK 0x3f00 + #define MII_BNX2_GP_TOP_AN_SPEED_10 0x0000 + #define MII_BNX2_GP_TOP_AN_SPEED_100 0x0100 + #define MII_BNX2_GP_TOP_AN_SPEED_1G 0x0200 + #define MII_BNX2_GP_TOP_AN_SPEED_2_5G 0x0300 + #define MII_BNX2_GP_TOP_AN_SPEED_1GKV 0x0d00 + #define MII_BNX2_GP_TOP_AN_FD 0x8 + #define MII_BNX2_BLK_ADDR_SERDES_DIG 0x8300 + #define MII_BNX2_SERDES_DIG_1000XCTL1 0x10 + #define MII_BNX2_SD_1000XCTL1_FIBER 0x01 + #define MII_BNX2_SD_1000XCTL1_AUTODET 0x10 + #define MII_BNX2_SERDES_DIG_MISC1 0x18 + #define MII_BNX2_SD_MISC1_FORCE_MSK 0xf + #define MII_BNX2_SD_MISC1_FORCE_2_5G 0x0 + #define MII_BNX2_SD_MISC1_FORCE 0x10 + #define MII_BNX2_BLK_ADDR_OVER1G 0x8320 + #define MII_BNX2_OVER1G_UP1 0x19 + #define MII_BNX2_BLK_ADDR_BAM_NXTPG 0x8350 + #define MII_BNX2_BAM_NXTPG_CTL 0x10 + #define MII_BNX2_NXTPG_CTL_BAM 0x1 + #define MII_BNX2_NXTPG_CTL_T2 0x2 + #define MII_BNX2_BLK_ADDR_CL73_USERB0 0x8370 + #define MII_BNX2_CL73_BAM_CTL1 0x12 + #define MII_BNX2_CL73_BAM_EN 0x8000 + #define MII_BNX2_CL73_BAM_STA_MGR_EN 0x4000 + #define MII_BNX2_CL73_BAM_NP_AFT_BP_EN 0x2000 + #define MII_BNX2_BLK_ADDR_AER 0xffd0 + #define MII_BNX2_AER_AER 0x1e + #define MII_BNX2_AER_AER_AN_MMD 0x3800 + #define MII_BNX2_BLK_ADDR_COMBO_IEEEB0 0xffe0 + + #define MIN_ETHERNET_PACKET_SIZE 60 + #define MAX_ETHERNET_PACKET_SIZE 1514 + #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 + + #define BNX2_RX_COPY_THRESH 128 + + #define BNX2_MISC_ENABLE_DEFAULT 0x17ffffff + + #define BNX2_START_UNICAST_ADDRESS_INDEX 4 + #define BNX2_END_UNICAST_ADDRESS_INDEX 7 + #define BNX2_MAX_UNICAST_ADDRESSES (BNX2_END_UNICAST_ADDRESS_INDEX - \ + BNX2_START_UNICAST_ADDRESS_INDEX + 1) + + #define DMA_READ_CHANS 5 + #define DMA_WRITE_CHANS 3 + + /* Use CPU native page size up to 16K for the ring sizes. */ + #if (PAGE_SHIFT > 14) + #define BCM_PAGE_BITS 14 + #else + #define BCM_PAGE_BITS PAGE_SHIFT + #endif + #define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS) + + #define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) + #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) + + #define MAX_RX_RINGS 8 + #define MAX_RX_PG_RINGS 32 + #define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd)) + #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1) + #define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS) + #define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS) + + #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \ + (MAX_TX_DESC_CNT - 1)) ? \ + (x) + 2 : (x) + 1 + + #define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT) + + #define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \ + (MAX_RX_DESC_CNT - 1)) ? \ + (x) + 2 : (x) + 1 + + #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx) + #define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx) + + #define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4)) + #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT) + + /* Context size. */ + #define CTX_SHIFT 7 + #define CTX_SIZE (1 << CTX_SHIFT) + #define CTX_MASK (CTX_SIZE - 1) + #define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT) + #define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT) + + #define PHY_CTX_SHIFT 6 + #define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT) + #define PHY_CTX_MASK (PHY_CTX_SIZE - 1) + #define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT) + #define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT) + + #define MB_KERNEL_CTX_SHIFT 8 + #define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT) + #define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1) + #define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT)) + + #define MAX_CID_CNT 0x4000 + #define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT)) + #define INVALID_CID_ADDR 0xffffffff + + #define TX_CID 16 + #define TX_TSS_CID 32 + #define RX_CID 0 + #define RX_RSS_CID 4 + #define RX_MAX_RSS_RINGS 7 + #define RX_MAX_RINGS (RX_MAX_RSS_RINGS + 1) + #define TX_MAX_TSS_RINGS 7 + #define TX_MAX_RINGS (TX_MAX_TSS_RINGS + 1) + + #define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID) + #define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID) + + struct sw_bd { + struct sk_buff *skb; + struct l2_fhdr *desc; + DEFINE_DMA_UNMAP_ADDR(mapping); + }; + + struct sw_pg { + struct page *page; + DEFINE_DMA_UNMAP_ADDR(mapping); + }; + + struct sw_tx_bd { + struct sk_buff *skb; + DEFINE_DMA_UNMAP_ADDR(mapping); + unsigned short is_gso; + unsigned short nr_frags; + }; + + #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT) + #define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT) + #define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT) + #define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT) + #define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT) + + /* Buffered flash (Atmel: AT45DB011B) specific information */ + #define SEEPROM_PAGE_BITS 2 + #define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS) + #define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1) + #define SEEPROM_PAGE_SIZE 4 + #define SEEPROM_TOTAL_SIZE 65536 + + #define BUFFERED_FLASH_PAGE_BITS 9 + #define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS) + #define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1) + #define BUFFERED_FLASH_PAGE_SIZE 264 + #define BUFFERED_FLASH_TOTAL_SIZE 0x21000 + + #define SAIFUN_FLASH_PAGE_BITS 8 + #define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS) + #define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1) + #define SAIFUN_FLASH_PAGE_SIZE 256 + #define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536 + + #define ST_MICRO_FLASH_PAGE_BITS 8 + #define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_PAGE_BITS) + #define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1) + #define ST_MICRO_FLASH_PAGE_SIZE 256 + #define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536 + + #define BCM5709_FLASH_PAGE_BITS 8 + #define BCM5709_FLASH_PHY_PAGE_SIZE (1 << BCM5709_FLASH_PAGE_BITS) + #define BCM5709_FLASH_BYTE_ADDR_MASK (BCM5709_FLASH_PHY_PAGE_SIZE-1) + #define BCM5709_FLASH_PAGE_SIZE 256 + + #define NVRAM_TIMEOUT_COUNT 30000 + + + #define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \ + BNX2_NVM_CFG1_BUFFER_MODE | \ + BNX2_NVM_CFG1_PROTECT_MODE | \ + BNX2_NVM_CFG1_FLASH_SIZE) + + #define FLASH_BACKUP_STRAP_MASK (0xf << 26) + + struct flash_spec { + u32 strapping; + u32 config1; + u32 config2; + u32 config3; + u32 write1; + u32 flags; + #define BNX2_NV_BUFFERED 0x00000001 + #define BNX2_NV_TRANSLATE 0x00000002 + #define BNX2_NV_WREN 0x00000004 + u32 page_bits; + u32 page_size; + u32 addr_mask; + u32 total_size; + u8 *name; + }; + + #define BNX2_MAX_MSIX_HW_VEC 9 + #define BNX2_MAX_MSIX_VEC 9 + #ifdef BCM_CNIC + #define BNX2_MIN_MSIX_VEC 2 + #else + #define BNX2_MIN_MSIX_VEC 1 + #endif + + + struct bnx2_irq { + irq_handler_t handler; + unsigned int vector; + u8 requested; + char name[IFNAMSIZ + 2]; + }; + + struct bnx2_tx_ring_info { + u32 tx_prod_bseq; + u16 tx_prod; + u32 tx_bidx_addr; + u32 tx_bseq_addr; + + struct tx_bd *tx_desc_ring; + struct sw_tx_bd *tx_buf_ring; + + u16 tx_cons; + u16 hw_tx_cons; + + dma_addr_t tx_desc_mapping; + }; + + struct bnx2_rx_ring_info { + u32 rx_prod_bseq; + u16 rx_prod; + u16 rx_cons; + + u32 rx_bidx_addr; + u32 rx_bseq_addr; + u32 rx_pg_bidx_addr; + + u16 rx_pg_prod; + u16 rx_pg_cons; + + struct sw_bd *rx_buf_ring; + struct rx_bd *rx_desc_ring[MAX_RX_RINGS]; + struct sw_pg *rx_pg_ring; + struct rx_bd *rx_pg_desc_ring[MAX_RX_PG_RINGS]; + + dma_addr_t rx_desc_mapping[MAX_RX_RINGS]; + dma_addr_t rx_pg_desc_mapping[MAX_RX_PG_RINGS]; + }; + + struct bnx2_napi { + struct napi_struct napi ____cacheline_aligned; + struct bnx2 *bp; + union { + struct status_block *msi; + struct status_block_msix *msix; + } status_blk; + u16 *hw_tx_cons_ptr; + u16 *hw_rx_cons_ptr; + u32 last_status_idx; + u32 int_num; + + #ifdef BCM_CNIC + u32 cnic_tag; + int cnic_present; + #endif + + struct bnx2_rx_ring_info rx_ring; + struct bnx2_tx_ring_info tx_ring; + }; + + struct bnx2 { + /* Fields used in the tx and intr/napi performance paths are grouped */ + /* together in the beginning of the structure. */ + void __iomem *regview; + + struct net_device *dev; + struct pci_dev *pdev; + + atomic_t intr_sem; + + u32 flags; + #define BNX2_FLAG_PCIX 0x00000001 + #define BNX2_FLAG_PCI_32BIT 0x00000002 + #define BNX2_FLAG_MSIX_CAP 0x00000004 + #define BNX2_FLAG_NO_WOL 0x00000008 + #define BNX2_FLAG_USING_MSI 0x00000020 + #define BNX2_FLAG_ASF_ENABLE 0x00000040 + #define BNX2_FLAG_MSI_CAP 0x00000080 + #define BNX2_FLAG_ONE_SHOT_MSI 0x00000100 + #define BNX2_FLAG_PCIE 0x00000200 + #define BNX2_FLAG_USING_MSIX 0x00000400 + #define BNX2_FLAG_USING_MSI_OR_MSIX (BNX2_FLAG_USING_MSI | \ + BNX2_FLAG_USING_MSIX) + #define BNX2_FLAG_JUMBO_BROKEN 0x00000800 + #define BNX2_FLAG_CAN_KEEP_VLAN 0x00001000 + #define BNX2_FLAG_BROKEN_STATS 0x00002000 + #define BNX2_FLAG_AER_ENABLED 0x00004000 + + struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC]; + + u32 rx_buf_use_size; /* useable size */ + u32 rx_buf_size; /* with alignment */ + u32 rx_copy_thresh; + u32 rx_jumbo_thresh; + u32 rx_max_ring_idx; + u32 rx_max_pg_ring_idx; + + /* TX constants */ + int tx_ring_size; + u32 tx_wake_thresh; + + #ifdef BCM_CNIC + struct cnic_ops __rcu *cnic_ops; + void *cnic_data; + #endif + + /* End of fields used in the performance code paths. */ + + unsigned int current_interval; + #define BNX2_TIMER_INTERVAL HZ + #define BNX2_SERDES_AN_TIMEOUT (HZ / 3) + #define BNX2_SERDES_FORCED_TIMEOUT (HZ / 10) + + struct timer_list timer; + struct work_struct reset_task; + + /* Used to synchronize phy accesses. */ + spinlock_t phy_lock; + spinlock_t indirect_lock; + + u32 phy_flags; + #define BNX2_PHY_FLAG_SERDES 0x00000001 + #define BNX2_PHY_FLAG_CRC_FIX 0x00000002 + #define BNX2_PHY_FLAG_PARALLEL_DETECT 0x00000004 + #define BNX2_PHY_FLAG_2_5G_CAPABLE 0x00000008 + #define BNX2_PHY_FLAG_INT_MODE_MASK 0x00000300 + #define BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING 0x00000100 + #define BNX2_PHY_FLAG_INT_MODE_LINK_READY 0x00000200 + #define BNX2_PHY_FLAG_DIS_EARLY_DAC 0x00000400 + #define BNX2_PHY_FLAG_REMOTE_PHY_CAP 0x00000800 + #define BNX2_PHY_FLAG_FORCED_DOWN 0x00001000 + #define BNX2_PHY_FLAG_NO_PARALLEL 0x00002000 + + u32 mii_bmcr; + u32 mii_bmsr; + u32 mii_bmsr1; + u32 mii_adv; + u32 mii_lpa; + u32 mii_up1; + + u32 chip_id; + /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ + #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) + #define CHIP_NUM_5706 0x57060000 + #define CHIP_NUM_5708 0x57080000 + #define CHIP_NUM_5709 0x57090000 + + #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) + #define CHIP_REV_Ax 0x00000000 + #define CHIP_REV_Bx 0x00001000 + #define CHIP_REV_Cx 0x00002000 + + #define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0) + #define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f) + + #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) + #define CHIP_ID_5706_A0 0x57060000 + #define CHIP_ID_5706_A1 0x57060010 + #define CHIP_ID_5706_A2 0x57060020 + #define CHIP_ID_5708_A0 0x57080000 + #define CHIP_ID_5708_B0 0x57081000 + #define CHIP_ID_5708_B1 0x57081010 + #define CHIP_ID_5709_A0 0x57090000 + #define CHIP_ID_5709_A1 0x57090010 + + #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) + + /* A serdes chip will have the first bit of the bond id set. */ + #define CHIP_BOND_ID_SERDES_BIT 0x01 + + u32 phy_addr; + u32 phy_id; + + u16 bus_speed_mhz; + u8 wol; + + u8 pad; + + u16 fw_wr_seq; + u16 fw_drv_pulse_wr_seq; + + int rx_max_ring; + int rx_ring_size; + + int rx_max_pg_ring; + int rx_pg_ring_size; + + u16 tx_quick_cons_trip; + u16 tx_quick_cons_trip_int; + u16 rx_quick_cons_trip; + u16 rx_quick_cons_trip_int; + u16 comp_prod_trip; + u16 comp_prod_trip_int; + u16 tx_ticks; + u16 tx_ticks_int; + u16 com_ticks; + u16 com_ticks_int; + u16 cmd_ticks; + u16 cmd_ticks_int; + u16 rx_ticks; + u16 rx_ticks_int; + + u32 stats_ticks; + + dma_addr_t status_blk_mapping; + + struct statistics_block *stats_blk; + struct statistics_block *temp_stats_blk; + dma_addr_t stats_blk_mapping; + + int ctx_pages; + void *ctx_blk[4]; + dma_addr_t ctx_blk_mapping[4]; + + u32 hc_cmd; + u32 rx_mode; + + u16 req_line_speed; + u8 req_duplex; + + u8 phy_port; + u8 link_up; + + u16 line_speed; + u8 duplex; + u8 flow_ctrl; /* actual flow ctrl settings */ + /* may be different from */ + /* req_flow_ctrl if autoneg */ + u32 advertising; + + u8 req_flow_ctrl; /* flow ctrl advertisement */ + /* settings or forced */ + /* settings */ + u8 autoneg; + #define AUTONEG_SPEED 1 + #define AUTONEG_FLOW_CTRL 2 + + u8 loopback; + #define MAC_LOOPBACK 1 + #define PHY_LOOPBACK 2 + + u8 serdes_an_pending; + + u8 mac_addr[8]; + + u32 shmem_base; + + char fw_version[32]; + + int pm_cap; + int pcix_cap; + + const struct flash_spec *flash_info; + u32 flash_size; + + int status_stats_size; + + struct bnx2_irq irq_tbl[BNX2_MAX_MSIX_VEC]; + int irq_nvecs; + + u8 num_tx_rings; + u8 num_rx_rings; + + u32 leds_save; + u32 idle_chk_status_idx; + + #ifdef BCM_CNIC + struct mutex cnic_lock; + struct cnic_eth_dev cnic_eth_dev; + #endif + + const struct firmware *mips_firmware; + const struct firmware *rv2p_firmware; + }; + + #define REG_RD(bp, offset) \ + readl(bp->regview + offset) + + #define REG_WR(bp, offset, val) \ + writel(val, bp->regview + offset) + + #define REG_WR16(bp, offset, val) \ + writew(val, bp->regview + offset) + + struct cpu_reg { + u32 mode; + u32 mode_value_halt; + u32 mode_value_sstep; + + u32 state; + u32 state_value_clear; + + u32 gpr0; + u32 evmask; + u32 pc; + u32 inst; + u32 bp; + + u32 spad_base; + + u32 mips_view_base; + }; + + struct bnx2_fw_file_section { + __be32 addr; + __be32 len; + __be32 offset; + }; + + struct bnx2_mips_fw_file_entry { + __be32 start_addr; + struct bnx2_fw_file_section text; + struct bnx2_fw_file_section data; + struct bnx2_fw_file_section rodata; + }; + + struct bnx2_rv2p_fw_file_entry { + struct bnx2_fw_file_section rv2p; + __be32 fixup[8]; + }; + + struct bnx2_mips_fw_file { + struct bnx2_mips_fw_file_entry com; + struct bnx2_mips_fw_file_entry cp; + struct bnx2_mips_fw_file_entry rxp; + struct bnx2_mips_fw_file_entry tpat; + struct bnx2_mips_fw_file_entry txp; + }; + + struct bnx2_rv2p_fw_file { + struct bnx2_rv2p_fw_file_entry proc1; + struct bnx2_rv2p_fw_file_entry proc2; + }; + + #define RV2P_P1_FIXUP_PAGE_SIZE_IDX 0 + #define RV2P_BD_PAGE_SIZE_MSK 0xffff + #define RV2P_BD_PAGE_SIZE ((BCM_PAGE_SIZE / 16) - 1) + + #define RV2P_PROC1 0 + #define RV2P_PROC2 1 + + + /* This value (in milliseconds) determines the frequency of the driver + * issuing the PULSE message code. The firmware monitors this periodic + * pulse to determine when to switch to an OS-absent mode. */ + #define BNX2_DRV_PULSE_PERIOD_MS 250 + + /* This value (in milliseconds) determines how long the driver should + * wait for an acknowledgement from the firmware before timing out. Once + * the firmware has timed out, the driver will assume there is no firmware + * running and there won't be any firmware-driver synchronization during a + * driver reset. */ + #define BNX2_FW_ACK_TIME_OUT_MS 1000 + + + #define BNX2_DRV_RESET_SIGNATURE 0x00000000 + #define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */ + //#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */ + + #define BNX2_DRV_MB 0x00000004 + #define BNX2_DRV_MSG_CODE 0xff000000 + #define BNX2_DRV_MSG_CODE_RESET 0x01000000 + #define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000 + #define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000 + #define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000 + #define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000 + #define BNX2_DRV_MSG_CODE_PULSE 0x06000000 + #define BNX2_DRV_MSG_CODE_DIAG 0x07000000 + #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000 + #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN 0x0b000000 + #define BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE 0x0d000000 + #define BNX2_DRV_MSG_CODE_CMD_SET_LINK 0x10000000 + + #define BNX2_DRV_MSG_DATA 0x00ff0000 + #define BNX2_DRV_MSG_DATA_WAIT0 0x00010000 + #define BNX2_DRV_MSG_DATA_WAIT1 0x00020000 + #define BNX2_DRV_MSG_DATA_WAIT2 0x00030000 + #define BNX2_DRV_MSG_DATA_WAIT3 0x00040000 + + #define BNX2_DRV_MSG_SEQ 0x0000ffff + + #define BNX2_FW_MB 0x00000008 + #define BNX2_FW_MSG_ACK 0x0000ffff + #define BNX2_FW_MSG_STATUS_MASK 0x00ff0000 + #define BNX2_FW_MSG_STATUS_OK 0x00000000 + #define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000 + + #define BNX2_LINK_STATUS 0x0000000c + #define BNX2_LINK_STATUS_INIT_VALUE 0xffffffff + #define BNX2_LINK_STATUS_LINK_UP 0x1 + #define BNX2_LINK_STATUS_LINK_DOWN 0x0 + #define BNX2_LINK_STATUS_SPEED_MASK 0x1e + #define BNX2_LINK_STATUS_AN_INCOMPLETE (0<<1) + #define BNX2_LINK_STATUS_10HALF (1<<1) + #define BNX2_LINK_STATUS_10FULL (2<<1) + #define BNX2_LINK_STATUS_100HALF (3<<1) + #define BNX2_LINK_STATUS_100BASE_T4 (4<<1) + #define BNX2_LINK_STATUS_100FULL (5<<1) + #define BNX2_LINK_STATUS_1000HALF (6<<1) + #define BNX2_LINK_STATUS_1000FULL (7<<1) + #define BNX2_LINK_STATUS_2500HALF (8<<1) + #define BNX2_LINK_STATUS_2500FULL (9<<1) + #define BNX2_LINK_STATUS_AN_ENABLED (1<<5) + #define BNX2_LINK_STATUS_AN_COMPLETE (1<<6) + #define BNX2_LINK_STATUS_PARALLEL_DET (1<<7) + #define BNX2_LINK_STATUS_RESERVED (1<<8) + #define BNX2_LINK_STATUS_PARTNER_AD_1000FULL (1<<9) + #define BNX2_LINK_STATUS_PARTNER_AD_1000HALF (1<<10) + #define BNX2_LINK_STATUS_PARTNER_AD_100BT4 (1<<11) + #define BNX2_LINK_STATUS_PARTNER_AD_100FULL (1<<12) + #define BNX2_LINK_STATUS_PARTNER_AD_100HALF (1<<13) + #define BNX2_LINK_STATUS_PARTNER_AD_10FULL (1<<14) + #define BNX2_LINK_STATUS_PARTNER_AD_10HALF (1<<15) + #define BNX2_LINK_STATUS_TX_FC_ENABLED (1<<16) + #define BNX2_LINK_STATUS_RX_FC_ENABLED (1<<17) + #define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP (1<<18) + #define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP (1<<19) + #define BNX2_LINK_STATUS_SERDES_LINK (1<<20) + #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21) + #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22) + #define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED (1<<31) + + #define BNX2_DRV_PULSE_MB 0x00000010 + #define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff + + /* Indicate to the firmware not to go into the + * OS absent when it is not getting driver pulse. + * This is used for debugging. */ + #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 + + #define BNX2_DRV_MB_ARG0 0x00000014 + #define BNX2_NETLINK_SET_LINK_SPEED_10HALF (1<<0) + #define BNX2_NETLINK_SET_LINK_SPEED_10FULL (1<<1) + #define BNX2_NETLINK_SET_LINK_SPEED_10 \ + (BNX2_NETLINK_SET_LINK_SPEED_10HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_10FULL) + #define BNX2_NETLINK_SET_LINK_SPEED_100HALF (1<<2) + #define BNX2_NETLINK_SET_LINK_SPEED_100FULL (1<<3) + #define BNX2_NETLINK_SET_LINK_SPEED_100 \ + (BNX2_NETLINK_SET_LINK_SPEED_100HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_100FULL) + #define BNX2_NETLINK_SET_LINK_SPEED_1GHALF (1<<4) + #define BNX2_NETLINK_SET_LINK_SPEED_1GFULL (1<<5) + #define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF (1<<6) + #define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL (1<<7) + #define BNX2_NETLINK_SET_LINK_SPEED_10GHALF (1<<8) + #define BNX2_NETLINK_SET_LINK_SPEED_10GFULL (1<<9) + #define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG (1<<10) + #define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE (1<<11) + #define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE (1<<12) + #define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE (1<<13) + #define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED (1<<14) + #define BNX2_NETLINK_SET_LINK_PHY_RESET (1<<15) + + #define BNX2_DEV_INFO_SIGNATURE 0x00000020 + #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 + #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00 + #define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01 + #define BNX2_DEV_INFO_SECONDARY_PORT 0x80 + #define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40 + + #define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024 + + #define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034 + #define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000 + #define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000 + #define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00 + #define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff + + #define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038 + #define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c + #define BNX2_SHARED_HW_CFG_DESIGN_NIC 0 + #define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1 + #define BNX2_SHARED_HW_CFG_PHY_COPPER 0 + #define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2 + #define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20 + #define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40 + #define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8 + #define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300 + #define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0 + #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100 + #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200 + #define BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX 0x8000 + + #define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040 + #define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000 + + #define BNX2_DEV_INFO_BC_REV 0x0000004c + + #define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050 + #define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff + + #define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 + #define BNX2_PORT_HW_CFG_CONFIG 0x00000058 + #define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff + #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000 + #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000 + #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000 + #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000 + + #define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 + #define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c + #define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070 + #define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074 + #define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078 + #define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c + + #define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4 + + #define BNX2_DEV_INFO_FORMAT_REV 0x000000c4 + #define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000 + #define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24) + + #define BNX2_SHARED_FEATURE 0x000000c8 + #define BNX2_SHARED_FEATURE_MASK 0xffffffff + + #define BNX2_PORT_FEATURE 0x000000d8 + #define BNX2_PORT2_FEATURE 0x00000014c + #define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000 + #define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000 + #define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000 + #define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000 + #define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf + #define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0 + #define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1 + #define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2 + #define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3 + #define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4 + #define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5 + #define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6 + #define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7 + #define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8 + #define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9 + #define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa + #define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb + #define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc + #define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd + #define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe + #define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf + + #define BNX2_PORT_FEATURE_WOL 0xdc + #define BNX2_PORT2_FEATURE_WOL 0x150 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20 + #define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5 + #define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6 + #define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40 + #define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400 + #define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800 + + #define BNX2_PORT_FEATURE_MBA 0xe0 + #define BNX2_PORT2_FEATURE_MBA 0x154 + #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0 + #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3 + #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0 + #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1 + #define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14 + #define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18 + #define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40 + #define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0 + #define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00 + #define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00 + #define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16 + #define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000 + #define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000 + + #define BNX2_PORT_FEATURE_IMD 0xe4 + #define BNX2_PORT2_FEATURE_IMD 0x158 + #define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0 + #define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1 + + #define BNX2_PORT_FEATURE_VLAN 0xe8 + #define BNX2_PORT2_FEATURE_VLAN 0x15c + #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff + #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000 + + #define BNX2_MFW_VER_PTR 0x00000014c + + #define BNX2_BC_STATE_RESET_TYPE 0x000001c0 + #define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254 + #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff + #define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00010000) + #define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00020000) + #define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00030000) + #define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE + #define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_RESET) + #define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_UNLOAD) + #define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_SHUTDOWN) + #define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_WOL) + #define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_DIAG) + #define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \ + (msg)) + + #define BNX2_BC_STATE 0x000001c4 + #define BNX2_BC_STATE_ERR_MASK 0x0000ff00 + #define BNX2_BC_STATE_SIGN 0x42530000 + #define BNX2_BC_STATE_SIGN_MASK 0xffff0000 + #define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1) + #define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2) + #define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3) + #define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4) + #define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5) + #define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6) + #define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7) + #define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8) + #define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9) + #define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81) + #define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82) + #define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83) + #define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84) + #define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85) + #define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86) + #define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87) + #define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88) + #define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89) + #define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100) + #define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200) + #define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300) + #define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400) + #define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500) + #define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600) + #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700) + + #define BNX2_BC_STATE_CONDITION 0x000001c8 + #define BNX2_CONDITION_MFW_RUN_UNKNOWN 0x00000000 + #define BNX2_CONDITION_MFW_RUN_IPMI 0x00002000 + #define BNX2_CONDITION_MFW_RUN_UMP 0x00004000 + #define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000 + #define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000 + #define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000 + + #define BNX2_BC_STATE_DEBUG_CMD 0x1dc + #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 + #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000 + #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff + #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff + + #define BNX2_FW_EVT_CODE_MB 0x354 + #define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000 + #define BNX2_FW_EVT_CODE_LINK_EVENT 0x00000001 + + #define BNX2_DRV_ACK_CAP_MB 0x364 + #define BNX2_DRV_ACK_CAP_SIGNATURE 0x35450000 + #define BNX2_CAPABILITY_SIGNATURE_MASK 0xFFFF0000 + + #define BNX2_FW_CAP_MB 0x368 + #define BNX2_FW_CAP_SIGNATURE 0xaa550000 + #define BNX2_FW_ACK_DRV_SIGNATURE 0x52500000 + #define BNX2_FW_CAP_SIGNATURE_MASK 0xffff0000 + #define BNX2_FW_CAP_REMOTE_PHY_CAPABLE 0x00000001 + #define BNX2_FW_CAP_REMOTE_PHY_PRESENT 0x00000002 + #define BNX2_FW_CAP_MFW_CAN_KEEP_VLAN 0x00000008 + #define BNX2_FW_CAP_BC_CAN_KEEP_VLAN 0x00000010 + #define BNX2_FW_CAP_CAN_KEEP_VLAN (BNX2_FW_CAP_BC_CAN_KEEP_VLAN | \ + BNX2_FW_CAP_MFW_CAN_KEEP_VLAN) + + #define BNX2_RPHY_SIGNATURE 0x36c + #define BNX2_RPHY_LOAD_SIGNATURE 0x5a5a5a5a + + #define BNX2_RPHY_FLAGS 0x370 + #define BNX2_RPHY_SERDES_LINK 0x374 + #define BNX2_RPHY_COPPER_LINK 0x378 + + #define BNX2_ISCSI_INITIATOR 0x3dc + #define BNX2_ISCSI_INITIATOR_EN 0x00080000 + + #define BNX2_ISCSI_MAX_CONN 0x3e4 + #define BNX2_ISCSI_MAX_CONN_MASK 0xffff0000 + #define BNX2_ISCSI_MAX_CONN_SHIFT 16 + + #define HOST_VIEW_SHMEM_BASE 0x167c00 + + #define DP_SHMEM_LINE(bp, offset) \ + netdev_err(bp->dev, "DEBUG: %08x: %08x %08x %08x %08x\n", \ + offset, \ + bnx2_shmem_rd(bp, offset), \ + bnx2_shmem_rd(bp, offset + 4), \ + bnx2_shmem_rd(bp, offset + 8), \ + bnx2_shmem_rd(bp, offset + 12)) + + #endif diff --cc drivers/net/ethernet/dec/tulip/21142.c index 000000000000,092c3faa882a..25b8deedbef8 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/21142.c +++ b/drivers/net/ethernet/dec/tulip/21142.c @@@ -1,0 -1,260 +1,257 @@@ + /* + drivers/net/tulip/21142.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + DC21143 manual "21143 PCI/CardBus 10/100Mb/s Ethernet LAN Controller + Hardware Reference Manual" is currently available at : + http://developer.intel.com/design/network/manuals/278074.htm + + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + #include + #include "tulip.h" + + + static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; + u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; + static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; + + + /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list + of available transceivers. */ + void t21142_media_task(struct work_struct *work) + { + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; + void __iomem *ioaddr = tp->base_addr; + int csr12 = ioread32(ioaddr + CSR12); + int next_tick = 60*HZ; + int new_csr6 = 0; + int csr14 = ioread32(ioaddr + CSR14); + + /* CSR12[LS10,LS100] are not reliable during autonegotiation */ + if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000) + csr12 |= 6; + if (tulip_debug > 2) + dev_info(&dev->dev, "21143 negotiation status %08x, %s\n", + csr12, medianame[dev->if_port]); + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + if (tulip_check_duplex(dev) < 0) { + netif_carrier_off(dev); + next_tick = 3*HZ; + } else { + netif_carrier_on(dev); + next_tick = 60*HZ; + } + } else if (tp->nwayset) { + /* Don't screw up a negotiated session! */ + if (tulip_debug > 1) + dev_info(&dev->dev, + "Using NWay-set %s media, csr12 %08x\n", + medianame[dev->if_port], csr12); + } else if (tp->medialock) { + ; + } else if (dev->if_port == 3) { + if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ + if (tulip_debug > 1) + dev_info(&dev->dev, + "No 21143 100baseTx link beat, %08x, trying NWay\n", + csr12); + t21142_start_nway(dev); + next_tick = 3*HZ; + } + } else if ((csr12 & 0x7000) != 0x5000) { + /* Negotiation failed. Search media types. */ + if (tulip_debug > 1) + dev_info(&dev->dev, + "21143 negotiation failed, status %08x\n", + csr12); + if (!(csr12 & 4)) { /* 10mbps link beat good. */ + new_csr6 = 0x82420000; + dev->if_port = 0; + iowrite32(0, ioaddr + CSR13); + iowrite32(0x0003FFFF, ioaddr + CSR14); + iowrite16(t21142_csr15[dev->if_port], ioaddr + CSR15); + iowrite32(t21142_csr13[dev->if_port], ioaddr + CSR13); + } else { + /* Select 100mbps port to check for link beat. */ + new_csr6 = 0x83860000; + dev->if_port = 3; + iowrite32(0, ioaddr + CSR13); + iowrite32(0x0003FFFF, ioaddr + CSR14); + iowrite16(8, ioaddr + CSR15); + iowrite32(1, ioaddr + CSR13); + } + if (tulip_debug > 1) + dev_info(&dev->dev, "Testing new 21143 media %s\n", + medianame[dev->if_port]); + if (new_csr6 != (tp->csr6 & ~0x00D5)) { + tp->csr6 &= 0x00D5; + tp->csr6 |= new_csr6; + iowrite32(0x0301, ioaddr + CSR12); + tulip_restart_rxtx(tp); + } + next_tick = 3*HZ; + } + + /* mod_timer synchronizes us with potential add_timer calls + * from interrupts. + */ + mod_timer(&tp->timer, RUN_AT(next_tick)); + } + + + void t21142_start_nway(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr14 = ((tp->sym_advertise & 0x0780) << 9) | + ((tp->sym_advertise & 0x0020) << 1) | 0xffbf; + + dev->if_port = 0; + tp->nway = tp->mediasense = 1; + tp->nwayset = tp->lpar = 0; + if (tulip_debug > 1) + netdev_dbg(dev, "Restarting 21143 autonegotiation, csr14=%08x\n", + csr14); + iowrite32(0x0001, ioaddr + CSR13); + udelay(100); + iowrite32(csr14, ioaddr + CSR14); + tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0); + iowrite32(tp->csr6, ioaddr + CSR6); + if (tp->mtable && tp->mtable->csr15dir) { + iowrite32(tp->mtable->csr15dir, ioaddr + CSR15); + iowrite32(tp->mtable->csr15val, ioaddr + CSR15); + } else + iowrite16(0x0008, ioaddr + CSR15); + iowrite32(0x1301, ioaddr + CSR12); /* Trigger NWAY. */ + } + + + + void t21142_lnk_change(struct net_device *dev, int csr5) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr12 = ioread32(ioaddr + CSR12); + int csr14 = ioread32(ioaddr + CSR14); + + /* CSR12[LS10,LS100] are not reliable during autonegotiation */ + if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000) + csr12 |= 6; + if (tulip_debug > 1) + dev_info(&dev->dev, + "21143 link status interrupt %08x, CSR5 %x, %08x\n", + csr12, csr5, csr14); + + /* If NWay finished and we have a negotiated partner capability. */ + if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { + int setup_done = 0; + int negotiated = tp->sym_advertise & (csr12 >> 16); + tp->lpar = csr12 >> 16; + tp->nwayset = 1; + /* If partner cannot negotiate, it is 10Mbps Half Duplex */ + if (!(csr12 & 0x8000)) dev->if_port = 0; + else if (negotiated & 0x0100) dev->if_port = 5; + else if (negotiated & 0x0080) dev->if_port = 3; + else if (negotiated & 0x0040) dev->if_port = 4; + else if (negotiated & 0x0020) dev->if_port = 0; + else { + tp->nwayset = 0; + if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) + dev->if_port = 3; + } + tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0; + + if (tulip_debug > 1) { + if (tp->nwayset) + dev_info(&dev->dev, + "Switching to %s based on link negotiation %04x & %04x = %04x\n", + medianame[dev->if_port], + tp->sym_advertise, tp->lpar, + negotiated); + else + dev_info(&dev->dev, + "Autonegotiation failed, using %s, link beat status %04x\n", + medianame[dev->if_port], csr12); + } + + if (tp->mtable) { + int i; + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == dev->if_port) { + int startup = ! ((tp->chip_id == DC21143 && (tp->revision == 48 || tp->revision == 65))); + tp->cur_index = i; + tulip_select_media(dev, startup); + setup_done = 1; + break; + } + } + if ( ! setup_done) { + tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff); + if (tp->full_duplex) + tp->csr6 |= 0x0200; + iowrite32(1, ioaddr + CSR13); + } + #if 0 /* Restart shouldn't be needed. */ + iowrite32(tp->csr6 | RxOn, ioaddr + CSR6); + if (tulip_debug > 2) + netdev_dbg(dev, " Restarting Tx and Rx, CSR5 is %08x\n", + ioread32(ioaddr + CSR5)); + #endif + tulip_start_rxtx(tp); + if (tulip_debug > 2) + netdev_dbg(dev, " Setting CSR6 %08x/%x CSR12 %08x\n", + tp->csr6, ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); + } else if ((tp->nwayset && (csr5 & 0x08000000) && + (dev->if_port == 3 || dev->if_port == 5) && + (csr12 & 2) == 2) || + (tp->nway && (csr5 & (TPLnkFail)))) { + /* Link blew? Maybe restart NWay. */ + del_timer_sync(&tp->timer); + t21142_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } else if (dev->if_port == 3 || dev->if_port == 5) { + if (tulip_debug > 1) + dev_info(&dev->dev, "21143 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 2) ? "failed" : "good"); + if ((csr12 & 2) && ! tp->medialock) { + del_timer_sync(&tp->timer); + t21142_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } else if (dev->if_port == 5) + iowrite32(csr14 & ~0x080, ioaddr + CSR14); + } else if (dev->if_port == 0 || dev->if_port == 4) { + if ((csr12 & 4) == 0) + dev_info(&dev->dev, "21143 10baseT link beat good\n"); + } else if (!(csr12 & 4)) { /* 10mbps link beat good. */ + if (tulip_debug) + dev_info(&dev->dev, "21143 10mbps sensed media\n"); + dev->if_port = 0; + } else if (tp->nwayset) { + if (tulip_debug) + dev_info(&dev->dev, "21143 using NWay-set %s, csr6 %08x\n", + medianame[dev->if_port], tp->csr6); + } else { /* 100mbps link beat good. */ + if (tulip_debug) + dev_info(&dev->dev, "21143 100baseTx sensed media\n"); + dev->if_port = 3; + tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff); + iowrite32(0x0003FF7F, ioaddr + CSR14); + iowrite32(0x0301, ioaddr + CSR12); + tulip_restart_rxtx(tp); + } + } + + diff --cc drivers/net/ethernet/dec/tulip/eeprom.c index 000000000000,fa5eee925f25..14d5b611783d mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/eeprom.c +++ b/drivers/net/ethernet/dec/tulip/eeprom.c @@@ -1,0 -1,385 +1,383 @@@ + /* + drivers/net/tulip/eeprom.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. + Please submit bug reports to http://bugzilla.kernel.org/. + */ + + #include + #include + #include "tulip.h" + #include + #include + + + + /* Serial EEPROM section. */ + /* The main routine to parse the very complicated SROM structure. + Search www.digital.com for "21X4 SROM" to get details. + This code is very complex, and will require changes to support + additional cards, so I'll be verbose about what is going on. + */ + + /* Known cards that have old-style EEPROMs. */ + static struct eeprom_fixup eeprom_fixups[] __devinitdata = { + {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c, + 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }}, + {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f, + 0x0000, 0x009E, /* 10baseT */ + 0x0004, 0x009E, /* 10baseT-FD */ + 0x0903, 0x006D, /* 100baseTx */ + 0x0905, 0x006D, /* 100baseTx-FD */ }}, + {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f, + 0x0107, 0x8021, /* 100baseFx */ + 0x0108, 0x8021, /* 100baseFx-FD */ + 0x0100, 0x009E, /* 10baseT */ + 0x0104, 0x009E, /* 10baseT-FD */ + 0x0103, 0x006D, /* 100baseTx */ + 0x0105, 0x006D, /* 100baseTx-FD */ }}, + {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513, + 0x1001, 0x009E, /* 10base2, CSR12 0x10*/ + 0x0000, 0x009E, /* 10baseT */ + 0x0004, 0x009E, /* 10baseT-FD */ + 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ + 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}}, + {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F, + 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */ + 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */ + 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */ + 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ + 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */ + }}, + {"NetWinder", 0x00, 0x10, 0x57, + /* Default media = MII + * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1 + */ + { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 } + }, + {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset */ + 0x0000, /* 0 == high offset, 0 == gap */ + 0x0800, /* Default Autoselect */ + 0x8001, /* 1 leaf, extended type, bogus len */ + 0x0003, /* Type 3 (MII), PHY #0 */ + 0x0400, /* 0 init instr, 4 reset instr */ + 0x0801, /* Set control mode, GP0 output */ + 0x0000, /* Drive GP0 Low (RST is active low) */ + 0x0800, /* control mode, GP0 input (undriven) */ + 0x0000, /* clear control mode */ + 0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX */ + 0x01e0, /* Advertise all above */ + 0x5000, /* FDX all above */ + 0x1800, /* Set fast TTM in 100bt modes */ + 0x0000, /* PHY cannot be unplugged */ + }}, + {NULL}}; + + + static const char *block_name[] __devinitdata = { + "21140 non-MII", + "21140 MII PHY", + "21142 Serial PHY", + "21142 MII PHY", + "21143 SYM PHY", + "21143 reset method" + }; + + + /** + * tulip_build_fake_mediatable - Build a fake mediatable entry. + * @tp: Ptr to the tulip private data. + * + * Some cards like the 3x5 HSC cards (J3514A) do not have a standard + * srom and can not be handled under the fixup routine. These cards + * still need a valid mediatable entry for correct csr12 setup and + * mii handling. + * + * Since this is currently a parisc-linux specific function, the + * #ifdef __hppa__ should completely optimize this function away for + * non-parisc hardware. + */ + static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) + { + #ifdef CONFIG_GSC + if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) { + static unsigned char leafdata[] = + { 0x01, /* phy number */ + 0x02, /* gpr setup sequence length */ + 0x02, 0x00, /* gpr setup sequence */ + 0x02, /* phy reset sequence length */ + 0x01, 0x00, /* phy reset sequence */ + 0x00, 0x78, /* media capabilities */ + 0x00, 0xe0, /* nway advertisement */ + 0x00, 0x05, /* fdx bit map */ + 0x00, 0x06 /* ttm bit map */ + }; + + tp->mtable = kmalloc(sizeof(struct mediatable) + + sizeof(struct medialeaf), GFP_KERNEL); + + if (tp->mtable == NULL) + return; /* Horrible, impossible failure. */ + + tp->mtable->defaultmedia = 0x800; + tp->mtable->leafcount = 1; + tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */ + tp->mtable->has_nonmii = 0; + tp->mtable->has_reset = 0; + tp->mtable->has_mii = 1; + tp->mtable->csr15dir = tp->mtable->csr15val = 0; + tp->mtable->mleaf[0].type = 1; + tp->mtable->mleaf[0].media = 11; + tp->mtable->mleaf[0].leafdata = &leafdata[0]; + tp->flags |= HAS_PHY_IRQ; + tp->csr12_shadow = -1; + } + #endif + } + + void __devinit tulip_parse_eeprom(struct net_device *dev) + { + /* + dev is not registered at this point, so logging messages can't + use dev_ or netdev_ but dev->name is good via a + hack in the caller + */ + + /* The last media info list parsed, for multiport boards. */ + static struct mediatable *last_mediatable; + static unsigned char *last_ee_data; + static int controller_index; + struct tulip_private *tp = netdev_priv(dev); + unsigned char *ee_data = tp->eeprom; + int i; + + tp->mtable = NULL; + /* Detect an old-style (SA only) EEPROM layout: + memcmp(eedata, eedata+16, 8). */ + for (i = 0; i < 8; i ++) + if (ee_data[i] != ee_data[16+i]) + break; + if (i >= 8) { + if (ee_data[0] == 0xff) { + if (last_mediatable) { + controller_index++; + pr_info("%s: Controller %d of multiport board\n", + dev->name, controller_index); + tp->mtable = last_mediatable; + ee_data = last_ee_data; + goto subsequent_board; + } else + pr_info("%s: Missing EEPROM, this interface may not work correctly!\n", + dev->name); + return; + } + /* Do a fix-up based on the vendor half of the station address prefix. */ + for (i = 0; eeprom_fixups[i].name; i++) { + if (dev->dev_addr[0] == eeprom_fixups[i].addr0 && + dev->dev_addr[1] == eeprom_fixups[i].addr1 && + dev->dev_addr[2] == eeprom_fixups[i].addr2) { + if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55) + i++; /* An Accton EN1207, not an outlaw Maxtech. */ + memcpy(ee_data + 26, eeprom_fixups[i].newtable, + sizeof(eeprom_fixups[i].newtable)); + pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n", + dev->name, eeprom_fixups[i].name); + break; + } + } + if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ + pr_info("%s: Old style EEPROM with no media selection information\n", + dev->name); + return; + } + } + + controller_index = 0; + if (ee_data[19] > 1) { /* Multiport board. */ + last_ee_data = ee_data; + } + subsequent_board: + + if (ee_data[27] == 0) { /* No valid media table. */ + tulip_build_fake_mediatable(tp); + } else { + unsigned char *p = (void *)ee_data + ee_data[27]; + unsigned char csr12dir = 0; + int count, new_advertise = 0; + struct mediatable *mtable; + u16 media = get_u16(p); + + p += 2; + if (tp->flags & CSR12_IN_SROM) + csr12dir = *p++; + count = *p++; + + /* there is no phy information, don't even try to build mtable */ + if (count == 0) { + if (tulip_debug > 0) + pr_warn("%s: no phy info, aborting mtable build\n", + dev->name); + return; + } + + mtable = kmalloc(sizeof(struct mediatable) + + count * sizeof(struct medialeaf), + GFP_KERNEL); + if (mtable == NULL) + return; /* Horrible, impossible failure. */ + last_mediatable = tp->mtable = mtable; + mtable->defaultmedia = media; + mtable->leafcount = count; + mtable->csr12dir = csr12dir; + mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; + mtable->csr15dir = mtable->csr15val = 0; + + pr_info("%s: EEPROM default media type %s\n", + dev->name, + media & 0x0800 ? "Autosense" + : medianame[media & MEDIA_MASK]); + for (i = 0; i < count; i++) { + struct medialeaf *leaf = &mtable->mleaf[i]; + + if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */ + leaf->type = 0; + leaf->media = p[0] & 0x3f; + leaf->leafdata = p; + if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */ + mtable->has_mii = 1; + p += 4; + } else { + leaf->type = p[1]; + if (p[1] == 0x05) { + mtable->has_reset = i; + leaf->media = p[2] & 0x0f; + } else if (tp->chip_id == DM910X && p[1] == 0x80) { + /* Hack to ignore Davicom delay period block */ + mtable->leafcount--; + count--; + i--; + leaf->leafdata = p + 2; + p += (p[0] & 0x3f) + 1; + continue; + } else if (p[1] & 1) { + int gpr_len, reset_len; + + mtable->has_mii = 1; + leaf->media = 11; + gpr_len=p[3]*2; + reset_len=p[4+gpr_len]*2; + new_advertise |= get_u16(&p[7+gpr_len+reset_len]); + } else { + mtable->has_nonmii = 1; + leaf->media = p[2] & MEDIA_MASK; + /* Davicom's media number for 100BaseTX is strange */ + if (tp->chip_id == DM910X && leaf->media == 1) + leaf->media = 3; + switch (leaf->media) { + case 0: new_advertise |= 0x0020; break; + case 4: new_advertise |= 0x0040; break; + case 3: new_advertise |= 0x0080; break; + case 5: new_advertise |= 0x0100; break; + case 6: new_advertise |= 0x0200; break; + } + if (p[1] == 2 && leaf->media == 0) { + if (p[2] & 0x40) { + u32 base15 = get_unaligned((u16*)&p[7]); + mtable->csr15dir = + (get_unaligned((u16*)&p[9])<<16) + base15; + mtable->csr15val = + (get_unaligned((u16*)&p[11])<<16) + base15; + } else { + mtable->csr15dir = get_unaligned((u16*)&p[3])<<16; + mtable->csr15val = get_unaligned((u16*)&p[5])<<16; + } + } + } + leaf->leafdata = p + 2; + p += (p[0] & 0x3f) + 1; + } + if (tulip_debug > 1 && leaf->media == 11) { + unsigned char *bp = leaf->leafdata; + pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", + dev->name, + bp[0], bp[1], bp[2 + bp[1]*2], + bp[5 + bp[2 + bp[1]*2]*2], + bp[4 + bp[2 + bp[1]*2]*2]); + } + pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n", + dev->name, + i, medianame[leaf->media & 15], leaf->media, + leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "", + leaf->type); + } + if (new_advertise) + tp->sym_advertise = new_advertise; + } + } + /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/ + + /* EEPROM_Ctrl bits. */ + #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ + #define EE_CS 0x01 /* EEPROM chip select. */ + #define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */ + #define EE_WRITE_0 0x01 + #define EE_WRITE_1 0x05 + #define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */ + #define EE_ENB (0x4800 | EE_CS) + + /* Delay between EEPROM clock transitions. + Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. + We add a bus turn-around to insure that this remains true. */ + #define eeprom_delay() ioread32(ee_addr) + + /* The EEPROM commands include the alway-set leading bit. */ + #define EE_READ_CMD (6) + + /* Note: this routine returns extra data bits for size detection. */ + int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len) + { + int i; + unsigned retval = 0; + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ee_addr = tp->base_addr + CSR9; + int read_cmd = location | (EE_READ_CMD << addr_len); + + /* If location is past the end of what we can address, don't + * read some other location (ie truncate). Just return zero. + */ + if (location > (1 << addr_len) - 1) + return 0; + + iowrite32(EE_ENB & ~EE_CS, ee_addr); + iowrite32(EE_ENB, ee_addr); + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + iowrite32(EE_ENB | dataval, ee_addr); + eeprom_delay(); + iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0); + } + iowrite32(EE_ENB, ee_addr); + eeprom_delay(); + + for (i = 16; i > 0; i--) { + iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0); + iowrite32(EE_ENB, ee_addr); + eeprom_delay(); + } + + /* Terminate the EEPROM access. */ + iowrite32(EE_ENB & ~EE_CS, ee_addr); + return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval; + } + diff --cc drivers/net/ethernet/dec/tulip/interrupt.c index 000000000000,5350d753e0ff..4fb8c8c0a420 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/interrupt.c +++ b/drivers/net/ethernet/dec/tulip/interrupt.c @@@ -1,0 -1,811 +1,808 @@@ + /* + drivers/net/tulip/interrupt.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. + Please submit bugs to http://bugzilla.kernel.org/ . - + */ + + #include + #include "tulip.h" + #include + + int tulip_rx_copybreak; + unsigned int tulip_max_interrupt_work; + + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + #define MIT_SIZE 15 + #define MIT_TABLE 15 /* We use 0 or max */ + + static unsigned int mit_table[MIT_SIZE+1] = + { + /* CRS11 21143 hardware Mitigation Control Interrupt + We use only RX mitigation we other techniques for + TX intr. mitigation. + + 31 Cycle Size (timer control) + 30:27 TX timer in 16 * Cycle size + 26:24 TX No pkts before Int. + 23:20 RX timer in Cycle size + 19:17 RX No pkts before Int. + 16 Continues Mode (CM) + */ + + 0x0, /* IM disabled */ + 0x80150000, /* RX time = 1, RX pkts = 2, CM = 1 */ + 0x80150000, + 0x80270000, + 0x80370000, + 0x80490000, + 0x80590000, + 0x80690000, + 0x807B0000, + 0x808B0000, + 0x809D0000, + 0x80AD0000, + 0x80BD0000, + 0x80CF0000, + 0x80DF0000, + // 0x80FF0000 /* RX time = 16, RX pkts = 7, CM = 1 */ + 0x80F10000 /* RX time = 16, RX pkts = 0, CM = 1 */ + }; + #endif + + + int tulip_refill_rx(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + int entry; + int refilled = 0; + + /* Refill the Rx ring buffers. */ + for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) { + entry = tp->dirty_rx % RX_RING_SIZE; + if (tp->rx_buffers[entry].skb == NULL) { + struct sk_buff *skb; + dma_addr_t mapping; + + skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ); + if (skb == NULL) + break; + + mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, + PCI_DMA_FROMDEVICE); + tp->rx_buffers[entry].mapping = mapping; + + skb->dev = dev; /* Mark as being used by this device. */ + tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); + refilled++; + } + tp->rx_ring[entry].status = cpu_to_le32(DescOwned); + } + if(tp->chip_id == LC82C168) { + if(((ioread32(tp->base_addr + CSR5)>>17)&0x07) == 4) { + /* Rx stopped due to out of buffers, + * restart it + */ + iowrite32(0x01, tp->base_addr + CSR2); + } + } + return refilled; + } + + #ifdef CONFIG_TULIP_NAPI + + void oom_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + napi_schedule(&tp->napi); + } + + int tulip_poll(struct napi_struct *napi, int budget) + { + struct tulip_private *tp = container_of(napi, struct tulip_private, napi); + struct net_device *dev = tp->dev; + int entry = tp->cur_rx % RX_RING_SIZE; + int work_done = 0; + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + int received = 0; + #endif + + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + + /* that one buffer is needed for mit activation; or might be a + bug in the ring buffer code; check later -- JHS*/ + + if (budget >=RX_RING_SIZE) budget--; + #endif + + if (tulip_debug > 4) + netdev_dbg(dev, " In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); + + do { + if (ioread32(tp->base_addr + CSR5) == 0xffffffff) { + netdev_dbg(dev, " In tulip_poll(), hardware disappeared\n"); + break; + } + /* Acknowledge current RX interrupt sources. */ + iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5); + + + /* If we own the next entry, it is a new packet. Send it up. */ + while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { + s32 status = le32_to_cpu(tp->rx_ring[entry].status); + short pkt_len; + + if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) + break; + + if (tulip_debug > 5) + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, status); + + if (++work_done >= budget) + goto not_done; + + /* + * Omit the four octet CRC from the length. + * (May not be considered valid until we have + * checked status for RxLengthOver2047 bits) + */ + pkt_len = ((status >> 16) & 0x7ff) - 4; + + /* + * Maximum pkt_len is 1518 (1514 + vlan header) + * Anything higher than this is always invalid + * regardless of RxLengthOver2047 bits + */ + + if ((status & (RxLengthOver2047 | + RxDescCRCError | + RxDescCollisionSeen | + RxDescRunt | + RxDescDescErr | + RxWholePkt)) != RxWholePkt || + pkt_len > 1518) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { + /* Ingore earlier buffers. */ + if ((status & 0xffff) != 0x7fff) { + if (tulip_debug > 1) + dev_warn(&dev->dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); + dev->stats.rx_length_errors++; + } + } else { + /* There was a fatal error. */ + if (tulip_debug > 2) + netdev_dbg(dev, "Receive error, Rx status %08x\n", + status); + dev->stats.rx_errors++; /* end of a packet.*/ + if (pkt_len > 1518 || + (status & RxDescRunt)) + dev->stats.rx_length_errors++; + + if (status & 0x0004) + dev->stats.rx_frame_errors++; + if (status & 0x0002) + dev->stats.rx_crc_errors++; + if (status & 0x0001) + dev->stats.rx_fifo_errors++; + } + } else { + struct sk_buff *skb; + + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < tulip_rx_copybreak && + (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single_for_cpu(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); + #if ! defined(__alpha__) + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); + skb_put(skb, pkt_len); + #else + memcpy(skb_put(skb, pkt_len), + tp->rx_buffers[entry].skb->data, + pkt_len); + #endif + pci_dma_sync_single_for_device(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); + } else { /* Pass up the skb already on the Rx ring. */ + char *temp = skb_put(skb = tp->rx_buffers[entry].skb, + pkt_len); + + #ifndef final_version + if (tp->rx_buffers[entry].mapping != + le32_to_cpu(tp->rx_ring[entry].buffer1)) { + dev_err(&dev->dev, + "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %08llx %p / %p\n", + le32_to_cpu(tp->rx_ring[entry].buffer1), + (unsigned long long)tp->rx_buffers[entry].mapping, + skb->head, temp); + } + #endif + + pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, + PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + + tp->rx_buffers[entry].skb = NULL; + tp->rx_buffers[entry].mapping = 0; + } + skb->protocol = eth_type_trans(skb, dev); + + netif_receive_skb(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + } + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + received++; + #endif + + entry = (++tp->cur_rx) % RX_RING_SIZE; + if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) + tulip_refill_rx(dev); + + } + + /* New ack strategy... irq does not ack Rx any longer + hopefully this helps */ + + /* Really bad things can happen here... If new packet arrives + * and an irq arrives (tx or just due to occasionally unset + * mask), it will be acked by irq handler, but new thread + * is not scheduled. It is major hole in design. + * No idea how to fix this if "playing with fire" will fail + * tomorrow (night 011029). If it will not fail, we won + * finally: amount of IO did not increase at all. */ + } while ((ioread32(tp->base_addr + CSR5) & RxIntr)); + + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + + /* We use this simplistic scheme for IM. It's proven by + real life installations. We can have IM enabled + continuesly but this would cause unnecessary latency. + Unfortunely we can't use all the NET_RX_* feedback here. + This would turn on IM for devices that is not contributing + to backlog congestion with unnecessary latency. + + We monitor the device RX-ring and have: + + HW Interrupt Mitigation either ON or OFF. + + ON: More then 1 pkt received (per intr.) OR we are dropping + OFF: Only 1 pkt received + + Note. We only use min and max (0, 15) settings from mit_table */ + + + if( tp->flags & HAS_INTR_MITIGATION) { + if( received > 1 ) { + if( ! tp->mit_on ) { + tp->mit_on = 1; + iowrite32(mit_table[MIT_TABLE], tp->base_addr + CSR11); + } + } + else { + if( tp->mit_on ) { + tp->mit_on = 0; + iowrite32(0, tp->base_addr + CSR11); + } + } + } + + #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */ + + tulip_refill_rx(dev); + + /* If RX ring is not full we are out of memory. */ + if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) + goto oom; + + /* Remove us from polling list and enable RX intr. */ + + napi_complete(napi); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); + + /* The last op happens after poll completion. Which means the following: + * 1. it can race with disabling irqs in irq handler + * 2. it can race with dise/enabling irqs in other poll threads + * 3. if an irq raised after beginning loop, it will be immediately + * triggered here. + * + * Summarizing: the logic results in some redundant irqs both + * due to races in masking and due to too late acking of already + * processed irqs. But it must not result in losing events. + */ + + return work_done; + + not_done: + if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 || + tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) + tulip_refill_rx(dev); + + if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) + goto oom; + + return work_done; + + oom: /* Executed with RX ints disabled */ + + /* Start timer, stop polling, but do not enable rx interrupts. */ + mod_timer(&tp->oom_timer, jiffies+1); + + /* Think: timer_pending() was an explicit signature of bug. + * Timer can be pending now but fired and completed + * before we did napi_complete(). See? We would lose it. */ + + /* remove ourselves from the polling list */ + napi_complete(napi); + + return work_done; + } + + #else /* CONFIG_TULIP_NAPI */ + + static int tulip_rx(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + int entry = tp->cur_rx % RX_RING_SIZE; + int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; + int received = 0; + + if (tulip_debug > 4) + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); + /* If we own the next entry, it is a new packet. Send it up. */ + while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { + s32 status = le32_to_cpu(tp->rx_ring[entry].status); + short pkt_len; + + if (tulip_debug > 5) + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, status); + if (--rx_work_limit < 0) + break; + + /* + Omit the four octet CRC from the length. + (May not be considered valid until we have + checked status for RxLengthOver2047 bits) + */ + pkt_len = ((status >> 16) & 0x7ff) - 4; + /* + Maximum pkt_len is 1518 (1514 + vlan header) + Anything higher than this is always invalid + regardless of RxLengthOver2047 bits + */ + + if ((status & (RxLengthOver2047 | + RxDescCRCError | + RxDescCollisionSeen | + RxDescRunt | + RxDescDescErr | + RxWholePkt)) != RxWholePkt || + pkt_len > 1518) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { + /* Ingore earlier buffers. */ + if ((status & 0xffff) != 0x7fff) { + if (tulip_debug > 1) + netdev_warn(dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); + dev->stats.rx_length_errors++; + } + } else { + /* There was a fatal error. */ + if (tulip_debug > 2) + netdev_dbg(dev, "Receive error, Rx status %08x\n", + status); + dev->stats.rx_errors++; /* end of a packet.*/ + if (pkt_len > 1518 || + (status & RxDescRunt)) + dev->stats.rx_length_errors++; + if (status & 0x0004) + dev->stats.rx_frame_errors++; + if (status & 0x0002) + dev->stats.rx_crc_errors++; + if (status & 0x0001) + dev->stats.rx_fifo_errors++; + } + } else { + struct sk_buff *skb; + + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < tulip_rx_copybreak && + (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single_for_cpu(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); + #if ! defined(__alpha__) + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); + skb_put(skb, pkt_len); + #else + memcpy(skb_put(skb, pkt_len), + tp->rx_buffers[entry].skb->data, + pkt_len); + #endif + pci_dma_sync_single_for_device(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); + } else { /* Pass up the skb already on the Rx ring. */ + char *temp = skb_put(skb = tp->rx_buffers[entry].skb, + pkt_len); + + #ifndef final_version + if (tp->rx_buffers[entry].mapping != + le32_to_cpu(tp->rx_ring[entry].buffer1)) { + dev_err(&dev->dev, + "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %Lx %p / %p\n", + le32_to_cpu(tp->rx_ring[entry].buffer1), + (long long)tp->rx_buffers[entry].mapping, + skb->head, temp); + } + #endif + + pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, + PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + + tp->rx_buffers[entry].skb = NULL; + tp->rx_buffers[entry].mapping = 0; + } + skb->protocol = eth_type_trans(skb, dev); + + netif_rx(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + } + received++; + entry = (++tp->cur_rx) % RX_RING_SIZE; + } + return received; + } + #endif /* CONFIG_TULIP_NAPI */ + + static inline unsigned int phy_interrupt (struct net_device *dev) + { + #ifdef __hppa__ + struct tulip_private *tp = netdev_priv(dev); + int csr12 = ioread32(tp->base_addr + CSR12) & 0xff; + + if (csr12 != tp->csr12_shadow) { + /* ack interrupt */ + iowrite32(csr12 | 0x02, tp->base_addr + CSR12); + tp->csr12_shadow = csr12; + /* do link change stuff */ + spin_lock(&tp->lock); + tulip_check_duplex(dev); + spin_unlock(&tp->lock); + /* clear irq ack bit */ + iowrite32(csr12 & ~0x02, tp->base_addr + CSR12); + + return 1; + } + #endif + + return 0; + } + + /* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ + irqreturn_t tulip_interrupt(int irq, void *dev_instance) + { + struct net_device *dev = (struct net_device *)dev_instance; + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr5; + int missed; + int rx = 0; + int tx = 0; + int oi = 0; + int maxrx = RX_RING_SIZE; + int maxtx = TX_RING_SIZE; + int maxoi = TX_RING_SIZE; + #ifdef CONFIG_TULIP_NAPI + int rxd = 0; + #else + int entry; + #endif + unsigned int work_count = tulip_max_interrupt_work; + unsigned int handled = 0; + + /* Let's see whether the interrupt really is for us */ + csr5 = ioread32(ioaddr + CSR5); + + if (tp->flags & HAS_PHY_IRQ) + handled = phy_interrupt (dev); + + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) + return IRQ_RETVAL(handled); + + tp->nir++; + + do { + + #ifdef CONFIG_TULIP_NAPI + + if (!rxd && (csr5 & (RxIntr | RxNoBuf))) { + rxd++; + /* Mask RX intrs and add the device to poll list. */ + iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); + napi_schedule(&tp->napi); + + if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) + break; + } + + /* Acknowledge the interrupt sources we handle here ASAP + the poll function does Rx and RxNoBuf acking */ + + iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5); + + #else + /* Acknowledge all of the current interrupt sources ASAP. */ + iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5); + + + if (csr5 & (RxIntr | RxNoBuf)) { + rx += tulip_rx(dev); + tulip_refill_rx(dev); + } + + #endif /* CONFIG_TULIP_NAPI */ + + if (tulip_debug > 4) + netdev_dbg(dev, "interrupt csr5=%#8.8x new csr5=%#8.8x\n", + csr5, ioread32(ioaddr + CSR5)); + + + if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { + unsigned int dirty_tx; + + spin_lock(&tp->lock); + + for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; + dirty_tx++) { + int entry = dirty_tx % TX_RING_SIZE; + int status = le32_to_cpu(tp->tx_ring[entry].status); + + if (status < 0) + break; /* It still has not been Txed */ + + /* Check for Rx filter setup frames. */ + if (tp->tx_buffers[entry].skb == NULL) { + /* test because dummy frames not mapped */ + if (tp->tx_buffers[entry].mapping) + pci_unmap_single(tp->pdev, + tp->tx_buffers[entry].mapping, + sizeof(tp->setup_frame), + PCI_DMA_TODEVICE); + continue; + } + + if (status & 0x8000) { + /* There was an major error, log it. */ + #ifndef final_version + if (tulip_debug > 1) + netdev_dbg(dev, "Transmit error, Tx status %08x\n", + status); + #endif + dev->stats.tx_errors++; + if (status & 0x4104) + dev->stats.tx_aborted_errors++; + if (status & 0x0C00) + dev->stats.tx_carrier_errors++; + if (status & 0x0200) + dev->stats.tx_window_errors++; + if (status & 0x0002) + dev->stats.tx_fifo_errors++; + if ((status & 0x0080) && tp->full_duplex == 0) + dev->stats.tx_heartbeat_errors++; + } else { + dev->stats.tx_bytes += + tp->tx_buffers[entry].skb->len; + dev->stats.collisions += (status >> 3) & 15; + dev->stats.tx_packets++; + } + + pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, + tp->tx_buffers[entry].skb->len, + PCI_DMA_TODEVICE); + + /* Free the original skb. */ + dev_kfree_skb_irq(tp->tx_buffers[entry].skb); + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = 0; + tx++; + } + + #ifndef final_version + if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { + dev_err(&dev->dev, + "Out-of-sync dirty pointer, %d vs. %d\n", + dirty_tx, tp->cur_tx); + dirty_tx += TX_RING_SIZE; + } + #endif + + if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) + netif_wake_queue(dev); + + tp->dirty_tx = dirty_tx; + if (csr5 & TxDied) { + if (tulip_debug > 2) + dev_warn(&dev->dev, + "The transmitter stopped. CSR5 is %x, CSR6 %x, new CSR6 %x\n", + csr5, ioread32(ioaddr + CSR6), + tp->csr6); + tulip_restart_rxtx(tp); + } + spin_unlock(&tp->lock); + } + + /* Log errors. */ + if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ + if (csr5 == 0xffffffff) + break; + if (csr5 & TxJabber) + dev->stats.tx_errors++; + if (csr5 & TxFIFOUnderflow) { + if ((tp->csr6 & 0xC000) != 0xC000) + tp->csr6 += 0x4000; /* Bump up the Tx threshold */ + else + tp->csr6 |= 0x00200000; /* Store-n-forward. */ + /* Restart the transmit process. */ + tulip_restart_rxtx(tp); + iowrite32(0, ioaddr + CSR1); + } + if (csr5 & (RxDied | RxNoBuf)) { + if (tp->flags & COMET_MAC_ADDR) { + iowrite32(tp->mc_filter[0], ioaddr + 0xAC); + iowrite32(tp->mc_filter[1], ioaddr + 0xB0); + } + } + if (csr5 & RxDied) { /* Missed a Rx frame. */ + dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; + dev->stats.rx_errors++; + tulip_start_rxtx(tp); + } + /* + * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this + * call is ever done under the spinlock + */ + if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { + if (tp->link_change) + (tp->link_change)(dev, csr5); + } + if (csr5 & SystemError) { + int error = (csr5 >> 23) & 7; + /* oops, we hit a PCI error. The code produced corresponds + * to the reason: + * 0 - parity error + * 1 - master abort + * 2 - target abort + * Note that on parity error, we should do a software reset + * of the chip to get it back into a sane state (according + * to the 21142/3 docs that is). + * -- rmk + */ + dev_err(&dev->dev, + "(%lu) System Error occurred (%d)\n", + tp->nir, error); + } + /* Clear all error sources, included undocumented ones! */ + iowrite32(0x0800f7ba, ioaddr + CSR5); + oi++; + } + if (csr5 & TimerInt) { + + if (tulip_debug > 2) + dev_err(&dev->dev, + "Re-enabling interrupts, %08x\n", + csr5); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + tp->ttimer = 0; + oi++; + } + if (tx > maxtx || rx > maxrx || oi > maxoi) { + if (tulip_debug > 1) + dev_warn(&dev->dev, "Too much work during an interrupt, csr5=0x%08x. (%lu) (%d,%d,%d)\n", + csr5, tp->nir, tx, rx, oi); + + /* Acknowledge all interrupt sources. */ + iowrite32(0x8001ffff, ioaddr + CSR5); + if (tp->flags & HAS_INTR_MITIGATION) { + /* Josip Loncaric at ICASE did extensive experimentation + to develop a good interrupt mitigation setting.*/ + iowrite32(0x8b240000, ioaddr + CSR11); + } else if (tp->chip_id == LC82C168) { + /* the LC82C168 doesn't have a hw timer.*/ + iowrite32(0x00, ioaddr + CSR7); + mod_timer(&tp->timer, RUN_AT(HZ/50)); + } else { + /* Mask all interrupting sources, set timer to + re-enable. */ + iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); + iowrite32(0x0012, ioaddr + CSR11); + } + break; + } + + work_count--; + if (work_count == 0) + break; + + csr5 = ioread32(ioaddr + CSR5); + + #ifdef CONFIG_TULIP_NAPI + if (rxd) + csr5 &= ~RxPollInt; + } while ((csr5 & (TxNoBuf | + TxDied | + TxIntr | + TimerInt | + /* Abnormal intr. */ + RxDied | + TxFIFOUnderflow | + TxJabber | + TPLnkFail | + SystemError )) != 0); + #else + } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); + + tulip_refill_rx(dev); + + /* check if the card is in suspend mode */ + entry = tp->dirty_rx % RX_RING_SIZE; + if (tp->rx_buffers[entry].skb == NULL) { + if (tulip_debug > 1) + dev_warn(&dev->dev, + "in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", + tp->nir, tp->cur_rx, tp->ttimer, rx); + if (tp->chip_id == LC82C168) { + iowrite32(0x00, ioaddr + CSR7); + mod_timer(&tp->timer, RUN_AT(HZ/50)); + } else { + if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) { + if (tulip_debug > 1) + dev_warn(&dev->dev, + "in rx suspend mode: (%lu) set timer\n", + tp->nir); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt, + ioaddr + CSR7); + iowrite32(TimerInt, ioaddr + CSR5); + iowrite32(12, ioaddr + CSR11); + tp->ttimer = 1; + } + } + } + #endif /* CONFIG_TULIP_NAPI */ + + if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) { + dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; + } + + if (tulip_debug > 4) + netdev_dbg(dev, "exiting interrupt, csr5=%#04x\n", + ioread32(ioaddr + CSR5)); + + return IRQ_HANDLED; + } diff --cc drivers/net/ethernet/dec/tulip/media.c index 000000000000,4bd13922875d..beeb17b52ad4 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/media.c +++ b/drivers/net/ethernet/dec/tulip/media.c @@@ -1,0 -1,556 +1,553 @@@ + /* + drivers/net/tulip/media.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + #include + #include + #include + #include + #include + #include "tulip.h" + + + /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues or future 66Mhz PCI. */ + #define mdio_delay() ioread32(mdio_addr) + + /* Read and write the MII registers using software-generated serial + MDIO protocol. It is just different enough from the EEPROM protocol + to not share code. The maxium data clock rate is 2.5 Mhz. */ + #define MDIO_SHIFT_CLK 0x10000 + #define MDIO_DATA_WRITE0 0x00000 + #define MDIO_DATA_WRITE1 0x20000 + #define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ + #define MDIO_ENB_IN 0x40000 + #define MDIO_DATA_READ 0x80000 + + static const unsigned char comet_miireg2offset[32] = { + 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC, 0, 0,0,0,0, 0,0,0,0, + 0,0xD0,0,0, 0,0,0,0, 0,0,0,0, 0, 0xD4, 0xD8, 0xDC, }; + + + /* MII transceiver control section. + Read and write the MII registers using software-generated serial + MDIO protocol. + See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management functions") + or DP83840A data sheet for more details. + */ + + int tulip_mdio_read(struct net_device *dev, int phy_id, int location) + { + struct tulip_private *tp = netdev_priv(dev); + int i; + int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location; + int retval = 0; + void __iomem *ioaddr = tp->base_addr; + void __iomem *mdio_addr = ioaddr + CSR9; + unsigned long flags; + + if (location & ~0x1f) + return 0xffff; + + if (tp->chip_id == COMET && phy_id == 30) { + if (comet_miireg2offset[location]) + return ioread32(ioaddr + comet_miireg2offset[location]); + return 0xffff; + } + + spin_lock_irqsave(&tp->mii_lock, flags); + if (tp->chip_id == LC82C168) { + iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); + ioread32(ioaddr + 0xA0); + ioread32(ioaddr + 0xA0); + for (i = 1000; i >= 0; --i) { + barrier(); + if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000)) + break; + } + spin_unlock_irqrestore(&tp->mii_lock, flags); + return retval & 0xffff; + } + + /* Establish sync by sending at least 32 logic ones. */ + for (i = 32; i >= 0; i--) { + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + + iowrite32(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + iowrite32(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + + spin_unlock_irqrestore(&tp->mii_lock, flags); + return (retval>>1) & 0xffff; + } + + void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) + { + struct tulip_private *tp = netdev_priv(dev); + int i; + int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff); + void __iomem *ioaddr = tp->base_addr; + void __iomem *mdio_addr = ioaddr + CSR9; + unsigned long flags; + + if (location & ~0x1f) + return; + + if (tp->chip_id == COMET && phy_id == 30) { + if (comet_miireg2offset[location]) + iowrite32(val, ioaddr + comet_miireg2offset[location]); + return; + } + + spin_lock_irqsave(&tp->mii_lock, flags); + if (tp->chip_id == LC82C168) { + iowrite32(cmd, ioaddr + 0xA0); + for (i = 1000; i >= 0; --i) { + barrier(); + if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000)) + break; + } + spin_unlock_irqrestore(&tp->mii_lock, flags); + return; + } + + /* Establish sync by sending 32 logic ones. */ + for (i = 32; i >= 0; i--) { + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + iowrite32(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + iowrite32(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + + spin_unlock_irqrestore(&tp->mii_lock, flags); + } + + + /* Set up the transceiver control registers for the selected media type. */ + void tulip_select_media(struct net_device *dev, int startup) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + struct mediatable *mtable = tp->mtable; + u32 new_csr6; + int i; + + if (mtable) { + struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index]; + unsigned char *p = mleaf->leafdata; + switch (mleaf->type) { + case 0: /* 21140 non-MII xcvr. */ + if (tulip_debug > 1) + netdev_dbg(dev, "Using a 21140 non-MII transceiver with control setting %02x\n", + p[1]); + dev->if_port = p[0]; + if (startup) + iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); + iowrite32(p[1], ioaddr + CSR12); + new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); + break; + case 2: case 4: { + u16 setup[5]; + u32 csr13val, csr14val, csr15dir, csr15val; + for (i = 0; i < 5; i++) + setup[i] = get_u16(&p[i*2 + 1]); + + dev->if_port = p[0] & MEDIA_MASK; + if (tulip_media_cap[dev->if_port] & MediaAlwaysFD) + tp->full_duplex = 1; + + if (startup && mtable->has_reset) { + struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; + unsigned char *rst = rleaf->leafdata; + if (tulip_debug > 1) + netdev_dbg(dev, "Resetting the transceiver\n"); + for (i = 0; i < rst[0]; i++) + iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); + } + if (tulip_debug > 1) + netdev_dbg(dev, "21143 non-MII %s transceiver control %04x/%04x\n", + medianame[dev->if_port], + setup[0], setup[1]); + if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ + csr13val = setup[0]; + csr14val = setup[1]; + csr15dir = (setup[3]<<16) | setup[2]; + csr15val = (setup[4]<<16) | setup[2]; + iowrite32(0, ioaddr + CSR13); + iowrite32(csr14val, ioaddr + CSR14); + iowrite32(csr15dir, ioaddr + CSR15); /* Direction */ + iowrite32(csr15val, ioaddr + CSR15); /* Data */ + iowrite32(csr13val, ioaddr + CSR13); + } else { + csr13val = 1; + csr14val = 0; + csr15dir = (setup[0]<<16) | 0x0008; + csr15val = (setup[1]<<16) | 0x0008; + if (dev->if_port <= 4) + csr14val = t21142_csr14[dev->if_port]; + if (startup) { + iowrite32(0, ioaddr + CSR13); + iowrite32(csr14val, ioaddr + CSR14); + } + iowrite32(csr15dir, ioaddr + CSR15); /* Direction */ + iowrite32(csr15val, ioaddr + CSR15); /* Data */ + if (startup) iowrite32(csr13val, ioaddr + CSR13); + } + if (tulip_debug > 1) + netdev_dbg(dev, "Setting CSR15 to %08x/%08x\n", + csr15dir, csr15val); + if (mleaf->type == 4) + new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); + else + new_csr6 = 0x82420000; + break; + } + case 1: case 3: { + int phy_num = p[0]; + int init_length = p[1]; + u16 *misc_info, tmp_info; + + dev->if_port = 11; + new_csr6 = 0x020E0000; + if (mleaf->type == 3) { /* 21142 */ + u16 *init_sequence = (u16*)(p+2); + u16 *reset_sequence = &((u16*)(p+3))[init_length]; + int reset_length = p[2 + init_length*2]; + misc_info = reset_sequence + reset_length; + if (startup) { + int timeout = 10; /* max 1 ms */ + for (i = 0; i < reset_length; i++) + iowrite32(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); + + /* flush posted writes */ + ioread32(ioaddr + CSR15); + + /* Sect 3.10.3 in DP83840A.pdf (p39) */ + udelay(500); + + /* Section 4.2 in DP83840A.pdf (p43) */ + /* and IEEE 802.3 "22.2.4.1.1 Reset" */ + while (timeout-- && + (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET)) + udelay(100); + } + for (i = 0; i < init_length; i++) + iowrite32(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); + + ioread32(ioaddr + CSR15); /* flush posted writes */ + } else { + u8 *init_sequence = p + 2; + u8 *reset_sequence = p + 3 + init_length; + int reset_length = p[2 + init_length]; + misc_info = (u16*)(reset_sequence + reset_length); + if (startup) { + int timeout = 10; /* max 1 ms */ + iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); + for (i = 0; i < reset_length; i++) + iowrite32(reset_sequence[i], ioaddr + CSR12); + + /* flush posted writes */ + ioread32(ioaddr + CSR12); + + /* Sect 3.10.3 in DP83840A.pdf (p39) */ + udelay(500); + + /* Section 4.2 in DP83840A.pdf (p43) */ + /* and IEEE 802.3 "22.2.4.1.1 Reset" */ + while (timeout-- && + (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET)) + udelay(100); + } + for (i = 0; i < init_length; i++) + iowrite32(init_sequence[i], ioaddr + CSR12); + + ioread32(ioaddr + CSR12); /* flush posted writes */ + } + + tmp_info = get_u16(&misc_info[1]); + if (tmp_info) + tp->advertising[phy_num] = tmp_info | 1; + if (tmp_info && startup < 2) { + if (tp->mii_advertise == 0) + tp->mii_advertise = tp->advertising[phy_num]; + if (tulip_debug > 1) + netdev_dbg(dev, " Advertising %04x on MII %d\n", + tp->mii_advertise, + tp->phys[phy_num]); + tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise); + } + break; + } + case 5: case 6: { + u16 setup[5]; + + new_csr6 = 0; /* FIXME */ + + for (i = 0; i < 5; i++) + setup[i] = get_u16(&p[i*2 + 1]); + + if (startup && mtable->has_reset) { + struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; + unsigned char *rst = rleaf->leafdata; + if (tulip_debug > 1) + netdev_dbg(dev, "Resetting the transceiver\n"); + for (i = 0; i < rst[0]; i++) + iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); + } + + break; + } + default: + netdev_dbg(dev, " Invalid media table selection %d\n", + mleaf->type); + new_csr6 = 0x020E0000; + } + if (tulip_debug > 1) + netdev_dbg(dev, "Using media type %s, CSR12 is %02x\n", + medianame[dev->if_port], + ioread32(ioaddr + CSR12) & 0xff); + } else if (tp->chip_id == LC82C168) { + if (startup && ! tp->medialock) + dev->if_port = tp->mii_cnt ? 11 : 0; + if (tulip_debug > 1) + netdev_dbg(dev, "PNIC PHY status is %3.3x, media %s\n", + ioread32(ioaddr + 0xB8), + medianame[dev->if_port]); + if (tp->mii_cnt) { + new_csr6 = 0x810C0000; + iowrite32(0x0001, ioaddr + CSR15); + iowrite32(0x0201B07A, ioaddr + 0xB8); + } else if (startup) { + /* Start with 10mbps to do autonegotiation. */ + iowrite32(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + iowrite32(0x0001B078, ioaddr + 0xB8); + iowrite32(0x0201B078, ioaddr + 0xB8); + } else if (dev->if_port == 3 || dev->if_port == 5) { + iowrite32(0x33, ioaddr + CSR12); + new_csr6 = 0x01860000; + /* Trigger autonegotiation. */ + iowrite32(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8); + } else { + iowrite32(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + iowrite32(0x1F078, ioaddr + 0xB8); + } + } else { /* Unknown chip type with no media table. */ + if (tp->default_port == 0) + dev->if_port = tp->mii_cnt ? 11 : 3; + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + new_csr6 = 0x020E0000; + } else if (tulip_media_cap[dev->if_port] & MediaIsFx) { + new_csr6 = 0x02860000; + } else + new_csr6 = 0x03860000; + if (tulip_debug > 1) + netdev_dbg(dev, "No media description table, assuming %s transceiver, CSR12 %02x\n", + medianame[dev->if_port], + ioread32(ioaddr + CSR12)); + } + + tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); + + mdelay(1); + } + + /* + Check the MII negotiated duplex and change the CSR6 setting if + required. + Return 0 if everything is OK. + Return < 0 if the transceiver is missing or has no link beat. + */ + int tulip_check_duplex(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + unsigned int bmsr, lpa, negotiated, new_csr6; + + bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); + lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA); + if (tulip_debug > 1) + dev_info(&dev->dev, "MII status %04x, Link partner report %04x\n", + bmsr, lpa); + if (bmsr == 0xffff) + return -2; + if ((bmsr & BMSR_LSTATUS) == 0) { + int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); + if ((new_bmsr & BMSR_LSTATUS) == 0) { + if (tulip_debug > 1) + dev_info(&dev->dev, + "No link beat on the MII interface, status %04x\n", + new_bmsr); + return -1; + } + } + negotiated = lpa & tp->advertising[0]; + tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated); + + new_csr6 = tp->csr6; + + if (negotiated & LPA_100) new_csr6 &= ~TxThreshold; + else new_csr6 |= TxThreshold; + if (tp->full_duplex) new_csr6 |= FullDuplex; + else new_csr6 &= ~FullDuplex; + + if (new_csr6 != tp->csr6) { + tp->csr6 = new_csr6; + tulip_restart_rxtx(tp); + + if (tulip_debug > 0) + dev_info(&dev->dev, + "Setting %s-duplex based on MII#%d link partner capability of %04x\n", + tp->full_duplex ? "full" : "half", + tp->phys[0], lpa); + return 1; + } + + return 0; + } + + void __devinit tulip_find_mii (struct net_device *dev, int board_idx) + { + struct tulip_private *tp = netdev_priv(dev); + int phyn, phy_idx = 0; + int mii_reg0; + int mii_advert; + unsigned int to_advert, new_bmcr, ane_switch; + + /* Find the connected MII xcvrs. + Doing this in open() would allow detecting external xcvrs later, + but takes much time. */ + for (phyn = 1; phyn <= 32 && phy_idx < sizeof (tp->phys); phyn++) { + int phy = phyn & 0x1f; + int mii_status = tulip_mdio_read (dev, phy, MII_BMSR); + if ((mii_status & 0x8301) == 0x8001 || + ((mii_status & BMSR_100BASE4) == 0 && + (mii_status & 0x7800) != 0)) { + /* preserve Becker logic, gain indentation level */ + } else { + continue; + } + + mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR); + mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE); + ane_switch = 0; + + /* if not advertising at all, gen an + * advertising value from the capability + * bits in BMSR + */ + if ((mii_advert & ADVERTISE_ALL) == 0) { + unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR); + mii_advert = ((tmpadv >> 6) & 0x3e0) | 1; + } + + if (tp->mii_advertise) { + tp->advertising[phy_idx] = + to_advert = tp->mii_advertise; + } else if (tp->advertising[phy_idx]) { + to_advert = tp->advertising[phy_idx]; + } else { + tp->advertising[phy_idx] = + tp->mii_advertise = + to_advert = mii_advert; + } + + tp->phys[phy_idx++] = phy; + + pr_info("tulip%d: MII transceiver #%d config %04x status %04x advertising %04x\n", + board_idx, phy, mii_reg0, mii_status, mii_advert); + + /* Fixup for DLink with miswired PHY. */ + if (mii_advert != to_advert) { + pr_debug("tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n", + board_idx, to_advert, phy, mii_advert); + tulip_mdio_write (dev, phy, 4, to_advert); + } + + /* Enable autonegotiation: some boards default to off. */ + if (tp->default_port == 0) { + new_bmcr = mii_reg0 | BMCR_ANENABLE; + if (new_bmcr != mii_reg0) { + new_bmcr |= BMCR_ANRESTART; + ane_switch = 1; + } + } + /* ...or disable nway, if forcing media */ + else { + new_bmcr = mii_reg0 & ~BMCR_ANENABLE; + if (new_bmcr != mii_reg0) + ane_switch = 1; + } + + /* clear out bits we never want at this point */ + new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE | + BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK | + BMCR_RESET); + + if (tp->full_duplex) + new_bmcr |= BMCR_FULLDPLX; + if (tulip_media_cap[tp->default_port] & MediaIs100) + new_bmcr |= BMCR_SPEED100; + + if (new_bmcr != mii_reg0) { + /* some phys need the ANE switch to + * happen before forced media settings + * will "take." However, we write the + * same value twice in order not to + * confuse the sane phys. + */ + if (ane_switch) { + tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr); + udelay (10); + } + tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr); + } + } + tp->mii_cnt = phy_idx; + if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) { + pr_info("tulip%d: ***WARNING***: No MII transceiver found!\n", + board_idx); + tp->phys[0] = 1; + } + } diff --cc drivers/net/ethernet/dec/tulip/pnic.c index 000000000000,52d898bdbeb4..9c16e4ad02a6 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/pnic.c +++ b/drivers/net/ethernet/dec/tulip/pnic.c @@@ -1,0 -1,173 +1,170 @@@ + /* + drivers/net/tulip/pnic.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + #include + #include + #include + #include "tulip.h" + + + void pnic_do_nway(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + u32 phy_reg = ioread32(ioaddr + 0xB8); + u32 new_csr6 = tp->csr6 & ~0x40C40200; + + if (phy_reg & 0x78000000) { /* Ignore baseT4 */ + if (phy_reg & 0x20000000) dev->if_port = 5; + else if (phy_reg & 0x40000000) dev->if_port = 3; + else if (phy_reg & 0x10000000) dev->if_port = 4; + else if (phy_reg & 0x08000000) dev->if_port = 0; + tp->nwayset = 1; + new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000; + iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12); + if (dev->if_port & 1) + iowrite32(0x1F868, ioaddr + 0xB8); + if (phy_reg & 0x30000000) { + tp->full_duplex = 1; + new_csr6 |= 0x00000200; + } + if (tulip_debug > 1) + netdev_dbg(dev, "PNIC autonegotiated status %08x, %s\n", + phy_reg, medianame[dev->if_port]); + if (tp->csr6 != new_csr6) { + tp->csr6 = new_csr6; + /* Restart Tx */ + tulip_restart_rxtx(tp); + dev->trans_start = jiffies; + } + } + } + + void pnic_lnk_change(struct net_device *dev, int csr5) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int phy_reg = ioread32(ioaddr + 0xB8); + + if (tulip_debug > 1) + netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n", + phy_reg, csr5); + if (ioread32(ioaddr + CSR5) & TPLnkFail) { + iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); + /* If we use an external MII, then we mustn't use the + * internal negotiation. + */ + if (tulip_media_cap[dev->if_port] & MediaIsMII) + return; + if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) { + tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); + iowrite32(tp->csr6, ioaddr + CSR6); + iowrite32(0x30, ioaddr + CSR12); + iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ + dev->trans_start = jiffies; + } + } else if (ioread32(ioaddr + CSR5) & TPLnkPass) { + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + spin_lock(&tp->lock); + tulip_check_duplex(dev); + spin_unlock(&tp->lock); + } else { + pnic_do_nway(dev); + } + iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); + } + } + + void pnic_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int next_tick = 60*HZ; + + if(!ioread32(ioaddr + CSR7)) { + /* the timer was called due to a work overflow + * in the interrupt handler. Skip the connection + * checks, the nic is definitively speaking with + * his link partner. + */ + goto too_good_connection; + } + + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + spin_lock_irq(&tp->lock); + if (tulip_check_duplex(dev) > 0) + next_tick = 3*HZ; + spin_unlock_irq(&tp->lock); + } else { + int csr12 = ioread32(ioaddr + CSR12); + int new_csr6 = tp->csr6 & ~0x40C40200; + int phy_reg = ioread32(ioaddr + 0xB8); + int csr5 = ioread32(ioaddr + CSR5); + + if (tulip_debug > 1) + netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n", + phy_reg, medianame[dev->if_port], csr5); + if (phy_reg & 0x04000000) { /* Remote link fault */ + iowrite32(0x0201F078, ioaddr + 0xB8); + next_tick = 1*HZ; + tp->nwayset = 0; + } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */ + pnic_do_nway(dev); + next_tick = 60*HZ; + } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */ + if (tulip_debug > 1) + netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n", + medianame[dev->if_port], + csr12, + ioread32(ioaddr + CSR5), + ioread32(ioaddr + 0xB8)); + next_tick = 3*HZ; + if (tp->medialock) { + } else if (tp->nwayset && (dev->if_port & 1)) { + next_tick = 1*HZ; + } else if (dev->if_port == 0) { + dev->if_port = 3; + iowrite32(0x33, ioaddr + CSR12); + new_csr6 = 0x01860000; + iowrite32(0x1F868, ioaddr + 0xB8); + } else { + dev->if_port = 0; + iowrite32(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + iowrite32(0x1F078, ioaddr + 0xB8); + } + if (tp->csr6 != new_csr6) { + tp->csr6 = new_csr6; + /* Restart Tx */ + tulip_restart_rxtx(tp); + dev->trans_start = jiffies; + if (tulip_debug > 1) + dev_info(&dev->dev, + "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n", + medianame[dev->if_port], + tp->full_duplex ? "full" : "half", + new_csr6); + } + } + } + too_good_connection: + mod_timer(&tp->timer, RUN_AT(next_tick)); + if(!ioread32(ioaddr + CSR7)) { + if (tulip_debug > 1) + dev_info(&dev->dev, "sw timer wakeup\n"); + disable_irq(dev->irq); + tulip_refill_rx(dev); + enable_irq(dev->irq); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + } + } diff --cc drivers/net/ethernet/dec/tulip/pnic2.c index 000000000000,93358ee4d830..04a7e477eaff mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/pnic2.c +++ b/drivers/net/ethernet/dec/tulip/pnic2.c @@@ -1,0 -1,406 +1,403 @@@ + /* + drivers/net/tulip/pnic2.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + Modified to hep support PNIC_II by Kevin B. Hendricks + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + + /* Understanding the PNIC_II - everything is this file is based + * on the PNIC_II_PDF datasheet which is sorely lacking in detail + * + * As I understand things, here are the registers and bits that + * explain the masks and constants used in this file that are + * either different from the 21142/3 or important for basic operation. + * + * + * CSR 6 (mask = 0xfe3bd1fd of bits not to change) + * ----- + * Bit 24 - SCR + * Bit 23 - PCS + * Bit 22 - TTM (Trasmit Threshold Mode) + * Bit 18 - Port Select + * Bit 13 - Start - 1, Stop - 0 Transmissions + * Bit 11:10 - Loop Back Operation Mode + * Bit 9 - Full Duplex mode (Advertise 10BaseT-FD is CSR14<7> is set) + * Bit 1 - Start - 1, Stop - 0 Receive + * + * + * CSR 14 (mask = 0xfff0ee39 of bits not to change) + * ------ + * Bit 19 - PAUSE-Pause + * Bit 18 - Advertise T4 + * Bit 17 - Advertise 100baseTx-FD + * Bit 16 - Advertise 100baseTx-HD + * Bit 12 - LTE - Link Test Enable + * Bit 7 - ANE - Auto Negotiate Enable + * Bit 6 - HDE - Advertise 10baseT-HD + * Bit 2 - Reset to Power down - kept as 1 for normal operation + * Bit 1 - Loop Back enable for 10baseT MCC + * + * + * CSR 12 + * ------ + * Bit 25 - Partner can do T4 + * Bit 24 - Partner can do 100baseTx-FD + * Bit 23 - Partner can do 100baseTx-HD + * Bit 22 - Partner can do 10baseT-FD + * Bit 21 - Partner can do 10baseT-HD + * Bit 15 - LPN is 1 if all above bits are valid other wise 0 + * Bit 14:12 - autonegotiation state (write 001 to start autonegotiate) + * Bit 3 - Autopolarity state + * Bit 2 - LS10B - link state of 10baseT 0 - good, 1 - failed + * Bit 1 - LS100B - link state of 100baseT 0 - good, 1 - failed + * + * + * Data Port Selection Info + *------------------------- + * + * CSR14<7> CSR6<18> CSR6<22> CSR6<23> CSR6<24> MODE/PORT + * 1 0 0 (X) 0 (X) 1 NWAY + * 0 0 1 0 (X) 0 10baseT + * 0 1 0 1 1 (X) 100baseT + * + * + */ + + + + #include "tulip.h" + #include + + + void pnic2_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int next_tick = 60*HZ; + + if (tulip_debug > 3) + dev_info(&dev->dev, "PNIC2 negotiation status %08x\n", + ioread32(ioaddr + CSR12)); + + if (next_tick) { + mod_timer(&tp->timer, RUN_AT(next_tick)); + } + } + + + void pnic2_start_nway(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr14; + int csr12; + + /* set up what to advertise during the negotiation */ + + /* load in csr14 and mask off bits not to touch + * comment at top of file explains mask value + */ + csr14 = (ioread32(ioaddr + CSR14) & 0xfff0ee39); + + /* bit 17 - advetise 100baseTx-FD */ + if (tp->sym_advertise & 0x0100) csr14 |= 0x00020000; + + /* bit 16 - advertise 100baseTx-HD */ + if (tp->sym_advertise & 0x0080) csr14 |= 0x00010000; + + /* bit 6 - advertise 10baseT-HD */ + if (tp->sym_advertise & 0x0020) csr14 |= 0x00000040; + + /* Now set bit 12 Link Test Enable, Bit 7 Autonegotiation Enable + * and bit 0 Don't PowerDown 10baseT + */ + csr14 |= 0x00001184; + + if (tulip_debug > 1) + netdev_dbg(dev, "Restarting PNIC2 autonegotiation, csr14=%08x\n", + csr14); + + /* tell pnic2_lnk_change we are doing an nway negotiation */ + dev->if_port = 0; + tp->nway = tp->mediasense = 1; + tp->nwayset = tp->lpar = 0; + + /* now we have to set up csr6 for NWAY state */ + + tp->csr6 = ioread32(ioaddr + CSR6); + if (tulip_debug > 1) + netdev_dbg(dev, "On Entry to Nway, csr6=%08x\n", tp->csr6); + + /* mask off any bits not to touch + * comment at top of file explains mask value + */ + tp->csr6 = tp->csr6 & 0xfe3bd1fd; + + /* don't forget that bit 9 is also used for advertising */ + /* advertise 10baseT-FD for the negotiation (bit 9) */ + if (tp->sym_advertise & 0x0040) tp->csr6 |= 0x00000200; + + /* set bit 24 for nway negotiation mode ... + * see Data Port Selection comment at top of file + * and "Stop" - reset both Transmit (bit 13) and Receive (bit 1) + */ + tp->csr6 |= 0x01000000; + iowrite32(csr14, ioaddr + CSR14); + iowrite32(tp->csr6, ioaddr + CSR6); + udelay(100); + + /* all set up so now force the negotiation to begin */ + + /* read in current values and mask off all but the + * Autonegotiation bits 14:12. Writing a 001 to those bits + * should start the autonegotiation + */ + csr12 = (ioread32(ioaddr + CSR12) & 0xffff8fff); + csr12 |= 0x1000; + iowrite32(csr12, ioaddr + CSR12); + } + + + + void pnic2_lnk_change(struct net_device *dev, int csr5) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr14; + + /* read the staus register to find out what is up */ + int csr12 = ioread32(ioaddr + CSR12); + + if (tulip_debug > 1) + dev_info(&dev->dev, + "PNIC2 link status interrupt %08x, CSR5 %x, %08x\n", + csr12, csr5, ioread32(ioaddr + CSR14)); + + /* If NWay finished and we have a negotiated partner capability. + * check bits 14:12 for bit pattern 101 - all is good + */ + if (tp->nway && !tp->nwayset) { + + /* we did an auto negotiation */ + + if ((csr12 & 0x7000) == 0x5000) { + + /* negotiation ended successfully */ + + /* get the link partners reply and mask out all but + * bits 24-21 which show the partners capabilities + * and match those to what we advertised + * + * then begin to interpret the results of the negotiation. + * Always go in this order : (we are ignoring T4 for now) + * 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD + */ + + int negotiated = ((csr12 >> 16) & 0x01E0) & tp->sym_advertise; + tp->lpar = (csr12 >> 16); + tp->nwayset = 1; + + if (negotiated & 0x0100) dev->if_port = 5; + else if (negotiated & 0x0080) dev->if_port = 3; + else if (negotiated & 0x0040) dev->if_port = 4; + else if (negotiated & 0x0020) dev->if_port = 0; + else { + if (tulip_debug > 1) + dev_info(&dev->dev, + "funny autonegotiate result csr12 %08x advertising %04x\n", + csr12, tp->sym_advertise); + tp->nwayset = 0; + /* so check if 100baseTx link state is okay */ + if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) + dev->if_port = 3; + } + + /* now record the duplex that was negotiated */ + tp->full_duplex = 0; + if ((dev->if_port == 4) || (dev->if_port == 5)) + tp->full_duplex = 1; + + if (tulip_debug > 1) { + if (tp->nwayset) + dev_info(&dev->dev, + "Switching to %s based on link negotiation %04x & %04x = %04x\n", + medianame[dev->if_port], + tp->sym_advertise, tp->lpar, + negotiated); + } + + /* remember to turn off bit 7 - autonegotiate + * enable so we can properly end nway mode and + * set duplex (ie. use csr6<9> again) + */ + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(csr14,ioaddr + CSR14); + + + /* now set the data port and operating mode + * (see the Data Port Selection comments at + * the top of the file + */ + + /* get current csr6 and mask off bits not to touch */ + /* see comment at top of file */ + + tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); + + /* so if using if_port 3 or 5 then select the 100baseT + * port else select the 10baseT port. + * See the Data Port Selection table at the top + * of the file which was taken from the PNIC_II.PDF + * datasheet + */ + if (dev->if_port & 1) tp->csr6 |= 0x01840000; + else tp->csr6 |= 0x00400000; + + /* now set the full duplex bit appropriately */ + if (tp->full_duplex) tp->csr6 |= 0x00000200; + + iowrite32(1, ioaddr + CSR13); + + if (tulip_debug > 2) + netdev_dbg(dev, "Setting CSR6 %08x/%x CSR12 %08x\n", + tp->csr6, + ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); + + /* now the following actually writes out the + * new csr6 values + */ + tulip_start_rxtx(tp); + + return; + + } else { + dev_info(&dev->dev, + "Autonegotiation failed, using %s, link beat status %04x\n", + medianame[dev->if_port], csr12); + + /* remember to turn off bit 7 - autonegotiate + * enable so we don't forget + */ + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(csr14,ioaddr + CSR14); + + /* what should we do when autonegotiate fails? + * should we try again or default to baseline + * case. I just don't know. + * + * for now default to some baseline case + */ + + dev->if_port = 0; + tp->nway = 0; + tp->nwayset = 1; + + /* set to 10baseTx-HD - see Data Port Selection + * comment given at the top of the file + */ + tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); + tp->csr6 |= 0x00400000; + + tulip_restart_rxtx(tp); + + return; + + } + } + + if ((tp->nwayset && (csr5 & 0x08000000) && + (dev->if_port == 3 || dev->if_port == 5) && + (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) { + + /* Link blew? Maybe restart NWay. */ + + if (tulip_debug > 2) + netdev_dbg(dev, "Ugh! Link blew?\n"); + + del_timer_sync(&tp->timer); + pnic2_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + + return; + } + + + if (dev->if_port == 3 || dev->if_port == 5) { + + /* we are at 100mb and a potential link change occurred */ + + if (tulip_debug > 1) + dev_info(&dev->dev, "PNIC2 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 2) ? "failed" : "good"); + + /* check 100 link beat */ + + tp->nway = 0; + tp->nwayset = 1; + + /* if failed then try doing an nway to get in sync */ + if ((csr12 & 2) && ! tp->medialock) { + del_timer_sync(&tp->timer); + pnic2_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } + + return; + } + + if (dev->if_port == 0 || dev->if_port == 4) { + + /* we are at 10mb and a potential link change occurred */ + + if (tulip_debug > 1) + dev_info(&dev->dev, "PNIC2 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 4) ? "failed" : "good"); + + + tp->nway = 0; + tp->nwayset = 1; + + /* if failed, try doing an nway to get in sync */ + if ((csr12 & 4) && ! tp->medialock) { + del_timer_sync(&tp->timer); + pnic2_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } + + return; + } + + + if (tulip_debug > 1) + dev_info(&dev->dev, "PNIC2 Link Change Default?\n"); + + /* if all else fails default to trying 10baseT-HD */ + dev->if_port = 0; + + /* make sure autonegotiate enable is off */ + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(csr14,ioaddr + CSR14); + + /* set to 10baseTx-HD - see Data Port Selection + * comment given at the top of the file + */ + tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); + tp->csr6 |= 0x00400000; + + tulip_restart_rxtx(tp); + } + diff --cc drivers/net/ethernet/dec/tulip/timer.c index 000000000000,2017faf2d0e6..19078d28ffb9 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/timer.c +++ b/drivers/net/ethernet/dec/tulip/timer.c @@@ -1,0 -1,179 +1,176 @@@ + /* + drivers/net/tulip/timer.c + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + + #include "tulip.h" + + + void tulip_media_task(struct work_struct *work) + { + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; + void __iomem *ioaddr = tp->base_addr; + u32 csr12 = ioread32(ioaddr + CSR12); + int next_tick = 2*HZ; + unsigned long flags; + + if (tulip_debug > 2) { + netdev_dbg(dev, "Media selection tick, %s, status %08x mode %08x SIA %08x %08x %08x %08x\n", + medianame[dev->if_port], + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR6), + csr12, ioread32(ioaddr + CSR13), + ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); + } + switch (tp->chip_id) { + case DC21140: + case DC21142: + case MX98713: + case COMPEX9881: + case DM910X: + default: { + struct medialeaf *mleaf; + unsigned char *p; + if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */ + /* Not much that can be done. + Assume this a generic MII or SYM transceiver. */ + next_tick = 60*HZ; + if (tulip_debug > 2) + netdev_dbg(dev, "network media monitor CSR6 %08x CSR12 0x%02x\n", + ioread32(ioaddr + CSR6), + csr12 & 0xff); + break; + } + mleaf = &tp->mtable->mleaf[tp->cur_index]; + p = mleaf->leafdata; + switch (mleaf->type) { + case 0: case 4: { + /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */ + int offset = mleaf->type == 4 ? 5 : 2; + s8 bitnum = p[offset]; + if (p[offset+1] & 0x80) { + if (tulip_debug > 1) + netdev_dbg(dev, "Transceiver monitor tick CSR12=%#02x, no media sense\n", + csr12); + if (mleaf->type == 4) { + if (mleaf->media == 3 && (csr12 & 0x02)) + goto select_next_media; + } + break; + } + if (tulip_debug > 2) + netdev_dbg(dev, "Transceiver monitor tick: CSR12=%#02x bit %d is %d, expecting %d\n", + csr12, (bitnum >> 1) & 7, + (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, + (bitnum >= 0)); + /* Check that the specified bit has the proper value. */ + if ((bitnum < 0) != + ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { + if (tulip_debug > 2) + netdev_dbg(dev, "Link beat detected for %s\n", + medianame[mleaf->media & MEDIA_MASK]); + if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ + goto actually_mii; + netif_carrier_on(dev); + break; + } + netif_carrier_off(dev); + if (tp->medialock) + break; + select_next_media: + if (--tp->cur_index < 0) { + /* We start again, but should instead look for default. */ + tp->cur_index = tp->mtable->leafcount - 1; + } + dev->if_port = tp->mtable->mleaf[tp->cur_index].media; + if (tulip_media_cap[dev->if_port] & MediaIsFD) + goto select_next_media; /* Skip FD entries. */ + if (tulip_debug > 1) + netdev_dbg(dev, "No link beat on media %s, trying transceiver type %s\n", + medianame[mleaf->media & MEDIA_MASK], + medianame[tp->mtable->mleaf[tp->cur_index].media]); + tulip_select_media(dev, 0); + /* Restart the transmit process. */ + tulip_restart_rxtx(tp); + next_tick = (24*HZ)/10; + break; + } + case 1: case 3: /* 21140, 21142 MII */ + actually_mii: + if (tulip_check_duplex(dev) < 0) { + netif_carrier_off(dev); + next_tick = 3*HZ; + } else { + netif_carrier_on(dev); + next_tick = 60*HZ; + } + break; + case 2: /* 21142 serial block has no link beat. */ + default: + break; + } + } + break; + } + + + spin_lock_irqsave(&tp->lock, flags); + if (tp->timeout_recovery) { + tulip_tx_timeout_complete(tp, ioaddr); + tp->timeout_recovery = 0; + } + spin_unlock_irqrestore(&tp->lock, flags); + + /* mod_timer synchronizes us with potential add_timer calls + * from interrupts. + */ + mod_timer(&tp->timer, RUN_AT(next_tick)); + } + + + void mxic_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int next_tick = 60*HZ; + + if (tulip_debug > 3) { + dev_info(&dev->dev, "MXIC negotiation status %08x\n", + ioread32(ioaddr + CSR12)); + } + if (next_tick) { + mod_timer(&tp->timer, RUN_AT(next_tick)); + } + } + + + void comet_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + int next_tick = 60*HZ; + + if (tulip_debug > 1) + netdev_dbg(dev, "Comet link status %04x partner capability %04x\n", + tulip_mdio_read(dev, tp->phys[0], 1), + tulip_mdio_read(dev, tp->phys[0], 5)); + /* mod_timer synchronizes us with potential add_timer calls + * from interrupts. + */ + if (tulip_check_duplex(dev) < 0) + { netif_carrier_off(dev); } + else + { netif_carrier_on(dev); } + mod_timer(&tp->timer, RUN_AT(next_tick)); + } + diff --cc drivers/net/ethernet/dec/tulip/tulip.h index 000000000000,9db528967da9..fb3887c18dc6 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/tulip.h +++ b/drivers/net/ethernet/dec/tulip/tulip.h @@@ -1,0 -1,573 +1,570 @@@ + /* + drivers/net/tulip/tulip.h + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + #ifndef __NET_TULIP_H__ + #define __NET_TULIP_H__ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + + + /* undefine, or define to various debugging levels (>4 == obscene levels) */ + #define TULIP_DEBUG 1 + + #ifdef CONFIG_TULIP_MMIO + #define TULIP_BAR 1 /* CBMA */ + #else + #define TULIP_BAR 0 /* CBIO */ + #endif + + + + struct tulip_chip_table { + char *chip_name; + int io_size; + int valid_intrs; /* CSR7 interrupt enable settings */ + int flags; + void (*media_timer) (unsigned long); + work_func_t media_task; + }; + + + enum tbl_flag { + HAS_MII = 0x00001, + HAS_MEDIA_TABLE = 0x00002, + CSR12_IN_SROM = 0x00004, + ALWAYS_CHECK_MII = 0x00008, + HAS_ACPI = 0x00010, + MC_HASH_ONLY = 0x00020, /* Hash-only multicast filter. */ + HAS_PNICNWAY = 0x00080, + HAS_NWAY = 0x00040, /* Uses internal NWay xcvr. */ + HAS_INTR_MITIGATION = 0x00100, + IS_ASIX = 0x00200, + HAS_8023X = 0x00400, + COMET_MAC_ADDR = 0x00800, + HAS_PCI_MWI = 0x01000, + HAS_PHY_IRQ = 0x02000, + HAS_SWAPPED_SEEPROM = 0x04000, + NEEDS_FAKE_MEDIA_TABLE = 0x08000, + COMET_PM = 0x10000, + }; + + + /* chip types. careful! order is VERY IMPORTANT here, as these + * are used throughout the driver as indices into arrays */ + /* Note 21142 == 21143. */ + enum chips { + DC21040 = 0, + DC21041 = 1, + DC21140 = 2, + DC21142 = 3, DC21143 = 3, + LC82C168, + MX98713, + MX98715, + MX98725, + AX88140, + PNIC2, + COMET, + COMPEX9881, + I21145, + DM910X, + CONEXANT, + }; + + + enum MediaIs { + MediaIsFD = 1, + MediaAlwaysFD = 2, + MediaIsMII = 4, + MediaIsFx = 8, + MediaIs100 = 16 + }; + + + /* Offsets to the Command and Status Registers, "CSRs". All accesses + must be longword instructions and quadword aligned. */ + enum tulip_offsets { + CSR0 = 0, + CSR1 = 0x08, + CSR2 = 0x10, + CSR3 = 0x18, + CSR4 = 0x20, + CSR5 = 0x28, + CSR6 = 0x30, + CSR7 = 0x38, + CSR8 = 0x40, + CSR9 = 0x48, + CSR10 = 0x50, + CSR11 = 0x58, + CSR12 = 0x60, + CSR13 = 0x68, + CSR14 = 0x70, + CSR15 = 0x78, + CSR18 = 0x88, + CSR19 = 0x8c, + CSR20 = 0x90, + CSR27 = 0xAC, + CSR28 = 0xB0, + }; + + /* register offset and bits for CFDD PCI config reg */ + enum pci_cfg_driver_reg { + CFDD = 0x40, + CFDD_Sleep = (1 << 31), + CFDD_Snooze = (1 << 30), + }; + + #define RxPollInt (RxIntr|RxNoBuf|RxDied|RxJabber) + + /* The bits in the CSR5 status registers, mostly interrupt sources. */ + enum status_bits { + TimerInt = 0x800, + SystemError = 0x2000, + TPLnkFail = 0x1000, + TPLnkPass = 0x10, + NormalIntr = 0x10000, + AbnormalIntr = 0x8000, + RxJabber = 0x200, + RxDied = 0x100, + RxNoBuf = 0x80, + RxIntr = 0x40, + TxFIFOUnderflow = 0x20, + RxErrIntr = 0x10, + TxJabber = 0x08, + TxNoBuf = 0x04, + TxDied = 0x02, + TxIntr = 0x01, + }; + + /* bit mask for CSR5 TX/RX process state */ + #define CSR5_TS 0x00700000 + #define CSR5_RS 0x000e0000 + + enum tulip_mode_bits { + TxThreshold = (1 << 22), + FullDuplex = (1 << 9), + TxOn = 0x2000, + AcceptBroadcast = 0x0100, + AcceptAllMulticast = 0x0080, + AcceptAllPhys = 0x0040, + AcceptRunt = 0x0008, + RxOn = 0x0002, + RxTx = (TxOn | RxOn), + }; + + + enum tulip_busconfig_bits { + MWI = (1 << 24), + MRL = (1 << 23), + MRM = (1 << 21), + CALShift = 14, + BurstLenShift = 8, + }; + + + /* The Tulip Rx and Tx buffer descriptors. */ + struct tulip_rx_desc { + __le32 status; + __le32 length; + __le32 buffer1; + __le32 buffer2; + }; + + + struct tulip_tx_desc { + __le32 status; + __le32 length; + __le32 buffer1; + __le32 buffer2; /* We use only buffer 1. */ + }; + + + enum desc_status_bits { + DescOwned = 0x80000000, + DescWholePkt = 0x60000000, + DescEndPkt = 0x40000000, + DescStartPkt = 0x20000000, + DescEndRing = 0x02000000, + DescUseLink = 0x01000000, + + /* + * Error summary flag is logical or of 'CRC Error', 'Collision Seen', + * 'Frame Too Long', 'Runt' and 'Descriptor Error' flags generated + * within tulip chip. + */ + RxDescErrorSummary = 0x8000, + RxDescCRCError = 0x0002, + RxDescCollisionSeen = 0x0040, + + /* + * 'Frame Too Long' flag is set if packet length including CRC exceeds + * 1518. However, a full sized VLAN tagged frame is 1522 bytes + * including CRC. + * + * The tulip chip does not block oversized frames, and if this flag is + * set on a receive descriptor it does not indicate the frame has been + * truncated. The receive descriptor also includes the actual length. + * Therefore we can safety ignore this flag and check the length + * ourselves. + */ + RxDescFrameTooLong = 0x0080, + RxDescRunt = 0x0800, + RxDescDescErr = 0x4000, + RxWholePkt = 0x00000300, + /* + * Top three bits of 14 bit frame length (status bits 27-29) should + * never be set as that would make frame over 2047 bytes. The Receive + * Watchdog flag (bit 4) may indicate the length is over 2048 and the + * length field is invalid. + */ + RxLengthOver2047 = 0x38000010 + }; + + + enum t21143_csr6_bits { + csr6_sc = (1<<31), + csr6_ra = (1<<30), + csr6_ign_dest_msb = (1<<26), + csr6_mbo = (1<<25), + csr6_scr = (1<<24), /* scramble mode flag: can't be set */ + csr6_pcs = (1<<23), /* Enables PCS functions (symbol mode requires csr6_ps be set) default is set */ + csr6_ttm = (1<<22), /* Transmit Threshold Mode, set for 10baseT, 0 for 100BaseTX */ + csr6_sf = (1<<21), /* Store and forward. If set ignores TR bits */ + csr6_hbd = (1<<19), /* Heart beat disable. Disables SQE function in 10baseT */ + csr6_ps = (1<<18), /* Port Select. 0 (defualt) = 10baseT, 1 = 100baseTX: can't be set */ + csr6_ca = (1<<17), /* Collision Offset Enable. If set uses special algorithm in low collision situations */ + csr6_trh = (1<<15), /* Transmit Threshold high bit */ + csr6_trl = (1<<14), /* Transmit Threshold low bit */ + + /*************************************************************** + * This table shows transmit threshold values based on media * + * and these two registers (from PNIC1 & 2 docs) Note: this is * + * all meaningless if sf is set. * + ***************************************************************/ + + /*********************************** + * (trh,trl) * 100BaseTX * 10BaseT * + *********************************** + * (0,0) * 128 * 72 * + * (0,1) * 256 * 96 * + * (1,0) * 512 * 128 * + * (1,1) * 1024 * 160 * + ***********************************/ + + csr6_fc = (1<<12), /* Forces a collision in next transmission (for testing in loopback mode) */ + csr6_om_int_loop = (1<<10), /* internal (FIFO) loopback flag */ + csr6_om_ext_loop = (1<<11), /* external (PMD) loopback flag */ + /* set both and you get (PHY) loopback */ + csr6_fd = (1<<9), /* Full duplex mode, disables hearbeat, no loopback */ + csr6_pm = (1<<7), /* Pass All Multicast */ + csr6_pr = (1<<6), /* Promiscuous mode */ + csr6_sb = (1<<5), /* Start(1)/Stop(0) backoff counter */ + csr6_if = (1<<4), /* Inverse Filtering, rejects only addresses in address table: can't be set */ + csr6_pb = (1<<3), /* Pass Bad Frames, (1) causes even bad frames to be passed on */ + csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ + csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ + + csr6_mask_capture = (csr6_sc | csr6_ca), + csr6_mask_defstate = (csr6_mask_capture | csr6_mbo), + csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps), + csr6_mask_hdcaptt = (csr6_mask_hdcap | csr6_trh | csr6_trl), + csr6_mask_fullcap = (csr6_mask_hdcaptt | csr6_fd), + csr6_mask_fullpromisc = (csr6_pr | csr6_pm), + csr6_mask_filters = (csr6_hp | csr6_ho | csr6_if), + csr6_mask_100bt = (csr6_scr | csr6_pcs | csr6_hbd), + }; + + enum tulip_comet_csr13_bits { + /* The LINKOFFE and LINKONE work in conjunction with LSCE, i.e. they + * determine which link status transition wakes up if LSCE is + * enabled */ + comet_csr13_linkoffe = (1 << 17), + comet_csr13_linkone = (1 << 16), + comet_csr13_wfre = (1 << 10), + comet_csr13_mpre = (1 << 9), + comet_csr13_lsce = (1 << 8), + comet_csr13_wfr = (1 << 2), + comet_csr13_mpr = (1 << 1), + comet_csr13_lsc = (1 << 0), + }; + + enum tulip_comet_csr18_bits { + comet_csr18_pmes_sticky = (1 << 24), + comet_csr18_pm_mode = (1 << 19), + comet_csr18_apm_mode = (1 << 18), + comet_csr18_d3a = (1 << 7) + }; + + enum tulip_comet_csr20_bits { + comet_csr20_pmes = (1 << 15), + }; + + /* Keep the ring sizes a power of two for efficiency. + Making the Tx ring too large decreases the effectiveness of channel + bonding and packet priority. + There are no ill effects from too-large receive rings. */ + + #define TX_RING_SIZE 32 + #define RX_RING_SIZE 128 + #define MEDIA_MASK 31 + + /* The receiver on the DC21143 rev 65 can fail to close the last + * receive descriptor in certain circumstances (see errata) when + * using MWI. This can only occur if the receive buffer ends on + * a cache line boundary, so the "+ 4" below ensures it doesn't. + */ + #define PKT_BUF_SZ (1536 + 4) /* Size of each temporary Rx buffer. */ + + #define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */ + + #if defined(__sparc__) || defined(__hppa__) + /* The UltraSparc PCI controllers will disconnect at every 64-byte + * crossing anyways so it makes no sense to tell Tulip to burst + * any more than that. + */ + #define TULIP_MAX_CACHE_LINE 16 /* in units of 32-bit words */ + #else + #define TULIP_MAX_CACHE_LINE 32 /* in units of 32-bit words */ + #endif + + + /* Ring-wrap flag in length field, use for last ring entry. + 0x01000000 means chain on buffer2 address, + 0x02000000 means use the ring start address in CSR2/3. + Note: Some work-alike chips do not function correctly in chained mode. + The ASIX chip works only in chained mode. + Thus we indicates ring mode, but always write the 'next' field for + chained mode as well. + */ + #define DESC_RING_WRAP 0x02000000 + + + #define EEPROM_SIZE 512 /* 2 << EEPROM_ADDRLEN */ + + + #define RUN_AT(x) (jiffies + (x)) + + #define get_u16(ptr) get_unaligned_le16((ptr)) + + struct medialeaf { + u8 type; + u8 media; + unsigned char *leafdata; + }; + + + struct mediatable { + u16 defaultmedia; + u8 leafcount; + u8 csr12dir; /* General purpose pin directions. */ + unsigned has_mii:1; + unsigned has_nonmii:1; + unsigned has_reset:6; + u32 csr15dir; + u32 csr15val; /* 21143 NWay setting. */ + struct medialeaf mleaf[0]; + }; + + + struct mediainfo { + struct mediainfo *next; + int info_type; + int index; + unsigned char *info; + }; + + struct ring_info { + struct sk_buff *skb; + dma_addr_t mapping; + }; + + + struct tulip_private { + const char *product_name; + struct net_device *next_module; + struct tulip_rx_desc *rx_ring; + struct tulip_tx_desc *tx_ring; + dma_addr_t rx_ring_dma; + dma_addr_t tx_ring_dma; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct ring_info tx_buffers[TX_RING_SIZE]; + /* The addresses of receive-in-place skbuffs. */ + struct ring_info rx_buffers[RX_RING_SIZE]; + u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ + int chip_id; + int revision; + int flags; + struct napi_struct napi; + struct timer_list timer; /* Media selection timer. */ + struct timer_list oom_timer; /* Out of memory timer. */ + u32 mc_filter[2]; + spinlock_t lock; + spinlock_t mii_lock; + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION + int mit_on; + #endif + unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int full_duplex_lock:1; + unsigned int fake_addr:1; /* Multiport board faked address. */ + unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int media2:4; /* Secondary monitored media port. */ + unsigned int medialock:1; /* Don't sense media type. */ + unsigned int mediasense:1; /* Media sensing in progress. */ + unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */ + unsigned int timeout_recovery:1; + unsigned int csr0; /* CSR0 setting. */ + unsigned int csr6; /* Current CSR6 control settings. */ + unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ + void (*link_change) (struct net_device * dev, int csr5); + struct ethtool_wolinfo wolinfo; /* WOL settings */ + u16 sym_advertise, mii_advertise; /* NWay capabilities advertised. */ + u16 lpar; /* 21143 Link partner ability. */ + u16 advertising[4]; + signed char phys[4], mii_cnt; /* MII device addresses. */ + struct mediatable *mtable; + int cur_index; /* Current media index. */ + int saved_if_port; + struct pci_dev *pdev; + int ttimer; + int susp_rx; + unsigned long nir; + void __iomem *base_addr; + int csr12_shadow; + int pad0; /* Used for 8-byte alignment */ + struct work_struct media_work; + struct net_device *dev; + }; + + + struct eeprom_fixup { + char *name; + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + u16 newtable[32]; /* Max length below. */ + }; + + + /* 21142.c */ + extern u16 t21142_csr14[]; + void t21142_media_task(struct work_struct *work); + void t21142_start_nway(struct net_device *dev); + void t21142_lnk_change(struct net_device *dev, int csr5); + + + /* PNIC2.c */ + void pnic2_lnk_change(struct net_device *dev, int csr5); + void pnic2_timer(unsigned long data); + void pnic2_start_nway(struct net_device *dev); + void pnic2_lnk_change(struct net_device *dev, int csr5); + + /* eeprom.c */ + void tulip_parse_eeprom(struct net_device *dev); + int tulip_read_eeprom(struct net_device *dev, int location, int addr_len); + + /* interrupt.c */ + extern unsigned int tulip_max_interrupt_work; + extern int tulip_rx_copybreak; + irqreturn_t tulip_interrupt(int irq, void *dev_instance); + int tulip_refill_rx(struct net_device *dev); + #ifdef CONFIG_TULIP_NAPI + int tulip_poll(struct napi_struct *napi, int budget); + #endif + + + /* media.c */ + int tulip_mdio_read(struct net_device *dev, int phy_id, int location); + void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int value); + void tulip_select_media(struct net_device *dev, int startup); + int tulip_check_duplex(struct net_device *dev); + void tulip_find_mii (struct net_device *dev, int board_idx); + + /* pnic.c */ + void pnic_do_nway(struct net_device *dev); + void pnic_lnk_change(struct net_device *dev, int csr5); + void pnic_timer(unsigned long data); + + /* timer.c */ + void tulip_media_task(struct work_struct *work); + void mxic_timer(unsigned long data); + void comet_timer(unsigned long data); + + /* tulip_core.c */ + extern int tulip_debug; + extern const char * const medianame[]; + extern const char tulip_media_cap[]; + extern struct tulip_chip_table tulip_tbl[]; + void oom_timer(unsigned long data); + extern u8 t21040_csr13[]; + + static inline void tulip_start_rxtx(struct tulip_private *tp) + { + void __iomem *ioaddr = tp->base_addr; + iowrite32(tp->csr6 | RxTx, ioaddr + CSR6); + barrier(); + (void) ioread32(ioaddr + CSR6); /* mmio sync */ + } + + static inline void tulip_stop_rxtx(struct tulip_private *tp) + { + void __iomem *ioaddr = tp->base_addr; + u32 csr6 = ioread32(ioaddr + CSR6); + + if (csr6 & RxTx) { + unsigned i=1300/10; + iowrite32(csr6 & ~RxTx, ioaddr + CSR6); + barrier(); + /* wait until in-flight frame completes. + * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) + * Typically expect this loop to end in < 50 us on 100BT. + */ + while (--i && (ioread32(ioaddr + CSR5) & (CSR5_TS|CSR5_RS))) + udelay(10); + + if (!i) + netdev_dbg(tp->dev, "tulip_stop_rxtx() failed (CSR5 0x%x CSR6 0x%x)\n", + ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); + } + } + + static inline void tulip_restart_rxtx(struct tulip_private *tp) + { + tulip_stop_rxtx(tp); + udelay(5); + tulip_start_rxtx(tp); + } + + static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __iomem *ioaddr) + { + /* Stop and restart the chip's Tx processes. */ + tulip_restart_rxtx(tp); + /* Trigger an immediate transmit demand. */ + iowrite32(0, ioaddr + CSR1); + + tp->dev->stats.tx_errors++; + } + + #endif /* __NET_TULIP_H__ */ diff --cc drivers/net/ethernet/dec/tulip/tulip_core.c index 000000000000,011f67c7ca47..9656dd0647d9 mode 000000,100644..100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@@ -1,0 -1,2011 +1,2008 @@@ + /* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. + + Copyright 2000,2001 The Linux Kernel Team + Written/copyright 1994-2001 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + - Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver. - + Please submit bugs to http://bugzilla.kernel.org/ . + */ + + #define pr_fmt(fmt) "tulip: " fmt + + #define DRV_NAME "tulip" + #ifdef CONFIG_TULIP_NAPI + #define DRV_VERSION "1.1.15-NAPI" /* Keep at least for test */ + #else + #define DRV_VERSION "1.1.15" + #endif + #define DRV_RELDATE "Feb 27, 2007" + + + #include + #include + #include + #include "tulip.h" + #include + #include + #include + #include + #include + #include + #include + #include + + #ifdef CONFIG_SPARC + #include + #endif + + static char version[] __devinitdata = + "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; + + /* A few user-configurable values. */ + + /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ + static unsigned int max_interrupt_work = 25; + + #define MAX_UNITS 8 + /* Used to pass the full-duplex flag, etc. */ + static int full_duplex[MAX_UNITS]; + static int options[MAX_UNITS]; + static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */ + + /* The possible media types that can be set in options[] are: */ + const char * const medianame[32] = { + "10baseT", "10base2", "AUI", "100baseTx", + "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx", + "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII", + "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4", + "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19", + "","","","", "","","","", "","","","Transceiver reset", + }; + + /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ + #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) || \ + defined(CONFIG_SPARC) || defined(__ia64__) || \ + defined(__sh__) || defined(__mips__) + static int rx_copybreak = 1518; + #else + static int rx_copybreak = 100; + #endif + + /* + Set the bus performance register. + Typical: Set 16 longword cache alignment, no burst limit. + Cache alignment bits 15:14 Burst length 13:8 + 0000 No alignment 0x00000000 unlimited 0800 8 longwords + 4000 8 longwords 0100 1 longword 1000 16 longwords + 8000 16 longwords 0200 2 longwords 2000 32 longwords + C000 32 longwords 0400 4 longwords + Warning: many older 486 systems are broken and require setting 0x00A04800 + 8 longword cache alignment, 8 longword burst. + ToDo: Non-Intel setting could be better. + */ + + #if defined(__alpha__) || defined(__ia64__) + static int csr0 = 0x01A00000 | 0xE000; + #elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__) + static int csr0 = 0x01A00000 | 0x8000; + #elif defined(CONFIG_SPARC) || defined(__hppa__) + /* The UltraSparc PCI controllers will disconnect at every 64-byte + * crossing anyways so it makes no sense to tell Tulip to burst + * any more than that. + */ + static int csr0 = 0x01A00000 | 0x9000; + #elif defined(__arm__) || defined(__sh__) + static int csr0 = 0x01A00000 | 0x4800; + #elif defined(__mips__) + static int csr0 = 0x00200000 | 0x4000; + #else + #warning Processor architecture undefined! + static int csr0 = 0x00A00000 | 0x4800; + #endif + + /* Operational parameters that usually are not changed. */ + /* Time in jiffies before concluding the transmitter is hung. */ + #define TX_TIMEOUT (4*HZ) + + + MODULE_AUTHOR("The Linux Kernel Team"); + MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + module_param(tulip_debug, int, 0); + module_param(max_interrupt_work, int, 0); + module_param(rx_copybreak, int, 0); + module_param(csr0, int, 0); + module_param_array(options, int, NULL, 0); + module_param_array(full_duplex, int, NULL, 0); + + #ifdef TULIP_DEBUG + int tulip_debug = TULIP_DEBUG; + #else + int tulip_debug = 1; + #endif + + static void tulip_timer(unsigned long data) + { + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = netdev_priv(dev); + + if (netif_running(dev)) + schedule_work(&tp->media_work); + } + + /* + * This table use during operation for capabilities and media timer. + * + * It is indexed via the values in 'enum chips' + */ + + struct tulip_chip_table tulip_tbl[] = { + { }, /* placeholder for array, slot unused currently */ + { }, /* placeholder for array, slot unused currently */ + + /* DC21140 */ + { "Digital DS21140 Tulip", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer, + tulip_media_task }, + + /* DC21142, DC21143 */ + { "Digital DS21142/43 Tulip", 128, 0x0801fbff, + HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY + | HAS_INTR_MITIGATION | HAS_PCI_MWI, tulip_timer, t21142_media_task }, + + /* LC82C168 */ + { "Lite-On 82c168 PNIC", 256, 0x0001fbef, + HAS_MII | HAS_PNICNWAY, pnic_timer, }, + + /* MX98713 */ + { "Macronix 98713 PMAC", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, }, + + /* MX98715 */ + { "Macronix 98715 PMAC", 256, 0x0001ebef, + HAS_MEDIA_TABLE, mxic_timer, }, + + /* MX98725 */ + { "Macronix 98725 PMAC", 256, 0x0001ebef, + HAS_MEDIA_TABLE, mxic_timer, }, + + /* AX88140 */ + { "ASIX AX88140", 128, 0x0001fbff, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY + | IS_ASIX, tulip_timer, tulip_media_task }, + + /* PNIC2 */ + { "Lite-On PNIC-II", 256, 0x0801fbff, + HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer, }, + + /* COMET */ + { "ADMtek Comet", 256, 0x0001abef, + HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer, }, + + /* COMPEX9881 */ + { "Compex 9881 PMAC", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, }, + + /* I21145 */ + { "Intel DS21145 Tulip", 128, 0x0801fbff, + HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI + | HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task }, + + /* DM910X */ + #ifdef CONFIG_TULIP_DM910X + { "Davicom DM9102/DM9102A", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, + tulip_timer, tulip_media_task }, + #else + { NULL }, + #endif + + /* RS7112 */ + { "Conexant LANfinity", 256, 0x0001ebef, + HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task }, + + }; + + + static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = { + { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, + { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 }, + { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 }, + { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 }, + { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, + /* { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 },*/ + { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 }, + { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 }, + { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1317, 0x1985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1317, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x13D1, 0xAB02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x13D1, 0xAB03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x13D1, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x104A, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x104A, 0x2774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 }, + { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 }, + #ifdef CONFIG_TULIP_DM910X + { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, + { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, + #endif + { 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, + { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1186, 0x1591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT }, + { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ + { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ + { 0x1414, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Microsoft MN-120 */ + { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { } /* terminate list */ + }; + MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); + + + /* A full-duplex map for media types. */ + const char tulip_media_cap[32] = + {0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 28,31,0,0, }; + + static void tulip_tx_timeout(struct net_device *dev); + static void tulip_init_ring(struct net_device *dev); + static void tulip_free_ring(struct net_device *dev); + static netdev_tx_t tulip_start_xmit(struct sk_buff *skb, + struct net_device *dev); + static int tulip_open(struct net_device *dev); + static int tulip_close(struct net_device *dev); + static void tulip_up(struct net_device *dev); + static void tulip_down(struct net_device *dev); + static struct net_device_stats *tulip_get_stats(struct net_device *dev); + static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + static void set_rx_mode(struct net_device *dev); + static void tulip_set_wolopts(struct pci_dev *pdev, u32 wolopts); + #ifdef CONFIG_NET_POLL_CONTROLLER + static void poll_tulip(struct net_device *dev); + #endif + + static void tulip_set_power_state (struct tulip_private *tp, + int sleep, int snooze) + { + if (tp->flags & HAS_ACPI) { + u32 tmp, newtmp; + pci_read_config_dword (tp->pdev, CFDD, &tmp); + newtmp = tmp & ~(CFDD_Sleep | CFDD_Snooze); + if (sleep) + newtmp |= CFDD_Sleep; + else if (snooze) + newtmp |= CFDD_Snooze; + if (tmp != newtmp) + pci_write_config_dword (tp->pdev, CFDD, newtmp); + } + + } + + + static void tulip_up(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int next_tick = 3*HZ; + u32 reg; + int i; + + #ifdef CONFIG_TULIP_NAPI + napi_enable(&tp->napi); + #endif + + /* Wake the chip from sleep/snooze mode. */ + tulip_set_power_state (tp, 0, 0); + + /* Disable all WOL events */ + pci_enable_wake(tp->pdev, PCI_D3hot, 0); + pci_enable_wake(tp->pdev, PCI_D3cold, 0); + tulip_set_wolopts(tp->pdev, 0); + + /* On some chip revs we must set the MII/SYM port before the reset!? */ + if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) + iowrite32(0x00040000, ioaddr + CSR6); + + /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ + iowrite32(0x00000001, ioaddr + CSR0); + pci_read_config_dword(tp->pdev, PCI_COMMAND, ®); /* flush write */ + udelay(100); + + /* Deassert reset. + Wait the specified 50 PCI cycles after a reset by initializing + Tx and Rx queues and the address filter list. */ + iowrite32(tp->csr0, ioaddr + CSR0); + pci_read_config_dword(tp->pdev, PCI_COMMAND, ®); /* flush write */ + udelay(100); + + if (tulip_debug > 1) + netdev_dbg(dev, "tulip_up(), irq==%d\n", dev->irq); + + iowrite32(tp->rx_ring_dma, ioaddr + CSR3); + iowrite32(tp->tx_ring_dma, ioaddr + CSR4); + tp->cur_rx = tp->cur_tx = 0; + tp->dirty_rx = tp->dirty_tx = 0; + + if (tp->flags & MC_HASH_ONLY) { + u32 addr_low = get_unaligned_le32(dev->dev_addr); + u32 addr_high = get_unaligned_le16(dev->dev_addr + 4); + if (tp->chip_id == AX88140) { + iowrite32(0, ioaddr + CSR13); + iowrite32(addr_low, ioaddr + CSR14); + iowrite32(1, ioaddr + CSR13); + iowrite32(addr_high, ioaddr + CSR14); + } else if (tp->flags & COMET_MAC_ADDR) { + iowrite32(addr_low, ioaddr + 0xA4); + iowrite32(addr_high, ioaddr + 0xA8); + iowrite32(0, ioaddr + CSR27); + iowrite32(0, ioaddr + CSR28); + } + } else { + /* This is set_rx_mode(), but without starting the transmitter. */ + u16 *eaddrs = (u16 *)dev->dev_addr; + u16 *setup_frm = &tp->setup_frame[15*6]; + dma_addr_t mapping; + + /* 21140 bug: you must add the broadcast address. */ + memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame)); + /* Fill the final entry of the table with our physical address. */ + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + + mapping = pci_map_single(tp->pdev, tp->setup_frame, + sizeof(tp->setup_frame), + PCI_DMA_TODEVICE); + tp->tx_buffers[tp->cur_tx].skb = NULL; + tp->tx_buffers[tp->cur_tx].mapping = mapping; + + /* Put the setup frame on the Tx list. */ + tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192); + tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping); + tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned); + + tp->cur_tx++; + } + + tp->saved_if_port = dev->if_port; + if (dev->if_port == 0) + dev->if_port = tp->default_port; + + /* Allow selecting a default media. */ + i = 0; + if (tp->mtable == NULL) + goto media_picked; + if (dev->if_port) { + int looking_for = tulip_media_cap[dev->if_port] & MediaIsMII ? 11 : + (dev->if_port == 12 ? 0 : dev->if_port); + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == looking_for) { + dev_info(&dev->dev, + "Using user-specified media %s\n", + medianame[dev->if_port]); + goto media_picked; + } + } + if ((tp->mtable->defaultmedia & 0x0800) == 0) { + int looking_for = tp->mtable->defaultmedia & MEDIA_MASK; + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == looking_for) { + dev_info(&dev->dev, + "Using EEPROM-set media %s\n", + medianame[looking_for]); + goto media_picked; + } + } + /* Start sensing first non-full-duplex media. */ + for (i = tp->mtable->leafcount - 1; + (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) + ; + media_picked: + + tp->csr6 = 0; + tp->cur_index = i; + tp->nwayset = 0; + + if (dev->if_port) { + if (tp->chip_id == DC21143 && + (tulip_media_cap[dev->if_port] & MediaIsMII)) { + /* We must reset the media CSRs when we force-select MII mode. */ + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + iowrite32(0x0008, ioaddr + CSR15); + } + tulip_select_media(dev, 1); + } else if (tp->chip_id == DC21142) { + if (tp->mii_cnt) { + tulip_select_media(dev, 1); + if (tulip_debug > 1) + dev_info(&dev->dev, + "Using MII transceiver %d, status %04x\n", + tp->phys[0], + tulip_mdio_read(dev, tp->phys[0], 1)); + iowrite32(csr6_mask_defstate, ioaddr + CSR6); + tp->csr6 = csr6_mask_hdcap; + dev->if_port = 11; + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + } else + t21142_start_nway(dev); + } else if (tp->chip_id == PNIC2) { + /* for initial startup advertise 10/100 Full and Half */ + tp->sym_advertise = 0x01E0; + /* enable autonegotiate end interrupt */ + iowrite32(ioread32(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5); + iowrite32(ioread32(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7); + pnic2_start_nway(dev); + } else if (tp->chip_id == LC82C168 && ! tp->medialock) { + if (tp->mii_cnt) { + dev->if_port = 11; + tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); + iowrite32(0x0001, ioaddr + CSR15); + } else if (ioread32(ioaddr + CSR5) & TPLnkPass) + pnic_do_nway(dev); + else { + /* Start with 10mbps to do autonegotiation. */ + iowrite32(0x32, ioaddr + CSR12); + tp->csr6 = 0x00420000; + iowrite32(0x0001B078, ioaddr + 0xB8); + iowrite32(0x0201B078, ioaddr + 0xB8); + next_tick = 1*HZ; + } + } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) && + ! tp->medialock) { + dev->if_port = 0; + tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); + iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); + } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { + /* Provided by BOLO, Macronix - 12/10/1998. */ + dev->if_port = 0; + tp->csr6 = 0x01a80200; + iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); + iowrite32(0x11000 | ioread16(ioaddr + 0xa0), ioaddr + 0xa0); + } else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) { + /* Enable automatic Tx underrun recovery. */ + iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); + dev->if_port = tp->mii_cnt ? 11 : 0; + tp->csr6 = 0x00040000; + } else if (tp->chip_id == AX88140) { + tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; + } else + tulip_select_media(dev, 1); + + /* Start the chip's Tx to process setup frame. */ + tulip_stop_rxtx(tp); + barrier(); + udelay(5); + iowrite32(tp->csr6 | TxOn, ioaddr + CSR6); + + /* Enable interrupts by setting the interrupt mask. */ + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + tulip_start_rxtx(tp); + iowrite32(0, ioaddr + CSR2); /* Rx poll demand */ + + if (tulip_debug > 2) { + netdev_dbg(dev, "Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n", + ioread32(ioaddr + CSR0), + ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); + } + + /* Set the timer to switch to check for link beat and perhaps switch + to an alternate media type. */ + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); + #ifdef CONFIG_TULIP_NAPI + init_timer(&tp->oom_timer); + tp->oom_timer.data = (unsigned long)dev; + tp->oom_timer.function = oom_timer; + #endif + } + + static int + tulip_open(struct net_device *dev) + { + int retval; + + tulip_init_ring (dev); + + retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto free_ring; + + tulip_up (dev); + + netif_start_queue (dev); + + return 0; + + free_ring: + tulip_free_ring (dev); + return retval; + } + + + static void tulip_tx_timeout(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + unsigned long flags; + + spin_lock_irqsave (&tp->lock, flags); + + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + /* Do nothing -- the media monitor should handle this. */ + if (tulip_debug > 1) + dev_warn(&dev->dev, + "Transmit timeout using MII device\n"); + } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142 || + tp->chip_id == MX98713 || tp->chip_id == COMPEX9881 || + tp->chip_id == DM910X) { + dev_warn(&dev->dev, + "21140 transmit timed out, status %08x, SIA %08x %08x %08x %08x, resetting...\n", + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), + ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), + ioread32(ioaddr + CSR15)); + tp->timeout_recovery = 1; + schedule_work(&tp->media_work); + goto out_unlock; + } else if (tp->chip_id == PNIC2) { + dev_warn(&dev->dev, + "PNIC2 transmit timed out, status %08x, CSR6/7 %08x / %08x CSR12 %08x, resetting...\n", + (int)ioread32(ioaddr + CSR5), + (int)ioread32(ioaddr + CSR6), + (int)ioread32(ioaddr + CSR7), + (int)ioread32(ioaddr + CSR12)); + } else { + dev_warn(&dev->dev, + "Transmit timed out, status %08x, CSR12 %08x, resetting...\n", + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12)); + dev->if_port = 0; + } + + #if defined(way_too_many_messages) + if (tulip_debug > 3) { + int i; + for (i = 0; i < RX_RING_SIZE; i++) { + u8 *buf = (u8 *)(tp->rx_ring[i].buffer1); + int j; + printk(KERN_DEBUG + "%2d: %08x %08x %08x %08x %02x %02x %02x\n", + i, + (unsigned int)tp->rx_ring[i].status, + (unsigned int)tp->rx_ring[i].length, + (unsigned int)tp->rx_ring[i].buffer1, + (unsigned int)tp->rx_ring[i].buffer2, + buf[0], buf[1], buf[2]); + for (j = 0; buf[j] != 0xee && j < 1600; j++) + if (j < 100) + pr_cont(" %02x", buf[j]); + pr_cont(" j=%d\n", j); + } + printk(KERN_DEBUG " Rx ring %p: ", tp->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + pr_cont(" %08x", (unsigned int)tp->rx_ring[i].status); + printk(KERN_DEBUG " Tx ring %p: ", tp->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + pr_cont(" %08x", (unsigned int)tp->tx_ring[i].status); + pr_cont("\n"); + } + #endif + + tulip_tx_timeout_complete(tp, ioaddr); + + out_unlock: + spin_unlock_irqrestore (&tp->lock, flags); + dev->trans_start = jiffies; /* prevent tx timeout */ + netif_wake_queue (dev); + } + + + /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ + static void tulip_init_ring(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + int i; + + tp->susp_rx = 0; + tp->ttimer = 0; + tp->nir = 0; + + for (i = 0; i < RX_RING_SIZE; i++) { + tp->rx_ring[i].status = 0x00000000; + tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ); + tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1)); + tp->rx_buffers[i].skb = NULL; + tp->rx_buffers[i].mapping = 0; + } + /* Mark the last entry as wrapping the ring. */ + tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP); + tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma); + + for (i = 0; i < RX_RING_SIZE; i++) { + dma_addr_t mapping; + + /* Note the receive buffer must be longword aligned. + dev_alloc_skb() provides 16 byte alignment. But do *not* + use skb_reserve() to align the IP header! */ + struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); + tp->rx_buffers[i].skb = skb; + if (skb == NULL) + break; + mapping = pci_map_single(tp->pdev, skb->data, + PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + tp->rx_buffers[i].mapping = mapping; + skb->dev = dev; /* Mark as being used by this device. */ + tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ + tp->rx_ring[i].buffer1 = cpu_to_le32(mapping); + } + tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); + + /* The Tx buffer descriptor is filled in as needed, but we + do need to clear the ownership bit. */ + for (i = 0; i < TX_RING_SIZE; i++) { + tp->tx_buffers[i].skb = NULL; + tp->tx_buffers[i].mapping = 0; + tp->tx_ring[i].status = 0x00000000; + tp->tx_ring[i].buffer2 = cpu_to_le32(tp->tx_ring_dma + sizeof(struct tulip_tx_desc) * (i + 1)); + } + tp->tx_ring[i-1].buffer2 = cpu_to_le32(tp->tx_ring_dma); + } + + static netdev_tx_t + tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + int entry; + u32 flag; + dma_addr_t mapping; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + /* Calculate the next Tx descriptor entry. */ + entry = tp->cur_tx % TX_RING_SIZE; + + tp->tx_buffers[entry].skb = skb; + mapping = pci_map_single(tp->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + tp->tx_buffers[entry].mapping = mapping; + tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); + + if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ + flag = 0x60000000; /* No interrupt */ + } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) { + flag = 0xe0000000; /* Tx-done intr. */ + } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { + flag = 0x60000000; /* No Tx-done intr. */ + } else { /* Leave room for set_rx_mode() to fill entries. */ + flag = 0xe0000000; /* Tx-done intr. */ + netif_stop_queue(dev); + } + if (entry == TX_RING_SIZE-1) + flag = 0xe0000000 | DESC_RING_WRAP; + + tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); + /* if we were using Transmit Automatic Polling, we would need a + * wmb() here. */ + tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + wmb(); + + tp->cur_tx++; + + /* Trigger an immediate transmit demand. */ + iowrite32(0, tp->base_addr + CSR1); + + spin_unlock_irqrestore(&tp->lock, flags); + + return NETDEV_TX_OK; + } + + static void tulip_clean_tx_ring(struct tulip_private *tp) + { + unsigned int dirty_tx; + + for (dirty_tx = tp->dirty_tx ; tp->cur_tx - dirty_tx > 0; + dirty_tx++) { + int entry = dirty_tx % TX_RING_SIZE; + int status = le32_to_cpu(tp->tx_ring[entry].status); + + if (status < 0) { + tp->dev->stats.tx_errors++; /* It wasn't Txed */ + tp->tx_ring[entry].status = 0; + } + + /* Check for Tx filter setup frames. */ + if (tp->tx_buffers[entry].skb == NULL) { + /* test because dummy frames not mapped */ + if (tp->tx_buffers[entry].mapping) + pci_unmap_single(tp->pdev, + tp->tx_buffers[entry].mapping, + sizeof(tp->setup_frame), + PCI_DMA_TODEVICE); + continue; + } + + pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, + tp->tx_buffers[entry].skb->len, + PCI_DMA_TODEVICE); + + /* Free the original skb. */ + dev_kfree_skb_irq(tp->tx_buffers[entry].skb); + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = 0; + } + } + + static void tulip_down (struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + unsigned long flags; + + cancel_work_sync(&tp->media_work); + + #ifdef CONFIG_TULIP_NAPI + napi_disable(&tp->napi); + #endif + + del_timer_sync (&tp->timer); + #ifdef CONFIG_TULIP_NAPI + del_timer_sync (&tp->oom_timer); + #endif + spin_lock_irqsave (&tp->lock, flags); + + /* Disable interrupts by clearing the interrupt mask. */ + iowrite32 (0x00000000, ioaddr + CSR7); + + /* Stop the Tx and Rx processes. */ + tulip_stop_rxtx(tp); + + /* prepare receive buffers */ + tulip_refill_rx(dev); + + /* release any unconsumed transmit buffers */ + tulip_clean_tx_ring(tp); + + if (ioread32(ioaddr + CSR6) != 0xffffffff) + dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; + + spin_unlock_irqrestore (&tp->lock, flags); + + init_timer(&tp->timer); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; + + dev->if_port = tp->saved_if_port; + + /* Leave the driver in snooze, not sleep, mode. */ + tulip_set_power_state (tp, 0, 1); + } + + static void tulip_free_ring (struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + int i; + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb = tp->rx_buffers[i].skb; + dma_addr_t mapping = tp->rx_buffers[i].mapping; + + tp->rx_buffers[i].skb = NULL; + tp->rx_buffers[i].mapping = 0; + + tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */ + tp->rx_ring[i].length = 0; + /* An invalid address. */ + tp->rx_ring[i].buffer1 = cpu_to_le32(0xBADF00D0); + if (skb) { + pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ, + PCI_DMA_FROMDEVICE); + dev_kfree_skb (skb); + } + } + + for (i = 0; i < TX_RING_SIZE; i++) { + struct sk_buff *skb = tp->tx_buffers[i].skb; + + if (skb != NULL) { + pci_unmap_single(tp->pdev, tp->tx_buffers[i].mapping, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb (skb); + } + tp->tx_buffers[i].skb = NULL; + tp->tx_buffers[i].mapping = 0; + } + } + + static int tulip_close (struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + netif_stop_queue (dev); + + tulip_down (dev); + + if (tulip_debug > 1) + netdev_dbg(dev, "Shutting down ethercard, status was %02x\n", + ioread32 (ioaddr + CSR5)); + + free_irq (dev->irq, dev); + + tulip_free_ring (dev); + + return 0; + } + + static struct net_device_stats *tulip_get_stats(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + if (netif_running(dev)) { + unsigned long flags; + + spin_lock_irqsave (&tp->lock, flags); + + dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; + + spin_unlock_irqrestore(&tp->lock, flags); + } + + return &dev->stats; + } + + + static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) + { + struct tulip_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); + } + + + static int tulip_ethtool_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wolinfo) + { + struct tulip_private *tp = netdev_priv(dev); + + if (wolinfo->wolopts & (~tp->wolinfo.supported)) + return -EOPNOTSUPP; + + tp->wolinfo.wolopts = wolinfo->wolopts; + device_set_wakeup_enable(&tp->pdev->dev, tp->wolinfo.wolopts); + return 0; + } + + static void tulip_ethtool_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wolinfo) + { + struct tulip_private *tp = netdev_priv(dev); + + wolinfo->supported = tp->wolinfo.supported; + wolinfo->wolopts = tp->wolinfo.wolopts; + return; + } + + + static const struct ethtool_ops ops = { + .get_drvinfo = tulip_get_drvinfo, + .set_wol = tulip_ethtool_set_wol, + .get_wol = tulip_ethtool_get_wol, + }; + + /* Provide ioctl() calls to examine the MII xcvr state. */ + static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + struct mii_ioctl_data *data = if_mii(rq); + const unsigned int phy_idx = 0; + int phy = tp->phys[phy_idx] & 0x1f; + unsigned int regnum = data->reg_num; + + switch (cmd) { + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + if (tp->mii_cnt) + data->phy_id = phy; + else if (tp->flags & HAS_NWAY) + data->phy_id = 32; + else if (tp->chip_id == COMET) + data->phy_id = 1; + else + return -ENODEV; + + case SIOCGMIIREG: /* Read MII PHY register. */ + if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { + int csr12 = ioread32 (ioaddr + CSR12); + int csr14 = ioread32 (ioaddr + CSR14); + switch (regnum) { + case 0: + if (((csr14<<5) & 0x1000) || + (dev->if_port == 5 && tp->nwayset)) + data->val_out = 0x1000; + else + data->val_out = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0) + | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0); + break; + case 1: + data->val_out = + 0x1848 + + ((csr12&0x7000) == 0x5000 ? 0x20 : 0) + + ((csr12&0x06) == 6 ? 0 : 4); + data->val_out |= 0x6048; + break; + case 4: + /* Advertised value, bogus 10baseTx-FD value from CSR6. */ + data->val_out = + ((ioread32(ioaddr + CSR6) >> 3) & 0x0040) + + ((csr14 >> 1) & 0x20) + 1; + data->val_out |= ((csr14 >> 9) & 0x03C0); + break; + case 5: data->val_out = tp->lpar; break; + default: data->val_out = 0; break; + } + } else { + data->val_out = tulip_mdio_read (dev, data->phy_id & 0x1f, regnum); + } + return 0; + + case SIOCSMIIREG: /* Write MII PHY register. */ + if (regnum & ~0x1f) + return -EINVAL; + if (data->phy_id == phy) { + u16 value = data->val_in; + switch (regnum) { + case 0: /* Check for autonegotiation on or reset. */ + tp->full_duplex_lock = (value & 0x9000) ? 0 : 1; + if (tp->full_duplex_lock) + tp->full_duplex = (value & 0x0100) ? 1 : 0; + break; + case 4: + tp->advertising[phy_idx] = + tp->mii_advertise = data->val_in; + break; + } + } + if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { + u16 value = data->val_in; + if (regnum == 0) { + if ((value & 0x1200) == 0x1200) { + if (tp->chip_id == PNIC2) { + pnic2_start_nway (dev); + } else { + t21142_start_nway (dev); + } + } + } else if (regnum == 4) + tp->sym_advertise = value; + } else { + tulip_mdio_write (dev, data->phy_id & 0x1f, regnum, data->val_in); + } + return 0; + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; + } + + + /* Set or clear the multicast filter for this adaptor. + Note that we only use exclusion around actually queueing the + new frame, not around filling tp->setup_frame. This is non-deterministic + when re-entered but still correct. */ + + #undef set_bit_le + #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) + + static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + u16 hash_table[32]; + struct netdev_hw_addr *ha; + int i; + u16 *eaddrs; + + memset(hash_table, 0, sizeof(hash_table)); + set_bit_le(255, hash_table); /* Broadcast entry */ + /* This should work on big-endian machines as well. */ + netdev_for_each_mc_addr(ha, dev) { + int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; + + set_bit_le(index, hash_table); + } + for (i = 0; i < 32; i++) { + *setup_frm++ = hash_table[i]; + *setup_frm++ = hash_table[i]; + } + setup_frm = &tp->setup_frame[13*6]; + + /* Fill the final entry with our physical address. */ + eaddrs = (u16 *)dev->dev_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + + static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + struct netdev_hw_addr *ha; + u16 *eaddrs; + + /* We have <= 14 addresses so we can use the wonderful + 16 address perfect filtering of the Tulip. */ + netdev_for_each_mc_addr(ha, dev) { + eaddrs = (u16 *) ha->addr; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + } + /* Fill the unused entries with the broadcast address. */ + memset(setup_frm, 0xff, (15 - netdev_mc_count(dev)) * 12); + setup_frm = &tp->setup_frame[15*6]; + + /* Fill the final entry with our physical address. */ + eaddrs = (u16 *)dev->dev_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + + + static void set_rx_mode(struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int csr6; + + csr6 = ioread32(ioaddr + CSR6) & ~0x00D5; + + tp->csr6 &= ~0x00D5; + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + tp->csr6 |= AcceptAllMulticast | AcceptAllPhys; + csr6 |= AcceptAllMulticast | AcceptAllPhys; + } else if ((netdev_mc_count(dev) > 1000) || + (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter well -- accept all multicasts. */ + tp->csr6 |= AcceptAllMulticast; + csr6 |= AcceptAllMulticast; + } else if (tp->flags & MC_HASH_ONLY) { + /* Some work-alikes have only a 64-entry hash filter table. */ + /* Should verify correctness on big-endian/__powerpc__ */ + struct netdev_hw_addr *ha; + if (netdev_mc_count(dev) > 64) { + /* Arbitrary non-effective limit. */ + tp->csr6 |= AcceptAllMulticast; + csr6 |= AcceptAllMulticast; + } else { + u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ + int filterbit; + netdev_for_each_mc_addr(ha, dev) { + if (tp->flags & COMET_MAC_ADDR) + filterbit = ether_crc_le(ETH_ALEN, + ha->addr); + else + filterbit = ether_crc(ETH_ALEN, + ha->addr) >> 26; + filterbit &= 0x3f; + mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); + if (tulip_debug > 2) + dev_info(&dev->dev, + "Added filter for %pM %08x bit %d\n", + ha->addr, + ether_crc(ETH_ALEN, ha->addr), + filterbit); + } + if (mc_filter[0] == tp->mc_filter[0] && + mc_filter[1] == tp->mc_filter[1]) + ; /* No change. */ + else if (tp->flags & IS_ASIX) { + iowrite32(2, ioaddr + CSR13); + iowrite32(mc_filter[0], ioaddr + CSR14); + iowrite32(3, ioaddr + CSR13); + iowrite32(mc_filter[1], ioaddr + CSR14); + } else if (tp->flags & COMET_MAC_ADDR) { + iowrite32(mc_filter[0], ioaddr + CSR27); + iowrite32(mc_filter[1], ioaddr + CSR28); + } + tp->mc_filter[0] = mc_filter[0]; + tp->mc_filter[1] = mc_filter[1]; + } + } else { + unsigned long flags; + u32 tx_flags = 0x08000000 | 192; + + /* Note that only the low-address shortword of setup_frame is valid! + The values are doubled for big-endian architectures. */ + if (netdev_mc_count(dev) > 14) { + /* Must use a multicast hash table. */ + build_setup_frame_hash(tp->setup_frame, dev); + tx_flags = 0x08400000 | 192; + } else { + build_setup_frame_perfect(tp->setup_frame, dev); + } + + spin_lock_irqsave(&tp->lock, flags); + + if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { + /* Same setup recently queued, we need not add it. */ + } else { + unsigned int entry; + int dummy = -1; + + /* Now add this frame to the Tx list. */ + + entry = tp->cur_tx++ % TX_RING_SIZE; + + if (entry != 0) { + /* Avoid a chip errata by prefixing a dummy entry. */ + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = 0; + tp->tx_ring[entry].length = + (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0; + tp->tx_ring[entry].buffer1 = 0; + /* Must set DescOwned later to avoid race with chip */ + dummy = entry; + entry = tp->cur_tx++ % TX_RING_SIZE; + + } + + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = + pci_map_single(tp->pdev, tp->setup_frame, + sizeof(tp->setup_frame), + PCI_DMA_TODEVICE); + /* Put the setup frame on the Tx list. */ + if (entry == TX_RING_SIZE-1) + tx_flags |= DESC_RING_WRAP; /* Wrap ring. */ + tp->tx_ring[entry].length = cpu_to_le32(tx_flags); + tp->tx_ring[entry].buffer1 = + cpu_to_le32(tp->tx_buffers[entry].mapping); + tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + if (dummy >= 0) + tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); + if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) + netif_stop_queue(dev); + + /* Trigger an immediate transmit demand. */ + iowrite32(0, ioaddr + CSR1); + } + + spin_unlock_irqrestore(&tp->lock, flags); + } + + iowrite32(csr6, ioaddr + CSR6); + } + + #ifdef CONFIG_TULIP_MWI + static void __devinit tulip_mwi_config (struct pci_dev *pdev, + struct net_device *dev) + { + struct tulip_private *tp = netdev_priv(dev); + u8 cache; + u16 pci_command; + u32 csr0; + + if (tulip_debug > 3) + netdev_dbg(dev, "tulip_mwi_config()\n"); + + tp->csr0 = csr0 = 0; + + /* if we have any cache line size at all, we can do MRM and MWI */ + csr0 |= MRM | MWI; + + /* Enable MWI in the standard PCI command bit. + * Check for the case where MWI is desired but not available + */ + pci_try_set_mwi(pdev); + + /* read result from hardware (in case bit refused to enable) */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if ((csr0 & MWI) && (!(pci_command & PCI_COMMAND_INVALIDATE))) + csr0 &= ~MWI; + + /* if cache line size hardwired to zero, no MWI */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); + if ((csr0 & MWI) && (cache == 0)) { + csr0 &= ~MWI; + pci_clear_mwi(pdev); + } + + /* assign per-cacheline-size cache alignment and + * burst length values + */ + switch (cache) { + case 8: + csr0 |= MRL | (1 << CALShift) | (16 << BurstLenShift); + break; + case 16: + csr0 |= MRL | (2 << CALShift) | (16 << BurstLenShift); + break; + case 32: + csr0 |= MRL | (3 << CALShift) | (32 << BurstLenShift); + break; + default: + cache = 0; + break; + } + + /* if we have a good cache line size, we by now have a good + * csr0, so save it and exit + */ + if (cache) + goto out; + + /* we don't have a good csr0 or cache line size, disable MWI */ + if (csr0 & MWI) { + pci_clear_mwi(pdev); + csr0 &= ~MWI; + } + + /* sane defaults for burst length and cache alignment + * originally from de4x5 driver + */ + csr0 |= (8 << BurstLenShift) | (1 << CALShift); + + out: + tp->csr0 = csr0; + if (tulip_debug > 2) + netdev_dbg(dev, "MWI config cacheline=%d, csr0=%08x\n", + cache, csr0); + } + #endif + + /* + * Chips that have the MRM/reserved bit quirk and the burst quirk. That + * is the DM910X and the on chip ULi devices + */ + + static int tulip_uli_dm_quirk(struct pci_dev *pdev) + { + if (pdev->vendor == 0x1282 && pdev->device == 0x9102) + return 1; + return 0; + } + + static const struct net_device_ops tulip_netdev_ops = { + .ndo_open = tulip_open, + .ndo_start_xmit = tulip_start_xmit, + .ndo_tx_timeout = tulip_tx_timeout, + .ndo_stop = tulip_close, + .ndo_get_stats = tulip_get_stats, + .ndo_do_ioctl = private_ioctl, + .ndo_set_rx_mode = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = poll_tulip, + #endif + }; + + DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) }, + { }, + }; + + static int __devinit tulip_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent) + { + struct tulip_private *tp; + /* See note below on the multiport cards. */ + static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'}; + static int last_irq; + static int multiport_cnt; /* For four-port boards w/one EEPROM */ + int i, irq; + unsigned short sum; + unsigned char *ee_data; + struct net_device *dev; + void __iomem *ioaddr; + static int board_idx = -1; + int chip_idx = ent->driver_data; + const char *chip_name = tulip_tbl[chip_idx].chip_name; + unsigned int eeprom_missing = 0; + unsigned int force_csr0 = 0; + + #ifndef MODULE + if (tulip_debug > 0) + printk_once(KERN_INFO "%s", version); + #endif + + board_idx++; + + /* + * Lan media wire a tulip chip to a wan interface. Needs a very + * different driver (lmc driver) + */ + + if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) { + pr_err("skipping LMC card\n"); + return -ENODEV; + } else if (pdev->subsystem_vendor == PCI_VENDOR_ID_SBE && + (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_T3E3 || + pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P0 || + pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)) { + pr_err("skipping SBE T3E3 port\n"); + return -ENODEV; + } + + /* + * DM910x chips should be handled by the dmfe driver, except + * on-board chips on SPARC systems. Also, early DM9100s need + * software CRC which only the dmfe driver supports. + */ + + #ifdef CONFIG_TULIP_DM910X + if (chip_idx == DM910X) { + struct device_node *dp; + + if (pdev->vendor == 0x1282 && pdev->device == 0x9100 && + pdev->revision < 0x30) { + pr_info("skipping early DM9100 with Crc bug (use dmfe)\n"); + return -ENODEV; + } + + dp = pci_device_to_OF_node(pdev); + if (!(dp && of_get_property(dp, "local-mac-address", NULL))) { + pr_info("skipping DM910x expansion card (use dmfe)\n"); + return -ENODEV; + } + } + #endif + + /* + * Looks for early PCI chipsets where people report hangs + * without the workarounds being on. + */ + + /* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache + aligned. Aries might need this too. The Saturn errata are not + pretty reading but thankfully it's an old 486 chipset. + + 2. The dreaded SiS496 486 chipset. Same workaround as Intel + Saturn. + */ + + if (pci_dev_present(early_486_chipsets)) { + csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift); + force_csr0 = 1; + } + + /* bugfix: the ASIX must have a burst limit or horrible things happen. */ + if (chip_idx == AX88140) { + if ((csr0 & 0x3f00) == 0) + csr0 |= 0x2000; + } + + /* PNIC doesn't have MWI/MRL/MRM... */ + if (chip_idx == LC82C168) + csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */ + + /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */ + if (tulip_uli_dm_quirk(pdev)) { + csr0 &= ~0x01f100ff; + #if defined(CONFIG_SPARC) + csr0 = (csr0 & ~0xff00) | 0xe000; + #endif + } + /* + * And back to business + */ + + i = pci_enable_device(pdev); + if (i) { + pr_err("Cannot enable tulip board #%d, aborting\n", board_idx); + return i; + } + + /* The chip will fail to enter a low-power state later unless + * first explicitly commanded into D0 */ + if (pci_set_power_state(pdev, PCI_D0)) { + pr_notice("Failed to set power state to D0\n"); + } + + irq = pdev->irq; + + /* alloc_etherdev ensures aligned and zeroed private structures */ + dev = alloc_etherdev (sizeof (*tp)); + if (!dev) { + pr_err("ether device alloc failed, aborting\n"); + return -ENOMEM; + } + + SET_NETDEV_DEV(dev, &pdev->dev); + if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { + pr_err("%s: I/O region (0x%llx@0x%llx) too small, aborting\n", + pci_name(pdev), + (unsigned long long)pci_resource_len (pdev, 0), + (unsigned long long)pci_resource_start (pdev, 0)); + goto err_out_free_netdev; + } + + /* grab all resources from both PIO and MMIO regions, as we + * don't want anyone else messing around with our hardware */ + if (pci_request_regions (pdev, DRV_NAME)) + goto err_out_free_netdev; + + ioaddr = pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size); + + if (!ioaddr) + goto err_out_free_res; + + /* + * initialize private data structure 'tp' + * it is zeroed and aligned in alloc_etherdev + */ + tp = netdev_priv(dev); + tp->dev = dev; + + tp->rx_ring = pci_alloc_consistent(pdev, + sizeof(struct tulip_rx_desc) * RX_RING_SIZE + + sizeof(struct tulip_tx_desc) * TX_RING_SIZE, + &tp->rx_ring_dma); + if (!tp->rx_ring) + goto err_out_mtable; + tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); + tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; + + tp->chip_id = chip_idx; + tp->flags = tulip_tbl[chip_idx].flags; + + tp->wolinfo.supported = 0; + tp->wolinfo.wolopts = 0; + /* COMET: Enable power management only for AN983B */ + if (chip_idx == COMET ) { + u32 sig; + pci_read_config_dword (pdev, 0x80, &sig); + if (sig == 0x09811317) { + tp->flags |= COMET_PM; + tp->wolinfo.supported = WAKE_PHY | WAKE_MAGIC; + pr_info("%s: Enabled WOL support for AN983B\n", + __func__); + } + } + tp->pdev = pdev; + tp->base_addr = ioaddr; + tp->revision = pdev->revision; + tp->csr0 = csr0; + spin_lock_init(&tp->lock); + spin_lock_init(&tp->mii_lock); + init_timer(&tp->timer); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; + + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); + + dev->base_addr = (unsigned long)ioaddr; + + #ifdef CONFIG_TULIP_MWI + if (!force_csr0 && (tp->flags & HAS_PCI_MWI)) + tulip_mwi_config (pdev, dev); + #endif + + /* Stop the chip's Tx and Rx processes. */ + tulip_stop_rxtx(tp); + + pci_set_master(pdev); + + #ifdef CONFIG_GSC + if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) { + switch (pdev->subsystem_device) { + default: + break; + case 0x1061: + case 0x1062: + case 0x1063: + case 0x1098: + case 0x1099: + case 0x10EE: + tp->flags |= HAS_SWAPPED_SEEPROM | NEEDS_FAKE_MEDIA_TABLE; + chip_name = "GSC DS21140 Tulip"; + } + } + #endif + + /* Clear the missed-packet counter. */ + ioread32(ioaddr + CSR8); + + /* The station address ROM is read byte serially. The register must + be polled, waiting for the value to be read bit serially from the + EEPROM. + */ + ee_data = tp->eeprom; + memset(ee_data, 0, sizeof(tp->eeprom)); + sum = 0; + if (chip_idx == LC82C168) { + for (i = 0; i < 3; i++) { + int value, boguscnt = 100000; + iowrite32(0x600 | i, ioaddr + 0x98); + do { + value = ioread32(ioaddr + CSR9); + } while (value < 0 && --boguscnt > 0); + put_unaligned_le16(value, ((__le16 *)dev->dev_addr) + i); + sum += value & 0xffff; + } + } else if (chip_idx == COMET) { + /* No need to read the EEPROM. */ + put_unaligned_le32(ioread32(ioaddr + 0xA4), dev->dev_addr); + put_unaligned_le16(ioread32(ioaddr + 0xA8), dev->dev_addr + 4); + for (i = 0; i < 6; i ++) + sum += dev->dev_addr[i]; + } else { + /* A serial EEPROM interface, we read now and sort it out later. */ + int sa_offset = 0; + int ee_addr_size = tulip_read_eeprom(dev, 0xff, 8) & 0x40000 ? 8 : 6; + int ee_max_addr = ((1 << ee_addr_size) - 1) * sizeof(u16); + + if (ee_max_addr > sizeof(tp->eeprom)) + ee_max_addr = sizeof(tp->eeprom); + + for (i = 0; i < ee_max_addr ; i += sizeof(u16)) { + u16 data = tulip_read_eeprom(dev, i/2, ee_addr_size); + ee_data[i] = data & 0xff; + ee_data[i + 1] = data >> 8; + } + + /* DEC now has a specification (see Notes) but early board makers + just put the address in the first EEPROM locations. */ + /* This does memcmp(ee_data, ee_data+16, 8) */ + for (i = 0; i < 8; i ++) + if (ee_data[i] != ee_data[16+i]) + sa_offset = 20; + if (chip_idx == CONEXANT) { + /* Check that the tuple type and length is correct. */ + if (ee_data[0x198] == 0x04 && ee_data[0x199] == 6) + sa_offset = 0x19A; + } else if (ee_data[0] == 0xff && ee_data[1] == 0xff && + ee_data[2] == 0) { + sa_offset = 2; /* Grrr, damn Matrox boards. */ + multiport_cnt = 4; + } + #ifdef CONFIG_MIPS_COBALT + if ((pdev->bus->number == 0) && + ((PCI_SLOT(pdev->devfn) == 7) || + (PCI_SLOT(pdev->devfn) == 12))) { + /* Cobalt MAC address in first EEPROM locations. */ + sa_offset = 0; + /* Ensure our media table fixup get's applied */ + memcpy(ee_data + 16, ee_data, 8); + } + #endif + #ifdef CONFIG_GSC + /* Check to see if we have a broken srom */ + if (ee_data[0] == 0x61 && ee_data[1] == 0x10) { + /* pci_vendor_id and subsystem_id are swapped */ + ee_data[0] = ee_data[2]; + ee_data[1] = ee_data[3]; + ee_data[2] = 0x61; + ee_data[3] = 0x10; + + /* HSC-PCI boards need to be byte-swaped and shifted + * up 1 word. This shift needs to happen at the end + * of the MAC first because of the 2 byte overlap. + */ + for (i = 4; i >= 0; i -= 2) { + ee_data[17 + i + 3] = ee_data[17 + i]; + ee_data[16 + i + 5] = ee_data[16 + i]; + } + } + #endif + + for (i = 0; i < 6; i ++) { + dev->dev_addr[i] = ee_data[i + sa_offset]; + sum += ee_data[i + sa_offset]; + } + } + /* Lite-On boards have the address byte-swapped. */ + if ((dev->dev_addr[0] == 0xA0 || + dev->dev_addr[0] == 0xC0 || + dev->dev_addr[0] == 0x02) && + dev->dev_addr[1] == 0x00) + for (i = 0; i < 6; i+=2) { + char tmp = dev->dev_addr[i]; + dev->dev_addr[i] = dev->dev_addr[i+1]; + dev->dev_addr[i+1] = tmp; + } + /* On the Zynx 315 Etherarray and other multiport boards only the + first Tulip has an EEPROM. + On Sparc systems the mac address is held in the OBP property + "local-mac-address". + The addresses of the subsequent ports are derived from the first. + Many PCI BIOSes also incorrectly report the IRQ line, so we correct + that here as well. */ + if (sum == 0 || sum == 6*0xff) { + #if defined(CONFIG_SPARC) + struct device_node *dp = pci_device_to_OF_node(pdev); + const unsigned char *addr; + int len; + #endif + eeprom_missing = 1; + for (i = 0; i < 5; i++) + dev->dev_addr[i] = last_phys_addr[i]; + dev->dev_addr[i] = last_phys_addr[i] + 1; + #if defined(CONFIG_SPARC) + addr = of_get_property(dp, "local-mac-address", &len); + if (addr && len == 6) + memcpy(dev->dev_addr, addr, 6); + #endif + #if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */ + if (last_irq) + irq = last_irq; + #endif + } + + for (i = 0; i < 6; i++) + last_phys_addr[i] = dev->dev_addr[i]; + last_irq = irq; + dev->irq = irq; + + /* The lower four bits are the media type. */ + if (board_idx >= 0 && board_idx < MAX_UNITS) { + if (options[board_idx] & MEDIA_MASK) + tp->default_port = options[board_idx] & MEDIA_MASK; + if ((options[board_idx] & FullDuplex) || full_duplex[board_idx] > 0) + tp->full_duplex = 1; + if (mtu[board_idx] > 0) + dev->mtu = mtu[board_idx]; + } + if (dev->mem_start & MEDIA_MASK) + tp->default_port = dev->mem_start & MEDIA_MASK; + if (tp->default_port) { + pr_info(DRV_NAME "%d: Transceiver selection forced to %s\n", + board_idx, medianame[tp->default_port & MEDIA_MASK]); + tp->medialock = 1; + if (tulip_media_cap[tp->default_port] & MediaAlwaysFD) + tp->full_duplex = 1; + } + if (tp->full_duplex) + tp->full_duplex_lock = 1; + + if (tulip_media_cap[tp->default_port] & MediaIsMII) { + static const u16 media2advert[] = { + 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 + }; + tp->mii_advertise = media2advert[tp->default_port - 9]; + tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */ + } + + if (tp->flags & HAS_MEDIA_TABLE) { + sprintf(dev->name, DRV_NAME "%d", board_idx); /* hack */ + tulip_parse_eeprom(dev); + strcpy(dev->name, "eth%d"); /* un-hack */ + } + + if ((tp->flags & ALWAYS_CHECK_MII) || + (tp->mtable && tp->mtable->has_mii) || + ( ! tp->mtable && (tp->flags & HAS_MII))) { + if (tp->mtable && tp->mtable->has_mii) { + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == 11) { + tp->cur_index = i; + tp->saved_if_port = dev->if_port; + tulip_select_media(dev, 2); + dev->if_port = tp->saved_if_port; + break; + } + } + + /* Find the connected MII xcvrs. + Doing this in open() would allow detecting external xcvrs + later, but takes much time. */ + tulip_find_mii (dev, board_idx); + } + + /* The Tulip-specific entries in the device structure. */ + dev->netdev_ops = &tulip_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; + #ifdef CONFIG_TULIP_NAPI + netif_napi_add(dev, &tp->napi, tulip_poll, 16); + #endif + SET_ETHTOOL_OPS(dev, &ops); + + if (register_netdev(dev)) + goto err_out_free_ring; + + pci_set_drvdata(pdev, dev); + + dev_info(&dev->dev, + #ifdef CONFIG_TULIP_MMIO + "%s rev %d at MMIO %#llx,%s %pM, IRQ %d\n", + #else + "%s rev %d at Port %#llx,%s %pM, IRQ %d\n", + #endif + chip_name, pdev->revision, + (unsigned long long)pci_resource_start(pdev, TULIP_BAR), + eeprom_missing ? " EEPROM not present," : "", + dev->dev_addr, irq); + + if (tp->chip_id == PNIC2) + tp->link_change = pnic2_lnk_change; + else if (tp->flags & HAS_NWAY) + tp->link_change = t21142_lnk_change; + else if (tp->flags & HAS_PNICNWAY) + tp->link_change = pnic_lnk_change; + + /* Reset the xcvr interface and turn on heartbeat. */ + switch (chip_idx) { + case DC21140: + case DM910X: + default: + if (tp->mtable) + iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); + break; + case DC21142: + if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) { + iowrite32(csr6_mask_defstate, ioaddr + CSR6); + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + iowrite32(csr6_mask_hdcap, ioaddr + CSR6); + } else + t21142_start_nway(dev); + break; + case PNIC2: + /* just do a reset for sanity sake */ + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + break; + case LC82C168: + if ( ! tp->mii_cnt) { + tp->nway = 1; + tp->nwayset = 0; + iowrite32(csr6_ttm | csr6_ca, ioaddr + CSR6); + iowrite32(0x30, ioaddr + CSR12); + iowrite32(0x0001F078, ioaddr + CSR6); + iowrite32(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */ + } + break; + case MX98713: + case COMPEX9881: + iowrite32(0x00000000, ioaddr + CSR6); + iowrite32(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ + iowrite32(0x00000001, ioaddr + CSR13); + break; + case MX98715: + case MX98725: + iowrite32(0x01a80000, ioaddr + CSR6); + iowrite32(0xFFFFFFFF, ioaddr + CSR14); + iowrite32(0x00001000, ioaddr + CSR12); + break; + case COMET: + /* No initialization necessary. */ + break; + } + + /* put the chip in snooze mode until opened */ + tulip_set_power_state (tp, 0, 1); + + return 0; + + err_out_free_ring: + pci_free_consistent (pdev, + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, + tp->rx_ring, tp->rx_ring_dma); + + err_out_mtable: + kfree (tp->mtable); + pci_iounmap(pdev, ioaddr); + + err_out_free_res: + pci_release_regions (pdev); + + err_out_free_netdev: + free_netdev (dev); + return -ENODEV; + } + + + /* set the registers according to the given wolopts */ + static void tulip_set_wolopts (struct pci_dev *pdev, u32 wolopts) + { + struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + if (tp->flags & COMET_PM) { + + unsigned int tmp; + + tmp = ioread32(ioaddr + CSR18); + tmp &= ~(comet_csr18_pmes_sticky | comet_csr18_apm_mode | comet_csr18_d3a); + tmp |= comet_csr18_pm_mode; + iowrite32(tmp, ioaddr + CSR18); + + /* Set the Wake-up Control/Status Register to the given WOL options*/ + tmp = ioread32(ioaddr + CSR13); + tmp &= ~(comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_wfre | comet_csr13_lsce | comet_csr13_mpre); + if (wolopts & WAKE_MAGIC) + tmp |= comet_csr13_mpre; + if (wolopts & WAKE_PHY) + tmp |= comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_lsce; + /* Clear the event flags */ + tmp |= comet_csr13_wfr | comet_csr13_mpr | comet_csr13_lsc; + iowrite32(tmp, ioaddr + CSR13); + } + } + + #ifdef CONFIG_PM + + + static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) + { + pci_power_t pstate; + struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); + + if (!dev) + return -EINVAL; + + if (!netif_running(dev)) + goto save_state; + + tulip_down(dev); + + netif_device_detach(dev); + free_irq(dev->irq, dev); + + save_state: + pci_save_state(pdev); + pci_disable_device(pdev); + pstate = pci_choose_state(pdev, state); + if (state.event == PM_EVENT_SUSPEND && pstate != PCI_D0) { + int rc; + + tulip_set_wolopts(pdev, tp->wolinfo.wolopts); + rc = pci_enable_wake(pdev, pstate, tp->wolinfo.wolopts); + if (rc) + pr_err("pci_enable_wake failed (%d)\n", rc); + } + pci_set_power_state(pdev, pstate); + + return 0; + } + + + static int tulip_resume(struct pci_dev *pdev) + { + struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + int retval; + unsigned int tmp; + + if (!dev) + return -EINVAL; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (!netif_running(dev)) + return 0; + + if ((retval = pci_enable_device(pdev))) { + pr_err("pci_enable_device failed in resume\n"); + return retval; + } + + if ((retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev))) { + pr_err("request_irq failed in resume\n"); + return retval; + } + + if (tp->flags & COMET_PM) { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + /* Clear the PMES flag */ + tmp = ioread32(ioaddr + CSR20); + tmp |= comet_csr20_pmes; + iowrite32(tmp, ioaddr + CSR20); + + /* Disable all wake-up events */ + tulip_set_wolopts(pdev, 0); + } + netif_device_attach(dev); + + if (netif_running(dev)) + tulip_up(dev); + + return 0; + } + + #endif /* CONFIG_PM */ + + + static void __devexit tulip_remove_one (struct pci_dev *pdev) + { + struct net_device *dev = pci_get_drvdata (pdev); + struct tulip_private *tp; + + if (!dev) + return; + + tp = netdev_priv(dev); + unregister_netdev(dev); + pci_free_consistent (pdev, + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, + tp->rx_ring, tp->rx_ring_dma); + kfree (tp->mtable); + pci_iounmap(pdev, tp->base_addr); + free_netdev (dev); + pci_release_regions (pdev); + pci_set_drvdata (pdev, NULL); + + /* pci_power_off (pdev, -1); */ + } + + #ifdef CONFIG_NET_POLL_CONTROLLER + /* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ + + static void poll_tulip (struct net_device *dev) + { + /* disable_irq here is not very nice, but with the lockless + interrupt handler we have no other choice. */ + disable_irq(dev->irq); + tulip_interrupt (dev->irq, dev); + enable_irq(dev->irq); + } + #endif + + static struct pci_driver tulip_driver = { + .name = DRV_NAME, + .id_table = tulip_pci_tbl, + .probe = tulip_init_one, + .remove = __devexit_p(tulip_remove_one), + #ifdef CONFIG_PM + .suspend = tulip_suspend, + .resume = tulip_resume, + #endif /* CONFIG_PM */ + }; + + + static int __init tulip_init (void) + { + #ifdef MODULE + pr_info("%s", version); + #endif + + /* copy module parms into globals */ + tulip_rx_copybreak = rx_copybreak; + tulip_max_interrupt_work = max_interrupt_work; + + /* probe for and init boards */ + return pci_register_driver(&tulip_driver); + } + + + static void __exit tulip_cleanup (void) + { + pci_unregister_driver (&tulip_driver); + } + + + module_init(tulip_init); + module_exit(tulip_cleanup); diff --cc drivers/net/ethernet/intel/igb/e1000_mbx.c index 000000000000,74f2f11ac290..469d95eaa154 mode 000000,100644..100644 --- a/drivers/net/ethernet/intel/igb/e1000_mbx.c +++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c @@@ -1,0 -1,446 +1,446 @@@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver + Copyright(c) 2007-2011 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + + *******************************************************************************/ + + #include "e1000_mbx.h" + + /** + * igb_read_mbx - Reads a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * - * returns SUCCESS if it successfuly read message from buffer ++ * returns SUCCESS if it successfully read message from buffer + **/ + s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size = mbx->size; + + if (mbx->ops.read) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; + } + + /** + * igb_write_mbx - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer + **/ + s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = 0; + + if (size > mbx->size) + ret_val = -E1000_ERR_MBX; + + else if (mbx->ops.write) + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + return ret_val; + } + + /** + * igb_check_for_msg - checks to see if someone sent us mail + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_msg) + ret_val = mbx->ops.check_for_msg(hw, mbx_id); + + return ret_val; + } + + /** + * igb_check_for_ack - checks to see if someone sent us ACK + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_ack) + ret_val = mbx->ops.check_for_ack(hw, mbx_id); + + return ret_val; + } + + /** + * igb_check_for_rst - checks to see if other side has reset + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_rst) + ret_val = mbx->ops.check_for_rst(hw, mbx_id); + + return ret_val; + } + + /** + * igb_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification + **/ + static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_msg) + goto out; + + while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + out: + return countdown ? 0 : -E1000_ERR_MBX; + } + + /** + * igb_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message acknowledgement + **/ + static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_ack) + goto out; + + while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + out: + return countdown ? 0 : -E1000_ERR_MBX; + } + + /** + * igb_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ + static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + ret_val = igb_poll_for_msg(hw, mbx_id); + + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + out: + return ret_val; + } + + /** + * igb_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ + static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + /* exit if either we can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + goto out; + + /* send msg */ + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = igb_poll_for_ack(hw, mbx_id); + out: + return ret_val; + } + + static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask) + { + u32 mbvficr = rd32(E1000_MBVFICR); + s32 ret_val = -E1000_ERR_MBX; + + if (mbvficr & mask) { + ret_val = 0; + wr32(E1000_MBVFICR, mask); + } + + return ret_val; + } + + /** + * igb_check_for_msg_pf - checks to see if the VF has sent mail + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) + { + s32 ret_val = -E1000_ERR_MBX; + + if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; + } + + /** + * igb_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) + { + s32 ret_val = -E1000_ERR_MBX; + + if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; + } + + /** + * igb_check_for_rst_pf - checks to see if the VF has reset + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) + { + u32 vflre = rd32(E1000_VFLRE); + s32 ret_val = -E1000_ERR_MBX; + + if (vflre & (1 << vf_number)) { + ret_val = 0; + wr32(E1000_VFLRE, (1 << vf_number)); + hw->mbx.stats.rsts++; + } + + return ret_val; + } + + /** + * igb_obtain_mbx_lock_pf - obtain mailbox lock + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * return SUCCESS if we obtained the mailbox lock + **/ + static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) + { + s32 ret_val = -E1000_ERR_MBX; + u32 p2v_mailbox; + + + /* Take ownership of the buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + + /* reserve mailbox for vf use */ + p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); + if (p2v_mailbox & E1000_P2VMAILBOX_PFU) + ret_val = 0; + + return ret_val; + } + + /** + * igb_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * returns SUCCESS if it successfully copied message into the buffer + **/ + static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, + u16 vf_number) + { + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_write; + + /* flush msg and acks as we are overwriting the message buffer */ + igb_check_for_msg_pf(hw, vf_number); + igb_check_for_ack_pf(hw, vf_number); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + array_wr32(E1000_VMBMEM(vf_number), i, msg[i]); + + /* Interrupt VF to tell it a message has been sent and release buffer*/ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + + out_no_write: + return ret_val; + + } + + /** + * igb_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a VF request so no polling for message is needed. + **/ + static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, + u16 vf_number) + { + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_read; + + /* copy the message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); + + /* Acknowledge the message and release buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + + out_no_read: + return ret_val; + } + + /** + * e1000_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for pf mailbox + */ + s32 igb_init_mbx_params_pf(struct e1000_hw *hw) + { + struct e1000_mbx_info *mbx = &hw->mbx; + + mbx->timeout = 0; + mbx->usec_delay = 0; + + mbx->size = E1000_VFMAILBOX_SIZE; + + mbx->ops.read = igb_read_mbx_pf; + mbx->ops.write = igb_write_mbx_pf; + mbx->ops.read_posted = igb_read_posted_mbx; + mbx->ops.write_posted = igb_write_posted_mbx; + mbx->ops.check_for_msg = igb_check_for_msg_pf; + mbx->ops.check_for_ack = igb_check_for_ack_pf; + mbx->ops.check_for_rst = igb_check_for_rst_pf; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + + return 0; + } + diff --cc drivers/net/ethernet/intel/igbvf/mbx.c index 000000000000,3d6f4cc3998a..048aae248d06 mode 000000,100644..100644 --- a/drivers/net/ethernet/intel/igbvf/mbx.c +++ b/drivers/net/ethernet/intel/igbvf/mbx.c @@@ -1,0 -1,350 +1,350 @@@ + /******************************************************************************* + + Intel(R) 82576 Virtual Function Linux driver + Copyright(c) 2009 - 2010 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + + *******************************************************************************/ + + #include "mbx.h" + + /** + * e1000_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * + * returns SUCCESS if it successfully received a message notification + **/ + static s32 e1000_poll_for_msg(struct e1000_hw *hw) + { + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!mbx->ops.check_for_msg) + goto out; + + while (countdown && mbx->ops.check_for_msg(hw)) { + countdown--; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + out: + return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; + } + + /** + * e1000_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * + * returns SUCCESS if it successfully received a message acknowledgement + **/ + static s32 e1000_poll_for_ack(struct e1000_hw *hw) + { + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!mbx->ops.check_for_ack) + goto out; + + while (countdown && mbx->ops.check_for_ack(hw)) { + countdown--; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + out: + return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; + } + + /** + * e1000_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ + static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + ret_val = e1000_poll_for_msg(hw); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size); + out: + return ret_val; + } + + /** + * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ + static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + /* exit if we either can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + goto out; + + /* send msg*/ + ret_val = mbx->ops.write(hw, msg, size); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = e1000_poll_for_ack(hw); + out: + return ret_val; + } + + /** + * e1000_read_v2p_mailbox - read v2p mailbox + * @hw: pointer to the HW structure + * + * This function is used to read the v2p mailbox without losing the read to + * clear status bits. + **/ + static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw) + { + u32 v2p_mailbox = er32(V2PMAILBOX(0)); + + v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox; + hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS; + + return v2p_mailbox; + } + + /** + * e1000_check_for_bit_vf - Determine if a status bit was set + * @hw: pointer to the HW structure + * @mask: bitmask for bits to be tested and cleared + * + * This function is used to check for the read to clear bits within + * the V2P mailbox. + **/ + static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask) + { + u32 v2p_mailbox = e1000_read_v2p_mailbox(hw); + s32 ret_val = -E1000_ERR_MBX; + + if (v2p_mailbox & mask) + ret_val = E1000_SUCCESS; + + hw->dev_spec.vf.v2p_mailbox &= ~mask; + + return ret_val; + } + + /** + * e1000_check_for_msg_vf - checks to see if the PF has sent mail + * @hw: pointer to the HW structure + * + * returns SUCCESS if the PF has set the Status bit or else ERR_MBX + **/ + static s32 e1000_check_for_msg_vf(struct e1000_hw *hw) + { + s32 ret_val = -E1000_ERR_MBX; + + if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) { + ret_val = E1000_SUCCESS; + hw->mbx.stats.reqs++; + } + + return ret_val; + } + + /** + * e1000_check_for_ack_vf - checks to see if the PF has ACK'd + * @hw: pointer to the HW structure + * + * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX + **/ + static s32 e1000_check_for_ack_vf(struct e1000_hw *hw) + { + s32 ret_val = -E1000_ERR_MBX; + + if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) { + ret_val = E1000_SUCCESS; + hw->mbx.stats.acks++; + } + + return ret_val; + } + + /** + * e1000_check_for_rst_vf - checks to see if the PF has reset + * @hw: pointer to the HW structure + * + * returns true if the PF has set the reset done bit or else false + **/ + static s32 e1000_check_for_rst_vf(struct e1000_hw *hw) + { + s32 ret_val = -E1000_ERR_MBX; + + if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD | + E1000_V2PMAILBOX_RSTI))) { + ret_val = E1000_SUCCESS; + hw->mbx.stats.rsts++; + } + + return ret_val; + } + + /** + * e1000_obtain_mbx_lock_vf - obtain mailbox lock + * @hw: pointer to the HW structure + * + * return SUCCESS if we obtained the mailbox lock + **/ + static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw) + { + s32 ret_val = -E1000_ERR_MBX; + + /* Take ownership of the buffer */ + ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); + + /* reserve mailbox for vf use */ + if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) + ret_val = E1000_SUCCESS; + + return ret_val; + } + + /** + * e1000_write_mbx_vf - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns SUCCESS if it successfully copied message into the buffer + **/ + static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) + { + s32 err; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + err = e1000_obtain_mbx_lock_vf(hw); + if (err) + goto out_no_write; + + /* flush any ack or msg as we are going to overwrite mailbox */ + e1000_check_for_ack_vf(hw); + e1000_check_for_msg_vf(hw); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + array_ew32(VMBMEM(0), i, msg[i]); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + + /* Drop VFU and interrupt the PF to tell it a message has been sent */ + ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ); + + out_no_write: + return err; + } + + /** + * e1000_read_mbx_vf - Reads a message from the inbox intended for vf + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * - * returns SUCCESS if it successfuly read message from buffer ++ * returns SUCCESS if it successfully read message from buffer + **/ + static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) + { + s32 err; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + err = e1000_obtain_mbx_lock_vf(hw); + if (err) + goto out_no_read; + + /* copy the message from the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = array_er32(VMBMEM(0), i); + + /* Acknowledge receipt and release mailbox, then we're done */ + ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + + out_no_read: + return err; + } + + /** + * e1000_init_mbx_params_vf - set initial values for vf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for vf mailbox + */ + s32 e1000_init_mbx_params_vf(struct e1000_hw *hw) + { + struct e1000_mbx_info *mbx = &hw->mbx; + + /* start mailbox as timed out and let the reset_hw call set the timeout + * value to being communications */ + mbx->timeout = 0; + mbx->usec_delay = E1000_VF_MBX_INIT_DELAY; + + mbx->size = E1000_VFMAILBOX_SIZE; + + mbx->ops.read = e1000_read_mbx_vf; + mbx->ops.write = e1000_write_mbx_vf; + mbx->ops.read_posted = e1000_read_posted_mbx; + mbx->ops.write_posted = e1000_write_posted_mbx; + mbx->ops.check_for_msg = e1000_check_for_msg_vf; + mbx->ops.check_for_ack = e1000_check_for_ack_vf; + mbx->ops.check_for_rst = e1000_check_for_rst_vf; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + + return E1000_SUCCESS; + } + diff --cc drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index 000000000000,1ff0eefcfd0a..3f725d48336d mode 000000,100644..100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@@ -1,0 -1,471 +1,471 @@@ + /******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2011 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + + *******************************************************************************/ + + #include + #include + #include "ixgbe_type.h" + #include "ixgbe_common.h" + #include "ixgbe_mbx.h" + + /** + * ixgbe_read_mbx - Reads a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * - * returns SUCCESS if it successfuly read message from buffer ++ * returns SUCCESS if it successfully read message from buffer + **/ + s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size = mbx->size; + + if (mbx->ops.read) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; + } + + /** + * ixgbe_write_mbx - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer + **/ + s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = 0; + + if (size > mbx->size) + ret_val = IXGBE_ERR_MBX; + + else if (mbx->ops.write) + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + return ret_val; + } + + /** + * ixgbe_check_for_msg - checks to see if someone sent us mail + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_msg) + ret_val = mbx->ops.check_for_msg(hw, mbx_id); + + return ret_val; + } + + /** + * ixgbe_check_for_ack - checks to see if someone sent us ACK + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_ack) + ret_val = mbx->ops.check_for_ack(hw, mbx_id); + + return ret_val; + } + + /** + * ixgbe_check_for_rst - checks to see if other side has reset + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ + s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_rst) + ret_val = mbx->ops.check_for_rst(hw, mbx_id); + + return ret_val; + } + + /** + * ixgbe_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification + **/ + static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_msg) + goto out; + + while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + out: + return countdown ? 0 : IXGBE_ERR_MBX; + } + + /** + * ixgbe_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message acknowledgement + **/ + static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_ack) + goto out; + + while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + out: + return countdown ? 0 : IXGBE_ERR_MBX; + } + + /** + * ixgbe_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ + static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + ret_val = ixgbe_poll_for_msg(hw, mbx_id); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + out: + return ret_val; + } + + /** + * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ + static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + /* exit if either we can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + goto out; + + /* send msg */ + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = ixgbe_poll_for_ack(hw, mbx_id); + out: + return ret_val; + } + + static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) + { + u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); + s32 ret_val = IXGBE_ERR_MBX; + + if (mbvficr & mask) { + ret_val = 0; + IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); + } + + return ret_val; + } + + /** + * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) + { + s32 ret_val = IXGBE_ERR_MBX; + s32 index = IXGBE_MBVFICR_INDEX(vf_number); + u32 vf_bit = vf_number % 16; + + if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, + index)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; + } + + /** + * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) + { + s32 ret_val = IXGBE_ERR_MBX; + s32 index = IXGBE_MBVFICR_INDEX(vf_number); + u32 vf_bit = vf_number % 16; + + if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, + index)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; + } + + /** + * ixgbe_check_for_rst_pf - checks to see if the VF has reset + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ + static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) + { + u32 reg_offset = (vf_number < 32) ? 0 : 1; + u32 vf_shift = vf_number % 32; + u32 vflre = 0; + s32 ret_val = IXGBE_ERR_MBX; + + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); + break; + case ixgbe_mac_X540: + vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); + break; + default: + break; + } + + if (vflre & (1 << vf_shift)) { + ret_val = 0; + IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); + hw->mbx.stats.rsts++; + } + + return ret_val; + } + + /** + * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * return SUCCESS if we obtained the mailbox lock + **/ + static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) + { + s32 ret_val = IXGBE_ERR_MBX; + u32 p2v_mailbox; + + /* Take ownership of the buffer */ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); + + /* reserve mailbox for vf use */ + p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); + if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) + ret_val = 0; + + return ret_val; + } + + /** + * ixgbe_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * returns SUCCESS if it successfully copied message into the buffer + **/ + static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_number) + { + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_write; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbe_check_for_msg_pf(hw, vf_number); + ixgbe_check_for_ack_pf(hw, vf_number); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); + + /* Interrupt VF to tell it a message has been sent and release buffer*/ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + + out_no_write: + return ret_val; + + } + + /** + * ixgbe_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a VF request so no polling for message is needed. + **/ + static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_number) + { + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_read; + + /* copy the message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); + + /* Acknowledge the message and release buffer */ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + + out_no_read: + return ret_val; + } + + #ifdef CONFIG_PCI_IOV + /** + * ixgbe_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for pf mailbox + */ + void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + + if (hw->mac.type != ixgbe_mac_82599EB && + hw->mac.type != ixgbe_mac_X540) + return; + + mbx->timeout = 0; + mbx->usec_delay = 0; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + } + #endif /* CONFIG_PCI_IOV */ + + struct ixgbe_mbx_operations mbx_ops_generic = { + .read = ixgbe_read_mbx_pf, + .write = ixgbe_write_mbx_pf, + .read_posted = ixgbe_read_posted_mbx, + .write_posted = ixgbe_write_posted_mbx, + .check_for_msg = ixgbe_check_for_msg_pf, + .check_for_ack = ixgbe_check_for_ack_pf, + .check_for_rst = ixgbe_check_for_rst_pf, + }; + diff --cc drivers/net/ethernet/intel/ixgbevf/mbx.c index 000000000000,7a8833125770..930fa83f2568 mode 000000,100644..100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.c +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c @@@ -1,0 -1,341 +1,341 @@@ + /******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2010 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + + *******************************************************************************/ + + #include "mbx.h" + + /** + * ixgbevf_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * + * returns 0 if it successfully received a message notification + **/ + static s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + while (countdown && mbx->ops.check_for_msg(hw)) { + countdown--; + udelay(mbx->udelay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + + return countdown ? 0 : IXGBE_ERR_MBX; + } + + /** + * ixgbevf_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * + * returns 0 if it successfully received a message acknowledgement + **/ + static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + while (countdown && mbx->ops.check_for_ack(hw)) { + countdown--; + udelay(mbx->udelay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + + return countdown ? 0 : IXGBE_ERR_MBX; + } + + /** + * ixgbevf_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully received a message notification and + * copied it into the receive buffer. + **/ + static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + ret_val = ixgbevf_poll_for_msg(hw); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size); + + return ret_val; + } + + /** + * ixgbevf_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ + static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val; + + /* send msg */ + ret_val = mbx->ops.write(hw, msg, size); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = ixgbevf_poll_for_ack(hw); + + return ret_val; + } + + /** + * ixgbevf_read_v2p_mailbox - read v2p mailbox + * @hw: pointer to the HW structure + * + * This function is used to read the v2p mailbox without losing the read to + * clear status bits. + **/ + static u32 ixgbevf_read_v2p_mailbox(struct ixgbe_hw *hw) + { + u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); + + v2p_mailbox |= hw->mbx.v2p_mailbox; + hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; + + return v2p_mailbox; + } + + /** + * ixgbevf_check_for_bit_vf - Determine if a status bit was set + * @hw: pointer to the HW structure + * @mask: bitmask for bits to be tested and cleared + * + * This function is used to check for the read to clear bits within + * the V2P mailbox. + **/ + static s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) + { + u32 v2p_mailbox = ixgbevf_read_v2p_mailbox(hw); + s32 ret_val = IXGBE_ERR_MBX; + + if (v2p_mailbox & mask) + ret_val = 0; + + hw->mbx.v2p_mailbox &= ~mask; + + return ret_val; + } + + /** + * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail + * @hw: pointer to the HW structure + * + * returns 0 if the PF has set the Status bit or else ERR_MBX + **/ + static s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw) + { + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; + } + + /** + * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd + * @hw: pointer to the HW structure + * + * returns 0 if the PF has set the ACK bit or else ERR_MBX + **/ + static s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw) + { + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; + } + + /** + * ixgbevf_check_for_rst_vf - checks to see if the PF has reset + * @hw: pointer to the HW structure + * + * returns true if the PF has set the reset done bit or else false + **/ + static s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw) + { + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | + IXGBE_VFMAILBOX_RSTI))) { + ret_val = 0; + hw->mbx.stats.rsts++; + } + + return ret_val; + } + + /** + * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock + * @hw: pointer to the HW structure + * + * return 0 if we obtained the mailbox lock + **/ + static s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw) + { + s32 ret_val = IXGBE_ERR_MBX; + + /* Take ownership of the buffer */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); + + /* reserve mailbox for vf use */ + if (ixgbevf_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) + ret_val = 0; + + return ret_val; + } + + /** + * ixgbevf_write_mbx_vf - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully copied message into the buffer + **/ + static s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) + { + s32 ret_val; + u16 i; + + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbevf_obtain_mbx_lock_vf(hw); + if (ret_val) + goto out_no_write; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbevf_check_for_msg_vf(hw); + ixgbevf_check_for_ack_vf(hw); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + + /* Drop VFU and interrupt the PF to tell it a message has been sent */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); + + out_no_write: + return ret_val; + } + + /** + * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for vf + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * - * returns 0 if it successfuly read message from buffer ++ * returns 0 if it successfully read message from buffer + **/ + static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) + { + s32 ret_val = 0; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbevf_obtain_mbx_lock_vf(hw); + if (ret_val) + goto out_no_read; + + /* copy the message from the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); + + /* Acknowledge receipt and release mailbox, then we're done */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + + out_no_read: + return ret_val; + } + + /** + * ixgbevf_init_mbx_params_vf - set initial values for vf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for vf mailbox + */ + static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) + { + struct ixgbe_mbx_info *mbx = &hw->mbx; + + /* start mailbox as timed out and let the reset_hw call set the timeout + * value to begin communications */ + mbx->timeout = 0; + mbx->udelay = IXGBE_VF_MBX_INIT_DELAY; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + + return 0; + } + + struct ixgbe_mbx_operations ixgbevf_mbx_ops = { + .init_params = ixgbevf_init_mbx_params_vf, + .read = ixgbevf_read_mbx_vf, + .write = ixgbevf_write_mbx_vf, + .read_posted = ixgbevf_read_posted_mbx, + .write_posted = ixgbevf_write_posted_mbx, + .check_for_msg = ixgbevf_check_for_msg_vf, + .check_for_ack = ixgbevf_check_for_ack_vf, + .check_for_rst = ixgbevf_check_for_rst_vf, + }; + diff --cc drivers/net/ethernet/marvell/sky2.c index 000000000000,7b083c438a14..cbd026f3bc57 mode 000000,100644..100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@@ -1,0 -1,5158 +1,5158 @@@ + /* + * New driver for Marvell Yukon 2 chipset. + * Based on earlier sk98lin, and skge driver. + * + * This driver intentionally does not support all the features + * of the original driver such as link fail-over and link management because + * those should be done at higher levels. + * + * Copyright (C) 2005 Stephen Hemminger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #include "sky2.h" + + #define DRV_NAME "sky2" + #define DRV_VERSION "1.29" + + /* + * The Yukon II chipset takes 64 bit command blocks (called list elements) + * that are organized into three (receive, transmit, status) different rings + * similar to Tigon3. + */ + + #define RX_LE_SIZE 1024 + #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) + #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) + #define RX_DEF_PENDING RX_MAX_PENDING + + /* This is the worst case number of transmit list elements for a single skb: + VLAN:GSO + CKSUM + Data + skb_frags * DMA */ + #define MAX_SKB_TX_LE (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1)) + #define TX_MIN_PENDING (MAX_SKB_TX_LE+1) + #define TX_MAX_PENDING 1024 + #define TX_DEF_PENDING 127 + + #define TX_WATCHDOG (5 * HZ) + #define NAPI_WEIGHT 64 + #define PHY_RETRIES 1000 + + #define SKY2_EEPROM_MAGIC 0x9955aabb + + #define RING_NEXT(x, s) (((x)+1) & ((s)-1)) + + static const u32 default_msg = + NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK + | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR + | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; + + static int debug = -1; /* defaults above */ + module_param(debug, int, 0); + MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + + static int copybreak __read_mostly = 128; + module_param(copybreak, int, 0); + MODULE_PARM_DESC(copybreak, "Receive copy threshold"); + + static int disable_msi = 0; + module_param(disable_msi, int, 0); + MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); + + static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E01) }, /* SK-9E21M */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B03) }, /* DGE-550T */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, /* 88E8062 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, /* 88E8021 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, /* 88E8022 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, /* 88E8061 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, /* 88E8062 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, /* 88E8035 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4355) }, /* 88E8040T */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */ + { 0 } + }; + + MODULE_DEVICE_TABLE(pci, sky2_id_table); + + /* Avoid conditionals by using array */ + static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; + static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; + static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 }; + + static void sky2_set_multicast(struct net_device *dev); + static irqreturn_t sky2_intr(int irq, void *dev_id); + + /* Access to PHY via serial interconnect */ + static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) + { + int i; + + gma_write16(hw, port, GM_SMI_DATA, val); + gma_write16(hw, port, GM_SMI_CTRL, + GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); + + for (i = 0; i < PHY_RETRIES; i++) { + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (!(ctrl & GM_SMI_CT_BUSY)) + return 0; + + udelay(10); + } + + dev_warn(&hw->pdev->dev, "%s: phy write timeout\n", hw->dev[port]->name); + return -ETIMEDOUT; + + io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; + } + + static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) + { + int i; + + gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) + | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); + + for (i = 0; i < PHY_RETRIES; i++) { + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (ctrl & GM_SMI_CT_RD_VAL) { + *val = gma_read16(hw, port, GM_SMI_DATA); + return 0; + } + + udelay(10); + } + + dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name); + return -ETIMEDOUT; + io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; + } + + static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) + { + u16 v; + __gm_phy_read(hw, port, reg, &v); + return v; + } + + + static void sky2_power_on(struct sky2_hw *hw) + { + /* switch power to VCC (WA for VAUX problem) */ + sky2_write8(hw, B0_POWER_CTRL, + PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); + + /* disable Core Clock Division, */ + sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); + + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1) + /* enable bits are inverted */ + sky2_write8(hw, B2_Y2_CLK_GATE, + Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + else + sky2_write8(hw, B2_Y2_CLK_GATE, 0); + + if (hw->flags & SKY2_HW_ADV_POWER_CTL) { + u32 reg; + + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + + reg = sky2_pci_read32(hw, PCI_DEV_REG4); + /* set all bits to 0 except bits 15..12 and 8 */ + reg &= P_ASPM_CONTROL_MSK; + sky2_pci_write32(hw, PCI_DEV_REG4, reg); + + reg = sky2_pci_read32(hw, PCI_DEV_REG5); + /* set all bits to 0 except bits 28 & 27 */ + reg &= P_CTL_TIM_VMAIN_AV_MSK; + sky2_pci_write32(hw, PCI_DEV_REG5, reg); + + sky2_pci_write32(hw, PCI_CFG_REG_1, 0); + + sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); + + /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ + reg = sky2_read32(hw, B2_GP_IO); + reg |= GLB_GPIO_STAT_RACE_DIS; + sky2_write32(hw, B2_GP_IO, reg); + + sky2_read32(hw, B2_GP_IO); + } + + /* Turn on "driver loaded" LED */ + sky2_write16(hw, B0_CTST, Y2_LED_STAT_ON); + } + + static void sky2_power_aux(struct sky2_hw *hw) + { + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1) + sky2_write8(hw, B2_Y2_CLK_GATE, 0); + else + /* enable bits are inverted */ + sky2_write8(hw, B2_Y2_CLK_GATE, + Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + + /* switch power to VAUX if supported and PME from D3cold */ + if ( (sky2_read32(hw, B0_CTST) & Y2_VAUX_AVAIL) && + pci_pme_capable(hw->pdev, PCI_D3cold)) + sky2_write8(hw, B0_POWER_CTRL, + (PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_ON | PC_VCC_OFF)); + + /* turn off "driver loaded LED" */ + sky2_write16(hw, B0_CTST, Y2_LED_STAT_OFF); + } + + static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) + { + u16 reg; + + /* disable all GMAC IRQ's */ + sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); + + gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ + gma_write16(hw, port, GM_MC_ADDR_H2, 0); + gma_write16(hw, port, GM_MC_ADDR_H3, 0); + gma_write16(hw, port, GM_MC_ADDR_H4, 0); + + reg = gma_read16(hw, port, GM_RX_CTRL); + reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA; + gma_write16(hw, port, GM_RX_CTRL, reg); + } + + /* flow control to advertise bits */ + static const u16 copper_fc_adv[] = { + [FC_NONE] = 0, + [FC_TX] = PHY_M_AN_ASP, + [FC_RX] = PHY_M_AN_PC, + [FC_BOTH] = PHY_M_AN_PC | PHY_M_AN_ASP, + }; + + /* flow control to advertise bits when using 1000BaseX */ + static const u16 fiber_fc_adv[] = { + [FC_NONE] = PHY_M_P_NO_PAUSE_X, + [FC_TX] = PHY_M_P_ASYM_MD_X, + [FC_RX] = PHY_M_P_SYM_MD_X, + [FC_BOTH] = PHY_M_P_BOTH_MD_X, + }; + + /* flow control to GMA disable bits */ + static const u16 gm_fc_disable[] = { + [FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS, + [FC_TX] = GM_GPCR_FC_RX_DIS, + [FC_RX] = GM_GPCR_FC_TX_DIS, + [FC_BOTH] = 0, + }; + + + static void sky2_phy_init(struct sky2_hw *hw, unsigned port) + { + struct sky2_port *sky2 = netdev_priv(hw->dev[port]); + u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; + + if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) && + !(hw->flags & SKY2_HW_NEWER_PHY)) { + u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); + + ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | + PHY_M_EC_MAC_S_MSK); + ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); + + /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */ + if (hw->chip_id == CHIP_ID_YUKON_EC) + /* set downshift counter to 3x and enable downshift */ + ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA; + else + /* set master & slave downshift counter to 1x */ + ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); + + gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); + } + + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + if (sky2_is_copper(hw)) { + if (!(hw->flags & SKY2_HW_GIGABIT)) { + /* enable automatic crossover */ + ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; + + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + u16 spec; + + /* Enable Class A driver for FE+ A0 */ + spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2); + spec |= PHY_M_FESC_SEL_CL_A; + gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); + } + } else { + if (hw->chip_id >= CHIP_ID_YUKON_OPT) { + u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); + + /* enable PHY Reverse Auto-Negotiation */ + ctrl2 |= 1u << 13; + + /* Write PHY changes (SW-reset must follow) */ + gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); + } + + + /* disable energy detect */ + ctrl &= ~PHY_M_PC_EN_DET_MSK; + + /* enable automatic crossover */ + ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); + + /* downshift on PHY 88E1112 and 88E1149 is changed */ + if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) && + (hw->flags & SKY2_HW_NEWER_PHY)) { + /* set downshift counter to 3x and enable downshift */ + ctrl &= ~PHY_M_PC_DSC_MSK; + ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; + } + } + } else { + /* workaround for deviation #4.88 (CRC errors) */ + /* disable Automatic Crossover */ + + ctrl &= ~PHY_M_PC_MDIX_MSK; + } + + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* special setup for PHY 88E1112 Fiber */ + if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) { + pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + + /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl &= ~PHY_M_MAC_MD_MSK; + ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + if (hw->pmd_type == 'P') { + /* select page 1 to access Fiber registers */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1); + + /* for SFP-module set SIGDET polarity to low */ + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl |= PHY_M_FIB_SIGD_POL; + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + } + + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + } + + ctrl = PHY_CT_RESET; + ct1000 = 0; + adv = PHY_AN_CSMA; + reg = 0; + + if (sky2->flags & SKY2_FLAG_AUTO_SPEED) { + if (sky2_is_copper(hw)) { + if (sky2->advertising & ADVERTISED_1000baseT_Full) + ct1000 |= PHY_M_1000C_AFD; + if (sky2->advertising & ADVERTISED_1000baseT_Half) + ct1000 |= PHY_M_1000C_AHD; + if (sky2->advertising & ADVERTISED_100baseT_Full) + adv |= PHY_M_AN_100_FD; + if (sky2->advertising & ADVERTISED_100baseT_Half) + adv |= PHY_M_AN_100_HD; + if (sky2->advertising & ADVERTISED_10baseT_Full) + adv |= PHY_M_AN_10_FD; + if (sky2->advertising & ADVERTISED_10baseT_Half) + adv |= PHY_M_AN_10_HD; + + } else { /* special defines for FIBER (88E1040S only) */ + if (sky2->advertising & ADVERTISED_1000baseT_Full) + adv |= PHY_M_AN_1000X_AFD; + if (sky2->advertising & ADVERTISED_1000baseT_Half) + adv |= PHY_M_AN_1000X_AHD; + } + + /* Restart Auto-negotiation */ + ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; + } else { + /* forced speed/duplex settings */ + ct1000 = PHY_M_1000C_MSE; + + /* Disable auto update for duplex flow control and duplex */ + reg |= GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_SPD_DIS; + + switch (sky2->speed) { + case SPEED_1000: + ctrl |= PHY_CT_SP1000; + reg |= GM_GPCR_SPEED_1000; + break; + case SPEED_100: + ctrl |= PHY_CT_SP100; + reg |= GM_GPCR_SPEED_100; + break; + } + + if (sky2->duplex == DUPLEX_FULL) { + reg |= GM_GPCR_DUP_FULL; + ctrl |= PHY_CT_DUP_MD; + } else if (sky2->speed < SPEED_1000) + sky2->flow_mode = FC_NONE; + } + + if (sky2->flags & SKY2_FLAG_AUTO_PAUSE) { + if (sky2_is_copper(hw)) + adv |= copper_fc_adv[sky2->flow_mode]; + else + adv |= fiber_fc_adv[sky2->flow_mode]; + } else { + reg |= GM_GPCR_AU_FCT_DIS; + reg |= gm_fc_disable[sky2->flow_mode]; + + /* Forward pause packets to GMAC? */ + if (sky2->flow_mode & FC_RX) + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); + else + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + } + + gma_write16(hw, port, GM_GP_CTRL, reg); + + if (hw->flags & SKY2_HW_GIGABIT) + gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); + + gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + + /* Setup Phy LED's */ + ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); + ledover = 0; + + switch (hw->chip_id) { + case CHIP_ID_YUKON_FE: + /* on 88E3082 these bits are at 11..9 (shifted left) */ + ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1; + + ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR); + + /* delete ACT LED control bits */ + ctrl &= ~PHY_M_FELP_LED1_MSK; + /* change ACT LED control to blink mode */ + ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL); + gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); + break; + + case CHIP_ID_YUKON_FE_P: + /* Enable Link Partner Next Page */ + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl |= PHY_M_PC_ENA_LIP_NP; + + /* disable Energy Detect and enable scrambler */ + ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB); + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */ + ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) | + PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) | + PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED); + + gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); + break; + + case CHIP_ID_YUKON_XL: + pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + + /* select page 3 to access LED control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); + + /* set LED Function Control register */ + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ + PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ + PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ + PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ + + /* set Polarity Control register */ + gm_phy_write(hw, port, PHY_MARV_PHY_STAT, + (PHY_M_POLC_LS1_P_MIX(4) | + PHY_M_POLC_IS0_P_MIX(4) | + PHY_M_POLC_LOS_CTRL(2) | + PHY_M_POLC_INIT_CTRL(2) | + PHY_M_POLC_STA1_CTRL(2) | + PHY_M_POLC_STA0_CTRL(2))); + + /* restore page register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + break; + + case CHIP_ID_YUKON_EC_U: + case CHIP_ID_YUKON_EX: + case CHIP_ID_YUKON_SUPR: + pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + + /* select page 3 to access LED control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); + + /* set LED Function Control register */ + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ + PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */ + PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ + PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */ + + /* set Blink Rate in LED Timer Control Register */ + gm_phy_write(hw, port, PHY_MARV_INT_MASK, + ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS)); + /* restore page register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + break; + + default: + /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ + ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; + + /* turn off the Rx LED (LED_RX) */ + ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); + } + + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_UL_2) { + /* apply fixes in PHY AFE */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); + + /* increase differential signal amplitude in 10BASE-T */ + gm_phy_write(hw, port, 0x18, 0xaa99); + gm_phy_write(hw, port, 0x17, 0x2011); + + if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ + gm_phy_write(hw, port, 0x18, 0xa204); + gm_phy_write(hw, port, 0x17, 0x2002); + } + + /* set page register to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } else if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + /* apply workaround for integrated resistors calibration */ + gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); + gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); + } else if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) { + /* apply fixes in PHY AFE */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff); + + /* apply RDAC termination workaround */ + gm_phy_write(hw, port, 24, 0x2800); + gm_phy_write(hw, port, 23, 0x2001); + + /* set page register back to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } else if (hw->chip_id != CHIP_ID_YUKON_EX && + hw->chip_id < CHIP_ID_YUKON_SUPR) { + /* no effect on Yukon-XL */ + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); + + if (!(sky2->flags & SKY2_FLAG_AUTO_SPEED) || + sky2->speed == SPEED_100) { + /* turn on 100 Mbps LED (LED_LINK100) */ + ledover |= PHY_M_LED_MO_100(MO_LED_ON); + } + + if (ledover) + gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); + + } else if (hw->chip_id == CHIP_ID_YUKON_PRM && + (sky2_read8(hw, B2_MAC_CFG) & 0xf) == 0x7) { + int i; + /* This a phy register setup workaround copied from vendor driver. */ + static const struct { + u16 reg, val; + } eee_afe[] = { + { 0x156, 0x58ce }, + { 0x153, 0x99eb }, + { 0x141, 0x8064 }, + /* { 0x155, 0x130b },*/ + { 0x000, 0x0000 }, + { 0x151, 0x8433 }, + { 0x14b, 0x8c44 }, + { 0x14c, 0x0f90 }, + { 0x14f, 0x39aa }, + /* { 0x154, 0x2f39 },*/ + { 0x14d, 0xba33 }, + { 0x144, 0x0048 }, + { 0x152, 0x2010 }, + /* { 0x158, 0x1223 },*/ + { 0x140, 0x4444 }, + { 0x154, 0x2f3b }, + { 0x158, 0xb203 }, + { 0x157, 0x2029 }, + }; + + /* Start Workaround for OptimaEEE Rev.Z0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fb); + + gm_phy_write(hw, port, 1, 0x4099); + gm_phy_write(hw, port, 3, 0x1120); + gm_phy_write(hw, port, 11, 0x113c); + gm_phy_write(hw, port, 14, 0x8100); + gm_phy_write(hw, port, 15, 0x112a); + gm_phy_write(hw, port, 17, 0x1008); + + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fc); + gm_phy_write(hw, port, 1, 0x20b0); + + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff); + + for (i = 0; i < ARRAY_SIZE(eee_afe); i++) { + /* apply AFE settings */ + gm_phy_write(hw, port, 17, eee_afe[i].val); + gm_phy_write(hw, port, 16, eee_afe[i].reg | 1u<<13); + } + + /* End Workaround for OptimaEEE */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + + /* Enable 10Base-Te (EEE) */ + if (hw->chip_id >= CHIP_ID_YUKON_PRM) { + reg = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); + gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, + reg | PHY_M_10B_TE_ENABLE); + } + } + + /* Enable phy interrupt on auto-negotiation complete (or link up) */ + if (sky2->flags & SKY2_FLAG_AUTO_SPEED) + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); + else + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + } + + static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; + static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; + + static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port) + { + u32 reg1; + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); + reg1 &= ~phy_power[port]; + + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > CHIP_REV_YU_XL_A1) + reg1 |= coma_mode[port]; + + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + sky2_pci_read32(hw, PCI_DEV_REG1); + + if (hw->chip_id == CHIP_ID_YUKON_FE) + gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_ANE); + else if (hw->flags & SKY2_HW_ADV_POWER_CTL) + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + } + + static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) + { + u32 reg1; + u16 ctrl; + + /* release GPHY Control reset */ + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + + /* release GMAC reset */ + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + + if (hw->flags & SKY2_HW_NEWER_PHY) { + /* select page 2 to access MAC control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + /* allow GMII Power Down */ + ctrl &= ~PHY_M_MAC_GMIF_PUP; + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set page register back to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } + + /* setup General Purpose Control Register */ + gma_write16(hw, port, GM_GP_CTRL, + GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | + GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS | + GM_GPCR_AU_SPD_DIS); + + if (hw->chip_id != CHIP_ID_YUKON_EC) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + /* select page 2 to access MAC control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + /* enable Power Down */ + ctrl |= PHY_M_PC_POW_D_ENA; + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set page register back to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } + + /* set IEEE compatible Power Down Mode (dev. #4.99) */ + gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN); + } + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); + reg1 |= phy_power[port]; /* set PHY to PowerDown/COMA Mode */ + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + } + + /* configure IPG according to used link speed */ + static void sky2_set_ipg(struct sky2_port *sky2) + { + u16 reg; + + reg = gma_read16(sky2->hw, sky2->port, GM_SERIAL_MODE); + reg &= ~GM_SMOD_IPG_MSK; + if (sky2->speed > SPEED_100) + reg |= IPG_DATA_VAL(IPG_DATA_DEF_1000); + else + reg |= IPG_DATA_VAL(IPG_DATA_DEF_10_100); + gma_write16(sky2->hw, sky2->port, GM_SERIAL_MODE, reg); + } + + /* Enable Rx/Tx */ + static void sky2_enable_rx_tx(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u16 reg; + + reg = gma_read16(hw, port, GM_GP_CTRL); + reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; + gma_write16(hw, port, GM_GP_CTRL, reg); + } + + /* Force a renegotiation */ + static void sky2_phy_reinit(struct sky2_port *sky2) + { + spin_lock_bh(&sky2->phy_lock); + sky2_phy_init(sky2->hw, sky2->port); + sky2_enable_rx_tx(sky2); + spin_unlock_bh(&sky2->phy_lock); + } + + /* Put device in state to listen for Wake On Lan */ + static void sky2_wol_init(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + enum flow_control save_mode; + u16 ctrl; + + /* Bring hardware out of reset */ + sky2_write16(hw, B0_CTST, CS_RST_CLR); + sky2_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); + + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + + /* Force to 10/100 + * sky2_reset will re-enable on resume + */ + save_mode = sky2->flow_mode; + ctrl = sky2->advertising; + + sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); + sky2->flow_mode = FC_NONE; + + spin_lock_bh(&sky2->phy_lock); + sky2_phy_power_up(hw, port); + sky2_phy_init(hw, port); + spin_unlock_bh(&sky2->phy_lock); + + sky2->flow_mode = save_mode; + sky2->advertising = ctrl; + + /* Set GMAC to no flow control and auto update for speed/duplex */ + gma_write16(hw, port, GM_GP_CTRL, + GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| + GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); + + /* Set WOL address */ + memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), + sky2->netdev->dev_addr, ETH_ALEN); + + /* Turn on appropriate WOL control bits */ + sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); + ctrl = 0; + if (sky2->wol & WAKE_PHY) + ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; + else + ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; + + if (sky2->wol & WAKE_MAGIC) + ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; + else + ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT; + + ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; + sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); + + /* Disable PiG firmware */ + sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF); + + /* block receiver */ + sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + } + + static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) + { + struct net_device *dev = hw->dev[port]; + + if ( (hw->chip_id == CHIP_ID_YUKON_EX && + hw->chip_rev != CHIP_REV_YU_EX_A0) || + hw->chip_id >= CHIP_ID_YUKON_FE_P) { + /* Yukon-Extreme B0 and further Extreme devices */ + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); + } else if (dev->mtu > ETH_DATA_LEN) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); + + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); + } + + static void sky2_mac_init(struct sky2_hw *hw, unsigned port) + { + struct sky2_port *sky2 = netdev_priv(hw->dev[port]); + u16 reg; + u32 rx_reg; + int i; + const u8 *addr = hw->dev[port]->dev_addr; + + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + + if (hw->chip_id == CHIP_ID_YUKON_XL && + hw->chip_rev == CHIP_REV_YU_XL_A0 && + port == 1) { + /* WA DEV_472 -- looks like crossed wires on port 2 */ + /* clear GMAC 1 Control reset */ + sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR); + do { + sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET); + sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR); + } while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL || + gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 || + gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0); + } + + sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); + + /* Enable Transmit FIFO Underrun */ + sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); + + spin_lock_bh(&sky2->phy_lock); + sky2_phy_power_up(hw, port); + sky2_phy_init(hw, port); + spin_unlock_bh(&sky2->phy_lock); + + /* MIB clear */ + reg = gma_read16(hw, port, GM_PHY_ADDR); + gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); + + for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4) + gma_read16(hw, port, i); + gma_write16(hw, port, GM_PHY_ADDR, reg); + + /* transmit control */ + gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); + + /* receive control reg: unicast + multicast + no FCS */ + gma_write16(hw, port, GM_RX_CTRL, + GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); + + /* transmit flow control */ + gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); + + /* transmit parameter */ + gma_write16(hw, port, GM_TX_PARAM, + TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | + TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | + TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) | + TX_BACK_OFF_LIM(TX_BOF_LIM_DEF)); + + /* serial mode register */ + reg = DATA_BLIND_VAL(DATA_BLIND_DEF) | + GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF_1000); + + if (hw->dev[port]->mtu > ETH_DATA_LEN) + reg |= GM_SMOD_JUMBO_ENA; + + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + hw->chip_rev == CHIP_REV_YU_EC_U_B1) + reg |= GM_NEW_FLOW_CTRL; + + gma_write16(hw, port, GM_SERIAL_MODE, reg); + + /* virtual address for data */ + gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); + + /* physical address: used for pause frames */ + gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); + + /* ignore counter overflows */ + gma_write16(hw, port, GM_TX_IRQ_MSK, 0); + gma_write16(hw, port, GM_RX_IRQ_MSK, 0); + gma_write16(hw, port, GM_TR_IRQ_MSK, 0); + + /* Configure Rx MAC FIFO */ + sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); + rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_FE_P) + rx_reg |= GMF_RX_OVER_ON; + + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); + + if (hw->chip_id == CHIP_ID_YUKON_XL) { + /* Hardware errata - clear flush mask */ + sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), 0); + } else { + /* Flush Rx MAC FIFO on any flow control or error */ + sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); + } + + /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ + reg = RX_GMF_FL_THR_DEF + 1; + /* Another magic mystery workaround from sk98lin */ + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) + reg = 0x178; + sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg); + + /* Configure Tx MAC FIFO */ + sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); + sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); + + /* On chips without ram buffer, pause is controlled by MAC level */ + if (!(hw->flags & SKY2_HW_RAM_BUFFER)) { + /* Pause threshold is scaled by 8 in bytes */ + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) + reg = 1568 / 8; + else + reg = 1024 / 8; + sky2_write16(hw, SK_REG(port, RX_GMF_UP_THR), reg); + sky2_write16(hw, SK_REG(port, RX_GMF_LP_THR), 768 / 8); + + sky2_set_tx_stfwd(hw, port); + } + + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + /* disable dynamic watermark */ + reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA)); + reg &= ~TX_DYN_WM_ENA; + sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg); + } + } + + /* Assign Ram Buffer allocation to queue */ + static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space) + { + u32 end; + + /* convert from K bytes to qwords used for hw register */ + start *= 1024/8; + space *= 1024/8; + end = start + space - 1; + + sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); + sky2_write32(hw, RB_ADDR(q, RB_START), start); + sky2_write32(hw, RB_ADDR(q, RB_END), end); + sky2_write32(hw, RB_ADDR(q, RB_WP), start); + sky2_write32(hw, RB_ADDR(q, RB_RP), start); + + if (q == Q_R1 || q == Q_R2) { + u32 tp = space - space/4; + + /* On receive queue's set the thresholds + * give receiver priority when > 3/4 full + * send pause when down to 2K + */ + sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp); + sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2); + + tp = space - 2048/8; + sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); + sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); + } else { + /* Enable store & forward on Tx queue's because + * Tx FIFO is only 1K on Yukon + */ + sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); + } + + sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); + sky2_read8(hw, RB_ADDR(q, RB_CTRL)); + } + + /* Setup Bus Memory Interface */ + static void sky2_qset(struct sky2_hw *hw, u16 q) + { + sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET); + sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT); + sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON); + sky2_write32(hw, Q_ADDR(q, Q_WM), BMU_WM_DEFAULT); + } + + /* Setup prefetch unit registers. This is the interface between + * hardware and driver list elements + */ + static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr, + dma_addr_t addr, u32 last) + { + sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); + sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR); + sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), upper_32_bits(addr)); + sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), lower_32_bits(addr)); + sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last); + sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON); + + sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL)); + } + + static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot) + { + struct sky2_tx_le *le = sky2->tx_le + *slot; + + *slot = RING_NEXT(*slot, sky2->tx_ring_size); + le->ctrl = 0; + return le; + } + + static void tx_init(struct sky2_port *sky2) + { + struct sky2_tx_le *le; + + sky2->tx_prod = sky2->tx_cons = 0; + sky2->tx_tcpsum = 0; + sky2->tx_last_mss = 0; + + le = get_tx_le(sky2, &sky2->tx_prod); + le->addr = 0; + le->opcode = OP_ADDR64 | HW_OWNER; + sky2->tx_last_upper = 0; + } + + /* Update chip's next pointer */ + static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) + { + /* Make sure write' to descriptors are complete before we tell hardware */ + wmb(); + sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); + + /* Synchronize I/O on since next processor may write to tail */ + mmiowb(); + } + + + static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) + { + struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; + sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE); + le->ctrl = 0; + return le; + } + + static unsigned sky2_get_rx_threshold(struct sky2_port *sky2) + { + unsigned size; + + /* Space needed for frame data + headers rounded up */ + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); + + /* Stopping point for hardware truncation */ + return (size - 8) / sizeof(u32); + } + + static unsigned sky2_get_rx_data_size(struct sky2_port *sky2) + { + struct rx_ring_info *re; + unsigned size; + + /* Space needed for frame data + headers rounded up */ + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); + + sky2->rx_nfrags = size >> PAGE_SHIFT; + BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr)); + + /* Compute residue after pages */ + size -= sky2->rx_nfrags << PAGE_SHIFT; + + /* Optimize to handle small packets and headers */ + if (size < copybreak) + size = copybreak; + if (size < ETH_HLEN) + size = ETH_HLEN; + + return size; + } + + /* Build description to hardware for one receive segment */ + static void sky2_rx_add(struct sky2_port *sky2, u8 op, + dma_addr_t map, unsigned len) + { + struct sky2_rx_le *le; + + if (sizeof(dma_addr_t) > sizeof(u32)) { + le = sky2_next_rx(sky2); + le->addr = cpu_to_le32(upper_32_bits(map)); + le->opcode = OP_ADDR64 | HW_OWNER; + } + + le = sky2_next_rx(sky2); + le->addr = cpu_to_le32(lower_32_bits(map)); + le->length = cpu_to_le16(len); + le->opcode = op | HW_OWNER; + } + + /* Build description to hardware for one possibly fragmented skb */ + static void sky2_rx_submit(struct sky2_port *sky2, + const struct rx_ring_info *re) + { + int i; + + sky2_rx_add(sky2, OP_PACKET, re->data_addr, sky2->rx_data_size); + + for (i = 0; i < skb_shinfo(re->skb)->nr_frags; i++) + sky2_rx_add(sky2, OP_BUFFER, re->frag_addr[i], PAGE_SIZE); + } + + + static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re, + unsigned size) + { + struct sk_buff *skb = re->skb; + int i; + + re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, re->data_addr)) + goto mapping_error; + + dma_unmap_len_set(re, data_size, size); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + re->frag_addr[i] = skb_frag_dma_map(&pdev->dev, frag, 0, + skb_frag_size(frag), + DMA_FROM_DEVICE); + + if (dma_mapping_error(&pdev->dev, re->frag_addr[i])) + goto map_page_error; + } + return 0; + + map_page_error: + while (--i >= 0) { + pci_unmap_page(pdev, re->frag_addr[i], + skb_frag_size(&skb_shinfo(skb)->frags[i]), + PCI_DMA_FROMDEVICE); + } + + pci_unmap_single(pdev, re->data_addr, dma_unmap_len(re, data_size), + PCI_DMA_FROMDEVICE); + + mapping_error: + if (net_ratelimit()) + dev_warn(&pdev->dev, "%s: rx mapping error\n", + skb->dev->name); + return -EIO; + } + + static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) + { + struct sk_buff *skb = re->skb; + int i; + + pci_unmap_single(pdev, re->data_addr, dma_unmap_len(re, data_size), + PCI_DMA_FROMDEVICE); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + pci_unmap_page(pdev, re->frag_addr[i], + skb_frag_size(&skb_shinfo(skb)->frags[i]), + PCI_DMA_FROMDEVICE); + } + + /* Tell chip where to start receive checksum. + * Actually has two checksums, but set both same to avoid possible byte + * order problems. + */ + static void rx_set_checksum(struct sky2_port *sky2) + { + struct sky2_rx_le *le = sky2_next_rx(sky2); + + le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); + le->ctrl = 0; + le->opcode = OP_TCPSTART | HW_OWNER; + + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + (sky2->netdev->features & NETIF_F_RXCSUM) + ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } + + /* Enable/disable receive hash calculation (RSS) */ + static void rx_set_rss(struct net_device *dev, u32 features) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + int i, nkeys = 4; + + /* Supports IPv6 and other modes */ + if (hw->flags & SKY2_HW_NEW_LE) { + nkeys = 10; + sky2_write32(hw, SK_REG(sky2->port, RSS_CFG), HASH_ALL); + } + + /* Program RSS initial values */ + if (features & NETIF_F_RXHASH) { + u32 key[nkeys]; + + get_random_bytes(key, nkeys * sizeof(u32)); + for (i = 0; i < nkeys; i++) + sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4), + key[i]); + + /* Need to turn on (undocumented) flag to make hashing work */ + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), + RX_STFW_ENA); + + sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + BMU_ENA_RX_RSS_HASH); + } else + sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + BMU_DIS_RX_RSS_HASH); + } + + /* + * The RX Stop command will not work for Yukon-2 if the BMU does not + * reach the end of packet and since we can't make sure that we have + * incoming data, we must reset the BMU while it is not doing a DMA + * transfer. Since it is possible that the RX path is still active, + * the RX RAM buffer will be stopped first, so any possible incoming + * data will not trigger a DMA. After the RAM buffer is stopped, the + * BMU is polled until any DMA in progress is ended and only then it + * will be reset. + */ + static void sky2_rx_stop(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned rxq = rxqaddr[sky2->port]; + int i; + + /* disable the RAM Buffer receive queue */ + sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD); + + for (i = 0; i < 0xffff; i++) + if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL)) + == sky2_read8(hw, RB_ADDR(rxq, Q_RL))) + goto stopped; + + netdev_warn(sky2->netdev, "receiver stop failed\n"); + stopped: + sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST); + + /* reset the Rx prefetch unit */ + sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); + mmiowb(); + } + + /* Clean out receive buffer area, assumes receiver hardware stopped */ + static void sky2_rx_clean(struct sky2_port *sky2) + { + unsigned i; + + memset(sky2->rx_le, 0, RX_LE_BYTES); + for (i = 0; i < sky2->rx_pending; i++) { + struct rx_ring_info *re = sky2->rx_ring + i; + + if (re->skb) { + sky2_rx_unmap_skb(sky2->hw->pdev, re); + kfree_skb(re->skb); + re->skb = NULL; + } + } + } + + /* Basic MII support */ + static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct mii_ioctl_data *data = if_mii(ifr); + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + int err = -EOPNOTSUPP; + + if (!netif_running(dev)) + return -ENODEV; /* Phy still in reset */ + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = PHY_ADDR_MARV; + + /* fallthru */ + case SIOCGMIIREG: { + u16 val = 0; + + spin_lock_bh(&sky2->phy_lock); + err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); + spin_unlock_bh(&sky2->phy_lock); + + data->val_out = val; + break; + } + + case SIOCSMIIREG: + spin_lock_bh(&sky2->phy_lock); + err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, + data->val_in); + spin_unlock_bh(&sky2->phy_lock); + break; + } + return err; + } + + #define SKY2_VLAN_OFFLOADS (NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO) + + static void sky2_vlan_mode(struct net_device *dev, u32 features) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + u16 port = sky2->port; + + if (features & NETIF_F_HW_VLAN_RX) + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), + RX_VLAN_STRIP_ON); + else + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), + RX_VLAN_STRIP_OFF); + + if (features & NETIF_F_HW_VLAN_TX) { + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_VLAN_TAG_ON); + + dev->vlan_features |= SKY2_VLAN_OFFLOADS; + } else { + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_VLAN_TAG_OFF); + + /* Can't do transmit offload of vlan without hw vlan */ + dev->vlan_features &= ~SKY2_VLAN_OFFLOADS; + } + } + + /* Amount of required worst case padding in rx buffer */ + static inline unsigned sky2_rx_pad(const struct sky2_hw *hw) + { + return (hw->flags & SKY2_HW_RAM_BUFFER) ? 8 : 2; + } + + /* + * Allocate an skb for receiving. If the MTU is large enough + * make the skb non-linear with a fragment list of pages. + */ + static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2, gfp_t gfp) + { + struct sk_buff *skb; + int i; + + skb = __netdev_alloc_skb(sky2->netdev, + sky2->rx_data_size + sky2_rx_pad(sky2->hw), + gfp); + if (!skb) + goto nomem; + + if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) { + unsigned char *start; + /* + * Workaround for a bug in FIFO that cause hang + * if the FIFO if the receive buffer is not 64 byte aligned. + * The buffer returned from netdev_alloc_skb is + * aligned except if slab debugging is enabled. + */ + start = PTR_ALIGN(skb->data, 8); + skb_reserve(skb, start - skb->data); + } else + skb_reserve(skb, NET_IP_ALIGN); + + for (i = 0; i < sky2->rx_nfrags; i++) { + struct page *page = alloc_page(gfp); + + if (!page) + goto free_partial; + skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE); + } + + return skb; + free_partial: + kfree_skb(skb); + nomem: + return NULL; + } + + static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) + { + sky2_put_idx(sky2->hw, rxq, sky2->rx_put); + } + + static int sky2_alloc_rx_skbs(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned i; + + sky2->rx_data_size = sky2_get_rx_data_size(sky2); + + /* Fill Rx ring */ + for (i = 0; i < sky2->rx_pending; i++) { + struct rx_ring_info *re = sky2->rx_ring + i; + + re->skb = sky2_rx_alloc(sky2, GFP_KERNEL); + if (!re->skb) + return -ENOMEM; + + if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) { + dev_kfree_skb(re->skb); + re->skb = NULL; + return -ENOMEM; + } + } + return 0; + } + + /* + * Setup receiver buffer pool. + * Normal case this ends up creating one list element for skb + * in the receive ring. Worst case if using large MTU and each + * allocation falls on a different 64 bit region, that results + * in 6 list elements per ring entry. + * One element is used for checksum enable/disable, and one + * extra to avoid wrap. + */ + static void sky2_rx_start(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + struct rx_ring_info *re; + unsigned rxq = rxqaddr[sky2->port]; + unsigned i, thresh; + + sky2->rx_put = sky2->rx_next = 0; + sky2_qset(hw, rxq); + + /* On PCI express lowering the watermark gives better performance */ + if (pci_is_pcie(hw->pdev)) + sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX); + + /* These chips have no ram buffer? + * MAC Rx RAM Read is controlled by hardware */ + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + hw->chip_rev > CHIP_REV_YU_EC_U_A0) + sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS); + + sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); + + if (!(hw->flags & SKY2_HW_NEW_LE)) + rx_set_checksum(sky2); + + if (!(hw->flags & SKY2_HW_RSS_BROKEN)) + rx_set_rss(sky2->netdev, sky2->netdev->features); + + /* submit Rx ring */ + for (i = 0; i < sky2->rx_pending; i++) { + re = sky2->rx_ring + i; + sky2_rx_submit(sky2, re); + } + + /* + * The receiver hangs if it receives frames larger than the + * packet buffer. As a workaround, truncate oversize frames, but + * the register is limited to 9 bits, so if you do frames > 2052 + * you better get the MTU right! + */ + thresh = sky2_get_rx_threshold(sky2); + if (thresh > 0x1ff) + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); + else { + sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh); + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); + } + + /* Tell chip about available buffers */ + sky2_rx_update(sky2, rxq); + + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_SUPR) { + /* + * Disable flushing of non ASF packets; + * must be done after initializing the BMUs; + * drivers without ASF support should do this too, otherwise + * it may happen that they cannot run on ASF devices; + * remember that the MAC FIFO isn't reset during initialization. + */ + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_MACSEC_FLUSH_OFF); + } + + if (hw->chip_id >= CHIP_ID_YUKON_SUPR) { + /* Enable RX Home Address & Routing Header checksum fix */ + sky2_write16(hw, SK_REG(sky2->port, RX_GMF_FL_CTRL), + RX_IPV6_SA_MOB_ENA | RX_IPV6_DA_MOB_ENA); + + /* Enable TX Home Address & Routing Header checksum fix */ + sky2_write32(hw, Q_ADDR(txqaddr[sky2->port], Q_TEST), + TBMU_TEST_HOME_ADD_FIX_EN | TBMU_TEST_ROUTING_ADD_FIX_EN); + } + } + + static int sky2_alloc_buffers(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + + /* must be power of 2 */ + sky2->tx_le = pci_alloc_consistent(hw->pdev, + sky2->tx_ring_size * + sizeof(struct sky2_tx_le), + &sky2->tx_le_map); + if (!sky2->tx_le) + goto nomem; + + sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info), + GFP_KERNEL); + if (!sky2->tx_ring) + goto nomem; + + sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, + &sky2->rx_le_map); + if (!sky2->rx_le) + goto nomem; + memset(sky2->rx_le, 0, RX_LE_BYTES); + + sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info), + GFP_KERNEL); + if (!sky2->rx_ring) + goto nomem; + + return sky2_alloc_rx_skbs(sky2); + nomem: + return -ENOMEM; + } + + static void sky2_free_buffers(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + + sky2_rx_clean(sky2); + + if (sky2->rx_le) { + pci_free_consistent(hw->pdev, RX_LE_BYTES, + sky2->rx_le, sky2->rx_le_map); + sky2->rx_le = NULL; + } + if (sky2->tx_le) { + pci_free_consistent(hw->pdev, + sky2->tx_ring_size * sizeof(struct sky2_tx_le), + sky2->tx_le, sky2->tx_le_map); + sky2->tx_le = NULL; + } + kfree(sky2->tx_ring); + kfree(sky2->rx_ring); + + sky2->tx_ring = NULL; + sky2->rx_ring = NULL; + } + + static void sky2_hw_up(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u32 ramsize; + int cap; + struct net_device *otherdev = hw->dev[sky2->port^1]; + + tx_init(sky2); + + /* + * On dual port PCI-X card, there is an problem where status + * can be received out of order due to split transactions + */ + if (otherdev && netif_running(otherdev) && + (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { + u16 cmd; + + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); + cmd &= ~PCI_X_CMD_MAX_SPLIT; + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); + } + + sky2_mac_init(hw, port); + + /* Register is number of 4K blocks on internal RAM buffer. */ + ramsize = sky2_read8(hw, B2_E_0) * 4; + if (ramsize > 0) { + u32 rxspace; + + netdev_dbg(sky2->netdev, "ram buffer %dK\n", ramsize); + if (ramsize < 16) + rxspace = ramsize / 2; + else + rxspace = 8 + (2*(ramsize - 16))/3; + + sky2_ramset(hw, rxqaddr[port], 0, rxspace); + sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace); + + /* Make sure SyncQ is disabled */ + sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), + RB_RST_SET); + } + + sky2_qset(hw, txqaddr[port]); + + /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */ + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0) + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF); + + /* Set almost empty threshold */ + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + hw->chip_rev == CHIP_REV_YU_EC_U_A0) + sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV); + + sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, + sky2->tx_ring_size - 1); + + sky2_vlan_mode(sky2->netdev, sky2->netdev->features); + netdev_update_features(sky2->netdev); + + sky2_rx_start(sky2); + } + + /* Setup device IRQ and enable napi to process */ + static int sky2_setup_irq(struct sky2_hw *hw, const char *name) + { + struct pci_dev *pdev = hw->pdev; + int err; + + err = request_irq(pdev->irq, sky2_intr, + (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, + name, hw); + if (err) + dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); + else { + napi_enable(&hw->napi); + sky2_write32(hw, B0_IMSK, Y2_IS_BASE); + sky2_read32(hw, B0_IMSK); + } + + return err; + } + + + /* Bring up network interface. */ + static int sky2_up(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u32 imask; + int err; + + netif_carrier_off(dev); + + err = sky2_alloc_buffers(sky2); + if (err) + goto err_out; + + /* With single port, IRQ is setup when device is brought up */ + if (hw->ports == 1 && (err = sky2_setup_irq(hw, dev->name))) + goto err_out; + + sky2_hw_up(sky2); + + /* Enable interrupts from phy/mac for port */ + imask = sky2_read32(hw, B0_IMSK); + imask |= portirq_msk[port]; + sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_IMSK); + + netif_info(sky2, ifup, dev, "enabling interface\n"); + + return 0; + + err_out: + sky2_free_buffers(sky2); + return err; + } + + /* Modular subtraction in ring */ + static inline int tx_inuse(const struct sky2_port *sky2) + { + return (sky2->tx_prod - sky2->tx_cons) & (sky2->tx_ring_size - 1); + } + + /* Number of list elements available for next tx */ + static inline int tx_avail(const struct sky2_port *sky2) + { + return sky2->tx_pending - tx_inuse(sky2); + } + + /* Estimate of number of transmit list elements required */ + static unsigned tx_le_req(const struct sk_buff *skb) + { + unsigned count; + + count = (skb_shinfo(skb)->nr_frags + 1) + * (sizeof(dma_addr_t) / sizeof(u32)); + + if (skb_is_gso(skb)) + ++count; + else if (sizeof(dma_addr_t) == sizeof(u32)) + ++count; /* possible vlan */ + + if (skb->ip_summed == CHECKSUM_PARTIAL) + ++count; + + return count; + } + + static void sky2_tx_unmap(struct pci_dev *pdev, struct tx_ring_info *re) + { + if (re->flags & TX_MAP_SINGLE) + pci_unmap_single(pdev, dma_unmap_addr(re, mapaddr), + dma_unmap_len(re, maplen), + PCI_DMA_TODEVICE); + else if (re->flags & TX_MAP_PAGE) + pci_unmap_page(pdev, dma_unmap_addr(re, mapaddr), + dma_unmap_len(re, maplen), + PCI_DMA_TODEVICE); + re->flags = 0; + } + + /* + * Put one packet in ring for transmit. + * A single packet can generate multiple list elements, and + * the number of ring elements will probably be less than the number + * of list elements used. + */ + static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb, + struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + struct sky2_tx_le *le = NULL; + struct tx_ring_info *re; + unsigned i, len; + dma_addr_t mapping; + u32 upper; + u16 slot; + u16 mss; + u8 ctrl; + + if (unlikely(tx_avail(sky2) < tx_le_req(skb))) + return NETDEV_TX_BUSY; + + len = skb_headlen(skb); + mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(hw->pdev, mapping)) + goto mapping_error; + + slot = sky2->tx_prod; + netif_printk(sky2, tx_queued, KERN_DEBUG, dev, + "tx queued, slot %u, len %d\n", slot, skb->len); + + /* Send high bits if needed */ + upper = upper_32_bits(mapping); + if (upper != sky2->tx_last_upper) { + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(upper); + sky2->tx_last_upper = upper; + le->opcode = OP_ADDR64 | HW_OWNER; + } + + /* Check for TCP Segmentation Offload */ + mss = skb_shinfo(skb)->gso_size; + if (mss != 0) { + + if (!(hw->flags & SKY2_HW_NEW_LE)) + mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); + + if (mss != sky2->tx_last_mss) { + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(mss); + + if (hw->flags & SKY2_HW_NEW_LE) + le->opcode = OP_MSS | HW_OWNER; + else + le->opcode = OP_LRGLEN | HW_OWNER; + sky2->tx_last_mss = mss; + } + } + + ctrl = 0; + + /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */ + if (vlan_tx_tag_present(skb)) { + if (!le) { + le = get_tx_le(sky2, &slot); + le->addr = 0; + le->opcode = OP_VLAN|HW_OWNER; + } else + le->opcode |= OP_VLAN; + le->length = cpu_to_be16(vlan_tx_tag_get(skb)); + ctrl |= INS_VLAN; + } + + /* Handle TCP checksum offload */ + if (skb->ip_summed == CHECKSUM_PARTIAL) { + /* On Yukon EX (some versions) encoding change. */ + if (hw->flags & SKY2_HW_AUTO_TX_SUM) + ctrl |= CALSUM; /* auto checksum */ + else { + const unsigned offset = skb_transport_offset(skb); + u32 tcpsum; + + tcpsum = offset << 16; /* sum start */ + tcpsum |= offset + skb->csum_offset; /* sum write */ + + ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; + if (ip_hdr(skb)->protocol == IPPROTO_UDP) + ctrl |= UDPTCP; + + if (tcpsum != sky2->tx_tcpsum) { + sky2->tx_tcpsum = tcpsum; + + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(tcpsum); + le->length = 0; /* initial checksum value */ + le->ctrl = 1; /* one packet */ + le->opcode = OP_TCPLISW | HW_OWNER; + } + } + } + + re = sky2->tx_ring + slot; + re->flags = TX_MAP_SINGLE; + dma_unmap_addr_set(re, mapaddr, mapping); + dma_unmap_len_set(re, maplen, len); + + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(lower_32_bits(mapping)); + le->length = cpu_to_le16(len); + le->ctrl = ctrl; + le->opcode = mss ? (OP_LARGESEND | HW_OWNER) : (OP_PACKET | HW_OWNER); + + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + mapping = skb_frag_dma_map(&hw->pdev->dev, frag, 0, + skb_frag_size(frag), DMA_TO_DEVICE); + + if (dma_mapping_error(&hw->pdev->dev, mapping)) + goto mapping_unwind; + + upper = upper_32_bits(mapping); + if (upper != sky2->tx_last_upper) { + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(upper); + sky2->tx_last_upper = upper; + le->opcode = OP_ADDR64 | HW_OWNER; + } + + re = sky2->tx_ring + slot; + re->flags = TX_MAP_PAGE; + dma_unmap_addr_set(re, mapaddr, mapping); + dma_unmap_len_set(re, maplen, skb_frag_size(frag)); + + le = get_tx_le(sky2, &slot); + le->addr = cpu_to_le32(lower_32_bits(mapping)); + le->length = cpu_to_le16(skb_frag_size(frag)); + le->ctrl = ctrl; + le->opcode = OP_BUFFER | HW_OWNER; + } + + re->skb = skb; + le->ctrl |= EOP; + + sky2->tx_prod = slot; + + if (tx_avail(sky2) <= MAX_SKB_TX_LE) + netif_stop_queue(dev); + + sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); + + return NETDEV_TX_OK; + + mapping_unwind: + for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, sky2->tx_ring_size)) { + re = sky2->tx_ring + i; + + sky2_tx_unmap(hw->pdev, re); + } + + mapping_error: + if (net_ratelimit()) + dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + /* + * Free ring elements from starting at tx_cons until "done" + * + * NB: + * 1. The hardware will tell us about partial completion of multi-part + * buffers so make sure not to free skb to early. + * 2. This may run in parallel start_xmit because the it only + * looks at the tail of the queue of FIFO (tx_cons), not + * the head (tx_prod) + */ + static void sky2_tx_complete(struct sky2_port *sky2, u16 done) + { + struct net_device *dev = sky2->netdev; + unsigned idx; + + BUG_ON(done >= sky2->tx_ring_size); + + for (idx = sky2->tx_cons; idx != done; + idx = RING_NEXT(idx, sky2->tx_ring_size)) { + struct tx_ring_info *re = sky2->tx_ring + idx; + struct sk_buff *skb = re->skb; + + sky2_tx_unmap(sky2->hw->pdev, re); + + if (skb) { + netif_printk(sky2, tx_done, KERN_DEBUG, dev, + "tx done %u\n", idx); + + u64_stats_update_begin(&sky2->tx_stats.syncp); + ++sky2->tx_stats.packets; + sky2->tx_stats.bytes += skb->len; + u64_stats_update_end(&sky2->tx_stats.syncp); + + re->skb = NULL; + dev_kfree_skb_any(skb); + + sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size); + } + } + + sky2->tx_cons = idx; + smp_mb(); + } + + static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) + { + /* Disable Force Sync bit and Enable Alloc bit */ + sky2_write8(hw, SK_REG(port, TXA_CTRL), + TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); + + /* Stop Interval Timer and Limit Counter of Tx Arbiter */ + sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); + sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); + + /* Reset the PCI FIFO of the async Tx queue */ + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), + BMU_RST_SET | BMU_FIFO_RST); + + /* Reset the Tx prefetch units */ + sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL), + PREF_UNIT_RST_SET); + + sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); + sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); + } + + static void sky2_hw_down(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u16 ctrl; + + /* Force flow control off */ + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + + /* Stop transmitter */ + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP); + sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR)); + + sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), + RB_RST_SET | RB_DIS_OP_MD); + + ctrl = gma_read16(hw, port, GM_GP_CTRL); + ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); + gma_write16(hw, port, GM_GP_CTRL, ctrl); + + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + + /* Workaround shared GMAC reset */ + if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 && + port == 0 && hw->dev[1] && netif_running(hw->dev[1]))) + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); + + sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + - /* Force any delayed status interrrupt and NAPI */ ++ /* Force any delayed status interrupt and NAPI */ + sky2_write32(hw, STAT_LEV_TIMER_CNT, 0); + sky2_write32(hw, STAT_TX_TIMER_CNT, 0); + sky2_write32(hw, STAT_ISR_TIMER_CNT, 0); + sky2_read8(hw, STAT_ISR_TIMER_CTRL); + + sky2_rx_stop(sky2); + + spin_lock_bh(&sky2->phy_lock); + sky2_phy_power_down(hw, port); + spin_unlock_bh(&sky2->phy_lock); + + sky2_tx_reset(hw, port); + + /* Free any pending frames stuck in HW queue */ + sky2_tx_complete(sky2, sky2->tx_prod); + } + + /* Network shutdown */ + static int sky2_down(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + + /* Never really got started! */ + if (!sky2->tx_le) + return 0; + + netif_info(sky2, ifdown, dev, "disabling interface\n"); + + /* Disable port IRQ */ + sky2_write32(hw, B0_IMSK, + sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]); + sky2_read32(hw, B0_IMSK); + + if (hw->ports == 1) { + napi_disable(&hw->napi); + free_irq(hw->pdev->irq, hw); + } else { + synchronize_irq(hw->pdev->irq); + napi_synchronize(&hw->napi); + } + + sky2_hw_down(sky2); + + sky2_free_buffers(sky2); + + return 0; + } + + static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) + { + if (hw->flags & SKY2_HW_FIBRE_PHY) + return SPEED_1000; + + if (!(hw->flags & SKY2_HW_GIGABIT)) { + if (aux & PHY_M_PS_SPEED_100) + return SPEED_100; + else + return SPEED_10; + } + + switch (aux & PHY_M_PS_SPEED_MSK) { + case PHY_M_PS_SPEED_1000: + return SPEED_1000; + case PHY_M_PS_SPEED_100: + return SPEED_100; + default: + return SPEED_10; + } + } + + static void sky2_link_up(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + static const char *fc_name[] = { + [FC_NONE] = "none", + [FC_TX] = "tx", + [FC_RX] = "rx", + [FC_BOTH] = "both", + }; + + sky2_set_ipg(sky2); + + sky2_enable_rx_tx(sky2); + + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + + netif_carrier_on(sky2->netdev); + + mod_timer(&hw->watchdog_timer, jiffies + 1); + + /* Turn on link LED */ + sky2_write8(hw, SK_REG(port, LNK_LED_REG), + LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); + + netif_info(sky2, link, sky2->netdev, + "Link is up at %d Mbps, %s duplex, flow control %s\n", + sky2->speed, + sky2->duplex == DUPLEX_FULL ? "full" : "half", + fc_name[sky2->flow_status]); + } + + static void sky2_link_down(struct sky2_port *sky2) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u16 reg; + + gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); + + reg = gma_read16(hw, port, GM_GP_CTRL); + reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + gma_write16(hw, port, GM_GP_CTRL, reg); + + netif_carrier_off(sky2->netdev); + + /* Turn off link LED */ + sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + + netif_info(sky2, link, sky2->netdev, "Link is down\n"); + + sky2_phy_init(hw, port); + } + + static enum flow_control sky2_flow(int rx, int tx) + { + if (rx) + return tx ? FC_BOTH : FC_RX; + else + return tx ? FC_TX : FC_NONE; + } + + static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u16 advert, lpa; + + advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); + lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP); + if (lpa & PHY_M_AN_RF) { + netdev_err(sky2->netdev, "remote fault\n"); + return -1; + } + + if (!(aux & PHY_M_PS_SPDUP_RES)) { + netdev_err(sky2->netdev, "speed/duplex mismatch\n"); + return -1; + } + + sky2->speed = sky2_phy_speed(hw, aux); + sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; + + /* Since the pause result bits seem to in different positions on + * different chips. look at registers. + */ + if (hw->flags & SKY2_HW_FIBRE_PHY) { + /* Shift for bits in fiber PHY */ + advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); + lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); + + if (advert & ADVERTISE_1000XPAUSE) + advert |= ADVERTISE_PAUSE_CAP; + if (advert & ADVERTISE_1000XPSE_ASYM) + advert |= ADVERTISE_PAUSE_ASYM; + if (lpa & LPA_1000XPAUSE) + lpa |= LPA_PAUSE_CAP; + if (lpa & LPA_1000XPAUSE_ASYM) + lpa |= LPA_PAUSE_ASYM; + } + + sky2->flow_status = FC_NONE; + if (advert & ADVERTISE_PAUSE_CAP) { + if (lpa & LPA_PAUSE_CAP) + sky2->flow_status = FC_BOTH; + else if (advert & ADVERTISE_PAUSE_ASYM) + sky2->flow_status = FC_RX; + } else if (advert & ADVERTISE_PAUSE_ASYM) { + if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM)) + sky2->flow_status = FC_TX; + } + + if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 && + !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)) + sky2->flow_status = FC_NONE; + + if (sky2->flow_status & FC_TX) + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); + else + sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + + return 0; + } + + /* Interrupt from PHY */ + static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) + { + struct net_device *dev = hw->dev[port]; + struct sky2_port *sky2 = netdev_priv(dev); + u16 istatus, phystat; + + if (!netif_running(dev)) + return; + + spin_lock(&sky2->phy_lock); + istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); + phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); + + netif_info(sky2, intr, sky2->netdev, "phy interrupt status 0x%x 0x%x\n", + istatus, phystat); + + if (istatus & PHY_M_IS_AN_COMPL) { + if (sky2_autoneg_done(sky2, phystat) == 0 && + !netif_carrier_ok(dev)) + sky2_link_up(sky2); + goto out; + } + + if (istatus & PHY_M_IS_LSP_CHANGE) + sky2->speed = sky2_phy_speed(hw, phystat); + + if (istatus & PHY_M_IS_DUP_CHANGE) + sky2->duplex = + (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; + + if (istatus & PHY_M_IS_LST_CHANGE) { + if (phystat & PHY_M_PS_LINK_UP) + sky2_link_up(sky2); + else + sky2_link_down(sky2); + } + out: + spin_unlock(&sky2->phy_lock); + } + + /* Special quick link interrupt (Yukon-2 Optima only) */ + static void sky2_qlink_intr(struct sky2_hw *hw) + { + struct sky2_port *sky2 = netdev_priv(hw->dev[0]); + u32 imask; + u16 phy; + + /* disable irq */ + imask = sky2_read32(hw, B0_IMSK); + imask &= ~Y2_IS_PHY_QLNK; + sky2_write32(hw, B0_IMSK, imask); + + /* reset PHY Link Detect */ + phy = sky2_pci_read16(hw, PSM_CONFIG_REG4); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + sky2_link_up(sky2); + } + + /* Transmit timeout is only called if we are running, carrier is up + * and tx queue is full (stopped). + */ + static void sky2_tx_timeout(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + + netif_err(sky2, timer, dev, "tx timeout\n"); + + netdev_printk(KERN_DEBUG, dev, "transmit ring %u .. %u report=%u done=%u\n", + sky2->tx_cons, sky2->tx_prod, + sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), + sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); + + /* can't restart safely under softirq */ + schedule_work(&hw->restart_work); + } + + static int sky2_change_mtu(struct net_device *dev, int new_mtu) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + int err; + u16 ctl, mode; + u32 imask; + + /* MTU size outside the spec */ + if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) + return -EINVAL; + + /* MTU > 1500 on yukon FE and FE+ not allowed */ + if (new_mtu > ETH_DATA_LEN && + (hw->chip_id == CHIP_ID_YUKON_FE || + hw->chip_id == CHIP_ID_YUKON_FE_P)) + return -EINVAL; + + if (!netif_running(dev)) { + dev->mtu = new_mtu; + netdev_update_features(dev); + return 0; + } + + imask = sky2_read32(hw, B0_IMSK); + sky2_write32(hw, B0_IMSK, 0); + + dev->trans_start = jiffies; /* prevent tx timeout */ + napi_disable(&hw->napi); + netif_tx_disable(dev); + + synchronize_irq(hw->pdev->irq); + + if (!(hw->flags & SKY2_HW_RAM_BUFFER)) + sky2_set_tx_stfwd(hw, port); + + ctl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); + sky2_rx_stop(sky2); + sky2_rx_clean(sky2); + + dev->mtu = new_mtu; + netdev_update_features(dev); + + mode = DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA; + if (sky2->speed > SPEED_100) + mode |= IPG_DATA_VAL(IPG_DATA_DEF_1000); + else + mode |= IPG_DATA_VAL(IPG_DATA_DEF_10_100); + + if (dev->mtu > ETH_DATA_LEN) + mode |= GM_SMOD_JUMBO_ENA; + + gma_write16(hw, port, GM_SERIAL_MODE, mode); + + sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); + + err = sky2_alloc_rx_skbs(sky2); + if (!err) + sky2_rx_start(sky2); + else + sky2_rx_clean(sky2); + sky2_write32(hw, B0_IMSK, imask); + + sky2_read32(hw, B0_Y2_SP_LISR); + napi_enable(&hw->napi); + + if (err) + dev_close(dev); + else { + gma_write16(hw, port, GM_GP_CTRL, ctl); + + netif_wake_queue(dev); + } + + return err; + } + + /* For small just reuse existing skb for next receive */ + static struct sk_buff *receive_copy(struct sky2_port *sky2, + const struct rx_ring_info *re, + unsigned length) + { + struct sk_buff *skb; + + skb = netdev_alloc_skb_ip_align(sky2->netdev, length); + if (likely(skb)) { + pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr, + length, PCI_DMA_FROMDEVICE); + skb_copy_from_linear_data(re->skb, skb->data, length); + skb->ip_summed = re->skb->ip_summed; + skb->csum = re->skb->csum; + pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr, + length, PCI_DMA_FROMDEVICE); + re->skb->ip_summed = CHECKSUM_NONE; + skb_put(skb, length); + } + return skb; + } + + /* Adjust length of skb with fragments to match received data */ + static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space, + unsigned int length) + { + int i, num_frags; + unsigned int size; + + /* put header into skb */ + size = min(length, hdr_space); + skb->tail += size; + skb->len += size; + length -= size; + + num_frags = skb_shinfo(skb)->nr_frags; + for (i = 0; i < num_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (length == 0) { + /* don't need this page */ + __skb_frag_unref(frag); + --skb_shinfo(skb)->nr_frags; + } else { + size = min(length, (unsigned) PAGE_SIZE); + + skb_frag_size_set(frag, size); + skb->data_len += size; + skb->truesize += PAGE_SIZE; + skb->len += size; + length -= size; + } + } + } + + /* Normal packet - take skb from ring element and put in a new one */ + static struct sk_buff *receive_new(struct sky2_port *sky2, + struct rx_ring_info *re, + unsigned int length) + { + struct sk_buff *skb; + struct rx_ring_info nre; + unsigned hdr_space = sky2->rx_data_size; + + nre.skb = sky2_rx_alloc(sky2, GFP_ATOMIC); + if (unlikely(!nre.skb)) + goto nobuf; + + if (sky2_rx_map_skb(sky2->hw->pdev, &nre, hdr_space)) + goto nomap; + + skb = re->skb; + sky2_rx_unmap_skb(sky2->hw->pdev, re); + prefetch(skb->data); + *re = nre; + + if (skb_shinfo(skb)->nr_frags) + skb_put_frags(skb, hdr_space, length); + else + skb_put(skb, length); + return skb; + + nomap: + dev_kfree_skb(nre.skb); + nobuf: + return NULL; + } + + /* + * Receive one packet. + * For larger packets, get new buffer. + */ + static struct sk_buff *sky2_receive(struct net_device *dev, + u16 length, u32 status) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; + struct sk_buff *skb = NULL; + u16 count = (status & GMR_FS_LEN) >> 16; + + if (status & GMR_FS_VLAN) + count -= VLAN_HLEN; /* Account for vlan tag */ + + netif_printk(sky2, rx_status, KERN_DEBUG, dev, + "rx slot %u status 0x%x len %d\n", + sky2->rx_next, status, length); + + sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; + prefetch(sky2->rx_ring + sky2->rx_next); + + /* This chip has hardware problems that generates bogus status. + * So do only marginal checking and expect higher level protocols + * to handle crap frames. + */ + if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && + sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && + length != count) + goto okay; + + if (status & GMR_FS_ANY_ERR) + goto error; + + if (!(status & GMR_FS_RX_OK)) + goto resubmit; + + /* if length reported by DMA does not match PHY, packet was truncated */ + if (length != count) + goto error; + + okay: + if (length < copybreak) + skb = receive_copy(sky2, re, length); + else + skb = receive_new(sky2, re, length); + + dev->stats.rx_dropped += (skb == NULL); + + resubmit: + sky2_rx_submit(sky2, re); + + return skb; + + error: + ++dev->stats.rx_errors; + + if (net_ratelimit()) + netif_info(sky2, rx_err, dev, + "rx error, status 0x%x length %d\n", status, length); + + goto resubmit; + } + + /* Transmit complete */ + static inline void sky2_tx_done(struct net_device *dev, u16 last) + { + struct sky2_port *sky2 = netdev_priv(dev); + + if (netif_running(dev)) { + sky2_tx_complete(sky2, last); + + /* Wake unless it's detached, and called e.g. from sky2_down() */ + if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) + netif_wake_queue(dev); + } + } + + static inline void sky2_skb_rx(const struct sky2_port *sky2, + u32 status, struct sk_buff *skb) + { + if (status & GMR_FS_VLAN) + __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag)); + + if (skb->ip_summed == CHECKSUM_NONE) + netif_receive_skb(skb); + else + napi_gro_receive(&sky2->hw->napi, skb); + } + + static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, + unsigned packets, unsigned bytes) + { + struct net_device *dev = hw->dev[port]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (packets == 0) + return; + + u64_stats_update_begin(&sky2->rx_stats.syncp); + sky2->rx_stats.packets += packets; + sky2->rx_stats.bytes += bytes; + u64_stats_update_end(&sky2->rx_stats.syncp); + + dev->last_rx = jiffies; + sky2_rx_update(netdev_priv(dev), rxqaddr[port]); + } + + static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) + { + /* If this happens then driver assuming wrong format for chip type */ + BUG_ON(sky2->hw->flags & SKY2_HW_NEW_LE); + + /* Both checksum counters are programmed to start at + * the same offset, so unless there is a problem they + * should match. This failure is an early indication that + * hardware receive checksumming won't work. + */ + if (likely((u16)(status >> 16) == (u16)status)) { + struct sk_buff *skb = sky2->rx_ring[sky2->rx_next].skb; + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = le16_to_cpu(status); + } else { + dev_notice(&sky2->hw->pdev->dev, + "%s: receive checksum problem (status = %#x)\n", + sky2->netdev->name, status); + + /* Disable checksum offload + * It will be reenabled on next ndo_set_features, but if it's + * really broken, will get disabled again + */ + sky2->netdev->features &= ~NETIF_F_RXCSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + BMU_DIS_RX_CHKSUM); + } + } + + static void sky2_rx_hash(struct sky2_port *sky2, u32 status) + { + struct sk_buff *skb; + + skb = sky2->rx_ring[sky2->rx_next].skb; + skb->rxhash = le32_to_cpu(status); + } + + /* Process status response ring */ + static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) + { + int work_done = 0; + unsigned int total_bytes[2] = { 0 }; + unsigned int total_packets[2] = { 0 }; + + rmb(); + do { + struct sky2_port *sky2; + struct sky2_status_le *le = hw->st_le + hw->st_idx; + unsigned port; + struct net_device *dev; + struct sk_buff *skb; + u32 status; + u16 length; + u8 opcode = le->opcode; + + if (!(opcode & HW_OWNER)) + break; + + hw->st_idx = RING_NEXT(hw->st_idx, hw->st_size); + + port = le->css & CSS_LINK_BIT; + dev = hw->dev[port]; + sky2 = netdev_priv(dev); + length = le16_to_cpu(le->length); + status = le32_to_cpu(le->status); + + le->opcode = 0; + switch (opcode & ~HW_OWNER) { + case OP_RXSTAT: + total_packets[port]++; + total_bytes[port] += length; + + skb = sky2_receive(dev, length, status); + if (!skb) + break; + + /* This chip reports checksum status differently */ + if (hw->flags & SKY2_HW_NEW_LE) { + if ((dev->features & NETIF_F_RXCSUM) && + (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && + (le->css & CSS_TCPUDPCSOK)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } + + skb->protocol = eth_type_trans(skb, dev); + + sky2_skb_rx(sky2, status, skb); + + /* Stop after net poll weight */ + if (++work_done >= to_do) + goto exit_loop; + break; + + case OP_RXVLAN: + sky2->rx_tag = length; + break; + + case OP_RXCHKSVLAN: + sky2->rx_tag = length; + /* fall through */ + case OP_RXCHKS: + if (likely(dev->features & NETIF_F_RXCSUM)) + sky2_rx_checksum(sky2, status); + break; + + case OP_RSS_HASH: + sky2_rx_hash(sky2, status); + break; + + case OP_TXINDEXLE: + /* TX index reports status for both ports */ + sky2_tx_done(hw->dev[0], status & 0xfff); + if (hw->dev[1]) + sky2_tx_done(hw->dev[1], + ((status >> 24) & 0xff) + | (u16)(length & 0xf) << 8); + break; + + default: + if (net_ratelimit()) + pr_warning("unknown status opcode 0x%x\n", opcode); + } + } while (hw->st_idx != idx); + + /* Fully processed status ring so clear irq */ + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + + exit_loop: + sky2_rx_done(hw, 0, total_packets[0], total_bytes[0]); + sky2_rx_done(hw, 1, total_packets[1], total_bytes[1]); + + return work_done; + } + + static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) + { + struct net_device *dev = hw->dev[port]; + + if (net_ratelimit()) + netdev_info(dev, "hw error interrupt status 0x%x\n", status); + + if (status & Y2_IS_PAR_RD1) { + if (net_ratelimit()) + netdev_err(dev, "ram data read parity error\n"); + /* Clear IRQ */ + sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR); + } + + if (status & Y2_IS_PAR_WR1) { + if (net_ratelimit()) + netdev_err(dev, "ram data write parity error\n"); + + sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR); + } + + if (status & Y2_IS_PAR_MAC1) { + if (net_ratelimit()) + netdev_err(dev, "MAC parity error\n"); + sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE); + } + + if (status & Y2_IS_PAR_RX1) { + if (net_ratelimit()) + netdev_err(dev, "RX parity error\n"); + sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR); + } + + if (status & Y2_IS_TCP_TXA1) { + if (net_ratelimit()) + netdev_err(dev, "TCP segmentation error\n"); + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP); + } + } + + static void sky2_hw_intr(struct sky2_hw *hw) + { + struct pci_dev *pdev = hw->pdev; + u32 status = sky2_read32(hw, B0_HWE_ISRC); + u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK); + + status &= hwmsk; + + if (status & Y2_IS_TIST_OV) + sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); + + if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { + u16 pci_err; + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + pci_err = sky2_pci_read16(hw, PCI_STATUS); + if (net_ratelimit()) + dev_err(&pdev->dev, "PCI hardware error (0x%x)\n", + pci_err); + + sky2_pci_write16(hw, PCI_STATUS, + pci_err | PCI_STATUS_ERROR_BITS); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + } + + if (status & Y2_IS_PCI_EXP) { + /* PCI-Express uncorrectable Error occurred */ + u32 err; + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); + if (net_ratelimit()) + dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); + + sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + } + + if (status & Y2_HWE_L1_MASK) + sky2_hw_error(hw, 0, status); + status >>= 8; + if (status & Y2_HWE_L1_MASK) + sky2_hw_error(hw, 1, status); + } + + static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) + { + struct net_device *dev = hw->dev[port]; + struct sky2_port *sky2 = netdev_priv(dev); + u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); + + netif_info(sky2, intr, dev, "mac interrupt status 0x%x\n", status); + + if (status & GM_IS_RX_CO_OV) + gma_read16(hw, port, GM_RX_IRQ_SRC); + + if (status & GM_IS_TX_CO_OV) + gma_read16(hw, port, GM_TX_IRQ_SRC); + + if (status & GM_IS_RX_FF_OR) { + ++dev->stats.rx_fifo_errors; + sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); + } + + if (status & GM_IS_TX_FF_UR) { + ++dev->stats.tx_fifo_errors; + sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); + } + } + + /* This should never happen it is a bug. */ + static void sky2_le_error(struct sky2_hw *hw, unsigned port, u16 q) + { + struct net_device *dev = hw->dev[port]; + u16 idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); + + dev_err(&hw->pdev->dev, "%s: descriptor error q=%#x get=%u put=%u\n", + dev->name, (unsigned) q, (unsigned) idx, + (unsigned) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX))); + + sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); + } + + static int sky2_rx_hung(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned rxq = rxqaddr[port]; + u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP)); + u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV)); + u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP)); + u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL)); + + /* If idle and MAC or PCI is stuck */ + if (sky2->check.last == dev->last_rx && + ((mac_rp == sky2->check.mac_rp && + mac_lev != 0 && mac_lev >= sky2->check.mac_lev) || + /* Check if the PCI RX hang */ + (fifo_rp == sky2->check.fifo_rp && + fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { + netdev_printk(KERN_DEBUG, dev, + "hung mac %d:%d fifo %d (%d:%d)\n", + mac_lev, mac_rp, fifo_lev, + fifo_rp, sky2_read8(hw, Q_ADDR(rxq, Q_WP))); + return 1; + } else { + sky2->check.last = dev->last_rx; + sky2->check.mac_rp = mac_rp; + sky2->check.mac_lev = mac_lev; + sky2->check.fifo_rp = fifo_rp; + sky2->check.fifo_lev = fifo_lev; + return 0; + } + } + + static void sky2_watchdog(unsigned long arg) + { + struct sky2_hw *hw = (struct sky2_hw *) arg; + + /* Check for lost IRQ once a second */ + if (sky2_read32(hw, B0_ISRC)) { + napi_schedule(&hw->napi); + } else { + int i, active = 0; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + if (!netif_running(dev)) + continue; + ++active; + + /* For chips with Rx FIFO, check if stuck */ + if ((hw->flags & SKY2_HW_RAM_BUFFER) && + sky2_rx_hung(dev)) { + netdev_info(dev, "receiver hang detected\n"); + schedule_work(&hw->restart_work); + return; + } + } + + if (active == 0) + return; + } + + mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); + } + + /* Hardware/software error handling */ + static void sky2_err_intr(struct sky2_hw *hw, u32 status) + { + if (net_ratelimit()) + dev_warn(&hw->pdev->dev, "error interrupt status=%#x\n", status); + + if (status & Y2_IS_HW_ERR) + sky2_hw_intr(hw); + + if (status & Y2_IS_IRQ_MAC1) + sky2_mac_intr(hw, 0); + + if (status & Y2_IS_IRQ_MAC2) + sky2_mac_intr(hw, 1); + + if (status & Y2_IS_CHK_RX1) + sky2_le_error(hw, 0, Q_R1); + + if (status & Y2_IS_CHK_RX2) + sky2_le_error(hw, 1, Q_R2); + + if (status & Y2_IS_CHK_TXA1) + sky2_le_error(hw, 0, Q_XA1); + + if (status & Y2_IS_CHK_TXA2) + sky2_le_error(hw, 1, Q_XA2); + } + + static int sky2_poll(struct napi_struct *napi, int work_limit) + { + struct sky2_hw *hw = container_of(napi, struct sky2_hw, napi); + u32 status = sky2_read32(hw, B0_Y2_SP_EISR); + int work_done = 0; + u16 idx; + + if (unlikely(status & Y2_IS_ERROR)) + sky2_err_intr(hw, status); + + if (status & Y2_IS_IRQ_PHY1) + sky2_phy_intr(hw, 0); + + if (status & Y2_IS_IRQ_PHY2) + sky2_phy_intr(hw, 1); + + if (status & Y2_IS_PHY_QLNK) + sky2_qlink_intr(hw); + + while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) { + work_done += sky2_status_intr(hw, work_limit - work_done, idx); + + if (work_done >= work_limit) + goto done; + } + + napi_complete(napi); + sky2_read32(hw, B0_Y2_SP_LISR); + done: + + return work_done; + } + + static irqreturn_t sky2_intr(int irq, void *dev_id) + { + struct sky2_hw *hw = dev_id; + u32 status; + + /* Reading this mask interrupts as side effect */ + status = sky2_read32(hw, B0_Y2_SP_ISRC2); + if (status == 0 || status == ~0) + return IRQ_NONE; + + prefetch(&hw->st_le[hw->st_idx]); + + napi_schedule(&hw->napi); + + return IRQ_HANDLED; + } + + #ifdef CONFIG_NET_POLL_CONTROLLER + static void sky2_netpoll(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + + napi_schedule(&sky2->hw->napi); + } + #endif + + /* Chip internal frequency for clock calculations */ + static u32 sky2_mhz(const struct sky2_hw *hw) + { + switch (hw->chip_id) { + case CHIP_ID_YUKON_EC: + case CHIP_ID_YUKON_EC_U: + case CHIP_ID_YUKON_EX: + case CHIP_ID_YUKON_SUPR: + case CHIP_ID_YUKON_UL_2: + case CHIP_ID_YUKON_OPT: + case CHIP_ID_YUKON_PRM: + case CHIP_ID_YUKON_OP_2: + return 125; + + case CHIP_ID_YUKON_FE: + return 100; + + case CHIP_ID_YUKON_FE_P: + return 50; + + case CHIP_ID_YUKON_XL: + return 156; + + default: + BUG(); + } + } + + static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us) + { + return sky2_mhz(hw) * us; + } + + static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) + { + return clk / sky2_mhz(hw); + } + + + static int __devinit sky2_init(struct sky2_hw *hw) + { + u8 t8; + + /* Enable all clocks and check for bad PCI access */ + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + + sky2_write8(hw, B0_CTST, CS_RST_CLR); + + hw->chip_id = sky2_read8(hw, B2_CHIP_ID); + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + + switch (hw->chip_id) { + case CHIP_ID_YUKON_XL: + hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; + if (hw->chip_rev < CHIP_REV_YU_XL_A2) + hw->flags |= SKY2_HW_RSS_BROKEN; + break; + + case CHIP_ID_YUKON_EC_U: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_ADV_POWER_CTL; + break; + + case CHIP_ID_YUKON_EX: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_ADV_POWER_CTL + | SKY2_HW_RSS_CHKSUM; + + /* New transmit checksum */ + if (hw->chip_rev != CHIP_REV_YU_EX_B0) + hw->flags |= SKY2_HW_AUTO_TX_SUM; + break; + + case CHIP_ID_YUKON_EC: + /* This rev is really old, and requires untested workarounds */ + if (hw->chip_rev == CHIP_REV_YU_EC_A1) { + dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); + return -EOPNOTSUPP; + } + hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RSS_BROKEN; + break; + + case CHIP_ID_YUKON_FE: + hw->flags = SKY2_HW_RSS_BROKEN; + break; + + case CHIP_ID_YUKON_FE_P: + hw->flags = SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_AUTO_TX_SUM + | SKY2_HW_ADV_POWER_CTL; + + /* The workaround for status conflicts VLAN tag detection. */ + if (hw->chip_rev == CHIP_REV_YU_FE2_A0) + hw->flags |= SKY2_HW_VLAN_BROKEN | SKY2_HW_RSS_CHKSUM; + break; + + case CHIP_ID_YUKON_SUPR: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_AUTO_TX_SUM + | SKY2_HW_ADV_POWER_CTL; + + if (hw->chip_rev == CHIP_REV_YU_SU_A0) + hw->flags |= SKY2_HW_RSS_CHKSUM; + break; + + case CHIP_ID_YUKON_UL_2: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_ADV_POWER_CTL; + break; + + case CHIP_ID_YUKON_OPT: + case CHIP_ID_YUKON_PRM: + case CHIP_ID_YUKON_OP_2: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEW_LE + | SKY2_HW_ADV_POWER_CTL; + break; + + default: + dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", + hw->chip_id); + return -EOPNOTSUPP; + } + + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); + if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') + hw->flags |= SKY2_HW_FIBRE_PHY; + + hw->ports = 1; + t8 = sky2_read8(hw, B2_Y2_HW_RES); + if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { + if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) + ++hw->ports; + } + + if (sky2_read8(hw, B2_E_0)) + hw->flags |= SKY2_HW_RAM_BUFFER; + + return 0; + } + + static void sky2_reset(struct sky2_hw *hw) + { + struct pci_dev *pdev = hw->pdev; + u16 status; + int i; + u32 hwe_mask = Y2_HWE_ALL_MASK; + + /* disable ASF */ + if (hw->chip_id == CHIP_ID_YUKON_EX + || hw->chip_id == CHIP_ID_YUKON_SUPR) { + sky2_write32(hw, CPU_WDOG, 0); + status = sky2_read16(hw, HCU_CCSR); + status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | + HCU_CCSR_UC_STATE_MSK); + /* + * CPU clock divider shouldn't be used because + * - ASF firmware may malfunction + * - Yukon-Supreme: Parallel FLASH doesn't support divided clocks + */ + status &= ~HCU_CCSR_CPU_CLK_DIVIDE_MSK; + sky2_write16(hw, HCU_CCSR, status); + sky2_write32(hw, CPU_WDOG, 0); + } else + sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); + sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); + + /* do a SW reset */ + sky2_write8(hw, B0_CTST, CS_RST_SET); + sky2_write8(hw, B0_CTST, CS_RST_CLR); + + /* allow writes to PCI config */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + /* clear PCI errors, if any */ + status = sky2_pci_read16(hw, PCI_STATUS); + status |= PCI_STATUS_ERROR_BITS; + sky2_pci_write16(hw, PCI_STATUS, status); + + sky2_write8(hw, B0_CTST, CS_MRST_CLR); + + if (pci_is_pcie(pdev)) { + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); + + /* If error bit is stuck on ignore it */ + if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) + dev_info(&pdev->dev, "ignoring stuck error report bit\n"); + else + hwe_mask |= Y2_IS_PCI_EXP; + } + + sky2_power_on(hw); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + for (i = 0; i < hw->ports; i++) { + sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); + sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_SUPR) + sky2_write16(hw, SK_REG(i, GMAC_CTRL), + GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON + | GMC_BYP_RETR_ON); + + } + + if (hw->chip_id == CHIP_ID_YUKON_SUPR && hw->chip_rev > CHIP_REV_YU_SU_B0) { + /* enable MACSec clock gating */ + sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS); + } + + if (hw->chip_id == CHIP_ID_YUKON_OPT || + hw->chip_id == CHIP_ID_YUKON_PRM || + hw->chip_id == CHIP_ID_YUKON_OP_2) { + u16 reg; + u32 msk; + + if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) { + /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */ + sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7)); + + /* set PHY Link Detect Timer to 1.1 second (11x 100ms) */ + reg = 10; + + /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ + sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16)); + } else { + /* set PHY Link Detect Timer to 0.4 second (4x 100ms) */ + reg = 3; + } + + reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE; + reg |= PSM_CONFIG_REG4_RST_PHY_LINK_DETECT; + + /* reset PHY Link Detect */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + sky2_pci_write16(hw, PSM_CONFIG_REG4, reg); + + /* enable PHY Quick Link */ + msk = sky2_read32(hw, B0_IMSK); + msk |= Y2_IS_PHY_QLNK; + sky2_write32(hw, B0_IMSK, msk); + + /* check if PSMv2 was running before */ + reg = sky2_pci_read16(hw, PSM_CONFIG_REG3); + if (reg & PCI_EXP_LNKCTL_ASPMC) + /* restore the PCIe Link Control register */ + sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL, + reg); + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ + sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16)); + } + + /* Clear I2C IRQ noise */ + sky2_write32(hw, B2_I2C_IRQ, 1); + + /* turn off hardware timer (unused) */ + sky2_write8(hw, B2_TI_CTRL, TIM_STOP); + sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ); + + /* Turn off descriptor polling */ + sky2_write32(hw, B28_DPT_CTRL, DPT_STOP); + + /* Turn off receive timestamp */ + sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP); + sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); + + /* enable the Tx Arbiters */ + for (i = 0; i < hw->ports; i++) + sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); + + /* Initialize ram interface */ + for (i = 0; i < hw->ports; i++) { + sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR); + + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53); + sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53); + } + + sky2_write32(hw, B0_HWE_IMSK, hwe_mask); + + for (i = 0; i < hw->ports; i++) + sky2_gmac_reset(hw, i); + + memset(hw->st_le, 0, hw->st_size * sizeof(struct sky2_status_le)); + hw->st_idx = 0; + + sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET); + sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR); + + sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma); + sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32); + + /* Set the list last index */ + sky2_write16(hw, STAT_LAST_IDX, hw->st_size - 1); + + sky2_write16(hw, STAT_TX_IDX_TH, 10); + sky2_write8(hw, STAT_FIFO_WM, 16); + + /* set Status-FIFO ISR watermark */ + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) + sky2_write8(hw, STAT_FIFO_ISR_WM, 4); + else + sky2_write8(hw, STAT_FIFO_ISR_WM, 16); + + sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); + sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20)); + sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100)); + + /* enable status unit */ + sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); + + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); + sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); + sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); + } + + /* Take device down (offline). + * Equivalent to doing dev_stop() but this does not + * inform upper layers of the transition. + */ + static void sky2_detach(struct net_device *dev) + { + if (netif_running(dev)) { + netif_tx_lock(dev); + netif_device_detach(dev); /* stop txq */ + netif_tx_unlock(dev); + sky2_down(dev); + } + } + + /* Bring device back after doing sky2_detach */ + static int sky2_reattach(struct net_device *dev) + { + int err = 0; + + if (netif_running(dev)) { + err = sky2_up(dev); + if (err) { + netdev_info(dev, "could not restart %d\n", err); + dev_close(dev); + } else { + netif_device_attach(dev); + sky2_set_multicast(dev); + } + } + + return err; + } + + static void sky2_all_down(struct sky2_hw *hw) + { + int i; + + sky2_read32(hw, B0_IMSK); + sky2_write32(hw, B0_IMSK, 0); + synchronize_irq(hw->pdev->irq); + napi_disable(&hw->napi); + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (!netif_running(dev)) + continue; + + netif_carrier_off(dev); + netif_tx_disable(dev); + sky2_hw_down(sky2); + } + } + + static void sky2_all_up(struct sky2_hw *hw) + { + u32 imask = Y2_IS_BASE; + int i; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (!netif_running(dev)) + continue; + + sky2_hw_up(sky2); + sky2_set_multicast(dev); + imask |= portirq_msk[i]; + netif_wake_queue(dev); + } + + sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_IMSK); + + sky2_read32(hw, B0_Y2_SP_LISR); + napi_enable(&hw->napi); + } + + static void sky2_restart(struct work_struct *work) + { + struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); + + rtnl_lock(); + + sky2_all_down(hw); + sky2_reset(hw); + sky2_all_up(hw); + + rtnl_unlock(); + } + + static inline u8 sky2_wol_supported(const struct sky2_hw *hw) + { + return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; + } + + static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + { + const struct sky2_port *sky2 = netdev_priv(dev); + + wol->supported = sky2_wol_supported(sky2->hw); + wol->wolopts = sky2->wol; + } + + static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + bool enable_wakeup = false; + int i; + + if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) || + !device_can_wakeup(&hw->pdev->dev)) + return -EOPNOTSUPP; + + sky2->wol = wol->wolopts; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (sky2->wol) + enable_wakeup = true; + } + device_set_wakeup_enable(&hw->pdev->dev, enable_wakeup); + + return 0; + } + + static u32 sky2_supported_modes(const struct sky2_hw *hw) + { + if (sky2_is_copper(hw)) { + u32 modes = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full; + + if (hw->flags & SKY2_HW_GIGABIT) + modes |= SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full; + return modes; + } else + return SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full; + } + + static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + + ecmd->transceiver = XCVR_INTERNAL; + ecmd->supported = sky2_supported_modes(hw); + ecmd->phy_address = PHY_ADDR_MARV; + if (sky2_is_copper(hw)) { + ecmd->port = PORT_TP; + ethtool_cmd_speed_set(ecmd, sky2->speed); + ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_TP; + } else { + ethtool_cmd_speed_set(ecmd, SPEED_1000); + ecmd->port = PORT_FIBRE; + ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE; + } + + ecmd->advertising = sky2->advertising; + ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED) + ? AUTONEG_ENABLE : AUTONEG_DISABLE; + ecmd->duplex = sky2->duplex; + return 0; + } + + static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; + u32 supported = sky2_supported_modes(hw); + + if (ecmd->autoneg == AUTONEG_ENABLE) { + if (ecmd->advertising & ~supported) + return -EINVAL; + + if (sky2_is_copper(hw)) + sky2->advertising = ecmd->advertising | + ADVERTISED_TP | + ADVERTISED_Autoneg; + else + sky2->advertising = ecmd->advertising | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg; + + sky2->flags |= SKY2_FLAG_AUTO_SPEED; + sky2->duplex = -1; + sky2->speed = -1; + } else { + u32 setting; + u32 speed = ethtool_cmd_speed(ecmd); + + switch (speed) { + case SPEED_1000: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_1000baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_1000baseT_Half; + else + return -EINVAL; + break; + case SPEED_100: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_100baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_100baseT_Half; + else + return -EINVAL; + break; + + case SPEED_10: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_10baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_10baseT_Half; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + if ((setting & supported) == 0) + return -EINVAL; + + sky2->speed = speed; + sky2->duplex = ecmd->duplex; + sky2->flags &= ~SKY2_FLAG_AUTO_SPEED; + } + + if (netif_running(dev)) { + sky2_phy_reinit(sky2); + sky2_set_multicast(dev); + } + + return 0; + } + + static void sky2_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) + { + struct sky2_port *sky2 = netdev_priv(dev); + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, pci_name(sky2->hw->pdev)); + } + + static const struct sky2_stat { + char name[ETH_GSTRING_LEN]; + u16 offset; + } sky2_stats[] = { + { "tx_bytes", GM_TXO_OK_HI }, + { "rx_bytes", GM_RXO_OK_HI }, + { "tx_broadcast", GM_TXF_BC_OK }, + { "rx_broadcast", GM_RXF_BC_OK }, + { "tx_multicast", GM_TXF_MC_OK }, + { "rx_multicast", GM_RXF_MC_OK }, + { "tx_unicast", GM_TXF_UC_OK }, + { "rx_unicast", GM_RXF_UC_OK }, + { "tx_mac_pause", GM_TXF_MPAUSE }, + { "rx_mac_pause", GM_RXF_MPAUSE }, + { "collisions", GM_TXF_COL }, + { "late_collision",GM_TXF_LAT_COL }, + { "aborted", GM_TXF_ABO_COL }, + { "single_collisions", GM_TXF_SNG_COL }, + { "multi_collisions", GM_TXF_MUL_COL }, + + { "rx_short", GM_RXF_SHT }, + { "rx_runt", GM_RXE_FRAG }, + { "rx_64_byte_packets", GM_RXF_64B }, + { "rx_65_to_127_byte_packets", GM_RXF_127B }, + { "rx_128_to_255_byte_packets", GM_RXF_255B }, + { "rx_256_to_511_byte_packets", GM_RXF_511B }, + { "rx_512_to_1023_byte_packets", GM_RXF_1023B }, + { "rx_1024_to_1518_byte_packets", GM_RXF_1518B }, + { "rx_1518_to_max_byte_packets", GM_RXF_MAX_SZ }, + { "rx_too_long", GM_RXF_LNG_ERR }, + { "rx_fifo_overflow", GM_RXE_FIFO_OV }, + { "rx_jabber", GM_RXF_JAB_PKT }, + { "rx_fcs_error", GM_RXF_FCS_ERR }, + + { "tx_64_byte_packets", GM_TXF_64B }, + { "tx_65_to_127_byte_packets", GM_TXF_127B }, + { "tx_128_to_255_byte_packets", GM_TXF_255B }, + { "tx_256_to_511_byte_packets", GM_TXF_511B }, + { "tx_512_to_1023_byte_packets", GM_TXF_1023B }, + { "tx_1024_to_1518_byte_packets", GM_TXF_1518B }, + { "tx_1519_to_max_byte_packets", GM_TXF_MAX_SZ }, + { "tx_fifo_underrun", GM_TXE_FIFO_UR }, + }; + + static u32 sky2_get_msglevel(struct net_device *netdev) + { + struct sky2_port *sky2 = netdev_priv(netdev); + return sky2->msg_enable; + } + + static int sky2_nway_reset(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + + if (!netif_running(dev) || !(sky2->flags & SKY2_FLAG_AUTO_SPEED)) + return -EINVAL; + + sky2_phy_reinit(sky2); + sky2_set_multicast(dev); + + return 0; + } + + static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + int i; + + data[0] = get_stats64(hw, port, GM_TXO_OK_LO); + data[1] = get_stats64(hw, port, GM_RXO_OK_LO); + + for (i = 2; i < count; i++) + data[i] = get_stats32(hw, port, sky2_stats[i].offset); + } + + static void sky2_set_msglevel(struct net_device *netdev, u32 value) + { + struct sky2_port *sky2 = netdev_priv(netdev); + sky2->msg_enable = value; + } + + static int sky2_get_sset_count(struct net_device *dev, int sset) + { + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(sky2_stats); + default: + return -EOPNOTSUPP; + } + } + + static void sky2_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 * data) + { + struct sky2_port *sky2 = netdev_priv(dev); + + sky2_phy_stats(sky2, data, ARRAY_SIZE(sky2_stats)); + } + + static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data) + { + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(sky2_stats); i++) + memcpy(data + i * ETH_GSTRING_LEN, + sky2_stats[i].name, ETH_GSTRING_LEN); + break; + } + } + + static int sky2_set_mac_address(struct net_device *dev, void *p) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + const struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_1 + port * 8, + dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port * 8, + dev->dev_addr, ETH_ALEN); + + /* virtual address for data */ + gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + + /* physical address: used for pause frames */ + gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); + + return 0; + } + + static inline void sky2_add_filter(u8 filter[8], const u8 *addr) + { + u32 bit; + + bit = ether_crc(ETH_ALEN, addr) & 63; + filter[bit >> 3] |= 1 << (bit & 7); + } + + static void sky2_set_multicast(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + struct netdev_hw_addr *ha; + u16 reg; + u8 filter[8]; + int rx_pause; + static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; + + rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH); + memset(filter, 0, sizeof(filter)); + + reg = gma_read16(hw, port, GM_RX_CTRL); + reg |= GM_RXCR_UCF_ENA; + + if (dev->flags & IFF_PROMISC) /* promiscuous */ + reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + else if (dev->flags & IFF_ALLMULTI) + memset(filter, 0xff, sizeof(filter)); + else if (netdev_mc_empty(dev) && !rx_pause) + reg &= ~GM_RXCR_MCF_ENA; + else { + reg |= GM_RXCR_MCF_ENA; + + if (rx_pause) + sky2_add_filter(filter, pause_mc_addr); + + netdev_for_each_mc_addr(ha, dev) + sky2_add_filter(filter, ha->addr); + } + + gma_write16(hw, port, GM_MC_ADDR_H1, + (u16) filter[0] | ((u16) filter[1] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H2, + (u16) filter[2] | ((u16) filter[3] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H3, + (u16) filter[4] | ((u16) filter[5] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H4, + (u16) filter[6] | ((u16) filter[7] << 8)); + + gma_write16(hw, port, GM_RX_CTRL, reg); + } + + static struct rtnl_link_stats64 *sky2_get_stats(struct net_device *dev, + struct rtnl_link_stats64 *stats) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned int start; + u64 _bytes, _packets; + + do { + start = u64_stats_fetch_begin_bh(&sky2->rx_stats.syncp); + _bytes = sky2->rx_stats.bytes; + _packets = sky2->rx_stats.packets; + } while (u64_stats_fetch_retry_bh(&sky2->rx_stats.syncp, start)); + + stats->rx_packets = _packets; + stats->rx_bytes = _bytes; + + do { + start = u64_stats_fetch_begin_bh(&sky2->tx_stats.syncp); + _bytes = sky2->tx_stats.bytes; + _packets = sky2->tx_stats.packets; + } while (u64_stats_fetch_retry_bh(&sky2->tx_stats.syncp, start)); + + stats->tx_packets = _packets; + stats->tx_bytes = _bytes; + + stats->multicast = get_stats32(hw, port, GM_RXF_MC_OK) + + get_stats32(hw, port, GM_RXF_BC_OK); + + stats->collisions = get_stats32(hw, port, GM_TXF_COL); + + stats->rx_length_errors = get_stats32(hw, port, GM_RXF_LNG_ERR); + stats->rx_crc_errors = get_stats32(hw, port, GM_RXF_FCS_ERR); + stats->rx_frame_errors = get_stats32(hw, port, GM_RXF_SHT) + + get_stats32(hw, port, GM_RXE_FRAG); + stats->rx_over_errors = get_stats32(hw, port, GM_RXE_FIFO_OV); + + stats->rx_dropped = dev->stats.rx_dropped; + stats->rx_fifo_errors = dev->stats.rx_fifo_errors; + stats->tx_fifo_errors = dev->stats.tx_fifo_errors; + + return stats; + } + + /* Can have one global because blinking is controlled by + * ethtool and that is always under RTNL mutex + */ + static void sky2_led(struct sky2_port *sky2, enum led_mode mode) + { + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + + spin_lock_bh(&sky2->phy_lock); + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_SUPR) { + u16 pg; + pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); + + switch (mode) { + case MO_LED_OFF: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(8) | + PHY_M_LEDC_INIT_CTRL(8) | + PHY_M_LEDC_STA1_CTRL(8) | + PHY_M_LEDC_STA0_CTRL(8)); + break; + case MO_LED_ON: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(9) | + PHY_M_LEDC_INIT_CTRL(9) | + PHY_M_LEDC_STA1_CTRL(9) | + PHY_M_LEDC_STA0_CTRL(9)); + break; + case MO_LED_BLINK: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(0xa) | + PHY_M_LEDC_INIT_CTRL(0xa) | + PHY_M_LEDC_STA1_CTRL(0xa) | + PHY_M_LEDC_STA0_CTRL(0xa)); + break; + case MO_LED_NORM: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(1) | + PHY_M_LEDC_INIT_CTRL(8) | + PHY_M_LEDC_STA1_CTRL(7) | + PHY_M_LEDC_STA0_CTRL(7)); + } + + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + } else + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(mode) | + PHY_M_LED_MO_10(mode) | + PHY_M_LED_MO_100(mode) | + PHY_M_LED_MO_1000(mode) | + PHY_M_LED_MO_RX(mode) | + PHY_M_LED_MO_TX(mode)); + + spin_unlock_bh(&sky2->phy_lock); + } + + /* blink LED's for finding board */ + static int sky2_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) + { + struct sky2_port *sky2 = netdev_priv(dev); + + switch (state) { + case ETHTOOL_ID_ACTIVE: + return 1; /* cycle on/off once per second */ + case ETHTOOL_ID_INACTIVE: + sky2_led(sky2, MO_LED_NORM); + break; + case ETHTOOL_ID_ON: + sky2_led(sky2, MO_LED_ON); + break; + case ETHTOOL_ID_OFF: + sky2_led(sky2, MO_LED_OFF); + break; + } + + return 0; + } + + static void sky2_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + + switch (sky2->flow_mode) { + case FC_NONE: + ecmd->tx_pause = ecmd->rx_pause = 0; + break; + case FC_TX: + ecmd->tx_pause = 1, ecmd->rx_pause = 0; + break; + case FC_RX: + ecmd->tx_pause = 0, ecmd->rx_pause = 1; + break; + case FC_BOTH: + ecmd->tx_pause = ecmd->rx_pause = 1; + } + + ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_PAUSE) + ? AUTONEG_ENABLE : AUTONEG_DISABLE; + } + + static int sky2_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + + if (ecmd->autoneg == AUTONEG_ENABLE) + sky2->flags |= SKY2_FLAG_AUTO_PAUSE; + else + sky2->flags &= ~SKY2_FLAG_AUTO_PAUSE; + + sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause); + + if (netif_running(dev)) + sky2_phy_reinit(sky2); + + return 0; + } + + static int sky2_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + + if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_STOP) + ecmd->tx_coalesce_usecs = 0; + else { + u32 clks = sky2_read32(hw, STAT_TX_TIMER_INI); + ecmd->tx_coalesce_usecs = sky2_clk2us(hw, clks); + } + ecmd->tx_max_coalesced_frames = sky2_read16(hw, STAT_TX_IDX_TH); + + if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_STOP) + ecmd->rx_coalesce_usecs = 0; + else { + u32 clks = sky2_read32(hw, STAT_LEV_TIMER_INI); + ecmd->rx_coalesce_usecs = sky2_clk2us(hw, clks); + } + ecmd->rx_max_coalesced_frames = sky2_read8(hw, STAT_FIFO_WM); + + if (sky2_read8(hw, STAT_ISR_TIMER_CTRL) == TIM_STOP) + ecmd->rx_coalesce_usecs_irq = 0; + else { + u32 clks = sky2_read32(hw, STAT_ISR_TIMER_INI); + ecmd->rx_coalesce_usecs_irq = sky2_clk2us(hw, clks); + } + + ecmd->rx_max_coalesced_frames_irq = sky2_read8(hw, STAT_FIFO_ISR_WM); + + return 0; + } + + /* Note: this affect both ports */ + static int sky2_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ecmd) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + const u32 tmax = sky2_clk2us(hw, 0x0ffffff); + + if (ecmd->tx_coalesce_usecs > tmax || + ecmd->rx_coalesce_usecs > tmax || + ecmd->rx_coalesce_usecs_irq > tmax) + return -EINVAL; + + if (ecmd->tx_max_coalesced_frames >= sky2->tx_ring_size-1) + return -EINVAL; + if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING) + return -EINVAL; + if (ecmd->rx_max_coalesced_frames_irq > RX_MAX_PENDING) + return -EINVAL; + + if (ecmd->tx_coalesce_usecs == 0) + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + else { + sky2_write32(hw, STAT_TX_TIMER_INI, + sky2_us2clk(hw, ecmd->tx_coalesce_usecs)); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); + } + sky2_write16(hw, STAT_TX_IDX_TH, ecmd->tx_max_coalesced_frames); + + if (ecmd->rx_coalesce_usecs == 0) + sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); + else { + sky2_write32(hw, STAT_LEV_TIMER_INI, + sky2_us2clk(hw, ecmd->rx_coalesce_usecs)); + sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); + } + sky2_write8(hw, STAT_FIFO_WM, ecmd->rx_max_coalesced_frames); + + if (ecmd->rx_coalesce_usecs_irq == 0) + sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); + else { + sky2_write32(hw, STAT_ISR_TIMER_INI, + sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); + sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); + } + sky2_write8(hw, STAT_FIFO_ISR_WM, ecmd->rx_max_coalesced_frames_irq); + return 0; + } + + static void sky2_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) + { + struct sky2_port *sky2 = netdev_priv(dev); + + ering->rx_max_pending = RX_MAX_PENDING; + ering->tx_max_pending = TX_MAX_PENDING; + + ering->rx_pending = sky2->rx_pending; + ering->tx_pending = sky2->tx_pending; + } + + static int sky2_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) + { + struct sky2_port *sky2 = netdev_priv(dev); + + if (ering->rx_pending > RX_MAX_PENDING || + ering->rx_pending < 8 || + ering->tx_pending < TX_MIN_PENDING || + ering->tx_pending > TX_MAX_PENDING) + return -EINVAL; + + sky2_detach(dev); + + sky2->rx_pending = ering->rx_pending; + sky2->tx_pending = ering->tx_pending; + sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1); + + return sky2_reattach(dev); + } + + static int sky2_get_regs_len(struct net_device *dev) + { + return 0x4000; + } + + static int sky2_reg_access_ok(struct sky2_hw *hw, unsigned int b) + { + /* This complicated switch statement is to make sure and + * only access regions that are unreserved. + * Some blocks are only valid on dual port cards. + */ + switch (b) { + /* second port */ + case 5: /* Tx Arbiter 2 */ + case 9: /* RX2 */ + case 14 ... 15: /* TX2 */ + case 17: case 19: /* Ram Buffer 2 */ + case 22 ... 23: /* Tx Ram Buffer 2 */ + case 25: /* Rx MAC Fifo 1 */ + case 27: /* Tx MAC Fifo 2 */ + case 31: /* GPHY 2 */ + case 40 ... 47: /* Pattern Ram 2 */ + case 52: case 54: /* TCP Segmentation 2 */ + case 112 ... 116: /* GMAC 2 */ + return hw->ports > 1; + + case 0: /* Control */ + case 2: /* Mac address */ + case 4: /* Tx Arbiter 1 */ + case 7: /* PCI express reg */ + case 8: /* RX1 */ + case 12 ... 13: /* TX1 */ + case 16: case 18:/* Rx Ram Buffer 1 */ + case 20 ... 21: /* Tx Ram Buffer 1 */ + case 24: /* Rx MAC Fifo 1 */ + case 26: /* Tx MAC Fifo 1 */ + case 28 ... 29: /* Descriptor and status unit */ + case 30: /* GPHY 1*/ + case 32 ... 39: /* Pattern Ram 1 */ + case 48: case 50: /* TCP Segmentation 1 */ + case 56 ... 60: /* PCI space */ + case 80 ... 84: /* GMAC 1 */ + return 1; + + default: + return 0; + } + } + + /* + * Returns copy of control register region + * Note: ethtool_get_regs always provides full size (16k) buffer + */ + static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) + { + const struct sky2_port *sky2 = netdev_priv(dev); + const void __iomem *io = sky2->hw->regs; + unsigned int b; + + regs->version = 1; + + for (b = 0; b < 128; b++) { + /* skip poisonous diagnostic ram region in block 3 */ + if (b == 3) + memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10); + else if (sky2_reg_access_ok(sky2->hw, b)) + memcpy_fromio(p, io, 128); + else + memset(p, 0, 128); + + p += 128; + io += 128; + } + } + + static int sky2_get_eeprom_len(struct net_device *dev) + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + u16 reg2; + + reg2 = sky2_pci_read16(hw, PCI_DEV_REG2); + return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); + } + + static int sky2_vpd_wait(const struct sky2_hw *hw, int cap, u16 busy) + { + unsigned long start = jiffies; + + while ( (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F) == busy) { + /* Can take up to 10.6 ms for write */ + if (time_after(jiffies, start + HZ/4)) { + dev_err(&hw->pdev->dev, "VPD cycle timed out\n"); + return -ETIMEDOUT; + } + mdelay(1); + } + + return 0; + } + + static int sky2_vpd_read(struct sky2_hw *hw, int cap, void *data, + u16 offset, size_t length) + { + int rc = 0; + + while (length > 0) { + u32 val; + + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); + rc = sky2_vpd_wait(hw, cap, 0); + if (rc) + break; + + val = sky2_pci_read32(hw, cap + PCI_VPD_DATA); + + memcpy(data, &val, min(sizeof(val), length)); + offset += sizeof(u32); + data += sizeof(u32); + length -= sizeof(u32); + } + + return rc; + } + + static int sky2_vpd_write(struct sky2_hw *hw, int cap, const void *data, + u16 offset, unsigned int length) + { + unsigned int i; + int rc = 0; + + for (i = 0; i < length; i += sizeof(u32)) { + u32 val = *(u32 *)(data + i); + + sky2_pci_write32(hw, cap + PCI_VPD_DATA, val); + sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); + + rc = sky2_vpd_wait(hw, cap, PCI_VPD_ADDR_F); + if (rc) + break; + } + return rc; + } + + static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) + { + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + + if (!cap) + return -EINVAL; + + eeprom->magic = SKY2_EEPROM_MAGIC; + + return sky2_vpd_read(sky2->hw, cap, data, eeprom->offset, eeprom->len); + } + + static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) + { + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + + if (!cap) + return -EINVAL; + + if (eeprom->magic != SKY2_EEPROM_MAGIC) + return -EINVAL; + + /* Partial writes not supported */ + if ((eeprom->offset & 3) || (eeprom->len & 3)) + return -EINVAL; + + return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len); + } + + static u32 sky2_fix_features(struct net_device *dev, u32 features) + { + const struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; + + /* In order to do Jumbo packets on these chips, need to turn off the + * transmit store/forward. Therefore checksum offload won't work. + */ + if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) { + netdev_info(dev, "checksum offload not possible with jumbo frames\n"); + features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM); + } + + /* Some hardware requires receive checksum for RSS to work. */ + if ( (features & NETIF_F_RXHASH) && + !(features & NETIF_F_RXCSUM) && + (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) { + netdev_info(dev, "receive hashing forces receive checksum\n"); + features |= NETIF_F_RXCSUM; + } + + return features; + } + + static int sky2_set_features(struct net_device *dev, u32 features) + { + struct sky2_port *sky2 = netdev_priv(dev); + u32 changed = dev->features ^ features; + + if (changed & NETIF_F_RXCSUM) { + u32 on = features & NETIF_F_RXCSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } + + if (changed & NETIF_F_RXHASH) + rx_set_rss(dev, features); + + if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)) + sky2_vlan_mode(dev, features); + + return 0; + } + + static const struct ethtool_ops sky2_ethtool_ops = { + .get_settings = sky2_get_settings, + .set_settings = sky2_set_settings, + .get_drvinfo = sky2_get_drvinfo, + .get_wol = sky2_get_wol, + .set_wol = sky2_set_wol, + .get_msglevel = sky2_get_msglevel, + .set_msglevel = sky2_set_msglevel, + .nway_reset = sky2_nway_reset, + .get_regs_len = sky2_get_regs_len, + .get_regs = sky2_get_regs, + .get_link = ethtool_op_get_link, + .get_eeprom_len = sky2_get_eeprom_len, + .get_eeprom = sky2_get_eeprom, + .set_eeprom = sky2_set_eeprom, + .get_strings = sky2_get_strings, + .get_coalesce = sky2_get_coalesce, + .set_coalesce = sky2_set_coalesce, + .get_ringparam = sky2_get_ringparam, + .set_ringparam = sky2_set_ringparam, + .get_pauseparam = sky2_get_pauseparam, + .set_pauseparam = sky2_set_pauseparam, + .set_phys_id = sky2_set_phys_id, + .get_sset_count = sky2_get_sset_count, + .get_ethtool_stats = sky2_get_ethtool_stats, + }; + + #ifdef CONFIG_SKY2_DEBUG + + static struct dentry *sky2_debug; + + + /* + * Read and parse the first part of Vital Product Data + */ + #define VPD_SIZE 128 + #define VPD_MAGIC 0x82 + + static const struct vpd_tag { + char tag[2]; + char *label; + } vpd_tags[] = { + { "PN", "Part Number" }, + { "EC", "Engineering Level" }, + { "MN", "Manufacturer" }, + { "SN", "Serial Number" }, + { "YA", "Asset Tag" }, + { "VL", "First Error Log Message" }, + { "VF", "Second Error Log Message" }, + { "VB", "Boot Agent ROM Configuration" }, + { "VE", "EFI UNDI Configuration" }, + }; + + static void sky2_show_vpd(struct seq_file *seq, struct sky2_hw *hw) + { + size_t vpd_size; + loff_t offs; + u8 len; + unsigned char *buf; + u16 reg2; + + reg2 = sky2_pci_read16(hw, PCI_DEV_REG2); + vpd_size = 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); + + seq_printf(seq, "%s Product Data\n", pci_name(hw->pdev)); + buf = kmalloc(vpd_size, GFP_KERNEL); + if (!buf) { + seq_puts(seq, "no memory!\n"); + return; + } + + if (pci_read_vpd(hw->pdev, 0, vpd_size, buf) < 0) { + seq_puts(seq, "VPD read failed\n"); + goto out; + } + + if (buf[0] != VPD_MAGIC) { + seq_printf(seq, "VPD tag mismatch: %#x\n", buf[0]); + goto out; + } + len = buf[1]; + if (len == 0 || len > vpd_size - 4) { + seq_printf(seq, "Invalid id length: %d\n", len); + goto out; + } + + seq_printf(seq, "%.*s\n", len, buf + 3); + offs = len + 3; + + while (offs < vpd_size - 4) { + int i; + + if (!memcmp("RW", buf + offs, 2)) /* end marker */ + break; + len = buf[offs + 2]; + if (offs + len + 3 >= vpd_size) + break; + + for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) { + if (!memcmp(vpd_tags[i].tag, buf + offs, 2)) { + seq_printf(seq, " %s: %.*s\n", + vpd_tags[i].label, len, buf + offs + 3); + break; + } + } + offs += len + 3; + } + out: + kfree(buf); + } + + static int sky2_debug_show(struct seq_file *seq, void *v) + { + struct net_device *dev = seq->private; + const struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned idx, last; + int sop; + + sky2_show_vpd(seq, hw); + + seq_printf(seq, "\nIRQ src=%x mask=%x control=%x\n", + sky2_read32(hw, B0_ISRC), + sky2_read32(hw, B0_IMSK), + sky2_read32(hw, B0_Y2_SP_ICR)); + + if (!netif_running(dev)) { + seq_printf(seq, "network not running\n"); + return 0; + } + + napi_disable(&hw->napi); + last = sky2_read16(hw, STAT_PUT_IDX); + + seq_printf(seq, "Status ring %u\n", hw->st_size); + if (hw->st_idx == last) + seq_puts(seq, "Status ring (empty)\n"); + else { + seq_puts(seq, "Status ring\n"); + for (idx = hw->st_idx; idx != last && idx < hw->st_size; + idx = RING_NEXT(idx, hw->st_size)) { + const struct sky2_status_le *le = hw->st_le + idx; + seq_printf(seq, "[%d] %#x %d %#x\n", + idx, le->opcode, le->length, le->status); + } + seq_puts(seq, "\n"); + } + + seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n", + sky2->tx_cons, sky2->tx_prod, + sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), + sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE))); + + /* Dump contents of tx ring */ + sop = 1; + for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < sky2->tx_ring_size; + idx = RING_NEXT(idx, sky2->tx_ring_size)) { + const struct sky2_tx_le *le = sky2->tx_le + idx; + u32 a = le32_to_cpu(le->addr); + + if (sop) + seq_printf(seq, "%u:", idx); + sop = 0; + + switch (le->opcode & ~HW_OWNER) { + case OP_ADDR64: + seq_printf(seq, " %#x:", a); + break; + case OP_LRGLEN: + seq_printf(seq, " mtu=%d", a); + break; + case OP_VLAN: + seq_printf(seq, " vlan=%d", be16_to_cpu(le->length)); + break; + case OP_TCPLISW: + seq_printf(seq, " csum=%#x", a); + break; + case OP_LARGESEND: + seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_PACKET: + seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_BUFFER: + seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length)); + break; + default: + seq_printf(seq, " op=%#x,%#x(%d)", le->opcode, + a, le16_to_cpu(le->length)); + } + + if (le->ctrl & EOP) { + seq_putc(seq, '\n'); + sop = 1; + } + } + + seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n", + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)), + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); + + sky2_read32(hw, B0_Y2_SP_LISR); + napi_enable(&hw->napi); + return 0; + } + + static int sky2_debug_open(struct inode *inode, struct file *file) + { + return single_open(file, sky2_debug_show, inode->i_private); + } + + static const struct file_operations sky2_debug_fops = { + .owner = THIS_MODULE, + .open = sky2_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + }; + + /* + * Use network device events to create/remove/rename + * debugfs file entries + */ + static int sky2_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) + { + struct net_device *dev = ptr; + struct sky2_port *sky2 = netdev_priv(dev); + + if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGENAME: + if (sky2->debugfs) { + sky2->debugfs = debugfs_rename(sky2_debug, sky2->debugfs, + sky2_debug, dev->name); + } + break; + + case NETDEV_GOING_DOWN: + if (sky2->debugfs) { + netdev_printk(KERN_DEBUG, dev, "remove debugfs\n"); + debugfs_remove(sky2->debugfs); + sky2->debugfs = NULL; + } + break; + + case NETDEV_UP: + sky2->debugfs = debugfs_create_file(dev->name, S_IRUGO, + sky2_debug, dev, + &sky2_debug_fops); + if (IS_ERR(sky2->debugfs)) + sky2->debugfs = NULL; + } + + return NOTIFY_DONE; + } + + static struct notifier_block sky2_notifier = { + .notifier_call = sky2_device_event, + }; + + + static __init void sky2_debug_init(void) + { + struct dentry *ent; + + ent = debugfs_create_dir("sky2", NULL); + if (!ent || IS_ERR(ent)) + return; + + sky2_debug = ent; + register_netdevice_notifier(&sky2_notifier); + } + + static __exit void sky2_debug_cleanup(void) + { + if (sky2_debug) { + unregister_netdevice_notifier(&sky2_notifier); + debugfs_remove(sky2_debug); + sky2_debug = NULL; + } + } + + #else + #define sky2_debug_init() + #define sky2_debug_cleanup() + #endif + + /* Two copies of network device operations to handle special case of + not allowing netpoll on second port */ + static const struct net_device_ops sky2_netdev_ops[2] = { + { + .ndo_open = sky2_up, + .ndo_stop = sky2_down, + .ndo_start_xmit = sky2_xmit_frame, + .ndo_do_ioctl = sky2_ioctl, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = sky2_set_mac_address, + .ndo_set_rx_mode = sky2_set_multicast, + .ndo_change_mtu = sky2_change_mtu, + .ndo_fix_features = sky2_fix_features, + .ndo_set_features = sky2_set_features, + .ndo_tx_timeout = sky2_tx_timeout, + .ndo_get_stats64 = sky2_get_stats, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = sky2_netpoll, + #endif + }, + { + .ndo_open = sky2_up, + .ndo_stop = sky2_down, + .ndo_start_xmit = sky2_xmit_frame, + .ndo_do_ioctl = sky2_ioctl, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = sky2_set_mac_address, + .ndo_set_rx_mode = sky2_set_multicast, + .ndo_change_mtu = sky2_change_mtu, + .ndo_fix_features = sky2_fix_features, + .ndo_set_features = sky2_set_features, + .ndo_tx_timeout = sky2_tx_timeout, + .ndo_get_stats64 = sky2_get_stats, + }, + }; + + /* Initialize network device */ + static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, + unsigned port, + int highmem, int wol) + { + struct sky2_port *sky2; + struct net_device *dev = alloc_etherdev(sizeof(*sky2)); + + if (!dev) { + dev_err(&hw->pdev->dev, "etherdev alloc failed\n"); + return NULL; + } + + SET_NETDEV_DEV(dev, &hw->pdev->dev); + dev->irq = hw->pdev->irq; + SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops); + dev->watchdog_timeo = TX_WATCHDOG; + dev->netdev_ops = &sky2_netdev_ops[port]; + + sky2 = netdev_priv(dev); + sky2->netdev = dev; + sky2->hw = hw; + sky2->msg_enable = netif_msg_init(debug, default_msg); + + /* Auto speed and flow control */ + sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE; + if (hw->chip_id != CHIP_ID_YUKON_XL) + dev->hw_features |= NETIF_F_RXCSUM; + + sky2->flow_mode = FC_BOTH; + + sky2->duplex = -1; + sky2->speed = -1; + sky2->advertising = sky2_supported_modes(hw); + sky2->wol = wol; + + spin_lock_init(&sky2->phy_lock); + + sky2->tx_pending = TX_DEF_PENDING; + sky2->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1); + sky2->rx_pending = RX_DEF_PENDING; + + hw->dev[port] = dev; + + sky2->port = port; + + dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; + + if (highmem) + dev->features |= NETIF_F_HIGHDMA; + + /* Enable receive hashing unless hardware is known broken */ + if (!(hw->flags & SKY2_HW_RSS_BROKEN)) + dev->hw_features |= NETIF_F_RXHASH; + + if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) { + dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features |= SKY2_VLAN_OFFLOADS; + } + + dev->features |= dev->hw_features; + + /* read the mac address */ + memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + return dev; + } + + static void __devinit sky2_show_addr(struct net_device *dev) + { + const struct sky2_port *sky2 = netdev_priv(dev); + + netif_info(sky2, probe, dev, "addr %pM\n", dev->dev_addr); + } + + /* Handle software interrupt used during MSI test */ + static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) + { + struct sky2_hw *hw = dev_id; + u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); + + if (status == 0) + return IRQ_NONE; + + if (status & Y2_IS_IRQ_SW) { + hw->flags |= SKY2_HW_USE_MSI; + wake_up(&hw->msi_wait); + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + } + sky2_write32(hw, B0_Y2_SP_ICR, 2); + + return IRQ_HANDLED; + } + + /* Test interrupt path by forcing a a software IRQ */ + static int __devinit sky2_test_msi(struct sky2_hw *hw) + { + struct pci_dev *pdev = hw->pdev; + int err; + + init_waitqueue_head(&hw->msi_wait); + + sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); + + err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw); + if (err) { + dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); + return err; + } + + sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); + sky2_read8(hw, B0_CTST); + + wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10); + + if (!(hw->flags & SKY2_HW_USE_MSI)) { + /* MSI test failed, go back to INTx mode */ + dev_info(&pdev->dev, "No interrupt generated using MSI, " + "switching to INTx mode.\n"); + + err = -EOPNOTSUPP; + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + } + + sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); + + free_irq(pdev->irq, hw); + + return err; + } + + /* This driver supports yukon2 chipset only */ + static const char *sky2_name(u8 chipid, char *buf, int sz) + { + const char *name[] = { + "XL", /* 0xb3 */ + "EC Ultra", /* 0xb4 */ + "Extreme", /* 0xb5 */ + "EC", /* 0xb6 */ + "FE", /* 0xb7 */ + "FE+", /* 0xb8 */ + "Supreme", /* 0xb9 */ + "UL 2", /* 0xba */ + "Unknown", /* 0xbb */ + "Optima", /* 0xbc */ + "Optima Prime", /* 0xbd */ + "Optima 2", /* 0xbe */ + }; + + if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2) + strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz); + else + snprintf(buf, sz, "(chip %#x)", chipid); + return buf; + } + + static int __devinit sky2_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + struct net_device *dev, *dev1; + struct sky2_hw *hw; + int err, using_dac = 0, wol_default; + u32 reg; + char buf1[16]; + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "cannot enable PCI device\n"); + goto err_out; + } + + /* Get configuration information + * Note: only regular PCI config access once to test for HW issues + * other PCI access through shared memory for speed and to + * avoid MMCONFIG problems. + */ + err = pci_read_config_dword(pdev, PCI_DEV_REG2, ®); + if (err) { + dev_err(&pdev->dev, "PCI read config failed\n"); + goto err_out; + } + + if (~reg == 0) { + dev_err(&pdev->dev, "PCI configuration read error\n"); + goto err_out; + } + + err = pci_request_regions(pdev, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "cannot obtain PCI resources\n"); + goto err_out_disable; + } + + pci_set_master(pdev); + + if (sizeof(dma_addr_t) > sizeof(u32) && + !(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))) { + using_dac = 1; + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (err < 0) { + dev_err(&pdev->dev, "unable to obtain 64 bit DMA " + "for consistent allocations\n"); + goto err_out_free_regions; + } + } else { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, "no usable DMA configuration\n"); + goto err_out_free_regions; + } + } + + + #ifdef __BIG_ENDIAN + /* The sk98lin vendor driver uses hardware byte swapping but + * this driver uses software swapping. + */ + reg &= ~PCI_REV_DESC; + err = pci_write_config_dword(pdev, PCI_DEV_REG2, reg); + if (err) { + dev_err(&pdev->dev, "PCI write config failed\n"); + goto err_out_free_regions; + } + #endif + + wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0; + + err = -ENOMEM; + + hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:") + + strlen(pci_name(pdev)) + 1, GFP_KERNEL); + if (!hw) { + dev_err(&pdev->dev, "cannot allocate hardware struct\n"); + goto err_out_free_regions; + } + + hw->pdev = pdev; + sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev)); + + hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); + if (!hw->regs) { + dev_err(&pdev->dev, "cannot map device registers\n"); + goto err_out_free_hw; + } + + err = sky2_init(hw); + if (err) + goto err_out_iounmap; + + /* ring for status responses */ + hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING); + hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), + &hw->st_dma); + if (!hw->st_le) + goto err_out_reset; + + dev_info(&pdev->dev, "Yukon-2 %s chip revision %d\n", + sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev); + + sky2_reset(hw); + + dev = sky2_init_netdev(hw, 0, using_dac, wol_default); + if (!dev) { + err = -ENOMEM; + goto err_out_free_pci; + } + + if (!disable_msi && pci_enable_msi(pdev) == 0) { + err = sky2_test_msi(hw); + if (err == -EOPNOTSUPP) + pci_disable_msi(pdev); + else if (err) + goto err_out_free_netdev; + } + + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "cannot register net device\n"); + goto err_out_free_netdev; + } + + netif_carrier_off(dev); + + netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); + + sky2_show_addr(dev); + + if (hw->ports > 1) { + dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default); + if (!dev1) { + err = -ENOMEM; + goto err_out_unregister; + } + + err = register_netdev(dev1); + if (err) { + dev_err(&pdev->dev, "cannot register second net device\n"); + goto err_out_free_dev1; + } + + err = sky2_setup_irq(hw, hw->irq_name); + if (err) + goto err_out_unregister_dev1; + + sky2_show_addr(dev1); + } + + setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw); + INIT_WORK(&hw->restart_work, sky2_restart); + + pci_set_drvdata(pdev, hw); + pdev->d3_delay = 150; + + return 0; + + err_out_unregister_dev1: + unregister_netdev(dev1); + err_out_free_dev1: + free_netdev(dev1); + err_out_unregister: + if (hw->flags & SKY2_HW_USE_MSI) + pci_disable_msi(pdev); + unregister_netdev(dev); + err_out_free_netdev: + free_netdev(dev); + err_out_free_pci: + pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), + hw->st_le, hw->st_dma); + err_out_reset: + sky2_write8(hw, B0_CTST, CS_RST_SET); + err_out_iounmap: + iounmap(hw->regs); + err_out_free_hw: + kfree(hw); + err_out_free_regions: + pci_release_regions(pdev); + err_out_disable: + pci_disable_device(pdev); + err_out: + pci_set_drvdata(pdev, NULL); + return err; + } + + static void __devexit sky2_remove(struct pci_dev *pdev) + { + struct sky2_hw *hw = pci_get_drvdata(pdev); + int i; + + if (!hw) + return; + + del_timer_sync(&hw->watchdog_timer); + cancel_work_sync(&hw->restart_work); + + for (i = hw->ports-1; i >= 0; --i) + unregister_netdev(hw->dev[i]); + + sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); + + sky2_power_aux(hw); + + sky2_write8(hw, B0_CTST, CS_RST_SET); + sky2_read8(hw, B0_CTST); + + if (hw->ports > 1) { + napi_disable(&hw->napi); + free_irq(pdev->irq, hw); + } + + if (hw->flags & SKY2_HW_USE_MSI) + pci_disable_msi(pdev); + pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), + hw->st_le, hw->st_dma); + pci_release_regions(pdev); + pci_disable_device(pdev); + + for (i = hw->ports-1; i >= 0; --i) + free_netdev(hw->dev[i]); + + iounmap(hw->regs); + kfree(hw); + + pci_set_drvdata(pdev, NULL); + } + + static int sky2_suspend(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct sky2_hw *hw = pci_get_drvdata(pdev); + int i; + + if (!hw) + return 0; + + del_timer_sync(&hw->watchdog_timer); + cancel_work_sync(&hw->restart_work); + + rtnl_lock(); + + sky2_all_down(hw); + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (sky2->wol) + sky2_wol_init(sky2); + } + + sky2_power_aux(hw); + rtnl_unlock(); + + return 0; + } + + #ifdef CONFIG_PM_SLEEP + static int sky2_resume(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct sky2_hw *hw = pci_get_drvdata(pdev); + int err; + + if (!hw) + return 0; + + /* Re-enable all clocks */ + err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + if (err) { + dev_err(&pdev->dev, "PCI write config failed\n"); + goto out; + } + + rtnl_lock(); + sky2_reset(hw); + sky2_all_up(hw); + rtnl_unlock(); + + return 0; + out: + + dev_err(&pdev->dev, "resume failed (%d)\n", err); + pci_disable_device(pdev); + return err; + } + + static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume); + #define SKY2_PM_OPS (&sky2_pm_ops) + + #else + + #define SKY2_PM_OPS NULL + #endif + + static void sky2_shutdown(struct pci_dev *pdev) + { + sky2_suspend(&pdev->dev); + pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); + pci_set_power_state(pdev, PCI_D3hot); + } + + static struct pci_driver sky2_driver = { + .name = DRV_NAME, + .id_table = sky2_id_table, + .probe = sky2_probe, + .remove = __devexit_p(sky2_remove), + .shutdown = sky2_shutdown, + .driver.pm = SKY2_PM_OPS, + }; + + static int __init sky2_init_module(void) + { + pr_info("driver version " DRV_VERSION "\n"); + + sky2_debug_init(); + return pci_register_driver(&sky2_driver); + } + + static void __exit sky2_cleanup_module(void) + { + pci_unregister_driver(&sky2_driver); + sky2_debug_cleanup(); + } + + module_init(sky2_init_module); + module_exit(sky2_cleanup_module); + + MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver"); + MODULE_AUTHOR("Stephen Hemminger "); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); diff --cc drivers/net/ethernet/micrel/ks8695net.c index 000000000000,70788401d699..ab81c0dc96e2 mode 000000,100644..100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@@ -1,0 -1,1656 +1,1656 @@@ + /* + * Micrel KS8695 (Centaur) Ethernet. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Copyright 2008 Simtec Electronics + * Daniel Silverstone + * Vincent Sanders + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #include + #include + #include + #include + + #include "ks8695net.h" + + #define MODULENAME "ks8695_ether" + #define MODULEVERSION "1.02" + + /* + * Transmit and device reset timeout, default 5 seconds. + */ + static int watchdog = 5000; + + /* Hardware structures */ + + /** + * struct rx_ring_desc - Receive descriptor ring element + * @status: The status of the descriptor element (E.g. who owns it) + * @length: The number of bytes in the block pointed to by data_ptr + * @data_ptr: The physical address of the data block to receive into + * @next_desc: The physical address of the next descriptor element. + */ + struct rx_ring_desc { + __le32 status; + __le32 length; + __le32 data_ptr; + __le32 next_desc; + }; + + /** + * struct tx_ring_desc - Transmit descriptor ring element + * @owner: Who owns the descriptor + * @status: The number of bytes in the block pointed to by data_ptr + * @data_ptr: The physical address of the data block to receive into + * @next_desc: The physical address of the next descriptor element. + */ + struct tx_ring_desc { + __le32 owner; + __le32 status; + __le32 data_ptr; + __le32 next_desc; + }; + + /** + * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings. + * @skb: The buffer in the ring + * @dma_ptr: The mapped DMA pointer of the buffer + * @length: The number of bytes mapped to dma_ptr + */ + struct ks8695_skbuff { + struct sk_buff *skb; + dma_addr_t dma_ptr; + u32 length; + }; + + /* Private device structure */ + + #define MAX_TX_DESC 8 + #define MAX_TX_DESC_MASK 0x7 + #define MAX_RX_DESC 16 + #define MAX_RX_DESC_MASK 0xf + + /*napi_weight have better more than rx DMA buffers*/ + #define NAPI_WEIGHT 64 + + #define MAX_RXBUF_SIZE 0x700 + + #define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC) + #define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC) + #define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE) + + /** + * enum ks8695_dtype - Device type + * @KS8695_DTYPE_WAN: This device is a WAN interface + * @KS8695_DTYPE_LAN: This device is a LAN interface + * @KS8695_DTYPE_HPNA: This device is an HPNA interface + */ + enum ks8695_dtype { + KS8695_DTYPE_WAN, + KS8695_DTYPE_LAN, + KS8695_DTYPE_HPNA, + }; + + /** + * struct ks8695_priv - Private data for the KS8695 Ethernet + * @in_suspend: Flag to indicate if we're suspending/resuming + * @ndev: The net_device for this interface + * @dev: The platform device object for this interface + * @dtype: The type of this device + * @io_regs: The ioremapped registers for this interface + * @napi : Add support NAPI for Rx + * @rx_irq_name: The textual name of the RX IRQ from the platform data + * @tx_irq_name: The textual name of the TX IRQ from the platform data + * @link_irq_name: The textual name of the link IRQ from the + * platform data if available + * @rx_irq: The IRQ number for the RX IRQ + * @tx_irq: The IRQ number for the TX IRQ + * @link_irq: The IRQ number for the link IRQ if available + * @regs_req: The resource request for the registers region + * @phyiface_req: The resource request for the phy/switch region + * if available + * @phyiface_regs: The ioremapped registers for the phy/switch if available + * @ring_base: The base pointer of the dma coherent memory for the rings + * @ring_base_dma: The DMA mapped equivalent of ring_base + * @tx_ring: The pointer in ring_base of the TX ring + * @tx_ring_used: The number of slots in the TX ring which are occupied + * @tx_ring_next_slot: The next slot to fill in the TX ring + * @tx_ring_dma: The DMA mapped equivalent of tx_ring + * @tx_buffers: The sk_buff mappings for the TX ring + * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables + * @rx_ring: The pointer in ring_base of the RX ring + * @rx_ring_dma: The DMA mapped equivalent of rx_ring + * @rx_buffers: The sk_buff mappings for the RX ring + * @next_rx_desc_read: The next RX descriptor to read from on IRQ + * @rx_lock: A lock to protect Rx irq function + * @msg_enable: The flags for which messages to emit + */ + struct ks8695_priv { + int in_suspend; + struct net_device *ndev; + struct device *dev; + enum ks8695_dtype dtype; + void __iomem *io_regs; + + struct napi_struct napi; + + const char *rx_irq_name, *tx_irq_name, *link_irq_name; + int rx_irq, tx_irq, link_irq; + + struct resource *regs_req, *phyiface_req; + void __iomem *phyiface_regs; + + void *ring_base; + dma_addr_t ring_base_dma; + + struct tx_ring_desc *tx_ring; + int tx_ring_used; + int tx_ring_next_slot; + dma_addr_t tx_ring_dma; + struct ks8695_skbuff tx_buffers[MAX_TX_DESC]; + spinlock_t txq_lock; + + struct rx_ring_desc *rx_ring; + dma_addr_t rx_ring_dma; + struct ks8695_skbuff rx_buffers[MAX_RX_DESC]; + int next_rx_desc_read; + spinlock_t rx_lock; + + int msg_enable; + }; + + /* Register access */ + + /** + * ks8695_readreg - Read from a KS8695 ethernet register + * @ksp: The device to read from + * @reg: The register to read + */ + static inline u32 + ks8695_readreg(struct ks8695_priv *ksp, int reg) + { + return readl(ksp->io_regs + reg); + } + + /** + * ks8695_writereg - Write to a KS8695 ethernet register + * @ksp: The device to write to + * @reg: The register to write + * @value: The value to write to the register + */ + static inline void + ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value) + { + writel(value, ksp->io_regs + reg); + } + + /* Utility functions */ + + /** + * ks8695_port_type - Retrieve port-type as user-friendly string + * @ksp: The device to return the type for + * + * Returns a string indicating which of the WAN, LAN or HPNA + * ports this device is likely to represent. + */ + static const char * + ks8695_port_type(struct ks8695_priv *ksp) + { + switch (ksp->dtype) { + case KS8695_DTYPE_LAN: + return "LAN"; + case KS8695_DTYPE_WAN: + return "WAN"; + case KS8695_DTYPE_HPNA: + return "HPNA"; + } + + return "UNKNOWN"; + } + + /** + * ks8695_update_mac - Update the MAC registers in the device + * @ksp: The device to update + * + * Updates the MAC registers in the KS8695 device from the address in the + * net_device structure associated with this interface. + */ + static void + ks8695_update_mac(struct ks8695_priv *ksp) + { + /* Update the HW with the MAC from the net_device */ + struct net_device *ndev = ksp->ndev; + u32 machigh, maclow; + + maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) | + (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0)); + machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0)); + + ks8695_writereg(ksp, KS8695_MAL, maclow); + ks8695_writereg(ksp, KS8695_MAH, machigh); + + } + + /** + * ks8695_refill_rxbuffers - Re-fill the RX buffer ring + * @ksp: The device to refill + * + * Iterates the RX ring of the device looking for empty slots. + * For each empty slot, we allocate and map a new SKB and give it + * to the hardware. + * This can be called from interrupt context safely. + */ + static void + ks8695_refill_rxbuffers(struct ks8695_priv *ksp) + { + /* Run around the RX ring, filling in any missing sk_buff's */ + int buff_n; + + for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { + if (!ksp->rx_buffers[buff_n].skb) { + struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE); + dma_addr_t mapping; + + ksp->rx_buffers[buff_n].skb = skb; + if (skb == NULL) { + /* Failed to allocate one, perhaps + * we'll try again later. + */ + break; + } + + mapping = dma_map_single(ksp->dev, skb->data, + MAX_RXBUF_SIZE, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(ksp->dev, mapping))) { + /* Failed to DMA map this SKB, try later */ + dev_kfree_skb_irq(skb); + ksp->rx_buffers[buff_n].skb = NULL; + break; + } + ksp->rx_buffers[buff_n].dma_ptr = mapping; + skb->dev = ksp->ndev; + ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE; + + /* Record this into the DMA ring */ + ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping); + ksp->rx_ring[buff_n].length = + cpu_to_le32(MAX_RXBUF_SIZE); + + wmb(); + + /* And give ownership over to the hardware */ + ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN); + } + } + } + + /* Maximum number of multicast addresses which the KS8695 HW supports */ + #define KS8695_NR_ADDRESSES 16 + + /** + * ks8695_init_partial_multicast - Init the mcast addr registers + * @ksp: The device to initialise + * @addr: The multicast address list to use + * @nr_addr: The number of addresses in the list + * + * This routine is a helper for ks8695_set_multicast - it writes + * the additional-address registers in the KS8695 ethernet device + * and cleans up any others left behind. + */ + static void + ks8695_init_partial_multicast(struct ks8695_priv *ksp, + struct net_device *ndev) + { + u32 low, high; + int i; + struct netdev_hw_addr *ha; + + i = 0; + netdev_for_each_mc_addr(ha, ndev) { + /* Ran out of space in chip? */ + BUG_ON(i == KS8695_NR_ADDRESSES); + + low = (ha->addr[2] << 24) | (ha->addr[3] << 16) | + (ha->addr[4] << 8) | (ha->addr[5]); + high = (ha->addr[0] << 8) | (ha->addr[1]); + + ks8695_writereg(ksp, KS8695_AAL_(i), low); + ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high); + i++; + } + + /* Clear the remaining Additional Station Addresses */ + for (; i < KS8695_NR_ADDRESSES; i++) { + ks8695_writereg(ksp, KS8695_AAL_(i), 0); + ks8695_writereg(ksp, KS8695_AAH_(i), 0); + } + } + + /* Interrupt handling */ + + /** + * ks8695_tx_irq - Transmit IRQ handler + * @irq: The IRQ which went off (ignored) + * @dev_id: The net_device for the interrupt + * + * Process the TX ring, clearing out any transmitted slots. + * Allows the net_device to pass us new packets once slots are + * freed. + */ + static irqreturn_t + ks8695_tx_irq(int irq, void *dev_id) + { + struct net_device *ndev = (struct net_device *)dev_id; + struct ks8695_priv *ksp = netdev_priv(ndev); + int buff_n; + + for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { + if (ksp->tx_buffers[buff_n].skb && + !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) { + rmb(); + /* An SKB which is not owned by HW is present */ + /* Update the stats for the net_device */ + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length; + + /* Free the packet from the ring */ + ksp->tx_ring[buff_n].data_ptr = 0; + + /* Free the sk_buff */ + dma_unmap_single(ksp->dev, + ksp->tx_buffers[buff_n].dma_ptr, + ksp->tx_buffers[buff_n].length, + DMA_TO_DEVICE); + dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb); + ksp->tx_buffers[buff_n].skb = NULL; + ksp->tx_ring_used--; + } + } + + netif_wake_queue(ndev); + + return IRQ_HANDLED; + } + + /** + * ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit + * @ksp: Private data for the KS8695 Ethernet + * + * For KS8695 document: + * Interrupt Enable Register (offset 0xE204) + * Bit29 : WAN MAC Receive Interrupt Enable + * Bit16 : LAN MAC Receive Interrupt Enable + * Interrupt Status Register (Offset 0xF208) + * Bit29: WAN MAC Receive Status + * Bit16: LAN MAC Receive Status - * So, this Rx interrrupt enable/status bit number is equal ++ * So, this Rx interrupt enable/status bit number is equal + * as Rx IRQ number. + */ + static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp) + { + return ksp->rx_irq; + } + + /** + * ks8695_rx_irq - Receive IRQ handler + * @irq: The IRQ which went off (ignored) + * @dev_id: The net_device for the interrupt + * + * Inform NAPI that packet reception needs to be scheduled + */ + + static irqreturn_t + ks8695_rx_irq(int irq, void *dev_id) + { + struct net_device *ndev = (struct net_device *)dev_id; + struct ks8695_priv *ksp = netdev_priv(ndev); + + spin_lock(&ksp->rx_lock); + + if (napi_schedule_prep(&ksp->napi)) { + unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN); + unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp); + /*disable rx interrupt*/ + status &= ~mask_bit; + writel(status , KS8695_IRQ_VA + KS8695_INTEN); + __napi_schedule(&ksp->napi); + } + + spin_unlock(&ksp->rx_lock); + return IRQ_HANDLED; + } + + /** + * ks8695_rx - Receive packets called by NAPI poll method + * @ksp: Private data for the KS8695 Ethernet + * @budget: Number of packets allowed to process + */ + static int ks8695_rx(struct ks8695_priv *ksp, int budget) + { + struct net_device *ndev = ksp->ndev; + struct sk_buff *skb; + int buff_n; + u32 flags; + int pktlen; + int received = 0; + + buff_n = ksp->next_rx_desc_read; + while (received < budget + && ksp->rx_buffers[buff_n].skb + && (!(ksp->rx_ring[buff_n].status & + cpu_to_le32(RDES_OWN)))) { + rmb(); + flags = le32_to_cpu(ksp->rx_ring[buff_n].status); + + /* Found an SKB which we own, this means we + * received a packet + */ + if ((flags & (RDES_FS | RDES_LS)) != + (RDES_FS | RDES_LS)) { + /* This packet is not the first and + * the last segment. Therefore it is + * a "spanning" packet and we can't + * handle it + */ + goto rx_failure; + } + + if (flags & (RDES_ES | RDES_RE)) { + /* It's an error packet */ + ndev->stats.rx_errors++; + if (flags & RDES_TL) + ndev->stats.rx_length_errors++; + if (flags & RDES_RF) + ndev->stats.rx_length_errors++; + if (flags & RDES_CE) + ndev->stats.rx_crc_errors++; + if (flags & RDES_RE) + ndev->stats.rx_missed_errors++; + + goto rx_failure; + } + + pktlen = flags & RDES_FLEN; + pktlen -= 4; /* Drop the CRC */ + + /* Retrieve the sk_buff */ + skb = ksp->rx_buffers[buff_n].skb; + + /* Clear it from the ring */ + ksp->rx_buffers[buff_n].skb = NULL; + ksp->rx_ring[buff_n].data_ptr = 0; + + /* Unmap the SKB */ + dma_unmap_single(ksp->dev, + ksp->rx_buffers[buff_n].dma_ptr, + ksp->rx_buffers[buff_n].length, + DMA_FROM_DEVICE); + + /* Relinquish the SKB to the network layer */ + skb_put(skb, pktlen); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + + /* Record stats */ + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += pktlen; + goto rx_finished; + + rx_failure: + /* This ring entry is an error, but we can + * re-use the skb + */ + /* Give the ring entry back to the hardware */ + ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN); + rx_finished: + received++; + buff_n = (buff_n + 1) & MAX_RX_DESC_MASK; + } + + /* And note which RX descriptor we last did */ + ksp->next_rx_desc_read = buff_n; + + /* And refill the buffers */ + ks8695_refill_rxbuffers(ksp); + + /* Kick the RX DMA engine, in case it became suspended */ + ks8695_writereg(ksp, KS8695_DRSC, 0); + + return received; + } + + + /** + * ks8695_poll - Receive packet by NAPI poll method + * @ksp: Private data for the KS8695 Ethernet + * @budget: The remaining number packets for network subsystem + * + * Invoked by the network core when it requests for new + * packets from the driver + */ + static int ks8695_poll(struct napi_struct *napi, int budget) + { + struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi); + unsigned long work_done; + + unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN); + unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp); + + work_done = ks8695_rx(ksp, budget); + + if (work_done < budget) { + unsigned long flags; + spin_lock_irqsave(&ksp->rx_lock, flags); + __napi_complete(napi); + /*enable rx interrupt*/ + writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN); + spin_unlock_irqrestore(&ksp->rx_lock, flags); + } + return work_done; + } + + /** + * ks8695_link_irq - Link change IRQ handler + * @irq: The IRQ which went off (ignored) + * @dev_id: The net_device for the interrupt + * + * The WAN interface can generate an IRQ when the link changes, + * report this to the net layer and the user. + */ + static irqreturn_t + ks8695_link_irq(int irq, void *dev_id) + { + struct net_device *ndev = (struct net_device *)dev_id; + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + if (ctrl & WMC_WLS) { + netif_carrier_on(ndev); + if (netif_msg_link(ksp)) + dev_info(ksp->dev, + "%s: Link is now up (10%sMbps/%s-duplex)\n", + ndev->name, + (ctrl & WMC_WSS) ? "0" : "", + (ctrl & WMC_WDS) ? "Full" : "Half"); + } else { + netif_carrier_off(ndev); + if (netif_msg_link(ksp)) + dev_info(ksp->dev, "%s: Link is now down.\n", + ndev->name); + } + + return IRQ_HANDLED; + } + + + /* KS8695 Device functions */ + + /** + * ks8695_reset - Reset a KS8695 ethernet interface + * @ksp: The interface to reset + * + * Perform an engine reset of the interface and re-program it + * with sensible defaults. + */ + static void + ks8695_reset(struct ks8695_priv *ksp) + { + int reset_timeout = watchdog; + /* Issue the reset via the TX DMA control register */ + ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST); + while (reset_timeout--) { + if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST)) + break; + msleep(1); + } + + if (reset_timeout < 0) { + dev_crit(ksp->dev, + "Timeout waiting for DMA engines to reset\n"); + /* And blithely carry on */ + } + + /* Definitely wait long enough before attempting to program + * the engines + */ + msleep(10); + + /* RX: unicast and broadcast */ + ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB); + /* TX: pad and add CRC */ + ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC); + } + + /** + * ks8695_shutdown - Shut down a KS8695 ethernet interface + * @ksp: The interface to shut down + * + * This disables packet RX/TX, cleans up IRQs, drains the rings, + * and basically places the interface into a clean shutdown + * state. + */ + static void + ks8695_shutdown(struct ks8695_priv *ksp) + { + u32 ctrl; + int buff_n; + + /* Disable packet transmission */ + ctrl = ks8695_readreg(ksp, KS8695_DTXC); + ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE); + + /* Disable packet reception */ + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE); + + /* Release the IRQs */ + free_irq(ksp->rx_irq, ksp->ndev); + free_irq(ksp->tx_irq, ksp->ndev); + if (ksp->link_irq != -1) + free_irq(ksp->link_irq, ksp->ndev); + + /* Throw away any pending TX packets */ + for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { + if (ksp->tx_buffers[buff_n].skb) { + /* Remove this SKB from the TX ring */ + ksp->tx_ring[buff_n].owner = 0; + ksp->tx_ring[buff_n].status = 0; + ksp->tx_ring[buff_n].data_ptr = 0; + + /* Unmap and bin this SKB */ + dma_unmap_single(ksp->dev, + ksp->tx_buffers[buff_n].dma_ptr, + ksp->tx_buffers[buff_n].length, + DMA_TO_DEVICE); + dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb); + ksp->tx_buffers[buff_n].skb = NULL; + } + } + + /* Purge the RX buffers */ + for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { + if (ksp->rx_buffers[buff_n].skb) { + /* Remove the SKB from the RX ring */ + ksp->rx_ring[buff_n].status = 0; + ksp->rx_ring[buff_n].data_ptr = 0; + + /* Unmap and bin the SKB */ + dma_unmap_single(ksp->dev, + ksp->rx_buffers[buff_n].dma_ptr, + ksp->rx_buffers[buff_n].length, + DMA_FROM_DEVICE); + dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb); + ksp->rx_buffers[buff_n].skb = NULL; + } + } + } + + + /** + * ks8695_setup_irq - IRQ setup helper function + * @irq: The IRQ number to claim + * @irq_name: The name to give the IRQ claimant + * @handler: The function to call to handle the IRQ + * @ndev: The net_device to pass in as the dev_id argument to the handler + * + * Return 0 on success. + */ + static int + ks8695_setup_irq(int irq, const char *irq_name, + irq_handler_t handler, struct net_device *ndev) + { + int ret; + + ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev); + + if (ret) { + dev_err(&ndev->dev, "failure to request IRQ %d\n", irq); + return ret; + } + + return 0; + } + + /** + * ks8695_init_net - Initialise a KS8695 ethernet interface + * @ksp: The interface to initialise + * + * This routine fills the RX ring, initialises the DMA engines, + * allocates the IRQs and then starts the packet TX and RX + * engines. + */ + static int + ks8695_init_net(struct ks8695_priv *ksp) + { + int ret; + u32 ctrl; + + ks8695_refill_rxbuffers(ksp); + + /* Initialise the DMA engines */ + ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma); + ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma); + + /* Request the IRQs */ + ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name, + ks8695_rx_irq, ksp->ndev); + if (ret) + return ret; + ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name, + ks8695_tx_irq, ksp->ndev); + if (ret) + return ret; + if (ksp->link_irq != -1) { + ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name, + ks8695_link_irq, ksp->ndev); + if (ret) + return ret; + } + + /* Set up the ring indices */ + ksp->next_rx_desc_read = 0; + ksp->tx_ring_next_slot = 0; + ksp->tx_ring_used = 0; + + /* Bring up transmission */ + ctrl = ks8695_readreg(ksp, KS8695_DTXC); + /* Enable packet transmission */ + ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE); + + /* Bring up the reception */ + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + /* Enable packet reception */ + ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE); + /* And start the DMA engine */ + ks8695_writereg(ksp, KS8695_DRSC, 0); + + /* All done */ + return 0; + } + + /** + * ks8695_release_device - HW resource release for KS8695 e-net + * @ksp: The device to be freed + * + * This unallocates io memory regions, dma-coherent regions etc + * which were allocated in ks8695_probe. + */ + static void + ks8695_release_device(struct ks8695_priv *ksp) + { + /* Unmap the registers */ + iounmap(ksp->io_regs); + if (ksp->phyiface_regs) + iounmap(ksp->phyiface_regs); + + /* And release the request */ + release_resource(ksp->regs_req); + kfree(ksp->regs_req); + if (ksp->phyiface_req) { + release_resource(ksp->phyiface_req); + kfree(ksp->phyiface_req); + } + + /* Free the ring buffers */ + dma_free_coherent(ksp->dev, RING_DMA_SIZE, + ksp->ring_base, ksp->ring_base_dma); + } + + /* Ethtool support */ + + /** + * ks8695_get_msglevel - Get the messages enabled for emission + * @ndev: The network device to read from + */ + static u32 + ks8695_get_msglevel(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + + return ksp->msg_enable; + } + + /** + * ks8695_set_msglevel - Set the messages enabled for emission + * @ndev: The network device to configure + * @value: The messages to set for emission + */ + static void + ks8695_set_msglevel(struct net_device *ndev, u32 value) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + + ksp->msg_enable = value; + } + + /** + * ks8695_wan_get_settings - Get device-specific settings. + * @ndev: The network device to read settings from + * @cmd: The ethtool structure to read into + */ + static int + ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + /* All ports on the KS8695 support these... */ + cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_TP | SUPPORTED_MII); + cmd->transceiver = XCVR_INTERNAL; + + cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; + cmd->port = PORT_MII; + cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); + cmd->phy_address = 0; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + if ((ctrl & WMC_WAND) == 0) { + /* auto-negotiation is enabled */ + cmd->advertising |= ADVERTISED_Autoneg; + if (ctrl & WMC_WANA100F) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (ctrl & WMC_WANA100H) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (ctrl & WMC_WANA10F) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (ctrl & WMC_WANA10H) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (ctrl & WMC_WANAP) + cmd->advertising |= ADVERTISED_Pause; + cmd->autoneg = AUTONEG_ENABLE; + + ethtool_cmd_speed_set(cmd, + (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10); + cmd->duplex = (ctrl & WMC_WDS) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + /* auto-negotiation is disabled */ + cmd->autoneg = AUTONEG_DISABLE; + + ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ? + SPEED_100 : SPEED_10)); + cmd->duplex = (ctrl & WMC_WANFF) ? + DUPLEX_FULL : DUPLEX_HALF; + } + + return 0; + } + + /** + * ks8695_wan_set_settings - Set device-specific settings. + * @ndev: The network device to configure + * @cmd: The settings to configure + */ + static int + ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100)) + return -EINVAL; + if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL)) + return -EINVAL; + if (cmd->port != PORT_MII) + return -EINVAL; + if (cmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if ((cmd->autoneg != AUTONEG_DISABLE) && + (cmd->autoneg != AUTONEG_ENABLE)) + return -EINVAL; + + if (cmd->autoneg == AUTONEG_ENABLE) { + if ((cmd->advertising & (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full)) == 0) + return -EINVAL; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | + WMC_WANA10F | WMC_WANA10H); + if (cmd->advertising & ADVERTISED_100baseT_Full) + ctrl |= WMC_WANA100F; + if (cmd->advertising & ADVERTISED_100baseT_Half) + ctrl |= WMC_WANA100H; + if (cmd->advertising & ADVERTISED_10baseT_Full) + ctrl |= WMC_WANA10F; + if (cmd->advertising & ADVERTISED_10baseT_Half) + ctrl |= WMC_WANA10H; + + /* force a re-negotiation */ + ctrl |= WMC_WANR; + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + } else { + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + /* disable auto-negotiation */ + ctrl |= WMC_WAND; + ctrl &= ~(WMC_WANF100 | WMC_WANFF); + + if (cmd->speed == SPEED_100) + ctrl |= WMC_WANF100; + if (cmd->duplex == DUPLEX_FULL) + ctrl |= WMC_WANFF; + + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + } + + return 0; + } + + /** + * ks8695_wan_nwayreset - Restart the autonegotiation on the port. + * @ndev: The network device to restart autoneotiation on + */ + static int + ks8695_wan_nwayreset(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + if ((ctrl & WMC_WAND) == 0) + writel(ctrl | WMC_WANR, + ksp->phyiface_regs + KS8695_WMC); + else + /* auto-negotiation not enabled */ + return -EINVAL; + + return 0; + } + + /** + * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising + * @ndev: The device to retrieve settings from + * @param: The structure to fill out with the information + */ + static void + ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + /* advertise Pause */ + param->autoneg = (ctrl & WMC_WANAP); + + /* current Rx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + param->rx_pause = (ctrl & DRXC_RFCE); + + /* current Tx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DTXC); + param->tx_pause = (ctrl & DTXC_TFCE); + } + + /** + * ks8695_get_drvinfo - Retrieve driver information + * @ndev: The network device to retrieve info about + * @info: The info structure to fill out. + */ + static void + ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) + { + strlcpy(info->driver, MODULENAME, sizeof(info->driver)); + strlcpy(info->version, MODULEVERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev_name(ndev->dev.parent), + sizeof(info->bus_info)); + } + + static const struct ethtool_ops ks8695_ethtool_ops = { + .get_msglevel = ks8695_get_msglevel, + .set_msglevel = ks8695_set_msglevel, + .get_drvinfo = ks8695_get_drvinfo, + }; + + static const struct ethtool_ops ks8695_wan_ethtool_ops = { + .get_msglevel = ks8695_get_msglevel, + .set_msglevel = ks8695_set_msglevel, + .get_settings = ks8695_wan_get_settings, + .set_settings = ks8695_wan_set_settings, + .nway_reset = ks8695_wan_nwayreset, + .get_link = ethtool_op_get_link, + .get_pauseparam = ks8695_wan_get_pause, + .get_drvinfo = ks8695_get_drvinfo, + }; + + /* Network device interface functions */ + + /** + * ks8695_set_mac - Update MAC in net dev and HW + * @ndev: The network device to update + * @addr: The new MAC address to set + */ + static int + ks8695_set_mac(struct net_device *ndev, void *addr) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + struct sockaddr *address = addr; + + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len); + + ks8695_update_mac(ksp); + + dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n", + ndev->name, ndev->dev_addr); + + return 0; + } + + /** + * ks8695_set_multicast - Set up the multicast behaviour of the interface + * @ndev: The net_device to configure + * + * This routine, called by the net layer, configures promiscuity + * and multicast reception behaviour for the interface. + */ + static void + ks8695_set_multicast(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + + if (ndev->flags & IFF_PROMISC) { + /* enable promiscuous mode */ + ctrl |= DRXC_RA; + } else if (ndev->flags & ~IFF_PROMISC) { + /* disable promiscuous mode */ + ctrl &= ~DRXC_RA; + } + + if (ndev->flags & IFF_ALLMULTI) { + /* enable all multicast mode */ + ctrl |= DRXC_RM; + } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) { + /* more specific multicast addresses than can be + * handled in hardware + */ + ctrl |= DRXC_RM; + } else { + /* enable specific multicasts */ + ctrl &= ~DRXC_RM; + ks8695_init_partial_multicast(ksp, ndev); + } + + ks8695_writereg(ksp, KS8695_DRXC, ctrl); + } + + /** + * ks8695_timeout - Handle a network tx/rx timeout. + * @ndev: The net_device which timed out. + * + * A network transaction timed out, reset the device. + */ + static void + ks8695_timeout(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + + netif_stop_queue(ndev); + ks8695_shutdown(ksp); + + ks8695_reset(ksp); + + ks8695_update_mac(ksp); + + /* We ignore the return from this since it managed to init + * before it probably will be okay to init again. + */ + ks8695_init_net(ksp); + + /* Reconfigure promiscuity etc */ + ks8695_set_multicast(ndev); + + /* And start the TX queue once more */ + netif_start_queue(ndev); + } + + /** + * ks8695_start_xmit - Start a packet transmission + * @skb: The packet to transmit + * @ndev: The network device to send the packet on + * + * This routine, called by the net layer, takes ownership of the + * sk_buff and adds it to the TX ring. It then kicks the TX DMA + * engine to ensure transmission begins. + */ + static int + ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + int buff_n; + dma_addr_t dmap; + + spin_lock_irq(&ksp->txq_lock); + + if (ksp->tx_ring_used == MAX_TX_DESC) { + /* Somehow we got entered when we have no room */ + spin_unlock_irq(&ksp->txq_lock); + return NETDEV_TX_BUSY; + } + + buff_n = ksp->tx_ring_next_slot; + + BUG_ON(ksp->tx_buffers[buff_n].skb); + + dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(ksp->dev, dmap))) { + /* Failed to DMA map this SKB, give it back for now */ + spin_unlock_irq(&ksp->txq_lock); + dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\ + "transmission, trying later\n", ndev->name); + return NETDEV_TX_BUSY; + } + + ksp->tx_buffers[buff_n].dma_ptr = dmap; + /* Mapped okay, store the buffer pointer and length for later */ + ksp->tx_buffers[buff_n].skb = skb; + ksp->tx_buffers[buff_n].length = skb->len; + + /* Fill out the TX descriptor */ + ksp->tx_ring[buff_n].data_ptr = + cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr); + ksp->tx_ring[buff_n].status = + cpu_to_le32(TDES_IC | TDES_FS | TDES_LS | + (skb->len & TDES_TBS)); + + wmb(); + + /* Hand it over to the hardware */ + ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN); + + if (++ksp->tx_ring_used == MAX_TX_DESC) + netif_stop_queue(ndev); + + /* Kick the TX DMA in case it decided to go IDLE */ + ks8695_writereg(ksp, KS8695_DTSC, 0); + + /* And update the next ring slot */ + ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK; + + spin_unlock_irq(&ksp->txq_lock); + return NETDEV_TX_OK; + } + + /** + * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface + * @ndev: The net_device to stop + * + * This disables the TX queue and cleans up a KS8695 ethernet + * device. + */ + static int + ks8695_stop(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + + netif_stop_queue(ndev); + napi_disable(&ksp->napi); + + ks8695_shutdown(ksp); + + return 0; + } + + /** + * ks8695_open - Open (bring up) a KS8695 ethernet interface + * @ndev: The net_device to open + * + * This resets, configures the MAC, initialises the RX ring and + * DMA engines and starts the TX queue for a KS8695 ethernet + * device. + */ + static int + ks8695_open(struct net_device *ndev) + { + struct ks8695_priv *ksp = netdev_priv(ndev); + int ret; + + if (!is_valid_ether_addr(ndev->dev_addr)) + return -EADDRNOTAVAIL; + + ks8695_reset(ksp); + + ks8695_update_mac(ksp); + + ret = ks8695_init_net(ksp); + if (ret) { + ks8695_shutdown(ksp); + return ret; + } + + napi_enable(&ksp->napi); + netif_start_queue(ndev); + + return 0; + } + + /* Platform device driver */ + + /** + * ks8695_init_switch - Init LAN switch to known good defaults. + * @ksp: The device to initialise + * + * This initialises the LAN switch in the KS8695 to a known-good + * set of defaults. + */ + static void __devinit + ks8695_init_switch(struct ks8695_priv *ksp) + { + u32 ctrl; + + /* Default value for SEC0 according to datasheet */ + ctrl = 0x40819e00; + + /* LED0 = Speed LED1 = Link/Activity */ + ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S); + ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY); + + /* Enable Switch */ + ctrl |= SEC0_ENABLE; + + writel(ctrl, ksp->phyiface_regs + KS8695_SEC0); + + /* Defaults for SEC1 */ + writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1); + } + + /** + * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults + * @ksp: The device to initialise + * + * This initialises a KS8695's WAN phy to sensible values for + * autonegotiation etc. + */ + static void __devinit + ks8695_init_wan_phy(struct ks8695_priv *ksp) + { + u32 ctrl; + + /* Support auto-negotiation */ + ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H | + WMC_WANA10F | WMC_WANA10H); + + /* LED0 = Activity , LED1 = Link */ + ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK); + + /* Restart Auto-negotiation */ + ctrl |= WMC_WANR; + + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + + writel(0, ksp->phyiface_regs + KS8695_WPPM); + writel(0, ksp->phyiface_regs + KS8695_PPS); + } + + static const struct net_device_ops ks8695_netdev_ops = { + .ndo_open = ks8695_open, + .ndo_stop = ks8695_stop, + .ndo_start_xmit = ks8695_start_xmit, + .ndo_tx_timeout = ks8695_timeout, + .ndo_set_mac_address = ks8695_set_mac, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = ks8695_set_multicast, + }; + + /** + * ks8695_probe - Probe and initialise a KS8695 ethernet interface + * @pdev: The platform device to probe + * + * Initialise a KS8695 ethernet device from platform data. + * + * This driver requires at least one IORESOURCE_MEM for the + * registers and two IORESOURCE_IRQ for the RX and TX IRQs + * respectively. It can optionally take an additional + * IORESOURCE_MEM for the switch or phy in the case of the lan or + * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan + * port. + */ + static int __devinit + ks8695_probe(struct platform_device *pdev) + { + struct ks8695_priv *ksp; + struct net_device *ndev; + struct resource *regs_res, *phyiface_res; + struct resource *rxirq_res, *txirq_res, *linkirq_res; + int ret = 0; + int buff_n; + u32 machigh, maclow; + + /* Initialise a net_device */ + ndev = alloc_etherdev(sizeof(struct ks8695_priv)); + if (!ndev) { + dev_err(&pdev->dev, "could not allocate device.\n"); + return -ENOMEM; + } + + SET_NETDEV_DEV(ndev, &pdev->dev); + + dev_dbg(&pdev->dev, "ks8695_probe() called\n"); + + /* Configure our private structure a little */ + ksp = netdev_priv(ndev); + + ksp->dev = &pdev->dev; + ksp->ndev = ndev; + ksp->msg_enable = NETIF_MSG_LINK; + + /* Retrieve resources */ + regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + + rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); + + if (!(regs_res && rxirq_res && txirq_res)) { + dev_err(ksp->dev, "insufficient resources\n"); + ret = -ENOENT; + goto failure; + } + + ksp->regs_req = request_mem_region(regs_res->start, + resource_size(regs_res), + pdev->name); + + if (!ksp->regs_req) { + dev_err(ksp->dev, "cannot claim register space\n"); + ret = -EIO; + goto failure; + } + + ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res)); + + if (!ksp->io_regs) { + dev_err(ksp->dev, "failed to ioremap registers\n"); + ret = -EINVAL; + goto failure; + } + + if (phyiface_res) { + ksp->phyiface_req = + request_mem_region(phyiface_res->start, + resource_size(phyiface_res), + phyiface_res->name); + + if (!ksp->phyiface_req) { + dev_err(ksp->dev, + "cannot claim switch register space\n"); + ret = -EIO; + goto failure; + } + + ksp->phyiface_regs = ioremap(phyiface_res->start, + resource_size(phyiface_res)); + + if (!ksp->phyiface_regs) { + dev_err(ksp->dev, + "failed to ioremap switch registers\n"); + ret = -EINVAL; + goto failure; + } + } + + ksp->rx_irq = rxirq_res->start; + ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX"; + ksp->tx_irq = txirq_res->start; + ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX"; + ksp->link_irq = (linkirq_res ? linkirq_res->start : -1); + ksp->link_irq_name = (linkirq_res && linkirq_res->name) ? + linkirq_res->name : "Ethernet Link"; + + /* driver system setup */ + ndev->netdev_ops = &ks8695_netdev_ops; + ndev->watchdog_timeo = msecs_to_jiffies(watchdog); + + netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); + + /* Retrieve the default MAC addr from the chip. */ + /* The bootloader should have left it in there for us. */ + + machigh = ks8695_readreg(ksp, KS8695_MAH); + maclow = ks8695_readreg(ksp, KS8695_MAL); + + ndev->dev_addr[0] = (machigh >> 8) & 0xFF; + ndev->dev_addr[1] = machigh & 0xFF; + ndev->dev_addr[2] = (maclow >> 24) & 0xFF; + ndev->dev_addr[3] = (maclow >> 16) & 0xFF; + ndev->dev_addr[4] = (maclow >> 8) & 0xFF; + ndev->dev_addr[5] = maclow & 0xFF; + + if (!is_valid_ether_addr(ndev->dev_addr)) + dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); + + /* In order to be efficient memory-wise, we allocate both + * rings in one go. + */ + ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE, + &ksp->ring_base_dma, GFP_KERNEL); + if (!ksp->ring_base) { + ret = -ENOMEM; + goto failure; + } + + /* Specify the TX DMA ring buffer */ + ksp->tx_ring = ksp->ring_base; + ksp->tx_ring_dma = ksp->ring_base_dma; + + /* And initialise the queue's lock */ + spin_lock_init(&ksp->txq_lock); + spin_lock_init(&ksp->rx_lock); + + /* Specify the RX DMA ring buffer */ + ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE; + ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE; + + /* Zero the descriptor rings */ + memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE); + memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE); + + /* Build the rings */ + for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { + ksp->tx_ring[buff_n].next_desc = + cpu_to_le32(ksp->tx_ring_dma + + (sizeof(struct tx_ring_desc) * + ((buff_n + 1) & MAX_TX_DESC_MASK))); + } + + for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { + ksp->rx_ring[buff_n].next_desc = + cpu_to_le32(ksp->rx_ring_dma + + (sizeof(struct rx_ring_desc) * + ((buff_n + 1) & MAX_RX_DESC_MASK))); + } + + /* Initialise the port (physically) */ + if (ksp->phyiface_regs && ksp->link_irq == -1) { + ks8695_init_switch(ksp); + ksp->dtype = KS8695_DTYPE_LAN; + SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); + } else if (ksp->phyiface_regs && ksp->link_irq != -1) { + ks8695_init_wan_phy(ksp); + ksp->dtype = KS8695_DTYPE_WAN; + SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); + } else { + /* No initialisation since HPNA does not have a PHY */ + ksp->dtype = KS8695_DTYPE_HPNA; + SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); + } + + /* And bring up the net_device with the net core */ + platform_set_drvdata(pdev, ndev); + ret = register_netdev(ndev); + + if (ret == 0) { + dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n", + ks8695_port_type(ksp), ndev->dev_addr); + } else { + /* Report the failure to register the net_device */ + dev_err(ksp->dev, "ks8695net: failed to register netdev.\n"); + goto failure; + } + + /* All is well */ + return 0; + + /* Error exit path */ + failure: + ks8695_release_device(ksp); + free_netdev(ndev); + + return ret; + } + + /** + * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device. + * @pdev: The device to suspend + * @state: The suspend state + * + * This routine detaches and shuts down a KS8695 ethernet device. + */ + static int + ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state) + { + struct net_device *ndev = platform_get_drvdata(pdev); + struct ks8695_priv *ksp = netdev_priv(ndev); + + ksp->in_suspend = 1; + + if (netif_running(ndev)) { + netif_device_detach(ndev); + ks8695_shutdown(ksp); + } + + return 0; + } + + /** + * ks8695_drv_resume - Resume a KS8695 ethernet platform device. + * @pdev: The device to resume + * + * This routine re-initialises and re-attaches a KS8695 ethernet + * device. + */ + static int + ks8695_drv_resume(struct platform_device *pdev) + { + struct net_device *ndev = platform_get_drvdata(pdev); + struct ks8695_priv *ksp = netdev_priv(ndev); + + if (netif_running(ndev)) { + ks8695_reset(ksp); + ks8695_init_net(ksp); + ks8695_set_multicast(ndev); + netif_device_attach(ndev); + } + + ksp->in_suspend = 0; + + return 0; + } + + /** + * ks8695_drv_remove - Remove a KS8695 net device on driver unload. + * @pdev: The platform device to remove + * + * This unregisters and releases a KS8695 ethernet device. + */ + static int __devexit + ks8695_drv_remove(struct platform_device *pdev) + { + struct net_device *ndev = platform_get_drvdata(pdev); + struct ks8695_priv *ksp = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + netif_napi_del(&ksp->napi); + + unregister_netdev(ndev); + ks8695_release_device(ksp); + free_netdev(ndev); + + dev_dbg(&pdev->dev, "released and freed device\n"); + return 0; + } + + static struct platform_driver ks8695_driver = { + .driver = { + .name = MODULENAME, + .owner = THIS_MODULE, + }, + .probe = ks8695_probe, + .remove = __devexit_p(ks8695_drv_remove), + .suspend = ks8695_drv_suspend, + .resume = ks8695_drv_resume, + }; + + /* Module interface */ + + static int __init + ks8695_init(void) + { + printk(KERN_INFO "%s Ethernet driver, V%s\n", + MODULENAME, MODULEVERSION); + + return platform_driver_register(&ks8695_driver); + } + + static void __exit + ks8695_cleanup(void) + { + platform_driver_unregister(&ks8695_driver); + } + + module_init(ks8695_init); + module_exit(ks8695_cleanup); + + MODULE_AUTHOR("Simtec Electronics"); + MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:" MODULENAME); + + module_param(watchdog, int, 0400); + MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); diff --cc drivers/net/ethernet/smsc/Kconfig index 000000000000,1854c88dfb92..5a689af516e9 mode 000000,100644..100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@@ -1,0 -1,137 +1,136 @@@ + # + # Western Digital/SMC network device configuration + # + + config NET_VENDOR_SMSC + bool "SMC (SMSC)/Western Digital devices" + default y + depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \ + BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about SMC/Western Digital cards. If you say Y, you will + be asked for your specific card in the following questions. + + if NET_VENDOR_SMSC + + config SMC9194 + tristate "SMC 9194 support" + depends on (ISA || MAC && BROKEN) + select CRC32 + ---help--- + This is support for the SMC9xxx based Ethernet cards. Choose this + option if you have a DELL laptop with the docking station, or + another SMC9192/9194 based chipset. Say Y if you want it compiled + into the kernel, and read the file + and the Ethernet-HOWTO, + available from . + + To compile this driver as a module, choose M here. The module + will be called smc9194. + + config SMC91X + tristate "SMC 91C9x/91C1xxx support" + select CRC32 + select NET_CORE + select MII + depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \ + MN10300 || COLDFIRE) + ---help--- + This is a driver for SMC's 91x series of Ethernet chipsets, + including the SMC91C94 and the SMC91C111. Say Y if you want it + compiled into the kernel, and read the file + and the Ethernet-HOWTO, + available from . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called smc91x. If you want to compile it as a + module, say M here and read . + + config PCMCIA_SMC91C92 + tristate "SMC 91Cxx PCMCIA support" + depends on PCMCIA + select CRC32 + select NET_CORE + select MII + ---help--- + Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA + (PC-card) Ethernet or Fast Ethernet card to your computer. + + To compile this driver as a module, choose M here: the module will be + called smc91c92_cs. If unsure, say N. + + config EPIC100 + tristate "SMC EtherPower II" + depends on PCI + select CRC32 + select NET_CORE + select MII + ---help--- + This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC, + which is based on the SMC83c17x (EPIC/100). + More specific information and updates are available from + . + + config SMC911X + tristate "SMSC LAN911[5678] support" + select CRC32 + select NET_CORE + select MII + depends on (ARM || SUPERH || MN10300) + ---help--- + This is a driver for SMSC's LAN911x series of Ethernet chipsets + including the new LAN9115, LAN9116, LAN9117, and LAN9118. + Say Y if you want it compiled into the kernel, + and read the Ethernet-HOWTO, available from + . + + This driver is also available as a module. The module will be + called smc911x. If you want to compile it as a module, say M + here and read + + config SMSC911X + tristate "SMSC LAN911x/LAN921x families embedded ethernet support" + depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300) + select CRC32 + select NET_CORE + select MII + select PHYLIB + ---help--- + Say Y here if you want support for SMSC LAN911x and LAN921x families + of ethernet controllers. + - To compile this driver as a module, choose M here and read - . The module ++ To compile this driver as a module, choose M here. The module + will be called smsc911x. + + config SMSC911X_ARCH_HOOKS + def_bool n + depends on SMSC911X + ---help--- + If the arch enables this, it allows the arch to implement various + hooks for more comprehensive interrupt control and also to override + the source of the MAC address. + + config SMSC9420 + tristate "SMSC LAN9420 PCI ethernet adapter support" + depends on PCI + select CRC32 + select PHYLIB + select SMSC_PHY + ---help--- + This is a driver for SMSC's LAN9420 PCI ethernet adapter. + Say Y if you want it compiled into the kernel, + and read the Ethernet-HOWTO, available from + . + + This driver is also available as a module. The module will be + called smsc9420. If you want to compile it as a module, say M + here and read + + endif # NET_VENDOR_SMSC diff --cc drivers/net/ethernet/tile/tilepro.c index 000000000000,78e3fb226cce..10826d8a2a2d mode 000000,100644..100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@@ -1,0 -1,2465 +1,2465 @@@ + /* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + + #include + #include + #include + #include + #include /* printk() */ + #include /* kmalloc() */ + #include /* error codes */ + #include /* size_t */ + #include + #include + #include /* struct device, and other headers */ + #include /* eth_type_trans */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + + /* For TSO */ + #include + #include + + + /* + * First, "tile_net_init_module()" initializes all four "devices" which + * can be used by linux. + * + * Then, "ifconfig DEVICE up" calls "tile_net_open()", which analyzes + * the network cpus, then uses "tile_net_open_aux()" to initialize + * LIPP/LEPP, and then uses "tile_net_open_inner()" to register all + * the tiles, provide buffers to LIPP, allow ingress to start, and + * turn on hypervisor interrupt handling (and NAPI) on all tiles. + * + * If registration fails due to the link being down, then "retry_work" + * is used to keep calling "tile_net_open_inner()" until it succeeds. + * + * If "ifconfig DEVICE down" is called, it uses "tile_net_stop()" to + * stop egress, drain the LIPP buffers, unregister all the tiles, stop + * LIPP/LEPP, and wipe the LEPP queue. + * + * We start out with the ingress interrupt enabled on each CPU. When + * this interrupt fires, we disable it, and call "napi_schedule()". + * This will cause "tile_net_poll()" to be called, which will pull + * packets from the netio queue, filtering them out, or passing them + * to "netif_receive_skb()". If our budget is exhausted, we will + * return, knowing we will be called again later. Otherwise, we + * reenable the ingress interrupt, and call "napi_complete()". + * + * HACK: Since disabling the ingress interrupt is not reliable, we + * ignore the interrupt if the global "active" flag is false. + * + * + * NOTE: The use of "native_driver" ensures that EPP exists, and that + * we are using "LIPP" and "LEPP". + * + * NOTE: Failing to free completions for an arbitrarily long time + * (which is defined to be illegal) does in fact cause bizarre + * problems. The "egress_timer" helps prevent this from happening. + */ + + + /* HACK: Allow use of "jumbo" packets. */ + /* This should be 1500 if "jumbo" is not set in LIPP. */ + /* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */ + /* ISSUE: This has not been thoroughly tested (except at 1500). */ + #define TILE_NET_MTU 1500 + + /* HACK: Define to support GSO. */ + /* ISSUE: This may actually hurt performance of the TCP blaster. */ + /* #define TILE_NET_GSO */ + + /* Define this to collapse "duplicate" acks. */ + /* #define IGNORE_DUP_ACKS */ + + /* HACK: Define this to verify incoming packets. */ + /* #define TILE_NET_VERIFY_INGRESS */ + + /* Use 3000 to enable the Linux Traffic Control (QoS) layer, else 0. */ + #define TILE_NET_TX_QUEUE_LEN 0 + + /* Define to dump packets (prints out the whole packet on tx and rx). */ + /* #define TILE_NET_DUMP_PACKETS */ + + /* Define to enable debug spew (all PDEBUG's are enabled). */ + /* #define TILE_NET_DEBUG */ + + + /* Define to activate paranoia checks. */ + /* #define TILE_NET_PARANOIA */ + + /* Default transmit lockup timeout period, in jiffies. */ + #define TILE_NET_TIMEOUT (5 * HZ) + + /* Default retry interval for bringing up the NetIO interface, in jiffies. */ + #define TILE_NET_RETRY_INTERVAL (5 * HZ) + + /* Number of ports (xgbe0, xgbe1, gbe0, gbe1). */ + #define TILE_NET_DEVS 4 + + + + /* Paranoia. */ + #if NET_IP_ALIGN != LIPP_PACKET_PADDING + #error "NET_IP_ALIGN must match LIPP_PACKET_PADDING." + #endif + + + /* Debug print. */ + #ifdef TILE_NET_DEBUG + #define PDEBUG(fmt, args...) net_printk(fmt, ## args) + #else + #define PDEBUG(fmt, args...) + #endif + + + MODULE_AUTHOR("Tilera"); + MODULE_LICENSE("GPL"); + + + /* + * Queue of incoming packets for a specific cpu and device. + * + * Includes a pointer to the "system" data, and the actual "user" data. + */ + struct tile_netio_queue { + netio_queue_impl_t *__system_part; + netio_queue_user_impl_t __user_part; + + }; + + + /* + * Statistics counters for a specific cpu and device. + */ + struct tile_net_stats_t { + u32 rx_packets; + u32 rx_bytes; + u32 tx_packets; + u32 tx_bytes; + }; + + + /* + * Info for a specific cpu and device. + * + * ISSUE: There is a "dev" pointer in "napi" as well. + */ + struct tile_net_cpu { + /* The NAPI struct. */ + struct napi_struct napi; + /* Packet queue. */ + struct tile_netio_queue queue; + /* Statistics. */ + struct tile_net_stats_t stats; + /* True iff NAPI is enabled. */ + bool napi_enabled; - /* True if this tile has succcessfully registered with the IPP. */ ++ /* True if this tile has successfully registered with the IPP. */ + bool registered; + /* True if the link was down last time we tried to register. */ + bool link_down; + /* True if "egress_timer" is scheduled. */ + bool egress_timer_scheduled; + /* Number of small sk_buffs which must still be provided. */ + unsigned int num_needed_small_buffers; + /* Number of large sk_buffs which must still be provided. */ + unsigned int num_needed_large_buffers; + /* A timer for handling egress completions. */ + struct timer_list egress_timer; + }; + + + /* + * Info for a specific device. + */ + struct tile_net_priv { + /* Our network device. */ + struct net_device *dev; + /* Pages making up the egress queue. */ + struct page *eq_pages; + /* Address of the actual egress queue. */ + lepp_queue_t *eq; + /* Protects "eq". */ + spinlock_t eq_lock; + /* The hypervisor handle for this interface. */ + int hv_devhdl; + /* The intr bit mask that IDs this device. */ + u32 intr_id; + /* True iff "tile_net_open_aux()" has succeeded. */ + bool partly_opened; + /* True iff the device is "active". */ + bool active; + /* Effective network cpus. */ + struct cpumask network_cpus_map; + /* Number of network cpus. */ + int network_cpus_count; + /* Credits per network cpu. */ + int network_cpus_credits; + /* Network stats. */ + struct net_device_stats stats; + /* For NetIO bringup retries. */ + struct delayed_work retry_work; + /* Quick access to per cpu data. */ + struct tile_net_cpu *cpu[NR_CPUS]; + }; + + /* Log2 of the number of small pages needed for the egress queue. */ + #define EQ_ORDER get_order(sizeof(lepp_queue_t)) + /* Size of the egress queue's pages. */ + #define EQ_SIZE (1 << (PAGE_SHIFT + EQ_ORDER)) + + /* + * The actual devices (xgbe0, xgbe1, gbe0, gbe1). + */ + static struct net_device *tile_net_devs[TILE_NET_DEVS]; + + /* + * The "tile_net_cpu" structures for each device. + */ + static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe0); + static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe1); + static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe0); + static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe1); + + + /* + * True if "network_cpus" was specified. + */ + static bool network_cpus_used; + + /* + * The actual cpus in "network_cpus". + */ + static struct cpumask network_cpus_map; + + + + #ifdef TILE_NET_DEBUG + /* + * printk with extra stuff. + * + * We print the CPU we're running in brackets. + */ + static void net_printk(char *fmt, ...) + { + int i; + int len; + va_list args; + static char buf[256]; + + len = sprintf(buf, "tile_net[%2.2d]: ", smp_processor_id()); + va_start(args, fmt); + i = vscnprintf(buf + len, sizeof(buf) - len - 1, fmt, args); + va_end(args); + buf[255] = '\0'; + pr_notice(buf); + } + #endif + + + #ifdef TILE_NET_DUMP_PACKETS + /* + * Dump a packet. + */ + static void dump_packet(unsigned char *data, unsigned long length, char *s) + { + int my_cpu = smp_processor_id(); + + unsigned long i; + char buf[128]; + + static unsigned int count; + + pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n", + data, length, s, count++); + + pr_info("\n"); + + for (i = 0; i < length; i++) { + if ((i & 0xf) == 0) + sprintf(buf, "[%02d] %8.8lx:", my_cpu, i); + sprintf(buf + strlen(buf), " %2.2x", data[i]); + if ((i & 0xf) == 0xf || i == length - 1) { + strcat(buf, "\n"); + pr_info("%s", buf); + } + } + } + #endif + + + /* + * Provide support for the __netio_fastio1() swint + * (see for how it is used). + * + * The fastio swint2 call may clobber all the caller-saved registers. + * It rarely clobbers memory, but we allow for the possibility in + * the signature just to be on the safe side. + * + * Also, gcc doesn't seem to allow an input operand to be + * clobbered, so we fake it with dummy outputs. + * + * This function can't be static because of the way it is declared + * in the netio header. + */ + inline int __netio_fastio1(u32 fastio_index, u32 arg0) + { + long result, clobber_r1, clobber_r10; + asm volatile("swint2" + : "=R00" (result), + "=R01" (clobber_r1), "=R10" (clobber_r10) + : "R10" (fastio_index), "R01" (arg0) + : "memory", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9", + "r11", "r12", "r13", "r14", + "r15", "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", "r24", + "r25", "r26", "r27", "r28", "r29"); + return result; + } + + + /* + * Provide a linux buffer to LIPP. + */ + static void tile_net_provide_linux_buffer(struct tile_net_cpu *info, + void *va, bool small) + { + struct tile_netio_queue *queue = &info->queue; + + /* Convert "va" and "small" to "linux_buffer_t". */ + unsigned int buffer = ((unsigned int)(__pa(va) >> 7) << 1) + small; + + __netio_fastio_free_buffer(queue->__user_part.__fastio_index, buffer); + } + + + /* + * Provide a linux buffer for LIPP. + * + * Note that the ACTUAL allocation for each buffer is a "struct sk_buff", + * plus a chunk of memory that includes not only the requested bytes, but + * also NET_SKB_PAD bytes of initial padding, and a "struct skb_shared_info". + * + * Note that "struct skb_shared_info" is 88 bytes with 64K pages and + * 268 bytes with 4K pages (since the frags[] array needs 18 entries). + * + * Without jumbo packets, the maximum packet size will be 1536 bytes, + * and we use 2 bytes (NET_IP_ALIGN) of padding. ISSUE: If we told + * the hardware to clip at 1518 bytes instead of 1536 bytes, then we + * could save an entire cache line, but in practice, we don't need it. + * + * Since CPAs are 38 bits, and we can only encode the high 31 bits in + * a "linux_buffer_t", the low 7 bits must be zero, and thus, we must + * align the actual "va" mod 128. + * + * We assume that the underlying "head" will be aligned mod 64. Note + * that in practice, we have seen "head" NOT aligned mod 128 even when + * using 2048 byte allocations, which is surprising. + * + * If "head" WAS always aligned mod 128, we could change LIPP to + * assume that the low SIX bits are zero, and the 7th bit is one, that + * is, align the actual "va" mod 128 plus 64, which would be "free". + * + * For now, the actual "head" pointer points at NET_SKB_PAD bytes of + * padding, plus 28 or 92 bytes of extra padding, plus the sk_buff + * pointer, plus the NET_IP_ALIGN padding, plus 126 or 1536 bytes for + * the actual packet, plus 62 bytes of empty padding, plus some + * padding and the "struct skb_shared_info". + * + * With 64K pages, a large buffer thus needs 32+92+4+2+1536+62+88 + * bytes, or 1816 bytes, which fits comfortably into 2048 bytes. + * + * With 64K pages, a small buffer thus needs 32+92+4+2+126+88 + * bytes, or 344 bytes, which means we are wasting 64+ bytes, and + * could presumably increase the size of small buffers. + * + * With 4K pages, a large buffer thus needs 32+92+4+2+1536+62+268 + * bytes, or 1996 bytes, which fits comfortably into 2048 bytes. + * + * With 4K pages, a small buffer thus needs 32+92+4+2+126+268 + * bytes, or 524 bytes, which is annoyingly wasteful. + * + * Maybe we should increase LIPP_SMALL_PACKET_SIZE to 192? + * + * ISSUE: Maybe we should increase "NET_SKB_PAD" to 64? + */ + static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info, + bool small) + { + #if TILE_NET_MTU <= 1536 + /* Without "jumbo", 2 + 1536 should be sufficient. */ + unsigned int large_size = NET_IP_ALIGN + 1536; + #else + /* ISSUE: This has not been tested. */ + unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100; + #endif + + /* Avoid "false sharing" with last cache line. */ + /* ISSUE: This is already done by "dev_alloc_skb()". */ + unsigned int len = + (((small ? LIPP_SMALL_PACKET_SIZE : large_size) + + CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE()); + + unsigned int padding = 128 - NET_SKB_PAD; + unsigned int align; + + struct sk_buff *skb; + void *va; + + struct sk_buff **skb_ptr; + + /* Request 96 extra bytes for alignment purposes. */ + skb = dev_alloc_skb(len + padding); + if (skb == NULL) + return false; + + /* Skip 32 or 96 bytes to align "data" mod 128. */ + align = -(long)skb->data & (128 - 1); + BUG_ON(align > padding); + skb_reserve(skb, align); + + /* This address is given to IPP. */ + va = skb->data; + + /* Buffers must not span a huge page. */ + BUG_ON(((((long)va & ~HPAGE_MASK) + len) & HPAGE_MASK) != 0); + + #ifdef TILE_NET_PARANOIA + #if CHIP_HAS_CBOX_HOME_MAP() + if (hash_default) { + HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va); + if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3) + panic("Non-HFH ingress buffer! VA=%p Mode=%d PTE=%llx", + va, hv_pte_get_mode(pte), hv_pte_val(pte)); + } + #endif + #endif + + /* Invalidate the packet buffer. */ + if (!hash_default) + __inv_buffer(va, len); + + /* Skip two bytes to satisfy LIPP assumptions. */ + /* Note that this aligns IP on a 16 byte boundary. */ + /* ISSUE: Do this when the packet arrives? */ + skb_reserve(skb, NET_IP_ALIGN); + + /* Save a back-pointer to 'skb'. */ + skb_ptr = va - sizeof(*skb_ptr); + *skb_ptr = skb; + + /* Make sure "skb_ptr" has been flushed. */ + __insn_mf(); + + /* Provide the new buffer. */ + tile_net_provide_linux_buffer(info, va, small); + + return true; + } + + + /* + * Provide linux buffers for LIPP. + */ + static void tile_net_provide_needed_buffers(struct tile_net_cpu *info) + { + while (info->num_needed_small_buffers != 0) { + if (!tile_net_provide_needed_buffer(info, true)) + goto oops; + info->num_needed_small_buffers--; + } + + while (info->num_needed_large_buffers != 0) { + if (!tile_net_provide_needed_buffer(info, false)) + goto oops; + info->num_needed_large_buffers--; + } + + return; + + oops: + + /* Add a description to the page allocation failure dump. */ + pr_notice("Could not provide a linux buffer to LIPP.\n"); + } + + + /* + * Grab some LEPP completions, and store them in "comps", of size + * "comps_size", and return the number of completions which were + * stored, so the caller can free them. + */ + static unsigned int tile_net_lepp_grab_comps(lepp_queue_t *eq, + struct sk_buff *comps[], + unsigned int comps_size, + unsigned int min_size) + { + unsigned int n = 0; + + unsigned int comp_head = eq->comp_head; + unsigned int comp_busy = eq->comp_busy; + + while (comp_head != comp_busy && n < comps_size) { + comps[n++] = eq->comps[comp_head]; + LEPP_QINC(comp_head); + } + + if (n < min_size) + return 0; + + eq->comp_head = comp_head; + + return n; + } + + + /* + * Free some comps, and return true iff there are still some pending. + */ + static bool tile_net_lepp_free_comps(struct net_device *dev, bool all) + { + struct tile_net_priv *priv = netdev_priv(dev); + + lepp_queue_t *eq = priv->eq; + + struct sk_buff *olds[64]; + unsigned int wanted = 64; + unsigned int i, n; + bool pending; + + spin_lock(&priv->eq_lock); + + if (all) + eq->comp_busy = eq->comp_tail; + + n = tile_net_lepp_grab_comps(eq, olds, wanted, 0); + + pending = (eq->comp_head != eq->comp_tail); + + spin_unlock(&priv->eq_lock); + + for (i = 0; i < n; i++) + kfree_skb(olds[i]); + + return pending; + } + + + /* + * Make sure the egress timer is scheduled. + * + * Note that we use "schedule if not scheduled" logic instead of the more + * obvious "reschedule" logic, because "reschedule" is fairly expensive. + */ + static void tile_net_schedule_egress_timer(struct tile_net_cpu *info) + { + if (!info->egress_timer_scheduled) { + mod_timer_pinned(&info->egress_timer, jiffies + 1); + info->egress_timer_scheduled = true; + } + } + + + /* + * The "function" for "info->egress_timer". + * + * This timer will reschedule itself as long as there are any pending + * completions expected (on behalf of any tile). + * + * ISSUE: Realistically, will the timer ever stop scheduling itself? + * + * ISSUE: This timer is almost never actually needed, so just use a global + * timer that can run on any tile. + * + * ISSUE: Maybe instead track number of expected completions, and free + * only that many, resetting to zero if "pending" is ever false. + */ + static void tile_net_handle_egress_timer(unsigned long arg) + { + struct tile_net_cpu *info = (struct tile_net_cpu *)arg; + struct net_device *dev = info->napi.dev; + + /* The timer is no longer scheduled. */ + info->egress_timer_scheduled = false; + + /* Free comps, and reschedule timer if more are pending. */ + if (tile_net_lepp_free_comps(dev, false)) + tile_net_schedule_egress_timer(info); + } + + + #ifdef IGNORE_DUP_ACKS + + /* + * Help detect "duplicate" ACKs. These are sequential packets (for a + * given flow) which are exactly 66 bytes long, sharing everything but + * ID=2@0x12, Hsum=2@0x18, Ack=4@0x2a, WinSize=2@0x30, Csum=2@0x32, + * Tstamps=10@0x38. The ID's are +1, the Hsum's are -1, the Ack's are + * +N, and the Tstamps are usually identical. + * + * NOTE: Apparently truly duplicate acks (with identical "ack" values), + * should not be collapsed, as they are used for some kind of flow control. + */ + static bool is_dup_ack(char *s1, char *s2, unsigned int len) + { + int i; + + unsigned long long ignorable = 0; + + /* Identification. */ + ignorable |= (1ULL << 0x12); + ignorable |= (1ULL << 0x13); + + /* Header checksum. */ + ignorable |= (1ULL << 0x18); + ignorable |= (1ULL << 0x19); + + /* ACK. */ + ignorable |= (1ULL << 0x2a); + ignorable |= (1ULL << 0x2b); + ignorable |= (1ULL << 0x2c); + ignorable |= (1ULL << 0x2d); + + /* WinSize. */ + ignorable |= (1ULL << 0x30); + ignorable |= (1ULL << 0x31); + + /* Checksum. */ + ignorable |= (1ULL << 0x32); + ignorable |= (1ULL << 0x33); + + for (i = 0; i < len; i++, ignorable >>= 1) { + + if ((ignorable & 1) || (s1[i] == s2[i])) + continue; + + #ifdef TILE_NET_DEBUG + /* HACK: Mention non-timestamp diffs. */ + if (i < 0x38 && i != 0x2f && + net_ratelimit()) + pr_info("Diff at 0x%x\n", i); + #endif + + return false; + } + + #ifdef TILE_NET_NO_SUPPRESS_DUP_ACKS + /* HACK: Do not suppress truly duplicate ACKs. */ + /* ISSUE: Is this actually necessary or helpful? */ + if (s1[0x2a] == s2[0x2a] && + s1[0x2b] == s2[0x2b] && + s1[0x2c] == s2[0x2c] && + s1[0x2d] == s2[0x2d]) { + return false; + } + #endif + + return true; + } + + #endif + + + + static void tile_net_discard_aux(struct tile_net_cpu *info, int index) + { + struct tile_netio_queue *queue = &info->queue; + netio_queue_impl_t *qsp = queue->__system_part; + netio_queue_user_impl_t *qup = &queue->__user_part; + + int index2_aux = index + sizeof(netio_pkt_t); + int index2 = + ((index2_aux == + qsp->__packet_receive_queue.__last_packet_plus_one) ? + 0 : index2_aux); + + netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index); + + /* Extract the "linux_buffer_t". */ + unsigned int buffer = pkt->__packet.word; + + /* Convert "linux_buffer_t" to "va". */ + void *va = __va((phys_addr_t)(buffer >> 1) << 7); + + /* Acquire the associated "skb". */ + struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); + struct sk_buff *skb = *skb_ptr; + + kfree_skb(skb); + + /* Consume this packet. */ + qup->__packet_receive_read = index2; + } + + + /* + * Like "tile_net_poll()", but just discard packets. + */ + static void tile_net_discard_packets(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + struct tile_netio_queue *queue = &info->queue; + netio_queue_impl_t *qsp = queue->__system_part; + netio_queue_user_impl_t *qup = &queue->__user_part; + + while (qup->__packet_receive_read != + qsp->__packet_receive_queue.__packet_write) { + int index = qup->__packet_receive_read; + tile_net_discard_aux(info, index); + } + } + + + /* + * Handle the next packet. Return true if "processed", false if "filtered". + */ + static bool tile_net_poll_aux(struct tile_net_cpu *info, int index) + { + struct net_device *dev = info->napi.dev; + + struct tile_netio_queue *queue = &info->queue; + netio_queue_impl_t *qsp = queue->__system_part; + netio_queue_user_impl_t *qup = &queue->__user_part; + struct tile_net_stats_t *stats = &info->stats; + + int filter; + + int index2_aux = index + sizeof(netio_pkt_t); + int index2 = + ((index2_aux == + qsp->__packet_receive_queue.__last_packet_plus_one) ? + 0 : index2_aux); + + netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index); + + netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt); + + /* Extract the packet size. FIXME: Shouldn't the second line */ + /* get subtracted? Mostly moot, since it should be "zero". */ + unsigned long len = + (NETIO_PKT_CUSTOM_LENGTH(pkt) + + NET_IP_ALIGN - NETIO_PACKET_PADDING); + + /* Extract the "linux_buffer_t". */ + unsigned int buffer = pkt->__packet.word; + + /* Extract "small" (vs "large"). */ + bool small = ((buffer & 1) != 0); + + /* Convert "linux_buffer_t" to "va". */ + void *va = __va((phys_addr_t)(buffer >> 1) << 7); + + /* Extract the packet data pointer. */ + /* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */ + unsigned char *buf = va + NET_IP_ALIGN; + + /* Invalidate the packet buffer. */ + if (!hash_default) + __inv_buffer(buf, len); + + /* ISSUE: Is this needed? */ + dev->last_rx = jiffies; + + #ifdef TILE_NET_DUMP_PACKETS + dump_packet(buf, len, "rx"); + #endif /* TILE_NET_DUMP_PACKETS */ + + #ifdef TILE_NET_VERIFY_INGRESS + if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) && + NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) { + /* Bug 6624: Includes UDP packets with a "zero" checksum. */ + pr_warning("Bad L4 checksum on %d byte packet.\n", len); + } + if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) && + NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) { + dump_packet(buf, len, "rx"); + panic("Bad L3 checksum."); + } + switch (NETIO_PKT_STATUS_M(metadata, pkt)) { + case NETIO_PKT_STATUS_OVERSIZE: + if (len >= 64) { + dump_packet(buf, len, "rx"); + panic("Unexpected OVERSIZE."); + } + break; + case NETIO_PKT_STATUS_BAD: + pr_warning("Unexpected BAD %ld byte packet.\n", len); + } + #endif + + filter = 0; + + /* ISSUE: Filter TCP packets with "bad" checksums? */ + + if (!(dev->flags & IFF_UP)) { + /* Filter packets received before we're up. */ + filter = 1; + } else if (NETIO_PKT_STATUS_M(metadata, pkt) == NETIO_PKT_STATUS_BAD) { + /* Filter "truncated" packets. */ + filter = 1; + } else if (!(dev->flags & IFF_PROMISC)) { + /* FIXME: Implement HW multicast filter. */ + if (!is_multicast_ether_addr(buf)) { + /* Filter packets not for our address. */ + const u8 *mine = dev->dev_addr; + filter = compare_ether_addr(mine, buf); + } + } + + if (filter) { + + /* ISSUE: Update "drop" statistics? */ + + tile_net_provide_linux_buffer(info, va, small); + + } else { + + /* Acquire the associated "skb". */ + struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); + struct sk_buff *skb = *skb_ptr; + + /* Paranoia. */ + if (skb->data != buf) + panic("Corrupt linux buffer from LIPP! " + "VA=%p, skb=%p, skb->data=%p\n", + va, skb, skb->data); + + /* Encode the actual packet length. */ + skb_put(skb, len); + + /* NOTE: This call also sets "skb->dev = dev". */ + skb->protocol = eth_type_trans(skb, dev); + + /* Avoid recomputing "good" TCP/UDP checksums. */ + if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + netif_receive_skb(skb); + + stats->rx_packets++; + stats->rx_bytes += len; + + if (small) + info->num_needed_small_buffers++; + else + info->num_needed_large_buffers++; + } + + /* Return four credits after every fourth packet. */ + if (--qup->__receive_credit_remaining == 0) { + u32 interval = qup->__receive_credit_interval; + qup->__receive_credit_remaining = interval; + __netio_fastio_return_credits(qup->__fastio_index, interval); + } + + /* Consume this packet. */ + qup->__packet_receive_read = index2; + + return !filter; + } + + + /* + * Handle some packets for the given device on the current CPU. + * + * If "tile_net_stop()" is called on some other tile while this + * function is running, we will return, hopefully before that + * other tile asks us to call "napi_disable()". + * + * The "rotting packet" race condition occurs if a packet arrives + * during the extremely narrow window between the queue appearing to + * be empty, and the ingress interrupt being re-enabled. This happens + * a LOT under heavy network load. + */ + static int tile_net_poll(struct napi_struct *napi, int budget) + { + struct net_device *dev = napi->dev; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + struct tile_netio_queue *queue = &info->queue; + netio_queue_impl_t *qsp = queue->__system_part; + netio_queue_user_impl_t *qup = &queue->__user_part; + + unsigned int work = 0; + + while (priv->active) { + int index = qup->__packet_receive_read; + if (index == qsp->__packet_receive_queue.__packet_write) + break; + + if (tile_net_poll_aux(info, index)) { + if (++work >= budget) + goto done; + } + } + + napi_complete(&info->napi); + + if (!priv->active) + goto done; + + /* Re-enable the ingress interrupt. */ + enable_percpu_irq(priv->intr_id); + + /* HACK: Avoid the "rotting packet" problem (see above). */ + if (qup->__packet_receive_read != + qsp->__packet_receive_queue.__packet_write) { + /* ISSUE: Sometimes this returns zero, presumably */ + /* because an interrupt was handled for this tile. */ + (void)napi_reschedule(&info->napi); + } + + done: + + if (priv->active) + tile_net_provide_needed_buffers(info); + + return work; + } + + + /* + * Handle an ingress interrupt for the given device on the current cpu. + * + * ISSUE: Sometimes this gets called after "disable_percpu_irq()" has + * been called! This is probably due to "pending hypervisor downcalls". + * + * ISSUE: Is there any race condition between the "napi_schedule()" here + * and the "napi_complete()" call above? + */ + static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + + /* Disable the ingress interrupt. */ + disable_percpu_irq(priv->intr_id); + + /* Ignore unwanted interrupts. */ + if (!priv->active) + return IRQ_HANDLED; + + /* ISSUE: Sometimes "info->napi_enabled" is false here. */ + + napi_schedule(&info->napi); + + return IRQ_HANDLED; + } + + + /* + * One time initialization per interface. + */ + static int tile_net_open_aux(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + + int ret; + int dummy; + unsigned int epp_lotar; + + /* + * Find out where EPP memory should be homed. + */ + ret = hv_dev_pread(priv->hv_devhdl, 0, + (HV_VirtAddr)&epp_lotar, sizeof(epp_lotar), + NETIO_EPP_SHM_OFF); + if (ret < 0) { + pr_err("could not read epp_shm_queue lotar.\n"); + return -EIO; + } + + /* + * Home the page on the EPP. + */ + { + int epp_home = hv_lotar_to_cpu(epp_lotar); + homecache_change_page_home(priv->eq_pages, EQ_ORDER, epp_home); + } + + /* + * Register the EPP shared memory queue. + */ + { + netio_ipp_address_t ea = { + .va = 0, + .pa = __pa(priv->eq), + .pte = hv_pte(0), + .size = EQ_SIZE, + }; + ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar); + ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3); + ret = hv_dev_pwrite(priv->hv_devhdl, 0, + (HV_VirtAddr)&ea, + sizeof(ea), + NETIO_EPP_SHM_OFF); + if (ret < 0) + return -EIO; + } + + /* + * Start LIPP/LEPP. + */ + if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, + sizeof(dummy), NETIO_IPP_START_SHIM_OFF) < 0) { + pr_warning("Failed to start LIPP/LEPP.\n"); + return -EIO; + } + + return 0; + } + + + /* + * Register with hypervisor on the current CPU. + * + * Strangely, this function does important things even if it "fails", + * which is especially common if the link is not up yet. Hopefully + * these things are all "harmless" if done twice! + */ + static void tile_net_register(void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info; + + struct tile_netio_queue *queue; + + /* Only network cpus can receive packets. */ + int queue_id = + cpumask_test_cpu(my_cpu, &priv->network_cpus_map) ? 0 : 255; + + netio_input_config_t config = { + .flags = 0, + .num_receive_packets = priv->network_cpus_credits, + .queue_id = queue_id + }; + + int ret = 0; + netio_queue_impl_t *queuep; + + PDEBUG("tile_net_register(queue_id %d)\n", queue_id); + + if (!strcmp(dev->name, "xgbe0")) + info = &__get_cpu_var(hv_xgbe0); + else if (!strcmp(dev->name, "xgbe1")) + info = &__get_cpu_var(hv_xgbe1); + else if (!strcmp(dev->name, "gbe0")) + info = &__get_cpu_var(hv_gbe0); + else if (!strcmp(dev->name, "gbe1")) + info = &__get_cpu_var(hv_gbe1); + else + BUG(); + + /* Initialize the egress timer. */ + init_timer(&info->egress_timer); + info->egress_timer.data = (long)info; + info->egress_timer.function = tile_net_handle_egress_timer; + + priv->cpu[my_cpu] = info; + + /* + * Register ourselves with LIPP. This does a lot of stuff, + * including invoking the LIPP registration code. + */ + ret = hv_dev_pwrite(priv->hv_devhdl, 0, + (HV_VirtAddr)&config, + sizeof(netio_input_config_t), + NETIO_IPP_INPUT_REGISTER_OFF); + PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n", + ret); + if (ret < 0) { + if (ret != NETIO_LINK_DOWN) { + printk(KERN_DEBUG "hv_dev_pwrite " + "NETIO_IPP_INPUT_REGISTER_OFF failure %d\n", + ret); + } + info->link_down = (ret == NETIO_LINK_DOWN); + return; + } + + /* + * Get the pointer to our queue's system part. + */ + + ret = hv_dev_pread(priv->hv_devhdl, 0, + (HV_VirtAddr)&queuep, + sizeof(netio_queue_impl_t *), + NETIO_IPP_INPUT_REGISTER_OFF); + PDEBUG("hv_dev_pread(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n", + ret); + PDEBUG("queuep %p\n", queuep); + if (ret <= 0) { + /* ISSUE: Shouldn't this be a fatal error? */ + pr_err("hv_dev_pread NETIO_IPP_INPUT_REGISTER_OFF failure\n"); + return; + } + + queue = &info->queue; + + queue->__system_part = queuep; + + memset(&queue->__user_part, 0, sizeof(netio_queue_user_impl_t)); + + /* This is traditionally "config.num_receive_packets / 2". */ + queue->__user_part.__receive_credit_interval = 4; + queue->__user_part.__receive_credit_remaining = + queue->__user_part.__receive_credit_interval; + + /* + * Get a fastio index from the hypervisor. + * ISSUE: Shouldn't this check the result? + */ + ret = hv_dev_pread(priv->hv_devhdl, 0, + (HV_VirtAddr)&queue->__user_part.__fastio_index, + sizeof(queue->__user_part.__fastio_index), + NETIO_IPP_GET_FASTIO_OFF); + PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret); + + /* Now we are registered. */ + info->registered = true; + } + + + /* + * Deregister with hypervisor on the current CPU. + * + * This simply discards all our credits, so no more packets will be + * delivered to this tile. There may still be packets in our queue. + * + * Also, disable the ingress interrupt. + */ + static void tile_net_deregister(void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + + /* Disable the ingress interrupt. */ + disable_percpu_irq(priv->intr_id); + + /* Do nothing else if not registered. */ + if (info == NULL || !info->registered) + return; + + { + struct tile_netio_queue *queue = &info->queue; + netio_queue_user_impl_t *qup = &queue->__user_part; + + /* Discard all our credits. */ + __netio_fastio_return_credits(qup->__fastio_index, -1); + } + } + + + /* + * Unregister with hypervisor on the current CPU. + * + * Also, disable the ingress interrupt. + */ + static void tile_net_unregister(void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + + int ret; + int dummy = 0; + + /* Disable the ingress interrupt. */ + disable_percpu_irq(priv->intr_id); + + /* Do nothing else if not registered. */ + if (info == NULL || !info->registered) + return; + + /* Unregister ourselves with LIPP/LEPP. */ + ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, + sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF); + if (ret < 0) + panic("Failed to unregister with LIPP/LEPP!\n"); + + /* Discard all packets still in our NetIO queue. */ + tile_net_discard_packets(dev); + + /* Reset state. */ + info->num_needed_small_buffers = 0; + info->num_needed_large_buffers = 0; + + /* Cancel egress timer. */ + del_timer(&info->egress_timer); + info->egress_timer_scheduled = false; + } + + + /* + * Helper function for "tile_net_stop()". + * + * Also used to handle registration failure in "tile_net_open_inner()", + * when the various extra steps in "tile_net_stop()" are not necessary. + */ + static void tile_net_stop_aux(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + int i; + + int dummy = 0; + + /* + * Unregister all tiles, so LIPP will stop delivering packets. + * Also, delete all the "napi" objects (sequentially, to protect + * "dev->napi_list"). + */ + on_each_cpu(tile_net_unregister, (void *)dev, 1); + for_each_online_cpu(i) { + struct tile_net_cpu *info = priv->cpu[i]; + if (info != NULL && info->registered) { + netif_napi_del(&info->napi); + info->registered = false; + } + } + + /* Stop LIPP/LEPP. */ + if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, + sizeof(dummy), NETIO_IPP_STOP_SHIM_OFF) < 0) + panic("Failed to stop LIPP/LEPP!\n"); + + priv->partly_opened = 0; + } + + + /* + * Disable NAPI for the given device on the current cpu. + */ + static void tile_net_stop_disable(void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + + /* Disable NAPI if needed. */ + if (info != NULL && info->napi_enabled) { + napi_disable(&info->napi); + info->napi_enabled = false; + } + } + + + /* + * Enable NAPI and the ingress interrupt for the given device + * on the current cpu. + * + * ISSUE: Only do this for "network cpus"? + */ + static void tile_net_open_enable(void *dev_ptr) + { + struct net_device *dev = (struct net_device *)dev_ptr; + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + + /* Enable NAPI. */ + napi_enable(&info->napi); + info->napi_enabled = true; + + /* Enable the ingress interrupt. */ + enable_percpu_irq(priv->intr_id); + } + + + /* + * tile_net_open_inner does most of the work of bringing up the interface. + * It's called from tile_net_open(), and also from tile_net_retry_open(). + * The return value is 0 if the interface was brought up, < 0 if + * tile_net_open() should return the return value as an error, and > 0 if + * tile_net_open() should return success and schedule a work item to + * periodically retry the bringup. + */ + static int tile_net_open_inner(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info; + struct tile_netio_queue *queue; + int result = 0; + int i; + int dummy = 0; + + /* + * First try to register just on the local CPU, and handle any + * semi-expected "link down" failure specially. Note that we + * do NOT call "tile_net_stop_aux()", unlike below. + */ + tile_net_register(dev); + info = priv->cpu[my_cpu]; + if (!info->registered) { + if (info->link_down) + return 1; + return -EAGAIN; + } + + /* + * Now register everywhere else. If any registration fails, + * even for "link down" (which might not be possible), we + * clean up using "tile_net_stop_aux()". Also, add all the + * "napi" objects (sequentially, to protect "dev->napi_list"). + * ISSUE: Only use "netif_napi_add()" for "network cpus"? + */ + smp_call_function(tile_net_register, (void *)dev, 1); + for_each_online_cpu(i) { + struct tile_net_cpu *info = priv->cpu[i]; + if (info->registered) + netif_napi_add(dev, &info->napi, tile_net_poll, 64); + else + result = -EAGAIN; + } + if (result != 0) { + tile_net_stop_aux(dev); + return result; + } + + queue = &info->queue; + + if (priv->intr_id == 0) { + unsigned int irq; + + /* + * Acquire the irq allocated by the hypervisor. Every + * queue gets the same irq. The "__intr_id" field is + * "1 << irq", so we use "__ffs()" to extract "irq". + */ + priv->intr_id = queue->__system_part->__intr_id; + BUG_ON(priv->intr_id == 0); + irq = __ffs(priv->intr_id); + + /* + * Register the ingress interrupt handler for this + * device, permanently. + * + * We used to call "free_irq()" in "tile_net_stop()", + * and then re-register the handler here every time, + * but that caused DNP errors in "handle_IRQ_event()" + * because "desc->action" was NULL. See bug 9143. + */ + tile_irq_activate(irq, TILE_IRQ_PERCPU); + BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt, + 0, dev->name, (void *)dev) != 0); + } + + { + /* Allocate initial buffers. */ + + int max_buffers = + priv->network_cpus_count * priv->network_cpus_credits; + + info->num_needed_small_buffers = + min(LIPP_SMALL_BUFFERS, max_buffers); + + info->num_needed_large_buffers = + min(LIPP_LARGE_BUFFERS, max_buffers); + + tile_net_provide_needed_buffers(info); + + if (info->num_needed_small_buffers != 0 || + info->num_needed_large_buffers != 0) + panic("Insufficient memory for buffer stack!"); + } + + /* We are about to be active. */ + priv->active = true; + + /* Make sure "active" is visible to all tiles. */ + mb(); + + /* On each tile, enable NAPI and the ingress interrupt. */ + on_each_cpu(tile_net_open_enable, (void *)dev, 1); + + /* Start LIPP/LEPP and activate "ingress" at the shim. */ + if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, + sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0) + panic("Failed to activate the LIPP Shim!\n"); + + /* Start our transmit queue. */ + netif_start_queue(dev); + + return 0; + } + + + /* + * Called periodically to retry bringing up the NetIO interface, + * if it doesn't come up cleanly during tile_net_open(). + */ + static void tile_net_open_retry(struct work_struct *w) + { + struct delayed_work *dw = + container_of(w, struct delayed_work, work); + + struct tile_net_priv *priv = + container_of(dw, struct tile_net_priv, retry_work); + + /* + * Try to bring the NetIO interface up. If it fails, reschedule + * ourselves to try again later; otherwise, tell Linux we now have + * a working link. ISSUE: What if the return value is negative? + */ + if (tile_net_open_inner(priv->dev) != 0) + schedule_delayed_work(&priv->retry_work, + TILE_NET_RETRY_INTERVAL); + else + netif_carrier_on(priv->dev); + } + + + /* + * Called when a network interface is made active. + * + * Returns 0 on success, negative value on failure. + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS (if needed), the watchdog timer + * is started, and the stack is notified that the interface is ready. + * + * If the actual link is not available yet, then we tell Linux that + * we have no carrier, and we keep checking until the link comes up. + */ + static int tile_net_open(struct net_device *dev) + { + int ret = 0; + struct tile_net_priv *priv = netdev_priv(dev); + + /* + * We rely on priv->partly_opened to tell us if this is the + * first time this interface is being brought up. If it is + * set, the IPP was already initialized and should not be + * initialized again. + */ + if (!priv->partly_opened) { + + int count; + int credits; + + /* Initialize LIPP/LEPP, and start the Shim. */ + ret = tile_net_open_aux(dev); + if (ret < 0) { + pr_err("tile_net_open_aux failed: %d\n", ret); + return ret; + } + + /* Analyze the network cpus. */ + + if (network_cpus_used) + cpumask_copy(&priv->network_cpus_map, + &network_cpus_map); + else + cpumask_copy(&priv->network_cpus_map, cpu_online_mask); + + + count = cpumask_weight(&priv->network_cpus_map); + + /* Limit credits to available buffers, and apply min. */ + credits = max(16, (LIPP_LARGE_BUFFERS / count) & ~1); + + /* Apply "GBE" max limit. */ + /* ISSUE: Use higher limit for XGBE? */ + credits = min(NETIO_MAX_RECEIVE_PKTS, credits); + + priv->network_cpus_count = count; + priv->network_cpus_credits = credits; + + #ifdef TILE_NET_DEBUG + pr_info("Using %d network cpus, with %d credits each\n", + priv->network_cpus_count, priv->network_cpus_credits); + #endif + + priv->partly_opened = 1; + + } else { + /* FIXME: Is this possible? */ + /* printk("Already partly opened.\n"); */ + } + + /* + * Attempt to bring up the link. + */ + ret = tile_net_open_inner(dev); + if (ret <= 0) { + if (ret == 0) + netif_carrier_on(dev); + return ret; + } + + /* + * We were unable to bring up the NetIO interface, but we want to + * try again in a little bit. Tell Linux that we have no carrier + * so it doesn't try to use the interface before the link comes up + * and then remember to try again later. + */ + netif_carrier_off(dev); + schedule_delayed_work(&priv->retry_work, TILE_NET_RETRY_INTERVAL); + + return 0; + } + + + static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv) + { + int n = 0; + + /* Drain all the LIPP buffers. */ + while (true) { + int buffer; + + /* NOTE: This should never fail. */ + if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer, + sizeof(buffer), NETIO_IPP_DRAIN_OFF) < 0) + break; + + /* Stop when done. */ + if (buffer == 0) + break; + + { + /* Convert "linux_buffer_t" to "va". */ + void *va = __va((phys_addr_t)(buffer >> 1) << 7); + + /* Acquire the associated "skb". */ + struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); + struct sk_buff *skb = *skb_ptr; + + kfree_skb(skb); + } + + n++; + } + + return n; + } + + + /* + * Disables a network interface. + * + * Returns 0, this is not allowed to fail. + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + * + * ISSUE: How closely does "netif_running(dev)" mirror "priv->active"? + * + * Before we are called by "__dev_close()", "netif_running()" will + * have been cleared, so no NEW calls to "tile_net_poll()" will be + * made by "netpoll_poll_dev()". + * + * Often, this can cause some tiles to still have packets in their + * queues, so we must call "tile_net_discard_packets()" later. + * + * Note that some other tile may still be INSIDE "tile_net_poll()", + * and in fact, many will be, if there is heavy network load. + * + * Calling "on_each_cpu(tile_net_stop_disable, (void *)dev, 1)" when + * any tile is still "napi_schedule()"'d will induce a horrible crash + * when "msleep()" is called. This includes tiles which are inside + * "tile_net_poll()" which have not yet called "napi_complete()". + * + * So, we must first try to wait long enough for other tiles to finish + * with any current "tile_net_poll()" call, and, hopefully, to clear + * the "scheduled" flag. ISSUE: It is unclear what happens to tiles + * which have called "napi_schedule()" but which had not yet tried to + * call "tile_net_poll()", or which exhausted their budget inside + * "tile_net_poll()" just before this function was called. + */ + static int tile_net_stop(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + + PDEBUG("tile_net_stop()\n"); + + /* Start discarding packets. */ + priv->active = false; + + /* Make sure "active" is visible to all tiles. */ + mb(); + + /* + * On each tile, make sure no NEW packets get delivered, and + * disable the ingress interrupt. + * + * Note that the ingress interrupt can fire AFTER this, + * presumably due to packets which were recently delivered, + * but it will have no effect. + */ + on_each_cpu(tile_net_deregister, (void *)dev, 1); + + /* Optimistically drain LIPP buffers. */ + (void)tile_net_drain_lipp_buffers(priv); + + /* ISSUE: Only needed if not yet fully open. */ + cancel_delayed_work_sync(&priv->retry_work); + + /* Can't transmit any more. */ + netif_stop_queue(dev); + + /* Disable NAPI on each tile. */ + on_each_cpu(tile_net_stop_disable, (void *)dev, 1); + + /* + * Drain any remaining LIPP buffers. NOTE: This "printk()" + * has never been observed, but in theory it could happen. + */ + if (tile_net_drain_lipp_buffers(priv) != 0) + printk("Had to drain some extra LIPP buffers!\n"); + + /* Stop LIPP/LEPP. */ + tile_net_stop_aux(dev); + + /* + * ISSUE: It appears that, in practice anyway, by the time we + * get here, there are no pending completions, but just in case, + * we free (all of) them anyway. + */ + while (tile_net_lepp_free_comps(dev, true)) + /* loop */; + + /* Wipe the EPP queue, and wait till the stores hit the EPP. */ + memset(priv->eq, 0, sizeof(lepp_queue_t)); + mb(); + + return 0; + } + + + /* + * Prepare the "frags" info for the resulting LEPP command. + * + * If needed, flush the memory used by the frags. + */ + static unsigned int tile_net_tx_frags(lepp_frag_t *frags, + struct sk_buff *skb, + void *b_data, unsigned int b_len) + { + unsigned int i, n = 0; + + struct skb_shared_info *sh = skb_shinfo(skb); + + phys_addr_t cpa; + + if (b_len != 0) { + + if (!hash_default) + finv_buffer_remote(b_data, b_len, 0); + + cpa = __pa(b_data); + frags[n].cpa_lo = cpa; + frags[n].cpa_hi = cpa >> 32; + frags[n].length = b_len; + frags[n].hash_for_home = hash_default; + n++; + } + + for (i = 0; i < sh->nr_frags; i++) { + + skb_frag_t *f = &sh->frags[i]; + unsigned long pfn = page_to_pfn(f->page); + + /* FIXME: Compute "hash_for_home" properly. */ + /* ISSUE: The hypervisor checks CHIP_HAS_REV1_DMA_PACKETS(). */ + int hash_for_home = hash_default; + + /* FIXME: Hmmm. */ + if (!hash_default) { + void *va = pfn_to_kaddr(pfn) + f->page_offset; + BUG_ON(PageHighMem(f->page)); + finv_buffer_remote(va, f->size, 0); + } + + cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset; + frags[n].cpa_lo = cpa; + frags[n].cpa_hi = cpa >> 32; + frags[n].length = skb_frag_size(f); + frags[n].hash_for_home = hash_for_home; + n++; + } + + return n; + } + + + /* + * This function takes "skb", consisting of a header template and a + * payload, and hands it to LEPP, to emit as one or more segments, + * each consisting of a possibly modified header, plus a piece of the + * payload, via a process known as "tcp segmentation offload". + * + * Usually, "data" will contain the header template, of size "sh_len", + * and "sh->frags" will contain "skb->data_len" bytes of payload, and + * there will be "sh->gso_segs" segments. + * + * Sometimes, if "sendfile()" requires copying, we will be called with + * "data" containing the header and payload, with "frags" being empty. + * + * In theory, "sh->nr_frags" could be 3, but in practice, it seems + * that this will never actually happen. + * + * See "emulate_large_send_offload()" for some reference code, which + * does not handle checksumming. + * + * ISSUE: How do we make sure that high memory DMA does not migrate? + */ + static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + struct tile_net_stats_t *stats = &info->stats; + + struct skb_shared_info *sh = skb_shinfo(skb); + + unsigned char *data = skb->data; + + /* The ip header follows the ethernet header. */ + struct iphdr *ih = ip_hdr(skb); + unsigned int ih_len = ih->ihl * 4; + + /* Note that "nh == ih", by definition. */ + unsigned char *nh = skb_network_header(skb); + unsigned int eh_len = nh - data; + + /* The tcp header follows the ip header. */ + struct tcphdr *th = (struct tcphdr *)(nh + ih_len); + unsigned int th_len = th->doff * 4; + + /* The total number of header bytes. */ + /* NOTE: This may be less than skb_headlen(skb). */ + unsigned int sh_len = eh_len + ih_len + th_len; + + /* The number of payload bytes at "skb->data + sh_len". */ + /* This is non-zero for sendfile() without HIGHDMA. */ + unsigned int b_len = skb_headlen(skb) - sh_len; + + /* The total number of payload bytes. */ + unsigned int d_len = b_len + skb->data_len; + + /* The maximum payload size. */ + unsigned int p_len = sh->gso_size; + + /* The total number of segments. */ + unsigned int num_segs = sh->gso_segs; + + /* The temporary copy of the command. */ + u32 cmd_body[(LEPP_MAX_CMD_SIZE + 3) / 4]; + lepp_tso_cmd_t *cmd = (lepp_tso_cmd_t *)cmd_body; + + /* Analyze the "frags". */ + unsigned int num_frags = + tile_net_tx_frags(cmd->frags, skb, data + sh_len, b_len); + + /* The size of the command, including frags and header. */ + size_t cmd_size = LEPP_TSO_CMD_SIZE(num_frags, sh_len); + + /* The command header. */ + lepp_tso_cmd_t cmd_init = { + .tso = true, + .header_size = sh_len, + .ip_offset = eh_len, + .tcp_offset = eh_len + ih_len, + .payload_size = p_len, + .num_frags = num_frags, + }; + + unsigned long irqflags; + + lepp_queue_t *eq = priv->eq; + + struct sk_buff *olds[8]; + unsigned int wanted = 8; + unsigned int i, nolds = 0; + + unsigned int cmd_head, cmd_tail, cmd_next; + unsigned int comp_tail; + + + /* Paranoia. */ + BUG_ON(skb->protocol != htons(ETH_P_IP)); + BUG_ON(ih->protocol != IPPROTO_TCP); + BUG_ON(skb->ip_summed != CHECKSUM_PARTIAL); + BUG_ON(num_frags > LEPP_MAX_FRAGS); + /*--BUG_ON(num_segs != (d_len + (p_len - 1)) / p_len); */ + BUG_ON(num_segs <= 1); + + + /* Finish preparing the command. */ + + /* Copy the command header. */ + *cmd = cmd_init; + + /* Copy the "header". */ + memcpy(&cmd->frags[num_frags], data, sh_len); + + + /* Prefetch and wait, to minimize time spent holding the spinlock. */ + prefetch_L1(&eq->comp_tail); + prefetch_L1(&eq->cmd_tail); + mb(); + + + /* Enqueue the command. */ + + spin_lock_irqsave(&priv->eq_lock, irqflags); + + /* + * Handle completions if needed to make room. + * HACK: Spin until there is sufficient room. + */ + if (lepp_num_free_comp_slots(eq) == 0) { + nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); + if (nolds == 0) { + busy: + spin_unlock_irqrestore(&priv->eq_lock, irqflags); + return NETDEV_TX_BUSY; + } + } + + cmd_head = eq->cmd_head; + cmd_tail = eq->cmd_tail; + + /* Prepare to advance, detecting full queue. */ + cmd_next = cmd_tail + cmd_size; + if (cmd_tail < cmd_head && cmd_next >= cmd_head) + goto busy; + if (cmd_next > LEPP_CMD_LIMIT) { + cmd_next = 0; + if (cmd_next == cmd_head) + goto busy; + } + + /* Copy the command. */ + memcpy(&eq->cmds[cmd_tail], cmd, cmd_size); + + /* Advance. */ + cmd_tail = cmd_next; + + /* Record "skb" for eventual freeing. */ + comp_tail = eq->comp_tail; + eq->comps[comp_tail] = skb; + LEPP_QINC(comp_tail); + eq->comp_tail = comp_tail; + + /* Flush before allowing LEPP to handle the command. */ + /* ISSUE: Is this the optimal location for the flush? */ + __insn_mf(); + + eq->cmd_tail = cmd_tail; + + /* NOTE: Using "4" here is more efficient than "0" or "2", */ + /* and, strangely, more efficient than pre-checking the number */ + /* of available completions, and comparing it to 4. */ + if (nolds == 0) + nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4); + + spin_unlock_irqrestore(&priv->eq_lock, irqflags); + + /* Handle completions. */ + for (i = 0; i < nolds; i++) + kfree_skb(olds[i]); + + /* Update stats. */ + stats->tx_packets += num_segs; + stats->tx_bytes += (num_segs * sh_len) + d_len; + + /* Make sure the egress timer is scheduled. */ + tile_net_schedule_egress_timer(info); + + return NETDEV_TX_OK; + } + + + /* + * Transmit a packet (called by the kernel via "hard_start_xmit" hook). + */ + static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + int my_cpu = smp_processor_id(); + struct tile_net_cpu *info = priv->cpu[my_cpu]; + struct tile_net_stats_t *stats = &info->stats; + + unsigned long irqflags; + + struct skb_shared_info *sh = skb_shinfo(skb); + + unsigned int len = skb->len; + unsigned char *data = skb->data; + + unsigned int csum_start = skb_checksum_start_offset(skb); + + lepp_frag_t frags[LEPP_MAX_FRAGS]; + + unsigned int num_frags; + + lepp_queue_t *eq = priv->eq; + + struct sk_buff *olds[8]; + unsigned int wanted = 8; + unsigned int i, nolds = 0; + + unsigned int cmd_size = sizeof(lepp_cmd_t); + + unsigned int cmd_head, cmd_tail, cmd_next; + unsigned int comp_tail; + + lepp_cmd_t cmds[LEPP_MAX_FRAGS]; + + + /* + * This is paranoia, since we think that if the link doesn't come + * up, telling Linux we have no carrier will keep it from trying + * to transmit. If it does, though, we can't execute this routine, + * since data structures we depend on aren't set up yet. + */ + if (!info->registered) + return NETDEV_TX_BUSY; + + + /* Save the timestamp. */ + dev->trans_start = jiffies; + + + #ifdef TILE_NET_PARANOIA + #if CHIP_HAS_CBOX_HOME_MAP() + if (hash_default) { + HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data); + if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3) + panic("Non-HFH egress buffer! VA=%p Mode=%d PTE=%llx", + data, hv_pte_get_mode(pte), hv_pte_val(pte)); + } + #endif + #endif + + + #ifdef TILE_NET_DUMP_PACKETS + /* ISSUE: Does not dump the "frags". */ + dump_packet(data, skb_headlen(skb), "tx"); + #endif /* TILE_NET_DUMP_PACKETS */ + + + if (sh->gso_size != 0) + return tile_net_tx_tso(skb, dev); + + + /* Prepare the commands. */ + + num_frags = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); + + for (i = 0; i < num_frags; i++) { + + bool final = (i == num_frags - 1); + + lepp_cmd_t cmd = { + .cpa_lo = frags[i].cpa_lo, + .cpa_hi = frags[i].cpa_hi, + .length = frags[i].length, + .hash_for_home = frags[i].hash_for_home, + .send_completion = final, + .end_of_packet = final + }; + + if (i == 0 && skb->ip_summed == CHECKSUM_PARTIAL) { + cmd.compute_checksum = 1; + cmd.checksum_data.bits.start_byte = csum_start; + cmd.checksum_data.bits.count = len - csum_start; + cmd.checksum_data.bits.destination_byte = + csum_start + skb->csum_offset; + } + + cmds[i] = cmd; + } + + + /* Prefetch and wait, to minimize time spent holding the spinlock. */ + prefetch_L1(&eq->comp_tail); + prefetch_L1(&eq->cmd_tail); + mb(); + + + /* Enqueue the commands. */ + + spin_lock_irqsave(&priv->eq_lock, irqflags); + + /* + * Handle completions if needed to make room. + * HACK: Spin until there is sufficient room. + */ + if (lepp_num_free_comp_slots(eq) == 0) { + nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); + if (nolds == 0) { + busy: + spin_unlock_irqrestore(&priv->eq_lock, irqflags); + return NETDEV_TX_BUSY; + } + } + + cmd_head = eq->cmd_head; + cmd_tail = eq->cmd_tail; + + /* Copy the commands, or fail. */ + for (i = 0; i < num_frags; i++) { + + /* Prepare to advance, detecting full queue. */ + cmd_next = cmd_tail + cmd_size; + if (cmd_tail < cmd_head && cmd_next >= cmd_head) + goto busy; + if (cmd_next > LEPP_CMD_LIMIT) { + cmd_next = 0; + if (cmd_next == cmd_head) + goto busy; + } + + /* Copy the command. */ + *(lepp_cmd_t *)&eq->cmds[cmd_tail] = cmds[i]; + + /* Advance. */ + cmd_tail = cmd_next; + } + + /* Record "skb" for eventual freeing. */ + comp_tail = eq->comp_tail; + eq->comps[comp_tail] = skb; + LEPP_QINC(comp_tail); + eq->comp_tail = comp_tail; + + /* Flush before allowing LEPP to handle the command. */ + /* ISSUE: Is this the optimal location for the flush? */ + __insn_mf(); + + eq->cmd_tail = cmd_tail; + + /* NOTE: Using "4" here is more efficient than "0" or "2", */ + /* and, strangely, more efficient than pre-checking the number */ + /* of available completions, and comparing it to 4. */ + if (nolds == 0) + nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4); + + spin_unlock_irqrestore(&priv->eq_lock, irqflags); + + /* Handle completions. */ + for (i = 0; i < nolds; i++) + kfree_skb(olds[i]); + + /* HACK: Track "expanded" size for short packets (e.g. 42 < 60). */ + stats->tx_packets++; + stats->tx_bytes += ((len >= ETH_ZLEN) ? len : ETH_ZLEN); + + /* Make sure the egress timer is scheduled. */ + tile_net_schedule_egress_timer(info); + + return NETDEV_TX_OK; + } + + + /* + * Deal with a transmit timeout. + */ + static void tile_net_tx_timeout(struct net_device *dev) + { + PDEBUG("tile_net_tx_timeout()\n"); + PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies, + jiffies - dev->trans_start); + + /* XXX: ISSUE: This doesn't seem useful for us. */ + netif_wake_queue(dev); + } + + + /* + * Ioctl commands. + */ + static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + { + return -EOPNOTSUPP; + } + + + /* + * Get System Network Statistics. + * + * Returns the address of the device statistics structure. + */ + static struct net_device_stats *tile_net_get_stats(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + u32 rx_packets = 0; + u32 tx_packets = 0; + u32 rx_bytes = 0; + u32 tx_bytes = 0; + int i; + + for_each_online_cpu(i) { + if (priv->cpu[i]) { + rx_packets += priv->cpu[i]->stats.rx_packets; + rx_bytes += priv->cpu[i]->stats.rx_bytes; + tx_packets += priv->cpu[i]->stats.tx_packets; + tx_bytes += priv->cpu[i]->stats.tx_bytes; + } + } + + priv->stats.rx_packets = rx_packets; + priv->stats.rx_bytes = rx_bytes; + priv->stats.tx_packets = tx_packets; + priv->stats.tx_bytes = tx_bytes; + + return &priv->stats; + } + + + /* + * Change the "mtu". + * + * The "change_mtu" method is usually not needed. + * If you need it, it must be like this. + */ + static int tile_net_change_mtu(struct net_device *dev, int new_mtu) + { + PDEBUG("tile_net_change_mtu()\n"); + + /* Check ranges. */ + if ((new_mtu < 68) || (new_mtu > 1500)) + return -EINVAL; + + /* Accept the value. */ + dev->mtu = new_mtu; + + return 0; + } + + + /* + * Change the Ethernet Address of the NIC. + * + * The hypervisor driver does not support changing MAC address. However, + * the IPP does not do anything with the MAC address, so the address which + * gets used on outgoing packets, and which is accepted on incoming packets, + * is completely up to the NetIO program or kernel driver which is actually + * handling them. + * + * Returns 0 on success, negative on failure. + */ + static int tile_net_set_mac_address(struct net_device *dev, void *p) + { + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + /* ISSUE: Note that "dev_addr" is now a pointer. */ + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + return 0; + } + + + /* + * Obtain the MAC address from the hypervisor. + * This must be done before opening the device. + */ + static int tile_net_get_mac(struct net_device *dev) + { + struct tile_net_priv *priv = netdev_priv(dev); + + char hv_dev_name[32]; + int len; + + __netio_getset_offset_t offset = { .word = NETIO_IPP_PARAM_OFF }; + + int ret; + + /* For example, "xgbe0". */ + strcpy(hv_dev_name, dev->name); + len = strlen(hv_dev_name); + + /* For example, "xgbe/0". */ + hv_dev_name[len] = hv_dev_name[len - 1]; + hv_dev_name[len - 1] = '/'; + len++; + + /* For example, "xgbe/0/native_hash". */ + strcpy(hv_dev_name + len, hash_default ? "/native_hash" : "/native"); + + /* Get the hypervisor handle for this device. */ + priv->hv_devhdl = hv_dev_open((HV_VirtAddr)hv_dev_name, 0); + PDEBUG("hv_dev_open(%s) returned %d %p\n", + hv_dev_name, priv->hv_devhdl, &priv->hv_devhdl); + if (priv->hv_devhdl < 0) { + if (priv->hv_devhdl == HV_ENODEV) + printk(KERN_DEBUG "Ignoring unconfigured device %s\n", + hv_dev_name); + else + printk(KERN_DEBUG "hv_dev_open(%s) returned %d\n", + hv_dev_name, priv->hv_devhdl); + return -1; + } + + /* + * Read the hardware address from the hypervisor. + * ISSUE: Note that "dev_addr" is now a pointer. + */ + offset.bits.class = NETIO_PARAM; + offset.bits.addr = NETIO_PARAM_MAC; + ret = hv_dev_pread(priv->hv_devhdl, 0, + (HV_VirtAddr)dev->dev_addr, dev->addr_len, + offset.word); + PDEBUG("hv_dev_pread(NETIO_PARAM_MAC) returned %d\n", ret); + if (ret <= 0) { + printk(KERN_DEBUG "hv_dev_pread(NETIO_PARAM_MAC) %s failed\n", + dev->name); + /* + * Since the device is configured by the hypervisor but we + * can't get its MAC address, we are most likely running + * the simulator, so let's generate a random MAC address. + */ + random_ether_addr(dev->dev_addr); + } + + return 0; + } + + + static struct net_device_ops tile_net_ops = { + .ndo_open = tile_net_open, + .ndo_stop = tile_net_stop, + .ndo_start_xmit = tile_net_tx, + .ndo_do_ioctl = tile_net_ioctl, + .ndo_get_stats = tile_net_get_stats, + .ndo_change_mtu = tile_net_change_mtu, + .ndo_tx_timeout = tile_net_tx_timeout, + .ndo_set_mac_address = tile_net_set_mac_address + }; + + + /* + * The setup function. + * + * This uses ether_setup() to assign various fields in dev, including + * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. + */ + static void tile_net_setup(struct net_device *dev) + { + PDEBUG("tile_net_setup()\n"); + + ether_setup(dev); + + dev->netdev_ops = &tile_net_ops; + + dev->watchdog_timeo = TILE_NET_TIMEOUT; + + /* We want lockless xmit. */ + dev->features |= NETIF_F_LLTX; + + /* We support hardware tx checksums. */ + dev->features |= NETIF_F_HW_CSUM; + + /* We support scatter/gather. */ + dev->features |= NETIF_F_SG; + + /* We support TSO. */ + dev->features |= NETIF_F_TSO; + + #ifdef TILE_NET_GSO + /* We support GSO. */ + dev->features |= NETIF_F_GSO; + #endif + + if (hash_default) + dev->features |= NETIF_F_HIGHDMA; + + /* ISSUE: We should support NETIF_F_UFO. */ + + dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN; + + dev->mtu = TILE_NET_MTU; + } + + + /* + * Allocate the device structure, register the device, and obtain the + * MAC address from the hypervisor. + */ + static struct net_device *tile_net_dev_init(const char *name) + { + int ret; + struct net_device *dev; + struct tile_net_priv *priv; + + /* + * Allocate the device structure. This allocates "priv", calls + * tile_net_setup(), and saves "name". Normally, "name" is a + * template, instantiated by register_netdev(), but not for us. + */ + dev = alloc_netdev(sizeof(*priv), name, tile_net_setup); + if (!dev) { + pr_err("alloc_netdev(%s) failed\n", name); + return NULL; + } + + priv = netdev_priv(dev); + + /* Initialize "priv". */ + + memset(priv, 0, sizeof(*priv)); + + /* Save "dev" for "tile_net_open_retry()". */ + priv->dev = dev; + + INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry); + + spin_lock_init(&priv->eq_lock); + + /* Allocate "eq". */ + priv->eq_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, EQ_ORDER); + if (!priv->eq_pages) { + free_netdev(dev); + return NULL; + } + priv->eq = page_address(priv->eq_pages); + + /* Register the network device. */ + ret = register_netdev(dev); + if (ret) { + pr_err("register_netdev %s failed %d\n", dev->name, ret); + __free_pages(priv->eq_pages, EQ_ORDER); + free_netdev(dev); + return NULL; + } + + /* Get the MAC address. */ + ret = tile_net_get_mac(dev); + if (ret < 0) { + unregister_netdev(dev); + __free_pages(priv->eq_pages, EQ_ORDER); + free_netdev(dev); + return NULL; + } + + return dev; + } + + + /* + * Module cleanup. + * + * FIXME: If compiled as a module, this module cannot be "unloaded", + * because the "ingress interrupt handler" is registered permanently. + */ + static void tile_net_cleanup(void) + { + int i; + + for (i = 0; i < TILE_NET_DEVS; i++) { + if (tile_net_devs[i]) { + struct net_device *dev = tile_net_devs[i]; + struct tile_net_priv *priv = netdev_priv(dev); + unregister_netdev(dev); + finv_buffer_remote(priv->eq, EQ_SIZE, 0); + __free_pages(priv->eq_pages, EQ_ORDER); + free_netdev(dev); + } + } + } + + + /* + * Module initialization. + */ + static int tile_net_init_module(void) + { + pr_info("Tilera IPP Net Driver\n"); + + tile_net_devs[0] = tile_net_dev_init("xgbe0"); + tile_net_devs[1] = tile_net_dev_init("xgbe1"); + tile_net_devs[2] = tile_net_dev_init("gbe0"); + tile_net_devs[3] = tile_net_dev_init("gbe1"); + + return 0; + } + + + module_init(tile_net_init_module); + module_exit(tile_net_cleanup); + + + #ifndef MODULE + + /* + * The "network_cpus" boot argument specifies the cpus that are dedicated + * to handle ingress packets. + * + * The parameter should be in the form "network_cpus=m-n[,x-y]", where + * m, n, x, y are integer numbers that represent the cpus that can be + * neither a dedicated cpu nor a dataplane cpu. + */ + static int __init network_cpus_setup(char *str) + { + int rc = cpulist_parse_crop(str, &network_cpus_map); + if (rc != 0) { + pr_warning("network_cpus=%s: malformed cpu list\n", + str); + } else { + + /* Remove dedicated cpus. */ + cpumask_and(&network_cpus_map, &network_cpus_map, + cpu_possible_mask); + + + if (cpumask_empty(&network_cpus_map)) { + pr_warning("Ignoring network_cpus='%s'.\n", + str); + } else { + char buf[1024]; + cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map); + pr_info("Linux network CPUs: %s\n", buf); + network_cpus_used = true; + } + } + + return 0; + } + __setup("network_cpus=", network_cpus_setup); + + #endif diff --cc fs/sysfs/dir.c index 83bb9d1f30aa,26f370a9b5ce..0344ee70a47c --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@@ -558,36 -547,22 +565,43 @@@ struct sysfs_dirent *sysfs_find_dirent( const void *ns, const unsigned char *name) { - struct sysfs_dirent *sd; + struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; + struct sysfs_dirent *found = NULL; + if (!!sysfs_ns_type(parent_sd) != !!ns) { + WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", + sysfs_ns_type(parent_sd)? "required": "invalid", + parent_sd->s_name, name); + return NULL; + } + - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { - if (sd->s_ns != ns) - continue; - if (!strcmp(sd->s_name, name)) - return sd; + while (p) { + int c; +#define node rb_entry(p, struct sysfs_dirent, name_node) + c = strcmp(name, node->s_name); + if (c < 0) { + p = node->name_node.rb_left; + } else if (c > 0) { + p = node->name_node.rb_right; + } else { + found = node; + p = node->name_node.rb_left; + } +#undef node } - return NULL; + + if (found && ns) { + while (found->s_ns && found->s_ns != ns) { + p = rb_next(&found->name_node); + if (!p) + return NULL; + found = rb_entry(p, struct sysfs_dirent, name_node); + if (strcmp(name, found->s_name)) + return NULL; + } + } + + return found; } /**