summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Le Moal <damien.lemoal@wdc.com>2021-02-04 17:43:42 +0900
committerJens Axboe <axboe@kernel.dk>2021-02-04 07:45:32 -0700
commitee8f353b1591cef4a29cddeb379c1503559f474e (patch)
treeb397117e9baacca439e3feb95cb8d31200975969
parent203c018079e13510f913fd0fd426370f4de0fd05 (diff)
downloadlinux-ee8f353b1591cef4a29cddeb379c1503559f474e.tar.gz
linux-ee8f353b1591cef4a29cddeb379c1503559f474e.tar.bz2
linux-ee8f353b1591cef4a29cddeb379c1503559f474e.zip
block: remove skd driver
The STEC S1220 PCIe SSD cards are EOL since 2014 and not supported by the vendor anymore. As the skd driver for this SSD is starting to cause problems with improvements to the block layer, stop supporting it in newer kernel versions. Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/block/Kconfig10
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/skd_main.c3670
-rw-r--r--drivers/block/skd_s1120.h322
5 files changed, 0 insertions, 4010 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 992fe3b0900a..f4766335189a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16938,12 +16938,6 @@ F: include/linux/static_call*.h
F: kernel/jump_label.c
F: kernel/static_call.c
-STEC S1220 SKD DRIVER
-M: Damien Le Moal <Damien.LeMoal@wdc.com>
-L: linux-block@vger.kernel.org
-S: Maintained
-F: drivers/block/skd*[ch]
-
STI AUDIO (ASoC) DRIVERS
M: Arnaud Pouliquen <arnaud.pouliquen@st.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 583b671b1d2d..2779e85795a7 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -267,16 +267,6 @@ config BLK_DEV_NBD
If unsure, say N.
-config BLK_DEV_SKD
- tristate "STEC S1120 Block Driver"
- depends on PCI
- depends on 64BIT
- help
- Saying Y or M here will enable support for the
- STEC, Inc. S1120 PCIe SSD.
-
- Use device /dev/skd$N amd /dev/skd$Np$M.
-
config BLK_DEV_SX8
tristate "Promise SATA SX8 support"
depends on PCI
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index a3170859e01d..b501b8728fb9 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
-obj-$(CONFIG_BLK_DEV_SKD) += skd.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
@@ -43,5 +42,4 @@ obj-$(CONFIG_BLK_DEV_RNBD) += rnbd/
obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_blk/
-skd-y := skd_main.o
swim_mod-y := swim.o swim_asm.o
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
deleted file mode 100644
index a962b4551bed..000000000000
--- a/drivers/block/skd_main.c
+++ /dev/null
@@ -1,3670 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for sTec s1120 PCIe SSDs. sTec was acquired in 2013 by HGST and HGST
- * was acquired by Western Digital in 2012.
- *
- * Copyright 2012 sTec, Inc.
- * Copyright (c) 2017 Western Digital Corporation or its affiliates.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/blkdev.h>
-#include <linux/blk-mq.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/compiler.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/hdreg.h>
-#include <linux/dma-mapping.h>
-#include <linux/completion.h>
-#include <linux/scatterlist.h>
-#include <linux/err.h>
-#include <linux/aer.h>
-#include <linux/wait.h>
-#include <linux/stringify.h>
-#include <scsi/scsi.h>
-#include <scsi/sg.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <asm/unaligned.h>
-
-#include "skd_s1120.h"
-
-static int skd_dbg_level;
-static int skd_isr_comp_limit = 4;
-
-#define SKD_ASSERT(expr) \
- do { \
- if (unlikely(!(expr))) { \
- pr_err("Assertion failed! %s,%s,%s,line=%d\n", \
- # expr, __FILE__, __func__, __LINE__); \
- } \
- } while (0)
-
-#define DRV_NAME "skd"
-#define PFX DRV_NAME ": "
-
-MODULE_LICENSE("GPL");
-
-MODULE_DESCRIPTION("STEC s1120 PCIe SSD block driver");
-
-#define PCI_VENDOR_ID_STEC 0x1B39
-#define PCI_DEVICE_ID_S1120 0x0001
-
-#define SKD_FUA_NV (1 << 1)
-#define SKD_MINORS_PER_DEVICE 16
-
-#define SKD_MAX_QUEUE_DEPTH 200u
-
-#define SKD_PAUSE_TIMEOUT (5 * 1000)
-
-#define SKD_N_FITMSG_BYTES (512u)
-#define SKD_MAX_REQ_PER_MSG 14
-
-#define SKD_N_SPECIAL_FITMSG_BYTES (128u)
-
-/* SG elements are 32 bytes, so we can make this 4096 and still be under the
- * 128KB limit. That allows 4096*4K = 16M xfer size
- */
-#define SKD_N_SG_PER_REQ_DEFAULT 256u
-
-#define SKD_N_COMPLETION_ENTRY 256u
-#define SKD_N_READ_CAP_BYTES (8u)
-
-#define SKD_N_INTERNAL_BYTES (512u)
-
-#define SKD_SKCOMP_SIZE \
- ((sizeof(struct fit_completion_entry_v1) + \
- sizeof(struct fit_comp_error_info)) * SKD_N_COMPLETION_ENTRY)
-
-/* 5 bits of uniqifier, 0xF800 */
-#define SKD_ID_TABLE_MASK (3u << 8u)
-#define SKD_ID_RW_REQUEST (0u << 8u)
-#define SKD_ID_INTERNAL (1u << 8u)
-#define SKD_ID_FIT_MSG (3u << 8u)
-#define SKD_ID_SLOT_MASK 0x00FFu
-#define SKD_ID_SLOT_AND_TABLE_MASK 0x03FFu
-
-#define SKD_N_MAX_SECTORS 2048u
-
-#define SKD_MAX_RETRIES 2u
-
-#define SKD_TIMER_SECONDS(seconds) (seconds)
-#define SKD_TIMER_MINUTES(minutes) ((minutes) * (60))
-
-#define INQ_STD_NBYTES 36
-
-enum skd_drvr_state {
- SKD_DRVR_STATE_LOAD,
- SKD_DRVR_STATE_IDLE,
- SKD_DRVR_STATE_BUSY,
- SKD_DRVR_STATE_STARTING,
- SKD_DRVR_STATE_ONLINE,
- SKD_DRVR_STATE_PAUSING,
- SKD_DRVR_STATE_PAUSED,
- SKD_DRVR_STATE_RESTARTING,
- SKD_DRVR_STATE_RESUMING,
- SKD_DRVR_STATE_STOPPING,
- SKD_DRVR_STATE_FAULT,
- SKD_DRVR_STATE_DISAPPEARED,
- SKD_DRVR_STATE_PROTOCOL_MISMATCH,
- SKD_DRVR_STATE_BUSY_ERASE,
- SKD_DRVR_STATE_BUSY_SANITIZE,
- SKD_DRVR_STATE_BUSY_IMMINENT,
- SKD_DRVR_STATE_WAIT_BOOT,
- SKD_DRVR_STATE_SYNCING,
-};
-
-#define SKD_WAIT_BOOT_TIMO SKD_TIMER_SECONDS(90u)
-#define SKD_STARTING_TIMO SKD_TIMER_SECONDS(8u)
-#define SKD_RESTARTING_TIMO SKD_TIMER_MINUTES(4u)
-#define SKD_BUSY_TIMO SKD_TIMER_MINUTES(20u)
-#define SKD_STARTED_BUSY_TIMO SKD_TIMER_SECONDS(60u)
-#define SKD_START_WAIT_SECONDS 90u
-
-enum skd_req_state {
- SKD_REQ_STATE_IDLE,
- SKD_REQ_STATE_SETUP,
- SKD_REQ_STATE_BUSY,
- SKD_REQ_STATE_COMPLETED,
- SKD_REQ_STATE_TIMEOUT,
-};
-
-enum skd_check_status_action {
- SKD_CHECK_STATUS_REPORT_GOOD,
- SKD_CHECK_STATUS_REPORT_SMART_ALERT,
- SKD_CHECK_STATUS_REQUEUE_REQUEST,
- SKD_CHECK_STATUS_REPORT_ERROR,
- SKD_CHECK_STATUS_BUSY_IMMINENT,
-};
-
-struct skd_msg_buf {
- struct fit_msg_hdr fmh;
- struct skd_scsi_request scsi[SKD_MAX_REQ_PER_MSG];
-};
-
-struct skd_fitmsg_context {
- u32 id;
-
- u32 length;
-
- struct skd_msg_buf *msg_buf;
- dma_addr_t mb_dma_address;
-};
-
-struct skd_request_context {
- enum skd_req_state state;
-
- u16 id;
- u32 fitmsg_id;
-
- u8 flush_cmd;
-
- enum dma_data_direction data_dir;
- struct scatterlist *sg;
- u32 n_sg;
- u32 sg_byte_count;
-
- struct fit_sg_descriptor *sksg_list;
- dma_addr_t sksg_dma_address;
-
- struct fit_completion_entry_v1 completion;
-
- struct fit_comp_error_info err_info;
- int retries;
-
- blk_status_t status;
-};
-
-struct skd_special_context {
- struct skd_request_context req;
-
- void *data_buf;
- dma_addr_t db_dma_address;
-
- struct skd_msg_buf *msg_buf;
- dma_addr_t mb_dma_address;
-};
-
-typedef enum skd_irq_type {
- SKD_IRQ_LEGACY,
- SKD_IRQ_MSI,
- SKD_IRQ_MSIX
-} skd_irq_type_t;
-
-#define SKD_MAX_BARS 2
-
-struct skd_device {
- void __iomem *mem_map[SKD_MAX_BARS];
- resource_size_t mem_phys[SKD_MAX_BARS];
- u32 mem_size[SKD_MAX_BARS];
-
- struct skd_msix_entry *msix_entries;
-
- struct pci_dev *pdev;
- int pcie_error_reporting_is_enabled;
-
- spinlock_t lock;
- struct gendisk *disk;
- struct blk_mq_tag_set tag_set;
- struct request_queue *queue;
- struct skd_fitmsg_context *skmsg;
- struct device *class_dev;
- int gendisk_on;
- int sync_done;
-
- u32 devno;
- u32 major;
- char isr_name[30];
-
- enum skd_drvr_state state;
- u32 drive_state;
-
- u32 cur_max_queue_depth;
- u32 queue_low_water_mark;
- u32 dev_max_queue_depth;
-
- u32 num_fitmsg_context;
- u32 num_req_context;
-
- struct skd_fitmsg_context *skmsg_table;
-
- struct skd_special_context internal_skspcl;
- u32 read_cap_blocksize;
- u32 read_cap_last_lba;
- int read_cap_is_valid;
- int inquiry_is_valid;
- u8 inq_serial_num[13]; /*12 chars plus null term */
-
- u8 skcomp_cycle;
- u32 skcomp_ix;
- struct kmem_cache *msgbuf_cache;
- struct kmem_cache *sglist_cache;
- struct kmem_cache *databuf_cache;
- struct fit_completion_entry_v1 *skcomp_table;
- struct fit_comp_error_info *skerr_table;
- dma_addr_t cq_dma_address;
-
- wait_queue_head_t waitq;
-
- struct timer_list timer;
- u32 timer_countdown;
- u32 timer_substate;
-
- int sgs_per_request;
- u32 last_mtd;
-
- u32 proto_ver;
-
- int dbg_level;
- u32 connect_time_stamp;
- int connect_retries;
-#define SKD_MAX_CONNECT_RETRIES 16
- u32 drive_jiffies;
-
- u32 timo_slot;
-
- struct work_struct start_queue;
- struct work_struct completion_worker;
-};
-
-#define SKD_WRITEL(DEV, VAL, OFF) skd_reg_write32(DEV, VAL, OFF)
-#define SKD_READL(DEV, OFF) skd_reg_read32(DEV, OFF)
-#define SKD_WRITEQ(DEV, VAL, OFF) skd_reg_write64(DEV, VAL, OFF)
-
-static inline u32 skd_reg_read32(struct skd_device *skdev, u32 offset)
-{
- u32 val = readl(skdev->mem_map[1] + offset);
-
- if (unlikely(skdev->dbg_level >= 2))
- dev_dbg(&skdev->pdev->dev, "offset %x = %x\n", offset, val);
- return val;
-}
-
-static inline void skd_reg_write32(struct skd_device *skdev, u32 val,
- u32 offset)
-{
- writel(val, skdev->mem_map[1] + offset);
- if (unlikely(skdev->dbg_level >= 2))
- dev_dbg(&skdev->pdev->dev, "offset %x = %x\n", offset, val);
-}
-
-static inline void skd_reg_write64(struct skd_device *skdev, u64 val,
- u32 offset)
-{
- writeq(val, skdev->mem_map[1] + offset);
- if (unlikely(skdev->dbg_level >= 2))
- dev_dbg(&skdev->pdev->dev, "offset %x = %016llx\n", offset,
- val);
-}
-
-
-#define SKD_IRQ_DEFAULT SKD_IRQ_MSIX
-static int skd_isr_type = SKD_IRQ_DEFAULT;
-
-module_param(skd_isr_type, int, 0444);
-MODULE_PARM_DESC(skd_isr_type, "Interrupt type capability."
- " (0==legacy, 1==MSI, 2==MSI-X, default==1)");
-
-#define SKD_MAX_REQ_PER_MSG_DEFAULT 1
-static int skd_max_req_per_msg = SKD_MAX_REQ_PER_MSG_DEFAULT;
-
-module_param(skd_max_req_per_msg, int, 0444);
-MODULE_PARM_DESC(skd_max_req_per_msg,
- "Maximum SCSI requests packed in a single message."
- " (1-" __stringify(SKD_MAX_REQ_PER_MSG) ", default==1)");
-
-#define SKD_MAX_QUEUE_DEPTH_DEFAULT 64
-#define SKD_MAX_QUEUE_DEPTH_DEFAULT_STR "64"
-static int skd_max_queue_depth = SKD_MAX_QUEUE_DEPTH_DEFAULT;
-
-module_param(skd_max_queue_depth, int, 0444);
-MODULE_PARM_DESC(skd_max_queue_depth,
- "Maximum SCSI requests issued to s1120."
- " (1-200, default==" SKD_MAX_QUEUE_DEPTH_DEFAULT_STR ")");
-
-static int skd_sgs_per_request = SKD_N_SG_PER_REQ_DEFAULT;
-module_param(skd_sgs_per_request, int, 0444);
-MODULE_PARM_DESC(skd_sgs_per_request,
- "Maximum SG elements per block request."
- " (1-4096, default==256)");
-
-static int skd_max_pass_thru = 1;
-module_param(skd_max_pass_thru, int, 0444);
-MODULE_PARM_DESC(skd_max_pass_thru,
- "Maximum SCSI pass-thru at a time. IGNORED");
-
-module_param(skd_dbg_level, int, 0444);
-MODULE_PARM_DESC(skd_dbg_level, "s1120 debug level (0,1,2)");
-
-module_param(skd_isr_comp_limit, int, 0444);
-MODULE_PARM_DESC(skd_isr_comp_limit, "s1120 isr comp limit (0=none) default=4");
-
-/* Major device number dynamically assigned. */
-static u32 skd_major;
-
-static void skd_destruct(struct skd_device *skdev);
-static const struct block_device_operations skd_blockdev_ops;
-static void skd_send_fitmsg(struct skd_device *skdev,
- struct skd_fitmsg_context *skmsg);
-static void skd_send_special_fitmsg(struct skd_device *skdev,
- struct skd_special_context *skspcl);
-static bool skd_preop_sg_list(struct skd_device *skdev,
- struct skd_request_context *skreq);
-static void skd_postop_sg_list(struct skd_device *skdev,
- struct skd_request_context *skreq);
-
-static void skd_restart_device(struct skd_device *skdev);
-static int skd_quiesce_dev(struct skd_device *skdev);
-static int skd_unquiesce_dev(struct skd_device *skdev);
-static void skd_disable_interrupts(struct skd_device *skdev);
-static void skd_isr_fwstate(struct skd_device *skdev);
-static void skd_recover_requests(struct skd_device *skdev);
-static void skd_soft_reset(struct skd_device *skdev);
-
-const char *skd_drive_state_to_str(int state);
-const char *skd_skdev_state_to_str(enum skd_drvr_state state);
-static void skd_log_skdev(struct skd_device *skdev, const char *event);
-static void skd_log_skreq(struct skd_device *skdev,
- struct skd_request_context *skreq, const char *event);
-
-/*
- *****************************************************************************
- * READ/WRITE REQUESTS
- *****************************************************************************
- */
-static bool skd_inc_in_flight(struct request *rq, void *data, bool reserved)
-{
- int *count = data;
-
- count++;
- return true;
-}
-
-static int skd_in_flight(struct skd_device *skdev)
-{
- int count = 0;
-
- blk_mq_tagset_busy_iter(&skdev->tag_set, skd_inc_in_flight, &count);
-
- return count;
-}
-
-static void
-skd_prep_rw_cdb(struct skd_scsi_request *scsi_req,
- int data_dir, unsigned lba,
- unsigned count)
-{
- if (data_dir == READ)
- scsi_req->cdb[0] = READ_10;
- else
- scsi_req->cdb[0] = WRITE_10;
-
- scsi_req->cdb[1] = 0;
- scsi_req->cdb[2] = (lba & 0xff000000) >> 24;
- scsi_req->cdb[3] = (lba & 0xff0000) >> 16;
- scsi_req->cdb[4] = (lba & 0xff00) >> 8;
- scsi_req->cdb[5] = (lba & 0xff);
- scsi_req->cdb[6] = 0;
- scsi_req->cdb[7] = (count & 0xff00) >> 8;
- scsi_req->cdb[8] = count & 0xff;
- scsi_req->cdb[9] = 0;
-}
-
-static void
-skd_prep_zerosize_flush_cdb(struct skd_scsi_request *scsi_req,
- struct skd_request_context *skreq)
-{
- skreq->flush_cmd = 1;
-
- scsi_req->cdb[0] = SYNCHRONIZE_CACHE;
- scsi_req->cdb[1] = 0;
- scsi_req->cdb[2] = 0;
- scsi_req->cdb[3] = 0;
- scsi_req->cdb[4] = 0;
- scsi_req->cdb[5] = 0;
- scsi_req->cdb[6] = 0;
- scsi_req->cdb[7] = 0;
- scsi_req->cdb[8] = 0;
- scsi_req->cdb[9] = 0;
-}
-
-/*
- * Return true if and only if all pending requests should be failed.
- */
-static bool skd_fail_all(struct request_queue *q)
-{
- struct skd_device *skdev = q->queuedata;
-
- SKD_ASSERT(skdev->state != SKD_DRVR_STATE_ONLINE);
-
- skd_log_skdev(skdev, "req_not_online");
- switch (skdev->state) {
- case SKD_DRVR_STATE_PAUSING:
- case SKD_DRVR_STATE_PAUSED:
- case SKD_DRVR_STATE_STARTING:
- case SKD_DRVR_STATE_RESTARTING:
- case SKD_DRVR_STATE_WAIT_BOOT:
- /* In case of starting, we haven't started the queue,
- * so we can't get here... but requests are
- * possibly hanging out waiting for us because we
- * reported the dev/skd0 already. They'll wait
- * forever if connect doesn't complete.
- * What to do??? delay dev/skd0 ??
- */
- case SKD_DRVR_STATE_BUSY:
- case SKD_DRVR_STATE_BUSY_IMMINENT:
- case SKD_DRVR_STATE_BUSY_ERASE:
- return false;
-
- case SKD_DRVR_STATE_BUSY_SANITIZE:
- case SKD_DRVR_STATE_STOPPING:
- case SKD_DRVR_STATE_SYNCING:
- case SKD_DRVR_STATE_FAULT:
- case SKD_DRVR_STATE_DISAPPEARED:
- default:
- return true;
- }
-}
-
-static blk_status_t skd_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
- const struct blk_mq_queue_data *mqd)
-{
- struct request *const req = mqd->rq;
- struct request_queue *const q = req->q;
- struct skd_device *skdev = q->queuedata;
- struct skd_fitmsg_context *skmsg;
- struct fit_msg_hdr *fmh;
- const u32 tag = blk_mq_unique_tag(req);
- struct skd_request_context *const skreq = blk_mq_rq_to_pdu(req);
- struct skd_scsi_request *scsi_req;
- unsigned long flags = 0;
- const u32 lba = blk_rq_pos(req);
- const u32 count = blk_rq_sectors(req);
- const int data_dir = rq_data_dir(req);
-
- if (unlikely(skdev->state != SKD_DRVR_STATE_ONLINE))
- return skd_fail_all(q) ? BLK_STS_IOERR : BLK_STS_RESOURCE;
-
- if (!(req->rq_flags & RQF_DONTPREP)) {
- skreq->retries = 0;
- req->rq_flags |= RQF_DONTPREP;
- }
-
- blk_mq_start_request(req);
-
- WARN_ONCE(tag >= skd_max_queue_depth, "%#x > %#x (nr_requests = %lu)\n",
- tag, skd_max_queue_depth, q->nr_requests);
-
- SKD_ASSERT(skreq->state == SKD_REQ_STATE_IDLE);
-
- dev_dbg(&skdev->pdev->dev,
- "new req=%p lba=%u(0x%x) count=%u(0x%x) dir=%d\n", req, lba,
- lba, count, count, data_dir);
-
- skreq->id = tag + SKD_ID_RW_REQUEST;
- skreq->flush_cmd = 0;
- skreq->n_sg = 0;
- skreq->sg_byte_count = 0;
-
- skreq->fitmsg_id = 0;
-
- skreq->data_dir = data_dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- if (req->bio && !skd_preop_sg_list(skdev, skreq)) {
- dev_dbg(&skdev->pdev->dev, "error Out\n");
- skreq->status = BLK_STS_RESOURCE;
- blk_mq_complete_request(req);
- return BLK_STS_OK;
- }
-
- dma_sync_single_for_device(&skdev->pdev->dev, skreq->sksg_dma_address,
- skreq->n_sg *
- sizeof(struct fit_sg_descriptor),
- DMA_TO_DEVICE);
-
- /* Either a FIT msg is in progress or we have to start one. */
- if (skd_max_req_per_msg == 1) {
- skmsg = NULL;
- } else {
- spin_lock_irqsave(&skdev->lock, flags);
- skmsg = skdev->skmsg;
- }
- if (!skmsg) {
- skmsg = &skdev->skmsg_table[tag];
- skdev->skmsg = skmsg;
-
- /* Initialize the FIT msg header */
- fmh = &skmsg->msg_buf->fmh;
- memset(fmh, 0, sizeof(*fmh));
- fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
- skmsg->length = sizeof(*fmh);
- } else {
- fmh = &skmsg->msg_buf->fmh;
- }
-
- skreq->fitmsg_id = skmsg->id;
-
- scsi_req = &skmsg->msg_buf->scsi[fmh->num_protocol_cmds_coalesced];
- memset(scsi_req, 0, sizeof(*scsi_req));
-
- scsi_req->hdr.tag = skreq->id;
- scsi_req->hdr.sg_list_dma_address =
- cpu_to_be64(skreq->sksg_dma_address);
-
- if (req_op(req) == REQ_OP_FLUSH) {
- skd_prep_zerosize_flush_cdb(scsi_req, skreq);
- SKD_ASSERT(skreq->flush_cmd == 1);
- } else {
- skd_prep_rw_cdb(scsi_req, data_dir, lba, count);
- }
-
- if (req->cmd_flags & REQ_FUA)
- scsi_req->cdb[1] |= SKD_FUA_NV;
-
- scsi_req->hdr.sg_list_len_bytes = cpu_to_be32(skreq->sg_byte_count);
-
- /* Complete resource allocations. */
- skreq->state = SKD_REQ_STATE_BUSY;
-
- skmsg->length += sizeof(struct skd_scsi_request);
- fmh->num_protocol_cmds_coalesced++;
-
- dev_dbg(&skdev->pdev->dev, "req=0x%x busy=%d\n", skreq->id,
- skd_in_flight(skdev));
-
- /*
- * If the FIT msg buffer is full send it.
- */
- if (skd_max_req_per_msg == 1) {
- skd_send_fitmsg(skdev, skmsg);
- } else {
- if (mqd->last ||
- fmh->num_protocol_cmds_coalesced >= skd_max_req_per_msg) {
- skd_send_fitmsg(skdev, skmsg);
- skdev->skmsg = NULL;
- }
- spin_unlock_irqrestore(&skdev->lock, flags);
- }
-
- return BLK_STS_OK;
-}
-
-static enum blk_eh_timer_return skd_timed_out(struct request *req,
- bool reserved)
-{
- struct skd_device *skdev = req->q->queuedata;
-
- dev_err(&skdev->pdev->dev, "request with tag %#x timed out\n",
- blk_mq_unique_tag(req));
-
- return BLK_EH_RESET_TIMER;
-}
-
-static void skd_complete_rq(struct request *req)
-{
- struct skd_request_context *skreq = blk_mq_rq_to_pdu(req);
-
- blk_mq_end_request(req, skreq->status);
-}
-
-static bool skd_preop_sg_list(struct skd_device *skdev,
- struct skd_request_context *skreq)
-{
- struct request *req = blk_mq_rq_from_pdu(skreq);
- struct scatterlist *sgl = &skreq->sg[0], *sg;
- int n_sg;
- int i;
-
- skreq->sg_byte_count = 0;
-
- WARN_ON_ONCE(skreq->data_dir != DMA_TO_DEVICE &&
- skreq->data_dir != DMA_FROM_DEVICE);
-
- n_sg = blk_rq_map_sg(skdev->queue, req, sgl);
- if (n_sg <= 0)
- return false;
-
- /*
- * Map scatterlist to PCI bus addresses.
- * Note PCI might change the number of entries.
- */
- n_sg = dma_map_sg(&skdev->pdev->dev, sgl, n_sg, skreq->data_dir);
- if (n_sg <= 0)
- return false;
-
- SKD_ASSERT(n_sg <= skdev->sgs_per_request);
-
- skreq->n_sg = n_sg;
-
- for_each_sg(sgl, sg, n_sg, i) {
- struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
- u32 cnt = sg_dma_len(sg);
- uint64_t dma_addr = sg_dma_address(sg);
-
- sgd->control = FIT_SGD_CONTROL_NOT_LAST;
- sgd->byte_count = cnt;
- skreq->sg_byte_count += cnt;
- sgd->host_side_addr = dma_addr;
- sgd->dev_side_addr = 0;
- }
-
- skreq->sksg_list[n_sg - 1].next_desc_ptr = 0LL;
- skreq->sksg_list[n_sg - 1].control = FIT_SGD_CONTROL_LAST;
-
- if (unlikely(skdev->dbg_level > 1)) {
- dev_dbg(&skdev->pdev->dev,
- "skreq=%x sksg_list=%p sksg_dma=%pad\n",
- skreq->id, skreq->sksg_list, &skreq->sksg_dma_address);
- for (i = 0; i < n_sg; i++) {
- struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
-
- dev_dbg(&skdev->pdev->dev,
- " sg[%d] count=%u ctrl=0x%x addr=0x%llx next=0x%llx\n",
- i, sgd->byte_count, sgd->control,
- sgd->host_side_addr, sgd->next_desc_ptr);
- }
- }
-
- return true;
-}
-
-static void skd_postop_sg_list(struct skd_device *skdev,
- struct skd_request_context *skreq)
-{
- /*
- * restore the next ptr for next IO request so we
- * don't have to set it every time.
- */
- skreq->sksg_list[skreq->n_sg - 1].next_desc_ptr =
- skreq->sksg_dma_address +
- ((skreq->n_sg) * sizeof(struct fit_sg_descriptor));
- dma_unmap_sg(&skdev->pdev->dev, &skreq->sg[0], skreq->n_sg,
- skreq->data_dir);
-}
-
-/*
- *****************************************************************************
- * TIMER
- *****************************************************************************
- */
-
-static void skd_timer_tick_not_online(struct skd_device *skdev);
-
-static void skd_start_queue(struct work_struct *work)
-{
- struct skd_device *skdev = container_of(work, typeof(*skdev),
- start_queue);
-
- /*
- * Although it is safe to call blk_start_queue() from interrupt
- * context, blk_mq_start_hw_queues() must not be called from
- * interrupt context.
- */
- blk_mq_start_hw_queues(skdev->queue);
-}
-
-static void skd_timer_tick(struct timer_list *t)
-{
- struct skd_device *skdev = from_timer(skdev, t, timer);
- unsigned long reqflags;
- u32 state;
-
- if (skdev->state == SKD_DRVR_STATE_FAULT)
- /* The driver has declared fault, and we want it to
- * stay that way until driver is reloaded.
- */
- return;
-
- spin_lock_irqsave(&skdev->lock, reqflags);
-
- state = SKD_READL(skdev, FIT_STATUS);
- state &= FIT_SR_DRIVE_STATE_MASK;
- if (state != skdev->drive_state)
- skd_isr_fwstate(skdev);
-
- if (skdev->state != SKD_DRVR_STATE_ONLINE)
- skd_timer_tick_not_online(skdev);
-
- mod_timer(&skdev->timer, (jiffies + HZ));
-
- spin_unlock_irqrestore(&skdev->lock, reqflags);
-}
-
-static void skd_timer_tick_not_online(struct skd_device *skdev)
-{
- switch (skdev->state) {
- case SKD_DRVR_STATE_IDLE:
- case SKD_DRVR_STATE_LOAD:
- break;
- case SKD_DRVR_STATE_BUSY_SANITIZE:
- dev_dbg(&skdev->pdev->dev,
- "drive busy sanitize[%x], driver[%x]\n",
- skdev->drive_state, skdev->state);
- /* If we've been in sanitize for 3 seconds, we figure we're not
- * going to get anymore completions, so recover requests now
- */
- if (skdev->timer_countdown > 0) {
- skdev->timer_countdown--;
- return;
- }
- skd_recover_requests(skdev);
- break;
-
- case SKD_DRVR_STATE_BUSY:
- case SKD_DRVR_STATE_BUSY_IMMINENT:
- case SKD_DRVR_STATE_BUSY_ERASE:
- dev_dbg(&skdev->pdev->dev, "busy[%x], countdown=%d\n",
- skdev->state, skdev->timer_countdown);
- if (skdev->timer_countdown > 0) {
- skdev->timer_countdown--;
- return;
- }
- dev_dbg(&skdev->pdev->dev,
- "busy[%x], timedout=%d, restarting device.",
- skdev->state, skdev->timer_countdown);
- skd_restart_device(skdev);
- break;
-
- case SKD_DRVR_STATE_WAIT_BOOT:
- case SKD_DRVR_STATE_STARTING:
- if (skdev->timer_countdown > 0) {
- skdev->timer_countdown--;
- return;
- }
- /* For now, we fault the drive. Could attempt resets to
- * revcover at some point. */
- skdev->state = SKD_DRVR_STATE_FAULT;
-
- dev_err(&skdev->pdev->dev, "DriveFault Connect Timeout (%x)\n",
- skdev->drive_state);
-
- /*start the queue so we can respond with error to requests */
- /* wakeup anyone waiting for startup complete */
- schedule_work(&skdev->start_queue);
- skdev->gendisk_on = -1;
- wake_up_interruptible(&skdev->waitq);
- break;
-
- case SKD_DRVR_STATE_ONLINE:
- /* shouldn't get here. */
- break;
-
- case SKD_DRVR_STATE_PAUSING:
- case SKD_DRVR_STATE_PAUSED:
- break;
-
- case SKD_DRVR_STATE_RESTARTING:
- if (skdev->timer_countdown > 0) {
- skdev->timer_countdown--;
- return;
- }
- /* For now, we fault the drive. Could attempt resets to
- * revcover at some point. */
- skdev->state = SKD_DRVR_STATE_FAULT;
- dev_err(&skdev->pdev->dev,
- "DriveFault Reconnect Timeout (%x)\n",
- skdev->drive_state);
-
- /*
- * Recovering does two things:
- * 1. completes IO with error
- * 2. reclaims dma resources
- * When is it safe to recover requests?
- * - if the drive state is faulted
- * - if the state is still soft reset after out timeout
- * - if the drive registers are dead (state = FF)
- * If it is "unsafe", we still need to recover, so we will
- * disable pci bus mastering and disable our interrupts.
- */
-
- if ((skdev->drive_state == FIT_SR_DRIVE_SOFT_RESET) ||
- (skdev->drive_state == FIT_SR_DRIVE_FAULT) ||
- (skdev->drive_state == FIT_SR_DRIVE_STATE_MASK))
- /* It never came out of soft reset. Try to
- * recover the requests and then let them
- * fail. This is to mitigate hung processes. */
- skd_recover_requests(skdev);
- else {
- dev_err(&skdev->pdev->dev, "Disable BusMaster (%x)\n",
- skdev->drive_state);
- pci_disable_device(skdev->pdev);
- skd_disable_interrupts(skdev);
- skd_recover_requests(skdev);
- }
-
- /*start the queue so we can respond with error to requests */
- /* wakeup anyone waiting for startup complete */
- schedule_work(&skdev->start_queue);
- skdev->gendisk_on = -1;
- wake_up_interruptible(&skdev->waitq);
- break;
-
- case SKD_DRVR_STATE_RESUMING:
- case SKD_DRVR_STATE_STOPPING:
- case SKD_DRVR_STATE_SYNCING:
- case SKD_DRVR_STATE_FAULT:
- case SKD_DRVR_STATE_DISAPPEARED:
- default:
- break;
- }
-}
-
-static int skd_start_timer(struct skd_device *skdev)
-{
- int rc;
-
- timer_setup(&skdev->timer, skd_timer_tick, 0);
-
- rc = mod_timer(&skdev->timer, (jiffies + HZ));
- if (rc)
- dev_err(&skdev->pdev->dev, "failed to start timer %d\n", rc);
- return rc;
-}
-
-static void skd_kill_timer(struct skd_device *skdev)
-{
- del_timer_sync(&skdev->timer);
-}
-
-/*
- *****************************************************************************
- * INTERNAL REQUESTS -- generated by driver itself
- *****************************************************************************
- */
-
-static int skd_format_internal_skspcl(struct skd_device *skdev)
-{
- struct skd_special_context *skspcl = &skdev->internal_skspcl;
- struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
- struct fit_msg_hdr *fmh;
- uint64_t dma_address;
- struct skd_scsi_request *scsi;
-
- fmh = &skspcl->msg_buf->fmh;
- fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
- fmh->num_protocol_cmds_coalesced = 1;
-
- scsi = &skspcl->msg_buf->scsi[0];
- memset(scsi, 0, sizeof(*scsi));
- dma_address = skspcl->req.sksg_dma_address;
- scsi->hdr.sg_list_dma_address = cpu_to_be64(dma_address);
- skspcl->req.n_sg = 1;
- sgd->control = FIT_SGD_CONTROL_LAST;
- sgd->byte_count = 0;
- sgd->host_side_addr = skspcl->db_dma_address;
- sgd->dev_side_addr = 0;
- sgd->next_desc_ptr = 0LL;
-
- return 1;
-}
-
-#define WR_BUF_SIZE SKD_N_INTERNAL_BYTES
-
-static void skd_send_internal_skspcl(struct skd_device *skdev,
- struct skd_special_context *skspcl,
- u8 opcode)
-{
- struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
- struct skd_scsi_request *scsi;
- unsigned char *buf = skspcl->data_buf;
- int i;
-
- if (skspcl->req.state != SKD_REQ_STATE_IDLE)
- /*
- * A refresh is already in progress.
- * Just wait for it to finish.
- */
- return;
-
- skspcl->req.state = SKD_REQ_STATE_BUSY;
-
- scsi = &skspcl->msg_buf->scsi[0];
- scsi->hdr.tag = skspcl->req.id;
-
- memset(scsi->cdb, 0, sizeof(scsi->cdb));
-
- switch (opcode) {
- case TEST_UNIT_READY:
- scsi->cdb[0] = TEST_UNIT_READY;
- sgd->byte_count = 0;
- scsi->hdr.sg_list_len_bytes = 0;
- break;
-
- case READ_CAPACITY:
- scsi->cdb[0] = READ_CAPACITY;
- sgd->byte_count = SKD_N_READ_CAP_BYTES;
- scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
- break;
-
- case INQUIRY:
- scsi->cdb[0] = INQUIRY;
- scsi->cdb[1] = 0x01; /* evpd */
- scsi->cdb[2] = 0x80; /* serial number page */
- scsi->cdb[4] = 0x10;
- sgd->byte_count = 16;
- scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
- break;
-
- case SYNCHRONIZE_CACHE:
- scsi->cdb[0] = SYNCHRONIZE_CACHE;
- sgd->byte_count = 0;
- scsi->hdr.sg_list_len_bytes = 0;
- break;
-
- case WRITE_BUFFER:
- scsi->cdb[0] = WRITE_BUFFER;
- scsi->cdb[1] = 0x02;
- scsi->cdb[7] = (WR_BUF_SIZE & 0xFF00) >> 8;
- scsi->cdb[8] = WR_BUF_SIZE & 0xFF;
- sgd->byte_count = WR_BUF_SIZE;
- scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
- /* fill incrementing byte pattern */
- for (i = 0; i < sgd->byte_count; i++)
- buf[i] = i & 0xFF;
- break;
-
- case READ_BUFFER:
- scsi->cdb[0] = READ_BUFFER;
- scsi->cdb[1] = 0x02;
- scsi->cdb[7] = (WR_BUF_SIZE & 0xFF00) >> 8;
- scsi->cdb[8] = WR_BUF_SIZE & 0xFF;
- sgd->byte_count = WR_BUF_SIZE;
- scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
- memset(skspcl->data_buf, 0, sgd->byte_count);
- break;
-
- default:
- SKD_ASSERT("Don't know what to send");
- return;
-
- }
- skd_send_special_fitmsg(skdev, skspcl);
-}
-
-static void skd_refresh_device_data(struct skd_device *skdev)
-{
- struct skd_special_context *skspcl = &skdev->internal_skspcl;
-
- skd_send_internal_skspcl(skdev, skspcl, TEST_UNIT_READY);
-}
-
-static int skd_chk_read_buf(struct skd_device *skdev,
- struct skd_special_context *skspcl)
-{
- unsigned char *buf = skspcl->data_buf;
- int i;
-
- /* check for incrementing byte pattern */
- for (i = 0; i < WR_BUF_SIZE; i++)
- if (buf[i] != (i & 0xFF))
- return 1;
-
- return 0;
-}
-
-static void skd_log_check_status(struct skd_device *skdev, u8 status, u8 key,
- u8 code, u8 qual, u8 fruc)
-{
- /* If the check condition is of special interest, log a message */
- if ((status == SAM_STAT_CHECK_CONDITION) && (key == 0x02)
- && (code == 0x04) && (qual == 0x06)) {
- dev_err(&skdev->pdev->dev,
- "*** LOST_WRITE_DATA ERROR *** key/asc/ascq/fruc %02x/%02x/%02x/%02x\n",
- key, code, qual, fruc);
- }
-}
-
-static void skd_complete_internal(struct skd_device *skdev,
- struct fit_completion_entry_v1 *skcomp,
- struct fit_comp_error_info *skerr,
- struct skd_special_context *skspcl)
-{
- u8 *buf = skspcl->data_buf;
- u8 status;
- int i;
- struct skd_scsi_request *scsi = &skspcl->msg_buf->scsi[0];
-
- lockdep_assert_held(&skdev->lock);
-
- SKD_ASSERT(skspcl == &skdev->internal_skspcl);
-
- dev_dbg(&skdev->pdev->dev, "complete interna