Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
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);
}