示例#1
0
	__checkReturn	efx_rc_t
efx_phy_adv_cap_set(
	__in		efx_nic_t *enp,
	__in		uint32_t mask)
{
	efx_port_t *epp = &(enp->en_port);
	efx_phy_ops_t *epop = epp->ep_epop;
	uint32_t old_mask;
	efx_rc_t rc;

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

	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
		rc = ENOTSUP;
		goto fail1;
	}

	if (epp->ep_adv_cap_mask == mask)
		goto done;

	old_mask = epp->ep_adv_cap_mask;
	epp->ep_adv_cap_mask = mask;

	if ((rc = epop->epo_reconfigure(enp)) != 0)
		goto fail2;

done:
	return (0);

fail2:
	EFSYS_PROBE(fail2);

	epp->ep_adv_cap_mask = old_mask;
	/* Reconfigure for robustness */
	if (epop->epo_reconfigure(enp) != 0) {
		/*
		 * We may have an inconsistent view of our advertised speed
		 * capabilities.
		 */
		EFSYS_ASSERT(0);
	}

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
示例#2
0
	__checkReturn	efx_rc_t
efx_mcdi_get_port_modes(
	__in		efx_nic_t *enp,
	__out		uint32_t *modesp)
{
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN,
			    MC_CMD_GET_PORT_MODES_OUT_LEN)];
	efx_rc_t rc;

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

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_GET_PORT_MODES;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail1;
	}

	/*
	 * Require only Modes and DefaultMode fields.
	 * (CurrentMode field was added for Medford)
	 */
	if (req.emr_out_length_used <
	    MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
		rc = EMSGSIZE;
		goto fail2;
	}

	*modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);

	return (0);

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

	return (rc);
}
示例#3
0
	__checkReturn	int
hunt_filter_init(
	__in		efx_nic_t *enp)
{
	int rc;
	hunt_filter_table_t *hftp;

	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);

#define	MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match))
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_IP));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_HOST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_IP));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_MAC ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_MAC));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_PORT ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_PORT));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_MAC ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_MAC));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_PORT ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_PORT));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_ETHER_TYPE ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_ETHER_TYPE));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_INNER_VID ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_INNER_VLAN));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_OUTER_VID ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_OUTER_VLAN));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO ==
	    MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_IP_PROTO));
#undef MATCH_MASK

	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (hunt_filter_table_t), hftp);

	if (!hftp) {
		rc = ENOMEM;
		goto fail1;
	}

	enp->en_filter.ef_hunt_filter_table = hftp;

	return (0);

fail1:
	EFSYS_PROBE1(fail1, int, rc);

	return (rc);
}
示例#4
0
		void
efx_tx_qdestroy(
	__in	efx_txq_t *etp)
{
	efx_nic_t *enp = etp->et_enp;
	const efx_tx_ops_t *etxop = enp->en_etxop;

	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);

	EFSYS_ASSERT(enp->en_tx_qcount != 0);
	--enp->en_tx_qcount;

	etxop->etxo_qdestroy(etp);

	/* Free the TXQ object */
	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
}
示例#5
0
		void
efx_ev_qdestroy(
	__in	efx_evq_t *eep)
{
	efx_nic_t *enp = eep->ee_enp;
	efx_ev_ops_t *eevop = enp->en_eevop;

	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);

	EFSYS_ASSERT(enp->en_ev_qcount != 0);
	--enp->en_ev_qcount;

	eevop->eevo_qdestroy(eep);

	/* Free the EVQ object */
	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
}
示例#6
0
文件: efx_lic.c 项目: tomtor/freebsd
static	__checkReturn	efx_rc_t
efx_mcdi_fc_license_update_license(
    __in		efx_nic_t *enp)
{
    efx_mcdi_req_t req;
    uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
    efx_rc_t rc;

    EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);

    (void) memset(payload, 0, sizeof (payload));
    req.emr_cmd = MC_CMD_FC;
    req.emr_in_buf = payload;
    req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
    req.emr_out_buf = payload;
    req.emr_out_length = 0;

    MCDI_IN_SET_DWORD(req, FC_IN_CMD,
                      MC_CMD_FC_OP_LICENSE);

    MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
                      MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);

    efx_mcdi_execute(enp, &req);

    if (req.emr_rc != 0) {
        rc = req.emr_rc;
        goto fail1;
    }

    if (req.emr_out_length_used != 0) {
        rc = EIO;
        goto fail2;
    }

    return (0);

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

    return (rc);
}
示例#7
0
文件: efx_mac.c 项目: tomtor/freebsd
	__checkReturn			efx_rc_t
efx_mac_pdu_set(
	__in				efx_nic_t *enp,
	__in				size_t pdu)
{
	efx_port_t *epp = &(enp->en_port);
	const efx_mac_ops_t *emop = epp->ep_emop;
	uint32_t old_pdu;
	efx_rc_t rc;

	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
	EFSYS_ASSERT(emop != NULL);

	if (pdu < EFX_MAC_PDU_MIN) {
		rc = EINVAL;
		goto fail1;
	}

	if (pdu > EFX_MAC_PDU_MAX) {
		rc = EINVAL;
		goto fail2;
	}

	old_pdu = epp->ep_mac_pdu;
	epp->ep_mac_pdu = (uint32_t)pdu;
	if ((rc = emop->emo_pdu_set(enp)) != 0)
		goto fail3;

	return (0);

fail3:
	EFSYS_PROBE(fail3);

	epp->ep_mac_pdu = old_pdu;

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

	return (rc);
}
示例#8
0
	__checkReturn	efx_rc_t
efx_mcdi_get_port_assignment(
	__in		efx_nic_t *enp,
	__out		uint32_t *portp)
{
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
			    MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)];
	efx_rc_t rc;

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

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail1;
	}

	if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
		rc = EMSGSIZE;
		goto fail2;
	}

	*portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);

	return (0);

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

	return (rc);
}
示例#9
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);
}
示例#10
0
	__checkReturn			efx_rc_t
ef10_mac_multicast_list_set(
	__in				efx_nic_t *enp)
{
	efx_port_t *epp = &(enp->en_port);
	const efx_mac_ops_t *emop = epp->ep_emop;
	efx_rc_t rc;

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

	if ((rc = emop->emo_reconfigure(enp)) != 0)
		goto fail1;

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
示例#11
0
	__checkReturn	efx_rc_t
efx_nic_reset(
	__in		efx_nic_t *enp)
{
	const efx_nic_ops_t *enop = enp->en_enop;
	unsigned int mod_flags;
	efx_rc_t rc;

	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
	/*
	 * All modules except the MCDI, PROBE, NVRAM, VPD, MON
	 * (which we do not reset here) must have been shut down or never
	 * initialized.
	 *
	 * A rule of thumb here is: If the controller or MC reboots, is *any*
	 * state lost. If it's lost and needs reapplying, then the module
	 * *must* not be initialised during the reset.
	 */
	mod_flags = enp->en_mod_flags;
	mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
		    EFX_MOD_VPD | EFX_MOD_MON);
	EFSYS_ASSERT3U(mod_flags, ==, 0);
	if (mod_flags != 0) {
		rc = EINVAL;
		goto fail1;
	}

	if ((rc = enop->eno_reset(enp)) != 0)
		goto fail2;

	return (0);

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

	return (rc);
}
示例#12
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_mcdi.em_emip);
	unsigned int seq;
	boolean_t new_epoch;
	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);

	/*
	 * 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 outstanding 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++ & EFX_MASK32(MCDI_HEADER_SEQ);
	new_epoch = emip->emi_new_epoch;
	EFSYS_UNLOCK(enp->en_eslp, state);

	efx_mcdi_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
}
示例#13
0
			void
siena_sram_init(
	__in		efx_nic_t *enp)
{
	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
	efx_oword_t oword;
	uint32_t rx_base, tx_base;

	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);

	rx_base = encp->enc_buftbl_limit;
	tx_base = rx_base + (encp->enc_rxq_limit *
	    EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));

	/* Initialize the transmit descriptor cache */
	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, tx_base);
	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);

	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DC_SIZE, EFX_TXQ_DC_SIZE);
	EFX_BAR_WRITEO(enp, FR_AZ_TX_DC_CFG_REG, &oword);

	/* Initialize the receive descriptor cache */
	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rx_base);
	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);

	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_SIZE, EFX_RXQ_DC_SIZE);
	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_CFG_REG, &oword);

	/* Set receive descriptor pre-fetch low water mark */
	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_PF_LWM, 56);
	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_PF_WM_REG, &oword);

	/* Set the event queue to use for SRAM updates */
	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_UPD_EVQ_ID, 0);
	EFX_BAR_WRITEO(enp, FR_AZ_SRM_UPD_EVQ_REG, &oword);
}
示例#14
0
			void
efx_nic_fini(
	__in		efx_nic_t *enp)
{
	const efx_nic_ops_t *enop = enp->en_enop;

	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));

	enop->eno_fini(enp);

	enp->en_mod_flags &= ~EFX_MOD_NIC;
}
示例#15
0
文件: ef10_filter.c 项目: btw616/dpdk
	__checkReturn	efx_rc_t
ef10_filter_init(
	__in		efx_nic_t *enp)
{
	efx_rc_t rc;
	ef10_filter_table_t *eftp;

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

#define	MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match))
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_IP));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_HOST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_IP));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_MAC ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_MAC));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_PORT ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_PORT));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_MAC ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_MAC));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_PORT ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_PORT));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_ETHER_TYPE ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_ETHER_TYPE));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_INNER_VID ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_INNER_VLAN));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_OUTER_VID ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_OUTER_VLAN));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IP_PROTO));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_VNI_OR_VSID ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_VNI_OR_VSID));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_LOC_MAC ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_DST_MAC));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_MCAST_DST));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST));
	EFX_STATIC_ASSERT(EFX_FILTER_MATCH_UNKNOWN_MCAST_DST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST));
	EFX_STATIC_ASSERT((uint32_t)EFX_FILTER_MATCH_UNKNOWN_UCAST_DST ==
	    MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_UCAST_DST));
#undef MATCH_MASK

	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (ef10_filter_table_t), eftp);

	if (!eftp) {
		rc = ENOMEM;
		goto fail1;
	}

	enp->en_filter.ef_ef10_filter_table = eftp;

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
示例#16
0
文件: ef10_filter.c 项目: btw616/dpdk
	__checkReturn	efx_rc_t
ef10_filter_restore(
	__in		efx_nic_t *enp)
{
	int tbl_id;
	efx_filter_spec_t *spec;
	ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
	boolean_t restoring;
	efsys_lock_state_t state;
	efx_rc_t rc;

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

	for (tbl_id = 0; tbl_id < EFX_EF10_FILTER_TBL_ROWS; tbl_id++) {

		EFSYS_LOCK(enp->en_eslp, state);

		spec = ef10_filter_entry_spec(eftp, tbl_id);
		if (spec == NULL) {
			restoring = B_FALSE;
		} else if (ef10_filter_entry_is_busy(eftp, tbl_id)) {
			/* Ignore busy entries. */
			restoring = B_FALSE;
		} else {
			ef10_filter_set_entry_busy(eftp, tbl_id);
			restoring = B_TRUE;
		}

		EFSYS_UNLOCK(enp->en_eslp, state);

		if (restoring == B_FALSE)
			continue;

		if (ef10_filter_is_exclusive(spec)) {
			rc = efx_mcdi_filter_op_add(enp, spec,
			    MC_CMD_FILTER_OP_IN_OP_INSERT,
			    &eftp->eft_entry[tbl_id].efe_handle);
		} else {
			rc = efx_mcdi_filter_op_add(enp, spec,
			    MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
			    &eftp->eft_entry[tbl_id].efe_handle);
		}

		if (rc != 0)
			goto fail1;

		EFSYS_LOCK(enp->en_eslp, state);

		ef10_filter_set_entry_not_busy(eftp, tbl_id);

		EFSYS_UNLOCK(enp->en_eslp, state);
	}

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
示例#17
0
文件: ef10_filter.c 项目: btw616/dpdk
static	__checkReturn	efx_rc_t
ef10_filter_add_internal(
	__in		efx_nic_t *enp,
	__inout		efx_filter_spec_t *spec,
	__in		boolean_t may_replace,
	__out_opt	uint32_t *filter_id)
{
	efx_rc_t rc;
	ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
	efx_filter_spec_t *saved_spec;
	uint32_t hash;
	unsigned int depth;
	int ins_index;
	boolean_t replacing = B_FALSE;
	unsigned int i;
	efsys_lock_state_t state;
	boolean_t locked = B_FALSE;

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

	hash = ef10_filter_hash(spec);

	/*
	 * FIXME: Add support for inserting filters of different priorities
	 * and removing lower priority multicast filters (bug 42378)
	 */

	/*
	 * Find any existing filters with the same match tuple or
	 * else a free slot to insert at.  If any of them are busy,
	 * we have to wait and retry.
	 */
	for (;;) {
		ins_index = -1;
		depth = 1;
		EFSYS_LOCK(enp->en_eslp, state);
		locked = B_TRUE;

		for (;;) {
			i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
			saved_spec = ef10_filter_entry_spec(eftp, i);

			if (!saved_spec) {
				if (ins_index < 0) {
					ins_index = i;
				}
			} else if (ef10_filter_equal(spec, saved_spec)) {
				if (ef10_filter_entry_is_busy(eftp, i))
					break;
				if (saved_spec->efs_priority
					    == EFX_FILTER_PRI_AUTO) {
					ins_index = i;
					goto found;
				} else if (ef10_filter_is_exclusive(spec)) {
					if (may_replace) {
						ins_index = i;
						goto found;
					} else {
						rc = EEXIST;
						goto fail1;
					}
				}

				/* Leave existing */
			}

			/*
			 * Once we reach the maximum search depth, use
			 * the first suitable slot or return EBUSY if
			 * there was none.
			 */
			if (depth == EF10_FILTER_SEARCH_LIMIT) {
				if (ins_index < 0) {
					rc = EBUSY;
					goto fail2;
				}
				goto found;
			}
			depth++;
		}
		EFSYS_UNLOCK(enp->en_eslp, state);
		locked = B_FALSE;
	}

found:
	/*
	 * Create a software table entry if necessary, and mark it
	 * busy.  We might yet fail to insert, but any attempt to
	 * insert a conflicting filter while we're waiting for the
	 * firmware must find the busy entry.
	 */
	saved_spec = ef10_filter_entry_spec(eftp, ins_index);
	if (saved_spec) {
		if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) {
			/* This is a filter we are refreshing */
			ef10_filter_set_entry_not_auto_old(eftp, ins_index);
			goto out_unlock;

		}
		replacing = B_TRUE;
	} else {
		EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), saved_spec);
		if (!saved_spec) {
			rc = ENOMEM;
			goto fail3;
		}
		*saved_spec = *spec;
		ef10_filter_set_entry(eftp, ins_index, saved_spec);
	}
	ef10_filter_set_entry_busy(eftp, ins_index);

	EFSYS_UNLOCK(enp->en_eslp, state);
	locked = B_FALSE;

	/*
	 * On replacing the filter handle may change after after a successful
	 * replace operation.
	 */
	if (replacing) {
		rc = efx_mcdi_filter_op_add(enp, spec,
		    MC_CMD_FILTER_OP_IN_OP_REPLACE,
		    &eftp->eft_entry[ins_index].efe_handle);
	} else if (ef10_filter_is_exclusive(spec)) {
		rc = efx_mcdi_filter_op_add(enp, spec,
		    MC_CMD_FILTER_OP_IN_OP_INSERT,
		    &eftp->eft_entry[ins_index].efe_handle);
	} else {
		rc = efx_mcdi_filter_op_add(enp, spec,
		    MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
		    &eftp->eft_entry[ins_index].efe_handle);
	}

	if (rc != 0)
		goto fail4;

	EFSYS_LOCK(enp->en_eslp, state);
	locked = B_TRUE;

	if (replacing) {
		/* Update the fields that may differ */
		saved_spec->efs_priority = spec->efs_priority;
		saved_spec->efs_flags = spec->efs_flags;
		saved_spec->efs_rss_context = spec->efs_rss_context;
		saved_spec->efs_dmaq_id = spec->efs_dmaq_id;
	}

	ef10_filter_set_entry_not_busy(eftp, ins_index);

out_unlock:

	EFSYS_UNLOCK(enp->en_eslp, state);
	locked = B_FALSE;

	if (filter_id)
		*filter_id = ins_index;

	return (0);

fail4:
	EFSYS_PROBE(fail4);

	if (!replacing) {
		EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), saved_spec);
		saved_spec = NULL;
	}
	ef10_filter_set_entry_not_busy(eftp, ins_index);
	ef10_filter_set_entry(eftp, ins_index, NULL);

fail3:
	EFSYS_PROBE(fail3);

fail2:
	EFSYS_PROBE(fail2);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	if (locked)
		EFSYS_UNLOCK(enp->en_eslp, state);

	return (rc);
}
示例#18
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);
}
示例#19
0
文件: ef10_filter.c 项目: btw616/dpdk
static	__checkReturn	efx_rc_t
efx_mcdi_filter_op_add(
	__in		efx_nic_t *enp,
	__in		efx_filter_spec_t *spec,
	__in		unsigned int filter_op,
	__inout		ef10_filter_handle_t *handle)
{
	efx_mcdi_req_t req;
	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_V3_IN_LEN,
		MC_CMD_FILTER_OP_EXT_OUT_LEN);
	efx_filter_match_flags_t match_flags;
	efx_rc_t rc;

	req.emr_cmd = MC_CMD_FILTER_OP;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_FILTER_OP_V3_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN;

	/*
	 * Remove match flag for encapsulated filters that does not correspond
	 * to the MCDI match flags
	 */
	match_flags = spec->efs_match_flags & ~EFX_FILTER_MATCH_ENCAP_TYPE;

	switch (filter_op) {
	case MC_CMD_FILTER_OP_IN_OP_REPLACE:
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO,
		    handle->efh_lo);
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_HI,
		    handle->efh_hi);
		/* Fall through */
	case MC_CMD_FILTER_OP_IN_OP_INSERT:
	case MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE:
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP, filter_op);
		break;
	default:
		EFSYS_ASSERT(0);
		rc = EINVAL;
		goto fail1;
	}

	MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID,
	    EVB_PORT_ID_ASSIGNED);
	MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS,
	    match_flags);
	if (spec->efs_dmaq_id == EFX_FILTER_SPEC_RX_DMAQ_ID_DROP) {
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST,
		    MC_CMD_FILTER_OP_EXT_IN_RX_DEST_DROP);
	} else {
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST,
		    MC_CMD_FILTER_OP_EXT_IN_RX_DEST_HOST);
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_QUEUE,
		    spec->efs_dmaq_id);
	}

#if EFSYS_OPT_RX_SCALE
	if (spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) {
		uint32_t rss_context;

		if (spec->efs_rss_context == EFX_RSS_CONTEXT_DEFAULT)
			rss_context = enp->en_rss_context;
		else
			rss_context = spec->efs_rss_context;
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_CONTEXT,
		    rss_context);
	}
#endif

	MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_MODE,
	    spec->efs_flags & EFX_FILTER_FLAG_RX_RSS ?
	    MC_CMD_FILTER_OP_EXT_IN_RX_MODE_RSS :
	    MC_CMD_FILTER_OP_EXT_IN_RX_MODE_SIMPLE);
	MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_TX_DEST,
	    MC_CMD_FILTER_OP_EXT_IN_TX_DEST_DEFAULT);

	if (filter_op != MC_CMD_FILTER_OP_IN_OP_REPLACE) {
		/*
		 * NOTE: Unlike most MCDI requests, the filter fields
		 * are presented in network (big endian) byte order.
		 */
		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_MAC),
		    spec->efs_rem_mac, EFX_MAC_ADDR_LEN);
		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_MAC),
		    spec->efs_loc_mac, EFX_MAC_ADDR_LEN);

		MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_SRC_PORT,
		    __CPU_TO_BE_16(spec->efs_rem_port));
		MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_DST_PORT,
		    __CPU_TO_BE_16(spec->efs_loc_port));

		MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_ETHER_TYPE,
		    __CPU_TO_BE_16(spec->efs_ether_type));

		MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_INNER_VLAN,
		    __CPU_TO_BE_16(spec->efs_inner_vid));
		MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_OUTER_VLAN,
		    __CPU_TO_BE_16(spec->efs_outer_vid));

		/* IP protocol (in low byte, high byte is zero) */
		MCDI_IN_SET_BYTE(req, FILTER_OP_EXT_IN_IP_PROTO,
		    spec->efs_ip_proto);

		EFX_STATIC_ASSERT(sizeof (spec->efs_rem_host) ==
		    MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN);
		EFX_STATIC_ASSERT(sizeof (spec->efs_loc_host) ==
		    MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN);

		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_IP),
		    &spec->efs_rem_host.eo_byte[0],
		    MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN);
		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_IP),
		    &spec->efs_loc_host.eo_byte[0],
		    MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN);

		/*
		 * On Medford, filters for encapsulated packets match based on
		 * the ether type and IP protocol in the outer frame.  In
		 * addition we need to fill in the VNI or VSID type field.
		 */
		switch (spec->efs_encap_type) {
		case EFX_TUNNEL_PROTOCOL_NONE:
			break;
		case EFX_TUNNEL_PROTOCOL_VXLAN:
		case EFX_TUNNEL_PROTOCOL_GENEVE:
			MCDI_IN_POPULATE_DWORD_1(req,
			    FILTER_OP_EXT_IN_VNI_OR_VSID,
			    FILTER_OP_EXT_IN_VNI_TYPE,
			    spec->efs_encap_type == EFX_TUNNEL_PROTOCOL_VXLAN ?
				    MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_VXLAN :
				    MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_GENEVE);
			break;
		case EFX_TUNNEL_PROTOCOL_NVGRE:
			MCDI_IN_POPULATE_DWORD_1(req,
			    FILTER_OP_EXT_IN_VNI_OR_VSID,
			    FILTER_OP_EXT_IN_VSID_TYPE,
			    MC_CMD_FILTER_OP_EXT_IN_VSID_TYPE_NVGRE);
			break;
		default:
			EFSYS_ASSERT(0);
			rc = EINVAL;
			goto fail2;
		}

		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_VNI_OR_VSID),
		    spec->efs_vni_or_vsid, EFX_VNI_OR_VSID_LEN);

		memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_IFRM_DST_MAC),
		    spec->efs_ifrm_loc_mac, EFX_MAC_ADDR_LEN);
	}

	/*
	 * Set the "MARK" or "FLAG" action for all packets matching this filter
	 * if necessary (only useful with equal stride packed stream Rx mode
	 * which provide the information in pseudo-header).
	 * These actions require MC_CMD_FILTER_OP_V3_IN msgrequest.
	 */
	if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
	    (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG)) {
		rc = EINVAL;
		goto fail3;
	}
	if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) {
		MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_ACTION,
		    MC_CMD_FILTER_OP_V3_IN_MATCH_ACTION_MARK);
		MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_MARK_VALUE,
		    spec->efs_mark);
	} else if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) {
		MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_ACTION,
		    MC_CMD_FILTER_OP_V3_IN_MATCH_ACTION_FLAG);
	}

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail4;
	}

	if (req.emr_out_length_used < MC_CMD_FILTER_OP_EXT_OUT_LEN) {
		rc = EMSGSIZE;
		goto fail5;
	}

	handle->efh_lo = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_LO);
	handle->efh_hi = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_HI);

	return (0);

fail5:
	EFSYS_PROBE(fail5);
fail4:
	EFSYS_PROBE(fail4);
fail3:
	EFSYS_PROBE(fail3);
fail2:
	EFSYS_PROBE(fail2);
fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);

}
示例#20
0
文件: hunt_phy.c 项目: fengsi/freebsd
	__checkReturn	int
hunt_phy_reconfigure(
	__in		efx_nic_t *enp)
{
	/*
	 * TBD: this is a little different for now (no LED support for Hunt
	 * yet), but ultimately should consider common Siena/Hunt function:
	 * Hunt should be a superset of Siena here (adds 40G)
	 */

	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
	efx_port_t *epp = &(enp->en_port);
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_SET_LINK_IN_LEN,
			    MC_CMD_SET_LINK_OUT_LEN)];
	uint32_t cap_mask;
	unsigned int led_mode;
	unsigned int speed;
	int rc;

	if (~encp->enc_func_flags & EFX_NIC_FUNC_LINKCTRL)
		goto out;

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_LINK;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN;

	cap_mask = epp->ep_adv_cap_mask;
	MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
		PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
		PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
		PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
		PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
		PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
		PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
		PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
		PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
		PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
		PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
	/* Too many fields for for POPULATE macros, so insert this afterwards */
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);

#if EFSYS_OPT_LOOPBACK
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
		    epp->ep_loopback_type);
	switch (epp->ep_loopback_link_mode) {
	case EFX_LINK_100FDX:
		speed = 100;
		break;
	case EFX_LINK_1000FDX:
		speed = 1000;
		break;
	case EFX_LINK_10000FDX:
		speed = 10000;
		break;
	case EFX_LINK_40000FDX:
		speed = 40000;
		break;
	default:
		speed = 0;
	}
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
	speed = 0;
#endif	/* EFSYS_OPT_LOOPBACK */
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);

#if EFSYS_OPT_PHY_FLAGS
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags);
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
#endif	/* EFSYS_OPT_PHY_FLAGS */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail1;
	}

	/* And set the blink mode */
	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_ID_LED;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN;

#if EFSYS_OPT_PHY_LED_CONTROL
	switch (epp->ep_phy_led_mode) {
	case EFX_PHY_LED_DEFAULT:
		led_mode = MC_CMD_LED_DEFAULT;
		break;
	case EFX_PHY_LED_OFF:
		led_mode = MC_CMD_LED_OFF;
		break;
	case EFX_PHY_LED_ON:
		led_mode = MC_CMD_LED_ON;
		break;
	default:
		EFSYS_ASSERT(0);
		led_mode = MC_CMD_LED_DEFAULT;
	}

	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode);
#else
	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
#endif	/* EFSYS_OPT_PHY_LED_CONTROL */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail2;
	}
out:
	return (0);

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

	return (rc);
}
示例#21
0
	__checkReturn	efx_rc_t
siena_phy_reconfigure(
	__in		efx_nic_t *enp)
{
	efx_port_t *epp = &(enp->en_port);
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MAX(MC_CMD_SET_ID_LED_IN_LEN,
				MC_CMD_SET_ID_LED_OUT_LEN),
			    MAX(MC_CMD_SET_LINK_IN_LEN,
				MC_CMD_SET_LINK_OUT_LEN))];
	uint32_t cap_mask;
	unsigned int led_mode;
	unsigned int speed;
	efx_rc_t rc;

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_LINK;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN;

	cap_mask = epp->ep_adv_cap_mask;
	MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
		PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
		PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
		PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
		PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
		PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
		PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
		PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
		PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
		PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
		PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);

#if EFSYS_OPT_LOOPBACK
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
		    epp->ep_loopback_type);
	switch (epp->ep_loopback_link_mode) {
	case EFX_LINK_100FDX:
		speed = 100;
		break;
	case EFX_LINK_1000FDX:
		speed = 1000;
		break;
	case EFX_LINK_10000FDX:
		speed = 10000;
		break;
	default:
		speed = 0;
	}
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
	speed = 0;
#endif	/* EFSYS_OPT_LOOPBACK */
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);

#if EFSYS_OPT_PHY_FLAGS
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags);
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
#endif	/* EFSYS_OPT_PHY_FLAGS */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail1;
	}

	/* And set the blink mode */
	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_ID_LED;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN;

#if EFSYS_OPT_PHY_LED_CONTROL
	switch (epp->ep_phy_led_mode) {
	case EFX_PHY_LED_DEFAULT:
		led_mode = MC_CMD_LED_DEFAULT;
		break;
	case EFX_PHY_LED_OFF:
		led_mode = MC_CMD_LED_OFF;
		break;
	case EFX_PHY_LED_ON:
		led_mode = MC_CMD_LED_ON;
		break;
	default:
		EFSYS_ASSERT(0);
		led_mode = MC_CMD_LED_DEFAULT;
	}

	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode);
#else
	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
#endif	/* EFSYS_OPT_PHY_LED_CONTROL */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail2;
	}

	return (0);

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

	return (rc);
}
示例#22
0
__checkReturn	int
efx_port_init(
    __in		efx_nic_t *enp)
{
    efx_port_t *epp = &(enp->en_port);
    efx_phy_ops_t *epop = epp->ep_epop;
    int rc;

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

    if (enp->en_mod_flags & EFX_MOD_PORT) {
        rc = EINVAL;
        goto fail1;
    }

    enp->en_mod_flags |= EFX_MOD_PORT;

    epp->ep_mac_type = EFX_MAC_INVALID;
    epp->ep_link_mode = EFX_LINK_UNKNOWN;
    epp->ep_mac_poll_needed = B_TRUE;
    epp->ep_mac_drain = B_TRUE;

    /* Configure the MAC */
    if ((rc = efx_mac_select(enp)) != 0)
        goto fail1;

    epp->ep_emop->emo_reconfigure(enp);

    /*
     * Turn on the PHY if available, otherwise reset it, and
     * reconfigure it with the current configuration.
     */
    if (epop->epo_power != NULL) {
        if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
            goto fail2;
    } else {
        if ((rc = epop->epo_reset(enp)) != 0)
            goto fail2;
    }

    EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
    enp->en_reset_flags &= ~EFX_RESET_PHY;

    if ((rc = epop->epo_reconfigure(enp)) != 0)
        goto fail3;

    return (0);

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

    enp->en_mod_flags &= ~EFX_MOD_PORT;

    return (rc);
}
示例#23
0
	__checkReturn	efx_rc_t
efx_tx_init(
	__in		efx_nic_t *enp)
{
	const efx_tx_ops_t *etxop;
	efx_rc_t rc;

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

	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
		rc = EINVAL;
		goto fail1;
	}

	if (enp->en_mod_flags & EFX_MOD_TX) {
		rc = EINVAL;
		goto fail2;
	}

	switch (enp->en_family) {
#if EFSYS_OPT_SIENA
	case EFX_FAMILY_SIENA:
		etxop = &__efx_tx_siena_ops;
		break;
#endif /* EFSYS_OPT_SIENA */

#if EFSYS_OPT_HUNTINGTON
	case EFX_FAMILY_HUNTINGTON:
		etxop = &__efx_tx_hunt_ops;
		break;
#endif /* EFSYS_OPT_HUNTINGTON */

#if EFSYS_OPT_MEDFORD
	case EFX_FAMILY_MEDFORD:
		etxop = &__efx_tx_medford_ops;
		break;
#endif /* EFSYS_OPT_MEDFORD */

	default:
		EFSYS_ASSERT(0);
		rc = ENOTSUP;
		goto fail3;
	}

	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);

	if ((rc = etxop->etxo_init(enp)) != 0)
		goto fail4;

	enp->en_etxop = etxop;
	enp->en_mod_flags |= EFX_MOD_TX;
	return (0);

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

	enp->en_etxop = NULL;
	enp->en_mod_flags &= ~EFX_MOD_TX;
	return (rc);
}
示例#24
0
	__checkReturn	efx_rc_t
efx_mcdi_init(
	__in		efx_nic_t *enp,
	__in		const efx_mcdi_transport_t *emtp)
{
	efx_mcdi_ops_t *emcop;
	efx_rc_t rc;

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

	switch (enp->en_family) {
#if EFSYS_OPT_FALCON
	case EFX_FAMILY_FALCON:
		emcop = NULL;
		emtp = NULL;
		break;
#endif	/* EFSYS_OPT_FALCON */

#if EFSYS_OPT_SIENA
	case EFX_FAMILY_SIENA:
		emcop = (efx_mcdi_ops_t *)&__efx_mcdi_siena_ops;
		break;
#endif	/* EFSYS_OPT_SIENA */

#if EFSYS_OPT_HUNTINGTON
	case EFX_FAMILY_HUNTINGTON:
		emcop = (efx_mcdi_ops_t *)&__efx_mcdi_ef10_ops;
		break;
#endif	/* EFSYS_OPT_HUNTINGTON */

#if EFSYS_OPT_MEDFORD
	case EFX_FAMILY_MEDFORD:
		emcop = (efx_mcdi_ops_t *)&__efx_mcdi_ef10_ops;
		break;
#endif	/* EFSYS_OPT_MEDFORD */

	default:
		EFSYS_ASSERT(0);
		rc = ENOTSUP;
		goto fail1;
	}

	if (enp->en_features & EFX_FEATURE_MCDI_DMA) {
		/* MCDI requires a DMA buffer in host memory */
		if ((emtp == NULL) || (emtp->emt_dma_mem) == NULL) {
			rc = EINVAL;
			goto fail2;
		}
	}
	enp->en_mcdi.em_emtp = emtp;

	if (emcop != NULL && emcop->emco_init != NULL) {
		if ((rc = emcop->emco_init(enp, emtp)) != 0)
			goto fail3;
	}

	enp->en_mcdi.em_emcop = emcop;
	enp->en_mod_flags |= EFX_MOD_MCDI;

	return (0);

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

	enp->en_mcdi.em_emcop = NULL;
	enp->en_mcdi.em_emtp = NULL;
	enp->en_mod_flags &= ~EFX_MOD_MCDI;

	return (rc);
}
示例#25
0
文件: efx_intr.c 项目: fengsi/freebsd
	__checkReturn	int
efx_intr_init(
	__in		efx_nic_t *enp,
	__in		efx_intr_type_t type,
	__in		efsys_mem_t *esmp)
{
	efx_intr_t *eip = &(enp->en_intr);
	efx_intr_ops_t *eiop;
	int rc;

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

	if (enp->en_mod_flags & EFX_MOD_INTR) {
		rc = EINVAL;
		goto fail1;
	}

	eip->ei_esmp = esmp;
	eip->ei_type = type;
	eip->ei_level = 0;

	enp->en_mod_flags |= EFX_MOD_INTR;

	switch (enp->en_family) {
#if EFSYS_OPT_FALCON
	case EFX_FAMILY_FALCON:
		eiop = (efx_intr_ops_t *)&__efx_intr_falcon_ops;
		break;
#endif	/* EFSYS_OPT_FALCON */

#if EFSYS_OPT_SIENA
	case EFX_FAMILY_SIENA:
		eiop = (efx_intr_ops_t *)&__efx_intr_siena_ops;
		break;
#endif	/* EFSYS_OPT_SIENA */

#if EFSYS_OPT_HUNTINGTON
	case EFX_FAMILY_HUNTINGTON:
		eiop = (efx_intr_ops_t *)&__efx_intr_hunt_ops;
		break;
#endif	/* EFSYS_OPT_HUNTINGTON */

	default:
		EFSYS_ASSERT(B_FALSE);
		rc = ENOTSUP;
		goto fail2;
	}

	if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
		goto fail3;

	eip->ei_eiop = eiop;

	return (0);

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

	return (rc);
}
示例#26
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;
	}
示例#27
0
	__checkReturn	int
efx_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;
	int rc;

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

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

	switch (enp->en_family) {
	case EFX_FAMILY_FALCON:
		if (level > EFX_NINTR_FALCON) {
			rc = EINVAL;
			goto fail1;
		}
		break;

	case EFX_FAMILY_SIENA:
		if (level > EFX_NINTR_SIENA) {
			rc = EINVAL;
			goto fail1;
		}
		break;

	default:
		EFSYS_ASSERT(B_FALSE);
		break;
	}

	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, int, rc);

	return (rc);
}
示例#28
0
文件: ef10_phy.c 项目: btw616/dpdk
	__checkReturn	efx_rc_t
ef10_phy_reconfigure(
	__in		efx_nic_t *enp)
{
	efx_port_t *epp = &(enp->en_port);
	efx_mcdi_req_t req;
	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_LINK_IN_LEN,
		MC_CMD_SET_LINK_OUT_LEN);
	uint32_t cap_mask;
#if EFSYS_OPT_PHY_LED_CONTROL
	unsigned int led_mode;
#endif
	unsigned int speed;
	boolean_t supported;
	efx_rc_t rc;

	if ((rc = efx_mcdi_link_control_supported(enp, &supported)) != 0)
		goto fail1;
	if (supported == B_FALSE)
		goto out;

	req.emr_cmd = MC_CMD_SET_LINK;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN;

	cap_mask = epp->ep_adv_cap_mask;
	MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
		PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
		PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
		PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
		PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
		PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
		PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
		PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
		PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
		PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
		PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
	/* Too many fields for for POPULATE macros, so insert this afterwards */
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_25000FDX, (cap_mask >> EFX_PHY_CAP_25000FDX) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_50000FDX, (cap_mask >> EFX_PHY_CAP_50000FDX) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_100000FDX, (cap_mask >> EFX_PHY_CAP_100000FDX) & 0x1);

	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_BASER_FEC, (cap_mask >> EFX_PHY_CAP_BASER_FEC) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_BASER_FEC_REQUESTED,
	    (cap_mask >> EFX_PHY_CAP_BASER_FEC_REQUESTED) & 0x1);

	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_RS_FEC, (cap_mask >> EFX_PHY_CAP_RS_FEC) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_RS_FEC_REQUESTED,
	    (cap_mask >> EFX_PHY_CAP_RS_FEC_REQUESTED) & 0x1);

	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_25G_BASER_FEC,
	    (cap_mask >> EFX_PHY_CAP_25G_BASER_FEC) & 0x1);
	MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
	    PHY_CAP_25G_BASER_FEC_REQUESTED,
	    (cap_mask >> EFX_PHY_CAP_25G_BASER_FEC_REQUESTED) & 0x1);

#if EFSYS_OPT_LOOPBACK
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
		    epp->ep_loopback_type);
	switch (epp->ep_loopback_link_mode) {
	case EFX_LINK_100FDX:
		speed = 100;
		break;
	case EFX_LINK_1000FDX:
		speed = 1000;
		break;
	case EFX_LINK_10000FDX:
		speed = 10000;
		break;
	case EFX_LINK_25000FDX:
		speed = 25000;
		break;
	case EFX_LINK_40000FDX:
		speed = 40000;
		break;
	case EFX_LINK_50000FDX:
		speed = 50000;
		break;
	case EFX_LINK_100000FDX:
		speed = 100000;
		break;
	default:
		speed = 0;
	}
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
	speed = 0;
#endif	/* EFSYS_OPT_LOOPBACK */
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);

#if EFSYS_OPT_PHY_FLAGS
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags);
#else
	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
#endif	/* EFSYS_OPT_PHY_FLAGS */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail2;
	}

	/* And set the blink mode */
	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_ID_LED;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN;

#if EFSYS_OPT_PHY_LED_CONTROL
	switch (epp->ep_phy_led_mode) {
	case EFX_PHY_LED_DEFAULT:
		led_mode = MC_CMD_LED_DEFAULT;
		break;
	case EFX_PHY_LED_OFF:
		led_mode = MC_CMD_LED_OFF;
		break;
	case EFX_PHY_LED_ON:
		led_mode = MC_CMD_LED_ON;
		break;
	default:
		EFSYS_ASSERT(0);
		led_mode = MC_CMD_LED_DEFAULT;
	}

	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode);
#else
	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
#endif	/* EFSYS_OPT_PHY_LED_CONTROL */

	efx_mcdi_execute(enp, &req);

	if (req.emr_rc != 0) {
		rc = req.emr_rc;
		goto fail3;
	}
out:
	return (0);

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

	return (rc);
}
示例#29
0
	__checkReturn	efx_rc_t
efx_mon_init(
	__in		efx_nic_t *enp)
{
	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
	efx_mon_t *emp = &(enp->en_mon);
	efx_mon_ops_t *emop;
	efx_rc_t rc;

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

	if (enp->en_mod_flags & EFX_MOD_MON) {
		rc = EINVAL;
		goto fail1;
	}

	enp->en_mod_flags |= EFX_MOD_MON;

	emp->em_type = encp->enc_mon_type;

	EFSYS_ASSERT(encp->enc_mon_type != EFX_MON_INVALID);
	EFSYS_ASSERT3U(emp->em_type, <, EFX_MON_NTYPES);
	if ((emop = (efx_mon_ops_t *)__efx_mon_ops[emp->em_type]) == NULL) {
		rc = ENOTSUP;
		goto fail2;
	}

	if (emop->emo_reset != NULL) {
		if ((rc = emop->emo_reset(enp)) != 0)
			goto fail3;
	}

	if (emop->emo_reconfigure != NULL) {
		if ((rc = emop->emo_reconfigure(enp)) != 0)
			goto fail4;
	}

	emp->em_emop = emop;
	return (0);

fail4:
	EFSYS_PROBE(fail5);

	if (emop->emo_reset != NULL)
		(void) emop->emo_reset(enp);

fail3:
	EFSYS_PROBE(fail4);
fail2:
	EFSYS_PROBE(fail3);

	emp->em_type = EFX_MON_INVALID;

	enp->en_mod_flags &= ~EFX_MOD_MON;

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
示例#30
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);
}