cxgb3 - fix EEH
Reset the chip when the PCI link goes down. Preserve the napi structure when a sge qset's resources are freed. Replay only HW initialization when the chip comes out of reset. Signed-off-by: Divy Le ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
@ -698,6 +698,7 @@ void mac_prep(struct cmac *mac, struct adapter *adapter, int index);
|
|||||||
void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
|
void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
|
||||||
int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
|
int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
|
||||||
int reset);
|
int reset);
|
||||||
|
int t3_replay_prep_adapter(struct adapter *adapter);
|
||||||
void t3_led_ready(struct adapter *adapter);
|
void t3_led_ready(struct adapter *adapter);
|
||||||
void t3_fatal_err(struct adapter *adapter);
|
void t3_fatal_err(struct adapter *adapter);
|
||||||
void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
|
void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
|
||||||
|
@ -2430,9 +2430,6 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
|
|||||||
test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
|
test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
|
||||||
offload_close(&adapter->tdev);
|
offload_close(&adapter->tdev);
|
||||||
|
|
||||||
/* Free sge resources */
|
|
||||||
t3_free_sge_resources(adapter);
|
|
||||||
|
|
||||||
adapter->flags &= ~FULL_INIT_DONE;
|
adapter->flags &= ~FULL_INIT_DONE;
|
||||||
|
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
@ -2457,8 +2454,12 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
|
pci_restore_state(pdev);
|
||||||
|
|
||||||
if (t3_prep_adapter(adapter, adapter->params.info, 1))
|
/* Free sge resources */
|
||||||
|
t3_free_sge_resources(adapter);
|
||||||
|
|
||||||
|
if (t3_replay_prep_adapter(adapter))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
return PCI_ERS_RESULT_RECOVERED;
|
return PCI_ERS_RESULT_RECOVERED;
|
||||||
@ -2610,6 +2611,7 @@ static int __devinit init_one(struct pci_dev *pdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
mmio_start = pci_resource_start(pdev, 0);
|
mmio_start = pci_resource_start(pdev, 0);
|
||||||
mmio_len = pci_resource_len(pdev, 0);
|
mmio_len = pci_resource_len(pdev, 0);
|
||||||
|
@ -444,6 +444,14 @@
|
|||||||
|
|
||||||
#define A_PCIE_CFG 0x88
|
#define A_PCIE_CFG 0x88
|
||||||
|
|
||||||
|
#define S_ENABLELINKDWNDRST 21
|
||||||
|
#define V_ENABLELINKDWNDRST(x) ((x) << S_ENABLELINKDWNDRST)
|
||||||
|
#define F_ENABLELINKDWNDRST V_ENABLELINKDWNDRST(1U)
|
||||||
|
|
||||||
|
#define S_ENABLELINKDOWNRST 20
|
||||||
|
#define V_ENABLELINKDOWNRST(x) ((x) << S_ENABLELINKDOWNRST)
|
||||||
|
#define F_ENABLELINKDOWNRST V_ENABLELINKDOWNRST(1U)
|
||||||
|
|
||||||
#define S_PCIE_CLIDECEN 16
|
#define S_PCIE_CLIDECEN 16
|
||||||
#define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN)
|
#define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN)
|
||||||
#define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U)
|
#define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U)
|
||||||
|
@ -538,6 +538,31 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* t3_reset_qset - reset a sge qset
|
||||||
|
* @q: the queue set
|
||||||
|
*
|
||||||
|
* Reset the qset structure.
|
||||||
|
* the NAPI structure is preserved in the event of
|
||||||
|
* the qset's reincarnation, for example during EEH recovery.
|
||||||
|
*/
|
||||||
|
static void t3_reset_qset(struct sge_qset *q)
|
||||||
|
{
|
||||||
|
if (q->adap &&
|
||||||
|
!(q->adap->flags & NAPI_INIT)) {
|
||||||
|
memset(q, 0, sizeof(*q));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->adap = NULL;
|
||||||
|
memset(&q->rspq, 0, sizeof(q->rspq));
|
||||||
|
memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET);
|
||||||
|
memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
|
||||||
|
q->txq_stopped = 0;
|
||||||
|
memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* free_qset - free the resources of an SGE queue set
|
* free_qset - free the resources of an SGE queue set
|
||||||
* @adapter: the adapter owning the queue set
|
* @adapter: the adapter owning the queue set
|
||||||
@ -594,7 +619,7 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
|
|||||||
q->rspq.desc, q->rspq.phys_addr);
|
q->rspq.desc, q->rspq.phys_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(q, 0, sizeof(*q));
|
t3_reset_qset(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3264,6 +3264,7 @@ static void config_pcie(struct adapter *adap)
|
|||||||
|
|
||||||
t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff);
|
t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff);
|
||||||
t3_set_reg_field(adap, A_PCIE_CFG, 0,
|
t3_set_reg_field(adap, A_PCIE_CFG, 0,
|
||||||
|
F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST |
|
||||||
F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN);
|
F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3655,3 +3656,30 @@ void t3_led_ready(struct adapter *adapter)
|
|||||||
t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
|
t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
|
||||||
F_GPIO0_OUT_VAL);
|
F_GPIO0_OUT_VAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int t3_replay_prep_adapter(struct adapter *adapter)
|
||||||
|
{
|
||||||
|
const struct adapter_info *ai = adapter->params.info;
|
||||||
|
unsigned int i, j = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
early_hw_init(adapter, ai);
|
||||||
|
ret = init_parity(adapter);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for_each_port(adapter, i) {
|
||||||
|
struct port_info *p = adap2pinfo(adapter, i);
|
||||||
|
while (!adapter->params.vpd.port_type[j])
|
||||||
|
++j;
|
||||||
|
|
||||||
|
p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
|
||||||
|
ai->mdio_ops);
|
||||||
|
|
||||||
|
p->phy.ops->power_down(&p->phy, 1);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user