From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- kernel/drivers/scsi/st.c | 114 ++++++++++++++++++++++++++++++++------------------------ 1 files changed, 65 insertions(+), 49 deletions(-) diff --git a/kernel/drivers/scsi/st.c b/kernel/drivers/scsi/st.c index 5078db7..19bc8c9 100644 --- a/kernel/drivers/scsi/st.c +++ b/kernel/drivers/scsi/st.c @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying - file Documentation/scsi/st.txt for more information. + file Documentation/scsi/st.rst for more information. History: Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara. @@ -21,6 +22,7 @@ #include <linux/module.h> +#include <linux/compat.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/sched/signal.h> @@ -43,6 +45,7 @@ #include <linux/uaccess.h> #include <asm/dma.h> +#include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_dbg.h> @@ -169,7 +172,7 @@ /* Remove mode bits and auto-rewind bit (7) */ #define TAPE_NR(x) ( ((iminor(x) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \ - (iminor(x) & ~(-1 << ST_MODE_SHIFT)) ) + (iminor(x) & ((1 << ST_MODE_SHIFT)-1))) #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT) /* Construct the minor number from the device (d), mode (m), and non-rewind (n) data */ @@ -227,7 +230,6 @@ -#include "osst_detect.h" #ifndef SIGS_FROM_OSST #define SIGS_FROM_OSST \ {"OnStream", "SC-", "", "osst"}, \ @@ -337,12 +339,14 @@ switch (sense[0] & 0x7f) { case 0x71: s->deferred = 1; + fallthrough; case 0x70: s->fixed_format = 1; s->flags = sense[2] & 0xe0; break; case 0x73: s->deferred = 1; + fallthrough; case 0x72: s->fixed_format = 0; ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4); @@ -530,7 +534,7 @@ complete(SRpnt->waiting); blk_rq_unmap_user(tmp); - __blk_put_request(req->q, req); + blk_put_request(req); } static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, @@ -1453,7 +1457,6 @@ accessing this tape. */ static int st_release(struct inode *inode, struct file *filp) { - int result = 0; struct scsi_tape *STp = filp->private_data; if (STp->door_locked == ST_LOCKED_AUTO) @@ -1466,9 +1469,9 @@ scsi_autopm_put_device(STp->device); scsi_tape_put(STp); - return result; + return 0; } - + /* The checks common to both reading and writing */ static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count) { @@ -2677,8 +2680,7 @@ if (!debugging) return; - sc = cmd[2] & 0x80 ? 0xff000000 : 0; - sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; + sc = sign_extend32(get_unaligned_be24(&cmd[2]), 23); if (direction) sc = -sc; st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n", @@ -2721,6 +2723,7 @@ switch (cmd_in) { case MTFSFM: chg_eof = 0; /* Changed from the FSF after this */ + fallthrough; case MTFSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2735,6 +2738,7 @@ break; case MTBSFM: chg_eof = 0; /* Changed from the FSF after this */ + fallthrough; case MTBSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -3496,7 +3500,7 @@ /* The ioctl command */ -static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) +static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p) { int i, cmd_nr, cmd_type, bt; int retval = 0; @@ -3504,7 +3508,6 @@ struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -3796,14 +3799,11 @@ if (STp->cleaning_req) mt_status.mt_gstat |= GMT_CLN(0xffffffff); - i = copy_to_user(p, &mt_status, sizeof(struct mtget)); - if (i) { - retval = (-EFAULT); + retval = put_user_mtget(p, &mt_status); + if (retval) goto out; - } STp->recover_reg = 0; /* Clear after read */ - retval = 0; goto out; } /* End of MTIOCGET */ if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) { @@ -3817,16 +3817,24 @@ goto out; } mt_pos.mt_blkno = blk; - i = copy_to_user(p, &mt_pos, sizeof(struct mtpos)); - if (i) - retval = (-EFAULT); + retval = put_user_mtpos(p, &mt_pos); goto out; } mutex_unlock(&STp->lock); switch (cmd_in) { + case SCSI_IOCTL_STOP_UNIT: + /* unload */ + retval = scsi_ioctl(STp->device, cmd_in, p); + if (!retval) { + STp->rew_at_close = 0; + STp->ready = ST_NO_TAPE; + } + return retval; + case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: break; + default: if ((cmd_in == SG_IO || cmd_in == SCSI_IOCTL_SEND_COMMAND || @@ -3840,30 +3848,46 @@ return i; break; } - retval = scsi_ioctl(STp->device, cmd_in, p); - if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */ - STp->rew_at_close = 0; - STp->ready = ST_NO_TAPE; - } - return retval; + return -ENOTTY; out: mutex_unlock(&STp->lock); return retval; } -#ifdef CONFIG_COMPAT -static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) { + void __user *p = (void __user *)arg; struct scsi_tape *STp = file->private_data; - struct scsi_device *sdev = STp->device; - int ret = -ENOIOCTLCMD; - if (sdev->host->hostt->compat_ioctl) { + int ret; - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + ret = st_ioctl_common(file, cmd_in, p); + if (ret != -ENOTTY) + return ret; + return scsi_ioctl(STp->device, cmd_in, p); +} + +#ifdef CONFIG_COMPAT +static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) +{ + void __user *p = compat_ptr(arg); + struct scsi_tape *STp = file->private_data; + int ret; + + /* argument conversion is handled using put_user_mtpos/put_user_mtget */ + switch (cmd_in) { + case MTIOCPOS32: + return st_ioctl_common(file, MTIOCPOS, p); + case MTIOCGET32: + return st_ioctl_common(file, MTIOCGET, p); } - return ret; + + ret = st_ioctl_common(file, cmd_in, p); + if (ret != -ENOTTY) + return ret; + + return scsi_compat_ioctl(STp->device, cmd_in, p); } #endif @@ -4262,9 +4286,10 @@ if (SDp->type != TYPE_TAPE) return -ENODEV; if ((stp = st_incompatible(SDp))) { - sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n"); sdev_printk(KERN_INFO, SDp, - "st: The suggested driver is %s.\n", stp); + "OnStream tapes are no longer supported;\n"); + sdev_printk(KERN_INFO, SDp, + "please mail to linux-scsi@vger.kernel.org.\n"); return -ENODEV; } @@ -4896,7 +4921,7 @@ unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; const int nr_pages = end - start; - int res, i, j; + int res, i; struct page **pages; struct rq_map_data *mdata = &STbp->map_data; @@ -4918,7 +4943,8 @@ /* Try to fault in all of the necessary pages */ /* rw==READ means read from drive, write into memory area */ - res = get_user_pages_fast(uaddr, nr_pages, rw == READ, pages); + res = pin_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0, + pages); /* Errors and no page mapped should return here */ if (res < nr_pages) @@ -4937,8 +4963,7 @@ return nr_pages; out_unmap: if (res > 0) { - for (j=0; j < res; j++) - put_page(pages[j]); + unpin_user_pages(pages, res); res = 0; } kfree(pages); @@ -4950,18 +4975,9 @@ static int sgl_unmap_user_pages(struct st_buffer *STbp, const unsigned int nr_pages, int dirtied) { - int i; + /* FIXME: cache flush missing for rw==READ */ + unpin_user_pages_dirty_lock(STbp->mapped_pages, nr_pages, dirtied); - for (i=0; i < nr_pages; i++) { - struct page *page = STbp->mapped_pages[i]; - - if (dirtied) - SetPageDirty(page); - /* FIXME: cache flush missing for rw==READ - * FIXME: call the correct reference counting function - */ - put_page(page); - } kfree(STbp->mapped_pages); STbp->mapped_pages = NULL; -- Gitblit v1.6.2