SCSI misc on 20191130

This is mostly update of the usual drivers: aacraid, ufs, zfcp,
 NCR5380, lpfc, qla2xxx, smartpqi, hisi_sas, target, mpt3sas, pm80xx
 plus a whole load of minor updates and fixes.  The two major core
 changes are Al Viro's reworking of sg's handling of copy to/from user,
 Ming Lei's removal of the host busy counter to avoid contention in the
 multiqueue case and Damien Le Moal's fixing of residual tracking
 across error handling.
 
 Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com>
 -----BEGIN PGP SIGNATURE-----
 
 iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCXeKvHCYcamFtZXMuYm90
 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishQJMAQDAjlAi
 SNfbyndMqyf+rZGWufDI+43Up1VvW9GeWJHeDwEAxfO5XZsCks2uT8UxXhpEp9L7
 HkiUww3zbcgl0FWFkUM=
 =cdVU
 -----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:
 "This is mostly update of the usual drivers: aacraid, ufs, zfcp,
  NCR5380, lpfc, qla2xxx, smartpqi, hisi_sas, target, mpt3sas, pm80xx
  plus a whole load of minor updates and fixes.

  The major core changes are Al Viro's reworking of sg's handling of
  copy to/from user, Ming Lei's removal of the host busy counter to
  avoid contention in the multiqueue case and Damien Le Moal's fixing of
  residual tracking across error handling"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (251 commits)
  scsi: bnx2fc: timeout calculation invalid for bnx2fc_eh_abort()
  scsi: target: core: Fix a pr_debug() argument
  scsi: iscsi: Don't send data to unbound connection
  scsi: target: iscsi: Wait for all commands to finish before freeing a session
  scsi: target: core: Release SPC-2 reservations when closing a session
  scsi: target: core: Document target_cmd_size_check()
  scsi: bnx2i: fix potential use after free
  Revert "scsi: qla2xxx: Fix memory leak when sending I/O fails"
  scsi: NCR5380: Add disconnect_mask module parameter
  scsi: NCR5380: Unconditionally clear ICR after do_abort()
  scsi: NCR5380: Call scsi_set_resid() on command completion
  scsi: scsi_debug: num_tgts must be >= 0
  scsi: lpfc: use hdwq assigned cpu for allocation
  scsi: arcmsr: fix indentation issues
  scsi: qla4xxx: fix double free bug
  scsi: pm80xx: Modified the logic to collect fatal dump
  scsi: pm80xx: Tie the interrupt name to the module instance
  scsi: pm80xx: Controller fatal error through sysfs
  scsi: pm80xx: Do not request 12G sas speeds
  scsi: pm80xx: Cleanup command when a reset times out
  ...
This commit is contained in:
Linus Torvalds 2019-12-02 13:37:02 -08:00
commit ef2cc88e2a
163 changed files with 5655 additions and 1986 deletions

View File

@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/ufs/ti,j721e-ufs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI J721e UFS Host Controller Glue Driver
maintainers:
- Vignesh Raghavendra <vigneshr@ti.com>
properties:
compatible:
items:
- const: ti,j721e-ufs
reg:
maxItems: 1
description: address of TI UFS glue registers
clocks:
maxItems: 1
description: phandle to the M-PHY clock
power-domains:
maxItems: 1
required:
- compatible
- reg
- clocks
- power-domains
patternProperties:
"^ufs@[0-9a-f]+$":
type: object
description: |
Cadence UFS controller node must be the child node. Refer
Documentation/devicetree/bindings/ufs/cdns,ufshc.txt for binding
documentation of child node
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
ufs_wrapper: ufs-wrapper@4e80000 {
compatible = "ti,j721e-ufs";
reg = <0x0 0x4e80000 0x0 0x100>;
power-domains = <&k3_pds 277>;
clocks = <&k3_clks 277 1>;
assigned-clocks = <&k3_clks 277 1>;
assigned-clock-parents = <&k3_clks 277 4>;
#address-cells = <2>;
#size-cells = <2>;
ufs@4e84000 {
compatible = "cdns,ufshc-m31-16nm", "jedec,ufs-2.0";
reg = <0x0 0x4e84000 0x0 0x10000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
freq-table-hz = <19200000 19200000>;
power-domains = <&k3_pds 277>;
clocks = <&k3_clks 277 1>;
assigned-clocks = <&k3_clks 277 1>;
assigned-clock-parents = <&k3_clks 277 4>;
clock-names = "core_clk";
};
};

View File

@ -13,6 +13,7 @@ Required properties:
"qcom,msm8996-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
"qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
"qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
"qcom,sm8150-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
- interrupts : <interrupt mapping for UFS host controller IRQ>
- reg : <registers mapping>

View File

@ -1084,7 +1084,8 @@ of interest:
commands to the adapter.
this_id - scsi id of host (scsi initiator) or -1 if not known
sg_tablesize - maximum scatter gather elements allowed by host.
0 implies scatter gather not supported by host
Set this to SG_ALL or less to avoid chained SG lists.
Must be at least 1.
max_sectors - maximum number of sectors (usually 512 bytes) allowed
in a single SCSI command. The default value of 0 leads
to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in

View File

@ -219,7 +219,6 @@ struct arasan_cf_dev {
static struct scsi_host_template arasan_cf_sht = {
ATA_BASE_SHT(DRIVER_NAME),
.sg_tablesize = SG_NONE,
.dma_boundary = 0xFFFFFFFFUL,
};

View File

@ -5,6 +5,6 @@
zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_dbf.o zfcp_erp.o \
zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
zfcp_unit.o
zfcp_unit.o zfcp_diag.o
obj-$(CONFIG_ZFCP) += zfcp.o

View File

@ -4,7 +4,7 @@
*
* Module interface and handling of zfcp data structures.
*
* Copyright IBM Corp. 2002, 2017
* Copyright IBM Corp. 2002, 2018
*/
/*
@ -25,6 +25,7 @@
* Martin Petermann
* Sven Schuetz
* Steffen Maier
* Benjamin Block
*/
#define KMSG_COMPONENT "zfcp"
@ -36,6 +37,7 @@
#include "zfcp_ext.h"
#include "zfcp_fc.h"
#include "zfcp_reqlist.h"
#include "zfcp_diag.h"
#define ZFCP_BUS_ID_SIZE 20
@ -356,6 +358,9 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
adapter->erp_action.adapter = adapter;
if (zfcp_diag_adapter_setup(adapter))
goto failed;
if (zfcp_qdio_setup(adapter))
goto failed;
@ -402,6 +407,9 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
&zfcp_sysfs_adapter_attrs))
goto failed;
if (zfcp_diag_sysfs_setup(adapter))
goto failed;
/* report size limit per scatter-gather segment */
adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
@ -426,6 +434,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
zfcp_fc_wka_ports_force_offline(adapter->gs);
zfcp_scsi_adapter_unregister(adapter);
zfcp_diag_sysfs_destroy(adapter);
sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
zfcp_erp_thread_kill(adapter);
@ -449,6 +458,7 @@ void zfcp_adapter_release(struct kref *ref)
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
zfcp_fc_gs_destroy(adapter);
zfcp_free_low_mem_buffers(adapter);
zfcp_diag_adapter_free(adapter);
kfree(adapter->req_list);
kfree(adapter->fc_stats);
kfree(adapter->stats_reset_data);

View File

@ -95,11 +95,9 @@ void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req)
memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual,
FSF_STATUS_QUALIFIER_SIZE);
if (q_head->fsf_command != FSF_QTCB_FCP_CMND) {
rec->pl_len = q_head->log_length;
zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start,
rec->pl_len, "fsf_res", req->req_id);
}
rec->pl_len = q_head->log_length;
zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start,
rec->pl_len, "fsf_res", req->req_id);
debug_event(dbf->hba, level, rec, sizeof(*rec));
spin_unlock_irqrestore(&dbf->hba_lock, flags);

View File

@ -4,7 +4,7 @@
*
* Global definitions for the zfcp device driver.
*
* Copyright IBM Corp. 2002, 2017
* Copyright IBM Corp. 2002, 2018
*/
#ifndef ZFCP_DEF_H
@ -86,6 +86,7 @@
#define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080
#define ZFCP_STATUS_FSFREQ_TMFUNCFAILED 0x00000200
#define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000
#define ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE 0x00020000
/************************* STRUCTURE DEFINITIONS *****************************/
@ -197,6 +198,7 @@ struct zfcp_adapter {
struct device_dma_parameters dma_parms;
struct zfcp_fc_events events;
unsigned long next_port_scan;
struct zfcp_diag_adapter *diagnostics;
};
struct zfcp_port {

View File

@ -0,0 +1,305 @@
// SPDX-License-Identifier: GPL-2.0
/*
* zfcp device driver
*
* Functions to handle diagnostics.
*
* Copyright IBM Corp. 2018
*/
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/kernfs.h>
#include <linux/sysfs.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include "zfcp_diag.h"
#include "zfcp_ext.h"
#include "zfcp_def.h"
static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
/**
* zfcp_diag_adapter_setup() - Setup storage for adapter diagnostics.
* @adapter: the adapter to setup diagnostics for.
*
* Creates the data-structures to store the diagnostics for an adapter. This
* overwrites whatever was stored before at &zfcp_adapter->diagnostics!
*
* Return:
* * 0 - Everyting is OK
* * -ENOMEM - Could not allocate all/parts of the data-structures;
* &zfcp_adapter->diagnostics remains unchanged
*/
int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
{
struct zfcp_diag_adapter *diag;
struct zfcp_diag_header *hdr;
diag = kzalloc(sizeof(*diag), GFP_KERNEL);
if (diag == NULL)
return -ENOMEM;
diag->max_age = (5 * 1000); /* default value: 5 s */
/* setup header for port_data */
hdr = &diag->port_data.header;
spin_lock_init(&hdr->access_lock);
hdr->buffer = &diag->port_data.data;
hdr->buffer_size = sizeof(diag->port_data.data);
/* set the timestamp so that the first test on age will always fail */
hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
/* setup header for config_data */
hdr = &diag->config_data.header;
spin_lock_init(&hdr->access_lock);
hdr->buffer = &diag->config_data.data;
hdr->buffer_size = sizeof(diag->config_data.data);
/* set the timestamp so that the first test on age will always fail */
hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
adapter->diagnostics = diag;
return 0;
}
/**
* zfcp_diag_adapter_free() - Frees all adapter diagnostics allocations.
* @adapter: the adapter whose diagnostic structures should be freed.
*
* Frees all data-structures in the given adapter that store diagnostics
* information. Can savely be called with partially setup diagnostics.
*/
void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter)
{
kfree(adapter->diagnostics);
adapter->diagnostics = NULL;
}
/**
* zfcp_diag_sysfs_setup() - Setup the sysfs-group for adapter-diagnostics.
* @adapter: target adapter to which the group should be added.
*
* Return: 0 on success; Something else otherwise (see sysfs_create_group()).
*/
int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter)
{
int rc = sysfs_create_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_diag_attr_group);
if (rc == 0)
adapter->diagnostics->sysfs_established = 1;
return rc;
}
/**
* zfcp_diag_sysfs_destroy() - Remove the sysfs-group for adapter-diagnostics.
* @adapter: target adapter from which the group should be removed.
*/
void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter)
{
if (adapter->diagnostics == NULL ||
!adapter->diagnostics->sysfs_established)
return;
/*
* We need this state-handling so we can prevent warnings being printed
* on the kernel-console in case we have to abort a halfway done
* zfcp_adapter_enqueue(), in which the sysfs-group was not yet
* established. sysfs_remove_group() does this checking as well, but
* still prints a warning in case we try to remove a group that has not
* been established before
*/
adapter->diagnostics->sysfs_established = 0;
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_diag_attr_group);
}
/**
* zfcp_diag_update_xdata() - Update a diagnostics buffer.
* @hdr: the meta data to update.
* @data: data to use for the update.
* @incomplete: flag stating whether the data in @data is incomplete.
*/
void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
const void *const data, const bool incomplete)
{
const unsigned long capture_timestamp = jiffies;
unsigned long flags;
spin_lock_irqsave(&hdr->access_lock, flags);
/* make sure we never go into the past with an update */
if (!time_after_eq(capture_timestamp, hdr->timestamp))
goto out;
hdr->timestamp = capture_timestamp;
hdr->incomplete = incomplete;
memcpy(hdr->buffer, data, hdr->buffer_size);
out:
spin_unlock_irqrestore(&hdr->access_lock, flags);
}
/**
* zfcp_diag_update_port_data_buffer() - Implementation of
* &typedef zfcp_diag_update_buffer_func
* to collect and update Port Data.
* @adapter: Adapter to collect Port Data from.
*
* This call is SYNCHRONOUS ! It blocks till the respective command has
* finished completely, or has failed in some way.
*
* Return:
* * 0 - Successfully retrieved new Diagnostics and Updated the buffer;
* this also includes cases where data was retrieved, but
* incomplete; you'll have to check the flag ``incomplete``
* of &struct zfcp_diag_header.
* * see zfcp_fsf_exchange_port_data_sync() for possible error-codes (
* excluding -EAGAIN)
*/
int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter)
{
int rc;
rc = zfcp_fsf_exchange_port_data_sync(adapter->qdio, NULL);
if (rc == -EAGAIN)
rc = 0; /* signaling incomplete via struct zfcp_diag_header */
/* buffer-data was updated in zfcp_fsf_exchange_port_data_handler() */
return rc;
}
/**
* zfcp_diag_update_config_data_buffer() - Implementation of
* &typedef zfcp_diag_update_buffer_func
* to collect and update Config Data.
* @adapter: Adapter to collect Config Data from.
*
* This call is SYNCHRONOUS ! It blocks till the respective command has
* finished completely, or has failed in some way.
*
* Return:
* * 0 - Successfully retrieved new Diagnostics and Updated the buffer;
* this also includes cases where data was retrieved, but
* incomplete; you'll have to check the flag ``incomplete``
* of &struct zfcp_diag_header.
* * see zfcp_fsf_exchange_config_data_sync() for possible error-codes (
* excluding -EAGAIN)
*/
int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter)
{
int rc;
rc = zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL);
if (rc == -EAGAIN)
rc = 0; /* signaling incomplete via struct zfcp_diag_header */
/* buffer-data was updated in zfcp_fsf_exchange_config_data_handler() */
return rc;
}
static int __zfcp_diag_update_buffer(struct zfcp_adapter *const adapter,
struct zfcp_diag_header *const hdr,
zfcp_diag_update_buffer_func buffer_update,
unsigned long *const flags)
__must_hold(hdr->access_lock)
{
int rc;
if (hdr->updating == 1) {
rc = wait_event_interruptible_lock_irq(__zfcp_diag_publish_wait,
hdr->updating == 0,
hdr->access_lock);
rc = (rc == 0 ? -EAGAIN : -EINTR);
} else {
hdr->updating = 1;
spin_unlock_irqrestore(&hdr->access_lock, *flags);
/* unlocked, because update function sleeps */
rc = buffer_update(adapter);
spin_lock_irqsave(&hdr->access_lock, *flags);
hdr->updating = 0;
/*
* every thread waiting here went via an interruptible wait,
* so its fine to only wake those
*/
wake_up_interruptible_all(&__zfcp_diag_publish_wait);
}
return rc;
}
static bool
__zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_adapter *const diag,
const struct zfcp_diag_header *const hdr)
__must_hold(hdr->access_lock)
{
const unsigned long now = jiffies;
/*
* Should not happen (data is from the future).. if it does, still
* signal that it needs refresh
*/
if (!time_after_eq(now, hdr->timestamp))
return false;
if (jiffies_to_msecs(now - hdr->timestamp) >= diag->max_age)
return false;
return true;
}
/**
* zfcp_diag_update_buffer_limited() - Collect diagnostics and update a
* diagnostics buffer rate limited.
* @adapter: Adapter to collect the diagnostics from.
* @hdr: buffer-header for which to update with the collected diagnostics.
* @buffer_update: Specific implementation for collecting and updating.
*
* This function will cause an update of the given @hdr by calling the also
* given @buffer_update function. If called by multiple sources at the same
* time, it will synchornize the update by only allowing one source to call
* @buffer_update and the others to wait for that source to complete instead
* (the wait is interruptible).
*
* Additionally this version is rate-limited and will only exit if either the
* buffer is fresh enough (within the limit) - it will do nothing if the buffer
* is fresh enough to begin with -, or if the source/thread that started this
* update is the one that made the update (to prevent endless loops).
*
* Return:
* * 0 - If the update was successfully published and/or the buffer is
* fresh enough
* * -EINTR - If the thread went into the wait-state and was interrupted
* * whatever @buffer_update returns
*/
int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
struct zfcp_diag_header *const hdr,
zfcp_diag_update_buffer_func buffer_update)
{
unsigned long flags;
int rc;
spin_lock_irqsave(&hdr->access_lock, flags);
for (rc = 0;
!__zfcp_diag_test_buffer_age_isfresh(adapter->diagnostics, hdr);
rc = 0) {
rc = __zfcp_diag_update_buffer(adapter, hdr, buffer_update,
&flags);
if (rc != -EAGAIN)
break;
}
spin_unlock_irqrestore(&hdr->access_lock, flags);
return rc;
}

View File

@ -0,0 +1,101 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* zfcp device driver
*
* Definitions for handling diagnostics in the the zfcp device driver.
*
* Copyright IBM Corp. 2018
*/
#ifndef ZFCP_DIAG_H
#define ZFCP_DIAG_H
#include <linux/spinlock.h>
#include "zfcp_fsf.h"
#include "zfcp_def.h"
/**
* struct zfcp_diag_header - general part of a diagnostic buffer.
* @access_lock: lock protecting all the data in this buffer.
* @updating: flag showing that an update for this buffer is currently running.
* @incomplete: flag showing that the data in @buffer is incomplete.
* @timestamp: time in jiffies when the data of this buffer was last captured.
* @buffer: implementation-depending data of this buffer
* @buffer_size: size of @buffer
*/
struct zfcp_diag_header {
spinlock_t access_lock;
/* Flags */
u64 updating :1;
u64 incomplete :1;
unsigned long timestamp;
void *buffer;
size_t buffer_size;
};
/**
* struct zfcp_diag_adapter - central storage for all diagnostics concerning an
* adapter.
* @sysfs_established: flag showing that the associated sysfs-group was created
* during run of zfcp_adapter_enqueue().
* @max_age: maximum age of data in diagnostic buffers before they need to be
* refreshed (in ms).
* @port_data: data retrieved using exchange port data.
* @port_data.header: header with metadata for the cache in @port_data.data.
* @port_data.data: cached QTCB Bottom of command exchange port data.
* @config_data: data retrieved using exchange config data.
* @config_data.header: header with metadata for the cache in @config_data.data.
* @config_data.data: cached QTCB Bottom of command exchange config data.
*/
struct zfcp_diag_adapter {
u64 sysfs_established :1;
unsigned long max_age;
struct {
struct zfcp_diag_header header;
struct fsf_qtcb_bottom_port data;
} port_data;
struct {
struct zfcp_diag_header header;
struct fsf_qtcb_bottom_config data;
} config_data;
};
int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter);
void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter);
int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter);
void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter);
void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
const void *const data, const bool incomplete);
/*
* Function-Type used in zfcp_diag_update_buffer_limited() for the function
* that does the buffer-implementation dependent work.
*/
typedef int (*zfcp_diag_update_buffer_func)(struct zfcp_adapter *const adapter);
int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter);
int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter);
int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
struct zfcp_diag_header *const hdr,
zfcp_diag_update_buffer_func buffer_update);
/**
* zfcp_diag_support_sfp() - Return %true if the @adapter supports reporting
* SFP Data.
* @adapter: adapter to test the availability of SFP Data reporting for.
*/
static inline bool
zfcp_diag_support_sfp(const struct zfcp_adapter *const adapter)
{
return !!(adapter->adapter_features & FSF_FEATURE_REPORT_SFP_DATA);
}
#endif /* ZFCP_DIAG_H */

View File

@ -174,7 +174,7 @@ static enum zfcp_erp_act_type zfcp_erp_required_act(enum zfcp_erp_act_type want,
return 0;
p_status = atomic_read(&port->status);
if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
return 0;
if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED))
need = ZFCP_ERP_ACTION_REOPEN_PORT;
@ -190,7 +190,7 @@ static enum zfcp_erp_act_type zfcp_erp_required_act(enum zfcp_erp_act_type want,
return 0;
a_status = atomic_read(&adapter->status);
if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
return 0;
if (p_status & ZFCP_STATUS_COMMON_NOESC)
return need;

View File

@ -167,6 +167,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[];
extern struct mutex zfcp_sysfs_port_units_mutex;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
extern const struct attribute_group zfcp_sysfs_diag_attr_group;
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
/* zfcp_unit.c */

View File

@ -11,6 +11,7 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/blktrace_api.h>
#include <linux/jiffies.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <scsi/fc/fc_els.h>
@ -19,6 +20,7 @@
#include "zfcp_dbf.h"
#include "zfcp_qdio.h"
#include "zfcp_reqlist.h"
#include "zfcp_diag.h"
/* timeout for FSF requests sent during scsi_eh: abort or FCP TMF */
#define ZFCP_FSF_SCSI_ER_TIMEOUT (10*HZ)
@ -554,6 +556,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
struct zfcp_diag_header *const diag_hdr =
&adapter->diagnostics->config_data.header;
struct fsf_qtcb *qtcb = req->qtcb;
struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
struct Scsi_Host *shost = adapter->scsi_host;
@ -570,6 +574,12 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
/*
* usually we wait with an update till the cache is too old,
* but because we have the data available, update it anyway
*/
zfcp_diag_update_xdata(diag_hdr, bottom, false);
if (zfcp_fsf_exchange_config_evaluate(req))
return;
@ -585,6 +595,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
&adapter->status);
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
zfcp_diag_update_xdata(diag_hdr, bottom, true);
req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
fc_host_node_name(shost) = 0;
fc_host_port_name(shost) = 0;
fc_host_port_id(shost) = 0;
@ -653,16 +666,28 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
{
struct zfcp_diag_header *const diag_hdr =
&req->adapter->diagnostics->port_data.header;
struct fsf_qtcb *qtcb = req->qtcb;
struct fsf_qtcb_bottom_port *bottom = &qtcb->bottom.port;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
/*
* usually we wait with an update till the cache is too old,
* but because we have the data available, update it anyway
*/
zfcp_diag_update_xdata(diag_hdr, bottom, false);
zfcp_fsf_exchange_port_evaluate(req);
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
zfcp_diag_update_xdata(diag_hdr, bottom, true);
req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
zfcp_fsf_exchange_port_evaluate(req);
zfcp_fsf_link_down_info_eval(req,
&qtcb->header.fsf_status_qual.link_down_info);
@ -1261,7 +1286,8 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
FSF_FEATURE_UPDATE_ALERT |
FSF_FEATURE_REQUEST_SFP_DATA;
req->erp_action = erp_action;
req->handler = zfcp_fsf_exchange_config_data_handler;
erp_action->fsf_req_id = req->req_id;
@ -1278,6 +1304,19 @@ out:
return retval;
}
/**
* zfcp_fsf_exchange_config_data_sync() - Request information about FCP channel.
* @qdio: pointer to the QDIO-Queue to use for sending the command.
* @data: pointer to the QTCB-Bottom for storing the result of the command,
* might be %NULL.
*
* Returns:
* * 0 - Exchange Config Data was successful, @data is complete
* * -EIO - Exchange Config Data was not successful, @data is invalid
* * -EAGAIN - @data contains incomplete data
* * -ENOMEM - Some memory allocation failed along the way
*/
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_config *data)
{
@ -1301,7 +1340,8 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
FSF_FEATURE_UPDATE_ALERT |
FSF_FEATURE_REQUEST_SFP_DATA;
if (data)
req->data = data;
@ -1309,9 +1349,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
spin_unlock_irq(&qdio->req_q_lock);
if (!retval) {
/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
wait_for_completion(&req->completion);
if (req->status &
(ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
retval = -EIO;
else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
retval = -EAGAIN;
}
zfcp_fsf_req_free(req);
@ -1369,10 +1416,17 @@ out:
}
/**
* zfcp_fsf_exchange_port_data_sync - request information about local port
* @qdio: pointer to struct zfcp_qdio
* @data: pointer to struct fsf_qtcb_bottom_port
* Returns: 0 on success, error otherwise
* zfcp_fsf_exchange_port_data_sync() - Request information about local port.
* @qdio: pointer to the QDIO-Queue to use for sending the command.
* @data: pointer to the QTCB-Bottom for storing the result of the command,
* might be %NULL.
*
* Returns:
* * 0 - Exchange Port Data was successful, @data is complete
* * -EIO - Exchange Port Data was not successful, @data is invalid
* * -EAGAIN - @data contains incomplete data
* * -ENOMEM - Some memory allocation failed along the way
* * -EOPNOTSUPP - This operation is not supported
*/
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_port *data)
@ -1408,10 +1462,15 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
if (!retval) {
/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
wait_for_completion(&req->completion);
if (req->status &
(ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
retval = -EIO;
else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
retval = -EAGAIN;
}
zfcp_fsf_req_free(req);
return retval;
out_unlock:

View File

@ -163,6 +163,8 @@
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
#define FSF_FEATURE_REQUEST_SFP_DATA 0x00000200
#define FSF_FEATURE_REPORT_SFP_DATA 0x00000800
#define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000
#define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000
@ -407,7 +409,24 @@ struct fsf_qtcb_bottom_port {
u8 cp_util;
u8 cb_util;
u8 a_util;
u8 res2[253];
u8 res2;
u16 temperature;
u16 vcc;
u16 tx_bias;
u16 tx_power;
u16 rx_power;
union {
u16 raw;
struct {
u16 fec_active :1;
u16:7;
u16 connector_type :2;
u16 sfp_invalid :1;
u16 optical_port :1;
u16 port_tx_type :4;
};
} sfp_flags;
u8 res3[240];
} __attribute__ ((packed));
union fsf_qtcb_bottom {

View File

@ -605,7 +605,7 @@ zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host)
return NULL;
ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret) {
if (ret != 0 && ret != -EAGAIN) {
kfree(data);
return NULL;
}
@ -634,7 +634,7 @@ static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost)
return;
ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret)
if (ret != 0 && ret != -EAGAIN)
kfree(data);
else {
adapter->stats_reset = jiffies/HZ;

View File

@ -11,6 +11,7 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/slab.h>
#include "zfcp_diag.h"
#include "zfcp_ext.h"
#define ZFCP_DEV_ATTR(_feat, _name, _mode, _show, _store) \
@ -325,6 +326,50 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
zfcp_sysfs_port_remove_store);
static ssize_t
zfcp_sysfs_adapter_diag_max_age_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
ssize_t rc;
if (!adapter)
return -ENODEV;
/* ceil(log(2^64 - 1) / log(10)) = 20 */
rc = scnprintf(buf, 20 + 2, "%lu\n", adapter->diagnostics->max_age);
zfcp_ccw_adapter_put(adapter);
return rc;
}
static ssize_t
zfcp_sysfs_adapter_diag_max_age_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
unsigned long max_age;
ssize_t rc;
if (!adapter)
return -ENODEV;
rc = kstrtoul(buf, 10, &max_age);
if (rc != 0)
goto out;
adapter->diagnostics->max_age = max_age;
rc = count;
out:
zfcp_ccw_adapter_put(adapter);
return rc;
}
static ZFCP_DEV_ATTR(adapter, diag_max_age, 0644,
zfcp_sysfs_adapter_diag_max_age_show,
zfcp_sysfs_adapter_diag_max_age_store);
static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_adapter_failed.attr,
&dev_attr_adapter_in_recovery.attr,
@ -337,6 +382,7 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_adapter_lic_version.attr,
&dev_attr_adapter_status.attr,
&dev_attr_adapter_hardware_version.attr,
&dev_attr_adapter_diag_max_age.attr,
NULL
};
@ -577,7 +623,7 @@ static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
return -ENOMEM;
retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
if (!retval)
if (retval == 0 || retval == -EAGAIN)
retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
qtcb_port->cb_util, qtcb_port->a_util);
kfree(qtcb_port);
@ -603,7 +649,7 @@ static int zfcp_sysfs_adapter_ex_config(struct device *dev,
return -ENOMEM;
retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
if (!retval)
if (retval == 0 || retval == -EAGAIN)
*stat_inf = qtcb_config->stat_info;
kfree(qtcb_config);
@ -664,3 +710,123 @@ struct device_attribute *zfcp_sysfs_shost_attrs[] = {
&dev_attr_queue_full,
NULL
};
static ssize_t zfcp_sysfs_adapter_diag_b2b_credit_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
struct zfcp_diag_header *diag_hdr;
struct fc_els_flogi *nsp;
ssize_t rc = -ENOLINK;
unsigned long flags;
unsigned int status;
if (!adapter)
return -ENODEV;
status = atomic_read(&adapter->status);
if (0 == (status & ZFCP_STATUS_COMMON_OPEN) ||
0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) ||
0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED))
goto out;
diag_hdr = &adapter->diagnostics->config_data.header;
rc = zfcp_diag_update_buffer_limited(
adapter, diag_hdr, zfcp_diag_update_config_data_buffer);
if (rc != 0)
goto out;
spin_lock_irqsave(&diag_hdr->access_lock, flags);
/* nport_serv_param doesn't contain the ELS_Command code */
nsp = (struct fc_els_flogi *)((unsigned long)
adapter->diagnostics->config_data
.data.nport_serv_param -
sizeof(u32));
rc = scnprintf(buf, 5 + 2, "%hu\n",
be16_to_cpu(nsp->fl_csp.sp_bb_cred));
spin_unlock_irqrestore(&diag_hdr->access_lock, flags);
out:
zfcp_ccw_adapter_put(adapter);
return rc;
}
static ZFCP_DEV_ATTR(adapter_diag, b2b_credit, 0400,
zfcp_sysfs_adapter_diag_b2b_credit_show, NULL);
#define ZFCP_DEFINE_DIAG_SFP_ATTR(_name, _qtcb_member, _prtsize, _prtfmt) \
static ssize_t zfcp_sysfs_adapter_diag_sfp_##_name##_show( \
struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct zfcp_adapter *const adapter = \
zfcp_ccw_adapter_by_cdev(to_ccwdev(dev)); \
struct zfcp_diag_header *diag_hdr; \
ssize_t rc = -ENOLINK; \
unsigned long flags; \
unsigned int status; \
\
if (!adapter) \
return -ENODEV; \
\
status = atomic_read(&adapter->status); \
if (0 == (status & ZFCP_STATUS_COMMON_OPEN) || \
0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) || \
0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED)) \
goto out; \
\
if (!zfcp_diag_support_sfp(adapter)) { \
rc = -EOPNOTSUPP; \
goto out; \
} \
\
diag_hdr = &adapter->diagnostics->port_data.header; \
\
rc = zfcp_diag_update_buffer_limited( \
adapter, diag_hdr, zfcp_diag_update_port_data_buffer); \
if (rc != 0) \
goto out; \
\
spin_lock_irqsave(&diag_hdr->access_lock, flags); \
rc = scnprintf( \
buf, (_prtsize) + 2, _prtfmt "\n", \
adapter->diagnostics->port_data.data._qtcb_member); \
spin_unlock_irqrestore(&diag_hdr->access_lock, flags); \
\
out: \
zfcp_ccw_adapter_put(adapter); \
return rc; \
} \
static ZFCP_DEV_ATTR(adapter_diag_sfp, _name, 0400, \
zfcp_sysfs_adapter_diag_sfp_##_name##_show, NULL)
ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 5, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(vcc, vcc, 5, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(tx_bias, tx_bias, 5, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(tx_power, tx_power, 5, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(rx_power, rx_power, 5, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(port_tx_type, sfp_flags.port_tx_type, 2, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(optical_port, sfp_flags.optical_port, 1, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(sfp_invalid, sfp_flags.sfp_invalid, 1, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(connector_type, sfp_flags.connector_type, 1, "%hu");
ZFCP_DEFINE_DIAG_SFP_ATTR(fec_active, sfp_flags.fec_active, 1, "%hu");
static struct attribute *zfcp_sysfs_diag_attrs[] = {
&dev_attr_adapter_diag_sfp_temperature.attr,
&dev_attr_adapter_diag_sfp_vcc.attr,
&dev_attr_adapter_diag_sfp_tx_bias.attr,
&dev_attr_adapter_diag_sfp_tx_power.attr,
&dev_attr_adapter_diag_sfp_rx_power.attr,
&dev_attr_adapter_diag_sfp_port_tx_type.attr,
&dev_attr_adapter_diag_sfp_optical_port.attr,
&dev_attr_adapter_diag_sfp_sfp_invalid.attr,
&dev_attr_adapter_diag_sfp_connector_type.attr,
&dev_attr_adapter_diag_sfp_fec_active.attr,
&dev_attr_adapter_diag_b2b_credit.attr,
NULL,
};
const struct attribute_group zfcp_sysfs_diag_attr_group = {
.name = "diagnostics",
.attrs = zfcp_sysfs_diag_attrs,
};

View File

@ -129,6 +129,9 @@
#define NCR5380_release_dma_irq(x)
#endif
static unsigned int disconnect_mask = ~0;
module_param(disconnect_mask, int, 0444);
static int do_abort(struct Scsi_Host *);
static void do_reset(struct Scsi_Host *);
static void bus_reset_cleanup(struct Scsi_Host *);
@ -172,6 +175,19 @@ static inline void advance_sg_buffer(struct scsi_cmnd *cmd)
}
}
static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
{
int resid = cmd->SCp.this_residual;
struct scatterlist *s = cmd->SCp.buffer;
if (s)
while (!sg_is_last(s)) {
s = sg_next(s);
resid += s->length;
}
scsi_set_resid(cmd, resid);
}
/**
* NCR5380_poll_politely2 - wait for two chip register values
* @hostdata: host private data
@ -954,7 +970,8 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
int err;
bool ret = true;
bool can_disconnect = instance->irq != NO_IRQ &&
cmd->cmnd[0] != REQUEST_SENSE;
cmd->cmnd[0] != REQUEST_SENSE &&
(disconnect_mask & BIT(scmd_id(cmd)));
NCR5380_dprint(NDEBUG_ARBITRATION, instance);
dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n",
@ -1379,7 +1396,7 @@ static void do_reset(struct Scsi_Host *instance)
* MESSAGE OUT phase and sending an ABORT message.
* @instance: relevant scsi host instance
*
* Returns 0 on success, -1 on failure.
* Returns 0 on success, negative error code on failure.
*/
static int do_abort(struct Scsi_Host *instance)
@ -1404,7 +1421,7 @@ static int do_abort(struct Scsi_Host *instance)
rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
if (rc < 0)
goto timeout;
goto out;
tmp = NCR5380_read(STATUS_REG) & PHASE_MASK;
@ -1415,7 +1432,7 @@ static int do_abort(struct Scsi_Host *instance)
ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ);
if (rc < 0)
goto timeout;
goto out;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
}
@ -1424,17 +1441,17 @@ static int do_abort(struct Scsi_Host *instance)
len = 1;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
if (len)
rc = -ENXIO;
/*
* If we got here, and the command completed successfully,
* we're about to go into bus free state.
*/
return len ? -1 : 0;
timeout:
out:
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
return -1;
return rc;
}
/*
@ -1803,6 +1820,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
cmd->result |= cmd->SCp.Status;
cmd->result |= cmd->SCp.Message << 8;
set_resid_from_SCp(cmd);
if (cmd->cmnd[0] == REQUEST_SENSE)
complete_cmd(instance, cmd);
else {
@ -2264,7 +2283,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
hostdata->dma_len = 0;
if (do_abort(instance)) {
if (do_abort(instance) < 0) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;

View File

@ -1477,6 +1477,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd
struct aac_srb * srbcmd;
u32 flag;
u32 timeout;
struct aac_dev *dev = fib->dev;
aac_fib_init(fib);
switch(cmd->sc_data_direction){
@ -1503,7 +1504,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd
srbcmd->flags = cpu_to_le32(flag);
timeout = cmd->request->timeout/HZ;
if (timeout == 0)
timeout = 1;
timeout = (dev->sa_firmware ? AAC_SA_TIMEOUT : AAC_ARC_TIMEOUT);
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
srbcmd->retry_limit = 0; /* Obsolete parameter */
srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
@ -2467,13 +2468,13 @@ static int aac_read(struct scsi_cmnd * scsicmd)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
SAM_STAT_CHECK_CONDITION;
set_sense(&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
ILLEGAL_REQUEST, SENCODE_LBA_OUT_OF_RANGE,
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
scsicmd->scsi_done(scsicmd);
return 1;
return 0;
}
dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
@ -2559,13 +2560,13 @@ static int aac_write(struct scsi_cmnd * scsicmd)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
SAM_STAT_CHECK_CONDITION;
set_sense(&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
ILLEGAL_REQUEST, SENCODE_LBA_OUT_OF_RANGE,
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
scsicmd->scsi_done(scsicmd);
return 1;
return 0;
}
dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",

View File

@ -85,7 +85,7 @@ enum {
#define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 50877
# define AAC_DRIVER_BUILD 50983
# define AAC_DRIVER_BRANCH "-custom"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@ -108,6 +108,8 @@ enum {
#define AAC_BUS_TARGET_LOOP (AAC_MAX_BUSES * AAC_MAX_TARGETS)
#define AAC_MAX_NATIVE_SIZE 2048
#define FW_ERROR_BUFFER_SIZE 512
#define AAC_SA_TIMEOUT 180
#define AAC_ARC_TIMEOUT 60
#define get_bus_number(x) (x/AAC_MAX_TARGETS)
#define get_target_number(x) (x%AAC_MAX_TARGETS)
@ -1328,7 +1330,7 @@ struct fib {
#define AAC_DEVTYPE_ARC_RAW 2
#define AAC_DEVTYPE_NATIVE_RAW 3
#define AAC_SAFW_RESCAN_DELAY (10 * HZ)
#define AAC_RESCAN_DELAY (10 * HZ)
struct aac_hba_map_info {
__le32 rmw_nexus; /* nexus for native HBA devices */
@ -1601,6 +1603,7 @@ struct aac_dev
struct fsa_dev_info *fsa_dev;
struct task_struct *thread;
struct delayed_work safw_rescan_work;
struct delayed_work src_reinit_aif_worker;
int cardtype;
/*
*This lock will protect the two 32-bit
@ -1673,6 +1676,7 @@ struct aac_dev
u8 adapter_shutdown;
u32 handle_pci_error;
bool init_reset;
u8 soft_reset_support;
};
#define aac_adapter_interrupt(dev) \
@ -2644,7 +2648,12 @@ int aac_scan_host(struct aac_dev *dev);
static inline void aac_schedule_safw_scan_worker(struct aac_dev *dev)
{
schedule_delayed_work(&dev->safw_rescan_work, AAC_SAFW_RESCAN_DELAY);
schedule_delayed_work(&dev->safw_rescan_work, AAC_RESCAN_DELAY);
}
static inline void aac_schedule_src_reinit_aif_worker(struct aac_dev *dev)
{
schedule_delayed_work(&dev->src_reinit_aif_worker, AAC_RESCAN_DELAY);
}
static inline void aac_safw_rescan_worker(struct work_struct *work)
@ -2658,10 +2667,10 @@ static inline void aac_safw_rescan_worker(struct work_struct *work)
aac_scan_host(dev);
}
static inline void aac_cancel_safw_rescan_worker(struct aac_dev *dev)
static inline void aac_cancel_rescan_worker(struct aac_dev *dev)
{
if (dev->sa_firmware)
cancel_delayed_work_sync(&dev->safw_rescan_work);
cancel_delayed_work_sync(&dev->safw_rescan_work);
cancel_delayed_work_sync(&dev->src_reinit_aif_worker);
}
/* SCp.phase values */
@ -2671,6 +2680,7 @@ static inline void aac_cancel_safw_rescan_worker(struct aac_dev *dev)
#define AAC_OWNER_FIRMWARE 0x106
void aac_safw_rescan_worker(struct work_struct *work);
void aac_src_reinit_aif_worker(struct work_struct *work);
int aac_acquire_irq(struct aac_dev *dev);
void aac_free_irq(struct aac_dev *dev);
int aac_setup_safw_adapter(struct aac_dev *dev);
@ -2728,6 +2738,7 @@ int aac_probe_container(struct aac_dev *dev, int cid);
int _aac_rx_init(struct aac_dev *dev);
int aac_rx_select_comm(struct aac_dev *dev, int comm);
int aac_rx_deliver_producer(struct fib * fib);
void aac_reinit_aif(struct aac_dev *aac, unsigned int index);
static inline int aac_is_src(struct aac_dev *dev)
{

View File

@ -571,6 +571,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
else
dev->sa_firmware = 0;
if (status[4] & le32_to_cpu(AAC_EXTOPT_SOFT_RESET))
dev->soft_reset_support = 1;
else
dev->soft_reset_support = 0;
if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
(status[2] > dev->base_size)) {
aac_adapter_ioremap(dev, 0);

View File

@ -232,6 +232,7 @@ struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
fibptr->type = FSAFS_NTC_FIB_CONTEXT;
fibptr->callback_data = NULL;
fibptr->callback = NULL;
fibptr->flags = 0;
return fibptr;
}
@ -1463,6 +1464,14 @@ retry_next:
}
}
static void aac_schedule_bus_scan(struct aac_dev *aac)
{
if (aac->sa_firmware)
aac_schedule_safw_scan_worker(aac);
else
aac_schedule_src_reinit_aif_worker(aac);
}
static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
{
int index, quirks;
@ -1638,7 +1647,7 @@ out:
*/
if (!retval && !is_kdump_kernel()) {
dev_info(&aac->pdev->dev, "Scheduling bus rescan\n");
aac_schedule_safw_scan_worker(aac);
aac_schedule_bus_scan(aac);
}
if (jafo) {
@ -1959,6 +1968,16 @@ int aac_scan_host(struct aac_dev *dev)
return rcode;
}
void aac_src_reinit_aif_worker(struct work_struct *work)
{
struct aac_dev *dev = container_of(to_delayed_work(work),
struct aac_dev, src_reinit_aif_worker);
wait_event(dev->scsi_host_ptr->host_wait,
!scsi_host_in_recovery(dev->scsi_host_ptr));
aac_reinit_aif(dev, dev->cardtype);
}
/**
* aac_handle_sa_aif Handle a message from the firmware
* @dev: Which adapter this fib is from

View File

@ -391,6 +391,7 @@ static int aac_slave_configure(struct scsi_device *sdev)
int chn, tid;
unsigned int depth = 0;
unsigned int set_timeout = 0;
int timeout = 0;
bool set_qd_dev_type = false;
u8 devtype = 0;
@ -483,10 +484,13 @@ common_config:
/*
* Firmware has an individual device recovery time typically
* of 35 seconds, give us a margin.
* of 35 seconds, give us a margin. Thor devices can take longer in
* error recovery, hence different value.
*/
if (set_timeout && sdev->request_queue->rq_timeout < (45 * HZ))
blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
if (set_timeout) {
timeout = aac->sa_firmware ? AAC_SA_TIMEOUT : AAC_ARC_TIMEOUT;
blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
}
if (depth > 256)
depth = 256;
@ -608,9 +612,13 @@ static struct device_attribute *aac_dev_attrs[] = {
static int aac_ioctl(struct scsi_device *sdev, unsigned int cmd,
void __user *arg)
{
int retval;
struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
retval = aac_adapter_check_health(dev);
if (retval)
return -EBUSY;
return aac_do_ioctl(dev, cmd, arg);
}
@ -1585,6 +1593,19 @@ static void aac_init_char(void)
}
}
void aac_reinit_aif(struct aac_dev *aac, unsigned int index)
{
/*
* Firmware may send a AIF messages very early and the Driver may have
* ignored as it is not fully ready to process the messages. Send
* AIF to firmware so that if there are any unprocessed events they
* can be processed now.
*/
if (aac_drivers[index].quirks & AAC_QUIRK_SRC)
aac_intr_normal(aac, 0, 2, 0, NULL);
}
static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
unsigned index = id->driver_data;
@ -1682,6 +1703,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_init(&aac->scan_mutex);
INIT_DELAYED_WORK(&aac->safw_rescan_work, aac_safw_rescan_worker);
INIT_DELAYED_WORK(&aac->src_reinit_aif_worker,
aac_src_reinit_aif_worker);
/*
* Map in the registers from the adapter.
*/
@ -1872,7 +1895,7 @@ static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
scsi_block_requests(shost);
aac_cancel_safw_rescan_worker(aac);
aac_cancel_rescan_worker(aac);
aac_send_shutdown(aac);
aac_release_resources(aac);
@ -1931,7 +1954,7 @@ static void aac_remove_one(struct pci_dev *pdev)
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
aac_cancel_safw_rescan_worker(aac);
aac_cancel_rescan_worker(aac);
scsi_remove_host(shost);
__aac_shutdown(aac);
@ -1989,7 +2012,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev,
aac->handle_pci_error = 1;
scsi_block_requests(aac->scsi_host_ptr);
aac_cancel_safw_rescan_worker(aac);
aac_cancel_rescan_worker(aac);
aac_flush_ios(aac);
aac_release_resources(aac);

View File

@ -733,10 +733,20 @@ static bool aac_is_ctrl_up_and_running(struct aac_dev *dev)
return ctrl_up;
}
static void aac_src_drop_io(struct aac_dev *dev)
{
if (!dev->soft_reset_support)
return;
aac_adapter_sync_cmd(dev, DROP_IO,
0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
static void aac_notify_fw_of_iop_reset(struct aac_dev *dev)
{
aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, NULL,
NULL, NULL, NULL, NULL);
aac_src_drop_io(dev);
}
static void aac_send_iop_reset(struct aac_dev *dev)

View File

@ -1400,7 +1400,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct Comma
, pCCB->acb
, pCCB->startdone
, atomic_read(&acb->ccboutstandingcount));
return;
return;
}
arcmsr_report_ccb_state(acb, pCCB, error);
}
@ -3476,8 +3476,8 @@ polling_hbc_ccb_retry:
, pCCB->pcmd->device->id
, (u32)pCCB->pcmd->device->lun
, pCCB);
pCCB->pcmd->result = DID_ABORT << 16;
arcmsr_ccb_complete(pCCB);
pCCB->pcmd->result = DID_ABORT << 16;
arcmsr_ccb_complete(pCCB);
continue;
}
printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb"

View File

@ -1067,7 +1067,7 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
* Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
* Params : host - host to finish
* Notes : This is called when a command is:
* terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT
* terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONNECT
* : This must not return until all transfers are completed.
*/
static
@ -1816,7 +1816,7 @@ int acornscsi_reconnect(AS_Host *host)
}
/*
* Function: int acornscsi_reconect_finish(AS_Host *host)
* Function: int acornscsi_reconnect_finish(AS_Host *host)
* Purpose : finish reconnecting a command
* Params : host - host to complete
* Returns : 0 if failed

View File

@ -742,7 +742,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
atari_scsi_template.sg_tablesize = SG_ALL;
} else {
atari_scsi_template.can_queue = 1;
atari_scsi_template.sg_tablesize = SG_NONE;
atari_scsi_template.sg_tablesize = 1;
}
if (setup_can_queue > 0)
@ -751,8 +751,8 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
if (setup_cmd_per_lun > 0)
atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
/* Leave sg_tablesize at 0 on a Falcon! */
if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0)
/* Don't increase sg_tablesize on Falcon! */
if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0)
atari_scsi_template.sg_tablesize = setup_sg_tablesize;
if (setup_hostid >= 0) {

View File

@ -1680,7 +1680,7 @@ static struct scsi_host_template atp870u_template = {
.bios_param = atp870u_biosparam /* biosparm */,
.can_queue = qcnt /* can_queue */,
.this_id = 7 /* SCSI ID */,
.sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/,
.sg_tablesize = ATP870U_SCATTER /*SG_ALL*/,
.max_sectors = ATP870U_MAX_SECTORS,
};

View File

@ -1487,8 +1487,7 @@ bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
return ret;
}
int
restart_bfa(struct bfad_s *bfad)
static int restart_bfa(struct bfad_s *bfad)
{
unsigned long flags;
struct pci_dev *pdev = bfad->pcidev;

View File

@ -275,8 +275,10 @@ bfad_im_get_stats(struct Scsi_Host *shost)
rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
fcstats, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
if (rc != BFA_STATUS_OK) {
kfree(fcstats);
return NULL;
}
wait_for_completion(&fcomp.comp);

View File

@ -813,7 +813,7 @@ struct fcoe_confqe {
/*
* FCoE conection data base
* FCoE connection data base
*/
struct fcoe_conn_db {
#if defined(__BIG_ENDIAN)

View File

@ -1242,7 +1242,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
/* Wait 2 * RA_TOV + 1 to be sure timeout function hasn't fired */
time_left = wait_for_completion_timeout(&io_req->abts_done,
(2 * rp->r_a_tov + 1) * HZ);
msecs_to_jiffies(2 * rp->r_a_tov + 1));
if (time_left)
BNX2FC_IO_DBG(io_req,
"Timed out in eh_abort waiting for abts_done");

View File

@ -915,12 +915,12 @@ void bnx2i_free_hba(struct bnx2i_hba *hba)
INIT_LIST_HEAD(&hba->ep_ofld_list);
INIT_LIST_HEAD(&hba->ep_active_list);
INIT_LIST_HEAD(&hba->ep_destroy_list);
pci_dev_put(hba->pcidev);
if (hba->regview) {
pci_iounmap(hba->pcidev, hba->regview);
hba->regview = NULL;
}
pci_dev_put(hba->pcidev);
bnx2i_free_mp_bdt(hba);
bnx2i_release_free_cid_que(hba);
iscsi_host_free(shost);

View File

@ -793,10 +793,10 @@ csio_hw_get_flash_params(struct csio_hw *hw)
goto found;
}
/* Decode Flash part size. The code below looks repetative with
/* Decode Flash part size. The code below looks repetitive with
* common encodings, but that's not guaranteed in the JEDEC
* specification for the Read JADEC ID command. The only thing that
* we're guaranteed by the JADEC specification is where the
* specification for the Read JEDEC ID command. The only thing that
* we're guaranteed by the JEDEC specification is where the
* Manufacturer ID is in the returned result. After that each
* Manufacturer ~could~ encode things completely differently.
* Note, all Flash parts must have 64KB sectors.
@ -983,8 +983,8 @@ retry:
waiting -= 50;
/*
* If neither Error nor Initialialized are indicated
* by the firmware keep waiting till we exaust our
* If neither Error nor Initialized are indicated
* by the firmware keep waiting till we exhaust our
* timeout ... and then retry if we haven't exhausted
* our retries ...
*/
@ -1738,7 +1738,7 @@ static void csio_link_l1cfg(struct link_config *lc, uint16_t fw_caps,
* Convert Common Code Forward Error Control settings into the
* Firmware's API. If the current Requested FEC has "Automatic"
* (IEEE 802.3) specified, then we use whatever the Firmware
* sent us as part of it's IEEE 802.3-based interpratation of
* sent us as part of it's IEEE 802.3-based interpretation of
* the Transceiver Module EPROM FEC parameters. Otherwise we
* use whatever is in the current Requested FEC settings.
*/
@ -2834,7 +2834,7 @@ csio_hws_configuring(struct csio_hw *hw, enum csio_hw_ev evt)
}
/*
* csio_hws_initializing - Initialiazing state
* csio_hws_initializing - Initializing state
* @hw - HW module
* @evt - Event
*
@ -3049,7 +3049,7 @@ csio_hws_removing(struct csio_hw *hw, enum csio_hw_ev evt)
if (!csio_is_hw_master(hw))
break;
/*
* The BYE should have alerady been issued, so we cant
* The BYE should have already been issued, so we can't
* use the mailbox interface. Hence we use the PL_RST
* register directly.
*/
@ -3104,7 +3104,7 @@ csio_hws_pcierr(struct csio_hw *hw, enum csio_hw_ev evt)
*
* A table driven interrupt handler that applies a set of masks to an
* interrupt status word and performs the corresponding actions if the
* interrupts described by the mask have occured. The actions include
* interrupts described by the mask have occurred. The actions include
* optionally emitting a warning or alert message. The table is terminated
* by an entry specifying mask 0. Returns the number of fatal interrupt
* conditions.
@ -4219,7 +4219,7 @@ csio_mgmtm_exit(struct csio_mgmtm *mgmtm)
* @hw: Pointer to HW module.
*
* It is assumed that the initialization is a synchronous operation.
* So when we return afer posting the event, the HW SM should be in
* So when we return after posting the event, the HW SM should be in
* the ready state, if there were no errors during init.
*/
int

View File

@ -154,13 +154,10 @@ csio_dfs_create(struct csio_hw *hw)
/*
* csio_dfs_destroy - Destroys per-hw debugfs.
*/
static int
static void
csio_dfs_destroy(struct csio_hw *hw)
{
if (hw->debugfs_root)
debugfs_remove_recursive(hw->debugfs_root);
return 0;
debugfs_remove_recursive(hw->debugfs_root);
}
/*

View File

@ -301,6 +301,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
struct fc_fdmi_port_name *port_name;
uint8_t buf[64];
uint8_t *fc4_type;
unsigned long flags;
if (fdmi_req->wr_status != FW_SUCCESS) {
csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n",
@ -385,13 +386,13 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
len = (uint32_t)(pld - (uint8_t *)cmd);
/* Submit FDMI RPA request */
spin_lock_irq(&hw->lock);
spin_lock_irqsave(&hw->lock, flags);
if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done,
FCOE_CT, &fdmi_req->dma_buf, len)) {
CSIO_INC_STATS(ln, n_fdmi_err);
csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n");
}
spin_unlock_irq(&hw->lock);
spin_unlock_irqrestore(&hw->lock, flags);
}
/*
@ -412,6 +413,7 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
struct fc_fdmi_rpl *reg_pl;
struct fs_fdmi_attrs *attrib_blk;
uint8_t buf[64];
unsigned long flags;
if (fdmi_req->wr_status != FW_SUCCESS) {
csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n",
@ -491,13 +493,13 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
attrib_blk->numattrs = htonl(numattrs);
/* Submit FDMI RHBA request */
spin_lock_irq(&hw->lock);
spin_lock_irqsave(&hw->lock, flags);
if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn,
FCOE_CT, &fdmi_req->dma_buf, len)) {
CSIO_INC_STATS(ln, n_fdmi_err);
csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n");
}
spin_unlock_irq(&hw->lock);
spin_unlock_irqrestore(&hw->lock, flags);
}
/*
@ -512,6 +514,7 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
void *cmd;
struct fc_fdmi_port_name *port_name;
uint32_t len;
unsigned long flags;
if (fdmi_req->wr_status != FW_SUCCESS) {
csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n",
@ -542,13 +545,13 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
len += sizeof(*port_name);
/* Submit FDMI request */
spin_lock_irq(&hw->lock);
spin_lock_irqsave(&hw->lock, flags);
if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn,
FCOE_CT, &fdmi_req->dma_buf, len)) {
CSIO_INC_STATS(ln, n_fdmi_err);
csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n");
}
spin_unlock_irq(&hw->lock);
spin_unlock_irqrestore(&hw->lock, flags);
}
/**
@ -1989,7 +1992,7 @@ static int
csio_ln_init(struct csio_lnode *ln)
{
int rv = -EINVAL;
struct csio_lnode *rln, *pln;
struct csio_lnode *pln;
struct csio_hw *hw = csio_lnode_to_hw(ln);
csio_init_state(&ln->sm, csio_lns_uninit);
@ -2019,7 +2022,6 @@ csio_ln_init(struct csio_lnode *ln)
* THe rest is common for non-root physical and NPIV lnodes.
* Just get references to all other modules
*/
rln = csio_root_lnode(ln);
if (csio_is_npiv_ln(ln)) {
/* NPIV */

View File

@ -1210,7 +1210,7 @@ csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp)
!csio_is_hw_intr_enabled(hw)) {
csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n",
*((uint8_t *)mbp->mb));
goto error_out;
goto error_out;
}
if (mbm->mcurrent != NULL) {

View File

@ -2073,7 +2073,6 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
struct net_device *ndev = cdev->ports[0];
struct cxgbi_tag_format tformat;
unsigned int ppmax;
int i, err;
if (!lldi->vr->iscsi.size) {
@ -2082,7 +2081,6 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
}
cdev->flags |= CXGBI_FLAG_USE_PPOD_OFLDQ;
ppmax = lldi->vr->iscsi.size >> PPOD_SIZE_SHIFT;
memset(&tformat, 0, sizeof(struct cxgbi_tag_format));
for (i = 0; i < 4; i++)

View File

@ -2284,34 +2284,6 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
}
EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
static inline int csk_print_port(struct cxgbi_sock *csk, char *buf)
{
int len;
cxgbi_sock_get(csk);
len = sprintf(buf, "%hu\n", ntohs(csk->daddr.sin_port));
cxgbi_sock_put(csk);
return len;
}
static inline int csk_print_ip(struct cxgbi_sock *csk, char *buf)
{
int len;
cxgbi_sock_get(csk);
if (csk->csk_family == AF_INET)
len = sprintf(buf, "%pI4",
&csk->daddr.sin_addr.s_addr);
else
len = sprintf(buf, "%pI6",
&csk->daddr6.sin6_addr);
cxgbi_sock_put(csk);
return len;
}
int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
char *buf)
{

View File

@ -44,14 +44,12 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
struct afu *afu = cmd->parent;
struct cxlflash_cfg *cfg = afu->parent;
struct device *dev = &cfg->dev->dev;
struct sisl_ioarcb *ioarcb;
struct sisl_ioasa *ioasa;
u32 resid;
if (unlikely(!cmd))
return;
ioarcb = &(cmd->rcb);
ioasa = &(cmd->sa);
if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) {

View File

@ -1197,6 +1197,7 @@ bool esas2r_nvram_read_direct(struct esas2r_adapter *a)
if (!esas2r_read_flash_block(a, a->nvram, FLS_OFFSET_NVR,
sizeof(struct esas2r_sas_nvram))) {
esas2r_hdebug("NVRAM read failed, using defaults");
up(&a->nvram_semaphore);
return false;
}

View File

@ -1024,7 +1024,8 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
atomic64_inc(&fnic_stats->io_stats.io_completions);
io_duration_time = jiffies_to_msecs(jiffies) - jiffies_to_msecs(io_req->start_time);
io_duration_time = jiffies_to_msecs(jiffies) -
jiffies_to_msecs(start_time);
if(io_duration_time <= 10)
atomic64_inc(&fnic_stats->io_stats.io_btw_0_to_10_msec);

View File

@ -259,7 +259,7 @@ int vnic_dev_cmd1(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait)
struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
int delay;
u32 status;
int dev_cmd_err[] = {
static const int dev_cmd_err[] = {
/* convert from fw's version of error.h to host's version */
0, /* ERR_SUCCESS */
EINVAL, /* ERR_EINVAL */

View File

@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/timer.h>
#include <scsi/sas_ata.h>
#include <scsi/libsas.h>
@ -84,6 +85,7 @@
#define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK | HISI_SAS_DIX_PROT_MASK)
#define HISI_SAS_WAIT_PHYUP_TIMEOUT 20
#define CLEAR_ITCT_TIMEOUT 20
struct hisi_hba;
@ -167,6 +169,7 @@ struct hisi_sas_phy {
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
int enable;
atomic_t down_cnt;
};
struct hisi_sas_port {
@ -296,8 +299,8 @@ struct hisi_sas_hw {
void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *linkrates);
enum sas_linkrate (*phy_get_max_linkrate)(void);
void (*clear_itct)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*clear_itct)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
void (*free_device)(struct hisi_sas_device *sas_dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
void (*dereg_device)(struct hisi_hba *hisi_hba,
@ -321,6 +324,44 @@ struct hisi_sas_hw {
const struct hisi_sas_debugfs_reg *debugfs_reg_port;
};
#define HISI_SAS_MAX_DEBUGFS_DUMP (50)
struct hisi_sas_debugfs_cq {
struct hisi_sas_cq *cq;
void *complete_hdr;
};
struct hisi_sas_debugfs_dq {
struct hisi_sas_dq *dq;
struct hisi_sas_cmd_hdr *hdr;
};
struct hisi_sas_debugfs_regs {
struct hisi_hba *hisi_hba;
u32 *data;
};
struct hisi_sas_debugfs_port {
struct hisi_sas_phy *phy;
u32 *data;
};
struct hisi_sas_debugfs_iost {
struct hisi_sas_iost *iost;
};
struct hisi_sas_debugfs_itct {
struct hisi_sas_itct *itct;
};
struct hisi_sas_debugfs_iost_cache {
struct hisi_sas_iost_itct_cache *cache;
};
struct hisi_sas_debugfs_itct_cache {
struct hisi_sas_iost_itct_cache *cache;
};
struct hisi_hba {
/* This must be the first element, used by SHOST_TO_SAS_HA */
struct sas_ha_struct *p;
@ -402,19 +443,20 @@ struct hisi_hba {
/* debugfs memories */
/* Put Global AXI and RAS Register into register array */
u32 *debugfs_regs[DEBUGFS_REGS_NUM];
u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS];
void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES];
struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES];
struct hisi_sas_iost *debugfs_iost;
struct hisi_sas_itct *debugfs_itct;
u64 *debugfs_iost_cache;
u64 *debugfs_itct_cache;
struct hisi_sas_debugfs_regs debugfs_regs[HISI_SAS_MAX_DEBUGFS_DUMP][DEBUGFS_REGS_NUM];
struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_PHYS];
struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
struct hisi_sas_debugfs_iost debugfs_iost[HISI_SAS_MAX_DEBUGFS_DUMP];
struct hisi_sas_debugfs_itct debugfs_itct[HISI_SAS_MAX_DEBUGFS_DUMP];
struct hisi_sas_debugfs_iost_cache debugfs_iost_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
struct hisi_sas_debugfs_itct_cache debugfs_itct_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
u64 debugfs_timestamp[HISI_SAS_MAX_DEBUGFS_DUMP];
int debugfs_dump_index;
struct dentry *debugfs_dir;
struct dentry *debugfs_dump_dentry;
struct dentry *debugfs_bist_dentry;
bool debugfs_snapshot;
};
/* Generic HW DMA host memory structures */
@ -556,6 +598,7 @@ struct hisi_sas_slot_dif_buf_table {
extern struct scsi_transport_template *hisi_sas_stt;
extern bool hisi_sas_debugfs_enable;
extern u32 hisi_sas_debugfs_dump_count;
extern struct dentry *hisi_sas_debugfs_dir;
extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);

View File

@ -587,7 +587,13 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
dev = hisi_hba->dev;
if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
if (in_softirq())
/*
* For IOs from upper layer, it may already disable preempt
* in the IO path, if disable preempt again in down(),
* function schedule() will report schedule_bug(), so check
* preemptible() before goto down().
*/
if (!preemptible())
return -EINVAL;
down(&hisi_hba->sem);
@ -968,12 +974,13 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
struct hisi_sas_phy *phy = sas_phy->lldd_phy;
struct asd_sas_port *sas_port = sas_phy->port;
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
struct hisi_sas_port *port;
unsigned long flags;
if (!sas_port)
return;
port = to_hisi_sas_port(sas_port);
spin_lock_irqsave(&hisi_hba->lock, flags);
port->port_attached = 1;
port->id = phy->port_id;
@ -1045,6 +1052,7 @@ static void hisi_sas_dev_gone(struct domain_device *device)
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
int ret = 0;
dev_info(dev, "dev[%d:%x] is gone\n",
sas_dev->device_id, sas_dev->dev_type);
@ -1056,13 +1064,16 @@ static void hisi_sas_dev_gone(struct domain_device *device)
hisi_sas_dereg_device(hisi_hba, device);
hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
ret = hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
device->lldd_dev = NULL;
}
if (hisi_hba->hw->free_device)
hisi_hba->hw->free_device(sas_dev);
sas_dev->dev_type = SAS_PHY_UNUSED;
/* Don't mark it as SAS_PHY_UNUSED if failed to clear ITCT */
if (!ret)
sas_dev->dev_type = SAS_PHY_UNUSED;
sas_dev->sas_device = NULL;
up(&hisi_hba->sem);
}
@ -1402,7 +1413,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct asd_sas_port *sas_port = sas_phy->port;
bool do_port_check = !!(_sas_port != sas_port);
bool do_port_check = _sas_port != sas_port;
if (!sas_phy->phy->enabled)
continue;
@ -1563,7 +1574,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
struct Scsi_Host *shost = hisi_hba->shost;
int rc;
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
if (!hisi_hba->hw->soft_reset)
@ -2055,7 +2066,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
/* Internal abort timed out */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
@ -2676,6 +2687,7 @@ int hisi_sas_probe(struct platform_device *pdev,
err_out_register_ha:
scsi_remove_host(shost);
err_out_ha:
hisi_sas_debugfs_exit(hisi_hba);
hisi_sas_free(hisi_hba);
scsi_host_put(shost);
return rc;
@ -2687,10 +2699,11 @@ struct dentry *hisi_sas_debugfs_dir;
static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
{
int queue_entry_size = hisi_hba->hw->complete_hdr_size;
int dump_index = hisi_hba->debugfs_dump_index;
int i;
for (i = 0; i < hisi_hba->queue_count; i++)
memcpy(hisi_hba->debugfs_complete_hdr[i],
memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr,
hisi_hba->complete_hdr[i],
HISI_SAS_QUEUE_SLOTS * queue_entry_size);
}
@ -2698,13 +2711,14 @@ static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
{
int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr);
int dump_index = hisi_hba->debugfs_dump_index;
int i;
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
int j;
debugfs_cmd_hdr = hisi_hba->debugfs_cmd_hdr[i];
debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr;
cmd_hdr = hisi_hba->cmd_hdr[i];
for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
@ -2715,6 +2729,7 @@ static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
{
int dump_index = hisi_hba->debugfs_dump_index;
const struct hisi_sas_debugfs_reg *port =
hisi_hba->hw->debugfs_reg_port;
int i, phy_cnt;
@ -2722,7 +2737,7 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
u32 *databuf;
for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) {
databuf = (u32 *)hisi_hba->debugfs_port_reg[phy_cnt];
databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data;
for (i = 0; i < port->count; i++, databuf++) {
offset = port->base_off + 4 * i;
*databuf = port->read_port_reg(hisi_hba, phy_cnt,
@ -2733,7 +2748,8 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
{
u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL];
int dump_index = hisi_hba->debugfs_dump_index;
u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *global =
hw->debugfs_reg_array[DEBUGFS_GLOBAL];
@ -2745,7 +2761,8 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
{
u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI];
int dump_index = hisi_hba->debugfs_dump_index;
u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *axi =
hw->debugfs_reg_array[DEBUGFS_AXI];
@ -2758,7 +2775,8 @@ static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
{
u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS];
int dump_index = hisi_hba->debugfs_dump_index;
u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *ras =
hw->debugfs_reg_array[DEBUGFS_RAS];
@ -2771,8 +2789,9 @@ static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
{
void *cachebuf = hisi_hba->debugfs_itct_cache;
void *databuf = hisi_hba->debugfs_itct;
int dump_index = hisi_hba->debugfs_dump_index;
void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache;
void *databuf = hisi_hba->debugfs_itct[dump_index].itct;
struct hisi_sas_itct *itct;
int i;
@ -2789,9 +2808,10 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
{
int dump_index = hisi_hba->debugfs_dump_index;
int max_command_entries = HISI_SAS_MAX_COMMANDS;
void *cachebuf = hisi_hba->debugfs_iost_cache;
void *databuf = hisi_hba->debugfs_iost;
void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache;
void *databuf = hisi_hba->debugfs_iost[dump_index].iost;
struct hisi_sas_iost *iost;
int i;
@ -2842,11 +2862,12 @@ static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr,
static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_debugfs_regs *global = s->private;
struct hisi_hba *hisi_hba = global->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL];
hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL],
hisi_sas_debugfs_print_reg(global->data,
reg_global, s);
return 0;
@ -2868,11 +2889,12 @@ static const struct file_operations hisi_sas_debugfs_global_fops = {
static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_debugfs_regs *axi = s->private;
struct hisi_hba *hisi_hba = axi->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI];
hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI],
hisi_sas_debugfs_print_reg(axi->data,
reg_axi, s);
return 0;
@ -2894,11 +2916,12 @@ static const struct file_operations hisi_sas_debugfs_axi_fops = {
static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_debugfs_regs *ras = s->private;
struct hisi_hba *hisi_hba = ras->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS];
hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS],
hisi_sas_debugfs_print_reg(ras->data,
reg_ras, s);
return 0;
@ -2920,13 +2943,13 @@ static const struct file_operations hisi_sas_debugfs_ras_fops = {
static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p)
{
struct hisi_sas_phy *phy = s->private;
struct hisi_sas_debugfs_port *port = s->private;
struct hisi_sas_phy *phy = port->phy;
struct hisi_hba *hisi_hba = phy->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port;
u32 *databuf = hisi_hba->debugfs_port_reg[phy->sas_phy.id];
hisi_sas_debugfs_print_reg(databuf, reg_port, s);
hisi_sas_debugfs_print_reg(port->data, reg_port, s);
return 0;
}
@ -2975,13 +2998,13 @@ static void hisi_sas_show_row_32(struct seq_file *s, int index,
seq_puts(s, "\n");
}
static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr)
static void hisi_sas_cq_show_slot(struct seq_file *s, int slot,
struct hisi_sas_debugfs_cq *debugfs_cq)
{
struct hisi_sas_cq *cq = cq_ptr;
struct hisi_sas_cq *cq = debugfs_cq->cq;
struct hisi_hba *hisi_hba = cq->hisi_hba;
void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id];
__le32 *complete_hdr = complete_queue +
(hisi_hba->hw->complete_hdr_size * slot);
__le32 *complete_hdr = debugfs_cq->complete_hdr +
(hisi_hba->hw->complete_hdr_size * slot);
hisi_sas_show_row_32(s, slot,
hisi_hba->hw->complete_hdr_size,
@ -2990,11 +3013,11 @@ static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr)
static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p)
{
struct hisi_sas_cq *cq = s->private;
struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
int slot;
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
hisi_sas_cq_show_slot(s, slot, cq);
hisi_sas_cq_show_slot(s, slot, debugfs_cq);
}
return 0;
}
@ -3014,9 +3037,8 @@ static const struct file_operations hisi_sas_debugfs_cq_fops = {
static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr)
{
struct hisi_sas_dq *dq = dq_ptr;
struct hisi_hba *hisi_hba = dq->hisi_hba;
void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id];
struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr;
void *cmd_queue = debugfs_dq->hdr;
__le32 *cmd_hdr = cmd_queue +
sizeof(struct hisi_sas_cmd_hdr) * slot;
@ -3048,14 +3070,14 @@ static const struct file_operations hisi_sas_debugfs_dq_fops = {
static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost;
struct hisi_sas_debugfs_iost *debugfs_iost = s->private;
struct hisi_sas_iost *iost = debugfs_iost->iost;
int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
for (i = 0; i < max_command_entries; i++, debugfs_iost++) {
__le64 *iost = &debugfs_iost->qw0;
for (i = 0; i < max_command_entries; i++, iost++) {
__le64 *data = &iost->qw0;
hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost);
hisi_sas_show_row_64(s, i, sizeof(*iost), data);
}
return 0;
@ -3076,9 +3098,8 @@ static const struct file_operations hisi_sas_debugfs_iost_fops = {
static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_iost_itct_cache *iost_cache =
(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache;
struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private;
struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache;
u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
int i, tab_idx;
__le64 *iost;
@ -3117,13 +3138,13 @@ static const struct file_operations hisi_sas_debugfs_iost_cache_fops = {
static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
{
int i;
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct;
struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
struct hisi_sas_itct *itct = debugfs_itct->itct;
for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) {
__le64 *itct = &debugfs_itct->qw0;
for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
__le64 *data = &itct->qw0;
hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct);
hisi_sas_show_row_64(s, i, sizeof(*itct), data);
}
return 0;
@ -3144,9 +3165,8 @@ static const struct file_operations hisi_sas_debugfs_itct_fops = {
static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
{
struct hisi_hba *hisi_hba = s->private;
struct hisi_sas_iost_itct_cache *itct_cache =
(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache;
struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private;
struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache;
u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
int i, tab_idx;
__le64 *itct;
@ -3184,6 +3204,8 @@ static const struct file_operations hisi_sas_debugfs_itct_cache_fops = {
static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
{
u64 *debugfs_timestamp;
int dump_index = hisi_hba->debugfs_dump_index;
struct dentry *dump_dentry;
struct dentry *dentry;
char name[256];
@ -3191,19 +3213,26 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
int c;
int d;
/* Create dump dir inside device dir */
dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir);
hisi_hba->debugfs_dump_dentry = dump_dentry;
snprintf(name, 256, "%d", dump_index);
debugfs_create_file("global", 0400, dump_dentry, hisi_hba,
&hisi_sas_debugfs_global_fops);
dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
debugfs_create_u64("timestamp", 0400, dump_dentry,
debugfs_timestamp);
debugfs_create_file("global", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
&hisi_sas_debugfs_global_fops);
/* Create port dir and files */
dentry = debugfs_create_dir("port", dump_dentry);
for (p = 0; p < hisi_hba->n_phy; p++) {
snprintf(name, 256, "%d", p);
debugfs_create_file(name, 0400, dentry, &hisi_hba->phy[p],
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_port_reg[dump_index][p],
&hisi_sas_debugfs_port_fops);
}
@ -3212,7 +3241,8 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
for (c = 0; c < hisi_hba->queue_count; c++) {
snprintf(name, 256, "%d", c);
debugfs_create_file(name, 0400, dentry, &hisi_hba->cq[c],
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_cq[dump_index][c],
&hisi_sas_debugfs_cq_fops);
}
@ -3221,26 +3251,33 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
for (d = 0; d < hisi_hba->queue_count; d++) {
snprintf(name, 256, "%d", d);
debugfs_create_file(name, 0400, dentry, &hisi_hba->dq[d],
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_dq[dump_index][d],
&hisi_sas_debugfs_dq_fops);
}
debugfs_create_file("iost", 0400, dump_dentry, hisi_hba,
debugfs_create_file("iost", 0400, dump_dentry,
&hisi_hba->debugfs_iost[dump_index],
&hisi_sas_debugfs_iost_fops);
debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba,
debugfs_create_file("iost_cache", 0400, dump_dentry,
&hisi_hba->debugfs_iost_cache[dump_index],
&hisi_sas_debugfs_iost_cache_fops);
debugfs_create_file("itct", 0400, dump_dentry, hisi_hba,
debugfs_create_file("itct", 0400, dump_dentry,
&hisi_hba->debugfs_itct[dump_index],
&hisi_sas_debugfs_itct_fops);
debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba,
debugfs_create_file("itct_cache", 0400, dump_dentry,
&hisi_hba->debugfs_itct_cache[dump_index],
&hisi_sas_debugfs_itct_cache_fops);
debugfs_create_file("axi", 0400, dump_dentry, hisi_hba,
debugfs_create_file("axi", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
&hisi_sas_debugfs_axi_fops);
debugfs_create_file("ras", 0400, dump_dentry, hisi_hba,
debugfs_create_file("ras", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
&hisi_sas_debugfs_ras_fops);
return;
@ -3271,8 +3308,7 @@ static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file,
struct hisi_hba *hisi_hba = file->f_inode->i_private;
char buf[8];
/* A bit racy, but don't care too much since it's only debugfs */
if (hisi_hba->debugfs_snapshot)
if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
return -EFAULT;
if (count > 8)
@ -3539,7 +3575,7 @@ static const struct {
int value;
char *name;
} hisi_sas_debugfs_loop_modes[] = {
{ HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digial" },
{ HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" },
{ HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" },
{ HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" },
};
@ -3670,132 +3706,201 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = {
.owner = THIS_MODULE,
};
static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
const char __user *buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = filp->private_data;
struct hisi_sas_phy *phy = s->private;
unsigned int set_val;
int res;
res = kstrtouint_from_user(buf, count, 0, &set_val);
if (res)
return res;
if (set_val > 0)
return -EINVAL;
atomic_set(&phy->down_cnt, 0);
return count;
}
static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p)
{
struct hisi_sas_phy *phy = s->private;
seq_printf(s, "%d\n", atomic_read(&phy->down_cnt));
return 0;
}
static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode,
struct file *filp)
{
return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show,
inode->i_private);
}
static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = {
.open = hisi_sas_debugfs_phy_down_cnt_open,
.read = seq_read,
.write = hisi_sas_debugfs_phy_down_cnt_write,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
};
void hisi_sas_debugfs_work_handler(struct work_struct *work)
{
struct hisi_hba *hisi_hba =
container_of(work, struct hisi_hba, debugfs_work);
int debugfs_dump_index = hisi_hba->debugfs_dump_index;
struct device *dev = hisi_hba->dev;
u64 timestamp = local_clock();
if (hisi_hba->debugfs_snapshot)
if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
dev_warn(dev, "dump count exceeded!\n");
return;
hisi_hba->debugfs_snapshot = true;
}
do_div(timestamp, NSEC_PER_MSEC);
hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
hisi_sas_debugfs_snapshot_regs(hisi_hba);
hisi_hba->debugfs_dump_index++;
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler);
static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba)
static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index)
{
struct device *dev = hisi_hba->dev;
int i;
devm_kfree(dev, hisi_hba->debugfs_iost_cache);
devm_kfree(dev, hisi_hba->debugfs_itct_cache);
devm_kfree(dev, hisi_hba->debugfs_iost);
devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
for (i = 0; i < hisi_hba->queue_count; i++)
devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]);
devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
for (i = 0; i < hisi_hba->queue_count; i++)
devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]);
devm_kfree(dev,
hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
for (i = 0; i < DEBUGFS_REGS_NUM; i++)
devm_kfree(dev, hisi_hba->debugfs_regs[i]);
devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
for (i = 0; i < hisi_hba->n_phy; i++)
devm_kfree(dev, hisi_hba->debugfs_port_reg[i]);
devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
}
static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba)
static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index)
{
const struct hisi_sas_hw *hw = hisi_hba->hw;
struct device *dev = hisi_hba->dev;
int p, c, d;
int p, c, d, r, i;
size_t sz;
hisi_hba->debugfs_dump_dentry =
debugfs_create_dir("dump", hisi_hba->debugfs_dir);
for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
struct hisi_sas_debugfs_regs *regs =
&hisi_hba->debugfs_regs[dump_index][r];
sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4;
hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL])
goto fail;
sz = hw->debugfs_reg_array[r]->count * 4;
regs->data = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!regs->data)
goto fail;
regs->hisi_hba = hisi_hba;
}
sz = hw->debugfs_reg_port->count * 4;
for (p = 0; p < hisi_hba->n_phy; p++) {
hisi_hba->debugfs_port_reg[p] =
devm_kmalloc(dev, sz, GFP_KERNEL);
struct hisi_sas_debugfs_port *port =
&hisi_hba->debugfs_port_reg[dump_index][p];
if (!hisi_hba->debugfs_port_reg[p])
port->data = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!port->data)
goto fail;
port->phy = &hisi_hba->phy[p];
}
sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4;
hisi_hba->debugfs_regs[DEBUGFS_AXI] =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_regs[DEBUGFS_AXI])
goto fail;
sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4;
hisi_hba->debugfs_regs[DEBUGFS_RAS] =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_regs[DEBUGFS_RAS])
goto fail;
sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
for (c = 0; c < hisi_hba->queue_count; c++) {
hisi_hba->debugfs_complete_hdr[c] =
devm_kmalloc(dev, sz, GFP_KERNEL);
struct hisi_sas_debugfs_cq *cq =
&hisi_hba->debugfs_cq[dump_index][c];
if (!hisi_hba->debugfs_complete_hdr[c])
cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!cq->complete_hdr)
goto fail;
cq->cq = &hisi_hba->cq[c];
}
sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
for (d = 0; d < hisi_hba->queue_count; d++) {
hisi_hba->debugfs_cmd_hdr[d] =
devm_kmalloc(dev, sz, GFP_KERNEL);
struct hisi_sas_debugfs_dq *dq =
&hisi_hba->debugfs_dq[dump_index][d];
if (!hisi_hba->debugfs_cmd_hdr[d])
dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!dq->hdr)
goto fail;
dq->dq = &hisi_hba->dq[d];
}
sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost);
hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_iost)
hisi_hba->debugfs_iost[dump_index].iost =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_iost[dump_index].iost)
goto fail;
sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
sizeof(struct hisi_sas_iost_itct_cache);
hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_iost_cache)
hisi_hba->debugfs_iost_cache[dump_index].cache =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_iost_cache[dump_index].cache)
goto fail;
sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
sizeof(struct hisi_sas_iost_itct_cache);
hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_itct_cache)
hisi_hba->debugfs_itct_cache[dump_index].cache =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_itct_cache[dump_index].cache)
goto fail;
/* New memory allocation must be locate before itct */
sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_itct)
hisi_hba->debugfs_itct[dump_index].itct =
devm_kmalloc(dev, sz, GFP_KERNEL);
if (!hisi_hba->debugfs_itct[dump_index].itct)
goto fail;
return 0;
fail:
hisi_sas_debugfs_release(hisi_hba);
for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
hisi_sas_debugfs_release(hisi_hba, i);
return -ENOMEM;
}
static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
{
struct dentry *dir = debugfs_create_dir("phy_down_cnt",
hisi_hba->debugfs_dir);
char name[16];
int phy_no;
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
snprintf(name, 16, "%d", phy_no);
debugfs_create_file(name, 0600, dir,
&hisi_hba->phy[phy_no],
&hisi_sas_debugfs_phy_down_cnt_ops);
}
}
static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
{
hisi_hba->debugfs_bist_dentry =
@ -3827,6 +3932,7 @@ static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
int i;
hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
hisi_sas_debugfs_dir);
@ -3838,9 +3944,17 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
/* create bist structures */
hisi_sas_debugfs_bist_init(hisi_hba);
if (hisi_sas_debugfs_alloc(hisi_hba)) {
debugfs_remove_recursive(hisi_hba->debugfs_dir);
dev_dbg(dev, "failed to init debugfs!\n");
hisi_hba->debugfs_dump_dentry =
debugfs_create_dir("dump", hisi_hba->debugfs_dir);
hisi_sas_debugfs_phy_down_cnt_init(hisi_hba);
for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
if (hisi_sas_debugfs_alloc(hisi_hba, i)) {
debugfs_remove_recursive(hisi_hba->debugfs_dir);
dev_dbg(dev, "failed to init debugfs!\n");
break;
}
}
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);
@ -3874,14 +3988,24 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable);
module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
u32 hisi_sas_debugfs_dump_count = 1;
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count);
module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444);
MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
static __init int hisi_sas_init(void)
{
hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
if (!hisi_sas_stt)
return -ENOMEM;
if (hisi_sas_debugfs_enable)
if (hisi_sas_debugfs_enable) {
hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL);
if (hisi_sas_debugfs_dump_count > HISI_SAS_MAX_DEBUGFS_DUMP) {
pr_info("hisi_sas: Limiting debugfs dump count\n");
hisi_sas_debugfs_dump_count = HISI_SAS_MAX_DEBUGFS_DUMP;
}
}
return 0;
}

View File

@ -531,8 +531,8 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
(0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF));
}
static void clear_itct_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
static int clear_itct_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
{
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
@ -551,6 +551,8 @@ static void clear_itct_v1_hw(struct hisi_hba *hisi_hba,
qw0 = le64_to_cpu(itct->qw0);
qw0 &= ~ITCT_HDR_VALID_MSK;
itct->qw0 = cpu_to_le64(qw0);
return 0;
}
static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)

View File

@ -974,13 +974,14 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
(0x1ULL << ITCT_HDR_RTOLT_OFF));
}
static void clear_itct_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
static int clear_itct_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
{
DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
struct device *dev = hisi_hba->dev;
int i;
sas_dev->completion = &completion;
@ -990,13 +991,19 @@ static void clear_itct_v2_hw(struct hisi_hba *hisi_hba,
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
ENT_INT_SRC3_ITC_INT_MSK);
/* need to set register twice to clear ITCT for v2 hw */
for (i = 0; i < 2; i++) {
reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
wait_for_completion(sas_dev->completion);
if (!wait_for_completion_timeout(sas_dev->completion,
CLEAR_ITCT_TIMEOUT * HZ)) {
dev_warn(dev, "failed to clear ITCT\n");
return -ETIMEDOUT;
}
memset(itct, 0, sizeof(struct hisi_sas_itct));
}
return 0;
}
static void free_device_v2_hw(struct hisi_sas_device *sas_dev)

View File

@ -795,13 +795,14 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba,
(0x1ULL << ITCT_HDR_RTOLT_OFF));
}
static void clear_itct_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
static int clear_itct_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
{
DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
struct device *dev = hisi_hba->dev;
sas_dev->completion = &completion;
@ -814,8 +815,14 @@ static void clear_itct_v3_hw(struct hisi_hba *hisi_hba,
reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
wait_for_completion(sas_dev->completion);
if (!wait_for_completion_timeout(sas_dev->completion,
CLEAR_ITCT_TIMEOUT * HZ)) {
dev_warn(dev, "failed to clear ITCT\n");
return -ETIMEDOUT;
}
memset(itct, 0, sizeof(struct hisi_sas_itct));
return 0;
}
static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
@ -1542,6 +1549,8 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
u32 phy_state, sl_ctrl, txid_auto;
struct device *dev = hisi_hba->dev;
atomic_inc(&phy->down_cnt);
del_timer(&phy->timer);
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
@ -3022,11 +3031,6 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable)
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL, reg_val);
mdelay(100);
reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL, reg_val);
/* set the bist init value */
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CODE,
@ -3035,6 +3039,11 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable)
SAS_PHY_BIST_CODE1,
SAS_PHY_BIST_CODE1_INIT);
mdelay(100);
reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL, reg_val);
/* clear error bit */
mdelay(100);
hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT);
@ -3259,6 +3268,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_out_register_ha:
scsi_remove_host(shost);
err_out_ha:
hisi_sas_debugfs_exit(hisi_hba);
scsi_host_put(shost);
err_out_regions:
pci_release_regions(pdev);
@ -3292,8 +3302,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct Scsi_Host *shost = sha->core.shost;
hisi_sas_debugfs_exit(hisi_hba);
if (timer_pending(&hisi_hba->timer))
del_timer(&hisi_hba->timer);
@ -3305,6 +3313,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
hisi_sas_free(hisi_hba);
hisi_sas_debugfs_exit(hisi_hba);
scsi_host_put(shost);
}
@ -3422,6 +3431,7 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev)
if (rc) {
scsi_remove_host(shost);
pci_disable_device(pdev);
return rc;
}
hisi_hba->hw->phys_init(hisi_hba);
sas_resume_ha(sha);

View File

@ -38,6 +38,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_cmnd.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@ -554,13 +555,29 @@ struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(scsi_host_get);
static bool scsi_host_check_in_flight(struct request *rq, void *data,
bool reserved)
{
int *count = data;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state))
(*count)++;
return true;
}
/**
* scsi_host_busy - Return the host busy counter
* @shost: Pointer to Scsi_Host to inc.
**/
int scsi_host_busy(struct Scsi_Host *shost)
{
return atomic_read(&shost->host_busy);
int cnt = 0;
blk_mq_tagset_busy_iter(&shost->tag_set,
scsi_host_check_in_flight, &cnt);
return cnt;
}
EXPORT_SYMBOL(scsi_host_busy);

View File

@ -498,7 +498,7 @@ ips_setup(char *ips_str)
int i;
char *key;
char *value;
IPS_OPTION options[] = {
static const IPS_OPTION options[] = {
{"noi2o", &ips_force_i2o, 0},
{"nommap", &ips_force_memio, 0},
{"ioctlsize", &ips_ioctlsize, IPS_IOCTL_SIZE},

View File

@ -147,7 +147,7 @@ static struct isci_port *sci_port_configuration_agent_find_port(
/**
*
* @controller: This is the controller object that contains the port agent
* @port_agent: This is the port configruation agent for the controller.
* @port_agent: This is the port configuration agent for the controller.
*
* This routine will validate the port configuration is correct for the SCU
* hardware. The SCU hardware allows for port configurations as follows. LP0

View File

@ -1504,7 +1504,7 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport,
* This function builds the isci_remote_device when a libsas dev_found message
* is received.
* @isci_host: This parameter specifies the isci host object.
* @port: This parameter specifies the isci_port conected to this device.
* @port: This parameter specifies the isci_port connected to this device.
*
* pointer to new isci_remote_device.
*/

View File

@ -369,8 +369,16 @@ static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
{
struct iscsi_conn *conn = task->conn;
unsigned int noreclaim_flag;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
int rc = 0;
if (!tcp_sw_conn->sock) {
iscsi_conn_printk(KERN_ERR, conn,
"Transport not bound to socket!\n");
return -EINVAL;
}
noreclaim_flag = memalloc_noreclaim_save();
while (iscsi_sw_tcp_xmit_qlen(conn)) {

View File

@ -605,6 +605,12 @@ struct lpfc_epd_pool {
spinlock_t lock; /* lock for expedite pool */
};
enum ras_state {
INACTIVE,
REG_INPROGRESS,
ACTIVE
};
struct lpfc_ras_fwlog {
uint8_t *fwlog_buff;
uint32_t fw_buffcount; /* Buffer size posted to FW */
@ -621,7 +627,7 @@ struct lpfc_ras_fwlog {
bool ras_enabled; /* Ras Enabled for the function */
#define LPFC_RAS_DISABLE_LOGGING 0x00
#define LPFC_RAS_ENABLE_LOGGING 0x01
bool ras_active; /* RAS logging running state */
enum ras_state state; /* RAS logging running state */
};
struct lpfc_hba {
@ -725,6 +731,7 @@ struct lpfc_hba {
#define HBA_FCOE_MODE 0x4 /* HBA function in FCoE Mode */
#define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/
#define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
#define HBA_PERSISTENT_TOPO 0x20 /* Persistent topology support in hba */
#define ELS_XRI_ABORT_EVENT 0x40
#define ASYNC_EVENT 0x80
#define LINK_DISABLED 0x100 /* Link disabled by user */
@ -830,6 +837,7 @@ struct lpfc_hba {
uint32_t cfg_fcp_mq_threshold;
uint32_t cfg_hdw_queue;
uint32_t cfg_irq_chann;
uint32_t cfg_irq_numa;
uint32_t cfg_suppress_rsp;
uint32_t cfg_nvme_oas;
uint32_t cfg_nvme_embed_cmd;
@ -872,7 +880,6 @@ struct lpfc_hba {
uint32_t cfg_aer_support;
uint32_t cfg_sriov_nr_virtfn;
uint32_t cfg_request_firmware_upgrade;
uint32_t cfg_iocb_cnt;
uint32_t cfg_suppress_link_up;
uint32_t cfg_rrq_xri_bitmap_sz;
uint32_t cfg_delay_discovery;
@ -990,7 +997,6 @@ struct lpfc_hba {
struct dma_pool *lpfc_drb_pool; /* data receive buffer pool */
struct dma_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */
struct dma_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */
struct dma_pool *txrdy_payload_pool;
struct dma_pool *lpfc_cmd_rsp_buf_pool;
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
@ -1055,6 +1061,7 @@ struct lpfc_hba {
#ifdef LPFC_HDWQ_LOCK_STAT
struct dentry *debug_lockstat;
#endif
struct dentry *debug_ras_log;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
uint32_t nvmeio_trc_output_idx;
@ -1209,6 +1216,13 @@ struct lpfc_hba {
uint64_t ktime_seg10_min;
uint64_t ktime_seg10_max;
#endif
struct hlist_node cpuhp; /* used for cpuhp per hba callback */
struct timer_list cpuhp_poll_timer;
struct list_head poll_list; /* slowpath eq polling list */
#define LPFC_POLL_HB 1 /* slowpath heartbeat */
#define LPFC_POLL_FASTPATH 0 /* called from fastpath */
#define LPFC_POLL_SLOWPATH 1 /* called from slowpath */
};
static inline struct Scsi_Host *
@ -1298,6 +1312,26 @@ lpfc_phba_elsring(struct lpfc_hba *phba)
return &phba->sli.sli3_ring[LPFC_ELS_RING];
}
/**
* lpfc_next_online_numa_cpu - Finds next online CPU on NUMA node
* @numa_mask: Pointer to phba's numa_mask member.
* @start: starting cpu index
*
* Note: If no valid cpu found, then nr_cpu_ids is returned.
*
**/
static inline unsigned int
lpfc_next_online_numa_cpu(const struct cpumask *numa_mask, unsigned int start)
{
unsigned int cpu_it;
for_each_cpu_wrap(cpu_it, numa_mask, start) {
if (cpu_online(cpu_it))
break;
}
return cpu_it;
}
/**
* lpfc_sli4_mod_hba_eq_delay - update EQ delay
* @phba: Pointer to HBA context object.

View File

@ -176,7 +176,6 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
int i;
int len = 0;
char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
unsigned long iflags = 0;
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
@ -347,7 +346,6 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE)
goto buffer_done;
rcu_read_lock();
scnprintf(tmp, sizeof(tmp),
"XRI Dist lpfc%d Total %d IO %d ELS %d\n",
phba->brd_no,
@ -355,7 +353,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
phba->sli4_hba.io_xri_max,
lpfc_sli4_get_els_iocb_cnt(phba));
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto buffer_done;
/* Port state is only one of two values for now. */
if (localport->port_id)
@ -371,15 +369,17 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
wwn_to_u64(vport->fc_nodename.u.wwn),
localport->port_id, statep);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto buffer_done;
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
nrport = NULL;
spin_lock_irqsave(&vport->phba->hbalock, iflags);
spin_lock(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
if (rport)
nrport = rport->remoteport;
spin_unlock_irqrestore(&vport->phba->hbalock, iflags);
spin_unlock(&vport->phba->hbalock);
if (!nrport)
continue;
@ -398,39 +398,39 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
/* Tab in to show lport ownership. */
if (strlcat(buf, "NVME RPORT ", PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
if (phba->brd_no >= 10) {
if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
scnprintf(tmp, sizeof(tmp), "WWPN x%llx ",
nrport->port_name);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
scnprintf(tmp, sizeof(tmp), "WWNN x%llx ",
nrport->node_name);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
scnprintf(tmp, sizeof(tmp), "DID x%06x ",
nrport->port_id);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
/* An NVME rport can have multiple roles. */
if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) {
if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) {
if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) {
if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
FC_PORT_ROLE_NVME_TARGET |
@ -438,14 +438,14 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x",
nrport->port_role);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
scnprintf(tmp, sizeof(tmp), "%s\n", statep);
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
goto rcu_unlock_buf_done;
goto unlock_buf_done;
}
rcu_read_unlock();
spin_unlock_irq(shost->host_lock);
if (!lport)
goto buffer_done;
@ -505,11 +505,11 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
atomic_read(&lport->cmpl_fcp_err));
strlcat(buf, tmp, PAGE_SIZE);
/* RCU is already unlocked. */
/* host_lock is already unlocked. */
goto buffer_done;
rcu_unlock_buf_done:
rcu_read_unlock();
unlock_buf_done:
spin_unlock_irq(shost->host_lock);
buffer_done:
len = strnlen(buf, PAGE_SIZE);
@ -1475,8 +1475,9 @@ lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
int i;
msleep(100);
lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0);
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0))
return -EIO;
/* verify if privileged for the request operation */
if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
@ -1486,8 +1487,9 @@ lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
/* wait for the SLI port firmware ready after firmware reset */
for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10);
lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0);
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0))
continue;
if (!bf_get(lpfc_sliport_status_err, &portstat_reg))
continue;
if (!bf_get(lpfc_sliport_status_rn, &portstat_reg))
@ -1642,7 +1644,7 @@ lpfc_set_trunking(struct lpfc_hba *phba, char *buff_out)
{
LPFC_MBOXQ_t *mbox = NULL;
unsigned long val = 0;
char *pval = 0;
char *pval = NULL;
int rc = 0;
if (!strncmp("enable", buff_out,
@ -3533,6 +3535,31 @@ LPFC_ATTR_R(enable_rrq, 2, 0, 2,
LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK,
LPFC_DELAY_INIT_LINK_INDEFINITELY,
"Suppress Link Up at initialization");
static ssize_t
lpfc_pls_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
return scnprintf(buf, PAGE_SIZE, "%d\n",
phba->sli4_hba.pc_sli4_params.pls);
}
static DEVICE_ATTR(pls, 0444,
lpfc_pls_show, NULL);
static ssize_t
lpfc_pt_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
return scnprintf(buf, PAGE_SIZE, "%d\n",
(phba->hba_flag & HBA_PERSISTENT_TOPO) ? 1 : 0);
}
static DEVICE_ATTR(pt, 0444,
lpfc_pt_show, NULL);
/*
# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS
# 1 - (1024)
@ -3580,9 +3607,6 @@ lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
lpfc_txcmplq_hw_show, NULL);
LPFC_ATTR_R(iocb_cnt, 2, 1, 5,
"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
# until the timer expires. Value range is [0,255]. Default value is 30.
@ -4096,7 +4120,16 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
val);
return -EINVAL;
}
if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
/*
* The 'topology' is not a configurable parameter if :
* - persistent topology enabled
* - G7 adapters
* - G6 with no private loop support
*/
if (((phba->hba_flag & HBA_PERSISTENT_TOPO) ||
(!phba->sli4_hba.pc_sli4_params.pls &&
phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC) ||
phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
val == 4) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
@ -5298,7 +5331,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
len += scnprintf(buf + len, PAGE_SIZE - len,
"CPU %02d not present\n",
phba->sli4_hba.curr_disp_cpu);
else if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) {
else if (cpup->eq == LPFC_VECTOR_MAP_EMPTY) {
if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
len += scnprintf(
buf + len, PAGE_SIZE - len,
@ -5311,10 +5344,10 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
else
len += scnprintf(
buf + len, PAGE_SIZE - len,
"CPU %02d EQ %04d hdwq %04d "
"CPU %02d EQ None hdwq %04d "
"physid %d coreid %d ht %d ua %d\n",
phba->sli4_hba.curr_disp_cpu,
cpup->eq, cpup->hdwq, cpup->phys_id,
cpup->hdwq, cpup->phys_id,
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN));
@ -5329,7 +5362,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
cpup->irq);
lpfc_get_irq(cpup->eq));
else
len += scnprintf(
buf + len, PAGE_SIZE - len,
@ -5340,7 +5373,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
cpup->irq);
lpfc_get_irq(cpup->eq));
}
phba->sli4_hba.curr_disp_cpu++;
@ -5711,7 +5744,7 @@ LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
* the driver will advertise it supports to the SCSI layer.
*
* 0 = Set nr_hw_queues by the number of CPUs or HW queues.
* 1,128 = Manually specify the maximum nr_hw_queue value to be set,
* 1,256 = Manually specify nr_hw_queue value to be advertised,
*
* Value range is [0,256]. Default value is 8.
*/
@ -5729,30 +5762,130 @@ LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
* A hardware IO queue maps (qidx) to a specific driver CQ/WQ.
*
* 0 = Configure the number of hdw queues to the number of active CPUs.
* 1,128 = Manually specify how many hdw queues to use.
* 1,256 = Manually specify how many hdw queues to use.
*
* Value range is [0,128]. Default value is 0.
* Value range is [0,256]. Default value is 0.
*/
LPFC_ATTR_R(hdw_queue,
LPFC_HBA_HDWQ_DEF,
LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
"Set the number of I/O Hardware Queues");
static inline void
lpfc_assign_default_irq_numa(struct lpfc_hba *phba)
{
#if IS_ENABLED(CONFIG_X86)
/* If AMD architecture, then default is LPFC_IRQ_CHANN_NUMA */
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
phba->cfg_irq_numa = 1;
else
phba->cfg_irq_numa = 0;
#else
phba->cfg_irq_numa = 0;
#endif
}
/*
* lpfc_irq_chann: Set the number of IRQ vectors that are available
* for Hardware Queues to utilize. This also will map to the number
* of EQ / MSI-X vectors the driver will create. This should never be
* more than the number of Hardware Queues
*
* 0 = Configure number of IRQ Channels to the number of active CPUs.
* 1,128 = Manually specify how many IRQ Channels to use.
* 0 = Configure number of IRQ Channels to:
* if AMD architecture, number of CPUs on HBA's NUMA node
* otherwise, number of active CPUs.
* [1,256] = Manually specify how many IRQ Channels to use.
*
* Value range is [0,128]. Default value is 0.
* Value range is [0,256]. Default value is [0].
*/
LPFC_ATTR_R(irq_chann,
LPFC_HBA_HDWQ_DEF,
LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
"Set the number of I/O IRQ Channels");
static uint lpfc_irq_chann = LPFC_IRQ_CHANN_DEF;
module_param(lpfc_irq_chann, uint, 0444);
MODULE_PARM_DESC(lpfc_irq_chann, "Set number of interrupt vectors to allocate");
/* lpfc_irq_chann_init - Set the hba irq_chann initial value
* @phba: lpfc_hba pointer.
* @val: contains the initial value
*
* Description:
* Validates the initial value is within range and assigns it to the
* adapter. If not in range, an error message is posted and the
* default value is assigned.
*
* Returns:
* zero if value is in range and is set
* -EINVAL if value was out of range
**/
static int
lpfc_irq_chann_init(struct lpfc_hba *phba, uint32_t val)
{
const struct cpumask *numa_mask;
if (phba->cfg_use_msi != 2) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"8532 use_msi = %u ignoring cfg_irq_numa\n",
phba->cfg_use_msi);
phba->cfg_irq_numa = 0;
phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
return 0;
}
/* Check if default setting was passed */
if (val == LPFC_IRQ_CHANN_DEF)
lpfc_assign_default_irq_numa(phba);
if (phba->cfg_irq_numa) {
numa_mask = &phba->sli4_hba.numa_mask;
if (cpumask_empty(numa_mask)) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"8533 Could not identify NUMA node, "
"ignoring cfg_irq_numa\n");
phba->cfg_irq_numa = 0;
phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
} else {
phba->cfg_irq_chann = cpumask_weight(numa_mask);
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"8543 lpfc_irq_chann set to %u "
"(numa)\n", phba->cfg_irq_chann);
}
} else {
if (val > LPFC_IRQ_CHANN_MAX) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"8545 lpfc_irq_chann attribute cannot "
"be set to %u, allowed range is "
"[%u,%u]\n",
val,
LPFC_IRQ_CHANN_MIN,
LPFC_IRQ_CHANN_MAX);
phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
return -EINVAL;
}
phba->cfg_irq_chann = val;
}
return 0;
}
/**
* lpfc_irq_chann_show - Display value of irq_chann
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains a string with the list sizes
*
* Returns: size of formatted string.
**/
static ssize_t
lpfc_irq_chann_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return scnprintf(buf, PAGE_SIZE, "%u\n", phba->cfg_irq_chann);
}
static DEVICE_ATTR_RO(lpfc_irq_chann);
/*
# lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware.
@ -5933,7 +6066,53 @@ LPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
* [1-4] = Multiple of 1/4th Mb of host memory for FW logging
* Value range [0..4]. Default value is 0
*/
LPFC_ATTR_RW(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
LPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
lpfc_param_show(ras_fwlog_buffsize);
static ssize_t
lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val)
{
int ret = 0;
enum ras_state state;
if (!lpfc_rangecheck(val, 0, 4))
return -EINVAL;
if (phba->cfg_ras_fwlog_buffsize == val)
return 0;
if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn))
return -EINVAL;
spin_lock_irq(&phba->hbalock);
state = phba->ras_fwlog.state;
spin_unlock_irq(&phba->hbalock);
if (state == REG_INPROGRESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
"registration is in progress\n");
return -EBUSY;
}
/* For disable logging: stop the logs and free the DMA.
* For ras_fwlog_buffsize size change we still need to free and
* reallocate the DMA in lpfc_sli4_ras_fwlog_init.
*/
phba->cfg_ras_fwlog_buffsize = val;
if (state == ACTIVE) {
lpfc_ras_stop_fwlog(phba);
lpfc_sli4_ras_dma_free(phba);
}
lpfc_sli4_ras_init(phba);
if (phba->ras_fwlog.ras_enabled)
ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
LPFC_RAS_ENABLE_LOGGING);
return ret;
}
lpfc_param_store(ras_fwlog_buffsize);
static DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize);
/*
* lpfc_ras_fwlog_level: Firmware logging verbosity level
@ -6071,8 +6250,9 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_sriov_nr_virtfn,
&dev_attr_lpfc_req_fw_upgrade,
&dev_attr_lpfc_suppress_link_up,
&dev_attr_lpfc_iocb_cnt,
&dev_attr_iocb_hw,
&dev_attr_pls,
&dev_attr_pt,
&dev_attr_txq_hw,
&dev_attr_txcmplq_hw,
&dev_attr_lpfc_fips_level,
@ -7085,11 +7265,22 @@ struct fc_function_template lpfc_vport_transport_functions = {
static void
lpfc_get_hba_function_mode(struct lpfc_hba *phba)
{
/* If it's a SkyHawk FCoE adapter */
if (phba->pcidev->device == PCI_DEVICE_ID_SKYHAWK)
/* If the adapter supports FCoE mode */
switch (phba->pcidev->device) {
case PCI_DEVICE_ID_SKYHAWK:
case PCI_DEVICE_ID_SKYHAWK_VF:
case PCI_DEVICE_ID_LANCER_FCOE:
case PCI_DEVICE_ID_LANCER_FCOE_VF:
case PCI_DEVICE_ID_ZEPHYR_DCSP:
case PCI_DEVICE_ID_HORNET:
case PCI_DEVICE_ID_TIGERSHARK:
case PCI_DEVICE_ID_TOMCAT:
phba->hba_flag |= HBA_FCOE_MODE;
else
break;
default:
/* for others, clear the flag */
phba->hba_flag &= ~HBA_FCOE_MODE;
}
}
/**
@ -7099,6 +7290,7 @@ lpfc_get_hba_function_mode(struct lpfc_hba *phba)
void
lpfc_get_cfgparam(struct lpfc_hba *phba)
{
lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
lpfc_ns_query_init(phba, lpfc_ns_query);
lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
@ -7205,12 +7397,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
phba->cfg_soft_wwpn = 0L;
lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_aer_support_init(phba, lpfc_aer_support);
lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
lpfc_delay_discovery_init(phba, lpfc_delay_discovery);
lpfc_sli_mode_init(phba, lpfc_sli_mode);
phba->cfg_enable_dss = 1;
@ -7256,11 +7446,11 @@ lpfc_nvme_mod_param_dep(struct lpfc_hba *phba)
}
if (!phba->cfg_nvmet_mrq)
phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
/* Adjust lpfc_nvmet_mrq to avoid running out of WQE slots */
if (phba->cfg_nvmet_mrq > phba->cfg_irq_chann) {
phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
if (phba->cfg_nvmet_mrq > phba->cfg_hdw_queue) {
phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
"6018 Adjust lpfc_nvmet_mrq to %d\n",
phba->cfg_nvmet_mrq);

View File

@ -5435,10 +5435,12 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
/* Current logging state */
if (ras_fwlog->ras_active == true)
spin_lock_irq(&phba->hbalock);
if (ras_fwlog->state == ACTIVE)
ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
else
ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
spin_unlock_irq(&phba->hbalock);
ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
@ -5495,10 +5497,13 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
if (action == LPFC_RASACTION_STOP_LOGGING) {
/* Check if already disabled */
if (ras_fwlog->ras_active == false) {
spin_lock_irq(&phba->hbalock);
if (ras_fwlog->state != ACTIVE) {
spin_unlock_irq(&phba->hbalock);
rc = -ESRCH;
goto ras_job_error;
}
spin_unlock_irq(&phba->hbalock);
/* Disable logging */
lpfc_ras_stop_fwlog(phba);
@ -5509,8 +5514,10 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
* FW-logging with new log-level. Return status
* "Logging already Running" to caller.
**/
if (ras_fwlog->ras_active)
spin_lock_irq(&phba->hbalock);
if (ras_fwlog->state != INACTIVE)
action_status = -EINPROGRESS;
spin_unlock_irq(&phba->hbalock);
/* Enable logging */
rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
@ -5626,10 +5633,13 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
goto ras_job_error;
/* Logging to be stopped before reading */
if (ras_fwlog->ras_active == true) {
spin_lock_irq(&phba->hbalock);
if (ras_fwlog->state == ACTIVE) {
spin_unlock_irq(&phba->hbalock);
rc = -EINPROGRESS;
goto ras_job_error;
}
spin_unlock_irq(&phba->hbalock);
if (job->request_len <
sizeof(struct fc_bsg_request) +

View File

@ -215,6 +215,12 @@ irqreturn_t lpfc_sli_fp_intr_handler(int, void *);
irqreturn_t lpfc_sli4_intr_handler(int, void *);
irqreturn_t lpfc_sli4_hba_intr_handler(int, void *);
void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba);
int lpfc_sli4_poll_eq(struct lpfc_queue *q, uint8_t path);
void lpfc_sli4_poll_hbtimer(struct timer_list *t);
void lpfc_sli4_start_polling(struct lpfc_queue *q);
void lpfc_sli4_stop_polling(struct lpfc_queue *q);
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli4_swap_str(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
@ -586,6 +592,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd,
void lpfc_nvme_cmd_template(void);
void lpfc_nvmet_cmd_template(void);
void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn);
void lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt);
extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;

View File

@ -763,9 +763,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0208 NameServer Rsp Data: x%x x%x "
"sz x%x\n",
"x%x x%x sz x%x\n",
vport->fc_flag,
CTreq->un.gid.Fc4Type,
vport->num_disc_nodes,
vport->gidft_inp,
irsp->un.genreq64.bdl.bdeSize);
lpfc_ns_rsp(vport,
@ -961,9 +963,13 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (CTrsp->CommandResponse.bits.CmdRsp ==
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"4105 NameServer Rsp Data: x%x x%x\n",
"4105 NameServer Rsp Data: x%x x%x "
"x%x x%x sz x%x\n",
vport->fc_flag,
CTreq->un.gid.Fc4Type);
CTreq->un.gid.Fc4Type,
vport->num_disc_nodes,
vport->gidft_inp,
irsp->un.genreq64.bdl.bdeSize);
lpfc_ns_rsp(vport,
outp,
@ -1025,6 +1031,11 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
vport->gidft_inp--;
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6450 GID_PT cmpl inp %d disc %d\n",
vport->gidft_inp, vport->num_disc_nodes);
/* Link up / RSCN discovery */
if ((vport->num_disc_nodes == 0) &&
(vport->gidft_inp == 0)) {
@ -1159,6 +1170,11 @@ out:
/* Link up / RSCN discovery */
if (vport->num_disc_nodes)
vport->num_disc_nodes--;
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6451 GFF_ID cmpl inp %d disc %d\n",
vport->gidft_inp, vport->num_disc_nodes);
if (vport->num_disc_nodes == 0) {
/*
* The driver has cycled through all Nports in the RSCN payload.
@ -1868,6 +1884,12 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) {
case IOERR_SLI_ABORTED:
case IOERR_SLI_DOWN:
/* Driver aborted this IO. No retry as error
* is likely Offline->Online or some adapter
* error. Recovery will try again.
*/
break;
case IOERR_ABORT_IN_PROGRESS:
case IOERR_SEQUENCE_TIMEOUT:
case IOERR_ILLEGAL_FRAME:

View File

@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/ctype.h>
#include <linux/vmalloc.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@ -2078,6 +2079,96 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
}
#endif
static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
char *buffer, int size)
{
int copied = 0;
struct lpfc_dmabuf *dmabuf, *next;
spin_lock_irq(&phba->hbalock);
if (phba->ras_fwlog.state != ACTIVE) {
spin_unlock_irq(&phba->hbalock);
return -EINVAL;
}
spin_unlock_irq(&phba->hbalock);
list_for_each_entry_safe(dmabuf, next,
&phba->ras_fwlog.fwlog_buff_list, list) {
memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
copied += LPFC_RAS_MAX_ENTRY_SIZE;
if (size > copied)
break;
}
return copied;
}
static int
lpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
{
struct lpfc_debug *debug = file->private_data;
vfree(debug->buffer);
kfree(debug);
return 0;
}
/**
* lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return a negative
* error value.
**/
static int
lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
{
struct lpfc_hba *phba = inode->i_private;
struct lpfc_debug *debug;
int size;
int rc = -ENOMEM;
spin_lock_irq(&phba->hbalock);
if (phba->ras_fwlog.state != ACTIVE) {
spin_unlock_irq(&phba->hbalock);
rc = -EINVAL;
goto out;
}
spin_unlock_irq(&phba->hbalock);
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
if (!debug)
goto out;
size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
debug->buffer = vmalloc(size);
if (!debug->buffer)
goto free_debug;
debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
if (debug->len < 0) {
rc = -EINVAL;
goto free_buffer;
}
file->private_data = debug;
return 0;
free_buffer:
vfree(debug->buffer);
free_debug:
kfree(debug);
out:
return rc;
}
/**
* lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
@ -5286,6 +5377,16 @@ static const struct file_operations lpfc_debugfs_op_lockstat = {
};
#endif
#undef lpfc_debugfs_ras_log
static const struct file_operations lpfc_debugfs_ras_log = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_ras_log_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_debugfs_read,
.release = lpfc_debugfs_ras_log_release,
};
#endif
#undef lpfc_debugfs_op_dumpHBASlim
static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
.owner = THIS_MODULE,
@ -5457,7 +5558,6 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
.release = lpfc_idiag_cmd_release,
};
#endif
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
* @phba: Pointer to HBA context object.
@ -5707,6 +5807,19 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
goto debug_failed;
}
/* RAS log */
snprintf(name, sizeof(name), "ras_log");
phba->debug_ras_log =
debugfs_create_file(name, 0644,
phba->hba_debugfs_root,
phba, &lpfc_debugfs_ras_log);
if (!phba->debug_ras_log) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"6148 Cannot create debugfs"
" ras_log\n");
goto debug_failed;
}
/* Setup hbqinfo */
snprintf(name, sizeof(name), "hbqinfo");
phba->debug_hbqinfo =
@ -6117,6 +6230,9 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
phba->debug_hbqinfo = NULL;
debugfs_remove(phba->debug_ras_log);
phba->debug_ras_log = NULL;
#ifdef LPFC_HDWQ_LOCK_STAT
debugfs_remove(phba->debug_lockstat); /* lockstat */
phba->debug_lockstat = NULL;

View File

@ -2236,6 +2236,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
IOCB_t *irsp;
struct lpfc_nodelist *ndlp;
char *mode;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
@ -2273,8 +2274,17 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
}
/* If we don't send GFT_ID to Fabric, a PRLI error
* could be expected.
*/
if ((vport->fc_flag & FC_FABRIC) ||
(vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH))
mode = KERN_ERR;
else
mode = KERN_INFO;
/* PRLI failed */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
lpfc_printf_vlog(vport, mode, LOG_ELS,
"2754 PRLI failure DID:%06X Status:x%x/x%x, "
"data: x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
@ -4291,6 +4301,11 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp = &rspiocb->iocb;
if (!vport) {
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
"3177 ELS response failed\n");
goto out;
}
if (cmdiocb->context_un.mbox)
mbox = cmdiocb->context_un.mbox;
@ -4430,7 +4445,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
mempool_free(mbox, phba->mbox_mem_pool);
}
out:
if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
if (ndlp && NLP_CHK_NODE_ACT(ndlp) && shost) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
spin_unlock_irq(shost->host_lock);
@ -5260,6 +5275,11 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
}
}
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6452 Discover PLOGI %d flag x%x\n",
sentplogi, vport->fc_flag);
if (sentplogi) {
lpfc_set_disctmo(vport);
}
@ -6455,7 +6475,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
uint32_t payload_len, length, nportid, *cmd;
int rscn_cnt;
int rscn_id = 0, hba_id = 0;
int i;
int i, tmo;
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
@ -6561,6 +6581,13 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DEFERRED;
/* Restart disctmo if its already running */
if (vport->fc_flag & FC_DISC_TMO) {
tmo = ((phba->fc_ratov * 3) + 3);
mod_timer(&vport->fc_disctmo,
jiffies + msecs_to_jiffies(1000 * tmo));
}
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
vport->fc_flag |= FC_RSCN_MODE;
@ -6663,9 +6690,10 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
/* RSCN processed */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0215 RSCN processed Data: x%x x%x x%x x%x\n",
"0215 RSCN processed Data: x%x x%x x%x x%x x%x x%x\n",
vport->fc_flag, 0, vport->fc_rscn_id_cnt,
vport->port_state);
vport->port_state, vport->num_disc_nodes,
vport->gidft_inp);
/* To process RSCN, first compare RSCN data with NameServer */
vport->fc_ns_retry = 0;
@ -7986,20 +8014,22 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd = NULL;
unsigned long iflags = 0;
lpfc_fabric_abort_vport(vport);
/*
* For SLI3, only the hbalock is required. But SLI4 needs to coordinate
* with the ring insert operation. Because lpfc_sli_issue_abort_iotag
* ultimately grabs the ring_lock, the driver must splice the list into
* a working list and release the locks before calling the abort.
*/
spin_lock_irq(&phba->hbalock);
spin_lock_irqsave(&phba->hbalock, iflags);
pring = lpfc_phba_elsring(phba);
/* Bail out if we've no ELS wq, like in PCI error recovery case. */
if (unlikely(!pring)) {
spin_unlock_irq(&phba->hbalock);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return;
}
@ -8014,6 +8044,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
if (piocb->vport != vport)
continue;
if (piocb->iocb_flag & LPFC_DRIVER_ABORTED)
continue;
/* On the ELS ring we can have ELS_REQUESTs or
* GEN_REQUESTs waiting for a response.
*/
@ -8037,21 +8070,21 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
if (phba->sli_rev == LPFC_SLI_REV4)
spin_unlock(&pring->ring_lock);
spin_unlock_irq(&phba->hbalock);
spin_unlock_irqrestore(&phba->hbalock, iflags);
/* Abort each txcmpl iocb on aborted list and remove the dlist links. */
list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
spin_lock_irq(&phba->hbalock);
spin_lock_irqsave(&phba->hbalock, iflags);
list_del_init(&piocb->dlist);
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
spin_unlock_irq(&phba->hbalock);
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
if (!list_empty(&abort_list))
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"3387 abort list for txq not empty\n");
INIT_LIST_HEAD(&abort_list);
spin_lock_irq(&phba->hbalock);
spin_lock_irqsave(&phba->hbalock, iflags);
if (phba->sli_rev == LPFC_SLI_REV4)
spin_lock(&pring->ring_lock);
@ -8091,7 +8124,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
if (phba->sli_rev == LPFC_SLI_REV4)
spin_unlock(&pring->ring_lock);
spin_unlock_irq(&phba->hbalock);
spin_unlock_irqrestore(&phba->hbalock, iflags);
/* Cancel all the IOCBs from the completions list */
lpfc_sli_cancel_iocbs(phba, &abort_list,

View File

@ -700,7 +700,10 @@ lpfc_work_done(struct lpfc_hba *phba)
if (!(phba->hba_flag & HBA_SP_QUEUE_EVT))
set_bit(LPFC_DATA_READY, &phba->data_flags);
} else {
if (phba->link_state >= LPFC_LINK_UP ||
/* Driver could have abort request completed in queue
* when link goes down. Allow for this transition.
*/
if (phba->link_state >= LPFC_LINK_DOWN ||
phba->link_flag & LS_MDS_LOOPBACK) {
pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
lpfc_sli_handle_slow_ring_event(phba, pring,
@ -1135,7 +1138,6 @@ void
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
uint8_t bbscn = 0;
if (pmb->u.mb.mbxStatus)
goto out;
@ -1162,17 +1164,11 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl
*/
if (vport->port_state != LPFC_FLOGI) {
if (phba->bbcredit_support && phba->cfg_enable_bbcr) {
bbscn = bf_get(lpfc_bbscn_def,
&phba->sli4_hba.bbscn_params);
vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf;
vport->fc_sparam.cmn.bbRcvSizeMsb |= (bbscn << 4);
}
if (vport->port_state != LPFC_FLOGI)
lpfc_initial_flogi(vport);
} else if (vport->fc_flag & FC_PT2PT) {
else if (vport->fc_flag & FC_PT2PT)
lpfc_disc_start(vport);
}
return;
out:
@ -3456,8 +3452,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
phba->pport->port_state, vport->fc_flag);
else if (attn_type == LPFC_ATT_UNEXP_WWPN)
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1313 Link Down UNEXP WWPN Event x%x received "
"Data: x%x x%x x%x x%x x%x\n",
"1313 Link Down Unexpected FA WWPN Event x%x "
"received Data: x%x x%x x%x x%x x%x\n",
la->eventTag, phba->fc_eventTag,
phba->pport->port_state, vport->fc_flag,
bf_get(lpfc_mbx_read_top_mm, la),
@ -4046,7 +4042,7 @@ out:
ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0003 rpi:%x DID:%x flg:%x %d map%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
@ -4575,8 +4571,10 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return ndlp;
free_rpi:
if (phba->sli_rev == LPFC_SLI_REV4)
if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_sli4_free_rpi(vport->phba, rpi);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
return NULL;
}
@ -4835,11 +4833,50 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi);
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
ndlp->nlp_flag &= ~NLP_UNREG_INP;
}
}
/*
* Sets the mailbox completion handler to be used for the
* unreg_rpi command. The handler varies based on the state of
* the port and what will be happening to the rpi next.
*/
static void
lpfc_set_unreg_login_mbx_cmpl(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp, LPFC_MBOXQ_t *mbox)
{
unsigned long iflags;
if (ndlp->nlp_flag & NLP_ISSUE_LOGO) {
mbox->ctx_ndlp = ndlp;
mbox->mbox_cmpl = lpfc_nlp_logo_unreg;
} else if (phba->sli_rev == LPFC_SLI_REV4 &&
(!(vport->load_flag & FC_UNLOADING)) &&
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
LPFC_SLI_INTF_IF_TYPE_2) &&
(kref_read(&ndlp->kref) > 0)) {
mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
mbox->mbox_cmpl = lpfc_sli4_unreg_rpi_cmpl_clr;
} else {
if (vport->load_flag & FC_UNLOADING) {
if (phba->sli_rev == LPFC_SLI_REV4) {
spin_lock_irqsave(&vport->phba->ndlp_lock,
iflags);
ndlp->nlp_flag |= NLP_RELEASE_RPI;
spin_unlock_irqrestore(&vport->phba->ndlp_lock,
iflags);
}
lpfc_nlp_get(ndlp);
}
mbox->ctx_ndlp = ndlp;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
}
}
/*
* Free rpi associated with LPFC_NODELIST entry.
* This routine is called from lpfc_freenode(), when we are removing
@ -4860,7 +4897,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (ndlp->nlp_flag & NLP_RPI_REGISTERED ||
ndlp->nlp_flag & NLP_REG_LOGIN_SEND) {
if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"3366 RPI x%x needs to be "
"unregistered nlp_flag x%x "
"did x%x\n",
@ -4871,7 +4909,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* no need to queue up another one.
*/
if (ndlp->nlp_flag & NLP_UNREG_INP) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"1436 unreg_rpi SKIP UNREG x%x on "
"NPort x%x deferred x%x flg x%x "
"Data: x%px\n",
@ -4890,39 +4929,19 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_unreg_login(phba, vport->vpi, rpi, mbox);
mbox->vport = vport;
if (ndlp->nlp_flag & NLP_ISSUE_LOGO) {
mbox->ctx_ndlp = ndlp;
mbox->mbox_cmpl = lpfc_nlp_logo_unreg;
} else {
if (phba->sli_rev == LPFC_SLI_REV4 &&
(!(vport->load_flag & FC_UNLOADING)) &&
(bf_get(lpfc_sli_intf_if_type,
&phba->sli4_hba.sli_intf) >=
LPFC_SLI_INTF_IF_TYPE_2) &&
(kref_read(&ndlp->kref) > 0)) {
mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
mbox->mbox_cmpl =
lpfc_sli4_unreg_rpi_cmpl_clr;
/*
* accept PLOGIs after unreg_rpi_cmpl
*/
acc_plogi = 0;
} else if (vport->load_flag & FC_UNLOADING) {
mbox->ctx_ndlp = NULL;
mbox->mbox_cmpl =
lpfc_sli_def_mbox_cmpl;
} else {
mbox->ctx_ndlp = ndlp;
mbox->mbox_cmpl =
lpfc_sli_def_mbox_cmpl;
}
}
lpfc_set_unreg_login_mbx_cmpl(phba, vport, ndlp, mbox);
if (mbox->mbox_cmpl == lpfc_sli4_unreg_rpi_cmpl_clr)
/*
* accept PLOGIs after unreg_rpi_cmpl
*/
acc_plogi = 0;
if (((ndlp->nlp_DID & Fabric_DID_MASK) !=
Fabric_DID_MASK) &&
(!(vport->fc_flag & FC_OFFLINE_MODE)))
ndlp->nlp_flag |= NLP_UNREG_INP;
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"1433 unreg_rpi UNREG x%x on "
"NPort x%x deferred flg x%x "
"Data:x%px\n",
@ -5057,6 +5076,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mb, *nextmb;
struct lpfc_dmabuf *mp;
unsigned long iflags;
/* Cleanup node for NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
@ -5138,8 +5158,20 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_cleanup_vports_rrqs(vport, ndlp);
if (phba->sli_rev == LPFC_SLI_REV4)
ndlp->nlp_flag |= NLP_RELEASE_RPI;
lpfc_unreg_rpi(vport, ndlp);
if (!lpfc_unreg_rpi(vport, ndlp)) {
/* Clean up unregistered and non freed rpis */
if ((ndlp->nlp_flag & NLP_RELEASE_RPI) &&
!(ndlp->nlp_rpi == LPFC_RPI_ALLOC_ERROR)) {
lpfc_sli4_free_rpi(vport->phba,
ndlp->nlp_rpi);
spin_lock_irqsave(&vport->phba->ndlp_lock,
iflags);
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
spin_unlock_irqrestore(&vport->phba->ndlp_lock,
iflags);
}
}
return 0;
}
@ -5165,8 +5197,10 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
/* For this case we need to cleanup the default rpi
* allocated by the firmware.
*/
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
"0005 rpi:%x DID:%x flg:%x %d map:%x x%px\n",
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"0005 Cleanup Default rpi:x%x DID:x%x flg:x%x "
"ref %d map:x%x ndlp x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
ndlp->nlp_usg_map, ndlp);
@ -5203,8 +5237,9 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
*/
lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
"0940 removed node x%px DID x%x "
" rport not null x%px\n",
ndlp, ndlp->nlp_DID, ndlp->rport);
"rpi %d rport not null x%px\n",
ndlp, ndlp->nlp_DID, ndlp->nlp_rpi,
ndlp->rport);
rport = ndlp->rport;
rdata = rport->dd_data;
rdata->pnode = NULL;
@ -5362,6 +5397,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
if (!ndlp)
return NULL;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6453 Setup New Node 2B_DISC x%x "
"Data:x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, vport->fc_flag);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
@ -5375,6 +5417,12 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
"0014 Could not enable ndlp\n");
return NULL;
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6454 Setup Enabled Node 2B_DISC x%x "
"Data:x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, vport->fc_flag);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
@ -5394,6 +5442,12 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
*/
lpfc_cancel_retry_delay_tmo(vport, ndlp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6455 Setup RSCN Node 2B_DISC x%x "
"Data:x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, vport->fc_flag);
/* NVME Target mode waits until rport is known to be
* impacted by the RSCN before it transitions. No
* active management - just go to NPR provided the
@ -5405,15 +5459,32 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
/* If we've already received a PLOGI from this NPort
* we don't need to try to discover it again.
*/
if (ndlp->nlp_flag & NLP_RCV_PLOGI)
if (ndlp->nlp_flag & NLP_RCV_PLOGI &&
!(ndlp->nlp_type &
(NLP_FCP_TARGET | NLP_NVME_TARGET)))
return NULL;
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
} else
} else {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6456 Skip Setup RSCN Node x%x "
"Data:x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, vport->fc_flag);
ndlp = NULL;
}
} else {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6457 Setup Active Node 2B_DISC x%x "
"Data:x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, vport->fc_flag);
/* If the initiator received a PLOGI from this NPort or if the
* initiator is already in the process of discovery on it,
* there's no need to try to discover it again.
@ -5565,10 +5636,10 @@ lpfc_disc_start(struct lpfc_vport *vport)
/* Start Discovery state <hba_state> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0202 Start Discovery hba state x%x "
"Data: x%x x%x x%x\n",
"0202 Start Discovery port state x%x "
"flg x%x Data: x%x x%x x%x\n",
vport->port_state, vport->fc_flag, vport->fc_plogi_cnt,
vport->fc_adisc_cnt);
vport->fc_adisc_cnt, vport->fc_npr_cnt);
/* First do ADISCs - if any */
num_sent = lpfc_els_disc_adisc(vport);
@ -5996,7 +6067,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
@ -6185,12 +6256,12 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did)
INIT_LIST_HEAD(&ndlp->nlp_listp);
if (vport->phba->sli_rev == LPFC_SLI_REV4) {
ndlp->nlp_rpi = rpi;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
"0007 rpi:%x DID:%x flg:%x refcnt:%d "
"map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID,
ndlp->nlp_flag,
kref_read(&ndlp->kref),
ndlp->nlp_usg_map, ndlp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0007 Init New ndlp x%px, rpi:x%x DID:%x "
"flg:x%x refcnt:%d map:x%x\n",
ndlp, ndlp->nlp_rpi, ndlp->nlp_DID,
ndlp->nlp_flag, kref_read(&ndlp->kref),
ndlp->nlp_usg_map);
ndlp->active_rrqs_xri_bitmap =
mempool_alloc(vport->phba->active_rrq_pool,
@ -6419,7 +6490,8 @@ lpfc_fcf_inuse(struct lpfc_hba *phba)
goto out;
} else if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
ret = 1;
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
lpfc_printf_log(phba, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"2624 RPI %x DID %x flag %x "
"still logged in\n",
ndlp->nlp_rpi, ndlp->nlp_DID,

View File

@ -210,7 +210,6 @@ struct lpfc_sli_intf {
#define LPFC_MAX_IMAX 5000000
#define LPFC_DEF_IMAX 0
#define LPFC_IMAX_THRESHOLD 1000
#define LPFC_MAX_AUTO_EQ_DELAY 120
#define LPFC_EQ_DELAY_STEP 15
#define LPFC_EQD_ISR_TRIGGER 20000
@ -2320,6 +2319,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
#define ADD_STATUS_INVALID_REQUEST 0x4B
#define ADD_STATUS_FW_DOWNLOAD_HW_DISABLED 0x58
struct lpfc_mbx_sli4_config {
struct mbox_header header;
@ -2809,6 +2809,15 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_trunk_SHIFT 12
#define lpfc_mbx_rd_conf_trunk_MASK 0x0000000F
#define lpfc_mbx_rd_conf_trunk_WORD word2
#define lpfc_mbx_rd_conf_pt_SHIFT 20
#define lpfc_mbx_rd_conf_pt_MASK 0x00000003
#define lpfc_mbx_rd_conf_pt_WORD word2
#define lpfc_mbx_rd_conf_tf_SHIFT 22
#define lpfc_mbx_rd_conf_tf_MASK 0x00000001
#define lpfc_mbx_rd_conf_tf_WORD word2
#define lpfc_mbx_rd_conf_ptv_SHIFT 23
#define lpfc_mbx_rd_conf_ptv_MASK 0x00000001
#define lpfc_mbx_rd_conf_ptv_WORD word2
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
@ -3479,6 +3488,9 @@ struct lpfc_sli4_parameters {
#define cfg_bv1s_SHIFT 10
#define cfg_bv1s_MASK 0x00000001
#define cfg_bv1s_WORD word19
#define cfg_pvl_SHIFT 13
#define cfg_pvl_MASK 0x00000001
#define cfg_pvl_WORD word19
#define cfg_nsler_SHIFT 12
#define cfg_nsler_MASK 0x00000001
@ -3518,6 +3530,7 @@ struct lpfc_sli4_parameters {
#define LPFC_SET_UE_RECOVERY 0x10
#define LPFC_SET_MDS_DIAGS 0x11
#define LPFC_SET_DUAL_DUMP 0x1e
struct lpfc_mbx_set_feature {
struct mbox_header header;
uint32_t feature;
@ -3532,6 +3545,15 @@ struct lpfc_mbx_set_feature {
#define lpfc_mbx_set_feature_mds_deep_loopbk_SHIFT 1
#define lpfc_mbx_set_feature_mds_deep_loopbk_MASK 0x00000001
#define lpfc_mbx_set_feature_mds_deep_loopbk_WORD word6
#define lpfc_mbx_set_feature_dd_SHIFT 0
#define lpfc_mbx_set_feature_dd_MASK 0x00000001
#define lpfc_mbx_set_feature_dd_WORD word6
#define lpfc_mbx_set_feature_ddquery_SHIFT 1
#define lpfc_mbx_set_feature_ddquery_MASK 0x00000001
#define lpfc_mbx_set_feature_ddquery_WORD word6
#define LPFC_DISABLE_DUAL_DUMP 0
#define LPFC_ENABLE_DUAL_DUMP 1
#define LPFC_QUERY_OP_DUAL_DUMP 2
uint32_t word7;
#define lpfc_mbx_set_feature_UERP_SHIFT 0
#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
@ -4261,6 +4283,8 @@ struct lpfc_acqe_sli {
#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5
#define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9
#define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA
#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
};
/*
@ -4659,6 +4683,7 @@ struct create_xri_wqe {
uint32_t rsvd_12_15[4]; /* word 12-15 */
};
#define INHIBIT_ABORT 1
#define T_REQUEST_TAG 3
#define T_XRI_TAG 1
@ -4807,8 +4832,8 @@ union lpfc_wqe128 {
struct send_frame_wqe send_frame;
};
#define MAGIC_NUMER_G6 0xFEAA0003
#define MAGIC_NUMER_G7 0xFEAA0005
#define MAGIC_NUMBER_G6 0xFEAA0003
#define MAGIC_NUMBER_G7 0xFEAA0005
struct lpfc_grp_hdr {
uint32_t size;

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,23 @@
#define LOG_NVME_IOERR 0x00800000 /* NVME IO Error events. */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
/* generate message by verbose log setting or severity */
#define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \
{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \
dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
fmt, (vport)->phba->brd_no, vport->vpi, ##arg); }
#define lpfc_log_msg(phba, level, mask, fmt, arg...) \
do { \
{ uint32_t log_verbose = (phba)->pport ? \
(phba)->pport->cfg_log_verbose : \
(phba)->cfg_log_verbose; \
if (((mask) & log_verbose) || (level[1] <= '4')) \
dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
fmt, phba->brd_no, ##arg); \
} \
} while (0)
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
do { \
{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) \

View File

@ -515,6 +515,7 @@ lpfc_init_link(struct lpfc_hba * phba,
if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
!(phba->sli4_hba.pc_sli4_params.pls) &&
mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT;

View File

@ -230,9 +230,6 @@ lpfc_mem_free(struct lpfc_hba *phba)
dma_pool_destroy(phba->lpfc_hrb_pool);
phba->lpfc_hrb_pool = NULL;
dma_pool_destroy(phba->txrdy_payload_pool);
phba->txrdy_payload_pool = NULL;
dma_pool_destroy(phba->lpfc_hbq_pool);
phba->lpfc_hbq_pool = NULL;

View File

@ -279,6 +279,55 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
}
/* lpfc_defer_pt2pt_acc - Complete SLI3 pt2pt processing on link up
* @phba: pointer to lpfc hba data structure.
* @link_mbox: pointer to CONFIG_LINK mailbox object
*
* This routine is only called if we are SLI3, direct connect pt2pt
* mode and the remote NPort issues the PLOGI after link up.
*/
static void
lpfc_defer_pt2pt_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *link_mbox)
{
LPFC_MBOXQ_t *login_mbox;
MAILBOX_t *mb = &link_mbox->u.mb;
struct lpfc_iocbq *save_iocb;
struct lpfc_nodelist *ndlp;
int rc;
ndlp = link_mbox->ctx_ndlp;
login_mbox = link_mbox->context3;
save_iocb = login_mbox->context3;
link_mbox->context3 = NULL;
login_mbox->context3 = NULL;
/* Check for CONFIG_LINK error */
if (mb->mbxStatus) {
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"4575 CONFIG_LINK fails pt2pt discovery: %x\n",
mb->mbxStatus);
mempool_free(login_mbox, phba->mbox_mem_pool);
mempool_free(link_mbox, phba->mbox_mem_pool);
lpfc_sli_release_iocbq(phba, save_iocb);
return;
}
/* Now that CONFIG_LINK completed, and our SID is configured,
* we can now proceed with sending the PLOGI ACC.
*/
rc = lpfc_els_rsp_acc(link_mbox->vport, ELS_CMD_PLOGI,
save_iocb, ndlp, login_mbox);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"4576 PLOGI ACC fails pt2pt discovery: %x\n",
rc);
mempool_free(login_mbox, phba->mbox_mem_pool);
}
mempool_free(link_mbox, phba->mbox_mem_pool);
lpfc_sli_release_iocbq(phba, save_iocb);
}
static int
lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb)
@ -291,10 +340,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
IOCB_t *icmd;
struct serv_parm *sp;
uint32_t ed_tov;
LPFC_MBOXQ_t *mbox;
LPFC_MBOXQ_t *link_mbox;
LPFC_MBOXQ_t *login_mbox;
struct lpfc_iocbq *save_iocb;
struct ls_rjt stat;
uint32_t vid, flag;
int rc;
int rc, defer_acc;
memset(&stat, 0, sizeof (struct ls_rjt));
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@ -343,6 +394,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
else
ndlp->nlp_fcp_info |= CLASS3;
defer_acc = 0;
ndlp->nlp_class_sup = 0;
if (sp->cls1.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS1;
@ -354,7 +406,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
/* if already logged in, do implicit logout */
switch (ndlp->nlp_state) {
case NLP_STE_NPR_NODE:
@ -396,6 +447,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
ndlp->nlp_flag &= ~NLP_FIRSTBURST;
login_mbox = NULL;
link_mbox = NULL;
save_iocb = NULL;
/* Check for Nport to NPort pt2pt protocol */
if ((vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_PT2PT_PLOGI)) {
@ -423,17 +478,22 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_issue_reg_vfi(vport);
else {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL)
defer_acc = 1;
link_mbox = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!link_mbox)
goto out;
lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
lpfc_config_link(phba, link_mbox);
link_mbox->mbox_cmpl = lpfc_defer_pt2pt_acc;
link_mbox->vport = vport;
link_mbox->ctx_ndlp = ndlp;
save_iocb = lpfc_sli_get_iocbq(phba);
if (!save_iocb)
goto out;
}
/* Save info from cmd IOCB used in rsp */
memcpy((uint8_t *)save_iocb, (uint8_t *)cmdiocb,
sizeof(struct lpfc_iocbq));
}
lpfc_can_disctmo(vport);
@ -448,8 +508,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_flag |= NLP_SUPPRESS_RSP;
}
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
login_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!login_mbox)
goto out;
/* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
@ -457,21 +517,19 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_unreg_rpi(vport, ndlp);
rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
(uint8_t *) sp, mbox, ndlp->nlp_rpi);
if (rc) {
mempool_free(mbox, phba->mbox_mem_pool);
(uint8_t *)sp, login_mbox, ndlp->nlp_rpi);
if (rc)
goto out;
}
/* ACC PLOGI rsp command needs to execute first,
* queue this mbox command to be processed later.
* queue this login_mbox command to be processed later.
*/
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
login_mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
/*
* mbox->ctx_ndlp = lpfc_nlp_get(ndlp) deferred until mailbox
* login_mbox->ctx_ndlp = lpfc_nlp_get(ndlp) deferred until mailbox
* command issued in lpfc_cmpl_els_acc().
*/
mbox->vport = vport;
login_mbox->vport = vport;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
spin_unlock_irq(shost->host_lock);
@ -484,8 +542,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
* single discovery thread, this will cause a huge delay in
* discovery. Also this will cause multiple state machines
* running in parallel for this node.
* This only applies to a fabric environment.
*/
if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&
(vport->fc_flag & FC_FABRIC)) {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
}
@ -504,16 +564,47 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
ndlp, mbox);
ndlp, login_mbox);
if (rc)
mempool_free(mbox, phba->mbox_mem_pool);
mempool_free(login_mbox, phba->mbox_mem_pool);
return 1;
}
rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
if (defer_acc) {
/* So the order here should be:
* Issue CONFIG_LINK mbox
* CONFIG_LINK cmpl
* Issue PLOGI ACC
* PLOGI ACC cmpl
* Issue REG_LOGIN mbox
*/
/* Save the REG_LOGIN mbox for and rcv IOCB copy later */
link_mbox->context3 = login_mbox;
login_mbox->context3 = save_iocb;
/* Start the ball rolling by issuing CONFIG_LINK here */
rc = lpfc_sli_issue_mbox(phba, link_mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED)
goto out;
return 1;
}
rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, login_mbox);
if (rc)
mempool_free(mbox, phba->mbox_mem_pool);
mempool_free(login_mbox, phba->mbox_mem_pool);
return 1;
out:
if (defer_acc)
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"4577 pt2pt discovery failure: %p %p %p\n",
save_iocb, link_mbox, login_mbox);
if (save_iocb)
lpfc_sli_release_iocbq(phba, save_iocb);
if (link_mbox)
mempool_free(link_mbox, phba->mbox_mem_pool);
if (login_mbox)
mempool_free(login_mbox, phba->mbox_mem_pool);
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
@ -2030,7 +2121,9 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (bf_get_be32(prli_init, nvpr))
ndlp->nlp_type |= NLP_NVME_INITIATOR;
if (phba->nsler && bf_get_be32(prli_nsler, nvpr))
if (phba->nsler && bf_get_be32(prli_nsler, nvpr) &&
bf_get_be32(prli_conf, nvpr))
ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
else
ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;

View File

@ -195,6 +195,46 @@ lpfc_nvme_cmd_template(void)
/* Word 12, 13, 14, 15 - is zero */
}
/**
* lpfc_nvme_prep_abort_wqe - set up 'abort' work queue entry.
* @pwqeq: Pointer to command iocb.
* @xritag: Tag that uniqely identifies the local exchange resource.
* @opt: Option bits -
* bit 0 = inhibit sending abts on the link
*
* This function is called with hbalock held.
**/
void
lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt)
{
union lpfc_wqe128 *wqe = &pwqeq->wqe;
/* WQEs are reused. Clear stale data and set key fields to
* zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
*/
memset(wqe, 0, sizeof(*wqe));
if (opt & INHIBIT_ABORT)
bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
/* Abort specified xri tag, with the mask deliberately zeroed */
bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG);
bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
/* Abort the IO associated with this outstanding exchange ID. */
wqe->abort_cmd.wqe_com.abort_tag = xritag;
/* iotag for the wqe completion. */
bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, pwqeq->iotag);
bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND);
bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
}
/**
* lpfc_nvme_create_queue -
* @lpfc_pnvme: Pointer to the driver's nvme instance data
@ -1791,7 +1831,6 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
struct lpfc_iocbq *abts_buf;
struct lpfc_iocbq *nvmereq_wqe;
struct lpfc_nvme_fcpreq_priv *freqpriv;
union lpfc_wqe128 *abts_wqe;
unsigned long flags;
int ret_val;
@ -1912,37 +1951,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
/* Ready - mark outstanding as aborted by driver. */
nvmereq_wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
/* Complete prepping the abort wqe and issue to the FW. */
abts_wqe = &abts_buf->wqe;
/* WQEs are reused. Clear stale data and set key fields to
* zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
*/
memset(abts_wqe, 0, sizeof(*abts_wqe));
bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG);
/* word 7 */
bf_set(wqe_cmnd, &abts_wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
bf_set(wqe_class, &abts_wqe->abort_cmd.wqe_com,
nvmereq_wqe->iocb.ulpClass);
/* word 8 - tell the FW to abort the IO associated with this
* outstanding exchange ID.
*/
abts_wqe->abort_cmd.wqe_com.abort_tag = nvmereq_wqe->sli4_xritag;
/* word 9 - this is the iotag for the abts_wqe completion. */
bf_set(wqe_reqtag, &abts_wqe->abort_cmd.wqe_com,
abts_buf->iotag);
/* word 10 */
bf_set(wqe_qosd, &abts_wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_lenloc, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
/* word 11 */
bf_set(wqe_cmd_type, &abts_wqe->abort_cmd.wqe_com, OTHER_COMMAND);
bf_set(wqe_wqec, &abts_wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_cqid, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
lpfc_nvme_prep_abort_wqe(abts_buf, nvmereq_wqe->sli4_xritag, 0);
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
abts_buf->iocb_flag |= LPFC_IO_NVME;
@ -2084,7 +2093,7 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd)
lpfc_ncmd->flags &= ~LPFC_SBUF_BUMP_QDEPTH;
qp = lpfc_ncmd->hdwq;
if (lpfc_ncmd->flags & LPFC_SBUF_XBUSY) {
if (unlikely(lpfc_ncmd->flags & LPFC_SBUF_XBUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6310 XB release deferred for "
"ox_id x%x on reqtag x%x\n",
@ -2139,12 +2148,10 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
*/
lpfc_nvme_template.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
/* Advertise how many hw queues we support based on fcp_io_sched */
if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
lpfc_nvme_template.max_hw_queues = phba->cfg_hdw_queue;
else
lpfc_nvme_template.max_hw_queues =
phba->sli4_hba.num_present_cpu;
/* Advertise how many hw queues we support based on cfg_hdw_queue,
* which will not exceed cpu count.
*/
lpfc_nvme_template.max_hw_queues = phba->cfg_hdw_queue;
if (!IS_ENABLED(CONFIG_NVME_FC))
return ret;

View File

@ -378,13 +378,6 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
int cpu;
unsigned long iflag;
if (ctxp->txrdy) {
dma_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
ctxp->txrdy_phys);
ctxp->txrdy = NULL;
ctxp->txrdy_phys = 0;
}
if (ctxp->state == LPFC_NVMET_STE_FREE) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"6411 NVMET free, already free IO x%x: %d %d\n",
@ -430,7 +423,6 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
ctxp->wqeq = NULL;
ctxp->txrdy = NULL;
ctxp->offset = 0;
ctxp->phba = phba;
ctxp->size = size;
@ -1958,12 +1950,10 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint32_t *payload;
uint32_t size, oxid, sid, rc;
fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
oxid = be16_to_cpu(fc_hdr->fh_ox_id);
if (!phba->targetport) {
if (!nvmebuf || !phba->targetport) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"6154 LS Drop IO x%x\n", oxid);
"6154 LS Drop IO\n");
oxid = 0;
size = 0;
sid = 0;
@ -1971,6 +1961,9 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
goto dropit;
}
fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
oxid = be16_to_cpu(fc_hdr->fh_ox_id);
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
payload = (uint32_t *)(nvmebuf->dbuf.virt);
size = bf_get(lpfc_rcqe_length, &nvmebuf->cq_event.cqe.rcqe_cmpl);
@ -2326,7 +2319,6 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
ctxp->state, ctxp->entry_cnt, ctxp->oxid);
}
ctxp->wqeq = NULL;
ctxp->txrdy = NULL;
ctxp->offset = 0;
ctxp->phba = phba;
ctxp->size = size;
@ -2401,6 +2393,11 @@ lpfc_nvmet_unsol_ls_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
d_buf = piocb->context2;
nvmebuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
if (!nvmebuf) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"3015 LS Drop IO\n");
return;
}
if (phba->nvmet_support == 0) {
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
return;
@ -2429,6 +2426,11 @@ lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
uint64_t isr_timestamp,
uint8_t cqflag)
{
if (!nvmebuf) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"3167 NVMET FCP Drop IO\n");
return;
}
if (phba->nvmet_support == 0) {
lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
return;
@ -2595,7 +2597,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
struct scatterlist *sgel;
union lpfc_wqe128 *wqe;
struct ulp_bde64 *bde;
uint32_t *txrdy;
dma_addr_t physaddr;
int i, cnt;
int do_pbde;
@ -2757,23 +2758,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
&lpfc_treceive_cmd_template.words[3],
sizeof(uint32_t) * 9);
/* Words 0 - 2 : The first sg segment */
txrdy = dma_pool_alloc(phba->txrdy_payload_pool,
GFP_KERNEL, &physaddr);
if (!txrdy) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"6041 Bad txrdy buffer: oxid x%x\n",
ctxp->oxid);
return NULL;
}
ctxp->txrdy = txrdy;
ctxp->txrdy_phys = physaddr;
wqe->fcp_treceive.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
wqe->fcp_treceive.bde.tus.f.bdeSize = TXRDY_PAYLOAD_LEN;
wqe->fcp_treceive.bde.addrLow =
cpu_to_le32(putPaddrLow(physaddr));
wqe->fcp_treceive.bde.addrHigh =
cpu_to_le32(putPaddrHigh(physaddr));
/* Words 0 - 2 : First SGE is skipped, set invalid BDE type */
wqe->fcp_treceive.bde.tus.f.bdeFlags = LPFC_SGE_TYPE_SKIP;
wqe->fcp_treceive.bde.tus.f.bdeSize = 0;
wqe->fcp_treceive.bde.addrLow = 0;
wqe->fcp_treceive.bde.addrHigh = 0;
/* Word 4 */
wqe->fcp_treceive.relative_offset = ctxp->offset;
@ -2808,17 +2797,13 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
/* Word 12 */
wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
/* Setup 1 TXRDY and 1 SKIP SGE */
txrdy[0] = 0;
txrdy[1] = cpu_to_be32(rsp->transfer_length);
txrdy[2] = 0;
sgl->addr_hi = putPaddrHigh(physaddr);
sgl->addr_lo = putPaddrLow(physaddr);
/* Setup 2 SKIP SGEs */
sgl->addr_hi = 0;
sgl->addr_lo = 0;
sgl->word2 = 0;
bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_SKIP);
sgl->word2 = cpu_to_le32(sgl->word2);
sgl->sge_len = cpu_to_le32(TXRDY_PAYLOAD_LEN);
sgl->sge_len = 0;
sgl++;
sgl->addr_hi = 0;
sgl->addr_lo = 0;
@ -3239,9 +3224,9 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
{
struct lpfc_nvmet_tgtport *tgtp;
struct lpfc_iocbq *abts_wqeq;
union lpfc_wqe128 *abts_wqe;
struct lpfc_nodelist *ndlp;
unsigned long flags;
u8 opt;
int rc;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
@ -3280,8 +3265,8 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
return 0;
}
abts_wqeq = ctxp->abort_wqeq;
abts_wqe = &abts_wqeq->wqe;
ctxp->state = LPFC_NVMET_STE_ABORT;
opt = (ctxp->flag & LPFC_NVMET_ABTS_RCV) ? INHIBIT_ABORT : 0;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
/* Announce entry to new IO submit field. */
@ -3327,40 +3312,12 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
/* Ready - mark outstanding as aborted by driver. */
abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED;
/* WQEs are reused. Clear stale data and set key fields to
* zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
*/
memset(abts_wqe, 0, sizeof(*abts_wqe));
/* word 3 */
bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG);
/* word 7 */
bf_set(wqe_ct, &abts_wqe->abort_cmd.wqe_com, 0);
bf_set(wqe_cmnd, &abts_wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
/* word 8 - tell the FW to abort the IO associated with this
* outstanding exchange ID.
*/
abts_wqe->abort_cmd.wqe_com.abort_tag = ctxp->wqeq->sli4_xritag;
/* word 9 - this is the iotag for the abts_wqe completion. */
bf_set(wqe_reqtag, &abts_wqe->abort_cmd.wqe_com,
abts_wqeq->iotag);
/* word 10 */
bf_set(wqe_qosd, &abts_wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_lenloc, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
/* word 11 */
bf_set(wqe_cmd_type, &abts_wqe->abort_cmd.wqe_com, OTHER_COMMAND);
bf_set(wqe_wqec, &abts_wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_cqid, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
lpfc_nvme_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt);
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx;
abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp;
abts_wqeq->iocb_cmpl = 0;
abts_wqeq->iocb_cmpl = NULL;
abts_wqeq->iocb_flag |= LPFC_IO_NVME;
abts_wqeq->context2 = ctxp;
abts_wqeq->vport = phba->pport;
@ -3495,7 +3452,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
spin_lock_irqsave(&phba->hbalock, flags);
abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp;
abts_wqeq->iocb_cmpl = 0;
abts_wqeq->iocb_cmpl = NULL;
abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS;
rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq);
spin_unlock_irqrestore(&phba->hbalock, flags);

View File

@ -112,9 +112,7 @@ struct lpfc_nvmet_rcv_ctx {
struct lpfc_hba *phba;
struct lpfc_iocbq *wqeq;
struct lpfc_iocbq *abort_wqeq;
dma_addr_t txrdy_phys;
spinlock_t ctxlock; /* protect flag access */
uint32_t *txrdy;
uint32_t sid;
uint32_t offset;
uint16_t oxid;

View File

@ -134,21 +134,21 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
/**
* lpfc_update_stats - Update statistical data for the command completion
* @phba: Pointer to HBA object.
* @vport: The virtual port on which this call is executing.
* @lpfc_cmd: lpfc scsi command object pointer.
*
* This function is called when there is a command completion and this
* function updates the statistical data for the command completion.
**/
static void
lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
lpfc_update_stats(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_rport_data *rdata;
struct lpfc_nodelist *pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
unsigned long flags;
struct Scsi_Host *shost = cmd->device->host;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
unsigned long latency;
int i;
@ -526,7 +526,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
&qp->lpfc_abts_io_buf_list, list) {
if (psb->cur_iocbq.sli4_xritag == xri) {
list_del_init(&psb->list);
psb->exch_busy = 0;
psb->flags &= ~LPFC_SBUF_XBUSY;
psb->status = IOSTAT_SUCCESS;
if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) {
qp->abts_nvme_io_bufs--;
@ -566,7 +566,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
if (iocbq->sli4_xritag != xri)
continue;
psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
psb->exch_busy = 0;
psb->flags &= ~LPFC_SBUF_XBUSY;
spin_unlock_irqrestore(&phba->hbalock, iflag);
if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba);
@ -786,7 +786,7 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
psb->prot_seg_cnt = 0;
qp = psb->hdwq;
if (psb->exch_busy) {
if (psb->flags & LPFC_SBUF_XBUSY) {
spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag);
psb->pCmd = NULL;
list_add_tail(&psb->list, &qp->lpfc_abts_io_buf_list);
@ -3812,7 +3812,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
/* Sanity check on return of outstanding command */
cmd = lpfc_cmd->pCmd;
if (!cmd) {
if (!cmd || !phba) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"2621 IO completion: Not an active IO\n");
spin_unlock(&lpfc_cmd->buf_lock);
@ -3824,7 +3824,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->cpucheck_on & LPFC_CHECK_SCSI_IO) {
if (unlikely(phba->cpucheck_on & LPFC_CHECK_SCSI_IO)) {
cpu = raw_smp_processor_id();
if (cpu < LPFC_CHECK_CPU_CNT && phba->sli4_hba.hdwq)
phba->sli4_hba.hdwq[idx].cpucheck_cmpl_io[cpu]++;
@ -3835,7 +3835,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK);
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
/* pick up SLI4 exhange busy status from HBA */
lpfc_cmd->exch_busy = pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY;
if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY)
lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
else
lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (lpfc_cmd->prot_data_type) {
@ -3869,7 +3872,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
#endif
if (lpfc_cmd->status) {
if (unlikely(lpfc_cmd->status)) {
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
(lpfc_cmd->result & IOERR_DRVR_MASK))
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
@ -4002,7 +4005,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
scsi_get_resid(cmd));
}
lpfc_update_stats(phba, lpfc_cmd);
lpfc_update_stats(vport, lpfc_cmd);
if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
@ -4610,17 +4613,18 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd);
}
if (err == 2) {
cmnd->result = DID_ERROR << 16;
goto out_fail_command_release_buf;
} else if (err) {
if (unlikely(err)) {
if (err == 2) {
cmnd->result = DID_ERROR << 16;
goto out_fail_command_release_buf;
}
goto out_host_busy_free_buf;
}
lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->cpucheck_on & LPFC_CHECK_SCSI_IO) {
if (unlikely(phba->cpucheck_on & LPFC_CHECK_SCSI_IO)) {
cpu = raw_smp_processor_id();
if (cpu < LPFC_CHECK_CPU_CNT) {
struct lpfc_sli4_hdw_queue *hdwq =
@ -4843,20 +4847,21 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING,
abtsiocb, 0);
}
/* no longer need the lock after this point */
spin_unlock_irqrestore(&phba->hbalock, flags);
if (ret_val == IOCB_ERROR) {
/* Indicate the IO is not being aborted by the driver. */
iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
lpfc_cmd->waitq = NULL;
spin_unlock(&lpfc_cmd->buf_lock);
spin_unlock_irqrestore(&phba->hbalock, flags);
lpfc_sli_release_iocbq(phba, abtsiocb);
ret = FAILED;
goto out;
}
/* no longer need the lock after this point */
spin_unlock(&lpfc_cmd->buf_lock);
spin_unlock_irqrestore(&phba->hbalock, flags);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_sli_handle_fast_ring_event(phba,

View File

@ -87,6 +87,10 @@ static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
struct lpfc_eqe *eqe);
static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba);
static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba);
static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q);
static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba,
struct lpfc_queue *cq,
struct lpfc_cqe *cqe);
static IOCB_t *
lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
@ -467,25 +471,52 @@ __lpfc_sli4_consume_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq,
}
static void
lpfc_sli4_eq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
{
struct lpfc_eqe *eqe;
uint32_t count = 0;
struct lpfc_eqe *eqe = NULL;
u32 eq_count = 0, cq_count = 0;
struct lpfc_cqe *cqe = NULL;
struct lpfc_queue *cq = NULL, *childq = NULL;
int cqid = 0;
/* walk all the EQ entries and drop on the floor */
eqe = lpfc_sli4_eq_get(eq);
while (eqe) {
/* Get the reference to the corresponding CQ */
cqid = bf_get_le32(lpfc_eqe_resource_id, eqe);
cq = NULL;
list_for_each_entry(childq, &eq->child_list, list) {
if (childq->queue_id == cqid) {
cq = childq;
break;
}
}
/* If CQ is valid, iterate through it and drop all the CQEs */
if (cq) {
cqe = lpfc_sli4_cq_get(cq);
while (cqe) {
__lpfc_sli4_consume_cqe(phba, cq, cqe);
cq_count++;
cqe = lpfc_sli4_cq_get(cq);
}
/* Clear and re-arm the CQ */
phba->sli4_hba.sli4_write_cq_db(phba, cq, cq_count,
LPFC_QUEUE_REARM);
cq_count = 0;
}
__lpfc_sli4_consume_eqe(phba, eq, eqe);
count++;
eq_count++;
eqe = lpfc_sli4_eq_get(eq);
}
/* Clear and re-arm the EQ */
phba->sli4_hba.sli4_write_eq_db(phba, eq, count, LPFC_QUEUE_REARM);
phba->sli4_hba.sli4_write_eq_db(phba, eq, eq_count, LPFC_QUEUE_REARM);
}
static int
lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq)
lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq,
uint8_t rearm)
{
struct lpfc_eqe *eqe;
int count = 0, consumed = 0;
@ -519,8 +550,8 @@ lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq)
eq->queue_claimed = 0;
rearm_and_exit:
/* Always clear and re-arm the EQ */
phba->sli4_hba.sli4_write_eq_db(phba, eq, consumed, LPFC_QUEUE_REARM);
/* Always clear the EQ. */
phba->sli4_hba.sli4_write_eq_db(phba, eq, consumed, rearm);
return count;
}
@ -2526,6 +2557,8 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
} else {
__lpfc_sli_rpi_release(vport, ndlp);
}
if (vport->load_flag & FC_UNLOADING)
lpfc_nlp_put(ndlp);
pmb->ctx_ndlp = NULL;
}
}
@ -2672,7 +2705,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"(%d):0323 Unknown Mailbox command "
"x%x (x%x/x%x) Cmpl\n",
pmb->vport ? pmb->vport->vpi : 0,
pmb->vport ? pmb->vport->vpi :
LPFC_VPORT_UNKNOWN,
pmbox->mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
pmb),
@ -2693,7 +2727,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
"(%d):0305 Mbox cmd cmpl "
"error - RETRYing Data: x%x "
"(x%x/x%x) x%x x%x x%x\n",
pmb->vport ? pmb->vport->vpi : 0,
pmb->vport ? pmb->vport->vpi :
LPFC_VPORT_UNKNOWN,
pmbox->mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
pmb),
@ -2701,7 +2736,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
pmb),
pmbox->mbxStatus,
pmbox->un.varWords[0],
pmb->vport->port_state);
pmb->vport ? pmb->vport->port_state :
LPFC_VPORT_UNKNOWN);
pmbox->mbxStatus = 0;
pmbox->mbxOwner = OWN_HOST;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
@ -6167,6 +6203,14 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
mbox->u.mqe.un.set_feature.param_len = 8;
break;
case LPFC_SET_DUAL_DUMP:
bf_set(lpfc_mbx_set_feature_dd,
&mbox->u.mqe.un.set_feature, LPFC_ENABLE_DUAL_DUMP);
bf_set(lpfc_mbx_set_feature_ddquery,
&mbox->u.mqe.un.set_feature, 0);
mbox->u.mqe.un.set_feature.feature = LPFC_SET_DUAL_DUMP;
mbox->u.mqe.un.set_feature.param_len = 4;
break;
}
return;
@ -6184,11 +6228,16 @@ lpfc_ras_stop_fwlog(struct lpfc_hba *phba)
{
struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
ras_fwlog->ras_active = false;
spin_lock_irq(&phba->hbalock);
ras_fwlog->state = INACTIVE;
spin_unlock_irq(&phba->hbalock);
/* Disable FW logging to host memory */
writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
/* Wait 10ms for firmware to stop using DMA buffer */
usleep_range(10 * 1000, 20 * 1000);
}
/**
@ -6224,7 +6273,9 @@ lpfc_sli4_ras_dma_free(struct lpfc_hba *phba)
ras_fwlog->lwpd.virt = NULL;
}
ras_fwlog->ras_active = false;
spin_lock_irq(&phba->hbalock);
ras_fwlog->state = INACTIVE;
spin_unlock_irq(&phba->hbalock);
}
/**
@ -6326,7 +6377,9 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
goto disable_ras;
}
ras_fwlog->ras_active = true;
spin_lock_irq(&phba->hbalock);
ras_fwlog->state = ACTIVE;
spin_unlock_irq(&phba->hbalock);
mempool_free(pmb, phba->mbox_mem_pool);
return;
@ -6358,6 +6411,10 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
uint32_t len = 0, fwlog_buffsize, fwlog_entry_count;
int rc = 0;
spin_lock_irq(&phba->hbalock);
ras_fwlog->state = INACTIVE;
spin_unlock_irq(&phba->hbalock);
fwlog_buffsize = (LPFC_RAS_MIN_BUFF_POST_SIZE *
phba->cfg_ras_fwlog_buffsize);
fwlog_entry_count = (fwlog_buffsize/LPFC_RAS_MAX_ENTRY_SIZE);
@ -6417,6 +6474,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
mbx_fwlog->u.request.lwpd.addr_lo = putPaddrLow(ras_fwlog->lwpd.phys);
mbx_fwlog->u.request.lwpd.addr_hi = putPaddrHigh(ras_fwlog->lwpd.phys);
spin_lock_irq(&phba->hbalock);
ras_fwlog->state = REG_INPROGRESS;
spin_unlock_irq(&phba->hbalock);
mbox->vport = phba->pport;
mbox->mbox_cmpl = lpfc_sli4_ras_mbox_cmpl;
@ -7148,7 +7208,7 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
int
lpfc_sli4_hba_setup(struct lpfc_hba *phba)
{
int rc, i, cnt, len;
int rc, i, cnt, len, dd;
LPFC_MBOXQ_t *mboxq;
struct lpfc_mqe *mqe;
uint8_t *vpd;
@ -7399,6 +7459,23 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED);
spin_unlock_irq(&phba->hbalock);
/* Always try to enable dual dump feature if we can */
lpfc_set_features(phba, mboxq, LPFC_SET_DUAL_DUMP);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
dd = bf_get(lpfc_mbx_set_feature_dd, &mboxq->u.mqe.un.set_feature);
if ((rc == MBX_SUCCESS) && (dd == LPFC_ENABLE_DUAL_DUMP))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_INIT,
"6448 Dual Dump is enabled\n");
else
lpfc_printf_log(phba, KERN_INFO, LOG_SLI | LOG_INIT,
"6447 Dual Dump Mailbox x%x (x%x/x%x) failed, "
"rc:x%x dd:x%x\n",
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
lpfc_sli_config_mbox_subsys_get(
phba, mboxq),
lpfc_sli_config_mbox_opcode_get(
phba, mboxq),
rc, dd);
/*
* Allocate all resources (xri,rpi,vpi,vfi) now. Subsequent
* calls depends on these resources to complete port setup.
@ -7523,9 +7600,11 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
}
phba->sli4_hba.nvmet_xri_cnt = rc;
cnt = phba->cfg_iocb_cnt * 1024;
/* We need 1 iocbq for every SGL, for IO processing */
cnt += phba->sli4_hba.nvmet_xri_cnt;
/* We allocate an iocbq for every receive context SGL.
* The additional allocation is for abort and ls handling.
*/
cnt = phba->sli4_hba.nvmet_xri_cnt +
phba->sli4_hba.max_cfg_param.max_xri;
} else {
/* update host common xri-sgl sizes and mappings */
rc = lpfc_sli4_io_sgl_update(phba);
@ -7547,14 +7626,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
rc = -ENODEV;
goto out_destroy_queue;
}
cnt = phba->cfg_iocb_cnt * 1024;
/* Each lpfc_io_buf job structure has an iocbq element.
* This cnt provides for abort, els, ct and ls requests.
*/
cnt = phba->sli4_hba.max_cfg_param.max_xri;
}
if (!phba->sli.iocbq_lookup) {
/* Initialize and populate the iocb list per host */
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2821 initialize iocb list %d total %d\n",
phba->cfg_iocb_cnt, cnt);
"2821 initialize iocb list with %d entries\n",
cnt);
rc = lpfc_init_iocb_list(phba, cnt);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@ -7892,7 +7974,7 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba)
if (mbox_pending)
/* process and rearm the EQ */
lpfc_sli4_process_eq(phba, fpeq);
lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM);
else
/* Always clear and re-arm the EQ */
sli4_hba->sli4_write_eq_db(phba, fpeq, 0, LPFC_QUEUE_REARM);
@ -8964,7 +9046,8 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
*
* This function is called with hbalock held to add a command
* This function is called with hbalock held for SLI3 ports or
* the ring lock held for SLI4 ports to add a command
* iocb to the txq when SLI layer cannot submit the command iocb
* to the ring.
**/
@ -8972,7 +9055,10 @@ void
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
lockdep_assert_held(&phba->hbalock);
if (phba->sli_rev == LPFC_SLI_REV4)
lockdep_assert_held(&pring->ring_lock);
else
lockdep_assert_held(&phba->hbalock);
/* Insert the caller's iocb in the txq tail for later processing. */
list_add_tail(&piocb->list, &pring->txq);
}
@ -9863,7 +9949,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
* __lpfc_sli_issue_iocb_s4 is used by other functions in the driver to issue
* an iocb command to an HBA with SLI-4 interface spec.
*
* This function is called with hbalock held. The function will return success
* This function is called with ringlock held. The function will return success
* after it successfully submit the iocb to firmware or after adding to the
* txq.
**/
@ -10053,10 +10139,13 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
struct lpfc_iocbq *piocb, uint32_t flag)
{
struct lpfc_sli_ring *pring;
struct lpfc_queue *eq;
unsigned long iflags;
int rc;
if (phba->sli_rev == LPFC_SLI_REV4) {
eq = phba->sli4_hba.hdwq[piocb->hba_wqidx].hba_eq;
pring = lpfc_sli4_calc_ring(phba, piocb);
if (unlikely(pring == NULL))
return IOCB_ERROR;
@ -10064,6 +10153,8 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
spin_lock_irqsave(&pring->ring_lock, iflags);
rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_sli4_poll_eq(eq, LPFC_POLL_FASTPATH);
} else {
/* For now, SLI2/3 will still use hbalock */
spin_lock_irqsave(&phba->hbalock, iflags);
@ -10678,14 +10769,14 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
set_bit(LPFC_DATA_READY, &phba->data_flags);
}
prev_pring_flag = pring->flag;
spin_lock_irq(&pring->ring_lock);
spin_lock(&pring->ring_lock);
list_for_each_entry_safe(iocb, next_iocb,
&pring->txq, list) {
if (iocb->vport != vport)
continue;
list_move_tail(&iocb->list, &completions);
}
spin_unlock_irq(&pring->ring_lock);
spin_unlock(&pring->ring_lock);
list_for_each_entry_safe(iocb, next_iocb,
&pring->txcmplq, list) {
if (iocb->vport != vport)
@ -11050,9 +11141,6 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp->ulpStatus, irsp->un.ulpWord[4]);
spin_unlock_irq(&phba->hbalock);
if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)
lpfc_sli_release_iocbq(phba, abort_iocb);
}
release_iocb:
lpfc_sli_release_iocbq(phba, cmdiocb);
@ -11736,7 +11824,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
!(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) {
lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf,
cur_iocbq);
lpfc_cmd->exch_busy = rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY;
if (rspiocbq && (rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY))
lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
else
lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
}
pdone_q = cmdiocbq->context_un.wait_queue;
@ -13158,13 +13249,19 @@ send_current_mbox:
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
/* Setting active mailbox pointer need to be in sync to flag clear */
phba->sli.mbox_active = NULL;
if (bf_get(lpfc_trailer_consumed, mcqe))
lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq);
spin_unlock_irqrestore(&phba->hbalock, iflags);
/* Wake up worker thread to post the next pending mailbox command */
lpfc_worker_wake_up(phba);
return workposted;
out_no_mqe_complete:
spin_lock_irqsave(&phba->hbalock, iflags);
if (bf_get(lpfc_trailer_consumed, mcqe))
lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq);
return workposted;
spin_unlock_irqrestore(&phba->hbalock, iflags);
return false;
}
/**
@ -13217,7 +13314,6 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
struct lpfc_sli_ring *pring = cq->pring;
int txq_cnt = 0;
int txcmplq_cnt = 0;
int fcp_txcmplq_cnt = 0;
/* Check for response status */
if (unlikely(bf_get(lpfc_wcqe_c_status, wcqe))) {
@ -13239,9 +13335,8 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
txcmplq_cnt++;
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d "
"fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n",
"els_txcmplq_cnt=%d\n",
txq_cnt, phba->iocb_cnt,
fcp_txcmplq_cnt,
txcmplq_cnt);
return false;
}
@ -13592,6 +13687,7 @@ __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq,
phba->sli4_hba.sli4_write_cq_db(phba, cq, consumed,
LPFC_QUEUE_NOARM);
consumed = 0;
cq->assoc_qp->q_flag |= HBA_EQ_DELAY_CHK;
}
if (count == LPFC_NVMET_CQ_NOTIFY)
@ -14220,7 +14316,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
spin_lock_irqsave(&phba->hbalock, iflag);
if (phba->link_state < LPFC_LINK_DOWN)
/* Flush, clear interrupt, and rearm the EQ */
lpfc_sli4_eq_flush(phba, fpeq);
lpfc_sli4_eqcq_flush(phba, fpeq);
spin_unlock_irqrestore(&phba->hbalock, iflag);
return IRQ_NONE;
}
@ -14230,14 +14326,14 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
fpeq->last_cpu = raw_smp_processor_id();
if (icnt > LPFC_EQD_ISR_TRIGGER &&
phba->cfg_irq_chann == 1 &&
fpeq->q_flag & HBA_EQ_DELAY_CHK &&
phba->cfg_auto_imax &&
fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY &&
phba->sli.sli_flag & LPFC_SLI_USE_EQDR)
lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY);
/* process and rearm the EQ */
ecount = lpfc_sli4_process_eq(phba, fpeq);
ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM);
if (unlikely(ecount == 0)) {
fpeq->EQ_no_entry++;
@ -14297,6 +14393,147 @@ lpfc_sli4_intr_handler(int irq, void *dev_id)
return (hba_handled == true) ? IRQ_HANDLED : IRQ_NONE;
} /* lpfc_sli4_intr_handler */
void lpfc_sli4_poll_hbtimer(struct timer_list *t)
{
struct lpfc_hba *phba = from_timer(phba, t, cpuhp_poll_timer);
struct lpfc_queue *eq;
int i = 0;
rcu_read_lock();
list_for_each_entry_rcu(eq, &phba->poll_list, _poll_list)
i += lpfc_sli4_poll_eq(eq, LPFC_POLL_SLOWPATH);
if (!list_empty(&phba->poll_list))
mod_timer(&phba->cpuhp_poll_timer,
jiffies + msecs_to_jiffies(LPFC_POLL_HB));
rcu_read_unlock();
}
inline int lpfc_sli4_poll_eq(struct lpfc_queue *eq, uint8_t path)
{
struct lpfc_hba *phba = eq->phba;
int i = 0;
/*
* Unlocking an irq is one of the entry point to check
* for re-schedule, but we are good for io submission
* path as midlayer does a get_cpu to glue us in. Flush
* out the invalidate queue so we can see the updated
* value for flag.
*/
smp_rmb();
if (READ_ONCE(eq->mode) == LPFC_EQ_POLL)
/* We will not likely get the completion for the caller
* during this iteration but i guess that's fine.
* Future io's coming on this eq should be able to
* pick it up. As for the case of single io's, they
* will be handled through a sched from polling timer
* function which is currently triggered every 1msec.
*/
i = lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM);
return i;
}
static inline void lpfc_sli4_add_to_poll_list(struct lpfc_queue *eq)
{
struct lpfc_hba *phba = eq->phba;
if (list_empty(&phba->poll_list)) {
timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
/* kickstart slowpath processing for this eq */
mod_timer(&phba->cpuhp_poll_timer,
jiffies + msecs_to_jiffies(LPFC_POLL_HB));
}
list_add_rcu(&eq->_poll_list, &phba->poll_list);
synchronize_rcu();
}
static inline void lpfc_sli4_remove_from_poll_list(struct lpfc_queue *eq)
{
struct lpfc_hba *phba = eq->phba;
/* Disable slowpath processing for this eq. Kick start the eq
* by RE-ARMING the eq's ASAP
*/
list_del_rcu(&eq->_poll_list);
synchronize_rcu();
if (list_empty(&phba->poll_list))
del_timer_sync(&phba->cpuhp_poll_timer);
}
void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba)
{
struct lpfc_queue *eq, *next;
list_for_each_entry_safe(eq, next, &phba->poll_list, _poll_list)
list_del(&eq->_poll_list);
INIT_LIST_HEAD(&phba->poll_list);
synchronize_rcu();
}
static inline void
__lpfc_sli4_switch_eqmode(struct lpfc_queue *eq, uint8_t mode)
{
if (mode == eq->mode)
return;
/*
* currently this function is only called during a hotplug
* event and the cpu on which this function is executing
* is going offline. By now the hotplug has instructed
* the scheduler to remove this cpu from cpu active mask.
* So we don't need to work about being put aside by the
* scheduler for a high priority process. Yes, the inte-
* rrupts could come but they are known to retire ASAP.
*/
/* Disable polling in the fastpath */
WRITE_ONCE(eq->mode, mode);
/* flush out the store buffer */
smp_wmb();
/*
* Add this eq to the polling list and start polling. For
* a grace period both interrupt handler and poller will
* try to process the eq _but_ that's fine. We have a
* synchronization mechanism in place (queue_claimed) to
* deal with it. This is just a draining phase for int-
* errupt handler (not eq's) as we have guranteed through
* barrier that all the CPUs have seen the new CQ_POLLED
* state. which will effectively disable the REARMING of
* the EQ. The whole idea is eq's die off eventually as
* we are not rearming EQ's anymore.
*/
mode ? lpfc_sli4_add_to_poll_list(eq) :
lpfc_sli4_remove_from_poll_list(eq);
}
void lpfc_sli4_start_polling(struct lpfc_queue *eq)
{
__lpfc_sli4_switch_eqmode(eq, LPFC_EQ_POLL);
}
void lpfc_sli4_stop_polling(struct lpfc_queue *eq)
{
struct lpfc_hba *phba = eq->phba;
__lpfc_sli4_switch_eqmode(eq, LPFC_EQ_INTERRUPT);
/* Kick start for the pending io's in h/w.
* Once we switch back to interrupt processing on a eq
* the io path completion will only arm eq's when it
* receives a completion. But since eq's are in disa-
* rmed state it doesn't receive a completion. This
* creates a deadlock scenaro.
*/
phba->sli4_hba.sli4_write_eq_db(phba, eq, 0, LPFC_QUEUE_REARM);
}
/**
* lpfc_sli4_queue_free - free a queue structure and associated memory
* @queue: The queue structure to free.
@ -14371,6 +14608,7 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size,
return NULL;
INIT_LIST_HEAD(&queue->list);
INIT_LIST_HEAD(&queue->_poll_list);
INIT_LIST_HEAD(&queue->wq_list);
INIT_LIST_HEAD(&queue->wqfull_list);
INIT_LIST_HEAD(&queue->page_list);
@ -18124,8 +18362,9 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba)
phba->sli4_hba.max_cfg_param.rpi_used++;
phba->sli4_hba.rpi_count++;
}
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"0001 rpi:%x max:%x lim:%x\n",
lpfc_printf_log(phba, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"0001 Allocated rpi:x%x max:x%x lim:x%x\n",
(int) rpi, max_rpi, rpi_limit);
/*
@ -18181,11 +18420,19 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba)
static void
__lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi)
{
/*
* if the rpi value indicates a prior unreg has already
* been done, skip the unreg.
*/
if (rpi == LPFC_RPI_ALLOC_ERROR)
return;
if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) {
phba->sli4_hba.rpi_count--;
phba->sli4_hba.max_cfg_param.rpi_used--;
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
lpfc_printf_log(phba, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"2016 rpi %x not inuse\n",
rpi);
}
@ -19683,6 +19930,8 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
lpfc_sli_ringtxcmpl_put(phba, pring, pwqe);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_sli4_poll_eq(qp->hba_eq, LPFC_POLL_FASTPATH);
return 0;
}
@ -19703,6 +19952,8 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
}
lpfc_sli_ringtxcmpl_put(phba, pring, pwqe);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_sli4_poll_eq(qp->hba_eq, LPFC_POLL_FASTPATH);
return 0;
}
@ -19731,6 +19982,8 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
}
lpfc_sli_ringtxcmpl_put(phba, pring, pwqe);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_sli4_poll_eq(qp->hba_eq, LPFC_POLL_FASTPATH);
return 0;
}
return WQE_ERROR;
@ -20093,6 +20346,13 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd,
lpfc_ncmd->cur_iocbq.wqe_cmpl = NULL;
lpfc_ncmd->cur_iocbq.iocb_cmpl = NULL;
if (phba->cfg_xpsgl && !phba->nvmet_support &&
!list_empty(&lpfc_ncmd->dma_sgl_xtra_list))
lpfc_put_sgl_per_hdwq(phba, lpfc_ncmd);
if (!list_empty(&lpfc_ncmd->dma_cmd_rsp_list))
lpfc_put_cmd_rsp_buf_per_hdwq(phba, lpfc_ncmd);
if (phba->cfg_xri_rebalancing) {
if (lpfc_ncmd->expedite) {
/* Return to expedite pool */
@ -20157,13 +20417,6 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd,
spin_unlock_irqrestore(&qp->io_buf_list_put_lock,
iflag);
}
if (phba->cfg_xpsgl && !phba->nvmet_support &&
!list_empty(&lpfc_ncmd->dma_sgl_xtra_list))
lpfc_put_sgl_per_hdwq(phba, lpfc_ncmd);
if (!list_empty(&lpfc_ncmd->dma_cmd_rsp_list))
lpfc_put_cmd_rsp_buf_per_hdwq(phba, lpfc_ncmd);
}
/**
@ -20399,8 +20652,9 @@ lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
struct sli4_hybrid_sgl *allocated_sgl = NULL;
struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq;
struct list_head *buf_list = &hdwq->sgl_list;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
if (likely(!list_empty(buf_list))) {
/* break off 1 chunk from the sgl_list */
@ -20412,9 +20666,9 @@ lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
}
} else {
/* allocate more */
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
tmp = kmalloc_node(sizeof(*tmp), GFP_ATOMIC,
cpu_to_node(smp_processor_id()));
cpu_to_node(hdwq->io_wq->chann));
if (!tmp) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"8353 error kmalloc memory for HDWQ "
@ -20434,7 +20688,7 @@ lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
return NULL;
}
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
list_add_tail(&tmp->list_node, &lpfc_buf->dma_sgl_xtra_list);
}
@ -20442,7 +20696,7 @@ lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
struct sli4_hybrid_sgl,
list_node);
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
return allocated_sgl;
}
@ -20466,8 +20720,9 @@ lpfc_put_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
struct sli4_hybrid_sgl *tmp = NULL;
struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq;
struct list_head *buf_list = &hdwq->sgl_list;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
if (likely(!list_empty(&lpfc_buf->dma_sgl_xtra_list))) {
list_for_each_entry_safe(list_entry, tmp,
@ -20480,7 +20735,7 @@ lpfc_put_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf)
rc = -EINVAL;
}
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
return rc;
}
@ -20501,8 +20756,9 @@ lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba,
struct list_head *buf_list = &hdwq->sgl_list;
struct sli4_hybrid_sgl *list_entry = NULL;
struct sli4_hybrid_sgl *tmp = NULL;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
/* Free sgl pool */
list_for_each_entry_safe(list_entry, tmp,
@ -20514,7 +20770,7 @@ lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba,
kfree(list_entry);
}
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
}
/**
@ -20538,8 +20794,9 @@ lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
struct fcp_cmd_rsp_buf *allocated_buf = NULL;
struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq;
struct list_head *buf_list = &hdwq->cmd_rsp_buf_list;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
if (likely(!list_empty(buf_list))) {
/* break off 1 chunk from the list */
@ -20552,9 +20809,9 @@ lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
}
} else {
/* allocate more */
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
tmp = kmalloc_node(sizeof(*tmp), GFP_ATOMIC,
cpu_to_node(smp_processor_id()));
cpu_to_node(hdwq->io_wq->chann));
if (!tmp) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"8355 error kmalloc memory for HDWQ "
@ -20579,7 +20836,7 @@ lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
tmp->fcp_rsp = (struct fcp_rsp *)((uint8_t *)tmp->fcp_cmnd +
sizeof(struct fcp_cmnd));
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
list_add_tail(&tmp->list_node, &lpfc_buf->dma_cmd_rsp_list);
}
@ -20587,7 +20844,7 @@ lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
struct fcp_cmd_rsp_buf,
list_node);
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
return allocated_buf;
}
@ -20612,8 +20869,9 @@ lpfc_put_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
struct fcp_cmd_rsp_buf *tmp = NULL;
struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq;
struct list_head *buf_list = &hdwq->cmd_rsp_buf_list;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
if (likely(!list_empty(&lpfc_buf->dma_cmd_rsp_list))) {
list_for_each_entry_safe(list_entry, tmp,
@ -20626,7 +20884,7 @@ lpfc_put_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
rc = -EINVAL;
}
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
return rc;
}
@ -20647,8 +20905,9 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
struct list_head *buf_list = &hdwq->cmd_rsp_buf_list;
struct fcp_cmd_rsp_buf *list_entry = NULL;
struct fcp_cmd_rsp_buf *tmp = NULL;
unsigned long iflags;
spin_lock_irq(&hdwq->hdwq_lock);
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
/* Free cmd_rsp buf pool */
list_for_each_entry_safe(list_entry, tmp,
@ -20661,5 +20920,5 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
kfree(list_entry);
}
spin_unlock_irq(&hdwq->hdwq_lock);
spin_unlock_irqrestore(&hdwq->hdwq_lock, iflags);
}

View File

@ -384,14 +384,13 @@ struct lpfc_io_buf {
struct lpfc_nodelist *ndlp;
uint32_t timeout;
uint16_t flags; /* TBD convert exch_busy to flags */
uint16_t flags;
#define LPFC_SBUF_XBUSY 0x1 /* SLI4 hba reported XB on WCQE cmpl */
#define LPFC_SBUF_BUMP_QDEPTH 0x2 /* bumped queue depth counter */
/* External DIF device IO conversions */
#define LPFC_SBUF_NORMAL_DIF 0x4 /* normal mode to insert/strip */
#define LPFC_SBUF_PASS_DIF 0x8 /* insert/strip mode to passthru */
#define LPFC_SBUF_NOT_POSTED 0x10 /* SGL failed post to FW. */
uint16_t exch_busy; /* SLI4 hba reported XB on complete WCQE */
uint16_t status; /* From IOCB Word 7- ulpStatus */
uint32_t result; /* From IOCB Word 4. */

View File

@ -41,8 +41,13 @@
/* Multi-queue arrangement for FCP EQ/CQ/WQ tuples */
#define LPFC_HBA_HDWQ_MIN 0
#define LPFC_HBA_HDWQ_MAX 128
#define LPFC_HBA_HDWQ_DEF 0
#define LPFC_HBA_HDWQ_MAX 256
#define LPFC_HBA_HDWQ_DEF LPFC_HBA_HDWQ_MIN
/* irq_chann range, values */
#define LPFC_IRQ_CHANN_MIN 0
#define LPFC_IRQ_CHANN_MAX 256
#define LPFC_IRQ_CHANN_DEF LPFC_IRQ_CHANN_MIN
/* FCP MQ queue count limiting */
#define LPFC_FCP_MQ_THRESHOLD_MIN 0
@ -133,6 +138,23 @@ struct lpfc_rqb {
struct lpfc_queue {
struct list_head list;
struct list_head wq_list;
/*
* If interrupts are in effect on _all_ the eq's the footprint
* of polling code is zero (except mode). This memory is chec-
* ked for every io to see if the io needs to be polled and
* while completion to check if the eq's needs to be rearmed.
* Keep in same cacheline as the queue ptr to avoid cpu fetch
* stalls. Using 1B memory will leave us with 7B hole. Fill
* it with other frequently used members.
*/
uint16_t last_cpu; /* most recent cpu */
uint16_t hdwq;
uint8_t qe_valid;
uint8_t mode; /* interrupt or polling */
#define LPFC_EQ_INTERRUPT 0
#define LPFC_EQ_POLL 1
struct list_head wqfull_list;
enum lpfc_sli4_queue_type type;
enum lpfc_sli4_queue_subtype subtype;
@ -199,6 +221,7 @@ struct lpfc_queue {
uint8_t q_flag;
#define HBA_NVMET_WQFULL 0x1 /* We hit WQ Full condition for NVMET */
#define HBA_NVMET_CQ_NOTIFY 0x1 /* LPFC_NVMET_CQ_NOTIFY CQEs this EQE */
#define HBA_EQ_DELAY_CHK 0x2 /* EQ is a candidate for coalescing */
#define LPFC_NVMET_CQ_NOTIFY 4
void __iomem *db_regaddr;
uint16_t dpp_enable;
@ -239,10 +262,8 @@ struct lpfc_queue {
struct delayed_work sched_spwork;
uint64_t isr_timestamp;
uint16_t hdwq;
uint16_t last_cpu; /* most recent cpu */
uint8_t qe_valid;
struct lpfc_queue *assoc_qp;
struct list_head _poll_list;
void **q_pgs; /* array to index entries per page */
};
@ -451,11 +472,17 @@ struct lpfc_hba;
#define LPFC_SLI4_HANDLER_NAME_SZ 16
struct lpfc_hba_eq_hdl {
uint32_t idx;
uint16_t irq;
char handler_name[LPFC_SLI4_HANDLER_NAME_SZ];
struct lpfc_hba *phba;
struct lpfc_queue *eq;
struct cpumask aff_mask;
};
#define lpfc_get_eq_hdl(eqidx) (&phba->sli4_hba.hba_eq_hdl[eqidx])
#define lpfc_get_aff_mask(eqidx) (&phba->sli4_hba.hba_eq_hdl[eqidx].aff_mask)
#define lpfc_get_irq(eqidx) (phba->sli4_hba.hba_eq_hdl[eqidx].irq)
/*BB Credit recovery value*/
struct lpfc_bbscn_params {
uint32_t word0;
@ -513,6 +540,7 @@ struct lpfc_pc_sli4_params {
uint8_t cqav;
uint8_t wqsize;
uint8_t bv1s;
uint8_t pls;
#define LPFC_WQ_SZ64_SUPPORT 1
#define LPFC_WQ_SZ128_SUPPORT 2
uint8_t wqpcnt;
@ -544,11 +572,10 @@ struct lpfc_sli4_lnk_info {
#define LPFC_SLI4_HANDLER_CNT (LPFC_HBA_IO_CHAN_MAX+ \
LPFC_FOF_IO_CHAN_NUM)
/* Used for IRQ vector to CPU mapping */
/* Used for tracking CPU mapping attributes */
struct lpfc_vector_map_info {
uint16_t phys_id;
uint16_t core_id;
uint16_t irq;
uint16_t eq;
uint16_t hdwq;
uint16_t flag;
@ -891,6 +918,7 @@ struct lpfc_sli4_hba {
struct lpfc_vector_map_info *cpu_map;
uint16_t num_possible_cpu;
uint16_t num_present_cpu;
struct cpumask numa_mask;
uint16_t curr_disp_cpu;
struct lpfc_eq_intr_info __percpu *eq_info;
uint32_t conf_trunk;

View File

@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "12.4.0.0"
#define LPFC_DRIVER_VERSION "12.6.0.2"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */

View File

@ -464,7 +464,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev)
mac_scsi_template.can_queue = setup_can_queue;
if (setup_cmd_per_lun > 0)
mac_scsi_template.cmd_per_lun = setup_cmd_per_lun;
if (setup_sg_tablesize >= 0)
if (setup_sg_tablesize > 0)
mac_scsi_template.sg_tablesize = setup_sg_tablesize;
if (setup_hostid >= 0)
mac_scsi_template.this_id = setup_hostid & 7;

View File

@ -24,6 +24,8 @@
#define MEGASAS_VERSION "07.710.50.00-rc1"
#define MEGASAS_RELDATE "June 28, 2019"
#define MEGASAS_MSIX_NAME_LEN 32
/*
* Device IDs
*/
@ -2203,6 +2205,7 @@ struct megasas_aen_event {
};
struct megasas_irq_context {
char name[MEGASAS_MSIX_NAME_LEN];
struct megasas_instance *instance;
u32 MSIxIndex;
u32 os_irq;

View File

@ -5546,9 +5546,11 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance)
pdev = instance->pdev;
instance->irq_context[0].instance = instance;
instance->irq_context[0].MSIxIndex = 0;
snprintf(instance->irq_context->name, MEGASAS_MSIX_NAME_LEN, "%s%u",
"megasas", instance->host->host_no);
if (request_irq(pci_irq_vector(pdev, 0),
instance->instancet->service_isr, IRQF_SHARED,
"megasas", &instance->irq_context[0])) {
instance->irq_context->name, &instance->irq_context[0])) {
dev_err(&instance->pdev->dev,
"Failed to register IRQ from %s %d\n",
__func__, __LINE__);
@ -5580,8 +5582,10 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
for (i = 0; i < instance->msix_vectors; i++) {
instance->irq_context[i].instance = instance;
instance->irq_context[i].MSIxIndex = i;
snprintf(instance->irq_context[i].name, MEGASAS_MSIX_NAME_LEN, "%s%u-msix%u",
"megasas", instance->host->host_no, i);
if (request_irq(pci_irq_vector(pdev, i),
instance->instancet->service_isr, 0, "megasas",
instance->instancet->service_isr, 0, instance->irq_context[i].name,
&instance->irq_context[i])) {
dev_err(&instance->pdev->dev,
"Failed to register IRQ for vector %d.\n", i);

View File

@ -386,9 +386,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
le64_to_cpu(quad->logEnd) && (mega_mod64(row - le64_to_cpu(quad->logStart),
le32_to_cpu(quad->diff))) == 0) {
if (span_blk != NULL) {
u64 blk, debugBlk;
u64 blk;
blk = mega_div64_32((row-le64_to_cpu(quad->logStart)), le32_to_cpu(quad->diff));
debugBlk = blk;
blk = (blk + le64_to_cpu(quad->offsetInSpan)) << raid->stripeShift;
*span_blk = blk;
@ -699,9 +698,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
__le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
u32 logArm, rowMod, armQ, arm;
struct fusion_context *fusion;
fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
/*Get row and span from io_info for Uneven Span IO.*/
@ -801,9 +798,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
struct fusion_context *fusion;
fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
row = mega_div64_32(stripRow, raid->rowDataSize);

View File

@ -3044,11 +3044,11 @@ _base_alloc_irq_vectors(struct MPT3SAS_ADAPTER *ioc)
descp = NULL;
ioc_info(ioc, " %d %d\n", ioc->high_iops_queues,
ioc->msix_vector_count);
ioc->reply_queue_count);
i = pci_alloc_irq_vectors_affinity(ioc->pdev,
ioc->high_iops_queues,
ioc->msix_vector_count, irq_flags, descp);
ioc->reply_queue_count, irq_flags, descp);
return i;
}
@ -4242,10 +4242,12 @@ _base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc)
static int
_base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc)
{
Mpi2FWImageHeader_t *FWImgHdr;
Mpi2FWImageHeader_t *fw_img_hdr;
Mpi26ComponentImageHeader_t *cmp_img_hdr;
Mpi25FWUploadRequest_t *mpi_request;
Mpi2FWUploadReply_t mpi_reply;
int r = 0;
u32 package_version = 0;
void *fwpkg_data = NULL;
dma_addr_t fwpkg_data_dma;
u16 smid, ioc_status;
@ -4302,14 +4304,26 @@ _base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc)
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
FWImgHdr = (Mpi2FWImageHeader_t *)fwpkg_data;
if (FWImgHdr->PackageVersion.Word) {
ioc_info(ioc, "FW Package Version (%02d.%02d.%02d.%02d)\n",
FWImgHdr->PackageVersion.Struct.Major,
FWImgHdr->PackageVersion.Struct.Minor,
FWImgHdr->PackageVersion.Struct.Unit,
FWImgHdr->PackageVersion.Struct.Dev);
}
fw_img_hdr = (Mpi2FWImageHeader_t *)fwpkg_data;
if (le32_to_cpu(fw_img_hdr->Signature) ==
MPI26_IMAGE_HEADER_SIGNATURE0_MPI26) {
cmp_img_hdr =
(Mpi26ComponentImageHeader_t *)
(fwpkg_data);
package_version =
le32_to_cpu(
cmp_img_hdr->ApplicationSpecific);
} else
package_version =
le32_to_cpu(
fw_img_hdr->PackageVersion.Word);
if (package_version)
ioc_info(ioc,
"FW Package Ver(%02d.%02d.%02d.%02d)\n",
((package_version) & 0xFF000000) >> 24,
((package_version) & 0x00FF0000) >> 16,
((package_version) & 0x0000FF00) >> 8,
(package_version) & 0x000000FF);
} else {
_debug_dump_mf(&mpi_reply,
sizeof(Mpi2FWUploadReply_t)/4);

View File

@ -76,8 +76,8 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
#define MPT3SAS_DRIVER_VERSION "31.100.00.00"
#define MPT3SAS_MAJOR_VERSION 31
#define MPT3SAS_DRIVER_VERSION "32.100.00.00"
#define MPT3SAS_MAJOR_VERSION 32
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@ -303,6 +303,8 @@ struct mpt3sas_nvme_cmd {
#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01)
#define MPT3_DIAG_BUFFER_IS_RELEASED (0x02)
#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
#define MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED (0x08)
#define MPT3_DIAG_BUFFER_IS_APP_OWNED (0x10)
/*
* HP HBA branding
@ -391,9 +393,12 @@ struct Mpi2ManufacturingPage11_t {
u8 Reserved6; /* 2Fh */
__le32 Reserved7[7]; /* 30h - 4Bh */
u8 NVMeAbortTO; /* 4Ch */
u8 Reserved8; /* 4Dh */
u16 Reserved9; /* 4Eh */
__le32 Reserved10[4]; /* 50h - 60h */
u8 NumPerDevEvents; /* 4Dh */
u8 HostTraceBufferDecrementSizeKB; /* 4Eh */
u8 HostTraceBufferFlags; /* 4Fh */
u16 HostTraceBufferMaxSizeKB; /* 50h */
u16 HostTraceBufferMinSizeKB; /* 52h */
__le32 Reserved10[2]; /* 54h - 5Bh */
};
/**

View File

@ -466,6 +466,13 @@ void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc)
if ((ioc->diag_buffer_status[i] &
MPT3_DIAG_BUFFER_IS_RELEASED))
continue;
/*
* add a log message to indicate the release
*/
ioc_info(ioc,
"%s: Releasing the trace buffer due to adapter reset.",
__func__);
mpt3sas_send_diag_release(ioc, i, &issue_reset);
}
}
@ -778,6 +785,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
case MPI2_FUNCTION_NVME_ENCAPSULATED:
{
nvme_encap_request = (Mpi26NVMeEncapsulatedRequest_t *)request;
if (!ioc->pcie_sg_lookup) {
dtmprintk(ioc, ioc_info(ioc,
"HBA doesn't support NVMe. Rejecting NVMe Encapsulated request.\n"
));
if (ioc->logging_level & MPT_DEBUG_TM)
_debug_dump_mf(nvme_encap_request,
ioc->request_sz/4);
mpt3sas_base_free_smid(ioc, smid);
ret = -EINVAL;
goto out;
}
/*
* Get the Physical Address of the sense buffer.
* Use Error Response buffer address field to hold the sense
@ -1484,6 +1503,26 @@ _ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type)
return rc;
}
/**
* _ctl_diag_get_bufftype - return diag buffer type
* either TRACE, SNAPSHOT, or EXTENDED
* @ioc: per adapter object
* @unique_id: specifies the unique_id for the buffer
*
* returns MPT3_DIAG_UID_NOT_FOUND if the id not found
*/
static u8
_ctl_diag_get_bufftype(struct MPT3SAS_ADAPTER *ioc, u32 unique_id)
{
u8 index;
for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
if (ioc->unique_id[index] == unique_id)
return index;
}
return MPT3_DIAG_UID_NOT_FOUND;
}
/**
* _ctl_diag_register_2 - wrapper for registering diag buffer support
@ -1531,11 +1570,88 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
return -EPERM;
}
if (diag_register->unique_id == 0) {
ioc_err(ioc,
"%s: Invalid UID(0x%08x), buffer_type(0x%02x)\n", __func__,
diag_register->unique_id, buffer_type);
return -EINVAL;
}
if ((ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_APP_OWNED) &&
!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_RELEASED)) {
ioc_err(ioc,
"%s: buffer_type(0x%02x) is already registered by application with UID(0x%08x)\n",
__func__, buffer_type, ioc->unique_id[buffer_type]);
return -EINVAL;
}
if (ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED) {
ioc_err(ioc, "%s: already has a registered buffer for buffer_type(0x%02x)\n",
__func__, buffer_type);
return -EINVAL;
/*
* If driver posts buffer initially, then an application wants
* to Register that buffer (own it) without Releasing first,
* the application Register command MUST have the same buffer
* type and size in the Register command (obtained from the
* Query command). Otherwise that Register command will be
* failed. If the application has released the buffer but wants
* to re-register it, it should be allowed as long as the
* Unique-Id/Size match.
*/
if (ioc->unique_id[buffer_type] == MPT3DIAGBUFFUNIQUEID &&
ioc->diag_buffer_sz[buffer_type] ==
diag_register->requested_buffer_size) {
if (!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_RELEASED)) {
dctlprintk(ioc, ioc_info(ioc,
"%s: diag_buffer (%d) ownership changed. old-ID(0x%08x), new-ID(0x%08x)\n",
__func__, buffer_type,
ioc->unique_id[buffer_type],
diag_register->unique_id));
/*
* Application wants to own the buffer with
* the same size.
*/
ioc->unique_id[buffer_type] =
diag_register->unique_id;
rc = 0; /* success */
goto out;
}
} else if (ioc->unique_id[buffer_type] !=
MPT3DIAGBUFFUNIQUEID) {
if (ioc->unique_id[buffer_type] !=
diag_register->unique_id ||
ioc->diag_buffer_sz[buffer_type] !=
diag_register->requested_buffer_size ||
!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_RELEASED)) {
ioc_err(ioc,
"%s: already has a registered buffer for buffer_type(0x%02x)\n",
__func__, buffer_type);
return -EINVAL;
}
} else {
ioc_err(ioc, "%s: already has a registered buffer for buffer_type(0x%02x)\n",
__func__, buffer_type);
return -EINVAL;
}
} else if (ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED) {
if (ioc->unique_id[buffer_type] != MPT3DIAGBUFFUNIQUEID ||
ioc->diag_buffer_sz[buffer_type] !=
diag_register->requested_buffer_size) {
ioc_err(ioc,
"%s: already a buffer is allocated for buffer_type(0x%02x) of size %d bytes, so please try registering again with same size\n",
__func__, buffer_type,
ioc->diag_buffer_sz[buffer_type]);
return -EINVAL;
}
}
if (diag_register->requested_buffer_size % 4) {
@ -1560,7 +1676,8 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
request_data = ioc->diag_buffer[buffer_type];
request_data_sz = diag_register->requested_buffer_size;
ioc->unique_id[buffer_type] = diag_register->unique_id;
ioc->diag_buffer_status[buffer_type] = 0;
ioc->diag_buffer_status[buffer_type] &=
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
memcpy(ioc->product_specific[buffer_type],
diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
@ -1584,7 +1701,8 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
ioc_err(ioc, "%s: failed allocating memory for diag buffers, requested size(%d)\n",
__func__, request_data_sz);
mpt3sas_base_free_smid(ioc, smid);
return -ENOMEM;
rc = -ENOMEM;
goto out;
}
ioc->diag_buffer[buffer_type] = request_data;
ioc->diag_buffer_sz[buffer_type] = request_data_sz;
@ -1649,9 +1767,12 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
out:
if (rc && request_data)
if (rc && request_data) {
dma_free_coherent(&ioc->pdev->dev, request_data_sz,
request_data, request_data_dma);
ioc->diag_buffer_status[buffer_type] &=
~MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
}
ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
return rc;
@ -1669,6 +1790,10 @@ void
mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
{
struct mpt3_diag_register diag_register;
u32 ret_val;
u32 trace_buff_size = ioc->manu_pg11.HostTraceBufferMaxSizeKB<<10;
u32 min_trace_buff_size = 0;
u32 decr_trace_buff_size = 0;
memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
@ -1677,10 +1802,68 @@ mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
ioc->diag_trigger_master.MasterData =
(MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
/* register for 2MB buffers */
diag_register.requested_buffer_size = 2 * (1024 * 1024);
diag_register.unique_id = 0x7075900;
_ctl_diag_register_2(ioc, &diag_register);
diag_register.unique_id =
(ioc->hba_mpi_version_belonged == MPI2_VERSION) ?
(MPT2DIAGBUFFUNIQUEID):(MPT3DIAGBUFFUNIQUEID);
if (trace_buff_size != 0) {
diag_register.requested_buffer_size = trace_buff_size;
min_trace_buff_size =
ioc->manu_pg11.HostTraceBufferMinSizeKB<<10;
decr_trace_buff_size =
ioc->manu_pg11.HostTraceBufferDecrementSizeKB<<10;
if (min_trace_buff_size > trace_buff_size) {
/* The buff size is not set correctly */
ioc_err(ioc,
"Min Trace Buff size (%d KB) greater than Max Trace Buff size (%d KB)\n",
min_trace_buff_size>>10,
trace_buff_size>>10);
ioc_err(ioc,
"Using zero Min Trace Buff Size\n");
min_trace_buff_size = 0;
}
if (decr_trace_buff_size == 0) {
/*
* retry the min size if decrement
* is not available.
*/
decr_trace_buff_size =
trace_buff_size - min_trace_buff_size;
}
} else {
/* register for 2MB buffers */
diag_register.requested_buffer_size = 2 * (1024 * 1024);
}
do {
ret_val = _ctl_diag_register_2(ioc, &diag_register);
if (ret_val == -ENOMEM && min_trace_buff_size &&
(trace_buff_size - decr_trace_buff_size) >=
min_trace_buff_size) {
/* adjust the buffer size */
trace_buff_size -= decr_trace_buff_size;
diag_register.requested_buffer_size =
trace_buff_size;
} else
break;
} while (true);
if (ret_val == -ENOMEM)
ioc_err(ioc,
"Cannot allocate trace buffer memory. Last memory tried = %d KB\n",
diag_register.requested_buffer_size>>10);
else if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE]
& MPT3_DIAG_BUFFER_IS_REGISTERED) {
ioc_err(ioc, "Trace buffer memory %d KB allocated\n",
diag_register.requested_buffer_size>>10);
if (ioc->hba_mpi_version_belonged != MPI2_VERSION)
ioc->diag_buffer_status[
MPI2_DIAG_BUF_TYPE_TRACE] |=
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
}
}
if (bits_to_register & 2) {
@ -1723,6 +1906,12 @@ _ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
}
rc = _ctl_diag_register_2(ioc, &karg);
if (!rc && (ioc->diag_buffer_status[karg.buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED))
ioc->diag_buffer_status[karg.buffer_type] |=
MPT3_DIAG_BUFFER_IS_APP_OWNED;
return rc;
}
@ -1752,7 +1941,13 @@ _ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
buffer_type = karg.unique_id & 0x000000ff;
buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
__func__, karg.unique_id);
return -EINVAL;
}
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@ -1785,12 +1980,21 @@ _ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
return -ENOMEM;
}
request_data_sz = ioc->diag_buffer_sz[buffer_type];
request_data_dma = ioc->diag_buffer_dma[buffer_type];
dma_free_coherent(&ioc->pdev->dev, request_data_sz,
request_data, request_data_dma);
ioc->diag_buffer[buffer_type] = NULL;
ioc->diag_buffer_status[buffer_type] = 0;
if (ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED) {
ioc->unique_id[buffer_type] = MPT3DIAGBUFFUNIQUEID;
ioc->diag_buffer_status[buffer_type] &=
~MPT3_DIAG_BUFFER_IS_APP_OWNED;
ioc->diag_buffer_status[buffer_type] &=
~MPT3_DIAG_BUFFER_IS_REGISTERED;
} else {
request_data_sz = ioc->diag_buffer_sz[buffer_type];
request_data_dma = ioc->diag_buffer_dma[buffer_type];
dma_free_coherent(&ioc->pdev->dev, request_data_sz,
request_data, request_data_dma);
ioc->diag_buffer[buffer_type] = NULL;
ioc->diag_buffer_status[buffer_type] = 0;
}
return 0;
}
@ -1829,14 +2033,17 @@ _ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
return -EPERM;
}
if ((ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
__func__, buffer_type);
return -EINVAL;
if (!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED)) {
if ((ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
__func__, buffer_type);
return -EINVAL;
}
}
if (karg.unique_id & 0xffffff00) {
if (karg.unique_id) {
if (karg.unique_id != ioc->unique_id[buffer_type]) {
ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
__func__, karg.unique_id);
@ -1851,13 +2058,21 @@ _ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
return -ENOMEM;
}
if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
MPT3_APP_FLAGS_BUFFER_VALID);
else
karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
MPT3_APP_FLAGS_BUFFER_VALID |
MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
if ((ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED))
karg.application_flags |= MPT3_APP_FLAGS_BUFFER_VALID;
if (!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_RELEASED))
karg.application_flags |= MPT3_APP_FLAGS_FW_BUFFER_ACCESS;
if (!(ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED))
karg.application_flags |= MPT3_APP_FLAGS_DYNAMIC_BUFFER_ALLOC;
if ((ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_APP_OWNED))
karg.application_flags |= MPT3_APP_FLAGS_APP_OWNED;
for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
karg.product_specific[i] =
@ -2002,7 +2217,13 @@ _ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
buffer_type = karg.unique_id & 0x000000ff;
buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
__func__, karg.unique_id);
return -EINVAL;
}
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@ -2026,7 +2247,7 @@ _ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
MPT3_DIAG_BUFFER_IS_RELEASED) {
ioc_err(ioc, "%s: buffer_type(0x%02x) is already released\n",
__func__, buffer_type);
return 0;
return -EINVAL;
}
request_data = ioc->diag_buffer[buffer_type];
@ -2086,7 +2307,13 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
buffer_type = karg.unique_id & 0x000000ff;
buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
__func__, karg.unique_id);
return -EINVAL;
}
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@ -2210,6 +2437,8 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
ioc->diag_buffer_status[buffer_type] |=
MPT3_DIAG_BUFFER_IS_REGISTERED;
ioc->diag_buffer_status[buffer_type] &=
~MPT3_DIAG_BUFFER_IS_RELEASED;
dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
} else {
ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
@ -3130,10 +3359,49 @@ host_trace_buffer_enable_store(struct device *cdev,
memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
ioc_info(ioc, "posting host trace buffers\n");
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
diag_register.requested_buffer_size = (1024 * 1024);
diag_register.unique_id = 0x7075900;
if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0 &&
ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0) {
/* post the same buffer allocated previously */
diag_register.requested_buffer_size =
ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE];
} else {
/*
* Free the diag buffer memory which was previously
* allocated by an application.
*/
if ((ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0)
&&
(ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
MPT3_DIAG_BUFFER_IS_APP_OWNED)) {
pci_free_consistent(ioc->pdev,
ioc->diag_buffer_sz[
MPI2_DIAG_BUF_TYPE_TRACE],
ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE],
ioc->diag_buffer_dma[
MPI2_DIAG_BUF_TYPE_TRACE]);
ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE] =
NULL;
}
diag_register.requested_buffer_size = (1024 * 1024);
}
diag_register.unique_id =
(ioc->hba_mpi_version_belonged == MPI2_VERSION) ?
(MPT2DIAGBUFFUNIQUEID):(MPT3DIAGBUFFUNIQUEID);
ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
_ctl_diag_register_2(ioc, &diag_register);
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
MPT3_DIAG_BUFFER_IS_REGISTERED) {
ioc_info(ioc,
"Trace buffer %d KB allocated through sysfs\n",
diag_register.requested_buffer_size>>10);
if (ioc->hba_mpi_version_belonged != MPI2_VERSION)
ioc->diag_buffer_status[
MPI2_DIAG_BUF_TYPE_TRACE] |=
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
}
} else if (!strcmp(str, "release")) {
/* exit out if host buffers are already released */
if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
@ -3702,12 +3970,6 @@ mpt3sas_ctl_exit(ushort hbas_to_enumerate)
for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
if (!ioc->diag_buffer[i])
continue;
if (!(ioc->diag_buffer_status[i] &
MPT3_DIAG_BUFFER_IS_REGISTERED))
continue;
if ((ioc->diag_buffer_status[i] &
MPT3_DIAG_BUFFER_IS_RELEASED))
continue;
dma_free_coherent(&ioc->pdev->dev,
ioc->diag_buffer_sz[i],
ioc->diag_buffer[i],

View File

@ -95,6 +95,14 @@
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
struct mpt3_diag_read_buffer)
/* Trace Buffer default UniqueId */
#define MPT2DIAGBUFFUNIQUEID (0x07075900)
#define MPT3DIAGBUFFUNIQUEID (0x4252434D)
/* UID not found */
#define MPT3_DIAG_UID_NOT_FOUND (0xFF)
/**
* struct mpt3_ioctl_header - main header structure
* @ioc_number - IOC unit number
@ -310,6 +318,7 @@ struct mpt3_ioctl_btdh_mapping {
#define MPT3_APP_FLAGS_APP_OWNED (0x0001)
#define MPT3_APP_FLAGS_BUFFER_VALID (0x0002)
#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
#define MPT3_APP_FLAGS_DYNAMIC_BUFFER_ALLOC (0x0008)
/* flags for mpt3_diag_read_buffer */
#define MPT3_FLAGS_REREGISTER (0x0001)

View File

@ -5161,7 +5161,7 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
/* insert into event log */
sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
sizeof(Mpi2EventDataSasDeviceStatusChange_t);
event_reply = kzalloc(sz, GFP_KERNEL);
event_reply = kzalloc(sz, GFP_ATOMIC);
if (!event_reply) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
@ -10193,6 +10193,8 @@ scsih_scan_start(struct Scsi_Host *shost)
int rc;
if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
else if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0)
mpt3sas_enable_diag_buffer(ioc, 1);
if (disable_discovery > 0)
return;

View File

@ -113,15 +113,21 @@ mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
{
u8 issue_reset = 0;
u32 *trig_data = (u32 *)&event_data->u.master;
dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__));
/* release the diag buffer trace */
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
dTriggerDiagPrintk(ioc,
ioc_info(ioc, "%s: release trace diag buffer\n",
__func__));
/*
* add a log message so that user knows which event caused
* the release
*/
ioc_info(ioc,
"%s: Releasing the trace buffer. Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n",
__func__, event_data->trigger_type,
trig_data[0], trig_data[1]);
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
&issue_reset);
}

View File

@ -1541,7 +1541,7 @@ out:
int mvs_abort_task_set(struct domain_device *dev, u8 *lun)
{
int rc = TMF_RESP_FUNC_FAILED;
int rc;
struct mvs_tmf_task tmf_task;
tmf_task.tmf = TMF_ABORT_TASK_SET;

View File

@ -1722,7 +1722,7 @@ struct ncb {
** Miscellaneous configuration and status parameters.
**----------------------------------------------------------------
*/
u_char disc; /* Diconnection allowed */
u_char disc; /* Disconnection allowed */
u_char scsi_mode; /* Current SCSI BUS mode */
u_char order; /* Tag order to use */
u_char verbose; /* Verbosity for this controller*/

View File

@ -1542,7 +1542,7 @@ static void nsp32_scsi_done(struct scsi_cmnd *SCpnt)
* with ACK reply when below condition is matched:
* MsgIn 00: Command Complete.
* MsgIn 02: Save Data Pointer.
* MsgIn 04: Diconnect.
* MsgIn 04: Disconnect.
* In other case, unexpected BUSFREE is detected.
*/
static int nsp32_busfree_occur(struct scsi_cmnd *SCpnt, unsigned short execph)

View File

@ -32,7 +32,7 @@ config PCMCIA_FDOMAIN
config PCMCIA_NINJA_SCSI
tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
depends on !64BIT
depends on !64BIT || COMPILE_TEST
help
If you intend to attach this type of PCMCIA SCSI host adapter to
your computer, say Y here and read

View File

@ -56,9 +56,7 @@
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#include "nsp_io.h"

View File

@ -69,6 +69,25 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
static
DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
/**
* controller_fatal_error_show - check controller is under fatal err
* @cdev: pointer to embedded class device
* @buf: the buffer returned
*
* A sysfs 'read only' shost attribute.
*/
static ssize_t controller_fatal_error_show(struct device *cdev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(cdev);
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
return snprintf(buf, PAGE_SIZE, "%d\n",
pm8001_ha->controller_fatal_error);
}
static DEVICE_ATTR_RO(controller_fatal_error);
/**
* pm8001_ctl_fw_version_show - firmware version
* @cdev: pointer to embedded class device
@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
pm8001_show_update_fw, pm8001_store_update_fw);
struct device_attribute *pm8001_host_attrs[] = {
&dev_attr_interface_rev,
&dev_attr_controller_fatal_error,
&dev_attr_fw_version,
&dev_attr_update_fw,
&dev_attr_aap_log,

View File

@ -1336,10 +1336,13 @@ int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
* @circularQ: the inbound queue we want to transfer to HBA.
* @opCode: the operation code represents commands which LLDD and fw recognized.
* @payload: the command payload of each operation command.
* @nb: size in bytes of the command payload
* @responseQueue: queue to interrupt on w/ command response (if any)
*/
int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
struct inbound_queue_table *circularQ,
u32 opCode, void *payload, u32 responseQueue)
u32 opCode, void *payload, size_t nb,
u32 responseQueue)
{
u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
void *pMessage;
@ -1350,10 +1353,13 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
pm8001_printk("No free mpi buffer\n"));
return -ENOMEM;
}
BUG_ON(!payload);
/*Copy to the payload*/
memcpy(pMessage, payload, (pm8001_ha->iomb_size -
sizeof(struct mpi_msg_hdr)));
if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr)))
nb = pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr);
memcpy(pMessage, payload, nb);
if (nb + sizeof(struct mpi_msg_hdr) < pm8001_ha->iomb_size)
memset(pMessage + nb, 0, pm8001_ha->iomb_size -
(nb + sizeof(struct mpi_msg_hdr)));
/*Build the header*/
Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@ -1364,7 +1370,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
/*Update the PI to the firmware*/
pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
circularQ->pi_offset, circularQ->producer_idx);
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
responseQueue, opCode, circularQ->producer_idx,
circularQ->consumer_index));
@ -1436,6 +1442,10 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
/* read header */
header_tmp = pm8001_read_32(msgHeader);
msgHeader_tmp = cpu_to_le32(header_tmp);
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"outbound opcode msgheader:%x ci=%d pi=%d\n",
msgHeader_tmp, circularQ->consumer_idx,
circularQ->producer_index));
if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) {
if (OPC_OUB_SKIP_ENTRY !=
(le32_to_cpu(msgHeader_tmp) & 0xfff)) {
@ -1604,7 +1614,8 @@ void pm8001_work_fn(struct work_struct *work)
break;
default:
pm8001_printk("...query task failed!!!\n");
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"...query task failed!!!\n"));
break;
});
@ -1758,7 +1769,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
task_abort.tag = cpu_to_le32(ccb_tag);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
sizeof(task_abort), 0);
if (ret)
pm8001_tag_free(pm8001_ha, ccb_tag);
@ -1831,7 +1843,8 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
sizeof(sata_cmd), 0);
if (res) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@ -1890,6 +1903,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
pm8001_printk("SAS Address of IO Failure Drive:"
"%016llx", SAS_ADDR(t->dev->sas_addr)));
if (status)
PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
"status:0x%x, tag:0x%x, task:0x%p\n",
status, tag, t));
switch (status) {
case IO_SUCCESS:
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
@ -2072,7 +2090,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2125,7 +2143,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("port_id = %x,device_id = %x\n",
port_id, dev_id));
switch (event) {
@ -2263,7 +2281,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
pm8001_printk(" IO_XFER_CMD_FRAME_ISSUED\n"));
return;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", event));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2352,6 +2370,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("ts null\n"));
return;
}
if (status)
PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
"status:0x%x, tag:0x%x, task::0x%p\n",
status, tag, t));
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW)) {
@ -2652,7 +2676,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2723,7 +2747,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
PM8001_IO_DBG(pm8001_ha, pm8001_printk(
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
port_id, dev_id, tag, event));
switch (event) {
@ -2872,7 +2896,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->stat = SAS_OPEN_TO;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", event));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2917,9 +2941,13 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
t = ccb->task;
ts = &t->task_status;
pm8001_dev = ccb->device;
if (status)
if (status) {
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("smp IO status 0x%x\n", status));
PM8001_IOERR_DBG(pm8001_ha,
pm8001_printk("status:0x%x, tag:0x%x, task:0x%p\n",
status, tag, t));
}
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
@ -3070,7 +3098,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
@ -3355,7 +3383,8 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
((phyId & 0x0F) << 4) | (port_id & 0x0F));
payload.param0 = cpu_to_le32(param0);
payload.param1 = cpu_to_le32(param1);
pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
}
static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@ -3416,7 +3445,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_get_lrate_mode(phy, link_rate);
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("unknown device type(%x)\n", deviceType));
break;
}
@ -3463,7 +3492,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
" phy id = %d\n", port_id, phy_id));
port->port_state = portstate;
@ -3541,7 +3570,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
default:
port->port_attached = 0;
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk(" phy Down and(default) = %x\n",
portstate));
break;
@ -3689,7 +3718,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
pm8001_printk(": FLASH_UPDATE_DISABLED\n"));
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("No matched status = %d\n", status));
break;
}
@ -3805,8 +3834,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("outbound queue HW event & event type : "));
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n",
port_id, phy_id, eventType, status));
switch (eventType) {
case HW_EVENT_PHY_START_STATUS:
PM8001_MSG_DBG(pm8001_ha,
@ -3990,7 +4020,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown event type = %x\n", eventType));
break;
}
@ -4161,7 +4191,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n"));
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n",
opc));
break;
@ -4284,7 +4314,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
(u32 *)&smp_cmd, 0);
&smp_cmd, sizeof(smp_cmd), 0);
if (rc)
goto err_out_2;
@ -4352,7 +4382,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
ssp_cmd.esgl = 0;
}
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd,
sizeof(ssp_cmd), 0);
return ret;
}
@ -4461,7 +4492,8 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
}
}
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
sizeof(sata_cmd), 0);
return ret;
}
@ -4496,7 +4528,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
memcpy(payload.sas_identify.sas_addr,
pm8001_ha->sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
sizeof(payload), 0);
return ret;
}
@ -4518,7 +4551,8 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
sizeof(payload), 0);
return ret;
}
@ -4577,7 +4611,8 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
return rc;
}
@ -4598,7 +4633,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
payload.device_id = cpu_to_le32(device_id);
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("unregister device device_id = %d\n", device_id));
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
return ret;
}
@ -4621,7 +4657,8 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(1);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
return ret;
}
@ -4649,6 +4686,9 @@ static irqreturn_t
pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
pm8001_chip_interrupt_disable(pm8001_ha, vec);
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"irq vec %d, ODMR:0x%x\n",
vec, pm8001_cr32(pm8001_ha, 0, 0x30)));
process_oq(pm8001_ha, vec);
pm8001_chip_interrupt_enable(pm8001_ha, vec);
return IRQ_HANDLED;
@ -4672,7 +4712,8 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
task_abort.device_id = cpu_to_le32(dev_id);
task_abort.tag = cpu_to_le32(cmd_tag);
}
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
sizeof(task_abort), 0);
return ret;
}
@ -4729,7 +4770,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
if (pm8001_ha->chip_id != chip_8001)
sspTMCmd.ds_ads_m = 0x08;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
sizeof(sspTMCmd), 0);
return ret;
}
@ -4819,7 +4861,8 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
default:
break;
}
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
sizeof(nvmd_req), 0);
if (rc) {
kfree(fw_control_context);
pm8001_tag_free(pm8001_ha, tag);
@ -4903,7 +4946,8 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
default:
break;
}
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
sizeof(nvmd_req), 0);
if (rc) {
kfree(fw_control_context);
pm8001_tag_free(pm8001_ha, tag);
@ -4938,7 +4982,8 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
payload.sgl_addr_hi =
cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
return ret;
}
@ -4960,6 +5005,8 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
if (!fw_control_context)
return -ENOMEM;
fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"dma fw_control context input length :%x\n", fw_control->len));
memcpy(buffer, fw_control->buffer, fw_control->len);
flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
@ -5083,7 +5130,8 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(tag);
payload.device_id = cpu_to_le32(pm8001_dev->device_id);
payload.nds = cpu_to_le32(state);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
return rc;
}
@ -5108,7 +5156,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
payload.SSAHOLT = cpu_to_le32(0xd << 25);
payload.sata_hol_tmo = cpu_to_le32(80);
payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
return rc;

View File

@ -41,6 +41,19 @@
#include <linux/slab.h>
#include "pm8001_sas.h"
#include "pm8001_chips.h"
#include "pm80xx_hwi.h"
static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
module_param(logging_level, ulong, 0644);
MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120;
module_param(link_rate, ulong, 0644);
MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
" 1: Link rate 1.5G\n"
" 2: Link rate 3.0G\n"
" 4: Link rate 6.0G\n"
" 8: Link rate 12.0G\n");
static struct scsi_transport_template *pm8001_stt;
@ -432,7 +445,7 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
} else {
pm8001_ha->io_mem[logicalBar].membase = 0;
pm8001_ha->io_mem[logicalBar].memsize = 0;
pm8001_ha->io_mem[logicalBar].memvirtaddr = 0;
pm8001_ha->io_mem[logicalBar].memvirtaddr = NULL;
}
logicalBar++;
}
@ -466,7 +479,15 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
pm8001_ha->sas = sha;
pm8001_ha->shost = shost;
pm8001_ha->id = pm8001_id++;
pm8001_ha->logging_level = 0x01;
pm8001_ha->logging_level = logging_level;
if (link_rate >= 1 && link_rate <= 15)
pm8001_ha->link_rate = (link_rate << 8);
else {
pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 |
LINKRATE_60 | LINKRATE_120;
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
"Setting link rate to default value\n"));
}
sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
/* IOMB size is 128 for 8088/89 controllers */
if (pm8001_ha->chip_id != chip_8001)
@ -873,7 +894,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
u32 number_of_intr;
int flag = 0;
int rc;
static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
/* SPCv controllers supports 64 msi-x */
if (pm8001_ha->chip_id == chip_8001) {
@ -894,14 +914,16 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
rc, pm8001_ha->number_of_intr));
for (i = 0; i < number_of_intr; i++) {
snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
DRV_NAME"%d", i);
snprintf(pm8001_ha->intr_drvname[i],
sizeof(pm8001_ha->intr_drvname[0]),
"%s-%d", pm8001_ha->name, i);
pm8001_ha->irq_vector[i].irq_id = i;
pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i),
pm8001_interrupt_handler_msix, flag,
intr_drvname[i], &(pm8001_ha->irq_vector[i]));
pm8001_ha->intr_drvname[i],
&(pm8001_ha->irq_vector[i]));
if (rc) {
for (j = 0; j < i; j++) {
free_irq(pci_irq_vector(pm8001_ha->pdev, i),
@ -942,7 +964,7 @@ intx:
pm8001_ha->irq_vector[0].irq_id = 0;
pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
return rc;
}

View File

@ -119,7 +119,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
&mem_dma_handle, GFP_KERNEL);
if (!mem_virt_alloc) {
pm8001_printk("memory allocation error\n");
pr_err("pm80xx: memory allocation error\n");
return -1;
}
*pphys_addr = mem_dma_handle;
@ -249,6 +249,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return 0;
default:
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("func 0x%x\n", func));
rc = -EOPNOTSUPP;
}
msleep(300);
@ -384,8 +386,9 @@ static int pm8001_task_exec(struct sas_task *task,
struct pm8001_port *port = NULL;
struct sas_task *t = task;
struct pm8001_ccb_info *ccb;
u32 tag = 0xdeadbeef, rc, n_elem = 0;
u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
unsigned long flags = 0;
enum sas_protocol task_proto = t->task_proto;
if (!dev->port) {
struct task_status_struct *tsm = &t->task_status;
@ -410,7 +413,7 @@ static int pm8001_task_exec(struct sas_task *task,
pm8001_dev = dev->lldd_dev;
port = &pm8001_ha->port[sas_find_local_port_id(dev)];
if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
if (sas_protocol_ata(task_proto)) {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
@ -432,7 +435,7 @@ static int pm8001_task_exec(struct sas_task *task,
goto err_out;
ccb = &pm8001_ha->ccb_info[tag];
if (!sas_protocol_ata(t->task_proto)) {
if (!sas_protocol_ata(task_proto)) {
if (t->num_scatter) {
n_elem = dma_map_sg(pm8001_ha->dev,
t->scatter,
@ -452,7 +455,7 @@ static int pm8001_task_exec(struct sas_task *task,
ccb->ccb_tag = tag;
ccb->task = t;
ccb->device = pm8001_dev;
switch (t->task_proto) {
switch (task_proto) {
case SAS_PROTOCOL_SMP:
rc = pm8001_task_prep_smp(pm8001_ha, ccb);
break;
@ -469,8 +472,7 @@ static int pm8001_task_exec(struct sas_task *task,
break;
default:
dev_printk(KERN_ERR, pm8001_ha->dev,
"unknown sas_task proto: 0x%x\n",
t->task_proto);
"unknown sas_task proto: 0x%x\n", task_proto);
rc = -EINVAL;
break;
}
@ -493,7 +495,7 @@ err_out_tag:
pm8001_tag_free(pm8001_ha, tag);
err_out:
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
if (!sas_protocol_ata(t->task_proto))
if (!sas_protocol_ata(task_proto))
if (n_elem)
dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
t->data_dir);
@ -1179,7 +1181,7 @@ int pm8001_query_task(struct sas_task *task)
break;
}
}
pm8001_printk(":rc= %d\n", rc);
pr_err("pm80xx: rc= %d\n", rc);
return rc;
}
@ -1202,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
phy_id = pm8001_dev->attached_phy;
rc = pm8001_find_tag(task, &tag);
if (rc == 0) {
ret = pm8001_find_tag(task, &tag);
if (ret == 0) {
pm8001_printk("no tag for task:%p\n", task);
return TMF_RESP_FUNC_FAILED;
}
@ -1241,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)
/* 2. Send Phy Control Hard Reset */
reinit_completion(&completion);
phy->port_reset_status = PORT_RESET_TMO;
phy->reset_success = false;
phy->enable_completion = &completion;
phy->reset_completion = &completion_reset;
ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
PHY_HARD_RESET);
if (ret)
if (ret) {
phy->enable_completion = NULL;
phy->reset_completion = NULL;
goto out;
}
/* In the case of the reset timeout/fail we still
* abort the command at the firmware. The assumption
* here is that the drive is off doing something so
* that it's not processing requests, and we want to
* avoid getting a completion for this and either
* leaking the task in libsas or losing the race and
* getting a double free.
*/
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("Waiting for local phy ctl\n"));
wait_for_completion(&completion);
if (!phy->reset_success)
goto out;
/* 3. Wait for Port Reset complete / Port reset TMO */
PM8001_MSG_DBG(pm8001_ha,
ret = wait_for_completion_timeout(&completion,
PM8001_TASK_TIMEOUT * HZ);
if (!ret || !phy->reset_success) {
phy->enable_completion = NULL;
phy->reset_completion = NULL;
} else {
/* 3. Wait for Port Reset complete or
* Port reset TMO
*/
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("Waiting for Port reset\n"));
wait_for_completion(&completion_reset);
if (phy->port_reset_status) {
pm8001_dev_gone_notify(dev);
goto out;
ret = wait_for_completion_timeout(
&completion_reset,
PM8001_TASK_TIMEOUT * HZ);
if (!ret)
phy->reset_completion = NULL;
WARN_ON(phy->port_reset_status ==
PORT_RESET_TMO);
if (phy->port_reset_status == PORT_RESET_TMO) {
pm8001_dev_gone_notify(dev);
goto out;
}
}
/*

View File

@ -66,8 +66,11 @@
#define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/
#define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */
#define PM8001_MSG_LOGGING 0x40 /* misc message logging */
#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \
format, __func__, __LINE__, ## arg)
#define PM8001_DEV_LOGGING 0x80 /* development message logging */
#define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */
#define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */
#define pm8001_printk(format, arg...) pr_info("%s:: %s %d:" \
format, pm8001_ha->name, __func__, __LINE__, ## arg)
#define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \
do { \
if (unlikely(HBA->logging_level & LEVEL)) \
@ -97,6 +100,14 @@ do { \
#define PM8001_MSG_DBG(HBA, CMD) \
PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD)
#define PM8001_DEV_DBG(HBA, CMD) \
PM8001_CHECK_LOGGING(HBA, PM8001_DEV_LOGGING, CMD)
#define PM8001_DEVIO_DBG(HBA, CMD) \
PM8001_CHECK_LOGGING(HBA, PM8001_DEVIO_LOGGING, CMD)
#define PM8001_IOERR_DBG(HBA, CMD) \
PM8001_CHECK_LOGGING(HBA, PM8001_IOERR_LOGGING, CMD)
#define PM8001_USE_TASKLET
#define PM8001_USE_MSIX
@ -141,6 +152,8 @@ struct pm8001_ioctl_payload {
#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */
#define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */
#define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */
#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18 /* TOTALLEN */
#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C /* SIGNITURE */
#define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1
#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0
#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0
@ -496,6 +509,7 @@ struct pm8001_hba_info {
u32 forensic_last_offset;
u32 fatal_forensic_shift_offset;
u32 forensic_fatal_step;
u32 forensic_preserved_accumulated_transfer;
u32 evtlog_ib_offset;
u32 evtlog_ob_offset;
void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/
@ -530,11 +544,14 @@ struct pm8001_hba_info {
struct pm8001_ccb_info *ccb_info;
#ifdef PM8001_USE_MSIX
int number_of_intr;/*will be used in remove()*/
char intr_drvname[PM8001_MAX_MSIX_VEC]
[PM8001_NAME_LENGTH+1+3+1];
#endif
#ifdef PM8001_USE_TASKLET
struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC];
#endif
u32 logging_level;
u32 link_rate;
u32 fw_status;
u32 smp_exp_mode;
bool controller_fatal_error;
@ -663,7 +680,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
struct inbound_queue_table *circularQ,
u32 opCode, void *payload, u32 responseQueue);
u32 opCode, void *payload, size_t nb,
u32 responseQueue);
int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
u16 messageSize, void **messagePtr);
u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,

View File

@ -37,6 +37,7 @@
* POSSIBILITY OF SUCH DAMAGES.
*
*/
#include <linux/version.h>
#include <linux/slab.h>
#include "pm8001_sas.h"
#include "pm80xx_hwi.h"
@ -75,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
destination1 = (u32 *)destination;
for (index = 0; index < dw_count; index += 4, destination1++) {
offset = (soffset + index / 4);
offset = (soffset + index);
if (offset < (64 * 1024)) {
value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
*destination1 = cpu_to_le32(value);
@ -92,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
u32 accum_len , reg_val, index, *temp;
u32 status = 1;
unsigned long start;
u8 *direct_data;
char *fatal_error_data = buf;
u32 length_to_read;
u32 offset;
pm8001_ha->forensic_info.data_buf.direct_data = buf;
if (pm8001_ha->chip_id == chip_8001) {
@ -104,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
/* initialize variables for very first call from host application */
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("forensic_info TYPE_NON_FATAL..............\n"));
direct_data = (u8 *)fatal_error_data;
pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
pm8001_ha->forensic_info.data_buf.direct_offset = 0;
pm8001_ha->forensic_info.data_buf.read_len = 0;
pm8001_ha->forensic_preserved_accumulated_transfer = 0;
/* Write signature to fatal dump table */
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("ossaHwCB: status1 %d\n", status));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("ossaHwCB: read_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.read_len));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("ossaHwCB: direct_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_len));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("ossaHwCB: direct_offset 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_offset));
}
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
/* start to get data */
/* Program the MEMBASE II Shifting Register with 0x00.*/
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
@ -126,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
/* Read until accum_len is retrived */
accum_len = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n",
accum_len));
/* Determine length of data between previously stored transfer length
* and current accumulated transfer length
*/
length_to_read =
accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n",
length_to_read));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: last_offset 0x%x\n",
pm8001_ha->forensic_last_offset));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: read_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.read_len));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_len));
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_offset));
/* If accumulated length failed to read correctly fail the attempt.*/
if (accum_len == 0xFFFFFFFF) {
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("Possible PCI issue 0x%x not expected\n",
accum_len));
return -EIO;
accum_len));
return status;
}
if (accum_len == 0 || accum_len >= 0x100000) {
/* If accumulated length is zero fail the attempt */
if (accum_len == 0) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 0xFFFFFFFF);
"%08x ", 0xFFFFFFFF);
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
/* Accumulated length is good so start capturing the first data */
temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
if (pm8001_ha->forensic_fatal_step == 0) {
moreData:
/* If data to read is less than SYSFS_OFFSET then reduce the
* length of dataLen
*/
if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
> length_to_read) {
pm8001_ha->forensic_info.data_buf.direct_len =
length_to_read -
pm8001_ha->forensic_last_offset;
} else {
pm8001_ha->forensic_info.data_buf.direct_len =
SYSFS_OFFSET;
}
if (pm8001_ha->forensic_info.data_buf.direct_data) {
/* Data is in bar, copy to host memory */
pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc,
pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
pm8001_ha->forensic_info.data_buf.direct_len ,
1);
pm80xx_pci_mem_copy(pm8001_ha,
pm8001_ha->fatal_bar_loc,
pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
pm8001_ha->forensic_info.data_buf.direct_len, 1);
}
pm8001_ha->fatal_bar_loc +=
pm8001_ha->forensic_info.data_buf.direct_len;
@ -160,21 +219,29 @@ moreData:
pm8001_ha->forensic_info.data_buf.read_len =
pm8001_ha->forensic_info.data_buf.direct_len;
if (pm8001_ha->forensic_last_offset >= accum_len) {
if (pm8001_ha->forensic_last_offset >= length_to_read) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 3);
for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
for (index = 0; index <
(pm8001_ha->forensic_info.data_buf.direct_len
/ 4); index++) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
sprintf(
pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
}
pm8001_ha->fatal_bar_loc = 0;
pm8001_ha->forensic_fatal_step = 1;
pm8001_ha->fatal_forensic_shift_offset = 0;
pm8001_ha->forensic_last_offset = 0;
status = 0;
offset = (int)
((char *)pm8001_ha->forensic_info.data_buf.direct_data
- (char *)buf);
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset));
return (char *)pm8001_ha->
forensic_info.data_buf.direct_data -
(char *)buf;
@ -184,12 +251,20 @@ moreData:
sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", 2);
for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->
for (index = 0; index <
(pm8001_ha->forensic_info.data_buf.direct_len
/ 4); index++) {
pm8001_ha->forensic_info.data_buf.direct_data
+= sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
}
status = 0;
offset = (int)
((char *)pm8001_ha->forensic_info.data_buf.direct_data
- (char *)buf);
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset));
return (char *)pm8001_ha->
forensic_info.data_buf.direct_data -
(char *)buf;
@ -199,63 +274,122 @@ moreData:
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 2);
for (index = 0; index < 256; index++) {
for (index = 0; index <
(pm8001_ha->forensic_info.data_buf.direct_len
/ 4) ; index++) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
}
pm8001_ha->fatal_forensic_shift_offset += 0x100;
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
pm8001_ha->fatal_forensic_shift_offset);
pm8001_ha->fatal_bar_loc = 0;
status = 0;
offset = (int)
((char *)pm8001_ha->forensic_info.data_buf.direct_data
- (char *)buf);
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset));
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
if (pm8001_ha->forensic_fatal_step == 1) {
pm8001_ha->fatal_forensic_shift_offset = 0;
/* Read 64K of the debug data. */
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
pm8001_ha->fatal_forensic_shift_offset);
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
/* store previous accumulated length before triggering next
* accumulated length update
*/
pm8001_ha->forensic_preserved_accumulated_transfer =
pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
/* continue capturing the fatal log until Dump status is 0x3 */
if (pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_STATUS) <
MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
/* reset fddstat bit by writing to zero*/
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
/* set dump control value to '1' so that new data will
* be transferred to shared memory
*/
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
MPI_FATAL_EDUMP_HANDSHAKE_RDY);
/* Poll FDDHSHK until clear */
start = jiffies + (2 * HZ); /* 2 sec */
/*Poll FDDHSHK until clear */
start = jiffies + (2 * HZ); /* 2 sec */
do {
reg_val = pm8001_mr32(fatal_table_address,
do {
reg_val = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
} while ((reg_val) && time_before(jiffies, start));
} while ((reg_val) && time_before(jiffies, start));
if (reg_val != 0) {
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
" = 0x%x\n", reg_val));
return -EIO;
}
if (reg_val != 0) {
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
"TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
reg_val));
/* Fail the dump if a timeout occurs */
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(
pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 0xFFFFFFFF);
return((char *)
pm8001_ha->forensic_info.data_buf.direct_data
- (char *)buf);
}
/* Poll status register until set to 2 or
* 3 for up to 2 seconds
*/
start = jiffies + (2 * HZ); /* 2 sec */
/* Read the next 64K of the debug data. */
pm8001_ha->forensic_fatal_step = 0;
if (pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_STATUS) !=
MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0);
goto moreData;
} else {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", 4);
pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;
pm8001_ha->forensic_info.data_buf.direct_len = 0;
pm8001_ha->forensic_info.data_buf.direct_offset = 0;
pm8001_ha->forensic_info.data_buf.read_len = 0;
do {
reg_val = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_STATUS);
} while (((reg_val != 2) || (reg_val != 3)) &&
time_before(jiffies, start));
if (reg_val < 2) {
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
"TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
reg_val));
/* Fail the dump if a timeout occurs */
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(
pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 0xFFFFFFFF);
pm8001_cw32(pm8001_ha, 0,
MEMBASE_II_SHIFT_REGISTER,
pm8001_ha->fatal_forensic_shift_offset);
}
/* Read the next block of the debug data.*/
length_to_read = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
pm8001_ha->forensic_preserved_accumulated_transfer;
if (length_to_read != 0x0) {
pm8001_ha->forensic_fatal_step = 0;
goto moreData;
} else {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(
pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 4);
pm8001_ha->forensic_info.data_buf.read_len
= 0xFFFFFFFF;
pm8001_ha->forensic_info.data_buf.direct_len
= 0;
pm8001_ha->forensic_info.data_buf.direct_offset
= 0;
pm8001_ha->forensic_info.data_buf.read_len = 0;
}
}
}
offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
- (char *)buf);
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset));
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
@ -317,6 +451,25 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Main cfg table; ila rev:%x Inactive fw rev:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
}
/**
@ -521,6 +674,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_mr32(addressib, (offsetib + 0x18));
pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"IQ %d pi_bar 0x%x pi_offset 0x%x\n", i,
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar,
pm8001_ha->inbnd_q_tbl[i].pi_offset));
}
for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
@ -549,6 +707,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_mr32(addressob, (offsetob + 0x18));
pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0;
pm8001_ha->outbnd_q_tbl[i].producer_index = 0;
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"OQ %d ci_bar 0x%x ci_offset 0x%x\n", i,
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar,
pm8001_ha->outbnd_q_tbl[i].ci_offset));
}
}
@ -582,6 +745,10 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
((pm8001_ha->number_of_intr - 1) << 8);
pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Updated Fatal error interrupt vector 0x%x\n",
pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT)));
pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
@ -591,6 +758,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Programming DW 0x21 in main cfg table with 0x%x\n",
pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET)));
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
@ -629,6 +799,21 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"IQ %d: Element pri size 0x%x\n",
number,
pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"IQ upr base addr 0x%x IQ lwr base addr 0x%x\n",
pm8001_ha->inbnd_q_tbl[number].upper_base_addr,
pm8001_ha->inbnd_q_tbl[number].lower_base_addr));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"CI upper base addr 0x%x CI lower base addr 0x%x\n",
pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr,
pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr));
}
/**
@ -652,6 +837,21 @@ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"OQ %d: Element pri size 0x%x\n",
number,
pm8001_ha->outbnd_q_tbl[number].element_size_cnt));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"OQ upr base addr 0x%x OQ lwr base addr 0x%x\n",
pm8001_ha->outbnd_q_tbl[number].upper_base_addr,
pm8001_ha->outbnd_q_tbl[number].lower_base_addr));
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"PI upper base addr 0x%x PI lower base addr 0x%x\n",
pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr,
pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr));
}
/**
@ -669,9 +869,9 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
/* wait until Inbound DoorBell Clear Register toggled */
if (IS_SPCV_12G(pm8001_ha->pdev)) {
max_wait_count = 4 * 1000 * 1000;/* 4 sec */
max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;
} else {
max_wait_count = 2 * 1000 * 1000;/* 2 sec */
max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;
}
do {
udelay(1);
@ -797,7 +997,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
PM8001_INIT_DBG(pm8001_ha,
PM8001_DEV_DBG(pm8001_ha,
pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n",
offset, value));
pcilogic = (value & 0xFC000000) >> 26;
@ -885,7 +1085,12 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
(THERMAL_ENABLE << 8) | page_code;
payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
payload.cfg_pg[0], payload.cfg_pg[1]));
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
return rc;
@ -967,7 +1172,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
memcpy(&payload.cfg_pg, &SASConfigPage,
sizeof(SASProtocolTimerConfig_t));
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@ -1090,7 +1296,12 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
KEK_MGMT_SUBOP_KEYCARDUPDATE);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"Saving Encryption info to flash. payload 0x%x\n",
payload.new_curidx_ksop));
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@ -1241,7 +1452,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
pm8001_printk("reset register before write : 0x%x\n", regval));
pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
mdelay(500);
msleep(500);
regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
PM8001_INIT_DBG(pm8001_ha,
@ -1443,7 +1654,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
task_abort.tag = cpu_to_le32(ccb_tag);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
sizeof(task_abort), 0);
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("Executing abort task end\n"));
if (ret) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@ -1519,7 +1733,9 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
sizeof(sata_cmd), 0);
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Executing read log end\n"));
if (res) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@ -1570,6 +1786,10 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
"tag::0x%x, status::0x%x task::0x%p\n", tag, status, t));
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW))
@ -1772,7 +1992,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -1826,7 +2046,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
PM8001_IO_DBG(pm8001_ha,
PM8001_IOERR_DBG(pm8001_ha,
pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
port_id, tag, event));
switch (event) {
@ -1963,7 +2183,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
PM8001_IO_DBG(pm8001_ha,
PM8001_IOERR_DBG(pm8001_ha,
pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
/* TBC: used default set values */
ts->resp = SAS_TASK_COMPLETE;
@ -1974,7 +2194,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
return;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", event));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2062,6 +2282,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("ts null\n"));
return;
}
if (unlikely(status))
PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
"status:0x%x, tag:0x%x, task::0x%p\n",
status, tag, t));
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW)) {
@ -2365,7 +2591,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
@ -2382,6 +2608,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("task 0x%p done with io_status 0x%x"
" resp 0x%x stat 0x%x but aborted by upper layer!\n",
t, status, ts->resp, ts->stat));
if (t->slow_task)
complete(&t->slow_task->completion);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@ -2435,7 +2663,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
}
ts = &t->task_status;
PM8001_IO_DBG(pm8001_ha,
PM8001_IOERR_DBG(pm8001_ha,
pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
port_id, tag, event));
switch (event) {
@ -2655,6 +2883,9 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
PM8001_DEV_DBG(pm8001_ha,
pm8001_printk("tag::0x%x status::0x%x\n", tag, status));
switch (status) {
case IO_SUCCESS:
@ -2822,7 +3053,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
PM8001_IO_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
@ -2873,7 +3104,8 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
((phyId & 0xFF) << 24) | (port_id & 0xFF));
payload.param0 = cpu_to_le32(param0);
payload.param1 = cpu_to_le32(param1);
pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
}
static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@ -2964,7 +3196,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_get_lrate_mode(phy, link_rate);
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("unknown device type(%x)\n", deviceType));
break;
}
@ -2984,7 +3216,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
if (pm8001_ha->flags == PM8001F_RUN_TIME)
mdelay(200);/*delay a moment to wait disk to spinup*/
msleep(200);/*delay a moment to wait disk to spinup*/
pm8001_bytes_dmaed(pm8001_ha, phy_id);
}
@ -3013,7 +3245,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"port id %d, phy id %d link_rate %d portstate 0x%x\n",
port_id, phy_id, link_rate, portstate));
@ -3101,7 +3333,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
default:
port->port_attached = 0;
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk(" Phy Down and(default) = 0x%x\n",
portstate));
break;
@ -3130,8 +3362,10 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
if (status == 0) {
phy->phy_state = PHY_LINK_DOWN;
if (pm8001_ha->flags == PM8001F_RUN_TIME &&
phy->enable_completion != NULL)
phy->enable_completion != NULL) {
complete(phy->enable_completion);
phy->enable_completion = NULL;
}
}
return 0;
@ -3191,7 +3425,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct pm8001_port *port = &pm8001_ha->port[port_id];
struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEV_DBG(pm8001_ha,
pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n",
port_id, phy_id, eventType, status));
@ -3376,7 +3610,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
break;
default:
PM8001_MSG_DBG(pm8001_ha,
PM8001_DEVIO_DBG(pm8001_ha,
pm8001_printk("Unknown event type 0x%x\n", eventType));
break;
}
@ -3758,7 +3992,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
ssp_coalesced_comp_resp(pm8001_ha, piomb);
break;
default:
PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
break;
}
@ -3991,8 +4225,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
&smp_cmd, pm8001_ha->smp_exp_mode, length);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
(u32 *)&smp_cmd, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
sizeof(smp_cmd), 0);
if (rc)
goto err_out_2;
return 0;
@ -4200,7 +4434,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
}
q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
&ssp_cmd, q_index);
&ssp_cmd, sizeof(ssp_cmd), q_index);
return ret;
}
@ -4441,7 +4675,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
}
q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
&sata_cmd, q_index);
&sata_cmd, sizeof(sata_cmd), q_index);
return ret;
}
@ -4465,23 +4699,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
/*
** [0:7] PHY Identifier
** [8:11] link rate 1.5G, 3G, 6G
** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
** [14] 0b disable spin up hold; 1b enable spin up hold
** [15] ob no change in current PHY analig setup 1b enable using SPAST
*/
if (!IS_SPCV_12G(pm8001_ha->pdev))
payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
LINKMODE_AUTO | LINKRATE_15 |
LINKRATE_30 | LINKRATE_60 | phy_id);
else
payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
LINKMODE_AUTO | LINKRATE_15 |
LINKRATE_30 | LINKRATE_60 | LINKRATE_120 |
phy_id);
payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);
/* SSC Disable and SAS Analog ST configuration */
/**
payload.ase_sh_lm_slr_phyid =
@ -4494,9 +4714,10 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
&pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
&pm8001_ha->sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
sizeof(payload), 0);
return ret;
}
@ -4518,7 +4739,8 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
sizeof(payload), 0);
return ret;
}
@ -4584,7 +4806,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@ -4614,7 +4837,8 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
}
static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
@ -4641,6 +4865,9 @@ static irqreturn_t
pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
pm80xx_chip_interrupt_disable(pm8001_ha, vec);
PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
"irq vec %d, ODMR:0x%x\n",
vec, pm8001_cr32(pm8001_ha, 0, 0x30)));
process_oq(pm8001_ha, vec);
pm80xx_chip_interrupt_enable(pm8001_ha, vec);
return IRQ_HANDLED;
@ -4669,7 +4896,8 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i));
j++;
}
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
}
@ -4711,7 +4939,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
for (i = 0; i < length; i++)
payload.reserved[i] = cpu_to_le32(*(buf + i));
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);

View File

@ -220,6 +220,9 @@
#define SAS_DOPNRJT_RTRY_TMO 128
#define SAS_COPNRJT_RTRY_TMO 128
#define SPCV_DOORBELL_CLEAR_TIMEOUT (30 * 1000 * 1000) /* 30 sec */
#define SPC_DOORBELL_CLEAR_TIMEOUT (15 * 1000 * 1000) /* 15 sec */
/*
Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128

View File

@ -42,7 +42,7 @@ extern uint qedf_debug;
#define QEDF_LOG_LPORT 0x4000 /* lport logs */
#define QEDF_LOG_ELS 0x8000 /* ELS logs */
#define QEDF_LOG_NPIV 0x10000 /* NPIV logs */
#define QEDF_LOG_SESS 0x20000 /* Conection setup, cleanup */
#define QEDF_LOG_SESS 0x20000 /* Connection setup, cleanup */
#define QEDF_LOG_TID 0x80000 /*
* FW TID context acquire
* free

View File

@ -1926,6 +1926,13 @@ static int qedf_fcoe_reset(struct Scsi_Host *shost)
return 0;
}
static void qedf_get_host_port_id(struct Scsi_Host *shost)
{
struct fc_lport *lport = shost_priv(shost);
fc_host_port_id(shost) = lport->port_id;
}
static struct fc_host_statistics *qedf_fc_get_host_stats(struct Scsi_Host
*shost)
{
@ -1996,6 +2003,7 @@ static struct fc_function_template qedf_fc_transport_fn = {
.show_host_active_fc4s = 1,
.show_host_maxframe_size = 1,
.get_host_port_id = qedf_get_host_port_id,
.show_host_port_id = 1,
.show_host_supported_speeds = 1,
.get_host_speed = fc_get_host_speed,

View File

@ -44,7 +44,7 @@ extern uint qedi_dbg_log;
#define QEDI_LOG_LPORT 0x4000 /* lport logs */
#define QEDI_LOG_ELS 0x8000 /* ELS logs */
#define QEDI_LOG_NPIV 0x10000 /* NPIV logs */
#define QEDI_LOG_SESS 0x20000 /* Conection setup, cleanup */
#define QEDI_LOG_SESS 0x20000 /* Connection setup, cleanup */
#define QEDI_LOG_UIO 0x40000 /* iSCSI UIO logs */
#define QEDI_LOG_TID 0x80000 /* FW TID context acquire,
* free

View File

@ -102,8 +102,10 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
qla8044_idc_lock(ha);
qla82xx_set_reset_owner(vha);
qla8044_idc_unlock(ha);
} else
} else {
ha->fw_dump_mpi = 1;
qla2x00_system_error(vha);
}
break;
case 4:
if (IS_P3P_TYPE(ha)) {

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