]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/cxgb3/t3_hw.c
sky2: be more selective about FIFO watchdog
[linux-2.6-omap-h63xx.git] / drivers / net / cxgb3 / t3_hw.c
index 365a7f5b1f94441c670c9c8c599d9199edb23eb7..b02d15daf5d90f56fac24a6b531fbf40ac2aa8f0 100644 (file)
@@ -438,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"},
 };
 
@@ -681,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 */
 };
 
 /**
@@ -846,6 +847,98 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
        return 0;
 }
 
+/**
+ *     t3_get_tp_version - read the tp sram version
+ *     @adapter: the adapter
+ *     @vers: where to place the version
+ *
+ *     Reads the protocol sram version from sram.
+ */
+int t3_get_tp_version(struct adapter *adapter, u32 *vers)
+{
+       int ret;
+
+       /* Get version loaded in SRAM */
+       t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+       ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+                             1, 1, 5, 1);
+       if (ret)
+               return ret;
+       
+       *vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+       return 0;
+}
+
+/**
+ *     t3_check_tpsram_version - read the tp sram version
+ *     @adapter: the adapter
+ *     @must_load: set to 1 if loading a new microcode image is required
+ *
+ *     Reads the protocol sram version from flash.
+ */
+int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
+{
+       int ret;
+       u32 vers;
+       unsigned int major, minor;
+
+       if (adapter->params.rev == T3_REV_A)
+               return 0;
+
+       *must_load = 1;
+
+       ret = t3_get_tp_version(adapter, &vers);
+       if (ret)
+               return ret;
+
+       major = G_TP_VERSION_MAJOR(vers);
+       minor = G_TP_VERSION_MINOR(vers);
+
+       if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) 
+               return 0;
+
+       if (major != TP_VERSION_MAJOR)
+               CH_ERR(adapter, "found wrong TP version (%u.%u), "
+                      "driver needs version %d.%d\n", major, minor,
+                      TP_VERSION_MAJOR, TP_VERSION_MINOR);
+       else {
+               *must_load = 0;
+               CH_ERR(adapter, "found wrong TP version (%u.%u), "
+                      "driver compiled for version %d.%d\n", major, minor,
+                      TP_VERSION_MAJOR, TP_VERSION_MINOR);
+       }
+       return -EINVAL;
+}
+
+/**
+ *     t3_check_tpsram - check if provided protocol SRAM 
+ *                       is compatible with this driver
+ *     @adapter: the adapter
+ *     @tp_sram: the firmware image to write
+ *     @size: image size
+ *
+ *     Checks if an adapter's tp sram is compatible with the driver.
+ *     Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+       u32 csum;
+       unsigned int i;
+       const u32 *p = (const u32 *)tp_sram;
+
+       /* Verify checksum */
+       for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+               csum += ntohl(p[i]);
+       if (csum != 0xffffffff) {
+               CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+                      csum);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 enum fw_version_type {
        FW_VERSION_N3,
        FW_VERSION_T3
@@ -884,11 +977,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;
 }
 
@@ -918,7 +1013,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
 /*
  *     t3_load_fw - download firmware
  *     @adapter: the adapter
- *     @fw_data: the firrware image to write
+ *     @fw_data: the firmware image to write
  *     @size: image size
  *
  *     Write the supplied firmware image to the card's serial flash.
@@ -933,7 +1028,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;
@@ -1520,19 +1615,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++;
                }
        }
 
@@ -2353,7 +2454,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
                     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
        t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
                     F_MTUENABLE | V_WINDOWSCALEMODE(1) |
-                    V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+                    V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
        t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
                     V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
                     V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2362,16 +2463,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
                         F_IPV6ENABLE | F_NICMODE);
        t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
        t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
-       t3_set_reg_field(adap, A_TP_PARA_REG6,
-                        adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
-                        0);
+       t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+                        adap->params.rev > 0 ? F_ENABLEESND :
+                        F_T3A_ENABLEESND);
 
        t3_set_reg_field(adap, A_TP_PC_CONFIG,
-                        F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
-                        F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
-                        F_RXCONGESTIONMODE);
+                        F_ENABLEEPCMDAFULL,
+                        F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+                        F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
        t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+       t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+       t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+       
        if (adap->params.rev > 0) {
                tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
                t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2381,9 +2484,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
        } else
                t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
 
-       t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
-       t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
-       t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+       t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+       t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+       t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+       t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
 }
 
 /* Desired TP timer resolution in usec */
@@ -2459,6 +2563,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
                val |= F_RXCOALESCEENABLE;
                if (psh)
                        val |= F_RXCOALESCEPSHEN;
+               size = min(MAX_RX_COALESCING_LEN, size);
                t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
                             V_MAXRXDATA(MAX_RX_COALESCING_LEN));
        }
@@ -2487,11 +2592,11 @@ static void __devinit init_mtus(unsigned short mtus[])
         * it can accomodate max size TCP/IP headers when SACK and timestamps
         * are enabled and still have at least 8 bytes of payload.
         */
-       mtus[0] = 88;
-       mtus[1] = 256;
-       mtus[2] = 512;
-       mtus[3] = 576;
-       mtus[4] = 808;
+       mtus[1] = 88;
+       mtus[1] = 88;
+       mtus[2] = 256;
+       mtus[3] = 512;
+       mtus[4] = 576;
        mtus[5] = 1024;
        mtus[6] = 1280;
        mtus[7] = 1492;
@@ -2673,6 +2778,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
        t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
 }
 
+/**
+ *     t3_set_proto_sram - set the contents of the protocol sram
+ *     @adapter: the adapter
+ *     @data: the protocol image
+ *
+ *     Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+       int i;
+       u32 *buf = (u32 *)data;
+
+       for (i = 0; i < PROTO_SRAM_LINES; i++) {
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+               
+               t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+               if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+                       return -EIO;
+       }
+       t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+       return 0;
+}
+
 void t3_config_trace_filter(struct adapter *adapter,
                            const struct trace_params *tp, int filter_index,
                            int invert, int enable)
@@ -2793,7 +2926,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports)
                t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
                t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
                             F_PORT0ACTIVE | F_ENFORCEPKT);
-               t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+               t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
        } else {
                t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
                t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -2897,6 +3030,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);
@@ -3085,7 +3221,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
        else
                t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
 
-       t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+       t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
        init_hw_for_avail_ports(adapter, adapter->params.nports);
        t3_sge_init(adapter, &adapter->params.sge);
 
@@ -3097,8 +3233,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:
@@ -3198,7 +3336,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);
 }
 
@@ -3225,6 +3363,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;
@@ -3241,15 +3380,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);
 
@@ -3267,7 +3408,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;
 }
@@ -3321,7 +3462,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;