forked from Minki/linux
SCSI misc on 20151105
This patch 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. Signed-off-by: James Bottomley <JBottomley@Odin.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABAgAGBQJWO48UAAoJEDeqqVYsXL0MLH0H/AqGdwI1GD9rGwQ0kRoGMpnv IaSu9cYooTmMJKKd1jrOBoJ9sZzESQ0bjOo+O5XJYmuTMnb9HJjSUHkrd1XWcN+r NNhllY22MJSQO/yvx9YhVG4qiWvBs46NPU/itEvTm9kXlWFRo9pwlC07JS3CuQZD 0AuLaCnpDYBu4km0guw72/fMyZj18vdFu6KI3GtlRSyvWVIPe9A4vZB9R/m4wzER fX//uh0ULaUDkDensGe/6k/l035X5s7AzIqN0l6BBXdQf8Nh6r62Y9rplmKmpSXQ f9VtHM+v4hmXODOM7voXofiWQDFiOJrnPkLmJVixS5nCdhvD+FAU5tE5peZa2Eo= =mNLs -----END PGP SIGNATURE----- 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:
commit
a3e7531535
13
MAINTAINERS
13
MAINTAINERS
@ -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
|
||||
|
@ -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,5 +1,5 @@
|
||||
#
|
||||
# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
|
||||
# Makefile to build the iSCSI driver for Emulex OneConnect.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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,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,
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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,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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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__,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -939,6 +939,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
|
||||
struct sk_buff *skb;
|
||||
u16 len;
|
||||
dma_addr_t pa;
|
||||
int r;
|
||||
|
||||
len = FC_FRAME_HEADROOM + FC_MAX_FRAME + FC_FRAME_TAILROOM;
|
||||
skb = dev_alloc_skb(len);
|
||||
@ -952,8 +953,19 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
|
||||
skb_reset_network_header(skb);
|
||||
skb_put(skb, len);
|
||||
pa = pci_map_single(fnic->pdev, skb->data, len, PCI_DMA_FROMDEVICE);
|
||||
|
||||
r = pci_dma_mapping_error(fnic->pdev, pa);
|
||||
if (r) {
|
||||
printk(KERN_ERR "PCI mapping failed with error %d\n", r);
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
fnic_queue_rq_desc(rq, skb, pa, len);
|
||||
return 0;
|
||||
|
||||
free_skb:
|
||||
kfree_skb(skb);
|
||||
return r;
|
||||
}
|
||||
|
||||
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
|
||||
@ -981,6 +993,7 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
||||
struct ethhdr *eth_hdr;
|
||||
struct vlan_ethhdr *vlan_hdr;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
|
||||
if (!fnic->vlan_hw_insert) {
|
||||
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
|
||||
@ -1003,18 +1016,27 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
||||
|
||||
pa = pci_map_single(fnic->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
spin_lock_irqsave(&fnic->wq_lock[0], flags);
|
||||
if (!vnic_wq_desc_avail(wq)) {
|
||||
pci_unmap_single(fnic->pdev, pa, skb->len, PCI_DMA_TODEVICE);
|
||||
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
r = pci_dma_mapping_error(fnic->pdev, pa);
|
||||
if (r) {
|
||||
printk(KERN_ERR "PCI mapping failed with error %d\n", r);
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fnic->wq_lock[0], flags);
|
||||
if (!vnic_wq_desc_avail(wq))
|
||||
goto irq_restore;
|
||||
|
||||
fnic_queue_wq_eth_desc(wq, skb, pa, skb->len,
|
||||
0 /* hw inserts cos value */,
|
||||
fnic->vlan_id, 1);
|
||||
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
|
||||
return;
|
||||
|
||||
irq_restore:
|
||||
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
|
||||
pci_unmap_single(fnic->pdev, pa, skb->len, PCI_DMA_TODEVICE);
|
||||
free_skb:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1071,6 +1093,12 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
|
||||
|
||||
pa = pci_map_single(fnic->pdev, eth_hdr, tot_len, PCI_DMA_TODEVICE);
|
||||
|
||||
ret = pci_dma_mapping_error(fnic->pdev, pa);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "DMA map failed with error %d\n", ret);
|
||||
goto free_skb_on_err;
|
||||
}
|
||||
|
||||
if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_SEND,
|
||||
(char *)eth_hdr, tot_len)) != 0) {
|
||||
printk(KERN_ERR "fnic ctlr frame trace error!!!");
|
||||
@ -1082,15 +1110,17 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
|
||||
pci_unmap_single(fnic->pdev, pa,
|
||||
tot_len, PCI_DMA_TODEVICE);
|
||||
ret = -1;
|
||||
goto fnic_send_frame_end;
|
||||
goto irq_restore;
|
||||
}
|
||||
|
||||
fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
|
||||
0 /* hw inserts cos value */,
|
||||
fnic->vlan_id, 1, 1, 1);
|
||||
fnic_send_frame_end:
|
||||
|
||||
irq_restore:
|
||||
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
|
||||
|
||||
free_skb_on_err:
|
||||
if (ret)
|
||||
dev_kfree_skb_any(fp_skb(fp));
|
||||
|
||||
|
@ -330,6 +330,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
|
||||
int flags;
|
||||
u8 exch_flags;
|
||||
struct scsi_lun fc_lun;
|
||||
int r;
|
||||
|
||||
if (sg_count) {
|
||||
/* For each SGE, create a device desc entry */
|
||||
@ -346,6 +347,12 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
|
||||
io_req->sgl_list,
|
||||
sizeof(io_req->sgl_list[0]) * sg_count,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
r = pci_dma_mapping_error(fnic->pdev, io_req->sgl_list_pa);
|
||||
if (r) {
|
||||
printk(KERN_ERR "PCI mapping failed with error %d\n", r);
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
io_req->sense_buf_pa = pci_map_single(fnic->pdev,
|
||||
@ -353,6 +360,15 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
r = pci_dma_mapping_error(fnic->pdev, io_req->sense_buf_pa);
|
||||
if (r) {
|
||||
pci_unmap_single(fnic->pdev, io_req->sgl_list_pa,
|
||||
sizeof(io_req->sgl_list[0]) * sg_count,
|
||||
PCI_DMA_TODEVICE);
|
||||
printk(KERN_ERR "PCI mapping failed with error %d\n", r);
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
/* Enqueue the descriptor in the Copy WQ */
|
||||
|
@ -495,15 +495,17 @@ struct unsol_rcv_ct_ctx {
|
||||
#define LPFC_USER_LINK_SPEED_8G 8 /* 8 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_16G
|
||||
#define LPFC_USER_LINK_SPEED_BITMAP ((1 << LPFC_USER_LINK_SPEED_16G) | \
|
||||
#define LPFC_USER_LINK_SPEED_32G 32 /* 32 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_32G
|
||||
#define LPFC_USER_LINK_SPEED_BITMAP ((1ULL << LPFC_USER_LINK_SPEED_32G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_16G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_10G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_8G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_4G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_2G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_1G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_AUTO))
|
||||
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16"
|
||||
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32"
|
||||
|
||||
enum nemb_type {
|
||||
nemb_mse = 1,
|
||||
|
@ -1642,8 +1642,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
struct lpfc_hba *phba = vport->phba;\
|
||||
uint val = 0;\
|
||||
val = phba->cfg_##attr;\
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",\
|
||||
phba->cfg_##attr);\
|
||||
}
|
||||
@ -1808,8 +1806,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
{ \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
uint val = 0;\
|
||||
val = vport->cfg_##attr;\
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
|
||||
}
|
||||
|
||||
@ -1835,8 +1831,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
{ \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
uint val = 0;\
|
||||
val = vport->cfg_##attr;\
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
|
||||
}
|
||||
|
||||
@ -3282,15 +3276,20 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
if (val >= 0 && val <= 6) {
|
||||
prev_val = phba->cfg_topology;
|
||||
phba->cfg_topology = val;
|
||||
if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G &&
|
||||
val == 4) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"3113 Loop mode not supported at speed %d\n",
|
||||
phba->cfg_link_speed);
|
||||
phba->cfg_topology = prev_val;
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
|
||||
val == 4) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"3114 Loop mode not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
phba->cfg_topology = val;
|
||||
if (nolip)
|
||||
return strlen(buf);
|
||||
|
||||
@ -3731,7 +3730,8 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
|
||||
((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) {
|
||||
((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb))) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2879 lpfc_link_speed attribute cannot be set "
|
||||
"to %d. Speed is not supported by this port.\n",
|
||||
@ -5267,6 +5267,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
|
||||
case LPFC_LINK_SPEED_16GHZ:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
|
||||
break;
|
||||
case LPFC_LINK_SPEED_32GHZ:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_32GBIT;
|
||||
break;
|
||||
default:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
@ -904,7 +904,6 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
{
|
||||
uint32_t evt_req_id = 0;
|
||||
uint32_t cmd;
|
||||
uint32_t len;
|
||||
struct lpfc_dmabuf *dmabuf = NULL;
|
||||
struct lpfc_bsg_event *evt;
|
||||
struct event_data *evt_dat = NULL;
|
||||
@ -946,7 +945,6 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
ct_req = (struct lpfc_sli_ct_request *)dmabuf->virt;
|
||||
evt_req_id = ct_req->FsType;
|
||||
cmd = ct_req->CommandResponse.bits.CmdRsp;
|
||||
len = ct_req->CommandResponse.bits.Size;
|
||||
if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
|
||||
lpfc_sli_ringpostbuf_put(phba, pring, dmabuf);
|
||||
|
||||
@ -2988,7 +2986,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
|
||||
{
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct diag_mode_test *diag_mode;
|
||||
struct lpfc_bsg_event *evt;
|
||||
struct event_data *evdat;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
@ -3031,8 +3028,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
|
||||
rc = -EINVAL;
|
||||
goto loopback_test_exit;
|
||||
}
|
||||
diag_mode = (struct diag_mode_test *)
|
||||
job->request->rqst_data.h_vendor.vendor_cmd;
|
||||
|
||||
if ((phba->link_state == LPFC_HBA_ERROR) ||
|
||||
(psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
|
||||
@ -3293,7 +3288,6 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
|
||||
{
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct get_mgmt_rev *event_req;
|
||||
struct get_mgmt_rev_reply *event_reply;
|
||||
int rc = 0;
|
||||
|
||||
@ -3306,9 +3300,6 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
|
||||
goto job_error;
|
||||
}
|
||||
|
||||
event_req = (struct get_mgmt_rev *)
|
||||
job->request->rqst_data.h_vendor.vendor_cmd;
|
||||
|
||||
event_reply = (struct get_mgmt_rev_reply *)
|
||||
job->reply->reply_data.vendor_reply.vendor_rsp;
|
||||
|
||||
@ -4348,7 +4339,6 @@ static int
|
||||
lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
|
||||
struct lpfc_dmabuf *dmabuf)
|
||||
{
|
||||
struct lpfc_sli_config_mbox *sli_cfg_mbx;
|
||||
struct bsg_job_data *dd_data = NULL;
|
||||
LPFC_MBOXQ_t *pmboxq = NULL;
|
||||
MAILBOX_t *pmb;
|
||||
@ -4362,9 +4352,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
|
||||
phba->mbox_ext_buf_ctx.seqNum++;
|
||||
nemb_tp = phba->mbox_ext_buf_ctx.nembType;
|
||||
|
||||
sli_cfg_mbx = (struct lpfc_sli_config_mbox *)
|
||||
phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
|
||||
|
||||
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
|
||||
if (!dd_data) {
|
||||
rc = -ENOMEM;
|
||||
@ -4606,7 +4593,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
|
||||
uint32_t transmit_length, receive_length, mode;
|
||||
struct lpfc_mbx_sli4_config *sli4_config;
|
||||
struct lpfc_mbx_nembed_cmd *nembed_sge;
|
||||
struct mbox_header *header;
|
||||
struct ulp_bde64 *bde;
|
||||
uint8_t *ext = NULL;
|
||||
int rc = 0;
|
||||
@ -4804,8 +4790,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
|
||||
/* rebuild the command for sli4 using our
|
||||
* own buffers like we do for biu diags
|
||||
*/
|
||||
header = (struct mbox_header *)
|
||||
&pmb->un.varWords[0];
|
||||
nembed_sge = (struct lpfc_mbx_nembed_cmd *)
|
||||
&pmb->un.varWords[0];
|
||||
receive_length = nembed_sge->sge[0].length;
|
||||
@ -5048,7 +5032,6 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
|
||||
IOCB_t *cmd;
|
||||
int rc = 0;
|
||||
struct menlo_command *menlo_cmd;
|
||||
struct menlo_response *menlo_resp;
|
||||
struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
|
||||
int request_nseg;
|
||||
int reply_nseg;
|
||||
@ -5088,9 +5071,6 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
|
||||
menlo_cmd = (struct menlo_command *)
|
||||
job->request->rqst_data.h_vendor.vendor_cmd;
|
||||
|
||||
menlo_resp = (struct menlo_response *)
|
||||
job->reply->reply_data.vendor_reply.vendor_rsp;
|
||||
|
||||
/* allocate our bsg tracking structure */
|
||||
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
|
||||
if (!dd_data) {
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */
|
||||
#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
|
||||
#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
|
||||
#define HBA_PORTSPEED_32GBIT 0x0040 /* 32 GBit/sec */
|
||||
#define HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */
|
||||
|
||||
#define FOURBYTES 4
|
||||
@ -575,7 +576,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_vport *vport = cmdiocb->vport;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_dmabuf *bmp;
|
||||
struct lpfc_dmabuf *outp;
|
||||
struct lpfc_sli_ct_request *CTrsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
@ -588,7 +588,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||
|
||||
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
|
||||
irsp = &rspiocb->iocb;
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
|
||||
@ -1733,12 +1732,9 @@ hba_out:
|
||||
case SLI_MGMT_RPRT:
|
||||
case SLI_MGMT_RPA:
|
||||
{
|
||||
lpfc_vpd_t *vp;
|
||||
struct serv_parm *hsp;
|
||||
int len = 0;
|
||||
|
||||
vp = &phba->vpd;
|
||||
|
||||
if (cmdcode == SLI_MGMT_RPRT) {
|
||||
rh = (struct lpfc_fdmi_reg_hba *)
|
||||
&CtReq->un.PortID;
|
||||
@ -1778,6 +1774,8 @@ hba_out:
|
||||
ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED);
|
||||
ad->AttrLen = cpu_to_be16(FOURBYTES + 4);
|
||||
ae->un.SupportSpeed = 0;
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
ae->un.SupportSpeed |= HBA_PORTSPEED_32GBIT;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT;
|
||||
if (phba->lmt & LMT_10Gb)
|
||||
@ -1821,6 +1819,9 @@ hba_out:
|
||||
case LPFC_LINK_SPEED_16GHZ:
|
||||
ae->un.PortSpeed = HBA_PORTSPEED_16GBIT;
|
||||
break;
|
||||
case LPFC_LINK_SPEED_32GHZ:
|
||||
ae->un.PortSpeed = HBA_PORTSPEED_32GBIT;
|
||||
break;
|
||||
default:
|
||||
ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
@ -457,11 +457,9 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
LPFC_MBOXQ_t *mboxq;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct serv_parm *sp;
|
||||
struct lpfc_dmabuf *dmabuf;
|
||||
int rc = 0;
|
||||
|
||||
sp = &phba->fc_fabparam;
|
||||
/* move forward in case of SLI4 FC port loopback test and pt2pt mode */
|
||||
if ((phba->sli_rev == LPFC_SLI_REV4) &&
|
||||
!(phba->link_flag & LS_LOOPBACK_MODE) &&
|
||||
@ -1028,9 +1026,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
stop_rr_fcf_flogi:
|
||||
/* FLOGI failure */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
||||
"2858 FLOGI failure Status:x%x/x%x TMO:x%x\n",
|
||||
"2858 FLOGI failure Status:x%x/x%x TMO:x%x "
|
||||
"Data x%x x%x\n",
|
||||
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||
irsp->ulpTimeout);
|
||||
irsp->ulpTimeout, phba->hba_flag,
|
||||
phba->fcf.fcf_flag);
|
||||
|
||||
/* Check for retry */
|
||||
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
||||
@ -1154,6 +1154,9 @@ stop_rr_fcf_flogi:
|
||||
}
|
||||
|
||||
flogifail:
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
lpfc_nlp_put(ndlp);
|
||||
|
||||
if (!lpfc_error_lost_link(irsp)) {
|
||||
@ -1205,14 +1208,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
struct serv_parm *sp;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli_ring *pring;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
uint32_t tmo;
|
||||
int rc;
|
||||
|
||||
pring = &phba->sli.ring[LPFC_ELS_RING];
|
||||
|
||||
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_FLOGI);
|
||||
@ -1454,8 +1454,6 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
|
||||
void
|
||||
lpfc_more_plogi(struct lpfc_vport *vport)
|
||||
{
|
||||
int sentplogi;
|
||||
|
||||
if (vport->num_disc_nodes)
|
||||
vport->num_disc_nodes--;
|
||||
|
||||
@ -1468,7 +1466,7 @@ lpfc_more_plogi(struct lpfc_vport *vport)
|
||||
/* Check to see if there are more PLOGIs to be sent */
|
||||
if (vport->fc_flag & FC_NLP_MORE)
|
||||
/* go thru NPR nodes and issue any remaining ELS PLOGIs */
|
||||
sentplogi = lpfc_els_disc_plogi(vport);
|
||||
lpfc_els_disc_plogi(vport);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1956,16 +1954,12 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct serv_parm *sp;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int ret;
|
||||
|
||||
psli = &phba->sli;
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, did);
|
||||
if (ndlp && !NLP_CHK_NODE_ACT(ndlp))
|
||||
ndlp = NULL;
|
||||
@ -1977,7 +1971,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
/* For PLOGI request, remainder of payload is service parameters */
|
||||
@ -2034,10 +2027,8 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_vport *vport = cmdiocb->vport;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_sli *psli;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
psli = &phba->sli;
|
||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||
|
||||
@ -2117,7 +2108,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
PRLI *npr;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
@ -2128,7 +2118,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
/* For PRLI request, remainder of payload is service parameters */
|
||||
@ -2413,7 +2402,6 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
ADISC *ap;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
@ -2424,7 +2412,6 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
/* For ADISC request, remainder of payload is service parameters */
|
||||
@ -2478,12 +2465,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_vport *vport = ndlp->vport;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_sli *psli;
|
||||
struct lpfcMboxq *mbox;
|
||||
unsigned long flags;
|
||||
uint32_t skip_recovery = 0;
|
||||
|
||||
psli = &phba->sli;
|
||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||
|
||||
@ -2609,7 +2594,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
{
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
@ -2628,7 +2612,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
|
||||
pcmd += sizeof(uint32_t);
|
||||
@ -2742,14 +2725,11 @@ int
|
||||
lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
psli = &phba->sli;
|
||||
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, nportid);
|
||||
@ -2776,7 +2756,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
return 1;
|
||||
}
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
*((uint32_t *) (pcmd)) = ELS_CMD_SCR;
|
||||
@ -2836,9 +2815,7 @@ static int
|
||||
lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
FARP *fp;
|
||||
uint8_t *pcmd;
|
||||
uint32_t *lp;
|
||||
@ -2846,7 +2823,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
struct lpfc_nodelist *ondlp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
psli = &phba->sli;
|
||||
cmdsize = (sizeof(uint32_t) + sizeof(FARP));
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, nportid);
|
||||
@ -2872,7 +2848,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
return 1;
|
||||
}
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
*((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
|
||||
@ -3922,13 +3897,11 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||
IOCB_t *icmd;
|
||||
IOCB_t *oldcmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
ELS_PKT *els_pkt_ptr;
|
||||
|
||||
psli = &phba->sli;
|
||||
oldcmd = &oldiocb->iocb;
|
||||
|
||||
switch (flag) {
|
||||
@ -4061,12 +4034,10 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
|
||||
IOCB_t *icmd;
|
||||
IOCB_t *oldcmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
|
||||
psli = &phba->sli;
|
||||
cmdsize = 2 * sizeof(uint32_t);
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_LS_RJT);
|
||||
@ -4212,13 +4183,10 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
|
||||
IOCB_t *icmd;
|
||||
IOCB_t *oldcmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
|
||||
psli = &phba->sli;
|
||||
|
||||
cmdsize = sizeof(uint32_t) + sizeof(PRLI);
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
|
||||
ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
|
||||
@ -4315,12 +4283,10 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
|
||||
RNID *rn;
|
||||
IOCB_t *icmd, *oldcmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
|
||||
psli = &phba->sli;
|
||||
cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
|
||||
+ (2 * sizeof(struct lpfc_name));
|
||||
if (format)
|
||||
@ -4447,12 +4413,10 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_sli *psli;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
|
||||
psli = &phba->sli;
|
||||
cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
|
||||
|
||||
/* The accumulated length can exceed the BPL_SIZE. For
|
||||
@ -4746,6 +4710,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
||||
|
||||
desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
|
||||
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
rdp_cap |= RDP_PS_32GB;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
rdp_cap |= RDP_PS_16GB;
|
||||
if (phba->lmt & LMT_10Gb)
|
||||
@ -5181,14 +5147,12 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_dmabuf *pcmd;
|
||||
IOCB_t *icmd;
|
||||
uint8_t *lp;
|
||||
struct fc_lcb_request_frame *beacon;
|
||||
struct lpfc_lcb_context *lcb_context;
|
||||
uint8_t state, rjt_err;
|
||||
struct ls_rjt stat;
|
||||
|
||||
icmd = &cmdiocb->iocb;
|
||||
pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
|
||||
lp = (uint8_t *)pcmd->virt;
|
||||
beacon = (struct fc_lcb_request_frame *)pcmd->virt;
|
||||
@ -5444,7 +5408,7 @@ lpfc_send_rscn_event(struct lpfc_vport *vport,
|
||||
|
||||
fc_host_post_vendor_event(shost,
|
||||
fc_get_event_number(),
|
||||
sizeof(struct lpfc_els_event_header) + payload_len,
|
||||
sizeof(struct lpfc_rscn_event_header) + payload_len,
|
||||
(char *)rscn_event_data,
|
||||
LPFC_NL_VENDOR_ID);
|
||||
|
||||
@ -5481,13 +5445,11 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_dmabuf *pcmd;
|
||||
uint32_t *lp, *datap;
|
||||
IOCB_t *icmd;
|
||||
uint32_t payload_len, length, nportid, *cmd;
|
||||
int rscn_cnt;
|
||||
int rscn_id = 0, hba_id = 0;
|
||||
int i;
|
||||
|
||||
icmd = &cmdiocb->iocb;
|
||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
lp = (uint32_t *) pcmd->virt;
|
||||
|
||||
@ -5893,6 +5855,13 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* send our FLOGI first */
|
||||
if (vport->port_state < LPFC_FLOGI) {
|
||||
vport->fc_myDID = 0;
|
||||
lpfc_initial_flogi(vport);
|
||||
vport->fc_myDID = Fabric_DID;
|
||||
}
|
||||
|
||||
/* Send back ACC */
|
||||
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
|
||||
|
||||
@ -5943,12 +5912,10 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
{
|
||||
struct lpfc_dmabuf *pcmd;
|
||||
uint32_t *lp;
|
||||
IOCB_t *icmd;
|
||||
RNID *rn;
|
||||
struct ls_rjt stat;
|
||||
uint32_t cmd;
|
||||
|
||||
icmd = &cmdiocb->iocb;
|
||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
lp = (uint32_t *) pcmd->virt;
|
||||
|
||||
@ -6259,7 +6226,6 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
LPFC_MBOXQ_t *mbox;
|
||||
struct lpfc_dmabuf *pcmd;
|
||||
struct ls_rjt stat;
|
||||
|
||||
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
|
||||
@ -6267,8 +6233,6 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
/* reject the unsolicited RPS request and done with it */
|
||||
goto reject_out;
|
||||
|
||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
|
||||
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
|
||||
if (mbox) {
|
||||
lpfc_read_lnk_stat(phba, mbox);
|
||||
@ -6482,7 +6446,6 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct RRQ *els_rrq;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
@ -6501,7 +6464,6 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
|
||||
/* For RRQ request, remainder of payload is Exchange IDs */
|
||||
@ -7374,6 +7336,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
cmd, did, vport->port_state, vport->fc_flag,
|
||||
vport->fc_myDID, vport->fc_prevDID);
|
||||
|
||||
/* reject till our FLOGI completes */
|
||||
if ((vport->port_state < LPFC_FABRIC_CFG_LINK) &&
|
||||
(cmd != ELS_CMD_FLOGI)) {
|
||||
rjt_err = LSRJT_UNABLE_TPC;
|
||||
rjt_exp = LSEXP_NOTHING_MORE;
|
||||
goto lsrjt;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ELS_CMD_PLOGI:
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||
@ -7411,20 +7382,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
rjt_exp = LSEXP_NOTHING_MORE;
|
||||
break;
|
||||
}
|
||||
/* We get here, and drop thru, if we are PT2PT with
|
||||
* another NPort and the other side has initiated
|
||||
* the PLOGI before responding to our FLOGI.
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
(phba->fc_topology_changed ||
|
||||
vport->fc_myDID != vport->fc_prevDID)) {
|
||||
lpfc_unregister_fcf_prep(phba);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag &= ~FC_VFI_REGISTERED;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
phba->fc_topology_changed = 0;
|
||||
lpfc_issue_reg_vfi(vport);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
@ -7655,6 +7612,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
break;
|
||||
}
|
||||
|
||||
lsrjt:
|
||||
/* check if need to LS_RJT received ELS cmd */
|
||||
if (rjt_err) {
|
||||
memset(&stat, 0, sizeof(stat));
|
||||
@ -8428,7 +8386,6 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
IOCB_t *icmd;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
@ -8439,7 +8396,6 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||
*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
|
||||
pcmd += sizeof(uint32_t);
|
||||
|
@ -800,7 +800,6 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
int rc;
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
if (!NLP_CHK_NODE_ACT(ndlp))
|
||||
@ -816,10 +815,10 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
|
||||
if ((phba->sli_rev < LPFC_SLI_REV4) &&
|
||||
(!remove && ndlp->nlp_type & NLP_FABRIC))
|
||||
continue;
|
||||
rc = lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
remove
|
||||
? NLP_EVT_DEVICE_RM
|
||||
: NLP_EVT_DEVICE_RECOVERY);
|
||||
lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
remove
|
||||
? NLP_EVT_DEVICE_RM
|
||||
: NLP_EVT_DEVICE_RECOVERY);
|
||||
}
|
||||
if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
@ -1774,7 +1773,6 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
|
||||
uint16_t *next_fcf_index)
|
||||
{
|
||||
void *virt_addr;
|
||||
dma_addr_t phys_addr;
|
||||
struct lpfc_mbx_sge sge;
|
||||
struct lpfc_mbx_read_fcf_tbl *read_fcf;
|
||||
uint32_t shdr_status, shdr_add_status, if_type;
|
||||
@ -1785,7 +1783,6 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
|
||||
* routine only uses a single SGE.
|
||||
*/
|
||||
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
|
||||
phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
|
||||
if (unlikely(!mboxq->sge_array)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
|
||||
"2524 Failed to get the non-embedded SGE "
|
||||
@ -2977,7 +2974,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
MAILBOX_t *mb = &pmb->u.mb;
|
||||
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
|
||||
struct lpfc_vport *vport = pmb->vport;
|
||||
|
||||
struct serv_parm *sp = &vport->fc_sparam;
|
||||
uint32_t ed_tov;
|
||||
|
||||
/* Check for error */
|
||||
if (mb->mbxStatus) {
|
||||
@ -2992,6 +2990,18 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
|
||||
memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
|
||||
sizeof (struct serv_parm));
|
||||
|
||||
ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
|
||||
if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
|
||||
ed_tov = (ed_tov + 999999) / 1000000;
|
||||
|
||||
phba->fc_edtov = ed_tov;
|
||||
phba->fc_ratov = (2 * ed_tov) / 1000;
|
||||
if (phba->fc_ratov < FF_DEF_RATOV) {
|
||||
/* RA_TOV should be atleast 10sec for initial flogi */
|
||||
phba->fc_ratov = FF_DEF_RATOV;
|
||||
}
|
||||
|
||||
lpfc_update_vport_wwn(vport);
|
||||
if (vport->port_type == LPFC_PHYSICAL_PORT) {
|
||||
memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
|
||||
@ -3032,6 +3042,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
|
||||
case LPFC_LINK_SPEED_8GHZ:
|
||||
case LPFC_LINK_SPEED_10GHZ:
|
||||
case LPFC_LINK_SPEED_16GHZ:
|
||||
case LPFC_LINK_SPEED_32GHZ:
|
||||
phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la);
|
||||
break;
|
||||
default:
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#define FF_DEF_EDTOV 2000 /* Default E_D_TOV (2000ms) */
|
||||
#define FF_DEF_ALTOV 15 /* Default AL_TIME (15ms) */
|
||||
#define FF_DEF_RATOV 2 /* Default RA_TOV (2s) */
|
||||
#define FF_DEF_RATOV 10 /* Default RA_TOV (10s) */
|
||||
#define FF_DEF_ARBTOV 1900 /* Default ARB_TOV (1900ms) */
|
||||
|
||||
#define LPFC_BUF_RING0 64 /* Number of buffers to post to RING
|
||||
@ -1400,6 +1400,7 @@ struct lpfc_fdmi_reg_portattr {
|
||||
#define PCI_DEVICE_ID_LANCER_FC_VF 0xe208
|
||||
#define PCI_DEVICE_ID_LANCER_FCOE 0xe260
|
||||
#define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268
|
||||
#define PCI_DEVICE_ID_LANCER_G6_FC 0xe300
|
||||
#define PCI_DEVICE_ID_SAT_SMB 0xf011
|
||||
#define PCI_DEVICE_ID_SAT_MID 0xf015
|
||||
#define PCI_DEVICE_ID_RFLY 0xf095
|
||||
@ -2075,6 +2076,7 @@ typedef struct {
|
||||
#define LINK_SPEED_8G 0x8 /* 8 Gigabaud */
|
||||
#define LINK_SPEED_10G 0x10 /* 10 Gigabaud */
|
||||
#define LINK_SPEED_16G 0x11 /* 16 Gigabaud */
|
||||
#define LINK_SPEED_32G 0x14 /* 32 Gigabaud */
|
||||
|
||||
} INIT_LINK_VAR;
|
||||
|
||||
@ -2246,6 +2248,7 @@ typedef struct {
|
||||
#define LMT_8Gb 0x080
|
||||
#define LMT_10Gb 0x100
|
||||
#define LMT_16Gb 0x200
|
||||
#define LMT_32Gb 0x400
|
||||
uint32_t rsvd2;
|
||||
uint32_t rsvd3;
|
||||
uint32_t max_xri;
|
||||
@ -2727,6 +2730,7 @@ struct lpfc_mbx_read_top {
|
||||
#define LPFC_LINK_SPEED_8GHZ 0x20
|
||||
#define LPFC_LINK_SPEED_10GHZ 0x40
|
||||
#define LPFC_LINK_SPEED_16GHZ 0x80
|
||||
#define LPFC_LINK_SPEED_32GHZ 0x90
|
||||
};
|
||||
|
||||
/* Structure for MB Command CLEAR_LA (22) */
|
||||
|
@ -699,7 +699,9 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology,
|
||||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) &&
|
||||
!(phba->lmt & LMT_10Gb)) ||
|
||||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) &&
|
||||
!(phba->lmt & LMT_16Gb))) {
|
||||
!(phba->lmt & LMT_16Gb)) ||
|
||||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_32G) &&
|
||||
!(phba->lmt & LMT_32Gb))) {
|
||||
/* Reset link speed to auto */
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1302 Invalid speed for this board:%d "
|
||||
@ -2035,7 +2037,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
&& descp && descp[0] != '\0')
|
||||
return;
|
||||
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
max_speed = 32;
|
||||
else if (phba->lmt & LMT_16Gb)
|
||||
max_speed = 16;
|
||||
else if (phba->lmt & LMT_10Gb)
|
||||
max_speed = 10;
|
||||
@ -2229,6 +2233,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
m = (typeof(m)){"OCe15100", "PCIe",
|
||||
"Obsolete, Unsupported FCoE"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_G6_FC:
|
||||
m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SKYHAWK:
|
||||
case PCI_DEVICE_ID_SKYHAWK_VF:
|
||||
oneConnect = 1;
|
||||
@ -2253,7 +2260,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
phba->Port);
|
||||
else if (max_speed == 0)
|
||||
snprintf(descp, 255,
|
||||
"Emulex %s %s %s ",
|
||||
"Emulex %s %s %s",
|
||||
m.name, m.bus, m.function);
|
||||
else
|
||||
snprintf(descp, 255,
|
||||
@ -3491,6 +3498,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
|
||||
sizeof fc_host_symbolic_name(shost));
|
||||
|
||||
fc_host_supported_speeds(shost) = 0;
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_16GBIT;
|
||||
if (phba->lmt & LMT_10Gb)
|
||||
@ -3854,6 +3863,9 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code,
|
||||
case LPFC_FC_LA_SPEED_16G:
|
||||
port_speed = 16000;
|
||||
break;
|
||||
case LPFC_FC_LA_SPEED_32G:
|
||||
port_speed = 32000;
|
||||
break;
|
||||
default:
|
||||
port_speed = 0;
|
||||
}
|
||||
@ -4982,8 +4994,7 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
|
||||
}
|
||||
|
||||
if (!phba->sli.ring)
|
||||
phba->sli.ring = (struct lpfc_sli_ring *)
|
||||
kzalloc(LPFC_SLI3_MAX_RING *
|
||||
phba->sli.ring = kzalloc(LPFC_SLI3_MAX_RING *
|
||||
sizeof(struct lpfc_sli_ring), GFP_KERNEL);
|
||||
if (!phba->sli.ring)
|
||||
return -ENOMEM;
|
||||
@ -4995,7 +5006,7 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
|
||||
|
||||
/* Initialize the host templates the configured values. */
|
||||
lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
|
||||
lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
|
||||
lpfc_template_s3.sg_tablesize = phba->cfg_sg_seg_cnt;
|
||||
|
||||
/* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */
|
||||
if (phba->cfg_enable_bg) {
|
||||
@ -8679,7 +8690,6 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
|
||||
#ifdef CONFIG_X86
|
||||
struct cpuinfo_x86 *cpuinfo;
|
||||
#endif
|
||||
struct cpumask *mask;
|
||||
uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1];
|
||||
|
||||
/* If there is no mapping, just return */
|
||||
@ -8773,11 +8783,8 @@ found:
|
||||
first_cpu = cpu;
|
||||
|
||||
/* Now affinitize to the selected CPU */
|
||||
mask = &cpup->maskbits;
|
||||
cpumask_clear(mask);
|
||||
cpumask_set_cpu(cpu, mask);
|
||||
i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
|
||||
vector, mask);
|
||||
vector, get_cpu_mask(cpu));
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"3330 Set Affinity: CPU %d channel %d "
|
||||
@ -10287,7 +10294,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
struct lpfc_hba *phba;
|
||||
struct lpfc_vport *vport = NULL;
|
||||
struct Scsi_Host *shost = NULL;
|
||||
int error, ret;
|
||||
int error;
|
||||
uint32_t cfg_mode, intr_mode;
|
||||
int adjusted_fcp_io_channel;
|
||||
|
||||
@ -10411,7 +10418,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
|
||||
/* check for firmware upgrade or downgrade */
|
||||
if (phba->cfg_request_firmware_upgrade)
|
||||
ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
|
||||
lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
|
||||
|
||||
/* Check if there are static vports to be created. */
|
||||
lpfc_create_static_vport(phba);
|
||||
@ -11354,6 +11361,8 @@ static struct pci_device_id lpfc_id_table[] = {
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
|
||||
@ -11477,6 +11486,7 @@ lpfc_exit(void)
|
||||
free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order);
|
||||
}
|
||||
kfree(lpfc_used_cpu);
|
||||
idr_destroy(&lpfc_hba_index);
|
||||
}
|
||||
|
||||
module_init(lpfc_init);
|
||||
|
@ -289,9 +289,7 @@ lpfc_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
|
||||
struct lpfc_dmabuf *mp)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->u.mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
@ -483,13 +481,11 @@ lpfc_init_link(struct lpfc_hba * phba,
|
||||
LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
|
||||
{
|
||||
lpfc_vpd_t *vpd;
|
||||
struct lpfc_sli *psli;
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->u.mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
psli = &phba->sli;
|
||||
switch (topology) {
|
||||
case FLAGS_TOPOLOGY_MODE_LOOP_PT:
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
|
||||
@ -510,6 +506,13 @@ lpfc_init_link(struct lpfc_hba * phba,
|
||||
break;
|
||||
}
|
||||
|
||||
if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
|
||||
mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
|
||||
/* Failover is not tried for Lancer G6 */
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
|
||||
phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT;
|
||||
}
|
||||
|
||||
/* Enable asynchronous ABTS responses from firmware */
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
|
||||
|
||||
@ -543,6 +546,10 @@ lpfc_init_link(struct lpfc_hba * phba,
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_16G;
|
||||
break;
|
||||
case LPFC_USER_LINK_SPEED_32G:
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_32G;
|
||||
break;
|
||||
case LPFC_USER_LINK_SPEED_AUTO:
|
||||
default:
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
|
||||
@ -585,9 +592,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
|
||||
{
|
||||
struct lpfc_dmabuf *mp;
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->u.mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
@ -2010,7 +2015,6 @@ lpfc_sli4_mbx_read_fcf_rec(struct lpfc_hba *phba,
|
||||
uint16_t fcf_index)
|
||||
{
|
||||
void *virt_addr;
|
||||
dma_addr_t phys_addr;
|
||||
uint8_t *bytep;
|
||||
struct lpfc_mbx_sge sge;
|
||||
uint32_t alloc_len, req_len;
|
||||
@ -2039,7 +2043,6 @@ lpfc_sli4_mbx_read_fcf_rec(struct lpfc_hba *phba,
|
||||
* routine only uses a single SGE.
|
||||
*/
|
||||
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
|
||||
phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
|
||||
virt_addr = mboxq->sge_array->addr[0];
|
||||
read_fcf = (struct lpfc_mbx_read_fcf_tbl *)virt_addr;
|
||||
|
||||
|
@ -820,7 +820,6 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
{
|
||||
struct lpfc_hba *phba;
|
||||
LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
|
||||
MAILBOX_t *mb;
|
||||
uint16_t rpi;
|
||||
|
||||
phba = vport->phba;
|
||||
@ -828,7 +827,6 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
if (!(phba->pport->load_flag & FC_UNLOADING) &&
|
||||
(evt == NLP_EVT_CMPL_REG_LOGIN) &&
|
||||
(!pmb->u.mb.mbxStatus)) {
|
||||
mb = &pmb->u.mb;
|
||||
rpi = pmb->u.mb.un.varWords[0];
|
||||
lpfc_release_rpi(phba, vport, rpi);
|
||||
}
|
||||
|
@ -1293,7 +1293,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
|
||||
{
|
||||
struct scatterlist *sgpe; /* s/g prot entry */
|
||||
struct scatterlist *sgde; /* s/g data entry */
|
||||
struct lpfc_scsi_buf *lpfc_cmd = NULL;
|
||||
struct scsi_dif_tuple *src = NULL;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
@ -1309,7 +1308,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
return 0;
|
||||
|
||||
sgpe = scsi_prot_sglist(sc);
|
||||
sgde = scsi_sglist(sc);
|
||||
lba = scsi_get_lba(sc);
|
||||
|
||||
/* First check if we need to match the LBA */
|
||||
@ -1882,7 +1880,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
#endif
|
||||
uint32_t checking = 1;
|
||||
uint32_t reftag;
|
||||
unsigned blksize;
|
||||
uint8_t txop, rxop;
|
||||
|
||||
status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
|
||||
@ -1890,7 +1887,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
goto out;
|
||||
|
||||
/* extract some info from the scsi command for pde*/
|
||||
blksize = lpfc_cmd_blksize(sc);
|
||||
reftag = (uint32_t)scsi_get_lba(sc); /* Truncate LBA */
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
@ -2263,7 +2259,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
dma_addr_t physaddr;
|
||||
int i = 0, num_sge = 0, status;
|
||||
uint32_t reftag;
|
||||
unsigned blksize;
|
||||
uint8_t txop, rxop;
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
uint32_t rc;
|
||||
@ -2277,7 +2272,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
||||
goto out;
|
||||
|
||||
/* extract some info from the scsi command for pde*/
|
||||
blksize = lpfc_cmd_blksize(sc);
|
||||
reftag = (uint32_t)scsi_get_lba(sc); /* Truncate LBA */
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
@ -2881,7 +2875,7 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
||||
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
|
||||
struct scsi_dif_tuple *src = NULL;
|
||||
uint8_t *data_src = NULL;
|
||||
uint16_t guard_tag, guard_type;
|
||||
uint16_t guard_tag;
|
||||
uint16_t start_app_tag, app_tag;
|
||||
uint32_t start_ref_tag, ref_tag;
|
||||
int prot, protsegcnt;
|
||||
@ -2922,7 +2916,6 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
||||
data_len = sgde->length;
|
||||
if ((data_len & (blksize - 1)) == 0)
|
||||
chk_guard = 1;
|
||||
guard_type = scsi_host_get_guard(cmd->device->host);
|
||||
|
||||
src = (struct scsi_dif_tuple *)sg_virt(sgpe);
|
||||
start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */
|
||||
@ -3908,12 +3901,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
|
||||
struct lpfc_nodelist *pnode = rdata->pnode;
|
||||
struct scsi_cmnd *cmd;
|
||||
int result;
|
||||
int depth;
|
||||
unsigned long flags;
|
||||
struct lpfc_fast_path_event *fast_path_evt;
|
||||
struct Scsi_Host *shost;
|
||||
uint32_t queue_depth, scsi_id;
|
||||
uint32_t logit = LOG_FCP;
|
||||
|
||||
/* Sanity check on return of outstanding command */
|
||||
@ -4095,7 +4086,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
}
|
||||
|
||||
lpfc_update_stats(phba, lpfc_cmd);
|
||||
result = cmd->result;
|
||||
if (vport->cfg_max_scsicmpl_time &&
|
||||
time_after(jiffies, lpfc_cmd->start_time +
|
||||
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
|
||||
@ -4132,8 +4122,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
|
||||
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
|
||||
queue_depth = cmd->device->queue_depth;
|
||||
scsi_id = cmd->device->id;
|
||||
cmd->scsi_done(cmd);
|
||||
|
||||
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
|
||||
|
@ -6696,7 +6696,7 @@ lpfc_mbox_timeout(unsigned long ptr)
|
||||
* This function checks if any mailbox completions are present on the mailbox
|
||||
* completion queue.
|
||||
**/
|
||||
bool
|
||||
static bool
|
||||
lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba)
|
||||
{
|
||||
|
||||
@ -12491,12 +12491,10 @@ lpfc_sli4_fof_intr_handler(int irq, void *dev_id)
|
||||
struct lpfc_eqe *eqe;
|
||||
unsigned long iflag;
|
||||
int ecount = 0;
|
||||
uint32_t eqidx;
|
||||
|
||||
/* Get the driver's phba structure from the dev_id */
|
||||
fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id;
|
||||
phba = fcp_eq_hdl->phba;
|
||||
eqidx = fcp_eq_hdl->idx;
|
||||
|
||||
if (unlikely(!phba))
|
||||
return IRQ_NONE;
|
||||
@ -12831,12 +12829,8 @@ out_fail:
|
||||
static void __iomem *
|
||||
lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (!phba->pcidev)
|
||||
return NULL;
|
||||
else
|
||||
pdev = phba->pcidev;
|
||||
|
||||
switch (pci_barset) {
|
||||
case WQ_PCI_BAR_0_AND_1:
|
||||
@ -15920,7 +15914,6 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record)
|
||||
LPFC_MBOXQ_t *mboxq;
|
||||
uint8_t *bytep;
|
||||
void *virt_addr;
|
||||
dma_addr_t phys_addr;
|
||||
struct lpfc_mbx_sge sge;
|
||||
uint32_t alloc_len, req_len;
|
||||
uint32_t fcfindex;
|
||||
@ -15953,7 +15946,6 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record)
|
||||
* routine only uses a single SGE.
|
||||
*/
|
||||
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
|
||||
phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
|
||||
virt_addr = mboxq->sge_array->addr[0];
|
||||
/*
|
||||
* Configure the FCF record for FCFI 0. This is the driver's
|
||||
|
@ -454,7 +454,6 @@ struct lpfc_vector_map_info {
|
||||
uint16_t core_id;
|
||||
uint16_t irq;
|
||||
uint16_t channel_id;
|
||||
struct cpumask maskbits;
|
||||
};
|
||||
#define LPFC_VECTOR_MAP_EMPTY 0xffff
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "10.7.0.0."
|
||||
#define LPFC_DRIVER_VERSION "11.0.0.0."
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
@ -390,25 +390,57 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
|
||||
EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
|
||||
|
||||
/**
|
||||
* scsi_dev_info_list_del_keyed - remove one dev_info list entry.
|
||||
* scsi_dev_info_list_find - find a matching dev_info list entry.
|
||||
* @vendor: vendor string
|
||||
* @model: model (product) string
|
||||
* @key: specify list to use
|
||||
*
|
||||
* Description:
|
||||
* Remove and destroy one dev_info entry for @vendor, @model
|
||||
* Finds the first dev_info entry matching @vendor, @model
|
||||
* in list specified by @key.
|
||||
*
|
||||
* Returns: 0 OK, -error on failure.
|
||||
* Returns: pointer to matching entry, or ERR_PTR on failure.
|
||||
**/
|
||||
int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
|
||||
static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
|
||||
const char *model, int key)
|
||||
{
|
||||
struct scsi_dev_info_list *devinfo, *found = NULL;
|
||||
struct scsi_dev_info_list *devinfo;
|
||||
struct scsi_dev_info_list_table *devinfo_table =
|
||||
scsi_devinfo_lookup_by_key(key);
|
||||
size_t vmax, mmax;
|
||||
const char *vskip, *mskip;
|
||||
|
||||
if (IS_ERR(devinfo_table))
|
||||
return PTR_ERR(devinfo_table);
|
||||
return (struct scsi_dev_info_list *) devinfo_table;
|
||||
|
||||
/* Prepare for "compatible" matches */
|
||||
|
||||
/*
|
||||
* XXX why skip leading spaces? If an odd INQUIRY
|
||||
* value, that should have been part of the
|
||||
* scsi_static_device_list[] entry, such as " FOO"
|
||||
* rather than "FOO". Since this code is already
|
||||
* here, and we don't know what device it is
|
||||
* trying to work with, leave it as-is.
|
||||
*/
|
||||
vmax = 8; /* max length of vendor */
|
||||
vskip = vendor;
|
||||
while (vmax > 0 && *vskip == ' ') {
|
||||
vmax--;
|
||||
vskip++;
|
||||
}
|
||||
/* Also skip trailing spaces */
|
||||
while (vmax > 0 && vskip[vmax - 1] == ' ')
|
||||
--vmax;
|
||||
|
||||
mmax = 16; /* max length of model */
|
||||
mskip = model;
|
||||
while (mmax > 0 && *mskip == ' ') {
|
||||
mmax--;
|
||||
mskip++;
|
||||
}
|
||||
while (mmax > 0 && mskip[mmax - 1] == ' ')
|
||||
--mmax;
|
||||
|
||||
list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
|
||||
dev_info_list) {
|
||||
@ -416,61 +448,48 @@ int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
|
||||
/*
|
||||
* Behave like the older version of get_device_flags.
|
||||
*/
|
||||
size_t max;
|
||||
/*
|
||||
* XXX why skip leading spaces? If an odd INQUIRY
|
||||
* value, that should have been part of the
|
||||
* scsi_static_device_list[] entry, such as " FOO"
|
||||
* rather than "FOO". Since this code is already
|
||||
* here, and we don't know what device it is
|
||||
* trying to work with, leave it as-is.
|
||||
*/
|
||||
max = 8; /* max length of vendor */
|
||||
while ((max > 0) && *vendor == ' ') {
|
||||
max--;
|
||||
vendor++;
|
||||
}
|
||||
/*
|
||||
* XXX removing the following strlen() would be
|
||||
* good, using it means that for a an entry not in
|
||||
* the list, we scan every byte of every vendor
|
||||
* listed in scsi_static_device_list[], and never match
|
||||
* a single one (and still have to compare at
|
||||
* least the first byte of each vendor).
|
||||
*/
|
||||
if (memcmp(devinfo->vendor, vendor,
|
||||
min(max, strlen(devinfo->vendor))))
|
||||
if (memcmp(devinfo->vendor, vskip, vmax) ||
|
||||
devinfo->vendor[vmax])
|
||||
continue;
|
||||
/*
|
||||
* Skip spaces again.
|
||||
*/
|
||||
max = 16; /* max length of model */
|
||||
while ((max > 0) && *model == ' ') {
|
||||
max--;
|
||||
model++;
|
||||
}
|
||||
if (memcmp(devinfo->model, model,
|
||||
min(max, strlen(devinfo->model))))
|
||||
if (memcmp(devinfo->model, mskip, mmax) ||
|
||||
devinfo->model[mmax])
|
||||
continue;
|
||||
found = devinfo;
|
||||
return devinfo;
|
||||
} else {
|
||||
if (!memcmp(devinfo->vendor, vendor,
|
||||
sizeof(devinfo->vendor)) &&
|
||||
!memcmp(devinfo->model, model,
|
||||
sizeof(devinfo->model)))
|
||||
found = devinfo;
|
||||
return devinfo;
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
list_del(&found->dev_info_list);
|
||||
kfree(found);
|
||||
return 0;
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
/**
|
||||
* scsi_dev_info_list_del_keyed - remove one dev_info list entry.
|
||||
* @vendor: vendor string
|
||||
* @model: model (product) string
|
||||
* @key: specify list to use
|
||||
*
|
||||
* Description:
|
||||
* Remove and destroy one dev_info entry for @vendor, @model
|
||||
* in list specified by @key.
|
||||
*
|
||||
* Returns: 0 OK, -error on failure.
|
||||
**/
|
||||
int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
|
||||
{
|
||||
struct scsi_dev_info_list *found;
|
||||
|
||||
found = scsi_dev_info_list_find(vendor, model, key);
|
||||
if (IS_ERR(found))
|
||||
return PTR_ERR(found);
|
||||
|
||||
list_del(&found->dev_info_list);
|
||||
kfree(found);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
|
||||
|
||||
@ -565,64 +584,16 @@ int scsi_get_device_flags_keyed(struct scsi_device *sdev,
|
||||
int key)
|
||||
{
|
||||
struct scsi_dev_info_list *devinfo;
|
||||
struct scsi_dev_info_list_table *devinfo_table;
|
||||
int err;
|
||||
|
||||
devinfo_table = scsi_devinfo_lookup_by_key(key);
|
||||
devinfo = scsi_dev_info_list_find(vendor, model, key);
|
||||
if (!IS_ERR(devinfo))
|
||||
return devinfo->flags;
|
||||
|
||||
if (IS_ERR(devinfo_table))
|
||||
return PTR_ERR(devinfo_table);
|
||||
err = PTR_ERR(devinfo);
|
||||
if (err != -ENOENT)
|
||||
return err;
|
||||
|
||||
list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
|
||||
dev_info_list) {
|
||||
if (devinfo->compatible) {
|
||||
/*
|
||||
* Behave like the older version of get_device_flags.
|
||||
*/
|
||||
size_t max;
|
||||
/*
|
||||
* XXX why skip leading spaces? If an odd INQUIRY
|
||||
* value, that should have been part of the
|
||||
* scsi_static_device_list[] entry, such as " FOO"
|
||||
* rather than "FOO". Since this code is already
|
||||
* here, and we don't know what device it is
|
||||
* trying to work with, leave it as-is.
|
||||
*/
|
||||
max = 8; /* max length of vendor */
|
||||
while ((max > 0) && *vendor == ' ') {
|
||||
max--;
|
||||
vendor++;
|
||||
}
|
||||
/*
|
||||
* XXX removing the following strlen() would be
|
||||
* good, using it means that for a an entry not in
|
||||
* the list, we scan every byte of every vendor
|
||||
* listed in scsi_static_device_list[], and never match
|
||||
* a single one (and still have to compare at
|
||||
* least the first byte of each vendor).
|
||||
*/
|
||||
if (memcmp(devinfo->vendor, vendor,
|
||||
min(max, strlen(devinfo->vendor))))
|
||||
continue;
|
||||
/*
|
||||
* Skip spaces again.
|
||||
*/
|
||||
max = 16; /* max length of model */
|
||||
while ((max > 0) && *model == ' ') {
|
||||
max--;
|
||||
model++;
|
||||
}
|
||||
if (memcmp(devinfo->model, model,
|
||||
min(max, strlen(devinfo->model))))
|
||||
continue;
|
||||
return devinfo->flags;
|
||||
} else {
|
||||
if (!memcmp(devinfo->vendor, vendor,
|
||||
sizeof(devinfo->vendor)) &&
|
||||
!memcmp(devinfo->model, model,
|
||||
sizeof(devinfo->model)))
|
||||
return devinfo->flags;
|
||||
}
|
||||
}
|
||||
/* nothing found, return nothing */
|
||||
if (key != SCSI_DEVINFO_GLOBAL)
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user