drivers/infiniband/sw/rxe/rxe_recv.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/sw/rxe/rxe_recv.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/sw/rxe/rxe_recv.c
Extension
.c
Size
8506 bytes
Lines
374
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(qp_state(qp) < IB_QPS_RTR)) {
			spin_unlock_irqrestore(&qp->state_lock, flags);
			return -EINVAL;
		}
	} else {
		if (unlikely(qp_state(qp) < IB_QPS_RTS)) {
			spin_unlock_irqrestore(&qp->state_lock, flags);
			return -EINVAL;
		}
	}
	spin_unlock_irqrestore(&qp->state_lock, flags);

	return 0;
}

static void set_bad_pkey_cntr(struct rxe_port *port)
{
	spin_lock_bh(&port->port_lock);
	port->attr.bad_pkey_cntr = min((u32)0xffff,
				       port->attr.bad_pkey_cntr + 1);
	spin_unlock_bh(&port->port_lock);
}

static void set_qkey_viol_cntr(struct rxe_port *port)
{
	spin_lock_bh(&port->port_lock);
	port->attr.qkey_viol_cntr = min((u32)0xffff,
					port->attr.qkey_viol_cntr + 1);
	spin_unlock_bh(&port->port_lock);
}

static int check_keys(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
		      u32 qpn, struct rxe_qp *qp)
{
	struct rxe_port *port = &rxe->port;
	u16 pkey = bth_pkey(pkt);

	pkt->pkey_index = 0;

	if (!pkey_match(pkey, IB_DEFAULT_PKEY_FULL)) {
		set_bad_pkey_cntr(port);
		return -EINVAL;
	}

	if (qp_type(qp) == IB_QPT_UD || qp_type(qp) == IB_QPT_GSI) {
		u32 qkey = (qpn == 1) ? GSI_QKEY : qp->attr.qkey;

		if (unlikely(deth_qkey(pkt) != qkey)) {
			set_qkey_viol_cntr(port);
			return -EINVAL;
		}
	}

	return 0;
}

static int check_addr(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
		      struct rxe_qp *qp)
{
	struct sk_buff *skb = PKT_TO_SKB(pkt);

	if (qp_type(qp) != IB_QPT_RC && qp_type(qp) != IB_QPT_UC)
		return 0;

	if (unlikely(pkt->port_num != qp->attr.port_num))
		return -EINVAL;

	if (skb->protocol == htons(ETH_P_IP)) {
		struct in_addr *saddr =
			&qp->pri_av.sgid_addr._sockaddr_in.sin_addr;
		struct in_addr *daddr =
			&qp->pri_av.dgid_addr._sockaddr_in.sin_addr;

		if ((ip_hdr(skb)->daddr != saddr->s_addr) ||
		    (ip_hdr(skb)->saddr != daddr->s_addr))
			return -EINVAL;

	} else if (skb->protocol == htons(ETH_P_IPV6)) {
		struct in6_addr *saddr =
			&qp->pri_av.sgid_addr._sockaddr_in6.sin6_addr;
		struct in6_addr *daddr =
			&qp->pri_av.dgid_addr._sockaddr_in6.sin6_addr;

		if (memcmp(&ipv6_hdr(skb)->daddr, saddr, sizeof(*saddr)) ||
		    memcmp(&ipv6_hdr(skb)->saddr, daddr, sizeof(*daddr)))
			return -EINVAL;
	}

	return 0;
}

Annotation

Implementation Notes