1
0
Fork 0

SCSI misc on 20171114

This is mostly updates of the usual suspects: lpfc, qla2xxx, hisi_sas,
 megaraid_sas, pm80xx, mpt3sas, be2iscsi, hpsa. and a host of minor
 updates.
 
 There's no major behaviour change or additions to the core in all of
 this, so the potential for regressions should be small (biggest
 potential being in the scsi error handler changes).
 
 Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJaCxtCAAoJEAVr7HOZEZN4d9EQAI+OHP6ss6zjKKC21c9jNPcH
 NhLrNv37gHg/LA2VXeUEL9RGUjCGLIUrI4HsrxzkFAMLKP4TkshMs8/2RvczY+Sa
 VpayPqVybEKLIS6ipQyM1SLIQff2nvtDVcN/T+8z1lkk45TrbA6ZGuwUwd2aJyEA
 2V2wtg51ObnL0Nr9QPPll0JrtL1AnCZyRlu9XrwTZuuSBZwk93opIuuvbZm/3dVg
 Ir4GSS4Y+PuHIfu4cxqdsPMdzRdY9I2me1YiE4jeFSn1/VTAjL4HBz7fO9eITT42
 VhXSpDz1XvFsa9dJ0ubkqoALpJzCfOcBw+EuGvSydLEvOBoEVwMccdfaD9lT1zc5
 L9e1Z5qqJoq7hTA6xTXCYfWG73I9HYvljtmc8yudKHhADOdnSTUXhaO6uBF0RNqD
 OxPSA1RZwRx3c6lDOcK6BTtvLAkTEuYKdrWSKJi0w+QXJAyQ6etqbmsKpmPdRim7
 Z4ZSpJFro2gyo9gcdJO0ykTG+z3U7Z/ay1sNgnuprsv+eU/QjUdlAPl18o79EkRf
 H54zZggZ4wC6q/cFVVt4Vx+V+oqIeu38s7NDXS9UltLoTZPm2EzDW6pXd/38Z4Tf
 a1oBAUET8kYLC90P8sVZxUIHZjITlpgDbyE2Lq00PMYXhk8S4IxF0aMN5RvVqzUv
 +7N2HrHkSSgG1nhw1t+E
 =3O85
 -----END PGP SIGNATURE-----

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

Pull SCSI updates from James Bottomley:
 "This is mostly updates of the usual suspects: lpfc, qla2xxx, hisi_sas,
  megaraid_sas, pm80xx, mpt3sas, be2iscsi, hpsa. and a host of minor
  updates.

  There's no major behaviour change or additions to the core in all of
  this, so the potential for regressions should be small (biggest
  potential being in the scsi error handler changes)"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (203 commits)
  scsi: lpfc: Fix hard lock up NMI in els timeout handling.
  scsi: mpt3sas: remove a stray KERN_INFO
  scsi: mpt3sas: cleanup _scsih_pcie_enumeration_event()
  scsi: aacraid: use timespec64 instead of timeval
  scsi: scsi_transport_fc: add 64GBIT and 128GBIT port speed definitions
  scsi: qla2xxx: Suppress a kernel complaint in qla_init_base_qpair()
  scsi: mpt3sas: fix dma_addr_t casts
  scsi: be2iscsi: Use kasprintf
  scsi: storvsc: Avoid excessive host scan on controller change
  scsi: lpfc: fix kzalloc-simple.cocci warnings
  scsi: mpt3sas: Update mpt3sas driver version.
  scsi: mpt3sas: Fix sparse warnings
  scsi: mpt3sas: Fix nvme drives checking for tlr.
  scsi: mpt3sas: NVMe drive support for BTDHMAPPING ioctl command and log info
  scsi: mpt3sas: Add-Task-management-debug-info-for-NVMe-drives.
  scsi: mpt3sas: scan and add nvme device after controller reset
  scsi: mpt3sas: Set NVMe device queue depth as 128
  scsi: mpt3sas: Handle NVMe PCIe device related events generated from firmware.
  scsi: mpt3sas: API's to remove nvme drive from sml
  scsi: mpt3sas: API 's to support NVMe drive addition to SML
  ...
hifive-unleashed-5.1
Linus Torvalds 2017-11-14 16:23:44 -08:00
commit 670ffccb2f
131 changed files with 8215 additions and 2409 deletions

View File

@ -28,7 +28,7 @@ SCSI commands can be transported over just about any kind of bus, and
are the default protocol for storage devices attached to USB, SATA, SAS,
Fibre Channel, FireWire, and ATAPI devices. SCSI packets are also
commonly exchanged over Infiniband,
`I20 <http://i2o.shadowconnect.com/faq.php>`__, TCP/IP
`I2O <http://i2o.shadowconnect.com/faq.php>`__, TCP/IP
(`iSCSI <https://en.wikipedia.org/wiki/ISCSI>`__), even `Parallel
ports <http://cyberelk.net/tim/parport/parscsi.html>`__.

View File

@ -50,10 +50,11 @@ parameters may be changed at runtime by the command
mac5380= [HW,SCSI]
See drivers/scsi/mac_scsi.c.
max_luns= [SCSI] Maximum number of LUNs to probe.
scsi_mod.max_luns=
[SCSI] Maximum number of LUNs to probe.
Should be between 1 and 2^32-1.
max_report_luns=
scsi_mod.max_report_luns=
[SCSI] Maximum number of LUNs received.
Should be between 1 and 16384.
@ -80,15 +81,17 @@ parameters may be changed at runtime by the command
scsi_debug_*= [SCSI]
See drivers/scsi/scsi_debug.c.
scsi_default_dev_flags=
scsi_mod.default_dev_flags=
[SCSI] SCSI default device flags
Format: <integer>
scsi_dev_flags= [SCSI] Black/white list entry for vendor and model
scsi_mod.dev_flags=
[SCSI] Black/white list entry for vendor and model
Format: <vendor>:<model>:<flags>
(flags are integer value)
scsi_logging_level= [SCSI] a bit mask of logging levels
scsi_mod.scsi_logging_level=
[SCSI] a bit mask of logging levels
See drivers/scsi/scsi_logging.h for bits. Also
settable via sysctl at dev.scsi.logging_level
(/proc/sys/dev/scsi/logging_level).

View File

@ -21,7 +21,7 @@ http://www.t10.org/members/w_pqi2.htm
Supported devices:
------------------
<Controller names to be added as they become publically available.>
<Controller names to be added as they become publicly available.>
smartpqi specific entries in /sys
-----------------------------

View File

@ -1 +1,2 @@
53c700_d.h
scsi_devinfo_tbl.c

View File

@ -192,6 +192,14 @@ clean-files := 53c700_d.h 53c700_u.h
$(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
$(obj)/scsi_sysfs.o: $(obj)/scsi_devinfo_tbl.c
quiet_cmd_bflags = GEN $@
cmd_bflags = sed -n 's/.*BLIST_\([A-Z0-9_]*\) *.*/BLIST_FLAG_NAME(\1),/p' $< > $@
$(obj)/scsi_devinfo_tbl.c: include/scsi/scsi_devinfo.h
$(call if_changed,bflags)
# If you want to play with the firmware, uncomment
# GENERATE_FIRMWARE := 1

View File

@ -1908,8 +1908,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
switch (extended_msg[2]) {
case EXTENDED_SDTR:
case EXTENDED_WDTR:
case EXTENDED_MODIFY_DATA_POINTER:
case EXTENDED_EXTENDED_IDENTIFY:
tmp = 0;
}
} else if (len) {
@ -1932,18 +1930,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* reject it.
*/
default:
if (!tmp) {
shost_printk(KERN_ERR, instance, "rejecting message ");
spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
scmd_printk(KERN_INFO, cmd,
"rejecting unknown message %02x\n",
tmp);
else
if (tmp == EXTENDED_MESSAGE)
scmd_printk(KERN_INFO, cmd,
"rejecting unknown extended message code %02x, length %d\n",
extended_msg[1], extended_msg[0]);
extended_msg[2], extended_msg[1]);
else if (tmp)
scmd_printk(KERN_INFO, cmd,
"rejecting unknown message code %02x\n",
tmp);
msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);

View File

@ -2383,19 +2383,19 @@ fib_free_out:
goto out;
}
int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now)
int aac_send_safw_hostttime(struct aac_dev *dev, struct timespec64 *now)
{
struct tm cur_tm;
char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ";
u32 datasize = sizeof(wellness_str);
unsigned long local_time;
time64_t local_time;
int ret = -ENODEV;
if (!dev->sa_firmware)
goto out;
local_time = (u32)(now->tv_sec - (sys_tz.tz_minuteswest * 60));
time_to_tm(local_time, 0, &cur_tm);
local_time = (now->tv_sec - (sys_tz.tz_minuteswest * 60));
time64_to_tm(local_time, 0, &cur_tm);
cur_tm.tm_mon += 1;
cur_tm.tm_year += 1900;
wellness_str[8] = bin2bcd(cur_tm.tm_hour);
@ -2412,7 +2412,7 @@ out:
return ret;
}
int aac_send_hosttime(struct aac_dev *dev, struct timeval *now)
int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now)
{
int ret = -ENOMEM;
struct fib *fibptr;
@ -2424,7 +2424,7 @@ int aac_send_hosttime(struct aac_dev *dev, struct timeval *now)
aac_fib_init(fibptr);
info = (__le32 *)fib_data(fibptr);
*info = cpu_to_le32(now->tv_sec);
*info = cpu_to_le32(now->tv_sec); /* overflow in y2106 */
ret = aac_fib_send(SendHostTime, fibptr, sizeof(*info), FsaNormal,
1, 1, NULL, NULL);
@ -2496,7 +2496,7 @@ int aac_command_thread(void *data)
}
if (!time_before(next_check_jiffies,next_jiffies)
&& ((difference = next_jiffies - jiffies) <= 0)) {
struct timeval now;
struct timespec64 now;
int ret;
/* Don't even try to talk to adapter if its sick */
@ -2506,15 +2506,15 @@ int aac_command_thread(void *data)
next_check_jiffies = jiffies
+ ((long)(unsigned)check_interval)
* HZ;
do_gettimeofday(&now);
ktime_get_real_ts64(&now);
/* Synchronize our watches */
if (((1000000 - (1000000 / HZ)) > now.tv_usec)
&& (now.tv_usec > (1000000 / HZ)))
difference = (((1000000 - now.tv_usec) * HZ)
+ 500000) / 1000000;
if (((NSEC_PER_SEC - (NSEC_PER_SEC / HZ)) > now.tv_nsec)
&& (now.tv_nsec > (NSEC_PER_SEC / HZ)))
difference = (((NSEC_PER_SEC - now.tv_nsec) * HZ)
+ NSEC_PER_SEC / 2) / NSEC_PER_SEC;
else {
if (now.tv_usec > 500000)
if (now.tv_nsec > NSEC_PER_SEC / 2)
++now.tv_sec;
if (dev->sa_firmware)

View File

@ -2212,7 +2212,7 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
* by the capabilities of the bus connectivity of and sync settings for
* the target.
*/
const struct ahc_syncrate *
static const struct ahc_syncrate *
ahc_devlimited_syncrate(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
u_int *period, u_int *ppr_options, role_t role)

View File

@ -1141,7 +1141,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
* or forcing transfer negotiations on the next command to any
* target.
*/
void
static void
ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
{
int i;

View File

@ -721,11 +721,8 @@ Out:
*/
static void asd_chip_reset(struct asd_ha_struct *asd_ha)
{
struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
ASD_DPRINTK("chip reset for %s\n", pci_name(asd_ha->pcidev));
asd_chip_hardrst(asd_ha);
sas_ha->notify_ha_event(sas_ha, HAE_RESET);
}
/* ---------- Done List Routines ---------- */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -81,12 +81,12 @@ static inline void queue_tail_inc(struct be_queue_info *q)
/*ISCSI */
struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
u32 min_eqd; /* in usecs */
u32 max_eqd; /* in usecs */
u32 prev_eqd; /* in usecs */
u32 et_eqd; /* configured val when aic is off */
ulong jiffies;
u64 eq_prev; /* Used to calculate eqe */
unsigned long jiffies;
u32 eq_prev; /* Used to calculate eqe */
u32 prev_eqd;
#define BEISCSI_EQ_DELAY_MIN 0
#define BEISCSI_EQ_DELAY_DEF 32
#define BEISCSI_EQ_DELAY_MAX 128
};
struct be_eq_obj {
@ -148,9 +148,8 @@ struct be_ctrl_info {
/* TAG is from 1...MAX_MCC_CMD, MASK includes MAX_MCC_CMD */
#define MCC_Q_CMD_TAG_MASK ((MAX_MCC_CMD << 1) - 1)
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
#define mcc_timeout 120000 /* 12s timeout */
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
/* Returns number of pages spanned by the data starting at the given addr */
#define PAGES_4K_SPANNED(_address, size) \

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -675,8 +675,8 @@ static int be_mbox_notify(struct be_ctrl_info *ctrl)
return status;
}
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
bool embedded, u8 sge_cnt)
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, u32 payload_len,
bool embedded, u8 sge_cnt)
{
if (embedded)
wrb->emb_sgecnt_special |= MCC_WRB_EMBEDDED_MASK;
@ -688,7 +688,7 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
}
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
u8 subsystem, u8 opcode, int cmd_len)
u8 subsystem, u8 opcode, u32 cmd_len)
{
req_hdr->opcode = opcode;
req_hdr->subsystem = subsystem;
@ -947,7 +947,6 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
default:
mutex_unlock(&ctrl->mbox_lock);
BUG();
return -ENXIO;
}
be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
if (queue_type != QTYPE_SGL)
@ -1522,6 +1521,52 @@ int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba)
return ret;
}
int beiscsi_set_host_data(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_cmd_set_host_data *ioctl;
struct be_mcc_wrb *wrb;
int ret = 0;
if (is_chip_be2_be3r(phba))
return ret;
mutex_lock(&ctrl->mbox_lock);
wrb = wrb_from_mbox(&ctrl->mbox_mem);
memset(wrb, 0, sizeof(*wrb));
ioctl = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0);
be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_SET_HOST_DATA,
EMBED_MBX_MAX_PAYLOAD_SIZE);
ioctl->param.req.param_id = BE_CMD_SET_HOST_PARAM_ID;
ioctl->param.req.param_len =
snprintf((char *)ioctl->param.req.param_data,
sizeof(ioctl->param.req.param_data),
"Linux iSCSI v%s", BUILD_STR);
ioctl->param.req.param_len = ALIGN(ioctl->param.req.param_len, 4);
if (ioctl->param.req.param_len > BE_CMD_MAX_DRV_VERSION)
ioctl->param.req.param_len = BE_CMD_MAX_DRV_VERSION;
ret = be_mbox_notify(ctrl);
if (!ret) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : HBA set host driver version\n");
} else {
/**
* Check "MCC_STATUS_INVALID_LENGTH" for SKH.
* Older FW versions return this error.
*/
if (ret == MCC_STATUS_ILLEGAL_REQUEST ||
ret == MCC_STATUS_INVALID_LENGTH)
__beiscsi_log(phba, KERN_INFO,
"BG_%d : HBA failed to set host driver version\n");
}
mutex_unlock(&ctrl->mbox_lock);
return ret;
}
int beiscsi_set_uer_feature(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -230,6 +230,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
#define OPCODE_COMMON_FUNCTION_RESET 61
#define OPCODE_COMMON_GET_PORT_NAME 77
#define OPCODE_COMMON_SET_HOST_DATA 93
#define OPCODE_COMMON_SET_FEATURES 191
/**
@ -737,6 +738,30 @@ struct be_cmd_hba_name {
u8 initiator_alias[BE_INI_ALIAS_LEN];
} __packed;
/******************** COMMON SET HOST DATA *******************/
#define BE_CMD_SET_HOST_PARAM_ID 0x2
#define BE_CMD_MAX_DRV_VERSION 0x30
struct be_sethost_req {
u32 param_id;
u32 param_len;
u32 param_data[32];
};
struct be_sethost_resp {
u32 rsvd0;
};
struct be_cmd_set_host_data {
union {
struct be_cmd_req_hdr req_hdr;
struct be_cmd_resp_hdr resp_hdr;
} h;
union {
struct be_sethost_req req;
struct be_sethost_resp resp;
} param;
} __packed;
/******************** COMMON SET Features *******************/
#define BE_CMD_SET_FEATURE_UER 0x10
#define BE_CMD_UER_SUPP_BIT 0x1
@ -793,8 +818,6 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
struct be_queue_info *mccq,
struct be_queue_info *cq);
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag);
int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
@ -847,6 +870,7 @@ int beiscsi_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba);
int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba);
int beiscsi_set_uer_feature(struct beiscsi_hba *phba);
int beiscsi_set_host_data(struct beiscsi_hba *phba);
struct be_default_pdu_context {
u32 dw[4];
@ -1274,19 +1298,9 @@ struct be_cmd_get_port_name {
* a read command
*/
#define TGT_CTX_UPDT_CMD 7 /* Target context update */
#define TGT_STS_CMD 8 /* Target R2T and other BHS
* where only the status number
* need to be updated
*/
#define TGT_DATAIN_CMD 9 /* Target Data-Ins in response
* to read command
*/
#define TGT_SOS_PDU 10 /* Target:standalone status
* response
*/
#define TGT_DM_CMD 11 /* Indicates that the bhs
* preparedby
* driver should not be touched
* prepared by driver should not
* be touched.
*/
/* Returns the number of items in the field array. */
@ -1444,9 +1458,9 @@ struct be_cmd_get_port_name {
* the cxn
*/
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, u32 payload_len,
bool embedded, u8 sge_cnt);
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
u8 subsystem, u8 opcode, int cmd_len);
u8 subsystem, u8 opcode, u32 cmd_len);
#endif /* !BEISCSI_CMDS_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -683,41 +683,6 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
return 0;
}
/**
* beiscsi_get_initname - Read Initiator Name from flash
* @buf: buffer bointer
* @phba: The device priv structure instance
*
* returns number of bytes
*/
static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
{
int rc;
unsigned int tag;
struct be_mcc_wrb *wrb;
struct be_cmd_hba_name *resp;
tag = be_cmd_get_initname(phba);
if (!tag) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Getting Initiator Name Failed\n");
return -EBUSY;
}
rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BS_%d : Initiator Name MBX Failed\n");
return rc;
}
resp = embedded_payload(wrb);
rc = sprintf(buf, "%s\n", resp->initiator_name);
return rc;
}
/**
* beiscsi_get_port_state - Get the Port State
* @shost : pointer to scsi_host structure
@ -772,7 +737,6 @@ static void beiscsi_get_port_speed(struct Scsi_Host *shost)
* @param: parameter type identifier
* @buf: buffer pointer
*
* returns host parameter
*/
int beiscsi_get_host_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf)
@ -783,7 +747,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return -EBUSY;
return 0;
}
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : In beiscsi_get_host_param, param = %d\n", param);
@ -794,15 +758,19 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
if (status < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : beiscsi_get_macaddr Failed\n");
return status;
return 0;
}
break;
case ISCSI_HOST_PARAM_INITIATOR_NAME:
status = beiscsi_get_initname(buf, phba);
/* try fetching user configured name first */
status = beiscsi_get_initiator_name(phba, buf, true);
if (status < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Retreiving Initiator Name Failed\n");
return status;
status = beiscsi_get_initiator_name(phba, buf, false);
if (status < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Retreiving Initiator Name Failed\n");
status = 0;
}
}
break;
case ISCSI_HOST_PARAM_PORT_STATE:

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -455,14 +455,12 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
return -ENOMEM;
phba->ctrl.csr = addr;
phba->csr_va = addr;
phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2);
addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024);
if (addr == NULL)
goto pci_map_err;
phba->ctrl.db = addr;
phba->db_va = addr;
phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4);
if (phba->generation == BE_GEN2)
pcicfg_reg = 1;
@ -476,7 +474,6 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
goto pci_map_err;
phba->ctrl.pcicfg = addr;
phba->pci_va = addr;
phba->pci_pa.u.a64.address = pci_resource_start(pcidev, pcicfg_reg);
return 0;
pci_map_err:
@ -790,6 +787,24 @@ static irqreturn_t be_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void beiscsi_free_irqs(struct beiscsi_hba *phba)
{
struct hwi_context_memory *phwi_context;
int i;
if (!phba->pcidev->msix_enabled) {
if (phba->pcidev->irq)
free_irq(phba->pcidev->irq, phba);
return;
}
phwi_context = phba->phwi_ctrlr->phwi_ctxt;
for (i = 0; i <= phba->num_cpus; i++) {
free_irq(pci_irq_vector(phba->pcidev, i),
&phwi_context->be_eq[i]);
kfree(phba->msi_name[i]);
}
}
static int beiscsi_init_irqs(struct beiscsi_hba *phba)
{
@ -803,15 +818,14 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
if (pcidev->msix_enabled) {
for (i = 0; i < phba->num_cpus; i++) {
phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
GFP_KERNEL);
phba->msi_name[i] = kasprintf(GFP_KERNEL,
"beiscsi_%02x_%02x",
phba->shost->host_no, i);
if (!phba->msi_name[i]) {
ret = -ENOMEM;
goto free_msix_irqs;
}
sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
phba->shost->host_no, i);
ret = request_irq(pci_irq_vector(pcidev, i),
be_isr_msix, 0, phba->msi_name[i],
&phwi_context->be_eq[i]);
@ -824,13 +838,12 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
goto free_msix_irqs;
}
}
phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL);
phba->msi_name[i] = kasprintf(GFP_KERNEL, "beiscsi_mcc_%02x",
phba->shost->host_no);
if (!phba->msi_name[i]) {
ret = -ENOMEM;
goto free_msix_irqs;
}
sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
phba->shost->host_no);
ret = request_irq(pci_irq_vector(pcidev, i), be_isr_mcc, 0,
phba->msi_name[i], &phwi_context->be_eq[i]);
if (ret) {
@ -924,12 +937,11 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
* this can happen if clean_task is called on a task that
* failed in xmit_task or alloc_pdu.
*/
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
"BM_%d : Double Free in IO SGL io_sgl_free_index=%d,"
"value there=%p\n", phba->io_sgl_free_index,
phba->io_sgl_hndl_base
[phba->io_sgl_free_index]);
spin_unlock_irqrestore(&phba->io_sgl_lock, flags);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
"BM_%d : Double Free in IO SGL io_sgl_free_index=%d, value there=%p\n",
phba->io_sgl_free_index,
phba->io_sgl_hndl_base[phba->io_sgl_free_index]);
spin_unlock_irqrestore(&phba->io_sgl_lock, flags);
return;
}
phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
@ -1864,8 +1876,8 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget)
be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
code = (sol->dw[offsetof(struct amap_sol_cqe, code) /
32] & CQE_CODE_MASK);
code = (sol->dw[offsetof(struct amap_sol_cqe, code) / 32] &
CQE_CODE_MASK);
/* Get the CID */
if (is_chip_be2_be3r(phba)) {
@ -3024,7 +3036,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
mem->dma = paddr;
ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
phwi_context->cur_eqd);
BEISCSI_EQ_DELAY_DEF);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_cmd_eq_create"
@ -3508,13 +3520,14 @@ static int be_mcc_queues_create(struct beiscsi_hba *phba,
goto err;
/* Ask BE to create MCC compl queue; */
if (phba->pcidev->msix_enabled) {
if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq
[phba->num_cpus].q, false, true, 0))
goto mcc_cq_free;
if (beiscsi_cmd_cq_create(ctrl, cq,
&phwi_context->be_eq[phba->num_cpus].q,
false, true, 0))
goto mcc_cq_free;
} else {
if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq[0].q,
false, true, 0))
goto mcc_cq_free;
goto mcc_cq_free;
}
/* Alloc MCC queue */
@ -3689,9 +3702,6 @@ static int hwi_init_port(struct beiscsi_hba *phba)
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
phwi_context->max_eqd = 128;
phwi_context->min_eqd = 0;
phwi_context->cur_eqd = 32;
/* set port optic state to unknown */
phba->optic_state = 0xff;
@ -4792,10 +4802,10 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
sg = scsi_sglist(sc);
if (sc->sc_data_direction == DMA_TO_DEVICE)
writedir = 1;
else
else
writedir = 0;
return phba->iotask_fn(task, sg, num_sg, xferlen, writedir);
return phba->iotask_fn(task, sg, num_sg, xferlen, writedir);
}
/**
@ -4917,6 +4927,13 @@ void beiscsi_start_boot_work(struct beiscsi_hba *phba, unsigned int s_handle)
schedule_work(&phba->boot_work);
}
/**
* Boot flag info for iscsi-utilities
* Bit 0 Block valid flag
* Bit 1 Firmware booting selected
*/
#define BEISCSI_SYSFS_ISCSI_BOOT_FLAGS 3
static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
{
struct beiscsi_hba *phba = data;
@ -4972,7 +4989,7 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
auth_data.chap.intr_secret);
break;
case ISCSI_BOOT_TGT_FLAGS:
rc = sprintf(str, "2\n");
rc = sprintf(str, "%d\n", BEISCSI_SYSFS_ISCSI_BOOT_FLAGS);
break;
case ISCSI_BOOT_TGT_NIC_ASSOC:
rc = sprintf(str, "0\n");
@ -5004,7 +5021,7 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
switch (type) {
case ISCSI_BOOT_ETH_FLAGS:
rc = sprintf(str, "2\n");
rc = sprintf(str, "%d\n", BEISCSI_SYSFS_ISCSI_BOOT_FLAGS);
break;
case ISCSI_BOOT_ETH_INDEX:
rc = sprintf(str, "0\n");
@ -5209,8 +5226,8 @@ static void beiscsi_eqd_update_work(struct work_struct *work)
if (eqd < 8)
eqd = 0;
eqd = min_t(u32, eqd, phwi_context->max_eqd);
eqd = max_t(u32, eqd, phwi_context->min_eqd);
eqd = min_t(u32, eqd, BEISCSI_EQ_DELAY_MAX);
eqd = max_t(u32, eqd, BEISCSI_EQ_DELAY_MIN);
aic->jiffies = now;
aic->eq_prev = pbe_eq->cq_count;
@ -5298,6 +5315,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
be2iscsi_enable_msix(phba);
beiscsi_get_params(phba);
beiscsi_set_host_data(phba);
/* Re-enable UER. If different TPE occurs then it is recoverable. */
beiscsi_set_uer_feature(phba);
@ -5387,15 +5405,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
hwi_disable_intr(phba);
if (phba->pcidev->msix_enabled) {
for (i = 0; i <= phba->num_cpus; i++) {
free_irq(pci_irq_vector(phba->pcidev, i),
&phwi_context->be_eq[i]);
kfree(phba->msi_name[i]);
}
} else
if (phba->pcidev->irq)
free_irq(phba->pcidev->irq, phba);
beiscsi_free_irqs(phba);
pci_free_irq_vectors(phba->pcidev);
for (i = 0; i < phba->num_cpus; i++) {
@ -5586,12 +5596,12 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : be_ctrl_init failed\n");
goto hba_free;
goto free_hba;
}
ret = beiscsi_init_sliport(phba);
if (ret)
goto hba_free;
goto free_hba;
spin_lock_init(&phba->io_sgl_lock);
spin_lock_init(&phba->mgmt_sgl_lock);
@ -5604,6 +5614,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
}
beiscsi_get_port_name(&phba->ctrl, phba);
beiscsi_get_params(phba);
beiscsi_set_host_data(phba);
beiscsi_set_uer_feature(phba);
be2iscsi_enable_msix(phba);
@ -5671,13 +5682,13 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe-"
"Failed to beiscsi_init_irqs\n");
goto free_blkenbld;
goto disable_iopoll;
}
hwi_enable_intr(phba);
ret = iscsi_host_add(phba->shost, &phba->pcidev->dev);
if (ret)
goto free_blkenbld;
goto free_irqs;
/* set online bit after port is operational */
set_bit(BEISCSI_HBA_ONLINE, &phba->state);
@ -5713,12 +5724,15 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
"\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
return 0;
free_blkenbld:
destroy_workqueue(phba->wq);
free_irqs:
hwi_disable_intr(phba);
beiscsi_free_irqs(phba);
disable_iopoll:
for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i];
irq_poll_disable(&pbe_eq->iopoll);
}
destroy_workqueue(phba->wq);
free_twq:
hwi_cleanup_port(phba);
beiscsi_cleanup_port(phba);
@ -5727,9 +5741,9 @@ free_port:
pci_free_consistent(phba->pcidev,
phba->ctrl.mbox_mem_alloced.size,
phba->ctrl.mbox_mem_alloced.va,
phba->ctrl.mbox_mem_alloced.dma);
phba->ctrl.mbox_mem_alloced.dma);
beiscsi_unmap_pci_function(phba);
hba_free:
free_hba:
pci_disable_msix(phba->pcidev);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -31,7 +31,7 @@
#include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi"
#define BUILD_STR "11.4.0.0"
#define BUILD_STR "11.4.0.1"
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@ -59,7 +59,7 @@
#define BE2_DEFPDU_DATA_SZ 8192
#define BE2_MAX_NUM_CQ_PROC 512
#define MAX_CPUS 64
#define MAX_CPUS 64U
#define BEISCSI_MAX_NUM_CPUS 7
#define BEISCSI_VER_STRLEN 32
@ -77,9 +77,7 @@
#define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */
#define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */
#define BEISCSI_NUM_DEVICES_SUPPORTED 0x01
#define BEISCSI_MAX_FRAGS_INIT 192
#define BE_NUM_MSIX_ENTRIES 1
#define BE_SENSE_INFO_SIZE 258
#define BE_ISCSI_PDU_HEADER_SIZE 64
@ -155,8 +153,6 @@
#define PAGES_REQUIRED(x) \
((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
#define BEISCSI_MSI_NAME 20 /* size of msi_name string */
#define MEM_DESCR_OFFSET 8
#define BEISCSI_DEFQ_HDR 1
#define BEISCSI_DEFQ_DATA 0
@ -209,13 +205,8 @@ struct mem_array {
};
struct be_mem_descriptor {
unsigned int index; /* Index of this memory parameter */
unsigned int category; /* type indicates cached/non-cached */
unsigned int num_elements; /* number of elements in this
* descriptor
*/
unsigned int alignment_mask; /* Alignment mask for this block */
unsigned int size_in_bytes; /* Size required by memory block */
unsigned int num_elements;
struct mem_array *mem_array;
};
@ -238,32 +229,12 @@ struct hba_parameters {
unsigned int num_eq_entries;
unsigned int wrbs_per_cxn;
unsigned int hwi_ws_sz;
/**
* These are calculated from other params. They're here
* for debug purposes
*/
unsigned int num_mcc_pages;
unsigned int num_mcc_cq_pages;
unsigned int num_cq_pages;
unsigned int num_eq_pages;
unsigned int num_async_pdu_buf_pages;
unsigned int num_async_pdu_buf_sgl_pages;
unsigned int num_async_pdu_buf_cq_pages;
unsigned int num_async_pdu_hdr_pages;
unsigned int num_async_pdu_hdr_sgl_pages;
unsigned int num_async_pdu_hdr_cq_pages;
unsigned int num_sge;
};
#define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \
(phwi_ctrlr->wrb_context[cri].ulp_num)
struct hwi_wrb_context {
spinlock_t wrb_lock;
struct list_head wrb_handle_list;
struct list_head wrb_handle_drvr_list;
struct wrb_handle **pwrb_handle_base;
struct wrb_handle **pwrb_handle_basestd;
struct iscsi_wrb *plast_wrb;
@ -272,8 +243,6 @@ struct hwi_wrb_context {
unsigned short wrb_handles_available;
unsigned short cid;
uint8_t ulp_num; /* ULP to which CID binded */
uint16_t register_set;
uint16_t doorbell_format;
uint32_t doorbell_offset;
};
@ -310,9 +279,6 @@ struct beiscsi_hba {
u8 __iomem *csr_va; /* CSR */
u8 __iomem *db_va; /* Door Bell */
u8 __iomem *pci_va; /* PCI Config */
struct be_bus_address csr_pa; /* CSR */
struct be_bus_address db_pa; /* CSR */
struct be_bus_address pci_pa; /* CSR */
/* PCI representation of our HBA */
struct pci_dev *pcidev;
unsigned int num_cpus;
@ -324,7 +290,6 @@ struct beiscsi_hba {
unsigned short io_sgl_free_index;
unsigned short io_sgl_hndl_avbl;
struct sgl_handle **io_sgl_hndl_base;
struct sgl_handle **sgl_hndl_array;
unsigned short eh_sgl_alloc_index;
unsigned short eh_sgl_free_index;
@ -1009,10 +974,6 @@ struct be_ring {
};
struct hwi_controller {
struct list_head io_sgl_list;
struct list_head eh_sgl_list;
struct sgl_handle *psgl_handle_base;
struct hwi_wrb_context *wrb_context;
struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT];
struct be_ring default_pdu_data[BEISCSI_ULP_COUNT];
@ -1036,10 +997,6 @@ struct wrb_handle {
};
struct hwi_context_memory {
/* Adaptive interrupt coalescing (AIC) info */
u16 min_eqd; /* in usecs */
u16 max_eqd; /* in usecs */
u16 cur_eqd; /* in usecs */
struct be_eq_obj be_eq[MAX_CPUS];
struct be_queue_info be_cq[MAX_CPUS - 1];

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -19,43 +19,6 @@
#include "be_iscsi.h"
#include "be_main.h"
int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *set_eqd,
int num)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct be_cmd_req_modify_eq_delay *req;
unsigned int tag;
int i;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
req->num_eq = cpu_to_le32(num);
for (i = 0; i < num; i++) {
req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
req->delay[i].phase = 0;
req->delay[i].delay_multiplier =
cpu_to_le32(set_eqd[i].delay_multiplier);
}
/* ignore the completion of this mbox command */
set_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba,
struct bsg_job *job,
@ -156,7 +119,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BG_%d : unknown addr family %d\n",
dst_addr->sa_family);
return -EINVAL;
return 0;
}
phwi_ctrlr = phba->phwi_ctrlr;
@ -236,16 +199,19 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
}
/*
* mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd
* @phba: Driver priv structure
* @nonemb_cmd: Address of the MBX command issued
* @resp_buf: Buffer to copy the MBX cmd response
* @resp_buf_len: respone lenght to be copied
* beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd
* @phba: driver priv structure
* @nonemb_cmd: DMA address of the MBX command to be issued
* @cbfn: callback func on MCC completion
* @resp_buf: buffer to copy the MBX cmd response
* @resp_buf_len: response length to be copied
*
**/
static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
struct be_dma_mem *nonemb_cmd, void *resp_buf,
int resp_buf_len)
static int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba,
struct be_dma_mem *nonemb_cmd,
void (*cbfn)(struct beiscsi_hba *,
unsigned int),
void *resp_buf, u32 resp_buf_len)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
@ -267,36 +233,54 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma));
sge->len = cpu_to_le32(nonemb_cmd->size);
if (cbfn) {
struct be_dma_mem *tag_mem;
set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
ctrl->ptag_state[tag].cbfn = cbfn;
tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;
/* store DMA mem to be freed in callback */
tag_mem->size = nonemb_cmd->size;
tag_mem->va = nonemb_cmd->va;
tag_mem->dma = nonemb_cmd->dma;
}
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
/* with cbfn set, its async cmd, don't wait */
if (cbfn)
return 0;
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd);
/* copy the response, if any */
if (resp_buf)
memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
/**
* This is special case of NTWK_GET_IF_INFO where the size of
* response is not known. beiscsi_if_get_info checks the return
* value to free DMA buffer.
*/
if (rc == -EAGAIN)
return rc;
if (rc) {
/* Check if the MBX Cmd needs to be re-issued */
if (rc == -EAGAIN)
return rc;
/**
* If FW is busy that is driver timed out, DMA buffer is saved with
* the tag, only when the cmd completes this buffer is freed.
*/
if (rc == -EBUSY)
return rc;
beiscsi_log(phba, KERN_WARNING,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
if (rc != -EBUSY)
goto free_cmd;
else
return rc;
}
free_cmd:
pci_free_consistent(ctrl->pdev, nonemb_cmd->size,
nonemb_cmd->va, nonemb_cmd->dma);
return rc;
}
static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
int iscsi_cmd, int size)
static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
struct be_dma_mem *cmd,
u8 subsystem, u8 opcode, u32 size)
{
cmd->va = pci_zalloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
if (!cmd->va) {
@ -305,13 +289,86 @@ static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
return -ENOMEM;
}
cmd->size = size;
be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
be_cmd_hdr_prepare(cmd->va, subsystem, opcode, size);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BG_%d : subsystem iSCSI cmd %d size %d\n",
iscsi_cmd, size);
"BG_%d : subsystem %u cmd %u size %u\n",
subsystem, opcode, size);
return 0;
}
static void __beiscsi_eq_delay_compl(struct beiscsi_hba *phba, unsigned int tag)
{
struct be_dma_mem *tag_mem;
/* status is ignored */
__beiscsi_mcc_compl_status(phba, tag, NULL, NULL);
tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;
if (tag_mem->size) {
pci_free_consistent(phba->pcidev, tag_mem->size,
tag_mem->va, tag_mem->dma);
tag_mem->size = 0;
}
}
int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *set_eqd, int num)
{
struct be_cmd_req_modify_eq_delay *req;
struct be_dma_mem nonemb_cmd;
int i, rc;
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
if (rc)
return rc;
req = nonemb_cmd.va;
req->num_eq = cpu_to_le32(num);
for (i = 0; i < num; i++) {
req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
req->delay[i].phase = 0;
req->delay[i].delay_multiplier =
cpu_to_le32(set_eqd[i].delay_multiplier);
}
return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd,
__beiscsi_eq_delay_compl, NULL, 0);
}
/**
* beiscsi_get_initiator_name - read initiator name from flash
* @phba: device priv structure
* @name: buffer pointer
* @cfg: fetch user configured
*
*/
int beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg)
{
struct be_dma_mem nonemb_cmd;
struct be_cmd_hba_name resp;
struct be_cmd_hba_name *req;
int rc;
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, sizeof(resp));
if (rc)
return rc;
req = nonemb_cmd.va;
if (cfg)
req->hdr.version = 1;
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
&resp, sizeof(resp));
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BS_%d : Initiator Name MBX Failed\n");
return rc;
}
rc = sprintf(name, "%s\n", resp.initiator_name);
return rc;
}
unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
@ -368,9 +425,9 @@ static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
struct be_dma_mem nonemb_cmd;
int rt_val;
rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
sizeof(*req));
rt_val = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
sizeof(*req));
if (rt_val)
return rt_val;
@ -379,7 +436,7 @@ static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
req->ip_addr.ip_type = ip_type;
memcpy(req->ip_addr.addr, gw,
(ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN);
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
}
int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)
@ -420,17 +477,17 @@ int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type,
struct be_dma_mem nonemb_cmd;
int rc;
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
sizeof(*resp));
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
sizeof(*resp));
if (rc)
return rc;
req = nonemb_cmd.va;
req->ip_type = ip_type;
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, resp,
sizeof(*resp));
return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
resp, sizeof(*resp));
}
static int
@ -441,9 +498,9 @@ beiscsi_if_clr_ip(struct beiscsi_hba *phba,
struct be_dma_mem nonemb_cmd;
int rc;
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
sizeof(*req));
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
sizeof(*req));
if (rc)
return rc;
@ -461,7 +518,7 @@ beiscsi_if_clr_ip(struct beiscsi_hba *phba,
memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
if_info->ip_addr.subnet_mask,
sizeof(if_info->ip_addr.subnet_mask));
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
if (rc < 0 || req->ip_params.ip_record.status) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BG_%d : failed to clear IP: rc %d status %d\n",
@ -479,9 +536,9 @@ beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
uint32_t ip_len;
int rc;
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
sizeof(*req));
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
sizeof(*req));
if (rc)
return rc;
@ -499,7 +556,7 @@ beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
subnet, ip_len);
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
/**
* In some cases, host needs to look into individual record status
* even though FW reported success for that IOCTL.
@ -527,7 +584,8 @@ int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
return rc;
if (if_info->dhcp_state) {
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,
CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
sizeof(*reldhcp));
if (rc)
@ -536,7 +594,7 @@ int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
reldhcp = nonemb_cmd.va;
reldhcp->interface_hndl = phba->interface_handle;
reldhcp->ip_type = ip_type;
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
if (rc < 0) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : failed to release existing DHCP: %d\n",
@ -606,7 +664,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
}
}
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
sizeof(*dhcpreq));
if (rc)
@ -617,7 +675,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
dhcpreq->retry_count = 1;
dhcpreq->interface_hndl = phba->interface_handle;
dhcpreq->ip_type = ip_type;
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
exit:
kfree(if_info);
@ -673,9 +731,10 @@ int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
return rc;
do {
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
ioctl_size);
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,
CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
ioctl_size);
if (rc)
return rc;
@ -698,8 +757,8 @@ int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
return -ENOMEM;
}
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info,
ioctl_size);
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, *if_info,
ioctl_size);
/* Check if the error is because of Insufficent_Buffer */
if (rc == -EAGAIN) {
@ -728,41 +787,14 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
struct be_dma_mem nonemb_cmd;
int rc;
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
sizeof(*nic));
rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
sizeof(*nic));
if (rc)
return rc;
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, nic, sizeof(*nic));
}
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba)
{
unsigned int tag;
struct be_mcc_wrb *wrb;
struct be_cmd_hba_name *req;
struct be_ctrl_info *ctrl = &phba->ctrl;
if (mutex_lock_interruptible(&ctrl->mbox_lock))
return 0;
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_CFG_GET_HBA_NAME,
sizeof(*req));
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
nic, sizeof(*nic));
}
static void beiscsi_boot_process_compl(struct beiscsi_hba *phba,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom. All Rights Reserved.
* Copyright 2017 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
@ -157,7 +157,6 @@ struct be_bsg_vendor_cmd {
struct beiscsi_endpoint {
struct beiscsi_hba *phba;
struct beiscsi_sess *sess;
struct beiscsi_conn *conn;
struct iscsi_endpoint *openiscsi_ep;
unsigned short ip_type;
@ -169,15 +168,12 @@ struct beiscsi_endpoint {
u16 cid_vld;
};
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
struct beiscsi_endpoint *beiscsi_ep,
unsigned short cid,
unsigned short issue_reset,
unsigned short savecfg_flag);
int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invldt_cmd_tbl *inv_tbl,
unsigned int nents);
int beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg);
int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type);
int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,

View File

@ -3137,16 +3137,9 @@ bfad_im_bsg_vendor_request(struct bsg_job *job)
uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0];
struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job));
struct bfad_s *bfad = im_port->bfad;
struct request_queue *request_q = job->req->q;
void *payload_kbuf;
int rc = -EINVAL;
/*
* Set the BSG device request_queue size to 256 to support
* payloads larger than 512*1024K bytes.
*/
blk_queue_max_segments(request_q, 256);
/* Allocate a temp buffer to hold the passed in user space command */
payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
if (!payload_kbuf) {

View File

@ -255,7 +255,8 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
struct bfad_s *bfad = port->bfad;
struct bfa_s *bfa = &bfad->bfa;
struct bfa_ioc_s *ioc = &bfa->ioc;
int addr, len, rc, i;
int addr, rc, i;
u32 len;
u32 *regbuf;
void __iomem *rb, *reg_addr;
unsigned long flags;
@ -266,7 +267,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
return PTR_ERR(kern_buf);
rc = sscanf(kern_buf, "%x:%x", &addr, &len);
if (rc < 2) {
if (rc < 2 || len > (UINT_MAX >> 2)) {
printk(KERN_INFO
"bfad[%d]: %s failed to read user buf\n",
bfad->inst_no, __func__);

View File

@ -332,12 +332,10 @@ static void bnx2i_ring_dbell_update_sq_params(struct bnx2i_conn *bnx2i_conn,
int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn,
struct iscsi_task *task)
{
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_login_request *login_wqe;
struct iscsi_login_req *login_hdr;
u32 dword;
bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
login_hdr = (struct iscsi_login_req *)task->hdr;
login_wqe = (struct bnx2i_login_request *)
bnx2i_conn->ep->qp.sq_prod_qe;
@ -391,12 +389,10 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
struct iscsi_tm *tmfabort_hdr;
struct scsi_cmnd *ref_sc;
struct iscsi_task *ctask;
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_tmf_request *tmfabort_wqe;
u32 dword;
u32 scsi_lun[2];
bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
tmfabort_wqe = (struct bnx2i_tmf_request *)
bnx2i_conn->ep->qp.sq_prod_qe;
@ -463,12 +459,10 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
int bnx2i_send_iscsi_text(struct bnx2i_conn *bnx2i_conn,
struct iscsi_task *mtask)
{
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_text_request *text_wqe;
struct iscsi_text *text_hdr;
u32 dword;
bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
text_hdr = (struct iscsi_text *)mtask->hdr;
text_wqe = (struct bnx2i_text_request *) bnx2i_conn->ep->qp.sq_prod_qe;
@ -541,11 +535,9 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
char *datap, int data_len, int unsol)
{
struct bnx2i_endpoint *ep = bnx2i_conn->ep;
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_nop_out_request *nopout_wqe;
struct iscsi_nopout *nopout_hdr;
bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
nopout_hdr = (struct iscsi_nopout *)task->hdr;
nopout_wqe = (struct bnx2i_nop_out_request *)ep->qp.sq_prod_qe;
@ -602,11 +594,9 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
int bnx2i_send_iscsi_logout(struct bnx2i_conn *bnx2i_conn,
struct iscsi_task *task)
{
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_logout_request *logout_wqe;
struct iscsi_logout *logout_hdr;
bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
logout_hdr = (struct iscsi_logout *)task->hdr;
logout_wqe = (struct bnx2i_logout_request *)

View File

@ -368,6 +368,9 @@ struct csio_hw_stats {
#define CSIO_HWF_HOST_INTR_ENABLED 0x00000200 /* Are host interrupts
* enabled?
*/
#define CSIO_HWF_ROOT_NO_RELAXED_ORDERING 0x00000400 /* Is PCIe relaxed
* ordering enabled
*/
#define csio_is_hw_intr_enabled(__hw) \
((__hw)->flags & CSIO_HWF_HW_INTR_ENABLED)

View File

@ -968,6 +968,9 @@ static int csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_pci_exit;
}
if (!pcie_relaxed_ordering_enabled(pdev))
hw->flags |= CSIO_HWF_ROOT_NO_RELAXED_ORDERING;
pci_set_drvdata(pdev, hw);
rv = csio_hw_start(hw);

View File

@ -491,6 +491,7 @@ csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
uint32_t iq_start_stop = (iq_params->iq_start) ?
FW_IQ_CMD_IQSTART_F :
FW_IQ_CMD_IQSTOP_F;
int relaxed = !(hw->flags & CSIO_HWF_ROOT_NO_RELAXED_ORDERING);
/*
* If this IQ write is cascaded with IQ alloc request, do not
@ -537,6 +538,8 @@ csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
cmdp->iqns_to_fl0congen |= htonl(
FW_IQ_CMD_FL0HOSTFCMODE_V(iq_params->fl0hostfcmode)|
FW_IQ_CMD_FL0CPRIO_V(iq_params->fl0cprio) |
FW_IQ_CMD_FL0FETCHRO_V(relaxed) |
FW_IQ_CMD_FL0DATARO_V(relaxed) |
FW_IQ_CMD_FL0PADEN_V(iq_params->fl0paden) |
FW_IQ_CMD_FL0PACKEN_V(iq_params->fl0packen));
cmdp->fl0dcaen_to_fl0cidxfthresh |= htons(

View File

@ -1575,6 +1575,7 @@ static void release_offload_resources(struct cxgbi_sock *csk)
csk, csk->state, csk->flags, csk->tid);
cxgbi_sock_free_cpl_skbs(csk);
cxgbi_sock_purge_write_queue(csk);
if (csk->wr_cred != csk->wr_max_cred) {
cxgbi_sock_purge_wr_queue(csk);
cxgbi_sock_reset_wr_list(csk);

View File

@ -688,8 +688,6 @@ rel_neigh:
rel_rt:
ip_rt_put(rt);
if (csk)
cxgbi_sock_closed(csk);
err_out:
return ERR_PTR(err);
}
@ -1889,16 +1887,13 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
struct iscsi_tcp_task *tcp_task = task->dd_data;
struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
struct scsi_cmnd *sc = task->sc;
struct cxgbi_sock *csk = cconn->cep->csk;
struct net_device *ndev = cdev->ports[csk->port_id];
int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
tcp_task->dd_data = tdata;
task->hdr = NULL;
if (tdata->skb) {
kfree_skb(tdata->skb);
tdata->skb = NULL;
}
if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
(opcode == ISCSI_OP_SCSI_DATA_OUT ||
(opcode == ISCSI_OP_SCSI_CMD &&
@ -1910,15 +1905,23 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
if (!tdata->skb) {
struct cxgbi_sock *csk = cconn->cep->csk;
struct net_device *ndev = cdev->ports[csk->port_id];
ndev->stats.tx_dropped++;
return -ENOMEM;
}
skb_get(tdata->skb);
skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
task->hdr = (struct iscsi_hdr *)tdata->skb->data;
if (task->sc) {
task->hdr = (struct iscsi_hdr *)tdata->skb->data;
} else {
task->hdr = kzalloc(SKB_TX_ISCSI_PDU_HEADER_MAX, GFP_KERNEL);
if (!task->hdr) {
__kfree_skb(tdata->skb);
tdata->skb = NULL;
ndev->stats.tx_dropped++;
return -ENOMEM;
}
}
task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
/* data_out uses scsi_cmd's itt */
@ -2062,9 +2065,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
unsigned int datalen;
int err;
if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) {
if (!skb) {
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
"task 0x%p, skb 0x%p\n", task, skb);
"task 0x%p\n", task);
return 0;
}
@ -2076,6 +2079,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
return -EPIPE;
}
tdata->skb = NULL;
datalen = skb->data_len;
/* write ppod first if using ofldq to write ppod */
@ -2089,6 +2093,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
/* continue. Let fl get the data */
}
if (!task->sc)
memcpy(skb->data, task->hdr, SKB_TX_ISCSI_PDU_HEADER_MAX);
err = cxgbi_sock_send_pdus(cconn->cep->csk, skb);
if (err > 0) {
int pdulen = err;
@ -2104,7 +2111,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
pdulen += ISCSI_DIGEST_SIZE;
task->conn->txdata_octets += pdulen;
cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE);
return 0;
}
@ -2113,6 +2119,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
"task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
task, skb, skb->len, skb->data_len, err);
/* reset skb to send when we are called again */
tdata->skb = skb;
return err;
}
@ -2120,8 +2127,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
"itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
task->itt, skb, skb->len, skb->data_len, err);
__kfree_skb(tdata->skb);
tdata->skb = NULL;
__kfree_skb(skb);
iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
@ -2146,9 +2152,14 @@ void cxgbi_cleanup_task(struct iscsi_task *task)
task, tdata->skb, task->hdr_itt);
tcp_task->dd_data = NULL;
if (!task->sc)
kfree(task->hdr);
task->hdr = NULL;
/* never reached the xmit task callout */
if (tdata->skb) {
kfree_skb(tdata->skb);
__kfree_skb(tdata->skb);
tdata->skb = NULL;
}
@ -2556,7 +2567,10 @@ struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
goto err_out;
}
ifindex = hba->ndev->ifindex;
rtnl_lock();
if (!vlan_uses_dev(hba->ndev))
ifindex = hba->ndev->ifindex;
rtnl_unlock();
}
if (dst_addr->sa_family == AF_INET) {

View File

@ -205,7 +205,6 @@ enum cxgbi_skcb_flags {
SKCBF_TX_NEED_HDR, /* packet needs a header */
SKCBF_TX_MEM_WRITE, /* memory write */
SKCBF_TX_FLAG_COMPL, /* wr completion flag */
SKCBF_TX_DONE, /* skb tx done */
SKCBF_RX_COALESCED, /* received whole pdu */
SKCBF_RX_HDR, /* received pdu header */
SKCBF_RX_DATA, /* received pdu payload */

View File

@ -1634,7 +1634,10 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
ssize_t vpd_size;
char vpd_data[CXLFLASH_VPD_LEN];
char tmp_buf[WWPN_BUF_LEN] = { 0 };
char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6", "V7", "V8" };
const struct dev_dependent_vals *ddv = (struct dev_dependent_vals *)
cfg->dev_id->driver_data;
const bool wwpn_vpd_required = ddv->flags & CXLFLASH_WWPN_VPD_REQUIRED;
const char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6", "V7", "V8" };
/* Get the VPD data from the device */
vpd_size = cxl_read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data));
@ -1671,17 +1674,24 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
* value. Note that we must copy to a temporary buffer
* because the conversion service requires that the ASCII
* string be terminated.
*
* Allow for WWPN not being found for all devices, setting
* the returned WWPN to zero when not found. Notify with a
* log error for cards that should have had WWPN keywords
* in the VPD - cards requiring WWPN will not have their
* ports programmed and operate in an undefined state.
*/
for (k = 0; k < cfg->num_fc_ports; k++) {
j = ro_size;
i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
i = pci_vpd_find_info_keyword(vpd_data, i, j, wwpn_vpd_tags[k]);
if (unlikely(i < 0)) {
dev_err(dev, "%s: Port %d WWPN not found in VPD\n",
__func__, k);
rc = -ENODEV;
goto out;
if (i < 0) {
if (wwpn_vpd_required)
dev_err(dev, "%s: Port %d WWPN not found\n",
__func__, k);
wwpn[k] = 0ULL;
continue;
}
j = pci_vpd_info_field_size(&vpd_data[i]);
@ -3145,7 +3155,7 @@ static struct scsi_host_template driver_template = {
* Device dependent values
*/
static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
0ULL };
CXLFLASH_WWPN_VPD_REQUIRED };
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
CXLFLASH_NOTIFY_SHUTDOWN };
static struct dev_dependent_vals dev_briard_vals = { CXLFLASH_MAX_SECTORS,

View File

@ -95,7 +95,8 @@ enum undo_level {
struct dev_dependent_vals {
u64 max_sectors;
u64 flags;
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
#define CXLFLASH_WWPN_VPD_REQUIRED 0x0000000000000002ULL
};
struct asyc_intr_info {

View File

@ -548,7 +548,4 @@ struct sisl_rht_entry_f1 {
#define TMF_LUN_RESET 0x1U
#define TMF_CLEAR_ACA 0x2U
#define SISLITE_MAX_WS_BLOCKS 512
#endif /* _SISLITE_H */

View File

@ -165,7 +165,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid,
struct llun_info *lli = arg;
u64 ctxid = DECODE_CTXID(rctxid);
int rc;
pid_t pid = current->tgid, ctxpid = 0;
pid_t pid = task_tgid_nr(current), ctxpid = 0;
if (ctx_ctrl & CTX_CTRL_FILE) {
lli = NULL;
@ -173,7 +173,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid,
}
if (ctx_ctrl & CTX_CTRL_CLONE)
pid = current->parent->tgid;
pid = task_ppid_nr(current);
if (likely(ctxid < MAX_CONTEXT)) {
while (true) {
@ -824,7 +824,7 @@ static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg,
ctxi->rht_perms = perms;
ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl;
ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid);
ctxi->pid = current->tgid; /* tgid = pid */
ctxi->pid = task_tgid_nr(current); /* tgid = pid */
ctxi->ctx = ctx;
ctxi->cfg = cfg;
ctxi->file = file;

View File

@ -428,12 +428,14 @@ static int write_same16(struct scsi_device *sdev,
u8 *sense_buf = NULL;
int rc = 0;
int result = 0;
int ws_limit = SISLITE_MAX_WS_BLOCKS;
u64 offset = lba;
int left = nblks;
u32 to = sdev->request_queue->rq_timeout;
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
const u32 s = ilog2(sdev->sector_size) - 9;
const u32 to = sdev->request_queue->rq_timeout;
const u32 ws_limit = blk_queue_get_max_sectors(sdev->request_queue,
REQ_OP_WRITE_SAME) >> s;
cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL);
scsi_cmd = kzalloc(MAX_COMMAND_SIZE, GFP_KERNEL);

View File

@ -1085,11 +1085,11 @@ static void alua_rescan(struct scsi_device *sdev)
static int alua_bus_attach(struct scsi_device *sdev)
{
struct alua_dh_data *h;
int err, ret = -EINVAL;
int err;
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return -ENOMEM;
return SCSI_DH_NOMEM;
spin_lock_init(&h->pg_lock);
rcu_assign_pointer(h->pg, NULL);
h->init_error = SCSI_DH_OK;
@ -1098,16 +1098,14 @@ static int alua_bus_attach(struct scsi_device *sdev)
mutex_init(&h->init_mutex);
err = alua_initialize(sdev, h);
if (err == SCSI_DH_NOMEM)
ret = -ENOMEM;
if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED)
goto failed;
sdev->handler_data = h;
return 0;
return SCSI_DH_OK;
failed:
kfree(h);
return ret;
return err;
}
/*

View File

@ -490,7 +490,7 @@ static int clariion_bus_attach(struct scsi_device *sdev)
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return -ENOMEM;
return SCSI_DH_NOMEM;
h->lun_state = CLARIION_LUN_UNINITIALIZED;
h->default_sp = CLARIION_UNBOUND_LU;
h->current_sp = CLARIION_UNBOUND_LU;
@ -510,11 +510,11 @@ static int clariion_bus_attach(struct scsi_device *sdev)
h->default_sp + 'A');
sdev->handler_data = h;
return 0;
return SCSI_DH_OK;
failed:
kfree(h);
return -EINVAL;
return err;
}
static void clariion_bus_detach(struct scsi_device *sdev)

View File

@ -218,24 +218,28 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
h = kzalloc(sizeof(*h), GFP_KERNEL);
if (!h)
return -ENOMEM;
return SCSI_DH_NOMEM;
h->path_state = HP_SW_PATH_UNINITIALIZED;
h->retries = HP_SW_RETRIES;
h->sdev = sdev;
ret = hp_sw_tur(sdev, h);
if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
if (ret != SCSI_DH_OK)
goto failed;
if (h->path_state == HP_SW_PATH_UNINITIALIZED) {
ret = SCSI_DH_NOSYS;
goto failed;
}
sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n",
HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE?
"active":"passive");
sdev->handler_data = h;
return 0;
return SCSI_DH_OK;
failed:
kfree(h);
return -EINVAL;
return ret;
}
static void hp_sw_bus_detach( struct scsi_device *sdev )

View File

@ -729,7 +729,7 @@ static int rdac_bus_attach(struct scsi_device *sdev)
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return -ENOMEM;
return SCSI_DH_NOMEM;
h->lun = UNINITIALIZED_LUN;
h->state = RDAC_STATE_ACTIVE;
@ -755,7 +755,7 @@ static int rdac_bus_attach(struct scsi_device *sdev)
lun_state[(int)h->lun_state]);
sdev->handler_data = h;
return 0;
return SCSI_DH_OK;
clean_ctlr:
spin_lock(&list_lock);
@ -764,7 +764,7 @@ clean_ctlr:
failed:
kfree(h);
return -EINVAL;
return err;
}
static void rdac_bus_detach( struct scsi_device *sdev )

View File

@ -155,7 +155,7 @@ static int fcoe_vport_disable(struct fc_vport *, bool disable);
static void fcoe_set_vport_symbolic_name(struct fc_vport *);
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *);
static void fcoe_vport_remove(struct fc_lport *);
static struct fcoe_sysfs_function_template fcoe_sysfs_templ = {
.set_fcoe_ctlr_mode = fcoe_ctlr_mode,
@ -501,11 +501,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
rtnl_lock();
if (!fcoe->removed)
fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Release the self-reference taken during fcoe_interface_create() */
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(fip);
@ -1014,6 +1009,8 @@ skip_oem:
* fcoe_if_destroy() - Tear down a SW FCoE instance
* @lport: The local port to be destroyed
*
* Locking: Must be called with the RTNL mutex held.
*
*/
static void fcoe_if_destroy(struct fc_lport *lport)
{
@ -1035,14 +1032,12 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Free existing transmit skbs */
fcoe_clean_pending_queue(lport);
rtnl_lock();
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(netdev, port->data_src_addr);
if (lport->vport)
synchronize_net();
else
fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Free queued packets for the per-CPU receive threads */
fcoe_percpu_clean(lport);
@ -1903,7 +1898,14 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_UNREGISTER:
list_del(&fcoe->list);
port = lport_priv(ctlr->lp);
queue_work(fcoe_wq, &port->destroy_work);
fcoe_vport_remove(lport);
mutex_lock(&fcoe_config_mutex);
fcoe_if_destroy(lport);
if (!fcoe->removed)
fcoe_interface_remove(fcoe);
fcoe_interface_cleanup(fcoe);
mutex_unlock(&fcoe_config_mutex);
fcoe_ctlr_device_delete(fcoe_ctlr_to_ctlr_dev(ctlr));
goto out;
break;
case NETDEV_FEAT_CHANGE:
@ -2108,30 +2110,10 @@ static void fcoe_destroy_work(struct work_struct *work)
struct fcoe_ctlr *ctlr;
struct fcoe_port *port;
struct fcoe_interface *fcoe;
struct Scsi_Host *shost;
struct fc_host_attrs *fc_host;
unsigned long flags;
struct fc_vport *vport;
struct fc_vport *next_vport;
port = container_of(work, struct fcoe_port, destroy_work);
shost = port->lport->host;
fc_host = shost_to_fc_host(shost);
/* Loop through all the vports and mark them for deletion */
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {
if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {
continue;
} else {
vport->flags |= FC_VPORT_DELETING;
queue_work(fc_host_work_q(shost),
&vport->vport_delete_work);
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
flush_workqueue(fc_host_work_q(shost));
fcoe_vport_remove(port->lport);
mutex_lock(&fcoe_config_mutex);
@ -2139,7 +2121,11 @@ static void fcoe_destroy_work(struct work_struct *work)
ctlr = fcoe_to_ctlr(fcoe);
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
rtnl_lock();
fcoe_if_destroy(port->lport);
if (!fcoe->removed)
fcoe_interface_remove(fcoe);
rtnl_unlock();
fcoe_interface_cleanup(fcoe);
mutex_unlock(&fcoe_config_mutex);
@ -2254,6 +2240,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_mode fip_mode,
printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
rc = -EIO;
if (!fcoe->removed)
fcoe_interface_remove(fcoe);
rtnl_unlock();
fcoe_interface_cleanup(fcoe);
mutex_unlock(&fcoe_config_mutex);
@ -2738,12 +2726,45 @@ static int fcoe_vport_destroy(struct fc_vport *vport)
mutex_unlock(&n_port->lp_mutex);
mutex_lock(&fcoe_config_mutex);
rtnl_lock();
fcoe_if_destroy(vn_port);
rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
return 0;
}
/**
* fcoe_vport_remove() - remove attached vports
* @lport: lport for which the vports should be removed
*/
static void fcoe_vport_remove(struct fc_lport *lport)
{
struct Scsi_Host *shost;
struct fc_host_attrs *fc_host;
unsigned long flags;
struct fc_vport *vport;
struct fc_vport *next_vport;
shost = lport->host;
fc_host = shost_to_fc_host(shost);
/* Loop through all the vports and mark them for deletion */
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {
if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {
continue;
} else {
vport->flags |= FC_VPORT_DELETING;
queue_work(fc_host_work_q(shost),
&vport->vport_delete_work);
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
flush_workqueue(fc_host_work_q(shost));
}
/**
* fcoe_vport_disable() - change vport state
* @vport: vport to bring online/offline

View File

@ -29,7 +29,7 @@
#define HISI_SAS_MAX_PHYS 9
#define HISI_SAS_MAX_QUEUES 32
#define HISI_SAS_QUEUE_SLOTS 512
#define HISI_SAS_MAX_ITCT_ENTRIES 2048
#define HISI_SAS_MAX_ITCT_ENTRIES 1024
#define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
#define HISI_SAS_RESET_BIT 0
#define HISI_SAS_REJECT_CMD_BIT 1
@ -96,6 +96,7 @@ struct hisi_sas_hw_error {
int shift;
const char *msg;
int reg;
const struct hisi_sas_hw_error *sub;
};
struct hisi_sas_phy {
@ -197,7 +198,7 @@ struct hisi_sas_hw {
int (*slot_complete)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
void (*phys_init)(struct hisi_hba *hisi_hba);
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_start)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no);
void (*get_events)(struct hisi_hba *hisi_hba, int phy_no);
@ -341,7 +342,11 @@ struct hisi_sas_initial_fis {
};
struct hisi_sas_breakpoint {
u8 data[128]; /*io128 byte*/
u8 data[128];
};
struct hisi_sas_sata_breakpoint {
struct hisi_sas_breakpoint tag[32];
};
struct hisi_sas_sge {
@ -419,4 +424,6 @@ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
extern void hisi_sas_rst_work_handler(struct work_struct *work);
extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
#endif

View File

@ -185,13 +185,16 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
if (!task->lldd_task)
return;
task->lldd_task = NULL;
if (!sas_protocol_ata(task->task_proto))
if (slot->n_elem)
dma_unmap_sg(dev, task->scatter, slot->n_elem,
task->data_dir);
task->lldd_task = NULL;
if (sas_dev)
atomic64_dec(&sas_dev->running_req);
}
@ -199,8 +202,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
if (slot->buf)
dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
list_del_init(&slot->entry);
slot->buf = NULL;
slot->task = NULL;
slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx);
@ -401,7 +404,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
goto err_out_buf;
}
spin_lock_irqsave(&hisi_hba->lock, flags);
list_add_tail(&slot->entry, &sas_dev->list);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@ -505,9 +510,10 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
{
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_device *sas_dev = NULL;
unsigned long flags;
int i;
spin_lock(&hisi_hba->lock);
spin_lock_irqsave(&hisi_hba->lock, flags);
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
int queue = i % hisi_hba->queue_count;
@ -524,7 +530,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
break;
}
}
spin_unlock(&hisi_hba->lock);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
return sas_dev;
}
@ -761,7 +767,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
case PHY_FUNC_LINK_RESET:
hisi_hba->hw->phy_disable(hisi_hba, phy_no);
msleep(100);
hisi_hba->hw->phy_enable(hisi_hba, phy_no);
hisi_hba->hw->phy_start(hisi_hba, phy_no);
break;
case PHY_FUNC_DISABLE:
@ -1045,7 +1051,6 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
{
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
struct device *dev = hisi_hba->dev;
struct Scsi_Host *shost = hisi_hba->shost;
u32 old_state, state;
@ -1073,7 +1078,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
hisi_sas_release_tasks(hisi_hba);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
sas_ha->notify_ha_event(sas_ha, HAE_RESET);
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
/* Init and wait for PHYs to come up and all libsas event finished. */
@ -1159,7 +1163,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_CMD, tag);
if (rc == TMF_RESP_FUNC_FAILED) {
if (rc == TMF_RESP_FUNC_FAILED && task->lldd_task) {
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_do_release_task(hisi_hba, task, slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
@ -1387,8 +1391,9 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
if (rc)
goto err_out_buf;
spin_lock_irqsave(&hisi_hba->lock, flags);
list_add_tail(&slot->entry, &sas_dev->list);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@ -1469,6 +1474,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
if (slot)
slot->task = NULL;
dev_err(dev, "internal task abort: timeout.\n");
goto exit;
}
}
@ -1540,6 +1546,17 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
}
EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
{
int i;
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
tasklet_kill(&cq->tasklet);
}
}
EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
struct scsi_transport_template *hisi_sas_stt;
EXPORT_SYMBOL_GPL(hisi_sas_stt);
@ -1608,7 +1625,7 @@ void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
memset(hisi_hba->breakpoint, 0, s);
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
memset(hisi_hba->sata_breakpoint, 0, s);
}
EXPORT_SYMBOL_GPL(hisi_sas_init_mem);
@ -1701,7 +1718,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
if (!hisi_hba->initial_fis)
goto err_out;
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
&hisi_hba->sata_breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->sata_breakpoint)
@ -1766,7 +1783,7 @@ void hisi_sas_free(struct hisi_hba *hisi_hba)
hisi_hba->initial_fis,
hisi_hba->initial_fis_dma);
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
if (hisi_hba->sata_breakpoint)
dma_free_coherent(dev, s,
hisi_hba->sata_breakpoint,
@ -1777,13 +1794,14 @@ void hisi_sas_free(struct hisi_hba *hisi_hba)
}
EXPORT_SYMBOL_GPL(hisi_sas_free);
static void hisi_sas_rst_work_handler(struct work_struct *work)
void hisi_sas_rst_work_handler(struct work_struct *work)
{
struct hisi_hba *hisi_hba =
container_of(work, struct hisi_hba, rst_work);
hisi_sas_controller_reset(hisi_hba);
}
EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler);
int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
{

View File

@ -1857,7 +1857,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
.start_delivery = start_delivery_v1_hw,
.slot_complete = slot_complete_v1_hw,
.phys_init = phys_init_v1_hw,
.phy_enable = enable_phy_v1_hw,
.phy_start = start_phy_v1_hw,
.phy_disable = disable_phy_v1_hw,
.phy_hard_reset = phy_hard_reset_v1_hw,
.phy_set_linkrate = phy_set_linkrate_v1_hw,

View File

@ -406,80 +406,70 @@ static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
.msk = HGC_DQE_ECC_1B_ADDR_MSK,
.shift = HGC_DQE_ECC_1B_ADDR_OFF,
.msg = "hgc_dqe_acc1b_intr found: \
Ram address is 0x%08X\n",
.msg = "hgc_dqe_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_DQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_1B_OFF),
.msk = HGC_IOST_ECC_1B_ADDR_MSK,
.shift = HGC_IOST_ECC_1B_ADDR_OFF,
.msg = "hgc_iost_acc1b_intr found: \
Ram address is 0x%08X\n",
.msg = "hgc_iost_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_IOST_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_1B_OFF),
.msk = HGC_ITCT_ECC_1B_ADDR_MSK,
.shift = HGC_ITCT_ECC_1B_ADDR_OFF,
.msg = "hgc_itct_acc1b_intr found: \
Ram address is 0x%08X\n",
.msg = "hgc_itct_acc1b_intr found: am address is 0x%08X\n",
.reg = HGC_ITCT_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF),
.msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
.msg = "hgc_iostl_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "hgc_iostl_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF),
.msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
.msg = "hgc_itctl_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "hgc_itctl_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_1B_OFF),
.msk = HGC_CQE_ECC_1B_ADDR_MSK,
.shift = HGC_CQE_ECC_1B_ADDR_OFF,
.msg = "hgc_cqe_acc1b_intr found: \
Ram address is 0x%08X\n",
.msg = "hgc_cqe_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_CQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
.msg = "rxm_mem0_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "rxm_mem0_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
.msg = "rxm_mem1_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "rxm_mem1_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
.msg = "rxm_mem2_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "rxm_mem2_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
.msg = "rxm_mem3_acc1b_intr found: \
memory address is 0x%08X\n",
.msg = "rxm_mem3_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS15,
},
};
@ -489,80 +479,70 @@ static const struct hisi_sas_hw_error multi_bit_ecc_errors[] = {
.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_MB_OFF),
.msk = HGC_DQE_ECC_MB_ADDR_MSK,
.shift = HGC_DQE_ECC_MB_ADDR_OFF,
.msg = "hgc_dqe_accbad_intr (0x%x) found: \
Ram address is 0x%08X\n",
.msg = "hgc_dqe_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
.reg = HGC_DQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_MB_OFF),
.msk = HGC_IOST_ECC_MB_ADDR_MSK,
.shift = HGC_IOST_ECC_MB_ADDR_OFF,
.msg = "hgc_iost_accbad_intr (0x%x) found: \
Ram address is 0x%08X\n",
.msg = "hgc_iost_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
.reg = HGC_IOST_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_MB_OFF),
.msk = HGC_ITCT_ECC_MB_ADDR_MSK,
.shift = HGC_ITCT_ECC_MB_ADDR_OFF,
.msg = "hgc_itct_accbad_intr (0x%x) found: \
Ram address is 0x%08X\n",
.msg = "hgc_itct_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
.reg = HGC_ITCT_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF),
.msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
.msg = "hgc_iostl_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "hgc_iostl_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF),
.msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
.msg = "hgc_itctl_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "hgc_itctl_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF),
.msk = HGC_CQE_ECC_MB_ADDR_MSK,
.shift = HGC_CQE_ECC_MB_ADDR_OFF,
.msg = "hgc_cqe_accbad_intr (0x%x) found: \
Ram address is 0x%08X\n",
.msg = "hgc_cqe_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
.reg = HGC_CQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
.msg = "rxm_mem0_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "rxm_mem0_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
.msg = "rxm_mem1_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "rxm_mem1_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
.msg = "rxm_mem2_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "rxm_mem2_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF),
.msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
.msg = "rxm_mem3_accbad_intr (0x%x) found: \
memory address is 0x%08X\n",
.msg = "rxm_mem3_accbad_intr (0x%x) found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS15,
},
};
@ -843,8 +823,9 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
struct hisi_sas_device *sas_dev = NULL;
int i, sata_dev = dev_is_sata(device);
int sata_idx = -1;
unsigned long flags;
spin_lock(&hisi_hba->lock);
spin_lock_irqsave(&hisi_hba->lock, flags);
if (sata_dev)
if (!sata_index_alloc_v2_hw(hisi_hba, &sata_idx))
@ -874,7 +855,7 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
}
out:
spin_unlock(&hisi_hba->lock);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
return sas_dev;
}
@ -2376,7 +2357,9 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
if (unlikely(aborted)) {
ts->stat = SAS_ABORTED_TASK;
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
return -1;
}
@ -2951,25 +2934,58 @@ static irqreturn_t fatal_ecc_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED;
}
#define AXI_ERR_NR 8
static const char axi_err_info[AXI_ERR_NR][32] = {
"IOST_AXI_W_ERR",
"IOST_AXI_R_ERR",
"ITCT_AXI_W_ERR",
"ITCT_AXI_R_ERR",
"SATA_AXI_W_ERR",
"SATA_AXI_R_ERR",
"DQE_AXI_R_ERR",
"CQE_AXI_W_ERR"
static const struct hisi_sas_hw_error axi_error[] = {
{ .msk = BIT(0), .msg = "IOST_AXI_W_ERR" },
{ .msk = BIT(1), .msg = "IOST_AXI_R_ERR" },
{ .msk = BIT(2), .msg = "ITCT_AXI_W_ERR" },
{ .msk = BIT(3), .msg = "ITCT_AXI_R_ERR" },
{ .msk = BIT(4), .msg = "SATA_AXI_W_ERR" },
{ .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
{ .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
{ .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
{},
};
#define FIFO_ERR_NR 5
static const char fifo_err_info[FIFO_ERR_NR][32] = {
"CQE_WINFO_FIFO",
"CQE_MSG_FIFIO",
"GETDQE_FIFO",
"CMDP_FIFO",
"AWTCTRL_FIFO"
static const struct hisi_sas_hw_error fifo_error[] = {
{ .msk = BIT(8), .msg = "CQE_WINFO_FIFO" },
{ .msk = BIT(9), .msg = "CQE_MSG_FIFIO" },
{ .msk = BIT(10), .msg = "GETDQE_FIFO" },
{ .msk = BIT(11), .msg = "CMDP_FIFO" },
{ .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
{},
};
static const struct hisi_sas_hw_error fatal_axi_errors[] = {
{
.irq_msk = BIT(ENT_INT_SRC3_WP_DEPTH_OFF),
.msg = "write pointer and depth",
},
{
.irq_msk = BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF),
.msg = "iptt no match slot",
},
{
.irq_msk = BIT(ENT_INT_SRC3_RP_DEPTH_OFF),
.msg = "read pointer and depth",
},
{
.irq_msk = BIT(ENT_INT_SRC3_AXI_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
.sub = axi_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_FIFO_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
.sub = fifo_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_LM_OFF),
.msg = "LM add/fetch list",
},
{
.irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
.msg = "SAS_HGC_ABT fetch LM list",
},
};
static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
@ -2977,98 +2993,47 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
struct hisi_hba *hisi_hba = p;
u32 irq_value, irq_msk, err_value;
struct device *dev = hisi_hba->dev;
const struct hisi_sas_hw_error *axi_error;
int i;
irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0xfffffffe);
irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
if (irq_value) {
if (irq_value & BIT(ENT_INT_SRC3_WP_DEPTH_OFF)) {
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << ENT_INT_SRC3_WP_DEPTH_OFF);
dev_warn(dev, "write pointer and depth error (0x%x) \
found!\n",
irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
if (irq_value & BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF)) {
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 <<
ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF);
dev_warn(dev, "iptt no match slot error (0x%x) found!\n",
irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
for (i = 0; i < ARRAY_SIZE(fatal_axi_errors); i++) {
axi_error = &fatal_axi_errors[i];
if (!(irq_value & axi_error->irq_msk))
continue;
if (irq_value & BIT(ENT_INT_SRC3_RP_DEPTH_OFF)) {
dev_warn(dev, "read pointer and depth error (0x%x) \
found!\n",
irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << axi_error->shift);
if (axi_error->sub) {
const struct hisi_sas_hw_error *sub = axi_error->sub;
if (irq_value & BIT(ENT_INT_SRC3_AXI_OFF)) {
int i;
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << ENT_INT_SRC3_AXI_OFF);
err_value = hisi_sas_read32(hisi_hba,
HGC_AXI_FIFO_ERR_INFO);
for (i = 0; i < AXI_ERR_NR; i++) {
if (err_value & BIT(i)) {
dev_warn(dev, "%s (0x%x) found!\n",
axi_err_info[i], irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
err_value = hisi_sas_read32(hisi_hba, axi_error->reg);
for (; sub->msk || sub->msg; sub++) {
if (!(err_value & sub->msk))
continue;
dev_warn(dev, "%s (0x%x) found!\n",
sub->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
}
if (irq_value & BIT(ENT_INT_SRC3_FIFO_OFF)) {
int i;
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << ENT_INT_SRC3_FIFO_OFF);
err_value = hisi_sas_read32(hisi_hba,
HGC_AXI_FIFO_ERR_INFO);
for (i = 0; i < FIFO_ERR_NR; i++) {
if (err_value & BIT(AXI_ERR_NR + i)) {
dev_warn(dev, "%s (0x%x) found!\n",
fifo_err_info[i], irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
}
}
if (irq_value & BIT(ENT_INT_SRC3_LM_OFF)) {
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << ENT_INT_SRC3_LM_OFF);
dev_warn(dev, "LM add/fetch list error (0x%x) found!\n",
irq_value);
} else {
dev_warn(dev, "%s (0x%x) found!\n",
axi_error->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
}
if (irq_value & BIT(ENT_INT_SRC3_ABT_OFF)) {
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
1 << ENT_INT_SRC3_ABT_OFF);
dev_warn(dev, "SAS_HGC_ABT fetch LM list error (0x%x) found!\n",
irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
u32 dev_id = reg_val & ITCT_DEV_MSK;
struct hisi_sas_device *sas_dev = &hisi_hba->devices[dev_id];
if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
u32 dev_id = reg_val & ITCT_DEV_MSK;
struct hisi_sas_device *sas_dev =
&hisi_hba->devices[dev_id];
hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
dev_dbg(dev, "clear ITCT ok\n");
complete(sas_dev->completion);
}
hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
dev_dbg(dev, "clear ITCT ok\n");
complete(sas_dev->completion);
}
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, irq_value);
@ -3408,6 +3373,7 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
interrupt_disable_v2_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
hisi_sas_kill_tasklets(hisi_hba);
hisi_sas_stop_phys(hisi_hba);
@ -3458,7 +3424,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.start_delivery = start_delivery_v2_hw,
.slot_complete = slot_complete_v2_hw,
.phys_init = phys_init_v2_hw,
.phy_enable = enable_phy_v2_hw,
.phy_start = start_phy_v2_hw,
.phy_disable = disable_phy_v2_hw,
.phy_hard_reset = phy_hard_reset_v2_hw,
.get_events = phy_get_events_v2_hw,
@ -3491,16 +3457,11 @@ static int hisi_sas_v2_remove(struct platform_device *pdev)
{
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
int i;
if (timer_pending(&hisi_hba->timer))
del_timer(&hisi_hba->timer);
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
tasklet_kill(&cq->tasklet);
}
hisi_sas_kill_tasklets(hisi_hba);
return hisi_sas_remove(pdev);
}

View File

@ -53,6 +53,11 @@
#define HGC_IOMB_PROC1_STATUS 0x104
#define CFG_1US_TIMER_TRSH 0xcc
#define CHNL_INT_STATUS 0x148
#define HGC_AXI_FIFO_ERR_INFO 0x154
#define AXI_ERR_INFO_OFF 0
#define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF)
#define FIFO_ERR_INFO_OFF 8
#define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF)
#define INT_COAL_EN 0x19c
#define OQ_INT_COAL_TIME 0x1a0
#define OQ_INT_COAL_CNT 0x1a4
@ -135,6 +140,7 @@
#define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
#define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
#define STP_LINK_TIMER (PORT_BASE + 0x120)
#define CON_CFG_DRIVER (PORT_BASE + 0x130)
#define SAS_SSP_CON_TIMER_CFG (PORT_BASE + 0x134)
#define SAS_SMP_CON_TIMER_CFG (PORT_BASE + 0x138)
#define SAS_STP_CON_TIMER_CFG (PORT_BASE + 0x13c)
@ -154,6 +160,10 @@
#define CHL_INT1_DMAC_TX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_TX_ECC_ERR_OFF)
#define CHL_INT1_DMAC_RX_ECC_ERR_OFF 17
#define CHL_INT1_DMAC_RX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_RX_ECC_ERR_OFF)
#define CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF 19
#define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF 20
#define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
#define CHL_INT2 (PORT_BASE + 0x1bc)
#define CHL_INT0_MSK (PORT_BASE + 0x1c0)
#define CHL_INT1_MSK (PORT_BASE + 0x1c4)
@ -171,8 +181,11 @@
#define DMA_RX_STATUS (PORT_BASE + 0x2e8)
#define DMA_RX_STATUS_BUSY_OFF 0
#define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
#define ERR_CNT_DWS_LOST (PORT_BASE + 0x380)
#define ERR_CNT_RESET_PROB (PORT_BASE + 0x384)
#define ERR_CNT_INVLD_DW (PORT_BASE + 0x390)
#define ERR_CNT_DISP_ERR (PORT_BASE + 0x398)
#define MAX_ITCT_HW 4096 /* max the hw can support */
#define DEFAULT_ITCT_HW 2048 /* reset value, not reprogrammed */
#if (HISI_SAS_MAX_DEVICES > DEFAULT_ITCT_HW)
#error Max ITCT exceeded
@ -377,6 +390,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
/* Global registers init */
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
(u32)((1ULL << hisi_hba->queue_count) - 1));
hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400);
hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
hisi_sas_write32(hisi_hba, CFG_1US_TIMER_TRSH, 0xd);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
@ -388,7 +402,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffffffff);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0);
@ -407,7 +421,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff87ffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff);
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
@ -422,6 +436,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
0xa03e8);
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER,
0x7f7a120);
hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER,
0x2a0a80);
}
for (i = 0; i < hisi_hba->queue_count; i++) {
/* Delivery queue */
@ -575,35 +591,24 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba,
static void free_device_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev)
{
DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
struct device *dev = hisi_hba->dev;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
sas_dev->completion = &completion;
/* clear the itct interrupt state */
if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
ENT_INT_SRC3_ITC_INT_MSK);
/* clear the itct table*/
reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
reg_val |= ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
udelay(10);
reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
if (ENT_INT_SRC3_ITC_INT_MSK & reg_val) {
dev_dbg(dev, "got clear ITCT done interrupt\n");
/* invalid the itct state*/
memset(itct, 0, sizeof(struct hisi_sas_itct));
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
ENT_INT_SRC3_ITC_INT_MSK);
/* clear the itct */
hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
dev_dbg(dev, "clear ITCT ok\n");
}
wait_for_completion(sas_dev->completion);
memset(itct, 0, sizeof(struct hisi_sas_itct));
}
static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
@ -755,10 +760,12 @@ static int get_wideport_bitmap_v3_hw(struct hisi_hba *hisi_hba, int port_id)
{
int i, bitmap = 0;
u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
for (i = 0; i < hisi_hba->n_phy; i++)
if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
bitmap |= 1 << i;
if (phy_state & BIT(i))
if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
bitmap |= BIT(i);
return bitmap;
}
@ -988,20 +995,6 @@ err_out_req:
return rc;
}
static int get_ncq_tag_v3_hw(struct sas_task *task, u32 *tag)
{
struct ata_queued_cmd *qc = task->uldd_task;
if (qc) {
if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
qc->tf.command == ATA_CMD_FPDMA_READ) {
*tag = qc->tag;
return 1;
}
}
return 0;
}
static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
@ -1050,7 +1043,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
hdr->dw1 = cpu_to_le32(dw1);
/* dw2 */
if (task->ata_task.use_ncq && get_ncq_tag_v3_hw(task, &hdr_tag)) {
if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, &hdr_tag)) {
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
}
@ -1276,6 +1269,25 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
return res;
}
static const struct hisi_sas_hw_error port_axi_error[] = {
{
.irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF),
.msg = "dma_tx_axi_wr_err",
},
{
.irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF),
.msg = "dma_tx_axi_rd_err",
},
{
.irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF),
.msg = "dma_rx_axi_wr_err",
},
{
.irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF),
.msg = "dma_rx_axi_rd_err",
},
};
static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
{
struct hisi_hba *hisi_hba = p;
@ -1301,10 +1313,19 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
if ((irq_msk & (4 << (phy_no * 4))) &&
irq_value1) {
if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
CHL_INT1_DMAC_TX_ECC_ERR_MSK))
panic("%s: DMAC RX/TX ecc bad error! (0x%x)",
dev_name(dev), irq_value1);
int i;
for (i = 0; i < ARRAY_SIZE(port_axi_error); i++) {
const struct hisi_sas_hw_error *error =
&port_axi_error[i];
if (!(irq_value1 & error->irq_msk))
continue;
dev_warn(dev, "%s error (phy%d 0x%x) found!\n",
error->msg, phy_no, irq_value1);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
hisi_sas_phy_write32(hisi_hba, phy_no,
CHL_INT1, irq_value1);
@ -1331,6 +1352,114 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
return IRQ_HANDLED;
}
static const struct hisi_sas_hw_error axi_error[] = {
{ .msk = BIT(0), .msg = "IOST_AXI_W_ERR" },
{ .msk = BIT(1), .msg = "IOST_AXI_R_ERR" },
{ .msk = BIT(2), .msg = "ITCT_AXI_W_ERR" },
{ .msk = BIT(3), .msg = "ITCT_AXI_R_ERR" },
{ .msk = BIT(4), .msg = "SATA_AXI_W_ERR" },
{ .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
{ .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
{ .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
{},
};
static const struct hisi_sas_hw_error fifo_error[] = {
{ .msk = BIT(8), .msg = "CQE_WINFO_FIFO" },
{ .msk = BIT(9), .msg = "CQE_MSG_FIFIO" },
{ .msk = BIT(10), .msg = "GETDQE_FIFO" },
{ .msk = BIT(11), .msg = "CMDP_FIFO" },
{ .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
{},
};
static const struct hisi_sas_hw_error fatal_axi_error[] = {
{
.irq_msk = BIT(ENT_INT_SRC3_WP_DEPTH_OFF),
.msg = "write pointer and depth",
},
{
.irq_msk = BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF),
.msg = "iptt no match slot",
},
{
.irq_msk = BIT(ENT_INT_SRC3_RP_DEPTH_OFF),
.msg = "read pointer and depth",
},
{
.irq_msk = BIT(ENT_INT_SRC3_AXI_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
.sub = axi_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_FIFO_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
.sub = fifo_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_LM_OFF),
.msg = "LM add/fetch list",
},
{
.irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
.msg = "SAS_HGC_ABT fetch LM list",
},
};
static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
{
u32 irq_value, irq_msk;
struct hisi_hba *hisi_hba = p;
struct device *dev = hisi_hba->dev;
int i;
irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0x1df00);
irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
for (i = 0; i < ARRAY_SIZE(fatal_axi_error); i++) {
const struct hisi_sas_hw_error *error = &fatal_axi_error[i];
if (!(irq_value & error->irq_msk))
continue;
if (error->sub) {
const struct hisi_sas_hw_error *sub = error->sub;
u32 err_value = hisi_sas_read32(hisi_hba, error->reg);
for (; sub->msk || sub->msg; sub++) {
if (!(err_value & sub->msk))
continue;
dev_warn(dev, "%s error (0x%x) found!\n",
sub->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
} else {
dev_warn(dev, "%s error (0x%x) found!\n",
error->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
}
if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
u32 dev_id = reg_val & ITCT_DEV_MSK;
struct hisi_sas_device *sas_dev =
&hisi_hba->devices[dev_id];
hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
dev_dbg(dev, "clear ITCT ok\n");
complete(sas_dev->completion);
}
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, irq_value & 0x1df00);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk);
return IRQ_HANDLED;
}
static void
slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot)
@ -1414,7 +1543,9 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
ts->resp = SAS_TASK_COMPLETE;
if (unlikely(aborted)) {
ts->stat = SAS_ABORTED_TASK;
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
return -1;
}
@ -1629,6 +1760,15 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
goto free_phy_irq;
}
rc = devm_request_irq(dev, pci_irq_vector(pdev, 11),
fatal_axi_int_v3_hw, 0,
DRV_NAME " fatal", hisi_hba);
if (rc) {
dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc);
rc = -ENOENT;
goto free_chnl_interrupt;
}
/* Init tasklets for cq only */
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
@ -1656,6 +1796,8 @@ free_cq_irqs:
free_irq(pci_irq_vector(pdev, k+16), cq);
}
free_irq(pci_irq_vector(pdev, 11), hisi_hba);
free_chnl_interrupt:
free_irq(pci_irq_vector(pdev, 2), hisi_hba);
free_phy_irq:
free_irq(pci_irq_vector(pdev, 1), hisi_hba);
@ -1749,6 +1891,31 @@ static u32 get_phys_state_v3_hw(struct hisi_hba *hisi_hba)
return hisi_sas_read32(hisi_hba, PHY_STATE);
}
static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct sas_phy *sphy = sas_phy->phy;
u32 reg_value;
/* loss dword sync */
reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
sphy->loss_of_dword_sync_count += reg_value;
/* phy reset problem */
reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
sphy->phy_reset_problem_count += reg_value;
/* invalid dword */
reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
sphy->invalid_dword_count += reg_value;
/* disparity err */
reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
sphy->running_disparity_error_count += reg_value;
}
static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
@ -1757,6 +1924,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
interrupt_disable_v3_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
hisi_sas_kill_tasklets(hisi_hba);
hisi_sas_stop_phys(hisi_hba);
@ -1793,7 +1961,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.start_delivery = start_delivery_v3_hw,
.slot_complete = slot_complete_v3_hw,
.phys_init = phys_init_v3_hw,
.phy_enable = enable_phy_v3_hw,
.phy_start = start_phy_v3_hw,
.phy_disable = disable_phy_v3_hw,
.phy_hard_reset = phy_hard_reset_v3_hw,
.phy_get_max_linkrate = phy_get_max_linkrate_v3_hw,
@ -1801,6 +1969,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.dereg_device = dereg_device_v3_hw,
.soft_reset = soft_reset_v3_hw,
.get_phys_state = get_phys_state_v3_hw,
.get_events = phy_get_events_v3_hw,
};
static struct Scsi_Host *
@ -1817,6 +1986,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
}
hisi_hba = shost_priv(shost);
INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
hisi_hba->hw = &hisi_sas_v3_hw;
hisi_hba->pci_dev = pdev;
hisi_hba->dev = dev;
@ -1960,11 +2130,11 @@ hisi_sas_v3_destroy_irqs(struct pci_dev *pdev, struct hisi_hba *hisi_hba)
free_irq(pci_irq_vector(pdev, 1), hisi_hba);
free_irq(pci_irq_vector(pdev, 2), hisi_hba);
free_irq(pci_irq_vector(pdev, 11), hisi_hba);
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
free_irq(pci_irq_vector(pdev, i+16), cq);
tasklet_kill(&cq->tasklet);
}
pci_free_irq_vectors(pdev);
}
@ -1980,6 +2150,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
sas_remove_host(sha->core.shost);
hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
hisi_sas_kill_tasklets(hisi_hba);
pci_release_regions(pdev);
pci_disable_device(pdev);
hisi_sas_free(hisi_hba);

View File

@ -60,7 +60,7 @@
* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.'
* with an optional trailing '-' followed by a byte value (0-255).
*/
#define HPSA_DRIVER_VERSION "3.4.20-0"
#define HPSA_DRIVER_VERSION "3.4.20-125"
#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
#define HPSA "hpsa"
@ -787,7 +787,12 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev,
}
offload_enabled = hdev->offload_enabled;
spin_unlock_irqrestore(&h->lock, flags);
return snprintf(buf, 20, "%d\n", offload_enabled);
if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC)
return snprintf(buf, 20, "%d\n", offload_enabled);
else
return snprintf(buf, 40, "%s\n",
"Not applicable for a controller");
}
#define MAX_PATHS 8
@ -1270,7 +1275,7 @@ static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
dev->model,
label,
dev->offload_config ? '+' : '-',
dev->offload_enabled ? '+' : '-',
dev->offload_to_be_enabled ? '+' : '-',
dev->expose_device);
}
@ -1345,36 +1350,42 @@ lun_assigned:
(*nadded)++;
hpsa_show_dev_msg(KERN_INFO, h, device,
device->expose_device ? "added" : "masked");
device->offload_to_be_enabled = device->offload_enabled;
device->offload_enabled = 0;
return 0;
}
/* Update an entry in h->dev[] array. */
/*
* Called during a scan operation.
*
* Update an entry in h->dev[] array.
*/
static void hpsa_scsi_update_entry(struct ctlr_info *h,
int entry, struct hpsa_scsi_dev_t *new_entry)
{
int offload_enabled;
/* assumes h->devlock is held */
BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES);
/* Raid level changed. */
h->dev[entry]->raid_level = new_entry->raid_level;
/*
* ioacccel_handle may have changed for a dual domain disk
*/
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
/* Raid offload parameters changed. Careful about the ordering. */
if (new_entry->offload_config && new_entry->offload_enabled) {
if (new_entry->offload_config && new_entry->offload_to_be_enabled) {
/*
* if drive is newly offload_enabled, we want to copy the
* raid map data first. If previously offload_enabled and
* offload_config were set, raid map data had better be
* the same as it was before. if raid map data is changed
* the same as it was before. If raid map data has changed
* then it had better be the case that
* h->dev[entry]->offload_enabled is currently 0.
*/
h->dev[entry]->raid_map = new_entry->raid_map;
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
}
if (new_entry->hba_ioaccel_enabled) {
if (new_entry->offload_to_be_enabled) {
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
wmb(); /* set ioaccel_handle *before* hba_ioaccel_enabled */
}
@ -1385,17 +1396,18 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h,
/*
* We can turn off ioaccel offload now, but need to delay turning
* it on until we can update h->dev[entry]->phys_disk[], but we
* ioaccel on until we can update h->dev[entry]->phys_disk[], but we
* can't do that until all the devices are updated.
*/
h->dev[entry]->offload_to_be_enabled = new_entry->offload_enabled;
if (!new_entry->offload_enabled)
h->dev[entry]->offload_to_be_enabled = new_entry->offload_to_be_enabled;
/*
* turn ioaccel off immediately if told to do so.
*/
if (!new_entry->offload_to_be_enabled)
h->dev[entry]->offload_enabled = 0;
offload_enabled = h->dev[entry]->offload_enabled;
h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled;
hpsa_show_dev_msg(KERN_INFO, h, h->dev[entry], "updated");
h->dev[entry]->offload_enabled = offload_enabled;
}
/* Replace an entry from h->dev[] array. */
@ -1421,9 +1433,8 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h,
h->dev[entry] = new_entry;
added[*nadded] = new_entry;
(*nadded)++;
hpsa_show_dev_msg(KERN_INFO, h, new_entry, "replaced");
new_entry->offload_to_be_enabled = new_entry->offload_enabled;
new_entry->offload_enabled = 0;
}
/* Remove an entry from h->dev[] array. */
@ -1513,11 +1524,22 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1,
return 1;
if (dev1->offload_config != dev2->offload_config)
return 1;
if (dev1->offload_enabled != dev2->offload_enabled)
if (dev1->offload_to_be_enabled != dev2->offload_to_be_enabled)
return 1;
if (!is_logical_dev_addr_mode(dev1->scsi3addr))
if (dev1->queue_depth != dev2->queue_depth)
return 1;
/*
* This can happen for dual domain devices. An active
* path change causes the ioaccel handle to change
*
* for example note the handle differences between p0 and p1
* Device WWN ,WWN hash,Handle
* D016 p0|0x3 [02]P2E:01:01,0x5000C5005FC4DACA,0x9B5616,0x01030003
* p1 0x5000C5005FC4DAC9,0x6798C0,0x00040004
*/
if (dev1->ioaccel_handle != dev2->ioaccel_handle)
return 1;
return 0;
}
@ -1727,6 +1749,11 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
* be 0, but we'll turn it off here just in case
*/
if (!logical_drive->phys_disk[i]) {
dev_warn(&h->pdev->dev,
"%s: [%d:%d:%d:%d] A phys disk component of LV is missing, turning off offload_enabled for LV.\n",
__func__,
h->scsi_host->host_no, logical_drive->bus,
logical_drive->target, logical_drive->lun);
logical_drive->offload_enabled = 0;
logical_drive->offload_to_be_enabled = 0;
logical_drive->queue_depth = 8;
@ -1738,8 +1765,12 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
* way too high for partial stripe writes
*/
logical_drive->queue_depth = qdepth;
else
logical_drive->queue_depth = h->nr_cmds;
else {
if (logical_drive->external)
logical_drive->queue_depth = EXTERNAL_QD;
else
logical_drive->queue_depth = h->nr_cmds;
}
}
static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
@ -1759,13 +1790,24 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
/*
* If offload is currently enabled, the RAID map and
* phys_disk[] assignment *better* not be changing
* and since it isn't changing, we do not need to
* update it.
* because we would be changing ioaccel phsy_disk[] pointers
* on a ioaccel volume processing I/O requests.
*
* If an ioaccel volume status changed, initially because it was
* re-configured and thus underwent a transformation, or
* a drive failed, we would have received a state change
* request and ioaccel should have been turned off. When the
* transformation completes, we get another state change
* request to turn ioaccel back on. In this case, we need
* to update the ioaccel information.
*
* Thus: If it is not currently enabled, but will be after
* the scan completes, make sure the ioaccel pointers
* are up to date.
*/
if (dev[i]->offload_enabled)
continue;
hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]);
if (!dev[i]->offload_enabled && dev[i]->offload_to_be_enabled)
hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]);
}
}
@ -1823,11 +1865,13 @@ static void hpsa_wait_for_outstanding_commands_for_dev(struct ctlr_info *h,
break;
if (++waits > 20)
break;
msleep(1000);
}
if (waits > 20)
dev_warn(&h->pdev->dev,
"%s: removing device with %d outstanding commands!\n",
__func__, cmds);
msleep(1000);
}
}
static void hpsa_remove_device(struct ctlr_info *h,
@ -1838,6 +1882,12 @@ static void hpsa_remove_device(struct ctlr_info *h,
if (!h->scsi_host)
return;
/*
* Allow for commands to drain
*/
device->removed = 1;
hpsa_wait_for_outstanding_commands_for_dev(h, device);
if (is_logical_device(device)) { /* RAID */
sdev = scsi_device_lookup(h->scsi_host, device->bus,
device->target, device->lun);
@ -1855,9 +1905,6 @@ static void hpsa_remove_device(struct ctlr_info *h,
}
} else { /* HBA */
device->removed = 1;
hpsa_wait_for_outstanding_commands_for_dev(h, device);
hpsa_remove_sas_device(device);
}
}
@ -1965,8 +2012,13 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h,
}
hpsa_update_log_drive_phys_drive_ptrs(h, h->dev, h->ndevices);
/* Now that h->dev[]->phys_disk[] is coherent, we can enable
/*
* Now that h->dev[]->phys_disk[] is coherent, we can enable
* any logical drives that need it enabled.
*
* The raid map should be current by now.
*
* We are updating the device list used for I/O requests.
*/
for (i = 0; i < h->ndevices; i++) {
if (h->dev[i] == NULL)
@ -2441,7 +2493,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
/*
* Any RAID offload error results in retry which will use
* the normal I/O path so the controller can handle whatever's
* the normal I/O path so the controller can handle whatever is
* wrong.
*/
if (is_logical_device(dev) &&
@ -2913,6 +2965,57 @@ static void hpsa_scsi_interpret_error(struct ctlr_info *h,
}
}
static int hpsa_do_receive_diagnostic(struct ctlr_info *h, u8 *scsi3addr,
u8 page, u8 *buf, size_t bufsize)
{
int rc = IO_OK;
struct CommandList *c;
struct ErrorInfo *ei;
c = cmd_alloc(h);
if (fill_cmd(c, RECEIVE_DIAGNOSTIC, h, buf, bufsize,
page, scsi3addr, TYPE_CMD)) {
rc = -1;
goto out;
}
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
hpsa_scsi_interpret_error(h, c);
rc = -1;
}
out:
cmd_free(h, c);
return rc;
}
static u64 hpsa_get_enclosure_logical_identifier(struct ctlr_info *h,
u8 *scsi3addr)
{
u8 *buf;
u64 sa = 0;
int rc = 0;
buf = kzalloc(1024, GFP_KERNEL);
if (!buf)
return 0;
rc = hpsa_do_receive_diagnostic(h, scsi3addr, RECEIVE_DIAGNOSTIC,
buf, 1024);
if (rc)
goto out;
sa = get_unaligned_be64(buf+12);
out:
kfree(buf);
return sa;
}
static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
u16 page, unsigned char *buf,
unsigned char bufsize)
@ -2929,7 +3032,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
goto out;
}
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
@ -3213,7 +3316,7 @@ static int hpsa_get_raid_map(struct ctlr_info *h,
return -1;
}
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
@ -3256,7 +3359,7 @@ static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h,
c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
@ -3284,7 +3387,7 @@ static int hpsa_bmic_id_controller(struct ctlr_info *h,
goto out;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
@ -3315,7 +3418,7 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff;
hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE,
DEFAULT_TIMEOUT);
NO_TIMEOUT);
ei = c->err_info;
if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
hpsa_scsi_interpret_error(h, c);
@ -3348,6 +3451,9 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h,
bmic_device_index = GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]);
encl_dev->sas_address =
hpsa_get_enclosure_logical_identifier(h, scsi3addr);
if (encl_dev->target == -1 || encl_dev->lun == -1) {
rc = IO_OK;
goto out;
@ -3388,7 +3494,7 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h,
c->Request.CDB[5] = 0;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE,
DEFAULT_TIMEOUT);
NO_TIMEOUT);
if (rc)
goto out;
@ -3472,6 +3578,30 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr,
dev->sas_address = sa;
}
static void hpsa_ext_ctrl_present(struct ctlr_info *h,
struct ReportExtendedLUNdata *physdev)
{
u32 nphysicals;
int i;
if (h->discovery_polling)
return;
nphysicals = (get_unaligned_be32(physdev->LUNListLength) / 24) + 1;
for (i = 0; i < nphysicals; i++) {
if (physdev->LUN[i].device_type ==
BMIC_DEVICE_TYPE_CONTROLLER
&& !is_hba_lunid(physdev->LUN[i].lunid)) {
dev_info(&h->pdev->dev,
"External controller present, activate discovery polling and disable rld caching\n");
hpsa_disable_rld_caching(h);
h->discovery_polling = 1;
break;
}
}
}
/* Get a device id from inquiry page 0x83 */
static bool hpsa_vpd_page_supported(struct ctlr_info *h,
unsigned char scsi3addr[], u8 page)
@ -3516,6 +3646,13 @@ exit_supported:
return true;
}
/*
* Called during a scan operation.
* Sets ioaccel status on the new device list, not the existing device list
*
* The device list used during I/O will be updated later in
* adjust_hpsa_scsi_table.
*/
static void hpsa_get_ioaccel_status(struct ctlr_info *h,
unsigned char *scsi3addr, struct hpsa_scsi_dev_t *this_device)
{
@ -3544,12 +3681,12 @@ static void hpsa_get_ioaccel_status(struct ctlr_info *h,
this_device->offload_config =
!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT);
if (this_device->offload_config) {
this_device->offload_enabled =
this_device->offload_to_be_enabled =
!!(ioaccel_status & OFFLOAD_ENABLED_BIT);
if (hpsa_get_raid_map(h, scsi3addr, this_device))
this_device->offload_enabled = 0;
this_device->offload_to_be_enabled = 0;
}
this_device->offload_to_be_enabled = this_device->offload_enabled;
out:
kfree(buf);
return;
@ -3604,7 +3741,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
if (extended_response)
c->Request.CDB[1] = extended_response;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
@ -3739,7 +3876,7 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h,
(void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD);
rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
DEFAULT_TIMEOUT);
NO_TIMEOUT);
if (rc) {
cmd_free(h, c);
return HPSA_VPD_LV_STATUS_UNSUPPORTED;
@ -4228,6 +4365,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
*/
ndevs_to_allocate = nphysicals + nlogicals + MAX_EXT_TARGETS + 1;
hpsa_ext_ctrl_present(h, physdev_list);
/* Allocate the per device structures */
for (i = 0; i < ndevs_to_allocate; i++) {
if (i >= HPSA_MAX_DEVICES) {
@ -4258,6 +4397,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
int phys_dev_index = i - (raid_ctlr_position == 0);
bool skip_device = false;
memset(tmpdevice, 0, sizeof(*tmpdevice));
physical_device = i < nphysicals + (raid_ctlr_position == 0);
/* Figure out where the LUN ID info is coming from */
@ -4279,7 +4420,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
continue;
}
/* Get device type, vendor, model, device id */
/* Get device type, vendor, model, device id, raid_map */
rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
&is_OBDR);
if (rc == -ENOMEM) {
@ -4296,18 +4437,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
this_device = currentsd[ncurrent];
/* Turn on discovery_polling if there are ext target devices.
* Event-based change notification is unreliable for those.
*/
if (!h->discovery_polling) {
if (tmpdevice->external) {
h->discovery_polling = 1;
dev_info(&h->pdev->dev,
"External target, activate discovery polling.\n");
}
}
*this_device = *tmpdevice;
this_device->physical_device = physical_device;
@ -6496,6 +6625,17 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.CDB[0] = HPSA_INQUIRY;
c->Request.CDB[4] = size & 0xFF;
break;
case RECEIVE_DIAGNOSTIC:
c->Request.CDBLen = 6;
c->Request.type_attr_dir =
TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
c->Request.CDB[1] = 1;
c->Request.CDB[2] = 1;
c->Request.CDB[3] = (size >> 8) & 0xFF;
c->Request.CDB[4] = size & 0xFF;
break;
case HPSA_REPORT_LOG:
case HPSA_REPORT_PHYS:
/* Talking to controller so It's a physical command
@ -8007,6 +8147,10 @@ static void controller_lockup_detected(struct ctlr_info *h)
spin_unlock_irqrestore(&h->lock, flags);
dev_warn(&h->pdev->dev, "Controller lockup detected: 0x%08x after %d\n",
lockup_detected, h->heartbeat_sample_interval / HZ);
if (lockup_detected == 0xffff0000) {
dev_warn(&h->pdev->dev, "Telling controller to do a CHKPT\n");
writel(DOORBELL_GENERATE_CHKPT, h->vaddr + SA5_DOORBELL);
}
pci_disable_device(h->pdev);
fail_all_outstanding_cmds(h);
}
@ -8047,9 +8191,79 @@ static int detect_controller_lockup(struct ctlr_info *h)
return false;
}
/*
* Set ioaccel status for all ioaccel volumes.
*
* Called from monitor controller worker (hpsa_event_monitor_worker)
*
* A Volume (or Volumes that comprise an Array set may be undergoing a
* transformation, so we will be turning off ioaccel for all volumes that
* make up the Array.
*/
static void hpsa_set_ioaccel_status(struct ctlr_info *h)
{
int rc;
int i;
u8 ioaccel_status;
unsigned char *buf;
struct hpsa_scsi_dev_t *device;
if (!h)
return;
buf = kmalloc(64, GFP_KERNEL);
if (!buf)
return;
/*
* Run through current device list used during I/O requests.
*/
for (i = 0; i < h->ndevices; i++) {
device = h->dev[i];
if (!device)
continue;
if (!device->scsi3addr)
continue;
if (!hpsa_vpd_page_supported(h, device->scsi3addr,
HPSA_VPD_LV_IOACCEL_STATUS))
continue;
memset(buf, 0, 64);
rc = hpsa_scsi_do_inquiry(h, device->scsi3addr,
VPD_PAGE | HPSA_VPD_LV_IOACCEL_STATUS,
buf, 64);
if (rc != 0)
continue;
ioaccel_status = buf[IOACCEL_STATUS_BYTE];
device->offload_config =
!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT);
if (device->offload_config)
device->offload_to_be_enabled =
!!(ioaccel_status & OFFLOAD_ENABLED_BIT);
/*
* Immediately turn off ioaccel for any volume the
* controller tells us to. Some of the reasons could be:
* transformation - change to the LVs of an Array.
* degraded volume - component failure
*
* If ioaccel is to be re-enabled, re-enable later during the
* scan operation so the driver can get a fresh raidmap
* before turning ioaccel back on.
*
*/
if (!device->offload_to_be_enabled)
device->offload_enabled = 0;
}
kfree(buf);
}
static void hpsa_ack_ctlr_events(struct ctlr_info *h)
{
int i;
char *event_type;
if (!(h->fw_support & MISC_FW_EVENT_NOTIFY))
@ -8067,10 +8281,7 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
event_type = "configuration change";
/* Stop sending new RAID offload reqs via the IO accelerator */
scsi_block_requests(h->scsi_host);
for (i = 0; i < h->ndevices; i++) {
h->dev[i]->offload_enabled = 0;
h->dev[i]->offload_to_be_enabled = 0;
}
hpsa_set_ioaccel_status(h);
hpsa_drain_accel_commands(h);
/* Set 'accelerator path config change' bit */
dev_warn(&h->pdev->dev,
@ -8087,10 +8298,6 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
writel(h->events, &(h->cfgtable->clear_event_notify));
writel(DOORBELL_CLEAR_EVENTS, h->vaddr + SA5_DOORBELL);
hpsa_wait_for_clear_event_notify_ack(h);
#if 0
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
hpsa_wait_for_mode_change_ack(h);
#endif
}
return;
}
@ -8241,7 +8448,6 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work)
if (h->drv_req_rescan || hpsa_offline_devices_ready(h)) {
hpsa_perform_rescan(h);
} else if (h->discovery_polling) {
hpsa_disable_rld_caching(h);
if (hpsa_luns_changed(h)) {
dev_info(&h->pdev->dev,
"driver discovery polling rescan.\n");
@ -8601,7 +8807,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h)
goto errout;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if ((rc != 0) || (c->err_info->CommandStatus != 0))
goto errout;
@ -8613,7 +8819,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h)
goto errout;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_TODEVICE, DEFAULT_TIMEOUT);
PCI_DMA_TODEVICE, NO_TIMEOUT);
if ((rc != 0) || (c->err_info->CommandStatus != 0))
goto errout;
@ -8623,7 +8829,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h)
goto errout;
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT);
PCI_DMA_FROMDEVICE, NO_TIMEOUT);
if ((rc != 0) || (c->err_info->CommandStatus != 0))
goto errout;
@ -8684,6 +8890,8 @@ static void hpsa_remove_one(struct pci_dev *pdev)
destroy_workqueue(h->rescan_ctlr_wq);
destroy_workqueue(h->resubmit_wq);
hpsa_delete_sas_host(h);
/*
* Call before disabling interrupts.
* scsi_remove_host can trigger I/O operations especially
@ -8718,8 +8926,6 @@ static void hpsa_remove_one(struct pci_dev *pdev)
h->lockup_detected = NULL; /* init_one 2 */
/* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */
hpsa_delete_sas_host(h);
kfree(h); /* init_one 1 */
}
@ -9207,9 +9413,9 @@ static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy)
struct sas_phy *phy = hpsa_sas_phy->phy;
sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy);
sas_phy_free(phy);
if (hpsa_sas_phy->added_to_port)
list_del(&hpsa_sas_phy->phy_list_entry);
sas_phy_delete(phy);
kfree(hpsa_sas_phy);
}
@ -9367,7 +9573,7 @@ static int hpsa_add_sas_host(struct ctlr_info *h)
struct hpsa_sas_port *hpsa_sas_port;
struct hpsa_sas_phy *hpsa_sas_phy;
parent_dev = &h->scsi_host->shost_gendev;
parent_dev = &h->scsi_host->shost_dev;
hpsa_sas_node = hpsa_alloc_sas_node(parent_dev);
if (!hpsa_sas_node)
@ -9458,7 +9664,7 @@ hpsa_sas_get_linkerrors(struct sas_phy *phy)
static int
hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
{
*identifier = 0;
*identifier = rphy->identify.sas_address;
return 0;
}

View File

@ -142,6 +142,7 @@
#define DOORBELL_CTLR_RESET 0x00000004l
#define DOORBELL_CTLR_RESET2 0x00000020l
#define DOORBELL_CLEAR_EVENTS 0x00000040l
#define DOORBELL_GENERATE_CHKPT 0x00000080l
#define CFGTBL_Trans_Simple 0x00000002l
#define CFGTBL_Trans_Performant 0x00000004l
@ -779,6 +780,8 @@ struct bmic_identify_physical_device {
u8 phys_bay_in_box; /* phys drv bay this drive resides */
__le32 rpm; /* Drive rotational speed in rpm */
u8 device_type; /* type of drive */
#define BMIC_DEVICE_TYPE_CONTROLLER 0x07
u8 sata_version; /* only valid when drive_type is SATA */
__le64 big_total_block_count;
__le64 ris_starting_lba;

View File

@ -2083,7 +2083,6 @@ int fc_lport_bsg_request(struct bsg_job *job)
{
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
struct request *rsp = job->req->next_rq;
struct Scsi_Host *shost = fc_bsg_to_shost(job);
struct fc_lport *lport = shost_priv(shost);
struct fc_rport *rport;
@ -2092,8 +2091,6 @@ int fc_lport_bsg_request(struct bsg_job *job)
u32 did, tov;
bsg_reply->reply_payload_rcv_len = 0;
if (rsp)
scsi_req(rsp)->resid_len = job->reply_payload.payload_len;
mutex_lock(&lport->lp_mutex);

View File

@ -24,10 +24,6 @@
#include "sas_dump.h"
static const char *sas_hae_str[] = {
[0] = "HAE_RESET",
};
static const char *sas_porte_str[] = {
[0] = "PORTE_BYTES_DMAED",
[1] = "PORTE_BROADCAST_RCVD",
@ -53,12 +49,6 @@ void sas_dprint_phye(int phyid, enum phy_event pe)
SAS_DPRINTK("phy%d: phy event: %s\n", phyid, sas_phye_str[pe]);
}
void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he)
{
SAS_DPRINTK("ha %s: %s event\n", dev_name(sas_ha->dev),
sas_hae_str[he]);
}
void sas_dump_port(struct asd_sas_port *port)
{
SAS_DPRINTK("port%d: class:0x%x\n", port->id, port->class);

View File

@ -26,5 +26,4 @@
void sas_dprint_porte(int phyid, enum port_event pe);
void sas_dprint_phye(int phyid, enum phy_event pe);
void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he);
void sas_dump_port(struct asd_sas_port *port);

View File

@ -37,7 +37,7 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
if (test_bit(SAS_HA_DRAINING, &ha->state)) {
/* add it to the defer list, if not already pending */
if (list_empty(&sw->drain_node))
list_add(&sw->drain_node, &ha->defer_q);
list_add_tail(&sw->drain_node, &ha->defer_q);
} else
rc = scsi_queue_work(ha->core.shost, &sw->work);
@ -124,15 +124,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
mutex_unlock(&ha->disco_mutex);
}
static int notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
{
BUG_ON(event >= HA_NUM_EVENTS);
return sas_queue_event(event, &sas_ha->pending,
&sas_ha->ha_events[event].work, sas_ha);
}
static int notify_port_event(struct asd_sas_phy *phy, enum port_event event)
static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
{
struct sas_ha_struct *ha = phy->ha;
@ -154,19 +146,7 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
int sas_init_events(struct sas_ha_struct *sas_ha)
{
static const work_func_t sas_ha_event_fns[HA_NUM_EVENTS] = {
[HAE_RESET] = sas_hae_reset,
};
int i;
for (i = 0; i < HA_NUM_EVENTS; i++) {
INIT_SAS_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
sas_ha->ha_events[i].ha = sas_ha;
}
sas_ha->notify_ha_event = notify_ha_event;
sas_ha->notify_port_event = notify_port_event;
sas_ha->notify_port_event = sas_notify_port_event;
sas_ha->notify_phy_event = sas_notify_phy_event;
return 0;

View File

@ -107,17 +107,6 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
hashed[2] = r & 0xFF;
}
/* ---------- HA events ---------- */
void sas_hae_reset(struct work_struct *work)
{
struct sas_ha_event *ev = to_sas_ha_event(work);
struct sas_ha_struct *ha = ev->ha;
clear_bit(HAE_RESET, &ha->pending);
}
int sas_register_ha(struct sas_ha_struct *sas_ha)
{
int error = 0;
@ -155,7 +144,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
INIT_LIST_HEAD(&sas_ha->eh_ata_q);
return 0;
Undo_ports:
sas_unregister_ports(sas_ha);
Undo_phys:

View File

@ -23,6 +23,7 @@
#include <scsi/scsi_host.h>
#include <linux/ktime.h>
#include <linux/workqueue.h>
#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS)
#define CONFIG_SCSI_LPFC_DEBUG_FS
@ -653,6 +654,8 @@ struct lpfc_hba {
/* SLI4 specific HBA data structure */
struct lpfc_sli4_hba sli4_hba;
struct workqueue_struct *wq;
struct lpfc_sli sli;
uint8_t pci_dev_grp; /* lpfc PCI dev group: 0x0, 0x1, 0x2,... */
uint32_t sli_rev; /* SLI2, SLI3, or SLI4 */

View File

@ -3134,7 +3134,8 @@ lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
return snprintf(buf, PAGE_SIZE, "%d\n", pring->txq_max);
return snprintf(buf, PAGE_SIZE, "%d\n",
pring ? pring->txq_max : 0);
}
static DEVICE_ATTR(txq_hw, S_IRUGO,
@ -3147,7 +3148,8 @@ lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr,
struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
return snprintf(buf, PAGE_SIZE, "%d\n", pring->txcmplq_max);
return snprintf(buf, PAGE_SIZE, "%d\n",
pring ? pring->txcmplq_max : 0);
}
static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
@ -3380,7 +3382,7 @@ LPFC_ATTR_R(nvmet_mrq,
*/
LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_FCP,
LPFC_ENABLE_FCP, LPFC_ENABLE_BOTH,
"Define fc4 type to register with fabric.");
"Enable FC4 Protocol support - FCP / NVME");
/*
* lpfc_xri_split: Defines the division of XRI resources between SCSI and NVME
@ -3396,7 +3398,7 @@ LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_FCP,
* percentage will go to NVME.
*/
LPFC_ATTR_R(xri_split, 50, 10, 90,
"Division of XRI resources between SCSI and NVME");
"Percentage of FCP XRI resources versus NVME");
/*
# lpfc_log_verbose: Only turn this flag on if you are willing to risk being

View File

@ -2911,7 +2911,7 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
}
}
if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) {
if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer || !pring) {
ret_val = -ENOMEM;
goto err_post_rxbufs_exit;
}
@ -5421,6 +5421,8 @@ lpfc_bsg_timeout(struct bsg_job *job)
struct lpfc_iocbq *check_iocb, *next_iocb;
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return -EIO;
/* if job's driver data is NULL, the command completed or is in the
* the process of completing. In this case, return status to request

View File

@ -2227,7 +2227,7 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
kfree(phba->nvmeio_trc);
/* Allocate new trace buffer and initialize */
phba->nvmeio_trc = kmalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) *
phba->nvmeio_trc = kzalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) *
sz), GFP_KERNEL);
if (!phba->nvmeio_trc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@ -2235,8 +2235,6 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
"nvmeio_trc buffer\n");
return -ENOMEM;
}
memset(phba->nvmeio_trc, 0,
(sizeof(struct lpfc_debugfs_nvmeio_trc) * sz));
atomic_set(&phba->nvmeio_trc_cnt, 0);
phba->nvmeio_trc_on = 0;
phba->nvmeio_trc_output_idx = 0;
@ -5457,7 +5455,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
/* Allocate trace buffer and initialize */
phba->nvmeio_trc = kmalloc(
phba->nvmeio_trc = kzalloc(
(sizeof(struct lpfc_debugfs_nvmeio_trc) *
phba->nvmeio_trc_size), GFP_KERNEL);
@ -5467,9 +5465,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
"nvmeio_trc buffer\n");
goto nvmeio_off;
}
memset(phba->nvmeio_trc, 0,
(sizeof(struct lpfc_debugfs_nvmeio_trc) *
phba->nvmeio_trc_size));
phba->nvmeio_trc_on = 1;
phba->nvmeio_trc_output_idx = 0;
phba->nvmeio_trc = NULL;

View File

@ -5394,10 +5394,6 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
(len + pcmd), vport, ndlp);
len += lpfc_rdp_res_fec_desc((struct fc_fec_rdp_desc *)(len + pcmd),
&rdp_context->link_stat);
/* Check if nport is logged, BZ190632 */
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
goto lpfc_skip_descriptor;
len += lpfc_rdp_res_bbc_desc((struct fc_rdp_bbc_desc *)(len + pcmd),
&rdp_context->link_stat, vport);
len += lpfc_rdp_res_oed_temp_desc(phba,
@ -5418,7 +5414,6 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
len += lpfc_rdp_res_opd_desc((struct fc_rdp_opd_sfp_desc *)(len + pcmd),
rdp_context->page_a0, vport);
lpfc_skip_descriptor:
rdp_res->length = cpu_to_be32(len - 8);
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
@ -5540,7 +5535,6 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
rdp_req = (struct fc_rdp_req_frame *) pcmd->virt;
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"2422 ELS RDP Request "
"dec len %d tag x%x port_id %d len %d\n",
@ -5549,12 +5543,6 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
be32_to_cpu(rdp_req->nport_id_desc.nport_id),
be32_to_cpu(rdp_req->nport_id_desc.length));
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED) &&
!phba->cfg_enable_SmartSAN) {
rjt_err = LSRJT_UNABLE_TPC;
rjt_expl = LSEXP_PORT_LOGIN_REQ;
goto error;
}
if (sizeof(struct fc_rdp_nport_desc) !=
be32_to_cpu(rdp_req->rdp_des_length))
goto rjt_logerr;
@ -7430,6 +7418,8 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
timeout = (uint32_t)(phba->fc_ratov << 1);
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return;
if ((phba->pport->load_flag & FC_UNLOADING))
return;
@ -9310,6 +9300,9 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
list) {
@ -9416,7 +9409,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
rxid, 1);
/* Check if TXQ queue needs to be serviced */
if (!(list_empty(&pring->txq)))
if (pring && !list_empty(&pring->txq))
lpfc_worker_wake_up(phba);
return;
}

View File

@ -3324,7 +3324,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Unblock ELS traffic */
pring = lpfc_phba_elsring(phba);
pring->flag &= ~LPFC_STOP_IOCB_EVENT;
if (pring)
pring->flag &= ~LPFC_STOP_IOCB_EVENT;
/* Check for error */
if (mb->mbxStatus) {
@ -4981,7 +4982,8 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_cancel_retry_delay_tmo(vport, ndlp);
if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
!(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
!(ndlp->nlp_flag & NLP_RPI_REGISTERED) &&
phba->sli_rev != LPFC_SLI_REV4) {
/* For this case we need to cleanup the default rpi
* allocated by the firmware.
*/
@ -5429,6 +5431,8 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
psli = &phba->sli;
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return;
/* Error matching iocb on txq or txcmplq
* First check the txq.

View File

@ -3636,7 +3636,7 @@ struct lpfc_mbx_get_port_name {
#define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4
#define MB_CQE_STATUS_DMA_FAILED 0x5
#define LPFC_MBX_WR_CONFIG_MAX_BDE 8
#define LPFC_MBX_WR_CONFIG_MAX_BDE 1
struct lpfc_mbx_wr_object {
struct mbox_header header;
union {

View File

@ -3216,6 +3216,9 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
lpfc_destroy_vport_work_array(phba, vports);
lpfc_sli_mbox_sys_shutdown(phba, mbx_action);
if (phba->wq)
flush_workqueue(phba->wq);
}
/**
@ -4173,6 +4176,9 @@ void
lpfc_stop_port(struct lpfc_hba *phba)
{
phba->lpfc_stop_port(phba);
if (phba->wq)
flush_workqueue(phba->wq);
}
/**
@ -6363,6 +6369,9 @@ lpfc_setup_driver_resource_phase2(struct lpfc_hba *phba)
return error;
}
/* workqueue for deferred irq use */
phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
return 0;
}
@ -6377,6 +6386,12 @@ lpfc_setup_driver_resource_phase2(struct lpfc_hba *phba)
static void
lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba)
{
if (phba->wq) {
flush_workqueue(phba->wq);
destroy_workqueue(phba->wq);
phba->wq = NULL;
}
/* Stop kernel worker thread */
kthread_stop(phba->worker_thread);
}
@ -11397,14 +11412,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
/* Remove FC host and then SCSI host with the physical port */
fc_remove_host(shost);
scsi_remove_host(shost);
/* Perform ndlp cleanup on the physical port. The nvme and nvmet
* localports are destroyed after to cleanup all transport memory.
*/
lpfc_cleanup(vport);
lpfc_nvmet_destroy_targetport(phba);
lpfc_nvme_destroy_localport(vport);
/*
* Bring down the SLI Layer. This step disables all interrupts,
* clears the rings, discards all mailbox commands, and resets
@ -11413,6 +11420,15 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
lpfc_debugfs_terminate(vport);
lpfc_sli4_hba_unset(phba);
/* Perform ndlp cleanup on the physical port. The nvme and nvmet
* localports are destroyed after to cleanup all transport memory.
*/
lpfc_cleanup(vport);
lpfc_nvmet_destroy_targetport(phba);
lpfc_nvme_destroy_localport(vport);
lpfc_stop_hba_timers(phba);
spin_lock_irq(&phba->hbalock);
list_del_init(&vport->listentry);
spin_unlock_irq(&phba->hbalock);

View File

@ -216,7 +216,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
pring = lpfc_phba_elsring(phba);
/* In case of error recovery path, we might have a NULL pring here */
if (!pring)
if (unlikely(!pring))
return;
/* Abort outstanding I/O on NPort <nlp_DID> */

View File

@ -416,6 +416,9 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
vport = lport->vport;
if (vport->load_flag & FC_UNLOADING)
return -ENODEV;
ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
@ -667,15 +670,17 @@ lpfc_nvme_ktime(struct lpfc_hba *phba,
struct lpfc_nvme_buf *lpfc_ncmd)
{
uint64_t seg1, seg2, seg3, seg4;
uint64_t segsum;
if (!phba->ktime_on)
return;
if (!lpfc_ncmd->ts_last_cmd ||
!lpfc_ncmd->ts_cmd_start ||
!lpfc_ncmd->ts_cmd_wqput ||
!lpfc_ncmd->ts_isr_cmpl ||
!lpfc_ncmd->ts_data_nvme)
return;
if (lpfc_ncmd->ts_data_nvme < lpfc_ncmd->ts_cmd_start)
return;
if (lpfc_ncmd->ts_cmd_start < lpfc_ncmd->ts_last_cmd)
return;
if (lpfc_ncmd->ts_cmd_wqput < lpfc_ncmd->ts_cmd_start)
@ -695,15 +700,23 @@ lpfc_nvme_ktime(struct lpfc_hba *phba,
* cmpl is handled off to the NVME Layer.
*/
seg1 = lpfc_ncmd->ts_cmd_start - lpfc_ncmd->ts_last_cmd;
if (seg1 > 5000000) /* 5 ms - for sequential IOs */
return;
if (seg1 > 5000000) /* 5 ms - for sequential IOs only */
seg1 = 0;
/* Calculate times relative to start of IO */
seg2 = (lpfc_ncmd->ts_cmd_wqput - lpfc_ncmd->ts_cmd_start);
seg3 = (lpfc_ncmd->ts_isr_cmpl -
lpfc_ncmd->ts_cmd_start) - seg2;
seg4 = (lpfc_ncmd->ts_data_nvme -
lpfc_ncmd->ts_cmd_start) - seg2 - seg3;
segsum = seg2;
seg3 = lpfc_ncmd->ts_isr_cmpl - lpfc_ncmd->ts_cmd_start;
if (segsum > seg3)
return;
seg3 -= segsum;
segsum += seg3;
seg4 = lpfc_ncmd->ts_data_nvme - lpfc_ncmd->ts_cmd_start;
if (segsum > seg4)
return;
seg4 -= segsum;
phba->ktime_data_samples++;
phba->ktime_seg1_total += seg1;
if (seg1 < phba->ktime_seg1_min)
@ -840,7 +853,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
} else {
lpfc_ncmd->status = (bf_get(lpfc_wcqe_c_status, wcqe) &
LPFC_IOCB_STATUS_MASK);
lpfc_ncmd->result = wcqe->parameter;
lpfc_ncmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
/* For NVME, the only failure path that results in an
* IO error is when the adapter rejects it. All other
@ -874,9 +887,20 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
lpfc_ncmd->status, lpfc_ncmd->result,
wcqe->total_data_placed);
break;
case IOSTAT_LOCAL_REJECT:
/* Let fall through to set command final state. */
if (lpfc_ncmd->result == IOERR_ABORT_REQUESTED)
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NVME_IOERR,
"6032 Delay Aborted cmd %p "
"nvme cmd %p, xri x%x, "
"xb %d\n",
lpfc_ncmd, nCmd,
lpfc_ncmd->cur_iocbq.sli4_xritag,
bf_get(lpfc_wcqe_c_xb, wcqe));
default:
out_err:
lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
"6072 NVME Completion Error: xri %x "
"status x%x result x%x placed x%x\n",
lpfc_ncmd->cur_iocbq.sli4_xritag,
@ -902,7 +926,7 @@ out_err:
* owns the dma address.
*/
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (lpfc_ncmd->ts_cmd_start) {
lpfc_ncmd->ts_isr_cmpl = pwqeIn->isr_timestamp;
lpfc_ncmd->ts_data_nvme = ktime_get_ns();
phba->ktime_last_cmd = lpfc_ncmd->ts_data_nvme;
@ -920,12 +944,18 @@ out_err:
#endif
freqpriv = nCmd->private;
freqpriv->nvme_buf = NULL;
nCmd->done(nCmd);
/* NVME targets need completion held off until the abort exchange
* completes.
*/
if (!(lpfc_ncmd->flags & LPFC_SBUF_XBUSY))
nCmd->done(nCmd);
spin_lock_irqsave(&phba->hbalock, flags);
lpfc_ncmd->nrport = NULL;
spin_unlock_irqrestore(&phba->hbalock, flags);
/* Call release with XB=1 to queue the IO into the abort list. */
lpfc_release_nvme_buf(phba, lpfc_ncmd);
}
@ -1119,12 +1149,12 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
first_data_sgl = sgl;
lpfc_ncmd->seg_cnt = nCmd->sg_cnt;
if (lpfc_ncmd->seg_cnt > phba->cfg_nvme_seg_cnt) {
if (lpfc_ncmd->seg_cnt > phba->cfg_nvme_seg_cnt + 1) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"6058 Too many sg segments from "
"NVME Transport. Max %d, "
"nvmeIO sg_cnt %d\n",
phba->cfg_nvme_seg_cnt,
phba->cfg_nvme_seg_cnt + 1,
lpfc_ncmd->seg_cnt);
lpfc_ncmd->seg_cnt = 0;
return 1;
@ -1225,6 +1255,21 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
vport = lport->vport;
phba = vport->phba;
if (vport->load_flag & FC_UNLOADING) {
ret = -ENODEV;
goto out_fail;
}
/* Validate pointers. */
if (!pnvme_lport || !pnvme_rport || !freqpriv) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR | LOG_NODE,
"6117 No Send:IO submit ptrs NULL, lport %p, "
"rport %p fcreq_priv %p\n",
pnvme_lport, pnvme_rport, freqpriv);
ret = -ENODEV;
goto out_fail;
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
start = ktime_get_ns();
@ -1283,9 +1328,11 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
goto out_fail;
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (start) {
lpfc_ncmd->ts_cmd_start = start;
lpfc_ncmd->ts_last_cmd = phba->ktime_last_cmd;
} else {
lpfc_ncmd->ts_cmd_start = 0;
}
#endif
@ -1327,7 +1374,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
ret = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, &lpfc_ncmd->cur_iocbq);
if (ret) {
atomic_dec(&ndlp->cmd_pending);
lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
"6113 FCP could not issue WQE err %x "
"sid: x%x did: x%x oxid: x%x\n",
ret, vport->fc_myDID, ndlp->nlp_DID,
@ -1336,7 +1383,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
if (lpfc_ncmd->ts_cmd_start)
lpfc_ncmd->ts_cmd_wqput = ktime_get_ns();
if (phba->cpucheck_on & LPFC_CHECK_NVME_IO) {
@ -1387,7 +1434,7 @@ void
lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_wcqe_complete *abts_cmpl)
{
lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
"6145 ABORT_XRI_CN completing on rpi x%x "
"original iotag x%x, abort cmd iotag x%x "
"req_tag x%x, status x%x, hwstatus x%x\n",
@ -1938,14 +1985,13 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc)
* pci bus space for an I/O. The DMA buffer includes the
* number of SGE's necessary to support the sg_tablesize.
*/
lpfc_ncmd->data = dma_pool_alloc(phba->lpfc_sg_dma_buf_pool,
GFP_KERNEL,
&lpfc_ncmd->dma_handle);
lpfc_ncmd->data = dma_pool_zalloc(phba->lpfc_sg_dma_buf_pool,
GFP_KERNEL,
&lpfc_ncmd->dma_handle);
if (!lpfc_ncmd->data) {
kfree(lpfc_ncmd);
break;
}
memset(lpfc_ncmd->data, 0, phba->cfg_sg_dma_buf_size);
lxri = lpfc_sli4_next_xritag(phba);
if (lxri == NO_XRI) {
@ -2042,9 +2088,6 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
spin_lock_irqsave(&phba->nvme_buf_list_get_lock, iflag);
list_for_each_entry_safe(lpfc_ncmd, lpfc_ncmd_next,
&phba->lpfc_nvme_buf_list_get, list) {
if (lpfc_test_rrq_active(phba, ndlp,
lpfc_ncmd->cur_iocbq.sli4_lxritag))
continue;
list_del_init(&lpfc_ncmd->list);
found = 1;
break;
@ -2057,9 +2100,6 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
spin_unlock(&phba->nvme_buf_list_put_lock);
list_for_each_entry_safe(lpfc_ncmd, lpfc_ncmd_next,
&phba->lpfc_nvme_buf_list_get, list) {
if (lpfc_test_rrq_active(
phba, ndlp, lpfc_ncmd->cur_iocbq.sli4_lxritag))
continue;
list_del_init(&lpfc_ncmd->list);
found = 1;
break;
@ -2096,7 +2136,6 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd)
spin_lock_irqsave(&phba->sli4_hba.abts_nvme_buf_list_lock,
iflag);
lpfc_ncmd->nvmeCmd = NULL;
list_add_tail(&lpfc_ncmd->list,
&phba->sli4_hba.lpfc_abts_nvme_buf_list);
spin_unlock_irqrestore(&phba->sli4_hba.abts_nvme_buf_list_lock,
@ -2296,6 +2335,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
struct lpfc_nvme_rport *rport;
struct nvme_fc_remote_port *remote_port;
struct nvme_fc_port_info rpinfo;
struct lpfc_nodelist *prev_ndlp;
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC,
"6006 Register NVME PORT. DID x%06x nlptype x%x\n",
@ -2332,7 +2372,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* new rport.
*/
rport = remote_port->private;
if (ndlp->nrport == rport) {
if (ndlp->nrport) {
lpfc_printf_vlog(ndlp->vport, KERN_INFO,
LOG_NVME_DISC,
"6014 Rebinding lport to "
@ -2343,24 +2383,33 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
remote_port->port_role,
ndlp->nlp_type,
ndlp->nlp_DID);
} else {
/* New rport. */
rport->remoteport = remote_port;
rport->lport = lport;
rport->ndlp = lpfc_nlp_get(ndlp);
if (!rport->ndlp)
return -1;
ndlp->nrport = rport;
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NVME_DISC | LOG_NODE,
"6022 Binding new rport to "
"lport %p Rport WWNN 0x%llx, "
"Rport WWPN 0x%llx DID "
"x%06x Role x%x\n",
lport,
rpinfo.node_name, rpinfo.port_name,
rpinfo.port_id, rpinfo.port_role);
prev_ndlp = rport->ndlp;
/* Sever the ndlp<->rport connection before dropping
* the ndlp ref from register.
*/
ndlp->nrport = NULL;
rport->ndlp = NULL;
if (prev_ndlp)
lpfc_nlp_put(ndlp);
}
/* Clean bind the rport to the ndlp. */
rport->remoteport = remote_port;
rport->lport = lport;
rport->ndlp = lpfc_nlp_get(ndlp);
if (!rport->ndlp)
return -1;
ndlp->nrport = rport;
lpfc_printf_vlog(vport, KERN_INFO,
LOG_NVME_DISC | LOG_NODE,
"6022 Binding new rport to "
"lport %p Rport WWNN 0x%llx, "
"Rport WWPN 0x%llx DID "
"x%06x Role x%x\n",
lport,
rpinfo.node_name, rpinfo.port_name,
rpinfo.port_id, rpinfo.port_role);
} else {
lpfc_printf_vlog(vport, KERN_ERR,
LOG_NVME_DISC | LOG_NODE,
@ -2454,18 +2503,18 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* @axri: pointer to the fcp xri abort wcqe structure.
*
* This routine is invoked by the worker thread to process a SLI4 fast-path
* FCP aborted xri.
* NVME aborted xri. Aborted NVME IO commands are completed to the transport
* here.
**/
void
lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
struct sli4_wcqe_xri_aborted *axri)
{
uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
struct lpfc_nvme_buf *lpfc_ncmd, *next_lpfc_ncmd;
struct nvmefc_fcp_req *nvme_cmd = NULL;
struct lpfc_nodelist *ndlp;
unsigned long iflag = 0;
int rrq_empty = 0;
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
return;
@ -2481,25 +2530,24 @@ lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
spin_unlock(
&phba->sli4_hba.abts_nvme_buf_list_lock);
rrq_empty = list_empty(&phba->active_rrq_list);
spin_unlock_irqrestore(&phba->hbalock, iflag);
ndlp = lpfc_ncmd->ndlp;
if (ndlp) {
lpfc_set_rrq_active(
phba, ndlp,
lpfc_ncmd->cur_iocbq.sli4_lxritag,
rxid, 1);
if (ndlp)
lpfc_sli4_abts_err_handler(phba, ndlp, axri);
}
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6311 XRI Aborted xri x%x tag x%x "
"released\n",
xri, lpfc_ncmd->cur_iocbq.iotag);
"6311 nvme_cmd %p xri x%x tag x%x "
"abort complete and xri released\n",
lpfc_ncmd->nvmeCmd, xri,
lpfc_ncmd->cur_iocbq.iotag);
/* Aborted NVME commands are required to not complete
* before the abort exchange command fully completes.
* Once completed, it is available via the put list.
*/
nvme_cmd = lpfc_ncmd->nvmeCmd;
nvme_cmd->done(nvme_cmd);
lpfc_release_nvme_buf(phba, lpfc_ncmd);
if (rrq_empty)
lpfc_worker_wake_up(phba);
return;
}
}

View File

@ -76,7 +76,7 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp)
{
unsigned long iflag;
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6313 NVMET Defer ctx release xri x%x flg x%x\n",
ctxp->oxid, ctxp->flag);
@ -221,9 +221,8 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
spin_lock_init(&ctxp->ctxlock);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (ctxp->ts_cmd_nvme) {
ctxp->ts_cmd_nvme = ktime_get_ns();
ctxp->ts_isr_cmd = ctxp->ts_cmd_nvme;
ctxp->ts_nvme_data = 0;
ctxp->ts_data_wqput = 0;
ctxp->ts_isr_data = 0;
@ -289,9 +288,7 @@ lpfc_nvmet_ktime(struct lpfc_hba *phba,
{
uint64_t seg1, seg2, seg3, seg4, seg5;
uint64_t seg6, seg7, seg8, seg9, seg10;
if (!phba->ktime_on)
return;
uint64_t segsum;
if (!ctxp->ts_isr_cmd || !ctxp->ts_cmd_nvme ||
!ctxp->ts_nvme_data || !ctxp->ts_data_wqput ||
@ -300,6 +297,8 @@ lpfc_nvmet_ktime(struct lpfc_hba *phba,
!ctxp->ts_isr_status || !ctxp->ts_status_nvme)
return;
if (ctxp->ts_status_nvme < ctxp->ts_isr_cmd)
return;
if (ctxp->ts_isr_cmd > ctxp->ts_cmd_nvme)
return;
if (ctxp->ts_cmd_nvme > ctxp->ts_nvme_data)
@ -344,34 +343,66 @@ lpfc_nvmet_ktime(struct lpfc_hba *phba,
* (Segments 1 thru 4) for READDATA_RSP
*/
seg1 = ctxp->ts_cmd_nvme - ctxp->ts_isr_cmd;
seg2 = (ctxp->ts_nvme_data - ctxp->ts_isr_cmd) - seg1;
seg3 = (ctxp->ts_data_wqput - ctxp->ts_isr_cmd) -
seg1 - seg2;
seg4 = (ctxp->ts_isr_data - ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3;
seg5 = (ctxp->ts_data_nvme - ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3 - seg4;
segsum = seg1;
seg2 = ctxp->ts_nvme_data - ctxp->ts_isr_cmd;
if (segsum > seg2)
return;
seg2 -= segsum;
segsum += seg2;
seg3 = ctxp->ts_data_wqput - ctxp->ts_isr_cmd;
if (segsum > seg3)
return;
seg3 -= segsum;
segsum += seg3;
seg4 = ctxp->ts_isr_data - ctxp->ts_isr_cmd;
if (segsum > seg4)
return;
seg4 -= segsum;
segsum += seg4;
seg5 = ctxp->ts_data_nvme - ctxp->ts_isr_cmd;
if (segsum > seg5)
return;
seg5 -= segsum;
segsum += seg5;
/* For auto rsp commands seg6 thru seg10 will be 0 */
if (ctxp->ts_nvme_status > ctxp->ts_data_nvme) {
seg6 = (ctxp->ts_nvme_status -
ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3 - seg4 - seg5;
seg7 = (ctxp->ts_status_wqput -
ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3 -
seg4 - seg5 - seg6;
seg8 = (ctxp->ts_isr_status -
ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3 - seg4 -
seg5 - seg6 - seg7;
seg9 = (ctxp->ts_status_nvme -
ctxp->ts_isr_cmd) -
seg1 - seg2 - seg3 - seg4 -
seg5 - seg6 - seg7 - seg8;
seg6 = ctxp->ts_nvme_status - ctxp->ts_isr_cmd;
if (segsum > seg6)
return;
seg6 -= segsum;
segsum += seg6;
seg7 = ctxp->ts_status_wqput - ctxp->ts_isr_cmd;
if (segsum > seg7)
return;
seg7 -= segsum;
segsum += seg7;
seg8 = ctxp->ts_isr_status - ctxp->ts_isr_cmd;
if (segsum > seg8)
return;
seg8 -= segsum;
segsum += seg8;
seg9 = ctxp->ts_status_nvme - ctxp->ts_isr_cmd;
if (segsum > seg9)
return;
seg9 -= segsum;
segsum += seg9;
if (ctxp->ts_isr_status < ctxp->ts_isr_cmd)
return;
seg10 = (ctxp->ts_isr_status -
ctxp->ts_isr_cmd);
} else {
if (ctxp->ts_isr_data < ctxp->ts_isr_cmd)
return;
seg6 = 0;
seg7 = 0;
seg8 = 0;
@ -463,7 +494,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_nvmet_tgtport *tgtp;
struct nvmefc_tgt_fcp_req *rsp;
struct lpfc_nvmet_rcv_ctx *ctxp;
uint32_t status, result, op, start_clean;
uint32_t status, result, op, start_clean, logerr;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t id;
#endif
@ -491,17 +522,21 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
if (tgtp)
atomic_inc(&tgtp->xmt_fcp_rsp_error);
logerr = LOG_NVME_IOERR;
/* pick up SLI4 exhange busy condition */
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
ctxp->flag |= LPFC_NVMET_XBUSY;
logerr |= LOG_NVME_ABTS;
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6315 IO Cmpl XBUSY: xri x%x: %x/%x\n",
ctxp->oxid, status, result);
} else {
ctxp->flag &= ~LPFC_NVMET_XBUSY;
}
lpfc_printf_log(phba, KERN_INFO, logerr,
"6315 IO Error Cmpl xri x%x: %x/%x XBUSY:x%x\n",
ctxp->oxid, status, result, ctxp->flag);
} else {
rsp->fcp_error = NVME_SC_SUCCESS;
if (op == NVMET_FCOP_RSP)
@ -519,7 +554,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
ctxp->entry_cnt++;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (ctxp->ts_cmd_nvme) {
if (rsp->op == NVMET_FCOP_READDATA_RSP) {
ctxp->ts_isr_data =
cmdwqe->isr_timestamp;
@ -553,7 +588,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
#endif
rsp->done(rsp);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
if (ctxp->ts_cmd_nvme)
lpfc_nvmet_ktime(phba, ctxp);
#endif
/* lpfc_nvmet_xmt_fcp_release() will recycle the context */
@ -563,7 +598,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
memset(((char *)cmdwqe) + start_clean, 0,
(sizeof(struct lpfc_iocbq) - start_clean));
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (ctxp->ts_cmd_nvme) {
ctxp->ts_isr_data = cmdwqe->isr_timestamp;
ctxp->ts_data_nvme = ktime_get_ns();
}
@ -597,6 +632,9 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
struct ulp_bde64 bpl;
int rc;
if (phba->pport->load_flag & FC_UNLOADING)
return -ENODEV;
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
"6023 NVMET LS rsp oxid x%x\n", ctxp->oxid);
@ -678,8 +716,13 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
struct lpfc_iocbq *nvmewqeq;
int rc;
if (phba->pport->load_flag & FC_UNLOADING) {
rc = -ENODEV;
goto aerr;
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (ctxp->ts_cmd_nvme) {
if (rsp->op == NVMET_FCOP_RSP)
ctxp->ts_nvme_status = ktime_get_ns();
else
@ -734,7 +777,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq);
if (rc == WQE_SUCCESS) {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (!phba->ktime_on)
if (!ctxp->ts_cmd_nvme)
return 0;
if (rsp->op == NVMET_FCOP_RSP)
ctxp->ts_status_wqput = ktime_get_ns();
@ -777,6 +820,9 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
struct lpfc_hba *phba = ctxp->phba;
unsigned long flags;
if (phba->pport->load_flag & FC_UNLOADING)
return;
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6103 NVMET Abort op: oxri x%x flg x%x ste %d\n",
ctxp->oxid, ctxp->flag, ctxp->state);
@ -787,6 +833,7 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
atomic_inc(&lpfc_nvmep->xmt_fcp_abort);
spin_lock_irqsave(&ctxp->ctxlock, flags);
ctxp->state = LPFC_NVMET_STE_ABORT;
/* Since iaab/iaar are NOT set, we need to check
* if the firmware is in process of aborting IO
@ -1125,9 +1172,7 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
}
lpfc_tgttemplate.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
lpfc_tgttemplate.max_hw_queues = phba->cfg_nvme_io_channel;
lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP |
NVMET_FCTGTFEAT_CMD_IN_ISR |
NVMET_FCTGTFEAT_OPDONE_IN_ISR;
lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP;
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
error = nvmet_fc_register_targetport(&pinfo, &lpfc_tgttemplate,
@ -1138,9 +1183,14 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
#endif
if (error) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
"6025 Cannot register NVME targetport "
"x%x\n", error);
"6025 Cannot register NVME targetport x%x: "
"portnm %llx nodenm %llx segs %d qs %d\n",
error,
pinfo.port_name, pinfo.node_name,
lpfc_tgttemplate.max_sgl_segments,
lpfc_tgttemplate.max_hw_queues);
phba->targetport = NULL;
phba->nvmet_support = 0;
lpfc_nvmet_cleanup_io_context(phba);
@ -1152,9 +1202,11 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
"6026 Registered NVME "
"targetport: %p, private %p "
"portnm %llx nodenm %llx\n",
"portnm %llx nodenm %llx segs %d qs %d\n",
phba->targetport, tgtp,
pinfo.port_name, pinfo.node_name);
pinfo.port_name, pinfo.node_name,
lpfc_tgttemplate.max_sgl_segments,
lpfc_tgttemplate.max_hw_queues);
atomic_set(&tgtp->rcv_ls_req_in, 0);
atomic_set(&tgtp->rcv_ls_req_out, 0);
@ -1457,6 +1509,7 @@ static struct lpfc_nvmet_ctxbuf *
lpfc_nvmet_replenish_context(struct lpfc_hba *phba,
struct lpfc_nvmet_ctx_info *current_infop)
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
struct lpfc_nvmet_ctxbuf *ctx_buf = NULL;
struct lpfc_nvmet_ctx_info *get_infop;
int i;
@ -1504,6 +1557,7 @@ lpfc_nvmet_replenish_context(struct lpfc_hba *phba,
get_infop = get_infop->nvmet_ctx_next_cpu;
}
#endif
/* Nothing found, all contexts for the MRQ are in-flight */
return NULL;
}
@ -1631,7 +1685,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
spin_lock_init(&ctxp->ctxlock);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on) {
if (isr_timestamp) {
ctxp->ts_isr_cmd = isr_timestamp;
ctxp->ts_cmd_nvme = ktime_get_ns();
ctxp->ts_nvme_data = 0;
@ -1642,6 +1696,8 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
ctxp->ts_status_wqput = 0;
ctxp->ts_isr_status = 0;
ctxp->ts_status_nvme = 0;
} else {
ctxp->ts_cmd_nvme = 0;
}
#endif
@ -2320,7 +2376,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
atomic_inc(&tgtp->xmt_abort_rsp);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6165 ABORT cmpl: xri x%x flg x%x (%d) "
"WCQE: %08x %08x %08x %08x\n",
ctxp->oxid, ctxp->flag, released,

View File

@ -80,8 +80,8 @@ static int lpfc_sli4_fp_handle_cqe(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_cqe *);
static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
int);
static int lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
struct lpfc_eqe *eqe, uint32_t qidx);
static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
struct lpfc_eqe *eqe, uint32_t qidx);
static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba);
static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba);
static int lpfc_sli4_abort_nvme_io(struct lpfc_hba *phba,
@ -2732,7 +2732,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
*
* This function looks up the iocb_lookup table to get the command iocb
* corresponding to the given response iocb using the iotag of the
* response iocb. This function is called with the hbalock held.
* response iocb. This function is called with the hbalock held
* for sli3 devices or the ring_lock for sli4 devices.
* This function returns the command iocb object if it finds the command
* iocb else returns NULL.
**/
@ -2828,9 +2829,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
unsigned long iflag;
/* Based on the iotag field, get the cmd IOCB from the txcmplq */
spin_lock_irqsave(&phba->hbalock, iflag);
if (phba->sli_rev == LPFC_SLI_REV4)
spin_lock_irqsave(&pring->ring_lock, iflag);
else
spin_lock_irqsave(&phba->hbalock, iflag);
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
spin_unlock_irqrestore(&phba->hbalock, iflag);
if (phba->sli_rev == LPFC_SLI_REV4)
spin_unlock_irqrestore(&pring->ring_lock, iflag);
else
spin_unlock_irqrestore(&phba->hbalock, iflag);
if (cmdiocbp) {
if (cmdiocbp->iocb_cmpl) {
@ -9396,10 +9403,13 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
* for abort iocb hba_wqidx should already
* be setup based on what work queue we used.
*/
if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX))
if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
piocb->hba_wqidx =
lpfc_sli4_scmd_to_wqidx_distr(phba,
piocb->context1);
piocb->hba_wqidx = piocb->hba_wqidx %
phba->cfg_fcp_io_channel;
}
return phba->sli4_hba.fcp_wq[piocb->hba_wqidx]->pring;
} else {
if (unlikely(!phba->sli4_hba.oas_wq))
@ -10632,6 +10642,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
(cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
return 0;
if (!pring) {
if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
else
cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
goto abort_iotag_exit;
}
/*
* If we're unloading, don't abort iocb on the ELS ring, but change
* the callback so that nothing happens when it finishes.
@ -12500,6 +12518,8 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
unsigned long iflags;
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return NULL;
wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
spin_lock_irqsave(&pring->ring_lock, iflags);
@ -12507,19 +12527,21 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
/* Look up the ELS command IOCB and create pseudo response IOCB */
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
bf_get(lpfc_wcqe_c_request_tag, wcqe));
/* Put the iocb back on the txcmplq */
lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
if (unlikely(!cmdiocbq)) {
spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"0386 ELS complete with no corresponding "
"cmdiocb: iotag (%d)\n",
bf_get(lpfc_wcqe_c_request_tag, wcqe));
"cmdiocb: 0x%x 0x%x 0x%x 0x%x\n",
wcqe->word0, wcqe->total_data_placed,
wcqe->parameter, wcqe->word3);
lpfc_sli_release_iocbq(phba, irspiocbq);
return NULL;
}
/* Put the iocb back on the txcmplq */
lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
/* Fake the irspiocbq and copy necessary response information */
lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
@ -13010,14 +13032,11 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
* completion queue, and then return.
*
**/
static int
static void
lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
struct lpfc_queue *speq)
{
struct lpfc_queue *cq = NULL, *childq;
struct lpfc_cqe *cqe;
bool workposted = false;
int ecount = 0;
uint16_t cqid;
/* Get the reference to the corresponding CQ */
@ -13034,48 +13053,84 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0365 Slow-path CQ identifier "
"(%d) does not exist\n", cqid);
return 0;
return;
}
/* Save EQ associated with this CQ */
cq->assoc_qp = speq;
if (!queue_work(phba->wq, &cq->spwork))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0390 Cannot schedule soft IRQ "
"for CQ eqcqid=%d, cqid=%d on CPU %d\n",
cqid, cq->queue_id, smp_processor_id());
}
/**
* lpfc_sli4_sp_process_cq - Process a slow-path event queue entry
* @phba: Pointer to HBA context object.
*
* This routine process a event queue entry from the slow-path event queue.
* It will check the MajorCode and MinorCode to determine this is for a
* completion event on a completion queue, if not, an error shall be logged
* and just return. Otherwise, it will get to the corresponding completion
* queue and process all the entries on that completion queue, rearm the
* completion queue, and then return.
*
**/
static void
lpfc_sli4_sp_process_cq(struct work_struct *work)
{
struct lpfc_queue *cq =
container_of(work, struct lpfc_queue, spwork);
struct lpfc_hba *phba = cq->phba;
struct lpfc_cqe *cqe;
bool workposted = false;
int ccount = 0;
/* Process all the entries to the CQ */
switch (cq->type) {
case LPFC_MCQ:
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
if (!(++ecount % cq->entry_repost))
if (!(++ccount % cq->entry_repost))
break;
cq->CQ_mbox++;
}
break;
case LPFC_WCQ:
while ((cqe = lpfc_sli4_cq_get(cq))) {
if ((cq->subtype == LPFC_FCP) ||
(cq->subtype == LPFC_NVME))
if (cq->subtype == LPFC_FCP ||
cq->subtype == LPFC_NVME) {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
cq->isr_timestamp = ktime_get_ns();
else
cq->isr_timestamp = 0;
#endif
workposted |= lpfc_sli4_fp_handle_cqe(phba, cq,
cqe);
else
} else {
workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
cqe);
if (!(++ecount % cq->entry_repost))
}
if (!(++ccount % cq->entry_repost))
break;
}
/* Track the max number of CQEs processed in 1 EQ */
if (ecount > cq->CQ_max_cqe)
cq->CQ_max_cqe = ecount;
if (ccount > cq->CQ_max_cqe)
cq->CQ_max_cqe = ccount;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0370 Invalid completion queue type (%d)\n",
cq->type);
return 0;
return;
}
/* Catch the no cq entry condition, log an error */
if (unlikely(ecount == 0))
if (unlikely(ccount == 0))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0371 No entry from the CQ: identifier "
"(x%x), type (%d)\n", cq->queue_id, cq->type);
@ -13086,8 +13141,6 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
/* wake up worker thread if there are works to be done */
if (workposted)
lpfc_worker_wake_up(phba);
return ecount;
}
/**
@ -13143,11 +13196,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
bf_get(lpfc_wcqe_c_request_tag, wcqe));
return;
}
if (cq->assoc_qp)
cmdiocbq->isr_timestamp =
cq->assoc_qp->isr_timestamp;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
cmdiocbq->isr_timestamp = cq->isr_timestamp;
#endif
if (cmdiocbq->iocb_cmpl == NULL) {
if (cmdiocbq->wqe_cmpl) {
if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
@ -13292,7 +13343,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
dma_buf->bytes_recv = bf_get(lpfc_rcqe_length, rcqe);
lpfc_nvmet_unsol_fcp_event(
phba, idx, dma_buf,
cq->assoc_qp->isr_timestamp);
cq->isr_timestamp);
return false;
}
drop:
@ -13395,15 +13446,12 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
* queue and process all the entries on the completion queue, rearm the
* completion queue, and then return.
**/
static int
static void
lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
uint32_t qidx)
{
struct lpfc_queue *cq = NULL;
struct lpfc_cqe *cqe;
bool workposted = false;
uint16_t cqid, id;
int ecount = 0;
if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@ -13411,7 +13459,7 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
"event: majorcode=x%x, minorcode=x%x\n",
bf_get_le32(lpfc_eqe_major_code, eqe),
bf_get_le32(lpfc_eqe_minor_code, eqe));
return 0;
return;
}
/* Get the reference to the corresponding CQ */
@ -13448,9 +13496,8 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
/* Otherwise this is a Slow path event */
if (cq == NULL) {
ecount = lpfc_sli4_sp_handle_eqe(phba, eqe,
phba->sli4_hba.hba_eq[qidx]);
return ecount;
lpfc_sli4_sp_handle_eqe(phba, eqe, phba->sli4_hba.hba_eq[qidx]);
return;
}
process_cq:
@ -13459,26 +13506,61 @@ process_cq:
"0368 Miss-matched fast-path completion "
"queue identifier: eqcqid=%d, fcpcqid=%d\n",
cqid, cq->queue_id);
return 0;
return;
}
/* Save EQ associated with this CQ */
cq->assoc_qp = phba->sli4_hba.hba_eq[qidx];
if (!queue_work(phba->wq, &cq->irqwork))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0363 Cannot schedule soft IRQ "
"for CQ eqcqid=%d, cqid=%d on CPU %d\n",
cqid, cq->queue_id, smp_processor_id());
}
/**
* lpfc_sli4_hba_process_cq - Process a fast-path event queue entry
* @phba: Pointer to HBA context object.
* @eqe: Pointer to fast-path event queue entry.
*
* This routine process a event queue entry from the fast-path event queue.
* It will check the MajorCode and MinorCode to determine this is for a
* completion event on a completion queue, if not, an error shall be logged
* and just return. Otherwise, it will get to the corresponding completion
* queue and process all the entries on the completion queue, rearm the
* completion queue, and then return.
**/
static void
lpfc_sli4_hba_process_cq(struct work_struct *work)
{
struct lpfc_queue *cq =
container_of(work, struct lpfc_queue, irqwork);
struct lpfc_hba *phba = cq->phba;
struct lpfc_cqe *cqe;
bool workposted = false;
int ccount = 0;
/* Process all the entries to the CQ */
while ((cqe = lpfc_sli4_cq_get(cq))) {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
cq->isr_timestamp = ktime_get_ns();
else
cq->isr_timestamp = 0;
#endif
workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
if (!(++ecount % cq->entry_repost))
if (!(++ccount % cq->entry_repost))
break;
}
/* Track the max number of CQEs processed in 1 EQ */
if (ecount > cq->CQ_max_cqe)
cq->CQ_max_cqe = ecount;
cq->assoc_qp->EQ_cqe_cnt += ecount;
if (ccount > cq->CQ_max_cqe)
cq->CQ_max_cqe = ccount;
cq->assoc_qp->EQ_cqe_cnt += ccount;
/* Catch the no cq entry condition */
if (unlikely(ecount == 0))
if (unlikely(ccount == 0))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0369 No entry from fast-path completion "
"queue fcpcqid=%d\n", cq->queue_id);
@ -13489,8 +13571,6 @@ process_cq:
/* wake up worker thread if there are works to be done */
if (workposted)
lpfc_worker_wake_up(phba);
return ecount;
}
static void
@ -13524,10 +13604,7 @@ static void
lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
{
struct lpfc_queue *cq;
struct lpfc_cqe *cqe;
bool workposted = false;
uint16_t cqid;
int ecount = 0;
if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@ -13562,30 +13639,12 @@ lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
/* Save EQ associated with this CQ */
cq->assoc_qp = phba->sli4_hba.fof_eq;
/* Process all the entries to the OAS CQ */
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
if (!(++ecount % cq->entry_repost))
break;
}
/* Track the max number of CQEs processed in 1 EQ */
if (ecount > cq->CQ_max_cqe)
cq->CQ_max_cqe = ecount;
cq->assoc_qp->EQ_cqe_cnt += ecount;
/* Catch the no cq entry condition */
if (unlikely(ecount == 0))
/* CQ work will be processed on CPU affinitized to this IRQ */
if (!queue_work(phba->wq, &cq->irqwork))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"9153 No entry from fast-path completion "
"queue fcpcqid=%d\n", cq->queue_id);
/* In any case, flash and re-arm the CQ */
lpfc_sli4_cq_release(cq, LPFC_QUEUE_REARM);
/* wake up worker thread if there are works to be done */
if (workposted)
lpfc_worker_wake_up(phba);
"0367 Cannot schedule soft IRQ "
"for CQ eqcqid=%d, cqid=%d on CPU %d\n",
cqid, cq->queue_id, smp_processor_id());
}
/**
@ -13711,7 +13770,6 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
struct lpfc_eqe *eqe;
unsigned long iflag;
int ecount = 0;
int ccount = 0;
int hba_eqidx;
/* Get the driver's phba structure from the dev_id */
@ -13729,11 +13787,6 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
if (unlikely(!fpeq))
return IRQ_NONE;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (phba->ktime_on)
fpeq->isr_timestamp = ktime_get_ns();
#endif
if (lpfc_fcp_look_ahead) {
if (atomic_dec_and_test(&hba_eq_hdl->hba_eq_in_use))
lpfc_sli4_eq_clr_intr(fpeq);
@ -13760,12 +13813,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
* Process all the event on FCP fast-path EQ
*/
while ((eqe = lpfc_sli4_eq_get(fpeq))) {
if (eqe == NULL)
break;
ccount += lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
if (!(++ecount % fpeq->entry_repost) ||
ccount > LPFC_MAX_ISR_CQE)
lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
if (!(++ecount % fpeq->entry_repost))
break;
fpeq->EQ_processed++;
}
@ -13948,6 +13997,8 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
queue->entry_size = entry_size;
queue->entry_count = entry_count;
queue->phba = phba;
INIT_WORK(&queue->irqwork, lpfc_sli4_hba_process_cq);
INIT_WORK(&queue->spwork, lpfc_sli4_sp_process_cq);
/* entry_repost will be set during q creation */
@ -17137,7 +17188,8 @@ exit:
if (pcmd && pcmd->virt)
dma_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
kfree(pcmd);
lpfc_sli_release_iocbq(phba, iocbq);
if (iocbq)
lpfc_sli_release_iocbq(phba, iocbq);
lpfc_in_buf_free(phba, &dmabuf->dbuf);
}
@ -18691,6 +18743,8 @@ lpfc_drain_txq(struct lpfc_hba *phba)
uint32_t txq_cnt = 0;
pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return 0;
spin_lock_irqsave(&pring->ring_lock, iflags);
list_for_each_entry(piocbq, &pring->txq, list) {

View File

@ -158,7 +158,6 @@ struct lpfc_queue {
#define LPFC_MQ_REPOST 8
#define LPFC_CQ_REPOST 64
#define LPFC_RQ_REPOST 64
#define LPFC_MAX_ISR_CQE 64
#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 /* For WQs */
uint32_t queue_id; /* Queue ID assigned by the hardware */
uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */
@ -202,6 +201,9 @@ struct lpfc_queue {
#define RQ_buf_posted q_cnt_3
#define RQ_rcv_buf q_cnt_4
struct work_struct irqwork;
struct work_struct spwork;
uint64_t isr_timestamp;
struct lpfc_queue *assoc_qp;
union sli4_qe qe[1]; /* array to index entries (must be last) */

View File

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

View File

@ -313,6 +313,15 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
goto error_out;
}
/* NPIV is not supported if HBA has NVME enabled */
if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
"3189 Create VPORT failed: "
"NPIV is not supported on NVME\n");
rc = VPORT_INVAL;
goto error_out;
}
vpi = lpfc_alloc_vpi(phba);
if (vpi == 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,

View File

@ -35,8 +35,8 @@
/*
* MegaRAID SAS Driver meta data
*/
#define MEGASAS_VERSION "07.702.06.00-rc1"
#define MEGASAS_RELDATE "June 21, 2017"
#define MEGASAS_VERSION "07.703.05.00-rc1"
#define MEGASAS_RELDATE "October 5, 2017"
/*
* Device IDs
@ -57,6 +57,7 @@
#define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052
#define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053
#define PCI_DEVICE_ID_LSI_VENTURA 0x0014
#define PCI_DEVICE_ID_LSI_CRUSADER 0x0015
#define PCI_DEVICE_ID_LSI_HARPOON 0x0016
#define PCI_DEVICE_ID_LSI_TOMCAT 0x0017
#define PCI_DEVICE_ID_LSI_VENTURA_4PORT 0x001B
@ -186,16 +187,19 @@
/*
* MFI command opcodes
*/
#define MFI_CMD_INIT 0x00
#define MFI_CMD_LD_READ 0x01
#define MFI_CMD_LD_WRITE 0x02
#define MFI_CMD_LD_SCSI_IO 0x03
#define MFI_CMD_PD_SCSI_IO 0x04
#define MFI_CMD_DCMD 0x05
#define MFI_CMD_ABORT 0x06
#define MFI_CMD_SMP 0x07
#define MFI_CMD_STP 0x08
#define MFI_CMD_INVALID 0xff
enum MFI_CMD_OP {
MFI_CMD_INIT = 0x0,
MFI_CMD_LD_READ = 0x1,
MFI_CMD_LD_WRITE = 0x2,
MFI_CMD_LD_SCSI_IO = 0x3,
MFI_CMD_PD_SCSI_IO = 0x4,
MFI_CMD_DCMD = 0x5,
MFI_CMD_ABORT = 0x6,
MFI_CMD_SMP = 0x7,
MFI_CMD_STP = 0x8,
MFI_CMD_OP_COUNT,
MFI_CMD_INVALID = 0xff
};
#define MR_DCMD_CTRL_GET_INFO 0x01010000
#define MR_DCMD_LD_GET_LIST 0x03010000
@ -1504,6 +1508,15 @@ enum FW_BOOT_CONTEXT {
#define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000
#define MR_CAN_HANDLE_64_BIT_DMA_OFFSET (1 << 25)
enum MR_ADAPTER_TYPE {
MFI_SERIES = 1,
THUNDERBOLT_SERIES = 2,
INVADER_SERIES = 3,
VENTURA_SERIES = 4,
};
/*
* register set for both 1068 and 1078 controllers
* structure extended for 1078 registers
@ -1617,7 +1630,8 @@ union megasas_sgl_frame {
typedef union _MFI_CAPABILITIES {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved:19;
u32 reserved:18;
u32 support_64bit_mode:1;
u32 support_pd_map_target_id:1;
u32 support_qd_throttling:1;
u32 support_fp_rlbypass:1;
@ -1645,7 +1659,8 @@ typedef union _MFI_CAPABILITIES {
u32 support_fp_rlbypass:1;
u32 support_qd_throttling:1;
u32 support_pd_map_target_id:1;
u32 reserved:19;
u32 support_64bit_mode:1;
u32 reserved:18;
#endif
} mfi_capabilities;
__le32 reg;
@ -2114,6 +2129,19 @@ struct megasas_instance {
u32 *crash_dump_buf;
dma_addr_t crash_dump_h;
struct MR_PD_LIST *pd_list_buf;
dma_addr_t pd_list_buf_h;
struct megasas_ctrl_info *ctrl_info_buf;
dma_addr_t ctrl_info_buf_h;
struct MR_LD_LIST *ld_list_buf;
dma_addr_t ld_list_buf_h;
struct MR_LD_TARGETID_LIST *ld_targetid_list_buf;
dma_addr_t ld_targetid_list_buf_h;
void *crash_buf[MAX_CRASH_DUMP_SIZE];
unsigned int fw_crash_buffer_size;
unsigned int fw_crash_state;
@ -2210,8 +2238,6 @@ struct megasas_instance {
/* Ptr to hba specific information */
void *ctrl_context;
u32 ctrl_context_pages;
struct megasas_ctrl_info *ctrl_info;
unsigned int msix_vectors;
struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
u64 map_id;
@ -2236,12 +2262,13 @@ struct megasas_instance {
bool dev_handle;
bool fw_sync_cache_support;
u32 mfi_frame_size;
bool is_ventura;
bool msix_combined;
u16 max_raid_mapsize;
/* preffered count to send as LDIO irrspective of FP capable.*/
u8 r1_ldio_hint_default;
u32 nvme_page_size;
u8 adapter_type;
bool consistent_mask_64bit;
};
struct MR_LD_VF_MAP {
u32 size;
@ -2488,4 +2515,7 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
u32 mega_mod64(u64 dividend, u32 divisor);
int megasas_alloc_fusion_context(struct megasas_instance *instance);
void megasas_free_fusion_context(struct megasas_instance *instance);
void megasas_set_dma_settings(struct megasas_instance *instance,
struct megasas_dcmd_frame *dcmd,
dma_addr_t dma_addr, u32 dma_len);
#endif /*LSI_MEGARAID_SAS_H */

File diff suppressed because it is too large Load Diff

View File

@ -737,7 +737,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
*pDevHandle = MR_PdDevHandleGet(pd, map);
*pPdInterface = MR_PdInterfaceTypeGet(pd, map);
/* get second pd also for raid 1/10 fast path writes*/
if (instance->is_ventura &&
if ((instance->adapter_type == VENTURA_SERIES) &&
(raid->level == 1) &&
!io_info->isRead) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
@ -747,8 +747,8 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
}
} else {
if ((raid->level >= 5) &&
((fusion->adapter_type == THUNDERBOLT_SERIES) ||
((fusion->adapter_type == INVADER_SERIES) &&
((instance->adapter_type == THUNDERBOLT_SERIES) ||
((instance->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
@ -762,7 +762,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
}
*pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
if (instance->is_ventura) {
if (instance->adapter_type == VENTURA_SERIES) {
((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm =
@ -853,7 +853,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
*pDevHandle = MR_PdDevHandleGet(pd, map);
*pPdInterface = MR_PdInterfaceTypeGet(pd, map);
/* get second pd also for raid 1/10 fast path writes*/
if (instance->is_ventura &&
if ((instance->adapter_type == VENTURA_SERIES) &&
(raid->level == 1) &&
!io_info->isRead) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
@ -863,8 +863,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
}
} else {
if ((raid->level >= 5) &&
((fusion->adapter_type == THUNDERBOLT_SERIES) ||
((fusion->adapter_type == INVADER_SERIES) &&
((instance->adapter_type == THUNDERBOLT_SERIES) ||
((instance->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
@ -880,7 +880,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
}
*pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
if (instance->is_ventura) {
if (instance->adapter_type == VENTURA_SERIES) {
((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm =
@ -1088,10 +1088,10 @@ MR_BuildRaidContext(struct megasas_instance *instance,
cpu_to_le16(raid->fpIoTimeoutForLd ?
raid->fpIoTimeoutForLd :
map->raidMap.fpPdIoTimeoutSec);
if (fusion->adapter_type == INVADER_SERIES)
if (instance->adapter_type == INVADER_SERIES)
pRAID_Context->reg_lock_flags = (isRead) ?
raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
else if (!instance->is_ventura)
else if (instance->adapter_type == THUNDERBOLT_SERIES)
pRAID_Context->reg_lock_flags = (isRead) ?
REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
pRAID_Context->virtual_disk_tgt_id = raid->targetId;

File diff suppressed because it is too large Load Diff

View File

@ -51,6 +51,8 @@
#define HOST_DIAG_RESET_ADAPTER 0x4
#define MEGASAS_FUSION_MAX_RESET_TRIES 3
#define MAX_MSIX_QUEUES_FUSION 128
#define RDPQ_MAX_INDEX_IN_ONE_CHUNK 16
#define RDPQ_MAX_CHUNK_COUNT (MAX_MSIX_QUEUES_FUSION / RDPQ_MAX_INDEX_IN_ONE_CHUNK)
/* Invader defines */
#define MPI2_TYPE_CUDA 0x2
@ -103,12 +105,8 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
#define THRESHOLD_REPLY_COUNT 50
#define RAID_1_PEER_CMDS 2
#define JBOD_MAPS_COUNT 2
enum MR_FUSION_ADAPTER_TYPE {
THUNDERBOLT_SERIES = 0,
INVADER_SERIES = 1,
VENTURA_SERIES = 2,
};
#define MEGASAS_REDUCE_QD_COUNT 64
#define IOC_INIT_FRAME_SIZE 4096
/*
* Raid Context structure which describes MegaRAID specific IO Parameters
@ -1270,6 +1268,12 @@ struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
u32 Reserved2;
};
struct rdpq_alloc_detail {
struct dma_pool *dma_pool_ptr;
dma_addr_t pool_entry_phys;
union MPI2_REPLY_DESCRIPTORS_UNION *pool_entry_virt;
};
struct fusion_context {
struct megasas_cmd_fusion **cmd_list;
dma_addr_t req_frames_desc_phys;
@ -1282,9 +1286,14 @@ struct fusion_context {
struct dma_pool *sg_dma_pool;
struct dma_pool *sense_dma_pool;
u8 *sense;
dma_addr_t sense_phys_addr;
dma_addr_t reply_frames_desc_phys[MAX_MSIX_QUEUES_FUSION];
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc[MAX_MSIX_QUEUES_FUSION];
struct rdpq_alloc_detail rdpq_tracker[RDPQ_MAX_CHUNK_COUNT];
struct dma_pool *reply_frames_desc_pool;
struct dma_pool *reply_frames_desc_pool_align;
u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
@ -1318,9 +1327,13 @@ struct fusion_context {
u8 fast_path_io;
struct LD_LOAD_BALANCE_INFO *load_balance_info;
u32 load_balance_info_pages;
LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
u8 adapter_type;
LD_SPAN_INFO *log_to_span;
u32 log_to_span_pages;
struct LD_STREAM_DETECT **stream_detect_by_ld;
dma_addr_t ioc_init_request_phys;
struct MPI2_IOC_INIT_REQUEST *ioc_init_request;
struct megasas_cmd *ioc_init_cmd;
};
union desc_value {

View File

@ -9,7 +9,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
* mpi2.h Version: 02.00.42
* mpi2.h Version: 02.00.48
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -104,6 +104,16 @@
* 08-25-15 02.00.40 Bumped MPI2_HEADER_VERSION_UNIT.
* 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT
* 01-01-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT
* 04-05-16 02.00.43 Modified MPI26_DIAG_BOOT_DEVICE_SELECT defines
* to be unique within first 32 characters.
* Removed AHCI support.
* Removed SOP support.
* Bumped MPI2_HEADER_VERSION_UNIT.
* 04-10-16 02.00.44 Bumped MPI2_HEADER_VERSION_UNIT.
* 07-06-16 02.00.45 Bumped MPI2_HEADER_VERSION_UNIT.
* 09-02-16 02.00.46 Bumped MPI2_HEADER_VERSION_UNIT.
* 11-23-16 02.00.47 Bumped MPI2_HEADER_VERSION_UNIT.
* 02-03-17 02.00.48 Bumped MPI2_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@ -143,7 +153,7 @@
#define MPI2_VERSION_02_06 (0x0206)
/*Unit and Dev versioning for this MPI header set */
#define MPI2_HEADER_VERSION_UNIT (0x2A)
#define MPI2_HEADER_VERSION_UNIT (0x30)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@ -250,6 +260,12 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
/* Defines for V7A/V7R HostDiagnostic Register */
#define MPI26_DIAG_BOOT_DEVICE_SEL_64FLASH (0x00000000)
#define MPI26_DIAG_BOOT_DEVICE_SEL_64HCDW (0x00000800)
#define MPI26_DIAG_BOOT_DEVICE_SEL_32FLASH (0x00001000)
#define MPI26_DIAG_BOOT_DEVICE_SEL_32HCDW (0x00001800)
#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
#define MPI2_DIAG_HCB_MODE (0x00000100)
@ -368,6 +384,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A)
#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C)
#define MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED (0x10)
#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
@ -426,6 +443,13 @@ typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
Mpi25FastPathSCSIIORequestDescriptor_t,
*pMpi25FastPathSCSIIORequestDescriptor_t;
/*PCIe Encapsulated Request Descriptor */
typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR,
*PTR_MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR,
Mpi26PCIeEncapsulatedRequestDescriptor_t,
*pMpi26PCIeEncapsulatedRequestDescriptor_t;
/*union of Request Descriptors */
typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
@ -434,6 +458,7 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO;
MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR PCIeEncapsulated;
U64 Words;
} MPI2_REQUEST_DESCRIPTOR_UNION,
*PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
@ -451,6 +476,7 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
* Atomic SCSI Target Request Descriptor
* Atomic RAID Accelerator Request Descriptor
* Atomic Fast Path SCSI IO Request Descriptor
* Atomic PCIe Encapsulated Request Descriptor
*/
/*Atomic Request Descriptor */
@ -488,6 +514,7 @@ typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR {
#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05)
#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06)
#define MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS (0x08)
#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
/*values for marking a reply descriptor as unused */
@ -566,6 +593,13 @@ typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
Mpi25FastPathSCSIIOSuccessReplyDescriptor_t,
*pMpi25FastPathSCSIIOSuccessReplyDescriptor_t;
/*PCIe Encapsulated Success Reply Descriptor */
typedef MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR,
*PTR_MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR,
Mpi26PCIeEncapsulatedSuccessReplyDescriptor_t,
*pMpi26PCIeEncapsulatedSuccessReplyDescriptor_t;
/*union of Reply Descriptors */
typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
@ -575,6 +609,8 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess;
MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR
PCIeEncapsulatedSuccess;
U64 Words;
} MPI2_REPLY_DESCRIPTORS_UNION,
*PTR_MPI2_REPLY_DESCRIPTORS_UNION,
@ -617,6 +653,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F)
#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30)
#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31)
#define MPI2_FUNCTION_NVME_ENCAPSULATED (0x33)
#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0)
#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF)
@ -1163,6 +1200,8 @@ typedef union _MPI25_SGE_IO_UNION {
#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C)
#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00)
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP (0x08)
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_SGL (0x10)
/*Data Location Address Space */

View File

@ -7,7 +7,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
* mpi2_cnfg.h Version: 02.00.35
* mpi2_cnfg.h Version: 02.00.40
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -190,6 +190,35 @@
* MPI2_CONFIG_PAGE_BIOS_1.
* 08-25-15 02.00.34 Bumped Header Version.
* 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4.
* 01-21-16 02.00.36 Added/modified MPI2_MFGPAGE_DEVID_SAS defines.
* Added Link field to PCIe Link Pages
* Added EnclosureLevel and ConnectorName to PCIe
* Device Page 0.
* Added define for PCIE IoUnit page 1 max rate shift.
* Added comment for reserved ExtPageTypes.
* Added SAS 4 22.5 gbs speed support.
* Added PCIe 4 16.0 GT/sec speec support.
* Removed AHCI support.
* Removed SOP support.
* Added NegotiatedLinkRate and NegotiatedPortWidth to
* PCIe device page 0.
* 04-10-16 02.00.37 Fixed MPI2_MFGPAGE_DEVID_SAS3616/3708 defines
* 07-01-16 02.00.38 Added Manufacturing page 7 Connector types.
* Changed declaration of ConnectorName in PCIe DevicePage0
* to match SAS DevicePage 0.
* Added SATADeviceWaitTime to IO Unit Page 11.
* Added MPI26_MFGPAGE_DEVID_SAS4008
* Added x16 PCIe width to IO Unit Page 7
* Added LINKFLAGS to control SRIS in PCIe IO Unit page 1
* phy data.
* Added InitStatus to PCIe IO Unit Page 1 header.
* 09-01-16 02.00.39 Added MPI26_CONFIG_PAGE_ENCLOSURE_0 and related defines.
* Added MPI26_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE and
* MPI26_ENCLOS_PGAD_FORM_HANDLE page address formats.
* 02-02-17 02.00.40 Added MPI2_MANPAGE7_SLOT_UNKNOWN.
* Added ChassisSlot field to SAS Enclosure Page 0.
* Added ChassisSlot Valid bit (bit 5) to the Flags field
* in SAS Enclosure Page 0.
* --------------------------------------------------------------------------
*/
@ -273,6 +302,10 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT (0x1B)
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH (0x1C)
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE (0x1D)
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK (0x1E)
/*****************************************************************************
@ -340,6 +373,12 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
/*Enclosure PageAddress format */
#define MPI26_ENCLOS_PGAD_FORM_MASK (0xF0000000)
#define MPI26_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
#define MPI26_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
#define MPI26_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
/*RAID Configuration PageAddress format */
#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
@ -366,6 +405,33 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF)
/*PCIe Switch PageAddress format */
#define MPI26_PCIE_SWITCH_PGAD_FORM_MASK (0xF0000000)
#define MPI26_PCIE_SWITCH_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
#define MPI26_PCIE_SWITCH_PGAD_FORM_HNDL_PORTNUM (0x10000000)
#define MPI26_PCIE_SWITCH_EXPAND_PGAD_FORM_HNDL (0x20000000)
#define MPI26_PCIE_SWITCH_PGAD_HANDLE_MASK (0x0000FFFF)
#define MPI26_PCIE_SWITCH_PGAD_PORTNUM_MASK (0x00FF0000)
#define MPI26_PCIE_SWITCH_PGAD_PORTNUM_SHIFT (16)
/*PCIe Device PageAddress format */
#define MPI26_PCIE_DEVICE_PGAD_FORM_MASK (0xF0000000)
#define MPI26_PCIE_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
#define MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE (0x20000000)
#define MPI26_PCIE_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
/*PCIe Link PageAddress format */
#define MPI26_PCIE_LINK_PGAD_FORM_MASK (0xF0000000)
#define MPI26_PCIE_LINK_PGAD_FORM_GET_NEXT_LINK (0x00000000)
#define MPI26_PCIE_LINK_PGAD_FORM_LINK_NUM (0x10000000)
#define MPI26_PCIE_DEVICE_PGAD_LINKNUM_MASK (0x000000FF)
/****************************************************************************
* Configuration messages
****************************************************************************/
@ -485,6 +551,12 @@ typedef struct _MPI2_CONFIG_REPLY {
#define MPI26_MFGPAGE_DEVID_SAS3508 (0x00AD)
#define MPI26_MFGPAGE_DEVID_SAS3508_1 (0x00AE)
#define MPI26_MFGPAGE_DEVID_SAS3408 (0x00AF)
#define MPI26_MFGPAGE_DEVID_SAS3716 (0x00D0)
#define MPI26_MFGPAGE_DEVID_SAS3616 (0x00D1)
#define MPI26_MFGPAGE_DEVID_SAS3708 (0x00D2)
#define MPI26_MFGPAGE_DEVID_SAS4008 (0x00A1)
/*Manufacturing Page 0 */
@ -727,6 +799,12 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
#define MPI2_MANPAGE7_PINOUT_SFF_8088_A (0x0E)
#define MPI2_MANPAGE7_PINOUT_SFF_8643_16i (0x0F)
#define MPI2_MANPAGE7_PINOUT_SFF_8654_4i (0x10)
#define MPI2_MANPAGE7_PINOUT_SFF_8654_8i (0x11)
#define MPI2_MANPAGE7_PINOUT_SFF_8611_4i (0x12)
#define MPI2_MANPAGE7_PINOUT_SFF_8611_8i (0x13)
/*defines for the Location field */
#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
@ -737,6 +815,9 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
/*defines for the Slot field */
#define MPI2_MANPAGE7_SLOT_UNKNOWN (0xFFFF)
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check the value returned for NumPhys at runtime.
@ -1000,11 +1081,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02)
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04)
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08)
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X16 (0x10)
/*defines for IO Unit Page 7 PCIeSpeed field */
#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00)
#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01)
#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02)
#define MPI2_IOUNITPAGE7_PCIE_SPEED_16_0_GBPS (0x03)
/*defines for IO Unit Page 7 ProcessorState field */
#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F)
@ -1971,6 +2054,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B)
#define MPI26_SAS_NEG_LINK_RATE_22_5 (0x0C)
/*values for AttachedPhyInfo fields */
@ -2038,12 +2122,14 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
#define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0)
#define MPI26_SAS_PRATE_MAX_RATE_22_5 (0xC0)
#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B)
#define MPI26_SAS_PRATE_MIN_RATE_22_5 (0x0C)
/*values for SAS HwLinkRate fields */
@ -2052,11 +2138,13 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
#define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0)
#define MPI26_SAS_HWRATE_MAX_RATE_22_5 (0xC0)
#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B)
#define MPI26_SAS_HWRATE_MIN_RATE_22_5 (0x0C)
@ -2241,11 +2329,13 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0)
#define MPI26_SASIOUNIT1_MAX_RATE_22_5 (0xC0)
#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B)
#define MPI26_SASIOUNIT1_MIN_RATE_22_5 (0x0C)
/*see mpi2_sas.h for values for
*SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
@ -3159,37 +3249,29 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 {
/*SAS Enclosure Page 0 */
typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER
Header; /*0x00 */
U32
Reserved1; /*0x08 */
U64
EnclosureLogicalID; /*0x0C */
U16
Flags; /*0x14 */
U16
EnclosureHandle; /*0x16 */
U16
NumSlots; /*0x18 */
U16
StartSlot; /*0x1A */
U8
Reserved2; /*0x1C */
U8
EnclosureLevel; /*0x1D */
U16
SEPDevHandle; /*0x1E */
U32
Reserved3; /*0x20 */
U32
Reserved4; /*0x24 */
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U32 Reserved1; /*0x08 */
U64 EnclosureLogicalID; /*0x0C */
U16 Flags; /*0x14 */
U16 EnclosureHandle; /*0x16 */
U16 NumSlots; /*0x18 */
U16 StartSlot; /*0x1A */
U8 ChassisSlot; /*0x1C */
U8 EnclosureLeve; /*0x1D */
U16 SEPDevHandle; /*0x1E */
U32 Reserved3; /*0x20 */
U32 Reserved4; /*0x24 */
} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
*PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t;
Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t,
MPI26_CONFIG_PAGE_ENCLOSURE_0,
*PTR_MPI26_CONFIG_PAGE_ENCLOSURE_0,
Mpi26EnclosurePage0_t, *pMpi26EnclosurePage0_t;
#define MPI2_SASENCLOSURE0_PAGEVERSION (0x04)
/*values for SAS Enclosure Page 0 Flags field */
#define MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID (0x0020)
#define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010)
#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
@ -3199,6 +3281,18 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
#define MPI26_ENCLOSURE0_PAGEVERSION (0x04)
/*Values for Enclosure Page 0 Flags field */
#define MPI26_ENCLS0_FLAGS_CHASSIS_SLOT_VALID (0x0020)
#define MPI26_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010)
#define MPI26_ENCLS0_FLAGS_MNG_MASK (0x000F)
#define MPI26_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
#define MPI26_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
#define MPI26_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
#define MPI26_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
#define MPI26_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
#define MPI26_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
/****************************************************************************
* Log Config Page
@ -3498,4 +3592,422 @@ typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
/*PageVersion should be provided by product-specific code */
/****************************************************************************
* values for fields used by several types of PCIe Config Pages
****************************************************************************/
/*values for NegotiatedLinkRates fields */
#define MPI26_PCIE_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
/*link rates used for Negotiated Physical Link Rate */
#define MPI26_PCIE_NEG_LINK_RATE_UNKNOWN (0x00)
#define MPI26_PCIE_NEG_LINK_RATE_PHY_DISABLED (0x01)
#define MPI26_PCIE_NEG_LINK_RATE_2_5 (0x02)
#define MPI26_PCIE_NEG_LINK_RATE_5_0 (0x03)
#define MPI26_PCIE_NEG_LINK_RATE_8_0 (0x04)
#define MPI26_PCIE_NEG_LINK_RATE_16_0 (0x05)
/****************************************************************************
* PCIe IO Unit Config Pages (MPI v2.6 and later)
****************************************************************************/
/*PCIe IO Unit Page 0 */
typedef struct _MPI26_PCIE_IO_UNIT0_PHY_DATA {
U8 Link; /*0x00 */
U8 LinkFlags; /*0x01 */
U8 PhyFlags; /*0x02 */
U8 NegotiatedLinkRate; /*0x03 */
U32 ControllerPhyDeviceInfo;/*0x04 */
U16 AttachedDevHandle; /*0x08 */
U16 ControllerDevHandle; /*0x0A */
U32 EnumerationStatus; /*0x0C */
U32 Reserved1; /*0x10 */
} MPI26_PCIE_IO_UNIT0_PHY_DATA,
*PTR_MPI26_PCIE_IO_UNIT0_PHY_DATA,
Mpi26PCIeIOUnit0PhyData_t, *pMpi26PCIeIOUnit0PhyData_t;
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check the value returned for NumPhys at runtime.
*/
#ifndef MPI26_PCIE_IOUNIT0_PHY_MAX
#define MPI26_PCIE_IOUNIT0_PHY_MAX (1)
#endif
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U32 Reserved1; /*0x08 */
U8 NumPhys; /*0x0C */
U8 InitStatus; /*0x0D */
U16 Reserved3; /*0x0E */
MPI26_PCIE_IO_UNIT0_PHY_DATA
PhyData[MPI26_PCIE_IOUNIT0_PHY_MAX]; /*0x10 */
} MPI26_CONFIG_PAGE_PIOUNIT_0,
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_0,
Mpi26PCIeIOUnitPage0_t, *pMpi26PCIeIOUnitPage0_t;
#define MPI26_PCIEIOUNITPAGE0_PAGEVERSION (0x00)
/*values for PCIe IO Unit Page 0 LinkFlags */
#define MPI26_PCIEIOUNIT0_LINKFLAGS_ENUMERATION_IN_PROGRESS (0x08)
/*values for PCIe IO Unit Page 0 PhyFlags */
#define MPI26_PCIEIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
/*use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
/*see mpi2_pci.h for values for PCIe IO Unit Page 0 ControllerPhyDeviceInfo
*values
*/
/*values for PCIe IO Unit Page 0 EnumerationStatus */
#define MPI26_PCIEIOUNIT0_ES_MAX_SWITCHES_EXCEEDED (0x40000000)
#define MPI26_PCIEIOUNIT0_ES_MAX_DEVICES_EXCEEDED (0x20000000)
/*PCIe IO Unit Page 1 */
typedef struct _MPI26_PCIE_IO_UNIT1_PHY_DATA {
U8 Link; /*0x00 */
U8 LinkFlags; /*0x01 */
U8 PhyFlags; /*0x02 */
U8 MaxMinLinkRate; /*0x03 */
U32 ControllerPhyDeviceInfo; /*0x04 */
U32 Reserved1; /*0x08 */
} MPI26_PCIE_IO_UNIT1_PHY_DATA,
*PTR_MPI26_PCIE_IO_UNIT1_PHY_DATA,
Mpi26PCIeIOUnit1PhyData_t, *pMpi26PCIeIOUnit1PhyData_t;
/*values for LinkFlags */
#define MPI26_PCIEIOUNIT1_LINKFLAGS_DIS_SRIS (0x00)
#define MPI26_PCIEIOUNIT1_LINKFLAGS_EN_SRIS (0x01)
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check the value returned for NumPhys at runtime.
*/
#ifndef MPI26_PCIE_IOUNIT1_PHY_MAX
#define MPI26_PCIE_IOUNIT1_PHY_MAX (1)
#endif
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U16 ControlFlags; /*0x08 */
U16 Reserved; /*0x0A */
U16 AdditionalControlFlags; /*0x0C */
U16 NVMeMaxQueueDepth; /*0x0E */
U8 NumPhys; /*0x10 */
U8 Reserved1; /*0x11 */
U16 Reserved2; /*0x12 */
MPI26_PCIE_IO_UNIT1_PHY_DATA
PhyData[MPI26_PCIE_IOUNIT1_PHY_MAX];/*0x14 */
} MPI26_CONFIG_PAGE_PIOUNIT_1,
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_1,
Mpi26PCIeIOUnitPage1_t, *pMpi26PCIeIOUnitPage1_t;
#define MPI26_PCIEIOUNITPAGE1_PAGEVERSION (0x00)
/*values for PCIe IO Unit Page 1 PhyFlags */
#define MPI26_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
#define MPI26_PCIEIOUNIT1_PHYFLAGS_ENDPOINT_ONLY (0x01)
/*values for PCIe IO Unit Page 1 MaxMinLinkRate */
#define MPI26_PCIEIOUNIT1_MAX_RATE_MASK (0xF0)
#define MPI26_PCIEIOUNIT1_MAX_RATE_SHIFT (4)
#define MPI26_PCIEIOUNIT1_MAX_RATE_2_5 (0x20)
#define MPI26_PCIEIOUNIT1_MAX_RATE_5_0 (0x30)
#define MPI26_PCIEIOUNIT1_MAX_RATE_8_0 (0x40)
#define MPI26_PCIEIOUNIT1_MAX_RATE_16_0 (0x50)
/*see mpi2_pci.h for values for PCIe IO Unit Page 0 ControllerPhyDeviceInfo
*values
*/
/****************************************************************************
* PCIe Switch Config Pages (MPI v2.6 and later)
****************************************************************************/
/*PCIe Switch Page 0 */
typedef struct _MPI26_CONFIG_PAGE_PSWITCH_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U8 PhysicalPort; /*0x08 */
U8 Reserved1; /*0x09 */
U16 Reserved2; /*0x0A */
U16 DevHandle; /*0x0C */
U16 ParentDevHandle; /*0x0E */
U8 NumPorts; /*0x10 */
U8 PCIeLevel; /*0x11 */
U16 Reserved3; /*0x12 */
U32 Reserved4; /*0x14 */
U32 Reserved5; /*0x18 */
U32 Reserved6; /*0x1C */
} MPI26_CONFIG_PAGE_PSWITCH_0, *PTR_MPI26_CONFIG_PAGE_PSWITCH_0,
Mpi26PCIeSwitchPage0_t, *pMpi26PCIeSwitchPage0_t;
#define MPI26_PCIESWITCH0_PAGEVERSION (0x00)
/*PCIe Switch Page 1 */
typedef struct _MPI26_CONFIG_PAGE_PSWITCH_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U8 PhysicalPort; /*0x08 */
U8 Reserved1; /*0x09 */
U16 Reserved2; /*0x0A */
U8 NumPorts; /*0x0C */
U8 PortNum; /*0x0D */
U16 AttachedDevHandle; /*0x0E */
U16 SwitchDevHandle; /*0x10 */
U8 NegotiatedPortWidth; /*0x12 */
U8 NegotiatedLinkRate; /*0x13 */
U32 Reserved4; /*0x14 */
U32 Reserved5; /*0x18 */
} MPI26_CONFIG_PAGE_PSWITCH_1, *PTR_MPI26_CONFIG_PAGE_PSWITCH_1,
Mpi26PCIeSwitchPage1_t, *pMpi26PCIeSwitchPage1_t;
#define MPI26_PCIESWITCH1_PAGEVERSION (0x00)
/*use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
/****************************************************************************
* PCIe Device Config Pages (MPI v2.6 and later)
****************************************************************************/
/*PCIe Device Page 0 */
typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U16 Slot; /*0x08 */
U16 EnclosureHandle; /*0x0A */
U64 WWID; /*0x0C */
U16 ParentDevHandle; /*0x14 */
U8 PortNum; /*0x16 */
U8 AccessStatus; /*0x17 */
U16 DevHandle; /*0x18 */
U8 PhysicalPort; /*0x1A */
U8 Reserved1; /*0x1B */
U32 DeviceInfo; /*0x1C */
U32 Flags; /*0x20 */
U8 SupportedLinkRates; /*0x24 */
U8 MaxPortWidth; /*0x25 */
U8 NegotiatedPortWidth; /*0x26 */
U8 NegotiatedLinkRate; /*0x27 */
U8 EnclosureLevel; /*0x28 */
U8 Reserved2; /*0x29 */
U16 Reserved3; /*0x2A */
U8 ConnectorName[4]; /*0x2C */
U32 Reserved4; /*0x30 */
U32 Reserved5; /*0x34 */
} MPI26_CONFIG_PAGE_PCIEDEV_0, *PTR_MPI26_CONFIG_PAGE_PCIEDEV_0,
Mpi26PCIeDevicePage0_t, *pMpi26PCIeDevicePage0_t;
#define MPI26_PCIEDEVICE0_PAGEVERSION (0x01)
/*values for PCIe Device Page 0 AccessStatus field */
#define MPI26_PCIEDEV0_ASTATUS_NO_ERRORS (0x00)
#define MPI26_PCIEDEV0_ASTATUS_NEEDS_INITIALIZATION (0x04)
#define MPI26_PCIEDEV0_ASTATUS_CAPABILITY_FAILED (0x02)
#define MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED (0x07)
#define MPI26_PCIEDEV0_ASTATUS_MEMORY_SPACE_ACCESS_FAILED (0x08)
#define MPI26_PCIEDEV0_ASTATUS_UNSUPPORTED_DEVICE (0x09)
#define MPI26_PCIEDEV0_ASTATUS_MSIX_REQUIRED (0x0A)
#define MPI26_PCIEDEV0_ASTATUS_UNKNOWN (0x10)
#define MPI26_PCIEDEV0_ASTATUS_NVME_READY_TIMEOUT (0x30)
#define MPI26_PCIEDEV0_ASTATUS_NVME_DEVCFG_UNSUPPORTED (0x31)
#define MPI26_PCIEDEV0_ASTATUS_NVME_IDENTIFY_FAILED (0x32)
#define MPI26_PCIEDEV0_ASTATUS_NVME_QCONFIG_FAILED (0x33)
#define MPI26_PCIEDEV0_ASTATUS_NVME_QCREATION_FAILED (0x34)
#define MPI26_PCIEDEV0_ASTATUS_NVME_EVENTCFG_FAILED (0x35)
#define MPI26_PCIEDEV0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED (0x36)
#define MPI26_PCIEDEV0_ASTATUS_NVME_IDLE_TIMEOUT (0x37)
#define MPI26_PCIEDEV0_ASTATUS_NVME_FAILURE_STATUS (0x38)
#define MPI26_PCIEDEV0_ASTATUS_INIT_FAIL_MAX (0x3F)
/*see mpi2_pci.h for the MPI26_PCIE_DEVINFO_ defines used for the DeviceInfo
*field
*/
/*values for PCIe Device Page 0 Flags field */
#define MPI26_PCIEDEV0_FLAGS_UNAUTHORIZED_DEVICE (0x8000)
#define MPI26_PCIEDEV0_FLAGS_ENABLED_FAST_PATH (0x4000)
#define MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE (0x2000)
#define MPI26_PCIEDEV0_FLAGS_ASYNCHRONOUS_NOTIFICATION (0x0400)
#define MPI26_PCIEDEV0_FLAGS_ATA_SW_PRESERVATION (0x0200)
#define MPI26_PCIEDEV0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
#define MPI26_PCIEDEV0_FLAGS_ATA_48BIT_LBA_SUPPORTED (0x0080)
#define MPI26_PCIEDEV0_FLAGS_ATA_SMART_SUPPORTED (0x0040)
#define MPI26_PCIEDEV0_FLAGS_ATA_NCQ_SUPPORTED (0x0020)
#define MPI26_PCIEDEV0_FLAGS_ATA_FUA_SUPPORTED (0x0010)
#define MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID (0x0002)
#define MPI26_PCIEDEV0_FLAGS_DEVICE_PRESENT (0x0001)
/* values for PCIe Device Page 0 SupportedLinkRates field */
#define MPI26_PCIEDEV0_LINK_RATE_16_0_SUPPORTED (0x08)
#define MPI26_PCIEDEV0_LINK_RATE_8_0_SUPPORTED (0x04)
#define MPI26_PCIEDEV0_LINK_RATE_5_0_SUPPORTED (0x02)
#define MPI26_PCIEDEV0_LINK_RATE_2_5_SUPPORTED (0x01)
/*use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
/*PCIe Device Page 2 */
typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U16 DevHandle; /*0x08 */
U16 Reserved1; /*0x0A */
U32 MaximumDataTransferSize;/*0x0C */
U32 Capabilities; /*0x10 */
U32 Reserved2; /*0x14 */
} MPI26_CONFIG_PAGE_PCIEDEV_2, *PTR_MPI26_CONFIG_PAGE_PCIEDEV_2,
Mpi26PCIeDevicePage2_t, *pMpi26PCIeDevicePage2_t;
#define MPI26_PCIEDEVICE2_PAGEVERSION (0x00)
/*defines for PCIe Device Page 2 Capabilities field */
#define MPI26_PCIEDEV2_CAP_SGL_FORMAT (0x00000004)
#define MPI26_PCIEDEV2_CAP_BIT_BUCKET_SUPPORT (0x00000002)
#define MPI26_PCIEDEV2_CAP_SGL_SUPPORT (0x00000001)
/****************************************************************************
* PCIe Link Config Pages (MPI v2.6 and later)
****************************************************************************/
/*PCIe Link Page 1 */
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U8 Link; /*0x08 */
U8 Reserved1; /*0x09 */
U16 Reserved2; /*0x0A */
U32 CorrectableErrorCount; /*0x0C */
U16 NonFatalErrorCount; /*0x10 */
U16 Reserved3; /*0x12 */
U16 FatalErrorCount; /*0x14 */
U16 Reserved4; /*0x16 */
} MPI26_CONFIG_PAGE_PCIELINK_1, *PTR_MPI26_CONFIG_PAGE_PCIELINK_1,
Mpi26PcieLinkPage1_t, *pMpi26PcieLinkPage1_t;
#define MPI26_PCIELINK1_PAGEVERSION (0x00)
/*PCIe Link Page 2 */
typedef struct _MPI26_PCIELINK2_LINK_EVENT {
U8 LinkEventCode; /*0x00 */
U8 Reserved1; /*0x01 */
U16 Reserved2; /*0x02 */
U32 LinkEventInfo; /*0x04 */
} MPI26_PCIELINK2_LINK_EVENT, *PTR_MPI26_PCIELINK2_LINK_EVENT,
Mpi26PcieLink2LinkEvent_t, *pMpi26PcieLink2LinkEvent_t;
/*use MPI26_PCIELINK3_EVTCODE_ for the LinkEventCode field */
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check the value returned for NumLinkEvents at runtime.
*/
#ifndef MPI26_PCIELINK2_LINK_EVENT_MAX
#define MPI26_PCIELINK2_LINK_EVENT_MAX (1)
#endif
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U8 Link; /*0x08 */
U8 Reserved1; /*0x09 */
U16 Reserved2; /*0x0A */
U8 NumLinkEvents; /*0x0C */
U8 Reserved3; /*0x0D */
U16 Reserved4; /*0x0E */
MPI26_PCIELINK2_LINK_EVENT
LinkEvent[MPI26_PCIELINK2_LINK_EVENT_MAX]; /*0x10 */
} MPI26_CONFIG_PAGE_PCIELINK_2, *PTR_MPI26_CONFIG_PAGE_PCIELINK_2,
Mpi26PcieLinkPage2_t, *pMpi26PcieLinkPage2_t;
#define MPI26_PCIELINK2_PAGEVERSION (0x00)
/*PCIe Link Page 3 */
typedef struct _MPI26_PCIELINK3_LINK_EVENT_CONFIG {
U8 LinkEventCode; /*0x00 */
U8 Reserved1; /*0x01 */
U16 Reserved2; /*0x02 */
U8 CounterType; /*0x04 */
U8 ThresholdWindow; /*0x05 */
U8 TimeUnits; /*0x06 */
U8 Reserved3; /*0x07 */
U32 EventThreshold; /*0x08 */
U16 ThresholdFlags; /*0x0C */
U16 Reserved4; /*0x0E */
} MPI26_PCIELINK3_LINK_EVENT_CONFIG, *PTR_MPI26_PCIELINK3_LINK_EVENT_CONFIG,
Mpi26PcieLink3LinkEventConfig_t, *pMpi26PcieLink3LinkEventConfig_t;
/*values for LinkEventCode field */
#define MPI26_PCIELINK3_EVTCODE_NO_EVENT (0x00)
#define MPI26_PCIELINK3_EVTCODE_CORRECTABLE_ERROR_RECEIVED (0x01)
#define MPI26_PCIELINK3_EVTCODE_NON_FATAL_ERROR_RECEIVED (0x02)
#define MPI26_PCIELINK3_EVTCODE_FATAL_ERROR_RECEIVED (0x03)
#define MPI26_PCIELINK3_EVTCODE_DATA_LINK_ERROR_DETECTED (0x04)
#define MPI26_PCIELINK3_EVTCODE_TRANSACTION_LAYER_ERROR_DETECTED (0x05)
#define MPI26_PCIELINK3_EVTCODE_TLP_ECRC_ERROR_DETECTED (0x06)
#define MPI26_PCIELINK3_EVTCODE_POISONED_TLP (0x07)
#define MPI26_PCIELINK3_EVTCODE_RECEIVED_NAK_DLLP (0x08)
#define MPI26_PCIELINK3_EVTCODE_SENT_NAK_DLLP (0x09)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_RECOVERY_STATE (0x0A)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_RXL0S_STATE (0x0B)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_TXL0S_STATE (0x0C)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_L1_STATE (0x0D)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_DISABLED_STATE (0x0E)
#define MPI26_PCIELINK3_EVTCODE_LTSSM_HOT_RESET_STATE (0x0F)
#define MPI26_PCIELINK3_EVTCODE_SYSTEM_ERROR (0x10)
#define MPI26_PCIELINK3_EVTCODE_DECODE_ERROR (0x11)
#define MPI26_PCIELINK3_EVTCODE_DISPARITY_ERROR (0x12)
/*values for the CounterType field */
#define MPI26_PCIELINK3_COUNTER_TYPE_WRAPPING (0x00)
#define MPI26_PCIELINK3_COUNTER_TYPE_SATURATING (0x01)
#define MPI26_PCIELINK3_COUNTER_TYPE_PEAK_VALUE (0x02)
/*values for the TimeUnits field */
#define MPI26_PCIELINK3_TM_UNITS_10_MICROSECONDS (0x00)
#define MPI26_PCIELINK3_TM_UNITS_100_MICROSECONDS (0x01)
#define MPI26_PCIELINK3_TM_UNITS_1_MILLISECOND (0x02)
#define MPI26_PCIELINK3_TM_UNITS_10_MILLISECONDS (0x03)
/*values for the ThresholdFlags field */
#define MPI26_PCIELINK3_TFLAGS_EVENT_NOTIFY (0x0001)
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check the value returned for NumLinkEvents at runtime.
*/
#ifndef MPI26_PCIELINK3_LINK_EVENT_MAX
#define MPI26_PCIELINK3_LINK_EVENT_MAX (1)
#endif
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U8 Link; /*0x08 */
U8 Reserved1; /*0x09 */
U16 Reserved2; /*0x0A */
U8 NumLinkEvents; /*0x0C */
U8 Reserved3; /*0x0D */
U16 Reserved4; /*0x0E */
MPI26_PCIELINK3_LINK_EVENT_CONFIG
LinkEventConfig[MPI26_PCIELINK3_LINK_EVENT_MAX]; /*0x10 */
} MPI26_CONFIG_PAGE_PCIELINK_3, *PTR_MPI26_CONFIG_PAGE_PCIELINK_3,
Mpi26PcieLinkPage3_t, *pMpi26PcieLinkPage3_t;
#define MPI26_PCIELINK3_PAGEVERSION (0x00)
#endif

View File

@ -7,7 +7,7 @@
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
* mpi2_init.h Version: 02.00.20
* mpi2_init.h Version: 02.00.21
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -55,6 +55,8 @@
* 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset.
* 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message.
* 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message.
* 01-21-16 02.00.21 Modified MPI26_SCSITASKMGMT_MSGFLAGS_PCIE* defines to
* be unique within first 32 characters.
* --------------------------------------------------------------------------
*/
@ -374,6 +376,11 @@ typedef struct _MPI2_SCSI_IO_REPLY {
} MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY,
Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t;
/*SCSI IO Reply MsgFlags bits */
#define MPI26_SCSIIO_REPLY_MSGFLAGS_REFTAG_OBSERVED_VALID (0x01)
#define MPI26_SCSIIO_REPLY_MSGFLAGS_GUARD_OBSERVED_VALID (0x02)
#define MPI26_SCSIIO_REPLY_MSGFLAGS_APPTAG_OBSERVED_VALID (0x04)
/*SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
#define MPI2_SCSI_STATUS_GOOD (0x00)
@ -447,11 +454,13 @@ typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST {
/*MsgFlags bits */
#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
#define MPI26_SCSITASKMGMT_MSGFLAGS_HOT_RESET_PCIE (0x00)
#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
#define MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE (0x18)
/*SCSI Task Management Reply Message */
typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY {

View File

@ -7,7 +7,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
* mpi2_ioc.h Version: 02.00.27
* mpi2_ioc.h Version: 02.00.32
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -141,7 +141,32 @@
* Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and
* MPI26_FW_HEADER_PID_FAMILY_3516_SAS.
* Added MPI26_CTRL_OP_SHUTDOWN.
* 08-25-15 02.00.27 Added IC ARCH Class based signature defines
* 08-25-15 02.00.27 Added IC ARCH Class based signature defines.
* Added MPI26_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED event.
* Added ConigurationFlags field to IOCInit message to
* support NVMe SGL format control.
* Added PCIe SRIOV support.
* 02-17-16 02.00.28 Added SAS 4 22.5 gbs speed support.
* Added PCIe 4 16.0 GT/sec speec support.
* Removed AHCI support.
* Removed SOP support.
* 07-01-16 02.00.29 Added Archclass for 4008 product.
* Added IOCException MPI2_IOCFACTS_EXCEPT_PCIE_DISABLED
* 08-23-16 02.00.30 Added new defines for the ImageType field of FWDownload
* Request Message.
* Added new defines for the ImageType field of FWUpload
* Request Message.
* Added new values for the RegionType field in the Layout
* Data sections of the FLASH Layout Extended Image Data.
* Added new defines for the ReasonCode field of
* Active Cable Exception Event.
* Added MPI2_EVENT_ENCL_DEVICE_STATUS_CHANGE and
* MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE.
* 11-23-16 02.00.31 Added MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR and
* MPI25_EVENT_DATA_SAS_DEVICE_DISCOVERY_ERROR.
* 02-02-17 02.00.32 Added MPI2_FW_DOWNLOAD_ITYPE_CBB_BACKUP.
* Added MPI25_EVENT_DATA_ACTIVE_CABLE_EXCEPT and related
* defines for the ReasonCode field.
* --------------------------------------------------------------------------
*/
@ -213,6 +238,9 @@ typedef struct _MPI2_IOC_INIT_REQUEST {
#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
/*ConfigurationFlags */
#define MPI26_IOCINIT_CFGFLAGS_NVME_SGL_FORMAT (0x0001)
/*minimum depth for a Reply Descriptor Post Queue */
#define MPI2_RDPQ_DEPTH_MIN (16)
@ -300,6 +328,10 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
U16 MinDevHandle; /*0x3C */
U8 CurrentHostPageSize; /* 0x3E */
U8 Reserved4; /* 0x3F */
U8 SGEModifierMask; /*0x40 */
U8 SGEModifierValue; /*0x41 */
U8 SGEModifierShift; /*0x42 */
U8 Reserved5; /*0x43 */
} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY,
Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t;
@ -316,6 +348,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
/*IOCExceptions */
#define MPI2_IOCFACTS_EXCEPT_PCIE_DISABLED (0x0400)
#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200)
#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
@ -336,6 +369,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
/*ProductID field uses MPI2_FW_HEADER_PID_ */
/*IOCCapabilities */
#define MPI26_IOCFACTS_CAPABILITY_PCIE_SRIOV (0x00100000)
#define MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ (0x00080000)
#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000)
#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000)
@ -354,6 +388,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
/*ProtocolFlags */
#define MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES (0x0008)
#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
@ -403,6 +438,8 @@ typedef struct _MPI2_PORT_FACTS_REPLY {
#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
#define MPI2_PORTFACTS_PORTTYPE_TRI_MODE (0x40)
/****************************************************************************
* PortEnable message
@ -509,6 +546,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY {
#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
#define MPI2_EVENT_ENCL_DEVICE_STATUS_CHANGE (0x001D)
#define MPI2_EVENT_IR_VOLUME (0x001E)
#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
@ -521,7 +559,12 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY {
#define MPI2_EVENT_TEMP_THRESHOLD (0x0027)
#define MPI2_EVENT_HOST_MESSAGE (0x0028)
#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029)
#define MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE (0x0030)
#define MPI2_EVENT_PCIE_ENUMERATION (0x0031)
#define MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST (0x0032)
#define MPI2_EVENT_PCIE_LINK_COUNTER (0x0033)
#define MPI2_EVENT_ACTIVE_CABLE_EXCEPTION (0x0034)
#define MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR (0x0035)
#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E)
#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F)
@ -618,11 +661,20 @@ typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT {
U8 ReasonCode; /* 0x04 */
U8 ReceptacleID; /* 0x05 */
U16 Reserved1; /* 0x06 */
} MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT,
} MPI25_EVENT_DATA_ACTIVE_CABLE_EXCEPT,
*PTR_MPI25_EVENT_DATA_ACTIVE_CABLE_EXCEPT,
Mpi25EventDataActiveCableExcept_t,
*pMpi25EventDataActiveCableExcept_t,
MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT,
*PTR_MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT,
Mpi26EventDataActiveCableExcept_t,
*pMpi26EventDataActiveCableExcept_t;
/*MPI2.5 defines for the ReasonCode field */
#define MPI25_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00)
#define MPI25_EVENT_ACTIVE_CABLE_PRESENT (0x01)
#define MPI25_EVENT_ACTIVE_CABLE_DEGRADED (0x02)
/* defines for ReasonCode field */
#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00)
#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01)
@ -958,6 +1010,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST {
#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B)
#define MPI26_EVENT_SAS_TOPO_LR_RATE_22_5 (0x0C)
/*values for the PhyStatus field */
#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
@ -983,12 +1036,37 @@ typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE {
} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
*PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
Mpi2EventDataSasEnclDevStatusChange_t,
*pMpi2EventDataSasEnclDevStatusChange_t;
*pMpi2EventDataSasEnclDevStatusChange_t,
MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE,
*PTR_MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE,
Mpi26EventDataEnclDevStatusChange_t,
*pMpi26EventDataEnclDevStatusChange_t;
/*SAS Enclosure Device Status Change event ReasonCode values */
#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
/*Enclosure Device Status Change event ReasonCode values */
#define MPI26_EVENT_ENCL_RC_ADDED (0x01)
#define MPI26_EVENT_ENCL_RC_NOT_RESPONDING (0x02)
typedef struct _MPI25_EVENT_DATA_SAS_DEVICE_DISCOVERY_ERROR {
U16 DevHandle; /*0x00 */
U8 ReasonCode; /*0x02 */
U8 PhysicalPort; /*0x03 */
U32 Reserved1[2]; /*0x04 */
U64 SASAddress; /*0x0C */
U32 Reserved2[2]; /*0x14 */
} MPI25_EVENT_DATA_SAS_DEVICE_DISCOVERY_ERROR,
*PTR_MPI25_EVENT_DATA_SAS_DEVICE_DISCOVERY_ERROR,
Mpi25EventDataSasDeviceDiscoveryError_t,
*pMpi25EventDataSasDeviceDiscoveryError_t;
/*SAS Device Discovery Error Event data ReasonCode values */
#define MPI25_EVENT_SAS_DISC_ERR_SMP_FAILED (0x01)
#define MPI25_EVENT_SAS_DISC_ERR_SMP_TIMEOUT (0x02)
/*SAS PHY Counter Event data */
typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER {
@ -1074,6 +1152,174 @@ typedef struct _MPI2_EVENT_DATA_HBD_PHY {
/*values for the DescriptorType field */
#define MPI2_EVENT_HBD_DT_SAS (0x01)
/*PCIe Device Status Change Event data (MPI v2.6 and later) */
typedef struct _MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE {
U16 TaskTag; /*0x00 */
U8 ReasonCode; /*0x02 */
U8 PhysicalPort; /*0x03 */
U8 ASC; /*0x04 */
U8 ASCQ; /*0x05 */
U16 DevHandle; /*0x06 */
U32 Reserved2; /*0x08 */
U64 WWID; /*0x0C */
U8 LUN[8]; /*0x14 */
} MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE,
*PTR_MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE,
Mpi26EventDataPCIeDeviceStatusChange_t,
*pMpi26EventDataPCIeDeviceStatusChange_t;
/*PCIe Device Status Change Event data ReasonCode values */
#define MPI26_EVENT_PCIDEV_STAT_RC_SMART_DATA (0x05)
#define MPI26_EVENT_PCIDEV_STAT_RC_UNSUPPORTED (0x07)
#define MPI26_EVENT_PCIDEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
#define MPI26_EVENT_PCIDEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
#define MPI26_EVENT_PCIDEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
#define MPI26_EVENT_PCIDEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
#define MPI26_EVENT_PCIDEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
#define MPI26_EVENT_PCIDEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
#define MPI26_EVENT_PCIDEV_STAT_RC_DEV_INIT_FAILURE (0x10)
/*PCIe Enumeration Event data (MPI v2.6 and later) */
typedef struct _MPI26_EVENT_DATA_PCIE_ENUMERATION {
U8 Flags; /*0x00 */
U8 ReasonCode; /*0x01 */
U8 PhysicalPort; /*0x02 */
U8 Reserved1; /*0x03 */
U32 EnumerationStatus; /*0x04 */
} MPI26_EVENT_DATA_PCIE_ENUMERATION,
*PTR_MPI26_EVENT_DATA_PCIE_ENUMERATION,
Mpi26EventDataPCIeEnumeration_t,
*pMpi26EventDataPCIeEnumeration_t;
/*PCIe Enumeration Event data Flags values */
#define MPI26_EVENT_PCIE_ENUM_DEVICE_CHANGE (0x02)
#define MPI26_EVENT_PCIE_ENUM_IN_PROGRESS (0x01)
/*PCIe Enumeration Event data ReasonCode values */
#define MPI26_EVENT_PCIE_ENUM_RC_STARTED (0x01)
#define MPI26_EVENT_PCIE_ENUM_RC_COMPLETED (0x02)
/*PCIe Enumeration Event data EnumerationStatus values */
#define MPI26_EVENT_PCIE_ENUM_ES_MAX_SWITCHES_EXCEED (0x40000000)
#define MPI26_EVENT_PCIE_ENUM_ES_MAX_DEVICES_EXCEED (0x20000000)
#define MPI26_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED (0x10000000)
/*PCIe Topology Change List Event data (MPI v2.6 and later) */
/*
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
*one and check NumEntries at runtime.
*/
#ifndef MPI26_EVENT_PCIE_TOPO_PORT_COUNT
#define MPI26_EVENT_PCIE_TOPO_PORT_COUNT (1)
#endif
typedef struct _MPI26_EVENT_PCIE_TOPO_PORT_ENTRY {
U16 AttachedDevHandle; /*0x00 */
U8 PortStatus; /*0x02 */
U8 Reserved1; /*0x03 */
U8 CurrentPortInfo; /*0x04 */
U8 Reserved2; /*0x05 */
U8 PreviousPortInfo; /*0x06 */
U8 Reserved3; /*0x07 */
} MPI26_EVENT_PCIE_TOPO_PORT_ENTRY,
*PTR_MPI26_EVENT_PCIE_TOPO_PORT_ENTRY,
Mpi26EventPCIeTopoPortEntry_t,
*pMpi26EventPCIeTopoPortEntry_t;
/*PCIe Topology Change List Event data PortStatus values */
#define MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED (0x01)
#define MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING (0x02)
#define MPI26_EVENT_PCIE_TOPO_PS_PORT_CHANGED (0x03)
#define MPI26_EVENT_PCIE_TOPO_PS_NO_CHANGE (0x04)
#define MPI26_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING (0x05)
/*PCIe Topology Change List Event data defines for CurrentPortInfo and
*PreviousPortInfo
*/
#define MPI26_EVENT_PCIE_TOPO_PI_LANE_MASK (0xF0)
#define MPI26_EVENT_PCIE_TOPO_PI_LANES_UNKNOWN (0x00)
#define MPI26_EVENT_PCIE_TOPO_PI_1_LANE (0x10)
#define MPI26_EVENT_PCIE_TOPO_PI_2_LANES (0x20)
#define MPI26_EVENT_PCIE_TOPO_PI_4_LANES (0x30)
#define MPI26_EVENT_PCIE_TOPO_PI_8_LANES (0x40)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_MASK (0x0F)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_UNKNOWN (0x00)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_DISABLED (0x01)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5 (0x02)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_5_0 (0x03)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_8_0 (0x04)
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_16_0 (0x05)
typedef struct _MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST {
U16 EnclosureHandle; /*0x00 */
U16 SwitchDevHandle; /*0x02 */
U8 NumPorts; /*0x04 */
U8 Reserved1; /*0x05 */
U16 Reserved2; /*0x06 */
U8 NumEntries; /*0x08 */
U8 StartPortNum; /*0x09 */
U8 SwitchStatus; /*0x0A */
U8 PhysicalPort; /*0x0B */
MPI26_EVENT_PCIE_TOPO_PORT_ENTRY
PortEntry[MPI26_EVENT_PCIE_TOPO_PORT_COUNT]; /*0x0C */
} MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
*PTR_MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
Mpi26EventDataPCIeTopologyChangeList_t,
*pMpi26EventDataPCIeTopologyChangeList_t;
/*PCIe Topology Change List Event data SwitchStatus values */
#define MPI26_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH (0x00)
#define MPI26_EVENT_PCIE_TOPO_SS_ADDED (0x01)
#define MPI26_EVENT_PCIE_TOPO_SS_NOT_RESPONDING (0x02)
#define MPI26_EVENT_PCIE_TOPO_SS_RESPONDING (0x03)
#define MPI26_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING (0x04)
/*PCIe Link Counter Event data (MPI v2.6 and later) */
typedef struct _MPI26_EVENT_DATA_PCIE_LINK_COUNTER {
U64 TimeStamp; /*0x00 */
U32 Reserved1; /*0x08 */
U8 LinkEventCode; /*0x0C */
U8 LinkNum; /*0x0D */
U16 Reserved2; /*0x0E */
U32 LinkEventInfo; /*0x10 */
U8 CounterType; /*0x14 */
U8 ThresholdWindow; /*0x15 */
U8 TimeUnits; /*0x16 */
U8 Reserved3; /*0x17 */
U32 EventThreshold; /*0x18 */
U16 ThresholdFlags; /*0x1C */
U16 Reserved4; /*0x1E */
} MPI26_EVENT_DATA_PCIE_LINK_COUNTER,
*PTR_MPI26_EVENT_DATA_PCIE_LINK_COUNTER,
Mpi26EventDataPcieLinkCounter_t, *pMpi26EventDataPcieLinkCounter_t;
/*use MPI26_PCIELINK3_EVTCODE_ values from mpi2_cnfg.h for the LinkEventCode
*field
*/
/*use MPI26_PCIELINK3_COUNTER_TYPE_ values from mpi2_cnfg.h for the CounterType
*field
*/
/*use MPI26_PCIELINK3_TIME_UNITS_ values from mpi2_cnfg.h for the TimeUnits
*field
*/
/*use MPI26_PCIELINK3_TFLAGS_ values from mpi2_cnfg.h for the ThresholdFlags
*field
*/
/****************************************************************************
* EventAck message
****************************************************************************/
@ -1191,6 +1437,14 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST {
#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
#define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C)
#define MPI2_FW_DOWNLOAD_ITYPE_CBB_BACKUP (0x0D)
#define MPI2_FW_DOWNLOAD_ITYPE_SBR (0x0E)
#define MPI2_FW_DOWNLOAD_ITYPE_SBR_BACKUP (0x0F)
#define MPI2_FW_DOWNLOAD_ITYPE_HIIM (0x10)
#define MPI2_FW_DOWNLOAD_ITYPE_HIIA (0x11)
#define MPI2_FW_DOWNLOAD_ITYPE_CTLR (0x12)
#define MPI2_FW_DOWNLOAD_ITYPE_IMR_FIRMWARE (0x13)
#define MPI2_FW_DOWNLOAD_ITYPE_MR_NVDATA (0x14)
#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
/*MPI v2.0 FWDownload TransactionContext Element */
@ -1277,6 +1531,14 @@ typedef struct _MPI2_FW_UPLOAD_REQUEST {
#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
#define MPI2_FW_UPLOAD_ITYPE_CBB_BACKUP (0x0D)
#define MPI2_FW_UPLOAD_ITYPE_SBR (0x0E)
#define MPI2_FW_UPLOAD_ITYPE_SBR_BACKUP (0x0F)
#define MPI2_FW_UPLOAD_ITYPE_HIIM (0x10)
#define MPI2_FW_UPLOAD_ITYPE_HIIA (0x11)
#define MPI2_FW_UPLOAD_ITYPE_CTLR (0x12)
#define MPI2_FW_UPLOAD_ITYPE_IMR_FIRMWARE (0x13)
#define MPI2_FW_UPLOAD_ITYPE_MR_NVDATA (0x14)
/*MPI v2.0 FWUpload TransactionContext Element */
typedef struct _MPI2_FW_UPLOAD_TCSGE {
@ -1395,10 +1657,13 @@ typedef struct _MPI2_FW_IMAGE_HEADER {
#define MPI26_FW_HEADER_SIGNATURE0_ARC_1 (0x00)
#define MPI26_FW_HEADER_SIGNATURE0_ARC_2 (0x01)
/* legacy (0x5AEAA55A) */
#define MPI26_FW_HEADER_SIGNATURE0_ARC_3 (0x02)
#define MPI26_FW_HEADER_SIGNATURE0 \
(MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_0)
#define MPI26_FW_HEADER_SIGNATURE0_3516 \
(MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_1)
#define MPI26_FW_HEADER_SIGNATURE0_4008 \
(MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_3)
/*Signature1 field */
#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
@ -1542,6 +1807,13 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
#define MPI2_FLASH_REGION_COMMON_BOOT_BLOCK (0x0A)
#define MPI2_FLASH_REGION_INIT (MPI2_FLASH_REGION_COMMON_BOOT_BLOCK)
#define MPI2_FLASH_REGION_CBB_BACKUP (0x0D)
#define MPI2_FLASH_REGION_SBR (0x0E)
#define MPI2_FLASH_REGION_SBR_BACKUP (0x0F)
#define MPI2_FLASH_REGION_HIIM (0x10)
#define MPI2_FLASH_REGION_HIIA (0x11)
#define MPI2_FLASH_REGION_CTLR (0x12)
#define MPI2_FLASH_REGION_IMR_FIRMWARE (0x13)
#define MPI2_FLASH_REGION_MR_NVDATA (0x14)
/*ImageRevision */
#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
@ -1826,6 +2098,8 @@ typedef struct _MPI26_IOUNIT_CONTROL_REQUEST {
#define MPI26_CTRL_OP_DEV_ENABLE_PERSIST_CONNECTION (0x17)
#define MPI26_CTRL_OP_DEV_DISABLE_PERSIST_CONNECTION (0x18)
#define MPI26_CTRL_OP_DEV_CLOSE_PERSIST_CONNECTION (0x19)
#define MPI26_CTRL_OP_ENABLE_NVME_SGL_FORMAT (0x1A)
#define MPI26_CTRL_OP_DISABLE_NVME_SGL_FORMAT (0x1B)
#define MPI26_CTRL_OP_PRODUCT_SPECIFIC_MIN (0x80)
/* values for the PrimFlags field */

View File

@ -0,0 +1,111 @@
/*
* Copyright 2012-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_pci.h
* Title: MPI PCIe Attached Devices structures and definitions.
* Creation Date: October 9, 2012
*
* mpi2_pci.h Version: 02.00.02
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
* with MPI v2.0 products. Unless otherwise noted, names beginning with
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
* 03-16-15 02.00.00 Initial version.
* 02-17-16 02.00.01 Removed AHCI support.
* Removed SOP support.
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
* NVME Encapsulated Request.
* --------------------------------------------------------------------------
*/
#ifndef MPI2_PCI_H
#define MPI2_PCI_H
/*
*Values for the PCIe DeviceInfo field used in PCIe Device Status Change Event
*data and PCIe Configuration pages.
*/
#define MPI26_PCIE_DEVINFO_DIRECT_ATTACH (0x00000010)
#define MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE (0x0000000F)
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
/****************************************************************************
* NVMe Encapsulated message
****************************************************************************/
/*NVME Encapsulated Request Message */
typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST {
U16 DevHandle; /*0x00 */
U8 ChainOffset; /*0x02 */
U8 Function; /*0x03 */
U16 EncapsulatedCommandLength; /*0x04 */
U8 Reserved1; /*0x06 */
U8 MsgFlags; /*0x07 */
U8 VP_ID; /*0x08 */
U8 VF_ID; /*0x09 */
U16 Reserved2; /*0x0A */
U32 Reserved3; /*0x0C */
U64 ErrorResponseBaseAddress; /*0x10 */
U16 ErrorResponseAllocationLength; /*0x18 */
U16 Flags; /*0x1A */
U32 DataLength; /*0x1C */
U8 NVMe_Command[4]; /*0x20 */
} MPI26_NVME_ENCAPSULATED_REQUEST, *PTR_MPI26_NVME_ENCAPSULATED_REQUEST,
Mpi26NVMeEncapsulatedRequest_t, *pMpi26NVMeEncapsulatedRequest_t;
/*defines for the Flags field */
#define MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP (0x0020)
/*Submission Queue Type*/
#define MPI26_NVME_FLAGS_SUBMISSIONQ_MASK (0x0010)
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
/*Error Response Address Space */
#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR (0x000C)
#define MPI26_NVME_FLAGS_SYSTEM_RSP_ADDR (0x0000)
#define MPI26_NVME_FLAGS_IOCPLB_RSP_ADDR (0x0008)
#define MPI26_NVME_FLAGS_IOCPLBNTA_RSP_ADDR (0x000C)
/*Data Direction*/
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
#define MPI26_NVME_FLAGS_WRITE (0x0001)
#define MPI26_NVME_FLAGS_READ (0x0002)
#define MPI26_NVME_FLAGS_BIDIRECTIONAL (0x0003)
/*NVMe Encapuslated Reply Message */
typedef struct _MPI26_NVME_ENCAPSULATED_ERROR_REPLY {
U16 DevHandle; /*0x00 */
U8 MsgLength; /*0x02 */
U8 Function; /*0x03 */
U16 EncapsulatedCommandLength; /*0x04 */
U8 Reserved1; /*0x06 */
U8 MsgFlags; /*0x07 */
U8 VP_ID; /*0x08 */
U8 VF_ID; /*0x09 */
U16 Reserved2; /*0x0A */
U16 Reserved3; /*0x0C */
U16 IOCStatus; /*0x0E */
U32 IOCLogInfo; /*0x10 */
U16 ErrorResponseCount; /*0x14 */
U16 Reserved4; /*0x16 */
} MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
*PTR_MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
Mpi26NVMeEncapsulatedErrorReply_t,
*pMpi26NVMeEncapsulatedErrorReply_t;
#endif

View File

@ -7,7 +7,7 @@
* Title: MPI diagnostic tool structures and definitions
* Creation Date: March 26, 2007
*
* mpi2_tool.h Version: 02.00.13
* mpi2_tool.h Version: 02.00.14
*
* Version History
* ---------------
@ -36,6 +36,8 @@
* 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
* 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
* 11-18-14 02.00.13 Updated copyright information.
* 08-25-16 02.00.14 Added new values for the Flags field of Toolbox Clean
* Tool Request Message.
* --------------------------------------------------------------------------
*/
@ -106,6 +108,16 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST {
#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000)
#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
#define MPI2_TOOLBOX_CLEAN_SBR (0x00800000)
#define MPI2_TOOLBOX_CLEAN_SBR_BACKUP (0x00400000)
#define MPI2_TOOLBOX_CLEAN_HIIM (0x00200000)
#define MPI2_TOOLBOX_CLEAN_HIIA (0x00100000)
#define MPI2_TOOLBOX_CLEAN_CTLR (0x00080000)
#define MPI2_TOOLBOX_CLEAN_IMR_FIRMWARE (0x00040000)
#define MPI2_TOOLBOX_CLEAN_MR_NVDATA (0x00020000)
#define MPI2_TOOLBOX_CLEAN_RESERVED_5_16 (0x0001FFE0)
#define MPI2_TOOLBOX_CLEAN_ALL_BUT_MPB (0x00000010)
#define MPI2_TOOLBOX_CLEAN_ENTIRE_FLASH (0x00000008)
#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)

View File

@ -59,6 +59,7 @@
#include <linux/time.h>
#include <linux/ktime.h>
#include <linux/kthread.h>
#include <asm/page.h> /* To get host page size per arch */
#include <linux/aer.h>
@ -556,6 +557,11 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
func_str = "smp_passthru";
break;
case MPI2_FUNCTION_NVME_ENCAPSULATED:
frame_sz = sizeof(Mpi26NVMeEncapsulatedRequest_t) +
ioc->sge_size;
func_str = "nvme_encapsulated";
break;
default:
frame_sz = 32;
func_str = "unknown";
@ -655,7 +661,27 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
desc = "Temperature Threshold";
break;
case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
desc = "Active cable exception";
desc = "Cable Event";
break;
case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE:
desc = "PCIE Device Status Change";
break;
case MPI2_EVENT_PCIE_ENUMERATION:
{
Mpi26EventDataPCIeEnumeration_t *event_data =
(Mpi26EventDataPCIeEnumeration_t *)mpi_reply->EventData;
pr_info(MPT3SAS_FMT "PCIE Enumeration: (%s)", ioc->name,
(event_data->ReasonCode ==
MPI26_EVENT_PCIE_ENUM_RC_STARTED) ?
"start" : "stop");
if (event_data->EnumerationStatus)
pr_info("enumeration_status(0x%08x)",
le32_to_cpu(event_data->EnumerationStatus));
pr_info("\n");
return;
}
case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
desc = "PCIE Topology Change List";
break;
}
@ -984,7 +1010,9 @@ _base_interrupt(int irq, void *bus_id)
if (request_desript_type ==
MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS ||
request_desript_type ==
MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
request_desript_type ==
MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS) {
cb_idx = _base_get_cb_idx(ioc, smid);
if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
(likely(mpt_callbacks[cb_idx] != NULL))) {
@ -1346,6 +1374,433 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge,
/* IEEE format sgls */
/**
* _base_build_nvme_prp - This function is called for NVMe end devices to build
* a native SGL (NVMe PRP). The native SGL is built starting in the first PRP
* entry of the NVMe message (PRP1). If the data buffer is small enough to be
* described entirely using PRP1, then PRP2 is not used. If needed, PRP2 is
* used to describe a larger data buffer. If the data buffer is too large to
* describe using the two PRP entriess inside the NVMe message, then PRP1
* describes the first data memory segment, and PRP2 contains a pointer to a PRP
* list located elsewhere in memory to describe the remaining data memory
* segments. The PRP list will be contiguous.
* The native SGL for NVMe devices is a Physical Region Page (PRP). A PRP
* consists of a list of PRP entries to describe a number of noncontigous
* physical memory segments as a single memory buffer, just as a SGL does. Note
* however, that this function is only used by the IOCTL call, so the memory
* given will be guaranteed to be contiguous. There is no need to translate
* non-contiguous SGL into a PRP in this case. All PRPs will describe
* contiguous space that is one page size each.
*
* Each NVMe message contains two PRP entries. The first (PRP1) either contains
* a PRP list pointer or a PRP element, depending upon the command. PRP2
* contains the second PRP element if the memory being described fits within 2
* PRP entries, or a PRP list pointer if the PRP spans more than two entries.
*
* A PRP list pointer contains the address of a PRP list, structured as a linear
* array of PRP entries. Each PRP entry in this list describes a segment of
* physical memory.
*
* Each 64-bit PRP entry comprises an address and an offset field. The address
* always points at the beginning of a 4KB physical memory page, and the offset
* describes where within that 4KB page the memory segment begins. Only the
* first element in a PRP list may contain a non-zero offest, implying that all
* memory segments following the first begin at the start of a 4KB page.
*
* Each PRP element normally describes 4KB of physical memory, with exceptions
* for the first and last elements in the list. If the memory being described
* by the list begins at a non-zero offset within the first 4KB page, then the
* first PRP element will contain a non-zero offset indicating where the region
* begins within the 4KB page. The last memory segment may end before the end
* of the 4KB segment, depending upon the overall size of the memory being
* described by the PRP list.
*
* Since PRP entries lack any indication of size, the overall data buffer length
* is used to determine where the end of the data memory buffer is located, and
* how many PRP entries are required to describe it.
*
* @ioc: per adapter object
* @smid: system request message index for getting asscociated SGL
* @nvme_encap_request: the NVMe request msg frame pointer
* @data_out_dma: physical address for WRITES
* @data_out_sz: data xfer size for WRITES
* @data_in_dma: physical address for READS
* @data_in_sz: data xfer size for READS
*
* Returns nothing.
*/
static void
_base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid,
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request,
dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
size_t data_in_sz)
{
int prp_size = NVME_PRP_SIZE;
__le64 *prp_entry, *prp1_entry, *prp2_entry;
__le64 *prp_page;
dma_addr_t prp_entry_dma, prp_page_dma, dma_addr;
u32 offset, entry_len;
u32 page_mask_result, page_mask;
size_t length;
/*
* Not all commands require a data transfer. If no data, just return
* without constructing any PRP.
*/
if (!data_in_sz && !data_out_sz)
return;
/*
* Set pointers to PRP1 and PRP2, which are in the NVMe command.
* PRP1 is located at a 24 byte offset from the start of the NVMe
* command. Then set the current PRP entry pointer to PRP1.
*/
prp1_entry = (__le64 *)(nvme_encap_request->NVMe_Command +
NVME_CMD_PRP1_OFFSET);
prp2_entry = (__le64 *)(nvme_encap_request->NVMe_Command +
NVME_CMD_PRP2_OFFSET);
prp_entry = prp1_entry;
/*
* For the PRP entries, use the specially allocated buffer of
* contiguous memory.
*/
prp_page = (__le64 *)mpt3sas_base_get_pcie_sgl(ioc, smid);
prp_page_dma = mpt3sas_base_get_pcie_sgl_dma(ioc, smid);
/*
* Check if we are within 1 entry of a page boundary we don't
* want our first entry to be a PRP List entry.
*/
page_mask = ioc->page_size - 1;
page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask;
if (!page_mask_result) {
/* Bump up to next page boundary. */
prp_page = (__le64 *)((u8 *)prp_page + prp_size);
prp_page_dma = prp_page_dma + prp_size;
}
/*
* Set PRP physical pointer, which initially points to the current PRP
* DMA memory page.
*/
prp_entry_dma = prp_page_dma;
/* Get physical address and length of the data buffer. */
if (data_in_sz) {
dma_addr = data_in_dma;
length = data_in_sz;
} else {
dma_addr = data_out_dma;
length = data_out_sz;
}
/* Loop while the length is not zero. */
while (length) {
/*
* Check if we need to put a list pointer here if we are at
* page boundary - prp_size (8 bytes).
*/
page_mask_result = (prp_entry_dma + prp_size) & page_mask;
if (!page_mask_result) {
/*
* This is the last entry in a PRP List, so we need to
* put a PRP list pointer here. What this does is:
* - bump the current memory pointer to the next
* address, which will be the next full page.
* - set the PRP Entry to point to that page. This
* is now the PRP List pointer.
* - bump the PRP Entry pointer the start of the
* next page. Since all of this PRP memory is
* contiguous, no need to get a new page - it's
* just the next address.
*/
prp_entry_dma++;
*prp_entry = cpu_to_le64(prp_entry_dma);
prp_entry++;
}
/* Need to handle if entry will be part of a page. */
offset = dma_addr & page_mask;
entry_len = ioc->page_size - offset;
if (prp_entry == prp1_entry) {
/*
* Must fill in the first PRP pointer (PRP1) before
* moving on.
*/
*prp1_entry = cpu_to_le64(dma_addr);
/*
* Now point to the second PRP entry within the
* command (PRP2).
*/
prp_entry = prp2_entry;
} else if (prp_entry == prp2_entry) {
/*
* Should the PRP2 entry be a PRP List pointer or just
* a regular PRP pointer? If there is more than one
* more page of data, must use a PRP List pointer.
*/
if (length > ioc->page_size) {
/*
* PRP2 will contain a PRP List pointer because
* more PRP's are needed with this command. The
* list will start at the beginning of the
* contiguous buffer.
*/
*prp2_entry = cpu_to_le64(prp_entry_dma);
/*
* The next PRP Entry will be the start of the
* first PRP List.
*/
prp_entry = prp_page;
} else {
/*
* After this, the PRP Entries are complete.
* This command uses 2 PRP's and no PRP list.
*/
*prp2_entry = cpu_to_le64(dma_addr);
}
} else {
/*
* Put entry in list and bump the addresses.
*
* After PRP1 and PRP2 are filled in, this will fill in
* all remaining PRP entries in a PRP List, one per
* each time through the loop.
*/
*prp_entry = cpu_to_le64(dma_addr);
prp_entry++;
prp_entry_dma++;
}
/*
* Bump the phys address of the command's data buffer by the
* entry_len.
*/
dma_addr += entry_len;
/* Decrement length accounting for last partial page. */
if (entry_len > length)
length = 0;
else
length -= entry_len;
}
}
/**
* base_make_prp_nvme -
* Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only
*
* @ioc: per adapter object
* @scmd: SCSI command from the mid-layer
* @mpi_request: mpi request
* @smid: msg Index
* @sge_count: scatter gather element count.
*
* Returns: true: PRPs are built
* false: IEEE SGLs needs to be built
*/
static void
base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc,
struct scsi_cmnd *scmd,
Mpi25SCSIIORequest_t *mpi_request,
u16 smid, int sge_count)
{
int sge_len, num_prp_in_chain = 0;
Mpi25IeeeSgeChain64_t *main_chain_element, *ptr_first_sgl;
__le64 *curr_buff;
dma_addr_t msg_dma, sge_addr, offset;
u32 page_mask, page_mask_result;
struct scatterlist *sg_scmd;
u32 first_prp_len;
int data_len = scsi_bufflen(scmd);
u32 nvme_pg_size;
nvme_pg_size = max_t(u32, ioc->page_size, NVME_PRP_PAGE_SIZE);
/*
* Nvme has a very convoluted prp format. One prp is required
* for each page or partial page. Driver need to split up OS sg_list
* entries if it is longer than one page or cross a page
* boundary. Driver also have to insert a PRP list pointer entry as
* the last entry in each physical page of the PRP list.
*
* NOTE: The first PRP "entry" is actually placed in the first
* SGL entry in the main message as IEEE 64 format. The 2nd
* entry in the main message is the chain element, and the rest
* of the PRP entries are built in the contiguous pcie buffer.
*/
page_mask = nvme_pg_size - 1;
/*
* Native SGL is needed.
* Put a chain element in main message frame that points to the first
* chain buffer.
*
* NOTE: The ChainOffset field must be 0 when using a chain pointer to
* a native SGL.
*/
/* Set main message chain element pointer */
main_chain_element = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL;
/*
* For NVMe the chain element needs to be the 2nd SG entry in the main
* message.
*/
main_chain_element = (Mpi25IeeeSgeChain64_t *)
((u8 *)main_chain_element + sizeof(MPI25_IEEE_SGE_CHAIN64));
/*
* For the PRP entries, use the specially allocated buffer of
* contiguous memory. Normal chain buffers can't be used
* because each chain buffer would need to be the size of an OS
* page (4k).
*/
curr_buff = mpt3sas_base_get_pcie_sgl(ioc, smid);
msg_dma = mpt3sas_base_get_pcie_sgl_dma(ioc, smid);
main_chain_element->Address = cpu_to_le64(msg_dma);
main_chain_element->NextChainOffset = 0;
main_chain_element->Flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP;
/* Build first prp, sge need not to be page aligned*/
ptr_first_sgl = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL;
sg_scmd = scsi_sglist(scmd);
sge_addr = sg_dma_address(sg_scmd);
sge_len = sg_dma_len(sg_scmd);
offset = sge_addr & page_mask;
first_prp_len = nvme_pg_size - offset;
ptr_first_sgl->Address = cpu_to_le64(sge_addr);
ptr_first_sgl->Length = cpu_to_le32(first_prp_len);
data_len -= first_prp_len;
if (sge_len > first_prp_len) {
sge_addr += first_prp_len;
sge_len -= first_prp_len;
} else if (data_len && (sge_len == first_prp_len)) {
sg_scmd = sg_next(sg_scmd);
sge_addr = sg_dma_address(sg_scmd);
sge_len = sg_dma_len(sg_scmd);
}
for (;;) {
offset = sge_addr & page_mask;
/* Put PRP pointer due to page boundary*/
page_mask_result = (uintptr_t)(curr_buff + 1) & page_mask;
if (unlikely(!page_mask_result)) {
scmd_printk(KERN_NOTICE,
scmd, "page boundary curr_buff: 0x%p\n",
curr_buff);
msg_dma += 8;
*curr_buff = cpu_to_le64(msg_dma);
curr_buff++;
num_prp_in_chain++;
}
*curr_buff = cpu_to_le64(sge_addr);
curr_buff++;
msg_dma += 8;
num_prp_in_chain++;
sge_addr += nvme_pg_size;
sge_len -= nvme_pg_size;
data_len -= nvme_pg_size;
if (data_len <= 0)
break;
if (sge_len > 0)
continue;
sg_scmd = sg_next(sg_scmd);
sge_addr = sg_dma_address(sg_scmd);
sge_len = sg_dma_len(sg_scmd);
}
main_chain_element->Length =
cpu_to_le32(num_prp_in_chain * sizeof(u64));
return;
}
static bool
base_is_prp_possible(struct MPT3SAS_ADAPTER *ioc,
struct _pcie_device *pcie_device, struct scsi_cmnd *scmd, int sge_count)
{
u32 data_length = 0;
struct scatterlist *sg_scmd;
bool build_prp = true;
data_length = scsi_bufflen(scmd);
sg_scmd = scsi_sglist(scmd);
/* If Datalenth is <= 16K and number of SGEs entries are <= 2
* we built IEEE SGL
*/
if ((data_length <= NVME_PRP_PAGE_SIZE*4) && (sge_count <= 2))
build_prp = false;
return build_prp;
}
/**
* _base_check_pcie_native_sgl - This function is called for PCIe end devices to
* determine if the driver needs to build a native SGL. If so, that native
* SGL is built in the special contiguous buffers allocated especially for
* PCIe SGL creation. If the driver will not build a native SGL, return
* TRUE and a normal IEEE SGL will be built. Currently this routine
* supports NVMe.
* @ioc: per adapter object
* @mpi_request: mf request pointer
* @smid: system request message index
* @scmd: scsi command
* @pcie_device: points to the PCIe device's info
*
* Returns 0 if native SGL was built, 1 if no SGL was built
*/
static int
_base_check_pcie_native_sgl(struct MPT3SAS_ADAPTER *ioc,
Mpi25SCSIIORequest_t *mpi_request, u16 smid, struct scsi_cmnd *scmd,
struct _pcie_device *pcie_device)
{
struct scatterlist *sg_scmd;
int sges_left;
/* Get the SG list pointer and info. */
sg_scmd = scsi_sglist(scmd);
sges_left = scsi_dma_map(scmd);
if (sges_left < 0) {
sdev_printk(KERN_ERR, scmd->device,
"scsi_dma_map failed: request for %d bytes!\n",
scsi_bufflen(scmd));
return 1;
}
/* Check if we need to build a native SG list. */
if (base_is_prp_possible(ioc, pcie_device,
scmd, sges_left) == 0) {
/* We built a native SG list, just return. */
goto out;
}
/*
* Build native NVMe PRP.
*/
base_make_prp_nvme(ioc, scmd, mpi_request,
smid, sges_left);
return 0;
out:
scsi_dma_unmap(scmd);
return 1;
}
/**
* _base_add_sg_single_ieee - add sg element for IEEE format
* @paddr: virtual address for SGE
@ -1391,9 +1846,11 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
/**
* _base_build_sg_scmd - main sg creation routine
* pcie_device is unused here!
* @ioc: per adapter object
* @scmd: scsi command
* @smid: system request message index
* @unused: unused pcie_device pointer
* Context: none.
*
* The main routine that builds scatter gather table from a given
@ -1403,7 +1860,7 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
*/
static int
_base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
struct scsi_cmnd *scmd, u16 smid)
struct scsi_cmnd *scmd, u16 smid, struct _pcie_device *unused)
{
Mpi2SCSIIORequest_t *mpi_request;
dma_addr_t chain_dma;
@ -1537,6 +1994,8 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
* @ioc: per adapter object
* @scmd: scsi command
* @smid: system request message index
* @pcie_device: Pointer to pcie_device. If set, the pcie native sgl will be
* constructed on need.
* Context: none.
*
* The main routine that builds scatter gather table from a given
@ -1546,9 +2005,9 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
*/
static int
_base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
struct scsi_cmnd *scmd, u16 smid)
struct scsi_cmnd *scmd, u16 smid, struct _pcie_device *pcie_device)
{
Mpi2SCSIIORequest_t *mpi_request;
Mpi25SCSIIORequest_t *mpi_request;
dma_addr_t chain_dma;
struct scatterlist *sg_scmd;
void *sg_local, *chain;
@ -1571,6 +2030,13 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
chain_sgl_flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
/* Check if we need to build a native SG list. */
if ((pcie_device) && (_base_check_pcie_native_sgl(ioc, mpi_request,
smid, scmd, pcie_device) == 0)) {
/* We built a native SG list, just return. */
return 0;
}
sg_scmd = scsi_sglist(scmd);
sges_left = scsi_dma_map(scmd);
if (sges_left < 0) {
@ -1582,12 +2048,12 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
sg_local = &mpi_request->SGL;
sges_in_segment = (ioc->request_sz -
offsetof(Mpi2SCSIIORequest_t, SGL))/ioc->sge_size_ieee;
offsetof(Mpi25SCSIIORequest_t, SGL))/ioc->sge_size_ieee;
if (sges_left <= sges_in_segment)
goto fill_in_last_segment;
mpi_request->ChainOffset = (sges_in_segment - 1 /* chain element */) +
(offsetof(Mpi2SCSIIORequest_t, SGL)/ioc->sge_size_ieee);
(offsetof(Mpi25SCSIIORequest_t, SGL)/ioc->sge_size_ieee);
/* fill in main message segment when there is a chain following */
while (sges_in_segment > 1) {
@ -1990,7 +2456,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
ioc->cpu_count, max_msix_vectors);
if (!ioc->rdpq_array_enable && max_msix_vectors == -1)
local_max_msix_vectors = 8;
local_max_msix_vectors = (reset_devices) ? 1 : 8;
else
local_max_msix_vectors = max_msix_vectors;
@ -2266,6 +2732,32 @@ mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid)
SCSI_SENSE_BUFFERSIZE));
}
/**
* mpt3sas_base_get_pcie_sgl - obtain a PCIe SGL virt addr
* @ioc: per adapter object
* @smid: system request message index
*
* Returns virt pointer to a PCIe SGL.
*/
void *
mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid)
{
return (void *)(ioc->scsi_lookup[smid - 1].pcie_sg_list.pcie_sgl);
}
/**
* mpt3sas_base_get_pcie_sgl_dma - obtain a PCIe SGL dma addr
* @ioc: per adapter object
* @smid: system request message index
*
* Returns phys pointer to the address of the PCIe buffer.
*/
dma_addr_t
mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid)
{
return ioc->scsi_lookup[smid - 1].pcie_sg_list.pcie_sgl_dma;
}
/**
* mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address
* @ioc: per adapter object
@ -2543,6 +3035,30 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
&ioc->scsi_lookup_lock);
}
/**
* _base_put_smid_nvme_encap - send NVMe encapsulated request to
* firmware
* @ioc: per adapter object
* @smid: system request message index
*
* Return nothing.
*/
static void
_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
{
Mpi2RequestDescriptorUnion_t descriptor;
u64 *request = (u64 *)&descriptor;
descriptor.Default.RequestFlags =
MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
descriptor.Default.SMID = cpu_to_le16(smid);
descriptor.Default.LMID = 0;
descriptor.Default.DescriptorTypeDependent = 0;
_base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
&ioc->scsi_lookup_lock);
}
/**
* _base_put_smid_default - Default, primarily used for config pages
* @ioc: per adapter object
@ -2633,6 +3149,27 @@ _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
}
/**
* _base_put_smid_nvme_encap_atomic - send NVMe encapsulated request to
* firmware using Atomic Request Descriptor
* @ioc: per adapter object
* @smid: system request message index
*
* Return nothing.
*/
static void
_base_put_smid_nvme_encap_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid)
{
Mpi26AtomicRequestDescriptor_t descriptor;
u32 *request = (u32 *)&descriptor;
descriptor.RequestFlags = MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
descriptor.MSIxIndex = _base_get_msix_index(ioc);
descriptor.SMID = cpu_to_le16(smid);
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
}
/**
* _base_put_smid_default - Default, primarily used for config pages
* use Atomic Request Descriptor
@ -2945,6 +3482,11 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
_base_display_OEMs_branding(ioc);
if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES) {
pr_info("%sNVMe", i ? "," : "");
i++;
}
pr_info(MPT3SAS_FMT "Protocol=(", ioc->name);
if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
@ -3245,6 +3787,17 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
kfree(ioc->reply_post);
}
if (ioc->pcie_sgl_dma_pool) {
for (i = 0; i < ioc->scsiio_depth; i++) {
if (ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl)
pci_pool_free(ioc->pcie_sgl_dma_pool,
ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl,
ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl_dma);
}
if (ioc->pcie_sgl_dma_pool)
pci_pool_destroy(ioc->pcie_sgl_dma_pool);
}
if (ioc->config_page) {
dexitprintk(ioc, pr_info(MPT3SAS_FMT
"config_page(0x%p): free\n", ioc->name,
@ -3286,7 +3839,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
u16 chains_needed_per_io;
u32 sz, total_sz, reply_post_free_sz;
u32 retry_sz;
u16 max_request_credit;
u16 max_request_credit, nvme_blocks_needed;
unsigned short sg_tablesize;
u16 sge_size;
int i;
@ -3308,6 +3861,11 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
sg_tablesize = MPT3SAS_SG_DEPTH;
}
/* max sgl entries <= MPT_KDUMP_MIN_PHYS_SEGMENTS in KDUMP mode */
if (reset_devices)
sg_tablesize = min_t(unsigned short, sg_tablesize,
MPT_KDUMP_MIN_PHYS_SEGMENTS);
if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
@ -3340,7 +3898,10 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->internal_depth, facts->RequestCredit);
if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
max_request_credit = MAX_HBA_QUEUE_DEPTH;
} else
} else if (reset_devices)
max_request_credit = min_t(u16, facts->RequestCredit,
(MPT3SAS_KDUMP_SCSI_IO_DEPTH + ioc->internal_depth));
else
max_request_credit = min_t(u16, facts->RequestCredit,
MAX_HBA_QUEUE_DEPTH);
@ -3622,7 +4183,52 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
"internal(0x%p): depth(%d), start smid(%d)\n",
ioc->name, ioc->internal,
ioc->internal_depth, ioc->internal_smid));
/*
* The number of NVMe page sized blocks needed is:
* (((sg_tablesize * 8) - 1) / (page_size - 8)) + 1
* ((sg_tablesize * 8) - 1) is the max PRP's minus the first PRP entry
* that is placed in the main message frame. 8 is the size of each PRP
* entry or PRP list pointer entry. 8 is subtracted from page_size
* because of the PRP list pointer entry at the end of a page, so this
* is not counted as a PRP entry. The 1 added page is a round up.
*
* To avoid allocation failures due to the amount of memory that could
* be required for NVMe PRP's, only each set of NVMe blocks will be
* contiguous, so a new set is allocated for each possible I/O.
*/
if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES) {
nvme_blocks_needed =
(ioc->shost->sg_tablesize * NVME_PRP_SIZE) - 1;
nvme_blocks_needed /= (ioc->page_size - NVME_PRP_SIZE);
nvme_blocks_needed++;
sz = nvme_blocks_needed * ioc->page_size;
ioc->pcie_sgl_dma_pool =
pci_pool_create("PCIe SGL pool", ioc->pdev, sz, 16, 0);
if (!ioc->pcie_sgl_dma_pool) {
pr_info(MPT3SAS_FMT
"PCIe SGL pool: pci_pool_create failed\n",
ioc->name);
goto out;
}
for (i = 0; i < ioc->scsiio_depth; i++) {
ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl =
pci_pool_alloc(ioc->pcie_sgl_dma_pool,
GFP_KERNEL,
&ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl_dma);
if (!ioc->scsi_lookup[i].pcie_sg_list.pcie_sgl) {
pr_info(MPT3SAS_FMT
"PCIe SGL pool: pci_pool_alloc failed\n",
ioc->name);
goto out;
}
}
dinitprintk(ioc, pr_info(MPT3SAS_FMT "PCIe sgl pool depth(%d), "
"element_size(%d), pool_size(%d kB)\n", ioc->name,
ioc->scsiio_depth, sz, (sz * ioc->scsiio_depth)/1024));
total_sz += sz * ioc->scsiio_depth;
}
/* sense buffers, 4 byte align */
sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
ioc->sense_dma_pool = dma_pool_create("sense pool", &ioc->pdev->dev, sz,
@ -4446,7 +5052,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc)
if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
ioc->ir_firmware = 1;
if ((facts->IOCCapabilities &
MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE))
MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE) && (!reset_devices))
ioc->rdpq_array_capable = 1;
if (facts->IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ)
ioc->atomic_desc_capable = 1;
@ -4467,6 +5073,19 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc)
le16_to_cpu(mpi_reply.HighPriorityCredit);
facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
facts->CurrentHostPageSize = mpi_reply.CurrentHostPageSize;
/*
* Get the Page Size from IOC Facts. If it's 0, default to 4k.
*/
ioc->page_size = 1 << facts->CurrentHostPageSize;
if (ioc->page_size == 1) {
pr_info(MPT3SAS_FMT "CurrentHostPageSize is 0: Setting "
"default host page size to 4k\n", ioc->name);
ioc->page_size = 1 << MPT3SAS_HOST_PAGE_SIZE_4K;
}
dinitprintk(ioc, pr_info(MPT3SAS_FMT "CurrentHostPageSize(%d)\n",
ioc->name, facts->CurrentHostPageSize));
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"hba queue depth(%d), max chains per io(%d)\n",
@ -4506,6 +5125,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
mpi_request.VP_ID = 0;
mpi_request.MsgVersion = cpu_to_le16(ioc->hba_mpi_version_belonged);
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
mpi_request.HostPageSize = MPT3SAS_HOST_PAGE_SIZE_4K;
if (_base_is_controller_msix_enabled(ioc))
mpi_request.HostMSIxVectors = ioc->reply_queue_count;
@ -5374,6 +5994,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
*/
ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
ioc->build_sg = &_base_build_sg_ieee;
ioc->build_nvme_prp = &_base_build_nvme_prp;
ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
@ -5385,11 +6006,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
ioc->put_smid_scsi_io = &_base_put_smid_scsi_io_atomic;
ioc->put_smid_fast_path = &_base_put_smid_fast_path_atomic;
ioc->put_smid_hi_priority = &_base_put_smid_hi_priority_atomic;
ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap_atomic;
} else {
ioc->put_smid_default = &_base_put_smid_default;
ioc->put_smid_scsi_io = &_base_put_smid_scsi_io;
ioc->put_smid_fast_path = &_base_put_smid_fast_path;
ioc->put_smid_hi_priority = &_base_put_smid_hi_priority;
ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap;
}
@ -5517,9 +6140,16 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
_base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
_base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
_base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD);
if (ioc->hba_mpi_version_belonged == MPI26_VERSION)
_base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
_base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
if (ioc->hba_mpi_version_belonged == MPI26_VERSION) {
if (ioc->is_gen35_ioc) {
_base_unmask_events(ioc,
MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE);
_base_unmask_events(ioc, MPI2_EVENT_PCIE_ENUMERATION);
_base_unmask_events(ioc,
MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
}
}
r = _base_make_ioc_operational(ioc);
if (r)
goto out_free_resources;

View File

@ -54,6 +54,7 @@
#include "mpi/mpi2_raid.h"
#include "mpi/mpi2_tool.h"
#include "mpi/mpi2_sas.h"
#include "mpi/mpi2_pci.h"
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@ -73,8 +74,8 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
#define MPT3SAS_DRIVER_VERSION "15.100.00.00"
#define MPT3SAS_MAJOR_VERSION 15
#define MPT3SAS_DRIVER_VERSION "17.100.00.00"
#define MPT3SAS_MAJOR_VERSION 17
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@ -92,6 +93,7 @@
*/
#define MPT_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE
#define MPT_MIN_PHYS_SEGMENTS 16
#define MPT_KDUMP_MIN_PHYS_SEGMENTS 32
#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE
@ -111,9 +113,11 @@
#define MPT3SAS_SATA_QUEUE_DEPTH 32
#define MPT3SAS_SAS_QUEUE_DEPTH 254
#define MPT3SAS_RAID_QUEUE_DEPTH 128
#define MPT3SAS_KDUMP_SCSI_IO_DEPTH 200
#define MPT3SAS_RAID_MAX_SECTORS 8192
#define MPT3SAS_HOST_PAGE_SIZE_4K 12
#define MPT3SAS_NVME_QUEUE_DEPTH 128
#define MPT_NAME_LENGTH 32 /* generic length of strings */
#define MPT_STRING_LENGTH 64
@ -130,6 +134,15 @@
#define MAX_CHAIN_ELEMT_SZ 16
#define DEFAULT_NUM_FWCHAIN_ELEMTS 8
/*
* NVMe defines
*/
#define NVME_PRP_SIZE 8 /* PRP size */
#define NVME_CMD_PRP1_OFFSET 24 /* PRP1 offset in NVMe cmd */
#define NVME_CMD_PRP2_OFFSET 32 /* PRP2 offset in NVMe cmd */
#define NVME_ERROR_RESPONSE_SIZE 16 /* Max NVME Error Response */
#define NVME_PRP_PAGE_SIZE 4096 /* Page size */
/*
* reset phases
*/
@ -159,6 +172,7 @@
#define MPT_TARGET_FLAGS_VOLUME 0x02
#define MPT_TARGET_FLAGS_DELETED 0x04
#define MPT_TARGET_FASTPATH_IO 0x08
#define MPT_TARGET_FLAGS_PCIE_DEVICE 0x10
#define SAS2_PCI_DEVICE_B0_REVISION (0x01)
#define SAS3_PCI_DEVICE_C0_REVISION (0x02)
@ -357,7 +371,8 @@ struct Mpi2ManufacturingPage11_t {
* @flags: MPT_TARGET_FLAGS_XXX flags
* @deleted: target flaged for deletion
* @tm_busy: target is busy with TM request.
* @sdev: The sas_device associated with this target
* @sas_dev: The sas_device associated with this target
* @pcie_dev: The pcie device associated with this target
*/
struct MPT3SAS_TARGET {
struct scsi_target *starget;
@ -368,7 +383,8 @@ struct MPT3SAS_TARGET {
u32 flags;
u8 deleted;
u8 tm_busy;
struct _sas_device *sdev;
struct _sas_device *sas_dev;
struct _pcie_device *pcie_dev;
};
@ -467,6 +483,8 @@ struct _internal_cmd {
* @pfa_led_on: flag for PFA LED status
* @pend_sas_rphy_add: flag to check if device is in sas_rphy_add()
* addition routine.
* @chassis_slot: chassis slot
* @is_chassis_slot_valid: chassis slot valid or not
*/
struct _sas_device {
struct list_head list;
@ -489,6 +507,8 @@ struct _sas_device {
u8 pfa_led_on;
u8 pend_sas_rphy_add;
u8 enclosure_level;
u8 chassis_slot;
u8 is_chassis_slot_valid;
u8 connector_name[5];
struct kref refcount;
};
@ -508,6 +528,89 @@ static inline void sas_device_put(struct _sas_device *s)
kref_put(&s->refcount, sas_device_free);
}
/*
* struct _pcie_device - attached PCIe device information
* @list: pcie device list
* @starget: starget object
* @wwid: device WWID
* @handle: device handle
* @device_info: bitfield provides detailed info about the device
* @id: target id
* @channel: target channel
* @slot: slot number
* @port_num: port number
* @responding: used in _scsih_pcie_device_mark_responding
* @fast_path: fast path feature enable bit
* @nvme_mdts: MaximumDataTransferSize from PCIe Device Page 2 for
* NVMe device only
* @enclosure_handle: enclosure handle
* @enclosure_logical_id: enclosure logical identifier
* @enclosure_level: The level of device's enclosure from the controller
* @connector_name: ASCII value of the Connector's name
* @serial_number: pointer of serial number string allocated runtime
* @refcount: reference count for deletion
*/
struct _pcie_device {
struct list_head list;
struct scsi_target *starget;
u64 wwid;
u16 handle;
u32 device_info;
int id;
int channel;
u16 slot;
u8 port_num;
u8 responding;
u8 fast_path;
u32 nvme_mdts;
u16 enclosure_handle;
u64 enclosure_logical_id;
u8 enclosure_level;
u8 connector_name[4];
u8 *serial_number;
struct kref refcount;
};
/**
* pcie_device_get - Increment the pcie device reference count
*
* @p: pcie_device object
*
* When ever this function called it will increment the
* reference count of the pcie device for which this function called.
*
*/
static inline void pcie_device_get(struct _pcie_device *p)
{
kref_get(&p->refcount);
}
/**
* pcie_device_free - Release the pcie device object
* @r - kref object
*
* Free's the pcie device object. It will be called when reference count
* reaches to zero.
*/
static inline void pcie_device_free(struct kref *r)
{
kfree(container_of(r, struct _pcie_device, refcount));
}
/**
* pcie_device_put - Decrement the pcie device reference count
*
* @p: pcie_device object
*
* When ever this function called it will decrement the
* reference count of the pcie device for which this function called.
*
* When refernce count reaches to Zero, this will call pcie_device_free to the
* pcie_device object.
*/
static inline void pcie_device_put(struct _pcie_device *p)
{
kref_put(&p->refcount, pcie_device_free);
}
/**
* struct _raid_device - raid volume link list
* @list: sas device list
@ -556,12 +659,13 @@ struct _raid_device {
/**
* struct _boot_device - boot device info
* @is_raid: flag to indicate whether this is volume
* @device: holds pointer for either struct _sas_device or
* struct _raid_device
*
* @channel: sas, raid, or pcie channel
* @device: holds pointer for struct _sas_device, struct _raid_device or
* struct _pcie_device
*/
struct _boot_device {
u8 is_raid;
int channel;
void *device;
};
@ -643,6 +747,16 @@ enum reset_type {
SOFT_RESET,
};
/**
* struct pcie_sg_list - PCIe SGL buffer (contiguous per I/O)
* @pcie_sgl: PCIe native SGL for NVMe devices
* @pcie_sgl_dma: physical address
*/
struct pcie_sg_list {
void *pcie_sgl;
dma_addr_t pcie_sgl_dma;
};
/**
* struct chain_tracker - firmware chain tracker
* @chain_buffer: chain buffer
@ -669,6 +783,7 @@ struct scsiio_tracker {
struct scsi_cmnd *scmd;
u8 cb_idx;
u8 direct_io;
struct pcie_sg_list pcie_sg_list;
struct list_head chain_list;
struct list_head tracker_list;
u16 msix_io;
@ -742,13 +857,19 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
/* SAS3.0 support */
typedef int (*MPT_BUILD_SG_SCMD)(struct MPT3SAS_ADAPTER *ioc,
struct scsi_cmnd *scmd, u16 smid);
struct scsi_cmnd *scmd, u16 smid, struct _pcie_device *pcie_device);
typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge,
dma_addr_t data_out_dma, size_t data_out_sz,
dma_addr_t data_in_dma, size_t data_in_sz);
typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc,
void *paddr);
/* SAS3.5 support */
typedef void (*NVME_BUILD_PRP)(struct MPT3SAS_ADAPTER *ioc, u16 smid,
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request,
dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
size_t data_in_sz);
/* To support atomic and non atomic descriptors*/
typedef void (*PUT_SMID_IO_FP_HIP) (struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 funcdep);
@ -791,6 +912,7 @@ struct mpt3sas_facts {
u16 MaxDevHandle;
u16 MaxPersistentEntries;
u16 MinDevHandle;
u8 CurrentHostPageSize;
};
struct mpt3sas_port_facts {
@ -825,6 +947,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @bars: bitmask of BAR's that must be configured
* @mask_interrupts: ignore interrupt
* @dma_mask: used to set the consistent dma mask
* @pci_access_mutex: Mutex to synchronize ioctl, sysfs show path and
* pci resource handling
* @fault_reset_work_q_name: fw fault work queue
* @fault_reset_work_q: ""
* @fault_reset_work: ""
@ -888,9 +1012,13 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @sas_device_list: sas device object list
* @sas_device_init_list: sas device object list (used only at init time)
* @sas_device_lock:
* @pcie_device_list: pcie device object list
* @pcie_device_init_list: pcie device object list (used only at init time)
* @pcie_device_lock:
* @io_missing_delay: time for IO completed by fw when PDR enabled
* @device_missing_delay: time for device missing by fw when PDR enabled
* @sas_id : used for setting volume target IDs
* @pcie_target_id: used for setting pcie target IDs
* @blocking_handles: bitmask used to identify which devices need blocking
* @pd_handles : bitmask for PD handles
* @pd_handles_sz : size of pd_handle bitmask
@ -1056,6 +1184,9 @@ struct MPT3SAS_ADAPTER {
MPT_BUILD_SG build_sg_mpi;
MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi;
/* function ptr for NVMe PRP elements only */
NVME_BUILD_PRP build_nvme_prp;
/* event log */
u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
u32 event_context;
@ -1086,11 +1217,16 @@ struct MPT3SAS_ADAPTER {
struct list_head sas_device_list;
struct list_head sas_device_init_list;
spinlock_t sas_device_lock;
struct list_head pcie_device_list;
struct list_head pcie_device_init_list;
spinlock_t pcie_device_lock;
struct list_head raid_device_list;
spinlock_t raid_device_lock;
u8 io_missing_delay;
u16 device_missing_delay;
int sas_id;
int pcie_target_id;
void *blocking_handles;
void *pd_handles;
@ -1119,6 +1255,11 @@ struct MPT3SAS_ADAPTER {
int pending_io_count;
wait_queue_head_t reset_wq;
/* PCIe SGL */
struct dma_pool *pcie_sgl_dma_pool;
/* Host Page Size */
u32 page_size;
/* chain */
struct chain_tracker *chain_lookup;
struct list_head free_chain_list;
@ -1216,6 +1357,7 @@ struct MPT3SAS_ADAPTER {
PUT_SMID_IO_FP_HIP put_smid_fast_path;
PUT_SMID_IO_FP_HIP put_smid_hi_priority;
PUT_SMID_DEFAULT put_smid_default;
PUT_SMID_DEFAULT put_smid_nvme_encap;
};
@ -1252,7 +1394,8 @@ void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid);
void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid);
__le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc,
u16 smid);
void *mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid);
dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid);
void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc);
/* hi-priority queue */
@ -1321,6 +1464,10 @@ struct _sas_device *mpt3sas_get_sdev_by_addr(
struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *__mpt3sas_get_sdev_by_addr(
struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
u16 handle);
struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
u16 handle);
void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
struct _raid_device *
@ -1359,6 +1506,12 @@ int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
u16 sz);
@ -1466,7 +1619,7 @@ void
mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io);
void
mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
struct _raid_device *raid_device, Mpi25SCSIIORequest_t *mpi_request,
u16 smid);
/* NCQ Prio Handling Check */

View File

@ -150,6 +150,24 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
desc = "driver_mapping";
break;
case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
desc = "sas_port";
break;
case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
desc = "ext_manufacturing";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
desc = "pcie_io_unit";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
desc = "pcie_switch";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
desc = "pcie_device";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
desc = "pcie_link";
break;
}
break;
}
@ -1052,6 +1070,88 @@ mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
return r;
}
/**
* mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* @form: GET_NEXT_HANDLE or HANDLE
* @handle: device handle
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
int
mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
u32 form, u32 handle)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
mpi_request.Header.PageNumber = 0;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.PageAddress = cpu_to_le32(form | handle);
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* @form: GET_NEXT_HANDLE or HANDLE
* @handle: device handle
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
int
mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
u32 form, u32 handle)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
mpi_request.Header.PageNumber = 2;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.PageAddress = cpu_to_le32(form | handle);
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
* @ioc: per adapter object

View File

@ -78,32 +78,6 @@ enum block_state {
BLOCKING,
};
/**
* _ctl_sas_device_find_by_handle - sas device search
* @ioc: per adapter object
* @handle: sas device handle (assigned by firmware)
* Context: Calling function should acquire ioc->sas_device_lock
*
* This searches for sas_device based on sas_address, then return sas_device
* object.
*/
static struct _sas_device *
_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _sas_device *sas_device, *r;
r = NULL;
list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
if (sas_device->handle != handle)
continue;
r = sas_device;
goto out;
}
out:
return r;
}
/**
* _ctl_display_some_debug - debug routine
* @ioc: per adapter object
@ -229,10 +203,9 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
Mpi2SCSIIOReply_t *scsi_reply =
(Mpi2SCSIIOReply_t *)mpi_reply;
struct _sas_device *sas_device = NULL;
unsigned long flags;
struct _pcie_device *pcie_device = NULL;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _ctl_sas_device_find_by_handle(ioc,
sas_device = mpt3sas_get_sdev_by_handle(ioc,
le16_to_cpu(scsi_reply->DevHandle));
if (sas_device) {
pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n",
@ -242,8 +215,25 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
"\tenclosure_logical_id(0x%016llx), slot(%d)\n",
ioc->name, (unsigned long long)
sas_device->enclosure_logical_id, sas_device->slot);
sas_device_put(sas_device);
}
if (!sas_device) {
pcie_device = mpt3sas_get_pdev_by_handle(ioc,
le16_to_cpu(scsi_reply->DevHandle));
if (pcie_device) {
pr_warn(MPT3SAS_FMT
"\tWWID(0x%016llx), port(%d)\n", ioc->name,
(unsigned long long)pcie_device->wwid,
pcie_device->port_num);
if (pcie_device->enclosure_handle != 0)
pr_warn(MPT3SAS_FMT
"\tenclosure_logical_id(0x%016llx), slot(%d)\n",
ioc->name, (unsigned long long)
pcie_device->enclosure_logical_id,
pcie_device->slot);
pcie_device_put(pcie_device);
}
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
pr_info(MPT3SAS_FMT
"\tscsi_state(0x%02x), scsi_status"
@ -272,6 +262,7 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
{
MPI2DefaultReply_t *mpi_reply;
Mpi2SCSIIOReply_t *scsiio_reply;
Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply;
const void *sense_data;
u32 sz;
@ -298,7 +289,20 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
memcpy(ioc->ctl_cmds.sense, sense_data, sz);
}
}
/*
* Get Error Response data for NVMe device. The ctl_cmds.sense
* buffer is used to store the Error Response data.
*/
if (mpi_reply->Function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
nvme_error_reply =
(Mpi26NVMeEncapsulatedErrorReply_t *)mpi_reply;
sz = min_t(u32, NVME_ERROR_RESPONSE_SIZE,
le32_to_cpu(nvme_error_reply->ErrorResponseCount));
sense_data = mpt3sas_base_get_sense_buffer(ioc, smid);
memcpy(ioc->ctl_cmds.sense, sense_data, sz);
}
}
_ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
complete(&ioc->ctl_cmds.done);
@ -640,11 +644,12 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
{
MPI2RequestHeader_t *mpi_request = NULL, *request;
MPI2DefaultReply_t *mpi_reply;
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
u32 ioc_state;
u16 smid;
unsigned long timeout;
u8 issue_reset;
u32 sz;
u32 sz, sz_arg;
void *psge;
void *data_out = NULL;
dma_addr_t data_out_dma = 0;
@ -741,7 +746,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT ||
mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH) {
mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH ||
mpi_request->Function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
device_handle = le16_to_cpu(mpi_request->FunctionDependent1);
if (!device_handle || (device_handle >
@ -792,6 +798,38 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
init_completion(&ioc->ctl_cmds.done);
switch (mpi_request->Function) {
case MPI2_FUNCTION_NVME_ENCAPSULATED:
{
nvme_encap_request = (Mpi26NVMeEncapsulatedRequest_t *)request;
/*
* Get the Physical Address of the sense buffer.
* Use Error Response buffer address field to hold the sense
* buffer address.
* Clear the internal sense buffer, which will potentially hold
* the Completion Queue Entry on return, or 0 if no Entry.
* Build the PRPs and set direction bits.
* Send the request.
*/
nvme_encap_request->ErrorResponseBaseAddress = ioc->sense_dma &
0xFFFFFFFF00000000;
nvme_encap_request->ErrorResponseBaseAddress |=
(U64)mpt3sas_base_get_sense_buffer_dma(ioc, smid);
nvme_encap_request->ErrorResponseAllocationLength =
NVME_ERROR_RESPONSE_SIZE;
memset(ioc->ctl_cmds.sense, 0, NVME_ERROR_RESPONSE_SIZE);
ioc->build_nvme_prp(ioc, smid, nvme_encap_request,
data_out_dma, data_out_sz, data_in_dma, data_in_sz);
if (test_bit(device_handle, ioc->device_remove_in_progress)) {
dtmprintk(ioc, pr_info(MPT3SAS_FMT "handle(0x%04x) :"
"ioctl failed due to device removal in progress\n",
ioc->name, device_handle));
mpt3sas_base_free_smid(ioc, smid);
ret = -EINVAL;
goto out;
}
ioc->put_smid_nvme_encap(ioc, smid);
break;
}
case MPI2_FUNCTION_SCSI_IO_REQUEST:
case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
{
@ -1007,15 +1045,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
}
}
/* copy out sense to user */
/* copy out sense/NVMe Error Response to user */
if (karg.max_sense_bytes && (mpi_request->Function ==
MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || mpi_request->Function ==
MPI2_FUNCTION_NVME_ENCAPSULATED)) {
if (karg.sense_data_ptr == NULL) {
pr_info(MPT3SAS_FMT "Response buffer provided"
" by application is NULL; Response data will"
" not be returned.\n", ioc->name);
goto out;
}
sz_arg = (mpi_request->Function ==
MPI2_FUNCTION_NVME_ENCAPSULATED) ? NVME_ERROR_RESPONSE_SIZE :
SCSI_SENSE_BUFFERSIZE;
sz = min_t(u32, karg.max_sense_bytes, sz_arg);
if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense,
sz)) {
pr_err("failure at %s:%d/%s()!\n", __FILE__,
__LINE__, __func__);
__LINE__, __func__);
ret = -ENODATA;
goto out;
}
@ -1065,12 +1113,6 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt3_ioctl_iocinfo karg;
if (copy_from_user(&karg, arg, sizeof(karg))) {
pr_err("failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
__func__));
@ -1294,6 +1336,42 @@ _ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc,
return rc;
}
/**
* _ctl_btdh_search_pcie_device - searching for pcie device
* @ioc: per adapter object
* @btdh: btdh ioctl payload
*/
static int
_ctl_btdh_search_pcie_device(struct MPT3SAS_ADAPTER *ioc,
struct mpt3_ioctl_btdh_mapping *btdh)
{
struct _pcie_device *pcie_device;
unsigned long flags;
int rc = 0;
if (list_empty(&ioc->pcie_device_list))
return rc;
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) {
if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
btdh->handle == pcie_device->handle) {
btdh->bus = pcie_device->channel;
btdh->id = pcie_device->id;
rc = 1;
goto out;
} else if (btdh->bus == pcie_device->channel && btdh->id ==
pcie_device->id && btdh->handle == 0xFFFF) {
btdh->handle = pcie_device->handle;
rc = 1;
goto out;
}
}
out:
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
return rc;
}
/**
* _ctl_btdh_search_raid_device - searching for raid device
* @ioc: per adapter object
@ -1351,6 +1429,8 @@ _ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
__func__));
rc = _ctl_btdh_search_sas_device(ioc, &karg);
if (!rc)
rc = _ctl_btdh_search_pcie_device(ioc, &karg);
if (!rc)
_ctl_btdh_search_raid_device(ioc, &karg);

File diff suppressed because it is too large Load Diff

View File

@ -299,7 +299,7 @@ mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
*/
void
mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
struct _raid_device *raid_device, Mpi25SCSIIORequest_t *mpi_request,
u16 smid)
{
sector_t v_lba, p_lba, stripe_off, column, io_size;

View File

@ -604,7 +604,7 @@ static int nsp32_selection_autoscsi(struct scsi_cmnd *SCpnt)
* check bus line
*/
phase = nsp32_read1(base, SCSI_BUS_MONITOR);
if(((phase & BUSMON_BSY) == 1) || (phase & BUSMON_SEL) == 1) {
if ((phase & BUSMON_BSY) || (phase & BUSMON_SEL)) {
nsp32_msg(KERN_WARNING, "bus busy");
SCpnt->result = DID_BUS_BUSY << 16;
status = 1;

View File

@ -98,6 +98,58 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,
}
}
static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
/**
* pm8001_ctl_ila_version_show - ila version
* @cdev: pointer to embedded class device
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
*/
static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(cdev);
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
if (pm8001_ha->chip_id != chip_8001) {
return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
}
return 0;
}
static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
/**
* pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
* @cdev: pointer to embedded class device
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
*/
static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(cdev);
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
if (pm8001_ha->chip_id != chip_8001) {
return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
}
return 0;
}
static
DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
/**
* pm8001_ctl_max_out_io_show - max outstanding io supported
* @cdev: pointer to embedded class device
@ -748,6 +800,8 @@ struct device_attribute *pm8001_host_attrs[] = {
&dev_attr_bios_version,
&dev_attr_ib_log,
&dev_attr_ob_log,
&dev_attr_ila_version,
&dev_attr_inc_fw_ver,
NULL,
};

View File

@ -3198,19 +3198,28 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
u32 tag;
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
u32 status = le32_to_cpu(pPayload->status);
u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
} else
} else {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
pm8001_ha->phy[phy_id].reset_success = true;
}
if (pm8001_ha->phy[phy_id].enable_completion) {
complete(pm8001_ha->phy[phy_id].enable_completion);
pm8001_ha->phy[phy_id].enable_completion = NULL;
}
pm8001_tag_free(pm8001_ha, tag);
return 0;
}

View File

@ -132,7 +132,7 @@ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
sas_phy->oob_mode = OOB_NOT_CONNECTED;
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
sas_phy->sas_addr = &pm8001_ha->sas_addr[0];
sas_phy->sas_addr = (u8 *)&phy->dev_sas_addr;
sas_phy->frame_rcvd = &phy->frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
sas_phy->lldd_phy = phy;
@ -591,10 +591,12 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
for (i = 0; i < chip_info->n_phy; i++) {
sha->sas_phy[i] = &pm8001_ha->phy[i].sas_phy;
sha->sas_port[i] = &pm8001_ha->port[i].sas_port;
sha->sas_phy[i]->sas_addr =
(u8 *)&pm8001_ha->phy[i].dev_sas_addr;
}
sha->sas_ha_name = DRV_NAME;
sha->dev = pm8001_ha->dev;
sha->strict_wide_ports = 1;
sha->lldd_module = THIS_MODULE;
sha->sas_addr = &pm8001_ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
@ -611,6 +613,7 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
{
u8 i, j;
u8 sas_add[8];
#ifdef PM8001_READ_VPD
/* For new SPC controllers WWN is stored in flash vpd
* For SPC/SPCve controllers WWN is stored in EEPROM
@ -672,10 +675,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
}
memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
if (i && ((i % 4) == 0))
sas_add[7] = sas_add[7] + 4;
memcpy(&pm8001_ha->phy[i].dev_sas_addr,
pm8001_ha->sas_addr, SAS_ADDR_SIZE);
sas_add, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));

View File

@ -1158,40 +1158,42 @@ int pm8001_query_task(struct sas_task *task)
int pm8001_abort_task(struct sas_task *task)
{
unsigned long flags;
u32 tag = 0xdeadbeef;
u32 tag;
u32 device_id;
struct domain_device *dev ;
struct pm8001_hba_info *pm8001_ha = NULL;
struct pm8001_ccb_info *ccb;
struct pm8001_hba_info *pm8001_ha;
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
int rc = TMF_RESP_FUNC_FAILED, ret;
u32 phy_id;
struct sas_task_slow slow_task;
if (unlikely(!task || !task->lldd_task || !task->dev))
return rc;
return TMF_RESP_FUNC_FAILED;
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
device_id = pm8001_dev->device_id;
phy_id = pm8001_dev->attached_phy;
rc = pm8001_find_tag(task, &tag);
if (rc == 0) {
pm8001_printk("no tag for task:%p\n", task);
return TMF_RESP_FUNC_FAILED;
}
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
goto out;
return TMF_RESP_FUNC_COMPLETE;
}
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
if (task->slow_task == NULL) {
init_completion(&slow_task.completion);
task->slow_task = &slow_task;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
dev = task->dev;
ccb = task->lldd_task;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
int_to_scsilun(cmnd->device->lun, &lun);
rc = pm8001_find_tag(task, &tag);
if (rc == 0) {
printk(KERN_INFO "No such tag in %s\n", __func__);
rc = TMF_RESP_FUNC_FAILED;
return rc;
}
device_id = pm8001_dev->device_id;
PM8001_EH_DBG(pm8001_ha,
pm8001_printk("abort io to deviceid= %d\n", device_id));
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = tag;
rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task);
@ -1199,33 +1201,77 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
rc = pm8001_find_tag(task, &tag);
if (rc == 0) {
printk(KERN_INFO "No such tag in %s\n", __func__);
rc = TMF_RESP_FUNC_FAILED;
return rc;
if (pm8001_ha->chip_id == chip_8006) {
DECLARE_COMPLETION_ONSTACK(completion_reset);
DECLARE_COMPLETION_ONSTACK(completion);
struct pm8001_phy *phy = pm8001_ha->phy + phy_id;
/* 1. Set Device state as Recovery */
pm8001_dev->setds_completion = &completion;
PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
pm8001_dev, 0x03);
wait_for_completion(&completion);
/* 2. Send Phy Control Hard Reset */
reinit_completion(&completion);
phy->reset_success = false;
phy->enable_completion = &completion;
phy->reset_completion = &completion_reset;
ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
PHY_HARD_RESET);
if (ret)
goto out;
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("Waiting for local phy ctl\n"));
wait_for_completion(&completion);
if (!phy->reset_success)
goto out;
/* 3. Wait for Port Reset complete / Port reset TMO */
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("Waiting for Port reset\n"));
wait_for_completion(&completion_reset);
if (phy->port_reset_status)
goto out;
/*
* 4. SATA Abort ALL
* we wait for the task to be aborted so that the task
* is removed from the ccb. on success the caller is
* going to free the task.
*/
ret = pm8001_exec_internal_task_abort(pm8001_ha,
pm8001_dev, pm8001_dev->sas_device, 1, tag);
if (ret)
goto out;
ret = wait_for_completion_timeout(
&task->slow_task->completion,
PM8001_TASK_TIMEOUT * HZ);
if (!ret)
goto out;
/* 5. Set Device State as Operational */
reinit_completion(&completion);
pm8001_dev->setds_completion = &completion;
PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
pm8001_dev, 0x01);
wait_for_completion(&completion);
} else {
rc = pm8001_exec_internal_task_abort(pm8001_ha,
pm8001_dev, pm8001_dev->sas_device, 0, tag);
}
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
rc = TMF_RESP_FUNC_COMPLETE;
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
rc = pm8001_find_tag(task, &tag);
if (rc == 0) {
printk(KERN_INFO "No such tag in %s\n", __func__);
rc = TMF_RESP_FUNC_FAILED;
return rc;
}
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
}
out:
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->slow_task == &slow_task)
task->slow_task = NULL;
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (rc != TMF_RESP_FUNC_COMPLETE)
pm8001_printk("rc= %d\n", rc);
return rc;

View File

@ -263,8 +263,15 @@ struct pm8001_phy {
u8 phy_state;
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
struct completion *reset_completion;
bool port_reset_status;
bool reset_success;
};
/* port reset status */
#define PORT_RESET_SUCCESS 0x00
#define PORT_RESET_TMO 0x01
struct pm8001_device {
enum sas_device_type dev_type;
struct domain_device *sas_device;
@ -404,6 +411,8 @@ union main_cfg_table {
u32 port_recovery_timer;
u32 interrupt_reassertion_delay;
u32 fatal_n_non_fatal_dump; /* 0x28 */
u32 ila_version;
u32 inc_fw_version;
} pm80xx_tbl;
};
@ -531,6 +540,7 @@ struct pm8001_hba_info {
u32 smp_exp_mode;
const struct firmware *fw_image;
struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
u32 reset_in_progress;
};
struct pm8001_work {

View File

@ -312,6 +312,11 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
/* read port recover and reset timeout */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
/* read ILA and inactive firmware version */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
}
/**
@ -592,6 +597,12 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0xffff0000;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
PORT_RECOVERY_TIMEOUT;
if (pm8001_ha->chip_id == chip_8006) {
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=
0x0000ffff;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
0x140000;
}
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
}
@ -1478,6 +1489,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
ccb->n_elem = 0;
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
@ -1770,6 +1782,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
"task 0x%p done with io_status 0x%x resp 0x%x "
"stat 0x%x but aborted by upper layer!\n",
t, status, ts->resp, ts->stat));
if (t->slow_task)
complete(&t->slow_task->completion);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@ -3033,10 +3047,10 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct pm8001_port *port = &pm8001_ha->port[port_id];
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
u32 port_sata = (phy->phy_type & PORT_TYPE_SATA);
port->port_state = portstate;
phy->identify.device_type = 0;
phy->phy_attached = 0;
memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
switch (portstate) {
case PORT_VALID:
break;
@ -3045,7 +3059,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk(" PortInvalid portID %d\n", port_id));
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" Last phy Down and port invalid\n"));
if (phy->phy_type & PORT_TYPE_SATA) {
if (port_sata) {
phy->phy_type = 0;
port->port_attached = 0;
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
@ -3067,7 +3081,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk(" Phy Down and PORT_LOSTCOMM\n"));
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" Last phy Down and port invalid\n"));
if (phy->phy_type & PORT_TYPE_SATA) {
if (port_sata) {
port->port_attached = 0;
phy->phy_type = 0;
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
@ -3083,6 +3097,11 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
}
if (port_sata && (portstate != PORT_IN_RESET)) {
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
}
}
static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
@ -3185,12 +3204,14 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
case HW_EVENT_PHY_DOWN:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_PHY_DOWN\n"));
if (phy->phy_type & PORT_TYPE_SATA)
sas_ha->notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
hw_event_phy_down(pm8001_ha, piomb);
if (pm8001_ha->reset_in_progress) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("Reset in progress\n"));
return 0;
}
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
break;
case HW_EVENT_PORT_INVALID:
PM8001_MSG_DBG(pm8001_ha,
@ -3297,9 +3318,17 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
case HW_EVENT_PORT_RESET_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
if (pm8001_ha->phy[phy_id].reset_completion) {
pm8001_ha->phy[phy_id].port_reset_status =
PORT_RESET_TMO;
complete(pm8001_ha->phy[phy_id].reset_completion);
pm8001_ha->phy[phy_id].reset_completion = NULL;
}
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
@ -3324,6 +3353,12 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
case HW_EVENT_PORT_RESET_COMPLETE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
if (pm8001_ha->phy[phy_id].reset_completion) {
pm8001_ha->phy[phy_id].port_reset_status =
PORT_RESET_SUCCESS;
complete(pm8001_ha->phy[phy_id].reset_completion);
pm8001_ha->phy[phy_id].reset_completion = NULL;
}
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
PM8001_MSG_DBG(pm8001_ha,
@ -4389,7 +4424,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
pm8001_ha->sas_addr, SAS_ADDR_SIZE);
&pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
return ret;
@ -4496,17 +4531,20 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
{
u32 tag;
int rc;
struct local_phy_ctl_req payload;
struct inbound_queue_table *circularQ;
int ret;
u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
memset(&payload, 0, sizeof(payload));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc)
return rc;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
payload.tag = cpu_to_le32(1);
payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return ret;
return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
}
static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)

View File

@ -167,7 +167,7 @@
#define LINKMODE_AUTO (0x03 << 12)
#define LINKRATE_15 (0x01 << 8)
#define LINKRATE_30 (0x02 << 8)
#define LINKRATE_60 (0x06 << 8)
#define LINKRATE_60 (0x04 << 8)
#define LINKRATE_120 (0x08 << 8)
/* phy_profile */
@ -229,6 +229,102 @@
#define IT_NEXUS_TIMEOUT 0x7D0
#define PORT_RECOVERY_TIMEOUT ((IT_NEXUS_TIMEOUT/100) + 30)
#ifdef __LITTLE_ENDIAN_BITFIELD
struct sas_identify_frame_local {
/* Byte 0 */
u8 frame_type:4;
u8 dev_type:3;
u8 _un0:1;
/* Byte 1 */
u8 _un1;
/* Byte 2 */
union {
struct {
u8 _un20:1;
u8 smp_iport:1;
u8 stp_iport:1;
u8 ssp_iport:1;
u8 _un247:4;
};
u8 initiator_bits;
};
/* Byte 3 */
union {
struct {
u8 _un30:1;
u8 smp_tport:1;
u8 stp_tport:1;
u8 ssp_tport:1;
u8 _un347:4;
};
u8 target_bits;
};
/* Byte 4 - 11 */
u8 _un4_11[8];
/* Byte 12 - 19 */
u8 sas_addr[SAS_ADDR_SIZE];
/* Byte 20 */
u8 phy_id;
u8 _un21_27[7];
} __packed;
#elif defined(__BIG_ENDIAN_BITFIELD)
struct sas_identify_frame_local {
/* Byte 0 */
u8 _un0:1;
u8 dev_type:3;
u8 frame_type:4;
/* Byte 1 */
u8 _un1;
/* Byte 2 */
union {
struct {
u8 _un247:4;
u8 ssp_iport:1;
u8 stp_iport:1;
u8 smp_iport:1;
u8 _un20:1;
};
u8 initiator_bits;
};
/* Byte 3 */
union {
struct {
u8 _un347:4;
u8 ssp_tport:1;
u8 stp_tport:1;
u8 smp_tport:1;
u8 _un30:1;
};
u8 target_bits;
};
/* Byte 4 - 11 */
u8 _un4_11[8];
/* Byte 12 - 19 */
u8 sas_addr[SAS_ADDR_SIZE];
/* Byte 20 */
u8 phy_id;
u8 _un21_27[7];
} __packed;
#else
#error "Bitfield order not defined!"
#endif
struct mpi_msg_hdr {
__le32 header; /* Bits [11:0] - Message operation code */
/* Bits [15:12] - Message Category */
@ -248,7 +344,7 @@ struct mpi_msg_hdr {
struct phy_start_req {
__le32 tag;
__le32 ase_sh_lm_slr_phyid;
struct sas_identify_frame sas_identify; /* 28 Bytes */
struct sas_identify_frame_local sas_identify; /* 28 Bytes */
__le32 spasti;
u32 reserved[21];
} __attribute__((packed, aligned(4)));
@ -1349,6 +1445,8 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
#define MAIN_SAS_PHY_ATTR_TABLE_OFFSET 0x90 /* DWORD 0x24 */
#define MAIN_PORT_RECOVERY_TIMER 0x94 /* DWORD 0x25 */
#define MAIN_INT_REASSERTION_DELAY 0x98 /* DWORD 0x26 */
#define MAIN_MPI_ILA_RELEASE_TYPE 0xA4 /* DWORD 0x29 */
#define MAIN_MPI_INACTIVE_FW_VERSION 0XB0 /* DWORD 0x2C */
/* Gereral Status Table offset - byte offset */
#define GST_GSTLEN_MPIS_OFFSET 0x00

View File

@ -92,7 +92,6 @@ static void qedi_process_text_resp(struct qedi_ctx *qedi,
struct iscsi_text_response_hdr *cqe_text_response;
struct qedi_cmd *cmd;
int pld_len;
u32 *tmp;
cmd = (struct qedi_cmd *)task->dd_data;
task_ctx = qedi_get_task_mem(&qedi->tasks, cmd->task_id);
@ -108,7 +107,6 @@ static void qedi_process_text_resp(struct qedi_ctx *qedi,
hton24(resp_hdr_ptr->dlength,
(cqe_text_response->hdr_second_dword &
ISCSI_TEXT_RESPONSE_HDR_DATA_SEG_LEN_MASK));
tmp = (u32 *)resp_hdr_ptr->dlength;
resp_hdr_ptr->itt = build_itt(cqe->cqe_solicited.itid,
conn->session->age);
@ -196,7 +194,6 @@ static void qedi_process_tmf_resp(struct qedi_ctx *qedi,
struct iscsi_tm_rsp *resp_hdr_ptr;
struct iscsi_tm *tmf_hdr;
struct qedi_cmd *qedi_cmd = NULL;
u32 *tmp;
cqe_tmp_response = &cqe->cqe_common.iscsi_hdr.tmf_response;
@ -222,7 +219,6 @@ static void qedi_process_tmf_resp(struct qedi_ctx *qedi,
hton24(resp_hdr_ptr->dlength,
(cqe_tmp_response->hdr_second_dword &
ISCSI_TMF_RESPONSE_HDR_DATA_SEG_LEN_MASK));
tmp = (u32 *)resp_hdr_ptr->dlength;
resp_hdr_ptr->itt = build_itt(cqe->cqe_solicited.itid,
conn->session->age);
resp_hdr_ptr->statsn = cpu_to_be32(cqe_tmp_response->stat_sn);
@ -269,7 +265,6 @@ static void qedi_process_login_resp(struct qedi_ctx *qedi,
struct iscsi_login_response_hdr *cqe_login_response;
struct qedi_cmd *cmd;
int pld_len;
u32 *tmp;
cmd = (struct qedi_cmd *)task->dd_data;
@ -286,7 +281,6 @@ static void qedi_process_login_resp(struct qedi_ctx *qedi,
hton24(resp_hdr_ptr->dlength,
(cqe_login_response->hdr_second_dword &
ISCSI_LOGIN_RESPONSE_HDR_DATA_SEG_LEN_MASK));
tmp = (u32 *)resp_hdr_ptr->dlength;
resp_hdr_ptr->itt = build_itt(cqe->cqe_solicited.itid,
conn->session->age);
resp_hdr_ptr->tsih = cqe_login_response->tsih;
@ -590,7 +584,6 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi,
int datalen = 0;
struct qedi_conn *qedi_conn;
u32 iscsi_cid;
bool mark_cmd_node_deleted = false;
u8 cqe_err_bits = 0;
iscsi_cid = cqe->cqe_common.conn_id;
@ -674,7 +667,6 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi,
cmd->io_cmd_in_list = false;
list_del_init(&cmd->io_cmd);
qedi_conn->active_cmd_count--;
mark_cmd_node_deleted = true;
}
spin_unlock(&qedi_conn->list_lock);
@ -763,7 +755,7 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
u32 rtid = 0;
u32 iscsi_cid;
struct qedi_conn *qedi_conn;
struct qedi_cmd *cmd_new, *dbg_cmd;
struct qedi_cmd *dbg_cmd;
struct iscsi_task *mtask;
struct iscsi_tm *tmf_hdr = NULL;
@ -856,7 +848,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
}
qedi_conn->cmd_cleanup_cmpl++;
wake_up(&qedi_conn->wait_queue);
cmd_new = task->dd_data;
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID,
"Freeing tid=0x%x for cid=0x%x\n",
@ -1029,7 +1020,6 @@ int qedi_send_iscsi_login(struct qedi_conn *qedi_conn,
struct iscsi_task_context *fw_task_ctx;
struct qedi_ctx *qedi = qedi_conn->qedi;
struct iscsi_login_req *login_hdr;
struct scsi_sge *req_sge = NULL;
struct scsi_sge *resp_sge = NULL;
struct qedi_cmd *qedi_cmd;
struct qedi_endpoint *ep;
@ -1037,7 +1027,6 @@ int qedi_send_iscsi_login(struct qedi_conn *qedi_conn,
u16 sq_idx = 0;
int rval = 0;
req_sge = (struct scsi_sge *)qedi_conn->gen_pdu.req_bd_tbl;
resp_sge = (struct scsi_sge *)qedi_conn->gen_pdu.resp_bd_tbl;
qedi_cmd = (struct qedi_cmd *)task->dd_data;
ep = qedi_conn->ep;
@ -1718,7 +1707,6 @@ int qedi_send_iscsi_nopout(struct qedi_conn *qedi_conn,
struct qedi_ctx *qedi = qedi_conn->qedi;
struct iscsi_task_context *fw_task_ctx;
struct iscsi_nopout *nopout_hdr;
struct scsi_sge *req_sge = NULL;
struct scsi_sge *resp_sge = NULL;
struct qedi_cmd *qedi_cmd;
struct qedi_endpoint *ep;
@ -1727,7 +1715,6 @@ int qedi_send_iscsi_nopout(struct qedi_conn *qedi_conn,
u16 sq_idx = 0;
int rval = 0;
req_sge = (struct scsi_sge *)qedi_conn->gen_pdu.req_bd_tbl;
resp_sge = (struct scsi_sge *)qedi_conn->gen_pdu.resp_bd_tbl;
qedi_cmd = (struct qedi_cmd *)task->dd_data;
nopout_hdr = (struct iscsi_nopout *)task->hdr;
@ -1995,7 +1982,6 @@ void qedi_trace_io(struct qedi_ctx *qedi, struct iscsi_task *task,
struct qedi_conn *qedi_conn = conn->dd_data;
struct scsi_cmnd *sc_cmd = task->sc;
unsigned long flags;
u8 op;
spin_lock_irqsave(&qedi->io_trace_lock, flags);
@ -2005,7 +1991,6 @@ void qedi_trace_io(struct qedi_ctx *qedi, struct iscsi_task *task,
io_log->cid = qedi_conn->iscsi_conn_id;
io_log->lun = sc_cmd->device->lun;
io_log->op = sc_cmd->cmnd[0];
op = sc_cmd->cmnd[0];
io_log->lba[0] = sc_cmd->cmnd[2];
io_log->lba[1] = sc_cmd->cmnd[3];
io_log->lba[2] = sc_cmd->cmnd[4];

View File

@ -919,9 +919,9 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
sizeof(response) + sizeof(uint8_t);
fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) +
sizeof(struct fc_bsg_reply);
memcpy(fw_sts_ptr, response, sizeof(response));
fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), response,
sizeof(response));
fw_sts_ptr += sizeof(response);
*fw_sts_ptr = command_sent;
@ -1116,14 +1116,13 @@ qla84xx_mgmt_cmd(struct bsg_job *bsg_job)
return -EINVAL;
}
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (!mn) {
ql_log(ql_log_warn, vha, 0x703c,
"DMA alloc failed for fw buffer.\n");
return -ENOMEM;
}
memset(mn, 0, sizeof(struct access_chip_84xx));
mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
mn->entry_count = 1;
ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request);
@ -2554,13 +2553,11 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
ql_log(ql_log_warn, vha, 0x7089,
"mbx abort_command "
"failed.\n");
scsi_req(bsg_job->req)->result =
bsg_reply->result = -EIO;
} else {
ql_dbg(ql_dbg_user, vha, 0x708a,
"mbx abort_command "
"success.\n");
scsi_req(bsg_job->req)->result =
bsg_reply->result = 0;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
@ -2571,7 +2568,7 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
scsi_req(bsg_job->req)->result = bsg_reply->result = -ENXIO;
bsg_reply->result = -ENXIO;
return 0;
done:

View File

@ -323,6 +323,12 @@ struct els_logo_payload {
uint8_t wwpn[WWN_SIZE];
};
struct els_plogi_payload {
uint8_t opcode;
uint8_t rsvd[3];
uint8_t data[112];
};
struct ct_arg {
void *iocb;
u16 nport_handle;
@ -358,6 +364,19 @@ struct srb_iocb {
dma_addr_t els_logo_pyld_dma;
} els_logo;
struct {
#define ELS_DCMD_PLOGI 0x3
uint32_t flags;
uint32_t els_cmd;
struct completion comp;
struct els_plogi_payload *els_plogi_pyld;
struct els_plogi_payload *els_resp_pyld;
dma_addr_t els_plogi_pyld_dma;
dma_addr_t els_resp_pyld_dma;
uint32_t fw_status[3];
__le16 comp_status;
__le16 len;
} els_plogi;
struct {
/*
* Values for flags field below are as
* defined in tsk_mgmt_entry struct
@ -922,6 +941,7 @@ struct mbx_cmd_32 {
#define INTR_RSP_QUE_UPDATE_83XX 0x14
#define INTR_ATIO_QUE_UPDATE 0x1C
#define INTR_ATIO_RSP_QUE_UPDATE 0x1D
#define INTR_ATIO_QUE_UPDATE_27XX 0x1E
/* ISP mailbox loopback echo diagnostic error code */
#define MBS_LB_RESET 0x17
@ -2302,6 +2322,7 @@ typedef struct fc_port {
unsigned int send_els_logo:1;
unsigned int login_pause:1;
unsigned int login_succ:1;
unsigned int query:1;
struct work_struct nvme_del_work;
struct completion nvme_del_done;
@ -2347,6 +2368,7 @@ typedef struct fc_port {
uint8_t fc4_type;
uint8_t fc4f_nvme;
uint8_t scan_state;
uint8_t n2n_flag;
unsigned long last_queue_full;
unsigned long last_ramp_up;
@ -2368,6 +2390,9 @@ typedef struct fc_port {
struct list_head gnl_entry;
struct work_struct del_work;
u8 iocb[IOCB_SIZE];
u8 current_login_state;
u8 last_login_state;
struct completion n2n_done;
} fc_port_t;
#define QLA_FCPORT_SCAN 1
@ -4113,6 +4138,7 @@ typedef struct scsi_qla_host {
#define QPAIR_ONLINE_CHECK_NEEDED 27
#define SET_ZIO_THRESHOLD_NEEDED 28
#define DETECT_SFP_CHANGE 29
#define N2N_LOGIN_NEEDED 30
unsigned long pci_flags;
#define PFLG_DISCONNECTED 0 /* PCI device removed */
@ -4223,6 +4249,9 @@ typedef struct scsi_qla_host {
wait_queue_head_t fcport_waitQ;
wait_queue_head_t vref_waitq;
uint8_t min_link_speed_feat;
uint8_t n2n_node_name[WWN_SIZE];
uint8_t n2n_port_name[WWN_SIZE];
uint16_t n2n_id;
} scsi_qla_host_t;
struct qla27xx_image_status {

View File

@ -753,9 +753,7 @@ struct els_entry_24xx {
uint8_t reserved_2;
uint8_t port_id[3];
uint8_t reserved_3;
uint16_t reserved_4;
uint8_t s_id[3];
uint16_t control_flags; /* Control flags. */
#define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13)

View File

@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *,
port_id_t);
extern void qla2x00_update_fcports(scsi_qla_host_t *);
@ -145,6 +147,7 @@ extern int ql2xmvasynctoatio;
extern int ql2xuctrlirq;
extern int ql2xnvmeenable;
extern int ql2xautodetectsfp;
extern int ql2xenablemsix;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@ -486,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
uint16_t *);
int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
struct port_database_24xx *);
int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t,
void *, uint16_t);
extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);

View File

@ -812,13 +812,12 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
sp->gen2 = fcport->login_gen;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
ql_log(ql_log_warn, vha, 0xd043,
"Failed to allocate port database structure.\n");
goto done_free_sp;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
mb = sp->u.iocb_cmd.u.mbx.out_mb;
mb[0] = MBC_GET_PORT_DATABASE;
@ -1434,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
qla24xx_post_gpdb_work(vha, ea->fcport, 0);
break;
default:
if (ea->fcport->n2n_flag) {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post fc4 prli\n",
__func__, __LINE__, ea->fcport->port_name);
ea->fcport->fc4f_nvme = 0;
ea->fcport->n2n_flag = 0;
qla24xx_post_prli_work(vha, ea->fcport);
}
ql_dbg(ql_dbg_disc, vha, 0x2119,
"%s %d %8phC unhandle event of %x\n",
__func__, __LINE__, ea->fcport->port_name, ea->data[0]);
@ -4367,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
return (rval);
}
/*
* N2N Login
* Updates Fibre Channel Device Database with local loop devices.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
*/
static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
fc_port_t *fcport)
{
struct qla_hw_data *ha = vha->hw;
int res = QLA_SUCCESS, rval;
int greater_wwpn = 0;
int logged_in = 0;
if (ha->current_topology != ISP_CFG_N)
return res;
if (wwn_to_u64(vha->port_name) >
wwn_to_u64(vha->n2n_port_name)) {
ql_dbg(ql_dbg_disc, vha, 0x2002,
"HBA WWPN is greater %llx > target %llx\n",
wwn_to_u64(vha->port_name),
wwn_to_u64(vha->n2n_port_name));
greater_wwpn = 1;
fcport->d_id.b24 = vha->n2n_id;
}
fcport->loop_id = vha->loop_id;
fcport->fc4f_nvme = 0;
fcport->query = 1;
ql_dbg(ql_dbg_disc, vha, 0x4001,
"Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
fcport->d_id.b24, vha->loop_id);
/* Fill in member data. */
if (!greater_wwpn) {
rval = qla2x00_get_port_database(vha, fcport, 0);
ql_dbg(ql_dbg_disc, vha, 0x1051,
"Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
fcport->current_login_state, fcport->last_login_state,
fcport->d_id.b24, fcport->loop_id, rval);
if (((fcport->current_login_state & 0xf) == 0x4) ||
((fcport->current_login_state & 0xf) == 0x6))
logged_in = 1;
}
if (logged_in || greater_wwpn) {
if (!vha->nvme_local_port && vha->flags.nvme_enabled)
qla_nvme_register_hba(vha);
/* Set connected N_Port d_id */
if (vha->flags.nvme_enabled)
fcport->fc4f_nvme = 1;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
fcport->disc_state = DSC_GNL;
fcport->n2n_flag = 1;
fcport->flags = 3;
vha->hw->flags.gpsc_supported = 0;
if (greater_wwpn) {
ql_dbg(ql_dbg_disc, vha, 0x20e5,
"%s %d PLOGI ELS %8phC\n",
__func__, __LINE__, fcport->port_name);
res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
fcport, fcport->d_id);
}
if (res != QLA_SUCCESS) {
ql_log(ql_log_info, vha, 0xd04d,
"PLOGI Failed: portid=%06x - retrying\n",
fcport->d_id.b24);
res = QLA_SUCCESS;
} else {
/* State 0x6 means FCP PRLI complete */
if ((fcport->current_login_state & 0xf) == 0x6) {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post GPDB work\n",
__func__, __LINE__, fcport->port_name);
fcport->chip_reset =
vha->hw->base_qpair->chip_reset;
qla24xx_post_gpdb_work(vha, fcport, 0);
} else {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post NVMe PRLI\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_prli_work(vha, fcport);
}
}
} else {
/* Wait for next database change */
set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
}
return res;
}
/*
* qla2x00_configure_local_loop
@ -4438,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
}
}
/* Inititae N2N login. */
if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
rval = qla24xx_n2n_handle_login(vha, new_fcport);
if (rval != QLA_SUCCESS)
goto cleanup_allocation;
return QLA_SUCCESS;
}
/* Add devices to port list. */
id_iter = (char *)ha->gid_list;
for (index = 0; index < entries; index++) {
@ -4479,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
"Failed to retrieve fcport information "
"-- get_port_database=%x, loop_id=0x%04x.\n",
rval2, new_fcport->loop_id);
ql_dbg(ql_dbg_disc, vha, 0x2105,
"Scheduling resync.\n");
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
continue;
/* Skip retry if N2N */
if (ha->current_topology != ISP_CFG_N) {
ql_dbg(ql_dbg_disc, vha, 0x2105,
"Scheduling resync.\n");
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
continue;
}
}
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
@ -7555,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
icb->firmware_options_3 |= BIT_0;
if (IS_QLA27XX(ha)) {
icb->firmware_options_3 |= BIT_8;
ql_dbg(ql_log_info, vha, 0x0075,
"Enabling direct connection.\n");
}
if (rval) {
ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n");
@ -7910,7 +8036,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
return NULL;
}
if (ql2xmqsupport) {
if (ql2xmqsupport || ql2xnvmeenable) {
qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
if (qpair == NULL) {
ql_log(ql_log_warn, vha, 0x0182,

View File

@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{
scsi_qla_host_t *vha = sp->vha;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
uint32_t dsd_len = 24;
els_iocb->entry_type = ELS_IOCB_TYPE;
els_iocb->entry_count = 1;
@ -2534,23 +2535,197 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
els_iocb->port_id[1] = sp->fcport->d_id.b.area;
els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
els_iocb->s_id[0] = vha->d_id.b.al_pa;
els_iocb->s_id[1] = vha->d_id.b.area;
els_iocb->s_id[2] = vha->d_id.b.domain;
els_iocb->control_flags = 0;
els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
els_iocb->tx_address[0] =
cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_address[1] =
cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
els_iocb->tx_byte_count = sizeof(struct els_plogi_payload);
els_iocb->tx_address[0] =
cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
els_iocb->tx_address[1] =
cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
els_iocb->tx_len = dsd_len;
els_iocb->rx_byte_count = 0;
els_iocb->rx_address[0] = 0;
els_iocb->rx_address[1] = 0;
els_iocb->rx_len = 0;
els_iocb->rx_dsd_count = 1;
els_iocb->rx_byte_count = sizeof(struct els_plogi_payload);
els_iocb->rx_address[0] =
cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
els_iocb->rx_address[1] =
cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
els_iocb->rx_len = dsd_len;
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
"PLOGI ELS IOCB:\n");
ql_dump_buffer(ql_log_info, vha, 0x0109,
(uint8_t *)els_iocb, 0x70);
} else {
els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
els_iocb->tx_address[0] =
cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_address[1] =
cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
els_iocb->rx_byte_count = 0;
els_iocb->rx_address[0] = 0;
els_iocb->rx_address[1] = 0;
els_iocb->rx_len = 0;
}
sp->vha->qla_stats.control_requests++;
}
static void
qla2x00_els_dcmd2_sp_free(void *data)
{
srb_t *sp = data;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
if (elsio->u.els_plogi.els_plogi_pyld)
dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
elsio->u.els_plogi.els_plogi_pyld,
elsio->u.els_plogi.els_plogi_pyld_dma);
if (elsio->u.els_plogi.els_resp_pyld)
dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
elsio->u.els_plogi.els_resp_pyld,
elsio->u.els_plogi.els_resp_pyld_dma);
del_timer(&elsio->timer);
qla2x00_rel_sp(sp);
}
static void
qla2x00_els_dcmd2_iocb_timeout(void *data)
{
srb_t *sp = data;
fc_port_t *fcport = sp->fcport;
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct srb_iocb *lio = &sp->u.iocb_cmd;
unsigned long flags = 0;
int res;
ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069,
"%s hdl=%x ELS Timeout, %8phC portid=%06x\n",
sp->name, sp->handle, fcport->port_name, fcport->d_id.b24);
/* Abort the exchange */
spin_lock_irqsave(&ha->hardware_lock, flags);
res = ha->isp_ops->abort_command(sp);
ql_dbg(ql_dbg_io, vha, 0x3070,
"mbx abort_command %s\n",
(res == QLA_SUCCESS) ? "successful" : "failed");
spin_unlock_irqrestore(&ha->hardware_lock, flags);
complete(&lio->u.els_plogi.comp);
}
static void
qla2x00_els_dcmd2_sp_done(void *ptr, int res)
{
srb_t *sp = ptr;
fc_port_t *fcport = sp->fcport;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072,
"%s ELS hdl=%x, portid=%06x done %8pC\n",
sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
complete(&lio->u.els_plogi.comp);
}
int
qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
fc_port_t *fcport, port_id_t remote_did)
{
srb_t *sp;
struct srb_iocb *elsio = NULL;
struct qla_hw_data *ha = vha->hw;
int rval = QLA_SUCCESS;
void *ptr, *resp_ptr;
dma_addr_t ptr_dma;
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) {
ql_log(ql_log_info, vha, 0x70e6,
"SRB allocation failed\n");
return -ENOMEM;
}
elsio = &sp->u.iocb_cmd;
fcport->d_id.b.domain = remote_did.b.domain;
fcport->d_id.b.area = remote_did.b.area;
fcport->d_id.b.al_pa = remote_did.b.al_pa;
ql_dbg(ql_dbg_io, vha, 0x3073,
"Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
sp->type = SRB_ELS_DCMD;
sp->name = "ELS_DCMD";
sp->fcport = fcport;
qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
sp->done = qla2x00_els_dcmd2_sp_done;
sp->free = qla2x00_els_dcmd2_sp_free;
ptr = elsio->u.els_plogi.els_plogi_pyld =
dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma;
if (!elsio->u.els_plogi.els_plogi_pyld) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
resp_ptr = elsio->u.els_plogi.els_resp_pyld =
dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
&elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL);
if (!elsio->u.els_plogi.els_resp_pyld) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
memset(ptr, 0, sizeof(struct els_plogi_payload));
memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
qla24xx_get_port_login_templ(vha, ptr_dma + 4,
&elsio->u.els_plogi.els_plogi_pyld->data[0],
sizeof(struct els_plogi_payload));
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
(uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
init_completion(&elsio->u.els_plogi.comp);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
ql_dbg(ql_dbg_io, vha, 0x3074,
"%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n",
sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24);
wait_for_completion(&elsio->u.els_plogi.comp);
if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
rval = QLA_FUNCTION_FAILED;
out:
sp->free(sp);
return rval;
}
static void
qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{

View File

@ -1041,6 +1041,7 @@ global_port_update:
*/
atomic_set(&vha->loop_down_timer, 0);
if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
!ha->flags.n2n_ae &&
atomic_read(&vha->loop_state) != LOOP_DEAD) {
ql_dbg(ql_dbg_async, vha, 0x5011,
"Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
@ -1543,8 +1544,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
struct fc_bsg_reply *bsg_reply;
uint16_t comp_status;
uint32_t fw_status[3];
uint8_t* fw_sts_ptr;
int res;
struct srb_iocb *els;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
@ -1561,10 +1562,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
break;
case SRB_ELS_DCMD:
type = "Driver ELS logo";
ql_dbg(ql_dbg_user, vha, 0x5047,
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
sp->done(sp, 0);
return;
if (iocb_type != ELS_IOCB_TYPE) {
ql_dbg(ql_dbg_user, vha, 0x5047,
"Completing %s: (%p) type=%d.\n",
type, sp, sp->type);
sp->done(sp, 0);
return;
}
break;
case SRB_CT_PTHRU_CMD:
/* borrowing sts_entry_24xx.comp_status.
same location as ct_entry_24xx.comp_status
@ -1584,6 +1589,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
if (iocb_type == ELS_IOCB_TYPE) {
els = &sp->u.iocb_cmd;
els->u.els_plogi.fw_status[0] = fw_status[0];
els->u.els_plogi.fw_status[1] = fw_status[1];
els->u.els_plogi.fw_status[2] = fw_status[2];
els->u.els_plogi.comp_status = fw_status[0];
if (comp_status == CS_COMPLETE) {
res = DID_OK << 16;
} else {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
els->u.els_plogi.len =
le16_to_cpu(((struct els_sts_entry_24xx *)
pkt)->total_byte_count);
} else {
els->u.els_plogi.len = 0;
res = DID_ERROR << 16;
}
}
ql_log(ql_log_info, vha, 0x503f,
"ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
type, sp->handle, comp_status, fw_status[1], fw_status[2],
le16_to_cpu(((struct els_sts_entry_24xx *)
pkt)->total_byte_count));
goto els_ct_done;
}
/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
* fc payload to the caller
*/
@ -1604,11 +1636,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
type, sp->handle, comp_status, fw_status[1], fw_status[2],
le16_to_cpu(((struct els_sts_entry_24xx *)
pkt)->total_byte_count));
fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
sizeof(struct fc_bsg_reply);
memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
}
else {
} else {
ql_dbg(ql_dbg_user, vha, 0x5040,
"ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
"error subcode 1=0x%x error subcode 2=0x%x.\n",
@ -1619,10 +1647,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
pkt)->error_subcode_2));
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
sizeof(struct fc_bsg_reply);
memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
}
memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply),
fw_status, sizeof(fw_status));
ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
(uint8_t *)pkt, sizeof(*pkt));
}
@ -1631,6 +1658,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
bsg_job->reply_len = 0;
}
els_ct_done:
sp->done(sp, res);
}
@ -3129,6 +3157,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
case INTR_RSP_QUE_UPDATE_83XX:
qla24xx_process_response_queue(vha, rsp);
break;
case INTR_ATIO_QUE_UPDATE_27XX:
case INTR_ATIO_QUE_UPDATE:{
unsigned long flags2;
spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
@ -3259,6 +3288,7 @@ qla24xx_msix_default(int irq, void *dev_id)
case INTR_RSP_QUE_UPDATE_83XX:
qla24xx_process_response_queue(vha, rsp);
break;
case INTR_ATIO_QUE_UPDATE_27XX:
case INTR_ATIO_QUE_UPDATE:{
unsigned long flags2;
spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
@ -3347,7 +3377,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
.pre_vectors = QLA_BASE_VECTORS,
};
if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
IS_ATIO_MSIX_CAPABLE(ha)) {
desc.pre_vectors++;
min_vecs++;
}
@ -3374,7 +3405,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
ha->msix_count, ret);
ha->msix_count = ret;
/* Recalculate queue values */
if (ha->mqiobase && ql2xmqsupport) {
if (ha->mqiobase && (ql2xmqsupport || ql2xnvmeenable)) {
ha->max_req_queues = ha->msix_count - 1;
/* ATIOQ needs 1 vector. That's 1 less QPair */
@ -3432,7 +3463,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
* If target mode is enable, also request the vector for the ATIO
* queue.
*/
if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
IS_ATIO_MSIX_CAPABLE(ha)) {
qentry = &ha->msix_entries[QLA_ATIO_VECTOR];
rsp->msix = qentry;
qentry->handle = rsp;
@ -3486,11 +3518,14 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
/* If possible, enable MSI-X. */
if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
!IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLAFX00(ha) &&
!IS_QLA27XX(ha))
if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
!IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
!IS_QLAFX00(ha) && !IS_QLA27XX(ha)))
goto skip_msi;
if (ql2xenablemsix == 2)
goto skip_msix;
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
(ha->pdev->subsystem_device == 0x7040 ||
ha->pdev->subsystem_device == 0x7041 ||

View File

@ -1782,13 +1782,13 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
"Entered %s.\n", __func__);
pd24 = NULL;
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
ql_log(ql_log_warn, vha, 0x1050,
"Failed to allocate port database structure.\n");
fcport->query = 0;
return QLA_MEMORY_ALLOC_FAILED;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
mcp->mb[0] = MBC_GET_PORT_DATABASE;
if (opt != 0 && !IS_FWI2_CAPABLE(ha))
@ -1823,17 +1823,32 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
if (IS_FWI2_CAPABLE(ha)) {
uint64_t zero = 0;
u8 current_login_state, last_login_state;
pd24 = (struct port_database_24xx *) pd;
/* Check for logged in state. */
if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
pd24->last_login_state != PDS_PRLI_COMPLETE) {
ql_dbg(ql_dbg_mbx, vha, 0x1051,
"Unable to verify login-state (%x/%x) for "
"loop_id %x.\n", pd24->current_login_state,
pd24->last_login_state, fcport->loop_id);
if (fcport->fc4f_nvme) {
current_login_state = pd24->current_login_state >> 4;
last_login_state = pd24->last_login_state >> 4;
} else {
current_login_state = pd24->current_login_state & 0xf;
last_login_state = pd24->last_login_state & 0xf;
}
fcport->current_login_state = pd24->current_login_state;
fcport->last_login_state = pd24->last_login_state;
/* Check for logged in state. */
if (current_login_state != PDS_PRLI_COMPLETE &&
last_login_state != PDS_PRLI_COMPLETE) {
ql_dbg(ql_dbg_mbx, vha, 0x119a,
"Unable to verify login-state (%x/%x) for loop_id %x.\n",
current_login_state, last_login_state,
fcport->loop_id);
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
if (!fcport->query)
goto gpd_error_out;
}
if (fcport->loop_id == FC_NO_LOOP_ID ||
@ -1912,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
gpd_error_out:
dma_pool_free(ha->s_dma_pool, pd, pd_dma);
fcport->query = 0;
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1052,
@ -2255,13 +2271,12 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
else
req = ha->req_q_map[0];
lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
if (lg == NULL) {
ql_log(ql_log_warn, vha, 0x1062,
"Failed to allocate login IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(lg, 0, sizeof(struct logio_entry_24xx));
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
lg->entry_count = 1;
@ -2525,13 +2540,12 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d,
"Entered %s.\n", __func__);
lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
if (lg == NULL) {
ql_log(ql_log_warn, vha, 0x106e,
"Failed to allocate logout IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(lg, 0, sizeof(struct logio_entry_24xx));
req = vha->req;
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
@ -2820,13 +2834,12 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f,
"Entered %s.\n", __func__);
pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
pmap = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
if (pmap == NULL) {
ql_log(ql_log_warn, vha, 0x1080,
"Memory alloc failed.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(pmap, 0, FCAL_MAP_SIZE);
mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
mcp->mb[2] = MSW(pmap_dma);
@ -3014,13 +3027,12 @@ qla24xx_abort_command(srb_t *sp)
return QLA_FUNCTION_FAILED;
}
abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
if (abt == NULL) {
ql_log(ql_log_warn, vha, 0x108d,
"Failed to allocate abort IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(abt, 0, sizeof(struct abort_entry_24xx));
abt->entry_type = ABORT_IOCB_TYPE;
abt->entry_count = 1;
@ -3098,13 +3110,12 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
rsp = req->rsp;
}
tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
tsk = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
if (tsk == NULL) {
ql_log(ql_log_warn, vha, 0x1093,
"Failed to allocate task management IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(tsk, 0, sizeof(struct tsk_mgmt_cmd));
tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
tsk->p.tsk.entry_count = 1;
@ -3753,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
rptid_entry->vp_status,
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Remote WWPN %8phC.\n",
rptid_entry->u.f1.port_name);
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: WWPN %8phC.\n",
vha->port_name);
/* N2N. direct connect */
if (IS_QLA27XX(ha) &&
((rptid_entry->u.f1.flags>>1) & 0x7) == 2) {
/* if our portname is higher then initiate N2N login */
if (wwn_to_u64(vha->port_name) >
wwn_to_u64(rptid_entry->u.f1.port_name)) {
// ??? qlt_update_host_map(vha, id);
vha->n2n_id = 0x1;
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Setting n2n_update_needed for id %d\n",
vha->n2n_id);
} else {
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Remote login - Waiting for WWPN %8phC.\n",
rptid_entry->u.f1.port_name);
}
memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name,
WWN_SIZE);
set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
return;
}
/* buffer to buffer credit flag */
vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
@ -3856,14 +3899,13 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb,
"Entered %s.\n", __func__);
vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
vpmod = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
if (!vpmod) {
ql_log(ql_log_warn, vha, 0x10bc,
"Failed to allocate modify VP IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(vpmod, 0, sizeof(struct vp_config_entry_24xx));
vpmod->entry_type = VP_CONFIG_IOCB_TYPE;
vpmod->entry_count = 1;
vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS;
@ -3934,13 +3976,12 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
return QLA_PARAMETER_ERROR;
vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
vce = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
if (!vce) {
ql_log(ql_log_warn, vha, 0x10c2,
"Failed to allocate VP control IOCB.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx));
vce->entry_type = VP_CTRL_IOCB_TYPE;
vce->entry_count = 1;
@ -4592,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
return rval;
}
int
qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
void *buf, uint16_t bufsiz)
{
int rval, i;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint32_t *bp;
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_RNID_PARAMS;
mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8;
mcp->mb[2] = MSW(buf_dma);
mcp->mb[3] = LSW(buf_dma);
mcp->mb[6] = MSW(MSD(buf_dma));
mcp->mb[7] = LSW(MSD(buf_dma));
mcp->mb[8] = bufsiz/4;
mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x115a,
"Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
"Done %s.\n", __func__);
bp = (uint32_t *) buf;
for (i = 0; i < (bufsiz-4)/4; i++, bp++)
*bp = cpu_to_be32(*bp);
}
return rval;
}
static int
qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
{
@ -6025,13 +6108,12 @@ int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
if (!vha->hw->flags.fw_started)
goto done;
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
ql_log(ql_log_warn, vha, 0xd047,
"Failed to allocate port database structure.\n");
goto done_free_sp;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
memset(&mc, 0, sizeof(mc));
mc.mb[0] = MBC_GET_PORT_DATABASE;

View File

@ -606,7 +606,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qpair, *tqpair;
if (ql2xmqsupport) {
if (ql2xmqsupport || ql2xnvmeenable) {
list_for_each_entry_safe(qpair, tqpair, &vha->qp_list,
qp_list_elem)
qla2xxx_delete_qpair(vha, qpair);

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