Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI updates from James Bottomley:
 "First round of SCSI updates for the 4.4 merge window.

  This batch includes a couple of minor fixes, some core changes to help
  issues we're still seeing with the suspend/resume code and updates to
  lpfc and cxlflash.

  We're (actually Martin Petersen is) trying to wrangle a mpt2/mpt3sas
  merger for the merge window which will help enormously with the
  maintenance burden, so there will be another round before it closes"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (56 commits)
  cxlflash: Fix to avoid bypassing context cleanup
  cxlflash: Fix to avoid lock instrumentation rejection
  cxlflash: Fix to avoid corrupting port selection mask
  cxlflash: Fix to escalate to LINK_RESET on login timeout
  cxlflash: Fix to avoid leaving dangling interrupt resources
  cxlflash: Fix to avoid potential deadlock on EEH
  cxlflash: Correct trace string
  cxlflash: Fix to avoid corrupting adapter fops
  cxlflash: Fix to double the delay each time
  MAINTAINERS: Add cxlflash driver
  cxlflash: Fix to prevent stale AFU RRQ
  cxlflash: Correct spelling, grammar, and alignment mistakes
  cxlflash: Fix to prevent EEH recovery failure
  cxlflash: Fix MMIO and endianness errors
  cxlflash: Fix function prolog parameters and return codes
  cxlflash: Remove unnecessary scsi_block_requests
  cxlflash: Correct behavior in device reset handler following EEH
  cxlflash: Fix to prevent workq from accessing freed memory
  cxlflash: Correct usage of scsi_host_put()
  cxlflash: Fix AFU version access/storage and add check
  ...
This commit is contained in:
Linus Torvalds
2015-11-05 16:20:21 -08:00
37 changed files with 1317 additions and 1138 deletions
+11 -2
View File
@@ -3186,6 +3186,15 @@ F: Documentation/powerpc/cxl.txt
F: Documentation/powerpc/cxl.txt
F: Documentation/ABI/testing/sysfs-class-cxl
CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
M: Manoj N. Kumar <manoj@linux.vnet.ibm.com>
M: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/cxlflash/
F: include/uapi/scsi/cxlflash_ioctls.h
F: Documentation/powerpc/cxlflash.txt
STMMAC ETHERNET DRIVER
M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
L: netdev@vger.kernel.org
@@ -9473,8 +9482,8 @@ F: include/uapi/linux/phantom.h
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com>
M: Minh Tran <minh.tran@avagotech.com>
M: John Soni Jose <sony.john-n@avagotech.com>
M: Ketan Mukadam <ketan.mukadam@avagotech.com>
M: John Soni Jose <sony.john@avagotech.com>
L: linux-scsi@vger.kernel.org
W: http://www.avagotech.com
S: Supported
+2 -2
View File
@@ -1,9 +1,9 @@
config BE2ISCSI
tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2"
tristate "Emulex 10Gbps iSCSI - BladeEngine 2"
depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS
select ISCSI_BOOT_SYSFS
help
This driver implements the iSCSI functionality for ServerEngines'
This driver implements the iSCSI functionality for Emulex
10Gbps Storage adapter - BladeEngine 2.
+1 -1
View File
@@ -1,5 +1,5 @@
#
# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
# Makefile to build the iSCSI driver for Emulex OneConnect.
#
#
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
+4 -4
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -50,7 +50,7 @@ static unsigned int enable_msix = 1;
MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
MODULE_VERSION(BUILD_STR);
MODULE_AUTHOR("Avago Technologies");
MODULE_AUTHOR("Emulex Corporation");
MODULE_LICENSE("GPL");
module_param(be_iopoll_budget, int, 0);
module_param(enable_msix, int, 0);
@@ -552,7 +552,7 @@ MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
static struct scsi_host_template beiscsi_sht = {
.module = THIS_MODULE,
.name = "Avago Technologies 10Gbe open-iscsi Initiator Driver",
.name = "Emulex 10Gbe open-iscsi Initiator Driver",
.proc_name = DRV_NAME,
.queuecommand = iscsi_queuecommand,
.change_queue_depth = scsi_change_queue_depth,
+3 -3
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -37,7 +37,7 @@
#define DRV_NAME "be2iscsi"
#define BUILD_STR "10.6.0.0"
#define BE_NAME "Avago Technologies OneConnect" \
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2015 Avago Technologies
* Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
* Avago Technologies
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
-1
View File
@@ -856,7 +856,6 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
return;
default:
printk(KERN_ERR PFX "Unknown netevent %ld", event);
return;
}
+13 -17
View File
@@ -16,10 +16,12 @@
#define _CXLFLASH_COMMON_H
#include <linux/list.h>
#include <linux/rwsem.h>
#include <linux/types.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
extern const struct file_operations cxlflash_cxl_fops;
#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */
@@ -78,7 +80,7 @@ enum cxlflash_init_state {
enum cxlflash_state {
STATE_NORMAL, /* Normal running state, everything good */
STATE_LIMBO, /* Limbo running state, trying to reset/recover */
STATE_RESET, /* Reset state, trying to reset/recover */
STATE_FAILTERM /* Failed/terminating state, error out users/threads */
};
@@ -101,29 +103,28 @@ struct cxlflash_cfg {
enum cxlflash_init_state init_state;
enum cxlflash_lr_state lr_state;
int lr_port;
atomic_t scan_host_needed;
struct cxl_afu *cxl_afu;
struct pci_pool *cxlflash_cmd_pool;
struct pci_dev *parent_dev;
atomic_t recovery_threads;
struct mutex ctx_recovery_mutex;
struct mutex ctx_tbl_list_mutex;
struct rw_semaphore ioctl_rwsem;
struct ctx_info *ctx_tbl[MAX_CONTEXT];
struct list_head ctx_err_recovery; /* contexts w/ recovery pending */
struct file_operations cxl_fops;
atomic_t num_user_contexts;
/* Parameters that are LUN table related */
int last_lun_index[CXLFLASH_NUM_FC_PORTS];
int promote_lun_index;
struct list_head lluns; /* list of llun_info structs */
wait_queue_head_t tmf_waitq;
spinlock_t tmf_slock;
bool tmf_active;
wait_queue_head_t limbo_waitq;
wait_queue_head_t reset_waitq;
enum cxlflash_state state;
};
@@ -160,9 +161,9 @@ struct afu {
/* AFU HW */
struct cxl_ioctl_start_work work;
struct cxlflash_afu_map *afu_map; /* entire MMIO map */
struct sisl_host_map *host_map; /* MC host map */
struct sisl_ctrl_map *ctrl_map; /* MC control map */
struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */
struct sisl_host_map __iomem *host_map; /* MC host map */
struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
ctx_hndl_t ctx_hndl; /* master's context handle */
u64 *hrrq_start;
@@ -175,7 +176,7 @@ struct afu {
u32 cmd_couts; /* Number of command checkouts */
u32 internal_lun; /* User-desired LUN mode for this AFU */
char version[8];
char version[16];
u64 interface_version;
struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
@@ -184,17 +185,12 @@ struct afu {
static inline u64 lun_to_lunid(u64 lun)
{
u64 lun_id;
__be64 lun_id;
int_to_scsilun(lun, (struct scsi_lun *)&lun_id);
return swab64(lun_id);
return be64_to_cpu(lun_id);
}
int cxlflash_send_cmd(struct afu *, struct afu_cmd *);
void cxlflash_wait_resp(struct afu *, struct afu_cmd *);
int cxlflash_afu_reset(struct cxlflash_cfg *);
struct afu_cmd *cxlflash_cmd_checkout(struct afu *);
void cxlflash_cmd_checkin(struct afu_cmd *);
int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8);
void cxlflash_list_init(void);
void cxlflash_term_global_luns(void);
+24 -21
View File
@@ -41,7 +41,6 @@ static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
}
lli->sdev = sdev;
lli->newly_created = true;
lli->host_no = sdev->host->host_no;
lli->in_table = false;
@@ -74,24 +73,19 @@ out:
}
/**
* refresh_local() - find and update local LUN information structure by WWID
* lookup_local() - find a local LUN information structure by WWID
* @cfg: Internal structure associated with the host.
* @wwid: WWID associated with LUN.
*
* When the LUN is found, mark it by updating it's newly_created field.
*
* Return: Found local lun_info structure on success, NULL on failure
* If a LUN with the WWID is found in the list, refresh it's state.
*/
static struct llun_info *refresh_local(struct cxlflash_cfg *cfg, u8 *wwid)
static struct llun_info *lookup_local(struct cxlflash_cfg *cfg, u8 *wwid)
{
struct llun_info *lli, *temp;
list_for_each_entry_safe(lli, temp, &cfg->lluns, list)
if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN)) {
lli->newly_created = false;
if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
return lli;
}
return NULL;
}
@@ -120,7 +114,8 @@ static struct glun_info *lookup_global(u8 *wwid)
*
* The LUN is kept both in a local list (per adapter) and in a global list
* (across all adapters). Certain attributes of the LUN are local to the
* adapter (such as index, port selection mask etc.).
* adapter (such as index, port selection mask, etc.).
*
* The block allocation map is shared across all adapters (i.e. associated
* wih the global list). Since different attributes are associated with
* the per adapter and global entries, allocate two separate structures for each
@@ -128,6 +123,8 @@ static struct glun_info *lookup_global(u8 *wwid)
*
* Keep a pointer back from the local to the global entry.
*
* This routine assumes the caller holds the global mutex.
*
* Return: Found/Allocated local lun_info structure on success, NULL on failure
*/
static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
@@ -137,11 +134,10 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
struct Scsi_Host *shost = sdev->host;
struct cxlflash_cfg *cfg = shost_priv(shost);
mutex_lock(&global.mutex);
if (unlikely(!wwid))
goto out;
lli = refresh_local(cfg, wwid);
lli = lookup_local(cfg, wwid);
if (lli)
goto out;
@@ -169,7 +165,6 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
list_add(&gli->list, &global.gluns);
out:
mutex_unlock(&global.mutex);
pr_debug("%s: returning %p\n", __func__, lli);
return lli;
}
@@ -235,10 +230,11 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
u64 flags = manage->hdr.flags;
u32 chan = sdev->channel;
mutex_lock(&global.mutex);
lli = find_and_create_lun(sdev, manage->wwid);
pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n",
__func__, get_unaligned_le64(&manage->wwid[0]),
get_unaligned_le64(&manage->wwid[8]),
__func__, get_unaligned_be64(&manage->wwid[0]),
get_unaligned_be64(&manage->wwid[8]),
manage->hdr.flags, lli);
if (unlikely(!lli)) {
rc = -ENOMEM;
@@ -246,21 +242,28 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
}
if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) {
if (lli->newly_created)
lli->port_sel = CHAN2PORT(chan);
else
lli->port_sel = BOTH_PORTS;
/* Store off lun in unpacked, AFU-friendly format */
/*
* Update port selection mask based upon channel, store off LUN
* in unpacked, AFU-friendly format, and hang LUN reference in
* the sdev.
*/
lli->port_sel |= CHAN2PORT(chan);
lli->lun_id[chan] = lun_to_lunid(sdev->lun);
sdev->hostdata = lli;
} else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
if (lli->parent->mode != MODE_NONE)
rc = -EBUSY;
else
else {
sdev->hostdata = NULL;
lli->port_sel &= ~CHAN2PORT(chan);
}
}
pr_debug("%s: port_sel = %08X chan = %u lun_id = %016llX\n", __func__,
lli->port_sel, chan, lli->lun_id[chan]);
out:
mutex_unlock(&global.mutex);
pr_debug("%s: returning rc=%d\n", __func__, rc);
return rc;
}
File diff suppressed because it is too large Load Diff
+1
View File
@@ -99,6 +99,7 @@ struct asyc_intr_info {
u8 action;
#define CLR_FC_ERROR 0x01
#define LINK_RESET 0x02
#define SCAN_HOST 0x04
};
#ifndef CONFIG_CXL_EEH
+4 -4
View File
@@ -146,7 +146,7 @@ struct sisl_rc {
#define SISL_FC_RC_ABORTFAIL 0x59 /* pending abort completed w/fail */
#define SISL_FC_RC_RESID 0x5A /* ioasa underrun/overrun flags set */
#define SISL_FC_RC_RESIDERR 0x5B /* actual data len does not match SCSI
reported len, possbly due to dropped
reported len, possibly due to dropped
frames */
#define SISL_FC_RC_TGTABORT 0x5C /* command aborted by target */
};
@@ -258,7 +258,7 @@ struct sisl_host_map {
__be64 rrq_start; /* start & end are both inclusive */
__be64 rrq_end; /* write sequence: start followed by end */
__be64 cmd_room;
__be64 ctx_ctrl; /* least signiifcant byte or b56:63 is LISN# */
__be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */
__be64 mbox_w; /* restricted use */
};
@@ -290,7 +290,7 @@ struct sisl_global_regs {
#define SISL_ASTATUS_FC0_LOGO 0x4000ULL /* b49, target sent FLOGI/PLOGI/LOGO
while logged in */
#define SISL_ASTATUS_FC0_CRC_T 0x2000ULL /* b50, CRC threshold exceeded */
#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state mechine timed out
#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state machine timed out
and retrying */
#define SISL_ASTATUS_FC0_LOGI_F 0x0800ULL /* b52, login failed,
FC_ERROR[19:0] */
@@ -340,7 +340,7 @@ struct sisl_global_regs {
#define SISL_AFUCONF_MBOX_CLR_READ 0x0010ULL
__be64 afu_config;
__be64 rsvd[0xf8];
__be64 afu_version;
__le64 afu_version;
__be64 interface_version;
};
+134 -75
View File
@@ -76,7 +76,7 @@ void cxlflash_free_errpage(void)
*
* When the host needs to go down, all users must be quiesced and their
* memory freed. This is accomplished by putting the contexts in error
* state which will notify the user and let them 'drive' the tear-down.
* state which will notify the user and let them 'drive' the tear down.
* Meanwhile, this routine camps until all user contexts have been removed.
*/
void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
@@ -100,7 +100,7 @@ void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
dev_dbg(dev, "%s: Wait for user contexts to quiesce...\n",
__func__);
wake_up_all(&cfg->limbo_waitq);
wake_up_all(&cfg->reset_waitq);
ssleep(1);
}
}
@@ -162,10 +162,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid,
if (likely(ctxid < MAX_CONTEXT)) {
while (true) {
rc = mutex_lock_interruptible(&cfg->ctx_tbl_list_mutex);
if (rc)
goto out;
mutex_lock(&cfg->ctx_tbl_list_mutex);
ctxi = cfg->ctx_tbl[ctxid];
if (ctxi)
if ((file && (ctxi->file != file)) ||
@@ -253,7 +250,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
{
struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu;
struct sisl_ctrl_map *ctrl_map = ctxi->ctrl_map;
struct sisl_ctrl_map __iomem *ctrl_map = ctxi->ctrl_map;
int rc = 0;
u64 val;
@@ -283,6 +280,24 @@ out:
* @sdev: SCSI device associated with LUN.
* @lli: LUN destined for capacity request.
*
* The READ_CAP16 can take quite a while to complete. Should an EEH occur while
* in scsi_execute(), the EEH handler will attempt to recover. As part of the
* recovery, the handler drains all currently running ioctls, waiting until they
* have completed before proceeding with a reset. As this routine is used on the
* ioctl path, this can create a condition where the EEH handler becomes stuck,
* infinitely waiting for this ioctl thread. To avoid this behavior, temporarily
* unmark this thread as an ioctl thread by releasing the ioctl read semaphore.
* This will allow the EEH handler to proceed with a recovery while this thread
* is still running. Once the scsi_execute() returns, reacquire the ioctl read
* semaphore and check the adapter state in case it changed while inside of
* scsi_execute(). The state check will wait if the adapter is still being
* recovered or return a failure if the recovery failed. In the event that the
* adapter reset failed, simply return the failure as the ioctl would be unable
* to continue.
*
* Note that the above puts a requirement on this routine to only be called on
* an ioctl thread.
*
* Return: 0 on success, -errno on failure
*/
static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
@@ -296,7 +311,7 @@ static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
int rc = 0;
int result = 0;
int retry_cnt = 0;
u32 tout = (MC_DISCOVERY_TIMEOUT * HZ);
u32 to = CMD_TIMEOUT * HZ;
retry:
cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL);
@@ -314,8 +329,18 @@ retry:
dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__,
retry_cnt ? "re" : "", scsi_cmd[0]);
/* Drop the ioctl read semahpore across lengthy call */
up_read(&cfg->ioctl_rwsem);
result = scsi_execute(sdev, scsi_cmd, DMA_FROM_DEVICE, cmd_buf,
CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL);
CMD_BUFSIZE, sense_buf, to, CMD_RETRIES, 0, NULL);
down_read(&cfg->ioctl_rwsem);
rc = check_state(cfg);
if (rc) {
dev_err(dev, "%s: Failed state! result=0x08%X\n",
__func__, result);
rc = -ENODEV;
goto out;
}
if (driver_byte(result) == DRIVER_SENSE) {
result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
@@ -365,8 +390,8 @@ retry:
* as the buffer is allocated on an aligned boundary.
*/
mutex_lock(&gli->mutex);
gli->max_lba = be64_to_cpu(*((u64 *)&cmd_buf[0]));
gli->blk_len = be32_to_cpu(*((u32 *)&cmd_buf[8]));
gli->max_lba = be64_to_cpu(*((__be64 *)&cmd_buf[0]));
gli->blk_len = be32_to_cpu(*((__be32 *)&cmd_buf[8]));
mutex_unlock(&gli->mutex);
out:
@@ -712,7 +737,6 @@ static void destroy_context(struct cxlflash_cfg *cfg,
kfree(ctxi->rht_needs_ws);
kfree(ctxi->rht_lun);
kfree(ctxi);
atomic_dec_if_positive(&cfg->num_user_contexts);
}
/**
@@ -737,7 +761,7 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
struct afu *afu = cfg->afu;
struct ctx_info *ctxi = NULL;
struct llun_info **lli = NULL;
bool *ws = NULL;
u8 *ws = NULL;
struct sisl_rht_entry *rhte;
ctxi = kzalloc(sizeof(*ctxi), GFP_KERNEL);
@@ -769,7 +793,6 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
INIT_LIST_HEAD(&ctxi->luns);
INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
atomic_inc(&cfg->num_user_contexts);
mutex_lock(&ctxi->mutex);
out:
return ctxi;
@@ -880,6 +903,9 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
sys_close(lfd);
}
/* Release the sdev reference that bound this LUN to the context */
scsi_device_put(sdev);
out:
if (put_ctx)
put_context(ctxi);
@@ -1161,10 +1187,7 @@ out:
return rc;
}
/*
* Local fops for adapter file descriptor
*/
static const struct file_operations cxlflash_cxl_fops = {
const struct file_operations cxlflash_cxl_fops = {
.owner = THIS_MODULE,
.mmap = cxlflash_cxl_mmap,
.release = cxlflash_cxl_release,
@@ -1210,6 +1233,46 @@ static const struct file_operations null_fops = {
.owner = THIS_MODULE,
};
/**
* check_state() - checks and responds to the current adapter state
* @cfg: Internal structure associated with the host.
*
* This routine can block and should only be used on process context.
* It assumes that the caller is an ioctl thread and holding the ioctl
* read semaphore. This is temporarily let up across the wait to allow
* for draining actively running ioctls. Also note that when waking up
* from waiting in reset, the state is unknown and must be checked again
* before proceeding.
*
* Return: 0 on success, -errno on failure
*/
int check_state(struct cxlflash_cfg *cfg)
{
struct device *dev = &cfg->dev->dev;
int rc = 0;
retry:
switch (cfg->state) {
case STATE_RESET:
dev_dbg(dev, "%s: Reset state, going to wait...\n", __func__);
up_read(&cfg->ioctl_rwsem);
rc = wait_event_interruptible(cfg->reset_waitq,
cfg->state != STATE_RESET);
down_read(&cfg->ioctl_rwsem);
if (unlikely(rc))
break;
goto retry;
case STATE_FAILTERM:
dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
rc = -ENODEV;
break;
default:
break;
}
return rc;
}
/**
* cxlflash_disk_attach() - attach a LUN to a context
* @sdev: SCSI device associated with LUN.
@@ -1243,10 +1306,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
int fd = -1;
/* On first attach set fileops */
if (atomic_read(&cfg->num_user_contexts) == 0)
cfg->cxl_fops = cxlflash_cxl_fops;
if (attach->num_interrupts > 4) {
dev_dbg(dev, "%s: Cannot support this many interrupts %llu\n",
__func__, attach->num_interrupts);
@@ -1287,11 +1346,17 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
}
}
rc = scsi_device_get(sdev);
if (unlikely(rc)) {
dev_err(dev, "%s: Unable to get sdev reference!\n", __func__);
goto out;
}
lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL);
if (unlikely(!lun_access)) {
dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__);
rc = -ENOMEM;
goto out;
goto err0;
}
lun_access->lli = lli;
@@ -1311,21 +1376,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
dev_err(dev, "%s: Could not initialize context %p\n",
__func__, ctx);
rc = -ENODEV;
goto err0;
goto err1;
}
ctxid = cxl_process_element(ctx);
if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM;
goto err1;
goto err2;
}
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) {
rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__);
goto err1;
goto err2;
}
/* Translate read/write O_* flags from fcntl.h to AFU permission bits */
@@ -1335,7 +1400,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n",
__func__, ctxid);
goto err2;
goto err3;
}
work = &ctxi->work;
@@ -1346,13 +1411,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc);
goto err3;
goto err4;
}
rc = afu_attach(cfg, ctxi);
if (unlikely(rc)) {
dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc);
goto err4;
goto err5;
}
/*
@@ -1375,7 +1440,8 @@ out_attach:
attach->block_size = gli->blk_len;
attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
attach->last_lba = gli->max_lba;
attach->max_xfer = (sdev->host->max_sectors * 512) / gli->blk_len;
attach->max_xfer = sdev->host->max_sectors * MAX_SECTOR_UNIT;
attach->max_xfer /= gli->blk_len;
out:
attach->adap_fd = fd;
@@ -1387,13 +1453,13 @@ out:
__func__, ctxid, fd, attach->block_size, rc, attach->last_lba);
return rc;
err4:
err5:
cxl_stop_context(ctx);
err3:
err4:
put_context(ctxi);
destroy_context(cfg, ctxi);
ctxi = NULL;
err2:
err3:
/*
* Here, we're overriding the fops with a dummy all-NULL fops because
* fput() calls the release fop, which will cause us to mistakenly
@@ -1405,10 +1471,12 @@ err2:
fput(file);
put_unused_fd(fd);
fd = -1;
err1:
err2:
cxl_release_context(ctx);
err0:
err1:
kfree(lun_access);
err0:
scsi_device_put(sdev);
goto out;
}
@@ -1510,41 +1578,6 @@ err1:
goto out;
}
/**
* check_state() - checks and responds to the current adapter state
* @cfg: Internal structure associated with the host.
*
* This routine can block and should only be used on process context.
* Note that when waking up from waiting in limbo, the state is unknown
* and must be checked again before proceeding.
*
* Return: 0 on success, -errno on failure
*/
static int check_state(struct cxlflash_cfg *cfg)
{
struct device *dev = &cfg->dev->dev;
int rc = 0;
retry:
switch (cfg->state) {
case STATE_LIMBO:
dev_dbg(dev, "%s: Limbo, going to wait...\n", __func__);
rc = wait_event_interruptible(cfg->limbo_waitq,
cfg->state != STATE_LIMBO);
if (unlikely(rc))
break;
goto retry;
case STATE_FAILTERM:
dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
rc = -ENODEV;
break;
default:
break;
}
return rc;
}
/**
* cxlflash_afu_recover() - initiates AFU recovery
* @sdev: SCSI device associated with LUN.
@@ -1561,10 +1594,10 @@ retry:
* quite possible for this routine to act as the kernel's EEH detection
* source (MMIO read of mbox_r). Because of this, there is a window of
* time where an EEH might have been detected but not yet 'serviced'
* (callback invoked, causing the device to enter limbo state). To avoid
* (callback invoked, causing the device to enter reset state). To avoid
* looping in this routine during that window, a 1 second sleep is in place
* between the time the MMIO failure is detected and the time a wait on the
* limbo wait queue is attempted via check_state().
* reset wait queue is attempted via check_state().
*
* Return: 0 on success, -errno on failure
*/
@@ -1634,9 +1667,14 @@ retry_recover:
/* Test if in error state */
reg = readq_be(&afu->ctrl_map->mbox_r);
if (reg == -1) {
dev_dbg(dev, "%s: MMIO read fail! Wait for recovery...\n",
__func__);
mutex_unlock(&ctxi->mutex);
dev_dbg(dev, "%s: MMIO fail, wait for recovery.\n", __func__);
/*
* Before checking the state, put back the context obtained with
* get_context() as it is no longer needed and sleep for a short
* period of time (see prolog notes).
*/
put_context(ctxi);
ctxi = NULL;
ssleep(1);
rc = check_state(cfg);
@@ -1765,12 +1803,21 @@ static int cxlflash_disk_verify(struct scsi_device *sdev,
* inquiry (i.e. the Unit attention is due to the WWN changing).
*/
if (verify->hint & DK_CXLFLASH_VERIFY_HINT_SENSE) {
/* Can't hold mutex across process_sense/read_cap16,
* since we could have an intervening EEH event.
*/
ctxi->unavail = true;
mutex_unlock(&ctxi->mutex);
rc = process_sense(sdev, verify);
if (unlikely(rc)) {
dev_err(dev, "%s: Failed to validate sense data (%d)\n",
__func__, rc);
mutex_lock(&ctxi->mutex);
ctxi->unavail = false;
goto out;
}
mutex_lock(&ctxi->mutex);
ctxi->unavail = false;
}
switch (gli->mode) {
@@ -1955,6 +2002,14 @@ out:
* @cmd: IOCTL command.
* @arg: Userspace ioctl data structure.
*
* A read/write semaphore is used to implement a 'drain' of currently
* running ioctls. The read semaphore is taken at the beginning of each
* ioctl thread and released upon concluding execution. Additionally the
* semaphore should be released and then reacquired in any ioctl execution
* path which will wait for an event to occur that is outside the scope of
* the ioctl (i.e. an adapter reset). To drain the ioctls currently running,
* a thread simply needs to acquire the write semaphore.
*
* Return: 0 on success, -errno on failure
*/
int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
@@ -1989,6 +2044,9 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{sizeof(struct dk_cxlflash_clone), (sioctl)cxlflash_disk_clone},
};
/* Hold read semaphore so we can drain if needed */
down_read(&cfg->ioctl_rwsem);
/* Restrict command set to physical support only for internal LUN */
if (afu->internal_lun)
switch (cmd) {
@@ -2070,6 +2128,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
/* fall through to exit */
cxlflash_ioctl_exit:
up_read(&cfg->ioctl_rwsem);
if (unlikely(rc && known_ioctl))
dev_err(dev, "%s: ioctl %s (%08X) on dev(%d/%d/%d/%llu) "
"returned rc %d\n", __func__,
+9 -5
View File
@@ -28,7 +28,10 @@ extern struct cxlflash_global global;
*/
#define MC_CHUNK_SIZE (1 << MC_RHT_NMASK) /* in LBAs */
#define MC_DISCOVERY_TIMEOUT 5 /* 5 secs */
#define CMD_TIMEOUT 30 /* 30 secs */
#define CMD_RETRIES 5 /* 5 retries for scsi_execute */
#define MAX_SECTOR_UNIT 512 /* max_sector is in 512 byte multiples */
#define CHAN2PORT(_x) ((_x) + 1)
#define PORT2CHAN(_x) ((_x) - 1)
@@ -60,7 +63,6 @@ struct llun_info {
u32 lun_index; /* Index in the LUN table */
u32 host_no; /* host_no from Scsi_host */
u32 port_sel; /* What port to use for this LUN */
bool newly_created; /* Whether the LUN was just discovered */
bool in_table; /* Whether a LUN table entry was created */
u8 wwid[16]; /* Keep a duplicate copy here? */
@@ -84,17 +86,17 @@ enum ctx_ctrl {
CTX_CTRL_FILE = (1 << 5)
};
#define ENCODE_CTXID(_ctx, _id) (((((u64)_ctx) & 0xFFFFFFFF0) << 28) | _id)
#define ENCODE_CTXID(_ctx, _id) (((((u64)_ctx) & 0xFFFFFFFF0ULL) << 28) | _id)
#define DECODE_CTXID(_val) (_val & 0xFFFFFFFF)
struct ctx_info {
struct sisl_ctrl_map *ctrl_map; /* initialized at startup */
struct sisl_ctrl_map __iomem *ctrl_map; /* initialized at startup */
struct sisl_rht_entry *rht_start; /* 1 page (req'd for alignment),
alloc/free on attach/detach */
u32 rht_out; /* Number of checked out RHT entries */
u32 rht_perms; /* User-defined permissions for RHT entries */
struct llun_info **rht_lun; /* Mapping of RHT entries to LUNs */
bool *rht_needs_ws; /* User-desired write-same function per RHTE */
u8 *rht_needs_ws; /* User-desired write-same function per RHTE */
struct cxl_ioctl_start_work work;
u64 ctxid;
@@ -144,4 +146,6 @@ void cxlflash_ba_terminate(struct ba_lun *);
int cxlflash_manage_lun(struct scsi_device *, struct dk_cxlflash_manage_lun *);
int check_state(struct cxlflash_cfg *);
#endif /* ifndef _CXLFLASH_SUPERPIPE_H */
+49 -19
View File
@@ -132,7 +132,7 @@ static int ba_init(struct ba_lun *ba_lun)
return -ENOMEM;
}
/* Pass the allocated lun info as a handle to the user */
/* Pass the allocated LUN info as a handle to the user */
ba_lun->ba_lun_handle = bali;
pr_debug("%s: Successfully initialized the LUN: "
@@ -165,7 +165,7 @@ static int find_free_range(u32 low,
num_bits = (sizeof(*lam) * BITS_PER_BYTE);
bit_pos = find_first_bit(lam, num_bits);
pr_devel("%s: Found free bit %llX in lun "
pr_devel("%s: Found free bit %llX in LUN "
"map entry %llX at bitmap index = %X\n",
__func__, bit_pos, bali->lun_alloc_map[i],
i);
@@ -400,6 +400,24 @@ static int init_vlun(struct llun_info *lli)
* @lba: Logical block address to start write same.
* @nblks: Number of logical blocks to write same.
*
* The SCSI WRITE_SAME16 can take quite a while to complete. Should an EEH occur
* while in scsi_execute(), the EEH handler will attempt to recover. As part of
* the recovery, the handler drains all currently running ioctls, waiting until
* they have completed before proceeding with a reset. As this routine is used
* on the ioctl path, this can create a condition where the EEH handler becomes
* stuck, infinitely waiting for this ioctl thread. To avoid this behavior,
* temporarily unmark this thread as an ioctl thread by releasing the ioctl read
* semaphore. This will allow the EEH handler to proceed with a recovery while
* this thread is still running. Once the scsi_execute() returns, reacquire the
* ioctl read semaphore and check the adapter state in case it changed while
* inside of scsi_execute(). The state check will wait if the adapter is still
* being recovered or return a failure if the recovery failed. In the event that
* the adapter reset failed, simply return the failure as the ioctl would be
* unable to continue.
*
* Note that the above puts a requirement on this routine to only be called on
* an ioctl thread.
*
* Return: 0 on success, -errno on failure
*/
static int write_same16(struct scsi_device *sdev,
@@ -414,7 +432,7 @@ static int write_same16(struct scsi_device *sdev,
int ws_limit = SISLITE_MAX_WS_BLOCKS;
u64 offset = lba;
int left = nblks;
u32 tout = sdev->request_queue->rq_timeout;
u32 to = sdev->request_queue->rq_timeout;
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata;
struct device *dev = &cfg->dev->dev;
@@ -433,8 +451,20 @@ static int write_same16(struct scsi_device *sdev,
put_unaligned_be32(ws_limit < left ? ws_limit : left,
&scsi_cmd[10]);
/* Drop the ioctl read semahpore across lengthy call */
up_read(&cfg->ioctl_rwsem);
result = scsi_execute(sdev, scsi_cmd, DMA_TO_DEVICE, cmd_buf,
CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL);
CMD_BUFSIZE, sense_buf, to, CMD_RETRIES,
0, NULL);
down_read(&cfg->ioctl_rwsem);
rc = check_state(cfg);
if (rc) {
dev_err(dev, "%s: Failed state! result=0x08%X\n",
__func__, result);
rc = -ENODEV;
goto out;
}
if (result) {
dev_err_ratelimited(dev, "%s: command failed for "
"offset %lld result=0x%x\n",
@@ -681,14 +711,14 @@ out:
}
/**
* _cxlflash_vlun_resize() - changes the size of a virtual lun
* _cxlflash_vlun_resize() - changes the size of a virtual LUN
* @sdev: SCSI device associated with LUN owning virtual LUN.
* @ctxi: Context owning resources.
* @resize: Resize ioctl data structure.
*
* On successful return, the user is informed of the new size (in blocks)
* of the virtual lun in last LBA format. When the size of the virtual
* lun is zero, the last LBA is reflected as -1. See comment in the
* of the virtual LUN in last LBA format. When the size of the virtual
* LUN is zero, the last LBA is reflected as -1. See comment in the
* prologue for _cxlflash_disk_release() regarding AFU syncs and contexts
* on the error recovery list.
*
@@ -785,7 +815,7 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
u32 chan;
u32 lind;
struct afu *afu = cfg->afu;
struct sisl_global_map *agm = &afu->afu_map->global;
struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex);
@@ -830,7 +860,7 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
u32 lind;
int rc = 0;
struct afu *afu = cfg->afu;
struct sisl_global_map *agm = &afu->afu_map->global;
struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex);
@@ -885,8 +915,8 @@ out:
* @arg: UVirtual ioctl data structure.
*
* On successful return, the user is informed of the resource handle
* to be used to identify the virtual lun and the size (in blocks) of
* the virtual lun in last LBA format. When the size of the virtual lun
* to be used to identify the virtual LUN and the size (in blocks) of
* the virtual LUN in last LBA format. When the size of the virtual LUN
* is zero, the last LBA is reflected as -1.
*
* Return: 0 on success, -errno on failure
@@ -914,16 +944,9 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size);
/* Setup the LUNs block allocator on first call */
mutex_lock(&gli->mutex);
if (gli->mode == MODE_NONE) {
/* Setup the LUN table and block allocator on first call */
rc = init_luntable(cfg, lli);
if (rc) {
dev_err(dev, "%s: call to init_luntable failed "
"rc=%d!\n", __func__, rc);
goto err0;
}
rc = init_vlun(lli);
if (rc) {
dev_err(dev, "%s: call to init_vlun failed rc=%d!\n",
@@ -941,6 +964,13 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
}
mutex_unlock(&gli->mutex);
rc = init_luntable(cfg, lli);
if (rc) {
dev_err(dev, "%s: call to init_luntable failed rc=%d!\n",
__func__, rc);
goto err1;
}
ctxi = get_context(cfg, rctxid, lli, 0);
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Bad context! (%llu)\n", __func__, ctxid);

Some files were not shown because too many files have changed in this diff Show More