inline void falcon_irq_ack_a1(struct efx_nic *efx)
{
	efx_dword_t reg;

	EFX_POPULATE_DWORD_1(reg, FRF_AA_INT_ACK_KER_FIELD, 0xb7eb7e);
	efx_writed(efx, &reg, FR_AA_INT_ACK_KER);
	efx_readd(efx, &reg, FR_AA_WORK_AROUND_BROKEN_PCI_READS);
}
Exemple #2
0
static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
	unsigned int max_frame_len;
	efx_oword_t reg;
	bool rx_fc = !!(efx->link_fc & EFX_FC_RX);

	
	EFX_POPULATE_DWORD_3(reg,
			     XM_RX_JUMBO_MODE, 1,
			     XM_TX_STAT_EN, 1,
			     XM_RX_STAT_EN, 1);
	falcon_write(efx, &reg, XM_GLB_CFG_REG);

	
	EFX_POPULATE_DWORD_6(reg,
			     XM_TXEN, 1,
			     XM_TX_PRMBL, 1,
			     XM_AUTO_PAD, 1,
			     XM_TXCRC, 1,
			     XM_FCNTL, 1,
			     XM_IPG, 0x3);
	falcon_write(efx, &reg, XM_TX_CFG_REG);

	
	EFX_POPULATE_DWORD_5(reg,
			     XM_RXEN, 1,
			     XM_AUTO_DEPAD, 0,
			     XM_ACPT_ALL_MCAST, 1,
			     XM_ACPT_ALL_UCAST, efx->promiscuous,
			     XM_PASS_CRC_ERR, 1);
	falcon_write(efx, &reg, XM_RX_CFG_REG);

	
	max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
	EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len);
	falcon_write(efx, &reg, XM_RX_PARAM_REG);
	EFX_POPULATE_DWORD_2(reg,
			     XM_MAX_TX_FRM_SIZE, max_frame_len,
			     XM_TX_JUMBO_MODE, 1);
	falcon_write(efx, &reg, XM_TX_PARAM_REG);

	EFX_POPULATE_DWORD_2(reg,
			     XM_PAUSE_TIME, 0xfffe, 
			     XM_DIS_FCNTL, !rx_fc);
	falcon_write(efx, &reg, XM_FC_REG);

	
	EFX_POPULATE_DWORD_4(reg,
			     XM_ADR_0, efx->net_dev->dev_addr[0],
			     XM_ADR_1, efx->net_dev->dev_addr[1],
			     XM_ADR_2, efx->net_dev->dev_addr[2],
			     XM_ADR_3, efx->net_dev->dev_addr[3]);
	falcon_write(efx, &reg, XM_ADR_LO_REG);
	EFX_POPULATE_DWORD_2(reg,
			     XM_ADR_4, efx->net_dev->dev_addr[4],
			     XM_ADR_5, efx->net_dev->dev_addr[5]);
	falcon_write(efx, &reg, XM_ADR_HI_REG);
}
Exemple #3
0
	__checkReturn	efx_rc_t
ef10_mcdi_init(
	__in		efx_nic_t *enp,
	__in		const efx_mcdi_transport_t *emtp)
{
	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
	efsys_mem_t *esmp = emtp->emt_dma_mem;
	efx_dword_t dword;
	efx_rc_t rc;

	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
	    enp->en_family == EFX_FAMILY_MEDFORD ||
	    enp->en_family == EFX_FAMILY_MEDFORD2);
	EFSYS_ASSERT(enp->en_features & EFX_FEATURE_MCDI_DMA);

	/*
	 * All EF10 firmware supports MCDIv2 and MCDIv1.
	 * Medford BootROM supports MCDIv2 and MCDIv1.
	 * Huntington BootROM supports MCDIv1 only.
	 */
	emip->emi_max_version = 2;

	/* A host DMA buffer is required for EF10 MCDI */
	if (esmp == NULL) {
		rc = EINVAL;
		goto fail1;
	}

	/*
	 * Ensure that the MC doorbell is in a known state before issuing MCDI
	 * commands. The recovery algorithm requires that the MC command buffer
	 * must be 256 byte aligned. See bug24769.
	 */
	if ((EFSYS_MEM_ADDR(esmp) & 0xFF) != 0) {
		rc = EINVAL;
		goto fail2;
	}
	EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 1);
	EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);

	/* Save initial MC reboot status */
	(void) ef10_mcdi_poll_reboot(enp);

	/* Start a new epoch (allow fresh MCDI requests to succeed) */
	efx_mcdi_new_epoch(enp);

	return (0);

fail2:
	EFSYS_PROBE(fail2);
fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
Exemple #4
0
int falcon_reset_xaui(struct efx_nic *efx)
{
	efx_oword_t reg;
	int count;

	EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
	falcon_write(efx, &reg, XX_PWR_RST_REG);

	/* Give some time for the link to establish */
	for (count = 0; count < 1000; count++) { /* wait upto 10ms */
		falcon_read(efx, &reg, XX_PWR_RST_REG);
		if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
			falcon_setup_xaui(efx);
			return 0;
		}
		udelay(10);
	}
	EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
	return -ETIMEDOUT;
}
Exemple #5
0
			void
ef10_mcdi_send_request(
	__in		efx_nic_t *enp,
	__in		void *hdrp,
	__in		size_t hdr_len,
	__in		void *sdup,
	__in		size_t sdu_len)
{
	const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
	efsys_mem_t *esmp = emtp->emt_dma_mem;
	efx_dword_t dword;
	unsigned int pos;

	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
		    enp->en_family == EFX_FAMILY_MEDFORD);

	/* Write the header */
	for (pos = 0; pos < hdr_len; pos += sizeof (efx_dword_t)) {
		dword = *(efx_dword_t *)((uint8_t *)hdrp + pos);
		EFSYS_MEM_WRITED(esmp, pos, &dword);
	}

	/* Write the payload */
	for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) {
		dword = *(efx_dword_t *)((uint8_t *)sdup + pos);
		EFSYS_MEM_WRITED(esmp, hdr_len + pos, &dword);
	}

	/* Guarantee ordering of memory (MCDI request) and PIO (MC doorbell) */
	EFSYS_DMA_SYNC_FOR_DEVICE(esmp, 0, hdr_len + sdu_len);
	EFSYS_PIO_WRITE_BARRIER();

	/* Ring the doorbell to post the command DMA address to the MC */
	EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
	    EFSYS_MEM_ADDR(esmp) >> 32);
	EFX_BAR_WRITED(enp, ER_DZ_MC_DB_LWRD_REG, &dword, B_FALSE);

	EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
	    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
	EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
}
Exemple #6
0
int falcon_reset_xaui(struct efx_nic *efx)
{
	efx_oword_t reg;
	int count;

	
	EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
	falcon_write(efx, &reg, XX_PWR_RST_REG);

	
	for (count = 0; count < 1000; count++) {
		falcon_read(efx, &reg, XX_PWR_RST_REG);
		if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0 &&
		    EFX_OWORD_FIELD(reg, XX_SD_RST_ACT) == 0) {
			falcon_setup_xaui(efx);
			return 0;
		}
		udelay(10);
	}
	EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
	return -ETIMEDOUT;
}
Exemple #7
0
int falcon_reset_xaui(struct efx_nic *efx)
{
	efx_oword_t reg;
	int count;

	/* Start reset sequence */
	EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
	falcon_write(efx, &reg, XX_PWR_RST_REG);

	/* Wait up to 10 ms for completion, then reinitialise */
	for (count = 0; count < 1000; count++) {
		falcon_read(efx, &reg, XX_PWR_RST_REG);
		if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0 &&
		    EFX_OWORD_FIELD(reg, XX_SD_RST_ACT) == 0) {
			falcon_setup_xaui(efx);
			return 0;
		}
		udelay(10);
	}
	EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
	return -ETIMEDOUT;
}
Exemple #8
0
			void
siena_mcdi_send_request(
	__in		efx_nic_t *enp,
	__in		void *hdrp,
	__in		size_t hdr_len,
	__in		void *sdup,
	__in		size_t sdu_len)
{
	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
	efx_dword_t dword;
	unsigned int pdur;
	unsigned int dbr;
	unsigned int pos;

	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);

	EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
	pdur = SIENA_MCDI_PDU(emip);
	dbr = SIENA_MCDI_DOORBELL(emip);

	/* Write the header */
	EFSYS_ASSERT3U(hdr_len, ==, sizeof (efx_dword_t));
	dword = *(efx_dword_t *)hdrp;
	EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_TRUE);

	/* Write the payload */
	for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) {
		dword = *(efx_dword_t *)((uint8_t *)sdup + pos);
		EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM,
		    pdur + 1 + (pos >> 2), &dword, B_FALSE);
	}

	/* Ring the doorbell */
	EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xd004be11);
	EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE);
}
Exemple #9
0
void
efx_mcdi_request_start(
    __in		efx_nic_t *enp,
    __in		efx_mcdi_req_t *emrp,
    __in		boolean_t ev_cpl)
{
    efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
    efx_dword_t dword;
    unsigned int seq;
    unsigned int xflags;
    unsigned int pdur;
    unsigned int dbr;
    unsigned int pos;
    int state;

    EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
    EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
    EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);

    switch (emip->emi_port)	{
    case 1:
        pdur = MCDI_P1_PDU_OFST;
        dbr = MCDI_P1_DBL_OFST;
        break;
    case 2:
        pdur = MCDI_P2_PDU_OFST;
        dbr = MCDI_P2_DBL_OFST;
        break;
    default:
        EFSYS_ASSERT(0);
        pdur = dbr = 0;
    };

    /*
     * efx_mcdi_request_start() is naturally serialised against both
     * efx_mcdi_request_poll() and efx_mcdi_ev_cpl()/efx_mcdi_ev_death(),
     * by virtue of there only being one oustanding MCDI request.
     * Unfortunately, upper layers may also call efx_mcdi_request_abort()
     * at any time, to timeout a pending mcdi request, That request may
     * then subsequently complete, meaning efx_mcdi_ev_cpl() or
     * efx_mcdi_ev_death() may end up running in parallel with
     * efx_mcdi_request_start(). This race is handled by ensuring that
     * %emi_pending_req, %emi_ev_cpl and %emi_seq are protected by the
     * en_eslp lock.
     */
    EFSYS_LOCK(enp->en_eslp, state);
    EFSYS_ASSERT(emip->emi_pending_req == NULL);
    emip->emi_pending_req = emrp;
    emip->emi_ev_cpl = ev_cpl;
    emip->emi_poll_cnt = 0;
    seq = emip->emi_seq++ & 0xf;
    EFSYS_UNLOCK(enp->en_eslp, state);

    xflags = 0;
    if (ev_cpl)
        xflags |= MCDI_HEADER_XFLAGS_EVREQ;

    /* Construct the header in shared memory */
    EFX_POPULATE_DWORD_6(dword,
                         MCDI_HEADER_CODE, emrp->emr_cmd,
                         MCDI_HEADER_RESYNC, 1,
                         MCDI_HEADER_DATALEN, emrp->emr_in_length,
                         MCDI_HEADER_SEQ, seq,
                         MCDI_HEADER_RESPONSE, 0,
                         MCDI_HEADER_XFLAGS, xflags);
    EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_TRUE);

    for (pos = 0; pos < emrp->emr_in_length; pos += sizeof (efx_dword_t)) {
        memcpy(&dword, MCDI_IN(*emrp, efx_dword_t, pos),
               MIN(sizeof (dword), emrp->emr_in_length - pos));
        EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM,
                           pdur + 1 + (pos >> 2), &dword, B_FALSE);
    }

    /* Ring the doorbell */
    EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xd004be11);
    EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE);
}
Exemple #10
0
			void
hunt_mcdi_request_copyin(
	__in		efx_nic_t *enp,
	__in		efx_mcdi_req_t *emrp,
	__in		unsigned int seq,
	__in		boolean_t ev_cpl,
	__in		boolean_t new_epoch)
{
	const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
	efsys_mem_t *esmp = emtp->emt_dma_mem;
	efx_mcdi_header_type_t hdr_type;
	efx_dword_t dword;
	efx_dword_t hdr[2];
	unsigned int xflags;
	unsigned int pos;
	size_t offset;

	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);

	xflags = 0;
	if (ev_cpl)
		xflags |= MCDI_HEADER_XFLAGS_EVREQ;

	offset = 0;

	hdr_type = EFX_MCDI_HEADER_TYPE(emrp->emr_cmd,
	    MAX(emrp->emr_in_length, emrp->emr_out_length));

	if (hdr_type == EFX_MCDI_HEADER_TYPE_V2) {
		/* Construct MCDI v2 header */
		EFX_POPULATE_DWORD_8(hdr[0],
		    MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
		    MCDI_HEADER_RESYNC, 1,
		    MCDI_HEADER_DATALEN, 0,
		    MCDI_HEADER_SEQ, seq,
		    MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
		    MCDI_HEADER_ERROR, 0,
		    MCDI_HEADER_RESPONSE, 0,
		    MCDI_HEADER_XFLAGS, xflags);
		EFSYS_MEM_WRITED(esmp, offset, &hdr[0]);
		offset += sizeof (efx_dword_t);

		EFX_POPULATE_DWORD_2(hdr[1],
		    MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd,
		    MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length);
		EFSYS_MEM_WRITED(esmp, offset, &hdr[1]);
		offset += sizeof (efx_dword_t);
	} else {
		/* Construct MCDI v1 header */
		EFX_POPULATE_DWORD_8(hdr[0],
		    MCDI_HEADER_CODE, emrp->emr_cmd,
		    MCDI_HEADER_RESYNC, 1,
		    MCDI_HEADER_DATALEN, emrp->emr_in_length,
		    MCDI_HEADER_SEQ, seq,
		    MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
		    MCDI_HEADER_ERROR, 0,
		    MCDI_HEADER_RESPONSE, 0,
		    MCDI_HEADER_XFLAGS, xflags);
		EFSYS_MEM_WRITED(esmp, 0, &hdr[0]);
		offset += sizeof (efx_dword_t);
	}

#if EFSYS_OPT_MCDI_LOGGING
	if (emtp->emt_logger != NULL) {
		emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
		    &hdr, offset,
		    emrp->emr_in_buf, emrp->emr_in_length);
	}
#endif /* EFSYS_OPT_MCDI_LOGGING */

	/* Construct the payload */
	for (pos = 0; pos < emrp->emr_in_length; pos += sizeof (efx_dword_t)) {
		memcpy(&dword, MCDI_IN(*emrp, efx_dword_t, pos),
		    MIN(sizeof (dword), emrp->emr_in_length - pos));
		EFSYS_MEM_WRITED(esmp, offset + pos, &dword);
	}

	/* Ring the doorbell to post the command DMA address to the MC */
	EFSYS_ASSERT((EFSYS_MEM_ADDR(esmp) & 0xFF) == 0);

	/* Guarantee ordering of memory (MCDI request) and PIO (MC doorbell) */
	EFSYS_DMA_SYNC_FOR_DEVICE(esmp, 0, offset + emrp->emr_in_length);
	EFSYS_PIO_WRITE_BARRIER();

	EFX_POPULATE_DWORD_1(dword,
	    EFX_DWORD_0, EFSYS_MEM_ADDR(esmp) >> 32);
	EFX_BAR_WRITED(enp, ER_DZ_MC_DB_LWRD_REG, &dword, B_FALSE);

	EFX_POPULATE_DWORD_1(dword,
	    EFX_DWORD_0, EFSYS_MEM_ADDR(esmp) & 0xffffffff);
	EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
}