summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_watch.c35
-rw-r--r--usr/src/uts/common/io/scsi/targets/sd.c20
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_watch.h3
3 files changed, 50 insertions, 8 deletions
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_watch.c b/usr/src/uts/common/io/scsi/impl/scsi_watch.c
index 9c3be4e6bc..b747dc45b5 100644
--- a/usr/src/uts/common/io/scsi/impl/scsi_watch.c
+++ b/usr/src/uts/common/io/scsi/impl/scsi_watch.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* generic scsi device watch
*/
@@ -962,3 +960,36 @@ done:
}
mutex_exit(&cpr_mutex);
}
+
+/*
+ * scsi_watch_get_ref_count
+ * called by clients to query the reference count for a given token.
+ * return the number of reference count or 0 if the given token is
+ * not found.
+ */
+int
+scsi_watch_get_ref_count(opaque_t token)
+{
+ struct scsi_watch_request *swr =
+ (struct scsi_watch_request *)token;
+ struct scsi_watch_request *sswr;
+ int rval = 0;
+
+ SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
+ "scsi_watch_get_ref_count: Entering(0x%p) ...\n",
+ (void *)swr);
+ mutex_enter(&sw.sw_mutex);
+
+ sswr = sw.sw_head;
+ while (sswr) {
+ if (sswr == swr) {
+ rval = swr->swr_ref;
+ mutex_exit(&sw.sw_mutex);
+ return (rval);
+ }
+ sswr = sswr->swr_next;
+ }
+
+ mutex_exit(&sw.sw_mutex);
+ return (rval);
+}
diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c
index 0f5d759839..72dd7318ca 100644
--- a/usr/src/uts/common/io/scsi/targets/sd.c
+++ b/usr/src/uts/common/io/scsi/targets/sd.c
@@ -22569,11 +22569,18 @@ sd_check_media(dev_t dev, enum dkio_state state)
opaque_t token = NULL;
int rval = 0;
sd_ssc_t *ssc;
+ dev_t sub_dev;
if ((un = ddi_get_soft_state(sd_state, SDUNIT(dev))) == NULL) {
return (ENXIO);
}
+ /*
+ * sub_dev is used when submitting request to scsi watch.
+ * All submissions are unified to use same device number.
+ */
+ sub_dev = sd_make_device(SD_DEVINFO(un));
+
SD_TRACE(SD_LOG_COMMON, un, "sd_check_media: entry\n");
ssc = sd_ssc_init(un);
@@ -22607,7 +22614,7 @@ sd_check_media(dev_t dev, enum dkio_state state)
token = scsi_watch_request_submit(SD_SCSI_DEVP(un),
sd_check_media_time, SENSE_LENGTH, sd_media_watch_cb,
- (caddr_t)dev);
+ (caddr_t)sub_dev);
sd_pm_exit(un);
@@ -22737,17 +22744,22 @@ sd_check_media(dev_t dev, enum dkio_state state)
done:
sd_ssc_fini(ssc);
un->un_f_watcht_stopped = FALSE;
+ if (token != NULL && un->un_swr_token != NULL) {
/*
* Use of this local token and the mutex ensures that we avoid
* some race conditions associated with terminating the
* scsi watch.
*/
- if (token) {
- un->un_swr_token = (opaque_t)NULL;
+ token = un->un_swr_token;
mutex_exit(SD_MUTEX(un));
(void) scsi_watch_request_terminate(token,
SCSI_WATCH_TERMINATE_WAIT);
- mutex_enter(SD_MUTEX(un));
+ if (scsi_watch_get_ref_count(token) == 0) {
+ mutex_enter(SD_MUTEX(un));
+ un->un_swr_token = (opaque_t)NULL;
+ } else {
+ mutex_enter(SD_MUTEX(un));
+ }
}
/*
diff --git a/usr/src/uts/common/sys/scsi/scsi_watch.h b/usr/src/uts/common/sys/scsi/scsi_watch.h
index 7bdd224253..a5dd6feae6 100644
--- a/usr/src/uts/common/sys/scsi/scsi_watch.h
+++ b/usr/src/uts/common/sys/scsi/scsi_watch.h
@@ -26,8 +26,6 @@
#ifndef _SYS_SCSI_SCSI_WATCH_H
#define _SYS_SCSI_SCSI_WATCH_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -60,6 +58,7 @@ opaque_t scsi_watch_request_submit(struct scsi_device *devp,
int interval, int sense_length,
int (*callback)(), caddr_t cb_arg);
int scsi_watch_request_terminate(opaque_t token, int flags);
+int scsi_watch_get_ref_count(opaque_t token);
void scsi_watch_resume(opaque_t token);
void scsi_watch_suspend(opaque_t token);