Esempio n. 1
0
static			void
siena_intr_disable(
	__in		efx_nic_t *enp)
{
	efx_oword_t oword;

	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);

	EFSYS_SPIN(10);
}
Esempio n. 2
0
static	__checkReturn	efx_rc_t
siena_intr_trigger(
	__in		efx_nic_t *enp,
	__in		unsigned int level)
{
	efx_intr_t *eip = &(enp->en_intr);
	efx_oword_t oword;
	unsigned int count;
	uint32_t sel;
	efx_rc_t rc;

	/* bug16757: No event queues can be initialized */
	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));

	if (level >= EFX_NINTR_SIENA) {
		rc = EINVAL;
		goto fail1;
	}

	if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
		return (ENOTSUP); /* avoid EFSYS_PROBE() */

	sel = level;

	/* Trigger a test interrupt */
	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);

	/*
	 * Wait up to 100ms for the interrupt to be raised before restoring
	 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
	 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
	 */
	count = 0;
	do {
		EFSYS_SPIN(100);	/* 100us */

		EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
	} while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);

	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
Esempio n. 3
0
			void
efx_intr_disable(
	__in		efx_nic_t *enp)
{
	efx_oword_t oword;

	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);

	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);

	EFSYS_SPIN(10);
}
Esempio n. 4
0
static	__checkReturn	efx_rc_t
ef10_filter_delete_internal(
	__in		efx_nic_t *enp,
	__in		uint32_t filter_id)
{
	efx_rc_t rc;
	ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
	efx_filter_spec_t *spec;
	efsys_lock_state_t state;
	uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS;

	/*
	 * Find the software table entry and mark it busy.  Don't
	 * remove it yet; any attempt to update while we're waiting
	 * for the firmware must find the busy entry.
	 *
	 * FIXME: What if the busy flag is never cleared?
	 */
	EFSYS_LOCK(enp->en_eslp, state);
	while (ef10_filter_entry_is_busy(table, filter_idx)) {
		EFSYS_UNLOCK(enp->en_eslp, state);
		EFSYS_SPIN(1);
		EFSYS_LOCK(enp->en_eslp, state);
	}
	if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) {
		ef10_filter_set_entry_busy(table, filter_idx);
	}
	EFSYS_UNLOCK(enp->en_eslp, state);

	if (spec == NULL) {
		rc = ENOENT;
		goto fail1;
	}

	/*
	 * Try to remove the hardware filter. This may fail if the MC has
	 * rebooted (which frees all hardware filter resources).
	 */
	if (ef10_filter_is_exclusive(spec)) {
		rc = efx_mcdi_filter_op_delete(enp,
		    MC_CMD_FILTER_OP_IN_OP_REMOVE,
		    &table->eft_entry[filter_idx].efe_handle);
	} else {
		rc = efx_mcdi_filter_op_delete(enp,
		    MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE,
		    &table->eft_entry[filter_idx].efe_handle);
	}

	/* Free the software table entry */
	EFSYS_LOCK(enp->en_eslp, state);
	ef10_filter_set_entry_not_busy(table, filter_idx);
	ef10_filter_set_entry(table, filter_idx, NULL);
	EFSYS_UNLOCK(enp->en_eslp, state);

	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);

	/* Check result of hardware filter removal */
	if (rc != 0)
		goto fail2;

	return (0);

fail2:
	EFSYS_PROBE(fail2);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
Esempio n. 5
0
__checkReturn	int
siena_sram_test(
    __in		efx_nic_t *enp,
    __in		efx_sram_pattern_fn_t func)
{
    efx_oword_t oword;
    efx_qword_t qword;
    efx_qword_t verify;
    size_t rows;
    unsigned int wptr;
    unsigned int rptr;
    int rc;

    EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);

    /* Reconfigure into HALF buffer table mode */
    EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 0);
    EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);

    /*
     * Move the descriptor caches up to the top of SRAM, and test
     * all of SRAM below them. We only miss out one row here.
     */
    rows = SIENA_SRAM_ROWS - 1;
    EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rows);
    EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);

    EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, rows + 1);
    EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);

    /*
     * Write the pattern through BUF_HALF_TBL. Write
     * in 64 entry batches, waiting 1us in between each batch
     * to guarantee not to overflow the SRAM fifo
     */
    for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
        func(wptr, B_FALSE, &qword);
        EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);

        if ((wptr - rptr) < 64 && wptr < rows - 1)
            continue;

        EFSYS_SPIN(1);

        for (; rptr <= wptr; ++rptr) {
            func(rptr, B_FALSE, &qword);
            EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
                              &verify);

            if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
                rc = EFAULT;
                goto fail1;
            }
        }
    }

    /* And do the same negated */
    for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
        func(wptr, B_TRUE, &qword);
        EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);

        if ((wptr - rptr) < 64 && wptr < rows - 1)
            continue;

        EFSYS_SPIN(1);

        for (; rptr <= wptr; ++rptr) {
            func(rptr, B_TRUE, &qword);
            EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
                              &verify);

            if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
                rc = EFAULT;
                goto fail2;
            }
        }
    }

    /* Restore back to FULL buffer table mode */
    EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
    EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);

    /*
     * We don't need to reconfigure SRAM again because the API
     * requires efx_nic_fini() to be called after an sram test.
     */
    return (0);

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

    /* Restore back to FULL buffer table mode */
    EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
    EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);

    return (rc);
}
Esempio n. 6
0
			void
efx_mcdi_read_response_header(
	__in		efx_nic_t *enp,
	__inout		efx_mcdi_req_t *emrp)
{
#if EFSYS_OPT_MCDI_LOGGING
	const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
#endif /* EFSYS_OPT_MCDI_LOGGING */
	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
	efx_dword_t hdr[2];
	unsigned int hdr_len;
	unsigned int data_len;
	unsigned int seq;
	unsigned int cmd;
	unsigned int error;
	efx_rc_t rc;

	EFSYS_ASSERT(emrp != NULL);

	efx_mcdi_read_response(enp, &hdr[0], 0, sizeof (hdr[0]));
	hdr_len = sizeof (hdr[0]);

	cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE);
	seq = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ);
	error = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR);

	if (cmd != MC_CMD_V2_EXTN) {
		data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN);
	} else {
		efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1]));
		hdr_len += sizeof (hdr[1]);

		cmd = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD);
		data_len =
		    EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
	}

	if (error && (data_len == 0)) {
		/* The MC has rebooted since the request was sent. */
		EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US);
		efx_mcdi_poll_reboot(enp);
		rc = EIO;
		goto fail1;
	}
	if ((cmd != emrp->emr_cmd) ||
	    (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) {
		/* Response is for a different request */
		rc = EIO;
		goto fail2;
	}
	if (error) {
		efx_dword_t err[2];
		unsigned int err_len = MIN(data_len, sizeof (err));
		int err_code = MC_CMD_ERR_EPROTO;
		int err_arg = 0;

		/* Read error code (and arg num for MCDI v2 commands) */
		efx_mcdi_read_response(enp, &err, hdr_len, err_len);

		if (err_len >= (MC_CMD_ERR_CODE_OFST + sizeof (efx_dword_t)))
			err_code = EFX_DWORD_FIELD(err[0], EFX_DWORD_0);
#ifdef WITH_MCDI_V2
		if (err_len >= (MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t)))
			err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0);
#endif
		emrp->emr_err_code = err_code;
		emrp->emr_err_arg = err_arg;

#if EFSYS_OPT_MCDI_PROXY_AUTH
		if ((err_code == MC_CMD_ERR_PROXY_PENDING) &&
		    (err_len == sizeof (err))) {
			/*
			 * The MCDI request would normally fail with EPERM, but
			 * firmware has forwarded it to an authorization agent
			 * attached to a privileged PF.
			 *
			 * Save the authorization request handle. The client
			 * must wait for a PROXY_RESPONSE event, or timeout.
			 */
			emrp->emr_proxy_handle = err_arg;
		}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */

#if EFSYS_OPT_MCDI_LOGGING
		if (emtp->emt_logger != NULL) {
			emtp->emt_logger(emtp->emt_context,
			    EFX_LOG_MCDI_RESPONSE,
			    &hdr, hdr_len,
			    &err, err_len);
		}
#endif /* EFSYS_OPT_MCDI_LOGGING */

		if (!emrp->emr_quiet) {
			EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd,
			    int, err_code, int, err_arg);
		}

		rc = efx_mcdi_request_errcode(err_code);
		goto fail3;
	}