summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/viohs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-18 10:23:37 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-18 10:23:37 -0700
commit31bdc5dc7666aa2fe04c626cea30fe3c20cf481c (patch)
treea1a78a39379e081e9982c3273a71b4e93e8c1fd0 /arch/sparc64/kernel/viohs.c
parent5cc97bf2d8eaa6cab60727c3eba3e85e29062669 (diff)
parenta5f8967e171a6fa27da8e6d06d3ef85f7fed43c1 (diff)
downloadlinux-31bdc5dc7666aa2fe04c626cea30fe3c20cf481c.tar.bz2
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Set vio->desc_buf to NULL after freeing. [SPARC]: Mark sparc and sparc64 as not having virt_to_bus [SPARC64]: Fix reset handling in VNET driver. [SPARC64]: Handle reset events in vio_link_state_change(). [SPARC64]: Handle LDC resets properly in domain-services driver. [SPARC64]: Massively simplify VIO device layer and support hot add/remove. [SPARC64]: Simplify VNET probing. [SPARC64]: Simplify VDC device probing. [SPARC64]: Add basic infrastructure for MD add/remove notification.
Diffstat (limited to 'arch/sparc64/kernel/viohs.c')
-rw-r--r--arch/sparc64/kernel/viohs.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
index 15613add45d1..09126fc338ba 100644
--- a/arch/sparc64/kernel/viohs.c
+++ b/arch/sparc64/kernel/viohs.c
@@ -78,6 +78,24 @@ 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);
+ vio->desc_buf = NULL;
+
+ 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 +116,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 +424,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;