Commit adddc32d authored by Sowmini Varadhan's avatar Sowmini Varadhan Committed by David S. Miller

sunvnet: Do not spin in an infinite loop when vio_ldc_send() returns EAGAIN

ldc_rx -> vnet_rx -> .. -> vnet_walk_rx->vnet_send_ack should not
spin into an infinite loop waiting  EAGAIN to lift.

The sender could have sent us a burst, and gone to lunch without
doing any more ldc_read()'s. That should not cause the receiver to
loop infinitely till soft-lockup kicks in.

Similarly __vnet_tx_trigger should only loop on EAGAIN a finite
number of times. The caller (vnet_start_xmit()) already has code
to reset the dring state and bail on errors from __vnet_tx_trigger
Signed-off-by: default avatarSowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: default avatarRaghuram Kothakota <raghuram.kothakota@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1f6394e3
...@@ -32,6 +32,11 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver"); ...@@ -32,6 +32,11 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION); MODULE_VERSION(DRV_MODULE_VERSION);
/* Heuristic for the number of times to exponentially backoff and
* retry sending an LDC trigger when EAGAIN is encountered
*/
#define VNET_MAX_RETRIES 10
/* Ordered from largest major to lowest */ /* Ordered from largest major to lowest */
static struct vio_version vnet_versions[] = { static struct vio_version vnet_versions[] = {
{ .major = 1, .minor = 0 }, { .major = 1, .minor = 0 },
...@@ -260,6 +265,7 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr, ...@@ -260,6 +265,7 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
.state = vio_dring_state, .state = vio_dring_state,
}; };
int err, delay; int err, delay;
int retries = 0;
hdr.seq = dr->snd_nxt; hdr.seq = dr->snd_nxt;
delay = 1; delay = 1;
...@@ -272,6 +278,13 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr, ...@@ -272,6 +278,13 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
udelay(delay); udelay(delay);
if ((delay <<= 1) > 128) if ((delay <<= 1) > 128)
delay = 128; delay = 128;
if (retries++ > VNET_MAX_RETRIES) {
pr_info("ECONNRESET %x:%x:%x:%x:%x:%x\n",
port->raddr[0], port->raddr[1],
port->raddr[2], port->raddr[3],
port->raddr[4], port->raddr[5]);
err = -ECONNRESET;
}
} while (err == -EAGAIN); } while (err == -EAGAIN);
return err; return err;
...@@ -593,6 +606,7 @@ static int __vnet_tx_trigger(struct vnet_port *port) ...@@ -593,6 +606,7 @@ static int __vnet_tx_trigger(struct vnet_port *port)
.end_idx = (u32) -1, .end_idx = (u32) -1,
}; };
int err, delay; int err, delay;
int retries = 0;
hdr.seq = dr->snd_nxt; hdr.seq = dr->snd_nxt;
delay = 1; delay = 1;
...@@ -605,6 +619,8 @@ static int __vnet_tx_trigger(struct vnet_port *port) ...@@ -605,6 +619,8 @@ static int __vnet_tx_trigger(struct vnet_port *port)
udelay(delay); udelay(delay);
if ((delay <<= 1) > 128) if ((delay <<= 1) > 128)
delay = 128; delay = 128;
if (retries++ > VNET_MAX_RETRIES)
break;
} while (err == -EAGAIN); } while (err == -EAGAIN);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment