Exemplo n.º 1
0
static void
ntb_handle_legacy_interrupt(void *arg)
{
	struct ntb_softc *ntb = arg;
	unsigned int i = 0;
	uint64_t pdb64;
	uint16_t pdb16;

	if (ntb->type == NTB_SOC) {
		pdb64 = ntb_reg_read(8, ntb->reg_ofs.pdb);

		while (pdb64) {
			i = ffs(pdb64);
			pdb64 &= pdb64 - 1;
			handle_soc_irq(&ntb->db_cb[i]);
		}
	} else {
		pdb16 = ntb_reg_read(2, ntb->reg_ofs.pdb);

		if ((pdb16 & XEON_DB_HW_LINK) != 0) {
			handle_xeon_event_irq(ntb);
			pdb16 &= ~XEON_DB_HW_LINK;
		}

		while (pdb16 != 0) {
			i = ffs(pdb16);
			pdb16 &= pdb16 - 1;
			handle_xeon_irq(&ntb->db_cb[i]);
		}
	}

}
Exemplo n.º 2
0
/*
 * Doorbell register and mask are 64-bit on SoC, 16-bit on Xeon.  Abstract it
 * out to make code clearer.
 */
static uint64_t
db_ioread(struct ntb_softc *ntb, uint32_t regoff)
{

	if (ntb->type == NTB_SOC)
		return (ntb_reg_read(8, regoff));

	KASSERT(ntb->type == NTB_XEON, ("bad ntb type"));

	return (ntb_reg_read(2, regoff));
}
Exemplo n.º 3
0
static void
ntb_handle_link_event(struct ntb_softc *ntb, int link_state)
{
	enum ntb_hw_event event;
	uint16_t status;

	if (ntb->link_status == link_state)
		return;

	if (link_state == NTB_LINK_UP) {
		device_printf(ntb->device, "Link Up\n");
		ntb->link_status = NTB_LINK_UP;
		event = NTB_EVENT_HW_LINK_UP;

		if (ntb->type == NTB_SOC)
			status = ntb_reg_read(2, ntb->reg_ofs.lnk_stat);
		else
			status = pci_read_config(ntb->device,
			    XEON_LINK_STATUS_OFFSET, 2);
		ntb->link_width = (status & NTB_LINK_WIDTH_MASK) >> 4;
		ntb->link_speed = (status & NTB_LINK_SPEED_MASK);
		device_printf(ntb->device, "Link Width %d, Link Speed %d\n",
		    ntb->link_width, ntb->link_speed);
		callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz,
		    ntb_handle_heartbeat, ntb);
	} else {
Exemplo n.º 4
0
static void
soc_perform_link_restart(struct ntb_softc *ntb)
{
	uint32_t status;

	/* Driver resets the NTB ModPhy lanes - magic! */
	ntb_reg_write(1, SOC_MODPHY_PCSREG6, 0xe0);
	ntb_reg_write(1, SOC_MODPHY_PCSREG4, 0x40);
	ntb_reg_write(1, SOC_MODPHY_PCSREG4, 0x60);
	ntb_reg_write(1, SOC_MODPHY_PCSREG6, 0x60);

	/* Driver waits 100ms to allow the NTB ModPhy to settle */
	pause("ModPhy", hz / 10);

	/* Clear AER Errors, write to clear */
	status = ntb_reg_read(4, SOC_ERRCORSTS_OFFSET);
	status &= PCIM_AER_COR_REPLAY_ROLLOVER;
	ntb_reg_write(4, SOC_ERRCORSTS_OFFSET, status);

	/* Clear unexpected electrical idle event in LTSSM, write to clear */
	status = ntb_reg_read(4, SOC_LTSSMERRSTS0_OFFSET);
	status |= SOC_LTSSMERRSTS0_UNEXPECTEDEI;
	ntb_reg_write(4, SOC_LTSSMERRSTS0_OFFSET, status);

	/* Clear DeSkew Buffer error, write to clear */
	status = ntb_reg_read(4, SOC_DESKEWSTS_OFFSET);
	status |= SOC_DESKEWSTS_DBERR;
	ntb_reg_write(4, SOC_DESKEWSTS_OFFSET, status);

	status = ntb_reg_read(4, SOC_IBSTERRRCRVSTS0_OFFSET);
	status &= SOC_IBIST_ERR_OFLOW;
	ntb_reg_write(4, SOC_IBSTERRRCRVSTS0_OFFSET, status);

	/* Releases the NTB state machine to allow the link to retrain */
	status = ntb_reg_read(4, SOC_LTSSMSTATEJMP_OFFSET);
	status &= ~SOC_LTSSMSTATEJMP_FORCEDETECT;
	ntb_reg_write(4, SOC_LTSSMSTATEJMP_OFFSET, status);
}
Exemplo n.º 5
0
/* SOC does not have link status interrupt, poll on that platform */
static void
ntb_handle_heartbeat(void *arg)
{
	struct ntb_softc *ntb = arg;
	uint32_t status32;
	int rc = ntb_check_link_status(ntb);

	if (rc != 0)
		device_printf(ntb->device,
		    "Error determining link status\n");
	/* Check to see if a link error is the cause of the link down */
	if (ntb->link_status == NTB_LINK_DOWN) {
		status32 = ntb_reg_read(4, SOC_LTSSMSTATEJMP_OFFSET);
		if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) {
			callout_reset(&ntb->lr_timer, 0, recover_soc_link,
			    ntb);
			return;
		}
	}

	callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz,
	    ntb_handle_heartbeat, ntb);
}