diff options
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam.h | 3 | ||||
-rw-r--r-- | sys/cam/cam_periph.c | 4 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_cd.c | 17 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_da.c | 18 |
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)); } |