Example #1
0
static	__checkReturn		efx_rc_t
efx_mcdi_vadaptor_alloc(
	__in			efx_nic_t *enp,
	__in			uint32_t port_id)
{
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN,
			    MC_CMD_VADAPTOR_ALLOC_OUT_LEN)];
	efx_rc_t rc;

	EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;

	MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
	MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
	    VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
	    enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);

	efx_mcdi_execute(enp, &req);

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

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
Example #2
0
static	__checkReturn	efx_rc_t
efx_mcdi_mtu_set(
	__in		efx_nic_t *enp,
	__in		uint32_t mtu)
{
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_SET_MAC_EXT_IN_LEN,
			    MC_CMD_SET_MAC_OUT_LEN)];
	efx_rc_t rc;

	(void) memset(payload, 0, sizeof (payload));
	req.emr_cmd = MC_CMD_SET_MAC;
	req.emr_in_buf = payload;
	req.emr_in_length = MC_CMD_SET_MAC_EXT_IN_LEN;
	req.emr_out_buf = payload;
	req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;

	/* Only configure the MTU in this call to MC_CMD_SET_MAC */
	MCDI_IN_SET_DWORD(req, SET_MAC_EXT_IN_MTU, mtu);
	MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_EXT_IN_CONTROL,
			    SET_MAC_EXT_IN_CFG_MTU, 1);

	efx_mcdi_execute(enp, &req);

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

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}
Example #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);

}
Example #4
0
__checkReturn	efx_rc_t
ef10_mac_reconfigure(
	__in		efx_nic_t *enp)
{
	efx_port_t *epp = &(enp->en_port);
	efx_mcdi_req_t req;
	uint8_t payload[MAX(MC_CMD_SET_MAC_IN_LEN,
			    MC_CMD_SET_MAC_OUT_LEN)];
	efx_rc_t rc;

	(void) memset(payload, 0, sizeof (payload));
	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);

	/*
	 * Note: The Huntington MAC does not support REJECT_BRDCST.
	 * The REJECT_UNCST flag will also prevent multicast traffic
	 * from reaching the filters. As Huntington filters drop any
	 * traffic that does not match a filter it is ok to leave the
	 * MAC running in promiscuous mode. See bug41141.
	 *
	 * FIXME: Does REJECT_UNCST behave the same way on Medford?
	 */
	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
				    SET_MAC_IN_REJECT_UNCST, 0,
				    SET_MAC_IN_REJECT_BRDCST, 0);

	/*
	 * Flow control, whether it is auto-negotiated or not,
	 * is set via the PHY advertised capabilities.  When set to
	 * automatic the MAC will use the PHY settings to determine
	 * the flow control settings.
	 */
	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, MC_CMD_FCNTL_AUTO);

	/* Do not include the Ethernet frame checksum in RX packets */
	MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_IN_FLAGS,
				    SET_MAC_IN_FLAG_INCLUDE_FCS, 0);

	efx_mcdi_execute_quiet(enp, &req);

	if (req.emr_rc != 0) {
		/*
		 * Unprivileged functions cannot control link state,
		 * but still need to configure filters.
		 */
		if (req.emr_rc != EACCES) {
			rc = req.emr_rc;
			goto fail1;
		}
	}

	/*
	 * Apply the filters for the MAC configuration.
	 * If the NIC isn't ready to accept filters this may
	 * return success without setting anything.
	 */
	rc = efx_filter_reconfigure(enp, epp->ep_mac_addr,
				    epp->ep_all_unicst, epp->ep_mulcst,
				    epp->ep_all_mulcst, epp->ep_brdcst,
				    epp->ep_mulcst_addr_list,
				    epp->ep_mulcst_addr_count);

	return (0);

fail1:
	EFSYS_PROBE1(fail1, efx_rc_t, rc);

	return (rc);
}