Exemplo n.º 1
0
static	__checkReturn	efx_rc_t
efx_mcdi_filter_op_delete(
	__in		efx_nic_t *enp,
	__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_EXT_IN_LEN,
		MC_CMD_FILTER_OP_EXT_OUT_LEN);
	efx_rc_t rc;

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

	switch (filter_op) {
	case MC_CMD_FILTER_OP_IN_OP_REMOVE:
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP,
		    MC_CMD_FILTER_OP_IN_OP_REMOVE);
		break;
	case MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE:
		MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP,
		    MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE);
		break;
	default:
		EFSYS_ASSERT(0);
		rc = EINVAL;
		goto fail1;
	}

	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);

	efx_mcdi_execute_quiet(enp, &req);

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

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

	return (0);

fail3:
	EFSYS_PROBE(fail3);

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

	return (rc);
}
Exemplo n.º 2
0
	__checkReturn	efx_rc_t
ef10_phy_verify(
	__in		efx_nic_t *enp)
{
	efx_mcdi_req_t req;
	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PHY_STATE_IN_LEN,
		MC_CMD_GET_PHY_STATE_OUT_LEN);
	uint32_t state;
	efx_rc_t rc;

	req.emr_cmd = MC_CMD_GET_PHY_STATE;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_GET_PHY_STATE_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_GET_PHY_STATE_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_PHY_STATE_OUT_LEN) {
		rc = EMSGSIZE;
		goto fail2;
	}

	state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE);
	if (state != MC_CMD_PHY_STATE_OK) {
		if (state != MC_CMD_PHY_STATE_ZOMBIE)
			EFSYS_PROBE1(mc_pcol_error, int, state);
		rc = ENOTACTIVE;
		goto fail3;
	}

	return (0);

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

	return (rc);
}
Exemplo n.º 3
0
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);

}
Exemplo n.º 4
0
	__checkReturn	efx_rc_t
siena_mac_reconfigure(
	__in		efx_nic_t *enp)
{
	efx_port_t *epp = &(enp->en_port);
	efx_oword_t multicast_hash[2];
	efx_mcdi_req_t req;
	EFX_MCDI_DECLARE_BUF(payload,
		MAX(MC_CMD_SET_MAC_IN_LEN, MC_CMD_SET_MCAST_HASH_IN_LEN),
		MAX(MC_CMD_SET_MAC_OUT_LEN, MC_CMD_SET_MCAST_HASH_OUT_LEN));

	unsigned int fcntl;
	efx_rc_t rc;

	req.emr_cmd = MC_CMD_SET_MAC;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;

	MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
	MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
	EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
			    epp->ep_mac_addr);
	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
			    SET_MAC_IN_REJECT_UNCST, !epp->ep_all_unicst,
			    SET_MAC_IN_REJECT_BRDCST, !epp->ep_brdcst);

	if (epp->ep_fcntl_autoneg)
		/* efx_fcntl_set() has already set the phy capabilities */
		fcntl = MC_CMD_FCNTL_AUTO;
	else if (epp->ep_fcntl & EFX_FCNTL_RESPOND)
		fcntl = (epp->ep_fcntl & EFX_FCNTL_GENERATE)
			? MC_CMD_FCNTL_BIDIR
			: MC_CMD_FCNTL_RESPOND;
	else
		fcntl = MC_CMD_FCNTL_OFF;

	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, fcntl);

	efx_mcdi_execute(enp, &req);

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

	/* Push multicast hash */

	if (epp->ep_all_mulcst) {
		/* A hash matching all multicast is all 1s */
		EFX_SET_OWORD(multicast_hash[0]);
		EFX_SET_OWORD(multicast_hash[1]);
	} else if (epp->ep_mulcst) {
		/* Use the hash set by the multicast list */
		multicast_hash[0] = epp->ep_multicst_hash[0];
		multicast_hash[1] = epp->ep_multicst_hash[1];
	} else {
		/* A hash matching no traffic is simply 0 */
		EFX_ZERO_OWORD(multicast_hash[0]);
		EFX_ZERO_OWORD(multicast_hash[1]);
	}

	/*
	 * Broadcast packets go through the multicast hash filter.
	 * The IEEE 802.3 CRC32 of the broadcast address is 0xbe2612ff
	 * so we always add bit 0xff to the mask (bit 0x7f in the
	 * second octword).
	 */
	if (epp->ep_brdcst) {
		/*
		 * NOTE: due to constant folding, some of this evaluates
		 * to null expressions, giving E_EXPR_NULL_EFFECT during
		 * lint on Illumos.  No good way to fix this without
		 * explicit coding the individual word/bit setting.
		 * So just suppress lint for this one line.
		 */
		/* LINTED */
		EFX_SET_OWORD_BIT(multicast_hash[1], 0x7f);
	}

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_MCAST_HASH;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_MCAST_HASH_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_MCAST_HASH_OUT_LEN;

	memcpy(MCDI_IN2(req, uint8_t, SET_MCAST_HASH_IN_HASH0),
	    multicast_hash, sizeof (multicast_hash));

	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);
}
Exemplo n.º 5
0
	__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);
}
Exemplo n.º 6
0
	__checkReturn	efx_rc_t
ef10_phy_get_link(
	__in		efx_nic_t *enp,
	__out		ef10_link_state_t *elsp)
{
	efx_mcdi_req_t req;
	uint32_t fec;
	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LINK_IN_LEN,
		MC_CMD_GET_LINK_OUT_V2_LEN);
	efx_rc_t rc;

	req.emr_cmd = MC_CMD_GET_LINK;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_GET_LINK_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_GET_LINK_OUT_V2_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_LINK_OUT_LEN) {
		rc = EMSGSIZE;
		goto fail2;
	}

	mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
			    &elsp->epls.epls_adv_cap_mask);
	mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
			    &elsp->epls.epls_lp_cap_mask);

	if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_V2_LEN)
		fec = MC_CMD_FEC_NONE;
	else
		fec = MCDI_OUT_DWORD(req, GET_LINK_OUT_V2_FEC_TYPE);

	mcdi_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
			    MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED),
			    MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
			    fec, &elsp->epls.epls_link_mode,
			    &elsp->epls.epls_fcntl, &elsp->epls.epls_fec);

	if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_V2_LEN) {
		elsp->epls.epls_ld_cap_mask = 0;
	} else {
		mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_V2_LD_CAP),
				    &elsp->epls.epls_ld_cap_mask);
	}


#if EFSYS_OPT_LOOPBACK
	/*
	 * MC_CMD_LOOPBACK and EFX_LOOPBACK names are equivalent, so use the
	 * MCDI value directly. Agreement is checked in efx_loopback_mask().
	 */
	elsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
#endif	/* EFSYS_OPT_LOOPBACK */

	elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;

	return (0);

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

	return (rc);
}