/* * Set up an L2T entry and send any packets waiting in the arp queue. The * supplied skb is used for the CPL_L2T_WRITE_REQ. Must be called with the * entry locked. */ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, struct l2t_entry *e) { struct cpl_l2t_write_req *req; if (!skb) { skb = alloc_skb(sizeof(*req), GFP_ATOMIC); if (!skb) return -ENOMEM; } req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req)); req->wr.wr_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 & VLAN_VID_MASK) | V_L2T_W_PRIO(vlan_prio(e))); memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac)); memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); skb->priority = CPL_PRIORITY_CONTROL; cxgb3_ofld_send(dev, skb); while (e->arpq_head) { skb = e->arpq_head; e->arpq_head = skb->next; skb->next = NULL; cxgb3_ofld_send(dev, skb); } e->arpq_tail = NULL; e->state = L2T_STATE_VALID; 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); }