aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index aa17e718666e..db52222885b7 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1973,27 +1973,57 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
1973} 1973}
1974EXPORT_SYMBOL(scsi_mode_sense); 1974EXPORT_SYMBOL(scsi_mode_sense);
1975 1975
1976/**
1977 * scsi_test_unit_ready - test if unit is ready
1978 * @sdev: scsi device to change the state of.
1979 * @timeout: command timeout
1980 * @retries: number of retries before failing
1981 * @sshdr_external: Optional pointer to struct scsi_sense_hdr for
1982 * returning sense. Make sure that this is cleared before passing
1983 * in.
1984 *
1985 * Returns zero if unsuccessful or an error if TUR failed. For
1986 * removable media, a return of NOT_READY or UNIT_ATTENTION is
1987 * translated to success, with the ->changed flag updated.
1988 **/
1976int 1989int
1977scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) 1990scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries,
1991 struct scsi_sense_hdr *sshdr_external)
1978{ 1992{
1979 char cmd[] = { 1993 char cmd[] = {
1980 TEST_UNIT_READY, 0, 0, 0, 0, 0, 1994 TEST_UNIT_READY, 0, 0, 0, 0, 0,
1981 }; 1995 };
1982 struct scsi_sense_hdr sshdr; 1996 struct scsi_sense_hdr *sshdr;
1983 int result; 1997 int result;
1984 1998
1985 result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, 1999 if (!sshdr_external)
1986 timeout, retries); 2000 sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
2001 else
2002 sshdr = sshdr_external;
2003
2004 /* try to eat the UNIT_ATTENTION if there are enough retries */
2005 do {
2006 result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr,
2007 timeout, retries);
2008 } while ((driver_byte(result) & DRIVER_SENSE) &&
2009 sshdr && sshdr->sense_key == UNIT_ATTENTION &&
2010 --retries);
2011
2012 if (!sshdr)
2013 /* could not allocate sense buffer, so can't process it */
2014 return result;
1987 2015
1988 if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { 2016 if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
1989 2017
1990 if ((scsi_sense_valid(&sshdr)) && 2018 if ((scsi_sense_valid(sshdr)) &&
1991 ((sshdr.sense_key == UNIT_ATTENTION) || 2019 ((sshdr->sense_key == UNIT_ATTENTION) ||
1992 (sshdr.sense_key == NOT_READY))) { 2020 (sshdr->sense_key == NOT_READY))) {
1993 sdev->changed = 1; 2021 sdev->changed = 1;
1994 result = 0; 2022 result = 0;
1995 } 2023 }
1996 } 2024 }
2025 if (!sshdr_external)
2026 kfree(sshdr);
1997 return result; 2027 return result;
1998} 2028}
1999EXPORT_SYMBOL(scsi_test_unit_ready); 2029EXPORT_SYMBOL(scsi_test_unit_ready);