1f7917c00SJeff Kirsher /* 2f7917c00SJeff Kirsher * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. 3f7917c00SJeff Kirsher * 4f7917c00SJeff Kirsher * This software is available to you under a choice of one of two 5f7917c00SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU 6f7917c00SJeff Kirsher * General Public License (GPL) Version 2, available from the file 7f7917c00SJeff Kirsher * COPYING in the main directory of this source tree, or the 8f7917c00SJeff Kirsher * OpenIB.org BSD license below: 9f7917c00SJeff Kirsher * 10f7917c00SJeff Kirsher * Redistribution and use in source and binary forms, with or 11f7917c00SJeff Kirsher * without modification, are permitted provided that the following 12f7917c00SJeff Kirsher * conditions are met: 13f7917c00SJeff Kirsher * 14f7917c00SJeff Kirsher * - Redistributions of source code must retain the above 15f7917c00SJeff Kirsher * copyright notice, this list of conditions and the following 16f7917c00SJeff Kirsher * disclaimer. 17f7917c00SJeff Kirsher * 18f7917c00SJeff Kirsher * - Redistributions in binary form must reproduce the above 19f7917c00SJeff Kirsher * copyright notice, this list of conditions and the following 20f7917c00SJeff Kirsher * disclaimer in the documentation and/or other materials 21f7917c00SJeff Kirsher * provided with the distribution. 22f7917c00SJeff Kirsher * 23f7917c00SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24f7917c00SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25f7917c00SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26f7917c00SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27f7917c00SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28f7917c00SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29f7917c00SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30f7917c00SJeff Kirsher * SOFTWARE. 31f7917c00SJeff Kirsher */ 32f7917c00SJeff Kirsher #include "common.h" 33f7917c00SJeff Kirsher #include "regs.h" 34f7917c00SJeff Kirsher #include "sge_defs.h" 35f7917c00SJeff Kirsher #include "firmware_exports.h" 36f7917c00SJeff Kirsher 37f7917c00SJeff Kirsher static void t3_port_intr_clear(struct adapter *adapter, int idx); 38f7917c00SJeff Kirsher 39f7917c00SJeff Kirsher /** 40f7917c00SJeff Kirsher * t3_wait_op_done_val - wait until an operation is completed 41f7917c00SJeff Kirsher * @adapter: the adapter performing the operation 42f7917c00SJeff Kirsher * @reg: the register to check for completion 43f7917c00SJeff Kirsher * @mask: a single-bit field within @reg that indicates completion 44f7917c00SJeff Kirsher * @polarity: the value of the field when the operation is completed 45f7917c00SJeff Kirsher * @attempts: number of check iterations 46f7917c00SJeff Kirsher * @delay: delay in usecs between iterations 47f7917c00SJeff Kirsher * @valp: where to store the value of the register at completion time 48f7917c00SJeff Kirsher * 49f7917c00SJeff Kirsher * Wait until an operation is completed by checking a bit in a register 50f7917c00SJeff Kirsher * up to @attempts times. If @valp is not NULL the value of the register 51f7917c00SJeff Kirsher * at the time it indicated completion is stored there. Returns 0 if the 52f7917c00SJeff Kirsher * operation completes and -EAGAIN otherwise. 53f7917c00SJeff Kirsher */ 54f7917c00SJeff Kirsher 55f7917c00SJeff Kirsher int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, 56f7917c00SJeff Kirsher int polarity, int attempts, int delay, u32 *valp) 57f7917c00SJeff Kirsher { 58f7917c00SJeff Kirsher while (1) { 59f7917c00SJeff Kirsher u32 val = t3_read_reg(adapter, reg); 60f7917c00SJeff Kirsher 61f7917c00SJeff Kirsher if (!!(val & mask) == polarity) { 62f7917c00SJeff Kirsher if (valp) 63f7917c00SJeff Kirsher *valp = val; 64f7917c00SJeff Kirsher return 0; 65f7917c00SJeff Kirsher } 66f7917c00SJeff Kirsher if (--attempts == 0) 67f7917c00SJeff Kirsher return -EAGAIN; 68f7917c00SJeff Kirsher if (delay) 69f7917c00SJeff Kirsher udelay(delay); 70f7917c00SJeff Kirsher } 71f7917c00SJeff Kirsher } 72f7917c00SJeff Kirsher 73f7917c00SJeff Kirsher /** 74f7917c00SJeff Kirsher * t3_write_regs - write a bunch of registers 75f7917c00SJeff Kirsher * @adapter: the adapter to program 76f7917c00SJeff Kirsher * @p: an array of register address/register value pairs 77f7917c00SJeff Kirsher * @n: the number of address/value pairs 78f7917c00SJeff Kirsher * @offset: register address offset 79f7917c00SJeff Kirsher * 80f7917c00SJeff Kirsher * Takes an array of register address/register value pairs and writes each 81f7917c00SJeff Kirsher * value to the corresponding register. Register addresses are adjusted 82f7917c00SJeff Kirsher * by the supplied offset. 83f7917c00SJeff Kirsher */ 84f7917c00SJeff Kirsher void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p, 85f7917c00SJeff Kirsher int n, unsigned int offset) 86f7917c00SJeff Kirsher { 87f7917c00SJeff Kirsher while (n--) { 88f7917c00SJeff Kirsher t3_write_reg(adapter, p->reg_addr + offset, p->val); 89f7917c00SJeff Kirsher p++; 90f7917c00SJeff Kirsher } 91f7917c00SJeff Kirsher } 92f7917c00SJeff Kirsher 93f7917c00SJeff Kirsher /** 94f7917c00SJeff Kirsher * t3_set_reg_field - set a register field to a value 95f7917c00SJeff Kirsher * @adapter: the adapter to program 96f7917c00SJeff Kirsher * @addr: the register address 97f7917c00SJeff Kirsher * @mask: specifies the portion of the register to modify 98f7917c00SJeff Kirsher * @val: the new value for the register field 99f7917c00SJeff Kirsher * 100f7917c00SJeff Kirsher * Sets a register field specified by the supplied mask to the 101f7917c00SJeff Kirsher * given value. 102f7917c00SJeff Kirsher */ 103f7917c00SJeff Kirsher void t3_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, 104f7917c00SJeff Kirsher u32 val) 105f7917c00SJeff Kirsher { 106f7917c00SJeff Kirsher u32 v = t3_read_reg(adapter, addr) & ~mask; 107f7917c00SJeff Kirsher 108f7917c00SJeff Kirsher t3_write_reg(adapter, addr, v | val); 109f7917c00SJeff Kirsher t3_read_reg(adapter, addr); /* flush */ 110f7917c00SJeff Kirsher } 111f7917c00SJeff Kirsher 112f7917c00SJeff Kirsher /** 113f7917c00SJeff Kirsher * t3_read_indirect - read indirectly addressed registers 114f7917c00SJeff Kirsher * @adap: the adapter 115f7917c00SJeff Kirsher * @addr_reg: register holding the indirect address 116f7917c00SJeff Kirsher * @data_reg: register holding the value of the indirect register 117f7917c00SJeff Kirsher * @vals: where the read register values are stored 118f7917c00SJeff Kirsher * @start_idx: index of first indirect register to read 119f7917c00SJeff Kirsher * @nregs: how many indirect registers to read 120f7917c00SJeff Kirsher * 121f7917c00SJeff Kirsher * Reads registers that are accessed indirectly through an address/data 122f7917c00SJeff Kirsher * register pair. 123f7917c00SJeff Kirsher */ 124f7917c00SJeff Kirsher static void t3_read_indirect(struct adapter *adap, unsigned int addr_reg, 125f7917c00SJeff Kirsher unsigned int data_reg, u32 *vals, 126f7917c00SJeff Kirsher unsigned int nregs, unsigned int start_idx) 127f7917c00SJeff Kirsher { 128f7917c00SJeff Kirsher while (nregs--) { 129f7917c00SJeff Kirsher t3_write_reg(adap, addr_reg, start_idx); 130f7917c00SJeff Kirsher *vals++ = t3_read_reg(adap, data_reg); 131f7917c00SJeff Kirsher start_idx++; 132f7917c00SJeff Kirsher } 133f7917c00SJeff Kirsher } 134f7917c00SJeff Kirsher 135f7917c00SJeff Kirsher /** 136f7917c00SJeff Kirsher * t3_mc7_bd_read - read from MC7 through backdoor accesses 137f7917c00SJeff Kirsher * @mc7: identifies MC7 to read from 138f7917c00SJeff Kirsher * @start: index of first 64-bit word to read 139f7917c00SJeff Kirsher * @n: number of 64-bit words to read 140f7917c00SJeff Kirsher * @buf: where to store the read result 141f7917c00SJeff Kirsher * 142f7917c00SJeff Kirsher * Read n 64-bit words from MC7 starting at word start, using backdoor 143f7917c00SJeff Kirsher * accesses. 144f7917c00SJeff Kirsher */ 145f7917c00SJeff Kirsher int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, 146f7917c00SJeff Kirsher u64 *buf) 147f7917c00SJeff Kirsher { 148f7917c00SJeff Kirsher static const int shift[] = { 0, 0, 16, 24 }; 149f7917c00SJeff Kirsher static const int step[] = { 0, 32, 16, 8 }; 150f7917c00SJeff Kirsher 151f7917c00SJeff Kirsher unsigned int size64 = mc7->size / 8; /* # of 64-bit words */ 152f7917c00SJeff Kirsher struct adapter *adap = mc7->adapter; 153f7917c00SJeff Kirsher 154f7917c00SJeff Kirsher if (start >= size64 || start + n > size64) 155f7917c00SJeff Kirsher return -EINVAL; 156f7917c00SJeff Kirsher 157f7917c00SJeff Kirsher start *= (8 << mc7->width); 158f7917c00SJeff Kirsher while (n--) { 159f7917c00SJeff Kirsher int i; 160f7917c00SJeff Kirsher u64 val64 = 0; 161f7917c00SJeff Kirsher 162f7917c00SJeff Kirsher for (i = (1 << mc7->width) - 1; i >= 0; --i) { 163f7917c00SJeff Kirsher int attempts = 10; 164f7917c00SJeff Kirsher u32 val; 165f7917c00SJeff Kirsher 166f7917c00SJeff Kirsher t3_write_reg(adap, mc7->offset + A_MC7_BD_ADDR, start); 167f7917c00SJeff Kirsher t3_write_reg(adap, mc7->offset + A_MC7_BD_OP, 0); 168f7917c00SJeff Kirsher val = t3_read_reg(adap, mc7->offset + A_MC7_BD_OP); 169f7917c00SJeff Kirsher while ((val & F_BUSY) && attempts--) 170f7917c00SJeff Kirsher val = t3_read_reg(adap, 171f7917c00SJeff Kirsher mc7->offset + A_MC7_BD_OP); 172f7917c00SJeff Kirsher if (val & F_BUSY) 173f7917c00SJeff Kirsher return -EIO; 174f7917c00SJeff Kirsher 175f7917c00SJeff Kirsher val = t3_read_reg(adap, mc7->offset + A_MC7_BD_DATA1); 176f7917c00SJeff Kirsher if (mc7->width == 0) { 177f7917c00SJeff Kirsher val64 = t3_read_reg(adap, 178f7917c00SJeff Kirsher mc7->offset + 179f7917c00SJeff Kirsher A_MC7_BD_DATA0); 180f7917c00SJeff Kirsher val64 |= (u64) val << 32; 181f7917c00SJeff Kirsher } else { 182f7917c00SJeff Kirsher if (mc7->width > 1) 183f7917c00SJeff Kirsher val >>= shift[mc7->width]; 184f7917c00SJeff Kirsher val64 |= (u64) val << (step[mc7->width] * i); 185f7917c00SJeff Kirsher } 186f7917c00SJeff Kirsher start += 8; 187f7917c00SJeff Kirsher } 188f7917c00SJeff Kirsher *buf++ = val64; 189f7917c00SJeff Kirsher } 190f7917c00SJeff Kirsher return 0; 191f7917c00SJeff Kirsher } 192f7917c00SJeff Kirsher 193f7917c00SJeff Kirsher /* 194f7917c00SJeff Kirsher * Initialize MI1. 195f7917c00SJeff Kirsher */ 196f7917c00SJeff Kirsher static void mi1_init(struct adapter *adap, const struct adapter_info *ai) 197f7917c00SJeff Kirsher { 198f7917c00SJeff Kirsher u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; 199f7917c00SJeff Kirsher u32 val = F_PREEN | V_CLKDIV(clkdiv); 200f7917c00SJeff Kirsher 201f7917c00SJeff Kirsher t3_write_reg(adap, A_MI1_CFG, val); 202f7917c00SJeff Kirsher } 203f7917c00SJeff Kirsher 204f7917c00SJeff Kirsher #define MDIO_ATTEMPTS 20 205f7917c00SJeff Kirsher 206f7917c00SJeff Kirsher /* 207f7917c00SJeff Kirsher * MI1 read/write operations for clause 22 PHYs. 208f7917c00SJeff Kirsher */ 209f7917c00SJeff Kirsher static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr, 210f7917c00SJeff Kirsher u16 reg_addr) 211f7917c00SJeff Kirsher { 212f7917c00SJeff Kirsher struct port_info *pi = netdev_priv(dev); 213f7917c00SJeff Kirsher struct adapter *adapter = pi->adapter; 214f7917c00SJeff Kirsher int ret; 215f7917c00SJeff Kirsher u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); 216f7917c00SJeff Kirsher 217f7917c00SJeff Kirsher mutex_lock(&adapter->mdio_lock); 218f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); 219f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_ADDR, addr); 220f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); 221f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); 222f7917c00SJeff Kirsher if (!ret) 223f7917c00SJeff Kirsher ret = t3_read_reg(adapter, A_MI1_DATA); 224f7917c00SJeff Kirsher mutex_unlock(&adapter->mdio_lock); 225f7917c00SJeff Kirsher return ret; 226f7917c00SJeff Kirsher } 227f7917c00SJeff Kirsher 228f7917c00SJeff Kirsher static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr, 229f7917c00SJeff Kirsher u16 reg_addr, u16 val) 230f7917c00SJeff Kirsher { 231f7917c00SJeff Kirsher struct port_info *pi = netdev_priv(dev); 232f7917c00SJeff Kirsher struct adapter *adapter = pi->adapter; 233f7917c00SJeff Kirsher int ret; 234f7917c00SJeff Kirsher u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); 235f7917c00SJeff Kirsher 236f7917c00SJeff Kirsher mutex_lock(&adapter->mdio_lock); 237f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); 238f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_ADDR, addr); 239f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_DATA, val); 240f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); 241f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); 242f7917c00SJeff Kirsher mutex_unlock(&adapter->mdio_lock); 243f7917c00SJeff Kirsher return ret; 244f7917c00SJeff Kirsher } 245f7917c00SJeff Kirsher 246f7917c00SJeff Kirsher static const struct mdio_ops mi1_mdio_ops = { 247f7917c00SJeff Kirsher .read = t3_mi1_read, 248f7917c00SJeff Kirsher .write = t3_mi1_write, 249f7917c00SJeff Kirsher .mode_support = MDIO_SUPPORTS_C22 250f7917c00SJeff Kirsher }; 251f7917c00SJeff Kirsher 252f7917c00SJeff Kirsher /* 253f7917c00SJeff Kirsher * Performs the address cycle for clause 45 PHYs. 254f7917c00SJeff Kirsher * Must be called with the MDIO_LOCK held. 255f7917c00SJeff Kirsher */ 256f7917c00SJeff Kirsher static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr, 257f7917c00SJeff Kirsher int reg_addr) 258f7917c00SJeff Kirsher { 259f7917c00SJeff Kirsher u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); 260f7917c00SJeff Kirsher 261f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0); 262f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_ADDR, addr); 263f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_DATA, reg_addr); 264f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); 265f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, 266f7917c00SJeff Kirsher MDIO_ATTEMPTS, 10); 267f7917c00SJeff Kirsher } 268f7917c00SJeff Kirsher 269f7917c00SJeff Kirsher /* 270f7917c00SJeff Kirsher * MI1 read/write operations for indirect-addressed PHYs. 271f7917c00SJeff Kirsher */ 272f7917c00SJeff Kirsher static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr, 273f7917c00SJeff Kirsher u16 reg_addr) 274f7917c00SJeff Kirsher { 275f7917c00SJeff Kirsher struct port_info *pi = netdev_priv(dev); 276f7917c00SJeff Kirsher struct adapter *adapter = pi->adapter; 277f7917c00SJeff Kirsher int ret; 278f7917c00SJeff Kirsher 279f7917c00SJeff Kirsher mutex_lock(&adapter->mdio_lock); 280f7917c00SJeff Kirsher ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); 281f7917c00SJeff Kirsher if (!ret) { 282f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); 283f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, 284f7917c00SJeff Kirsher MDIO_ATTEMPTS, 10); 285f7917c00SJeff Kirsher if (!ret) 286f7917c00SJeff Kirsher ret = t3_read_reg(adapter, A_MI1_DATA); 287f7917c00SJeff Kirsher } 288f7917c00SJeff Kirsher mutex_unlock(&adapter->mdio_lock); 289f7917c00SJeff Kirsher return ret; 290f7917c00SJeff Kirsher } 291f7917c00SJeff Kirsher 292f7917c00SJeff Kirsher static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr, 293f7917c00SJeff Kirsher u16 reg_addr, u16 val) 294f7917c00SJeff Kirsher { 295f7917c00SJeff Kirsher struct port_info *pi = netdev_priv(dev); 296f7917c00SJeff Kirsher struct adapter *adapter = pi->adapter; 297f7917c00SJeff Kirsher int ret; 298f7917c00SJeff Kirsher 299f7917c00SJeff Kirsher mutex_lock(&adapter->mdio_lock); 300f7917c00SJeff Kirsher ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); 301f7917c00SJeff Kirsher if (!ret) { 302f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_DATA, val); 303f7917c00SJeff Kirsher t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); 304f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, 305f7917c00SJeff Kirsher MDIO_ATTEMPTS, 10); 306f7917c00SJeff Kirsher } 307f7917c00SJeff Kirsher mutex_unlock(&adapter->mdio_lock); 308f7917c00SJeff Kirsher return ret; 309f7917c00SJeff Kirsher } 310f7917c00SJeff Kirsher 311f7917c00SJeff Kirsher static const struct mdio_ops mi1_mdio_ext_ops = { 312f7917c00SJeff Kirsher .read = mi1_ext_read, 313f7917c00SJeff Kirsher .write = mi1_ext_write, 314f7917c00SJeff Kirsher .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22 315f7917c00SJeff Kirsher }; 316f7917c00SJeff Kirsher 317f7917c00SJeff Kirsher /** 318f7917c00SJeff Kirsher * t3_mdio_change_bits - modify the value of a PHY register 319f7917c00SJeff Kirsher * @phy: the PHY to operate on 320f7917c00SJeff Kirsher * @mmd: the device address 321f7917c00SJeff Kirsher * @reg: the register address 322f7917c00SJeff Kirsher * @clear: what part of the register value to mask off 323f7917c00SJeff Kirsher * @set: what part of the register value to set 324f7917c00SJeff Kirsher * 325f7917c00SJeff Kirsher * Changes the value of a PHY register by applying a mask to its current 326f7917c00SJeff Kirsher * value and ORing the result with a new value. 327f7917c00SJeff Kirsher */ 328f7917c00SJeff Kirsher int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, 329f7917c00SJeff Kirsher unsigned int set) 330f7917c00SJeff Kirsher { 331f7917c00SJeff Kirsher int ret; 332f7917c00SJeff Kirsher unsigned int val; 333f7917c00SJeff Kirsher 334f7917c00SJeff Kirsher ret = t3_mdio_read(phy, mmd, reg, &val); 335f7917c00SJeff Kirsher if (!ret) { 336f7917c00SJeff Kirsher val &= ~clear; 337f7917c00SJeff Kirsher ret = t3_mdio_write(phy, mmd, reg, val | set); 338f7917c00SJeff Kirsher } 339f7917c00SJeff Kirsher return ret; 340f7917c00SJeff Kirsher } 341f7917c00SJeff Kirsher 342f7917c00SJeff Kirsher /** 343f7917c00SJeff Kirsher * t3_phy_reset - reset a PHY block 344f7917c00SJeff Kirsher * @phy: the PHY to operate on 345f7917c00SJeff Kirsher * @mmd: the device address of the PHY block to reset 346f7917c00SJeff Kirsher * @wait: how long to wait for the reset to complete in 1ms increments 347f7917c00SJeff Kirsher * 348f7917c00SJeff Kirsher * Resets a PHY block and optionally waits for the reset to complete. 349f7917c00SJeff Kirsher * @mmd should be 0 for 10/100/1000 PHYs and the device address to reset 350f7917c00SJeff Kirsher * for 10G PHYs. 351f7917c00SJeff Kirsher */ 352f7917c00SJeff Kirsher int t3_phy_reset(struct cphy *phy, int mmd, int wait) 353f7917c00SJeff Kirsher { 354f7917c00SJeff Kirsher int err; 355f7917c00SJeff Kirsher unsigned int ctl; 356f7917c00SJeff Kirsher 357f7917c00SJeff Kirsher err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER, 358f7917c00SJeff Kirsher MDIO_CTRL1_RESET); 359f7917c00SJeff Kirsher if (err || !wait) 360f7917c00SJeff Kirsher return err; 361f7917c00SJeff Kirsher 362f7917c00SJeff Kirsher do { 363f7917c00SJeff Kirsher err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl); 364f7917c00SJeff Kirsher if (err) 365f7917c00SJeff Kirsher return err; 366f7917c00SJeff Kirsher ctl &= MDIO_CTRL1_RESET; 367f7917c00SJeff Kirsher if (ctl) 368f7917c00SJeff Kirsher msleep(1); 369f7917c00SJeff Kirsher } while (ctl && --wait); 370f7917c00SJeff Kirsher 371f7917c00SJeff Kirsher return ctl ? -1 : 0; 372f7917c00SJeff Kirsher } 373f7917c00SJeff Kirsher 374f7917c00SJeff Kirsher /** 375f7917c00SJeff Kirsher * t3_phy_advertise - set the PHY advertisement registers for autoneg 376f7917c00SJeff Kirsher * @phy: the PHY to operate on 377f7917c00SJeff Kirsher * @advert: bitmap of capabilities the PHY should advertise 378f7917c00SJeff Kirsher * 379f7917c00SJeff Kirsher * Sets a 10/100/1000 PHY's advertisement registers to advertise the 380f7917c00SJeff Kirsher * requested capabilities. 381f7917c00SJeff Kirsher */ 382f7917c00SJeff Kirsher int t3_phy_advertise(struct cphy *phy, unsigned int advert) 383f7917c00SJeff Kirsher { 384f7917c00SJeff Kirsher int err; 385f7917c00SJeff Kirsher unsigned int val = 0; 386f7917c00SJeff Kirsher 387f7917c00SJeff Kirsher err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val); 388f7917c00SJeff Kirsher if (err) 389f7917c00SJeff Kirsher return err; 390f7917c00SJeff Kirsher 391f7917c00SJeff Kirsher val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); 392f7917c00SJeff Kirsher if (advert & ADVERTISED_1000baseT_Half) 393f7917c00SJeff Kirsher val |= ADVERTISE_1000HALF; 394f7917c00SJeff Kirsher if (advert & ADVERTISED_1000baseT_Full) 395f7917c00SJeff Kirsher val |= ADVERTISE_1000FULL; 396f7917c00SJeff Kirsher 397f7917c00SJeff Kirsher err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val); 398f7917c00SJeff Kirsher if (err) 399f7917c00SJeff Kirsher return err; 400f7917c00SJeff Kirsher 401f7917c00SJeff Kirsher val = 1; 402f7917c00SJeff Kirsher if (advert & ADVERTISED_10baseT_Half) 403f7917c00SJeff Kirsher val |= ADVERTISE_10HALF; 404f7917c00SJeff Kirsher if (advert & ADVERTISED_10baseT_Full) 405f7917c00SJeff Kirsher val |= ADVERTISE_10FULL; 406f7917c00SJeff Kirsher if (advert & ADVERTISED_100baseT_Half) 407f7917c00SJeff Kirsher val |= ADVERTISE_100HALF; 408f7917c00SJeff Kirsher if (advert & ADVERTISED_100baseT_Full) 409f7917c00SJeff Kirsher val |= ADVERTISE_100FULL; 410f7917c00SJeff Kirsher if (advert & ADVERTISED_Pause) 411f7917c00SJeff Kirsher val |= ADVERTISE_PAUSE_CAP; 412f7917c00SJeff Kirsher if (advert & ADVERTISED_Asym_Pause) 413f7917c00SJeff Kirsher val |= ADVERTISE_PAUSE_ASYM; 414f7917c00SJeff Kirsher return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); 415f7917c00SJeff Kirsher } 416f7917c00SJeff Kirsher 417f7917c00SJeff Kirsher /** 418f7917c00SJeff Kirsher * t3_phy_advertise_fiber - set fiber PHY advertisement register 419f7917c00SJeff Kirsher * @phy: the PHY to operate on 420f7917c00SJeff Kirsher * @advert: bitmap of capabilities the PHY should advertise 421f7917c00SJeff Kirsher * 422f7917c00SJeff Kirsher * Sets a fiber PHY's advertisement register to advertise the 423f7917c00SJeff Kirsher * requested capabilities. 424f7917c00SJeff Kirsher */ 425f7917c00SJeff Kirsher int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert) 426f7917c00SJeff Kirsher { 427f7917c00SJeff Kirsher unsigned int val = 0; 428f7917c00SJeff Kirsher 429f7917c00SJeff Kirsher if (advert & ADVERTISED_1000baseT_Half) 430f7917c00SJeff Kirsher val |= ADVERTISE_1000XHALF; 431f7917c00SJeff Kirsher if (advert & ADVERTISED_1000baseT_Full) 432f7917c00SJeff Kirsher val |= ADVERTISE_1000XFULL; 433f7917c00SJeff Kirsher if (advert & ADVERTISED_Pause) 434f7917c00SJeff Kirsher val |= ADVERTISE_1000XPAUSE; 435f7917c00SJeff Kirsher if (advert & ADVERTISED_Asym_Pause) 436f7917c00SJeff Kirsher val |= ADVERTISE_1000XPSE_ASYM; 437f7917c00SJeff Kirsher return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); 438f7917c00SJeff Kirsher } 439f7917c00SJeff Kirsher 440f7917c00SJeff Kirsher /** 441f7917c00SJeff Kirsher * t3_set_phy_speed_duplex - force PHY speed and duplex 442f7917c00SJeff Kirsher * @phy: the PHY to operate on 443f7917c00SJeff Kirsher * @speed: requested PHY speed 444f7917c00SJeff Kirsher * @duplex: requested PHY duplex 445f7917c00SJeff Kirsher * 446f7917c00SJeff Kirsher * Force a 10/100/1000 PHY's speed and duplex. This also disables 447f7917c00SJeff Kirsher * auto-negotiation except for GigE, where auto-negotiation is mandatory. 448f7917c00SJeff Kirsher */ 449f7917c00SJeff Kirsher int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) 450f7917c00SJeff Kirsher { 451f7917c00SJeff Kirsher int err; 452f7917c00SJeff Kirsher unsigned int ctl; 453f7917c00SJeff Kirsher 454f7917c00SJeff Kirsher err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl); 455f7917c00SJeff Kirsher if (err) 456f7917c00SJeff Kirsher return err; 457f7917c00SJeff Kirsher 458f7917c00SJeff Kirsher if (speed >= 0) { 459f7917c00SJeff Kirsher ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); 460f7917c00SJeff Kirsher if (speed == SPEED_100) 461f7917c00SJeff Kirsher ctl |= BMCR_SPEED100; 462f7917c00SJeff Kirsher else if (speed == SPEED_1000) 463f7917c00SJeff Kirsher ctl |= BMCR_SPEED1000; 464f7917c00SJeff Kirsher } 465f7917c00SJeff Kirsher if (duplex >= 0) { 466f7917c00SJeff Kirsher ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE); 467f7917c00SJeff Kirsher if (duplex == DUPLEX_FULL) 468f7917c00SJeff Kirsher ctl |= BMCR_FULLDPLX; 469f7917c00SJeff Kirsher } 470f7917c00SJeff Kirsher if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */ 471f7917c00SJeff Kirsher ctl |= BMCR_ANENABLE; 472f7917c00SJeff Kirsher return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl); 473f7917c00SJeff Kirsher } 474f7917c00SJeff Kirsher 475f7917c00SJeff Kirsher int t3_phy_lasi_intr_enable(struct cphy *phy) 476f7917c00SJeff Kirsher { 477f7917c00SJeff Kirsher return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 478f7917c00SJeff Kirsher MDIO_PMA_LASI_LSALARM); 479f7917c00SJeff Kirsher } 480f7917c00SJeff Kirsher 481f7917c00SJeff Kirsher int t3_phy_lasi_intr_disable(struct cphy *phy) 482f7917c00SJeff Kirsher { 483f7917c00SJeff Kirsher return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0); 484f7917c00SJeff Kirsher } 485f7917c00SJeff Kirsher 486f7917c00SJeff Kirsher int t3_phy_lasi_intr_clear(struct cphy *phy) 487f7917c00SJeff Kirsher { 488f7917c00SJeff Kirsher u32 val; 489f7917c00SJeff Kirsher 490f7917c00SJeff Kirsher return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); 491f7917c00SJeff Kirsher } 492f7917c00SJeff Kirsher 493f7917c00SJeff Kirsher int t3_phy_lasi_intr_handler(struct cphy *phy) 494f7917c00SJeff Kirsher { 495f7917c00SJeff Kirsher unsigned int status; 496f7917c00SJeff Kirsher int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, 497f7917c00SJeff Kirsher &status); 498f7917c00SJeff Kirsher 499f7917c00SJeff Kirsher if (err) 500f7917c00SJeff Kirsher return err; 501f7917c00SJeff Kirsher return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0; 502f7917c00SJeff Kirsher } 503f7917c00SJeff Kirsher 504f7917c00SJeff Kirsher static const struct adapter_info t3_adap_info[] = { 505f7917c00SJeff Kirsher {1, 1, 0, 506f7917c00SJeff Kirsher F_GPIO2_OEN | F_GPIO4_OEN | 507f7917c00SJeff Kirsher F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, 508f7917c00SJeff Kirsher &mi1_mdio_ops, "Chelsio PE9000"}, 509f7917c00SJeff Kirsher {1, 1, 0, 510f7917c00SJeff Kirsher F_GPIO2_OEN | F_GPIO4_OEN | 511f7917c00SJeff Kirsher F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, 512f7917c00SJeff Kirsher &mi1_mdio_ops, "Chelsio T302"}, 513f7917c00SJeff Kirsher {1, 0, 0, 514f7917c00SJeff Kirsher F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | 515f7917c00SJeff Kirsher F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 516f7917c00SJeff Kirsher { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, 517f7917c00SJeff Kirsher &mi1_mdio_ext_ops, "Chelsio T310"}, 518f7917c00SJeff Kirsher {1, 1, 0, 519f7917c00SJeff Kirsher F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | 520f7917c00SJeff Kirsher F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | 521f7917c00SJeff Kirsher F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 522f7917c00SJeff Kirsher { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, 523f7917c00SJeff Kirsher &mi1_mdio_ext_ops, "Chelsio T320"}, 524f7917c00SJeff Kirsher {}, 525f7917c00SJeff Kirsher {}, 526f7917c00SJeff Kirsher {1, 0, 0, 527f7917c00SJeff Kirsher F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN | 528f7917c00SJeff Kirsher F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 529f7917c00SJeff Kirsher { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, 530f7917c00SJeff Kirsher &mi1_mdio_ext_ops, "Chelsio T310" }, 531f7917c00SJeff Kirsher {1, 0, 0, 532f7917c00SJeff Kirsher F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | 533f7917c00SJeff Kirsher F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL, 534f7917c00SJeff Kirsher { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, 535f7917c00SJeff Kirsher &mi1_mdio_ext_ops, "Chelsio N320E-G2" }, 536f7917c00SJeff Kirsher }; 537f7917c00SJeff Kirsher 538f7917c00SJeff Kirsher /* 539f7917c00SJeff Kirsher * Return the adapter_info structure with a given index. Out-of-range indices 540f7917c00SJeff Kirsher * return NULL. 541f7917c00SJeff Kirsher */ 542f7917c00SJeff Kirsher const struct adapter_info *t3_get_adapter_info(unsigned int id) 543f7917c00SJeff Kirsher { 544f7917c00SJeff Kirsher return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; 545f7917c00SJeff Kirsher } 546f7917c00SJeff Kirsher 547f7917c00SJeff Kirsher struct port_type_info { 548f7917c00SJeff Kirsher int (*phy_prep)(struct cphy *phy, struct adapter *adapter, 549f7917c00SJeff Kirsher int phy_addr, const struct mdio_ops *ops); 550f7917c00SJeff Kirsher }; 551f7917c00SJeff Kirsher 552f7917c00SJeff Kirsher static const struct port_type_info port_types[] = { 553f7917c00SJeff Kirsher { NULL }, 554f7917c00SJeff Kirsher { t3_ael1002_phy_prep }, 555f7917c00SJeff Kirsher { t3_vsc8211_phy_prep }, 556f7917c00SJeff Kirsher { NULL}, 557f7917c00SJeff Kirsher { t3_xaui_direct_phy_prep }, 558f7917c00SJeff Kirsher { t3_ael2005_phy_prep }, 559f7917c00SJeff Kirsher { t3_qt2045_phy_prep }, 560f7917c00SJeff Kirsher { t3_ael1006_phy_prep }, 561f7917c00SJeff Kirsher { NULL }, 562f7917c00SJeff Kirsher { t3_aq100x_phy_prep }, 563f7917c00SJeff Kirsher { t3_ael2020_phy_prep }, 564f7917c00SJeff Kirsher }; 565f7917c00SJeff Kirsher 566f7917c00SJeff Kirsher #define VPD_ENTRY(name, len) \ 567f7917c00SJeff Kirsher u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] 568f7917c00SJeff Kirsher 569f7917c00SJeff Kirsher /* 570f7917c00SJeff Kirsher * Partial EEPROM Vital Product Data structure. Includes only the ID and 571f7917c00SJeff Kirsher * VPD-R sections. 572f7917c00SJeff Kirsher */ 573f7917c00SJeff Kirsher struct t3_vpd { 574f7917c00SJeff Kirsher u8 id_tag; 575f7917c00SJeff Kirsher u8 id_len[2]; 576f7917c00SJeff Kirsher u8 id_data[16]; 577f7917c00SJeff Kirsher u8 vpdr_tag; 578f7917c00SJeff Kirsher u8 vpdr_len[2]; 579f7917c00SJeff Kirsher VPD_ENTRY(pn, 16); /* part number */ 580f7917c00SJeff Kirsher VPD_ENTRY(ec, 16); /* EC level */ 581f7917c00SJeff Kirsher VPD_ENTRY(sn, SERNUM_LEN); /* serial number */ 582f7917c00SJeff Kirsher VPD_ENTRY(na, 12); /* MAC address base */ 583f7917c00SJeff Kirsher VPD_ENTRY(cclk, 6); /* core clock */ 584f7917c00SJeff Kirsher VPD_ENTRY(mclk, 6); /* mem clock */ 585f7917c00SJeff Kirsher VPD_ENTRY(uclk, 6); /* uP clk */ 586f7917c00SJeff Kirsher VPD_ENTRY(mdc, 6); /* MDIO clk */ 587f7917c00SJeff Kirsher VPD_ENTRY(mt, 2); /* mem timing */ 588f7917c00SJeff Kirsher VPD_ENTRY(xaui0cfg, 6); /* XAUI0 config */ 589f7917c00SJeff Kirsher VPD_ENTRY(xaui1cfg, 6); /* XAUI1 config */ 590f7917c00SJeff Kirsher VPD_ENTRY(port0, 2); /* PHY0 complex */ 591f7917c00SJeff Kirsher VPD_ENTRY(port1, 2); /* PHY1 complex */ 592f7917c00SJeff Kirsher VPD_ENTRY(port2, 2); /* PHY2 complex */ 593f7917c00SJeff Kirsher VPD_ENTRY(port3, 2); /* PHY3 complex */ 594f7917c00SJeff Kirsher VPD_ENTRY(rv, 1); /* csum */ 595f7917c00SJeff Kirsher u32 pad; /* for multiple-of-4 sizing and alignment */ 596f7917c00SJeff Kirsher }; 597f7917c00SJeff Kirsher 598f7917c00SJeff Kirsher #define EEPROM_MAX_POLL 40 599f7917c00SJeff Kirsher #define EEPROM_STAT_ADDR 0x4000 600f7917c00SJeff Kirsher #define VPD_BASE 0xc00 601f7917c00SJeff Kirsher 602f7917c00SJeff Kirsher /** 603f7917c00SJeff Kirsher * t3_seeprom_read - read a VPD EEPROM location 604f7917c00SJeff Kirsher * @adapter: adapter to read 605f7917c00SJeff Kirsher * @addr: EEPROM address 606f7917c00SJeff Kirsher * @data: where to store the read data 607f7917c00SJeff Kirsher * 608f7917c00SJeff Kirsher * Read a 32-bit word from a location in VPD EEPROM using the card's PCI 609f7917c00SJeff Kirsher * VPD ROM capability. A zero is written to the flag bit when the 610f7917c00SJeff Kirsher * address is written to the control register. The hardware device will 611f7917c00SJeff Kirsher * set the flag to 1 when 4 bytes have been read into the data register. 612f7917c00SJeff Kirsher */ 613f7917c00SJeff Kirsher int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data) 614f7917c00SJeff Kirsher { 615f7917c00SJeff Kirsher u16 val; 616f7917c00SJeff Kirsher int attempts = EEPROM_MAX_POLL; 617f7917c00SJeff Kirsher u32 v; 618f7917c00SJeff Kirsher unsigned int base = adapter->params.pci.vpd_cap_addr; 619f7917c00SJeff Kirsher 620f7917c00SJeff Kirsher if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) 621f7917c00SJeff Kirsher return -EINVAL; 622f7917c00SJeff Kirsher 623f7917c00SJeff Kirsher pci_write_config_word(adapter->pdev, base + PCI_VPD_ADDR, addr); 624f7917c00SJeff Kirsher do { 625f7917c00SJeff Kirsher udelay(10); 626f7917c00SJeff Kirsher pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); 627f7917c00SJeff Kirsher } while (!(val & PCI_VPD_ADDR_F) && --attempts); 628f7917c00SJeff Kirsher 629f7917c00SJeff Kirsher if (!(val & PCI_VPD_ADDR_F)) { 630f7917c00SJeff Kirsher CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr); 631f7917c00SJeff Kirsher return -EIO; 632f7917c00SJeff Kirsher } 633f7917c00SJeff Kirsher pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, &v); 634f7917c00SJeff Kirsher *data = cpu_to_le32(v); 635f7917c00SJeff Kirsher return 0; 636f7917c00SJeff Kirsher } 637f7917c00SJeff Kirsher 638f7917c00SJeff Kirsher /** 639f7917c00SJeff Kirsher * t3_seeprom_write - write a VPD EEPROM location 640f7917c00SJeff Kirsher * @adapter: adapter to write 641f7917c00SJeff Kirsher * @addr: EEPROM address 642f7917c00SJeff Kirsher * @data: value to write 643f7917c00SJeff Kirsher * 644f7917c00SJeff Kirsher * Write a 32-bit word to a location in VPD EEPROM using the card's PCI 645f7917c00SJeff Kirsher * VPD ROM capability. 646f7917c00SJeff Kirsher */ 647f7917c00SJeff Kirsher int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data) 648f7917c00SJeff Kirsher { 649f7917c00SJeff Kirsher u16 val; 650f7917c00SJeff Kirsher int attempts = EEPROM_MAX_POLL; 651f7917c00SJeff Kirsher unsigned int base = adapter->params.pci.vpd_cap_addr; 652f7917c00SJeff Kirsher 653f7917c00SJeff Kirsher if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) 654f7917c00SJeff Kirsher return -EINVAL; 655f7917c00SJeff Kirsher 656f7917c00SJeff Kirsher pci_write_config_dword(adapter->pdev, base + PCI_VPD_DATA, 657f7917c00SJeff Kirsher le32_to_cpu(data)); 658f7917c00SJeff Kirsher pci_write_config_word(adapter->pdev,base + PCI_VPD_ADDR, 659f7917c00SJeff Kirsher addr | PCI_VPD_ADDR_F); 660f7917c00SJeff Kirsher do { 661f7917c00SJeff Kirsher msleep(1); 662f7917c00SJeff Kirsher pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); 663f7917c00SJeff Kirsher } while ((val & PCI_VPD_ADDR_F) && --attempts); 664f7917c00SJeff Kirsher 665f7917c00SJeff Kirsher if (val & PCI_VPD_ADDR_F) { 666f7917c00SJeff Kirsher CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr); 667f7917c00SJeff Kirsher return -EIO; 668f7917c00SJeff Kirsher } 669f7917c00SJeff Kirsher return 0; 670f7917c00SJeff Kirsher } 671f7917c00SJeff Kirsher 672f7917c00SJeff Kirsher /** 673f7917c00SJeff Kirsher * t3_seeprom_wp - enable/disable EEPROM write protection 674f7917c00SJeff Kirsher * @adapter: the adapter 675f7917c00SJeff Kirsher * @enable: 1 to enable write protection, 0 to disable it 676f7917c00SJeff Kirsher * 677f7917c00SJeff Kirsher * Enables or disables write protection on the serial EEPROM. 678f7917c00SJeff Kirsher */ 679f7917c00SJeff Kirsher int t3_seeprom_wp(struct adapter *adapter, int enable) 680f7917c00SJeff Kirsher { 681f7917c00SJeff Kirsher return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0); 682f7917c00SJeff Kirsher } 683f7917c00SJeff Kirsher 684f7917c00SJeff Kirsher /** 685f7917c00SJeff Kirsher * get_vpd_params - read VPD parameters from VPD EEPROM 686f7917c00SJeff Kirsher * @adapter: adapter to read 687f7917c00SJeff Kirsher * @p: where to store the parameters 688f7917c00SJeff Kirsher * 689f7917c00SJeff Kirsher * Reads card parameters stored in VPD EEPROM. 690f7917c00SJeff Kirsher */ 691f7917c00SJeff Kirsher static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) 692f7917c00SJeff Kirsher { 693f7917c00SJeff Kirsher int i, addr, ret; 694f7917c00SJeff Kirsher struct t3_vpd vpd; 695f7917c00SJeff Kirsher 696f7917c00SJeff Kirsher /* 697f7917c00SJeff Kirsher * Card information is normally at VPD_BASE but some early cards had 698f7917c00SJeff Kirsher * it at 0. 699f7917c00SJeff Kirsher */ 700f7917c00SJeff Kirsher ret = t3_seeprom_read(adapter, VPD_BASE, (__le32 *)&vpd); 701f7917c00SJeff Kirsher if (ret) 702f7917c00SJeff Kirsher return ret; 703f7917c00SJeff Kirsher addr = vpd.id_tag == 0x82 ? VPD_BASE : 0; 704f7917c00SJeff Kirsher 705f7917c00SJeff Kirsher for (i = 0; i < sizeof(vpd); i += 4) { 706f7917c00SJeff Kirsher ret = t3_seeprom_read(adapter, addr + i, 707f7917c00SJeff Kirsher (__le32 *)((u8 *)&vpd + i)); 708f7917c00SJeff Kirsher if (ret) 709f7917c00SJeff Kirsher return ret; 710f7917c00SJeff Kirsher } 711f7917c00SJeff Kirsher 712f7917c00SJeff Kirsher p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10); 713f7917c00SJeff Kirsher p->mclk = simple_strtoul(vpd.mclk_data, NULL, 10); 714f7917c00SJeff Kirsher p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10); 715f7917c00SJeff Kirsher p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10); 716f7917c00SJeff Kirsher p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10); 717f7917c00SJeff Kirsher memcpy(p->sn, vpd.sn_data, SERNUM_LEN); 718f7917c00SJeff Kirsher 719f7917c00SJeff Kirsher /* Old eeproms didn't have port information */ 720f7917c00SJeff Kirsher if (adapter->params.rev == 0 && !vpd.port0_data[0]) { 721f7917c00SJeff Kirsher p->port_type[0] = uses_xaui(adapter) ? 1 : 2; 722f7917c00SJeff Kirsher p->port_type[1] = uses_xaui(adapter) ? 6 : 2; 723f7917c00SJeff Kirsher } else { 724f7917c00SJeff Kirsher p->port_type[0] = hex_to_bin(vpd.port0_data[0]); 725f7917c00SJeff Kirsher p->port_type[1] = hex_to_bin(vpd.port1_data[0]); 726f7917c00SJeff Kirsher p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16); 727f7917c00SJeff Kirsher p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16); 728f7917c00SJeff Kirsher } 729f7917c00SJeff Kirsher 7307aee42c6SAndy Shevchenko ret = hex2bin(p->eth_base, vpd.na_data, 6); 7317aee42c6SAndy Shevchenko if (ret < 0) 7327aee42c6SAndy Shevchenko return -EINVAL; 733f7917c00SJeff Kirsher return 0; 734f7917c00SJeff Kirsher } 735f7917c00SJeff Kirsher 736f7917c00SJeff Kirsher /* serial flash and firmware constants */ 737f7917c00SJeff Kirsher enum { 738f7917c00SJeff Kirsher SF_ATTEMPTS = 5, /* max retries for SF1 operations */ 739f7917c00SJeff Kirsher SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ 740f7917c00SJeff Kirsher SF_SIZE = SF_SEC_SIZE * 8, /* serial flash size */ 741f7917c00SJeff Kirsher 742f7917c00SJeff Kirsher /* flash command opcodes */ 743f7917c00SJeff Kirsher SF_PROG_PAGE = 2, /* program page */ 744f7917c00SJeff Kirsher SF_WR_DISABLE = 4, /* disable writes */ 745f7917c00SJeff Kirsher SF_RD_STATUS = 5, /* read status register */ 746f7917c00SJeff Kirsher SF_WR_ENABLE = 6, /* enable writes */ 747f7917c00SJeff Kirsher SF_RD_DATA_FAST = 0xb, /* read flash */ 748f7917c00SJeff Kirsher SF_ERASE_SECTOR = 0xd8, /* erase sector */ 749f7917c00SJeff Kirsher 750f7917c00SJeff Kirsher FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ 751f7917c00SJeff Kirsher FW_VERS_ADDR = 0x7fffc, /* flash address holding FW version */ 752f7917c00SJeff Kirsher FW_MIN_SIZE = 8 /* at least version and csum */ 753f7917c00SJeff Kirsher }; 754f7917c00SJeff Kirsher 755f7917c00SJeff Kirsher /** 756f7917c00SJeff Kirsher * sf1_read - read data from the serial flash 757f7917c00SJeff Kirsher * @adapter: the adapter 758f7917c00SJeff Kirsher * @byte_cnt: number of bytes to read 759f7917c00SJeff Kirsher * @cont: whether another operation will be chained 760f7917c00SJeff Kirsher * @valp: where to store the read data 761f7917c00SJeff Kirsher * 762f7917c00SJeff Kirsher * Reads up to 4 bytes of data from the serial flash. The location of 763f7917c00SJeff Kirsher * the read needs to be specified prior to calling this by issuing the 764f7917c00SJeff Kirsher * appropriate commands to the serial flash. 765f7917c00SJeff Kirsher */ 766f7917c00SJeff Kirsher static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont, 767f7917c00SJeff Kirsher u32 *valp) 768f7917c00SJeff Kirsher { 769f7917c00SJeff Kirsher int ret; 770f7917c00SJeff Kirsher 771f7917c00SJeff Kirsher if (!byte_cnt || byte_cnt > 4) 772f7917c00SJeff Kirsher return -EINVAL; 773f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) 774f7917c00SJeff Kirsher return -EBUSY; 775f7917c00SJeff Kirsher t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1)); 776f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10); 777f7917c00SJeff Kirsher if (!ret) 778f7917c00SJeff Kirsher *valp = t3_read_reg(adapter, A_SF_DATA); 779f7917c00SJeff Kirsher return ret; 780f7917c00SJeff Kirsher } 781f7917c00SJeff Kirsher 782f7917c00SJeff Kirsher /** 783f7917c00SJeff Kirsher * sf1_write - write data to the serial flash 784f7917c00SJeff Kirsher * @adapter: the adapter 785f7917c00SJeff Kirsher * @byte_cnt: number of bytes to write 786f7917c00SJeff Kirsher * @cont: whether another operation will be chained 787f7917c00SJeff Kirsher * @val: value to write 788f7917c00SJeff Kirsher * 789f7917c00SJeff Kirsher * Writes up to 4 bytes of data to the serial flash. The location of 790f7917c00SJeff Kirsher * the write needs to be specified prior to calling this by issuing the 791f7917c00SJeff Kirsher * appropriate commands to the serial flash. 792f7917c00SJeff Kirsher */ 793f7917c00SJeff Kirsher static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont, 794f7917c00SJeff Kirsher u32 val) 795f7917c00SJeff Kirsher { 796f7917c00SJeff Kirsher if (!byte_cnt || byte_cnt > 4) 797f7917c00SJeff Kirsher return -EINVAL; 798f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) 799f7917c00SJeff Kirsher return -EBUSY; 800f7917c00SJeff Kirsher t3_write_reg(adapter, A_SF_DATA, val); 801f7917c00SJeff Kirsher t3_write_reg(adapter, A_SF_OP, 802f7917c00SJeff Kirsher V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1)); 803f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10); 804f7917c00SJeff Kirsher } 805f7917c00SJeff Kirsher 806f7917c00SJeff Kirsher /** 807f7917c00SJeff Kirsher * flash_wait_op - wait for a flash operation to complete 808f7917c00SJeff Kirsher * @adapter: the adapter 809f7917c00SJeff Kirsher * @attempts: max number of polls of the status register 810f7917c00SJeff Kirsher * @delay: delay between polls in ms 811f7917c00SJeff Kirsher * 812f7917c00SJeff Kirsher * Wait for a flash operation to complete by polling the status register. 813f7917c00SJeff Kirsher */ 814f7917c00SJeff Kirsher static int flash_wait_op(struct adapter *adapter, int attempts, int delay) 815f7917c00SJeff Kirsher { 816f7917c00SJeff Kirsher int ret; 817f7917c00SJeff Kirsher u32 status; 818f7917c00SJeff Kirsher 819f7917c00SJeff Kirsher while (1) { 820f7917c00SJeff Kirsher if ((ret = sf1_write(adapter, 1, 1, SF_RD_STATUS)) != 0 || 821f7917c00SJeff Kirsher (ret = sf1_read(adapter, 1, 0, &status)) != 0) 822f7917c00SJeff Kirsher return ret; 823f7917c00SJeff Kirsher if (!(status & 1)) 824f7917c00SJeff Kirsher return 0; 825f7917c00SJeff Kirsher if (--attempts == 0) 826f7917c00SJeff Kirsher return -EAGAIN; 827f7917c00SJeff Kirsher if (delay) 828f7917c00SJeff Kirsher msleep(delay); 829f7917c00SJeff Kirsher } 830f7917c00SJeff Kirsher } 831f7917c00SJeff Kirsher 832f7917c00SJeff Kirsher /** 833f7917c00SJeff Kirsher * t3_read_flash - read words from serial flash 834f7917c00SJeff Kirsher * @adapter: the adapter 835f7917c00SJeff Kirsher * @addr: the start address for the read 836f7917c00SJeff Kirsher * @nwords: how many 32-bit words to read 837f7917c00SJeff Kirsher * @data: where to store the read data 838f7917c00SJeff Kirsher * @byte_oriented: whether to store data as bytes or as words 839f7917c00SJeff Kirsher * 840f7917c00SJeff Kirsher * Read the specified number of 32-bit words from the serial flash. 841f7917c00SJeff Kirsher * If @byte_oriented is set the read data is stored as a byte array 842f7917c00SJeff Kirsher * (i.e., big-endian), otherwise as 32-bit words in the platform's 843dbedd44eSJoe Perches * natural endianness. 844f7917c00SJeff Kirsher */ 845f7917c00SJeff Kirsher static int t3_read_flash(struct adapter *adapter, unsigned int addr, 846f7917c00SJeff Kirsher unsigned int nwords, u32 *data, int byte_oriented) 847f7917c00SJeff Kirsher { 848f7917c00SJeff Kirsher int ret; 849f7917c00SJeff Kirsher 850f7917c00SJeff Kirsher if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) 851f7917c00SJeff Kirsher return -EINVAL; 852f7917c00SJeff Kirsher 853f7917c00SJeff Kirsher addr = swab32(addr) | SF_RD_DATA_FAST; 854f7917c00SJeff Kirsher 855f7917c00SJeff Kirsher if ((ret = sf1_write(adapter, 4, 1, addr)) != 0 || 856f7917c00SJeff Kirsher (ret = sf1_read(adapter, 1, 1, data)) != 0) 857f7917c00SJeff Kirsher return ret; 858f7917c00SJeff Kirsher 859f7917c00SJeff Kirsher for (; nwords; nwords--, data++) { 860f7917c00SJeff Kirsher ret = sf1_read(adapter, 4, nwords > 1, data); 861f7917c00SJeff Kirsher if (ret) 862f7917c00SJeff Kirsher return ret; 863f7917c00SJeff Kirsher if (byte_oriented) 864f7917c00SJeff Kirsher *data = htonl(*data); 865f7917c00SJeff Kirsher } 866f7917c00SJeff Kirsher return 0; 867f7917c00SJeff Kirsher } 868f7917c00SJeff Kirsher 869f7917c00SJeff Kirsher /** 870f7917c00SJeff Kirsher * t3_write_flash - write up to a page of data to the serial flash 871f7917c00SJeff Kirsher * @adapter: the adapter 872f7917c00SJeff Kirsher * @addr: the start address to write 873f7917c00SJeff Kirsher * @n: length of data to write 874f7917c00SJeff Kirsher * @data: the data to write 875f7917c00SJeff Kirsher * 876f7917c00SJeff Kirsher * Writes up to a page of data (256 bytes) to the serial flash starting 877f7917c00SJeff Kirsher * at the given address. 878f7917c00SJeff Kirsher */ 879f7917c00SJeff Kirsher static int t3_write_flash(struct adapter *adapter, unsigned int addr, 880f7917c00SJeff Kirsher unsigned int n, const u8 *data) 881f7917c00SJeff Kirsher { 882f7917c00SJeff Kirsher int ret; 883f7917c00SJeff Kirsher u32 buf[64]; 884f7917c00SJeff Kirsher unsigned int i, c, left, val, offset = addr & 0xff; 885f7917c00SJeff Kirsher 886f7917c00SJeff Kirsher if (addr + n > SF_SIZE || offset + n > 256) 887f7917c00SJeff Kirsher return -EINVAL; 888f7917c00SJeff Kirsher 889f7917c00SJeff Kirsher val = swab32(addr) | SF_PROG_PAGE; 890f7917c00SJeff Kirsher 891f7917c00SJeff Kirsher if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 || 892f7917c00SJeff Kirsher (ret = sf1_write(adapter, 4, 1, val)) != 0) 893f7917c00SJeff Kirsher return ret; 894f7917c00SJeff Kirsher 895f7917c00SJeff Kirsher for (left = n; left; left -= c) { 896f7917c00SJeff Kirsher c = min(left, 4U); 897f7917c00SJeff Kirsher for (val = 0, i = 0; i < c; ++i) 898f7917c00SJeff Kirsher val = (val << 8) + *data++; 899f7917c00SJeff Kirsher 900f7917c00SJeff Kirsher ret = sf1_write(adapter, c, c != left, val); 901f7917c00SJeff Kirsher if (ret) 902f7917c00SJeff Kirsher return ret; 903f7917c00SJeff Kirsher } 904f7917c00SJeff Kirsher if ((ret = flash_wait_op(adapter, 5, 1)) != 0) 905f7917c00SJeff Kirsher return ret; 906f7917c00SJeff Kirsher 907f7917c00SJeff Kirsher /* Read the page to verify the write succeeded */ 908f7917c00SJeff Kirsher ret = t3_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1); 909f7917c00SJeff Kirsher if (ret) 910f7917c00SJeff Kirsher return ret; 911f7917c00SJeff Kirsher 912f7917c00SJeff Kirsher if (memcmp(data - n, (u8 *) buf + offset, n)) 913f7917c00SJeff Kirsher return -EIO; 914f7917c00SJeff Kirsher return 0; 915f7917c00SJeff Kirsher } 916f7917c00SJeff Kirsher 917f7917c00SJeff Kirsher /** 918f7917c00SJeff Kirsher * t3_get_tp_version - read the tp sram version 919f7917c00SJeff Kirsher * @adapter: the adapter 920f7917c00SJeff Kirsher * @vers: where to place the version 921f7917c00SJeff Kirsher * 922f7917c00SJeff Kirsher * Reads the protocol sram version from sram. 923f7917c00SJeff Kirsher */ 924f7917c00SJeff Kirsher int t3_get_tp_version(struct adapter *adapter, u32 *vers) 925f7917c00SJeff Kirsher { 926f7917c00SJeff Kirsher int ret; 927f7917c00SJeff Kirsher 928f7917c00SJeff Kirsher /* Get version loaded in SRAM */ 929f7917c00SJeff Kirsher t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0); 930f7917c00SJeff Kirsher ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0, 931f7917c00SJeff Kirsher 1, 1, 5, 1); 932f7917c00SJeff Kirsher if (ret) 933f7917c00SJeff Kirsher return ret; 934f7917c00SJeff Kirsher 935f7917c00SJeff Kirsher *vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1); 936f7917c00SJeff Kirsher 937f7917c00SJeff Kirsher return 0; 938f7917c00SJeff Kirsher } 939f7917c00SJeff Kirsher 940f7917c00SJeff Kirsher /** 941f7917c00SJeff Kirsher * t3_check_tpsram_version - read the tp sram version 942f7917c00SJeff Kirsher * @adapter: the adapter 943f7917c00SJeff Kirsher * 944f7917c00SJeff Kirsher * Reads the protocol sram version from flash. 945f7917c00SJeff Kirsher */ 946f7917c00SJeff Kirsher int t3_check_tpsram_version(struct adapter *adapter) 947f7917c00SJeff Kirsher { 948f7917c00SJeff Kirsher int ret; 949f7917c00SJeff Kirsher u32 vers; 950f7917c00SJeff Kirsher unsigned int major, minor; 951f7917c00SJeff Kirsher 952f7917c00SJeff Kirsher if (adapter->params.rev == T3_REV_A) 953f7917c00SJeff Kirsher return 0; 954f7917c00SJeff Kirsher 955f7917c00SJeff Kirsher 956f7917c00SJeff Kirsher ret = t3_get_tp_version(adapter, &vers); 957f7917c00SJeff Kirsher if (ret) 958f7917c00SJeff Kirsher return ret; 959f7917c00SJeff Kirsher 960f7917c00SJeff Kirsher major = G_TP_VERSION_MAJOR(vers); 961f7917c00SJeff Kirsher minor = G_TP_VERSION_MINOR(vers); 962f7917c00SJeff Kirsher 963f7917c00SJeff Kirsher if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) 964f7917c00SJeff Kirsher return 0; 965f7917c00SJeff Kirsher else { 966f7917c00SJeff Kirsher CH_ERR(adapter, "found wrong TP version (%u.%u), " 967f7917c00SJeff Kirsher "driver compiled for version %d.%d\n", major, minor, 968f7917c00SJeff Kirsher TP_VERSION_MAJOR, TP_VERSION_MINOR); 969f7917c00SJeff Kirsher } 970f7917c00SJeff Kirsher return -EINVAL; 971f7917c00SJeff Kirsher } 972f7917c00SJeff Kirsher 973f7917c00SJeff Kirsher /** 974f7917c00SJeff Kirsher * t3_check_tpsram - check if provided protocol SRAM 975f7917c00SJeff Kirsher * is compatible with this driver 976f7917c00SJeff Kirsher * @adapter: the adapter 977f7917c00SJeff Kirsher * @tp_sram: the firmware image to write 978f7917c00SJeff Kirsher * @size: image size 979f7917c00SJeff Kirsher * 980f7917c00SJeff Kirsher * Checks if an adapter's tp sram is compatible with the driver. 981f7917c00SJeff Kirsher * Returns 0 if the versions are compatible, a negative error otherwise. 982f7917c00SJeff Kirsher */ 983f7917c00SJeff Kirsher int t3_check_tpsram(struct adapter *adapter, const u8 *tp_sram, 984f7917c00SJeff Kirsher unsigned int size) 985f7917c00SJeff Kirsher { 986f7917c00SJeff Kirsher u32 csum; 987f7917c00SJeff Kirsher unsigned int i; 988f7917c00SJeff Kirsher const __be32 *p = (const __be32 *)tp_sram; 989f7917c00SJeff Kirsher 990f7917c00SJeff Kirsher /* Verify checksum */ 991f7917c00SJeff Kirsher for (csum = 0, i = 0; i < size / sizeof(csum); i++) 992f7917c00SJeff Kirsher csum += ntohl(p[i]); 993f7917c00SJeff Kirsher if (csum != 0xffffffff) { 994f7917c00SJeff Kirsher CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n", 995f7917c00SJeff Kirsher csum); 996f7917c00SJeff Kirsher return -EINVAL; 997f7917c00SJeff Kirsher } 998f7917c00SJeff Kirsher 999f7917c00SJeff Kirsher return 0; 1000f7917c00SJeff Kirsher } 1001f7917c00SJeff Kirsher 1002f7917c00SJeff Kirsher enum fw_version_type { 1003f7917c00SJeff Kirsher FW_VERSION_N3, 1004f7917c00SJeff Kirsher FW_VERSION_T3 1005f7917c00SJeff Kirsher }; 1006f7917c00SJeff Kirsher 1007f7917c00SJeff Kirsher /** 1008f7917c00SJeff Kirsher * t3_get_fw_version - read the firmware version 1009f7917c00SJeff Kirsher * @adapter: the adapter 1010f7917c00SJeff Kirsher * @vers: where to place the version 1011f7917c00SJeff Kirsher * 1012f7917c00SJeff Kirsher * Reads the FW version from flash. 1013f7917c00SJeff Kirsher */ 1014f7917c00SJeff Kirsher int t3_get_fw_version(struct adapter *adapter, u32 *vers) 1015f7917c00SJeff Kirsher { 1016f7917c00SJeff Kirsher return t3_read_flash(adapter, FW_VERS_ADDR, 1, vers, 0); 1017f7917c00SJeff Kirsher } 1018f7917c00SJeff Kirsher 1019f7917c00SJeff Kirsher /** 1020f7917c00SJeff Kirsher * t3_check_fw_version - check if the FW is compatible with this driver 1021f7917c00SJeff Kirsher * @adapter: the adapter 1022f7917c00SJeff Kirsher * 1023f7917c00SJeff Kirsher * Checks if an adapter's FW is compatible with the driver. Returns 0 1024f7917c00SJeff Kirsher * if the versions are compatible, a negative error otherwise. 1025f7917c00SJeff Kirsher */ 1026f7917c00SJeff Kirsher int t3_check_fw_version(struct adapter *adapter) 1027f7917c00SJeff Kirsher { 1028f7917c00SJeff Kirsher int ret; 1029f7917c00SJeff Kirsher u32 vers; 1030f7917c00SJeff Kirsher unsigned int type, major, minor; 1031f7917c00SJeff Kirsher 1032f7917c00SJeff Kirsher ret = t3_get_fw_version(adapter, &vers); 1033f7917c00SJeff Kirsher if (ret) 1034f7917c00SJeff Kirsher return ret; 1035f7917c00SJeff Kirsher 1036f7917c00SJeff Kirsher type = G_FW_VERSION_TYPE(vers); 1037f7917c00SJeff Kirsher major = G_FW_VERSION_MAJOR(vers); 1038f7917c00SJeff Kirsher minor = G_FW_VERSION_MINOR(vers); 1039f7917c00SJeff Kirsher 1040f7917c00SJeff Kirsher if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR && 1041f7917c00SJeff Kirsher minor == FW_VERSION_MINOR) 1042f7917c00SJeff Kirsher return 0; 1043f7917c00SJeff Kirsher else if (major != FW_VERSION_MAJOR || minor < FW_VERSION_MINOR) 1044f7917c00SJeff Kirsher CH_WARN(adapter, "found old FW minor version(%u.%u), " 1045f7917c00SJeff Kirsher "driver compiled for version %u.%u\n", major, minor, 1046f7917c00SJeff Kirsher FW_VERSION_MAJOR, FW_VERSION_MINOR); 1047f7917c00SJeff Kirsher else { 1048f7917c00SJeff Kirsher CH_WARN(adapter, "found newer FW version(%u.%u), " 1049f7917c00SJeff Kirsher "driver compiled for version %u.%u\n", major, minor, 1050f7917c00SJeff Kirsher FW_VERSION_MAJOR, FW_VERSION_MINOR); 1051f7917c00SJeff Kirsher return 0; 1052f7917c00SJeff Kirsher } 1053f7917c00SJeff Kirsher return -EINVAL; 1054f7917c00SJeff Kirsher } 1055f7917c00SJeff Kirsher 1056f7917c00SJeff Kirsher /** 1057f7917c00SJeff Kirsher * t3_flash_erase_sectors - erase a range of flash sectors 1058f7917c00SJeff Kirsher * @adapter: the adapter 1059f7917c00SJeff Kirsher * @start: the first sector to erase 1060f7917c00SJeff Kirsher * @end: the last sector to erase 1061f7917c00SJeff Kirsher * 1062f7917c00SJeff Kirsher * Erases the sectors in the given range. 1063f7917c00SJeff Kirsher */ 1064f7917c00SJeff Kirsher static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end) 1065f7917c00SJeff Kirsher { 1066f7917c00SJeff Kirsher while (start <= end) { 1067f7917c00SJeff Kirsher int ret; 1068f7917c00SJeff Kirsher 1069f7917c00SJeff Kirsher if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 || 1070f7917c00SJeff Kirsher (ret = sf1_write(adapter, 4, 0, 1071f7917c00SJeff Kirsher SF_ERASE_SECTOR | (start << 8))) != 0 || 1072f7917c00SJeff Kirsher (ret = flash_wait_op(adapter, 5, 500)) != 0) 1073f7917c00SJeff Kirsher return ret; 1074f7917c00SJeff Kirsher start++; 1075f7917c00SJeff Kirsher } 1076f7917c00SJeff Kirsher return 0; 1077f7917c00SJeff Kirsher } 1078f7917c00SJeff Kirsher 107949ce9c2cSBen Hutchings /** 1080f7917c00SJeff Kirsher * t3_load_fw - download firmware 1081f7917c00SJeff Kirsher * @adapter: the adapter 1082f7917c00SJeff Kirsher * @fw_data: the firmware image to write 1083f7917c00SJeff Kirsher * @size: image size 1084f7917c00SJeff Kirsher * 1085f7917c00SJeff Kirsher * Write the supplied firmware image to the card's serial flash. 1086f7917c00SJeff Kirsher * The FW image has the following sections: @size - 8 bytes of code and 1087f7917c00SJeff Kirsher * data, followed by 4 bytes of FW version, followed by the 32-bit 1088f7917c00SJeff Kirsher * 1's complement checksum of the whole image. 1089f7917c00SJeff Kirsher */ 1090f7917c00SJeff Kirsher int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size) 1091f7917c00SJeff Kirsher { 1092f7917c00SJeff Kirsher u32 csum; 1093f7917c00SJeff Kirsher unsigned int i; 1094f7917c00SJeff Kirsher const __be32 *p = (const __be32 *)fw_data; 1095f7917c00SJeff Kirsher int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16; 1096f7917c00SJeff Kirsher 1097f7917c00SJeff Kirsher if ((size & 3) || size < FW_MIN_SIZE) 1098f7917c00SJeff Kirsher return -EINVAL; 1099f7917c00SJeff Kirsher if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR) 1100f7917c00SJeff Kirsher return -EFBIG; 1101f7917c00SJeff Kirsher 1102f7917c00SJeff Kirsher for (csum = 0, i = 0; i < size / sizeof(csum); i++) 1103f7917c00SJeff Kirsher csum += ntohl(p[i]); 1104f7917c00SJeff Kirsher if (csum != 0xffffffff) { 1105f7917c00SJeff Kirsher CH_ERR(adapter, "corrupted firmware image, checksum %u\n", 1106f7917c00SJeff Kirsher csum); 1107f7917c00SJeff Kirsher return -EINVAL; 1108f7917c00SJeff Kirsher } 1109f7917c00SJeff Kirsher 1110f7917c00SJeff Kirsher ret = t3_flash_erase_sectors(adapter, fw_sector, fw_sector); 1111f7917c00SJeff Kirsher if (ret) 1112f7917c00SJeff Kirsher goto out; 1113f7917c00SJeff Kirsher 1114f7917c00SJeff Kirsher size -= 8; /* trim off version and checksum */ 1115f7917c00SJeff Kirsher for (addr = FW_FLASH_BOOT_ADDR; size;) { 1116f7917c00SJeff Kirsher unsigned int chunk_size = min(size, 256U); 1117f7917c00SJeff Kirsher 1118f7917c00SJeff Kirsher ret = t3_write_flash(adapter, addr, chunk_size, fw_data); 1119f7917c00SJeff Kirsher if (ret) 1120f7917c00SJeff Kirsher goto out; 1121f7917c00SJeff Kirsher 1122f7917c00SJeff Kirsher addr += chunk_size; 1123f7917c00SJeff Kirsher fw_data += chunk_size; 1124f7917c00SJeff Kirsher size -= chunk_size; 1125f7917c00SJeff Kirsher } 1126f7917c00SJeff Kirsher 1127f7917c00SJeff Kirsher ret = t3_write_flash(adapter, FW_VERS_ADDR, 4, fw_data); 1128f7917c00SJeff Kirsher out: 1129f7917c00SJeff Kirsher if (ret) 1130f7917c00SJeff Kirsher CH_ERR(adapter, "firmware download failed, error %d\n", ret); 1131f7917c00SJeff Kirsher return ret; 1132f7917c00SJeff Kirsher } 1133f7917c00SJeff Kirsher 1134f7917c00SJeff Kirsher #define CIM_CTL_BASE 0x2000 1135f7917c00SJeff Kirsher 1136f7917c00SJeff Kirsher /** 1137f7917c00SJeff Kirsher * t3_cim_ctl_blk_read - read a block from CIM control region 1138f7917c00SJeff Kirsher * 1139f7917c00SJeff Kirsher * @adap: the adapter 1140f7917c00SJeff Kirsher * @addr: the start address within the CIM control region 1141f7917c00SJeff Kirsher * @n: number of words to read 1142f7917c00SJeff Kirsher * @valp: where to store the result 1143f7917c00SJeff Kirsher * 1144f7917c00SJeff Kirsher * Reads a block of 4-byte words from the CIM control region. 1145f7917c00SJeff Kirsher */ 1146f7917c00SJeff Kirsher int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr, 1147f7917c00SJeff Kirsher unsigned int n, unsigned int *valp) 1148f7917c00SJeff Kirsher { 1149f7917c00SJeff Kirsher int ret = 0; 1150f7917c00SJeff Kirsher 1151f7917c00SJeff Kirsher if (t3_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY) 1152f7917c00SJeff Kirsher return -EBUSY; 1153f7917c00SJeff Kirsher 1154f7917c00SJeff Kirsher for ( ; !ret && n--; addr += 4) { 1155f7917c00SJeff Kirsher t3_write_reg(adap, A_CIM_HOST_ACC_CTRL, CIM_CTL_BASE + addr); 1156f7917c00SJeff Kirsher ret = t3_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY, 1157f7917c00SJeff Kirsher 0, 5, 2); 1158f7917c00SJeff Kirsher if (!ret) 1159f7917c00SJeff Kirsher *valp++ = t3_read_reg(adap, A_CIM_HOST_ACC_DATA); 1160f7917c00SJeff Kirsher } 1161f7917c00SJeff Kirsher return ret; 1162f7917c00SJeff Kirsher } 1163f7917c00SJeff Kirsher 1164f7917c00SJeff Kirsher static void t3_gate_rx_traffic(struct cmac *mac, u32 *rx_cfg, 1165f7917c00SJeff Kirsher u32 *rx_hash_high, u32 *rx_hash_low) 1166f7917c00SJeff Kirsher { 1167f7917c00SJeff Kirsher /* stop Rx unicast traffic */ 1168f7917c00SJeff Kirsher t3_mac_disable_exact_filters(mac); 1169f7917c00SJeff Kirsher 1170f7917c00SJeff Kirsher /* stop broadcast, multicast, promiscuous mode traffic */ 1171f7917c00SJeff Kirsher *rx_cfg = t3_read_reg(mac->adapter, A_XGM_RX_CFG); 1172f7917c00SJeff Kirsher t3_set_reg_field(mac->adapter, A_XGM_RX_CFG, 1173f7917c00SJeff Kirsher F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES, 1174f7917c00SJeff Kirsher F_DISBCAST); 1175f7917c00SJeff Kirsher 1176f7917c00SJeff Kirsher *rx_hash_high = t3_read_reg(mac->adapter, A_XGM_RX_HASH_HIGH); 1177f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, 0); 1178f7917c00SJeff Kirsher 1179f7917c00SJeff Kirsher *rx_hash_low = t3_read_reg(mac->adapter, A_XGM_RX_HASH_LOW); 1180f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, 0); 1181f7917c00SJeff Kirsher 1182f7917c00SJeff Kirsher /* Leave time to drain max RX fifo */ 1183f7917c00SJeff Kirsher msleep(1); 1184f7917c00SJeff Kirsher } 1185f7917c00SJeff Kirsher 1186f7917c00SJeff Kirsher static void t3_open_rx_traffic(struct cmac *mac, u32 rx_cfg, 1187f7917c00SJeff Kirsher u32 rx_hash_high, u32 rx_hash_low) 1188f7917c00SJeff Kirsher { 1189f7917c00SJeff Kirsher t3_mac_enable_exact_filters(mac); 1190f7917c00SJeff Kirsher t3_set_reg_field(mac->adapter, A_XGM_RX_CFG, 1191f7917c00SJeff Kirsher F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES, 1192f7917c00SJeff Kirsher rx_cfg); 1193f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, rx_hash_high); 1194f7917c00SJeff Kirsher t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, rx_hash_low); 1195f7917c00SJeff Kirsher } 1196f7917c00SJeff Kirsher 1197f7917c00SJeff Kirsher /** 1198f7917c00SJeff Kirsher * t3_link_changed - handle interface link changes 1199f7917c00SJeff Kirsher * @adapter: the adapter 1200f7917c00SJeff Kirsher * @port_id: the port index that changed link state 1201f7917c00SJeff Kirsher * 1202f7917c00SJeff Kirsher * Called when a port's link settings change to propagate the new values 1203f7917c00SJeff Kirsher * to the associated PHY and MAC. After performing the common tasks it 1204f7917c00SJeff Kirsher * invokes an OS-specific handler. 1205f7917c00SJeff Kirsher */ 1206f7917c00SJeff Kirsher void t3_link_changed(struct adapter *adapter, int port_id) 1207f7917c00SJeff Kirsher { 1208f7917c00SJeff Kirsher int link_ok, speed, duplex, fc; 1209f7917c00SJeff Kirsher struct port_info *pi = adap2pinfo(adapter, port_id); 1210f7917c00SJeff Kirsher struct cphy *phy = &pi->phy; 1211f7917c00SJeff Kirsher struct cmac *mac = &pi->mac; 1212f7917c00SJeff Kirsher struct link_config *lc = &pi->link_config; 1213f7917c00SJeff Kirsher 1214f7917c00SJeff Kirsher phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); 1215f7917c00SJeff Kirsher 1216f7917c00SJeff Kirsher if (!lc->link_ok && link_ok) { 1217f7917c00SJeff Kirsher u32 rx_cfg, rx_hash_high, rx_hash_low; 1218f7917c00SJeff Kirsher u32 status; 1219f7917c00SJeff Kirsher 1220f7917c00SJeff Kirsher t3_xgm_intr_enable(adapter, port_id); 1221f7917c00SJeff Kirsher t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low); 1222f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0); 1223f7917c00SJeff Kirsher t3_mac_enable(mac, MAC_DIRECTION_RX); 1224f7917c00SJeff Kirsher 1225f7917c00SJeff Kirsher status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset); 1226f7917c00SJeff Kirsher if (status & F_LINKFAULTCHANGE) { 1227f7917c00SJeff Kirsher mac->stats.link_faults++; 1228f7917c00SJeff Kirsher pi->link_fault = 1; 1229f7917c00SJeff Kirsher } 1230f7917c00SJeff Kirsher t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low); 1231f7917c00SJeff Kirsher } 1232f7917c00SJeff Kirsher 1233f7917c00SJeff Kirsher if (lc->requested_fc & PAUSE_AUTONEG) 1234f7917c00SJeff Kirsher fc &= lc->requested_fc; 1235f7917c00SJeff Kirsher else 1236f7917c00SJeff Kirsher fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); 1237f7917c00SJeff Kirsher 1238f7917c00SJeff Kirsher if (link_ok == lc->link_ok && speed == lc->speed && 1239f7917c00SJeff Kirsher duplex == lc->duplex && fc == lc->fc) 1240f7917c00SJeff Kirsher return; /* nothing changed */ 1241f7917c00SJeff Kirsher 1242f7917c00SJeff Kirsher if (link_ok != lc->link_ok && adapter->params.rev > 0 && 1243f7917c00SJeff Kirsher uses_xaui(adapter)) { 1244f7917c00SJeff Kirsher if (link_ok) 1245f7917c00SJeff Kirsher t3b_pcs_reset(mac); 1246f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 1247f7917c00SJeff Kirsher link_ok ? F_TXACTENABLE | F_RXEN : 0); 1248f7917c00SJeff Kirsher } 1249f7917c00SJeff Kirsher lc->link_ok = link_ok; 1250f7917c00SJeff Kirsher lc->speed = speed < 0 ? SPEED_INVALID : speed; 1251f7917c00SJeff Kirsher lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; 1252f7917c00SJeff Kirsher 1253f7917c00SJeff Kirsher if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { 1254f7917c00SJeff Kirsher /* Set MAC speed, duplex, and flow control to match PHY. */ 1255f7917c00SJeff Kirsher t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc); 1256f7917c00SJeff Kirsher lc->fc = fc; 1257f7917c00SJeff Kirsher } 1258f7917c00SJeff Kirsher 1259f7917c00SJeff Kirsher t3_os_link_changed(adapter, port_id, link_ok && !pi->link_fault, 1260f7917c00SJeff Kirsher speed, duplex, fc); 1261f7917c00SJeff Kirsher } 1262f7917c00SJeff Kirsher 1263f7917c00SJeff Kirsher void t3_link_fault(struct adapter *adapter, int port_id) 1264f7917c00SJeff Kirsher { 1265f7917c00SJeff Kirsher struct port_info *pi = adap2pinfo(adapter, port_id); 1266f7917c00SJeff Kirsher struct cmac *mac = &pi->mac; 1267f7917c00SJeff Kirsher struct cphy *phy = &pi->phy; 1268f7917c00SJeff Kirsher struct link_config *lc = &pi->link_config; 1269f7917c00SJeff Kirsher int link_ok, speed, duplex, fc, link_fault; 1270f7917c00SJeff Kirsher u32 rx_cfg, rx_hash_high, rx_hash_low; 1271f7917c00SJeff Kirsher 1272f7917c00SJeff Kirsher t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low); 1273f7917c00SJeff Kirsher 1274f7917c00SJeff Kirsher if (adapter->params.rev > 0 && uses_xaui(adapter)) 1275f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 0); 1276f7917c00SJeff Kirsher 1277f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0); 1278f7917c00SJeff Kirsher t3_mac_enable(mac, MAC_DIRECTION_RX); 1279f7917c00SJeff Kirsher 1280f7917c00SJeff Kirsher t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low); 1281f7917c00SJeff Kirsher 1282f7917c00SJeff Kirsher link_fault = t3_read_reg(adapter, 1283f7917c00SJeff Kirsher A_XGM_INT_STATUS + mac->offset); 1284f7917c00SJeff Kirsher link_fault &= F_LINKFAULTCHANGE; 1285f7917c00SJeff Kirsher 1286f7917c00SJeff Kirsher link_ok = lc->link_ok; 1287f7917c00SJeff Kirsher speed = lc->speed; 1288f7917c00SJeff Kirsher duplex = lc->duplex; 1289f7917c00SJeff Kirsher fc = lc->fc; 1290f7917c00SJeff Kirsher 1291f7917c00SJeff Kirsher phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); 1292f7917c00SJeff Kirsher 1293f7917c00SJeff Kirsher if (link_fault) { 1294f7917c00SJeff Kirsher lc->link_ok = 0; 1295f7917c00SJeff Kirsher lc->speed = SPEED_INVALID; 1296f7917c00SJeff Kirsher lc->duplex = DUPLEX_INVALID; 1297f7917c00SJeff Kirsher 1298f7917c00SJeff Kirsher t3_os_link_fault(adapter, port_id, 0); 1299f7917c00SJeff Kirsher 1300f7917c00SJeff Kirsher /* Account link faults only when the phy reports a link up */ 1301f7917c00SJeff Kirsher if (link_ok) 1302f7917c00SJeff Kirsher mac->stats.link_faults++; 1303f7917c00SJeff Kirsher } else { 1304f7917c00SJeff Kirsher if (link_ok) 1305f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 1306f7917c00SJeff Kirsher F_TXACTENABLE | F_RXEN); 1307f7917c00SJeff Kirsher 1308f7917c00SJeff Kirsher pi->link_fault = 0; 1309f7917c00SJeff Kirsher lc->link_ok = (unsigned char)link_ok; 1310f7917c00SJeff Kirsher lc->speed = speed < 0 ? SPEED_INVALID : speed; 1311f7917c00SJeff Kirsher lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; 1312f7917c00SJeff Kirsher t3_os_link_fault(adapter, port_id, link_ok); 1313f7917c00SJeff Kirsher } 1314f7917c00SJeff Kirsher } 1315f7917c00SJeff Kirsher 1316f7917c00SJeff Kirsher /** 1317f7917c00SJeff Kirsher * t3_link_start - apply link configuration to MAC/PHY 1318f7917c00SJeff Kirsher * @phy: the PHY to setup 1319f7917c00SJeff Kirsher * @mac: the MAC to setup 1320f7917c00SJeff Kirsher * @lc: the requested link configuration 1321f7917c00SJeff Kirsher * 1322f7917c00SJeff Kirsher * Set up a port's MAC and PHY according to a desired link configuration. 1323f7917c00SJeff Kirsher * - If the PHY can auto-negotiate first decide what to advertise, then 1324f7917c00SJeff Kirsher * enable/disable auto-negotiation as desired, and reset. 1325f7917c00SJeff Kirsher * - If the PHY does not auto-negotiate just reset it. 1326f7917c00SJeff Kirsher * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC, 1327f7917c00SJeff Kirsher * otherwise do it later based on the outcome of auto-negotiation. 1328f7917c00SJeff Kirsher */ 1329f7917c00SJeff Kirsher int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) 1330f7917c00SJeff Kirsher { 1331f7917c00SJeff Kirsher unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); 1332f7917c00SJeff Kirsher 1333f7917c00SJeff Kirsher lc->link_ok = 0; 1334f7917c00SJeff Kirsher if (lc->supported & SUPPORTED_Autoneg) { 1335f7917c00SJeff Kirsher lc->advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause); 1336f7917c00SJeff Kirsher if (fc) { 1337f7917c00SJeff Kirsher lc->advertising |= ADVERTISED_Asym_Pause; 1338f7917c00SJeff Kirsher if (fc & PAUSE_RX) 1339f7917c00SJeff Kirsher lc->advertising |= ADVERTISED_Pause; 1340f7917c00SJeff Kirsher } 1341f7917c00SJeff Kirsher phy->ops->advertise(phy, lc->advertising); 1342f7917c00SJeff Kirsher 1343f7917c00SJeff Kirsher if (lc->autoneg == AUTONEG_DISABLE) { 1344f7917c00SJeff Kirsher lc->speed = lc->requested_speed; 1345f7917c00SJeff Kirsher lc->duplex = lc->requested_duplex; 1346f7917c00SJeff Kirsher lc->fc = (unsigned char)fc; 1347f7917c00SJeff Kirsher t3_mac_set_speed_duplex_fc(mac, lc->speed, lc->duplex, 1348f7917c00SJeff Kirsher fc); 1349f7917c00SJeff Kirsher /* Also disables autoneg */ 1350f7917c00SJeff Kirsher phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); 1351f7917c00SJeff Kirsher } else 1352f7917c00SJeff Kirsher phy->ops->autoneg_enable(phy); 1353f7917c00SJeff Kirsher } else { 1354f7917c00SJeff Kirsher t3_mac_set_speed_duplex_fc(mac, -1, -1, fc); 1355f7917c00SJeff Kirsher lc->fc = (unsigned char)fc; 1356f7917c00SJeff Kirsher phy->ops->reset(phy, 0); 1357f7917c00SJeff Kirsher } 1358f7917c00SJeff Kirsher return 0; 1359f7917c00SJeff Kirsher } 1360f7917c00SJeff Kirsher 1361f7917c00SJeff Kirsher /** 1362f7917c00SJeff Kirsher * t3_set_vlan_accel - control HW VLAN extraction 1363f7917c00SJeff Kirsher * @adapter: the adapter 1364f7917c00SJeff Kirsher * @ports: bitmap of adapter ports to operate on 1365f7917c00SJeff Kirsher * @on: enable (1) or disable (0) HW VLAN extraction 1366f7917c00SJeff Kirsher * 1367f7917c00SJeff Kirsher * Enables or disables HW extraction of VLAN tags for the given port. 1368f7917c00SJeff Kirsher */ 1369f7917c00SJeff Kirsher void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on) 1370f7917c00SJeff Kirsher { 1371f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_TP_OUT_CONFIG, 1372f7917c00SJeff Kirsher ports << S_VLANEXTRACTIONENABLE, 1373f7917c00SJeff Kirsher on ? (ports << S_VLANEXTRACTIONENABLE) : 0); 1374f7917c00SJeff Kirsher } 1375f7917c00SJeff Kirsher 1376f7917c00SJeff Kirsher struct intr_info { 1377f7917c00SJeff Kirsher unsigned int mask; /* bits to check in interrupt status */ 1378f7917c00SJeff Kirsher const char *msg; /* message to print or NULL */ 1379f7917c00SJeff Kirsher short stat_idx; /* stat counter to increment or -1 */ 1380f7917c00SJeff Kirsher unsigned short fatal; /* whether the condition reported is fatal */ 1381f7917c00SJeff Kirsher }; 1382f7917c00SJeff Kirsher 1383f7917c00SJeff Kirsher /** 1384f7917c00SJeff Kirsher * t3_handle_intr_status - table driven interrupt handler 1385f7917c00SJeff Kirsher * @adapter: the adapter that generated the interrupt 1386f7917c00SJeff Kirsher * @reg: the interrupt status register to process 1387f7917c00SJeff Kirsher * @mask: a mask to apply to the interrupt status 1388f7917c00SJeff Kirsher * @acts: table of interrupt actions 1389f7917c00SJeff Kirsher * @stats: statistics counters tracking interrupt occurrences 1390f7917c00SJeff Kirsher * 1391f7917c00SJeff Kirsher * A table driven interrupt handler that applies a set of masks to an 1392f7917c00SJeff Kirsher * interrupt status word and performs the corresponding actions if the 1393f7917c00SJeff Kirsher * interrupts described by the mask have occurred. The actions include 1394f7917c00SJeff Kirsher * optionally printing a warning or alert message, and optionally 1395f7917c00SJeff Kirsher * incrementing a stat counter. The table is terminated by an entry 1396f7917c00SJeff Kirsher * specifying mask 0. Returns the number of fatal interrupt conditions. 1397f7917c00SJeff Kirsher */ 1398f7917c00SJeff Kirsher static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg, 1399f7917c00SJeff Kirsher unsigned int mask, 1400f7917c00SJeff Kirsher const struct intr_info *acts, 1401f7917c00SJeff Kirsher unsigned long *stats) 1402f7917c00SJeff Kirsher { 1403f7917c00SJeff Kirsher int fatal = 0; 1404f7917c00SJeff Kirsher unsigned int status = t3_read_reg(adapter, reg) & mask; 1405f7917c00SJeff Kirsher 1406f7917c00SJeff Kirsher for (; acts->mask; ++acts) { 1407f7917c00SJeff Kirsher if (!(status & acts->mask)) 1408f7917c00SJeff Kirsher continue; 1409f7917c00SJeff Kirsher if (acts->fatal) { 1410f7917c00SJeff Kirsher fatal++; 1411f7917c00SJeff Kirsher CH_ALERT(adapter, "%s (0x%x)\n", 1412f7917c00SJeff Kirsher acts->msg, status & acts->mask); 1413f7917c00SJeff Kirsher status &= ~acts->mask; 1414f7917c00SJeff Kirsher } else if (acts->msg) 1415f7917c00SJeff Kirsher CH_WARN(adapter, "%s (0x%x)\n", 1416f7917c00SJeff Kirsher acts->msg, status & acts->mask); 1417f7917c00SJeff Kirsher if (acts->stat_idx >= 0) 1418f7917c00SJeff Kirsher stats[acts->stat_idx]++; 1419f7917c00SJeff Kirsher } 1420f7917c00SJeff Kirsher if (status) /* clear processed interrupts */ 1421f7917c00SJeff Kirsher t3_write_reg(adapter, reg, status); 1422f7917c00SJeff Kirsher return fatal; 1423f7917c00SJeff Kirsher } 1424f7917c00SJeff Kirsher 1425f7917c00SJeff Kirsher #define SGE_INTR_MASK (F_RSPQDISABLED | \ 1426f7917c00SJeff Kirsher F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR | \ 1427f7917c00SJeff Kirsher F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \ 1428f7917c00SJeff Kirsher F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \ 1429f7917c00SJeff Kirsher V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \ 1430f7917c00SJeff Kirsher F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \ 1431f7917c00SJeff Kirsher F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \ 1432f7917c00SJeff Kirsher F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \ 1433f7917c00SJeff Kirsher F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \ 1434f7917c00SJeff Kirsher F_LOPIODRBDROPERR) 1435f7917c00SJeff Kirsher #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \ 1436f7917c00SJeff Kirsher F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \ 1437f7917c00SJeff Kirsher F_NFASRCHFAIL) 1438f7917c00SJeff Kirsher #define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE)) 1439f7917c00SJeff Kirsher #define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ 1440f7917c00SJeff Kirsher V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \ 1441f7917c00SJeff Kirsher F_TXFIFO_UNDERRUN) 1442f7917c00SJeff Kirsher #define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \ 1443f7917c00SJeff Kirsher F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \ 1444f7917c00SJeff Kirsher F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \ 1445f7917c00SJeff Kirsher F_DETCORECCERR | F_DETUNCECCERR | F_PIOPARERR | \ 1446f7917c00SJeff Kirsher V_WFPARERR(M_WFPARERR) | V_RFPARERR(M_RFPARERR) | \ 1447f7917c00SJeff Kirsher V_CFPARERR(M_CFPARERR) /* | V_MSIXPARERR(M_MSIXPARERR) */) 1448f7917c00SJeff Kirsher #define PCIE_INTR_MASK (F_UNXSPLCPLERRR | F_UNXSPLCPLERRC | F_PCIE_PIOPARERR |\ 1449f7917c00SJeff Kirsher F_PCIE_WFPARERR | F_PCIE_RFPARERR | F_PCIE_CFPARERR | \ 1450f7917c00SJeff Kirsher /* V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR) | */ \ 1451f7917c00SJeff Kirsher F_RETRYBUFPARERR | F_RETRYLUTPARERR | F_RXPARERR | \ 1452f7917c00SJeff Kirsher F_TXPARERR | V_BISTERR(M_BISTERR)) 1453f7917c00SJeff Kirsher #define ULPRX_INTR_MASK (F_PARERRDATA | F_PARERRPCMD | F_ARBPF1PERR | \ 1454f7917c00SJeff Kirsher F_ARBPF0PERR | F_ARBFPERR | F_PCMDMUXPERR | \ 1455f7917c00SJeff Kirsher F_DATASELFRAMEERR1 | F_DATASELFRAMEERR0) 1456f7917c00SJeff Kirsher #define ULPTX_INTR_MASK 0xfc 1457f7917c00SJeff Kirsher #define CPLSW_INTR_MASK (F_CIM_OP_MAP_PERR | F_TP_FRAMING_ERROR | \ 1458f7917c00SJeff Kirsher F_SGE_FRAMING_ERROR | F_CIM_FRAMING_ERROR | \ 1459f7917c00SJeff Kirsher F_ZERO_SWITCH_ERROR) 1460f7917c00SJeff Kirsher #define CIM_INTR_MASK (F_BLKWRPLINT | F_BLKRDPLINT | F_BLKWRCTLINT | \ 1461f7917c00SJeff Kirsher F_BLKRDCTLINT | F_BLKWRFLASHINT | F_BLKRDFLASHINT | \ 1462f7917c00SJeff Kirsher F_SGLWRFLASHINT | F_WRBLKFLASHINT | F_BLKWRBOOTINT | \ 1463f7917c00SJeff Kirsher F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT | \ 1464f7917c00SJeff Kirsher F_DRAMPARERR | F_ICACHEPARERR | F_DCACHEPARERR | \ 1465f7917c00SJeff Kirsher F_OBQSGEPARERR | F_OBQULPHIPARERR | F_OBQULPLOPARERR | \ 1466f7917c00SJeff Kirsher F_IBQSGELOPARERR | F_IBQSGEHIPARERR | F_IBQULPPARERR | \ 1467f7917c00SJeff Kirsher F_IBQTPPARERR | F_ITAGPARERR | F_DTAGPARERR) 1468f7917c00SJeff Kirsher #define PMTX_INTR_MASK (F_ZERO_C_CMD_ERROR | ICSPI_FRM_ERR | OESPI_FRM_ERR | \ 1469f7917c00SJeff Kirsher V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR) | \ 1470f7917c00SJeff Kirsher V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR)) 1471f7917c00SJeff Kirsher #define PMRX_INTR_MASK (F_ZERO_E_CMD_ERROR | IESPI_FRM_ERR | OCSPI_FRM_ERR | \ 1472f7917c00SJeff Kirsher V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR) | \ 1473f7917c00SJeff Kirsher V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR)) 1474f7917c00SJeff Kirsher #define MPS_INTR_MASK (V_TX0TPPARERRENB(M_TX0TPPARERRENB) | \ 1475f7917c00SJeff Kirsher V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \ 1476f7917c00SJeff Kirsher V_RXTPPARERRENB(M_RXTPPARERRENB) | \ 1477f7917c00SJeff Kirsher V_MCAPARERRENB(M_MCAPARERRENB)) 1478f7917c00SJeff Kirsher #define XGM_EXTRA_INTR_MASK (F_LINKFAULTCHANGE) 1479f7917c00SJeff Kirsher #define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \ 1480f7917c00SJeff Kirsher F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \ 1481f7917c00SJeff Kirsher F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \ 1482f7917c00SJeff Kirsher F_MPS0 | F_CPL_SWITCH) 1483f7917c00SJeff Kirsher /* 1484f7917c00SJeff Kirsher * Interrupt handler for the PCIX1 module. 1485f7917c00SJeff Kirsher */ 1486f7917c00SJeff Kirsher static void pci_intr_handler(struct adapter *adapter) 1487f7917c00SJeff Kirsher { 1488f7917c00SJeff Kirsher static const struct intr_info pcix1_intr_info[] = { 1489f7917c00SJeff Kirsher {F_MSTDETPARERR, "PCI master detected parity error", -1, 1}, 1490f7917c00SJeff Kirsher {F_SIGTARABT, "PCI signaled target abort", -1, 1}, 1491f7917c00SJeff Kirsher {F_RCVTARABT, "PCI received target abort", -1, 1}, 1492f7917c00SJeff Kirsher {F_RCVMSTABT, "PCI received master abort", -1, 1}, 1493f7917c00SJeff Kirsher {F_SIGSYSERR, "PCI signaled system error", -1, 1}, 1494f7917c00SJeff Kirsher {F_DETPARERR, "PCI detected parity error", -1, 1}, 1495f7917c00SJeff Kirsher {F_SPLCMPDIS, "PCI split completion discarded", -1, 1}, 1496f7917c00SJeff Kirsher {F_UNXSPLCMP, "PCI unexpected split completion error", -1, 1}, 1497f7917c00SJeff Kirsher {F_RCVSPLCMPERR, "PCI received split completion error", -1, 1498f7917c00SJeff Kirsher 1}, 1499f7917c00SJeff Kirsher {F_DETCORECCERR, "PCI correctable ECC error", 1500f7917c00SJeff Kirsher STAT_PCI_CORR_ECC, 0}, 1501f7917c00SJeff Kirsher {F_DETUNCECCERR, "PCI uncorrectable ECC error", -1, 1}, 1502f7917c00SJeff Kirsher {F_PIOPARERR, "PCI PIO FIFO parity error", -1, 1}, 1503f7917c00SJeff Kirsher {V_WFPARERR(M_WFPARERR), "PCI write FIFO parity error", -1, 1504f7917c00SJeff Kirsher 1}, 1505f7917c00SJeff Kirsher {V_RFPARERR(M_RFPARERR), "PCI read FIFO parity error", -1, 1506f7917c00SJeff Kirsher 1}, 1507f7917c00SJeff Kirsher {V_CFPARERR(M_CFPARERR), "PCI command FIFO parity error", -1, 1508f7917c00SJeff Kirsher 1}, 1509f7917c00SJeff Kirsher {V_MSIXPARERR(M_MSIXPARERR), "PCI MSI-X table/PBA parity " 1510f7917c00SJeff Kirsher "error", -1, 1}, 1511f7917c00SJeff Kirsher {0} 1512f7917c00SJeff Kirsher }; 1513f7917c00SJeff Kirsher 1514f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_PCIX_INT_CAUSE, PCIX_INTR_MASK, 1515f7917c00SJeff Kirsher pcix1_intr_info, adapter->irq_stats)) 1516f7917c00SJeff Kirsher t3_fatal_err(adapter); 1517f7917c00SJeff Kirsher } 1518f7917c00SJeff Kirsher 1519f7917c00SJeff Kirsher /* 1520f7917c00SJeff Kirsher * Interrupt handler for the PCIE module. 1521f7917c00SJeff Kirsher */ 1522f7917c00SJeff Kirsher static void pcie_intr_handler(struct adapter *adapter) 1523f7917c00SJeff Kirsher { 1524f7917c00SJeff Kirsher static const struct intr_info pcie_intr_info[] = { 1525f7917c00SJeff Kirsher {F_PEXERR, "PCI PEX error", -1, 1}, 1526f7917c00SJeff Kirsher {F_UNXSPLCPLERRR, 1527f7917c00SJeff Kirsher "PCI unexpected split completion DMA read error", -1, 1}, 1528f7917c00SJeff Kirsher {F_UNXSPLCPLERRC, 1529f7917c00SJeff Kirsher "PCI unexpected split completion DMA command error", -1, 1}, 1530f7917c00SJeff Kirsher {F_PCIE_PIOPARERR, "PCI PIO FIFO parity error", -1, 1}, 1531f7917c00SJeff Kirsher {F_PCIE_WFPARERR, "PCI write FIFO parity error", -1, 1}, 1532f7917c00SJeff Kirsher {F_PCIE_RFPARERR, "PCI read FIFO parity error", -1, 1}, 1533f7917c00SJeff Kirsher {F_PCIE_CFPARERR, "PCI command FIFO parity error", -1, 1}, 1534f7917c00SJeff Kirsher {V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR), 1535f7917c00SJeff Kirsher "PCI MSI-X table/PBA parity error", -1, 1}, 1536f7917c00SJeff Kirsher {F_RETRYBUFPARERR, "PCI retry buffer parity error", -1, 1}, 1537f7917c00SJeff Kirsher {F_RETRYLUTPARERR, "PCI retry LUT parity error", -1, 1}, 1538f7917c00SJeff Kirsher {F_RXPARERR, "PCI Rx parity error", -1, 1}, 1539f7917c00SJeff Kirsher {F_TXPARERR, "PCI Tx parity error", -1, 1}, 1540f7917c00SJeff Kirsher {V_BISTERR(M_BISTERR), "PCI BIST error", -1, 1}, 1541f7917c00SJeff Kirsher {0} 1542f7917c00SJeff Kirsher }; 1543f7917c00SJeff Kirsher 1544f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_PCIE_INT_CAUSE) & F_PEXERR) 1545f7917c00SJeff Kirsher CH_ALERT(adapter, "PEX error code 0x%x\n", 1546f7917c00SJeff Kirsher t3_read_reg(adapter, A_PCIE_PEX_ERR)); 1547f7917c00SJeff Kirsher 1548f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_PCIE_INT_CAUSE, PCIE_INTR_MASK, 1549f7917c00SJeff Kirsher pcie_intr_info, adapter->irq_stats)) 1550f7917c00SJeff Kirsher t3_fatal_err(adapter); 1551f7917c00SJeff Kirsher } 1552f7917c00SJeff Kirsher 1553f7917c00SJeff Kirsher /* 1554f7917c00SJeff Kirsher * TP interrupt handler. 1555f7917c00SJeff Kirsher */ 1556f7917c00SJeff Kirsher static void tp_intr_handler(struct adapter *adapter) 1557f7917c00SJeff Kirsher { 1558f7917c00SJeff Kirsher static const struct intr_info tp_intr_info[] = { 1559f7917c00SJeff Kirsher {0xffffff, "TP parity error", -1, 1}, 1560f7917c00SJeff Kirsher {0x1000000, "TP out of Rx pages", -1, 1}, 1561f7917c00SJeff Kirsher {0x2000000, "TP out of Tx pages", -1, 1}, 1562f7917c00SJeff Kirsher {0} 1563f7917c00SJeff Kirsher }; 1564f7917c00SJeff Kirsher 1565f7917c00SJeff Kirsher static const struct intr_info tp_intr_info_t3c[] = { 1566f7917c00SJeff Kirsher {0x1fffffff, "TP parity error", -1, 1}, 1567f7917c00SJeff Kirsher {F_FLMRXFLSTEMPTY, "TP out of Rx pages", -1, 1}, 1568f7917c00SJeff Kirsher {F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1}, 1569f7917c00SJeff Kirsher {0} 1570f7917c00SJeff Kirsher }; 1571f7917c00SJeff Kirsher 1572f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_TP_INT_CAUSE, 0xffffffff, 1573f7917c00SJeff Kirsher adapter->params.rev < T3_REV_C ? 1574f7917c00SJeff Kirsher tp_intr_info : tp_intr_info_t3c, NULL)) 1575f7917c00SJeff Kirsher t3_fatal_err(adapter); 1576f7917c00SJeff Kirsher } 1577f7917c00SJeff Kirsher 1578f7917c00SJeff Kirsher /* 1579f7917c00SJeff Kirsher * CIM interrupt handler. 1580f7917c00SJeff Kirsher */ 1581f7917c00SJeff Kirsher static void cim_intr_handler(struct adapter *adapter) 1582f7917c00SJeff Kirsher { 1583f7917c00SJeff Kirsher static const struct intr_info cim_intr_info[] = { 1584f7917c00SJeff Kirsher {F_RSVDSPACEINT, "CIM reserved space write", -1, 1}, 1585f7917c00SJeff Kirsher {F_SDRAMRANGEINT, "CIM SDRAM address out of range", -1, 1}, 1586f7917c00SJeff Kirsher {F_FLASHRANGEINT, "CIM flash address out of range", -1, 1}, 1587f7917c00SJeff Kirsher {F_BLKWRBOOTINT, "CIM block write to boot space", -1, 1}, 1588f7917c00SJeff Kirsher {F_WRBLKFLASHINT, "CIM write to cached flash space", -1, 1}, 1589f7917c00SJeff Kirsher {F_SGLWRFLASHINT, "CIM single write to flash space", -1, 1}, 1590f7917c00SJeff Kirsher {F_BLKRDFLASHINT, "CIM block read from flash space", -1, 1}, 1591f7917c00SJeff Kirsher {F_BLKWRFLASHINT, "CIM block write to flash space", -1, 1}, 1592f7917c00SJeff Kirsher {F_BLKRDCTLINT, "CIM block read from CTL space", -1, 1}, 1593f7917c00SJeff Kirsher {F_BLKWRCTLINT, "CIM block write to CTL space", -1, 1}, 1594f7917c00SJeff Kirsher {F_BLKRDPLINT, "CIM block read from PL space", -1, 1}, 1595f7917c00SJeff Kirsher {F_BLKWRPLINT, "CIM block write to PL space", -1, 1}, 1596f7917c00SJeff Kirsher {F_DRAMPARERR, "CIM DRAM parity error", -1, 1}, 1597f7917c00SJeff Kirsher {F_ICACHEPARERR, "CIM icache parity error", -1, 1}, 1598f7917c00SJeff Kirsher {F_DCACHEPARERR, "CIM dcache parity error", -1, 1}, 1599f7917c00SJeff Kirsher {F_OBQSGEPARERR, "CIM OBQ SGE parity error", -1, 1}, 1600f7917c00SJeff Kirsher {F_OBQULPHIPARERR, "CIM OBQ ULPHI parity error", -1, 1}, 1601f7917c00SJeff Kirsher {F_OBQULPLOPARERR, "CIM OBQ ULPLO parity error", -1, 1}, 1602f7917c00SJeff Kirsher {F_IBQSGELOPARERR, "CIM IBQ SGELO parity error", -1, 1}, 1603f7917c00SJeff Kirsher {F_IBQSGEHIPARERR, "CIM IBQ SGEHI parity error", -1, 1}, 1604f7917c00SJeff Kirsher {F_IBQULPPARERR, "CIM IBQ ULP parity error", -1, 1}, 1605f7917c00SJeff Kirsher {F_IBQTPPARERR, "CIM IBQ TP parity error", -1, 1}, 1606f7917c00SJeff Kirsher {F_ITAGPARERR, "CIM itag parity error", -1, 1}, 1607f7917c00SJeff Kirsher {F_DTAGPARERR, "CIM dtag parity error", -1, 1}, 1608f7917c00SJeff Kirsher {0} 1609f7917c00SJeff Kirsher }; 1610f7917c00SJeff Kirsher 1611f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE, 0xffffffff, 1612f7917c00SJeff Kirsher cim_intr_info, NULL)) 1613f7917c00SJeff Kirsher t3_fatal_err(adapter); 1614f7917c00SJeff Kirsher } 1615f7917c00SJeff Kirsher 1616f7917c00SJeff Kirsher /* 1617f7917c00SJeff Kirsher * ULP RX interrupt handler. 1618f7917c00SJeff Kirsher */ 1619f7917c00SJeff Kirsher static void ulprx_intr_handler(struct adapter *adapter) 1620f7917c00SJeff Kirsher { 1621f7917c00SJeff Kirsher static const struct intr_info ulprx_intr_info[] = { 1622f7917c00SJeff Kirsher {F_PARERRDATA, "ULP RX data parity error", -1, 1}, 1623f7917c00SJeff Kirsher {F_PARERRPCMD, "ULP RX command parity error", -1, 1}, 1624f7917c00SJeff Kirsher {F_ARBPF1PERR, "ULP RX ArbPF1 parity error", -1, 1}, 1625f7917c00SJeff Kirsher {F_ARBPF0PERR, "ULP RX ArbPF0 parity error", -1, 1}, 1626f7917c00SJeff Kirsher {F_ARBFPERR, "ULP RX ArbF parity error", -1, 1}, 1627f7917c00SJeff Kirsher {F_PCMDMUXPERR, "ULP RX PCMDMUX parity error", -1, 1}, 1628f7917c00SJeff Kirsher {F_DATASELFRAMEERR1, "ULP RX frame error", -1, 1}, 1629f7917c00SJeff Kirsher {F_DATASELFRAMEERR0, "ULP RX frame error", -1, 1}, 1630f7917c00SJeff Kirsher {0} 1631f7917c00SJeff Kirsher }; 1632f7917c00SJeff Kirsher 1633f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_ULPRX_INT_CAUSE, 0xffffffff, 1634f7917c00SJeff Kirsher ulprx_intr_info, NULL)) 1635f7917c00SJeff Kirsher t3_fatal_err(adapter); 1636f7917c00SJeff Kirsher } 1637f7917c00SJeff Kirsher 1638f7917c00SJeff Kirsher /* 1639f7917c00SJeff Kirsher * ULP TX interrupt handler. 1640f7917c00SJeff Kirsher */ 1641f7917c00SJeff Kirsher static void ulptx_intr_handler(struct adapter *adapter) 1642f7917c00SJeff Kirsher { 1643f7917c00SJeff Kirsher static const struct intr_info ulptx_intr_info[] = { 1644f7917c00SJeff Kirsher {F_PBL_BOUND_ERR_CH0, "ULP TX channel 0 PBL out of bounds", 1645f7917c00SJeff Kirsher STAT_ULP_CH0_PBL_OOB, 0}, 1646f7917c00SJeff Kirsher {F_PBL_BOUND_ERR_CH1, "ULP TX channel 1 PBL out of bounds", 1647f7917c00SJeff Kirsher STAT_ULP_CH1_PBL_OOB, 0}, 1648f7917c00SJeff Kirsher {0xfc, "ULP TX parity error", -1, 1}, 1649f7917c00SJeff Kirsher {0} 1650f7917c00SJeff Kirsher }; 1651f7917c00SJeff Kirsher 1652f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_ULPTX_INT_CAUSE, 0xffffffff, 1653f7917c00SJeff Kirsher ulptx_intr_info, adapter->irq_stats)) 1654f7917c00SJeff Kirsher t3_fatal_err(adapter); 1655f7917c00SJeff Kirsher } 1656f7917c00SJeff Kirsher 1657f7917c00SJeff Kirsher #define ICSPI_FRM_ERR (F_ICSPI0_FIFO2X_RX_FRAMING_ERROR | \ 1658f7917c00SJeff Kirsher F_ICSPI1_FIFO2X_RX_FRAMING_ERROR | F_ICSPI0_RX_FRAMING_ERROR | \ 1659f7917c00SJeff Kirsher F_ICSPI1_RX_FRAMING_ERROR | F_ICSPI0_TX_FRAMING_ERROR | \ 1660f7917c00SJeff Kirsher F_ICSPI1_TX_FRAMING_ERROR) 1661f7917c00SJeff Kirsher #define OESPI_FRM_ERR (F_OESPI0_RX_FRAMING_ERROR | \ 1662f7917c00SJeff Kirsher F_OESPI1_RX_FRAMING_ERROR | F_OESPI0_TX_FRAMING_ERROR | \ 1663f7917c00SJeff Kirsher F_OESPI1_TX_FRAMING_ERROR | F_OESPI0_OFIFO2X_TX_FRAMING_ERROR | \ 1664f7917c00SJeff Kirsher F_OESPI1_OFIFO2X_TX_FRAMING_ERROR) 1665f7917c00SJeff Kirsher 1666f7917c00SJeff Kirsher /* 1667f7917c00SJeff Kirsher * PM TX interrupt handler. 1668f7917c00SJeff Kirsher */ 1669f7917c00SJeff Kirsher static void pmtx_intr_handler(struct adapter *adapter) 1670f7917c00SJeff Kirsher { 1671f7917c00SJeff Kirsher static const struct intr_info pmtx_intr_info[] = { 1672f7917c00SJeff Kirsher {F_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1}, 1673f7917c00SJeff Kirsher {ICSPI_FRM_ERR, "PMTX ispi framing error", -1, 1}, 1674f7917c00SJeff Kirsher {OESPI_FRM_ERR, "PMTX ospi framing error", -1, 1}, 1675f7917c00SJeff Kirsher {V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR), 1676f7917c00SJeff Kirsher "PMTX ispi parity error", -1, 1}, 1677f7917c00SJeff Kirsher {V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR), 1678f7917c00SJeff Kirsher "PMTX ospi parity error", -1, 1}, 1679f7917c00SJeff Kirsher {0} 1680f7917c00SJeff Kirsher }; 1681f7917c00SJeff Kirsher 1682f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_PM1_TX_INT_CAUSE, 0xffffffff, 1683f7917c00SJeff Kirsher pmtx_intr_info, NULL)) 1684f7917c00SJeff Kirsher t3_fatal_err(adapter); 1685f7917c00SJeff Kirsher } 1686f7917c00SJeff Kirsher 1687f7917c00SJeff Kirsher #define IESPI_FRM_ERR (F_IESPI0_FIFO2X_RX_FRAMING_ERROR | \ 1688f7917c00SJeff Kirsher F_IESPI1_FIFO2X_RX_FRAMING_ERROR | F_IESPI0_RX_FRAMING_ERROR | \ 1689f7917c00SJeff Kirsher F_IESPI1_RX_FRAMING_ERROR | F_IESPI0_TX_FRAMING_ERROR | \ 1690f7917c00SJeff Kirsher F_IESPI1_TX_FRAMING_ERROR) 1691f7917c00SJeff Kirsher #define OCSPI_FRM_ERR (F_OCSPI0_RX_FRAMING_ERROR | \ 1692f7917c00SJeff Kirsher F_OCSPI1_RX_FRAMING_ERROR | F_OCSPI0_TX_FRAMING_ERROR | \ 1693f7917c00SJeff Kirsher F_OCSPI1_TX_FRAMING_ERROR | F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR | \ 1694f7917c00SJeff Kirsher F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR) 1695f7917c00SJeff Kirsher 1696f7917c00SJeff Kirsher /* 1697f7917c00SJeff Kirsher * PM RX interrupt handler. 1698f7917c00SJeff Kirsher */ 1699f7917c00SJeff Kirsher static void pmrx_intr_handler(struct adapter *adapter) 1700f7917c00SJeff Kirsher { 1701f7917c00SJeff Kirsher static const struct intr_info pmrx_intr_info[] = { 1702f7917c00SJeff Kirsher {F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1}, 1703f7917c00SJeff Kirsher {IESPI_FRM_ERR, "PMRX ispi framing error", -1, 1}, 1704f7917c00SJeff Kirsher {OCSPI_FRM_ERR, "PMRX ospi framing error", -1, 1}, 1705f7917c00SJeff Kirsher {V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR), 1706f7917c00SJeff Kirsher "PMRX ispi parity error", -1, 1}, 1707f7917c00SJeff Kirsher {V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR), 1708f7917c00SJeff Kirsher "PMRX ospi parity error", -1, 1}, 1709f7917c00SJeff Kirsher {0} 1710f7917c00SJeff Kirsher }; 1711f7917c00SJeff Kirsher 1712f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_PM1_RX_INT_CAUSE, 0xffffffff, 1713f7917c00SJeff Kirsher pmrx_intr_info, NULL)) 1714f7917c00SJeff Kirsher t3_fatal_err(adapter); 1715f7917c00SJeff Kirsher } 1716f7917c00SJeff Kirsher 1717f7917c00SJeff Kirsher /* 1718f7917c00SJeff Kirsher * CPL switch interrupt handler. 1719f7917c00SJeff Kirsher */ 1720f7917c00SJeff Kirsher static void cplsw_intr_handler(struct adapter *adapter) 1721f7917c00SJeff Kirsher { 1722f7917c00SJeff Kirsher static const struct intr_info cplsw_intr_info[] = { 1723f7917c00SJeff Kirsher {F_CIM_OP_MAP_PERR, "CPL switch CIM parity error", -1, 1}, 1724f7917c00SJeff Kirsher {F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1}, 1725f7917c00SJeff Kirsher {F_TP_FRAMING_ERROR, "CPL switch TP framing error", -1, 1}, 1726f7917c00SJeff Kirsher {F_SGE_FRAMING_ERROR, "CPL switch SGE framing error", -1, 1}, 1727f7917c00SJeff Kirsher {F_CIM_FRAMING_ERROR, "CPL switch CIM framing error", -1, 1}, 1728f7917c00SJeff Kirsher {F_ZERO_SWITCH_ERROR, "CPL switch no-switch error", -1, 1}, 1729f7917c00SJeff Kirsher {0} 1730f7917c00SJeff Kirsher }; 1731f7917c00SJeff Kirsher 1732f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_CPL_INTR_CAUSE, 0xffffffff, 1733f7917c00SJeff Kirsher cplsw_intr_info, NULL)) 1734f7917c00SJeff Kirsher t3_fatal_err(adapter); 1735f7917c00SJeff Kirsher } 1736f7917c00SJeff Kirsher 1737f7917c00SJeff Kirsher /* 1738f7917c00SJeff Kirsher * MPS interrupt handler. 1739f7917c00SJeff Kirsher */ 1740f7917c00SJeff Kirsher static void mps_intr_handler(struct adapter *adapter) 1741f7917c00SJeff Kirsher { 1742f7917c00SJeff Kirsher static const struct intr_info mps_intr_info[] = { 1743f7917c00SJeff Kirsher {0x1ff, "MPS parity error", -1, 1}, 1744f7917c00SJeff Kirsher {0} 1745f7917c00SJeff Kirsher }; 1746f7917c00SJeff Kirsher 1747f7917c00SJeff Kirsher if (t3_handle_intr_status(adapter, A_MPS_INT_CAUSE, 0xffffffff, 1748f7917c00SJeff Kirsher mps_intr_info, NULL)) 1749f7917c00SJeff Kirsher t3_fatal_err(adapter); 1750f7917c00SJeff Kirsher } 1751f7917c00SJeff Kirsher 1752f7917c00SJeff Kirsher #define MC7_INTR_FATAL (F_UE | V_PE(M_PE) | F_AE) 1753f7917c00SJeff Kirsher 1754f7917c00SJeff Kirsher /* 1755f7917c00SJeff Kirsher * MC7 interrupt handler. 1756f7917c00SJeff Kirsher */ 1757f7917c00SJeff Kirsher static void mc7_intr_handler(struct mc7 *mc7) 1758f7917c00SJeff Kirsher { 1759f7917c00SJeff Kirsher struct adapter *adapter = mc7->adapter; 1760f7917c00SJeff Kirsher u32 cause = t3_read_reg(adapter, mc7->offset + A_MC7_INT_CAUSE); 1761f7917c00SJeff Kirsher 1762f7917c00SJeff Kirsher if (cause & F_CE) { 1763f7917c00SJeff Kirsher mc7->stats.corr_err++; 1764f7917c00SJeff Kirsher CH_WARN(adapter, "%s MC7 correctable error at addr 0x%x, " 1765f7917c00SJeff Kirsher "data 0x%x 0x%x 0x%x\n", mc7->name, 1766f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CE_ADDR), 1767f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA0), 1768f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA1), 1769f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA2)); 1770f7917c00SJeff Kirsher } 1771f7917c00SJeff Kirsher 1772f7917c00SJeff Kirsher if (cause & F_UE) { 1773f7917c00SJeff Kirsher mc7->stats.uncorr_err++; 1774f7917c00SJeff Kirsher CH_ALERT(adapter, "%s MC7 uncorrectable error at addr 0x%x, " 1775f7917c00SJeff Kirsher "data 0x%x 0x%x 0x%x\n", mc7->name, 1776f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_UE_ADDR), 1777f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA0), 1778f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA1), 1779f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA2)); 1780f7917c00SJeff Kirsher } 1781f7917c00SJeff Kirsher 1782f7917c00SJeff Kirsher if (G_PE(cause)) { 1783f7917c00SJeff Kirsher mc7->stats.parity_err++; 1784f7917c00SJeff Kirsher CH_ALERT(adapter, "%s MC7 parity error 0x%x\n", 1785f7917c00SJeff Kirsher mc7->name, G_PE(cause)); 1786f7917c00SJeff Kirsher } 1787f7917c00SJeff Kirsher 1788f7917c00SJeff Kirsher if (cause & F_AE) { 1789f7917c00SJeff Kirsher u32 addr = 0; 1790f7917c00SJeff Kirsher 1791f7917c00SJeff Kirsher if (adapter->params.rev > 0) 1792f7917c00SJeff Kirsher addr = t3_read_reg(adapter, 1793f7917c00SJeff Kirsher mc7->offset + A_MC7_ERR_ADDR); 1794f7917c00SJeff Kirsher mc7->stats.addr_err++; 1795f7917c00SJeff Kirsher CH_ALERT(adapter, "%s MC7 address error: 0x%x\n", 1796f7917c00SJeff Kirsher mc7->name, addr); 1797f7917c00SJeff Kirsher } 1798f7917c00SJeff Kirsher 1799f7917c00SJeff Kirsher if (cause & MC7_INTR_FATAL) 1800f7917c00SJeff Kirsher t3_fatal_err(adapter); 1801f7917c00SJeff Kirsher 1802f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_INT_CAUSE, cause); 1803f7917c00SJeff Kirsher } 1804f7917c00SJeff Kirsher 1805f7917c00SJeff Kirsher #define XGM_INTR_FATAL (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ 1806f7917c00SJeff Kirsher V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) 1807f7917c00SJeff Kirsher /* 1808f7917c00SJeff Kirsher * XGMAC interrupt handler. 1809f7917c00SJeff Kirsher */ 1810f7917c00SJeff Kirsher static int mac_intr_handler(struct adapter *adap, unsigned int idx) 1811f7917c00SJeff Kirsher { 1812f7917c00SJeff Kirsher struct cmac *mac = &adap2pinfo(adap, idx)->mac; 1813f7917c00SJeff Kirsher /* 1814f7917c00SJeff Kirsher * We mask out interrupt causes for which we're not taking interrupts. 1815f7917c00SJeff Kirsher * This allows us to use polling logic to monitor some of the other 1816f7917c00SJeff Kirsher * conditions when taking interrupts would impose too much load on the 1817f7917c00SJeff Kirsher * system. 1818f7917c00SJeff Kirsher */ 1819f7917c00SJeff Kirsher u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset) & 1820f7917c00SJeff Kirsher ~F_RXFIFO_OVERFLOW; 1821f7917c00SJeff Kirsher 1822f7917c00SJeff Kirsher if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) { 1823f7917c00SJeff Kirsher mac->stats.tx_fifo_parity_err++; 1824f7917c00SJeff Kirsher CH_ALERT(adap, "port%d: MAC TX FIFO parity error\n", idx); 1825f7917c00SJeff Kirsher } 1826f7917c00SJeff Kirsher if (cause & V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) { 1827f7917c00SJeff Kirsher mac->stats.rx_fifo_parity_err++; 1828f7917c00SJeff Kirsher CH_ALERT(adap, "port%d: MAC RX FIFO parity error\n", idx); 1829f7917c00SJeff Kirsher } 1830f7917c00SJeff Kirsher if (cause & F_TXFIFO_UNDERRUN) 1831f7917c00SJeff Kirsher mac->stats.tx_fifo_urun++; 1832f7917c00SJeff Kirsher if (cause & F_RXFIFO_OVERFLOW) 1833f7917c00SJeff Kirsher mac->stats.rx_fifo_ovfl++; 1834f7917c00SJeff Kirsher if (cause & V_SERDES_LOS(M_SERDES_LOS)) 1835f7917c00SJeff Kirsher mac->stats.serdes_signal_loss++; 1836f7917c00SJeff Kirsher if (cause & F_XAUIPCSCTCERR) 1837f7917c00SJeff Kirsher mac->stats.xaui_pcs_ctc_err++; 1838f7917c00SJeff Kirsher if (cause & F_XAUIPCSALIGNCHANGE) 1839f7917c00SJeff Kirsher mac->stats.xaui_pcs_align_change++; 1840f7917c00SJeff Kirsher if (cause & F_XGM_INT) { 1841f7917c00SJeff Kirsher t3_set_reg_field(adap, 1842f7917c00SJeff Kirsher A_XGM_INT_ENABLE + mac->offset, 1843f7917c00SJeff Kirsher F_XGM_INT, 0); 1844f7917c00SJeff Kirsher mac->stats.link_faults++; 1845f7917c00SJeff Kirsher 1846f7917c00SJeff Kirsher t3_os_link_fault_handler(adap, idx); 1847f7917c00SJeff Kirsher } 1848f7917c00SJeff Kirsher 1849f7917c00SJeff Kirsher if (cause & XGM_INTR_FATAL) 1850f7917c00SJeff Kirsher t3_fatal_err(adap); 1851f7917c00SJeff Kirsher 1852f7917c00SJeff Kirsher t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause); 1853f7917c00SJeff Kirsher return cause != 0; 1854f7917c00SJeff Kirsher } 1855f7917c00SJeff Kirsher 1856f7917c00SJeff Kirsher /* 1857f7917c00SJeff Kirsher * Interrupt handler for PHY events. 1858f7917c00SJeff Kirsher */ 1859f7917c00SJeff Kirsher int t3_phy_intr_handler(struct adapter *adapter) 1860f7917c00SJeff Kirsher { 1861f7917c00SJeff Kirsher u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); 1862f7917c00SJeff Kirsher 1863f7917c00SJeff Kirsher for_each_port(adapter, i) { 1864f7917c00SJeff Kirsher struct port_info *p = adap2pinfo(adapter, i); 1865f7917c00SJeff Kirsher 1866f7917c00SJeff Kirsher if (!(p->phy.caps & SUPPORTED_IRQ)) 1867f7917c00SJeff Kirsher continue; 1868f7917c00SJeff Kirsher 1869f7917c00SJeff Kirsher if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) { 1870f7917c00SJeff Kirsher int phy_cause = p->phy.ops->intr_handler(&p->phy); 1871f7917c00SJeff Kirsher 1872f7917c00SJeff Kirsher if (phy_cause & cphy_cause_link_change) 1873f7917c00SJeff Kirsher t3_link_changed(adapter, i); 1874f7917c00SJeff Kirsher if (phy_cause & cphy_cause_fifo_error) 1875f7917c00SJeff Kirsher p->phy.fifo_errors++; 1876f7917c00SJeff Kirsher if (phy_cause & cphy_cause_module_change) 1877f7917c00SJeff Kirsher t3_os_phymod_changed(adapter, i); 1878f7917c00SJeff Kirsher } 1879f7917c00SJeff Kirsher } 1880f7917c00SJeff Kirsher 1881f7917c00SJeff Kirsher t3_write_reg(adapter, A_T3DBG_INT_CAUSE, cause); 1882f7917c00SJeff Kirsher return 0; 1883f7917c00SJeff Kirsher } 1884f7917c00SJeff Kirsher 1885f7917c00SJeff Kirsher /* 1886f7917c00SJeff Kirsher * T3 slow path (non-data) interrupt handler. 1887f7917c00SJeff Kirsher */ 1888f7917c00SJeff Kirsher int t3_slow_intr_handler(struct adapter *adapter) 1889f7917c00SJeff Kirsher { 1890f7917c00SJeff Kirsher u32 cause = t3_read_reg(adapter, A_PL_INT_CAUSE0); 1891f7917c00SJeff Kirsher 1892f7917c00SJeff Kirsher cause &= adapter->slow_intr_mask; 1893f7917c00SJeff Kirsher if (!cause) 1894f7917c00SJeff Kirsher return 0; 1895f7917c00SJeff Kirsher if (cause & F_PCIM0) { 1896f7917c00SJeff Kirsher if (is_pcie(adapter)) 1897f7917c00SJeff Kirsher pcie_intr_handler(adapter); 1898f7917c00SJeff Kirsher else 1899f7917c00SJeff Kirsher pci_intr_handler(adapter); 1900f7917c00SJeff Kirsher } 1901f7917c00SJeff Kirsher if (cause & F_SGE3) 1902f7917c00SJeff Kirsher t3_sge_err_intr_handler(adapter); 1903f7917c00SJeff Kirsher if (cause & F_MC7_PMRX) 1904f7917c00SJeff Kirsher mc7_intr_handler(&adapter->pmrx); 1905f7917c00SJeff Kirsher if (cause & F_MC7_PMTX) 1906f7917c00SJeff Kirsher mc7_intr_handler(&adapter->pmtx); 1907f7917c00SJeff Kirsher if (cause & F_MC7_CM) 1908f7917c00SJeff Kirsher mc7_intr_handler(&adapter->cm); 1909f7917c00SJeff Kirsher if (cause & F_CIM) 1910f7917c00SJeff Kirsher cim_intr_handler(adapter); 1911f7917c00SJeff Kirsher if (cause & F_TP1) 1912f7917c00SJeff Kirsher tp_intr_handler(adapter); 1913f7917c00SJeff Kirsher if (cause & F_ULP2_RX) 1914f7917c00SJeff Kirsher ulprx_intr_handler(adapter); 1915f7917c00SJeff Kirsher if (cause & F_ULP2_TX) 1916f7917c00SJeff Kirsher ulptx_intr_handler(adapter); 1917f7917c00SJeff Kirsher if (cause & F_PM1_RX) 1918f7917c00SJeff Kirsher pmrx_intr_handler(adapter); 1919f7917c00SJeff Kirsher if (cause & F_PM1_TX) 1920f7917c00SJeff Kirsher pmtx_intr_handler(adapter); 1921f7917c00SJeff Kirsher if (cause & F_CPL_SWITCH) 1922f7917c00SJeff Kirsher cplsw_intr_handler(adapter); 1923f7917c00SJeff Kirsher if (cause & F_MPS0) 1924f7917c00SJeff Kirsher mps_intr_handler(adapter); 1925f7917c00SJeff Kirsher if (cause & F_MC5A) 1926f7917c00SJeff Kirsher t3_mc5_intr_handler(&adapter->mc5); 1927f7917c00SJeff Kirsher if (cause & F_XGMAC0_0) 1928f7917c00SJeff Kirsher mac_intr_handler(adapter, 0); 1929f7917c00SJeff Kirsher if (cause & F_XGMAC0_1) 1930f7917c00SJeff Kirsher mac_intr_handler(adapter, 1); 1931f7917c00SJeff Kirsher if (cause & F_T3DBG) 1932f7917c00SJeff Kirsher t3_os_ext_intr_handler(adapter); 1933f7917c00SJeff Kirsher 1934f7917c00SJeff Kirsher /* Clear the interrupts just processed. */ 1935f7917c00SJeff Kirsher t3_write_reg(adapter, A_PL_INT_CAUSE0, cause); 1936f7917c00SJeff Kirsher t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ 1937f7917c00SJeff Kirsher return 1; 1938f7917c00SJeff Kirsher } 1939f7917c00SJeff Kirsher 1940f7917c00SJeff Kirsher static unsigned int calc_gpio_intr(struct adapter *adap) 1941f7917c00SJeff Kirsher { 1942f7917c00SJeff Kirsher unsigned int i, gpi_intr = 0; 1943f7917c00SJeff Kirsher 1944f7917c00SJeff Kirsher for_each_port(adap, i) 1945f7917c00SJeff Kirsher if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) && 1946f7917c00SJeff Kirsher adapter_info(adap)->gpio_intr[i]) 1947f7917c00SJeff Kirsher gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i]; 1948f7917c00SJeff Kirsher return gpi_intr; 1949f7917c00SJeff Kirsher } 1950f7917c00SJeff Kirsher 1951f7917c00SJeff Kirsher /** 1952f7917c00SJeff Kirsher * t3_intr_enable - enable interrupts 1953f7917c00SJeff Kirsher * @adapter: the adapter whose interrupts should be enabled 1954f7917c00SJeff Kirsher * 1955f7917c00SJeff Kirsher * Enable interrupts by setting the interrupt enable registers of the 1956f7917c00SJeff Kirsher * various HW modules and then enabling the top-level interrupt 1957f7917c00SJeff Kirsher * concentrator. 1958f7917c00SJeff Kirsher */ 1959f7917c00SJeff Kirsher void t3_intr_enable(struct adapter *adapter) 1960f7917c00SJeff Kirsher { 1961f7917c00SJeff Kirsher static const struct addr_val_pair intr_en_avp[] = { 1962f7917c00SJeff Kirsher {A_SG_INT_ENABLE, SGE_INTR_MASK}, 1963f7917c00SJeff Kirsher {A_MC7_INT_ENABLE, MC7_INTR_MASK}, 1964f7917c00SJeff Kirsher {A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR, 1965f7917c00SJeff Kirsher MC7_INTR_MASK}, 1966f7917c00SJeff Kirsher {A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR, 1967f7917c00SJeff Kirsher MC7_INTR_MASK}, 1968f7917c00SJeff Kirsher {A_MC5_DB_INT_ENABLE, MC5_INTR_MASK}, 1969f7917c00SJeff Kirsher {A_ULPRX_INT_ENABLE, ULPRX_INTR_MASK}, 1970f7917c00SJeff Kirsher {A_PM1_TX_INT_ENABLE, PMTX_INTR_MASK}, 1971f7917c00SJeff Kirsher {A_PM1_RX_INT_ENABLE, PMRX_INTR_MASK}, 1972f7917c00SJeff Kirsher {A_CIM_HOST_INT_ENABLE, CIM_INTR_MASK}, 1973f7917c00SJeff Kirsher {A_MPS_INT_ENABLE, MPS_INTR_MASK}, 1974f7917c00SJeff Kirsher }; 1975f7917c00SJeff Kirsher 1976f7917c00SJeff Kirsher adapter->slow_intr_mask = PL_INTR_MASK; 1977f7917c00SJeff Kirsher 1978f7917c00SJeff Kirsher t3_write_regs(adapter, intr_en_avp, ARRAY_SIZE(intr_en_avp), 0); 1979f7917c00SJeff Kirsher t3_write_reg(adapter, A_TP_INT_ENABLE, 1980f7917c00SJeff Kirsher adapter->params.rev >= T3_REV_C ? 0x2bfffff : 0x3bfffff); 1981f7917c00SJeff Kirsher 1982f7917c00SJeff Kirsher if (adapter->params.rev > 0) { 1983f7917c00SJeff Kirsher t3_write_reg(adapter, A_CPL_INTR_ENABLE, 1984f7917c00SJeff Kirsher CPLSW_INTR_MASK | F_CIM_OVFL_ERROR); 1985f7917c00SJeff Kirsher t3_write_reg(adapter, A_ULPTX_INT_ENABLE, 1986f7917c00SJeff Kirsher ULPTX_INTR_MASK | F_PBL_BOUND_ERR_CH0 | 1987f7917c00SJeff Kirsher F_PBL_BOUND_ERR_CH1); 1988f7917c00SJeff Kirsher } else { 1989f7917c00SJeff Kirsher t3_write_reg(adapter, A_CPL_INTR_ENABLE, CPLSW_INTR_MASK); 1990f7917c00SJeff Kirsher t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); 1991f7917c00SJeff Kirsher } 1992f7917c00SJeff Kirsher 1993f7917c00SJeff Kirsher t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter)); 1994f7917c00SJeff Kirsher 1995f7917c00SJeff Kirsher if (is_pcie(adapter)) 1996f7917c00SJeff Kirsher t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); 1997f7917c00SJeff Kirsher else 1998f7917c00SJeff Kirsher t3_write_reg(adapter, A_PCIX_INT_ENABLE, PCIX_INTR_MASK); 1999f7917c00SJeff Kirsher t3_write_reg(adapter, A_PL_INT_ENABLE0, adapter->slow_intr_mask); 2000f7917c00SJeff Kirsher t3_read_reg(adapter, A_PL_INT_ENABLE0); /* flush */ 2001f7917c00SJeff Kirsher } 2002f7917c00SJeff Kirsher 2003f7917c00SJeff Kirsher /** 2004f7917c00SJeff Kirsher * t3_intr_disable - disable a card's interrupts 2005f7917c00SJeff Kirsher * @adapter: the adapter whose interrupts should be disabled 2006f7917c00SJeff Kirsher * 2007f7917c00SJeff Kirsher * Disable interrupts. We only disable the top-level interrupt 2008f7917c00SJeff Kirsher * concentrator and the SGE data interrupts. 2009f7917c00SJeff Kirsher */ 2010f7917c00SJeff Kirsher void t3_intr_disable(struct adapter *adapter) 2011f7917c00SJeff Kirsher { 2012f7917c00SJeff Kirsher t3_write_reg(adapter, A_PL_INT_ENABLE0, 0); 2013f7917c00SJeff Kirsher t3_read_reg(adapter, A_PL_INT_ENABLE0); /* flush */ 2014f7917c00SJeff Kirsher adapter->slow_intr_mask = 0; 2015f7917c00SJeff Kirsher } 2016f7917c00SJeff Kirsher 2017f7917c00SJeff Kirsher /** 2018f7917c00SJeff Kirsher * t3_intr_clear - clear all interrupts 2019f7917c00SJeff Kirsher * @adapter: the adapter whose interrupts should be cleared 2020f7917c00SJeff Kirsher * 2021f7917c00SJeff Kirsher * Clears all interrupts. 2022f7917c00SJeff Kirsher */ 2023f7917c00SJeff Kirsher void t3_intr_clear(struct adapter *adapter) 2024f7917c00SJeff Kirsher { 2025f7917c00SJeff Kirsher static const unsigned int cause_reg_addr[] = { 2026f7917c00SJeff Kirsher A_SG_INT_CAUSE, 2027f7917c00SJeff Kirsher A_SG_RSPQ_FL_STATUS, 2028f7917c00SJeff Kirsher A_PCIX_INT_CAUSE, 2029f7917c00SJeff Kirsher A_MC7_INT_CAUSE, 2030f7917c00SJeff Kirsher A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR, 2031f7917c00SJeff Kirsher A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR, 2032f7917c00SJeff Kirsher A_CIM_HOST_INT_CAUSE, 2033f7917c00SJeff Kirsher A_TP_INT_CAUSE, 2034f7917c00SJeff Kirsher A_MC5_DB_INT_CAUSE, 2035f7917c00SJeff Kirsher A_ULPRX_INT_CAUSE, 2036f7917c00SJeff Kirsher A_ULPTX_INT_CAUSE, 2037f7917c00SJeff Kirsher A_CPL_INTR_CAUSE, 2038f7917c00SJeff Kirsher A_PM1_TX_INT_CAUSE, 2039f7917c00SJeff Kirsher A_PM1_RX_INT_CAUSE, 2040f7917c00SJeff Kirsher A_MPS_INT_CAUSE, 2041f7917c00SJeff Kirsher A_T3DBG_INT_CAUSE, 2042f7917c00SJeff Kirsher }; 2043f7917c00SJeff Kirsher unsigned int i; 2044f7917c00SJeff Kirsher 2045f7917c00SJeff Kirsher /* Clear PHY and MAC interrupts for each port. */ 2046f7917c00SJeff Kirsher for_each_port(adapter, i) 2047f7917c00SJeff Kirsher t3_port_intr_clear(adapter, i); 2048f7917c00SJeff Kirsher 2049f7917c00SJeff Kirsher for (i = 0; i < ARRAY_SIZE(cause_reg_addr); ++i) 2050f7917c00SJeff Kirsher t3_write_reg(adapter, cause_reg_addr[i], 0xffffffff); 2051f7917c00SJeff Kirsher 2052f7917c00SJeff Kirsher if (is_pcie(adapter)) 2053f7917c00SJeff Kirsher t3_write_reg(adapter, A_PCIE_PEX_ERR, 0xffffffff); 2054f7917c00SJeff Kirsher t3_write_reg(adapter, A_PL_INT_CAUSE0, 0xffffffff); 2055f7917c00SJeff Kirsher t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ 2056f7917c00SJeff Kirsher } 2057f7917c00SJeff Kirsher 2058f7917c00SJeff Kirsher void t3_xgm_intr_enable(struct adapter *adapter, int idx) 2059f7917c00SJeff Kirsher { 2060f7917c00SJeff Kirsher struct port_info *pi = adap2pinfo(adapter, idx); 2061f7917c00SJeff Kirsher 2062f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XGM_INT_ENABLE + pi->mac.offset, 2063f7917c00SJeff Kirsher XGM_EXTRA_INTR_MASK); 2064f7917c00SJeff Kirsher } 2065f7917c00SJeff Kirsher 2066f7917c00SJeff Kirsher void t3_xgm_intr_disable(struct adapter *adapter, int idx) 2067f7917c00SJeff Kirsher { 2068f7917c00SJeff Kirsher struct port_info *pi = adap2pinfo(adapter, idx); 2069f7917c00SJeff Kirsher 2070f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XGM_INT_DISABLE + pi->mac.offset, 2071f7917c00SJeff Kirsher 0x7ff); 2072f7917c00SJeff Kirsher } 2073f7917c00SJeff Kirsher 2074f7917c00SJeff Kirsher /** 2075f7917c00SJeff Kirsher * t3_port_intr_enable - enable port-specific interrupts 2076f7917c00SJeff Kirsher * @adapter: associated adapter 2077f7917c00SJeff Kirsher * @idx: index of port whose interrupts should be enabled 2078f7917c00SJeff Kirsher * 2079f7917c00SJeff Kirsher * Enable port-specific (i.e., MAC and PHY) interrupts for the given 2080f7917c00SJeff Kirsher * adapter port. 2081f7917c00SJeff Kirsher */ 2082f7917c00SJeff Kirsher void t3_port_intr_enable(struct adapter *adapter, int idx) 2083f7917c00SJeff Kirsher { 2084f7917c00SJeff Kirsher struct cphy *phy = &adap2pinfo(adapter, idx)->phy; 2085f7917c00SJeff Kirsher 2086f7917c00SJeff Kirsher t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), XGM_INTR_MASK); 2087f7917c00SJeff Kirsher t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */ 2088f7917c00SJeff Kirsher phy->ops->intr_enable(phy); 2089f7917c00SJeff Kirsher } 2090f7917c00SJeff Kirsher 2091f7917c00SJeff Kirsher /** 2092f7917c00SJeff Kirsher * t3_port_intr_disable - disable port-specific interrupts 2093f7917c00SJeff Kirsher * @adapter: associated adapter 2094f7917c00SJeff Kirsher * @idx: index of port whose interrupts should be disabled 2095f7917c00SJeff Kirsher * 2096f7917c00SJeff Kirsher * Disable port-specific (i.e., MAC and PHY) interrupts for the given 2097f7917c00SJeff Kirsher * adapter port. 2098f7917c00SJeff Kirsher */ 2099f7917c00SJeff Kirsher void t3_port_intr_disable(struct adapter *adapter, int idx) 2100f7917c00SJeff Kirsher { 2101f7917c00SJeff Kirsher struct cphy *phy = &adap2pinfo(adapter, idx)->phy; 2102f7917c00SJeff Kirsher 2103f7917c00SJeff Kirsher t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), 0); 2104f7917c00SJeff Kirsher t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */ 2105f7917c00SJeff Kirsher phy->ops->intr_disable(phy); 2106f7917c00SJeff Kirsher } 2107f7917c00SJeff Kirsher 2108f7917c00SJeff Kirsher /** 2109f7917c00SJeff Kirsher * t3_port_intr_clear - clear port-specific interrupts 2110f7917c00SJeff Kirsher * @adapter: associated adapter 2111f7917c00SJeff Kirsher * @idx: index of port whose interrupts to clear 2112f7917c00SJeff Kirsher * 2113f7917c00SJeff Kirsher * Clear port-specific (i.e., MAC and PHY) interrupts for the given 2114f7917c00SJeff Kirsher * adapter port. 2115f7917c00SJeff Kirsher */ 2116f7917c00SJeff Kirsher static void t3_port_intr_clear(struct adapter *adapter, int idx) 2117f7917c00SJeff Kirsher { 2118f7917c00SJeff Kirsher struct cphy *phy = &adap2pinfo(adapter, idx)->phy; 2119f7917c00SJeff Kirsher 2120f7917c00SJeff Kirsher t3_write_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx), 0xffffffff); 2121f7917c00SJeff Kirsher t3_read_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx)); /* flush */ 2122f7917c00SJeff Kirsher phy->ops->intr_clear(phy); 2123f7917c00SJeff Kirsher } 2124f7917c00SJeff Kirsher 2125f7917c00SJeff Kirsher #define SG_CONTEXT_CMD_ATTEMPTS 100 2126f7917c00SJeff Kirsher 2127f7917c00SJeff Kirsher /** 2128f7917c00SJeff Kirsher * t3_sge_write_context - write an SGE context 2129f7917c00SJeff Kirsher * @adapter: the adapter 2130f7917c00SJeff Kirsher * @id: the context id 2131f7917c00SJeff Kirsher * @type: the context type 2132f7917c00SJeff Kirsher * 2133f7917c00SJeff Kirsher * Program an SGE context with the values already loaded in the 2134f7917c00SJeff Kirsher * CONTEXT_DATA? registers. 2135f7917c00SJeff Kirsher */ 2136f7917c00SJeff Kirsher static int t3_sge_write_context(struct adapter *adapter, unsigned int id, 2137f7917c00SJeff Kirsher unsigned int type) 2138f7917c00SJeff Kirsher { 2139f7917c00SJeff Kirsher if (type == F_RESPONSEQ) { 2140f7917c00SJeff Kirsher /* 2141f7917c00SJeff Kirsher * Can't write the Response Queue Context bits for 2142f7917c00SJeff Kirsher * Interrupt Armed or the Reserve bits after the chip 2143f7917c00SJeff Kirsher * has been initialized out of reset. Writing to these 2144f7917c00SJeff Kirsher * bits can confuse the hardware. 2145f7917c00SJeff Kirsher */ 2146f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); 2147f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); 2148f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0x17ffffff); 2149f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); 2150f7917c00SJeff Kirsher } else { 2151f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); 2152f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); 2153f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff); 2154f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); 2155f7917c00SJeff Kirsher } 2156f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2157f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); 2158f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2159f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2160f7917c00SJeff Kirsher } 2161f7917c00SJeff Kirsher 2162f7917c00SJeff Kirsher /** 2163f7917c00SJeff Kirsher * clear_sge_ctxt - completely clear an SGE context 2164f7917c00SJeff Kirsher * @adapter: the adapter 2165f7917c00SJeff Kirsher * @id: the context id 2166f7917c00SJeff Kirsher * @type: the context type 2167f7917c00SJeff Kirsher * 2168f7917c00SJeff Kirsher * Completely clear an SGE context. Used predominantly at post-reset 2169f7917c00SJeff Kirsher * initialization. Note in particular that we don't skip writing to any 2170f7917c00SJeff Kirsher * "sensitive bits" in the contexts the way that t3_sge_write_context() 2171f7917c00SJeff Kirsher * does ... 2172f7917c00SJeff Kirsher */ 2173f7917c00SJeff Kirsher static int clear_sge_ctxt(struct adapter *adap, unsigned int id, 2174f7917c00SJeff Kirsher unsigned int type) 2175f7917c00SJeff Kirsher { 2176f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_DATA0, 0); 2177f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_DATA1, 0); 2178f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_DATA2, 0); 2179f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_DATA3, 0); 2180f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_MASK0, 0xffffffff); 2181f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_MASK1, 0xffffffff); 2182f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_MASK2, 0xffffffff); 2183f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_MASK3, 0xffffffff); 2184f7917c00SJeff Kirsher t3_write_reg(adap, A_SG_CONTEXT_CMD, 2185f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); 2186f7917c00SJeff Kirsher return t3_wait_op_done(adap, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2187f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2188f7917c00SJeff Kirsher } 2189f7917c00SJeff Kirsher 2190f7917c00SJeff Kirsher /** 2191f7917c00SJeff Kirsher * t3_sge_init_ecntxt - initialize an SGE egress context 2192f7917c00SJeff Kirsher * @adapter: the adapter to configure 2193f7917c00SJeff Kirsher * @id: the context id 2194f7917c00SJeff Kirsher * @gts_enable: whether to enable GTS for the context 2195f7917c00SJeff Kirsher * @type: the egress context type 2196f7917c00SJeff Kirsher * @respq: associated response queue 2197f7917c00SJeff Kirsher * @base_addr: base address of queue 2198f7917c00SJeff Kirsher * @size: number of queue entries 2199f7917c00SJeff Kirsher * @token: uP token 2200f7917c00SJeff Kirsher * @gen: initial generation value for the context 2201f7917c00SJeff Kirsher * @cidx: consumer pointer 2202f7917c00SJeff Kirsher * 2203f7917c00SJeff Kirsher * Initialize an SGE egress context and make it ready for use. If the 2204f7917c00SJeff Kirsher * platform allows concurrent context operations, the caller is 2205f7917c00SJeff Kirsher * responsible for appropriate locking. 2206f7917c00SJeff Kirsher */ 2207f7917c00SJeff Kirsher int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable, 2208f7917c00SJeff Kirsher enum sge_context_type type, int respq, u64 base_addr, 2209f7917c00SJeff Kirsher unsigned int size, unsigned int token, int gen, 2210f7917c00SJeff Kirsher unsigned int cidx) 2211f7917c00SJeff Kirsher { 2212f7917c00SJeff Kirsher unsigned int credits = type == SGE_CNTXT_OFLD ? 0 : FW_WR_NUM; 2213f7917c00SJeff Kirsher 2214f7917c00SJeff Kirsher if (base_addr & 0xfff) /* must be 4K aligned */ 2215f7917c00SJeff Kirsher return -EINVAL; 2216f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2217f7917c00SJeff Kirsher return -EBUSY; 2218f7917c00SJeff Kirsher 2219f7917c00SJeff Kirsher base_addr >>= 12; 2220f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_EC_INDEX(cidx) | 2221f7917c00SJeff Kirsher V_EC_CREDITS(credits) | V_EC_GTS(gts_enable)); 2222f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA1, V_EC_SIZE(size) | 2223f7917c00SJeff Kirsher V_EC_BASE_LO(base_addr & 0xffff)); 2224f7917c00SJeff Kirsher base_addr >>= 16; 2225f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA2, base_addr); 2226f7917c00SJeff Kirsher base_addr >>= 32; 2227f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA3, 2228f7917c00SJeff Kirsher V_EC_BASE_HI(base_addr & 0xf) | V_EC_RESPQ(respq) | 2229f7917c00SJeff Kirsher V_EC_TYPE(type) | V_EC_GEN(gen) | V_EC_UP_TOKEN(token) | 2230f7917c00SJeff Kirsher F_EC_VALID); 2231f7917c00SJeff Kirsher return t3_sge_write_context(adapter, id, F_EGRESS); 2232f7917c00SJeff Kirsher } 2233f7917c00SJeff Kirsher 2234f7917c00SJeff Kirsher /** 2235f7917c00SJeff Kirsher * t3_sge_init_flcntxt - initialize an SGE free-buffer list context 2236f7917c00SJeff Kirsher * @adapter: the adapter to configure 2237f7917c00SJeff Kirsher * @id: the context id 2238f7917c00SJeff Kirsher * @gts_enable: whether to enable GTS for the context 2239f7917c00SJeff Kirsher * @base_addr: base address of queue 2240f7917c00SJeff Kirsher * @size: number of queue entries 2241f7917c00SJeff Kirsher * @bsize: size of each buffer for this queue 2242f7917c00SJeff Kirsher * @cong_thres: threshold to signal congestion to upstream producers 2243f7917c00SJeff Kirsher * @gen: initial generation value for the context 2244f7917c00SJeff Kirsher * @cidx: consumer pointer 2245f7917c00SJeff Kirsher * 2246f7917c00SJeff Kirsher * Initialize an SGE free list context and make it ready for use. The 2247f7917c00SJeff Kirsher * caller is responsible for ensuring only one context operation occurs 2248f7917c00SJeff Kirsher * at a time. 2249f7917c00SJeff Kirsher */ 2250f7917c00SJeff Kirsher int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id, 2251f7917c00SJeff Kirsher int gts_enable, u64 base_addr, unsigned int size, 2252f7917c00SJeff Kirsher unsigned int bsize, unsigned int cong_thres, int gen, 2253f7917c00SJeff Kirsher unsigned int cidx) 2254f7917c00SJeff Kirsher { 2255f7917c00SJeff Kirsher if (base_addr & 0xfff) /* must be 4K aligned */ 2256f7917c00SJeff Kirsher return -EINVAL; 2257f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2258f7917c00SJeff Kirsher return -EBUSY; 2259f7917c00SJeff Kirsher 2260f7917c00SJeff Kirsher base_addr >>= 12; 2261f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, base_addr); 2262f7917c00SJeff Kirsher base_addr >>= 32; 2263f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA1, 2264f7917c00SJeff Kirsher V_FL_BASE_HI((u32) base_addr) | 2265f7917c00SJeff Kirsher V_FL_INDEX_LO(cidx & M_FL_INDEX_LO)); 2266f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA2, V_FL_SIZE(size) | 2267f7917c00SJeff Kirsher V_FL_GEN(gen) | V_FL_INDEX_HI(cidx >> 12) | 2268f7917c00SJeff Kirsher V_FL_ENTRY_SIZE_LO(bsize & M_FL_ENTRY_SIZE_LO)); 2269f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA3, 2270f7917c00SJeff Kirsher V_FL_ENTRY_SIZE_HI(bsize >> (32 - S_FL_ENTRY_SIZE_LO)) | 2271f7917c00SJeff Kirsher V_FL_CONG_THRES(cong_thres) | V_FL_GTS(gts_enable)); 2272f7917c00SJeff Kirsher return t3_sge_write_context(adapter, id, F_FREELIST); 2273f7917c00SJeff Kirsher } 2274f7917c00SJeff Kirsher 2275f7917c00SJeff Kirsher /** 2276f7917c00SJeff Kirsher * t3_sge_init_rspcntxt - initialize an SGE response queue context 2277f7917c00SJeff Kirsher * @adapter: the adapter to configure 2278f7917c00SJeff Kirsher * @id: the context id 2279f7917c00SJeff Kirsher * @irq_vec_idx: MSI-X interrupt vector index, 0 if no MSI-X, -1 if no IRQ 2280f7917c00SJeff Kirsher * @base_addr: base address of queue 2281f7917c00SJeff Kirsher * @size: number of queue entries 2282f7917c00SJeff Kirsher * @fl_thres: threshold for selecting the normal or jumbo free list 2283f7917c00SJeff Kirsher * @gen: initial generation value for the context 2284f7917c00SJeff Kirsher * @cidx: consumer pointer 2285f7917c00SJeff Kirsher * 2286f7917c00SJeff Kirsher * Initialize an SGE response queue context and make it ready for use. 2287f7917c00SJeff Kirsher * The caller is responsible for ensuring only one context operation 2288f7917c00SJeff Kirsher * occurs at a time. 2289f7917c00SJeff Kirsher */ 2290f7917c00SJeff Kirsher int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id, 2291f7917c00SJeff Kirsher int irq_vec_idx, u64 base_addr, unsigned int size, 2292f7917c00SJeff Kirsher unsigned int fl_thres, int gen, unsigned int cidx) 2293f7917c00SJeff Kirsher { 2294f7917c00SJeff Kirsher unsigned int intr = 0; 2295f7917c00SJeff Kirsher 2296f7917c00SJeff Kirsher if (base_addr & 0xfff) /* must be 4K aligned */ 2297f7917c00SJeff Kirsher return -EINVAL; 2298f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2299f7917c00SJeff Kirsher return -EBUSY; 2300f7917c00SJeff Kirsher 2301f7917c00SJeff Kirsher base_addr >>= 12; 2302f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size) | 2303f7917c00SJeff Kirsher V_CQ_INDEX(cidx)); 2304f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr); 2305f7917c00SJeff Kirsher base_addr >>= 32; 2306f7917c00SJeff Kirsher if (irq_vec_idx >= 0) 2307f7917c00SJeff Kirsher intr = V_RQ_MSI_VEC(irq_vec_idx) | F_RQ_INTR_EN; 2308f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 2309f7917c00SJeff Kirsher V_CQ_BASE_HI((u32) base_addr) | intr | V_RQ_GEN(gen)); 2310f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA3, fl_thres); 2311f7917c00SJeff Kirsher return t3_sge_write_context(adapter, id, F_RESPONSEQ); 2312f7917c00SJeff Kirsher } 2313f7917c00SJeff Kirsher 2314f7917c00SJeff Kirsher /** 2315f7917c00SJeff Kirsher * t3_sge_init_cqcntxt - initialize an SGE completion queue context 2316f7917c00SJeff Kirsher * @adapter: the adapter to configure 2317f7917c00SJeff Kirsher * @id: the context id 2318f7917c00SJeff Kirsher * @base_addr: base address of queue 2319f7917c00SJeff Kirsher * @size: number of queue entries 2320f7917c00SJeff Kirsher * @rspq: response queue for async notifications 2321f7917c00SJeff Kirsher * @ovfl_mode: CQ overflow mode 2322f7917c00SJeff Kirsher * @credits: completion queue credits 2323f7917c00SJeff Kirsher * @credit_thres: the credit threshold 2324f7917c00SJeff Kirsher * 2325f7917c00SJeff Kirsher * Initialize an SGE completion queue context and make it ready for use. 2326f7917c00SJeff Kirsher * The caller is responsible for ensuring only one context operation 2327f7917c00SJeff Kirsher * occurs at a time. 2328f7917c00SJeff Kirsher */ 2329f7917c00SJeff Kirsher int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr, 2330f7917c00SJeff Kirsher unsigned int size, int rspq, int ovfl_mode, 2331f7917c00SJeff Kirsher unsigned int credits, unsigned int credit_thres) 2332f7917c00SJeff Kirsher { 2333f7917c00SJeff Kirsher if (base_addr & 0xfff) /* must be 4K aligned */ 2334f7917c00SJeff Kirsher return -EINVAL; 2335f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2336f7917c00SJeff Kirsher return -EBUSY; 2337f7917c00SJeff Kirsher 2338f7917c00SJeff Kirsher base_addr >>= 12; 2339f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size)); 2340f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr); 2341f7917c00SJeff Kirsher base_addr >>= 32; 2342f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 2343f7917c00SJeff Kirsher V_CQ_BASE_HI((u32) base_addr) | V_CQ_RSPQ(rspq) | 2344f7917c00SJeff Kirsher V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode) | 2345f7917c00SJeff Kirsher V_CQ_ERR(ovfl_mode)); 2346f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_CQ_CREDITS(credits) | 2347f7917c00SJeff Kirsher V_CQ_CREDIT_THRES(credit_thres)); 2348f7917c00SJeff Kirsher return t3_sge_write_context(adapter, id, F_CQ); 2349f7917c00SJeff Kirsher } 2350f7917c00SJeff Kirsher 2351f7917c00SJeff Kirsher /** 2352f7917c00SJeff Kirsher * t3_sge_enable_ecntxt - enable/disable an SGE egress context 2353f7917c00SJeff Kirsher * @adapter: the adapter 2354f7917c00SJeff Kirsher * @id: the egress context id 2355f7917c00SJeff Kirsher * @enable: enable (1) or disable (0) the context 2356f7917c00SJeff Kirsher * 2357f7917c00SJeff Kirsher * Enable or disable an SGE egress context. The caller is responsible for 2358f7917c00SJeff Kirsher * ensuring only one context operation occurs at a time. 2359f7917c00SJeff Kirsher */ 2360f7917c00SJeff Kirsher int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable) 2361f7917c00SJeff Kirsher { 2362f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2363f7917c00SJeff Kirsher return -EBUSY; 2364f7917c00SJeff Kirsher 2365f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0); 2366f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); 2367f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); 2368f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, F_EC_VALID); 2369f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_EC_VALID(enable)); 2370f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2371f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | F_EGRESS | V_CONTEXT(id)); 2372f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2373f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2374f7917c00SJeff Kirsher } 2375f7917c00SJeff Kirsher 2376f7917c00SJeff Kirsher /** 2377f7917c00SJeff Kirsher * t3_sge_disable_fl - disable an SGE free-buffer list 2378f7917c00SJeff Kirsher * @adapter: the adapter 2379f7917c00SJeff Kirsher * @id: the free list context id 2380f7917c00SJeff Kirsher * 2381f7917c00SJeff Kirsher * Disable an SGE free-buffer list. The caller is responsible for 2382f7917c00SJeff Kirsher * ensuring only one context operation occurs at a time. 2383f7917c00SJeff Kirsher */ 2384f7917c00SJeff Kirsher int t3_sge_disable_fl(struct adapter *adapter, unsigned int id) 2385f7917c00SJeff Kirsher { 2386f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2387f7917c00SJeff Kirsher return -EBUSY; 2388f7917c00SJeff Kirsher 2389f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0); 2390f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); 2391f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, V_FL_SIZE(M_FL_SIZE)); 2392f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); 2393f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 0); 2394f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2395f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | F_FREELIST | V_CONTEXT(id)); 2396f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2397f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2398f7917c00SJeff Kirsher } 2399f7917c00SJeff Kirsher 2400f7917c00SJeff Kirsher /** 2401f7917c00SJeff Kirsher * t3_sge_disable_rspcntxt - disable an SGE response queue 2402f7917c00SJeff Kirsher * @adapter: the adapter 2403f7917c00SJeff Kirsher * @id: the response queue context id 2404f7917c00SJeff Kirsher * 2405f7917c00SJeff Kirsher * Disable an SGE response queue. The caller is responsible for 2406f7917c00SJeff Kirsher * ensuring only one context operation occurs at a time. 2407f7917c00SJeff Kirsher */ 2408f7917c00SJeff Kirsher int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id) 2409f7917c00SJeff Kirsher { 2410f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2411f7917c00SJeff Kirsher return -EBUSY; 2412f7917c00SJeff Kirsher 2413f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE)); 2414f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); 2415f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); 2416f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); 2417f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0); 2418f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2419f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | F_RESPONSEQ | V_CONTEXT(id)); 2420f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2421f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2422f7917c00SJeff Kirsher } 2423f7917c00SJeff Kirsher 2424f7917c00SJeff Kirsher /** 2425f7917c00SJeff Kirsher * t3_sge_disable_cqcntxt - disable an SGE completion queue 2426f7917c00SJeff Kirsher * @adapter: the adapter 2427f7917c00SJeff Kirsher * @id: the completion queue context id 2428f7917c00SJeff Kirsher * 2429f7917c00SJeff Kirsher * Disable an SGE completion queue. The caller is responsible for 2430f7917c00SJeff Kirsher * ensuring only one context operation occurs at a time. 2431f7917c00SJeff Kirsher */ 2432f7917c00SJeff Kirsher int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id) 2433f7917c00SJeff Kirsher { 2434f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2435f7917c00SJeff Kirsher return -EBUSY; 2436f7917c00SJeff Kirsher 2437f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE)); 2438f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); 2439f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); 2440f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); 2441f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0); 2442f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2443f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(1) | F_CQ | V_CONTEXT(id)); 2444f7917c00SJeff Kirsher return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2445f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1); 2446f7917c00SJeff Kirsher } 2447f7917c00SJeff Kirsher 2448f7917c00SJeff Kirsher /** 2449f7917c00SJeff Kirsher * t3_sge_cqcntxt_op - perform an operation on a completion queue context 2450f7917c00SJeff Kirsher * @adapter: the adapter 2451f7917c00SJeff Kirsher * @id: the context id 2452f7917c00SJeff Kirsher * @op: the operation to perform 2453f7917c00SJeff Kirsher * 2454f7917c00SJeff Kirsher * Perform the selected operation on an SGE completion queue context. 2455f7917c00SJeff Kirsher * The caller is responsible for ensuring only one context operation 2456f7917c00SJeff Kirsher * occurs at a time. 2457f7917c00SJeff Kirsher */ 2458f7917c00SJeff Kirsher int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op, 2459f7917c00SJeff Kirsher unsigned int credits) 2460f7917c00SJeff Kirsher { 2461f7917c00SJeff Kirsher u32 val; 2462f7917c00SJeff Kirsher 2463f7917c00SJeff Kirsher if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 2464f7917c00SJeff Kirsher return -EBUSY; 2465f7917c00SJeff Kirsher 2466f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_DATA0, credits << 16); 2467f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(op) | 2468f7917c00SJeff Kirsher V_CONTEXT(id) | F_CQ); 2469f7917c00SJeff Kirsher if (t3_wait_op_done_val(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 2470f7917c00SJeff Kirsher 0, SG_CONTEXT_CMD_ATTEMPTS, 1, &val)) 2471f7917c00SJeff Kirsher return -EIO; 2472f7917c00SJeff Kirsher 2473f7917c00SJeff Kirsher if (op >= 2 && op < 7) { 2474f7917c00SJeff Kirsher if (adapter->params.rev > 0) 2475f7917c00SJeff Kirsher return G_CQ_INDEX(val); 2476f7917c00SJeff Kirsher 2477f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_CONTEXT_CMD, 2478f7917c00SJeff Kirsher V_CONTEXT_CMD_OPCODE(0) | F_CQ | V_CONTEXT(id)); 2479f7917c00SJeff Kirsher if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, 2480f7917c00SJeff Kirsher F_CONTEXT_CMD_BUSY, 0, 2481f7917c00SJeff Kirsher SG_CONTEXT_CMD_ATTEMPTS, 1)) 2482f7917c00SJeff Kirsher return -EIO; 2483f7917c00SJeff Kirsher return G_CQ_INDEX(t3_read_reg(adapter, A_SG_CONTEXT_DATA0)); 2484f7917c00SJeff Kirsher } 2485f7917c00SJeff Kirsher return 0; 2486f7917c00SJeff Kirsher } 2487f7917c00SJeff Kirsher 2488f7917c00SJeff Kirsher /** 2489f7917c00SJeff Kirsher * t3_config_rss - configure Rx packet steering 2490f7917c00SJeff Kirsher * @adapter: the adapter 2491f7917c00SJeff Kirsher * @rss_config: RSS settings (written to TP_RSS_CONFIG) 2492f7917c00SJeff Kirsher * @cpus: values for the CPU lookup table (0xff terminated) 2493f7917c00SJeff Kirsher * @rspq: values for the response queue lookup table (0xffff terminated) 2494f7917c00SJeff Kirsher * 2495f7917c00SJeff Kirsher * Programs the receive packet steering logic. @cpus and @rspq provide 2496f7917c00SJeff Kirsher * the values for the CPU and response queue lookup tables. If they 2497f7917c00SJeff Kirsher * provide fewer values than the size of the tables the supplied values 2498f7917c00SJeff Kirsher * are used repeatedly until the tables are fully populated. 2499f7917c00SJeff Kirsher */ 2500f7917c00SJeff Kirsher void t3_config_rss(struct adapter *adapter, unsigned int rss_config, 2501f7917c00SJeff Kirsher const u8 * cpus, const u16 *rspq) 2502f7917c00SJeff Kirsher { 2503f7917c00SJeff Kirsher int i, j, cpu_idx = 0, q_idx = 0; 2504f7917c00SJeff Kirsher 2505f7917c00SJeff Kirsher if (cpus) 2506f7917c00SJeff Kirsher for (i = 0; i < RSS_TABLE_SIZE; ++i) { 2507f7917c00SJeff Kirsher u32 val = i << 16; 2508f7917c00SJeff Kirsher 2509f7917c00SJeff Kirsher for (j = 0; j < 2; ++j) { 2510f7917c00SJeff Kirsher val |= (cpus[cpu_idx++] & 0x3f) << (8 * j); 2511f7917c00SJeff Kirsher if (cpus[cpu_idx] == 0xff) 2512f7917c00SJeff Kirsher cpu_idx = 0; 2513f7917c00SJeff Kirsher } 2514f7917c00SJeff Kirsher t3_write_reg(adapter, A_TP_RSS_LKP_TABLE, val); 2515f7917c00SJeff Kirsher } 2516f7917c00SJeff Kirsher 2517f7917c00SJeff Kirsher if (rspq) 2518f7917c00SJeff Kirsher for (i = 0; i < RSS_TABLE_SIZE; ++i) { 2519f7917c00SJeff Kirsher t3_write_reg(adapter, A_TP_RSS_MAP_TABLE, 2520f7917c00SJeff Kirsher (i << 16) | rspq[q_idx++]); 2521f7917c00SJeff Kirsher if (rspq[q_idx] == 0xffff) 2522f7917c00SJeff Kirsher q_idx = 0; 2523f7917c00SJeff Kirsher } 2524f7917c00SJeff Kirsher 2525f7917c00SJeff Kirsher t3_write_reg(adapter, A_TP_RSS_CONFIG, rss_config); 2526f7917c00SJeff Kirsher } 2527f7917c00SJeff Kirsher 2528f7917c00SJeff Kirsher /** 2529f7917c00SJeff Kirsher * t3_tp_set_offload_mode - put TP in NIC/offload mode 2530f7917c00SJeff Kirsher * @adap: the adapter 2531f7917c00SJeff Kirsher * @enable: 1 to select offload mode, 0 for regular NIC 2532f7917c00SJeff Kirsher * 2533f7917c00SJeff Kirsher * Switches TP to NIC/offload mode. 2534f7917c00SJeff Kirsher */ 2535f7917c00SJeff Kirsher void t3_tp_set_offload_mode(struct adapter *adap, int enable) 2536f7917c00SJeff Kirsher { 2537f7917c00SJeff Kirsher if (is_offload(adap) || !enable) 2538f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_IN_CONFIG, F_NICMODE, 2539f7917c00SJeff Kirsher V_NICMODE(!enable)); 2540f7917c00SJeff Kirsher } 2541f7917c00SJeff Kirsher 2542f7917c00SJeff Kirsher /** 2543f7917c00SJeff Kirsher * pm_num_pages - calculate the number of pages of the payload memory 2544f7917c00SJeff Kirsher * @mem_size: the size of the payload memory 2545f7917c00SJeff Kirsher * @pg_size: the size of each payload memory page 2546f7917c00SJeff Kirsher * 2547f7917c00SJeff Kirsher * Calculate the number of pages, each of the given size, that fit in a 2548f7917c00SJeff Kirsher * memory of the specified size, respecting the HW requirement that the 2549f7917c00SJeff Kirsher * number of pages must be a multiple of 24. 2550f7917c00SJeff Kirsher */ 2551f7917c00SJeff Kirsher static inline unsigned int pm_num_pages(unsigned int mem_size, 2552f7917c00SJeff Kirsher unsigned int pg_size) 2553f7917c00SJeff Kirsher { 2554f7917c00SJeff Kirsher unsigned int n = mem_size / pg_size; 2555f7917c00SJeff Kirsher 2556f7917c00SJeff Kirsher return n - n % 24; 2557f7917c00SJeff Kirsher } 2558f7917c00SJeff Kirsher 2559f7917c00SJeff Kirsher #define mem_region(adap, start, size, reg) \ 2560f7917c00SJeff Kirsher t3_write_reg((adap), A_ ## reg, (start)); \ 2561f7917c00SJeff Kirsher start += size 2562f7917c00SJeff Kirsher 2563f7917c00SJeff Kirsher /** 2564f7917c00SJeff Kirsher * partition_mem - partition memory and configure TP memory settings 2565f7917c00SJeff Kirsher * @adap: the adapter 2566f7917c00SJeff Kirsher * @p: the TP parameters 2567f7917c00SJeff Kirsher * 2568f7917c00SJeff Kirsher * Partitions context and payload memory and configures TP's memory 2569f7917c00SJeff Kirsher * registers. 2570f7917c00SJeff Kirsher */ 2571f7917c00SJeff Kirsher static void partition_mem(struct adapter *adap, const struct tp_params *p) 2572f7917c00SJeff Kirsher { 2573f7917c00SJeff Kirsher unsigned int m, pstructs, tids = t3_mc5_size(&adap->mc5); 2574f7917c00SJeff Kirsher unsigned int timers = 0, timers_shift = 22; 2575f7917c00SJeff Kirsher 2576f7917c00SJeff Kirsher if (adap->params.rev > 0) { 2577f7917c00SJeff Kirsher if (tids <= 16 * 1024) { 2578f7917c00SJeff Kirsher timers = 1; 2579f7917c00SJeff Kirsher timers_shift = 16; 2580f7917c00SJeff Kirsher } else if (tids <= 64 * 1024) { 2581f7917c00SJeff Kirsher timers = 2; 2582f7917c00SJeff Kirsher timers_shift = 18; 2583f7917c00SJeff Kirsher } else if (tids <= 256 * 1024) { 2584f7917c00SJeff Kirsher timers = 3; 2585f7917c00SJeff Kirsher timers_shift = 20; 2586f7917c00SJeff Kirsher } 2587f7917c00SJeff Kirsher } 2588f7917c00SJeff Kirsher 2589f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_SIZE, 2590f7917c00SJeff Kirsher p->chan_rx_size | (p->chan_tx_size >> 16)); 2591f7917c00SJeff Kirsher 2592f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_TX_BASE, 0); 2593f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_TX_PAGE_SIZE, p->tx_pg_size); 2594f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_TX_MAX_PAGE, p->tx_num_pgs); 2595f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PARA_REG3, V_TXDATAACKIDX(M_TXDATAACKIDX), 2596f7917c00SJeff Kirsher V_TXDATAACKIDX(fls(p->tx_pg_size) - 12)); 2597f7917c00SJeff Kirsher 2598f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_RX_BASE, 0); 2599f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_RX_PAGE_SIZE, p->rx_pg_size); 2600f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PMM_RX_MAX_PAGE, p->rx_num_pgs); 2601f7917c00SJeff Kirsher 2602f7917c00SJeff Kirsher pstructs = p->rx_num_pgs + p->tx_num_pgs; 2603f7917c00SJeff Kirsher /* Add a bit of headroom and make multiple of 24 */ 2604f7917c00SJeff Kirsher pstructs += 48; 2605f7917c00SJeff Kirsher pstructs -= pstructs % 24; 2606f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_CMM_MM_MAX_PSTRUCT, pstructs); 2607f7917c00SJeff Kirsher 2608f7917c00SJeff Kirsher m = tids * TCB_SIZE; 2609f7917c00SJeff Kirsher mem_region(adap, m, (64 << 10) * 64, SG_EGR_CNTX_BADDR); 2610f7917c00SJeff Kirsher mem_region(adap, m, (64 << 10) * 64, SG_CQ_CONTEXT_BADDR); 2611f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_CMM_TIMER_BASE, V_CMTIMERMAXNUM(timers) | m); 2612f7917c00SJeff Kirsher m += ((p->ntimer_qs - 1) << timers_shift) + (1 << 22); 2613f7917c00SJeff Kirsher mem_region(adap, m, pstructs * 64, TP_CMM_MM_BASE); 2614f7917c00SJeff Kirsher mem_region(adap, m, 64 * (pstructs / 24), TP_CMM_MM_PS_FLST_BASE); 2615f7917c00SJeff Kirsher mem_region(adap, m, 64 * (p->rx_num_pgs / 24), TP_CMM_MM_RX_FLST_BASE); 2616f7917c00SJeff Kirsher mem_region(adap, m, 64 * (p->tx_num_pgs / 24), TP_CMM_MM_TX_FLST_BASE); 2617f7917c00SJeff Kirsher 2618f7917c00SJeff Kirsher m = (m + 4095) & ~0xfff; 2619f7917c00SJeff Kirsher t3_write_reg(adap, A_CIM_SDRAM_BASE_ADDR, m); 2620f7917c00SJeff Kirsher t3_write_reg(adap, A_CIM_SDRAM_ADDR_SIZE, p->cm_size - m); 2621f7917c00SJeff Kirsher 2622f7917c00SJeff Kirsher tids = (p->cm_size - m - (3 << 20)) / 3072 - 32; 2623f7917c00SJeff Kirsher m = t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers - 2624f7917c00SJeff Kirsher adap->params.mc5.nfilters - adap->params.mc5.nroutes; 2625f7917c00SJeff Kirsher if (tids < m) 2626f7917c00SJeff Kirsher adap->params.mc5.nservers += m - tids; 2627f7917c00SJeff Kirsher } 2628f7917c00SJeff Kirsher 2629f7917c00SJeff Kirsher static inline void tp_wr_indirect(struct adapter *adap, unsigned int addr, 2630f7917c00SJeff Kirsher u32 val) 2631f7917c00SJeff Kirsher { 2632f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_ADDR, addr); 2633f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PIO_DATA, val); 2634f7917c00SJeff Kirsher } 2635f7917c00SJeff Kirsher 2636f7917c00SJeff Kirsher static void tp_config(struct adapter *adap, const struct tp_params *p) 2637f7917c00SJeff Kirsher { 2638f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU | 2639f7917c00SJeff Kirsher F_IPCHECKSUMOFFLOAD | F_UDPCHECKSUMOFFLOAD | 2640f7917c00SJeff Kirsher F_TCPCHECKSUMOFFLOAD | V_IPTTL(64)); 2641f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) | 2642f7917c00SJeff Kirsher F_MTUENABLE | V_WINDOWSCALEMODE(1) | 2643f7917c00SJeff Kirsher V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1)); 2644f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) | 2645f7917c00SJeff Kirsher V_AUTOSTATE2(1) | V_AUTOSTATE1(0) | 2646f7917c00SJeff Kirsher V_BYTETHRESHOLD(26880) | V_MSSTHRESHOLD(2) | 2647f7917c00SJeff Kirsher F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1)); 2648f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_IN_CONFIG, F_RXFBARBPRIO | F_TXFBARBPRIO, 2649f7917c00SJeff Kirsher F_IPV6ENABLE | F_NICMODE); 2650f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814); 2651f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105); 2652f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PARA_REG6, 0, 2653f7917c00SJeff Kirsher adap->params.rev > 0 ? F_ENABLEESND : 2654f7917c00SJeff Kirsher F_T3A_ENABLEESND); 2655f7917c00SJeff Kirsher 2656f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PC_CONFIG, 2657f7917c00SJeff Kirsher F_ENABLEEPCMDAFULL, 2658f7917c00SJeff Kirsher F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK | 2659f7917c00SJeff Kirsher F_TXCONGESTIONMODE | F_RXCONGESTIONMODE); 2660f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 2661f7917c00SJeff Kirsher F_ENABLEIPV6RSS | F_ENABLENONOFDTNLSYN | 2662f7917c00SJeff Kirsher F_ENABLEARPMISS | F_DISBLEDAPARBIT0); 2663f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080); 2664f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000); 2665f7917c00SJeff Kirsher 2666f7917c00SJeff Kirsher if (adap->params.rev > 0) { 2667f7917c00SJeff Kirsher tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE); 2668f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO, 2669f7917c00SJeff Kirsher F_TXPACEAUTO); 2670f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PC_CONFIG, F_LOCKTID, F_LOCKTID); 2671f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEAUTOSTRICT); 2672f7917c00SJeff Kirsher } else 2673f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED); 2674f7917c00SJeff Kirsher 2675f7917c00SJeff Kirsher if (adap->params.rev == T3_REV_C) 2676f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PC_CONFIG, 2677f7917c00SJeff Kirsher V_TABLELATENCYDELTA(M_TABLELATENCYDELTA), 2678f7917c00SJeff Kirsher V_TABLELATENCYDELTA(4)); 2679f7917c00SJeff Kirsher 2680f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0); 2681f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0); 2682f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0); 2683f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000); 2684f7917c00SJeff Kirsher } 2685f7917c00SJeff Kirsher 2686f7917c00SJeff Kirsher /* Desired TP timer resolution in usec */ 2687f7917c00SJeff Kirsher #define TP_TMR_RES 50 2688f7917c00SJeff Kirsher 2689f7917c00SJeff Kirsher /* TCP timer values in ms */ 2690f7917c00SJeff Kirsher #define TP_DACK_TIMER 50 2691f7917c00SJeff Kirsher #define TP_RTO_MIN 250 2692f7917c00SJeff Kirsher 2693f7917c00SJeff Kirsher /** 2694f7917c00SJeff Kirsher * tp_set_timers - set TP timing parameters 2695f7917c00SJeff Kirsher * @adap: the adapter to set 2696f7917c00SJeff Kirsher * @core_clk: the core clock frequency in Hz 2697f7917c00SJeff Kirsher * 2698f7917c00SJeff Kirsher * Set TP's timing parameters, such as the various timer resolutions and 2699f7917c00SJeff Kirsher * the TCP timer values. 2700f7917c00SJeff Kirsher */ 2701f7917c00SJeff Kirsher static void tp_set_timers(struct adapter *adap, unsigned int core_clk) 2702f7917c00SJeff Kirsher { 2703f7917c00SJeff Kirsher unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1; 2704f7917c00SJeff Kirsher unsigned int dack_re = fls(core_clk / 5000) - 1; /* 200us */ 2705f7917c00SJeff Kirsher unsigned int tstamp_re = fls(core_clk / 1000); /* 1ms, at least */ 2706f7917c00SJeff Kirsher unsigned int tps = core_clk >> tre; 2707f7917c00SJeff Kirsher 2708f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TIMER_RESOLUTION, V_TIMERRESOLUTION(tre) | 2709f7917c00SJeff Kirsher V_DELAYEDACKRESOLUTION(dack_re) | 2710f7917c00SJeff Kirsher V_TIMESTAMPRESOLUTION(tstamp_re)); 2711f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_DACK_TIMER, 2712f7917c00SJeff Kirsher (core_clk >> dack_re) / (1000 / TP_DACK_TIMER)); 2713f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TCP_BACKOFF_REG0, 0x3020100); 2714f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TCP_BACKOFF_REG1, 0x7060504); 2715f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TCP_BACKOFF_REG2, 0xb0a0908); 2716f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TCP_BACKOFF_REG3, 0xf0e0d0c); 2717f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_SHIFT_CNT, V_SYNSHIFTMAX(6) | 2718f7917c00SJeff Kirsher V_RXTSHIFTMAXR1(4) | V_RXTSHIFTMAXR2(15) | 2719f7917c00SJeff Kirsher V_PERSHIFTBACKOFFMAX(8) | V_PERSHIFTMAX(8) | 2720f7917c00SJeff Kirsher V_KEEPALIVEMAX(9)); 2721f7917c00SJeff Kirsher 2722f7917c00SJeff Kirsher #define SECONDS * tps 2723f7917c00SJeff Kirsher 2724f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_MSL, adap->params.rev > 0 ? 0 : 2 SECONDS); 2725f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_RXT_MIN, tps / (1000 / TP_RTO_MIN)); 2726f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_RXT_MAX, 64 SECONDS); 2727f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PERS_MIN, 5 SECONDS); 2728f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PERS_MAX, 64 SECONDS); 2729f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_KEEP_IDLE, 7200 SECONDS); 2730f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_KEEP_INTVL, 75 SECONDS); 2731f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_INIT_SRTT, 3 SECONDS); 2732f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_FINWAIT2_TIMER, 600 SECONDS); 2733f7917c00SJeff Kirsher 2734f7917c00SJeff Kirsher #undef SECONDS 2735f7917c00SJeff Kirsher } 2736f7917c00SJeff Kirsher 2737f7917c00SJeff Kirsher /** 2738f7917c00SJeff Kirsher * t3_tp_set_coalescing_size - set receive coalescing size 2739f7917c00SJeff Kirsher * @adap: the adapter 2740f7917c00SJeff Kirsher * @size: the receive coalescing size 2741f7917c00SJeff Kirsher * @psh: whether a set PSH bit should deliver coalesced data 2742f7917c00SJeff Kirsher * 2743f7917c00SJeff Kirsher * Set the receive coalescing size and PSH bit handling. 2744f7917c00SJeff Kirsher */ 2745f7917c00SJeff Kirsher static int t3_tp_set_coalescing_size(struct adapter *adap, 2746f7917c00SJeff Kirsher unsigned int size, int psh) 2747f7917c00SJeff Kirsher { 2748f7917c00SJeff Kirsher u32 val; 2749f7917c00SJeff Kirsher 2750f7917c00SJeff Kirsher if (size > MAX_RX_COALESCING_LEN) 2751f7917c00SJeff Kirsher return -EINVAL; 2752f7917c00SJeff Kirsher 2753f7917c00SJeff Kirsher val = t3_read_reg(adap, A_TP_PARA_REG3); 2754f7917c00SJeff Kirsher val &= ~(F_RXCOALESCEENABLE | F_RXCOALESCEPSHEN); 2755f7917c00SJeff Kirsher 2756f7917c00SJeff Kirsher if (size) { 2757f7917c00SJeff Kirsher val |= F_RXCOALESCEENABLE; 2758f7917c00SJeff Kirsher if (psh) 2759f7917c00SJeff Kirsher val |= F_RXCOALESCEPSHEN; 2760f7917c00SJeff Kirsher size = min(MAX_RX_COALESCING_LEN, size); 2761f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) | 2762f7917c00SJeff Kirsher V_MAXRXDATA(MAX_RX_COALESCING_LEN)); 2763f7917c00SJeff Kirsher } 2764f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PARA_REG3, val); 2765f7917c00SJeff Kirsher return 0; 2766f7917c00SJeff Kirsher } 2767f7917c00SJeff Kirsher 2768f7917c00SJeff Kirsher /** 2769f7917c00SJeff Kirsher * t3_tp_set_max_rxsize - set the max receive size 2770f7917c00SJeff Kirsher * @adap: the adapter 2771f7917c00SJeff Kirsher * @size: the max receive size 2772f7917c00SJeff Kirsher * 2773f7917c00SJeff Kirsher * Set TP's max receive size. This is the limit that applies when 2774f7917c00SJeff Kirsher * receive coalescing is disabled. 2775f7917c00SJeff Kirsher */ 2776f7917c00SJeff Kirsher static void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size) 2777f7917c00SJeff Kirsher { 2778f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_PARA_REG7, 2779f7917c00SJeff Kirsher V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size)); 2780f7917c00SJeff Kirsher } 2781f7917c00SJeff Kirsher 2782f7917c00SJeff Kirsher static void init_mtus(unsigned short mtus[]) 2783f7917c00SJeff Kirsher { 2784f7917c00SJeff Kirsher /* 2785f7917c00SJeff Kirsher * See draft-mathis-plpmtud-00.txt for the values. The min is 88 so 2786f7917c00SJeff Kirsher * it can accommodate max size TCP/IP headers when SACK and timestamps 2787f7917c00SJeff Kirsher * are enabled and still have at least 8 bytes of payload. 2788f7917c00SJeff Kirsher */ 2789f7917c00SJeff Kirsher mtus[0] = 88; 2790f7917c00SJeff Kirsher mtus[1] = 88; 2791f7917c00SJeff Kirsher mtus[2] = 256; 2792f7917c00SJeff Kirsher mtus[3] = 512; 2793f7917c00SJeff Kirsher mtus[4] = 576; 2794f7917c00SJeff Kirsher mtus[5] = 1024; 2795f7917c00SJeff Kirsher mtus[6] = 1280; 2796f7917c00SJeff Kirsher mtus[7] = 1492; 2797f7917c00SJeff Kirsher mtus[8] = 1500; 2798f7917c00SJeff Kirsher mtus[9] = 2002; 2799f7917c00SJeff Kirsher mtus[10] = 2048; 2800f7917c00SJeff Kirsher mtus[11] = 4096; 2801f7917c00SJeff Kirsher mtus[12] = 4352; 2802f7917c00SJeff Kirsher mtus[13] = 8192; 2803f7917c00SJeff Kirsher mtus[14] = 9000; 2804f7917c00SJeff Kirsher mtus[15] = 9600; 2805f7917c00SJeff Kirsher } 2806f7917c00SJeff Kirsher 2807f7917c00SJeff Kirsher /* 2808f7917c00SJeff Kirsher * Initial congestion control parameters. 2809f7917c00SJeff Kirsher */ 2810f7917c00SJeff Kirsher static void init_cong_ctrl(unsigned short *a, unsigned short *b) 2811f7917c00SJeff Kirsher { 2812f7917c00SJeff Kirsher a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1; 2813f7917c00SJeff Kirsher a[9] = 2; 2814f7917c00SJeff Kirsher a[10] = 3; 2815f7917c00SJeff Kirsher a[11] = 4; 2816f7917c00SJeff Kirsher a[12] = 5; 2817f7917c00SJeff Kirsher a[13] = 6; 2818f7917c00SJeff Kirsher a[14] = 7; 2819f7917c00SJeff Kirsher a[15] = 8; 2820f7917c00SJeff Kirsher a[16] = 9; 2821f7917c00SJeff Kirsher a[17] = 10; 2822f7917c00SJeff Kirsher a[18] = 14; 2823f7917c00SJeff Kirsher a[19] = 17; 2824f7917c00SJeff Kirsher a[20] = 21; 2825f7917c00SJeff Kirsher a[21] = 25; 2826f7917c00SJeff Kirsher a[22] = 30; 2827f7917c00SJeff Kirsher a[23] = 35; 2828f7917c00SJeff Kirsher a[24] = 45; 2829f7917c00SJeff Kirsher a[25] = 60; 2830f7917c00SJeff Kirsher a[26] = 80; 2831f7917c00SJeff Kirsher a[27] = 100; 2832f7917c00SJeff Kirsher a[28] = 200; 2833f7917c00SJeff Kirsher a[29] = 300; 2834f7917c00SJeff Kirsher a[30] = 400; 2835f7917c00SJeff Kirsher a[31] = 500; 2836f7917c00SJeff Kirsher 2837f7917c00SJeff Kirsher b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0; 2838f7917c00SJeff Kirsher b[9] = b[10] = 1; 2839f7917c00SJeff Kirsher b[11] = b[12] = 2; 2840f7917c00SJeff Kirsher b[13] = b[14] = b[15] = b[16] = 3; 2841f7917c00SJeff Kirsher b[17] = b[18] = b[19] = b[20] = b[21] = 4; 2842f7917c00SJeff Kirsher b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5; 2843f7917c00SJeff Kirsher b[28] = b[29] = 6; 2844f7917c00SJeff Kirsher b[30] = b[31] = 7; 2845f7917c00SJeff Kirsher } 2846f7917c00SJeff Kirsher 2847f7917c00SJeff Kirsher /* The minimum additive increment value for the congestion control table */ 2848f7917c00SJeff Kirsher #define CC_MIN_INCR 2U 2849f7917c00SJeff Kirsher 2850f7917c00SJeff Kirsher /** 2851f7917c00SJeff Kirsher * t3_load_mtus - write the MTU and congestion control HW tables 2852f7917c00SJeff Kirsher * @adap: the adapter 2853f7917c00SJeff Kirsher * @mtus: the unrestricted values for the MTU table 2854f7917c00SJeff Kirsher * @alphs: the values for the congestion control alpha parameter 2855f7917c00SJeff Kirsher * @beta: the values for the congestion control beta parameter 2856f7917c00SJeff Kirsher * @mtu_cap: the maximum permitted effective MTU 2857f7917c00SJeff Kirsher * 2858f7917c00SJeff Kirsher * Write the MTU table with the supplied MTUs capping each at &mtu_cap. 2859f7917c00SJeff Kirsher * Update the high-speed congestion control table with the supplied alpha, 2860f7917c00SJeff Kirsher * beta, and MTUs. 2861f7917c00SJeff Kirsher */ 2862f7917c00SJeff Kirsher void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS], 2863f7917c00SJeff Kirsher unsigned short alpha[NCCTRL_WIN], 2864f7917c00SJeff Kirsher unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap) 2865f7917c00SJeff Kirsher { 2866f7917c00SJeff Kirsher static const unsigned int avg_pkts[NCCTRL_WIN] = { 2867f7917c00SJeff Kirsher 2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640, 2868f7917c00SJeff Kirsher 896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480, 2869f7917c00SJeff Kirsher 28672, 40960, 57344, 81920, 114688, 163840, 229376 2870f7917c00SJeff Kirsher }; 2871f7917c00SJeff Kirsher 2872f7917c00SJeff Kirsher unsigned int i, w; 2873f7917c00SJeff Kirsher 2874f7917c00SJeff Kirsher for (i = 0; i < NMTUS; ++i) { 2875f7917c00SJeff Kirsher unsigned int mtu = min(mtus[i], mtu_cap); 2876f7917c00SJeff Kirsher unsigned int log2 = fls(mtu); 2877f7917c00SJeff Kirsher 2878f7917c00SJeff Kirsher if (!(mtu & ((1 << log2) >> 2))) /* round */ 2879f7917c00SJeff Kirsher log2--; 2880f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_MTU_TABLE, 2881f7917c00SJeff Kirsher (i << 24) | (log2 << 16) | mtu); 2882f7917c00SJeff Kirsher 2883f7917c00SJeff Kirsher for (w = 0; w < NCCTRL_WIN; ++w) { 2884f7917c00SJeff Kirsher unsigned int inc; 2885f7917c00SJeff Kirsher 2886f7917c00SJeff Kirsher inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w], 2887f7917c00SJeff Kirsher CC_MIN_INCR); 2888f7917c00SJeff Kirsher 2889f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) | 2890f7917c00SJeff Kirsher (w << 16) | (beta[w] << 13) | inc); 2891f7917c00SJeff Kirsher } 2892f7917c00SJeff Kirsher } 2893f7917c00SJeff Kirsher } 2894f7917c00SJeff Kirsher 2895f7917c00SJeff Kirsher /** 2896f7917c00SJeff Kirsher * t3_tp_get_mib_stats - read TP's MIB counters 2897f7917c00SJeff Kirsher * @adap: the adapter 2898f7917c00SJeff Kirsher * @tps: holds the returned counter values 2899f7917c00SJeff Kirsher * 2900f7917c00SJeff Kirsher * Returns the values of TP's MIB counters. 2901f7917c00SJeff Kirsher */ 2902f7917c00SJeff Kirsher void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps) 2903f7917c00SJeff Kirsher { 2904f7917c00SJeff Kirsher t3_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_RDATA, (u32 *) tps, 2905f7917c00SJeff Kirsher sizeof(*tps) / sizeof(u32), 0); 2906f7917c00SJeff Kirsher } 2907f7917c00SJeff Kirsher 2908f7917c00SJeff Kirsher #define ulp_region(adap, name, start, len) \ 2909f7917c00SJeff Kirsher t3_write_reg((adap), A_ULPRX_ ## name ## _LLIMIT, (start)); \ 2910f7917c00SJeff Kirsher t3_write_reg((adap), A_ULPRX_ ## name ## _ULIMIT, \ 2911f7917c00SJeff Kirsher (start) + (len) - 1); \ 2912f7917c00SJeff Kirsher start += len 2913f7917c00SJeff Kirsher 2914f7917c00SJeff Kirsher #define ulptx_region(adap, name, start, len) \ 2915f7917c00SJeff Kirsher t3_write_reg((adap), A_ULPTX_ ## name ## _LLIMIT, (start)); \ 2916f7917c00SJeff Kirsher t3_write_reg((adap), A_ULPTX_ ## name ## _ULIMIT, \ 2917f7917c00SJeff Kirsher (start) + (len) - 1) 2918f7917c00SJeff Kirsher 2919f7917c00SJeff Kirsher static void ulp_config(struct adapter *adap, const struct tp_params *p) 2920f7917c00SJeff Kirsher { 2921f7917c00SJeff Kirsher unsigned int m = p->chan_rx_size; 2922f7917c00SJeff Kirsher 2923f7917c00SJeff Kirsher ulp_region(adap, ISCSI, m, p->chan_rx_size / 8); 2924f7917c00SJeff Kirsher ulp_region(adap, TDDP, m, p->chan_rx_size / 8); 2925f7917c00SJeff Kirsher ulptx_region(adap, TPT, m, p->chan_rx_size / 4); 2926f7917c00SJeff Kirsher ulp_region(adap, STAG, m, p->chan_rx_size / 4); 2927f7917c00SJeff Kirsher ulp_region(adap, RQ, m, p->chan_rx_size / 4); 2928f7917c00SJeff Kirsher ulptx_region(adap, PBL, m, p->chan_rx_size / 4); 2929f7917c00SJeff Kirsher ulp_region(adap, PBL, m, p->chan_rx_size / 4); 2930f7917c00SJeff Kirsher t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff); 2931f7917c00SJeff Kirsher } 2932f7917c00SJeff Kirsher 2933f7917c00SJeff Kirsher /** 2934f7917c00SJeff Kirsher * t3_set_proto_sram - set the contents of the protocol sram 2935f7917c00SJeff Kirsher * @adapter: the adapter 2936f7917c00SJeff Kirsher * @data: the protocol image 2937f7917c00SJeff Kirsher * 2938f7917c00SJeff Kirsher * Write the contents of the protocol SRAM. 2939f7917c00SJeff Kirsher */ 2940f7917c00SJeff Kirsher int t3_set_proto_sram(struct adapter *adap, const u8 *data) 2941f7917c00SJeff Kirsher { 2942f7917c00SJeff Kirsher int i; 2943f7917c00SJeff Kirsher const __be32 *buf = (const __be32 *)data; 2944f7917c00SJeff Kirsher 2945f7917c00SJeff Kirsher for (i = 0; i < PROTO_SRAM_LINES; i++) { 2946f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, be32_to_cpu(*buf++)); 2947f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, be32_to_cpu(*buf++)); 2948f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, be32_to_cpu(*buf++)); 2949f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, be32_to_cpu(*buf++)); 2950f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, be32_to_cpu(*buf++)); 2951f7917c00SJeff Kirsher 2952f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31); 2953f7917c00SJeff Kirsher if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1)) 2954f7917c00SJeff Kirsher return -EIO; 2955f7917c00SJeff Kirsher } 2956f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0); 2957f7917c00SJeff Kirsher 2958f7917c00SJeff Kirsher return 0; 2959f7917c00SJeff Kirsher } 2960f7917c00SJeff Kirsher 2961f7917c00SJeff Kirsher void t3_config_trace_filter(struct adapter *adapter, 2962f7917c00SJeff Kirsher const struct trace_params *tp, int filter_index, 2963f7917c00SJeff Kirsher int invert, int enable) 2964f7917c00SJeff Kirsher { 2965f7917c00SJeff Kirsher u32 addr, key[4], mask[4]; 2966f7917c00SJeff Kirsher 2967f7917c00SJeff Kirsher key[0] = tp->sport | (tp->sip << 16); 2968f7917c00SJeff Kirsher key[1] = (tp->sip >> 16) | (tp->dport << 16); 2969f7917c00SJeff Kirsher key[2] = tp->dip; 2970f7917c00SJeff Kirsher key[3] = tp->proto | (tp->vlan << 8) | (tp->intf << 20); 2971f7917c00SJeff Kirsher 2972f7917c00SJeff Kirsher mask[0] = tp->sport_mask | (tp->sip_mask << 16); 2973f7917c00SJeff Kirsher mask[1] = (tp->sip_mask >> 16) | (tp->dport_mask << 16); 2974f7917c00SJeff Kirsher mask[2] = tp->dip_mask; 2975f7917c00SJeff Kirsher mask[3] = tp->proto_mask | (tp->vlan_mask << 8) | (tp->intf_mask << 20); 2976f7917c00SJeff Kirsher 2977f7917c00SJeff Kirsher if (invert) 2978f7917c00SJeff Kirsher key[3] |= (1 << 29); 2979f7917c00SJeff Kirsher if (enable) 2980f7917c00SJeff Kirsher key[3] |= (1 << 28); 2981f7917c00SJeff Kirsher 2982f7917c00SJeff Kirsher addr = filter_index ? A_TP_RX_TRC_KEY0 : A_TP_TX_TRC_KEY0; 2983f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, key[0]); 2984f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, mask[0]); 2985f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, key[1]); 2986f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, mask[1]); 2987f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, key[2]); 2988f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, mask[2]); 2989f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr++, key[3]); 2990f7917c00SJeff Kirsher tp_wr_indirect(adapter, addr, mask[3]); 2991f7917c00SJeff Kirsher t3_read_reg(adapter, A_TP_PIO_DATA); 2992f7917c00SJeff Kirsher } 2993f7917c00SJeff Kirsher 2994f7917c00SJeff Kirsher /** 2995f7917c00SJeff Kirsher * t3_config_sched - configure a HW traffic scheduler 2996f7917c00SJeff Kirsher * @adap: the adapter 2997f7917c00SJeff Kirsher * @kbps: target rate in Kbps 2998f7917c00SJeff Kirsher * @sched: the scheduler index 2999f7917c00SJeff Kirsher * 3000f7917c00SJeff Kirsher * Configure a HW scheduler for the target rate 3001f7917c00SJeff Kirsher */ 3002f7917c00SJeff Kirsher int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched) 3003f7917c00SJeff Kirsher { 3004f7917c00SJeff Kirsher unsigned int v, tps, cpt, bpt, delta, mindelta = ~0; 3005f7917c00SJeff Kirsher unsigned int clk = adap->params.vpd.cclk * 1000; 3006f7917c00SJeff Kirsher unsigned int selected_cpt = 0, selected_bpt = 0; 3007f7917c00SJeff Kirsher 3008f7917c00SJeff Kirsher if (kbps > 0) { 3009f7917c00SJeff Kirsher kbps *= 125; /* -> bytes */ 3010f7917c00SJeff Kirsher for (cpt = 1; cpt <= 255; cpt++) { 3011f7917c00SJeff Kirsher tps = clk / cpt; 3012f7917c00SJeff Kirsher bpt = (kbps + tps / 2) / tps; 3013f7917c00SJeff Kirsher if (bpt > 0 && bpt <= 255) { 3014f7917c00SJeff Kirsher v = bpt * tps; 3015f7917c00SJeff Kirsher delta = v >= kbps ? v - kbps : kbps - v; 3016f7917c00SJeff Kirsher if (delta <= mindelta) { 3017f7917c00SJeff Kirsher mindelta = delta; 3018f7917c00SJeff Kirsher selected_cpt = cpt; 3019f7917c00SJeff Kirsher selected_bpt = bpt; 3020f7917c00SJeff Kirsher } 3021f7917c00SJeff Kirsher } else if (selected_cpt) 3022f7917c00SJeff Kirsher break; 3023f7917c00SJeff Kirsher } 3024f7917c00SJeff Kirsher if (!selected_cpt) 3025f7917c00SJeff Kirsher return -EINVAL; 3026f7917c00SJeff Kirsher } 3027f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TM_PIO_ADDR, 3028f7917c00SJeff Kirsher A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2); 3029f7917c00SJeff Kirsher v = t3_read_reg(adap, A_TP_TM_PIO_DATA); 3030f7917c00SJeff Kirsher if (sched & 1) 3031f7917c00SJeff Kirsher v = (v & 0xffff) | (selected_cpt << 16) | (selected_bpt << 24); 3032f7917c00SJeff Kirsher else 3033f7917c00SJeff Kirsher v = (v & 0xffff0000) | selected_cpt | (selected_bpt << 8); 3034f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TM_PIO_DATA, v); 3035f7917c00SJeff Kirsher return 0; 3036f7917c00SJeff Kirsher } 3037f7917c00SJeff Kirsher 3038f7917c00SJeff Kirsher static int tp_init(struct adapter *adap, const struct tp_params *p) 3039f7917c00SJeff Kirsher { 3040f7917c00SJeff Kirsher int busy = 0; 3041f7917c00SJeff Kirsher 3042f7917c00SJeff Kirsher tp_config(adap, p); 3043f7917c00SJeff Kirsher t3_set_vlan_accel(adap, 3, 0); 3044f7917c00SJeff Kirsher 3045f7917c00SJeff Kirsher if (is_offload(adap)) { 3046f7917c00SJeff Kirsher tp_set_timers(adap, adap->params.vpd.cclk * 1000); 3047f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_RESET, F_FLSTINITENABLE); 3048f7917c00SJeff Kirsher busy = t3_wait_op_done(adap, A_TP_RESET, F_FLSTINITENABLE, 3049f7917c00SJeff Kirsher 0, 1000, 5); 3050f7917c00SJeff Kirsher if (busy) 3051f7917c00SJeff Kirsher CH_ERR(adap, "TP initialization timed out\n"); 3052f7917c00SJeff Kirsher } 3053f7917c00SJeff Kirsher 3054f7917c00SJeff Kirsher if (!busy) 3055f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_RESET, F_TPRESET); 3056f7917c00SJeff Kirsher return busy; 3057f7917c00SJeff Kirsher } 3058f7917c00SJeff Kirsher 3059f7917c00SJeff Kirsher /* 3060f7917c00SJeff Kirsher * Perform the bits of HW initialization that are dependent on the Tx 3061f7917c00SJeff Kirsher * channels being used. 3062f7917c00SJeff Kirsher */ 3063f7917c00SJeff Kirsher static void chan_init_hw(struct adapter *adap, unsigned int chan_map) 3064f7917c00SJeff Kirsher { 3065f7917c00SJeff Kirsher int i; 3066f7917c00SJeff Kirsher 3067f7917c00SJeff Kirsher if (chan_map != 3) { /* one channel */ 3068f7917c00SJeff Kirsher t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0); 3069f7917c00SJeff Kirsher t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0); 3070f7917c00SJeff Kirsher t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_ENFORCEPKT | 3071f7917c00SJeff Kirsher (chan_map == 1 ? F_TPTXPORT0EN | F_PORT0ACTIVE : 3072f7917c00SJeff Kirsher F_TPTXPORT1EN | F_PORT1ACTIVE)); 3073f7917c00SJeff Kirsher t3_write_reg(adap, A_PM1_TX_CFG, 3074f7917c00SJeff Kirsher chan_map == 1 ? 0xffffffff : 0); 3075f7917c00SJeff Kirsher } else { /* two channels */ 3076f7917c00SJeff Kirsher t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); 3077f7917c00SJeff Kirsher t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); 3078f7917c00SJeff Kirsher t3_write_reg(adap, A_ULPTX_DMA_WEIGHT, 3079f7917c00SJeff Kirsher V_D1_WEIGHT(16) | V_D0_WEIGHT(16)); 3080f7917c00SJeff Kirsher t3_write_reg(adap, A_MPS_CFG, F_TPTXPORT0EN | F_TPTXPORT1EN | 3081f7917c00SJeff Kirsher F_TPRXPORTEN | F_PORT0ACTIVE | F_PORT1ACTIVE | 3082f7917c00SJeff Kirsher F_ENFORCEPKT); 3083f7917c00SJeff Kirsher t3_write_reg(adap, A_PM1_TX_CFG, 0x80008000); 3084f7917c00SJeff Kirsher t3_set_reg_field(adap, A_TP_PC_CONFIG, 0, F_TXTOSQUEUEMAPMODE); 3085f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, 3086f7917c00SJeff Kirsher V_TX_MOD_QUEUE_REQ_MAP(0xaa)); 3087f7917c00SJeff Kirsher for (i = 0; i < 16; i++) 3088f7917c00SJeff Kirsher t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, 3089f7917c00SJeff Kirsher (i << 16) | 0x1010); 3090f7917c00SJeff Kirsher } 3091f7917c00SJeff Kirsher } 3092f7917c00SJeff Kirsher 3093f7917c00SJeff Kirsher static int calibrate_xgm(struct adapter *adapter) 3094f7917c00SJeff Kirsher { 3095f7917c00SJeff Kirsher if (uses_xaui(adapter)) { 3096f7917c00SJeff Kirsher unsigned int v, i; 3097f7917c00SJeff Kirsher 3098f7917c00SJeff Kirsher for (i = 0; i < 5; ++i) { 3099f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XAUI_IMP, 0); 3100f7917c00SJeff Kirsher t3_read_reg(adapter, A_XGM_XAUI_IMP); 3101f7917c00SJeff Kirsher msleep(1); 3102f7917c00SJeff Kirsher v = t3_read_reg(adapter, A_XGM_XAUI_IMP); 3103f7917c00SJeff Kirsher if (!(v & (F_XGM_CALFAULT | F_CALBUSY))) { 3104f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_XAUI_IMP, 3105f7917c00SJeff Kirsher V_XAUIIMP(G_CALIMP(v) >> 2)); 3106f7917c00SJeff Kirsher return 0; 3107f7917c00SJeff Kirsher } 3108f7917c00SJeff Kirsher } 3109f7917c00SJeff Kirsher CH_ERR(adapter, "MAC calibration failed\n"); 3110f7917c00SJeff Kirsher return -1; 3111f7917c00SJeff Kirsher } else { 3112f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_RGMII_IMP, 3113f7917c00SJeff Kirsher V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3)); 3114f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE, 3115f7917c00SJeff Kirsher F_XGM_IMPSETUPDATE); 3116f7917c00SJeff Kirsher } 3117f7917c00SJeff Kirsher return 0; 3118f7917c00SJeff Kirsher } 3119f7917c00SJeff Kirsher 3120f7917c00SJeff Kirsher static void calibrate_xgm_t3b(struct adapter *adapter) 3121f7917c00SJeff Kirsher { 3122f7917c00SJeff Kirsher if (!uses_xaui(adapter)) { 3123f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_RGMII_IMP, F_CALRESET | 3124f7917c00SJeff Kirsher F_CALUPDATE | V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3)); 3125f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALRESET, 0); 3126f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, 3127f7917c00SJeff Kirsher F_XGM_IMPSETUPDATE); 3128f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE, 3129f7917c00SJeff Kirsher 0); 3130f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALUPDATE, 0); 3131f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, F_CALUPDATE); 3132f7917c00SJeff Kirsher } 3133f7917c00SJeff Kirsher } 3134f7917c00SJeff Kirsher 3135f7917c00SJeff Kirsher struct mc7_timing_params { 3136f7917c00SJeff Kirsher unsigned char ActToPreDly; 3137f7917c00SJeff Kirsher unsigned char ActToRdWrDly; 3138f7917c00SJeff Kirsher unsigned char PreCyc; 3139f7917c00SJeff Kirsher unsigned char RefCyc[5]; 3140f7917c00SJeff Kirsher unsigned char BkCyc; 3141f7917c00SJeff Kirsher unsigned char WrToRdDly; 3142f7917c00SJeff Kirsher unsigned char RdToWrDly; 3143f7917c00SJeff Kirsher }; 3144f7917c00SJeff Kirsher 3145f7917c00SJeff Kirsher /* 3146f7917c00SJeff Kirsher * Write a value to a register and check that the write completed. These 3147f7917c00SJeff Kirsher * writes normally complete in a cycle or two, so one read should suffice. 3148f7917c00SJeff Kirsher * The very first read exists to flush the posted write to the device. 3149f7917c00SJeff Kirsher */ 3150f7917c00SJeff Kirsher static int wrreg_wait(struct adapter *adapter, unsigned int addr, u32 val) 3151f7917c00SJeff Kirsher { 3152f7917c00SJeff Kirsher t3_write_reg(adapter, addr, val); 3153f7917c00SJeff Kirsher t3_read_reg(adapter, addr); /* flush */ 3154f7917c00SJeff Kirsher if (!(t3_read_reg(adapter, addr) & F_BUSY)) 3155f7917c00SJeff Kirsher return 0; 3156f7917c00SJeff Kirsher CH_ERR(adapter, "write to MC7 register 0x%x timed out\n", addr); 3157f7917c00SJeff Kirsher return -EIO; 3158f7917c00SJeff Kirsher } 3159f7917c00SJeff Kirsher 3160f7917c00SJeff Kirsher static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type) 3161f7917c00SJeff Kirsher { 3162f7917c00SJeff Kirsher static const unsigned int mc7_mode[] = { 3163f7917c00SJeff Kirsher 0x632, 0x642, 0x652, 0x432, 0x442 3164f7917c00SJeff Kirsher }; 3165f7917c00SJeff Kirsher static const struct mc7_timing_params mc7_timings[] = { 3166f7917c00SJeff Kirsher {12, 3, 4, {20, 28, 34, 52, 0}, 15, 6, 4}, 3167f7917c00SJeff Kirsher {12, 4, 5, {20, 28, 34, 52, 0}, 16, 7, 4}, 3168f7917c00SJeff Kirsher {12, 5, 6, {20, 28, 34, 52, 0}, 17, 8, 4}, 3169f7917c00SJeff Kirsher {9, 3, 4, {15, 21, 26, 39, 0}, 12, 6, 4}, 3170f7917c00SJeff Kirsher {9, 4, 5, {15, 21, 26, 39, 0}, 13, 7, 4} 3171f7917c00SJeff Kirsher }; 3172f7917c00SJeff Kirsher 3173f7917c00SJeff Kirsher u32 val; 3174f7917c00SJeff Kirsher unsigned int width, density, slow, attempts; 3175f7917c00SJeff Kirsher struct adapter *adapter = mc7->adapter; 3176f7917c00SJeff Kirsher const struct mc7_timing_params *p = &mc7_timings[mem_type]; 3177f7917c00SJeff Kirsher 3178f7917c00SJeff Kirsher if (!mc7->size) 3179f7917c00SJeff Kirsher return 0; 3180f7917c00SJeff Kirsher 3181f7917c00SJeff Kirsher val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); 3182f7917c00SJeff Kirsher slow = val & F_SLOW; 3183f7917c00SJeff Kirsher width = G_WIDTH(val); 3184f7917c00SJeff Kirsher density = G_DEN(val); 3185f7917c00SJeff Kirsher 3186f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_CFG, val | F_IFEN); 3187f7917c00SJeff Kirsher val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); /* flush */ 3188f7917c00SJeff Kirsher msleep(1); 3189f7917c00SJeff Kirsher 3190f7917c00SJeff Kirsher if (!slow) { 3191f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_CAL, F_SGL_CAL_EN); 3192f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CAL); 3193f7917c00SJeff Kirsher msleep(1); 3194f7917c00SJeff Kirsher if (t3_read_reg(adapter, mc7->offset + A_MC7_CAL) & 3195f7917c00SJeff Kirsher (F_BUSY | F_SGL_CAL_EN | F_CAL_FAULT)) { 3196f7917c00SJeff Kirsher CH_ERR(adapter, "%s MC7 calibration timed out\n", 3197f7917c00SJeff Kirsher mc7->name); 3198f7917c00SJeff Kirsher goto out_fail; 3199f7917c00SJeff Kirsher } 3200f7917c00SJeff Kirsher } 3201f7917c00SJeff Kirsher 3202f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_PARM, 3203f7917c00SJeff Kirsher V_ACTTOPREDLY(p->ActToPreDly) | 3204f7917c00SJeff Kirsher V_ACTTORDWRDLY(p->ActToRdWrDly) | V_PRECYC(p->PreCyc) | 3205f7917c00SJeff Kirsher V_REFCYC(p->RefCyc[density]) | V_BKCYC(p->BkCyc) | 3206f7917c00SJeff Kirsher V_WRTORDDLY(p->WrToRdDly) | V_RDTOWRDLY(p->RdToWrDly)); 3207f7917c00SJeff Kirsher 3208f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_CFG, 3209f7917c00SJeff Kirsher val | F_CLKEN | F_TERM150); 3210f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_CFG); /* flush */ 3211f7917c00SJeff Kirsher 3212f7917c00SJeff Kirsher if (!slow) 3213f7917c00SJeff Kirsher t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLENB, 3214f7917c00SJeff Kirsher F_DLLENB); 3215f7917c00SJeff Kirsher udelay(1); 3216f7917c00SJeff Kirsher 3217f7917c00SJeff Kirsher val = slow ? 3 : 6; 3218f7917c00SJeff Kirsher if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) || 3219f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE2, 0) || 3220f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE3, 0) || 3221f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val)) 3222f7917c00SJeff Kirsher goto out_fail; 3223f7917c00SJeff Kirsher 3224f7917c00SJeff Kirsher if (!slow) { 3225f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_MODE, 0x100); 3226f7917c00SJeff Kirsher t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLRST, 0); 3227f7917c00SJeff Kirsher udelay(5); 3228f7917c00SJeff Kirsher } 3229f7917c00SJeff Kirsher 3230f7917c00SJeff Kirsher if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) || 3231f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) || 3232f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) || 3233f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_MODE, 3234f7917c00SJeff Kirsher mc7_mode[mem_type]) || 3235f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val | 0x380) || 3236f7917c00SJeff Kirsher wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val)) 3237f7917c00SJeff Kirsher goto out_fail; 3238f7917c00SJeff Kirsher 3239f7917c00SJeff Kirsher /* clock value is in KHz */ 3240f7917c00SJeff Kirsher mc7_clock = mc7_clock * 7812 + mc7_clock / 2; /* ns */ 3241f7917c00SJeff Kirsher mc7_clock /= 1000000; /* KHz->MHz, ns->us */ 3242f7917c00SJeff Kirsher 3243f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_REF, 3244f7917c00SJeff Kirsher F_PERREFEN | V_PREREFDIV(mc7_clock)); 3245f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_REF); /* flush */ 3246f7917c00SJeff Kirsher 3247f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_ECC, F_ECCGENEN | F_ECCCHKEN); 3248f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_BIST_DATA, 0); 3249f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_BEG, 0); 3250f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_END, 3251f7917c00SJeff Kirsher (mc7->size << width) - 1); 3252f7917c00SJeff Kirsher t3_write_reg(adapter, mc7->offset + A_MC7_BIST_OP, V_OP(1)); 3253f7917c00SJeff Kirsher t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP); /* flush */ 3254f7917c00SJeff Kirsher 3255f7917c00SJeff Kirsher attempts = 50; 3256f7917c00SJeff Kirsher do { 3257f7917c00SJeff Kirsher msleep(250); 3258f7917c00SJeff Kirsher val = t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP); 3259f7917c00SJeff Kirsher } while ((val & F_BUSY) && --attempts); 3260f7917c00SJeff Kirsher if (val & F_BUSY) { 3261f7917c00SJeff Kirsher CH_ERR(adapter, "%s MC7 BIST timed out\n", mc7->name); 3262f7917c00SJeff Kirsher goto out_fail; 3263f7917c00SJeff Kirsher } 3264f7917c00SJeff Kirsher 3265f7917c00SJeff Kirsher /* Enable normal memory accesses. */ 3266f7917c00SJeff Kirsher t3_set_reg_field(adapter, mc7->offset + A_MC7_CFG, 0, F_RDY); 3267f7917c00SJeff Kirsher return 0; 3268f7917c00SJeff Kirsher 3269f7917c00SJeff Kirsher out_fail: 3270f7917c00SJeff Kirsher return -1; 3271f7917c00SJeff Kirsher } 3272f7917c00SJeff Kirsher 3273f7917c00SJeff Kirsher static void config_pcie(struct adapter *adap) 3274f7917c00SJeff Kirsher { 3275f7917c00SJeff Kirsher static const u16 ack_lat[4][6] = { 3276f7917c00SJeff Kirsher {237, 416, 559, 1071, 2095, 4143}, 3277f7917c00SJeff Kirsher {128, 217, 289, 545, 1057, 2081}, 3278f7917c00SJeff Kirsher {73, 118, 154, 282, 538, 1050}, 3279f7917c00SJeff Kirsher {67, 107, 86, 150, 278, 534} 3280f7917c00SJeff Kirsher }; 3281f7917c00SJeff Kirsher static const u16 rpl_tmr[4][6] = { 3282f7917c00SJeff Kirsher {711, 1248, 1677, 3213, 6285, 12429}, 3283f7917c00SJeff Kirsher {384, 651, 867, 1635, 3171, 6243}, 3284f7917c00SJeff Kirsher {219, 354, 462, 846, 1614, 3150}, 3285f7917c00SJeff Kirsher {201, 321, 258, 450, 834, 1602} 3286f7917c00SJeff Kirsher }; 3287f7917c00SJeff Kirsher 3288f7917c00SJeff Kirsher u16 val, devid; 3289f7917c00SJeff Kirsher unsigned int log2_width, pldsize; 3290f7917c00SJeff Kirsher unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt; 3291f7917c00SJeff Kirsher 3292c772b44eSJiang Liu pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL, &val); 3293f7917c00SJeff Kirsher pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5; 3294f7917c00SJeff Kirsher 3295f7917c00SJeff Kirsher pci_read_config_word(adap->pdev, 0x2, &devid); 3296f7917c00SJeff Kirsher if (devid == 0x37) { 3297c772b44eSJiang Liu pcie_capability_write_word(adap->pdev, PCI_EXP_DEVCTL, 3298f7917c00SJeff Kirsher val & ~PCI_EXP_DEVCTL_READRQ & 3299f7917c00SJeff Kirsher ~PCI_EXP_DEVCTL_PAYLOAD); 3300f7917c00SJeff Kirsher pldsize = 0; 3301f7917c00SJeff Kirsher } 3302f7917c00SJeff Kirsher 3303c772b44eSJiang Liu pcie_capability_read_word(adap->pdev, PCI_EXP_LNKCTL, &val); 3304f7917c00SJeff Kirsher 3305f7917c00SJeff Kirsher fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0)); 3306f7917c00SJeff Kirsher fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx : 3307f7917c00SJeff Kirsher G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE)); 3308f7917c00SJeff Kirsher log2_width = fls(adap->params.pci.width) - 1; 3309f7917c00SJeff Kirsher acklat = ack_lat[log2_width][pldsize]; 3310f2692bd9SBjorn Helgaas if (val & PCI_EXP_LNKCTL_ASPM_L0S) /* check LOsEnable */ 3311f7917c00SJeff Kirsher acklat += fst_trn_tx * 4; 3312f7917c00SJeff Kirsher rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4; 3313f7917c00SJeff Kirsher 3314f7917c00SJeff Kirsher if (adap->params.rev == 0) 3315f7917c00SJeff Kirsher t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, 3316f7917c00SJeff Kirsher V_T3A_ACKLAT(M_T3A_ACKLAT), 3317f7917c00SJeff Kirsher V_T3A_ACKLAT(acklat)); 3318f7917c00SJeff Kirsher else 3319f7917c00SJeff Kirsher t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, V_ACKLAT(M_ACKLAT), 3320f7917c00SJeff Kirsher V_ACKLAT(acklat)); 3321f7917c00SJeff Kirsher 3322f7917c00SJeff Kirsher t3_set_reg_field(adap, A_PCIE_PEX_CTRL0, V_REPLAYLMT(M_REPLAYLMT), 3323f7917c00SJeff Kirsher V_REPLAYLMT(rpllmt)); 3324f7917c00SJeff Kirsher 3325f7917c00SJeff Kirsher t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff); 3326f7917c00SJeff Kirsher t3_set_reg_field(adap, A_PCIE_CFG, 0, 3327f7917c00SJeff Kirsher F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST | 3328f7917c00SJeff Kirsher F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN); 3329f7917c00SJeff Kirsher } 3330f7917c00SJeff Kirsher 3331f7917c00SJeff Kirsher /* 3332f7917c00SJeff Kirsher * Initialize and configure T3 HW modules. This performs the 3333f7917c00SJeff Kirsher * initialization steps that need to be done once after a card is reset. 3334f7917c00SJeff Kirsher * MAC and PHY initialization is handled separarely whenever a port is enabled. 3335f7917c00SJeff Kirsher * 3336f7917c00SJeff Kirsher * fw_params are passed to FW and their value is platform dependent. Only the 3337f7917c00SJeff Kirsher * top 8 bits are available for use, the rest must be 0. 3338f7917c00SJeff Kirsher */ 3339f7917c00SJeff Kirsher int t3_init_hw(struct adapter *adapter, u32 fw_params) 3340f7917c00SJeff Kirsher { 3341f7917c00SJeff Kirsher int err = -EIO, attempts, i; 3342f7917c00SJeff Kirsher const struct vpd_params *vpd = &adapter->params.vpd; 3343f7917c00SJeff Kirsher 3344f7917c00SJeff Kirsher if (adapter->params.rev > 0) 3345f7917c00SJeff Kirsher calibrate_xgm_t3b(adapter); 3346f7917c00SJeff Kirsher else if (calibrate_xgm(adapter)) 3347f7917c00SJeff Kirsher goto out_err; 3348f7917c00SJeff Kirsher 3349f7917c00SJeff Kirsher if (vpd->mclk) { 3350f7917c00SJeff Kirsher partition_mem(adapter, &adapter->params.tp); 3351f7917c00SJeff Kirsher 3352f7917c00SJeff Kirsher if (mc7_init(&adapter->pmrx, vpd->mclk, vpd->mem_timing) || 3353f7917c00SJeff Kirsher mc7_init(&adapter->pmtx, vpd->mclk, vpd->mem_timing) || 3354f7917c00SJeff Kirsher mc7_init(&adapter->cm, vpd->mclk, vpd->mem_timing) || 3355f7917c00SJeff Kirsher t3_mc5_init(&adapter->mc5, adapter->params.mc5.nservers, 3356f7917c00SJeff Kirsher adapter->params.mc5.nfilters, 3357f7917c00SJeff Kirsher adapter->params.mc5.nroutes)) 3358f7917c00SJeff Kirsher goto out_err; 3359f7917c00SJeff Kirsher 3360f7917c00SJeff Kirsher for (i = 0; i < 32; i++) 3361f7917c00SJeff Kirsher if (clear_sge_ctxt(adapter, i, F_CQ)) 3362f7917c00SJeff Kirsher goto out_err; 3363f7917c00SJeff Kirsher } 3364f7917c00SJeff Kirsher 3365f7917c00SJeff Kirsher if (tp_init(adapter, &adapter->params.tp)) 3366f7917c00SJeff Kirsher goto out_err; 3367f7917c00SJeff Kirsher 3368f7917c00SJeff Kirsher t3_tp_set_coalescing_size(adapter, 3369f7917c00SJeff Kirsher min(adapter->params.sge.max_pkt_size, 3370f7917c00SJeff Kirsher MAX_RX_COALESCING_LEN), 1); 3371f7917c00SJeff Kirsher t3_tp_set_max_rxsize(adapter, 3372f7917c00SJeff Kirsher min(adapter->params.sge.max_pkt_size, 16384U)); 3373f7917c00SJeff Kirsher ulp_config(adapter, &adapter->params.tp); 3374f7917c00SJeff Kirsher 3375f7917c00SJeff Kirsher if (is_pcie(adapter)) 3376f7917c00SJeff Kirsher config_pcie(adapter); 3377f7917c00SJeff Kirsher else 3378f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_PCIX_CFG, 0, 3379f7917c00SJeff Kirsher F_DMASTOPEN | F_CLIDECEN); 3380f7917c00SJeff Kirsher 3381f7917c00SJeff Kirsher if (adapter->params.rev == T3_REV_C) 3382f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_ULPTX_CONFIG, 0, 3383f7917c00SJeff Kirsher F_CFG_CQE_SOP_MASK); 3384f7917c00SJeff Kirsher 3385f7917c00SJeff Kirsher t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff); 3386f7917c00SJeff Kirsher t3_write_reg(adapter, A_PM1_RX_MODE, 0); 3387f7917c00SJeff Kirsher t3_write_reg(adapter, A_PM1_TX_MODE, 0); 3388f7917c00SJeff Kirsher chan_init_hw(adapter, adapter->params.chan_map); 3389f7917c00SJeff Kirsher t3_sge_init(adapter, &adapter->params.sge); 3390f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_PL_RST, 0, F_FATALPERREN); 3391f7917c00SJeff Kirsher 3392f7917c00SJeff Kirsher t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter)); 3393f7917c00SJeff Kirsher 3394f7917c00SJeff Kirsher t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); 3395f7917c00SJeff Kirsher t3_write_reg(adapter, A_CIM_BOOT_CFG, 3396f7917c00SJeff Kirsher V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); 3397f7917c00SJeff Kirsher t3_read_reg(adapter, A_CIM_BOOT_CFG); /* flush */ 3398f7917c00SJeff Kirsher 3399f7917c00SJeff Kirsher attempts = 100; 3400f7917c00SJeff Kirsher do { /* wait for uP to initialize */ 3401f7917c00SJeff Kirsher msleep(20); 3402f7917c00SJeff Kirsher } while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts); 3403f7917c00SJeff Kirsher if (!attempts) { 3404f7917c00SJeff Kirsher CH_ERR(adapter, "uP initialization timed out\n"); 3405f7917c00SJeff Kirsher goto out_err; 3406f7917c00SJeff Kirsher } 3407f7917c00SJeff Kirsher 3408f7917c00SJeff Kirsher err = 0; 3409f7917c00SJeff Kirsher out_err: 3410f7917c00SJeff Kirsher return err; 3411f7917c00SJeff Kirsher } 3412f7917c00SJeff Kirsher 3413f7917c00SJeff Kirsher /** 3414f7917c00SJeff Kirsher * get_pci_mode - determine a card's PCI mode 3415f7917c00SJeff Kirsher * @adapter: the adapter 3416f7917c00SJeff Kirsher * @p: where to store the PCI settings 3417f7917c00SJeff Kirsher * 3418f7917c00SJeff Kirsher * Determines a card's PCI mode and associated parameters, such as speed 3419f7917c00SJeff Kirsher * and width. 3420f7917c00SJeff Kirsher */ 3421f7917c00SJeff Kirsher static void get_pci_mode(struct adapter *adapter, struct pci_params *p) 3422f7917c00SJeff Kirsher { 3423f7917c00SJeff Kirsher static unsigned short speed_map[] = { 33, 66, 100, 133 }; 3424c772b44eSJiang Liu u32 pci_mode; 3425f7917c00SJeff Kirsher 3426c772b44eSJiang Liu if (pci_is_pcie(adapter->pdev)) { 3427f7917c00SJeff Kirsher u16 val; 3428f7917c00SJeff Kirsher 3429f7917c00SJeff Kirsher p->variant = PCI_VARIANT_PCIE; 3430c772b44eSJiang Liu pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val); 3431f7917c00SJeff Kirsher p->width = (val >> 4) & 0x3f; 3432f7917c00SJeff Kirsher return; 3433f7917c00SJeff Kirsher } 3434f7917c00SJeff Kirsher 3435f7917c00SJeff Kirsher pci_mode = t3_read_reg(adapter, A_PCIX_MODE); 3436f7917c00SJeff Kirsher p->speed = speed_map[G_PCLKRANGE(pci_mode)]; 3437f7917c00SJeff Kirsher p->width = (pci_mode & F_64BIT) ? 64 : 32; 3438f7917c00SJeff Kirsher pci_mode = G_PCIXINITPAT(pci_mode); 3439f7917c00SJeff Kirsher if (pci_mode == 0) 3440f7917c00SJeff Kirsher p->variant = PCI_VARIANT_PCI; 3441f7917c00SJeff Kirsher else if (pci_mode < 4) 3442f7917c00SJeff Kirsher p->variant = PCI_VARIANT_PCIX_MODE1_PARITY; 3443f7917c00SJeff Kirsher else if (pci_mode < 8) 3444f7917c00SJeff Kirsher p->variant = PCI_VARIANT_PCIX_MODE1_ECC; 3445f7917c00SJeff Kirsher else 3446f7917c00SJeff Kirsher p->variant = PCI_VARIANT_PCIX_266_MODE2; 3447f7917c00SJeff Kirsher } 3448f7917c00SJeff Kirsher 3449f7917c00SJeff Kirsher /** 3450f7917c00SJeff Kirsher * init_link_config - initialize a link's SW state 3451f7917c00SJeff Kirsher * @lc: structure holding the link state 3452f7917c00SJeff Kirsher * @ai: information about the current card 3453f7917c00SJeff Kirsher * 3454f7917c00SJeff Kirsher * Initializes the SW state maintained for each link, including the link's 3455f7917c00SJeff Kirsher * capabilities and default speed/duplex/flow-control/autonegotiation 3456f7917c00SJeff Kirsher * settings. 3457f7917c00SJeff Kirsher */ 3458f7917c00SJeff Kirsher static void init_link_config(struct link_config *lc, unsigned int caps) 3459f7917c00SJeff Kirsher { 3460f7917c00SJeff Kirsher lc->supported = caps; 3461f7917c00SJeff Kirsher lc->requested_speed = lc->speed = SPEED_INVALID; 3462f7917c00SJeff Kirsher lc->requested_duplex = lc->duplex = DUPLEX_INVALID; 3463f7917c00SJeff Kirsher lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; 3464f7917c00SJeff Kirsher if (lc->supported & SUPPORTED_Autoneg) { 3465f7917c00SJeff Kirsher lc->advertising = lc->supported; 3466f7917c00SJeff Kirsher lc->autoneg = AUTONEG_ENABLE; 3467f7917c00SJeff Kirsher lc->requested_fc |= PAUSE_AUTONEG; 3468f7917c00SJeff Kirsher } else { 3469f7917c00SJeff Kirsher lc->advertising = 0; 3470f7917c00SJeff Kirsher lc->autoneg = AUTONEG_DISABLE; 3471f7917c00SJeff Kirsher } 3472f7917c00SJeff Kirsher } 3473f7917c00SJeff Kirsher 3474f7917c00SJeff Kirsher /** 3475f7917c00SJeff Kirsher * mc7_calc_size - calculate MC7 memory size 3476f7917c00SJeff Kirsher * @cfg: the MC7 configuration 3477f7917c00SJeff Kirsher * 3478f7917c00SJeff Kirsher * Calculates the size of an MC7 memory in bytes from the value of its 3479f7917c00SJeff Kirsher * configuration register. 3480f7917c00SJeff Kirsher */ 3481f7917c00SJeff Kirsher static unsigned int mc7_calc_size(u32 cfg) 3482f7917c00SJeff Kirsher { 3483f7917c00SJeff Kirsher unsigned int width = G_WIDTH(cfg); 3484f7917c00SJeff Kirsher unsigned int banks = !!(cfg & F_BKS) + 1; 3485f7917c00SJeff Kirsher unsigned int org = !!(cfg & F_ORG) + 1; 3486f7917c00SJeff Kirsher unsigned int density = G_DEN(cfg); 3487f7917c00SJeff Kirsher unsigned int MBs = ((256 << density) * banks) / (org << width); 3488f7917c00SJeff Kirsher 3489f7917c00SJeff Kirsher return MBs << 20; 3490f7917c00SJeff Kirsher } 3491f7917c00SJeff Kirsher 3492f7917c00SJeff Kirsher static void mc7_prep(struct adapter *adapter, struct mc7 *mc7, 3493f7917c00SJeff Kirsher unsigned int base_addr, const char *name) 3494f7917c00SJeff Kirsher { 3495f7917c00SJeff Kirsher u32 cfg; 3496f7917c00SJeff Kirsher 3497f7917c00SJeff Kirsher mc7->adapter = adapter; 3498f7917c00SJeff Kirsher mc7->name = name; 3499f7917c00SJeff Kirsher mc7->offset = base_addr - MC7_PMRX_BASE_ADDR; 3500f7917c00SJeff Kirsher cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); 3501f7917c00SJeff Kirsher mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg); 3502f7917c00SJeff Kirsher mc7->width = G_WIDTH(cfg); 3503f7917c00SJeff Kirsher } 3504f7917c00SJeff Kirsher 3505f7917c00SJeff Kirsher static void mac_prep(struct cmac *mac, struct adapter *adapter, int index) 3506f7917c00SJeff Kirsher { 3507f7917c00SJeff Kirsher u16 devid; 3508f7917c00SJeff Kirsher 3509f7917c00SJeff Kirsher mac->adapter = adapter; 3510f7917c00SJeff Kirsher pci_read_config_word(adapter->pdev, 0x2, &devid); 3511f7917c00SJeff Kirsher 3512f7917c00SJeff Kirsher if (devid == 0x37 && !adapter->params.vpd.xauicfg[1]) 3513f7917c00SJeff Kirsher index = 0; 3514f7917c00SJeff Kirsher mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index; 3515f7917c00SJeff Kirsher mac->nucast = 1; 3516f7917c00SJeff Kirsher 3517f7917c00SJeff Kirsher if (adapter->params.rev == 0 && uses_xaui(adapter)) { 3518f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_SERDES_CTRL + mac->offset, 3519f7917c00SJeff Kirsher is_10G(adapter) ? 0x2901c04 : 0x2301c04); 3520f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_XGM_PORT_CFG + mac->offset, 3521f7917c00SJeff Kirsher F_ENRGMII, 0); 3522f7917c00SJeff Kirsher } 3523f7917c00SJeff Kirsher } 3524f7917c00SJeff Kirsher 3525f7917c00SJeff Kirsher static void early_hw_init(struct adapter *adapter, 3526f7917c00SJeff Kirsher const struct adapter_info *ai) 3527f7917c00SJeff Kirsher { 3528f7917c00SJeff Kirsher u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2); 3529f7917c00SJeff Kirsher 3530f7917c00SJeff Kirsher mi1_init(adapter, ai); 3531f7917c00SJeff Kirsher t3_write_reg(adapter, A_I2C_CFG, /* set for 80KHz */ 3532f7917c00SJeff Kirsher V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1)); 3533f7917c00SJeff Kirsher t3_write_reg(adapter, A_T3DBG_GPIO_EN, 3534f7917c00SJeff Kirsher ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL); 3535f7917c00SJeff Kirsher t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0); 3536f7917c00SJeff Kirsher t3_write_reg(adapter, A_SG_OCO_BASE, V_BASE1(0xfff)); 3537f7917c00SJeff Kirsher 3538f7917c00SJeff Kirsher if (adapter->params.rev == 0 || !uses_xaui(adapter)) 3539f7917c00SJeff Kirsher val |= F_ENRGMII; 3540f7917c00SJeff Kirsher 3541f7917c00SJeff Kirsher /* Enable MAC clocks so we can access the registers */ 3542f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_PORT_CFG, val); 3543f7917c00SJeff Kirsher t3_read_reg(adapter, A_XGM_PORT_CFG); 3544f7917c00SJeff Kirsher 3545f7917c00SJeff Kirsher val |= F_CLKDIVRESET_; 3546f7917c00SJeff Kirsher t3_write_reg(adapter, A_XGM_PORT_CFG, val); 3547f7917c00SJeff Kirsher t3_read_reg(adapter, A_XGM_PORT_CFG); 3548f7917c00SJeff Kirsher t3_write_reg(adapter, XGM_REG(A_XGM_PORT_CFG, 1), val); 3549f7917c00SJeff Kirsher t3_read_reg(adapter, A_XGM_PORT_CFG); 3550f7917c00SJeff Kirsher } 3551f7917c00SJeff Kirsher 3552f7917c00SJeff Kirsher /* 3553f7917c00SJeff Kirsher * Reset the adapter. 3554f7917c00SJeff Kirsher * Older PCIe cards lose their config space during reset, PCI-X 3555f7917c00SJeff Kirsher * ones don't. 3556f7917c00SJeff Kirsher */ 3557f7917c00SJeff Kirsher int t3_reset_adapter(struct adapter *adapter) 3558f7917c00SJeff Kirsher { 3559f7917c00SJeff Kirsher int i, save_and_restore_pcie = 3560f7917c00SJeff Kirsher adapter->params.rev < T3_REV_B2 && is_pcie(adapter); 3561f7917c00SJeff Kirsher uint16_t devid = 0; 3562f7917c00SJeff Kirsher 3563f7917c00SJeff Kirsher if (save_and_restore_pcie) 3564f7917c00SJeff Kirsher pci_save_state(adapter->pdev); 3565f7917c00SJeff Kirsher t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE); 3566f7917c00SJeff Kirsher 3567f7917c00SJeff Kirsher /* 3568f7917c00SJeff Kirsher * Delay. Give Some time to device to reset fully. 3569f7917c00SJeff Kirsher * XXX The delay time should be modified. 3570f7917c00SJeff Kirsher */ 3571f7917c00SJeff Kirsher for (i = 0; i < 10; i++) { 3572f7917c00SJeff Kirsher msleep(50); 3573f7917c00SJeff Kirsher pci_read_config_word(adapter->pdev, 0x00, &devid); 3574f7917c00SJeff Kirsher if (devid == 0x1425) 3575f7917c00SJeff Kirsher break; 3576f7917c00SJeff Kirsher } 3577f7917c00SJeff Kirsher 3578f7917c00SJeff Kirsher if (devid != 0x1425) 3579f7917c00SJeff Kirsher return -1; 3580f7917c00SJeff Kirsher 3581f7917c00SJeff Kirsher if (save_and_restore_pcie) 3582f7917c00SJeff Kirsher pci_restore_state(adapter->pdev); 3583f7917c00SJeff Kirsher return 0; 3584f7917c00SJeff Kirsher } 3585f7917c00SJeff Kirsher 3586f7917c00SJeff Kirsher static int init_parity(struct adapter *adap) 3587f7917c00SJeff Kirsher { 3588f7917c00SJeff Kirsher int i, err, addr; 3589f7917c00SJeff Kirsher 3590f7917c00SJeff Kirsher if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) 3591f7917c00SJeff Kirsher return -EBUSY; 3592f7917c00SJeff Kirsher 3593f7917c00SJeff Kirsher for (err = i = 0; !err && i < 16; i++) 3594f7917c00SJeff Kirsher err = clear_sge_ctxt(adap, i, F_EGRESS); 3595f7917c00SJeff Kirsher for (i = 0xfff0; !err && i <= 0xffff; i++) 3596f7917c00SJeff Kirsher err = clear_sge_ctxt(adap, i, F_EGRESS); 3597f7917c00SJeff Kirsher for (i = 0; !err && i < SGE_QSETS; i++) 3598f7917c00SJeff Kirsher err = clear_sge_ctxt(adap, i, F_RESPONSEQ); 3599f7917c00SJeff Kirsher if (err) 3600f7917c00SJeff Kirsher return err; 3601f7917c00SJeff Kirsher 3602f7917c00SJeff Kirsher t3_write_reg(adap, A_CIM_IBQ_DBG_DATA, 0); 3603f7917c00SJeff Kirsher for (i = 0; i < 4; i++) 3604f7917c00SJeff Kirsher for (addr = 0; addr <= M_IBQDBGADDR; addr++) { 3605f7917c00SJeff Kirsher t3_write_reg(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGEN | 3606f7917c00SJeff Kirsher F_IBQDBGWR | V_IBQDBGQID(i) | 3607f7917c00SJeff Kirsher V_IBQDBGADDR(addr)); 3608f7917c00SJeff Kirsher err = t3_wait_op_done(adap, A_CIM_IBQ_DBG_CFG, 3609f7917c00SJeff Kirsher F_IBQDBGBUSY, 0, 2, 1); 3610f7917c00SJeff Kirsher if (err) 3611f7917c00SJeff Kirsher return err; 3612f7917c00SJeff Kirsher } 3613f7917c00SJeff Kirsher return 0; 3614f7917c00SJeff Kirsher } 3615f7917c00SJeff Kirsher 3616f7917c00SJeff Kirsher /* 3617f7917c00SJeff Kirsher * Initialize adapter SW state for the various HW modules, set initial values 3618f7917c00SJeff Kirsher * for some adapter tunables, take PHYs out of reset, and initialize the MDIO 3619f7917c00SJeff Kirsher * interface. 3620f7917c00SJeff Kirsher */ 3621f7917c00SJeff Kirsher int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, 3622f7917c00SJeff Kirsher int reset) 3623f7917c00SJeff Kirsher { 3624f7917c00SJeff Kirsher int ret; 3625f7917c00SJeff Kirsher unsigned int i, j = -1; 3626f7917c00SJeff Kirsher 3627f7917c00SJeff Kirsher get_pci_mode(adapter, &adapter->params.pci); 3628f7917c00SJeff Kirsher 3629f7917c00SJeff Kirsher adapter->params.info = ai; 3630f7917c00SJeff Kirsher adapter->params.nports = ai->nports0 + ai->nports1; 3631f7917c00SJeff Kirsher adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1); 3632f7917c00SJeff Kirsher adapter->params.rev = t3_read_reg(adapter, A_PL_REV); 3633f7917c00SJeff Kirsher /* 3634f7917c00SJeff Kirsher * We used to only run the "adapter check task" once a second if 3635f7917c00SJeff Kirsher * we had PHYs which didn't support interrupts (we would check 3636f7917c00SJeff Kirsher * their link status once a second). Now we check other conditions 3637f7917c00SJeff Kirsher * in that routine which could potentially impose a very high 3638f7917c00SJeff Kirsher * interrupt load on the system. As such, we now always scan the 3639f7917c00SJeff Kirsher * adapter state once a second ... 3640f7917c00SJeff Kirsher */ 3641f7917c00SJeff Kirsher adapter->params.linkpoll_period = 10; 3642f7917c00SJeff Kirsher adapter->params.stats_update_period = is_10G(adapter) ? 3643f7917c00SJeff Kirsher MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10); 3644f7917c00SJeff Kirsher adapter->params.pci.vpd_cap_addr = 3645f7917c00SJeff Kirsher pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD); 3646f7917c00SJeff Kirsher ret = get_vpd_params(adapter, &adapter->params.vpd); 3647f7917c00SJeff Kirsher if (ret < 0) 3648f7917c00SJeff Kirsher return ret; 3649f7917c00SJeff Kirsher 3650f7917c00SJeff Kirsher if (reset && t3_reset_adapter(adapter)) 3651f7917c00SJeff Kirsher return -1; 3652f7917c00SJeff Kirsher 3653f7917c00SJeff Kirsher t3_sge_prep(adapter, &adapter->params.sge); 3654f7917c00SJeff Kirsher 3655f7917c00SJeff Kirsher if (adapter->params.vpd.mclk) { 3656f7917c00SJeff Kirsher struct tp_params *p = &adapter->params.tp; 3657f7917c00SJeff Kirsher 3658f7917c00SJeff Kirsher mc7_prep(adapter, &adapter->pmrx, MC7_PMRX_BASE_ADDR, "PMRX"); 3659f7917c00SJeff Kirsher mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX"); 3660f7917c00SJeff Kirsher mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM"); 3661f7917c00SJeff Kirsher 3662f7917c00SJeff Kirsher p->nchan = adapter->params.chan_map == 3 ? 2 : 1; 3663f7917c00SJeff Kirsher p->pmrx_size = t3_mc7_size(&adapter->pmrx); 3664f7917c00SJeff Kirsher p->pmtx_size = t3_mc7_size(&adapter->pmtx); 3665f7917c00SJeff Kirsher p->cm_size = t3_mc7_size(&adapter->cm); 3666f7917c00SJeff Kirsher p->chan_rx_size = p->pmrx_size / 2; /* only 1 Rx channel */ 3667f7917c00SJeff Kirsher p->chan_tx_size = p->pmtx_size / p->nchan; 3668f7917c00SJeff Kirsher p->rx_pg_size = 64 * 1024; 3669f7917c00SJeff Kirsher p->tx_pg_size = is_10G(adapter) ? 64 * 1024 : 16 * 1024; 3670f7917c00SJeff Kirsher p->rx_num_pgs = pm_num_pages(p->chan_rx_size, p->rx_pg_size); 3671f7917c00SJeff Kirsher p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size); 3672f7917c00SJeff Kirsher p->ntimer_qs = p->cm_size >= (128 << 20) || 3673f7917c00SJeff Kirsher adapter->params.rev > 0 ? 12 : 6; 3674f7917c00SJeff Kirsher } 3675f7917c00SJeff Kirsher 3676f7917c00SJeff Kirsher adapter->params.offload = t3_mc7_size(&adapter->pmrx) && 3677f7917c00SJeff Kirsher t3_mc7_size(&adapter->pmtx) && 3678f7917c00SJeff Kirsher t3_mc7_size(&adapter->cm); 3679f7917c00SJeff Kirsher 3680f7917c00SJeff Kirsher if (is_offload(adapter)) { 3681f7917c00SJeff Kirsher adapter->params.mc5.nservers = DEFAULT_NSERVERS; 3682f7917c00SJeff Kirsher adapter->params.mc5.nfilters = adapter->params.rev > 0 ? 3683f7917c00SJeff Kirsher DEFAULT_NFILTERS : 0; 3684f7917c00SJeff Kirsher adapter->params.mc5.nroutes = 0; 3685f7917c00SJeff Kirsher t3_mc5_prep(adapter, &adapter->mc5, MC5_MODE_144_BIT); 3686f7917c00SJeff Kirsher 3687f7917c00SJeff Kirsher init_mtus(adapter->params.mtus); 3688f7917c00SJeff Kirsher init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd); 3689f7917c00SJeff Kirsher } 3690f7917c00SJeff Kirsher 3691f7917c00SJeff Kirsher early_hw_init(adapter, ai); 3692f7917c00SJeff Kirsher ret = init_parity(adapter); 3693f7917c00SJeff Kirsher if (ret) 3694f7917c00SJeff Kirsher return ret; 3695f7917c00SJeff Kirsher 3696f7917c00SJeff Kirsher for_each_port(adapter, i) { 3697f7917c00SJeff Kirsher u8 hw_addr[6]; 3698f7917c00SJeff Kirsher const struct port_type_info *pti; 3699f7917c00SJeff Kirsher struct port_info *p = adap2pinfo(adapter, i); 3700f7917c00SJeff Kirsher 3701f7917c00SJeff Kirsher while (!adapter->params.vpd.port_type[++j]) 3702f7917c00SJeff Kirsher ; 3703f7917c00SJeff Kirsher 3704f7917c00SJeff Kirsher pti = &port_types[adapter->params.vpd.port_type[j]]; 3705f7917c00SJeff Kirsher if (!pti->phy_prep) { 3706f7917c00SJeff Kirsher CH_ALERT(adapter, "Invalid port type index %d\n", 3707f7917c00SJeff Kirsher adapter->params.vpd.port_type[j]); 3708f7917c00SJeff Kirsher return -EINVAL; 3709f7917c00SJeff Kirsher } 3710f7917c00SJeff Kirsher 3711f7917c00SJeff Kirsher p->phy.mdio.dev = adapter->port[i]; 3712f7917c00SJeff Kirsher ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, 3713f7917c00SJeff Kirsher ai->mdio_ops); 3714f7917c00SJeff Kirsher if (ret) 3715f7917c00SJeff Kirsher return ret; 3716f7917c00SJeff Kirsher mac_prep(&p->mac, adapter, j); 3717f7917c00SJeff Kirsher 3718f7917c00SJeff Kirsher /* 3719f7917c00SJeff Kirsher * The VPD EEPROM stores the base Ethernet address for the 3720f7917c00SJeff Kirsher * card. A port's address is derived from the base by adding 3721f7917c00SJeff Kirsher * the port's index to the base's low octet. 3722f7917c00SJeff Kirsher */ 3723f7917c00SJeff Kirsher memcpy(hw_addr, adapter->params.vpd.eth_base, 5); 3724f7917c00SJeff Kirsher hw_addr[5] = adapter->params.vpd.eth_base[5] + i; 3725f7917c00SJeff Kirsher 3726f7917c00SJeff Kirsher memcpy(adapter->port[i]->dev_addr, hw_addr, 3727f7917c00SJeff Kirsher ETH_ALEN); 3728f7917c00SJeff Kirsher init_link_config(&p->link_config, p->phy.caps); 3729f7917c00SJeff Kirsher p->phy.ops->power_down(&p->phy, 1); 3730f7917c00SJeff Kirsher 3731f7917c00SJeff Kirsher /* 3732f7917c00SJeff Kirsher * If the PHY doesn't support interrupts for link status 3733f7917c00SJeff Kirsher * changes, schedule a scan of the adapter links at least 3734f7917c00SJeff Kirsher * once a second. 3735f7917c00SJeff Kirsher */ 3736f7917c00SJeff Kirsher if (!(p->phy.caps & SUPPORTED_IRQ) && 3737f7917c00SJeff Kirsher adapter->params.linkpoll_period > 10) 3738f7917c00SJeff Kirsher adapter->params.linkpoll_period = 10; 3739f7917c00SJeff Kirsher } 3740f7917c00SJeff Kirsher 3741f7917c00SJeff Kirsher return 0; 3742f7917c00SJeff Kirsher } 3743f7917c00SJeff Kirsher 3744f7917c00SJeff Kirsher void t3_led_ready(struct adapter *adapter) 3745f7917c00SJeff Kirsher { 3746f7917c00SJeff Kirsher t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 3747f7917c00SJeff Kirsher F_GPIO0_OUT_VAL); 3748f7917c00SJeff Kirsher } 3749f7917c00SJeff Kirsher 3750f7917c00SJeff Kirsher int t3_replay_prep_adapter(struct adapter *adapter) 3751f7917c00SJeff Kirsher { 3752f7917c00SJeff Kirsher const struct adapter_info *ai = adapter->params.info; 3753f7917c00SJeff Kirsher unsigned int i, j = -1; 3754f7917c00SJeff Kirsher int ret; 3755f7917c00SJeff Kirsher 3756f7917c00SJeff Kirsher early_hw_init(adapter, ai); 3757f7917c00SJeff Kirsher ret = init_parity(adapter); 3758f7917c00SJeff Kirsher if (ret) 3759f7917c00SJeff Kirsher return ret; 3760f7917c00SJeff Kirsher 3761f7917c00SJeff Kirsher for_each_port(adapter, i) { 3762f7917c00SJeff Kirsher const struct port_type_info *pti; 3763f7917c00SJeff Kirsher struct port_info *p = adap2pinfo(adapter, i); 3764f7917c00SJeff Kirsher 3765f7917c00SJeff Kirsher while (!adapter->params.vpd.port_type[++j]) 3766f7917c00SJeff Kirsher ; 3767f7917c00SJeff Kirsher 3768f7917c00SJeff Kirsher pti = &port_types[adapter->params.vpd.port_type[j]]; 3769f7917c00SJeff Kirsher ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL); 3770f7917c00SJeff Kirsher if (ret) 3771f7917c00SJeff Kirsher return ret; 3772f7917c00SJeff Kirsher p->phy.ops->power_down(&p->phy, 1); 3773f7917c00SJeff Kirsher } 3774f7917c00SJeff Kirsher 3775f7917c00SJeff Kirsher return 0; 3776f7917c00SJeff Kirsher } 3777f7917c00SJeff Kirsher 3778