2005-04-18 03:04:54 +07:00
|
|
|
/*
|
2005-10-28 01:10:08 +07:00
|
|
|
* QLogic Fibre Channel HBA Driver
|
2014-04-12 03:54:24 +07:00
|
|
|
* Copyright (c) 2003-2014 QLogic Corporation
|
2005-04-18 03:04:54 +07:00
|
|
|
*
|
2005-10-28 01:10:08 +07:00
|
|
|
* See LICENSE.qla2xxx for copyright and licensing details.
|
2005-04-18 03:04:54 +07:00
|
|
|
*/
|
|
|
|
#include "qla_def.h"
|
2012-05-16 01:34:28 +07:00
|
|
|
#include "qla_target.h"
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2007-07-06 03:16:51 +07:00
|
|
|
#include <linux/kthread.h>
|
2005-04-18 04:32:42 +07:00
|
|
|
#include <linux/vmalloc.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 15:04:11 +07:00
|
|
|
#include <linux/slab.h>
|
2008-07-28 09:59:20 +07:00
|
|
|
#include <linux/delay.h>
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2008-01-18 00:02:15 +07:00
|
|
|
static int qla24xx_vport_disable(struct fc_vport *, bool);
|
2010-03-20 07:03:58 +07:00
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
/* SYSFS attributes --------------------------------------------------------- */
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2005-04-18 03:04:54 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2011-08-17 01:31:44 +07:00
|
|
|
int rval = 0;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2012-08-23 01:21:04 +07:00
|
|
|
if (!(ha->fw_dump_reading || ha->mctp_dump_reading))
|
2005-04-18 03:04:54 +07:00
|
|
|
return 0;
|
|
|
|
|
2019-04-03 04:24:28 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
2013-08-27 12:37:28 +07:00
|
|
|
if (IS_P3P_TYPE(ha)) {
|
2011-08-17 01:31:44 +07:00
|
|
|
if (off < ha->md_template_size) {
|
|
|
|
rval = memory_read_from_buffer(buf, count,
|
|
|
|
&off, ha->md_tmplt_hdr, ha->md_template_size);
|
2019-04-03 04:24:28 +07:00
|
|
|
} else {
|
|
|
|
off -= ha->md_template_size;
|
|
|
|
rval = memory_read_from_buffer(buf, count,
|
|
|
|
&off, ha->md_dump, ha->md_dump_size);
|
2011-08-17 01:31:44 +07:00
|
|
|
}
|
2019-04-03 04:24:28 +07:00
|
|
|
} else if (ha->mctp_dumped && ha->mctp_dump_reading) {
|
|
|
|
rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump,
|
2012-08-23 01:21:04 +07:00
|
|
|
MCTP_DUMP_SIZE);
|
2019-04-03 04:24:28 +07:00
|
|
|
} else if (ha->fw_dump_reading) {
|
|
|
|
rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump,
|
2008-07-24 22:31:47 +07:00
|
|
|
ha->fw_dump_len);
|
2019-04-03 04:24:28 +07:00
|
|
|
} else {
|
|
|
|
rval = 0;
|
|
|
|
}
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
return rval;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2005-04-18 03:04:54 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2005-04-18 03:04:54 +07:00
|
|
|
int reading;
|
|
|
|
|
|
|
|
if (off != 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
reading = simple_strtol(buf, NULL, 10);
|
|
|
|
switch (reading) {
|
|
|
|
case 0:
|
2006-06-24 06:10:29 +07:00
|
|
|
if (!ha->fw_dump_reading)
|
|
|
|
break;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x705d,
|
2008-11-07 01:40:19 +07:00
|
|
|
"Firmware dump cleared on (%ld).\n", vha->host_no);
|
2006-06-24 06:10:29 +07:00
|
|
|
|
2013-08-27 12:37:28 +07:00
|
|
|
if (IS_P3P_TYPE(ha)) {
|
2011-08-17 01:31:44 +07:00
|
|
|
qla82xx_md_free(vha);
|
|
|
|
qla82xx_md_prep(vha);
|
|
|
|
}
|
2006-06-24 06:10:29 +07:00
|
|
|
ha->fw_dump_reading = 0;
|
|
|
|
ha->fw_dumped = 0;
|
2005-04-18 03:04:54 +07:00
|
|
|
break;
|
|
|
|
case 1:
|
2006-05-18 05:09:50 +07:00
|
|
|
if (ha->fw_dumped && !ha->fw_dump_reading) {
|
2005-04-18 03:04:54 +07:00
|
|
|
ha->fw_dump_reading = 1;
|
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x705e,
|
2006-06-24 06:10:29 +07:00
|
|
|
"Raw firmware dump ready for read on (%ld).\n",
|
2008-11-07 01:40:19 +07:00
|
|
|
vha->host_no);
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
break;
|
2006-06-24 06:10:29 +07:00
|
|
|
case 2:
|
2008-11-07 01:40:19 +07:00
|
|
|
qla2x00_alloc_fw_dump(vha);
|
2006-06-24 06:10:29 +07:00
|
|
|
break;
|
2008-05-13 12:21:13 +07:00
|
|
|
case 3:
|
2011-08-17 01:31:44 +07:00
|
|
|
if (IS_QLA82XX(ha)) {
|
|
|
|
qla82xx_idc_lock(ha);
|
|
|
|
qla82xx_set_reset_owner(vha);
|
|
|
|
qla82xx_idc_unlock(ha);
|
2013-08-27 12:37:28 +07:00
|
|
|
} else if (IS_QLA8044(ha)) {
|
|
|
|
qla8044_idc_lock(ha);
|
|
|
|
qla82xx_set_reset_owner(vha);
|
|
|
|
qla8044_idc_unlock(ha);
|
2019-09-13 01:09:16 +07:00
|
|
|
} else {
|
|
|
|
ha->fw_dump_mpi = 1;
|
2011-08-17 01:31:44 +07:00
|
|
|
qla2x00_system_error(vha);
|
2019-09-13 01:09:16 +07:00
|
|
|
}
|
2011-08-17 01:31:44 +07:00
|
|
|
break;
|
|
|
|
case 4:
|
2013-08-27 12:37:28 +07:00
|
|
|
if (IS_P3P_TYPE(ha)) {
|
2011-08-17 01:31:44 +07:00
|
|
|
if (ha->md_tmplt_hdr)
|
|
|
|
ql_dbg(ql_dbg_user, vha, 0x705b,
|
|
|
|
"MiniDump supported with this firmware.\n");
|
|
|
|
else
|
|
|
|
ql_dbg(ql_dbg_user, vha, 0x709d,
|
|
|
|
"MiniDump not supported with this firmware.\n");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
2013-08-27 12:37:28 +07:00
|
|
|
if (IS_P3P_TYPE(ha))
|
2011-08-17 01:31:44 +07:00
|
|
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
2008-05-13 12:21:13 +07:00
|
|
|
break;
|
2012-08-23 01:21:04 +07:00
|
|
|
case 6:
|
|
|
|
if (!ha->mctp_dump_reading)
|
|
|
|
break;
|
|
|
|
ql_log(ql_log_info, vha, 0x70c1,
|
|
|
|
"MCTP dump cleared on (%ld).\n", vha->host_no);
|
|
|
|
ha->mctp_dump_reading = 0;
|
|
|
|
ha->mctp_dumped = 0;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
if (ha->mctp_dumped && !ha->mctp_dump_reading) {
|
|
|
|
ha->mctp_dump_reading = 1;
|
|
|
|
ql_log(ql_log_info, vha, 0x70c2,
|
|
|
|
"Raw mctp dump ready for read on (%ld).\n",
|
|
|
|
vha->host_no);
|
|
|
|
}
|
|
|
|
break;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
2011-11-19 00:03:13 +07:00
|
|
|
return count;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_fw_dump_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "fw_dump",
|
|
|
|
.mode = S_IRUSR | S_IWUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.read = qla2x00_sysfs_read_fw_dump,
|
|
|
|
.write = qla2x00_sysfs_write_fw_dump,
|
|
|
|
};
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2005-04-18 03:04:54 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-03-13 01:08:21 +07:00
|
|
|
uint32_t faddr;
|
|
|
|
struct active_regions active_regions = { };
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2008-07-24 22:31:47 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
2005-04-18 03:04:54 +07:00
|
|
|
return 0;
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2019-03-13 01:08:21 +07:00
|
|
|
if (!IS_NOCACHE_VPD_TYPE(ha)) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
goto skip;
|
|
|
|
}
|
|
|
|
|
|
|
|
faddr = ha->flt_region_nvram;
|
|
|
|
if (IS_QLA28XX(ha)) {
|
2019-12-04 05:36:55 +07:00
|
|
|
qla28xx_get_aux_images(vha, &active_regions);
|
2019-03-13 01:08:21 +07:00
|
|
|
if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
|
|
|
|
faddr = ha->flt_region_nvram_sec;
|
|
|
|
}
|
|
|
|
ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
|
2019-03-13 01:08:21 +07:00
|
|
|
skip:
|
2008-07-24 22:31:47 +07:00
|
|
|
return memory_read_from_buffer(buf, count, &off, ha->nvram,
|
|
|
|
ha->nvram_size);
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2005-04-18 03:04:54 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2005-04-18 03:04:54 +07:00
|
|
|
uint16_t cnt;
|
|
|
|
|
2009-03-24 23:08:14 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size ||
|
|
|
|
!ha->isp_ops->write_nvram)
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EINVAL;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
|
|
|
/* Checksum NVRAM. */
|
2007-07-20 05:05:56 +07:00
|
|
|
if (IS_FWI2_CAPABLE(ha)) {
|
2005-07-07 00:31:07 +07:00
|
|
|
uint32_t *iter;
|
|
|
|
uint32_t chksum;
|
|
|
|
|
|
|
|
iter = (uint32_t *)buf;
|
|
|
|
chksum = 0;
|
2016-01-28 00:03:34 +07:00
|
|
|
for (cnt = 0; cnt < ((count >> 2) - 1); cnt++, iter++)
|
|
|
|
chksum += le32_to_cpu(*iter);
|
2005-07-07 00:31:07 +07:00
|
|
|
chksum = ~chksum + 1;
|
|
|
|
*iter = cpu_to_le32(chksum);
|
|
|
|
} else {
|
|
|
|
uint8_t *iter;
|
|
|
|
uint8_t chksum;
|
|
|
|
|
|
|
|
iter = (uint8_t *)buf;
|
|
|
|
chksum = 0;
|
|
|
|
for (cnt = 0; cnt < count - 1; cnt++)
|
|
|
|
chksum += *iter++;
|
|
|
|
chksum = ~chksum + 1;
|
|
|
|
*iter = chksum;
|
|
|
|
}
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2009-03-24 23:08:07 +07:00
|
|
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x705f,
|
2009-03-24 23:08:07 +07:00
|
|
|
"HBA not online, failing NVRAM update.\n");
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
2018-10-19 05:45:43 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2018-09-05 04:19:09 +07:00
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
/* Write NVRAM. */
|
2019-03-13 01:08:18 +07:00
|
|
|
ha->isp_ops->write_nvram(vha, buf, ha->nvram_base, count);
|
|
|
|
ha->isp_ops->read_nvram(vha, ha->nvram, ha->nvram_base,
|
|
|
|
count);
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7060,
|
|
|
|
"Setting ISP_ABORT_NEEDED\n");
|
2009-03-24 23:08:07 +07:00
|
|
|
/* NVRAM settings take effect immediately. */
|
2008-11-07 01:40:19 +07:00
|
|
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
2009-03-24 23:08:07 +07:00
|
|
|
qla2xxx_wake_dpc(vha);
|
|
|
|
qla2x00_wait_for_chip_reset(vha);
|
2007-01-30 01:22:28 +07:00
|
|
|
|
2011-08-17 01:31:53 +07:00
|
|
|
return count;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_nvram_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "nvram",
|
|
|
|
.mode = S_IRUSR | S_IWUSR,
|
|
|
|
},
|
2006-02-01 07:05:12 +07:00
|
|
|
.size = 512,
|
2005-04-18 03:04:54 +07:00
|
|
|
.read = qla2x00_sysfs_read_nvram,
|
|
|
|
.write = qla2x00_sysfs_write_nvram,
|
|
|
|
};
|
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_optrom(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-02-01 07:05:17 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-02-01 07:05:17 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2014-02-26 16:14:56 +07:00
|
|
|
ssize_t rval = 0;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2016-12-24 23:32:46 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
if (ha->optrom_state != QLA_SREADING)
|
2016-12-24 23:32:46 +07:00
|
|
|
goto out;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
|
|
|
|
ha->optrom_region_size);
|
2016-12-24 23:32:46 +07:00
|
|
|
|
|
|
|
out:
|
2014-02-26 16:14:56 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
|
|
|
|
return rval;
|
2006-02-01 07:05:17 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-02-01 07:05:17 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-02-01 07:05:17 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2016-12-24 23:32:46 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
|
|
|
|
if (ha->optrom_state != QLA_SWRITING) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2006-02-01 07:05:17 +07:00
|
|
|
return -EINVAL;
|
2016-12-24 23:32:46 +07:00
|
|
|
}
|
|
|
|
if (off > ha->optrom_region_size) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2006-02-01 07:05:17 +07:00
|
|
|
return -ERANGE;
|
2016-12-24 23:32:46 +07:00
|
|
|
}
|
2007-09-21 04:07:35 +07:00
|
|
|
if (off + count > ha->optrom_region_size)
|
|
|
|
count = ha->optrom_region_size - off;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
|
|
|
memcpy(&ha->optrom_buffer[off], buf, count);
|
2014-02-26 16:14:56 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2006-02-01 07:05:17 +07:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_optrom_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "optrom",
|
|
|
|
.mode = S_IRUSR | S_IWUSR,
|
|
|
|
},
|
2007-07-20 10:37:34 +07:00
|
|
|
.size = 0,
|
2006-02-01 07:05:17 +07:00
|
|
|
.read = qla2x00_sysfs_read_optrom,
|
|
|
|
.write = qla2x00_sysfs_write_optrom,
|
|
|
|
};
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-02-01 07:05:17 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-02-01 07:05:17 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2007-09-21 04:07:35 +07:00
|
|
|
uint32_t start = 0;
|
|
|
|
uint32_t size = ha->optrom_size;
|
|
|
|
int val, valid;
|
2014-02-26 16:14:56 +07:00
|
|
|
ssize_t rval = count;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
|
|
|
if (off)
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EINVAL;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2009-12-16 12:29:46 +07:00
|
|
|
if (unlikely(pci_channel_offline(ha->pdev)))
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EAGAIN;
|
2009-12-16 12:29:46 +07:00
|
|
|
|
2007-09-21 04:07:35 +07:00
|
|
|
if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
if (start > ha->optrom_size)
|
2006-02-01 07:05:17 +07:00
|
|
|
return -EINVAL;
|
2017-08-30 20:30:35 +07:00
|
|
|
if (size > ha->optrom_size - start)
|
|
|
|
size = ha->optrom_size - start;
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2014-02-26 16:14:56 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
2018-09-05 04:19:09 +07:00
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
2006-02-01 07:05:17 +07:00
|
|
|
switch (val) {
|
|
|
|
case 0:
|
|
|
|
if (ha->optrom_state != QLA_SREADING &&
|
2014-02-26 16:14:56 +07:00
|
|
|
ha->optrom_state != QLA_SWRITING) {
|
|
|
|
rval = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2006-02-01 07:05:17 +07:00
|
|
|
ha->optrom_state = QLA_SWAITING;
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7061,
|
2007-09-21 04:07:35 +07:00
|
|
|
"Freeing flash region allocation -- 0x%x bytes.\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
ha->optrom_region_size);
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
vfree(ha->optrom_buffer);
|
|
|
|
ha->optrom_buffer = NULL;
|
|
|
|
break;
|
|
|
|
case 1:
|
2014-02-26 16:14:56 +07:00
|
|
|
if (ha->optrom_state != QLA_SWAITING) {
|
|
|
|
rval = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2007-09-21 04:07:35 +07:00
|
|
|
ha->optrom_region_start = start;
|
2019-04-03 04:24:25 +07:00
|
|
|
ha->optrom_region_size = size;
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
ha->optrom_state = QLA_SREADING;
|
2019-07-18 14:45:18 +07:00
|
|
|
ha->optrom_buffer = vzalloc(ha->optrom_region_size);
|
2006-02-01 07:05:17 +07:00
|
|
|
if (ha->optrom_buffer == NULL) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7062,
|
2006-02-01 07:05:17 +07:00
|
|
|
"Unable to allocate memory for optrom retrieval "
|
2007-09-21 04:07:35 +07:00
|
|
|
"(%x).\n", ha->optrom_region_size);
|
2006-02-01 07:05:17 +07:00
|
|
|
|
|
|
|
ha->optrom_state = QLA_SWAITING;
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -ENOMEM;
|
|
|
|
goto out;
|
2006-02-01 07:05:17 +07:00
|
|
|
}
|
|
|
|
|
2010-05-05 05:01:32 +07:00
|
|
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7063,
|
|
|
|
"HBA not online, failing NVRAM update.\n");
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -EAGAIN;
|
|
|
|
goto out;
|
2010-05-05 05:01:32 +07:00
|
|
|
}
|
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7064,
|
2007-09-21 04:07:35 +07:00
|
|
|
"Reading flash region -- 0x%x/0x%x.\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
ha->optrom_region_start, ha->optrom_region_size);
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
|
2007-09-21 04:07:35 +07:00
|
|
|
ha->optrom_region_start, ha->optrom_region_size);
|
2006-02-01 07:05:17 +07:00
|
|
|
break;
|
|
|
|
case 2:
|
2014-02-26 16:14:56 +07:00
|
|
|
if (ha->optrom_state != QLA_SWAITING) {
|
|
|
|
rval = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2007-09-21 04:07:35 +07:00
|
|
|
/*
|
|
|
|
* We need to be more restrictive on which FLASH regions are
|
|
|
|
* allowed to be updated via user-space. Regions accessible
|
|
|
|
* via this method include:
|
|
|
|
*
|
|
|
|
* ISP21xx/ISP22xx/ISP23xx type boards:
|
|
|
|
*
|
|
|
|
* 0x000000 -> 0x020000 -- Boot code.
|
|
|
|
*
|
|
|
|
* ISP2322/ISP24xx type boards:
|
|
|
|
*
|
|
|
|
* 0x000000 -> 0x07ffff -- Boot code.
|
|
|
|
* 0x080000 -> 0x0fffff -- Firmware.
|
|
|
|
*
|
|
|
|
* ISP25xx type boards:
|
|
|
|
*
|
|
|
|
* 0x000000 -> 0x07ffff -- Boot code.
|
|
|
|
* 0x080000 -> 0x0fffff -- Firmware.
|
|
|
|
* 0x120000 -> 0x12ffff -- VPD and HBA parameters.
|
2019-04-03 04:24:26 +07:00
|
|
|
*
|
|
|
|
* > ISP25xx type boards:
|
|
|
|
*
|
|
|
|
* None -- should go through BSG.
|
2007-09-21 04:07:35 +07:00
|
|
|
*/
|
|
|
|
valid = 0;
|
|
|
|
if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
|
|
|
|
valid = 1;
|
2019-04-03 04:24:26 +07:00
|
|
|
else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
|
2010-04-13 07:59:55 +07:00
|
|
|
valid = 1;
|
2007-09-21 04:07:35 +07:00
|
|
|
if (!valid) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7065,
|
2007-09-21 04:07:35 +07:00
|
|
|
"Invalid start region 0x%x/0x%x.\n", start, size);
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -EINVAL;
|
|
|
|
goto out;
|
2007-09-21 04:07:35 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
ha->optrom_region_start = start;
|
2019-04-03 04:24:25 +07:00
|
|
|
ha->optrom_region_size = size;
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
ha->optrom_state = QLA_SWRITING;
|
2019-07-18 14:45:18 +07:00
|
|
|
ha->optrom_buffer = vzalloc(ha->optrom_region_size);
|
2006-02-01 07:05:17 +07:00
|
|
|
if (ha->optrom_buffer == NULL) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7066,
|
2006-02-01 07:05:17 +07:00
|
|
|
"Unable to allocate memory for optrom update "
|
2011-07-15 02:00:13 +07:00
|
|
|
"(%x)\n", ha->optrom_region_size);
|
2006-02-01 07:05:17 +07:00
|
|
|
|
|
|
|
ha->optrom_state = QLA_SWAITING;
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -ENOMEM;
|
|
|
|
goto out;
|
2006-02-01 07:05:17 +07:00
|
|
|
}
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7067,
|
2007-09-21 04:07:35 +07:00
|
|
|
"Staging flash region write -- 0x%x/0x%x.\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
ha->optrom_region_start, ha->optrom_region_size);
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2006-02-01 07:05:17 +07:00
|
|
|
break;
|
|
|
|
case 3:
|
2014-02-26 16:14:56 +07:00
|
|
|
if (ha->optrom_state != QLA_SWRITING) {
|
|
|
|
rval = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2006-02-01 07:05:17 +07:00
|
|
|
|
2009-03-24 23:08:07 +07:00
|
|
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7068,
|
2009-03-24 23:08:07 +07:00
|
|
|
"HBA not online, failing flash update.\n");
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -EAGAIN;
|
|
|
|
goto out;
|
2009-03-24 23:08:07 +07:00
|
|
|
}
|
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7069,
|
2007-09-21 04:07:35 +07:00
|
|
|
"Writing flash region -- 0x%x/0x%x.\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
ha->optrom_region_start, ha->optrom_region_size);
|
2007-09-21 04:07:35 +07:00
|
|
|
|
2019-10-23 02:36:43 +07:00
|
|
|
rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
|
2007-09-21 04:07:35 +07:00
|
|
|
ha->optrom_region_start, ha->optrom_region_size);
|
2019-10-23 02:36:43 +07:00
|
|
|
if (rval)
|
|
|
|
rval = -EIO;
|
2006-02-01 07:05:17 +07:00
|
|
|
break;
|
2007-09-21 04:07:35 +07:00
|
|
|
default:
|
2014-02-26 16:14:56 +07:00
|
|
|
rval = -EINVAL;
|
2006-02-01 07:05:17 +07:00
|
|
|
}
|
2014-02-26 16:14:56 +07:00
|
|
|
|
|
|
|
out:
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
return rval;
|
2006-02-01 07:05:17 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_optrom_ctl_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "optrom_ctl",
|
|
|
|
.mode = S_IWUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.write = qla2x00_sysfs_write_optrom_ctl,
|
|
|
|
};
|
|
|
|
|
2006-03-10 05:27:34 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-03-10 05:27:34 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-03-10 05:27:34 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2016-01-28 00:03:31 +07:00
|
|
|
uint32_t faddr;
|
2019-03-13 01:08:21 +07:00
|
|
|
struct active_regions active_regions = { };
|
2006-03-10 05:27:34 +07:00
|
|
|
|
2009-12-16 12:29:46 +07:00
|
|
|
if (unlikely(pci_channel_offline(ha->pdev)))
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EAGAIN;
|
2009-12-16 12:29:46 +07:00
|
|
|
|
2008-07-24 22:31:47 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EINVAL;
|
2006-03-10 05:27:34 +07:00
|
|
|
|
2019-03-13 01:08:18 +07:00
|
|
|
if (IS_NOCACHE_VPD_TYPE(ha))
|
|
|
|
goto skip;
|
2016-01-28 00:03:31 +07:00
|
|
|
|
2019-03-13 01:08:18 +07:00
|
|
|
faddr = ha->flt_region_vpd << 2;
|
2016-01-28 00:03:31 +07:00
|
|
|
|
2019-03-13 01:08:21 +07:00
|
|
|
if (IS_QLA28XX(ha)) {
|
|
|
|
qla28xx_get_aux_images(vha, &active_regions);
|
|
|
|
if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
|
|
|
|
faddr = ha->flt_region_vpd_sec << 2;
|
|
|
|
|
|
|
|
ql_dbg(ql_dbg_init, vha, 0x7070,
|
|
|
|
"Loading %s nvram image.\n",
|
|
|
|
active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
|
|
|
|
"primary" : "secondary");
|
|
|
|
}
|
2019-03-13 01:08:18 +07:00
|
|
|
|
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2019-03-13 01:08:18 +07:00
|
|
|
return -EAGAIN;
|
2016-01-28 00:03:31 +07:00
|
|
|
}
|
2019-03-13 01:08:18 +07:00
|
|
|
|
|
|
|
ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2019-03-13 01:08:21 +07:00
|
|
|
|
|
|
|
ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
|
2019-03-13 01:08:18 +07:00
|
|
|
skip:
|
2008-07-24 22:31:47 +07:00
|
|
|
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
|
2006-03-10 05:27:34 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-03-10 05:27:34 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-03-10 05:27:34 +07:00
|
|
|
struct device, kobj)));
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2009-03-24 23:08:09 +07:00
|
|
|
uint8_t *tmp_data;
|
2006-03-10 05:27:34 +07:00
|
|
|
|
2009-12-16 12:29:46 +07:00
|
|
|
if (unlikely(pci_channel_offline(ha->pdev)))
|
|
|
|
return 0;
|
|
|
|
|
2019-02-16 05:37:18 +07:00
|
|
|
if (qla2x00_chip_is_down(vha))
|
|
|
|
return 0;
|
|
|
|
|
2009-03-24 23:08:14 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size ||
|
|
|
|
!ha->isp_ops->write_nvram)
|
2006-03-10 05:27:34 +07:00
|
|
|
return 0;
|
|
|
|
|
2009-03-24 23:08:07 +07:00
|
|
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x706a,
|
2009-03-24 23:08:07 +07:00
|
|
|
"HBA not online, failing VPD update.\n");
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&ha->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2006-03-10 05:27:34 +07:00
|
|
|
/* Write NVRAM. */
|
2019-03-13 01:08:18 +07:00
|
|
|
ha->isp_ops->write_nvram(vha, buf, ha->vpd_base, count);
|
|
|
|
ha->isp_ops->read_nvram(vha, ha->vpd, ha->vpd_base, count);
|
2006-03-10 05:27:34 +07:00
|
|
|
|
2009-03-24 23:08:09 +07:00
|
|
|
/* Update flash version information for 4Gb & above. */
|
2018-09-05 04:19:09 +07:00
|
|
|
if (!IS_FWI2_CAPABLE(ha)) {
|
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EINVAL;
|
2018-09-05 04:19:09 +07:00
|
|
|
}
|
2009-03-24 23:08:09 +07:00
|
|
|
|
|
|
|
tmp_data = vmalloc(256);
|
|
|
|
if (!tmp_data) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x706b,
|
2009-03-24 23:08:09 +07:00
|
|
|
"Unable to allocate memory for VPD information update.\n");
|
2011-08-17 01:31:53 +07:00
|
|
|
return -ENOMEM;
|
2009-03-24 23:08:09 +07:00
|
|
|
}
|
|
|
|
ha->isp_ops->get_flash_version(vha, tmp_data);
|
|
|
|
vfree(tmp_data);
|
2011-08-17 01:31:53 +07:00
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&ha->optrom_mutex);
|
|
|
|
|
2006-03-10 05:27:34 +07:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_vpd_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "vpd",
|
|
|
|
.mode = S_IRUSR | S_IWUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.read = qla2x00_sysfs_read_vpd,
|
|
|
|
.write = qla2x00_sysfs_write_vpd,
|
|
|
|
};
|
|
|
|
|
2006-06-24 06:10:50 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_sfp(struct file *filp, struct kobject *kobj,
|
2007-06-09 12:57:22 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
2006-06-24 06:10:50 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
2006-06-24 06:10:50 +07:00
|
|
|
struct device, kobj)));
|
|
|
|
int rval;
|
|
|
|
|
2017-08-24 05:05:07 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < SFP_DEV_SIZE)
|
2006-06-24 06:10:50 +07:00
|
|
|
return 0;
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2008-02-01 03:33:48 +07:00
|
|
|
return 0;
|
2018-09-05 04:19:09 +07:00
|
|
|
}
|
2011-07-15 02:00:13 +07:00
|
|
|
|
2017-08-24 05:05:07 +07:00
|
|
|
rval = qla2x00_read_sfp_dev(vha, buf, count);
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
|
2017-08-24 05:05:07 +07:00
|
|
|
if (rval)
|
|
|
|
return -EIO;
|
2006-06-24 06:10:50 +07:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_sfp_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "sfp",
|
|
|
|
.mode = S_IRUSR | S_IWUSR,
|
|
|
|
},
|
2017-08-24 05:05:07 +07:00
|
|
|
.size = SFP_DEV_SIZE,
|
2006-06-24 06:10:50 +07:00
|
|
|
.read = qla2x00_sysfs_read_sfp,
|
|
|
|
};
|
|
|
|
|
2009-03-26 22:49:17 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
|
2009-03-26 22:49:17 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
|
|
|
struct device, kobj)));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2010-04-13 07:59:55 +07:00
|
|
|
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
2009-03-26 22:49:17 +07:00
|
|
|
int type;
|
2012-08-23 01:21:03 +07:00
|
|
|
uint32_t idc_control;
|
2013-08-27 12:37:51 +07:00
|
|
|
uint8_t *tmp_data = NULL;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2009-03-26 22:49:17 +07:00
|
|
|
if (off != 0)
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EINVAL;
|
2009-03-26 22:49:17 +07:00
|
|
|
|
|
|
|
type = simple_strtol(buf, NULL, 10);
|
|
|
|
switch (type) {
|
|
|
|
case 0x2025c:
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x706e,
|
|
|
|
"Issuing ISP reset.\n");
|
2009-03-26 22:49:17 +07:00
|
|
|
|
|
|
|
scsi_block_requests(vha->host);
|
2011-08-17 01:31:44 +07:00
|
|
|
if (IS_QLA82XX(ha)) {
|
2012-05-16 01:34:25 +07:00
|
|
|
ha->flags.isp82xx_no_md_cap = 1;
|
2011-08-17 01:31:44 +07:00
|
|
|
qla82xx_idc_lock(ha);
|
|
|
|
qla82xx_set_reset_owner(vha);
|
|
|
|
qla82xx_idc_unlock(ha);
|
2013-08-27 12:37:28 +07:00
|
|
|
} else if (IS_QLA8044(ha)) {
|
|
|
|
qla8044_idc_lock(ha);
|
|
|
|
idc_control = qla8044_rd_reg(ha,
|
|
|
|
QLA8044_IDC_DRV_CTRL);
|
|
|
|
qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
|
|
|
|
(idc_control | GRACEFUL_RESET_BIT1));
|
|
|
|
qla82xx_set_reset_owner(vha);
|
|
|
|
qla8044_idc_unlock(ha);
|
|
|
|
} else {
|
|
|
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
|
|
|
qla2xxx_wake_dpc(vha);
|
2011-08-17 01:31:44 +07:00
|
|
|
}
|
2009-03-26 22:49:17 +07:00
|
|
|
qla2x00_wait_for_chip_reset(vha);
|
|
|
|
scsi_unblock_requests(vha->host);
|
|
|
|
break;
|
|
|
|
case 0x2025d:
|
2012-08-23 01:21:03 +07:00
|
|
|
if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha))
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EPERM;
|
2009-03-26 22:49:17 +07:00
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x706f,
|
|
|
|
"Issuing MPI reset.\n");
|
2009-03-26 22:49:17 +07:00
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
|
2012-08-23 01:21:03 +07:00
|
|
|
uint32_t idc_control;
|
|
|
|
|
|
|
|
qla83xx_idc_lock(vha, 0);
|
|
|
|
__qla83xx_get_idc_control(vha, &idc_control);
|
|
|
|
idc_control |= QLA83XX_IDC_GRACEFUL_RESET;
|
|
|
|
__qla83xx_set_idc_control(vha, idc_control);
|
|
|
|
qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
|
|
|
|
QLA8XXX_DEV_NEED_RESET);
|
|
|
|
qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
|
|
|
|
qla83xx_idc_unlock(vha, 0);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
/* Make sure FC side is not in reset */
|
2019-08-09 10:01:52 +07:00
|
|
|
WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) !=
|
|
|
|
QLA_SUCCESS);
|
2012-08-23 01:21:03 +07:00
|
|
|
|
|
|
|
/* Issue MPI reset */
|
|
|
|
scsi_block_requests(vha->host);
|
|
|
|
if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
|
|
|
|
ql_log(ql_log_warn, vha, 0x7070,
|
|
|
|
"MPI reset failed.\n");
|
|
|
|
scsi_unblock_requests(vha->host);
|
|
|
|
break;
|
|
|
|
}
|
2010-04-13 07:59:55 +07:00
|
|
|
case 0x2025e:
|
2013-08-27 12:37:28 +07:00
|
|
|
if (!IS_P3P_TYPE(ha) || vha != base_vha) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x7071,
|
2017-04-01 04:37:04 +07:00
|
|
|
"FCoE ctx reset not supported.\n");
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EPERM;
|
2010-04-13 07:59:55 +07:00
|
|
|
}
|
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x7072,
|
|
|
|
"Issuing FCoE ctx reset.\n");
|
2010-04-13 07:59:55 +07:00
|
|
|
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
|
|
|
|
qla2xxx_wake_dpc(vha);
|
|
|
|
qla2x00_wait_for_fcoe_ctx_reset(vha);
|
|
|
|
break;
|
2012-08-23 01:21:03 +07:00
|
|
|
case 0x2025f:
|
|
|
|
if (!IS_QLA8031(ha))
|
|
|
|
return -EPERM;
|
|
|
|
ql_log(ql_log_info, vha, 0x70bc,
|
|
|
|
"Disabling Reset by IDC control\n");
|
|
|
|
qla83xx_idc_lock(vha, 0);
|
|
|
|
__qla83xx_get_idc_control(vha, &idc_control);
|
|
|
|
idc_control |= QLA83XX_IDC_RESET_DISABLED;
|
|
|
|
__qla83xx_set_idc_control(vha, idc_control);
|
|
|
|
qla83xx_idc_unlock(vha, 0);
|
|
|
|
break;
|
|
|
|
case 0x20260:
|
|
|
|
if (!IS_QLA8031(ha))
|
|
|
|
return -EPERM;
|
|
|
|
ql_log(ql_log_info, vha, 0x70bd,
|
|
|
|
"Enabling Reset by IDC control\n");
|
|
|
|
qla83xx_idc_lock(vha, 0);
|
|
|
|
__qla83xx_get_idc_control(vha, &idc_control);
|
|
|
|
idc_control &= ~QLA83XX_IDC_RESET_DISABLED;
|
|
|
|
__qla83xx_set_idc_control(vha, idc_control);
|
|
|
|
qla83xx_idc_unlock(vha, 0);
|
|
|
|
break;
|
2013-08-27 12:37:51 +07:00
|
|
|
case 0x20261:
|
|
|
|
ql_dbg(ql_dbg_user, vha, 0x70e0,
|
|
|
|
"Updating cache versions without reset ");
|
|
|
|
|
|
|
|
tmp_data = vmalloc(256);
|
|
|
|
if (!tmp_data) {
|
|
|
|
ql_log(ql_log_warn, vha, 0x70e1,
|
|
|
|
"Unable to allocate memory for VPD information update.\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
ha->isp_ops->get_flash_version(vha, tmp_data);
|
|
|
|
vfree(tmp_data);
|
|
|
|
break;
|
2009-03-26 22:49:17 +07:00
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_reset_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "reset",
|
|
|
|
.mode = S_IWUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.write = qla2x00_sysfs_write_reset,
|
|
|
|
};
|
|
|
|
|
2015-12-18 02:57:00 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_issue_logo(struct file *filp, struct kobject *kobj,
|
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
|
|
|
struct device, kobj)));
|
|
|
|
int type;
|
|
|
|
port_id_t did;
|
|
|
|
|
2018-08-03 03:16:47 +07:00
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (unlikely(pci_channel_offline(vha->hw->pdev)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (qla2x00_chip_is_down(vha))
|
|
|
|
return 0;
|
|
|
|
|
2015-12-18 02:57:00 +07:00
|
|
|
type = simple_strtol(buf, NULL, 10);
|
|
|
|
|
|
|
|
did.b.domain = (type & 0x00ff0000) >> 16;
|
|
|
|
did.b.area = (type & 0x0000ff00) >> 8;
|
|
|
|
did.b.al_pa = (type & 0x000000ff);
|
|
|
|
|
2017-06-02 23:12:01 +07:00
|
|
|
ql_log(ql_log_info, vha, 0xd04d, "portid=%02x%02x%02x done\n",
|
2015-12-18 02:57:00 +07:00
|
|
|
did.b.domain, did.b.area, did.b.al_pa);
|
|
|
|
|
|
|
|
ql_log(ql_log_info, vha, 0x70e4, "%s: %d\n", __func__, type);
|
|
|
|
|
2016-03-31 05:25:21 +07:00
|
|
|
qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, did);
|
2015-12-18 02:57:00 +07:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_issue_logo_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "issue_logo",
|
|
|
|
.mode = S_IWUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.write = qla2x00_issue_logo,
|
|
|
|
};
|
|
|
|
|
2009-06-03 23:55:13 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_xgmac_stats(struct file *filp, struct kobject *kobj,
|
2009-06-03 23:55:13 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
|
|
|
struct device, kobj)));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
int rval;
|
|
|
|
uint16_t actual_size;
|
|
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count > XGMAC_DATA_SIZE)
|
|
|
|
return 0;
|
|
|
|
|
2018-08-03 03:16:47 +07:00
|
|
|
if (unlikely(pci_channel_offline(ha->pdev)))
|
|
|
|
return 0;
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2018-08-03 03:16:47 +07:00
|
|
|
return 0;
|
2018-09-05 04:19:09 +07:00
|
|
|
}
|
2018-08-03 03:16:47 +07:00
|
|
|
|
2009-06-03 23:55:13 +07:00
|
|
|
if (ha->xgmac_data)
|
|
|
|
goto do_read;
|
|
|
|
|
|
|
|
ha->xgmac_data = dma_alloc_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
|
|
|
|
&ha->xgmac_data_dma, GFP_KERNEL);
|
|
|
|
if (!ha->xgmac_data) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7076,
|
2009-06-03 23:55:13 +07:00
|
|
|
"Unable to allocate memory for XGMAC read-data.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
do_read:
|
|
|
|
actual_size = 0;
|
|
|
|
memset(ha->xgmac_data, 0, XGMAC_DATA_SIZE);
|
|
|
|
|
|
|
|
rval = qla2x00_get_xgmac_stats(vha, ha->xgmac_data_dma,
|
|
|
|
XGMAC_DATA_SIZE, &actual_size);
|
2018-09-05 04:19:09 +07:00
|
|
|
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2009-06-03 23:55:13 +07:00
|
|
|
if (rval != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7077,
|
2009-06-03 23:55:13 +07:00
|
|
|
"Unable to read XGMAC data (%x).\n", rval);
|
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
|
2019-04-12 04:53:19 +07:00
|
|
|
count = actual_size > count ? count : actual_size;
|
2009-06-03 23:55:13 +07:00
|
|
|
memcpy(buf, ha->xgmac_data, count);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_xgmac_stats_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "xgmac_stats",
|
|
|
|
.mode = S_IRUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.read = qla2x00_sysfs_read_xgmac_stats,
|
|
|
|
};
|
|
|
|
|
2009-06-03 23:55:14 +07:00
|
|
|
static ssize_t
|
2010-05-13 08:28:57 +07:00
|
|
|
qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj,
|
2009-06-03 23:55:14 +07:00
|
|
|
struct bin_attribute *bin_attr,
|
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
|
|
|
struct device, kobj)));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
int rval;
|
|
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count > DCBX_TLV_DATA_SIZE)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ha->dcbx_tlv)
|
|
|
|
goto do_read;
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2018-08-03 03:16:47 +07:00
|
|
|
return 0;
|
2018-09-05 04:19:09 +07:00
|
|
|
}
|
2018-08-03 03:16:47 +07:00
|
|
|
|
2009-06-03 23:55:14 +07:00
|
|
|
ha->dcbx_tlv = dma_alloc_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
|
|
|
|
&ha->dcbx_tlv_dma, GFP_KERNEL);
|
|
|
|
if (!ha->dcbx_tlv) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7078,
|
2009-06-03 23:55:14 +07:00
|
|
|
"Unable to allocate memory for DCBX TLV read-data.\n");
|
2011-08-17 01:31:53 +07:00
|
|
|
return -ENOMEM;
|
2009-06-03 23:55:14 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
do_read:
|
|
|
|
memset(ha->dcbx_tlv, 0, DCBX_TLV_DATA_SIZE);
|
|
|
|
|
|
|
|
rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma,
|
|
|
|
DCBX_TLV_DATA_SIZE);
|
2018-09-05 04:19:09 +07:00
|
|
|
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
|
2009-06-03 23:55:14 +07:00
|
|
|
if (rval != QLA_SUCCESS) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7079,
|
|
|
|
"Unable to read DCBX TLV (%x).\n", rval);
|
2011-08-17 01:31:53 +07:00
|
|
|
return -EIO;
|
2009-06-03 23:55:14 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(buf, ha->dcbx_tlv, count);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bin_attribute sysfs_dcbx_tlv_attr = {
|
|
|
|
.attr = {
|
|
|
|
.name = "dcbx_tlv",
|
|
|
|
.mode = S_IRUSR,
|
|
|
|
},
|
|
|
|
.size = 0,
|
|
|
|
.read = qla2x00_sysfs_read_dcbx_tlv,
|
|
|
|
};
|
|
|
|
|
2006-10-13 23:33:37 +07:00
|
|
|
static struct sysfs_entry {
|
|
|
|
char *name;
|
|
|
|
struct bin_attribute *attr;
|
2019-03-13 01:08:18 +07:00
|
|
|
int type;
|
2006-10-13 23:33:37 +07:00
|
|
|
} bin_file_entries[] = {
|
|
|
|
{ "fw_dump", &sysfs_fw_dump_attr, },
|
|
|
|
{ "nvram", &sysfs_nvram_attr, },
|
|
|
|
{ "optrom", &sysfs_optrom_attr, },
|
|
|
|
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
|
|
|
|
{ "vpd", &sysfs_vpd_attr, 1 },
|
|
|
|
{ "sfp", &sysfs_sfp_attr, 1 },
|
2009-03-26 22:49:17 +07:00
|
|
|
{ "reset", &sysfs_reset_attr, },
|
2015-12-18 02:57:00 +07:00
|
|
|
{ "issue_logo", &sysfs_issue_logo_attr, },
|
2009-06-03 23:55:13 +07:00
|
|
|
{ "xgmac_stats", &sysfs_xgmac_stats_attr, 3 },
|
2009-06-03 23:55:14 +07:00
|
|
|
{ "dcbx_tlv", &sysfs_dcbx_tlv_attr, 3 },
|
2006-11-28 00:35:42 +07:00
|
|
|
{ NULL },
|
2006-10-13 23:33:37 +07:00
|
|
|
};
|
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
void
|
2008-11-07 01:40:19 +07:00
|
|
|
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct Scsi_Host *host = vha->host;
|
2006-10-13 23:33:37 +07:00
|
|
|
struct sysfs_entry *iter;
|
|
|
|
int ret;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2006-10-13 23:33:37 +07:00
|
|
|
for (iter = bin_file_entries; iter->name; iter++) {
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type && !IS_FWI2_CAPABLE(vha->hw))
|
2006-10-13 23:33:37 +07:00
|
|
|
continue;
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type == 2 && !IS_QLA25XX(vha->hw))
|
2009-03-24 23:08:12 +07:00
|
|
|
continue;
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type == 3 && !(IS_CNA_CAPABLE(vha->hw)))
|
2009-06-03 23:55:13 +07:00
|
|
|
continue;
|
2006-10-13 23:33:37 +07:00
|
|
|
|
|
|
|
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
|
|
|
|
iter->attr);
|
|
|
|
if (ret)
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x00f3,
|
|
|
|
"Unable to create sysfs %s binary attribute (%d).\n",
|
|
|
|
iter->name, ret);
|
|
|
|
else
|
|
|
|
ql_dbg(ql_dbg_init, vha, 0x00f4,
|
2017-06-30 20:47:41 +07:00
|
|
|
"Successfully created sysfs %s binary attribute.\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
iter->name);
|
2006-06-24 06:10:55 +07:00
|
|
|
}
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-10-30 14:38:15 +07:00
|
|
|
qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct Scsi_Host *host = vha->host;
|
2006-10-13 23:33:37 +07:00
|
|
|
struct sysfs_entry *iter;
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2006-10-13 23:33:37 +07:00
|
|
|
|
|
|
|
for (iter = bin_file_entries; iter->name; iter++) {
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type && !IS_FWI2_CAPABLE(ha))
|
2006-10-13 23:33:37 +07:00
|
|
|
continue;
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type == 2 && !IS_QLA25XX(ha))
|
2009-03-24 23:08:12 +07:00
|
|
|
continue;
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type == 3 && !(IS_CNA_CAPABLE(ha)))
|
2009-06-03 23:55:13 +07:00
|
|
|
continue;
|
2019-03-13 01:08:18 +07:00
|
|
|
if (iter->type == 0x27 &&
|
|
|
|
(!IS_QLA27XX(ha) || !IS_QLA28XX(ha)))
|
2014-09-25 16:16:56 +07:00
|
|
|
continue;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2006-06-24 06:10:50 +07:00
|
|
|
sysfs_remove_bin_file(&host->shost_gendev.kobj,
|
2006-10-13 23:33:37 +07:00
|
|
|
iter->attr);
|
2006-06-24 06:10:55 +07:00
|
|
|
}
|
2006-02-01 07:05:07 +07:00
|
|
|
|
2013-10-30 14:38:15 +07:00
|
|
|
if (stop_beacon && ha->beacon_blink_led == 1)
|
2008-11-07 01:40:19 +07:00
|
|
|
ha->isp_ops->beacon_off(vha);
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
2005-08-27 09:09:40 +07:00
|
|
|
/* Scsi_Host attributes. */
|
|
|
|
|
|
|
|
static ssize_t
|
2018-12-22 00:33:45 +07:00
|
|
|
qla2x00_driver_version_show(struct device *dev,
|
2008-02-22 06:13:36 +07:00
|
|
|
struct device_attribute *attr, char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_fw_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
char fw_str[128];
|
2005-08-27 09:09:40 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2014-09-25 16:16:46 +07:00
|
|
|
ha->isp_ops->fw_version_str(vha, fw_str, sizeof(fw_str)));
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2005-08-27 09:09:40 +07:00
|
|
|
uint32_t sn;
|
|
|
|
|
2013-03-28 19:21:23 +07:00
|
|
|
if (IS_QLAFX00(vha->hw)) {
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2013-03-28 19:21:23 +07:00
|
|
|
vha->hw->mr.serial_num);
|
|
|
|
} else if (IS_FWI2_CAPABLE(ha)) {
|
2013-10-30 14:38:19 +07:00
|
|
|
qla2xxx_get_vpd_field(vha, "SN", buf, PAGE_SIZE - 1);
|
|
|
|
return strlen(strcat(buf, "\n"));
|
2008-07-11 06:55:53 +07:00
|
|
|
}
|
2007-10-20 05:59:19 +07:00
|
|
|
|
2005-08-27 09:09:40 +07:00
|
|
|
sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
|
2005-08-27 09:09:40 +07:00
|
|
|
sn % 100000);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "ISP%04X\n", vha->hw->pdev->device);
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2013-03-28 19:21:23 +07:00
|
|
|
|
|
|
|
if (IS_QLAFX00(vha->hw))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2013-03-28 19:21:23 +07:00
|
|
|
vha->hw->mr.hw_version);
|
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
|
2005-08-27 09:09:40 +07:00
|
|
|
ha->product_id[0], ha->product_id[1], ha->product_id[2],
|
|
|
|
ha->product_id[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2013-03-28 19:21:23 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_number);
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2015-07-09 21:25:07 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_desc);
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2005-08-27 09:09:40 +07:00
|
|
|
char pci_info[30];
|
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2019-08-09 10:01:55 +07:00
|
|
|
vha->hw->isp_ops->pci_info_str(vha, pci_info,
|
|
|
|
sizeof(pci_info)));
|
2005-08-27 09:09:40 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-03-18 20:32:28 +07:00
|
|
|
qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-08-27 09:09:40 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2005-08-27 09:09:40 +07:00
|
|
|
int len = 0;
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
if (atomic_read(&vha->loop_state) == LOOP_DOWN ||
|
2010-05-05 05:01:22 +07:00
|
|
|
atomic_read(&vha->loop_state) == LOOP_DEAD ||
|
|
|
|
vha->device_flags & DFLG_NO_CABLE)
|
2013-10-30 14:38:24 +07:00
|
|
|
len = scnprintf(buf, PAGE_SIZE, "Link Down\n");
|
2008-11-07 01:40:19 +07:00
|
|
|
else if (atomic_read(&vha->loop_state) != LOOP_READY ||
|
2018-08-03 03:16:47 +07:00
|
|
|
qla2x00_chip_is_down(vha))
|
2013-10-30 14:38:24 +07:00
|
|
|
len = scnprintf(buf, PAGE_SIZE, "Unknown Link State\n");
|
2005-08-27 09:09:40 +07:00
|
|
|
else {
|
2013-10-30 14:38:24 +07:00
|
|
|
len = scnprintf(buf, PAGE_SIZE, "Link Up - ");
|
2005-08-27 09:09:40 +07:00
|
|
|
|
|
|
|
switch (ha->current_topology) {
|
|
|
|
case ISP_CFG_NL:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Loop\n");
|
2005-08-27 09:09:40 +07:00
|
|
|
break;
|
|
|
|
case ISP_CFG_FL:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
|
2005-08-27 09:09:40 +07:00
|
|
|
break;
|
|
|
|
case ISP_CFG_N:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
2005-08-27 09:09:40 +07:00
|
|
|
"N_Port to N_Port\n");
|
|
|
|
break;
|
|
|
|
case ISP_CFG_F:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
|
2005-08-27 09:09:40 +07:00
|
|
|
break;
|
|
|
|
default:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Loop\n");
|
2005-08-27 09:09:40 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2005-10-28 01:09:48 +07:00
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-10-28 01:09:48 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2005-10-28 01:09:48 +07:00
|
|
|
int len = 0;
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
switch (vha->hw->zio_mode) {
|
2005-10-28 01:09:48 +07:00
|
|
|
case QLA_ZIO_MODE_6:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
|
2005-10-28 01:09:48 +07:00
|
|
|
break;
|
|
|
|
case QLA_ZIO_DISABLED:
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
|
2005-10-28 01:09:48 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_zio_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
2005-10-28 01:09:48 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2005-10-28 01:09:48 +07:00
|
|
|
int val = 0;
|
|
|
|
uint16_t zio_mode;
|
|
|
|
|
2006-03-10 05:27:39 +07:00
|
|
|
if (!IS_ZIO_SUPPORTED(ha))
|
|
|
|
return -ENOTSUPP;
|
|
|
|
|
2005-10-28 01:09:48 +07:00
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2006-03-10 05:27:39 +07:00
|
|
|
if (val)
|
2005-10-28 01:09:48 +07:00
|
|
|
zio_mode = QLA_ZIO_MODE_6;
|
2006-03-10 05:27:39 +07:00
|
|
|
else
|
2005-10-28 01:09:48 +07:00
|
|
|
zio_mode = QLA_ZIO_DISABLED;
|
|
|
|
|
|
|
|
/* Update per-hba values and queue a reset. */
|
|
|
|
if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) {
|
|
|
|
ha->zio_mode = zio_mode;
|
2008-11-07 01:40:19 +07:00
|
|
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
2005-10-28 01:09:48 +07:00
|
|
|
}
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2005-10-28 01:09:48 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2005-10-28 01:09:48 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d us\n", vha->hw->zio_timer * 100);
|
2005-10-28 01:09:48 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
2005-10-28 01:09:48 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2005-10-28 01:09:48 +07:00
|
|
|
int val = 0;
|
|
|
|
uint16_t zio_timer;
|
|
|
|
|
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
if (val > 25500 || val < 100)
|
|
|
|
return -ERANGE;
|
|
|
|
|
|
|
|
zio_timer = (uint16_t)(val / 100);
|
2008-11-07 01:40:19 +07:00
|
|
|
vha->hw->zio_timer = zio_timer;
|
2005-10-28 01:09:48 +07:00
|
|
|
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
2018-09-05 04:19:14 +07:00
|
|
|
static ssize_t
|
|
|
|
qla_zio_threshold_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d exchanges\n",
|
|
|
|
vha->hw->last_zio_threshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla_zio_threshold_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int val = 0;
|
|
|
|
|
|
|
|
if (vha->hw->zio_mode != QLA_ZIO_MODE_6)
|
|
|
|
return -EINVAL;
|
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
2018-09-20 17:02:36 +07:00
|
|
|
if (val < 0 || val > 256)
|
2018-09-05 04:19:14 +07:00
|
|
|
return -ERANGE;
|
|
|
|
|
|
|
|
atomic_set(&vha->hw->zio_threshold, val);
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
2006-02-01 07:05:07 +07:00
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2006-02-01 07:05:07 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2006-02-01 07:05:07 +07:00
|
|
|
int len = 0;
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
if (vha->hw->beacon_blink_led)
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
|
2006-02-01 07:05:07 +07:00
|
|
|
else
|
2013-10-30 14:38:24 +07:00
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
|
2006-02-01 07:05:07 +07:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
2006-02-01 07:05:07 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2006-02-01 07:05:07 +07:00
|
|
|
int val = 0;
|
|
|
|
int rval;
|
|
|
|
|
|
|
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
|
|
|
return -EPERM;
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
2018-08-03 03:16:47 +07:00
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x707a,
|
2006-02-01 07:05:07 +07:00
|
|
|
"Abort ISP active -- ignoring beacon request.\n");
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val)
|
2008-11-07 01:40:19 +07:00
|
|
|
rval = ha->isp_ops->beacon_on(vha);
|
2006-02-01 07:05:07 +07:00
|
|
|
else
|
2008-11-07 01:40:19 +07:00
|
|
|
rval = ha->isp_ops->beacon_off(vha);
|
2006-02-01 07:05:07 +07:00
|
|
|
|
|
|
|
if (rval != QLA_SUCCESS)
|
|
|
|
count = 0;
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
|
2006-02-01 07:05:07 +07:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2007-01-30 01:22:21 +07:00
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_optrom_bios_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2007-01-30 01:22:21 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
|
2007-01-30 01:22:21 +07:00
|
|
|
ha->bios_revision[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_optrom_efi_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2007-01-30 01:22:21 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
|
2007-01-30 01:22:21 +07:00
|
|
|
ha->efi_revision[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_optrom_fcode_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2007-01-30 01:22:21 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
|
2007-01-30 01:22:21 +07:00
|
|
|
ha->fcode_revision[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2008-02-22 06:13:36 +07:00
|
|
|
qla2x00_optrom_fw_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2007-01-30 01:22:21 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
|
2007-01-30 01:22:21 +07:00
|
|
|
ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
|
|
|
|
ha->fw_revision[3]);
|
|
|
|
}
|
|
|
|
|
2010-07-23 17:28:26 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_optrom_gold_fw_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
|
|
|
|
!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2010-07-23 17:28:26 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n",
|
2010-07-23 17:28:26 +07:00
|
|
|
ha->gold_fw_version[0], ha->gold_fw_version[1],
|
|
|
|
ha->gold_fw_version[2], ha->gold_fw_version[3]);
|
|
|
|
}
|
|
|
|
|
2008-07-11 06:55:49 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_total_isp_aborts_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
2012-05-16 01:34:16 +07:00
|
|
|
vha->qla_stats.total_isp_aborts);
|
2008-07-11 06:55:49 +07:00
|
|
|
}
|
|
|
|
|
2010-01-13 04:02:47 +07:00
|
|
|
static ssize_t
|
|
|
|
qla24xx_84xx_fw_version_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
int rval = QLA_SUCCESS;
|
2019-03-13 01:08:18 +07:00
|
|
|
uint16_t status[2] = { 0 };
|
2010-01-13 04:02:47 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2010-05-05 05:01:21 +07:00
|
|
|
if (!IS_QLA84XX(ha))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2010-05-05 05:01:21 +07:00
|
|
|
|
2019-03-13 01:08:18 +07:00
|
|
|
if (!ha->cs84xx->op_fw_version) {
|
2010-05-05 05:01:21 +07:00
|
|
|
rval = qla84xx_verify_chip(vha, status);
|
2010-01-13 04:02:47 +07:00
|
|
|
|
2019-03-13 01:08:18 +07:00
|
|
|
if (!rval && !status[0])
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
|
|
|
(uint32_t)ha->cs84xx->op_fw_version);
|
|
|
|
}
|
2010-01-13 04:02:47 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2010-01-13 04:02:47 +07:00
|
|
|
}
|
|
|
|
|
2019-03-13 01:08:14 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_serdes_version_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
|
|
|
|
ha->serdes_version[0], ha->serdes_version[1],
|
|
|
|
ha->serdes_version[2]);
|
|
|
|
}
|
|
|
|
|
2009-01-06 02:18:11 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2015-08-05 00:37:59 +07:00
|
|
|
if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) &&
|
2019-03-13 01:08:13 +07:00
|
|
|
!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2009-01-06 02:18:11 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
|
2009-01-06 02:18:11 +07:00
|
|
|
ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2],
|
2009-03-24 23:08:03 +07:00
|
|
|
ha->mpi_capabilities);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2012-05-16 01:34:19 +07:00
|
|
|
if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2009-03-24 23:08:03 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
|
2009-03-24 23:08:03 +07:00
|
|
|
ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]);
|
2009-01-06 02:18:11 +07:00
|
|
|
}
|
|
|
|
|
2009-03-24 23:08:11 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_flash_block_size_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size);
|
2009-03-24 23:08:11 +07:00
|
|
|
}
|
|
|
|
|
2009-04-07 12:33:38 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_vlan_id_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
2012-02-10 02:15:34 +07:00
|
|
|
if (!IS_CNA_CAPABLE(vha->hw))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2009-04-07 12:33:38 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id);
|
2009-04-07 12:33:38 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_vn_port_mac_address_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
2012-02-10 02:15:34 +07:00
|
|
|
if (!IS_CNA_CAPABLE(vha->hw))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2009-04-07 12:33:38 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%pMR\n", vha->fcoe_vn_port_mac);
|
2009-04-07 12:33:38 +07:00
|
|
|
}
|
|
|
|
|
2009-06-03 23:55:12 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_fabric_param_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", vha->hw->switch_cap);
|
2009-06-03 23:55:12 +07:00
|
|
|
}
|
|
|
|
|
2010-12-22 07:00:21 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_thermal_temp_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2013-02-08 13:58:03 +07:00
|
|
|
uint16_t temp = 0;
|
2018-09-05 04:19:09 +07:00
|
|
|
int rc;
|
2010-12-22 07:00:21 +07:00
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
2018-08-03 03:16:47 +07:00
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2013-02-08 13:58:03 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x70dc, "ISP reset active.\n");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vha->hw->flags.eeh_busy) {
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2013-02-08 13:58:03 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x70dd, "PCI EEH busy.\n");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
rc = qla2x00_get_thermal_temp(vha, &temp);
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
if (rc == QLA_SUCCESS)
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
|
2010-12-22 07:00:21 +07:00
|
|
|
|
2013-02-08 13:58:03 +07:00
|
|
|
done:
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2010-12-22 07:00:21 +07:00
|
|
|
}
|
|
|
|
|
2009-06-03 23:55:29 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
2009-12-16 12:29:46 +07:00
|
|
|
int rval = QLA_FUNCTION_FAILED;
|
2014-09-25 16:16:48 +07:00
|
|
|
uint16_t state[6];
|
2013-03-28 19:21:23 +07:00
|
|
|
uint32_t pstate;
|
|
|
|
|
|
|
|
if (IS_QLAFX00(vha->hw)) {
|
|
|
|
pstate = qlafx00_fw_state_show(dev, attr, buf);
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "0x%x\n", pstate);
|
2013-03-28 19:21:23 +07:00
|
|
|
}
|
2009-06-03 23:55:29 +07:00
|
|
|
|
2018-09-05 04:19:09 +07:00
|
|
|
mutex_lock(&vha->hw->optrom_mutex);
|
|
|
|
if (qla2x00_chip_is_down(vha)) {
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x707c,
|
|
|
|
"ISP reset active.\n");
|
2018-09-05 04:19:09 +07:00
|
|
|
goto out;
|
|
|
|
} else if (vha->hw->flags.eeh_busy) {
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rval = qla2x00_get_firmware_state(vha, state);
|
|
|
|
mutex_unlock(&vha->hw->optrom_mutex);
|
|
|
|
out:
|
|
|
|
if (rval != QLA_SUCCESS) {
|
2009-06-03 23:55:29 +07:00
|
|
|
memset(state, -1, sizeof(state));
|
2018-09-05 04:19:09 +07:00
|
|
|
rval = qla2x00_get_firmware_state(vha, state);
|
|
|
|
}
|
2009-06-03 23:55:29 +07:00
|
|
|
|
2014-09-25 16:16:48 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
|
|
|
state[0], state[1], state[2], state[3], state[4], state[5]);
|
2009-06-03 23:55:29 +07:00
|
|
|
}
|
|
|
|
|
2012-08-23 01:21:01 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_diag_requests_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
|
|
|
if (!IS_BIDI_CAPABLE(vha->hw))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2012-08-23 01:21:01 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%llu\n", vha->bidi_stats.io_count);
|
2012-08-23 01:21:01 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_diag_megabytes_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
|
|
|
if (!IS_BIDI_CAPABLE(vha->hw))
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
2012-08-23 01:21:01 +07:00
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
2012-08-23 01:21:01 +07:00
|
|
|
vha->bidi_stats.transfer_bytes >> 20);
|
|
|
|
}
|
|
|
|
|
2012-08-23 01:21:02 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_fw_dump_size_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
uint32_t size;
|
|
|
|
|
|
|
|
if (!ha->fw_dumped)
|
|
|
|
size = 0;
|
2014-04-12 03:54:22 +07:00
|
|
|
else if (IS_P3P_TYPE(ha))
|
2012-08-23 01:21:02 +07:00
|
|
|
size = ha->md_template_size + ha->md_dump_size;
|
|
|
|
else
|
|
|
|
size = ha->fw_dump_len;
|
|
|
|
|
2013-10-30 14:38:24 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", size);
|
2012-08-23 01:21:02 +07:00
|
|
|
}
|
|
|
|
|
2014-02-26 16:15:12 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_allow_cna_fw_dump_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
|
|
|
if (!IS_P3P_TYPE(vha->hw))
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
else
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
|
|
|
vha->hw->allow_cna_fw_dump ? "true" : "false");
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_allow_cna_fw_dump_store(struct device *dev,
|
|
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int val = 0;
|
|
|
|
|
|
|
|
if (!IS_P3P_TYPE(vha->hw))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
vha->hw->allow_cna_fw_dump = val != 0;
|
|
|
|
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
2015-08-05 00:37:59 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2015-08-05 00:37:59 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
|
|
|
|
ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]);
|
|
|
|
}
|
|
|
|
|
2017-08-24 05:05:16 +07:00
|
|
|
static ssize_t
|
2019-03-13 01:08:15 +07:00
|
|
|
qla2x00_min_supported_speed_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2017-08-24 05:05:16 +07:00
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2017-08-24 05:05:16 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2019-03-13 01:08:15 +07:00
|
|
|
ha->min_supported_speed == 6 ? "64Gps" :
|
|
|
|
ha->min_supported_speed == 5 ? "32Gps" :
|
|
|
|
ha->min_supported_speed == 4 ? "16Gps" :
|
|
|
|
ha->min_supported_speed == 3 ? "8Gps" :
|
|
|
|
ha->min_supported_speed == 2 ? "4Gps" :
|
|
|
|
ha->min_supported_speed != 0 ? "unknown" : "");
|
2017-08-24 05:05:16 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2019-03-13 01:08:15 +07:00
|
|
|
qla2x00_max_supported_speed_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2017-08-24 05:05:16 +07:00
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2017-08-24 05:05:16 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
2019-03-13 01:08:15 +07:00
|
|
|
ha->max_supported_speed == 2 ? "64Gps" :
|
|
|
|
ha->max_supported_speed == 1 ? "32Gps" :
|
|
|
|
ha->max_supported_speed == 0 ? "16Gps" : "unknown");
|
2017-08-24 05:05:16 +07:00
|
|
|
}
|
|
|
|
|
2019-02-16 05:37:17 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
|
|
|
|
ulong type, speed;
|
|
|
|
int oldspeed, rval;
|
|
|
|
int mode = QLA_SET_DATA_RATE_LR;
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) {
|
2019-02-16 05:37:17 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x70d8,
|
|
|
|
"Speed setting not supported \n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rval = kstrtol(buf, 10, &type);
|
2019-02-20 12:39:13 +07:00
|
|
|
if (rval)
|
|
|
|
return rval;
|
2019-02-16 05:37:17 +07:00
|
|
|
speed = type;
|
|
|
|
if (type == 40 || type == 80 || type == 160 ||
|
|
|
|
type == 320) {
|
|
|
|
ql_dbg(ql_dbg_user, vha, 0x70d9,
|
|
|
|
"Setting will be affected after a loss of sync\n");
|
|
|
|
type = type/10;
|
|
|
|
mode = QLA_SET_DATA_RATE_NOLR;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldspeed = ha->set_data_rate;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 0:
|
|
|
|
ha->set_data_rate = PORT_SPEED_AUTO;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
ha->set_data_rate = PORT_SPEED_4GB;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
ha->set_data_rate = PORT_SPEED_8GB;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
ha->set_data_rate = PORT_SPEED_16GB;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
ha->set_data_rate = PORT_SPEED_32GB;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ql_log(ql_log_warn, vha, 0x1199,
|
|
|
|
"Unrecognized speed setting:%lx. Setting Autoneg\n",
|
|
|
|
speed);
|
|
|
|
ha->set_data_rate = PORT_SPEED_AUTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qla2x00_chip_is_down(vha) || (oldspeed == ha->set_data_rate))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ql_log(ql_log_info, vha, 0x70da,
|
|
|
|
"Setting speed to %lx Gbps \n", type);
|
|
|
|
|
|
|
|
rval = qla2x00_set_data_rate(vha, mode);
|
|
|
|
if (rval != QLA_SUCCESS)
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
ssize_t rval;
|
|
|
|
char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"};
|
|
|
|
|
|
|
|
rval = qla2x00_get_data_rate(vha);
|
|
|
|
if (rval != QLA_SUCCESS) {
|
|
|
|
ql_log(ql_log_warn, vha, 0x70db,
|
|
|
|
"Unable to get port speed rval:%zd\n", rval);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ql_log(ql_log_info, vha, 0x70d6,
|
|
|
|
"port speed:%d\n", ha->link_data_rate);
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]);
|
|
|
|
}
|
|
|
|
|
2018-09-12 00:18:18 +07:00
|
|
|
/* ----- */
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qlini_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
"Supported options: enabled | disabled | dual | exclusive\n");
|
|
|
|
|
|
|
|
/* --- */
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "Current selection: ");
|
|
|
|
|
|
|
|
switch (vha->qlini_mode) {
|
|
|
|
case QLA2XXX_INI_MODE_EXCLUSIVE:
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
QLA2XXX_INI_MODE_STR_EXCLUSIVE);
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
QLA2XXX_INI_MODE_STR_DISABLED);
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
QLA2XXX_INI_MODE_STR_ENABLED);
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_DUAL:
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
QLA2XXX_INI_MODE_STR_DUAL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len, "\n");
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *mode_to_str[] = {
|
|
|
|
"exclusive",
|
|
|
|
"disabled",
|
|
|
|
"enabled",
|
|
|
|
"dual",
|
|
|
|
};
|
|
|
|
|
|
|
|
#define NEED_EXCH_OFFLOAD(_exchg) ((_exchg) > FW_DEF_EXCHANGES_CNT)
|
|
|
|
static int qla_set_ini_mode(scsi_qla_host_t *vha, int op)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
enum {
|
|
|
|
NO_ACTION,
|
|
|
|
MODE_CHANGE_ACCEPT,
|
|
|
|
MODE_CHANGE_NO_ACTION,
|
|
|
|
TARGET_STILL_ACTIVE,
|
|
|
|
};
|
|
|
|
int action = NO_ACTION;
|
|
|
|
int set_mode = 0;
|
|
|
|
u8 eo_toggle = 0; /* exchange offload flipped */
|
|
|
|
|
|
|
|
switch (vha->qlini_mode) {
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
switch (op) {
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
if (((vha->ql2xexchoffld !=
|
|
|
|
vha->u_ql2xexchoffld) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
|
|
|
|
eo_toggle) {
|
|
|
|
/*
|
|
|
|
* The number of exchange to be offload
|
|
|
|
* was tweaked or offload option was
|
|
|
|
* flipped
|
|
|
|
*/
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_EXCLUSIVE:
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
if (((vha->ql2xexchoffld !=
|
|
|
|
vha->u_ql2xexchoffld) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
|
|
|
|
eo_toggle) {
|
|
|
|
/*
|
|
|
|
* The number of exchange to be offload
|
|
|
|
* was tweaked or offload option was
|
|
|
|
* flipped
|
|
|
|
*/
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_DUAL:
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
/* active_mode is target only, reset it to dual */
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
set_mode = 1;
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha))
|
|
|
|
action = TARGET_STILL_ACTIVE;
|
|
|
|
else {
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
set_mode = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_EXCLUSIVE:
|
|
|
|
switch (op) {
|
|
|
|
case QLA2XXX_INI_MODE_EXCLUSIVE:
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
if (((vha->ql2xexchoffld !=
|
|
|
|
vha->u_ql2xexchoffld) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
|
|
|
|
eo_toggle)
|
|
|
|
/*
|
|
|
|
* The number of exchange to be offload
|
|
|
|
* was tweaked or offload option was
|
|
|
|
* flipped
|
|
|
|
*/
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
else
|
|
|
|
action = NO_ACTION;
|
|
|
|
} else
|
|
|
|
action = NO_ACTION;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
if (((vha->ql2xexchoffld !=
|
|
|
|
vha->u_ql2xexchoffld) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
|
|
|
|
eo_toggle)
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
else
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
} else
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_DUAL: /* exclusive -> dual */
|
|
|
|
if (qla_tgt_mode_enabled(vha)) {
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
set_mode = 1;
|
|
|
|
} else
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha))
|
|
|
|
action = TARGET_STILL_ACTIVE;
|
|
|
|
else {
|
|
|
|
if (vha->hw->flags.fw_started)
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
else
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
switch (op) {
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
if (((vha->ql2xiniexchg != vha->u_ql2xiniexchg) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg)) ||
|
|
|
|
eo_toggle)
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
else
|
|
|
|
action = NO_ACTION;
|
|
|
|
break;
|
|
|
|
case QLA2XXX_INI_MODE_DUAL:
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_DUAL:
|
|
|
|
switch (op) {
|
|
|
|
case QLA2XXX_INI_MODE_DUAL:
|
|
|
|
if (qla_tgt_mode_enabled(vha) ||
|
|
|
|
qla_dual_mode_enabled(vha)) {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
|
|
|
|
vha->u_ql2xiniexchg) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
|
|
|
|
if ((((vha->ql2xexchoffld +
|
|
|
|
vha->ql2xiniexchg) !=
|
|
|
|
(vha->u_ql2xiniexchg +
|
|
|
|
vha->u_ql2xexchoffld)) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
|
|
|
|
vha->u_ql2xexchoffld)) || eo_toggle)
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
else
|
|
|
|
action = NO_ACTION;
|
|
|
|
} else {
|
|
|
|
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
|
|
|
|
vha->u_ql2xiniexchg) !=
|
|
|
|
vha->hw->flags.exchoffld_enabled)
|
|
|
|
eo_toggle = 1;
|
|
|
|
|
|
|
|
if ((((vha->ql2xexchoffld + vha->ql2xiniexchg)
|
|
|
|
!= (vha->u_ql2xiniexchg +
|
|
|
|
vha->u_ql2xexchoffld)) &&
|
|
|
|
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
|
|
|
|
vha->u_ql2xexchoffld)) || eo_toggle)
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
else
|
|
|
|
action = NO_ACTION;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_DISABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha) ||
|
|
|
|
qla_dual_mode_enabled(vha)) {
|
|
|
|
/* turning off initiator mode */
|
|
|
|
set_mode = 1;
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_NO_ACTION;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_EXCLUSIVE:
|
|
|
|
if (qla_tgt_mode_enabled(vha) ||
|
|
|
|
qla_dual_mode_enabled(vha)) {
|
|
|
|
set_mode = 1;
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QLA2XXX_INI_MODE_ENABLED:
|
|
|
|
if (qla_tgt_mode_enabled(vha) ||
|
|
|
|
qla_dual_mode_enabled(vha)) {
|
|
|
|
action = TARGET_STILL_ACTIVE;
|
|
|
|
} else {
|
|
|
|
action = MODE_CHANGE_ACCEPT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case MODE_CHANGE_ACCEPT:
|
|
|
|
ql_log(ql_log_warn, vha, 0xffff,
|
|
|
|
"Mode change accepted. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
|
|
|
|
mode_to_str[vha->qlini_mode], mode_to_str[op],
|
|
|
|
vha->ql2xexchoffld, vha->u_ql2xexchoffld,
|
|
|
|
vha->ql2xiniexchg, vha->u_ql2xiniexchg);
|
|
|
|
|
|
|
|
vha->qlini_mode = op;
|
|
|
|
vha->ql2xexchoffld = vha->u_ql2xexchoffld;
|
|
|
|
vha->ql2xiniexchg = vha->u_ql2xiniexchg;
|
|
|
|
if (set_mode)
|
|
|
|
qlt_set_mode(vha);
|
|
|
|
vha->flags.online = 1;
|
|
|
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MODE_CHANGE_NO_ACTION:
|
|
|
|
ql_log(ql_log_warn, vha, 0xffff,
|
|
|
|
"Mode is set. No action taken. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
|
|
|
|
mode_to_str[vha->qlini_mode], mode_to_str[op],
|
|
|
|
vha->ql2xexchoffld, vha->u_ql2xexchoffld,
|
|
|
|
vha->ql2xiniexchg, vha->u_ql2xiniexchg);
|
|
|
|
vha->qlini_mode = op;
|
|
|
|
vha->ql2xexchoffld = vha->u_ql2xexchoffld;
|
|
|
|
vha->ql2xiniexchg = vha->u_ql2xiniexchg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TARGET_STILL_ACTIVE:
|
|
|
|
ql_log(ql_log_warn, vha, 0xffff,
|
|
|
|
"Target Mode is active. Unable to change Mode.\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NO_ACTION:
|
|
|
|
default:
|
|
|
|
ql_log(ql_log_warn, vha, 0xffff,
|
|
|
|
"Mode unchange. No action taken. %d|%d pct %d|%d.\n",
|
|
|
|
vha->qlini_mode, op,
|
|
|
|
vha->ql2xexchoffld, vha->u_ql2xexchoffld);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qlini_mode_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int ini;
|
|
|
|
|
|
|
|
if (!buf)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (strncasecmp(QLA2XXX_INI_MODE_STR_EXCLUSIVE, buf,
|
|
|
|
strlen(QLA2XXX_INI_MODE_STR_EXCLUSIVE)) == 0)
|
|
|
|
ini = QLA2XXX_INI_MODE_EXCLUSIVE;
|
|
|
|
else if (strncasecmp(QLA2XXX_INI_MODE_STR_DISABLED, buf,
|
|
|
|
strlen(QLA2XXX_INI_MODE_STR_DISABLED)) == 0)
|
|
|
|
ini = QLA2XXX_INI_MODE_DISABLED;
|
|
|
|
else if (strncasecmp(QLA2XXX_INI_MODE_STR_ENABLED, buf,
|
|
|
|
strlen(QLA2XXX_INI_MODE_STR_ENABLED)) == 0)
|
|
|
|
ini = QLA2XXX_INI_MODE_ENABLED;
|
|
|
|
else if (strncasecmp(QLA2XXX_INI_MODE_STR_DUAL, buf,
|
|
|
|
strlen(QLA2XXX_INI_MODE_STR_DUAL)) == 0)
|
|
|
|
ini = QLA2XXX_INI_MODE_DUAL;
|
|
|
|
else
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
qla_set_ini_mode(vha, ini);
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
ql2xexchoffld_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
"target exchange: new %d : current: %d\n\n",
|
|
|
|
vha->u_ql2xexchoffld, vha->ql2xexchoffld);
|
|
|
|
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
"Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n",
|
|
|
|
vha->host_no);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
ql2xexchoffld_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int val = 0;
|
|
|
|
|
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > FW_MAX_EXCHANGES_CNT)
|
|
|
|
val = FW_MAX_EXCHANGES_CNT;
|
|
|
|
else if (val < 0)
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
vha->u_ql2xexchoffld = val;
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
ql2xiniexchg_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
"target exchange: new %d : current: %d\n\n",
|
|
|
|
vha->u_ql2xiniexchg, vha->ql2xiniexchg);
|
|
|
|
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE-len,
|
|
|
|
"Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n",
|
|
|
|
vha->host_no);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
ql2xiniexchg_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
int val = 0;
|
|
|
|
|
|
|
|
if (sscanf(buf, "%d", &val) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > FW_MAX_EXCHANGES_CNT)
|
|
|
|
val = FW_MAX_EXCHANGES_CNT;
|
|
|
|
else if (val < 0)
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
vha->u_ql2xiniexchg = val;
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
2018-12-22 00:33:45 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_dif_bundle_statistics_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE,
|
|
|
|
"cross=%llu read=%llu write=%llu kalloc=%llu dma_alloc=%llu unusable=%u\n",
|
|
|
|
ha->dif_bundle_crossed_pages, ha->dif_bundle_reads,
|
|
|
|
ha->dif_bundle_writes, ha->dif_bundle_kallocs,
|
|
|
|
ha->dif_bundle_dma_allocs, ha->pool.unusable.count);
|
|
|
|
}
|
|
|
|
|
2019-03-13 01:08:10 +07:00
|
|
|
static ssize_t
|
|
|
|
qla2x00_fw_attr_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
|
2019-03-13 01:08:13 +07:00
|
|
|
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
2019-03-13 01:08:10 +07:00
|
|
|
return scnprintf(buf, PAGE_SIZE, "\n");
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%llx\n",
|
|
|
|
(uint64_t)ha->fw_attributes_ext[1] << 48 |
|
|
|
|
(uint64_t)ha->fw_attributes_ext[0] << 32 |
|
|
|
|
(uint64_t)ha->fw_attributes_h << 16 |
|
|
|
|
(uint64_t)ha->fw_attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
qla2x00_port_no_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
|
|
|
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no);
|
|
|
|
}
|
|
|
|
|
2018-12-22 00:33:45 +07:00
|
|
|
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL);
|
2008-02-22 06:13:36 +07:00
|
|
|
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
|
|
|
|
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
|
|
|
|
static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
|
|
|
|
static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
|
|
|
|
static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
|
|
|
|
static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
|
|
|
|
static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
|
2008-03-18 20:32:28 +07:00
|
|
|
static DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL);
|
2008-02-22 06:13:36 +07:00
|
|
|
static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
|
|
|
|
static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
|
|
|
|
qla2x00_zio_timer_store);
|
|
|
|
static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
|
|
|
|
qla2x00_beacon_store);
|
|
|
|
static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
|
|
|
|
qla2x00_optrom_bios_version_show, NULL);
|
|
|
|
static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
|
|
|
|
qla2x00_optrom_efi_version_show, NULL);
|
|
|
|
static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
|
|
|
|
qla2x00_optrom_fcode_version_show, NULL);
|
|
|
|
static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
|
|
|
|
NULL);
|
2010-07-23 17:28:26 +07:00
|
|
|
static DEVICE_ATTR(optrom_gold_fw_version, S_IRUGO,
|
|
|
|
qla2x00_optrom_gold_fw_version_show, NULL);
|
2010-01-13 04:02:47 +07:00
|
|
|
static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show,
|
|
|
|
NULL);
|
2008-07-11 06:55:49 +07:00
|
|
|
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
|
|
|
|
NULL);
|
2019-03-13 01:08:14 +07:00
|
|
|
static DEVICE_ATTR(serdes_version, 0444, qla2x00_serdes_version_show, NULL);
|
2009-01-06 02:18:11 +07:00
|
|
|
static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
|
2009-03-24 23:08:03 +07:00
|
|
|
static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
|
2009-03-24 23:08:11 +07:00
|
|
|
static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show,
|
|
|
|
NULL);
|
2009-04-07 12:33:38 +07:00
|
|
|
static DEVICE_ATTR(vlan_id, S_IRUGO, qla2x00_vlan_id_show, NULL);
|
|
|
|
static DEVICE_ATTR(vn_port_mac_address, S_IRUGO,
|
|
|
|
qla2x00_vn_port_mac_address_show, NULL);
|
2009-06-03 23:55:12 +07:00
|
|
|
static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL);
|
2009-06-03 23:55:29 +07:00
|
|
|
static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL);
|
2010-12-22 07:00:21 +07:00
|
|
|
static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL);
|
2012-08-23 01:21:01 +07:00
|
|
|
static DEVICE_ATTR(diag_requests, S_IRUGO, qla2x00_diag_requests_show, NULL);
|
|
|
|
static DEVICE_ATTR(diag_megabytes, S_IRUGO, qla2x00_diag_megabytes_show, NULL);
|
2012-08-23 01:21:02 +07:00
|
|
|
static DEVICE_ATTR(fw_dump_size, S_IRUGO, qla2x00_fw_dump_size_show, NULL);
|
2014-02-26 16:15:12 +07:00
|
|
|
static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR,
|
|
|
|
qla2x00_allow_cna_fw_dump_show,
|
|
|
|
qla2x00_allow_cna_fw_dump_store);
|
2015-08-05 00:37:59 +07:00
|
|
|
static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL);
|
2019-03-13 01:08:15 +07:00
|
|
|
static DEVICE_ATTR(min_supported_speed, 0444,
|
|
|
|
qla2x00_min_supported_speed_show, NULL);
|
|
|
|
static DEVICE_ATTR(max_supported_speed, 0444,
|
|
|
|
qla2x00_max_supported_speed_show, NULL);
|
2018-09-05 04:19:14 +07:00
|
|
|
static DEVICE_ATTR(zio_threshold, 0644,
|
|
|
|
qla_zio_threshold_show,
|
|
|
|
qla_zio_threshold_store);
|
2018-09-12 00:18:18 +07:00
|
|
|
static DEVICE_ATTR_RW(qlini_mode);
|
|
|
|
static DEVICE_ATTR_RW(ql2xexchoffld);
|
|
|
|
static DEVICE_ATTR_RW(ql2xiniexchg);
|
2018-12-22 00:33:45 +07:00
|
|
|
static DEVICE_ATTR(dif_bundle_statistics, 0444,
|
|
|
|
qla2x00_dif_bundle_statistics_show, NULL);
|
2019-02-16 05:37:17 +07:00
|
|
|
static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show,
|
|
|
|
qla2x00_port_speed_store);
|
2019-03-13 01:08:10 +07:00
|
|
|
static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
|
|
|
|
static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
|
2018-09-12 00:18:18 +07:00
|
|
|
|
2008-02-22 06:13:36 +07:00
|
|
|
|
|
|
|
struct device_attribute *qla2x00_host_attrs[] = {
|
|
|
|
&dev_attr_driver_version,
|
|
|
|
&dev_attr_fw_version,
|
|
|
|
&dev_attr_serial_num,
|
|
|
|
&dev_attr_isp_name,
|
|
|
|
&dev_attr_isp_id,
|
|
|
|
&dev_attr_model_name,
|
|
|
|
&dev_attr_model_desc,
|
|
|
|
&dev_attr_pci_info,
|
2008-03-18 20:32:28 +07:00
|
|
|
&dev_attr_link_state,
|
2008-02-22 06:13:36 +07:00
|
|
|
&dev_attr_zio,
|
|
|
|
&dev_attr_zio_timer,
|
|
|
|
&dev_attr_beacon,
|
|
|
|
&dev_attr_optrom_bios_version,
|
|
|
|
&dev_attr_optrom_efi_version,
|
|
|
|
&dev_attr_optrom_fcode_version,
|
|
|
|
&dev_attr_optrom_fw_version,
|
2010-01-13 04:02:47 +07:00
|
|
|
&dev_attr_84xx_fw_version,
|
2008-07-11 06:55:49 +07:00
|
|
|
&dev_attr_total_isp_aborts,
|
2019-03-13 01:08:14 +07:00
|
|
|
&dev_attr_serdes_version,
|
2009-01-06 02:18:11 +07:00
|
|
|
&dev_attr_mpi_version,
|
2009-03-24 23:08:03 +07:00
|
|
|
&dev_attr_phy_version,
|
2009-03-24 23:08:11 +07:00
|
|
|
&dev_attr_flash_block_size,
|
2009-04-07 12:33:38 +07:00
|
|
|
&dev_attr_vlan_id,
|
|
|
|
&dev_attr_vn_port_mac_address,
|
2009-06-03 23:55:12 +07:00
|
|
|
&dev_attr_fabric_param,
|
2009-06-03 23:55:29 +07:00
|
|
|
&dev_attr_fw_state,
|
2010-07-23 17:28:26 +07:00
|
|
|
&dev_attr_optrom_gold_fw_version,
|
2010-12-22 07:00:21 +07:00
|
|
|
&dev_attr_thermal_temp,
|
2012-08-23 01:21:01 +07:00
|
|
|
&dev_attr_diag_requests,
|
|
|
|
&dev_attr_diag_megabytes,
|
2012-08-23 01:21:02 +07:00
|
|
|
&dev_attr_fw_dump_size,
|
2014-02-26 16:15:12 +07:00
|
|
|
&dev_attr_allow_cna_fw_dump,
|
2015-08-05 00:37:59 +07:00
|
|
|
&dev_attr_pep_version,
|
2019-03-13 01:08:15 +07:00
|
|
|
&dev_attr_min_supported_speed,
|
|
|
|
&dev_attr_max_supported_speed,
|
2018-09-05 04:19:14 +07:00
|
|
|
&dev_attr_zio_threshold,
|
2018-12-22 00:33:45 +07:00
|
|
|
&dev_attr_dif_bundle_statistics,
|
2019-02-16 05:37:17 +07:00
|
|
|
&dev_attr_port_speed,
|
2019-03-13 01:08:10 +07:00
|
|
|
&dev_attr_port_no,
|
|
|
|
&dev_attr_fw_attr,
|
2018-09-12 00:18:18 +07:00
|
|
|
NULL, /* reserve for qlini_mode */
|
|
|
|
NULL, /* reserve for ql2xiniexchg */
|
|
|
|
NULL, /* reserve for ql2xexchoffld */
|
2005-08-27 09:09:40 +07:00
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
2018-09-12 00:18:18 +07:00
|
|
|
void qla_insert_tgt_attrs(void)
|
|
|
|
{
|
|
|
|
struct device_attribute **attr;
|
|
|
|
|
|
|
|
/* advance to empty slot */
|
|
|
|
for (attr = &qla2x00_host_attrs[0]; *attr; ++attr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*attr = &dev_attr_qlini_mode;
|
|
|
|
attr++;
|
|
|
|
*attr = &dev_attr_ql2xiniexchg;
|
|
|
|
attr++;
|
|
|
|
*attr = &dev_attr_ql2xexchoffld;
|
|
|
|
}
|
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
/* Host attributes. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
qla2x00_get_host_port_id(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_host_port_id(shost) = vha->d_id.b.domain << 16 |
|
|
|
|
vha->d_id.b.area << 8 | vha->d_id.b.al_pa;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
2006-02-01 07:04:51 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_host_speed(struct Scsi_Host *shost)
|
|
|
|
{
|
2019-03-13 01:08:14 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
|
|
|
u32 speed;
|
2006-02-01 07:04:51 +07:00
|
|
|
|
2019-03-13 01:08:14 +07:00
|
|
|
if (IS_QLAFX00(vha->hw)) {
|
2013-03-28 19:21:23 +07:00
|
|
|
qlafx00_get_host_speed(shost);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 01:08:14 +07:00
|
|
|
switch (vha->hw->link_data_rate) {
|
2006-10-03 02:00:43 +07:00
|
|
|
case PORT_SPEED_1GB:
|
2008-04-04 03:13:14 +07:00
|
|
|
speed = FC_PORTSPEED_1GBIT;
|
2006-02-01 07:04:51 +07:00
|
|
|
break;
|
2006-10-03 02:00:43 +07:00
|
|
|
case PORT_SPEED_2GB:
|
2008-04-04 03:13:14 +07:00
|
|
|
speed = FC_PORTSPEED_2GBIT;
|
2006-02-01 07:04:51 +07:00
|
|
|
break;
|
2006-10-03 02:00:43 +07:00
|
|
|
case PORT_SPEED_4GB:
|
2008-04-04 03:13:14 +07:00
|
|
|
speed = FC_PORTSPEED_4GBIT;
|
2006-02-01 07:04:51 +07:00
|
|
|
break;
|
2008-02-01 03:33:52 +07:00
|
|
|
case PORT_SPEED_8GB:
|
2008-04-04 03:13:14 +07:00
|
|
|
speed = FC_PORTSPEED_8GBIT;
|
2008-02-01 03:33:52 +07:00
|
|
|
break;
|
2009-01-06 02:18:11 +07:00
|
|
|
case PORT_SPEED_10GB:
|
|
|
|
speed = FC_PORTSPEED_10GBIT;
|
|
|
|
break;
|
2012-02-10 02:15:34 +07:00
|
|
|
case PORT_SPEED_16GB:
|
|
|
|
speed = FC_PORTSPEED_16GBIT;
|
|
|
|
break;
|
2014-02-26 16:15:06 +07:00
|
|
|
case PORT_SPEED_32GB:
|
|
|
|
speed = FC_PORTSPEED_32GBIT;
|
|
|
|
break;
|
2019-03-13 01:08:13 +07:00
|
|
|
case PORT_SPEED_64GB:
|
|
|
|
speed = FC_PORTSPEED_64GBIT;
|
|
|
|
break;
|
2019-03-13 01:08:14 +07:00
|
|
|
default:
|
|
|
|
speed = FC_PORTSPEED_UNKNOWN;
|
|
|
|
break;
|
2006-02-01 07:04:51 +07:00
|
|
|
}
|
2019-03-13 01:08:14 +07:00
|
|
|
|
2006-02-01 07:04:51 +07:00
|
|
|
fc_host_speed(shost) = speed;
|
|
|
|
}
|
|
|
|
|
2006-02-01 07:04:56 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_host_port_type(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2019-03-13 01:08:14 +07:00
|
|
|
uint32_t port_type;
|
2006-02-01 07:04:56 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
if (vha->vp_idx) {
|
2008-05-13 12:21:07 +07:00
|
|
|
fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
|
|
|
|
return;
|
|
|
|
}
|
2008-11-07 01:40:19 +07:00
|
|
|
switch (vha->hw->current_topology) {
|
2006-02-01 07:04:56 +07:00
|
|
|
case ISP_CFG_NL:
|
|
|
|
port_type = FC_PORTTYPE_LPORT;
|
|
|
|
break;
|
|
|
|
case ISP_CFG_FL:
|
|
|
|
port_type = FC_PORTTYPE_NLPORT;
|
|
|
|
break;
|
|
|
|
case ISP_CFG_N:
|
|
|
|
port_type = FC_PORTTYPE_PTP;
|
|
|
|
break;
|
|
|
|
case ISP_CFG_F:
|
|
|
|
port_type = FC_PORTTYPE_NPORT;
|
|
|
|
break;
|
2019-03-13 01:08:14 +07:00
|
|
|
default:
|
|
|
|
port_type = FC_PORTTYPE_UNKNOWN;
|
|
|
|
break;
|
2006-02-01 07:04:56 +07:00
|
|
|
}
|
2019-03-13 01:08:14 +07:00
|
|
|
|
2006-02-01 07:04:56 +07:00
|
|
|
fc_host_port_type(shost) = port_type;
|
|
|
|
}
|
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_starget_node_name(struct scsi_target *starget)
|
|
|
|
{
|
|
|
|
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(host);
|
2005-04-18 03:06:53 +07:00
|
|
|
fc_port_t *fcport;
|
2005-09-01 05:21:20 +07:00
|
|
|
u64 node_name = 0;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
2008-04-04 03:13:16 +07:00
|
|
|
if (fcport->rport &&
|
|
|
|
starget->id == fcport->rport->scsi_target_id) {
|
2005-09-01 05:21:20 +07:00
|
|
|
node_name = wwn_to_u64(fcport->node_name);
|
2005-04-18 03:06:53 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-01 05:21:20 +07:00
|
|
|
fc_starget_node_name(starget) = node_name;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
qla2x00_get_starget_port_name(struct scsi_target *starget)
|
|
|
|
{
|
|
|
|
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(host);
|
2005-04-18 03:06:53 +07:00
|
|
|
fc_port_t *fcport;
|
2005-09-01 05:21:20 +07:00
|
|
|
u64 port_name = 0;
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
2008-04-04 03:13:16 +07:00
|
|
|
if (fcport->rport &&
|
|
|
|
starget->id == fcport->rport->scsi_target_id) {
|
2005-09-01 05:21:20 +07:00
|
|
|
port_name = wwn_to_u64(fcport->port_name);
|
2005-04-18 03:06:53 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-01 05:21:20 +07:00
|
|
|
fc_starget_port_name(starget) = port_name;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
qla2x00_get_starget_port_id(struct scsi_target *starget)
|
|
|
|
{
|
|
|
|
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(host);
|
2005-04-18 03:06:53 +07:00
|
|
|
fc_port_t *fcport;
|
|
|
|
uint32_t port_id = ~0U;
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
2008-04-04 03:13:16 +07:00
|
|
|
if (fcport->rport &&
|
|
|
|
starget->id == fcport->rport->scsi_target_id) {
|
2005-04-18 03:06:53 +07:00
|
|
|
port_id = fcport->d_id.b.domain << 16 |
|
|
|
|
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-04-18 03:04:54 +07:00
|
|
|
|
|
|
|
fc_starget_port_id(starget) = port_id;
|
|
|
|
}
|
|
|
|
|
2019-03-13 01:08:14 +07:00
|
|
|
static inline void
|
2005-04-18 03:04:54 +07:00
|
|
|
qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
|
|
|
|
{
|
2019-03-13 01:08:14 +07:00
|
|
|
rport->dev_loss_tmo = timeout ? timeout : 1;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|
|
|
|
|
2008-07-11 06:55:47 +07:00
|
|
|
static void
|
|
|
|
qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|
|
|
{
|
|
|
|
struct Scsi_Host *host = rport_to_shost(rport);
|
|
|
|
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
|
2011-01-29 06:17:56 +07:00
|
|
|
unsigned long flags;
|
2008-07-11 06:55:47 +07:00
|
|
|
|
2009-01-23 00:45:38 +07:00
|
|
|
if (!fcport)
|
|
|
|
return;
|
|
|
|
|
2010-10-16 01:27:49 +07:00
|
|
|
/* Now that the rport has been deleted, set the fcport state to
|
|
|
|
FCS_DEVICE_DEAD */
|
2011-03-31 01:46:32 +07:00
|
|
|
qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
|
2010-10-16 01:27:49 +07:00
|
|
|
|
2008-07-11 06:55:47 +07:00
|
|
|
/*
|
|
|
|
* Transport has effectively 'deleted' the rport, clear
|
|
|
|
* all local references.
|
|
|
|
*/
|
2011-01-29 06:17:56 +07:00
|
|
|
spin_lock_irqsave(host->host_lock, flags);
|
2010-09-04 05:20:55 +07:00
|
|
|
fcport->rport = fcport->drport = NULL;
|
2008-07-11 06:55:47 +07:00
|
|
|
*((fc_port_t **)rport->dd_data) = NULL;
|
2011-01-29 06:17:56 +07:00
|
|
|
spin_unlock_irqrestore(host->host_lock, flags);
|
2010-09-04 05:20:55 +07:00
|
|
|
|
|
|
|
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
|
|
|
|
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
|
|
|
|
return;
|
|
|
|
}
|
2008-07-11 06:55:47 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
qla2x00_terminate_rport_io(struct fc_rport *rport)
|
|
|
|
{
|
|
|
|
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
|
|
|
|
|
2009-01-23 00:45:38 +07:00
|
|
|
if (!fcport)
|
|
|
|
return;
|
|
|
|
|
2016-07-06 22:14:32 +07:00
|
|
|
if (test_bit(UNLOADING, &fcport->vha->dpc_flags))
|
|
|
|
return;
|
|
|
|
|
2009-12-16 12:29:46 +07:00
|
|
|
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
|
|
|
|
return;
|
|
|
|
|
2009-03-24 23:08:18 +07:00
|
|
|
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
|
|
|
|
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
|
|
|
|
return;
|
|
|
|
}
|
2008-08-14 11:36:56 +07:00
|
|
|
/*
|
|
|
|
* At this point all fcport's software-states are cleared. Perform any
|
|
|
|
* final cleanup of firmware resources (PCBs and XCBs).
|
|
|
|
*/
|
2012-11-21 14:39:55 +07:00
|
|
|
if (fcport->loop_id != FC_NO_LOOP_ID) {
|
2012-02-10 02:15:43 +07:00
|
|
|
if (IS_FWI2_CAPABLE(fcport->vha->hw))
|
|
|
|
fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
|
|
|
|
fcport->loop_id, fcport->d_id.b.domain,
|
|
|
|
fcport->d_id.b.area, fcport->d_id.b.al_pa);
|
|
|
|
else
|
|
|
|
qla2x00_port_logout(fcport->vha, fcport);
|
|
|
|
}
|
2008-07-11 06:55:47 +07:00
|
|
|
}
|
|
|
|
|
2005-10-28 06:03:37 +07:00
|
|
|
static int
|
|
|
|
qla2x00_issue_lip(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2005-10-28 06:03:37 +07:00
|
|
|
|
2013-03-28 19:21:23 +07:00
|
|
|
if (IS_QLAFX00(vha->hw))
|
|
|
|
return 0;
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
qla2x00_loop_reset(vha);
|
2005-10-28 06:03:37 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-01 07:05:02 +07:00
|
|
|
static struct fc_host_statistics *
|
|
|
|
qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
2006-02-01 07:05:02 +07:00
|
|
|
int rval;
|
2008-01-18 00:02:08 +07:00
|
|
|
struct link_statistics *stats;
|
|
|
|
dma_addr_t stats_dma;
|
2016-07-06 22:14:23 +07:00
|
|
|
struct fc_host_statistics *p = &vha->fc_host_stat;
|
2006-02-01 07:05:02 +07:00
|
|
|
|
2016-07-06 22:14:23 +07:00
|
|
|
memset(p, -1, sizeof(*p));
|
2006-02-01 07:05:02 +07:00
|
|
|
|
2013-03-28 19:21:23 +07:00
|
|
|
if (IS_QLAFX00(vha->hw))
|
|
|
|
goto done;
|
|
|
|
|
2009-12-16 12:29:46 +07:00
|
|
|
if (test_bit(UNLOADING, &vha->dpc_flags))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (unlikely(pci_channel_offline(ha->pdev)))
|
|
|
|
goto done;
|
|
|
|
|
2018-08-03 03:16:47 +07:00
|
|
|
if (qla2x00_chip_is_down(vha))
|
[SCSI] qla2xxx: Do not query FC statistics during chip reset.
During a chip reset, the mailbox call to get FC statistics from the ISP will
not work resulting in needless mailbox accesses and errors printing out:
qla2xxx [0000:05:00.0]-00af:11: Performing ISP error recovery - ha=ffff881fad044800.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
To prevent this, check for a chip reset when an application queries for FC
stats and return immediately if a chip reset is occurring.
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-06-25 22:27:19 +07:00
|
|
|
goto done;
|
|
|
|
|
cross-tree: phase out dma_zalloc_coherent()
We already need to zero out memory for dma_alloc_coherent(), as such
using dma_zalloc_coherent() is superflous. Phase it out.
This change was generated with the following Coccinelle SmPL patch:
@ replace_dma_zalloc_coherent @
expression dev, size, data, handle, flags;
@@
-dma_zalloc_coherent(dev, size, handle, flags)
+dma_alloc_coherent(dev, size, handle, flags)
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
[hch: re-ran the script on the latest tree]
Signed-off-by: Christoph Hellwig <hch@lst.de>
2019-01-04 15:23:09 +07:00
|
|
|
stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
|
|
|
|
GFP_KERNEL);
|
2016-07-06 22:14:24 +07:00
|
|
|
if (!stats) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x707d,
|
|
|
|
"Failed to allocate memory for stats.\n");
|
2008-01-18 00:02:08 +07:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
rval = QLA_FUNCTION_FAILED;
|
2007-07-20 05:05:56 +07:00
|
|
|
if (IS_FWI2_CAPABLE(ha)) {
|
2016-07-06 22:14:24 +07:00
|
|
|
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, 0);
|
2008-11-07 01:40:19 +07:00
|
|
|
} else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
|
[SCSI] qla2xxx: Do not query FC statistics during chip reset.
During a chip reset, the mailbox call to get FC statistics from the ISP will
not work resulting in needless mailbox accesses and errors printing out:
qla2xxx [0000:05:00.0]-00af:11: Performing ISP error recovery - ha=ffff881fad044800.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****.
To prevent this, check for a chip reset when an application queries for FC
stats and return immediately if a chip reset is occurring.
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-06-25 22:27:19 +07:00
|
|
|
!ha->dpc_active) {
|
2007-01-30 01:22:25 +07:00
|
|
|
/* Must be in a 'READY' state for statistics retrieval. */
|
2008-11-07 01:40:19 +07:00
|
|
|
rval = qla2x00_get_link_status(base_vha, base_vha->loop_id,
|
|
|
|
stats, stats_dma);
|
2006-02-01 07:05:02 +07:00
|
|
|
}
|
2007-01-30 01:22:25 +07:00
|
|
|
|
|
|
|
if (rval != QLA_SUCCESS)
|
2008-01-18 00:02:08 +07:00
|
|
|
goto done_free;
|
|
|
|
|
2016-07-06 22:14:23 +07:00
|
|
|
p->link_failure_count = stats->link_fail_cnt;
|
|
|
|
p->loss_of_sync_count = stats->loss_sync_cnt;
|
|
|
|
p->loss_of_signal_count = stats->loss_sig_cnt;
|
|
|
|
p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
|
|
|
|
p->invalid_tx_word_count = stats->inval_xmit_word_cnt;
|
|
|
|
p->invalid_crc_count = stats->inval_crc_cnt;
|
2008-01-18 00:02:08 +07:00
|
|
|
if (IS_FWI2_CAPABLE(ha)) {
|
2016-07-06 22:14:23 +07:00
|
|
|
p->lip_count = stats->lip_cnt;
|
|
|
|
p->tx_frames = stats->tx_frames;
|
|
|
|
p->rx_frames = stats->rx_frames;
|
|
|
|
p->dumped_frames = stats->discarded_frames;
|
|
|
|
p->nos_count = stats->nos_rcvd;
|
|
|
|
p->error_frames =
|
2013-08-27 12:37:40 +07:00
|
|
|
stats->dropped_frames + stats->discarded_frames;
|
2016-07-06 22:14:23 +07:00
|
|
|
p->rx_words = vha->qla_stats.input_bytes;
|
|
|
|
p->tx_words = vha->qla_stats.output_bytes;
|
2008-01-18 00:02:08 +07:00
|
|
|
}
|
2016-07-06 22:14:23 +07:00
|
|
|
p->fcp_control_requests = vha->qla_stats.control_requests;
|
|
|
|
p->fcp_input_requests = vha->qla_stats.input_requests;
|
|
|
|
p->fcp_output_requests = vha->qla_stats.output_requests;
|
|
|
|
p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20;
|
|
|
|
p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20;
|
|
|
|
p->seconds_since_last_reset =
|
2013-08-27 12:37:40 +07:00
|
|
|
get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset;
|
2016-07-06 22:14:23 +07:00
|
|
|
do_div(p->seconds_since_last_reset, HZ);
|
2006-02-01 07:05:02 +07:00
|
|
|
|
2008-01-18 00:02:08 +07:00
|
|
|
done_free:
|
2016-01-28 00:03:33 +07:00
|
|
|
dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
|
|
|
|
stats, stats_dma);
|
2007-01-30 01:22:25 +07:00
|
|
|
done:
|
2016-07-06 22:14:23 +07:00
|
|
|
return p;
|
2006-02-01 07:05:02 +07:00
|
|
|
}
|
|
|
|
|
2013-08-27 12:37:40 +07:00
|
|
|
static void
|
|
|
|
qla2x00_reset_host_stats(struct Scsi_Host *shost)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2016-07-06 22:14:24 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
|
|
|
struct link_statistics *stats;
|
|
|
|
dma_addr_t stats_dma;
|
2013-08-27 12:37:40 +07:00
|
|
|
|
2016-07-06 22:14:23 +07:00
|
|
|
memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
|
2013-08-27 12:37:40 +07:00
|
|
|
memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
|
|
|
|
|
|
|
|
vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
|
2016-07-06 22:14:24 +07:00
|
|
|
|
|
|
|
if (IS_FWI2_CAPABLE(ha)) {
|
|
|
|
stats = dma_alloc_coherent(&ha->pdev->dev,
|
|
|
|
sizeof(*stats), &stats_dma, GFP_KERNEL);
|
|
|
|
if (!stats) {
|
|
|
|
ql_log(ql_log_warn, vha, 0x70d7,
|
|
|
|
"Failed to allocate memory for stats.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset firmware statistics */
|
|
|
|
qla24xx_get_isp_stats(base_vha, stats, stats_dma, BIT_0);
|
|
|
|
|
|
|
|
dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
|
|
|
|
stats, stats_dma);
|
|
|
|
}
|
2013-08-27 12:37:40 +07:00
|
|
|
}
|
|
|
|
|
2006-10-03 02:00:44 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2006-10-03 02:00:44 +07:00
|
|
|
|
2014-09-25 16:16:46 +07:00
|
|
|
qla2x00_get_sym_node_name(vha, fc_host_symbolic_name(shost),
|
|
|
|
sizeof(fc_host_symbolic_name(shost)));
|
2006-10-03 02:00:44 +07:00
|
|
|
}
|
|
|
|
|
2006-10-03 02:00:45 +07:00
|
|
|
static void
|
|
|
|
qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2006-10-03 02:00:45 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
|
2006-10-03 02:00:45 +07:00
|
|
|
}
|
|
|
|
|
2006-10-03 02:00:46 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
2019-04-05 02:44:39 +07:00
|
|
|
static const uint8_t node_name[WWN_SIZE] = {
|
|
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
|
|
|
};
|
2010-09-04 05:20:51 +07:00
|
|
|
u64 fabric_name = wwn_to_u64(node_name);
|
2006-10-03 02:00:46 +07:00
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
if (vha->device_flags & SWITCH_FOUND)
|
2010-09-04 05:20:51 +07:00
|
|
|
fabric_name = wwn_to_u64(vha->fabric_node_name);
|
2006-10-03 02:00:46 +07:00
|
|
|
|
2010-09-04 05:20:51 +07:00
|
|
|
fc_host_fabric_name(shost) = fabric_name;
|
2006-10-03 02:00:46 +07:00
|
|
|
}
|
|
|
|
|
2006-10-03 02:00:47 +07:00
|
|
|
static void
|
|
|
|
qla2x00_get_host_port_state(struct Scsi_Host *shost)
|
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *vha = shost_priv(shost);
|
|
|
|
struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);
|
2006-10-03 02:00:47 +07:00
|
|
|
|
2011-11-19 00:02:20 +07:00
|
|
|
if (!base_vha->flags.online) {
|
2006-10-03 02:00:47 +07:00
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
|
2011-11-19 00:02:20 +07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (atomic_read(&base_vha->loop_state)) {
|
|
|
|
case LOOP_UPDATE:
|
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS;
|
|
|
|
break;
|
|
|
|
case LOOP_DOWN:
|
|
|
|
if (test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags))
|
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS;
|
|
|
|
else
|
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
|
|
|
|
break;
|
|
|
|
case LOOP_DEAD:
|
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
|
|
|
|
break;
|
|
|
|
case LOOP_READY:
|
2006-10-03 02:00:47 +07:00
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
|
2011-11-19 00:02:20 +07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
2006-10-03 02:00:47 +07:00
|
|
|
}
|
|
|
|
|
2007-07-06 03:16:51 +07:00
|
|
|
static int
|
|
|
|
qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2009-04-07 12:33:40 +07:00
|
|
|
uint8_t qos = 0;
|
2008-11-07 01:40:19 +07:00
|
|
|
scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
|
|
|
|
scsi_qla_host_t *vha = NULL;
|
2008-12-10 07:45:39 +07:00
|
|
|
struct qla_hw_data *ha = base_vha->hw;
|
2009-04-07 12:33:40 +07:00
|
|
|
int cnt;
|
2009-06-03 23:55:19 +07:00
|
|
|
struct req_que *req = ha->req_q_map[0];
|
2016-12-13 05:40:07 +07:00
|
|
|
struct qla_qpair *qpair;
|
2007-07-06 03:16:51 +07:00
|
|
|
|
|
|
|
ret = qla24xx_vport_create_req_sanity_check(fc_vport);
|
|
|
|
if (ret) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x707e,
|
|
|
|
"Vport sanity check failed, status %x\n", ret);
|
2007-07-06 03:16:51 +07:00
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
vha = qla24xx_create_vhost(fc_vport);
|
|
|
|
if (vha == NULL) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x707f, "Vport create host failed.\n");
|
2007-07-06 03:16:51 +07:00
|
|
|
return FC_VPORT_FAILED;
|
|
|
|
}
|
|
|
|
if (disable) {
|
|
|
|
atomic_set(&vha->vp_state, VP_OFFLINE);
|
|
|
|
fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
|
|
|
|
} else
|
|
|
|
atomic_set(&vha->vp_state, VP_FAILED);
|
|
|
|
|
|
|
|
/* ready to create vport */
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x7080,
|
|
|
|
"VP entry id %d assigned.\n", vha->vp_idx);
|
2007-07-06 03:16:51 +07:00
|
|
|
|
|
|
|
/* initialized vport states */
|
|
|
|
atomic_set(&vha->loop_state, LOOP_DOWN);
|
2019-04-12 04:53:19 +07:00
|
|
|
vha->vp_err_state = VP_ERR_PORTDWN;
|
|
|
|
vha->vp_prev_err_state = VP_ERR_UNKWN;
|
2007-07-06 03:16:51 +07:00
|
|
|
/* Check if physical ha port is Up */
|
2008-11-07 01:40:19 +07:00
|
|
|
if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
|
|
|
|
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
|
2007-07-06 03:16:51 +07:00
|
|
|
/* Don't retry or attempt login of this virtual port */
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7081,
|
|
|
|
"Vport loop state is not UP.\n");
|
2007-07-06 03:16:51 +07:00
|
|
|
atomic_set(&vha->loop_state, LOOP_DEAD);
|
|
|
|
if (!disable)
|
|
|
|
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
|
|
|
|
}
|
|
|
|
|
2011-08-17 01:29:23 +07:00
|
|
|
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
|
2010-05-05 05:01:30 +07:00
|
|
|
if (ha->fw_attributes & BIT_4) {
|
2012-08-23 01:21:31 +07:00
|
|
|
int prot = 0, guard;
|
2019-04-12 04:53:17 +07:00
|
|
|
|
2010-05-05 05:01:30 +07:00
|
|
|
vha->flags.difdix_supported = 1;
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7082,
|
|
|
|
"Registered for DIF/DIX type 1 and 3 protection.\n");
|
2011-08-17 01:29:22 +07:00
|
|
|
if (ql2xenabledif == 1)
|
|
|
|
prot = SHOST_DIX_TYPE0_PROTECTION;
|
2010-05-05 05:01:30 +07:00
|
|
|
scsi_host_set_prot(vha->host,
|
2011-08-17 01:29:22 +07:00
|
|
|
prot | SHOST_DIF_TYPE1_PROTECTION
|
2010-07-23 17:28:38 +07:00
|
|
|
| SHOST_DIF_TYPE2_PROTECTION
|
2010-05-05 05:01:30 +07:00
|
|
|
| SHOST_DIF_TYPE3_PROTECTION
|
|
|
|
| SHOST_DIX_TYPE1_PROTECTION
|
2010-07-23 17:28:38 +07:00
|
|
|
| SHOST_DIX_TYPE2_PROTECTION
|
2010-05-05 05:01:30 +07:00
|
|
|
| SHOST_DIX_TYPE3_PROTECTION);
|
2012-08-23 01:21:31 +07:00
|
|
|
|
|
|
|
guard = SHOST_DIX_GUARD_CRC;
|
|
|
|
|
|
|
|
if (IS_PI_IPGUARD_CAPABLE(ha) &&
|
|
|
|
(ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
|
|
|
|
guard |= SHOST_DIX_GUARD_IP;
|
|
|
|
|
|
|
|
scsi_host_set_guard(vha->host, guard);
|
2010-05-05 05:01:30 +07:00
|
|
|
} else
|
|
|
|
vha->flags.difdix_supported = 0;
|
|
|
|
}
|
|
|
|
|
2009-11-06 02:33:12 +07:00
|
|
|
if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
|
|
|
|
&ha->pdev->dev)) {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7083,
|
|
|
|
"scsi_add_host failure for VP[%d].\n", vha->vp_idx);
|
2007-07-06 03:16:51 +07:00
|
|
|
goto vport_create_failed_2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize attributes */
|
2010-09-16 04:52:30 +07:00
|
|
|
fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
|
2007-07-06 03:16:51 +07:00
|
|
|
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
|
|
|
|
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
|
|
|
|
fc_host_supported_classes(vha->host) =
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_host_supported_classes(base_vha->host);
|
2007-07-06 03:16:51 +07:00
|
|
|
fc_host_supported_speeds(vha->host) =
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_host_supported_speeds(base_vha->host);
|
2007-07-06 03:16:51 +07:00
|
|
|
|
2012-05-16 01:34:28 +07:00
|
|
|
qlt_vport_create(vha, ha);
|
2007-07-06 03:16:51 +07:00
|
|
|
qla24xx_vport_disable(fc_vport, disable);
|
|
|
|
|
2016-12-13 05:40:07 +07:00
|
|
|
if (!ql2xmqsupport || !ha->npiv_info)
|
2009-04-07 12:33:40 +07:00
|
|
|
goto vport_queue;
|
2016-12-13 05:40:07 +07:00
|
|
|
|
2009-04-07 12:33:40 +07:00
|
|
|
/* Create a request queue in QoS mode for the vport */
|
2009-06-03 23:55:16 +07:00
|
|
|
for (cnt = 0; cnt < ha->nvram_npiv_size; cnt++) {
|
|
|
|
if (memcmp(ha->npiv_info[cnt].port_name, vha->port_name, 8) == 0
|
|
|
|
&& memcmp(ha->npiv_info[cnt].node_name, vha->node_name,
|
2009-06-03 23:55:19 +07:00
|
|
|
8) == 0) {
|
2009-04-07 12:33:40 +07:00
|
|
|
qos = ha->npiv_info[cnt].q_qos;
|
|
|
|
break;
|
2008-12-10 07:45:39 +07:00
|
|
|
}
|
2009-04-07 12:33:40 +07:00
|
|
|
}
|
2012-02-10 02:15:34 +07:00
|
|
|
|
2009-04-07 12:33:40 +07:00
|
|
|
if (qos) {
|
2017-06-14 10:47:17 +07:00
|
|
|
qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx, true);
|
2016-12-13 05:40:07 +07:00
|
|
|
if (!qpair)
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7084,
|
2016-12-13 05:40:07 +07:00
|
|
|
"Can't create qpair for VP[%d]\n",
|
2011-07-15 02:00:13 +07:00
|
|
|
vha->vp_idx);
|
2009-06-03 23:55:19 +07:00
|
|
|
else {
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_multiq, vha, 0xc001,
|
2016-12-13 05:40:07 +07:00
|
|
|
"Queue pair: %d Qos: %d) created for VP[%d]\n",
|
|
|
|
qpair->id, qos, vha->vp_idx);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7085,
|
2016-12-13 05:40:07 +07:00
|
|
|
"Queue Pair: %d Qos: %d) created for VP[%d]\n",
|
|
|
|
qpair->id, qos, vha->vp_idx);
|
|
|
|
req = qpair->req;
|
|
|
|
vha->qpair = qpair;
|
2009-06-03 23:55:19 +07:00
|
|
|
}
|
2008-12-10 07:45:39 +07:00
|
|
|
}
|
|
|
|
|
2009-04-07 12:33:40 +07:00
|
|
|
vport_queue:
|
2009-06-03 23:55:19 +07:00
|
|
|
vha->req = req;
|
2007-07-06 03:16:51 +07:00
|
|
|
return 0;
|
2009-04-07 12:33:40 +07:00
|
|
|
|
2007-07-06 03:16:51 +07:00
|
|
|
vport_create_failed_2:
|
|
|
|
qla24xx_disable_vp(vha);
|
|
|
|
qla24xx_deallocate_vp_id(vha);
|
|
|
|
scsi_host_put(vha->host);
|
|
|
|
return FC_VPORT_FAILED;
|
|
|
|
}
|
|
|
|
|
2008-01-18 00:02:15 +07:00
|
|
|
static int
|
2007-07-06 03:16:51 +07:00
|
|
|
qla24xx_vport_delete(struct fc_vport *fc_vport)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = fc_vport->dd_data;
|
2008-12-10 07:45:39 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
|
|
|
uint16_t id = vha->vp_idx;
|
2008-07-24 22:31:49 +07:00
|
|
|
|
2019-09-13 01:09:08 +07:00
|
|
|
set_bit(VPORT_DELETE, &vha->dpc_flags);
|
|
|
|
|
2008-07-24 22:31:49 +07:00
|
|
|
while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
|
2008-11-07 01:40:19 +07:00
|
|
|
test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
|
2008-07-24 22:31:49 +07:00
|
|
|
msleep(1000);
|
2007-07-06 03:16:51 +07:00
|
|
|
|
2018-12-11 03:36:24 +07:00
|
|
|
qla_nvme_delete(vha);
|
|
|
|
|
2007-07-06 03:16:51 +07:00
|
|
|
qla24xx_disable_vp(vha);
|
2018-07-19 04:29:52 +07:00
|
|
|
qla2x00_wait_for_sess_deletion(vha);
|
2007-07-06 03:16:51 +07:00
|
|
|
|
2010-09-04 04:57:00 +07:00
|
|
|
vha->flags.delete_progress = 1;
|
|
|
|
|
2014-01-15 11:40:38 +07:00
|
|
|
qlt_remove_target(ha, vha);
|
|
|
|
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_remove_host(vha->host);
|
|
|
|
|
|
|
|
scsi_remove_host(vha->host);
|
|
|
|
|
2011-05-11 01:18:17 +07:00
|
|
|
/* Allow timer to run to drain queued items, when removing vp */
|
|
|
|
qla24xx_deallocate_vp_id(vha);
|
|
|
|
|
2010-09-04 04:57:00 +07:00
|
|
|
if (vha->timer_active) {
|
|
|
|
qla2x00_vp_stop_timer(vha);
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_dbg(ql_dbg_user, vha, 0x7086,
|
|
|
|
"Timer for the VP[%d] has stopped\n", vha->vp_idx);
|
2010-09-04 04:57:00 +07:00
|
|
|
}
|
2008-11-07 01:40:19 +07:00
|
|
|
|
2010-09-04 04:57:00 +07:00
|
|
|
qla2x00_free_fcports(vha);
|
|
|
|
|
2009-08-26 01:36:19 +07:00
|
|
|
mutex_lock(&ha->vport_lock);
|
|
|
|
ha->cur_vport_count--;
|
|
|
|
clear_bit(vha->vp_idx, ha->vp_idx_map);
|
|
|
|
mutex_unlock(&ha->vport_lock);
|
|
|
|
|
2017-01-20 13:28:00 +07:00
|
|
|
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
|
|
|
|
vha->gnl.ldma);
|
|
|
|
|
2019-08-14 21:24:41 +07:00
|
|
|
vha->gnl.l = NULL;
|
|
|
|
|
2017-12-29 03:33:26 +07:00
|
|
|
vfree(vha->scan.l);
|
|
|
|
|
2017-03-15 23:48:43 +07:00
|
|
|
if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
|
2016-12-13 05:40:07 +07:00
|
|
|
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_warn, vha, 0x7087,
|
2016-12-13 05:40:07 +07:00
|
|
|
"Queue Pair delete failed.\n");
|
2009-02-09 11:50:13 +07:00
|
|
|
}
|
|
|
|
|
2011-07-15 02:00:13 +07:00
|
|
|
ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id);
|
2011-11-19 00:03:07 +07:00
|
|
|
scsi_host_put(vha->host);
|
2007-07-06 03:16:51 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-01-18 00:02:15 +07:00
|
|
|
static int
|
2007-07-06 03:16:51 +07:00
|
|
|
qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
|
|
|
|
{
|
|
|
|
scsi_qla_host_t *vha = fc_vport->dd_data;
|
|
|
|
|
|
|
|
if (disable)
|
|
|
|
qla24xx_disable_vp(vha);
|
|
|
|
else
|
|
|
|
qla24xx_enable_vp(vha);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-22 03:13:36 +07:00
|
|
|
struct fc_function_template qla2xxx_transport_functions = {
|
2005-04-18 03:04:54 +07:00
|
|
|
|
|
|
|
.show_host_node_name = 1,
|
|
|
|
.show_host_port_name = 1,
|
2005-08-27 09:08:10 +07:00
|
|
|
.show_host_supported_classes = 1,
|
2008-04-04 03:13:14 +07:00
|
|
|
.show_host_supported_speeds = 1,
|
2005-08-27 09:08:10 +07:00
|
|
|
|
2005-04-18 03:04:54 +07:00
|
|
|
.get_host_port_id = qla2x00_get_host_port_id,
|
|
|
|
.show_host_port_id = 1,
|
2006-02-01 07:04:51 +07:00
|
|
|
.get_host_speed = qla2x00_get_host_speed,
|
|
|
|
.show_host_speed = 1,
|
2006-02-01 07:04:56 +07:00
|
|
|
.get_host_port_type = qla2x00_get_host_port_type,
|
|
|
|
.show_host_port_type = 1,
|
2006-10-03 02:00:44 +07:00
|
|
|
.get_host_symbolic_name = qla2x00_get_host_symbolic_name,
|
|
|
|
.show_host_symbolic_name = 1,
|
2006-10-03 02:00:45 +07:00
|
|
|
.set_host_system_hostname = qla2x00_set_host_system_hostname,
|
|
|
|
.show_host_system_hostname = 1,
|
2006-10-03 02:00:46 +07:00
|
|
|
.get_host_fabric_name = qla2x00_get_host_fabric_name,
|
|
|
|
.show_host_fabric_name = 1,
|
2006-10-03 02:00:47 +07:00
|
|
|
.get_host_port_state = qla2x00_get_host_port_state,
|
|
|
|
.show_host_port_state = 1,
|
2005-04-18 03:04:54 +07:00
|
|
|
|
2005-04-18 03:06:53 +07:00
|
|
|
.dd_fcrport_size = sizeof(struct fc_port *),
|
2005-08-27 09:08:10 +07:00
|
|
|
.show_rport_supported_classes = 1,
|
2005-04-18 03:04:54 +07:00
|
|
|
|
|
|
|
.get_starget_node_name = qla2x00_get_starget_node_name,
|
|
|
|
.show_starget_node_name = 1,
|
|
|
|
.get_starget_port_name = qla2x00_get_starget_port_name,
|
|
|
|
.show_starget_port_name = 1,
|
|
|
|
.get_starget_port_id = qla2x00_get_starget_port_id,
|
|
|
|
.show_starget_port_id = 1,
|
|
|
|
|
|
|
|
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
|
|
|
|
.show_rport_dev_loss_tmo = 1,
|
|
|
|
|
2005-10-28 06:03:37 +07:00
|
|
|
.issue_fc_host_lip = qla2x00_issue_lip,
|
2008-07-11 06:55:47 +07:00
|
|
|
.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
|
|
|
|
.terminate_rport_io = qla2x00_terminate_rport_io,
|
2006-02-01 07:05:02 +07:00
|
|
|
.get_fc_host_stats = qla2x00_get_fc_host_stats,
|
2013-08-27 12:37:40 +07:00
|
|
|
.reset_fc_host_stats = qla2x00_reset_host_stats,
|
2007-07-06 03:16:51 +07:00
|
|
|
|
|
|
|
.vport_create = qla24xx_vport_create,
|
|
|
|
.vport_disable = qla24xx_vport_disable,
|
|
|
|
.vport_delete = qla24xx_vport_delete,
|
2010-01-13 04:02:47 +07:00
|
|
|
.bsg_request = qla24xx_bsg_request,
|
|
|
|
.bsg_timeout = qla24xx_bsg_timeout,
|
2007-07-06 03:16:51 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct fc_function_template qla2xxx_transport_vport_functions = {
|
|
|
|
|
|
|
|
.show_host_node_name = 1,
|
|
|
|
.show_host_port_name = 1,
|
|
|
|
.show_host_supported_classes = 1,
|
|
|
|
|
|
|
|
.get_host_port_id = qla2x00_get_host_port_id,
|
|
|
|
.show_host_port_id = 1,
|
|
|
|
.get_host_speed = qla2x00_get_host_speed,
|
|
|
|
.show_host_speed = 1,
|
|
|
|
.get_host_port_type = qla2x00_get_host_port_type,
|
|
|
|
.show_host_port_type = 1,
|
|
|
|
.get_host_symbolic_name = qla2x00_get_host_symbolic_name,
|
|
|
|
.show_host_symbolic_name = 1,
|
|
|
|
.set_host_system_hostname = qla2x00_set_host_system_hostname,
|
|
|
|
.show_host_system_hostname = 1,
|
|
|
|
.get_host_fabric_name = qla2x00_get_host_fabric_name,
|
|
|
|
.show_host_fabric_name = 1,
|
|
|
|
.get_host_port_state = qla2x00_get_host_port_state,
|
|
|
|
.show_host_port_state = 1,
|
|
|
|
|
|
|
|
.dd_fcrport_size = sizeof(struct fc_port *),
|
|
|
|
.show_rport_supported_classes = 1,
|
|
|
|
|
|
|
|
.get_starget_node_name = qla2x00_get_starget_node_name,
|
|
|
|
.show_starget_node_name = 1,
|
|
|
|
.get_starget_port_name = qla2x00_get_starget_port_name,
|
|
|
|
.show_starget_port_name = 1,
|
|
|
|
.get_starget_port_id = qla2x00_get_starget_port_id,
|
|
|
|
.show_starget_port_id = 1,
|
|
|
|
|
|
|
|
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
|
|
|
|
.show_rport_dev_loss_tmo = 1,
|
|
|
|
|
|
|
|
.issue_fc_host_lip = qla2x00_issue_lip,
|
2008-07-11 06:55:47 +07:00
|
|
|
.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
|
|
|
|
.terminate_rport_io = qla2x00_terminate_rport_io,
|
2007-07-06 03:16:51 +07:00
|
|
|
.get_fc_host_stats = qla2x00_get_fc_host_stats,
|
2013-08-27 12:37:40 +07:00
|
|
|
.reset_fc_host_stats = qla2x00_reset_host_stats,
|
|
|
|
|
2010-01-13 04:02:47 +07:00
|
|
|
.bsg_request = qla24xx_bsg_request,
|
|
|
|
.bsg_timeout = qla24xx_bsg_timeout,
|
2005-04-18 03:04:54 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-11-07 01:40:19 +07:00
|
|
|
qla2x00_init_host_attr(scsi_qla_host_t *vha)
|
2005-04-18 03:04:54 +07:00
|
|
|
{
|
2008-11-07 01:40:19 +07:00
|
|
|
struct qla_hw_data *ha = vha->hw;
|
2019-03-13 01:08:15 +07:00
|
|
|
u32 speeds = FC_PORTSPEED_UNKNOWN;
|
2008-04-04 03:13:14 +07:00
|
|
|
|
2010-09-16 04:52:30 +07:00
|
|
|
fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
|
|
|
|
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
|
2017-06-14 10:47:22 +07:00
|
|
|
fc_host_supported_classes(vha->host) = ha->base_qpair->enable_class_2 ?
|
2012-05-16 01:34:28 +07:00
|
|
|
(FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3;
|
2008-11-07 01:40:19 +07:00
|
|
|
fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
|
|
|
|
fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
|
2008-04-04 03:13:14 +07:00
|
|
|
|
2012-02-10 02:15:34 +07:00
|
|
|
if (IS_CNA_CAPABLE(ha))
|
2019-03-13 01:08:15 +07:00
|
|
|
speeds = FC_PORTSPEED_10GBIT;
|
|
|
|
else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
|
|
|
|
if (ha->max_supported_speed == 2) {
|
|
|
|
if (ha->min_supported_speed <= 6)
|
|
|
|
speeds |= FC_PORTSPEED_64GBIT;
|
|
|
|
}
|
|
|
|
if (ha->max_supported_speed == 2 ||
|
|
|
|
ha->max_supported_speed == 1) {
|
|
|
|
if (ha->min_supported_speed <= 5)
|
|
|
|
speeds |= FC_PORTSPEED_32GBIT;
|
|
|
|
}
|
|
|
|
if (ha->max_supported_speed == 2 ||
|
|
|
|
ha->max_supported_speed == 1 ||
|
|
|
|
ha->max_supported_speed == 0) {
|
|
|
|
if (ha->min_supported_speed <= 4)
|
|
|
|
speeds |= FC_PORTSPEED_16GBIT;
|
|
|
|
}
|
|
|
|
if (ha->max_supported_speed == 1 ||
|
|
|
|
ha->max_supported_speed == 0) {
|
|
|
|
if (ha->min_supported_speed <= 3)
|
|
|
|
speeds |= FC_PORTSPEED_8GBIT;
|
|
|
|
}
|
|
|
|
if (ha->max_supported_speed == 0) {
|
|
|
|
if (ha->min_supported_speed <= 2)
|
|
|
|
speeds |= FC_PORTSPEED_4GBIT;
|
|
|
|
}
|
|
|
|
} else if (IS_QLA2031(ha))
|
|
|
|
speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT|
|
|
|
|
FC_PORTSPEED_4GBIT;
|
|
|
|
else if (IS_QLA25XX(ha) || IS_QLAFX00(ha))
|
|
|
|
speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT|
|
|
|
|
FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
|
2008-04-04 03:13:26 +07:00
|
|
|
else if (IS_QLA24XX_TYPE(ha))
|
2019-03-13 01:08:15 +07:00
|
|
|
speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT|
|
|
|
|
FC_PORTSPEED_1GBIT;
|
2008-04-04 03:13:14 +07:00
|
|
|
else if (IS_QLA23XX(ha))
|
2019-03-13 01:08:15 +07:00
|
|
|
speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
|
2008-04-04 03:13:14 +07:00
|
|
|
else
|
2019-03-13 01:08:15 +07:00
|
|
|
speeds = FC_PORTSPEED_1GBIT;
|
|
|
|
|
|
|
|
fc_host_supported_speeds(vha->host) = speeds;
|
2005-04-18 03:04:54 +07:00
|
|
|
}
|