static int write_smt_entry(struct adapter *sc, int idx) { struct port_info *pi = &sc->port[idx]; struct cpl_smt_write_req *req; struct mbuf *m; m = M_GETHDR_OFLD(0, CPL_PRIORITY_CONTROL, req); if (m == NULL) { log(LOG_ERR, "%s: no mbuf, can't write SMT entry for %d\n", __func__, idx); return (ENOMEM); } req->wr.wrh_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, idx)); req->mtu_idx = NMTUS - 1; /* should be 0 but there's a T3 bug */ req->iff = idx; memset(req->src_mac1, 0, sizeof(req->src_mac1)); memcpy(req->src_mac0, pi->hw_addr, ETHER_ADDR_LEN); t3_offload_tx(sc, m); return (0); }
/* * Set up an L2T entry and send any packets waiting in the arp queue. Must be * called with the entry locked. */ static int setup_l2e_send_pending(struct adapter *sc, struct l2t_entry *e) { struct mbuf *m; struct cpl_l2t_write_req *req; struct port_info *pi = &sc->port[e->smt_idx]; /* smt_idx is port_id */ mtx_assert(&e->lock, MA_OWNED); m = M_GETHDR_OFLD(pi->first_qset, CPL_PRIORITY_CONTROL, req); if (m == NULL) { log(LOG_ERR, "%s: no mbuf, can't setup L2 entry at index %d\n", __func__, e->idx); return (ENOMEM); } req->wr.wrh_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx)); req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) | V_L2T_W_VLAN(e->vlan & EVL_VLID_MASK) | V_L2T_W_PRIO(EVL_PRIOFTAG(e->vlan))); memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); t3_offload_tx(sc, m); /* * XXX: We used pi->first_qset to send the L2T_WRITE_REQ. If any mbuf * on the arpq is going out via another queue set associated with the * port then it has a bad race with the L2T_WRITE_REQ. Ideally we * should wait till the reply to the write before draining the arpq. */ while (e->arpq_head) { m = e->arpq_head; e->arpq_head = m->m_next; m->m_next = NULL; t3_offload_tx(sc, m); } e->arpq_tail = NULL; return (0); }