Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d21385fa authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sunvnet-next'



Sowmini Varadhan says:

====================
sunvnet: edge-case/race-conditions bug fixes

This patch series contains fixes for race-conditions in sunvnet,
that can encountered when there is a difference in latency between
producer and consumer.

Patch 1 addresses a case when the STOPPED LDC ack from a peer is
processed before vnet_start_xmit can finish updating the dr->prod
state.

Patch 2 fixes the edge-case when outgoing data and incoming
stopped-ack cross each other in flight.

Patch 3 adds a missing rcu_read_unlock(), found by code-inspection.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6f6e741f df20286a
Loading
Loading
Loading
Loading
+10 −6
Original line number Original line Diff line number Diff line
@@ -559,18 +559,20 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf)
		return 0;
		return 0;


	end = pkt->end_idx;
	end = pkt->end_idx;
	if (unlikely(!idx_is_pending(dr, end)))
		return 0;

	vp = port->vp;
	vp = port->vp;
	dev = vp->dev;
	dev = vp->dev;
	netif_tx_lock(dev);
	if (unlikely(!idx_is_pending(dr, end))) {
		netif_tx_unlock(dev);
		return 0;
	}

	/* sync for race conditions with vnet_start_xmit() and tell xmit it
	/* sync for race conditions with vnet_start_xmit() and tell xmit it
	 * is time to send a trigger.
	 * is time to send a trigger.
	 */
	 */
	netif_tx_lock(dev);
	dr->cons = next_idx(end, dr);
	dr->cons = next_idx(end, dr);
	desc = vio_dring_entry(dr, dr->cons);
	desc = vio_dring_entry(dr, dr->cons);
	if (desc->hdr.state == VIO_DESC_READY && port->start_cons) {
	if (desc->hdr.state == VIO_DESC_READY && !port->start_cons) {
		/* vnet_start_xmit() just populated this dring but missed
		/* vnet_start_xmit() just populated this dring but missed
		 * sending the "start" LDC message to the consumer.
		 * sending the "start" LDC message to the consumer.
		 * Send a "start" trigger on its behalf.
		 * Send a "start" trigger on its behalf.
@@ -979,8 +981,10 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)


	rcu_read_lock();
	rcu_read_lock();
	port = __tx_port_find(vp, skb);
	port = __tx_port_find(vp, skb);
	if (unlikely(!port))
	if (unlikely(!port)) {
		rcu_read_unlock();
		goto out_dropped;
		goto out_dropped;
	}


	if (skb->len > port->rmtu) {
	if (skb->len > port->rmtu) {
		unsigned long localmtu = port->rmtu - ETH_HLEN;
		unsigned long localmtu = port->rmtu - ETH_HLEN;