summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam.h3
-rw-r--r--sys/cam/cam_periph.c4
-rw-r--r--sys/cam/scsi/scsi_cd.c17
-rw-r--r--sys/cam/scsi/scsi_da.c18
4 files changed, 35 insertions, 7 deletions
diff --git a/sys/cam/cam.h b/sys/cam/cam.h
index 302504f..e08524b 100644
--- a/sys/cam/cam.h
+++ b/sys/cam/cam.h
@@ -121,7 +121,8 @@ enum {
SF_QUIET_IR = 0x04, /* Be quiet about Illegal Request reponses */
SF_PRINT_ALWAYS = 0x08, /* Always print error status. */
SF_NO_RECOVERY = 0x10, /* Don't do active error recovery. */
- SF_NO_RETRY = 0x20 /* Don't do any retries. */
+ SF_NO_RETRY = 0x20, /* Don't do any retries. */
+ SF_RETRY_BUSY = 0x40 /* Retry BUSY status. */
};
/* CAM Status field values */
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 2e23996..87c1bdd 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1359,8 +1359,8 @@ camperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb,
* Restart the queue after either another
* command completes or a 1 second timeout.
*/
- if (ccb->ccb_h.retry_count > 0) {
- ccb->ccb_h.retry_count--;
+ if ((sense_flags & SF_RETRY_BUSY) != 0 ||
+ (ccb->ccb_h.retry_count--) > 0) {
error = ERESTART;
*relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT
| RELSIM_RELEASE_AFTER_CMDCMPLT;
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 47a5a43..f252b86 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -87,14 +87,16 @@ typedef enum {
CD_Q_NONE = 0x00,
CD_Q_NO_TOUCH = 0x01,
CD_Q_BCD_TRACKS = 0x02,
- CD_Q_10_BYTE_ONLY = 0x10
+ CD_Q_10_BYTE_ONLY = 0x10,
+ CD_Q_RETRY_BUSY = 0x40
} cd_quirks;
#define CD_Q_BIT_STRING \
"\020" \
"\001NO_TOUCH" \
"\002BCD_TRACKS" \
- "\00510_BYTE_ONLY"
+ "\00510_BYTE_ONLY" \
+ "\007RETRY_BUSY"
typedef enum {
CD_FLAG_INVALID = 0x0001,
@@ -189,6 +191,14 @@ static struct cd_quirk_entry cd_quirk_table[] =
{
{ T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"},
/* quirks */ CD_Q_BCD_TRACKS
+ },
+ {
+ /*
+ * VMware returns BUSY status when storage has transient
+ * connectivity problems, so better wait.
+ */
+ {T_CDROM, SIP_MEDIA_REMOVABLE, "NECVMWar", "VMware IDE CDR10", "*"},
+ /*quirks*/ CD_Q_RETRY_BUSY
}
};
@@ -2581,6 +2591,9 @@ cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
* don't treat UAs as errors.
*/
sense_flags |= SF_RETRY_UA;
+
+ if (softc->quirks & CD_Q_RETRY_BUSY)
+ sense_flags |= SF_RETRY_BUSY;
return (cam_periph_error(ccb, cam_flags, sense_flags,
&softc->saved_ccb));
}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index a65d2dc..9b50d7a 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -101,7 +101,8 @@ typedef enum {
DA_Q_NO_PREVENT = 0x04,
DA_Q_4K = 0x08,
DA_Q_NO_RC16 = 0x10,
- DA_Q_NO_UNMAP = 0x20
+ DA_Q_NO_UNMAP = 0x20,
+ DA_Q_RETRY_BUSY = 0x40
} da_quirks;
#define DA_Q_BIT_STRING \
@@ -110,7 +111,9 @@ typedef enum {
"\002NO_6_BYTE" \
"\003NO_PREVENT" \
"\0044K" \
- "\005NO_RC16"
+ "\005NO_RC16" \
+ "\006NO_UNMAP" \
+ "\007RETRY_BUSY"
typedef enum {
DA_CCB_PROBE_RC = 0x01,
@@ -359,6 +362,14 @@ static struct da_quirk_entry da_quirk_table[] =
{T_DIRECT, SIP_MEDIA_FIXED, "STEC", "*", "*"},
/*quirks*/ DA_Q_NO_UNMAP
},
+ {
+ /*
+ * VMware returns BUSY status when storage has transient
+ * connectivity problems, so better wait.
+ */
+ {T_DIRECT, SIP_MEDIA_FIXED, "VMware", "Virtual disk", "*"},
+ /*quirks*/ DA_Q_RETRY_BUSY
+ },
/* USB mass storage devices supported by umass(4) */
{
/*
@@ -3630,6 +3641,9 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
* don't treat UAs as errors.
*/
sense_flags |= SF_RETRY_UA;
+
+ if (softc->quirks & DA_Q_RETRY_BUSY)
+ sense_flags |= SF_RETRY_BUSY;
return(cam_periph_error(ccb, cam_flags, sense_flags,
&softc->saved_ccb));
}
OpenPOWER on IntegriCloud