Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[pandora-kernel.git] / drivers / net / cxgb3 / t3_hw.c
index 4545acb..fb485d0 100644 (file)
@@ -1,34 +1,54 @@
 /*
- * This file is part of the Chelsio T3 Ethernet driver.
- *
- * Copyright (C) 2003-2006 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
+ * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
  */
-
 #include "common.h"
 #include "regs.h"
 #include "sge_defs.h"
 #include "firmware_exports.h"
 
- /**
 *    t3_wait_op_done_val - wait until an operation is completed
 *    @adapter: the adapter performing the operation
 *    @reg: the register to check for completion
 *    @mask: a single-bit field within @reg that indicates completion
 *    @polarity: the value of the field when the operation is completed
 *    @attempts: number of check iterations
 *    @delay: delay in usecs between iterations
 *    @valp: where to store the value of the register at completion time
 *
 *    Wait until an operation is completed by checking a bit in a register
 *    up to @attempts times.  If @valp is not NULL the value of the register
 *    at the time it indicated completion is stored there.  Returns 0 if the
 *    operation completes and -EAGAIN otherwise.
 */
+/**
    t3_wait_op_done_val - wait until an operation is completed
    @adapter: the adapter performing the operation
    @reg: the register to check for completion
    @mask: a single-bit field within @reg that indicates completion
    @polarity: the value of the field when the operation is completed
    @attempts: number of check iterations
    @delay: delay in usecs between iterations
    @valp: where to store the value of the register at completion time
+ *
    Wait until an operation is completed by checking a bit in a register
    up to @attempts times.  If @valp is not NULL the value of the register
    at the time it indicated completion is stored there.  Returns 0 if the
    operation completes and -EAGAIN otherwise.
+ */
 
 int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
                        int polarity, int attempts, int delay, u32 *valp)
@@ -418,23 +438,23 @@ static const struct adapter_info t3_adap_info[] = {
        {2, 0, 0, 0,
         F_GPIO2_OEN | F_GPIO4_OEN |
         F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
-        SUPPORTED_OFFLOAD,
+        0,
         &mi1_mdio_ops, "Chelsio PE9000"},
        {2, 0, 0, 0,
         F_GPIO2_OEN | F_GPIO4_OEN |
         F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
-        SUPPORTED_OFFLOAD,
+        0,
         &mi1_mdio_ops, "Chelsio T302"},
        {1, 0, 0, 0,
         F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
         F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
-        SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD,
+        SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
         &mi1_mdio_ext_ops, "Chelsio T310"},
        {2, 0, 0, 0,
         F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
         F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
         F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
-        SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD,
+        SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
         &mi1_mdio_ext_ops, "Chelsio T320"},
 };
 
@@ -661,7 +681,8 @@ enum {
        SF_ERASE_SECTOR = 0xd8, /* erase sector */
 
        FW_FLASH_BOOT_ADDR = 0x70000,   /* start address of FW in flash */
-       FW_VERS_ADDR = 0x77ffc  /* flash address holding FW version */
+       FW_VERS_ADDR = 0x77ffc,    /* flash address holding FW version */
+       FW_MIN_SIZE = 8            /* at least version and csum */
 };
 
 /**
@@ -864,11 +885,13 @@ int t3_check_fw_version(struct adapter *adapter)
        major = G_FW_VERSION_MAJOR(vers);
        minor = G_FW_VERSION_MINOR(vers);
 
-       if (type == FW_VERSION_T3 && major == 3 && minor == 1)
+       if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
+           minor == FW_VERSION_MINOR)
                return 0;
 
        CH_ERR(adapter, "found wrong FW version(%u.%u), "
-              "driver needs version 3.1\n", major, minor);
+              "driver needs version %u.%u\n", major, minor,
+              FW_VERSION_MAJOR, FW_VERSION_MINOR);
        return -EINVAL;
 }
 
@@ -913,7 +936,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
        const u32 *p = (const u32 *)fw_data;
        int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
 
-       if (size & 3)
+       if ((size & 3) || size < FW_MIN_SIZE)
                return -EINVAL;
        if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
                return -EFBIG;
@@ -1181,7 +1204,6 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
 static void pci_intr_handler(struct adapter *adapter)
 {
        static const struct intr_info pcix1_intr_info[] = {
-               { F_PEXERR, "PCI PEX error", -1, 1 },
                {F_MSTDETPARERR, "PCI master detected parity error", -1, 1},
                {F_SIGTARABT, "PCI signaled target abort", -1, 1},
                {F_RCVTARABT, "PCI received target abort", -1, 1},
@@ -1218,6 +1240,7 @@ static void pci_intr_handler(struct adapter *adapter)
 static void pcie_intr_handler(struct adapter *adapter)
 {
        static const struct intr_info pcie_intr_info[] = {
+               {F_PEXERR, "PCI PEX error", -1, 1},
                {F_UNXSPLCPLERRR,
                 "PCI unexpected split completion DMA read error", -1, 1},
                {F_UNXSPLCPLERRC,
@@ -1500,19 +1523,25 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx)
  */
 int t3_phy_intr_handler(struct adapter *adapter)
 {
-       static const int intr_gpio_bits[] = { 8, 0x20 };
-
+       u32 mask, gpi = adapter_info(adapter)->gpio_intr;
        u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
 
        for_each_port(adapter, i) {
-               if (cause & intr_gpio_bits[i]) {
-                       struct cphy *phy = &adap2pinfo(adapter, i)->phy;
-                       int phy_cause = phy->ops->intr_handler(phy);
+               struct port_info *p = adap2pinfo(adapter, i);
+
+               mask = gpi - (gpi & (gpi - 1));
+               gpi -= mask;
+
+               if (!(p->port_type->caps & SUPPORTED_IRQ))
+                       continue;
+
+               if (cause & mask) {
+                       int phy_cause = p->phy.ops->intr_handler(&p->phy);
 
                        if (phy_cause & cphy_cause_link_change)
                                t3_link_changed(adapter, i);
                        if (phy_cause & cphy_cause_fifo_error)
-                               phy->fifo_errors++;
+                               p->phy.fifo_errors++;
                }
        }
 
@@ -2328,8 +2357,6 @@ static inline void tp_wr_indirect(struct adapter *adap, unsigned int addr,
 
 static void tp_config(struct adapter *adap, const struct tp_params *p)
 {
-       unsigned int v;
-
        t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU |
                     F_IPCHECKSUMOFFLOAD | F_UDPCHECKSUMOFFLOAD |
                     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
@@ -2348,15 +2375,11 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
                         adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
                         0);
 
-       v = t3_read_reg(adap, A_TP_PC_CONFIG);
-       v &= ~(F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL);
-       t3_write_reg(adap, A_TP_PC_CONFIG, v | F_TXDEFERENABLE |
-                    F_MODULATEUNIONMODE | F_HEARBEATDACK |
-                    F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
-
-       v = t3_read_reg(adap, A_TP_PC_CONFIG2);
-       v &= ~F_CHDRAFULL;
-       t3_write_reg(adap, A_TP_PC_CONFIG2, v);
+       t3_set_reg_field(adap, A_TP_PC_CONFIG,
+                        F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
+                        F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
+                        F_RXCONGESTIONMODE);
+       t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
 
        if (adap->params.rev > 0) {
                tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
@@ -2883,6 +2906,9 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
        struct adapter *adapter = mc7->adapter;
        const struct mc7_timing_params *p = &mc7_timings[mem_type];
 
+       if (!mc7->size)
+               return 0;
+
        val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
        slow = val & F_SLOW;
        width = G_WIDTH(val);
@@ -3083,8 +3109,10 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
        do {                    /* wait for uP to initialize */
                msleep(20);
        } while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
-       if (!attempts)
+       if (!attempts) {
+               CH_ERR(adapter, "uP initialization timed out\n");
                goto out_err;
+       }
 
        err = 0;
 out_err:
@@ -3184,7 +3212,7 @@ static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7,
        mc7->name = name;
        mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
        cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
-       mc7->size = mc7_calc_size(cfg);
+       mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
        mc7->width = G_WIDTH(cfg);
 }
 
@@ -3211,6 +3239,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
                     V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1));
        t3_write_reg(adapter, A_T3DBG_GPIO_EN,
                     ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
+       t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
 
        if (adapter->params.rev == 0 || !uses_xaui(adapter))
                val |= F_ENRGMII;
@@ -3227,15 +3256,17 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
 }
 
 /*
- * Reset the adapter.  PCIe cards lose their config space during reset, PCI-X
+ * Reset the adapter. 
+ * Older PCIe cards lose their config space during reset, PCI-X
  * ones don't.
  */
 int t3_reset_adapter(struct adapter *adapter)
 {
-       int i;
+       int i, save_and_restore_pcie = 
+           adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
        uint16_t devid = 0;
 
-       if (is_pcie(adapter))
+       if (save_and_restore_pcie)
                pci_save_state(adapter->pdev);
        t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE);
 
@@ -3253,7 +3284,7 @@ int t3_reset_adapter(struct adapter *adapter)
        if (devid != 0x1425)
                return -1;
 
-       if (is_pcie(adapter))
+       if (save_and_restore_pcie)
                pci_restore_state(adapter->pdev);
        return 0;
 }
@@ -3307,7 +3338,13 @@ int __devinit t3_prep_adapter(struct adapter *adapter,
                p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
                p->ntimer_qs = p->cm_size >= (128 << 20) ||
                    adapter->params.rev > 0 ? 12 : 6;
+       }
+
+       adapter->params.offload = t3_mc7_size(&adapter->pmrx) &&
+                                 t3_mc7_size(&adapter->pmtx) &&
+                                 t3_mc7_size(&adapter->cm);
 
+       if (is_offload(adapter)) {
                adapter->params.mc5.nservers = DEFAULT_NSERVERS;
                adapter->params.mc5.nfilters = adapter->params.rev > 0 ?
                    DEFAULT_NFILTERS : 0;