summary refs log tree commit diff
path: root/arch/sparc64
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-18 00:06:22 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-18 01:20:13 -0700
commita4cd184503f448dda346d2338aa61cb560cc1b14 (patch)
treee9df02626899ca7ac0368ab06f6f1f13c9bf5226 /arch/sparc64
parent8a2950cce6c8fa29bcbf6a3b33a63e0e68337f0e (diff)
downloadlinux-a4cd184503f448dda346d2338aa61cb560cc1b14.tar.gz
[SPARC64]: Handle reset events in vio_link_state_change().
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/viohs.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
index 15613add45d1..8eb381fa0f28 100644
--- a/arch/sparc64/kernel/viohs.c
+++ b/arch/sparc64/kernel/viohs.c
@@ -78,6 +78,23 @@ static int start_handshake(struct vio_driver_state *vio)
 	return 0;
 }
 
+static void flush_rx_dring(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr;
+	u64 ident;
+
+	BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG));
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+	ident = dr->ident;
+
+	BUG_ON(!vio->desc_buf);
+	kfree(vio->desc_buf);
+
+	memset(dr, 0, sizeof(*dr));
+	dr->ident = ident;
+}
+
 void vio_link_state_change(struct vio_driver_state *vio, int event)
 {
 	if (event == LDC_EVENT_UP) {
@@ -98,6 +115,16 @@ void vio_link_state_change(struct vio_driver_state *vio, int event)
 			break;
 		}
 		start_handshake(vio);
+	} else if (event == LDC_EVENT_RESET) {
+		vio->hs_state = VIO_HS_INVALID;
+
+		if (vio->dr_state & VIO_DR_STATE_RXREG)
+			flush_rx_dring(vio);
+
+		vio->dr_state = 0x00;
+		memset(&vio->ver, 0, sizeof(vio->ver));
+
+		ldc_disconnect(vio->lp);
 	}
 }
 EXPORT_SYMBOL(vio_link_state_change);
@@ -396,6 +423,8 @@ static int process_dreg_info(struct vio_driver_state *vio,
 	if (vio->dr_state & VIO_DR_STATE_RXREG)
 		goto send_nack;
 
+	BUG_ON(vio->desc_buf);
+
 	vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
 	if (!vio->desc_buf)
 		goto send_nack;