__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_oword_t oword; 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; } enp->en_mod_flags |= EFX_MOD_INTR; eip->ei_type = type; eip->ei_esmp = esmp; /* * bug17213 workaround. * * Under legacy interrupts, don't share a level between fatal * interrupts and event queue interrupts. Under MSI-X, they * must share, or we won't get an interrupt. */ if (enp->en_family == EFX_FAMILY_SIENA && eip->ei_type == EFX_INTR_LINE) eip->ei_level = 0x1f; else eip->ei_level = 0; /* Enable all the genuinely fatal interrupts */ EFX_SET_OWORD(oword); EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0); EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0); EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0); if (enp->en_family >= EFX_FAMILY_SIENA) EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0); EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword); /* Set up the interrupt address register */ EFX_POPULATE_OWORD_3(oword, FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0, FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff, FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32); EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); return (0); fail1: EFSYS_PROBE1(fail1, int, rc); return (rc); }
static __checkReturn efx_rc_t siena_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_oword_t oword; /* * bug17213 workaround. * * Under legacy interrupts, don't share a level between fatal * interrupts and event queue interrupts. Under MSI-X, they * must share, or we won't get an interrupt. */ if (enp->en_family == EFX_FAMILY_SIENA && eip->ei_type == EFX_INTR_LINE) eip->ei_level = 0x1f; else eip->ei_level = 0; /* Enable all the genuinely fatal interrupts */ EFX_SET_OWORD(oword); EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0); EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0); EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0); if (enp->en_family >= EFX_FAMILY_SIENA) EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0); EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword); /* Set up the interrupt address register */ EFX_POPULATE_OWORD_3(oword, FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0, FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff, FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32); EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); return (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); }