--- /dev/null
+From fd1232b214af43a973443aec6a2808f16ee5bf70 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 8 Apr 2014 21:52:05 -0400
+Subject: sym53c8xx_2: Set DID_REQUEUE return code when aborting squeue
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit fd1232b214af43a973443aec6a2808f16ee5bf70 upstream.
+
+This patch fixes I/O errors with the sym53c8xx_2 driver when the disk
+returns QUEUE FULL status.
+
+When the controller encounters an error (including QUEUE FULL or BUSY
+status), it aborts all not yet submitted requests in the function
+sym_dequeue_from_squeue.
+
+This function aborts them with DID_SOFT_ERROR.
+
+If the disk has full tag queue, the request that caused the overflow is
+aborted with QUEUE FULL status (and the scsi midlayer properly retries
+it until it is accepted by the disk), but the sym53c8xx_2 driver aborts
+the following requests with DID_SOFT_ERROR --- for them, the midlayer
+does just a few retries and then signals the error up to sd.
+
+The result is that disk returning QUEUE FULL causes request failures.
+
+The error was reproduced on 53c895 with COMPAQ BD03685A24 disk
+(rebranded ST336607LC) with command queue 48 or 64 tags. The disk has
+64 tags, but under some access patterns it return QUEUE FULL when there
+are less than 64 pending tags. The SCSI specification allows returning
+QUEUE FULL anytime and it is up to the host to retry.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: Matthew Wilcox <matthew@wil.cx>
+Cc: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sym53c8xx_2/sym_hipd.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
++++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
+@@ -3000,7 +3000,11 @@ sym_dequeue_from_squeue(struct sym_hcb *
+ if ((target == -1 || cp->target == target) &&
+ (lun == -1 || cp->lun == lun) &&
+ (task == -1 || cp->tag == task)) {
++#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ sym_set_cam_status(cp->cmd, DID_SOFT_ERROR);
++#else
++ sym_set_cam_status(cp->cmd, DID_REQUEUE);
++#endif
+ sym_remque(&cp->link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
+ }