Beispiel #1
0
static int aq100x_reset(struct cphy *phy, int wait)
{
	
	int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000);

	if (err)
		CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n",
			phy->mdio.prtad, err);

	return err;
}
Beispiel #2
0
static int aq100x_reset(struct cphy *phy, int wait)
{
	/*
	 * Ignore the caller specified wait time; always wait for the reset to
	 * complete. Can take up to 3s.
	 */
	int err = t3_phy_reset(phy, MDIO_DEV_VEND1, 3000);

	if (err)
		CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n",
			phy->addr, err);

	return err;
}
Beispiel #3
0
int t1_mc4_intr_handler(struct pemc4 *mc4)
{
	adapter_t *adapter = mc4->adapter;
	u32 cause = t1_read_reg_4(adapter, A_MC4_INT_CAUSE);

	if (cause & F_MC4_CORR_ERR) {
		mc4->intr_cnt.corr_err++;
		CH_WARN("%s: MC4 correctable error at addr 0x%x, "
			"data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
			adapter_name(adapter),
			G_MC4_CE_ADDR(t1_read_reg_4(adapter, A_MC4_CE_ADDR)),
			t1_read_reg_4(adapter, A_MC4_CE_DATA0),
			t1_read_reg_4(adapter, A_MC4_CE_DATA1),
			t1_read_reg_4(adapter, A_MC4_CE_DATA2),
			t1_read_reg_4(adapter, A_MC4_CE_DATA3),
			t1_read_reg_4(adapter, A_MC4_CE_DATA4));
	}

	if (cause & F_MC4_UNCORR_ERR) {
		mc4->intr_cnt.uncorr_err++;
		CH_ALERT("%s: MC4 uncorrectable error at addr 0x%x, "
			 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
			 adapter_name(adapter),
			 G_MC4_UE_ADDR(t1_read_reg_4(adapter, A_MC4_UE_ADDR)),
			 t1_read_reg_4(adapter, A_MC4_UE_DATA0),
			 t1_read_reg_4(adapter, A_MC4_UE_DATA1),
			 t1_read_reg_4(adapter, A_MC4_UE_DATA2),
			 t1_read_reg_4(adapter, A_MC4_UE_DATA3),
			 t1_read_reg_4(adapter, A_MC4_UE_DATA4));
	}

	if (cause & F_MC4_ADDR_ERR) {
		mc4->intr_cnt.addr_err++;
		CH_ALERT("%s: MC4 address error\n", adapter_name(adapter));
	}

	if (cause & MC4_INT_FATAL)
		t1_fatal_err(adapter);

	t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, cause);
	return 0;
}
Beispiel #4
0
static int __devinit init_one(struct pci_dev *pdev,
			      const struct pci_device_id *ent)
{
	static int version_printed;

	int i, err, pci_using_dac = 0;
	unsigned long mmio_start, mmio_len;
	const struct board_info *bi;
	struct adapter *adapter = NULL;
	struct port_info *pi;

	if (!version_printed) {
		printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
		       DRV_VERSION);
		++version_printed;
	}

	err = pci_enable_device(pdev);
	if (err)
        return err;

	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
		CH_ERR("%s: cannot find PCI device memory base address\n",
		       pci_name(pdev));
		err = -ENODEV;
		goto out_disable_pdev;
	}

	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
		pci_using_dac = 1;

		if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
			CH_ERR("%s: unable to obtain 64-bit DMA for"
			       "consistent allocations\n", pci_name(pdev));
			err = -ENODEV;
			goto out_disable_pdev;
		}

	} else if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
		CH_ERR("%s: no usable DMA configuration\n", pci_name(pdev));
		goto out_disable_pdev;
	}

	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		CH_ERR("%s: cannot obtain PCI resources\n", pci_name(pdev));
		goto out_disable_pdev;
	}

	pci_set_master(pdev);

    mmio_start = pci_resource_start(pdev, 0);
	mmio_len = pci_resource_len(pdev, 0);
	bi = t1_get_board_info(ent->driver_data);

	for (i = 0; i < bi->port_number; ++i) {
		struct net_device *netdev;

		netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
		if (!netdev) {
			err = -ENOMEM;
			goto out_free_dev;
		}

		SET_MODULE_OWNER(netdev);
		SET_NETDEV_DEV(netdev, &pdev->dev);

		if (!adapter) {
			adapter = netdev->priv;
			adapter->pdev = pdev;
			adapter->port[0].dev = netdev;  /* so we don't leak it */

			adapter->regs = ioremap(mmio_start, mmio_len);
			if (!adapter->regs) {
				CH_ERR("%s: cannot map device registers\n",
				       pci_name(pdev));
				err = -ENOMEM;
				goto out_free_dev;
			}

			if (t1_get_board_rev(adapter, bi, &adapter->params)) {
				err = -ENODEV;	  /* Can't handle this chip rev */
				goto out_free_dev;
			}

			adapter->name = pci_name(pdev);
			adapter->msg_enable = dflt_msg_enable;
			adapter->mmio_len = mmio_len;

			init_MUTEX(&adapter->mib_mutex);
			spin_lock_init(&adapter->tpi_lock);
			spin_lock_init(&adapter->work_lock);
			spin_lock_init(&adapter->async_lock);

			INIT_WORK(&adapter->ext_intr_handler_task,
				  ext_intr_task, adapter);
			INIT_WORK(&adapter->stats_update_task, mac_stats_task,
				  adapter);
#ifdef work_struct
			init_timer(&adapter->stats_update_timer);
			adapter->stats_update_timer.function = mac_stats_timer;
			adapter->stats_update_timer.data =
				(unsigned long)adapter;
#endif

			pci_set_drvdata(pdev, netdev);
		}

		pi = &adapter->port[i];
		pi->dev = netdev;
		netif_carrier_off(netdev);
		netdev->irq = pdev->irq;
		netdev->if_port = i;
		netdev->mem_start = mmio_start;
		netdev->mem_end = mmio_start + mmio_len - 1;
		netdev->priv = adapter;
		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
		netdev->features |= NETIF_F_LLTX;

		adapter->flags |= RX_CSUM_ENABLED | TCP_CSUM_CAPABLE;
		if (pci_using_dac)
			netdev->features |= NETIF_F_HIGHDMA;
		if (vlan_tso_capable(adapter)) {
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
			adapter->flags |= VLAN_ACCEL_CAPABLE;
			netdev->features |=
				NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
			netdev->vlan_rx_register = vlan_rx_register;
			netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
#endif
			adapter->flags |= TSO_CAPABLE;
			netdev->features |= NETIF_F_TSO;
		}

		netdev->open = cxgb_open;
		netdev->stop = cxgb_close;
		netdev->hard_start_xmit = t1_start_xmit;
		netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
			sizeof(struct cpl_tx_pkt_lso) :
			sizeof(struct cpl_tx_pkt);
		netdev->get_stats = t1_get_stats;
		netdev->set_multicast_list = t1_set_rxmode;
		netdev->do_ioctl = t1_ioctl;
		netdev->change_mtu = t1_change_mtu;
		netdev->set_mac_address = t1_set_mac_addr;
#ifdef CONFIG_NET_POLL_CONTROLLER
		netdev->poll_controller = t1_netpoll;
#endif
		netdev->weight = 64;

        SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
	}

	if (t1_init_sw_modules(adapter, bi) < 0) {
		err = -ENODEV;
		goto out_free_dev;
	}

	/*
	 * The card is now ready to go.  If any errors occur during device
	 * registration we do not fail the whole card but rather proceed only
	 * with the ports we manage to register successfully.  However we must
	 * register at least one net device.
	 */
	for (i = 0; i < bi->port_number; ++i) {
		err = register_netdev(adapter->port[i].dev);
		if (err)
			CH_WARN("%s: cannot register net device %s, skipping\n",
				pci_name(pdev), adapter->port[i].dev->name);
		else {
			/*
			 * Change the name we use for messages to the name of
			 * the first successfully registered interface.
			 */
			if (!adapter->registered_device_map)
				adapter->name = adapter->port[i].dev->name;

                __set_bit(i, &adapter->registered_device_map);
		}
	}
	if (!adapter->registered_device_map) {
		CH_ERR("%s: could not register any net devices\n",
		       pci_name(pdev));
		goto out_release_adapter_res;
	}

	printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
	       bi->desc, adapter->params.chip_revision,
	       adapter->params.pci.is_pcix ? "PCIX" : "PCI",
	       adapter->params.pci.speed, adapter->params.pci.width);
	return 0;

 out_release_adapter_res:
	t1_free_sw_modules(adapter);
 out_free_dev:
	if (adapter) {
		if (adapter->regs) iounmap(adapter->regs);
		for (i = bi->port_number - 1; i >= 0; --i)
			if (adapter->port[i].dev) {
				cxgb_proc_cleanup(adapter, proc_root_driver);
				kfree(adapter->port[i].dev);
			}
	}
	pci_release_regions(pdev);
 out_disable_pdev:
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
	return err;
}
Beispiel #5
0
int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
		       const struct mdio_ops *mdio_ops)
{
	unsigned int v, v2, gpio, wait;
	int err;

	cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
		  SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI,
		  "1000/10GBASE-T");

	/*
	 * The PHY has been out of reset ever since the system powered up.  So
	 * we do a hard reset over here.
	 */
	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
	msleep(1);
	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);

	/*
	 * Give it enough time to load the firmware and get ready for mdio.
	 */
	msleep(1000);
	wait = 500; /* in 10ms increments */
	do {
		err = mdio_read(phy, MDIO_DEV_VEND1, MII_BMCR, &v);
		if (err || v == 0xffff) {

			/* Allow prep_adapter to succeed when ffff is read */

			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
				phy_addr, err, v);
			goto done;
		}

		v &= AQ_RESET;
		if (v)
			msleep(10);
	} while (v && --wait);
	if (v) {
		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
			phy_addr, v);

		goto done; /* let prep_adapter succeed */
	}

	/* Datasheet says 3s max but this has been observed */
	wait = (500 - wait) * 10 + 1000;
	if (wait > 3000)
		CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait);

	/* Firmware version check. */
	(void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
	if (v != 101)
		CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
			phy_addr, v);

	/*
	 * The PHY should start in really-low-power mode.  Prepare it for normal
	 * operations.
	 */
	err = mdio_read(phy, MDIO_DEV_VEND1, MII_BMCR, &v);
	if (err)
		return err;
	if (v & AQ_LOWPOWER) {
		err = t3_mdio_change_bits(phy, MDIO_DEV_VEND1, MII_BMCR,
					  AQ_LOWPOWER, 0);
		if (err)
			return err;
		msleep(10);
	} else
		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
			phy_addr);

	/*
	 * Verify XAUI settings, but let prep succeed no matter what.
	 */
	v = v2 = 0;
	mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
	mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
	if (v != 0x1b || v2 != 0x1b)
		CH_WARN(adapter, "PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n",
			phy_addr, v, v2);

done:
	return err;
}
Beispiel #6
0
/**
 *	t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
 *	@adapter: the adapter
 *
 *	Retrieves various core SGE parameters in the form of hardware SGE
 *	register values.  The caller is responsible for decoding these as
 *	needed.  The SGE parameters are stored in @adapter->params.sge.
 */
int t4vf_get_sge_params(struct adapter *adapter)
{
    struct sge_params *sp = &adapter->params.sge;
    u32 params[7], vals[7];
    u32 whoami;
    unsigned int pf, s_hps;
    int i, v;

    params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL));
    params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
    params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
    params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
    params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
    params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL));
    params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                 V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
    v = t4vf_query_params(adapter, 7, params, vals);
    if (v != FW_SUCCESS)
        return v;

    sp->sge_control = vals[0];
    sp->counter_val[0] = G_THRESHOLD_0(vals[6]);
    sp->counter_val[1] = G_THRESHOLD_1(vals[6]);
    sp->counter_val[2] = G_THRESHOLD_2(vals[6]);
    sp->counter_val[3] = G_THRESHOLD_3(vals[6]);
    sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2]));
    sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2]));
    sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3]));
    sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3]));
    sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4]));
    sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4]));

    sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1;
    if (is_t4(adapter))
        sp->fl_starve_threshold2 = sp->fl_starve_threshold;
    else
        sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 +
                                   1;

    /*
     * We need the Queues/Page and Host Page Size for our VF.
     * This is based on the PF from which we're instantiated.
     */
    whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI));
    pf = G_SOURCEPF(whoami);

    s_hps = (S_HOSTPAGESIZEPF0 +
             (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf);
    sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10;

    for (i = 0; i < SGE_FLBUF_SIZES; i++) {
        params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                     V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i)));
        v = t4vf_query_params(adapter, 1, params, vals);
        if (v != FW_SUCCESS)
            return v;

        sp->sge_fl_buffer_size[i] = vals[0];
    }

    /*
     * T4 uses a single control field to specify both the PCIe Padding and
     * Packing Boundary.  T5 introduced the ability to specify these
     * separately with the Padding Boundary in SGE_CONTROL and and Packing
     * Boundary in SGE_CONTROL2.  So for T5 and later we need to grab
     * SGE_CONTROL in order to determine how ingress packet data will be
     * laid out in Packed Buffer Mode.  Unfortunately, older versions of
     * the firmware won't let us retrieve SGE_CONTROL2 so if we get a
     * failure grabbing it we throw an error since we can't figure out the
     * right value.
     */
    sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64;
    sp->fl_pktshift = G_PKTSHIFT(sp->sge_control);
    sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 5);
    if (is_t4(adapter))
        sp->pack_boundary = sp->pad_boundary;
    else {
        params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2));
        v = t4vf_query_params(adapter, 1, params, vals);
        if (v != FW_SUCCESS) {
            CH_ERR(adapter, "Unable to get SGE Control2; "
                   "probably old firmware.\n");
            return v;
        }
        if (G_INGPACKBOUNDARY(vals[0]) == 0)
            sp->pack_boundary = 16;
        else
            sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) +
                                      5);
    }

    /*
     * For T5 and later we want to use the new BAR2 Doorbells.
     * Unfortunately, older firmware didn't allow the this register to be
     * read.
     */
    if (!is_t4(adapter)) {
        unsigned int s_qpp;

        params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                     V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF));
        params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                     V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF));
        v = t4vf_query_params(adapter, 2, params, vals);
        if (v != FW_SUCCESS) {
            CH_WARN(adapter, "Unable to get VF SGE Queues/Page; "
                    "probably old firmware.\n");
            return v;
        }

        s_qpp = (S_QUEUESPERPAGEPF0 +
                 (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf);
        sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0);
        sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0);
    }
Beispiel #7
0
int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
		       const struct mdio_ops *mdio_ops)
{
	unsigned int v, v2, gpio, wait;
	int err;

	cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
		  SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI,
		  "1000/10GBASE-T");

	
	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
	msleep(1);
	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);

	
	msleep(1000);
	wait = 500; 
	do {
		err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
		if (err || v == 0xffff) {

			

			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
				phy_addr, err, v);
			goto done;
		}

		v &= AQ_RESET;
		if (v)
			msleep(10);
	} while (v && --wait);
	if (v) {
		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
			phy_addr, v);

		goto done; 
	}

	
	wait = (500 - wait) * 10 + 1000;
	if (wait > 3000)
		CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait);

	
	t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v);
	if (v != 101)
		CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
			phy_addr, v);

	
	err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
	if (err)
		return err;
	if (v & AQ_LOWPOWER) {
		err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1,
					  AQ_LOWPOWER, 0);
		if (err)
			return err;
		msleep(10);
	} else
		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
			phy_addr);

	
	v = v2 = 0;
	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v);
	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2);
	if (v != 0x1b || v2 != 0x1b)
		CH_WARN(adapter,
			"PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n",
			phy_addr, v, v2);

done:
	return err;
}
Beispiel #8
0
int t1_mc3_intr_handler(struct pemc3 *mc3)
{
	adapter_t *adapter = mc3->adapter;
	int cause_reg = A_MC3_INT_CAUSE;
	u32 cause;

#ifdef CONFIG_CHELSIO_T1_1G
	if (!t1_is_asic(adapter))
		cause_reg = FPGA_MC3_REG_INTRCAUSE;
#endif
	cause = t1_read_reg_4(adapter, cause_reg);

	if (cause & F_MC3_CORR_ERR) {
		mc3->intr_cnt.corr_err++;
		CH_WARN("%s: MC3 correctable error at addr 0x%x, "
			"data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
			adapter_name(adapter),
			G_MC3_CE_ADDR(t1_read_reg_4(adapter, A_MC3_CE_ADDR)),
			t1_read_reg_4(adapter, A_MC3_CE_DATA0),
			t1_read_reg_4(adapter, A_MC3_CE_DATA1),
			t1_read_reg_4(adapter, A_MC3_CE_DATA2),
			t1_read_reg_4(adapter, A_MC3_CE_DATA3),
			t1_read_reg_4(adapter, A_MC3_CE_DATA4));
	}

	if (cause & F_MC3_UNCORR_ERR) {
		mc3->intr_cnt.uncorr_err++;
		CH_ALERT("%s: MC3 uncorrectable error at addr 0x%x, "
			 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n",
			 adapter_name(adapter),
			 G_MC3_UE_ADDR(t1_read_reg_4(adapter, A_MC3_UE_ADDR)),
			 t1_read_reg_4(adapter, A_MC3_UE_DATA0),
			 t1_read_reg_4(adapter, A_MC3_UE_DATA1),
			 t1_read_reg_4(adapter, A_MC3_UE_DATA2),
			 t1_read_reg_4(adapter, A_MC3_UE_DATA3),
			 t1_read_reg_4(adapter, A_MC3_UE_DATA4));
	}

	if (G_MC3_PARITY_ERR(cause)) {
		mc3->intr_cnt.parity_err++;
		CH_ALERT("%s: MC3 parity error 0x%x\n", adapter_name(adapter),
			 G_MC3_PARITY_ERR(cause));
	}

	if (cause & F_MC3_ADDR_ERR) {
		mc3->intr_cnt.addr_err++;
		CH_ALERT("%s: MC3 address error\n", adapter_name(adapter));
	}

	if (cause & MC3_INTR_FATAL)
		t1_fatal_err(adapter);

	if (t1_is_T1B(adapter)) {
		/*
		 * Workaround for T1B bug: we must write to enable register to
		 * clear interrupts.
		 */
		t1_write_reg_4(adapter, A_MC3_INT_ENABLE, cause);
		/* restore enable */
		t1_write_reg_4(adapter, A_MC3_INT_ENABLE, MC3_INTR_MASK);
	} else
		t1_write_reg_4(adapter, cause_reg, cause);

	return 0;
}