]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: st: Modify st.c to use the new scsi_error counters
authorKai Mäkisara <Kai.Makisara@kolumbus.fi>
Mon, 20 Jan 2025 19:49:24 +0000 (21:49 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 3 Feb 2025 22:43:31 +0000 (17:43 -0500)
Compare the stored values of por_ctr and new_media_ctr against the values
in the device struct. In case of mismatch, the Unit Attention corresponding
to the counter has happened.  This is a safeguard against another ULD
catching the Unit Attention sense data.

Macros scsi_get_ua_new_media_ctr and scsi_get_ua_por_ctr are added to read
the current values of the counters.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
Link: https://lore.kernel.org/r/20250120194925.44432-4-Kai.Makisara@kolumbus.fi
Reviewed-by: John Meneghini <jmeneghi@redhat.com>
Tested-by: John Meneghini <jmeneghi@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/st.c
drivers/scsi/st.h
include/scsi/scsi_device.h

index 0fc9afe60862fc7a817c13378145b9809cf12208..6ec1cfeb92ff13a739e57c970881bd02e0f5455a 100644 (file)
@@ -163,9 +163,11 @@ static const char *st_formats[] = {
 
 static int debugging = DEBUG;
 
+/* Setting these non-zero may risk recognizing resets */
 #define MAX_RETRIES 0
 #define MAX_WRITE_RETRIES 0
 #define MAX_READY_RETRIES 0
+
 #define NO_TAPE  NOT_READY
 
 #define ST_TIMEOUT (900 * HZ)
@@ -357,10 +359,18 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
 {
        int result = SRpnt->result;
        u8 scode;
+       unsigned int ctr;
        DEB(const char *stp;)
        char *name = STp->name;
        struct st_cmdstatus *cmdstatp;
 
+       ctr = scsi_get_ua_por_ctr(STp->device);
+       if (ctr != STp->por_ctr) {
+               STp->por_ctr = ctr;
+               STp->pos_unknown = 1; /* ASC => power on / reset */
+               st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
+       }
+
        if (!result)
                return 0;
 
@@ -413,10 +423,11 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
        if (cmdstatp->have_sense &&
            cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
                STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
-       if (cmdstatp->have_sense && scode == UNIT_ATTENTION && cmdstatp->sense_hdr.asc == 0x29)
+       if (cmdstatp->have_sense && scode == UNIT_ATTENTION &&
+               cmdstatp->sense_hdr.asc == 0x29 && !STp->pos_unknown) {
                STp->pos_unknown = 1; /* ASC => power on / reset */
-
-       STp->pos_unknown |= STp->device->was_reset;
+               st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
+       }
 
        if (cmdstatp->have_sense &&
            scode == RECOVERED_ERROR
@@ -968,6 +979,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
 {
        int attentions, waits, max_wait, scode;
        int retval = CHKRES_READY, new_session = 0;
+       unsigned int ctr;
        unsigned char cmd[MAX_COMMAND_SIZE];
        struct st_request *SRpnt = NULL;
        struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
@@ -1024,6 +1036,13 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
                        }
                }
 
+               ctr = scsi_get_ua_new_media_ctr(STp->device);
+               if (ctr != STp->new_media_ctr) {
+                       STp->new_media_ctr = ctr;
+                       new_session = 1;
+                       DEBC_printk(STp, "New tape session.");
+               }
+
                retval = (STp->buffer)->syscall_result;
                if (!retval)
                        retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
@@ -3639,8 +3658,6 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
                                goto out;
                        }
                        reset_state(STp); /* Clears pos_unknown */
-                       /* remove this when the midlevel properly clears was_reset */
-                       STp->device->was_reset = 0;
 
                        /* Fix the device settings after reset, ignore errors */
                        if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK ||
@@ -4402,6 +4419,9 @@ static int st_probe(struct device *dev)
                goto out_idr_remove;
        }
 
+       tpnt->new_media_ctr = scsi_get_ua_new_media_ctr(SDp);
+       tpnt->por_ctr = scsi_get_ua_por_ctr(SDp);
+
        dev_set_drvdata(dev, tpnt);
 
 
index 6d31b894ee84cc76cd3441fcbedee7e203c84f8c..0d7c4b8c2c8a89751599225a2f8d81553d972980 100644 (file)
@@ -179,6 +179,10 @@ struct scsi_tape {
        int recover_count;     /* From tape opening */
        int recover_reg;       /* From last status call */
 
+       /* The saved values of midlevel counters */
+       unsigned int new_media_ctr;
+       unsigned int por_ctr;
+
 #if DEBUG
        unsigned char write_pending;
        int nbr_finished;
index bcc76986096b4e02fa4d452f41de1f288633a27a..68dd49947d041d1656a74fac9bb496abacfc3c75 100644 (file)
@@ -687,6 +687,12 @@ static inline int scsi_device_busy(struct scsi_device *sdev)
        return sbitmap_weight(&sdev->budget_map);
 }
 
+/* Macros to access the UNIT ATTENTION counters */
+#define scsi_get_ua_new_media_ctr(sdev) \
+       ((const unsigned int)(sdev->ua_new_media_ctr))
+#define scsi_get_ua_por_ctr(sdev) \
+       ((const unsigned int)(sdev->ua_por_ctr))
+
 #define MODULE_ALIAS_SCSI_DEVICE(type) \
        MODULE_ALIAS("scsi:t-" __stringify(type) "*")
 #define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"