Ejemplo n.º 1
0
static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
	unsigned int max_frame_len;
	efx_oword_t reg;
	bool rx_fc = !!(efx->link_fc & EFX_FC_RX);

	
	EFX_POPULATE_DWORD_3(reg,
			     XM_RX_JUMBO_MODE, 1,
			     XM_TX_STAT_EN, 1,
			     XM_RX_STAT_EN, 1);
	falcon_write(efx, &reg, XM_GLB_CFG_REG);

	
	EFX_POPULATE_DWORD_6(reg,
			     XM_TXEN, 1,
			     XM_TX_PRMBL, 1,
			     XM_AUTO_PAD, 1,
			     XM_TXCRC, 1,
			     XM_FCNTL, 1,
			     XM_IPG, 0x3);
	falcon_write(efx, &reg, XM_TX_CFG_REG);

	
	EFX_POPULATE_DWORD_5(reg,
			     XM_RXEN, 1,
			     XM_AUTO_DEPAD, 0,
			     XM_ACPT_ALL_MCAST, 1,
			     XM_ACPT_ALL_UCAST, efx->promiscuous,
			     XM_PASS_CRC_ERR, 1);
	falcon_write(efx, &reg, XM_RX_CFG_REG);

	
	max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
	EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len);
	falcon_write(efx, &reg, XM_RX_PARAM_REG);
	EFX_POPULATE_DWORD_2(reg,
			     XM_MAX_TX_FRM_SIZE, max_frame_len,
			     XM_TX_JUMBO_MODE, 1);
	falcon_write(efx, &reg, XM_TX_PARAM_REG);

	EFX_POPULATE_DWORD_2(reg,
			     XM_PAUSE_TIME, 0xfffe, 
			     XM_DIS_FCNTL, !rx_fc);
	falcon_write(efx, &reg, XM_FC_REG);

	
	EFX_POPULATE_DWORD_4(reg,
			     XM_ADR_0, efx->net_dev->dev_addr[0],
			     XM_ADR_1, efx->net_dev->dev_addr[1],
			     XM_ADR_2, efx->net_dev->dev_addr[2],
			     XM_ADR_3, efx->net_dev->dev_addr[3]);
	falcon_write(efx, &reg, XM_ADR_LO_REG);
	EFX_POPULATE_DWORD_2(reg,
			     XM_ADR_4, efx->net_dev->dev_addr[4],
			     XM_ADR_5, efx->net_dev->dev_addr[5]);
	falcon_write(efx, &reg, XM_ADR_HI_REG);
}
Ejemplo n.º 2
0
static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
			    const u8 *inbuf, size_t inlen)
{
	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
	unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
	unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
	unsigned int i;
	efx_dword_t hdr;
	u32 xflags, seqno;

	BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
	BUG_ON(inlen & 3 || inlen >= 0x100);

	seqno = mcdi->seqno & SEQ_MASK;
	xflags = 0;
	if (mcdi->mode == MCDI_MODE_EVENTS)
		xflags |= MCDI_HEADER_XFLAGS_EVREQ;

	EFX_POPULATE_DWORD_6(hdr,
			     MCDI_HEADER_RESPONSE, 0,
			     MCDI_HEADER_RESYNC, 1,
			     MCDI_HEADER_CODE, cmd,
			     MCDI_HEADER_DATALEN, inlen,
			     MCDI_HEADER_SEQ, seqno,
			     MCDI_HEADER_XFLAGS, xflags);

	efx_writed(efx, &hdr, pdu);

	for (i = 0; i < inlen; i += 4) {
		_efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i);
		/* use wmb() within loop to inhibit write combining */
		wmb();
	}

	/* ring the doorbell with a distinctive value */
	_efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
	wmb();
}
Ejemplo n.º 3
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);
}