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