Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 03 May 2004 08:09:22 -0600
From:      Scott Long <scottl@freebsd.org>
To:        freebsd-stable@freebsd.org
Cc:        Paul Saab <ps@freebsd.org>
Subject:   [PATCH] Fix for 3ware driver
Message-ID:  <40965292.2040608@freebsd.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------030007050308030708030905
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

All,

Release testing has shown several recent problems with the 3ware (twe) 
driver.  Attached is a patch that appears to fix these problems.  I
would appreciate as much testing as possible before I commit so that I
can be sure that all of the problems are caught and fixed correctly.
The patch applies to both RELENG_4_10 and RELENG_4 branches.  Symptoms
of the problems included i/o hangs under heavy load and filesystem
corruption.

Thanks,

Scott

--------------030007050308030708030905
Content-Type: text/plain;
 name="twe.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="twe.diff"

Index: twe.c
===================================================================
RCS file: /mnt/ncvs/src/sys/dev/twe/twe.c,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 twe.c
--- twe.c	7 Apr 2004 22:18:00 -0000	1.1.2.8
+++ twe.c	3 May 2004 01:03:37 -0000
@@ -393,14 +393,14 @@
 
 	/* build a command from an outstanding bio */
 	if (tr == NULL) {
-	    
-	    /* see if there's work to be done */
-	    if ((bp = twe_dequeue_bio(sc)) == NULL)
-		break;
 
 	    /* get a command to handle the bio with */
-	    if (twe_get_request(sc, &tr)) {
-		twe_enqueue_bio(sc, bp);	/* failed, put the bio back */
+	    if (twe_get_request(sc, &tr))
+		break;
+
+	    /* see if there's work to be done */
+	    if ((bp = twe_dequeue_bio(sc)) == NULL) {
+		twe_release_request(tr);
 		break;
 	    }
 
@@ -1093,20 +1093,18 @@
 {
     TWE_Response_Queue	rq;
     struct twe_request	*tr;
-    int			s, found;
+    int			s;
     u_int32_t		status_reg;
     
     debug_called(5);
 
     /* loop collecting completed commands */
-    found = 0;
     s = splbio();
     for (;;) {
 	status_reg = TWE_STATUS(sc);
 	twe_check_bits(sc, status_reg);		/* XXX should this fail? */
 
 	if (!(status_reg & TWE_STATUS_RESPONSE_QUEUE_EMPTY)) {
-	    found = 1;
 	    rq = TWE_RESPONSE_QUEUE(sc);
 	    tr = sc->twe_lookup[rq.u.response_id];	/* find command */
 	    if (tr->tr_status != TWE_CMD_BUSY)
@@ -1117,6 +1115,7 @@
 	    /* move to completed queue */
 	    twe_remove_busy(tr);
 	    twe_enqueue_complete(tr);
+	    sc->twe_state &= ~TWE_STATE_FRZN;
 	} else {
 	    break;					/* no response ready */
 	}
@@ -1124,8 +1123,7 @@
     splx(s);
 
     /* if we've completed any commands, try posting some more */
-    if (found)
-	twe_startio(sc);
+    twe_startio(sc);
 
     /* handle completion and timeouts */
     twe_complete(sc);		/* XXX use deferred completion? */
Index: twe_freebsd.c
===================================================================
RCS file: /mnt/ncvs/src/sys/dev/twe/twe_freebsd.c,v
retrieving revision 1.2.2.8
diff -u -r1.2.2.8 twe_freebsd.c
--- twe_freebsd.c	7 Apr 2004 22:18:00 -0000	1.2.2.8
+++ twe_freebsd.c	3 May 2004 01:00:32 -0000
@@ -944,8 +944,6 @@
 
     tr->tr_flags |= TWE_CMD_MAPPED;
 
-    if (tr->tr_flags & TWE_CMD_IN_PROGRESS)
-	tr->tr_sc->twe_state &= ~TWE_STATE_FRZN;
     /* save base of first segment in command (applicable if there only one segment) */
     tr->tr_dataphys = segs[0].ds_addr;
 
@@ -1055,7 +1053,6 @@
 	if ((error = bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_dmamap, tr->tr_data,
 			tr->tr_length, twe_setup_data_dmamap, tr, 0)
 			== EINPROGRESS)) {
-	    tr->tr_flags |= TWE_CMD_IN_PROGRESS;
 	    sc->twe_state |= TWE_STATE_FRZN;
 	    error = 0;
 	}
@@ -1102,6 +1099,8 @@
 	free(tr->tr_data, TWE_MALLOC_CLASS);
 	tr->tr_data = tr->tr_realdata;		/* restore 'real' data pointer */
     }
+
+    tr->tr_flags &= ~TWE_CMD_MAPPED;
 }
 
 #ifdef TWE_DEBUG
Index: twevar.h
===================================================================
RCS file: /mnt/ncvs/src/sys/dev/twe/twevar.h,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 twevar.h
--- twevar.h	7 Apr 2004 22:18:01 -0000	1.1.2.6
+++ twevar.h	3 May 2004 00:49:34 -0000
@@ -121,7 +121,6 @@
 #define TWE_CMD_ALIGNBUF	(1<<2)	/* data in bio is misaligned, have to copy to/from private buffer */
 #define TWE_CMD_SLEEPER		(1<<3)	/* owner is sleeping on this command */
 #define TWE_CMD_MAPPED		(1<<4)	/* cmd has been mapped */
-#define TWE_CMD_IN_PROGRESS	(1<<5)	/* bus_dmamap_load returned EINPROGRESS */
     void			(* tr_complete)(struct twe_request *tr);	/* completion handler */
     void			*tr_private;	/* submitter-private data or wait channel */
 

--------------030007050308030708030905--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?40965292.2040608>