mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
SCSI misc on 20221007
Updates to the usual drivers (qla2xxx, lpfc, ufs, hisi_sas, mpi3mr, mpt3sas, target); the biggest change (from my biased viewpoint) being that the mpi3mr now attached to the SAS transport class, making it the first fusion type device to do so. Beyond the usual bug fixing and security class reworks, there aren't a huge number of core changes. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCY0B74yYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishW2NAP9CPp2R 7NRmSyxcyVYvtCNUW3WxXh65Gn+KgArmg8XucgEAhUBX1fSjOzpERWEU+UaXitbE Rb+FbjxSc5YxR+nJ/Qc= =0Wlp -----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: "Updates to the usual drivers (qla2xxx, lpfc, ufs, hisi_sas, mpi3mr, mpt3sas, target). The biggest change (from my biased viewpoint) being that the mpi3mr now attached to the SAS transport class, making it the first fusion type device to do so. Beyond the usual bug fixing and security class reworks, there aren't a huge number of core changes" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (141 commits) scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername() scsi: mpi3mr: Remove unnecessary cast scsi: stex: Properly zero out the passthrough command structure scsi: mpi3mr: Update driver version to 8.2.0.3.0 scsi: mpi3mr: Fix scheduling while atomic type bug scsi: mpi3mr: Scan the devices during resume time scsi: mpi3mr: Free enclosure objects during driver unload scsi: mpi3mr: Handle 0xF003 Fault Code scsi: mpi3mr: Graceful handling of surprise removal of PCIe HBA scsi: mpi3mr: Schedule IRQ kthreads only on non-RT kernels scsi: mpi3mr: Support new power management framework scsi: mpi3mr: Update mpi3 header files scsi: mpt3sas: Revert "scsi: mpt3sas: Fix ioc->base_readl() use" scsi: mpt3sas: Revert "scsi: mpt3sas: Fix writel() use" scsi: wd33c93: Remove dead code related to the long-gone config WD33C93_PIO scsi: core: Add I/O timeout count for SCSI device scsi: qedf: Populate sysfs attributes for vport scsi: pm8001: Replace one-element array with flexible-array member scsi: 3w-xxxx: Replace one-element array with flexible-array member scsi: hptiop: Replace one-element array with flexible-array member in struct hpt_iop_request_ioctl_command() ...
This commit is contained in:
commit
62e6e5940c
@ -1417,6 +1417,15 @@ Description: This node is used to set or display whether UFS WriteBooster is
|
||||
platform that doesn't support UFSHCD_CAP_CLK_SCALING, we can
|
||||
disable/enable WriteBooster through this sysfs node.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/enable_wb_buf_flush
|
||||
What: /sys/bus/platform/devices/*.ufs/enable_wb_buf_flush
|
||||
Date: July 2022
|
||||
Contact: Jinyoung Choi <j-young.choi@samsung.com>
|
||||
Description: This entry shows the status of WriteBooster buffer flushing
|
||||
and it can be used to enable or disable the flushing.
|
||||
If flushing is enabled, the device executes the flush
|
||||
operation when the command queue is empty.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/hpb_version
|
||||
What: /sys/bus/platform/devices/*.ufs/device_descriptor/hpb_version
|
||||
Date: June 2021
|
||||
@ -1591,6 +1600,43 @@ Description: This entry shows the status of HPB.
|
||||
|
||||
The file is read only.
|
||||
|
||||
Contact: Daniil Lunev <dlunev@chromium.org>
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/capabilities/
|
||||
What: /sys/bus/platform/devices/*.ufs/capabilities/
|
||||
Date: August 2022
|
||||
Description: The group represents the effective capabilities of the
|
||||
host-device pair. i.e. the capabilities which are enabled in the
|
||||
driver for the specific host controller, supported by the host
|
||||
controller and are supported and/or have compatible
|
||||
configuration on the device side.
|
||||
|
||||
Contact: Daniil Lunev <dlunev@chromium.org>
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/capabilities/clock_scaling
|
||||
What: /sys/bus/platform/devices/*.ufs/capabilities/clock_scaling
|
||||
Date: August 2022
|
||||
Contact: Daniil Lunev <dlunev@chromium.org>
|
||||
Description: Indicates status of clock scaling.
|
||||
|
||||
== ============================
|
||||
0 Clock scaling is not supported.
|
||||
1 Clock scaling is supported.
|
||||
== ============================
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/capabilities/write_booster
|
||||
What: /sys/bus/platform/devices/*.ufs/capabilities/write_booster
|
||||
Date: August 2022
|
||||
Contact: Daniil Lunev <dlunev@chromium.org>
|
||||
Description: Indicates status of Write Booster.
|
||||
|
||||
== ============================
|
||||
0 Write Booster can not be enabled.
|
||||
1 Write Booster can be enabled.
|
||||
== ============================
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/hpb_param_sysfs/activation_thld
|
||||
Date: February 2021
|
||||
Contact: Avri Altman <avri.altman@wdc.com>
|
||||
|
@ -401,7 +401,7 @@ Changes from 20041213 to 20041220
|
||||
structure.
|
||||
* Integrated patch from Christoph Hellwig <hch@lst.de> Kill
|
||||
compile warnings on 64 bit platforms: %variables for %llx format
|
||||
specifiers must be caste to long long because %(u)int64_t can
|
||||
specifiers must be cast to long long because %(u)int64_t can
|
||||
just be long on 64bit platforms.
|
||||
* Integrated patch from Christoph Hellwig <hch@lst.de> Removes
|
||||
dead code.
|
||||
|
@ -620,7 +620,6 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
mpt_ioctl_header __user *uhdr = (void __user *) arg;
|
||||
mpt_ioctl_header khdr;
|
||||
int iocnum;
|
||||
unsigned iocnumX;
|
||||
int nonblock = (file->f_flags & O_NONBLOCK);
|
||||
int ret;
|
||||
@ -634,12 +633,11 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
ret = -ENXIO; /* (-6) No such device or address */
|
||||
|
||||
/* Verify intended MPT adapter - set iocnum and the adapter
|
||||
/* Verify intended MPT adapter - set iocnumX and the adapter
|
||||
* pointer (iocp)
|
||||
*/
|
||||
iocnumX = khdr.iocnum & 0xFF;
|
||||
if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
|
||||
(iocp == NULL))
|
||||
if ((mpt_verify_adapter(iocnumX, &iocp) < 0) || (iocp == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
if (!iocp->active) {
|
||||
|
@ -2006,7 +2006,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
|
||||
retval = pci_enable_device(pdev);
|
||||
if (retval) {
|
||||
TW_PRINTK(host, TW_DRIVER, 0x34, "Failed to enable pci device");
|
||||
goto out_disable_device;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
@ -912,7 +912,7 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
||||
data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
|
||||
|
||||
/* Now allocate ioctl buf memory */
|
||||
cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle, GFP_KERNEL);
|
||||
cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted + sizeof(TW_New_Ioctl), &dma_handle, GFP_KERNEL);
|
||||
if (cpu_addr == NULL) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
@ -921,7 +921,7 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
||||
tw_ioctl = (TW_New_Ioctl *)cpu_addr;
|
||||
|
||||
/* Now copy down the entire ioctl */
|
||||
if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1))
|
||||
if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl)))
|
||||
goto out2;
|
||||
|
||||
passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
|
||||
@ -966,15 +966,15 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
||||
/* Load the sg list */
|
||||
switch (TW_SGL_OUT(tw_ioctl->firmware_command.opcode__sgloffset)) {
|
||||
case 2:
|
||||
tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
|
||||
tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl);
|
||||
tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
|
||||
break;
|
||||
case 3:
|
||||
tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
|
||||
tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl);
|
||||
tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
|
||||
break;
|
||||
case 5:
|
||||
passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
|
||||
passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl);
|
||||
passthru->sg_list[0].length = data_buffer_length_adjusted;
|
||||
break;
|
||||
}
|
||||
@ -1017,12 +1017,12 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
||||
}
|
||||
|
||||
/* Now copy the response to userspace */
|
||||
if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1))
|
||||
if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length))
|
||||
goto out2;
|
||||
retval = 0;
|
||||
out2:
|
||||
/* Now free ioctl buf memory */
|
||||
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
|
||||
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted + sizeof(TW_New_Ioctl), cpu_addr, dma_handle);
|
||||
out:
|
||||
mutex_unlock(&tw_dev->ioctl_lock);
|
||||
mutex_unlock(&tw_mutex);
|
||||
|
@ -348,7 +348,7 @@ typedef struct TAG_TW_New_Ioctl {
|
||||
unsigned int data_buffer_length;
|
||||
unsigned char padding [508];
|
||||
TW_Command firmware_command;
|
||||
char data_buffer[1];
|
||||
char data_buffer[];
|
||||
} TW_New_Ioctl;
|
||||
|
||||
/* GetParam descriptor */
|
||||
|
@ -2,9 +2,10 @@
|
||||
menu "SCSI device support"
|
||||
|
||||
config SCSI_MOD
|
||||
tristate
|
||||
default y if SCSI=n || SCSI=y
|
||||
default m if SCSI=m
|
||||
tristate
|
||||
default y if SCSI=n || SCSI=y
|
||||
default m if SCSI=m
|
||||
depends on BLOCK
|
||||
|
||||
config RAID_ATTRS
|
||||
tristate "RAID Transport Class"
|
||||
|
@ -194,7 +194,7 @@ struct ahd_linux_iocell_opts
|
||||
#define AIC79XX_PRECOMP_INDEX 0
|
||||
#define AIC79XX_SLEWRATE_INDEX 1
|
||||
#define AIC79XX_AMPLITUDE_INDEX 2
|
||||
static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
|
||||
static struct ahd_linux_iocell_opts aic79xx_iocell_info[] __ro_after_init =
|
||||
{
|
||||
AIC79XX_DEFAULT_IOOPTS,
|
||||
AIC79XX_DEFAULT_IOOPTS,
|
||||
|
@ -1366,9 +1366,9 @@ csio_show_hw_state(struct device *dev,
|
||||
struct csio_hw *hw = csio_lnode_to_hw(ln);
|
||||
|
||||
if (csio_is_hw_ready(hw))
|
||||
return snprintf(buf, PAGE_SIZE, "ready\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "not ready\n");
|
||||
return sysfs_emit(buf, "ready\n");
|
||||
|
||||
return sysfs_emit(buf, "not ready\n");
|
||||
}
|
||||
|
||||
/* Device reset */
|
||||
@ -1430,7 +1430,7 @@ csio_show_dbg_level(struct device *dev,
|
||||
{
|
||||
struct csio_lnode *ln = shost_priv(class_to_shost(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", ln->params.log_level);
|
||||
return sysfs_emit(buf, "%x\n", ln->params.log_level);
|
||||
}
|
||||
|
||||
/* Store debug level */
|
||||
@ -1476,7 +1476,7 @@ csio_show_num_reg_rnodes(struct device *dev,
|
||||
{
|
||||
struct csio_lnode *ln = shost_priv(class_to_shost(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ln->num_reg_rnodes);
|
||||
return sysfs_emit(buf, "%d\n", ln->num_reg_rnodes);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(num_reg_rnodes, S_IRUGO, csio_show_num_reg_rnodes, NULL);
|
||||
|
@ -132,7 +132,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
|
||||
break;
|
||||
case SISL_AFU_RC_OUT_OF_DATA_BUFS:
|
||||
/* Retry */
|
||||
scp->result = (DID_ALLOC_FAILURE << 16);
|
||||
scp->result = (DID_ERROR << 16);
|
||||
break;
|
||||
default:
|
||||
scp->result = (DID_ERROR << 16);
|
||||
|
@ -831,6 +831,7 @@ struct __packed atto_hba_trace {
|
||||
u32 total_length;
|
||||
u32 trace_mask;
|
||||
u8 reserved2[48];
|
||||
u8 contents[];
|
||||
};
|
||||
|
||||
#define ATTO_FUNC_SCSI_PASS_THRU 0x04
|
||||
|
@ -947,10 +947,9 @@ static int hba_ioctl_callback(struct esas2r_adapter *a,
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(trc + 1,
|
||||
memcpy(trc->contents,
|
||||
a->fw_coredump_buff + offset,
|
||||
len);
|
||||
|
||||
hi->data_length = len;
|
||||
} else if (trc->trace_func == ATTO_TRC_TF_RESET) {
|
||||
memset(a->fw_coredump_buff, 0,
|
||||
|
@ -649,6 +649,7 @@ extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
|
||||
int enable);
|
||||
extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy,
|
||||
gfp_t gfp_flags);
|
||||
extern void hisi_sas_phy_bcast(struct hisi_sas_phy *phy);
|
||||
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
|
||||
struct sas_task *task,
|
||||
struct hisi_sas_slot *slot);
|
||||
|
@ -1341,6 +1341,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
|
||||
|
||||
static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
|
||||
struct asd_sas_port *_sas_port = NULL;
|
||||
int phy_no;
|
||||
|
||||
@ -1369,6 +1370,12 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
|
||||
hisi_sas_phy_down(hisi_hba, phy_no, 0, GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Ensure any bcast events are processed prior to calling async nexus
|
||||
* reset calls from hisi_sas_clear_nexus_ha() ->
|
||||
* hisi_sas_async_I_T_nexus_reset()
|
||||
*/
|
||||
sas_drain_work(sas_ha);
|
||||
}
|
||||
|
||||
static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
|
||||
@ -1527,9 +1534,9 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
|
||||
clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags);
|
||||
return rc;
|
||||
}
|
||||
clear_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags);
|
||||
|
||||
hisi_sas_controller_reset_done(hisi_hba);
|
||||
clear_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags);
|
||||
dev_info(dev, "controller reset complete\n");
|
||||
|
||||
return 0;
|
||||
@ -1816,12 +1823,14 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
|
||||
struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
|
||||
HISI_SAS_DECLARE_RST_WORK_ON_STACK(r);
|
||||
ASYNC_DOMAIN_EXCLUSIVE(async);
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
queue_work(hisi_hba->wq, &r.work);
|
||||
wait_for_completion(r.completion);
|
||||
if (!r.done)
|
||||
return TMF_RESP_FUNC_FAILED;
|
||||
if (!r.done) {
|
||||
ret = TMF_RESP_FUNC_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
|
||||
struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
|
||||
@ -1838,7 +1847,9 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
|
||||
async_synchronize_full_domain(&async);
|
||||
hisi_sas_release_tasks(hisi_hba);
|
||||
|
||||
return TMF_RESP_FUNC_COMPLETE;
|
||||
ret = TMF_RESP_FUNC_COMPLETE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hisi_sas_query_task(struct sas_task *task)
|
||||
@ -1982,6 +1993,22 @@ 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_phy_bcast(struct hisi_sas_phy *phy)
|
||||
{
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
struct hisi_hba *hisi_hba = phy->hisi_hba;
|
||||
struct sas_ha_struct *sha = &hisi_hba->sha;
|
||||
|
||||
if (test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags))
|
||||
return;
|
||||
|
||||
if (test_bit(SAS_HA_FROZEN, &sha->state))
|
||||
return;
|
||||
|
||||
sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, GFP_ATOMIC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_phy_bcast);
|
||||
|
||||
void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i;
|
||||
|
@ -1412,9 +1412,7 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags))
|
||||
sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
|
||||
GFP_ATOMIC);
|
||||
hisi_sas_phy_bcast(phy);
|
||||
|
||||
end:
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
|
||||
|
@ -2811,15 +2811,12 @@ static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
|
||||
static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
u32 bcast_status;
|
||||
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
|
||||
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
|
||||
if ((bcast_status & RX_BCAST_CHG_MSK) &&
|
||||
!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags))
|
||||
sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
|
||||
GFP_ATOMIC);
|
||||
if (bcast_status & RX_BCAST_CHG_MSK)
|
||||
hisi_sas_phy_bcast(phy);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
|
||||
CHL_INT0_SL_RX_BCST_ACK_MSK);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
|
||||
|
@ -1626,15 +1626,12 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
u32 bcast_status;
|
||||
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
|
||||
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
|
||||
if ((bcast_status & RX_BCAST_CHG_MSK) &&
|
||||
!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags))
|
||||
sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
|
||||
GFP_ATOMIC);
|
||||
if (bcast_status & RX_BCAST_CHG_MSK)
|
||||
hisi_sas_phy_bcast(phy);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
|
||||
CHL_INT0_SL_RX_BCST_ACK_MSK);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
|
||||
@ -2786,7 +2783,6 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
|
||||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||
int ret = hisi_sas_slave_configure(sdev);
|
||||
struct device *dev = hisi_hba->dev;
|
||||
unsigned int max_sectors;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2802,12 +2798,6 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set according to IOMMU IOVA caching limit */
|
||||
max_sectors = min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
|
||||
(PAGE_SIZE * 32) >> SECTOR_SHIFT);
|
||||
|
||||
blk_queue_max_hw_sectors(sdev->request_queue, max_sectors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6233,8 +6233,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
|
||||
offset = (i + 1) % HPSA_NRESERVED_CMDS;
|
||||
continue;
|
||||
}
|
||||
set_bit(i & (BITS_PER_LONG - 1),
|
||||
h->cmd_pool_bits + (i / BITS_PER_LONG));
|
||||
set_bit(i, h->cmd_pool_bits);
|
||||
break; /* it's ours now. */
|
||||
}
|
||||
hpsa_cmd_partial_init(h, i, c);
|
||||
@ -6261,8 +6260,7 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c)
|
||||
int i;
|
||||
|
||||
i = c - h->cmd_pool;
|
||||
clear_bit(i & (BITS_PER_LONG - 1),
|
||||
h->cmd_pool_bits + (i / BITS_PER_LONG));
|
||||
clear_bit(i, h->cmd_pool_bits);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8030,7 +8028,7 @@ out_disable:
|
||||
|
||||
static void hpsa_free_cmd_pool(struct ctlr_info *h)
|
||||
{
|
||||
kfree(h->cmd_pool_bits);
|
||||
bitmap_free(h->cmd_pool_bits);
|
||||
h->cmd_pool_bits = NULL;
|
||||
if (h->cmd_pool) {
|
||||
dma_free_coherent(&h->pdev->dev,
|
||||
@ -8052,9 +8050,7 @@ static void hpsa_free_cmd_pool(struct ctlr_info *h)
|
||||
|
||||
static int hpsa_alloc_cmd_pool(struct ctlr_info *h)
|
||||
{
|
||||
h->cmd_pool_bits = kcalloc(DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG),
|
||||
sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
h->cmd_pool_bits = bitmap_zalloc(h->nr_cmds, GFP_KERNEL);
|
||||
h->cmd_pool = dma_alloc_coherent(&h->pdev->dev,
|
||||
h->nr_cmds * sizeof(*h->cmd_pool),
|
||||
&h->cmd_pool_dhandle, GFP_KERNEL);
|
||||
|
@ -1044,10 +1044,7 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp)
|
||||
req->channel = scp->device->channel;
|
||||
req->target = scp->device->id;
|
||||
req->lun = scp->device->lun;
|
||||
req->header.size = cpu_to_le32(
|
||||
sizeof(struct hpt_iop_request_scsi_command)
|
||||
- sizeof(struct hpt_iopsg)
|
||||
+ sg_count * sizeof(struct hpt_iopsg));
|
||||
req->header.size = cpu_to_le32(struct_size(req, sg_list, sg_count));
|
||||
|
||||
memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
|
||||
hba->ops->post_req(hba, _req);
|
||||
@ -1397,8 +1394,8 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
|
||||
host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
|
||||
host->max_cmd_len = 16;
|
||||
|
||||
req_size = sizeof(struct hpt_iop_request_scsi_command)
|
||||
+ sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
|
||||
req_size = struct_size((struct hpt_iop_request_scsi_command *)0,
|
||||
sg_list, hba->max_sg_descriptors);
|
||||
if ((req_size & 0x1f) != 0)
|
||||
req_size = (req_size + 0x1f) & ~0x1f;
|
||||
|
||||
|
@ -228,7 +228,7 @@ struct hpt_iop_request_scsi_command {
|
||||
u8 pad1;
|
||||
u8 cdb[16];
|
||||
__le32 dataxfer_length;
|
||||
struct hpt_iopsg sg_list[1];
|
||||
struct hpt_iopsg sg_list[];
|
||||
};
|
||||
|
||||
struct hpt_iop_request_ioctl_command {
|
||||
@ -237,7 +237,7 @@ struct hpt_iop_request_ioctl_command {
|
||||
__le32 inbuf_size;
|
||||
__le32 outbuf_size;
|
||||
__le32 bytes_returned;
|
||||
u8 buf[1];
|
||||
u8 buf[];
|
||||
/* out data should be put at buf[(inbuf_size+3)&~3] */
|
||||
};
|
||||
|
||||
|
@ -444,7 +444,7 @@ static void ibmvscsis_disconnect(struct work_struct *work)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Can transition from this state to to unconfiguring
|
||||
* Can transition from this state to unconfiguring
|
||||
* or err disconnect.
|
||||
*/
|
||||
case ERR_DISCONNECT_RECONNECT:
|
||||
|
@ -1166,7 +1166,7 @@ static void tulip_scsi(struct initio_host * host)
|
||||
return;
|
||||
}
|
||||
if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */
|
||||
if ((scb = host->active) != NULL)
|
||||
if (host->active)
|
||||
initio_next_state(host);
|
||||
return;
|
||||
}
|
||||
|
@ -595,6 +595,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
|
||||
INIT_WORK(&conn->recvwork, iscsi_sw_tcp_recv_data_work);
|
||||
tcp_sw_conn->queue_recv = iscsi_recv_from_iscsi_q;
|
||||
|
||||
mutex_init(&tcp_sw_conn->sock_lock);
|
||||
|
||||
tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
goto free_conn;
|
||||
@ -629,11 +631,15 @@ free_conn:
|
||||
|
||||
static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
||||
struct socket *sock = tcp_sw_conn->sock;
|
||||
|
||||
/*
|
||||
* The iscsi transport class will make sure we are not called in
|
||||
* parallel with start, stop, bind and destroys. However, this can be
|
||||
* called twice if userspace does a stop then a destroy.
|
||||
*/
|
||||
if (!sock)
|
||||
return;
|
||||
|
||||
@ -649,9 +655,9 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
|
||||
|
||||
iscsi_suspend_rx(conn);
|
||||
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
mutex_lock(&tcp_sw_conn->sock_lock);
|
||||
tcp_sw_conn->sock = NULL;
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
sockfd_put(sock);
|
||||
}
|
||||
|
||||
@ -703,7 +709,6 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
|
||||
int is_leading)
|
||||
{
|
||||
struct iscsi_session *session = cls_session->dd_data;
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
||||
@ -723,10 +728,10 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
if (err)
|
||||
goto free_socket;
|
||||
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
mutex_lock(&tcp_sw_conn->sock_lock);
|
||||
/* bind iSCSI connection and socket */
|
||||
tcp_sw_conn->sock = sock;
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
|
||||
/* setup Socket parameters */
|
||||
sk = sock->sk;
|
||||
@ -763,8 +768,15 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
|
||||
break;
|
||||
case ISCSI_PARAM_DATADGST_EN:
|
||||
iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
|
||||
mutex_lock(&tcp_sw_conn->sock_lock);
|
||||
if (!tcp_sw_conn->sock) {
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
tcp_sw_conn->sendpage = conn->datadgst_en ?
|
||||
sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
break;
|
||||
case ISCSI_PARAM_MAX_R2T:
|
||||
return iscsi_tcp_set_max_r2t(conn, buf);
|
||||
@ -779,8 +791,8 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn;
|
||||
struct iscsi_tcp_conn *tcp_conn;
|
||||
struct sockaddr_in6 addr;
|
||||
struct socket *sock;
|
||||
int rc;
|
||||
@ -790,21 +802,36 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
||||
case ISCSI_PARAM_CONN_ADDRESS:
|
||||
case ISCSI_PARAM_LOCAL_PORT:
|
||||
spin_lock_bh(&conn->session->frwd_lock);
|
||||
if (!tcp_sw_conn || !tcp_sw_conn->sock) {
|
||||
if (!conn->session->leadconn) {
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
sock = tcp_sw_conn->sock;
|
||||
sock_hold(sock->sk);
|
||||
/*
|
||||
* The conn has been setup and bound, so just grab a ref
|
||||
* incase a destroy runs while we are in the net layer.
|
||||
*/
|
||||
iscsi_get_conn(conn->cls_conn);
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
|
||||
tcp_conn = conn->dd_data;
|
||||
tcp_sw_conn = tcp_conn->dd_data;
|
||||
|
||||
mutex_lock(&tcp_sw_conn->sock_lock);
|
||||
sock = tcp_sw_conn->sock;
|
||||
if (!sock) {
|
||||
rc = -ENOTCONN;
|
||||
goto sock_unlock;
|
||||
}
|
||||
|
||||
if (param == ISCSI_PARAM_LOCAL_PORT)
|
||||
rc = kernel_getsockname(sock,
|
||||
(struct sockaddr *)&addr);
|
||||
else
|
||||
rc = kernel_getpeername(sock,
|
||||
(struct sockaddr *)&addr);
|
||||
sock_put(sock->sk);
|
||||
sock_unlock:
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
iscsi_put_conn(conn->cls_conn);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
@ -842,17 +869,21 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
|
||||
}
|
||||
tcp_conn = conn->dd_data;
|
||||
tcp_sw_conn = tcp_conn->dd_data;
|
||||
sock = tcp_sw_conn->sock;
|
||||
if (!sock) {
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
sock_hold(sock->sk);
|
||||
/*
|
||||
* The conn has been setup and bound, so just grab a ref
|
||||
* incase a destroy runs while we are in the net layer.
|
||||
*/
|
||||
iscsi_get_conn(conn->cls_conn);
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
|
||||
rc = kernel_getsockname(sock,
|
||||
(struct sockaddr *)&addr);
|
||||
sock_put(sock->sk);
|
||||
mutex_lock(&tcp_sw_conn->sock_lock);
|
||||
sock = tcp_sw_conn->sock;
|
||||
if (!sock)
|
||||
rc = -ENOTCONN;
|
||||
else
|
||||
rc = kernel_getsockname(sock, (struct sockaddr *)&addr);
|
||||
mutex_unlock(&tcp_sw_conn->sock_lock);
|
||||
iscsi_put_conn(conn->cls_conn);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
|
@ -28,6 +28,9 @@ struct iscsi_sw_tcp_send {
|
||||
|
||||
struct iscsi_sw_tcp_conn {
|
||||
struct socket *sock;
|
||||
/* Taken when accessing the sock from the netlink/sysfs interface */
|
||||
struct mutex sock_lock;
|
||||
|
||||
struct work_struct recvwork;
|
||||
bool queue_recv;
|
||||
|
||||
|
@ -67,7 +67,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
|
||||
res = i->dft->lldd_execute_task(task, GFP_KERNEL);
|
||||
|
||||
if (res) {
|
||||
del_timer(&task->slow_task->timer);
|
||||
del_timer_sync(&task->slow_task->timer);
|
||||
pr_notice("executing SMP task failed:%d\n", res);
|
||||
break;
|
||||
}
|
||||
|
@ -68,8 +68,6 @@ struct lpfc_sli2_slim;
|
||||
#define LPFC_MIN_TGT_QDEPTH 10
|
||||
#define LPFC_MAX_TGT_QDEPTH 0xFFFF
|
||||
|
||||
#define LPFC_MAX_BUCKET_COUNT 20 /* Maximum no. of buckets for stat data
|
||||
collection. */
|
||||
/*
|
||||
* Following time intervals are used of adjusting SCSI device
|
||||
* queue depths when there are driver resource error or Firmware
|
||||
@ -405,6 +403,7 @@ struct lpfc_trunk_link {
|
||||
link1,
|
||||
link2,
|
||||
link3;
|
||||
u32 phy_lnk_speed;
|
||||
};
|
||||
|
||||
/* Format of congestion module parameters */
|
||||
@ -732,8 +731,6 @@ struct lpfc_vport {
|
||||
struct lpfc_debugfs_trc *disc_trc;
|
||||
atomic_t disc_trc_cnt;
|
||||
#endif
|
||||
uint8_t stat_data_enabled;
|
||||
uint8_t stat_data_blocked;
|
||||
struct list_head rcv_buffer_list;
|
||||
unsigned long rcv_buffer_time_stamp;
|
||||
uint32_t vport_flag;
|
||||
@ -1436,13 +1433,6 @@ struct lpfc_hba {
|
||||
*/
|
||||
#define QUE_BUFTAG_BIT (1<<31)
|
||||
uint32_t buffer_tag_count;
|
||||
/* data structure used for latency data collection */
|
||||
#define LPFC_NO_BUCKET 0
|
||||
#define LPFC_LINEAR_BUCKET 1
|
||||
#define LPFC_POWER2_BUCKET 2
|
||||
uint8_t bucket_type;
|
||||
uint32_t bucket_base;
|
||||
uint32_t bucket_step;
|
||||
|
||||
/* Maximum number of events that can be outstanding at any time*/
|
||||
#define LPFC_MAX_EVT_COUNT 512
|
||||
@ -1564,16 +1554,13 @@ struct lpfc_hba {
|
||||
/* cgn_reg_signal and cgn_init_reg_signal use
|
||||
* enum fc_edc_cg_signal_cap_types
|
||||
*/
|
||||
u16 cgn_fpin_frequency;
|
||||
u16 cgn_fpin_frequency; /* In units of msecs */
|
||||
#define LPFC_FPIN_INIT_FREQ 0xffff
|
||||
u32 cgn_sig_freq;
|
||||
u32 cgn_acqe_cnt;
|
||||
|
||||
/* RX monitor handling for CMF */
|
||||
struct rxtable_entry *rxtable; /* RX_monitor information */
|
||||
atomic_t rxtable_idx_head;
|
||||
#define LPFC_RXMONITOR_TABLE_IN_USE (LPFC_MAX_RXMONITOR_ENTRY + 73)
|
||||
atomic_t rxtable_idx_tail;
|
||||
struct lpfc_rx_info_monitor *rx_monitor;
|
||||
atomic_t rx_max_read_cnt; /* Maximum read bytes */
|
||||
uint64_t rx_block_cnt;
|
||||
|
||||
@ -1610,10 +1597,11 @@ struct lpfc_hba {
|
||||
|
||||
char os_host_name[MAXHOSTNAMELEN];
|
||||
|
||||
/* SCSI host template information - for physical port */
|
||||
struct scsi_host_template port_template;
|
||||
/* SCSI host template information - for all vports */
|
||||
struct scsi_host_template vport_template;
|
||||
/* LD Signaling */
|
||||
u32 degrade_activate_threshold;
|
||||
u32 degrade_deactivate_threshold;
|
||||
u32 fec_degrade_interval;
|
||||
|
||||
atomic_t dbg_log_idx;
|
||||
atomic_t dbg_log_cnt;
|
||||
atomic_t dbg_log_dmping;
|
||||
@ -1622,7 +1610,7 @@ struct lpfc_hba {
|
||||
|
||||
#define LPFC_MAX_RXMONITOR_ENTRY 800
|
||||
#define LPFC_MAX_RXMONITOR_DUMP 32
|
||||
struct rxtable_entry {
|
||||
struct rx_info_entry {
|
||||
uint64_t cmf_bytes; /* Total no of read bytes for CMF_SYNC_WQE */
|
||||
uint64_t total_bytes; /* Total no of read bytes requested */
|
||||
uint64_t rcv_bytes; /* Total no of read bytes completed */
|
||||
@ -1637,6 +1625,13 @@ struct rxtable_entry {
|
||||
uint32_t timer_interval;
|
||||
};
|
||||
|
||||
struct lpfc_rx_info_monitor {
|
||||
struct rx_info_entry *ring; /* info organized in a circular buffer */
|
||||
u32 head_idx, tail_idx; /* index to head/tail of ring */
|
||||
spinlock_t lock; /* spinlock for ring */
|
||||
u32 entries; /* storing number entries/size of ring */
|
||||
};
|
||||
|
||||
static inline struct Scsi_Host *
|
||||
lpfc_shost_from_vport(struct lpfc_vport *vport)
|
||||
{
|
||||
|
@ -4093,333 +4093,6 @@ lpfc_static_vport_show(struct device *dev, struct device_attribute *attr,
|
||||
*/
|
||||
static DEVICE_ATTR_RO(lpfc_static_vport);
|
||||
|
||||
/**
|
||||
* lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file
|
||||
* @dev: Pointer to class device.
|
||||
* @attr: Unused.
|
||||
* @buf: Data buffer.
|
||||
* @count: Size of the data buffer.
|
||||
*
|
||||
* This function get called when a user write to the lpfc_stat_data_ctrl
|
||||
* sysfs file. This function parse the command written to the sysfs file
|
||||
* and take appropriate action. These commands are used for controlling
|
||||
* driver statistical data collection.
|
||||
* Following are the command this function handles.
|
||||
*
|
||||
* setbucket <bucket_type> <base> <step>
|
||||
* = Set the latency buckets.
|
||||
* destroybucket = destroy all the buckets.
|
||||
* start = start data collection
|
||||
* stop = stop data collection
|
||||
* reset = reset the collected data
|
||||
**/
|
||||
static ssize_t
|
||||
lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
#define LPFC_MAX_DATA_CTRL_LEN 1024
|
||||
static char bucket_data[LPFC_MAX_DATA_CTRL_LEN];
|
||||
unsigned long i;
|
||||
char *str_ptr, *token;
|
||||
struct lpfc_vport **vports;
|
||||
struct Scsi_Host *v_shost;
|
||||
char *bucket_type_str, *base_str, *step_str;
|
||||
unsigned long base, step, bucket_type;
|
||||
|
||||
if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
|
||||
if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1))
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(bucket_data, buf, LPFC_MAX_DATA_CTRL_LEN);
|
||||
str_ptr = &bucket_data[0];
|
||||
/* Ignore this token - this is command token */
|
||||
token = strsep(&str_ptr, "\t ");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
bucket_type_str = strsep(&str_ptr, "\t ");
|
||||
if (!bucket_type_str)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp(bucket_type_str, "linear", strlen("linear")))
|
||||
bucket_type = LPFC_LINEAR_BUCKET;
|
||||
else if (!strncmp(bucket_type_str, "power2", strlen("power2")))
|
||||
bucket_type = LPFC_POWER2_BUCKET;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
base_str = strsep(&str_ptr, "\t ");
|
||||
if (!base_str)
|
||||
return -EINVAL;
|
||||
base = simple_strtoul(base_str, NULL, 0);
|
||||
|
||||
step_str = strsep(&str_ptr, "\t ");
|
||||
if (!step_str)
|
||||
return -EINVAL;
|
||||
step = simple_strtoul(step_str, NULL, 0);
|
||||
if (!step)
|
||||
return -EINVAL;
|
||||
|
||||
/* Block the data collection for every vport */
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
||||
v_shost = lpfc_shost_from_vport(vports[i]);
|
||||
spin_lock_irq(v_shost->host_lock);
|
||||
/* Block and reset data collection */
|
||||
vports[i]->stat_data_blocked = 1;
|
||||
if (vports[i]->stat_data_enabled)
|
||||
lpfc_vport_reset_stat_data(vports[i]);
|
||||
spin_unlock_irq(v_shost->host_lock);
|
||||
}
|
||||
|
||||
/* Set the bucket attributes */
|
||||
phba->bucket_type = bucket_type;
|
||||
phba->bucket_base = base;
|
||||
phba->bucket_step = step;
|
||||
|
||||
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
||||
v_shost = lpfc_shost_from_vport(vports[i]);
|
||||
|
||||
/* Unblock data collection */
|
||||
spin_lock_irq(v_shost->host_lock);
|
||||
vports[i]->stat_data_blocked = 0;
|
||||
spin_unlock_irq(v_shost->host_lock);
|
||||
}
|
||||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
if (!strncmp(buf, "destroybucket", strlen("destroybucket"))) {
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
||||
v_shost = lpfc_shost_from_vport(vports[i]);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vports[i]->stat_data_blocked = 1;
|
||||
lpfc_free_bucket(vport);
|
||||
vport->stat_data_enabled = 0;
|
||||
vports[i]->stat_data_blocked = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
}
|
||||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
phba->bucket_type = LPFC_NO_BUCKET;
|
||||
phba->bucket_base = 0;
|
||||
phba->bucket_step = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
if (!strncmp(buf, "start", strlen("start"))) {
|
||||
/* If no buckets configured return error */
|
||||
if (phba->bucket_type == LPFC_NO_BUCKET)
|
||||
return -EINVAL;
|
||||
spin_lock_irq(shost->host_lock);
|
||||
if (vport->stat_data_enabled) {
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return strlen(buf);
|
||||
}
|
||||
lpfc_alloc_bucket(vport);
|
||||
vport->stat_data_enabled = 1;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
if (!strncmp(buf, "stop", strlen("stop"))) {
|
||||
spin_lock_irq(shost->host_lock);
|
||||
if (vport->stat_data_enabled == 0) {
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return strlen(buf);
|
||||
}
|
||||
lpfc_free_bucket(vport);
|
||||
vport->stat_data_enabled = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
if (!strncmp(buf, "reset", strlen("reset"))) {
|
||||
if ((phba->bucket_type == LPFC_NO_BUCKET)
|
||||
|| !vport->stat_data_enabled)
|
||||
return strlen(buf);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->stat_data_blocked = 1;
|
||||
lpfc_vport_reset_stat_data(vport);
|
||||
vport->stat_data_blocked = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return strlen(buf);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file
|
||||
* @dev: Pointer to class device.
|
||||
* @attr: Unused.
|
||||
* @buf: Data buffer.
|
||||
*
|
||||
* This function is the read call back function for
|
||||
* lpfc_stat_data_ctrl sysfs file. This function report the
|
||||
* current statistical data collection state.
|
||||
**/
|
||||
static ssize_t
|
||||
lpfc_stat_data_ctrl_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
int index = 0;
|
||||
int i;
|
||||
char *bucket_type;
|
||||
unsigned long bucket_value;
|
||||
|
||||
switch (phba->bucket_type) {
|
||||
case LPFC_LINEAR_BUCKET:
|
||||
bucket_type = "linear";
|
||||
break;
|
||||
case LPFC_POWER2_BUCKET:
|
||||
bucket_type = "power2";
|
||||
break;
|
||||
default:
|
||||
bucket_type = "No Bucket";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(&buf[index], "Statistical Data enabled :%d, "
|
||||
"blocked :%d, Bucket type :%s, Bucket base :%d,"
|
||||
" Bucket step :%d\nLatency Ranges :",
|
||||
vport->stat_data_enabled, vport->stat_data_blocked,
|
||||
bucket_type, phba->bucket_base, phba->bucket_step);
|
||||
index = strlen(buf);
|
||||
if (phba->bucket_type != LPFC_NO_BUCKET) {
|
||||
for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
|
||||
if (phba->bucket_type == LPFC_LINEAR_BUCKET)
|
||||
bucket_value = phba->bucket_base +
|
||||
phba->bucket_step * i;
|
||||
else
|
||||
bucket_value = phba->bucket_base +
|
||||
(1 << i) * phba->bucket_step;
|
||||
|
||||
if (index + 10 > PAGE_SIZE)
|
||||
break;
|
||||
sprintf(&buf[index], "%08ld ", bucket_value);
|
||||
index = strlen(buf);
|
||||
}
|
||||
}
|
||||
sprintf(&buf[index], "\n");
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sysfs attribute to control the statistical data collection.
|
||||
*/
|
||||
static DEVICE_ATTR_RW(lpfc_stat_data_ctrl);
|
||||
|
||||
/*
|
||||
* lpfc_drvr_stat_data: sysfs attr to get driver statistical data.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Each Bucket takes 11 characters and 1 new line + 17 bytes WWN
|
||||
* for each target.
|
||||
*/
|
||||
#define STAT_DATA_SIZE_PER_TARGET(NUM_BUCKETS) ((NUM_BUCKETS) * 11 + 18)
|
||||
#define MAX_STAT_DATA_SIZE_PER_TARGET \
|
||||
STAT_DATA_SIZE_PER_TARGET(LPFC_MAX_BUCKET_COUNT)
|
||||
|
||||
|
||||
/**
|
||||
* sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute
|
||||
* @filp: sysfs file
|
||||
* @kobj: Pointer to the kernel object
|
||||
* @bin_attr: Attribute object
|
||||
* @buf: Buffer pointer
|
||||
* @off: File offset
|
||||
* @count: Buffer size
|
||||
*
|
||||
* This function is the read call back function for lpfc_drvr_stat_data
|
||||
* sysfs file. This function export the statistical data to user
|
||||
* applications.
|
||||
**/
|
||||
static ssize_t
|
||||
sysfs_drvr_stat_data_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device,
|
||||
kobj);
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
int i = 0, index = 0;
|
||||
unsigned long nport_index;
|
||||
struct lpfc_nodelist *ndlp = NULL;
|
||||
nport_index = (unsigned long)off /
|
||||
MAX_STAT_DATA_SIZE_PER_TARGET;
|
||||
|
||||
if (!vport->stat_data_enabled || vport->stat_data_blocked
|
||||
|| (phba->bucket_type == LPFC_NO_BUCKET))
|
||||
return 0;
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
if (!ndlp->lat_data)
|
||||
continue;
|
||||
|
||||
if (nport_index > 0) {
|
||||
nport_index--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((index + MAX_STAT_DATA_SIZE_PER_TARGET)
|
||||
> count)
|
||||
break;
|
||||
|
||||
if (!ndlp->lat_data)
|
||||
continue;
|
||||
|
||||
/* Print the WWN */
|
||||
sprintf(&buf[index], "%02x%02x%02x%02x%02x%02x%02x%02x:",
|
||||
ndlp->nlp_portname.u.wwn[0],
|
||||
ndlp->nlp_portname.u.wwn[1],
|
||||
ndlp->nlp_portname.u.wwn[2],
|
||||
ndlp->nlp_portname.u.wwn[3],
|
||||
ndlp->nlp_portname.u.wwn[4],
|
||||
ndlp->nlp_portname.u.wwn[5],
|
||||
ndlp->nlp_portname.u.wwn[6],
|
||||
ndlp->nlp_portname.u.wwn[7]);
|
||||
|
||||
index = strlen(buf);
|
||||
|
||||
for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
|
||||
sprintf(&buf[index], "%010u,",
|
||||
ndlp->lat_data[i].cmd_count);
|
||||
index = strlen(buf);
|
||||
}
|
||||
sprintf(&buf[index], "\n");
|
||||
index = strlen(buf);
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return index;
|
||||
}
|
||||
|
||||
static struct bin_attribute sysfs_drvr_stat_data_attr = {
|
||||
.attr = {
|
||||
.name = "lpfc_drvr_stat_data",
|
||||
.mode = S_IRUSR,
|
||||
},
|
||||
.size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
|
||||
.read = sysfs_drvr_stat_data_read,
|
||||
.write = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
|
||||
# connection.
|
||||
@ -6273,7 +5946,6 @@ static struct attribute *lpfc_hba_attrs[] = {
|
||||
&dev_attr_lpfc_xlane_priority.attr,
|
||||
&dev_attr_lpfc_sg_seg_cnt.attr,
|
||||
&dev_attr_lpfc_max_scsicmpl_time.attr,
|
||||
&dev_attr_lpfc_stat_data_ctrl.attr,
|
||||
&dev_attr_lpfc_aer_support.attr,
|
||||
&dev_attr_lpfc_aer_state_cleanup.attr,
|
||||
&dev_attr_lpfc_sriov_nr_virtfn.attr,
|
||||
@ -6332,7 +6004,6 @@ static struct attribute *lpfc_vport_attrs[] = {
|
||||
&dev_attr_npiv_info.attr,
|
||||
&dev_attr_lpfc_enable_da_id.attr,
|
||||
&dev_attr_lpfc_max_scsicmpl_time.attr,
|
||||
&dev_attr_lpfc_stat_data_ctrl.attr,
|
||||
&dev_attr_lpfc_static_vport.attr,
|
||||
&dev_attr_cmf_info.attr,
|
||||
NULL,
|
||||
@ -6545,17 +6216,14 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
int error;
|
||||
|
||||
error = sysfs_create_bin_file(&shost->shost_dev.kobj,
|
||||
&sysfs_drvr_stat_data_attr);
|
||||
|
||||
/* Virtual ports do not need ctrl_reg and mbox */
|
||||
if (error || vport->port_type == LPFC_NPIV_PORT)
|
||||
goto out;
|
||||
if (vport->port_type == LPFC_NPIV_PORT)
|
||||
return 0;
|
||||
|
||||
error = sysfs_create_bin_file(&shost->shost_dev.kobj,
|
||||
&sysfs_ctlreg_attr);
|
||||
if (error)
|
||||
goto out_remove_stat_attr;
|
||||
goto out;
|
||||
|
||||
error = sysfs_create_bin_file(&shost->shost_dev.kobj,
|
||||
&sysfs_mbox_attr);
|
||||
@ -6565,9 +6233,6 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
|
||||
return 0;
|
||||
out_remove_ctlreg_attr:
|
||||
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
|
||||
out_remove_stat_attr:
|
||||
sysfs_remove_bin_file(&shost->shost_dev.kobj,
|
||||
&sysfs_drvr_stat_data_attr);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
@ -6580,8 +6245,7 @@ void
|
||||
lpfc_free_sysfs_attr(struct lpfc_vport *vport)
|
||||
{
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
sysfs_remove_bin_file(&shost->shost_dev.kobj,
|
||||
&sysfs_drvr_stat_data_attr);
|
||||
|
||||
/* Virtual ports do not need ctrl_reg and mbox */
|
||||
if (vport->port_type == LPFC_NPIV_PORT)
|
||||
return;
|
||||
|
@ -1977,8 +1977,6 @@ lpfc_sli4_bsg_set_loopback_mode(struct lpfc_hba *phba, int mode,
|
||||
static int
|
||||
lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (phba->pport->fc_flag & FC_VFI_REGISTERED) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
|
||||
"3136 Port still had vfi registered: "
|
||||
@ -1988,8 +1986,7 @@ lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba)
|
||||
phba->vpi_ids[phba->pport->vpi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = lpfc_issue_reg_vfi(phba->pport);
|
||||
return rc;
|
||||
return lpfc_issue_reg_vfi(phba->pport);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,6 +78,7 @@ int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
|
||||
void lpfc_free_iocb_list(struct lpfc_hba *phba);
|
||||
int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
|
||||
struct lpfc_queue *drq, int count, int idx);
|
||||
int lpfc_read_lds_params(struct lpfc_hba *phba);
|
||||
uint32_t lpfc_calc_cmf_latency(struct lpfc_hba *phba);
|
||||
void lpfc_cmf_signal_init(struct lpfc_hba *phba);
|
||||
void lpfc_cmf_start(struct lpfc_hba *phba);
|
||||
@ -92,6 +93,14 @@ void lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba);
|
||||
void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
|
||||
void lpfc_unblock_requests(struct lpfc_hba *phba);
|
||||
void lpfc_block_requests(struct lpfc_hba *phba);
|
||||
int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
|
||||
u32 entries);
|
||||
void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor);
|
||||
void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor,
|
||||
struct rx_info_entry *entry);
|
||||
u32 lpfc_rx_monitor_report(struct lpfc_hba *phba,
|
||||
struct lpfc_rx_info_monitor *rx_monitor, char *buf,
|
||||
u32 buf_len, u32 max_read_entries);
|
||||
|
||||
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
@ -454,6 +463,7 @@ extern const struct attribute_group *lpfc_hba_groups[];
|
||||
extern const struct attribute_group *lpfc_vport_groups[];
|
||||
extern struct scsi_host_template lpfc_template;
|
||||
extern struct scsi_host_template lpfc_template_nvme;
|
||||
extern struct scsi_host_template lpfc_vport_template;
|
||||
extern struct fc_function_template lpfc_transport_functions;
|
||||
extern struct fc_function_template lpfc_vport_transport_functions;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5156,7 +5156,7 @@ error_out:
|
||||
static int
|
||||
lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
|
||||
{
|
||||
uint16_t ext_cnt, ext_size;
|
||||
uint16_t ext_cnt = 0, ext_size = 0;
|
||||
|
||||
len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
|
||||
"\nAvailable Extents Information:\n");
|
||||
@ -5531,7 +5531,7 @@ lpfc_rx_monitor_open(struct inode *inode, struct file *file)
|
||||
if (!debug)
|
||||
goto out;
|
||||
|
||||
debug->buffer = vmalloc(MAX_DEBUGFS_RX_TABLE_SIZE);
|
||||
debug->buffer = vmalloc(MAX_DEBUGFS_RX_INFO_SIZE);
|
||||
if (!debug->buffer) {
|
||||
kfree(debug);
|
||||
goto out;
|
||||
@ -5552,57 +5552,18 @@ lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
|
||||
struct lpfc_rx_monitor_debug *debug = file->private_data;
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
|
||||
char *buffer = debug->buffer;
|
||||
struct rxtable_entry *entry;
|
||||
int i, len = 0, head, tail, last, start;
|
||||
|
||||
head = atomic_read(&phba->rxtable_idx_head);
|
||||
while (head == LPFC_RXMONITOR_TABLE_IN_USE) {
|
||||
/* Table is getting updated */
|
||||
msleep(20);
|
||||
head = atomic_read(&phba->rxtable_idx_head);
|
||||
if (!phba->rx_monitor) {
|
||||
scnprintf(buffer, MAX_DEBUGFS_RX_INFO_SIZE,
|
||||
"Rx Monitor Info is empty.\n");
|
||||
} else {
|
||||
lpfc_rx_monitor_report(phba, phba->rx_monitor, buffer,
|
||||
MAX_DEBUGFS_RX_INFO_SIZE,
|
||||
LPFC_MAX_RXMONITOR_ENTRY);
|
||||
}
|
||||
|
||||
tail = atomic_xchg(&phba->rxtable_idx_tail, head);
|
||||
if (!phba->rxtable || head == tail) {
|
||||
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
|
||||
"Rxtable is empty\n");
|
||||
goto out;
|
||||
}
|
||||
last = (head > tail) ? head : LPFC_MAX_RXMONITOR_ENTRY;
|
||||
start = tail;
|
||||
|
||||
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
|
||||
" MaxBPI Tot_Data_CMF Tot_Data_Cmd "
|
||||
"Tot_Data_Cmpl Lat(us) Avg_IO Max_IO "
|
||||
"Bsy IO_cnt Info BWutil(ms)\n");
|
||||
get_table:
|
||||
for (i = start; i < last; i++) {
|
||||
entry = &phba->rxtable[i];
|
||||
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
|
||||
"%3d:%12lld %12lld %12lld %12lld "
|
||||
"%7lldus %8lld %7lld "
|
||||
"%2d %4d %2d %2d(%2d)\n",
|
||||
i, entry->max_bytes_per_interval,
|
||||
entry->cmf_bytes,
|
||||
entry->total_bytes,
|
||||
entry->rcv_bytes,
|
||||
entry->avg_io_latency,
|
||||
entry->avg_io_size,
|
||||
entry->max_read_cnt,
|
||||
entry->cmf_busy,
|
||||
entry->io_cnt,
|
||||
entry->cmf_info,
|
||||
entry->timer_utilization,
|
||||
entry->timer_interval);
|
||||
}
|
||||
|
||||
if (head != last) {
|
||||
start = 0;
|
||||
last = head;
|
||||
goto get_table;
|
||||
}
|
||||
out:
|
||||
return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
|
||||
return simple_read_from_buffer(buf, nbytes, ppos, buffer,
|
||||
strlen(buffer));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -282,7 +282,7 @@ struct lpfc_idiag {
|
||||
void *ptr_private;
|
||||
};
|
||||
|
||||
#define MAX_DEBUGFS_RX_TABLE_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
|
||||
#define MAX_DEBUGFS_RX_INFO_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
|
||||
struct lpfc_rx_monitor_debug {
|
||||
char *i_private;
|
||||
char *buffer;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -149,7 +149,6 @@ struct lpfc_nodelist {
|
||||
uint32_t cmd_qdepth;
|
||||
unsigned long last_change_time;
|
||||
unsigned long *active_rrqs_xri_bitmap;
|
||||
struct lpfc_scsicmd_bkt *lat_data; /* Latency data */
|
||||
uint32_t fc4_prli_sent;
|
||||
|
||||
/* flags to keep ndlp alive until special conditions are met */
|
||||
@ -188,7 +187,6 @@ struct lpfc_node_rrq {
|
||||
#define NLP_RNID_SND 0x00000400 /* sent RNID request for this entry */
|
||||
#define NLP_ELS_SND_MASK 0x000007e0 /* sent ELS request for this entry */
|
||||
#define NLP_NVMET_RECOV 0x00001000 /* NVMET auditing node for recovery. */
|
||||
#define NLP_FCP_PRLI_RJT 0x00002000 /* Rport does not support FCP PRLI. */
|
||||
#define NLP_UNREG_INP 0x00008000 /* UNREG_RPI cmd is in progress */
|
||||
#define NLP_DROPPED 0x00010000 /* Init ref count has been dropped */
|
||||
#define NLP_DELAY_TMO 0x00020000 /* delay timeout is running for node */
|
||||
|
@ -2200,10 +2200,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->nlp_flag &= ~NLP_FCP_PRLI_RJT;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
|
||||
pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
|
||||
|
||||
/* For PLOGI request, remainder of payload is service parameters */
|
||||
@ -3992,7 +3988,8 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
goto out;
|
||||
|
||||
/* ELS cmd tag <ulpIoTag> completes */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"4676 Fabric EDC Rsp: "
|
||||
"0x%02x, 0x%08x\n",
|
||||
edc_rsp->acc_hdr.la_cmd,
|
||||
@ -4029,18 +4026,18 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
|
||||
FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
|
||||
sizeof(struct fc_diag_lnkflt_desc)) {
|
||||
lpfc_printf_log(
|
||||
phba, KERN_WARNING, LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"6462 Truncated Link Fault Diagnostic "
|
||||
"descriptor[%d]: %d vs 0x%zx 0x%zx\n",
|
||||
desc_cnt, bytes_remain,
|
||||
FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
|
||||
sizeof(struct fc_diag_cg_sig_desc));
|
||||
sizeof(struct fc_diag_lnkflt_desc));
|
||||
goto out;
|
||||
}
|
||||
plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
|
||||
lpfc_printf_log(
|
||||
phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_ELS | LOG_LDS_EVENT,
|
||||
"4617 Link Fault Desc Data: 0x%08x 0x%08x "
|
||||
"0x%08x 0x%08x 0x%08x\n",
|
||||
be32_to_cpu(plnkflt->desc_tag),
|
||||
@ -4120,8 +4117,26 @@ out:
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_diag_cg_sig_desc *cgd)
|
||||
lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
|
||||
{
|
||||
struct fc_diag_lnkflt_desc *lft = (struct fc_diag_lnkflt_desc *)tlv;
|
||||
|
||||
lft->desc_tag = cpu_to_be32(ELS_DTAG_LNK_FAULT_CAP);
|
||||
lft->desc_len = cpu_to_be32(
|
||||
FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_diag_lnkflt_desc));
|
||||
|
||||
lft->degrade_activate_threshold =
|
||||
cpu_to_be32(phba->degrade_activate_threshold);
|
||||
lft->degrade_deactivate_threshold =
|
||||
cpu_to_be32(phba->degrade_deactivate_threshold);
|
||||
lft->fec_degrade_interval = cpu_to_be32(phba->fec_degrade_interval);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
|
||||
{
|
||||
struct fc_diag_cg_sig_desc *cgd = (struct fc_diag_cg_sig_desc *)tlv;
|
||||
|
||||
/* We are assuming cgd was zero'ed before calling this routine */
|
||||
|
||||
/* Configure the congestion detection capability */
|
||||
@ -4165,6 +4180,23 @@ lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_diag_cg_sig_desc *cgd)
|
||||
cpu_to_be16(EDC_CG_SIGFREQ_MSEC);
|
||||
}
|
||||
|
||||
static bool
|
||||
lpfc_link_is_lds_capable(struct lpfc_hba *phba)
|
||||
{
|
||||
if (!(phba->lmt & LMT_64Gb))
|
||||
return false;
|
||||
if (phba->sli_rev != LPFC_SLI_REV4)
|
||||
return false;
|
||||
|
||||
if (phba->sli4_hba.conf_trunk) {
|
||||
if (phba->trunk_link.phy_lnk_speed == LPFC_USER_LINK_SPEED_64G)
|
||||
return true;
|
||||
} else if (phba->fc_linkspeed == LPFC_LINK_SPEED_64GHZ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_issue_els_edc - Exchange Diagnostic Capabilities with the fabric.
|
||||
* @vport: pointer to a host virtual N_Port data structure.
|
||||
@ -4192,12 +4224,12 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
struct lpfc_els_edc_req *edc_req;
|
||||
struct fc_diag_cg_sig_desc *cgn_desc;
|
||||
struct fc_els_edc *edc_req;
|
||||
struct fc_tlv_desc *tlv;
|
||||
u16 cmdsize;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
u8 *pcmd = NULL;
|
||||
u32 edc_req_size, cgn_desc_size;
|
||||
u32 cgn_desc_size, lft_desc_size;
|
||||
int rc;
|
||||
|
||||
if (vport->port_type == LPFC_NPIV_PORT)
|
||||
@ -4207,13 +4239,17 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
|
||||
if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
|
||||
return -ENODEV;
|
||||
|
||||
/* If HBA doesn't support signals, drop into RDF */
|
||||
if (!phba->cgn_init_reg_signal)
|
||||
cgn_desc_size = (phba->cgn_init_reg_signal) ?
|
||||
sizeof(struct fc_diag_cg_sig_desc) : 0;
|
||||
lft_desc_size = (lpfc_link_is_lds_capable(phba)) ?
|
||||
sizeof(struct fc_diag_lnkflt_desc) : 0;
|
||||
cmdsize = cgn_desc_size + lft_desc_size;
|
||||
|
||||
/* Skip EDC if no applicable descriptors */
|
||||
if (!cmdsize)
|
||||
goto try_rdf;
|
||||
|
||||
edc_req_size = sizeof(struct fc_els_edc);
|
||||
cgn_desc_size = sizeof(struct fc_diag_cg_sig_desc);
|
||||
cmdsize = edc_req_size + cgn_desc_size;
|
||||
cmdsize += sizeof(struct fc_els_edc);
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_EDC);
|
||||
if (!elsiocb)
|
||||
@ -4222,15 +4258,19 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
|
||||
/* Configure the payload for the supported Diagnostics capabilities. */
|
||||
pcmd = (u8 *)elsiocb->cmd_dmabuf->virt;
|
||||
memset(pcmd, 0, cmdsize);
|
||||
edc_req = (struct lpfc_els_edc_req *)pcmd;
|
||||
edc_req->edc.desc_len = cpu_to_be32(cgn_desc_size);
|
||||
edc_req->edc.edc_cmd = ELS_EDC;
|
||||
edc_req = (struct fc_els_edc *)pcmd;
|
||||
edc_req->desc_len = cpu_to_be32(cgn_desc_size + lft_desc_size);
|
||||
edc_req->edc_cmd = ELS_EDC;
|
||||
tlv = edc_req->desc;
|
||||
|
||||
cgn_desc = &edc_req->cgn_desc;
|
||||
if (cgn_desc_size) {
|
||||
lpfc_format_edc_cgn_desc(phba, tlv);
|
||||
phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
|
||||
tlv = fc_tlv_next_desc(tlv);
|
||||
}
|
||||
|
||||
lpfc_format_edc_cgn_desc(phba, cgn_desc);
|
||||
|
||||
phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
|
||||
if (lft_desc_size)
|
||||
lpfc_format_edc_lft_desc(phba, tlv);
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
"4623 Xmit EDC to remote "
|
||||
@ -4676,47 +4716,52 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
}
|
||||
switch (stat.un.b.lsRjtRsnCode) {
|
||||
case LSRJT_UNABLE_TPC:
|
||||
/* The driver has a VALID PLOGI but the rport has
|
||||
* rejected the PRLI - can't do it now. Delay
|
||||
* for 1 second and try again.
|
||||
*
|
||||
* However, if explanation is REQ_UNSUPPORTED there's
|
||||
* no point to retry PRLI.
|
||||
/* Special case for PRLI LS_RJTs. Recall that lpfc
|
||||
* uses a single routine to issue both PRLI FC4 types.
|
||||
* If the PRLI is rejected because that FC4 type
|
||||
* isn't really supported, don't retry and cause
|
||||
* multiple transport registrations. Otherwise, parse
|
||||
* the reason code/reason code explanation and take the
|
||||
* appropriate action.
|
||||
*/
|
||||
if ((cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) &&
|
||||
stat.un.b.lsRjtRsnCodeExp !=
|
||||
LSEXP_REQ_UNSUPPORTED) {
|
||||
delay = 1000;
|
||||
maxretry = lpfc_max_els_tries + 1;
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
LOG_DISCOVERY | LOG_ELS | LOG_NODE,
|
||||
"0153 ELS cmd x%x LS_RJT by x%x. "
|
||||
"RsnCode x%x RsnCodeExp x%x\n",
|
||||
cmd, did, stat.un.b.lsRjtRsnCode,
|
||||
stat.un.b.lsRjtRsnCodeExp);
|
||||
|
||||
switch (stat.un.b.lsRjtRsnCodeExp) {
|
||||
case LSEXP_CANT_GIVE_DATA:
|
||||
case LSEXP_CMD_IN_PROGRESS:
|
||||
if (cmd == ELS_CMD_PLOGI) {
|
||||
delay = 1000;
|
||||
maxretry = 48;
|
||||
}
|
||||
retry = 1;
|
||||
break;
|
||||
case LSEXP_REQ_UNSUPPORTED:
|
||||
case LSEXP_NO_RSRC_ASSIGN:
|
||||
/* These explanation codes get no retry. */
|
||||
if (cmd == ELS_CMD_PRLI ||
|
||||
cmd == ELS_CMD_NVMEPRLI)
|
||||
break;
|
||||
fallthrough;
|
||||
default:
|
||||
/* Limit the delay and retry action to a limited
|
||||
* cmd set. There are other ELS commands where
|
||||
* a retry is not expected.
|
||||
*/
|
||||
if (cmd == ELS_CMD_PLOGI ||
|
||||
cmd == ELS_CMD_PRLI ||
|
||||
cmd == ELS_CMD_NVMEPRLI) {
|
||||
delay = 1000;
|
||||
maxretry = lpfc_max_els_tries + 1;
|
||||
retry = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Legacy bug fix code for targets with PLOGI delays. */
|
||||
if (stat.un.b.lsRjtRsnCodeExp ==
|
||||
LSEXP_CMD_IN_PROGRESS) {
|
||||
if (cmd == ELS_CMD_PLOGI) {
|
||||
delay = 1000;
|
||||
maxretry = 48;
|
||||
}
|
||||
retry = 1;
|
||||
break;
|
||||
}
|
||||
if (stat.un.b.lsRjtRsnCodeExp ==
|
||||
LSEXP_CANT_GIVE_DATA) {
|
||||
if (cmd == ELS_CMD_PLOGI) {
|
||||
delay = 1000;
|
||||
maxretry = 48;
|
||||
}
|
||||
retry = 1;
|
||||
break;
|
||||
}
|
||||
if (cmd == ELS_CMD_PLOGI) {
|
||||
delay = 1000;
|
||||
maxretry = lpfc_max_els_tries + 1;
|
||||
retry = 1;
|
||||
break;
|
||||
}
|
||||
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
||||
(cmd == ELS_CMD_FDISC) &&
|
||||
(stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
|
||||
@ -4797,13 +4842,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
*/
|
||||
if (stat.un.b.lsRjtRsnCodeExp ==
|
||||
LSEXP_REQ_UNSUPPORTED) {
|
||||
if (cmd == ELS_CMD_PRLI) {
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->nlp_flag |= NLP_FCP_PRLI_RJT;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
retry = 0;
|
||||
if (cmd == ELS_CMD_PRLI)
|
||||
goto out_retry;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -5784,14 +5824,21 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_els_edc_rsp *edc_rsp;
|
||||
struct fc_els_edc_resp *edc_rsp;
|
||||
struct fc_tlv_desc *tlv;
|
||||
struct lpfc_iocbq *elsiocb;
|
||||
IOCB_t *icmd, *cmd;
|
||||
union lpfc_wqe128 *wqe;
|
||||
u32 cgn_desc_size, lft_desc_size;
|
||||
u16 cmdsize;
|
||||
uint8_t *pcmd;
|
||||
int cmdsize, rc;
|
||||
int rc;
|
||||
|
||||
cmdsize = sizeof(struct lpfc_els_edc_rsp);
|
||||
cmdsize = sizeof(struct fc_els_edc_resp);
|
||||
cgn_desc_size = sizeof(struct fc_diag_cg_sig_desc);
|
||||
lft_desc_size = (lpfc_link_is_lds_capable(phba)) ?
|
||||
sizeof(struct fc_diag_lnkflt_desc) : 0;
|
||||
cmdsize += cgn_desc_size + lft_desc_size;
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, cmdiocb->retry,
|
||||
ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
|
||||
if (!elsiocb)
|
||||
@ -5813,15 +5860,19 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
pcmd = elsiocb->cmd_dmabuf->virt;
|
||||
memset(pcmd, 0, cmdsize);
|
||||
|
||||
edc_rsp = (struct lpfc_els_edc_rsp *)pcmd;
|
||||
edc_rsp->edc_rsp.acc_hdr.la_cmd = ELS_LS_ACC;
|
||||
edc_rsp->edc_rsp.desc_list_len = cpu_to_be32(
|
||||
FC_TLV_DESC_LENGTH_FROM_SZ(struct lpfc_els_edc_rsp));
|
||||
edc_rsp->edc_rsp.lsri.desc_tag = cpu_to_be32(ELS_DTAG_LS_REQ_INFO);
|
||||
edc_rsp->edc_rsp.lsri.desc_len = cpu_to_be32(
|
||||
edc_rsp = (struct fc_els_edc_resp *)pcmd;
|
||||
edc_rsp->acc_hdr.la_cmd = ELS_LS_ACC;
|
||||
edc_rsp->desc_list_len = cpu_to_be32(sizeof(struct fc_els_lsri_desc) +
|
||||
cgn_desc_size + lft_desc_size);
|
||||
edc_rsp->lsri.desc_tag = cpu_to_be32(ELS_DTAG_LS_REQ_INFO);
|
||||
edc_rsp->lsri.desc_len = cpu_to_be32(
|
||||
FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_els_lsri_desc));
|
||||
edc_rsp->edc_rsp.lsri.rqst_w0.cmd = ELS_EDC;
|
||||
lpfc_format_edc_cgn_desc(phba, &edc_rsp->cgn_desc);
|
||||
edc_rsp->lsri.rqst_w0.cmd = ELS_EDC;
|
||||
tlv = edc_rsp->desc;
|
||||
lpfc_format_edc_cgn_desc(phba, tlv);
|
||||
tlv = fc_tlv_next_desc(tlv);
|
||||
if (lft_desc_size)
|
||||
lpfc_format_edc_lft_desc(phba, tlv);
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||
"Issue EDC ACC: did:x%x flg:x%x refcnt %d",
|
||||
@ -6006,7 +6057,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
|
||||
if (prli_fc4_req == PRLI_FCP_TYPE) {
|
||||
cmdsize = sizeof(uint32_t) + sizeof(PRLI);
|
||||
elsrspcmd = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
|
||||
} else if (prli_fc4_req & PRLI_NVME_TYPE) {
|
||||
} else if (prli_fc4_req == PRLI_NVME_TYPE) {
|
||||
cmdsize = sizeof(uint32_t) + sizeof(struct lpfc_nvme_prli);
|
||||
elsrspcmd = (ELS_CMD_ACC | (ELS_CMD_NVMEPRLI & ~ELS_RSP_MASK));
|
||||
} else {
|
||||
@ -6069,7 +6120,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
|
||||
npr->ConfmComplAllowed = 1;
|
||||
npr->prliType = PRLI_FCP_TYPE;
|
||||
npr->initiatorFunc = 1;
|
||||
} else if (prli_fc4_req & PRLI_NVME_TYPE) {
|
||||
} else if (prli_fc4_req == PRLI_NVME_TYPE) {
|
||||
/* Respond with an NVME PRLI Type */
|
||||
npr_nvme = (struct lpfc_nvme_prli *) pcmd;
|
||||
bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE);
|
||||
@ -9086,7 +9137,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
uint32_t *ptr, dtag;
|
||||
const char *dtag_nm;
|
||||
int desc_cnt = 0, bytes_remain;
|
||||
bool rcv_cap_desc = false;
|
||||
struct fc_diag_lnkflt_desc *plnkflt;
|
||||
|
||||
payload = cmdiocb->cmd_dmabuf->virt;
|
||||
|
||||
@ -9094,7 +9145,8 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
bytes_remain = be32_to_cpu(edc_req->desc_len);
|
||||
|
||||
ptr = (uint32_t *)payload;
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"3319 Rcv EDC payload len %d: x%x x%x x%x\n",
|
||||
bytes_remain, be32_to_cpu(*ptr),
|
||||
be32_to_cpu(*(ptr + 1)), be32_to_cpu(*(ptr + 2)));
|
||||
@ -9113,9 +9165,10 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
* cycle through EDC diagnostic descriptors to find the
|
||||
* congestion signaling capability descriptor
|
||||
*/
|
||||
while (bytes_remain && !rcv_cap_desc) {
|
||||
while (bytes_remain) {
|
||||
if (bytes_remain < FC_TLV_DESC_HDR_SZ) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"6464 Truncated TLV hdr on "
|
||||
"Diagnostic descriptor[%d]\n",
|
||||
desc_cnt);
|
||||
@ -9128,16 +9181,27 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
|
||||
FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
|
||||
sizeof(struct fc_diag_lnkflt_desc)) {
|
||||
lpfc_printf_log(
|
||||
phba, KERN_WARNING, LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"6465 Truncated Link Fault Diagnostic "
|
||||
"descriptor[%d]: %d vs 0x%zx 0x%zx\n",
|
||||
desc_cnt, bytes_remain,
|
||||
FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
|
||||
sizeof(struct fc_diag_cg_sig_desc));
|
||||
sizeof(struct fc_diag_lnkflt_desc));
|
||||
goto out;
|
||||
}
|
||||
/* No action for Link Fault descriptor for now */
|
||||
plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_ELS | LOG_LDS_EVENT,
|
||||
"4626 Link Fault Desc Data: x%08x len x%x "
|
||||
"da x%x dd x%x interval x%x\n",
|
||||
be32_to_cpu(plnkflt->desc_tag),
|
||||
be32_to_cpu(plnkflt->desc_len),
|
||||
be32_to_cpu(
|
||||
plnkflt->degrade_activate_threshold),
|
||||
be32_to_cpu(
|
||||
plnkflt->degrade_deactivate_threshold),
|
||||
be32_to_cpu(plnkflt->fec_degrade_interval));
|
||||
break;
|
||||
case ELS_DTAG_CG_SIGNAL_CAP:
|
||||
if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
|
||||
@ -9164,11 +9228,11 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
|
||||
lpfc_least_capable_settings(
|
||||
phba, (struct fc_diag_cg_sig_desc *)tlv);
|
||||
rcv_cap_desc = true;
|
||||
break;
|
||||
default:
|
||||
dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
|
||||
"6467 unknown Diagnostic "
|
||||
"Descriptor[%d]: tag x%x (%s)\n",
|
||||
desc_cnt, dtag, dtag_nm);
|
||||
|
@ -1242,6 +1242,8 @@ lpfc_linkdown(struct lpfc_hba *phba)
|
||||
phba->trunk_link.link1.state = 0;
|
||||
phba->trunk_link.link2.state = 0;
|
||||
phba->trunk_link.link3.state = 0;
|
||||
phba->trunk_link.phy_lnk_speed =
|
||||
LPFC_LINK_SPEED_UNKNOWN;
|
||||
phba->sli4_hba.link_state.logical_speed =
|
||||
LPFC_LINK_SPEED_UNKNOWN;
|
||||
}
|
||||
@ -1353,8 +1355,13 @@ lpfc_linkup_port(struct lpfc_vport *vport)
|
||||
FCH_EVT_LINKUP, 0);
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
|
||||
FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
|
||||
if (phba->defer_flogi_acc_flag)
|
||||
vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_RSCN_MODE |
|
||||
FC_NLP_MORE | FC_RSCN_DISCOVERY);
|
||||
else
|
||||
vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI |
|
||||
FC_ABORT_DISCOVERY | FC_RSCN_MODE |
|
||||
FC_NLP_MORE | FC_RSCN_DISCOVERY);
|
||||
vport->fc_flag |= FC_NDISC_ACTIVE;
|
||||
vport->fc_ns_retry = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
@ -1392,7 +1399,6 @@ lpfc_linkup(struct lpfc_hba *phba)
|
||||
|
||||
/* reinitialize initial HBA flag */
|
||||
phba->hba_flag &= ~(HBA_FLOGI_ISSUED | HBA_RHBA_CMPL);
|
||||
phba->defer_flogi_acc_flag = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2964,7 +2970,7 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
||||
uint32_t boot_flag, addr_mode;
|
||||
uint16_t next_fcf_index, fcf_index;
|
||||
uint16_t current_fcf_index;
|
||||
uint16_t vlan_id;
|
||||
uint16_t vlan_id = LPFC_FCOE_NULL_VID;
|
||||
int rc;
|
||||
|
||||
/* If link state is not up, stop the roundrobin failover process */
|
||||
@ -3069,7 +3075,7 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
||||
struct fcf_record *new_fcf_record;
|
||||
uint32_t boot_flag, addr_mode;
|
||||
uint16_t fcf_index, next_fcf_index;
|
||||
uint16_t vlan_id;
|
||||
uint16_t vlan_id = LPFC_FCOE_NULL_VID;
|
||||
int rc;
|
||||
|
||||
/* If link state is not up, no need to proceed */
|
||||
@ -3790,6 +3796,9 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
if (phba->cmf_active_mode != LPFC_CFG_OFF)
|
||||
lpfc_cmf_signal_init(phba);
|
||||
|
||||
if (phba->lmt & LMT_64Gb)
|
||||
lpfc_read_lds_params(phba);
|
||||
|
||||
} else if (attn_type == LPFC_ATT_LINK_DOWN ||
|
||||
attn_type == LPFC_ATT_UNEXP_WWPN) {
|
||||
phba->fc_stat.LinkDown++;
|
||||
@ -4389,8 +4398,11 @@ out:
|
||||
rc = lpfc_issue_els_edc(vport, 0);
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_INIT | LOG_ELS | LOG_DISCOVERY,
|
||||
"4220 EDC issue error x%x, Data: x%x\n",
|
||||
"4220 Issue EDC status x%x Data x%x\n",
|
||||
rc, phba->cgn_init_reg_signal);
|
||||
} else if (phba->lmt & LMT_64Gb) {
|
||||
/* may send link fault capability descriptor */
|
||||
lpfc_issue_els_edc(vport, 0);
|
||||
} else {
|
||||
lpfc_issue_els_rdf(vport, 0);
|
||||
}
|
||||
@ -4788,22 +4800,6 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
new_state == NLP_STE_UNMAPPED_NODE)
|
||||
lpfc_nlp_reg_node(vport, ndlp);
|
||||
|
||||
if ((new_state == NLP_STE_MAPPED_NODE) &&
|
||||
(vport->stat_data_enabled)) {
|
||||
/*
|
||||
* A new target is discovered, if there is no buffer for
|
||||
* statistical data collection allocate buffer.
|
||||
*/
|
||||
ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
|
||||
sizeof(struct lpfc_scsicmd_bkt),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ndlp->lat_data)
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0286 lpfc_nlp_state_cleanup failed to "
|
||||
"allocate statistical data buffer DID "
|
||||
"0x%x\n", ndlp->nlp_DID);
|
||||
}
|
||||
/*
|
||||
* If the node just added to Mapped list was an FCP target,
|
||||
* but the remote port registration failed or assigned a target
|
||||
@ -6648,7 +6644,6 @@ lpfc_nlp_release(struct kref *kref)
|
||||
ndlp->fc4_xpt_flags = 0;
|
||||
|
||||
/* free ndlp memory for final ndlp release */
|
||||
kfree(ndlp->lat_data);
|
||||
if (ndlp->phba->sli_rev == LPFC_SLI_REV4)
|
||||
mempool_free(ndlp->active_rrqs_xri_bitmap,
|
||||
ndlp->phba->active_rrq_pool);
|
||||
|
@ -703,6 +703,7 @@ struct ls_rjt { /* Structure is in Big Endian format */
|
||||
#define LSEXP_OUT_OF_RESOURCE 0x29
|
||||
#define LSEXP_CANT_GIVE_DATA 0x2A
|
||||
#define LSEXP_REQ_UNSUPPORTED 0x2C
|
||||
#define LSEXP_NO_RSRC_ASSIGN 0x52
|
||||
uint8_t vendorUnique; /* FC Word 0, bit 0: 7 */
|
||||
} b;
|
||||
} un;
|
||||
@ -1441,30 +1442,56 @@ struct lpfc_vmid_gallapp_ident_list {
|
||||
|
||||
/* Definitions for HBA / Port attribute entries */
|
||||
|
||||
/* Attribute Entry */
|
||||
struct lpfc_fdmi_attr_entry {
|
||||
union {
|
||||
uint32_t AttrInt;
|
||||
uint8_t AttrTypes[32];
|
||||
uint8_t AttrString[256];
|
||||
struct lpfc_name AttrWWN;
|
||||
} un;
|
||||
/* Attribute Entry Structures */
|
||||
|
||||
struct lpfc_fdmi_attr_u32 {
|
||||
__be16 type;
|
||||
__be16 len;
|
||||
__be32 value_u32;
|
||||
};
|
||||
|
||||
struct lpfc_fdmi_attr_def { /* Defined in TLV format */
|
||||
/* Structure is in Big Endian format */
|
||||
uint32_t AttrType:16;
|
||||
uint32_t AttrLen:16;
|
||||
/* Marks start of Value (ATTRIBUTE_ENTRY) */
|
||||
struct lpfc_fdmi_attr_entry AttrValue;
|
||||
} __packed;
|
||||
struct lpfc_fdmi_attr_wwn {
|
||||
__be16 type;
|
||||
__be16 len;
|
||||
|
||||
/* Keep as u8[8] instead of __be64 to avoid accidental zero padding
|
||||
* by compiler
|
||||
*/
|
||||
u8 name[8];
|
||||
};
|
||||
|
||||
struct lpfc_fdmi_attr_fullwwn {
|
||||
__be16 type;
|
||||
__be16 len;
|
||||
|
||||
/* Keep as u8[8] instead of __be64 to avoid accidental zero padding
|
||||
* by compiler
|
||||
*/
|
||||
u8 nname[8];
|
||||
u8 pname[8];
|
||||
};
|
||||
|
||||
struct lpfc_fdmi_attr_fc4types {
|
||||
__be16 type;
|
||||
__be16 len;
|
||||
u8 value_types[32];
|
||||
};
|
||||
|
||||
struct lpfc_fdmi_attr_string {
|
||||
__be16 type;
|
||||
__be16 len;
|
||||
char value_string[256];
|
||||
};
|
||||
|
||||
/* Maximum FDMI attribute length is Type+Len (4 bytes) + 256 byte string */
|
||||
#define FDMI_MAX_ATTRLEN sizeof(struct lpfc_fdmi_attr_string)
|
||||
|
||||
/*
|
||||
* HBA Attribute Block
|
||||
*/
|
||||
struct lpfc_fdmi_attr_block {
|
||||
uint32_t EntryCnt; /* Number of HBA attribute entries */
|
||||
struct lpfc_fdmi_attr_entry Entry; /* Variable-length array */
|
||||
/* Variable Length Attribute Entry TLV's follow */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -738,6 +738,7 @@ struct lpfc_register {
|
||||
#define lpfc_sliport_eqdelay_id_WORD word0
|
||||
#define LPFC_SEC_TO_USEC 1000000
|
||||
#define LPFC_SEC_TO_MSEC 1000
|
||||
#define LPFC_MSECS_TO_SECS(msecs) ((msecs) / 1000)
|
||||
|
||||
/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
|
||||
* reside in BAR 2.
|
||||
@ -3483,9 +3484,10 @@ struct lpfc_sli4_parameters {
|
||||
|
||||
#define LPFC_SET_UE_RECOVERY 0x10
|
||||
#define LPFC_SET_MDS_DIAGS 0x12
|
||||
#define LPFC_SET_CGN_SIGNAL 0x1f
|
||||
#define LPFC_SET_DUAL_DUMP 0x1e
|
||||
#define LPFC_SET_CGN_SIGNAL 0x1f
|
||||
#define LPFC_SET_ENABLE_MI 0x21
|
||||
#define LPFC_SET_LD_SIGNAL 0x23
|
||||
#define LPFC_SET_ENABLE_CMF 0x24
|
||||
struct lpfc_mbx_set_feature {
|
||||
struct mbox_header header;
|
||||
@ -3516,13 +3518,17 @@ struct lpfc_mbx_set_feature {
|
||||
#define lpfc_mbx_set_feature_cmf_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_cmf_MASK 0x00000001
|
||||
#define lpfc_mbx_set_feature_cmf_WORD word6
|
||||
#define lpfc_mbx_set_feature_lds_qry_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_lds_qry_MASK 0x00000001
|
||||
#define lpfc_mbx_set_feature_lds_qry_WORD word6
|
||||
#define LPFC_QUERY_LDS_OP 1
|
||||
#define lpfc_mbx_set_feature_mi_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_mi_MASK 0x0000ffff
|
||||
#define lpfc_mbx_set_feature_mi_WORD word6
|
||||
#define lpfc_mbx_set_feature_milunq_SHIFT 16
|
||||
#define lpfc_mbx_set_feature_milunq_MASK 0x0000ffff
|
||||
#define lpfc_mbx_set_feature_milunq_WORD word6
|
||||
uint32_t word7;
|
||||
u32 word7;
|
||||
#define lpfc_mbx_set_feature_UERP_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
|
||||
#define lpfc_mbx_set_feature_UERP_WORD word7
|
||||
@ -3536,6 +3542,8 @@ struct lpfc_mbx_set_feature {
|
||||
#define lpfc_mbx_set_feature_CGN_acqe_freq_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_CGN_acqe_freq_MASK 0x000000ff
|
||||
#define lpfc_mbx_set_feature_CGN_acqe_freq_WORD word8
|
||||
u32 word9;
|
||||
u32 word10;
|
||||
};
|
||||
|
||||
|
||||
@ -4313,7 +4321,7 @@ struct lpfc_acqe_cgn_signal {
|
||||
struct lpfc_acqe_sli {
|
||||
uint32_t event_data1;
|
||||
uint32_t event_data2;
|
||||
uint32_t reserved;
|
||||
uint32_t event_data3;
|
||||
uint32_t trailer;
|
||||
#define LPFC_SLI_EVENT_TYPE_PORT_ERROR 0x1
|
||||
#define LPFC_SLI_EVENT_TYPE_OVER_TEMP 0x2
|
||||
@ -4326,6 +4334,7 @@ struct lpfc_acqe_sli {
|
||||
#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
|
||||
#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
|
||||
#define LPFC_SLI_EVENT_TYPE_CGN_SIGNAL 0x11
|
||||
#define LPFC_SLI_EVENT_TYPE_RD_SIGNAL 0x12
|
||||
};
|
||||
|
||||
/*
|
||||
@ -4798,6 +4807,9 @@ struct cmf_sync_wqe {
|
||||
#define cmf_sync_cqid_WORD word11
|
||||
uint32_t read_bytes;
|
||||
uint32_t word13;
|
||||
#define cmf_sync_period_SHIFT 16
|
||||
#define cmf_sync_period_MASK 0x0000ffff
|
||||
#define cmf_sync_period_WORD word13
|
||||
uint32_t word14;
|
||||
uint32_t word15;
|
||||
};
|
||||
@ -5046,22 +5058,6 @@ struct lpfc_grp_hdr {
|
||||
{ FPIN_CONGN_SEVERITY_ERROR, "Alarm" }, \
|
||||
}
|
||||
|
||||
/* EDC supports two descriptors. When allocated, it is the
|
||||
* size of this structure plus each supported descriptor.
|
||||
*/
|
||||
struct lpfc_els_edc_req {
|
||||
struct fc_els_edc edc; /* hdr up to descriptors */
|
||||
struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
|
||||
};
|
||||
|
||||
/* Minimum structure defines for the EDC response.
|
||||
* Balance is in buffer.
|
||||
*/
|
||||
struct lpfc_els_edc_rsp {
|
||||
struct fc_els_edc_resp edc_rsp; /* hdr up to descriptors */
|
||||
struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
|
||||
};
|
||||
|
||||
/* Used for logging FPIN messages */
|
||||
#define LPFC_FPIN_WWPN_LINE_SZ 128
|
||||
#define LPFC_FPIN_WWPN_LINE_CNT 6
|
||||
|
@ -325,8 +325,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
||||
prog_id_word = pmboxq->u.mb.un.varWords[7];
|
||||
|
||||
/* Decode the Option rom version word to a readable string */
|
||||
if (prg->dist < 4)
|
||||
dist = dist_char[prg->dist];
|
||||
dist = dist_char[prg->dist];
|
||||
|
||||
if ((prg->dist == 3) && (prg->num == 0))
|
||||
snprintf(phba->OptionROMVersion, 32, "%d.%d%d",
|
||||
@ -2258,6 +2257,101 @@ lpfc_handle_latt_err_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_fill_vpd(struct lpfc_hba *phba, uint8_t *vpd, int length, int *pindex)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
while (length > 0) {
|
||||
/* Look for Serial Number */
|
||||
if ((vpd[*pindex] == 'S') && (vpd[*pindex + 1] == 'N')) {
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
j = 0;
|
||||
length -= (3+i);
|
||||
while (i--) {
|
||||
phba->SerialNumber[j++] = vpd[(*pindex)++];
|
||||
if (j == 31)
|
||||
break;
|
||||
}
|
||||
phba->SerialNumber[j] = 0;
|
||||
continue;
|
||||
} else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '1')) {
|
||||
phba->vpd_flag |= VPD_MODEL_DESC;
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
j = 0;
|
||||
length -= (3+i);
|
||||
while (i--) {
|
||||
phba->ModelDesc[j++] = vpd[(*pindex)++];
|
||||
if (j == 255)
|
||||
break;
|
||||
}
|
||||
phba->ModelDesc[j] = 0;
|
||||
continue;
|
||||
} else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '2')) {
|
||||
phba->vpd_flag |= VPD_MODEL_NAME;
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
j = 0;
|
||||
length -= (3+i);
|
||||
while (i--) {
|
||||
phba->ModelName[j++] = vpd[(*pindex)++];
|
||||
if (j == 79)
|
||||
break;
|
||||
}
|
||||
phba->ModelName[j] = 0;
|
||||
continue;
|
||||
} else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '3')) {
|
||||
phba->vpd_flag |= VPD_PROGRAM_TYPE;
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
j = 0;
|
||||
length -= (3+i);
|
||||
while (i--) {
|
||||
phba->ProgramType[j++] = vpd[(*pindex)++];
|
||||
if (j == 255)
|
||||
break;
|
||||
}
|
||||
phba->ProgramType[j] = 0;
|
||||
continue;
|
||||
} else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '4')) {
|
||||
phba->vpd_flag |= VPD_PORT;
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
j = 0;
|
||||
length -= (3 + i);
|
||||
while (i--) {
|
||||
if ((phba->sli_rev == LPFC_SLI_REV4) &&
|
||||
(phba->sli4_hba.pport_name_sta ==
|
||||
LPFC_SLI4_PPNAME_GET)) {
|
||||
j++;
|
||||
(*pindex)++;
|
||||
} else
|
||||
phba->Port[j++] = vpd[(*pindex)++];
|
||||
if (j == 19)
|
||||
break;
|
||||
}
|
||||
if ((phba->sli_rev != LPFC_SLI_REV4) ||
|
||||
(phba->sli4_hba.pport_name_sta ==
|
||||
LPFC_SLI4_PPNAME_NON))
|
||||
phba->Port[j] = 0;
|
||||
continue;
|
||||
} else {
|
||||
*pindex += 2;
|
||||
i = vpd[*pindex];
|
||||
*pindex += 1;
|
||||
*pindex += i;
|
||||
length -= (3 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_parse_vpd - Parse VPD (Vital Product Data)
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
@ -2277,7 +2371,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
|
||||
{
|
||||
uint8_t lenlo, lenhi;
|
||||
int Length;
|
||||
int i, j;
|
||||
int i;
|
||||
int finished = 0;
|
||||
int index = 0;
|
||||
|
||||
@ -2310,101 +2404,10 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
|
||||
Length = ((((unsigned short)lenhi) << 8) + lenlo);
|
||||
if (Length > len - index)
|
||||
Length = len - index;
|
||||
while (Length > 0) {
|
||||
/* Look for Serial Number */
|
||||
if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) {
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
j = 0;
|
||||
Length -= (3+i);
|
||||
while(i--) {
|
||||
phba->SerialNumber[j++] = vpd[index++];
|
||||
if (j == 31)
|
||||
break;
|
||||
}
|
||||
phba->SerialNumber[j] = 0;
|
||||
continue;
|
||||
}
|
||||
else if ((vpd[index] == 'V') && (vpd[index+1] == '1')) {
|
||||
phba->vpd_flag |= VPD_MODEL_DESC;
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
j = 0;
|
||||
Length -= (3+i);
|
||||
while(i--) {
|
||||
phba->ModelDesc[j++] = vpd[index++];
|
||||
if (j == 255)
|
||||
break;
|
||||
}
|
||||
phba->ModelDesc[j] = 0;
|
||||
continue;
|
||||
}
|
||||
else if ((vpd[index] == 'V') && (vpd[index+1] == '2')) {
|
||||
phba->vpd_flag |= VPD_MODEL_NAME;
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
j = 0;
|
||||
Length -= (3+i);
|
||||
while(i--) {
|
||||
phba->ModelName[j++] = vpd[index++];
|
||||
if (j == 79)
|
||||
break;
|
||||
}
|
||||
phba->ModelName[j] = 0;
|
||||
continue;
|
||||
}
|
||||
else if ((vpd[index] == 'V') && (vpd[index+1] == '3')) {
|
||||
phba->vpd_flag |= VPD_PROGRAM_TYPE;
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
j = 0;
|
||||
Length -= (3+i);
|
||||
while(i--) {
|
||||
phba->ProgramType[j++] = vpd[index++];
|
||||
if (j == 255)
|
||||
break;
|
||||
}
|
||||
phba->ProgramType[j] = 0;
|
||||
continue;
|
||||
}
|
||||
else if ((vpd[index] == 'V') && (vpd[index+1] == '4')) {
|
||||
phba->vpd_flag |= VPD_PORT;
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
j = 0;
|
||||
Length -= (3+i);
|
||||
while(i--) {
|
||||
if ((phba->sli_rev == LPFC_SLI_REV4) &&
|
||||
(phba->sli4_hba.pport_name_sta ==
|
||||
LPFC_SLI4_PPNAME_GET)) {
|
||||
j++;
|
||||
index++;
|
||||
} else
|
||||
phba->Port[j++] = vpd[index++];
|
||||
if (j == 19)
|
||||
break;
|
||||
}
|
||||
if ((phba->sli_rev != LPFC_SLI_REV4) ||
|
||||
(phba->sli4_hba.pport_name_sta ==
|
||||
LPFC_SLI4_PPNAME_NON))
|
||||
phba->Port[j] = 0;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
index += 2;
|
||||
i = vpd[index];
|
||||
index += 1;
|
||||
index += i;
|
||||
Length -= (3 + i);
|
||||
}
|
||||
}
|
||||
finished = 0;
|
||||
break;
|
||||
|
||||
lpfc_fill_vpd(phba, vpd, Length, &index);
|
||||
finished = 0;
|
||||
break;
|
||||
case 0x78:
|
||||
finished = 1;
|
||||
break;
|
||||
@ -4614,6 +4617,17 @@ lpfc_get_wwpn(struct lpfc_hba *phba)
|
||||
return rol64(wwn, 32);
|
||||
}
|
||||
|
||||
static unsigned short lpfc_get_sg_tablesize(struct lpfc_hba *phba)
|
||||
{
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
if (phba->cfg_xpsgl && !phba->nvmet_support)
|
||||
return LPFC_MAX_SG_TABLESIZE;
|
||||
else
|
||||
return phba->cfg_scsi_seg_cnt;
|
||||
else
|
||||
return phba->cfg_sg_seg_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_vmid_res_alloc - Allocates resources for VMID
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
@ -4716,42 +4730,26 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
|
||||
|
||||
/* Seed template for SCSI host registration */
|
||||
if (dev == &phba->pcidev->dev) {
|
||||
template = &phba->port_template;
|
||||
|
||||
if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) {
|
||||
/* Seed physical port template */
|
||||
memcpy(template, &lpfc_template, sizeof(*template));
|
||||
template = &lpfc_template;
|
||||
|
||||
if (use_no_reset_hba)
|
||||
/* template is for a no reset SCSI Host */
|
||||
template->eh_host_reset_handler = NULL;
|
||||
|
||||
/* Template for all vports this physical port creates */
|
||||
memcpy(&phba->vport_template, &lpfc_template,
|
||||
sizeof(*template));
|
||||
phba->vport_template.shost_groups = lpfc_vport_groups;
|
||||
phba->vport_template.eh_bus_reset_handler = NULL;
|
||||
phba->vport_template.eh_host_reset_handler = NULL;
|
||||
phba->vport_template.vendor_id = 0;
|
||||
|
||||
/* Initialize the host templates with updated value */
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
template->sg_tablesize = phba->cfg_scsi_seg_cnt;
|
||||
phba->vport_template.sg_tablesize =
|
||||
phba->cfg_scsi_seg_cnt;
|
||||
} else {
|
||||
template->sg_tablesize = phba->cfg_sg_seg_cnt;
|
||||
phba->vport_template.sg_tablesize =
|
||||
phba->cfg_sg_seg_cnt;
|
||||
}
|
||||
|
||||
/* Seed updated value of sg_tablesize */
|
||||
template->sg_tablesize = lpfc_get_sg_tablesize(phba);
|
||||
} else {
|
||||
/* NVMET is for physical port only */
|
||||
memcpy(template, &lpfc_template_nvme,
|
||||
sizeof(*template));
|
||||
template = &lpfc_template_nvme;
|
||||
}
|
||||
} else {
|
||||
template = &phba->vport_template;
|
||||
/* Seed vport template */
|
||||
template = &lpfc_vport_template;
|
||||
|
||||
/* Seed updated value of sg_tablesize */
|
||||
template->sg_tablesize = lpfc_get_sg_tablesize(phba);
|
||||
}
|
||||
|
||||
shost = scsi_host_alloc(template, sizeof(struct lpfc_vport));
|
||||
@ -4784,11 +4782,6 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
|
||||
|
||||
shost->dma_boundary =
|
||||
phba->sli4_hba.pc_sli4_params.sge_supp_len-1;
|
||||
|
||||
if (phba->cfg_xpsgl && !phba->nvmet_support)
|
||||
shost->sg_tablesize = LPFC_MAX_SG_TABLESIZE;
|
||||
else
|
||||
shost->sg_tablesize = phba->cfg_scsi_seg_cnt;
|
||||
} else
|
||||
/* SLI-3 has a limited number of hardware queues (3),
|
||||
* thus there is only one for FCP processing.
|
||||
@ -5569,38 +5562,12 @@ lpfc_async_link_speed_to_read_top(struct lpfc_hba *phba, uint8_t speed_code)
|
||||
void
|
||||
lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba)
|
||||
{
|
||||
struct rxtable_entry *entry;
|
||||
int cnt = 0, head, tail, last, start;
|
||||
|
||||
head = atomic_read(&phba->rxtable_idx_head);
|
||||
tail = atomic_read(&phba->rxtable_idx_tail);
|
||||
if (!phba->rxtable || head == tail) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
|
||||
"4411 Rxtable is empty\n");
|
||||
return;
|
||||
}
|
||||
last = tail;
|
||||
start = head;
|
||||
|
||||
/* Display the last LPFC_MAX_RXMONITOR_DUMP entries from the rxtable */
|
||||
while (start != last) {
|
||||
if (start)
|
||||
start--;
|
||||
else
|
||||
start = LPFC_MAX_RXMONITOR_ENTRY - 1;
|
||||
entry = &phba->rxtable[start];
|
||||
if (!phba->rx_monitor) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"4410 %02d: MBPI %lld Xmit %lld Cmpl %lld "
|
||||
"Lat %lld ASz %lld Info %02d BWUtil %d "
|
||||
"Int %d slot %d\n",
|
||||
cnt, entry->max_bytes_per_interval,
|
||||
entry->total_bytes, entry->rcv_bytes,
|
||||
entry->avg_io_latency, entry->avg_io_size,
|
||||
entry->cmf_info, entry->timer_utilization,
|
||||
entry->timer_interval, start);
|
||||
cnt++;
|
||||
if (cnt >= LPFC_MAX_RXMONITOR_DUMP)
|
||||
return;
|
||||
"4411 Rx Monitor Info is empty.\n");
|
||||
} else {
|
||||
lpfc_rx_monitor_report(phba, phba->rx_monitor, NULL, 0,
|
||||
LPFC_MAX_RXMONITOR_DUMP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6007,9 +5974,8 @@ lpfc_cmf_timer(struct hrtimer *timer)
|
||||
{
|
||||
struct lpfc_hba *phba = container_of(timer, struct lpfc_hba,
|
||||
cmf_timer);
|
||||
struct rxtable_entry *entry;
|
||||
struct rx_info_entry entry;
|
||||
uint32_t io_cnt;
|
||||
uint32_t head, tail;
|
||||
uint32_t busy, max_read;
|
||||
uint64_t total, rcv, lat, mbpi, extra, cnt;
|
||||
int timer_interval = LPFC_CMF_INTERVAL;
|
||||
@ -6129,40 +6095,30 @@ lpfc_cmf_timer(struct hrtimer *timer)
|
||||
}
|
||||
|
||||
/* Save rxmonitor information for debug */
|
||||
if (phba->rxtable) {
|
||||
head = atomic_xchg(&phba->rxtable_idx_head,
|
||||
LPFC_RXMONITOR_TABLE_IN_USE);
|
||||
entry = &phba->rxtable[head];
|
||||
entry->total_bytes = total;
|
||||
entry->cmf_bytes = total + extra;
|
||||
entry->rcv_bytes = rcv;
|
||||
entry->cmf_busy = busy;
|
||||
entry->cmf_info = phba->cmf_active_info;
|
||||
if (phba->rx_monitor) {
|
||||
entry.total_bytes = total;
|
||||
entry.cmf_bytes = total + extra;
|
||||
entry.rcv_bytes = rcv;
|
||||
entry.cmf_busy = busy;
|
||||
entry.cmf_info = phba->cmf_active_info;
|
||||
if (io_cnt) {
|
||||
entry->avg_io_latency = div_u64(lat, io_cnt);
|
||||
entry->avg_io_size = div_u64(rcv, io_cnt);
|
||||
entry.avg_io_latency = div_u64(lat, io_cnt);
|
||||
entry.avg_io_size = div_u64(rcv, io_cnt);
|
||||
} else {
|
||||
entry->avg_io_latency = 0;
|
||||
entry->avg_io_size = 0;
|
||||
entry.avg_io_latency = 0;
|
||||
entry.avg_io_size = 0;
|
||||
}
|
||||
entry->max_read_cnt = max_read;
|
||||
entry->io_cnt = io_cnt;
|
||||
entry->max_bytes_per_interval = mbpi;
|
||||
entry.max_read_cnt = max_read;
|
||||
entry.io_cnt = io_cnt;
|
||||
entry.max_bytes_per_interval = mbpi;
|
||||
if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
|
||||
entry->timer_utilization = phba->cmf_last_ts;
|
||||
entry.timer_utilization = phba->cmf_last_ts;
|
||||
else
|
||||
entry->timer_utilization = ms;
|
||||
entry->timer_interval = ms;
|
||||
entry.timer_utilization = ms;
|
||||
entry.timer_interval = ms;
|
||||
phba->cmf_last_ts = 0;
|
||||
|
||||
/* Increment rxtable index */
|
||||
head = (head + 1) % LPFC_MAX_RXMONITOR_ENTRY;
|
||||
tail = atomic_read(&phba->rxtable_idx_tail);
|
||||
if (head == tail) {
|
||||
tail = (tail + 1) % LPFC_MAX_RXMONITOR_ENTRY;
|
||||
atomic_set(&phba->rxtable_idx_tail, tail);
|
||||
}
|
||||
atomic_set(&phba->rxtable_idx_head, head);
|
||||
lpfc_rx_monitor_record(phba->rx_monitor, &entry);
|
||||
}
|
||||
|
||||
if (phba->cmf_active_mode == LPFC_CFG_MONITOR) {
|
||||
@ -6232,6 +6188,7 @@ lpfc_update_trunk_link_status(struct lpfc_hba *phba,
|
||||
{
|
||||
uint8_t port_fault = bf_get(lpfc_acqe_fc_la_trunk_linkmask, acqe_fc);
|
||||
uint8_t err = bf_get(lpfc_acqe_fc_la_trunk_fault, acqe_fc);
|
||||
u8 cnt = 0;
|
||||
|
||||
phba->sli4_hba.link_state.speed =
|
||||
lpfc_sli4_port_speed_parse(phba, LPFC_TRAILER_CODE_FC,
|
||||
@ -6250,26 +6207,36 @@ lpfc_update_trunk_link_status(struct lpfc_hba *phba,
|
||||
bf_get(lpfc_acqe_fc_la_trunk_link_status_port0, acqe_fc)
|
||||
? LPFC_LINK_UP : LPFC_LINK_DOWN;
|
||||
phba->trunk_link.link0.fault = port_fault & 0x1 ? err : 0;
|
||||
cnt++;
|
||||
}
|
||||
if (bf_get(lpfc_acqe_fc_la_trunk_config_port1, acqe_fc)) {
|
||||
phba->trunk_link.link1.state =
|
||||
bf_get(lpfc_acqe_fc_la_trunk_link_status_port1, acqe_fc)
|
||||
? LPFC_LINK_UP : LPFC_LINK_DOWN;
|
||||
phba->trunk_link.link1.fault = port_fault & 0x2 ? err : 0;
|
||||
cnt++;
|
||||
}
|
||||
if (bf_get(lpfc_acqe_fc_la_trunk_config_port2, acqe_fc)) {
|
||||
phba->trunk_link.link2.state =
|
||||
bf_get(lpfc_acqe_fc_la_trunk_link_status_port2, acqe_fc)
|
||||
? LPFC_LINK_UP : LPFC_LINK_DOWN;
|
||||
phba->trunk_link.link2.fault = port_fault & 0x4 ? err : 0;
|
||||
cnt++;
|
||||
}
|
||||
if (bf_get(lpfc_acqe_fc_la_trunk_config_port3, acqe_fc)) {
|
||||
phba->trunk_link.link3.state =
|
||||
bf_get(lpfc_acqe_fc_la_trunk_link_status_port3, acqe_fc)
|
||||
? LPFC_LINK_UP : LPFC_LINK_DOWN;
|
||||
phba->trunk_link.link3.fault = port_fault & 0x8 ? err : 0;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt)
|
||||
phba->trunk_link.phy_lnk_speed =
|
||||
phba->sli4_hba.link_state.logical_speed / (cnt * 1000);
|
||||
else
|
||||
phba->trunk_link.phy_lnk_speed = LPFC_LINK_SPEED_UNKNOWN;
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2910 Async FC Trunking Event - Speed:%d\n"
|
||||
"\tLogical speed:%d "
|
||||
@ -6347,7 +6314,7 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
|
||||
if (bf_get(lpfc_acqe_fc_la_att_type, acqe_fc) ==
|
||||
LPFC_FC_LA_TYPE_LINK_DOWN)
|
||||
phba->sli4_hba.link_state.logical_speed = 0;
|
||||
else if (!phba->sli4_hba.conf_trunk)
|
||||
else if (!phba->sli4_hba.conf_trunk)
|
||||
phba->sli4_hba.link_state.logical_speed =
|
||||
bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc) * 10;
|
||||
|
||||
@ -6465,7 +6432,7 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
|
||||
"2901 Async SLI event - Type:%d, Event Data: x%08x "
|
||||
"x%08x x%08x x%08x\n", evt_type,
|
||||
acqe_sli->event_data1, acqe_sli->event_data2,
|
||||
acqe_sli->reserved, acqe_sli->trailer);
|
||||
acqe_sli->event_data3, acqe_sli->trailer);
|
||||
|
||||
port_name = phba->Port[0];
|
||||
if (port_name == 0x00)
|
||||
@ -6494,7 +6461,7 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
|
||||
temp_event_data.event_code = LPFC_NORMAL_TEMP;
|
||||
temp_event_data.data = (uint32_t)acqe_sli->event_data1;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI | LOG_LDS_EVENT,
|
||||
"3191 Normal Temperature:%d Celsius - Port Name %c\n",
|
||||
acqe_sli->event_data1, port_name);
|
||||
|
||||
@ -6672,6 +6639,15 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LPFC_SLI_EVENT_TYPE_RD_SIGNAL:
|
||||
/* May be accompanied by a temperature event */
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_SLI | LOG_LINK_EVENT | LOG_LDS_EVENT,
|
||||
"2902 Remote Degrade Signaling: x%08x x%08x "
|
||||
"x%08x\n",
|
||||
acqe_sli->event_data1, acqe_sli->event_data2,
|
||||
acqe_sli->event_data3);
|
||||
break;
|
||||
default:
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"3193 Unrecognized SLI event, type: 0x%x",
|
||||
@ -7085,6 +7061,12 @@ lpfc_cgn_params_val(struct lpfc_hba *phba, struct lpfc_cgn_param *p_cfg_param)
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
}
|
||||
|
||||
static const char * const lpfc_cmf_mode_to_str[] = {
|
||||
"OFF",
|
||||
"MANAGED",
|
||||
"MONITOR",
|
||||
};
|
||||
|
||||
/**
|
||||
* lpfc_cgn_params_parse - Process a FW cong parm change event
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
@ -7104,6 +7086,7 @@ lpfc_cgn_params_parse(struct lpfc_hba *phba,
|
||||
{
|
||||
struct lpfc_cgn_info *cp;
|
||||
uint32_t crc, oldmode;
|
||||
char acr_string[4] = {0};
|
||||
|
||||
/* Make sure the FW has encoded the correct magic number to
|
||||
* validate the congestion parameter in FW memory.
|
||||
@ -7180,9 +7163,6 @@ lpfc_cgn_params_parse(struct lpfc_hba *phba,
|
||||
lpfc_issue_els_edc(phba->pport, 0);
|
||||
break;
|
||||
case LPFC_CFG_MONITOR:
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"4661 Switch from MANAGED to "
|
||||
"`MONITOR mode\n");
|
||||
phba->cmf_max_bytes_per_interval =
|
||||
phba->cmf_link_byte_count;
|
||||
|
||||
@ -7201,14 +7181,26 @@ lpfc_cgn_params_parse(struct lpfc_hba *phba,
|
||||
lpfc_issue_els_edc(phba->pport, 0);
|
||||
break;
|
||||
case LPFC_CFG_MANAGED:
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"4662 Switch from MONITOR to "
|
||||
"MANAGED mode\n");
|
||||
lpfc_cmf_signal_init(phba);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (oldmode != LPFC_CFG_OFF ||
|
||||
oldmode != phba->cgn_p.cgn_param_mode) {
|
||||
if (phba->cgn_p.cgn_param_mode == LPFC_CFG_MANAGED)
|
||||
scnprintf(acr_string, sizeof(acr_string), "%u",
|
||||
phba->cgn_p.cgn_param_level0);
|
||||
else
|
||||
scnprintf(acr_string, sizeof(acr_string), "NA");
|
||||
|
||||
dev_info(&phba->pcidev->dev, "%d: "
|
||||
"4663 CMF: Mode %s acr %s\n",
|
||||
phba->brd_no,
|
||||
lpfc_cmf_mode_to_str
|
||||
[phba->cgn_p.cgn_param_mode],
|
||||
acr_string);
|
||||
}
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
|
||||
"4669 FW cgn parm buf wrong magic 0x%x "
|
||||
@ -8315,8 +8307,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
&phba->pcidev->dev,
|
||||
phba->cfg_sg_dma_buf_size,
|
||||
i, 0);
|
||||
if (!phba->lpfc_sg_dma_buf_pool)
|
||||
if (!phba->lpfc_sg_dma_buf_pool) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free_bsmbx;
|
||||
}
|
||||
|
||||
phba->lpfc_cmd_rsp_buf_pool =
|
||||
dma_pool_create("lpfc_cmd_rsp_buf_pool",
|
||||
@ -8324,8 +8318,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
sizeof(struct fcp_cmnd) +
|
||||
sizeof(struct fcp_rsp),
|
||||
i, 0);
|
||||
if (!phba->lpfc_cmd_rsp_buf_pool)
|
||||
if (!phba->lpfc_cmd_rsp_buf_pool) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free_sg_dma_buf;
|
||||
}
|
||||
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
|
||||
@ -12416,7 +12412,7 @@ lpfc_hba_eq_hdl_array_init(struct lpfc_hba *phba)
|
||||
|
||||
for (i = 0; i < phba->cfg_irq_chann; i++) {
|
||||
eqhdl = lpfc_get_eq_hdl(i);
|
||||
eqhdl->irq = LPFC_VECTOR_MAP_EMPTY;
|
||||
eqhdl->irq = LPFC_IRQ_EMPTY;
|
||||
eqhdl->phba = phba;
|
||||
}
|
||||
}
|
||||
@ -12789,7 +12785,7 @@ static void __lpfc_cpuhp_remove(struct lpfc_hba *phba)
|
||||
|
||||
static void lpfc_cpuhp_remove(struct lpfc_hba *phba)
|
||||
{
|
||||
if (phba->pport->fc_flag & FC_OFFLINE_MODE)
|
||||
if (phba->pport && (phba->pport->fc_flag & FC_OFFLINE_MODE))
|
||||
return;
|
||||
|
||||
__lpfc_cpuhp_remove(phba);
|
||||
@ -13053,9 +13049,17 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
|
||||
LPFC_DRIVER_HANDLER_NAME"%d", index);
|
||||
|
||||
eqhdl->idx = index;
|
||||
rc = request_irq(pci_irq_vector(phba->pcidev, index),
|
||||
&lpfc_sli4_hba_intr_handler, 0,
|
||||
name, eqhdl);
|
||||
rc = pci_irq_vector(phba->pcidev, index);
|
||||
if (rc < 0) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
||||
"0489 MSI-X fast-path (%d) "
|
||||
"pci_irq_vec failed (%d)\n", index, rc);
|
||||
goto cfg_fail_out;
|
||||
}
|
||||
eqhdl->irq = rc;
|
||||
|
||||
rc = request_irq(eqhdl->irq, &lpfc_sli4_hba_intr_handler, 0,
|
||||
name, eqhdl);
|
||||
if (rc) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
||||
"0486 MSI-X fast-path (%d) "
|
||||
@ -13063,8 +13067,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
|
||||
goto cfg_fail_out;
|
||||
}
|
||||
|
||||
eqhdl->irq = pci_irq_vector(phba->pcidev, index);
|
||||
|
||||
if (aff_mask) {
|
||||
/* If found a neighboring online cpu, set affinity */
|
||||
if (cpu_select < nr_cpu_ids)
|
||||
@ -13181,7 +13183,14 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
|
||||
}
|
||||
|
||||
eqhdl = lpfc_get_eq_hdl(0);
|
||||
eqhdl->irq = pci_irq_vector(phba->pcidev, 0);
|
||||
rc = pci_irq_vector(phba->pcidev, 0);
|
||||
if (rc < 0) {
|
||||
pci_free_irq_vectors(phba->pcidev);
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
||||
"0496 MSI pci_irq_vec failed (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
eqhdl->irq = rc;
|
||||
|
||||
cpu = cpumask_first(cpu_present_mask);
|
||||
lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ, cpu);
|
||||
@ -13208,8 +13217,8 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
|
||||
* MSI-X -> MSI -> IRQ.
|
||||
*
|
||||
* Return codes
|
||||
* 0 - successful
|
||||
* other values - error
|
||||
* Interrupt mode (2, 1, 0) - successful
|
||||
* LPFC_INTR_ERROR - error
|
||||
**/
|
||||
static uint32_t
|
||||
lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
|
||||
@ -13254,7 +13263,14 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
|
||||
intr_mode = 0;
|
||||
|
||||
eqhdl = lpfc_get_eq_hdl(0);
|
||||
eqhdl->irq = pci_irq_vector(phba->pcidev, 0);
|
||||
retval = pci_irq_vector(phba->pcidev, 0);
|
||||
if (retval < 0) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
||||
"0502 INTR pci_irq_vec failed (%d)\n",
|
||||
retval);
|
||||
return LPFC_INTR_ERROR;
|
||||
}
|
||||
eqhdl->irq = retval;
|
||||
|
||||
cpu = cpumask_first(cpu_present_mask);
|
||||
lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ,
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */
|
||||
#define LOG_LIBDFC 0x00002000 /* Libdfc events */
|
||||
#define LOG_VPORT 0x00004000 /* NPIV events */
|
||||
#define LOG_SECURITY 0x00008000 /* Security events */
|
||||
#define LOG_LDS_EVENT 0x00008000 /* Link Degrade Signaling events */
|
||||
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
|
||||
#define LOG_FIP 0x00020000 /* FIP events */
|
||||
#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2014 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -344,9 +344,12 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
|
||||
phba->cgn_i = NULL;
|
||||
}
|
||||
|
||||
/* Free RX table */
|
||||
kfree(phba->rxtable);
|
||||
phba->rxtable = NULL;
|
||||
/* Free RX Monitor */
|
||||
if (phba->rx_monitor) {
|
||||
lpfc_rx_monitor_destroy_ring(phba->rx_monitor);
|
||||
kfree(phba->rx_monitor);
|
||||
phba->rx_monitor = NULL;
|
||||
}
|
||||
|
||||
/* Free the iocb lookup array */
|
||||
kfree(psli->iocbq_lookup);
|
||||
|
@ -111,62 +111,6 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
|
||||
|
||||
#define LPFC_INVALID_REFTAG ((u32)-1)
|
||||
|
||||
/**
|
||||
* lpfc_update_stats - Update statistical data for the command completion
|
||||
* @vport: The virtual port on which this call is executing.
|
||||
* @lpfc_cmd: lpfc scsi command object pointer.
|
||||
*
|
||||
* This function is called when there is a command completion and this
|
||||
* function updates the statistical data for the command completion.
|
||||
**/
|
||||
static void
|
||||
lpfc_update_stats(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_rport_data *rdata;
|
||||
struct lpfc_nodelist *pnode;
|
||||
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
|
||||
unsigned long flags;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
unsigned long latency;
|
||||
int i;
|
||||
|
||||
if (!vport->stat_data_enabled ||
|
||||
vport->stat_data_blocked ||
|
||||
(cmd->result))
|
||||
return;
|
||||
|
||||
latency = jiffies_to_msecs((long)jiffies - (long)lpfc_cmd->start_time);
|
||||
rdata = lpfc_cmd->rdata;
|
||||
pnode = rdata->pnode;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (!pnode ||
|
||||
!pnode->lat_data ||
|
||||
(phba->bucket_type == LPFC_NO_BUCKET)) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (phba->bucket_type == LPFC_LINEAR_BUCKET) {
|
||||
i = (latency + phba->bucket_step - 1 - phba->bucket_base)/
|
||||
phba->bucket_step;
|
||||
/* check array subscript bounds */
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
else if (i >= LPFC_MAX_BUCKET_COUNT)
|
||||
i = LPFC_MAX_BUCKET_COUNT - 1;
|
||||
} else {
|
||||
for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++)
|
||||
if (latency <= (phba->bucket_base +
|
||||
((1<<i)*phba->bucket_step)))
|
||||
break;
|
||||
}
|
||||
|
||||
pnode->lat_data[i].cmd_count++;
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
@ -4335,8 +4279,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
|
||||
cmd->retries, scsi_get_resid(cmd));
|
||||
}
|
||||
|
||||
lpfc_update_stats(vport, lpfc_cmd);
|
||||
|
||||
if (vport->cfg_max_scsicmpl_time &&
|
||||
time_after(jiffies, lpfc_cmd->start_time +
|
||||
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
|
||||
@ -4617,7 +4559,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
scsi_get_resid(cmd));
|
||||
}
|
||||
|
||||
lpfc_update_stats(vport, lpfc_cmd);
|
||||
if (vport->cfg_max_scsicmpl_time &&
|
||||
time_after(jiffies, lpfc_cmd->start_time +
|
||||
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
|
||||
@ -6853,3 +6794,30 @@ struct scsi_host_template lpfc_template = {
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
struct scsi_host_template lpfc_vport_template = {
|
||||
.module = THIS_MODULE,
|
||||
.name = LPFC_DRIVER_NAME,
|
||||
.proc_name = LPFC_DRIVER_NAME,
|
||||
.info = lpfc_info,
|
||||
.queuecommand = lpfc_queuecommand,
|
||||
.eh_timed_out = fc_eh_timed_out,
|
||||
.eh_should_retry_cmd = fc_eh_should_retry_cmd,
|
||||
.eh_abort_handler = lpfc_abort_handler,
|
||||
.eh_device_reset_handler = lpfc_device_reset_handler,
|
||||
.eh_target_reset_handler = lpfc_target_reset_handler,
|
||||
.eh_bus_reset_handler = NULL,
|
||||
.eh_host_reset_handler = NULL,
|
||||
.slave_alloc = lpfc_slave_alloc,
|
||||
.slave_configure = lpfc_slave_configure,
|
||||
.slave_destroy = lpfc_slave_destroy,
|
||||
.scan_finished = lpfc_scan_finished,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT,
|
||||
.cmd_per_lun = LPFC_CMD_PER_LUN,
|
||||
.shost_groups = lpfc_vport_groups,
|
||||
.max_sectors = 0xFFFFFFFF,
|
||||
.vendor_id = 0,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -126,10 +126,6 @@ struct fcp_cmnd {
|
||||
|
||||
};
|
||||
|
||||
struct lpfc_scsicmd_bkt {
|
||||
uint32_t cmd_count;
|
||||
};
|
||||
|
||||
#define LPFC_SCSI_DMA_EXT_SIZE 264
|
||||
#define LPFC_BPL_SIZE 1024
|
||||
#define MDAC_DIRECT_CMD 0x22
|
||||
|
@ -1916,6 +1916,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
|
||||
unsigned long iflags;
|
||||
u32 ret_val;
|
||||
u32 atot, wtot, max;
|
||||
u16 warn_sync_period = 0;
|
||||
|
||||
/* First address any alarm / warning activity */
|
||||
atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
|
||||
@ -1970,10 +1971,14 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
|
||||
lpfc_acqe_cgn_frequency;
|
||||
bf_set(cmf_sync_wsigmax, &wqe->cmf_sync, max);
|
||||
bf_set(cmf_sync_wsigcnt, &wqe->cmf_sync, wtot);
|
||||
warn_sync_period = lpfc_acqe_cgn_frequency;
|
||||
} else {
|
||||
/* We hit a FPIN warning condition */
|
||||
bf_set(cmf_sync_wfpinmax, &wqe->cmf_sync, 1);
|
||||
bf_set(cmf_sync_wfpincnt, &wqe->cmf_sync, 1);
|
||||
if (phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ)
|
||||
warn_sync_period =
|
||||
LPFC_MSECS_TO_SECS(phba->cgn_fpin_frequency);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1989,6 +1994,7 @@ initpath:
|
||||
bf_set(cmf_sync_reqtag, &wqe->cmf_sync, sync_buf->iotag);
|
||||
|
||||
bf_set(cmf_sync_qosd, &wqe->cmf_sync, 1);
|
||||
bf_set(cmf_sync_period, &wqe->cmf_sync, warn_sync_period);
|
||||
|
||||
bf_set(cmf_sync_cmd_type, &wqe->cmf_sync, CMF_SYNC_COMMAND);
|
||||
bf_set(cmf_sync_wqec, &wqe->cmf_sync, 1);
|
||||
@ -2850,6 +2856,7 @@ void
|
||||
lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
{
|
||||
struct lpfc_vport *vport = pmb->vport;
|
||||
struct lpfc_dmabuf *mp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct Scsi_Host *shost;
|
||||
uint16_t rpi, vpi;
|
||||
@ -2862,6 +2869,12 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
if (!(phba->pport->load_flag & FC_UNLOADING) &&
|
||||
pmb->u.mb.mbxCommand == MBX_REG_LOGIN64 &&
|
||||
!pmb->u.mb.mbxStatus) {
|
||||
mp = (struct lpfc_dmabuf *)pmb->ctx_buf;
|
||||
if (mp) {
|
||||
pmb->ctx_buf = NULL;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
rpi = pmb->u.mb.un.varWords[0];
|
||||
vpi = pmb->u.mb.un.varRegLogin.vpi;
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
@ -6202,6 +6215,9 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
|
||||
struct lpfc_mbx_get_rsrc_extent_info *rsrc_info;
|
||||
LPFC_MBOXQ_t *mbox;
|
||||
|
||||
*extnt_count = 0;
|
||||
*extnt_size = 0;
|
||||
|
||||
mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!mbox)
|
||||
return -ENOMEM;
|
||||
@ -6817,8 +6833,13 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
|
||||
bf_set(lpfc_mbx_set_feature_mi, &mbox->u.mqe.un.set_feature,
|
||||
phba->sli4_hba.pc_sli4_params.mi_ver);
|
||||
break;
|
||||
case LPFC_SET_LD_SIGNAL:
|
||||
mbox->u.mqe.un.set_feature.feature = LPFC_SET_LD_SIGNAL;
|
||||
mbox->u.mqe.un.set_feature.param_len = 16;
|
||||
bf_set(lpfc_mbx_set_feature_lds_qry,
|
||||
&mbox->u.mqe.un.set_feature, LPFC_QUERY_LDS_OP);
|
||||
break;
|
||||
case LPFC_SET_ENABLE_CMF:
|
||||
bf_set(lpfc_mbx_set_feature_dd, &mbox->u.mqe.un.set_feature, 1);
|
||||
mbox->u.mqe.un.set_feature.feature = LPFC_SET_ENABLE_CMF;
|
||||
mbox->u.mqe.un.set_feature.param_len = 4;
|
||||
bf_set(lpfc_mbx_set_feature_cmf,
|
||||
@ -7813,6 +7834,62 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_mbx_cmpl_read_lds_params(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
{
|
||||
union lpfc_sli4_cfg_shdr *shdr;
|
||||
u32 shdr_status, shdr_add_status;
|
||||
|
||||
shdr = (union lpfc_sli4_cfg_shdr *)
|
||||
&pmb->u.mqe.un.sli4_config.header.cfg_shdr;
|
||||
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
||||
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
||||
if (shdr_status || shdr_add_status || pmb->u.mb.mbxStatus) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_LDS_EVENT | LOG_MBOX,
|
||||
"4622 SET_FEATURE (x%x) mbox failed, "
|
||||
"status x%x add_status x%x, mbx status x%x\n",
|
||||
LPFC_SET_LD_SIGNAL, shdr_status,
|
||||
shdr_add_status, pmb->u.mb.mbxStatus);
|
||||
phba->degrade_activate_threshold = 0;
|
||||
phba->degrade_deactivate_threshold = 0;
|
||||
phba->fec_degrade_interval = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phba->degrade_activate_threshold = pmb->u.mqe.un.set_feature.word7;
|
||||
phba->degrade_deactivate_threshold = pmb->u.mqe.un.set_feature.word8;
|
||||
phba->fec_degrade_interval = pmb->u.mqe.un.set_feature.word10;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_LDS_EVENT,
|
||||
"4624 Success: da x%x dd x%x interval x%x\n",
|
||||
phba->degrade_activate_threshold,
|
||||
phba->degrade_deactivate_threshold,
|
||||
phba->fec_degrade_interval);
|
||||
out:
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_read_lds_params(struct lpfc_hba *phba)
|
||||
{
|
||||
LPFC_MBOXQ_t *mboxq;
|
||||
int rc;
|
||||
|
||||
mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!mboxq)
|
||||
return -ENOMEM;
|
||||
|
||||
lpfc_set_features(phba, mboxq, LPFC_SET_LD_SIGNAL);
|
||||
mboxq->vport = phba->pport;
|
||||
mboxq->mbox_cmpl = lpfc_mbx_cmpl_read_lds_params;
|
||||
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
|
||||
if (rc == MBX_NOT_FINISHED) {
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_mbx_cmpl_cgn_set_ftrs(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
{
|
||||
@ -7959,6 +8036,172 @@ static void lpfc_sli4_dip(struct lpfc_hba *phba)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rx_monitor_create_ring - Initialize ring buffer for rx_monitor
|
||||
* @rx_monitor: Pointer to lpfc_rx_info_monitor object
|
||||
* @entries: Number of rx_info_entry objects to allocate in ring
|
||||
*
|
||||
* Return:
|
||||
* 0 - Success
|
||||
* ENOMEM - Failure to kmalloc
|
||||
**/
|
||||
int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
|
||||
u32 entries)
|
||||
{
|
||||
rx_monitor->ring = kmalloc_array(entries, sizeof(struct rx_info_entry),
|
||||
GFP_KERNEL);
|
||||
if (!rx_monitor->ring)
|
||||
return -ENOMEM;
|
||||
|
||||
rx_monitor->head_idx = 0;
|
||||
rx_monitor->tail_idx = 0;
|
||||
spin_lock_init(&rx_monitor->lock);
|
||||
rx_monitor->entries = entries;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rx_monitor_destroy_ring - Free ring buffer for rx_monitor
|
||||
* @rx_monitor: Pointer to lpfc_rx_info_monitor object
|
||||
**/
|
||||
void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor)
|
||||
{
|
||||
spin_lock(&rx_monitor->lock);
|
||||
kfree(rx_monitor->ring);
|
||||
rx_monitor->ring = NULL;
|
||||
rx_monitor->entries = 0;
|
||||
rx_monitor->head_idx = 0;
|
||||
rx_monitor->tail_idx = 0;
|
||||
spin_unlock(&rx_monitor->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rx_monitor_record - Insert an entry into rx_monitor's ring
|
||||
* @rx_monitor: Pointer to lpfc_rx_info_monitor object
|
||||
* @entry: Pointer to rx_info_entry
|
||||
*
|
||||
* Used to insert an rx_info_entry into rx_monitor's ring. Note that this is a
|
||||
* deep copy of rx_info_entry not a shallow copy of the rx_info_entry ptr.
|
||||
*
|
||||
* This is called from lpfc_cmf_timer, which is in timer/softirq context.
|
||||
*
|
||||
* In cases of old data overflow, we do a best effort of FIFO order.
|
||||
**/
|
||||
void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor,
|
||||
struct rx_info_entry *entry)
|
||||
{
|
||||
struct rx_info_entry *ring = rx_monitor->ring;
|
||||
u32 *head_idx = &rx_monitor->head_idx;
|
||||
u32 *tail_idx = &rx_monitor->tail_idx;
|
||||
spinlock_t *ring_lock = &rx_monitor->lock;
|
||||
u32 ring_size = rx_monitor->entries;
|
||||
|
||||
spin_lock(ring_lock);
|
||||
memcpy(&ring[*tail_idx], entry, sizeof(*entry));
|
||||
*tail_idx = (*tail_idx + 1) % ring_size;
|
||||
|
||||
/* Best effort of FIFO saved data */
|
||||
if (*tail_idx == *head_idx)
|
||||
*head_idx = (*head_idx + 1) % ring_size;
|
||||
|
||||
spin_unlock(ring_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rx_monitor_report - Read out rx_monitor's ring
|
||||
* @phba: Pointer to lpfc_hba object
|
||||
* @rx_monitor: Pointer to lpfc_rx_info_monitor object
|
||||
* @buf: Pointer to char buffer that will contain rx monitor info data
|
||||
* @buf_len: Length buf including null char
|
||||
* @max_read_entries: Maximum number of entries to read out of ring
|
||||
*
|
||||
* Used to dump/read what's in rx_monitor's ring buffer.
|
||||
*
|
||||
* If buf is NULL || buf_len == 0, then it is implied that we want to log the
|
||||
* information to kmsg instead of filling out buf.
|
||||
*
|
||||
* Return:
|
||||
* Number of entries read out of the ring
|
||||
**/
|
||||
u32 lpfc_rx_monitor_report(struct lpfc_hba *phba,
|
||||
struct lpfc_rx_info_monitor *rx_monitor, char *buf,
|
||||
u32 buf_len, u32 max_read_entries)
|
||||
{
|
||||
struct rx_info_entry *ring = rx_monitor->ring;
|
||||
struct rx_info_entry *entry;
|
||||
u32 *head_idx = &rx_monitor->head_idx;
|
||||
u32 *tail_idx = &rx_monitor->tail_idx;
|
||||
spinlock_t *ring_lock = &rx_monitor->lock;
|
||||
u32 ring_size = rx_monitor->entries;
|
||||
u32 cnt = 0;
|
||||
char tmp[DBG_LOG_STR_SZ] = {0};
|
||||
bool log_to_kmsg = (!buf || !buf_len) ? true : false;
|
||||
|
||||
if (!log_to_kmsg) {
|
||||
/* clear the buffer to be sure */
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
scnprintf(buf, buf_len, "\t%-16s%-16s%-16s%-16s%-8s%-8s%-8s"
|
||||
"%-8s%-8s%-8s%-16s\n",
|
||||
"MaxBPI", "Tot_Data_CMF",
|
||||
"Tot_Data_Cmd", "Tot_Data_Cmpl",
|
||||
"Lat(us)", "Avg_IO", "Max_IO", "Bsy",
|
||||
"IO_cnt", "Info", "BWutil(ms)");
|
||||
}
|
||||
|
||||
/* Needs to be _bh because record is called from timer interrupt
|
||||
* context
|
||||
*/
|
||||
spin_lock_bh(ring_lock);
|
||||
while (*head_idx != *tail_idx) {
|
||||
entry = &ring[*head_idx];
|
||||
|
||||
/* Read out this entry's data. */
|
||||
if (!log_to_kmsg) {
|
||||
/* If !log_to_kmsg, then store to buf. */
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"%03d:\t%-16llu%-16llu%-16llu%-16llu%-8llu"
|
||||
"%-8llu%-8llu%-8u%-8u%-8u%u(%u)\n",
|
||||
*head_idx, entry->max_bytes_per_interval,
|
||||
entry->cmf_bytes, entry->total_bytes,
|
||||
entry->rcv_bytes, entry->avg_io_latency,
|
||||
entry->avg_io_size, entry->max_read_cnt,
|
||||
entry->cmf_busy, entry->io_cnt,
|
||||
entry->cmf_info, entry->timer_utilization,
|
||||
entry->timer_interval);
|
||||
|
||||
/* Check for buffer overflow */
|
||||
if ((strlen(buf) + strlen(tmp)) >= buf_len)
|
||||
break;
|
||||
|
||||
/* Append entry's data to buffer */
|
||||
strlcat(buf, tmp, buf_len);
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"4410 %02u: MBPI %llu Xmit %llu "
|
||||
"Cmpl %llu Lat %llu ASz %llu Info %02u "
|
||||
"BWUtil %u Int %u slot %u\n",
|
||||
cnt, entry->max_bytes_per_interval,
|
||||
entry->total_bytes, entry->rcv_bytes,
|
||||
entry->avg_io_latency,
|
||||
entry->avg_io_size, entry->cmf_info,
|
||||
entry->timer_utilization,
|
||||
entry->timer_interval, *head_idx);
|
||||
}
|
||||
|
||||
*head_idx = (*head_idx + 1) % ring_size;
|
||||
|
||||
/* Don't feed more than max_read_entries */
|
||||
cnt++;
|
||||
if (cnt >= max_read_entries)
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(ring_lock);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_cmf_setup - Initialize idle_stat tracking
|
||||
* @phba: Pointer to HBA context object.
|
||||
@ -8133,19 +8376,29 @@ no_cmf:
|
||||
phba->cmf_interval_rate = LPFC_CMF_INTERVAL;
|
||||
|
||||
/* Allocate RX Monitor Buffer */
|
||||
if (!phba->rxtable) {
|
||||
phba->rxtable = kmalloc_array(LPFC_MAX_RXMONITOR_ENTRY,
|
||||
sizeof(struct rxtable_entry),
|
||||
GFP_KERNEL);
|
||||
if (!phba->rxtable) {
|
||||
if (!phba->rx_monitor) {
|
||||
phba->rx_monitor = kzalloc(sizeof(*phba->rx_monitor),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!phba->rx_monitor) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2644 Failed to alloc memory "
|
||||
"for RX Monitor Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Instruct the rx_monitor object to instantiate its ring */
|
||||
if (lpfc_rx_monitor_create_ring(phba->rx_monitor,
|
||||
LPFC_MAX_RXMONITOR_ENTRY)) {
|
||||
kfree(phba->rx_monitor);
|
||||
phba->rx_monitor = NULL;
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2645 Failed to alloc memory "
|
||||
"for RX Monitor's Ring\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
atomic_set(&phba->rxtable_idx_head, 0);
|
||||
atomic_set(&phba->rxtable_idx_tail, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -10322,12 +10575,10 @@ static int
|
||||
__lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
||||
struct lpfc_iocbq *piocb, uint32_t flag)
|
||||
{
|
||||
int rc;
|
||||
struct lpfc_io_buf *lpfc_cmd = piocb->io_buf;
|
||||
|
||||
lpfc_prep_embed_io(phba, lpfc_cmd);
|
||||
rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
|
||||
return rc;
|
||||
return lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -489,7 +489,7 @@ struct lpfc_hba;
|
||||
#define LPFC_SLI4_HANDLER_NAME_SZ 16
|
||||
struct lpfc_hba_eq_hdl {
|
||||
uint32_t idx;
|
||||
uint16_t irq;
|
||||
int irq;
|
||||
char handler_name[LPFC_SLI4_HANDLER_NAME_SZ];
|
||||
struct lpfc_hba *phba;
|
||||
struct lpfc_queue *eq;
|
||||
@ -611,6 +611,8 @@ struct lpfc_vector_map_info {
|
||||
};
|
||||
#define LPFC_VECTOR_MAP_EMPTY 0xffff
|
||||
|
||||
#define LPFC_IRQ_EMPTY 0xffffffff
|
||||
|
||||
/* Multi-XRI pool */
|
||||
#define XRI_BATCH 8
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.5"
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.7"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
@ -245,9 +245,7 @@ int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
|
||||
/* allocate the per cpu variable for holding */
|
||||
/* the last access time stamp only if VMID is enabled */
|
||||
if (!vmp->last_io_time)
|
||||
vmp->last_io_time = __alloc_percpu(sizeof(u64),
|
||||
__alignof__(struct
|
||||
lpfc_vmid));
|
||||
vmp->last_io_time = alloc_percpu_gfp(u64, GFP_ATOMIC);
|
||||
if (!vmp->last_io_time) {
|
||||
hash_del(&vmp->hnode);
|
||||
vmp->flag = LPFC_VMID_SLOT_FREE;
|
||||
|
@ -809,74 +809,3 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
|
||||
kfree(vports);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_vport_reset_stat_data - Reset the statistical data for the vport
|
||||
* @vport: Pointer to vport object.
|
||||
*
|
||||
* This function resets the statistical data for the vport. This function
|
||||
* is called with the host_lock held
|
||||
**/
|
||||
void
|
||||
lpfc_vport_reset_stat_data(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
if (ndlp->lat_data)
|
||||
memset(ndlp->lat_data, 0, LPFC_MAX_BUCKET_COUNT *
|
||||
sizeof(struct lpfc_scsicmd_bkt));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_alloc_bucket - Allocate data buffer required for statistical data
|
||||
* @vport: Pointer to vport object.
|
||||
*
|
||||
* This function allocates data buffer required for all the FC
|
||||
* nodes of the vport to collect statistical data.
|
||||
**/
|
||||
void
|
||||
lpfc_alloc_bucket(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
|
||||
kfree(ndlp->lat_data);
|
||||
ndlp->lat_data = NULL;
|
||||
|
||||
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
|
||||
ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
|
||||
sizeof(struct lpfc_scsicmd_bkt),
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (!ndlp->lat_data)
|
||||
lpfc_printf_vlog(vport, KERN_ERR,
|
||||
LOG_TRACE_EVENT,
|
||||
"0287 lpfc_alloc_bucket failed to "
|
||||
"allocate statistical data buffer DID "
|
||||
"0x%x\n", ndlp->nlp_DID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_free_bucket - Free data buffer required for statistical data
|
||||
* @vport: Pointer to vport object.
|
||||
*
|
||||
* Th function frees statistical data buffer of all the FC
|
||||
* nodes of the vport.
|
||||
**/
|
||||
void
|
||||
lpfc_free_bucket(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
|
||||
kfree(ndlp->lat_data);
|
||||
ndlp->lat_data = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -115,8 +115,4 @@ struct vport_cmd_tag {
|
||||
void lpfc_vport_set_state(struct lpfc_vport *vport,
|
||||
enum fc_vport_state new_state);
|
||||
|
||||
void lpfc_vport_reset_stat_data(struct lpfc_vport *);
|
||||
void lpfc_alloc_bucket(struct lpfc_vport *);
|
||||
void lpfc_free_bucket(struct lpfc_vport *);
|
||||
|
||||
#endif /* H_LPFC_VPORT */
|
||||
|
@ -3979,7 +3979,7 @@ megaraid_mbox_app_hndl_show(struct device *dev, struct device_attribute *attr, c
|
||||
|
||||
app_hndl = mraid_mm_adapter_app_handle(adapter->unique_id);
|
||||
|
||||
return snprintf(buf, 8, "%u\n", app_hndl);
|
||||
return sysfs_emit(buf, "%u\n", app_hndl);
|
||||
}
|
||||
|
||||
|
||||
@ -4048,7 +4048,7 @@ megaraid_mbox_ld_show(struct device *dev, struct device_attribute *attr, char *b
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(buf, 36, "%d %d %d %d\n", scsi_id, logical_drv,
|
||||
return sysfs_emit(buf, "%d %d %d %d\n", scsi_id, logical_drv,
|
||||
ldid_map, app_hndl);
|
||||
}
|
||||
|
||||
|
@ -4021,10 +4021,8 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
|
||||
u32 mfiStatus;
|
||||
u32 fw_state;
|
||||
|
||||
if ((mfiStatus = instance->instancet->check_reset(instance,
|
||||
instance->reg_set)) == 1) {
|
||||
if (instance->instancet->check_reset(instance, instance->reg_set) == 1)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mfiStatus = instance->instancet->clear_intr(instance);
|
||||
if (mfiStatus == 0) {
|
||||
@ -5155,9 +5153,9 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance)
|
||||
fusion->current_map_sz = ventura_map_sz;
|
||||
fusion->max_map_sz = ventura_map_sz;
|
||||
} else {
|
||||
fusion->old_map_sz = sizeof(struct MR_FW_RAID_MAP) +
|
||||
(sizeof(struct MR_LD_SPAN_MAP) *
|
||||
(instance->fw_supported_vd_count - 1));
|
||||
fusion->old_map_sz =
|
||||
struct_size((struct MR_FW_RAID_MAP *)0, ldSpanMap,
|
||||
instance->fw_supported_vd_count);
|
||||
fusion->new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT);
|
||||
|
||||
fusion->max_map_sz =
|
||||
@ -5790,10 +5788,10 @@ megasas_setup_jbod_map(struct megasas_instance *instance)
|
||||
{
|
||||
int i;
|
||||
struct fusion_context *fusion = instance->ctrl_context;
|
||||
u32 pd_seq_map_sz;
|
||||
size_t pd_seq_map_sz;
|
||||
|
||||
pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
|
||||
(sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1));
|
||||
pd_seq_map_sz = struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, seq,
|
||||
MAX_PHYSICAL_DEVICES);
|
||||
|
||||
instance->use_seqnum_jbod_fp =
|
||||
instance->support_seqnum_jbod_fp;
|
||||
@ -7968,7 +7966,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
||||
struct Scsi_Host *host;
|
||||
struct megasas_instance *instance;
|
||||
struct fusion_context *fusion;
|
||||
u32 pd_seq_map_sz;
|
||||
size_t pd_seq_map_sz;
|
||||
|
||||
instance = pci_get_drvdata(pdev);
|
||||
|
||||
@ -8040,9 +8038,9 @@ skip_firing_dcmds:
|
||||
|
||||
if (instance->adapter_type != MFI_SERIES) {
|
||||
megasas_release_fusion(instance);
|
||||
pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
|
||||
(sizeof(struct MR_PD_CFG_SEQ) *
|
||||
(MAX_PHYSICAL_DEVICES - 1));
|
||||
pd_seq_map_sz =
|
||||
struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0,
|
||||
seq, MAX_PHYSICAL_DEVICES);
|
||||
for (i = 0; i < 2 ; i++) {
|
||||
if (fusion->ld_map[i])
|
||||
dma_free_coherent(&instance->pdev->dev,
|
||||
|
@ -326,9 +326,9 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
|
||||
else if (instance->supportmax256vd)
|
||||
expected_size = sizeof(struct MR_FW_RAID_MAP_EXT);
|
||||
else
|
||||
expected_size =
|
||||
(sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) +
|
||||
(sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount)));
|
||||
expected_size = struct_size((struct MR_FW_RAID_MAP *)0,
|
||||
ldSpanMap,
|
||||
le16_to_cpu(pDrvRaidMap->ldCount));
|
||||
|
||||
if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
|
||||
dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x",
|
||||
|
@ -1310,7 +1310,7 @@ megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) {
|
||||
|
||||
pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)];
|
||||
pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)];
|
||||
pd_seq_map_sz = struct_size(pd_sync, seq, MAX_PHYSICAL_DEVICES - 1);
|
||||
pd_seq_map_sz = struct_size(pd_sync, seq, MAX_PHYSICAL_DEVICES);
|
||||
|
||||
cmd = megasas_get_cmd(instance);
|
||||
if (!cmd) {
|
||||
|
@ -942,7 +942,7 @@ struct MR_FW_RAID_MAP {
|
||||
u8 reserved2[7];
|
||||
struct MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS];
|
||||
struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[1];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[];
|
||||
};
|
||||
|
||||
struct IO_REQUEST_INFO {
|
||||
@ -1053,7 +1053,7 @@ struct MR_FW_RAID_MAP_DYNAMIC {
|
||||
struct MR_RAID_MAP_DESC_TABLE
|
||||
raid_map_desc_table[RAID_MAP_DESC_TYPE_COUNT];
|
||||
/* Variable Size buffer containing all data */
|
||||
u32 raid_map_desc_data[1];
|
||||
u32 raid_map_desc_data[];
|
||||
}; /* Dynamicaly sized RAID MAp structure */
|
||||
|
||||
#define IEEE_SGE_FLAGS_ADDR_MASK (0x03)
|
||||
@ -1148,7 +1148,7 @@ typedef struct LOG_BLOCK_SPAN_INFO {
|
||||
|
||||
struct MR_FW_RAID_MAP_ALL {
|
||||
struct MR_FW_RAID_MAP raidMap;
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct MR_DRV_RAID_MAP {
|
||||
@ -1182,7 +1182,7 @@ struct MR_DRV_RAID_MAP {
|
||||
devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES_DYN];
|
||||
u16 ldTgtIdToLd[MAX_LOGICAL_DRIVES_DYN];
|
||||
struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_DYN];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[1];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[];
|
||||
|
||||
};
|
||||
|
||||
@ -1193,7 +1193,7 @@ struct MR_DRV_RAID_MAP {
|
||||
struct MR_DRV_RAID_MAP_ALL {
|
||||
|
||||
struct MR_DRV_RAID_MAP raidMap;
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN - 1];
|
||||
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN];
|
||||
} __packed;
|
||||
|
||||
|
||||
@ -1249,7 +1249,7 @@ struct MR_PD_CFG_SEQ {
|
||||
struct MR_PD_CFG_SEQ_NUM_SYNC {
|
||||
__le32 size;
|
||||
__le32 count;
|
||||
struct MR_PD_CFG_SEQ seq[1];
|
||||
struct MR_PD_CFG_SEQ seq[];
|
||||
} __packed;
|
||||
|
||||
/* stream detection */
|
||||
|
@ -3,3 +3,4 @@ obj-m += mpi3mr.o
|
||||
mpi3mr-y += mpi3mr_os.o \
|
||||
mpi3mr_fw.o \
|
||||
mpi3mr_app.o \
|
||||
mpi3mr_transport.o
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2017-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2017-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_CNFG_H
|
||||
#define MPI30_CNFG_H 1
|
||||
@ -100,6 +99,7 @@ struct mpi3_config_page_header {
|
||||
#define MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK (0xf0)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT (4)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_MASK (0x0f)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_SHIFT (0)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02)
|
||||
@ -135,6 +135,16 @@ struct mpi3_config_page_header {
|
||||
#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_ACTIVE (0x00000000)
|
||||
#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_PARTIAL (0x08000000)
|
||||
#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_SLUMBER (0x10000000)
|
||||
#define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_SHIFT (0)
|
||||
#define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_MASK (0x04000000)
|
||||
#define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_SHIFT (26)
|
||||
#define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT_MASK (0x02000000)
|
||||
#define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT_SHIFT (25)
|
||||
#define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_MASK (0x01000000)
|
||||
#define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_SHIFT (24)
|
||||
#define MPI3_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000)
|
||||
#define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_WITHIN (0x00200000)
|
||||
#define MPI3_SAS_PHYINFO_ZONING_ENABLED (0x00100000)
|
||||
#define MPI3_SAS_PHYINFO_REASON_MASK (0x000f0000)
|
||||
#define MPI3_SAS_PHYINFO_REASON_UNKNOWN (0x00000000)
|
||||
#define MPI3_SAS_PHYINFO_REASON_POWER_ON (0x00010000)
|
||||
@ -210,7 +220,7 @@ struct mpi3_man_page0 {
|
||||
u8 board_rework_day;
|
||||
u8 board_rework_month;
|
||||
__le16 board_rework_year;
|
||||
__le64 board_revision;
|
||||
u8 board_revision[8];
|
||||
u8 e_pack_fru[16];
|
||||
u8 product_name[256];
|
||||
};
|
||||
@ -226,6 +236,15 @@ struct mpi3_man_page1 {
|
||||
};
|
||||
|
||||
#define MPI3_MAN1_PAGEVERSION (0x00)
|
||||
struct mpi3_man_page2 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 flags;
|
||||
u8 reserved09[3];
|
||||
__le32 reserved0c[3];
|
||||
u8 oem_board_tracer_number[32];
|
||||
};
|
||||
#define MPI3_MAN2_PAGEVERSION (0x00)
|
||||
#define MPI3_MAN2_FLAGS_TRACER_PRESENT (0x01)
|
||||
struct mpi3_man5_phy_entry {
|
||||
__le64 ioc_wwid;
|
||||
__le64 device_name;
|
||||
@ -338,6 +357,8 @@ struct mpi3_man7_receptacle_info {
|
||||
#define MPI3_MAN7_LOCATION_INTERNAL (0x01)
|
||||
#define MPI3_MAN7_LOCATION_EXTERNAL (0x02)
|
||||
#define MPI3_MAN7_LOCATION_VIRTUAL (0x03)
|
||||
#define MPI3_MAN7_LOCATION_HOST (0x04)
|
||||
#define MPI3_MAN7_CONNECTOR_TYPE_NO_INFO (0x00)
|
||||
#define MPI3_MAN7_PEDCLK_ROUTING_MASK (0x10)
|
||||
#define MPI3_MAN7_PEDCLK_ROUTING_DIRECT (0x00)
|
||||
#define MPI3_MAN7_PEDCLK_ROUTING_CLOCK_BUFFER (0x10)
|
||||
@ -369,7 +390,8 @@ struct mpi3_man8_phy_info {
|
||||
__le32 reserved0c;
|
||||
};
|
||||
|
||||
#define MPI3_MAN8_PHY_INFO_RECEPTACLE_ID_HOST_PHY (0xff)
|
||||
#define MPI3_MAN8_PHY_INFO_RECEPTACLE_ID_NOT_ASSOCIATED (0xff)
|
||||
#define MPI3_MAN8_PHY_INFO_CONNECTOR_LANE_NOT_ASSOCIATED (0xff)
|
||||
#ifndef MPI3_MAN8_PHY_INFO_MAX
|
||||
#define MPI3_MAN8_PHY_INFO_MAX (1)
|
||||
#endif
|
||||
@ -536,6 +558,10 @@ struct mpi3_man11_bkplane_spec_non_ubm_format {
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_MASK (0xf000)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_SHIFT (12)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0200)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_MASK (0x00c0)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_4 (0x0000)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_2 (0x0040)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_1 (0x0080)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_MASK (0x0030)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_GPIO (0x0000)
|
||||
#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_REG (0x0010)
|
||||
@ -825,19 +851,16 @@ struct mpi3_man_page21 {
|
||||
};
|
||||
|
||||
#define MPI3_MAN21_PAGEVERSION (0x00)
|
||||
#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_MASK (0x80)
|
||||
#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_ENABLED (0x80)
|
||||
#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_DISABLED (0x00)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_MASK (0x60)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_BLOCK (0x00)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_ALLOW (0x20)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_WARN (0x40)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_MASK (0x08)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_ALLOW (0x00)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_PREVENT (0x08)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_MASK (0x01)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_DEFAULT (0x00)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_OEM_SPECIFIC (0x01)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_MASK (0x00000060)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_BLOCK (0x00000000)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_ALLOW (0x00000020)
|
||||
#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_WARN (0x00000040)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_MASK (0x00000008)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_ALLOW (0x00000000)
|
||||
#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_PREVENT (0x00000008)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_MASK (0x00000001)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_DEFAULT (0x00000000)
|
||||
#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_OEM_SPECIFIC (0x00000001)
|
||||
#ifndef MPI3_MAN_PROD_SPECIFIC_MAX
|
||||
#define MPI3_MAN_PROD_SPECIFIC_MAX (1)
|
||||
#endif
|
||||
@ -995,7 +1018,12 @@ struct mpi3_io_unit_page5 {
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_MASK (0x000c)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_SHIFT (2)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_MASK (0x0003)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAA_SSD_SHIFT (0)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_SHIFT (0)
|
||||
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_MASK (0x0c)
|
||||
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_NOT_SUPPORTED (0x00)
|
||||
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_OS_CONTROLLED (0x04)
|
||||
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_APP_CONTROLLED (0x08)
|
||||
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_BLOCKED (0x0c)
|
||||
#define MPI3_IOUNIT5_FLAGS_POWER_CAPABLE_SPINUP (0x02)
|
||||
#define MPI3_IOUNIT5_FLAGS_AUTO_PORT_ENABLE (0x01)
|
||||
#define MPI3_IOUNIT5_PHY_SPINUP_GROUP_MASK (0x03)
|
||||
@ -1027,7 +1055,8 @@ struct mpi3_io_unit_page8 {
|
||||
u8 slots_available;
|
||||
u8 current_key_encryption_algo;
|
||||
u8 key_digest_hash_algo;
|
||||
__le32 reserved10[2];
|
||||
union mpi3_version_union current_svn;
|
||||
__le32 reserved14;
|
||||
__le32 current_key[128];
|
||||
union mpi3_iounit8_digest digest[MPI3_IOUNIT8_DIGEST_MAX];
|
||||
};
|
||||
@ -1036,6 +1065,7 @@ struct mpi3_io_unit_page8 {
|
||||
#define MPI3_IOUNIT8_SBMODE_SECURE_DEBUG (0x04)
|
||||
#define MPI3_IOUNIT8_SBMODE_HARD_SECURE (0x02)
|
||||
#define MPI3_IOUNIT8_SBMODE_CONFIG_SECURE (0x01)
|
||||
#define MPI3_IOUNIT8_SBSTATE_SVN_UPDATE_PENDING (0x04)
|
||||
#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02)
|
||||
#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01)
|
||||
struct mpi3_io_unit_page9 {
|
||||
@ -1045,9 +1075,14 @@ struct mpi3_io_unit_page9 {
|
||||
__le16 reserved0e;
|
||||
};
|
||||
|
||||
#define MPI3_IOUNIT9_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT9_FLAGS_VDFIRST_ENABLED (0x01)
|
||||
#define MPI3_IOUNIT9_FIRSTDEVICE_UNKNOWN (0xffff)
|
||||
#define MPI3_IOUNIT9_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_MASK (0x00000006)
|
||||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_SHIFT (1)
|
||||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_NONE (0x00000000)
|
||||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_RECEPTACLE (0x00000002)
|
||||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_BACKPLANE_TYPE (0x00000004)
|
||||
#define MPI3_IOUNIT9_FLAGS_VDFIRST_ENABLED (0x00000001)
|
||||
#define MPI3_IOUNIT9_FIRSTDEVICE_UNKNOWN (0xffff)
|
||||
struct mpi3_io_unit_page10 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 flags;
|
||||
@ -1090,6 +1125,57 @@ struct mpi3_io_unit_page11 {
|
||||
struct mpi3_iounit11_profile profile[MPI3_IOUNIT11_PROFILE_MAX];
|
||||
};
|
||||
#define MPI3_IOUNIT11_PAGEVERSION (0x00)
|
||||
#ifndef MPI3_IOUNIT12_BUCKET_MAX
|
||||
#define MPI3_IOUNIT12_BUCKET_MAX (1)
|
||||
#endif
|
||||
struct mpi3_iounit12_bucket {
|
||||
u8 coalescing_depth;
|
||||
u8 coalescing_timeout;
|
||||
__le16 io_count_low_boundary;
|
||||
__le32 reserved04;
|
||||
};
|
||||
struct mpi3_io_unit_page12 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 flags;
|
||||
__le32 reserved0c[4];
|
||||
u8 num_buckets;
|
||||
u8 reserved1d[3];
|
||||
struct mpi3_iounit12_bucket bucket[MPI3_IOUNIT12_BUCKET_MAX];
|
||||
};
|
||||
#define MPI3_IOUNIT12_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_MASK (0x00000300)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_SHIFT (8)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_8 (0x00000000)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_16 (0x00000100)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_32 (0x00000200)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_64 (0x00000300)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_MASK (0x00000003)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_DISABLED (0x00000000)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_500US (0x00000001)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_1MS (0x00000002)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_2MS (0x00000003)
|
||||
#ifndef MPI3_IOUNIT13_FUNC_MAX
|
||||
#define MPI3_IOUNIT13_FUNC_MAX (1)
|
||||
#endif
|
||||
struct mpi3_iounit13_allowed_function {
|
||||
__le16 sub_function;
|
||||
u8 function_code;
|
||||
u8 fuction_flags;
|
||||
};
|
||||
#define MPI3_IOUNIT13_FUNCTION_FLAGS_ADMIN_BLOCKED (0x04)
|
||||
#define MPI3_IOUNIT13_FUNCTION_FLAGS_OOB_BLOCKED (0x02)
|
||||
#define MPI3_IOUNIT13_FUNCTION_FLAGS_CHECK_SUBFUNCTION_ENABLED (0x01)
|
||||
struct mpi3_io_unit_page13 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le16 flags;
|
||||
__le16 reserved0a;
|
||||
u8 num_allowed_functions;
|
||||
u8 reserved0d[3];
|
||||
struct mpi3_iounit13_allowed_function allowed_function[MPI3_IOUNIT13_FUNC_MAX];
|
||||
};
|
||||
#define MPI3_IOUNIT13_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT13_FLAGS_ADMIN_BLOCKED (0x0002)
|
||||
#define MPI3_IOUNIT13_FLAGS_OOB_BLOCKED (0x0001)
|
||||
struct mpi3_ioc_page0 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 reserved08;
|
||||
@ -1182,6 +1268,7 @@ struct mpi3_driver_page0 {
|
||||
__le32 reserved18;
|
||||
};
|
||||
#define MPI3_DRIVER0_PAGEVERSION (0x00)
|
||||
#define MPI3_DRIVER0_BSDOPTS_HEADLESS_MODE_ENABLE (0x00000008)
|
||||
#define MPI3_DRIVER0_BSDOPTS_DIS_HII_CONFIG_UTIL (0x00000004)
|
||||
#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_MASK (0x00000003)
|
||||
#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000)
|
||||
@ -1906,19 +1993,30 @@ struct mpi3_pcie_io_unit_page1 {
|
||||
};
|
||||
|
||||
#define MPI3_PCIEIOUNIT1_PAGEVERSION (0x00)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_OVERRIDE_DISABLE (0x80)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_DISABLE (0x40)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_MASK (0x30)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_MASK (0xe0000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_NONE (0x00000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_DEASSERT (0x20000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_ASSERT (0x40000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_BACKPLANE_ERROR (0x60000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_MASK (0x1c000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_NONE (0x00000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_DEASSERT (0x04000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_ASSERT (0x08000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_BACKPLANE_ERROR (0x0c000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_OVERRIDE_DISABLE (0x00000080)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_DISABLE (0x00000040)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_MASK (0x00000030)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SHIFT (4)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_SRNS_DISABLED (0x00)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_ENABLED (0x10)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRNS_ENABLED (0x20)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MASK (0x0f)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_2_5 (0x02)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_5_0 (0x03)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_8_0 (0x04)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_16_0 (0x05)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_32_0 (0x06)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_SRNS_DISABLED (0x00000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_ENABLED (0x00000010)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRNS_ENABLED (0x00000020)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MASK (0x0000000f)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_USE_BACKPLANE (0x00000000)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_2_5 (0x00000002)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_5_0 (0x00000003)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_8_0 (0x00000004)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_16_0 (0x00000005)
|
||||
#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_32_0 (0x00000006)
|
||||
#define MPI3_PCIEIOUNIT1_ASPM_SWITCH_MASK (0x0c)
|
||||
#define MPI3_PCIEIOUNIT1_ASPM_SWITCH_SHIFT (2)
|
||||
#define MPI3_PCIEIOUNIT1_ASPM_DIRECT_MASK (0x03)
|
||||
@ -2169,10 +2267,7 @@ struct mpi3_device0_vd_format {
|
||||
#define MPI3_DEVICE0_VD_DEVICE_INFO_SATA (0x0002)
|
||||
#define MPI3_DEVICE0_VD_DEVICE_INFO_SAS (0x0001)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_MASK (0xf000)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_MASK (0x0003)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_NONE (0x0000)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_HOST (0x0001)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_IOC (0x0002)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_SHIFT (12)
|
||||
union mpi3_device0_dev_spec_format {
|
||||
struct mpi3_device0_sas_sata_format sas_sata_format;
|
||||
struct mpi3_device0_pcie_format pcie_format;
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2018-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2018-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_IMAGE_H
|
||||
#define MPI30_IMAGE_H 1
|
||||
@ -63,6 +62,9 @@ struct mpi3_component_image_header {
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_PBLP (0x504c4250)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_MANIFEST (0x464e414d)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_OEM (0x204d454f)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_RMC (0x20434d52)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_SMM (0x204d4d53)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE1_PSW (0x20575350)
|
||||
#define MPI3_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546)
|
||||
#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_MASK (0x00000030)
|
||||
#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_CDI (0x00000000)
|
||||
|
@ -1,13 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2016-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_INIT_H
|
||||
#define MPI30_INIT_H 1
|
||||
struct mpi3_scsi_io_cdb_eedp32 {
|
||||
u8 cdb[20];
|
||||
__be32 primary_reference_tag;
|
||||
__be32 primary_reference_tag;
|
||||
__le16 primary_application_tag;
|
||||
__le16 primary_application_tag_mask;
|
||||
__le32 transfer_length;
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2016-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_IOC_H
|
||||
#define MPI30_IOC_H 1
|
||||
@ -158,6 +157,7 @@ struct mpi3_ioc_facts_data {
|
||||
#define MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA (0x00000000)
|
||||
#define MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR (0x00000002)
|
||||
#define MPI3_IOCFACTS_IO_THROTTLE_DATA_LENGTH_NOT_REQUIRED (0x0000)
|
||||
#define MPI3_IOCFACTS_MAX_IO_THROTTLE_GROUP_NOT_REQUIRED (0x0000)
|
||||
struct mpi3_mgmt_passthrough_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
@ -637,6 +637,23 @@ struct mpi3_event_data_diag_buffer_status_change {
|
||||
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED (0x01)
|
||||
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED (0x02)
|
||||
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED (0x03)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_CONFIGURATION (0x0040)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_CONTROLER (0x0020)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_SAS (0x0010)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_EPACK (0x0008)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_ENCLOSURE (0x0004)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_PD (0x0002)
|
||||
#define MPI3_PEL_LOCALE_FLAGS_VD (0x0001)
|
||||
#define MPI3_PEL_CLASS_DEBUG (0x00)
|
||||
#define MPI3_PEL_CLASS_PROGRESS (0x01)
|
||||
#define MPI3_PEL_CLASS_INFORMATIONAL (0x02)
|
||||
#define MPI3_PEL_CLASS_WARNING (0x03)
|
||||
#define MPI3_PEL_CLASS_CRITICAL (0x04)
|
||||
#define MPI3_PEL_CLASS_FATAL (0x05)
|
||||
#define MPI3_PEL_CLASS_FAULT (0x06)
|
||||
#define MPI3_PEL_CLEARTYPE_CLEAR (0x00)
|
||||
#define MPI3_PEL_WAITTIME_INFINITE_WAIT (0x00)
|
||||
#define MPI3_PEL_ACTION_GET_SEQNUM (0x01)
|
||||
@ -924,6 +941,7 @@ struct mpi3_ci_download_reply {
|
||||
};
|
||||
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_DOWNLOAD_IN_PROGRESS (0x80)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_FAILURE (0x40)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_OFFLINE_ACTIVATION_REQUIRED (0x20)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_KEY_UPDATE_PENDING (0x10)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_MASK (0x0e)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
* Copyright 2016-2022 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
#ifndef MPI30_PCI_H
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2016-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_SAS_H
|
||||
#define MPI30_SAS_H 1
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Copyright 2016-2022 Broadcom Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef MPI30_TRANSPORT_H
|
||||
#define MPI30_TRANSPORT_H 1
|
||||
@ -19,8 +18,8 @@ union mpi3_version_union {
|
||||
|
||||
#define MPI3_VERSION_MAJOR (3)
|
||||
#define MPI3_VERSION_MINOR (0)
|
||||
#define MPI3_VERSION_UNIT (23)
|
||||
#define MPI3_VERSION_DEV (1)
|
||||
#define MPI3_VERSION_UNIT (26)
|
||||
#define MPI3_VERSION_DEV (0)
|
||||
#define MPI3_DEVHANDLE_INVALID (0xffff)
|
||||
struct mpi3_sysif_oper_queue_indexes {
|
||||
__le16 producer_index;
|
||||
@ -212,6 +211,7 @@ struct mpi3_default_reply_descriptor {
|
||||
#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS (0x1000)
|
||||
#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_TARGET_COMMAND_BUFFER (0x2000)
|
||||
#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS (0x3000)
|
||||
#define MPI3_REPLY_DESCRIPT_REQUEST_QUEUE_ID_INVALID (0xffff)
|
||||
struct mpi3_address_reply_descriptor {
|
||||
__le64 reply_frame_address;
|
||||
__le16 request_queue_ci;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <uapi/scsi/scsi_bsg_mpi3mr.h>
|
||||
#include <scsi/scsi_transport_sas.h>
|
||||
|
||||
#include "mpi/mpi30_transport.h"
|
||||
#include "mpi/mpi30_cnfg.h"
|
||||
@ -55,8 +56,8 @@ extern struct list_head mrioc_list;
|
||||
extern int prot_mask;
|
||||
extern atomic64_t event_counter;
|
||||
|
||||
#define MPI3MR_DRIVER_VERSION "8.0.0.69.0"
|
||||
#define MPI3MR_DRIVER_RELDATE "16-March-2022"
|
||||
#define MPI3MR_DRIVER_VERSION "8.2.0.3.0"
|
||||
#define MPI3MR_DRIVER_RELDATE "08-September-2022"
|
||||
|
||||
#define MPI3MR_DRIVER_NAME "mpi3mr"
|
||||
#define MPI3MR_DRIVER_LICENSE "GPL"
|
||||
@ -97,9 +98,11 @@ extern atomic64_t event_counter;
|
||||
#define MPI3MR_HOSTTAG_PEL_ABORT 3
|
||||
#define MPI3MR_HOSTTAG_PEL_WAIT 4
|
||||
#define MPI3MR_HOSTTAG_BLK_TMS 5
|
||||
#define MPI3MR_HOSTTAG_CFG_CMDS 6
|
||||
#define MPI3MR_HOSTTAG_TRANSPORT_CMDS 7
|
||||
|
||||
#define MPI3MR_NUM_DEVRMCMD 16
|
||||
#define MPI3MR_HOSTTAG_DEVRMCMD_MIN (MPI3MR_HOSTTAG_BLK_TMS + 1)
|
||||
#define MPI3MR_HOSTTAG_DEVRMCMD_MIN (MPI3MR_HOSTTAG_TRANSPORT_CMDS + 1)
|
||||
#define MPI3MR_HOSTTAG_DEVRMCMD_MAX (MPI3MR_HOSTTAG_DEVRMCMD_MIN + \
|
||||
MPI3MR_NUM_DEVRMCMD - 1)
|
||||
|
||||
@ -115,6 +118,7 @@ extern atomic64_t event_counter;
|
||||
/* command/controller interaction timeout definitions in seconds */
|
||||
#define MPI3MR_INTADMCMD_TIMEOUT 60
|
||||
#define MPI3MR_PORTENABLE_TIMEOUT 300
|
||||
#define MPI3MR_PORTENABLE_POLL_INTERVAL 5
|
||||
#define MPI3MR_ABORTTM_TIMEOUT 60
|
||||
#define MPI3MR_RESETTM_TIMEOUT 60
|
||||
#define MPI3MR_RESET_HOST_IOWAIT_TIMEOUT 5
|
||||
@ -126,6 +130,10 @@ extern atomic64_t event_counter;
|
||||
|
||||
#define MPI3MR_WATCHDOG_INTERVAL 1000 /* in milli seconds */
|
||||
|
||||
#define MPI3MR_DEFAULT_CFG_PAGE_SZ 1024 /* in bytes */
|
||||
|
||||
#define MPI3MR_RESET_TOPOLOGY_SETTLE_TIME 10
|
||||
|
||||
#define MPI3MR_SCMD_TIMEOUT (60 * HZ)
|
||||
#define MPI3MR_EH_SCMD_TIMEOUT (60 * HZ)
|
||||
|
||||
@ -274,6 +282,8 @@ enum mpi3mr_reset_reason {
|
||||
MPI3MR_RESET_FROM_SYSFS = 23,
|
||||
MPI3MR_RESET_FROM_SYSFS_TIMEOUT = 24,
|
||||
MPI3MR_RESET_FROM_FIRMWARE = 27,
|
||||
MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29,
|
||||
MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30,
|
||||
};
|
||||
|
||||
/* Queue type definitions */
|
||||
@ -421,12 +431,14 @@ struct op_reply_qinfo {
|
||||
* struct mpi3mr_intr_info - Interrupt cookie information
|
||||
*
|
||||
* @mrioc: Adapter instance reference
|
||||
* @os_irq: irq number
|
||||
* @msix_index: MSIx index
|
||||
* @op_reply_q: Associated operational reply queue
|
||||
* @name: Dev name for the irq claiming device
|
||||
*/
|
||||
struct mpi3mr_intr_info {
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
int os_irq;
|
||||
u16 msix_index;
|
||||
struct op_reply_qinfo *op_reply_q;
|
||||
char name[MPI3MR_NAME_LENGTH];
|
||||
@ -457,16 +469,138 @@ struct mpi3mr_throttle_group_info {
|
||||
atomic_t pend_large_data_sz;
|
||||
};
|
||||
|
||||
/* HBA port flags */
|
||||
#define MPI3MR_HBA_PORT_FLAG_DIRTY 0x01
|
||||
|
||||
/**
|
||||
* struct mpi3mr_hba_port - HBA's port information
|
||||
* @port_id: Port number
|
||||
* @flags: HBA port flags
|
||||
*/
|
||||
struct mpi3mr_hba_port {
|
||||
struct list_head list;
|
||||
u8 port_id;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_sas_port - Internal SAS port information
|
||||
* @port_list: List of ports belonging to a SAS node
|
||||
* @num_phys: Number of phys associated with port
|
||||
* @marked_responding: used while refresing the sas ports
|
||||
* @lowest_phy: lowest phy ID of current sas port
|
||||
* @phy_mask: phy_mask of current sas port
|
||||
* @hba_port: HBA port entry
|
||||
* @remote_identify: Attached device identification
|
||||
* @rphy: SAS transport layer rphy object
|
||||
* @port: SAS transport layer port object
|
||||
* @phy_list: mpi3mr_sas_phy objects belonging to this port
|
||||
*/
|
||||
struct mpi3mr_sas_port {
|
||||
struct list_head port_list;
|
||||
u8 num_phys;
|
||||
u8 marked_responding;
|
||||
int lowest_phy;
|
||||
u32 phy_mask;
|
||||
struct mpi3mr_hba_port *hba_port;
|
||||
struct sas_identify remote_identify;
|
||||
struct sas_rphy *rphy;
|
||||
struct sas_port *port;
|
||||
struct list_head phy_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_sas_phy - Internal SAS Phy information
|
||||
* @port_siblings: List of phys belonging to a port
|
||||
* @identify: Phy identification
|
||||
* @remote_identify: Attached device identification
|
||||
* @phy: SAS transport layer Phy object
|
||||
* @phy_id: Unique phy id within a port
|
||||
* @handle: Firmware device handle for this phy
|
||||
* @attached_handle: Firmware device handle for attached device
|
||||
* @phy_belongs_to_port: Flag to indicate phy belongs to port
|
||||
@hba_port: HBA port entry
|
||||
*/
|
||||
struct mpi3mr_sas_phy {
|
||||
struct list_head port_siblings;
|
||||
struct sas_identify identify;
|
||||
struct sas_identify remote_identify;
|
||||
struct sas_phy *phy;
|
||||
u8 phy_id;
|
||||
u16 handle;
|
||||
u16 attached_handle;
|
||||
u8 phy_belongs_to_port;
|
||||
struct mpi3mr_hba_port *hba_port;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_sas_node - SAS host/expander information
|
||||
* @list: List of sas nodes in a controller
|
||||
* @parent_dev: Parent device class
|
||||
* @num_phys: Number phys belonging to sas_node
|
||||
* @sas_address: SAS address of sas_node
|
||||
* @handle: Firmware device handle for this sas_host/expander
|
||||
* @sas_address_parent: SAS address of parent expander or host
|
||||
* @enclosure_handle: Firmware handle of enclosure of this node
|
||||
* @device_info: Capabilities of this sas_host/expander
|
||||
* @non_responding: used to refresh the expander devices during reset
|
||||
* @host_node: Flag to indicate this is a host_node
|
||||
* @hba_port: HBA port entry
|
||||
* @phy: A list of phys that make up this sas_host/expander
|
||||
* @sas_port_list: List of internal ports of this node
|
||||
* @rphy: sas_rphy object of this expander node
|
||||
*/
|
||||
struct mpi3mr_sas_node {
|
||||
struct list_head list;
|
||||
struct device *parent_dev;
|
||||
u8 num_phys;
|
||||
u64 sas_address;
|
||||
u16 handle;
|
||||
u64 sas_address_parent;
|
||||
u16 enclosure_handle;
|
||||
u64 enclosure_logical_id;
|
||||
u8 non_responding;
|
||||
u8 host_node;
|
||||
struct mpi3mr_hba_port *hba_port;
|
||||
struct mpi3mr_sas_phy *phy;
|
||||
struct list_head sas_port_list;
|
||||
struct sas_rphy *rphy;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_enclosure_node - enclosure information
|
||||
* @list: List of enclosures
|
||||
* @pg0: Enclosure page 0;
|
||||
*/
|
||||
struct mpi3mr_enclosure_node {
|
||||
struct list_head list;
|
||||
struct mpi3_enclosure_page0 pg0;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_sas_sata - SAS/SATA device specific
|
||||
* information cached from firmware given data
|
||||
*
|
||||
* @sas_address: World wide unique SAS address
|
||||
* @sas_address_parent: Sas address of parent expander or host
|
||||
* @dev_info: Device information bits
|
||||
* @phy_id: Phy identifier provided in device page 0
|
||||
* @attached_phy_id: Attached phy identifier provided in device page 0
|
||||
* @sas_transport_attached: Is this device exposed to transport
|
||||
* @pend_sas_rphy_add: Flag to check device is in process of add
|
||||
* @hba_port: HBA port entry
|
||||
* @rphy: SAS transport layer rphy object
|
||||
*/
|
||||
struct tgt_dev_sas_sata {
|
||||
u64 sas_address;
|
||||
u64 sas_address_parent;
|
||||
u16 dev_info;
|
||||
u8 phy_id;
|
||||
u8 attached_phy_id;
|
||||
u8 sas_transport_attached;
|
||||
u8 pend_sas_rphy_add;
|
||||
struct mpi3mr_hba_port *hba_port;
|
||||
struct sas_rphy *rphy;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -531,12 +665,16 @@ union _form_spec_inf {
|
||||
* @slot: Slot number
|
||||
* @encl_handle: FW enclosure handle
|
||||
* @perst_id: FW assigned Persistent ID
|
||||
* @devpg0_flag: Device Page0 flag
|
||||
* @dev_type: SAS/SATA/PCIE device type
|
||||
* @is_hidden: Should be exposed to upper layers or not
|
||||
* @host_exposed: Already exposed to host or not
|
||||
* @io_unit_port: IO Unit port ID
|
||||
* @non_stl: Is this device not to be attached with SAS TL
|
||||
* @io_throttle_enabled: I/O throttling needed or not
|
||||
* @q_depth: Device specific Queue Depth
|
||||
* @wwid: World wide ID
|
||||
* @enclosure_logical_id: Enclosure logical identifier
|
||||
* @dev_spec: Device type specific information
|
||||
* @ref_count: Reference count
|
||||
*/
|
||||
@ -548,12 +686,16 @@ struct mpi3mr_tgt_dev {
|
||||
u16 slot;
|
||||
u16 encl_handle;
|
||||
u16 perst_id;
|
||||
u16 devpg0_flag;
|
||||
u8 dev_type;
|
||||
u8 is_hidden;
|
||||
u8 host_exposed;
|
||||
u8 io_unit_port;
|
||||
u8 non_stl;
|
||||
u8 io_throttle_enabled;
|
||||
u16 q_depth;
|
||||
u64 wwid;
|
||||
u64 enclosure_logical_id;
|
||||
union _form_spec_inf dev_spec;
|
||||
struct kref ref_count;
|
||||
};
|
||||
@ -679,6 +821,21 @@ struct mpi3mr_drv_cmd {
|
||||
struct mpi3mr_drv_cmd *drv_cmd);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dma_memory_desc - memory descriptor structure to store
|
||||
* virtual address, dma address and size for any generic dma
|
||||
* memory allocations in the driver.
|
||||
*
|
||||
* @size: buffer size
|
||||
* @addr: virtual address
|
||||
* @dma_addr: dma address
|
||||
*/
|
||||
struct dma_memory_desc {
|
||||
u32 size;
|
||||
void *addr;
|
||||
dma_addr_t dma_addr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct chain_element - memory descriptor structure to store
|
||||
@ -756,6 +913,7 @@ struct scmd_priv {
|
||||
* @num_op_reply_q: Number of operational reply queues
|
||||
* @op_reply_qinfo: Operational reply queue info pointer
|
||||
* @init_cmds: Command tracker for initialization commands
|
||||
* @cfg_cmds: Command tracker for configuration requests
|
||||
* @facts: Cached IOC facts data
|
||||
* @op_reply_desc_sz: Operational reply descriptor size
|
||||
* @num_reply_bufs: Number of reply buffers allocated
|
||||
@ -792,6 +950,7 @@ struct scmd_priv {
|
||||
* @scan_started: Async scan started
|
||||
* @scan_failed: Asycn scan failed
|
||||
* @stop_drv_processing: Stop all command processing
|
||||
* @device_refresh_on: Don't process the events until devices are refreshed
|
||||
* @max_host_ios: Maximum host I/O count
|
||||
* @chain_buf_count: Chain buffer count
|
||||
* @chain_buf_pool: Chain buffer pool
|
||||
@ -854,6 +1013,17 @@ struct scmd_priv {
|
||||
* @io_throttle_low: I/O size to stop throttle in 512b blocks
|
||||
* @num_io_throttle_group: Maximum number of throttle groups
|
||||
* @throttle_groups: Pointer to throttle group info structures
|
||||
* @cfg_page: Default memory for configuration pages
|
||||
* @cfg_page_dma: Configuration page DMA address
|
||||
* @cfg_page_sz: Default configuration page memory size
|
||||
* @sas_transport_enabled: SAS transport enabled or not
|
||||
* @scsi_device_channel: Channel ID for SCSI devices
|
||||
* @transport_cmds: Command tracker for SAS transport commands
|
||||
* @sas_hba: SAS node for the controller
|
||||
* @sas_expander_list: SAS node list of expanders
|
||||
* @sas_node_lock: Lock to protect SAS node list
|
||||
* @hba_port_table_list: List of HBA Ports
|
||||
* @enclosure_list: List of Enclosure objects
|
||||
*/
|
||||
struct mpi3mr_ioc {
|
||||
struct list_head list;
|
||||
@ -904,6 +1074,7 @@ struct mpi3mr_ioc {
|
||||
struct op_reply_qinfo *op_reply_qinfo;
|
||||
|
||||
struct mpi3mr_drv_cmd init_cmds;
|
||||
struct mpi3mr_drv_cmd cfg_cmds;
|
||||
struct mpi3mr_ioc_facts facts;
|
||||
u16 op_reply_desc_sz;
|
||||
|
||||
@ -948,6 +1119,7 @@ struct mpi3mr_ioc {
|
||||
u8 scan_started;
|
||||
u16 scan_failed;
|
||||
u8 stop_drv_processing;
|
||||
u8 device_refresh_on;
|
||||
|
||||
u16 max_host_ios;
|
||||
spinlock_t tgtdev_lock;
|
||||
@ -1025,6 +1197,19 @@ struct mpi3mr_ioc {
|
||||
u32 io_throttle_low;
|
||||
u16 num_io_throttle_group;
|
||||
struct mpi3mr_throttle_group_info *throttle_groups;
|
||||
|
||||
void *cfg_page;
|
||||
dma_addr_t cfg_page_dma;
|
||||
u16 cfg_page_sz;
|
||||
|
||||
u8 sas_transport_enabled;
|
||||
u8 scsi_device_channel;
|
||||
struct mpi3mr_drv_cmd transport_cmds;
|
||||
struct mpi3mr_sas_node sas_hba;
|
||||
struct list_head sas_expander_list;
|
||||
spinlock_t sas_node_lock;
|
||||
struct list_head hba_port_table_list;
|
||||
struct list_head enclosure_list;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1149,6 +1334,67 @@ int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_drv_cmd *drv_cmd);
|
||||
void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data,
|
||||
u16 event_data_size);
|
||||
struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
|
||||
struct mpi3mr_ioc *mrioc, u16 handle);
|
||||
extern const struct attribute_group *mpi3mr_host_groups[];
|
||||
extern const struct attribute_group *mpi3mr_dev_groups[];
|
||||
|
||||
extern struct sas_function_template mpi3mr_transport_functions;
|
||||
extern struct scsi_transport_template *mpi3mr_transport_template;
|
||||
|
||||
int mpi3mr_cfg_get_dev_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_device_page0 *dev_pg0, u16 pg_sz, u32 form, u32 form_spec);
|
||||
int mpi3mr_cfg_get_sas_phy_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_sas_phy_page0 *phy_pg0, u16 pg_sz, u32 form,
|
||||
u32 form_spec);
|
||||
int mpi3mr_cfg_get_sas_phy_pg1(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_sas_phy_page1 *phy_pg1, u16 pg_sz, u32 form,
|
||||
u32 form_spec);
|
||||
int mpi3mr_cfg_get_sas_exp_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_sas_expander_page0 *exp_pg0, u16 pg_sz, u32 form,
|
||||
u32 form_spec);
|
||||
int mpi3mr_cfg_get_sas_exp_pg1(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_sas_expander_page1 *exp_pg1, u16 pg_sz, u32 form,
|
||||
u32 form_spec);
|
||||
int mpi3mr_cfg_get_enclosure_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
|
||||
struct mpi3_enclosure_page0 *encl_pg0, u16 pg_sz, u32 form,
|
||||
u32 form_spec);
|
||||
int mpi3mr_cfg_get_sas_io_unit_pg0(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0, u16 pg_sz);
|
||||
int mpi3mr_cfg_get_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz);
|
||||
int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz);
|
||||
int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_driver_page1 *driver_pg1, u16 pg_sz);
|
||||
|
||||
u8 mpi3mr_is_expander_device(u16 device_info);
|
||||
int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle);
|
||||
void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
|
||||
struct mpi3mr_hba_port *hba_port);
|
||||
struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
|
||||
*mrioc, u16 handle);
|
||||
struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
|
||||
u8 port_id);
|
||||
void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
|
||||
u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
|
||||
struct mpi3mr_hba_port *hba_port);
|
||||
void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_tgt_dev *tgtdev);
|
||||
int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_tgt_dev *tgtdev);
|
||||
void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_tgt_dev *tgtdev);
|
||||
struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
|
||||
struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy);
|
||||
void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
|
||||
bool device_add);
|
||||
void mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc);
|
||||
#endif /*MPI3MR_H_INCLUDED*/
|
||||
|
@ -23,9 +23,13 @@
|
||||
#define MPI3_DEBUG_RESET 0x00000020
|
||||
#define MPI3_DEBUG_SCSI_ERROR 0x00000040
|
||||
#define MPI3_DEBUG_REPLY 0x00000080
|
||||
#define MPI3_DEBUG_CFG_ERROR 0x00000100
|
||||
#define MPI3_DEBUG_TRANSPORT_ERROR 0x00000200
|
||||
#define MPI3_DEBUG_BSG_ERROR 0x00008000
|
||||
#define MPI3_DEBUG_BSG_INFO 0x00010000
|
||||
#define MPI3_DEBUG_SCSI_INFO 0x00020000
|
||||
#define MPI3_DEBUG_CFG_INFO 0x00040000
|
||||
#define MPI3_DEBUG_TRANSPORT_INFO 0x00080000
|
||||
#define MPI3_DEBUG 0x01000000
|
||||
#define MPI3_DEBUG_SG 0x02000000
|
||||
|
||||
@ -122,6 +126,29 @@
|
||||
pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dprint_cfg_info(ioc, fmt, ...) \
|
||||
do { \
|
||||
if (ioc->logging_level & MPI3_DEBUG_CFG_INFO) \
|
||||
pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dprint_cfg_err(ioc, fmt, ...) \
|
||||
do { \
|
||||
if (ioc->logging_level & MPI3_DEBUG_CFG_ERROR) \
|
||||
pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define dprint_transport_info(ioc, fmt, ...) \
|
||||
do { \
|
||||
if (ioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO) \
|
||||
pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dprint_transport_err(ioc, fmt, ...) \
|
||||
do { \
|
||||
if (ioc->logging_level & MPI3_DEBUG_TRANSPORT_ERROR) \
|
||||
pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif /* MPT3SAS_DEBUG_H_INCLUDED */
|
||||
|
||||
/**
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,8 @@ static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
|
||||
|
||||
#define MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION (0xFFFF)
|
||||
|
||||
#define MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH (0xFFFE)
|
||||
|
||||
/**
|
||||
* mpi3mr_host_tag_for_scmd - Get host tag for a scmd
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -422,6 +424,8 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc)
|
||||
tgt_priv->io_throttle_enabled = 0;
|
||||
tgt_priv->io_divert = 0;
|
||||
tgt_priv->throttle_group = NULL;
|
||||
if (tgtdev->host_exposed)
|
||||
atomic_set(&tgt_priv->block_io, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -578,6 +582,39 @@ void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc)
|
||||
mrioc->flush_io_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_flush_cmds_for_unrecovered_controller - Flush all pending cmds
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* This function waits for currently running IO poll threads to
|
||||
* exit and then flushes all host I/Os and any internal pending
|
||||
* cmds. This is executed after controller is marked as
|
||||
* unrecoverable.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct Scsi_Host *shost = mrioc->shost;
|
||||
int i;
|
||||
|
||||
if (!mrioc->unrecoverable)
|
||||
return;
|
||||
|
||||
if (mrioc->op_reply_qinfo) {
|
||||
for (i = 0; i < mrioc->num_queues; i++) {
|
||||
while (atomic_read(&mrioc->op_reply_qinfo[i].in_use))
|
||||
udelay(500);
|
||||
atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0);
|
||||
}
|
||||
}
|
||||
mrioc->flush_io_count = 0;
|
||||
blk_mq_tagset_busy_iter(&shost->tag_set,
|
||||
mpi3mr_flush_scmd, (void *)mrioc);
|
||||
mpi3mr_flush_delayed_cmd_lists(mrioc);
|
||||
mpi3mr_flush_drv_cmds(mrioc);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_alloc_tgtdev - target device allocator
|
||||
*
|
||||
@ -796,7 +833,7 @@ static void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
|
||||
void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
|
||||
bool device_add)
|
||||
{
|
||||
ioc_notice(mrioc, "Device %s was in progress before the reset and\n",
|
||||
@ -816,7 +853,7 @@ static void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
|
||||
*
|
||||
* Return: 0 on success, non zero on failure.
|
||||
*/
|
||||
static void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
||||
void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_tgt_dev *tgtdev)
|
||||
{
|
||||
struct mpi3mr_stgt_priv_data *tgt_priv;
|
||||
@ -825,22 +862,29 @@ static void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
||||
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
||||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
atomic_set(&tgt_priv->block_io, 0);
|
||||
tgt_priv->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
|
||||
}
|
||||
|
||||
if (tgtdev->starget) {
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
scsi_remove_target(&tgtdev->starget->dev);
|
||||
tgtdev->host_exposed = 0;
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc, false);
|
||||
return;
|
||||
if (!mrioc->sas_transport_enabled || (tgtdev->dev_type !=
|
||||
MPI3_DEVICE_DEVFORM_SAS_SATA) || tgtdev->non_stl) {
|
||||
if (tgtdev->starget) {
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
scsi_remove_target(&tgtdev->starget->dev);
|
||||
tgtdev->host_exposed = 0;
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
mpi3mr_remove_tgtdev_from_sas_transport(mrioc, tgtdev);
|
||||
|
||||
ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n",
|
||||
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
||||
}
|
||||
@ -862,21 +906,25 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
|
||||
int retval = 0;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
|
||||
if (mrioc->reset_in_progress)
|
||||
return -1;
|
||||
|
||||
tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id);
|
||||
if (!tgtdev) {
|
||||
retval = -1;
|
||||
goto out;
|
||||
}
|
||||
if (tgtdev->is_hidden) {
|
||||
if (tgtdev->is_hidden || tgtdev->host_exposed) {
|
||||
retval = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!tgtdev->host_exposed && !mrioc->reset_in_progress) {
|
||||
if (!mrioc->sas_transport_enabled || (tgtdev->dev_type !=
|
||||
MPI3_DEVICE_DEVFORM_SAS_SATA) || tgtdev->non_stl){
|
||||
tgtdev->host_exposed = 1;
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
scsi_scan_target(&mrioc->shost->shost_gendev, 0,
|
||||
tgtdev->perst_id,
|
||||
scsi_scan_target(&mrioc->shost->shost_gendev,
|
||||
mrioc->scsi_device_channel, tgtdev->perst_id,
|
||||
SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
|
||||
if (!tgtdev->starget)
|
||||
tgtdev->host_exposed = 0;
|
||||
@ -887,7 +935,8 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
mpi3mr_report_tgtdev_to_sas_transport(mrioc, tgtdev);
|
||||
out:
|
||||
if (tgtdev)
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
@ -1018,18 +1067,29 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
{
|
||||
u16 flags = 0;
|
||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL;
|
||||
struct mpi3mr_enclosure_node *enclosure_dev = NULL;
|
||||
u8 prot_mask = 0;
|
||||
|
||||
tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
tgtdev->dev_handle = le16_to_cpu(dev_pg0->dev_handle);
|
||||
tgtdev->dev_type = dev_pg0->device_form;
|
||||
tgtdev->io_unit_port = dev_pg0->io_unit_port;
|
||||
tgtdev->encl_handle = le16_to_cpu(dev_pg0->enclosure_handle);
|
||||
tgtdev->parent_handle = le16_to_cpu(dev_pg0->parent_dev_handle);
|
||||
tgtdev->slot = le16_to_cpu(dev_pg0->slot);
|
||||
tgtdev->q_depth = le16_to_cpu(dev_pg0->queue_depth);
|
||||
tgtdev->wwid = le64_to_cpu(dev_pg0->wwid);
|
||||
tgtdev->devpg0_flag = le16_to_cpu(dev_pg0->flags);
|
||||
|
||||
if (tgtdev->encl_handle)
|
||||
enclosure_dev = mpi3mr_enclosure_find_by_handle(mrioc,
|
||||
tgtdev->encl_handle);
|
||||
if (enclosure_dev)
|
||||
tgtdev->enclosure_logical_id = le64_to_cpu(
|
||||
enclosure_dev->pg0.enclosure_logical_id);
|
||||
|
||||
flags = tgtdev->devpg0_flag;
|
||||
|
||||
flags = le16_to_cpu(dev_pg0->flags);
|
||||
tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN);
|
||||
|
||||
if (is_added == true)
|
||||
@ -1045,6 +1105,8 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
scsi_tgt_priv_data->dev_type = tgtdev->dev_type;
|
||||
scsi_tgt_priv_data->io_throttle_enabled =
|
||||
tgtdev->io_throttle_enabled;
|
||||
if (is_added == true)
|
||||
atomic_set(&scsi_tgt_priv_data->block_io, 0);
|
||||
}
|
||||
|
||||
switch (dev_pg0->access_status) {
|
||||
@ -1068,12 +1130,25 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
tgtdev->dev_spec.sas_sata_inf.dev_info = dev_info;
|
||||
tgtdev->dev_spec.sas_sata_inf.sas_address =
|
||||
le64_to_cpu(sasinf->sas_address);
|
||||
tgtdev->dev_spec.sas_sata_inf.phy_id = sasinf->phy_num;
|
||||
tgtdev->dev_spec.sas_sata_inf.attached_phy_id =
|
||||
sasinf->attached_phy_identifier;
|
||||
if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) !=
|
||||
MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE)
|
||||
tgtdev->is_hidden = 1;
|
||||
else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET |
|
||||
MPI3_SAS_DEVICE_INFO_SSP_TARGET)))
|
||||
tgtdev->is_hidden = 1;
|
||||
|
||||
if (((tgtdev->devpg0_flag &
|
||||
MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)
|
||||
&& (tgtdev->devpg0_flag &
|
||||
MPI3_DEVICE0_FLAGS_ATT_METHOD_VIRTUAL)) ||
|
||||
(tgtdev->parent_handle == 0xFFFF))
|
||||
tgtdev->non_stl = 1;
|
||||
if (tgtdev->dev_spec.sas_sata_inf.hba_port)
|
||||
tgtdev->dev_spec.sas_sata_inf.hba_port->port_id =
|
||||
dev_pg0->io_unit_port;
|
||||
break;
|
||||
}
|
||||
case MPI3_DEVICE_DEVFORM_PCIE:
|
||||
@ -1106,6 +1181,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
|
||||
MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE))
|
||||
tgtdev->is_hidden = 1;
|
||||
tgtdev->non_stl = 1;
|
||||
if (!mrioc->shost)
|
||||
break;
|
||||
prot_mask = scsi_host_get_prot(mrioc->shost);
|
||||
@ -1129,6 +1205,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
tgtdev->dev_spec.vd_inf.state = vdinf->vd_state;
|
||||
if (vdinf->vd_state == MPI3_DEVICE0_VD_STATE_OFFLINE)
|
||||
tgtdev->is_hidden = 1;
|
||||
tgtdev->non_stl = 1;
|
||||
tgtdev->dev_spec.vd_inf.tg_id = vdinf_io_throttle_group;
|
||||
tgtdev->dev_spec.vd_inf.tg_high =
|
||||
le16_to_cpu(vdinf->io_throttle_group_high) * 2048;
|
||||
@ -1257,6 +1334,135 @@ out:
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_free_enclosure_list - release enclosures
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Free memory allocated during encloure add.
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3mr_enclosure_node *enclosure_dev, *enclosure_dev_next;
|
||||
|
||||
list_for_each_entry_safe(enclosure_dev,
|
||||
enclosure_dev_next, &mrioc->enclosure_list, list) {
|
||||
list_del(&enclosure_dev->list);
|
||||
kfree(enclosure_dev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_enclosure_find_by_handle - enclosure search by handle
|
||||
* @mrioc: Adapter instance reference
|
||||
* @handle: Firmware device handle of the enclosure
|
||||
*
|
||||
* This searches for enclosure device based on handle, then returns the
|
||||
* enclosure object.
|
||||
*
|
||||
* Return: Enclosure object reference or NULL
|
||||
*/
|
||||
struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
|
||||
struct mpi3mr_ioc *mrioc, u16 handle)
|
||||
{
|
||||
struct mpi3mr_enclosure_node *enclosure_dev, *r = NULL;
|
||||
|
||||
list_for_each_entry(enclosure_dev, &mrioc->enclosure_list, list) {
|
||||
if (le16_to_cpu(enclosure_dev->pg0.enclosure_handle) != handle)
|
||||
continue;
|
||||
r = enclosure_dev;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event
|
||||
* @mrioc: Adapter instance reference
|
||||
* @encl_pg0: Enclosure page 0.
|
||||
* @is_added: Added event or not
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void mpi3mr_encldev_add_chg_evt_debug(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_enclosure_page0 *encl_pg0, u8 is_added)
|
||||
{
|
||||
char *reason_str = NULL;
|
||||
|
||||
if (!(mrioc->logging_level & MPI3_DEBUG_EVENT_WORK_TASK))
|
||||
return;
|
||||
|
||||
if (is_added)
|
||||
reason_str = "enclosure added";
|
||||
else
|
||||
reason_str = "enclosure dev status changed";
|
||||
|
||||
ioc_info(mrioc,
|
||||
"%s: handle(0x%04x), enclosure logical id(0x%016llx)\n",
|
||||
reason_str, le16_to_cpu(encl_pg0->enclosure_handle),
|
||||
(unsigned long long)le64_to_cpu(encl_pg0->enclosure_logical_id));
|
||||
ioc_info(mrioc,
|
||||
"number of slots(%d), port(%d), flags(0x%04x), present(%d)\n",
|
||||
le16_to_cpu(encl_pg0->num_slots), encl_pg0->io_unit_port,
|
||||
le16_to_cpu(encl_pg0->flags),
|
||||
((le16_to_cpu(encl_pg0->flags) &
|
||||
MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK) >> 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_encldev_add_chg_evt_bh - Enclosure evt bottomhalf
|
||||
* @mrioc: Adapter instance reference
|
||||
* @fwevt: Firmware event reference
|
||||
*
|
||||
* Prints information about the Enclosure device status or
|
||||
* Enclosure add events if logging is enabled and add or remove
|
||||
* the enclosure from the controller's internal list of
|
||||
* enclosures.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
static void mpi3mr_encldev_add_chg_evt_bh(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_fwevt *fwevt)
|
||||
{
|
||||
struct mpi3mr_enclosure_node *enclosure_dev = NULL;
|
||||
struct mpi3_enclosure_page0 *encl_pg0;
|
||||
u16 encl_handle;
|
||||
u8 added, present;
|
||||
|
||||
encl_pg0 = (struct mpi3_enclosure_page0 *) fwevt->event_data;
|
||||
added = (fwevt->event_id == MPI3_EVENT_ENCL_DEVICE_ADDED) ? 1 : 0;
|
||||
mpi3mr_encldev_add_chg_evt_debug(mrioc, encl_pg0, added);
|
||||
|
||||
|
||||
encl_handle = le16_to_cpu(encl_pg0->enclosure_handle);
|
||||
present = ((le16_to_cpu(encl_pg0->flags) &
|
||||
MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK) >> 4);
|
||||
|
||||
if (encl_handle)
|
||||
enclosure_dev = mpi3mr_enclosure_find_by_handle(mrioc,
|
||||
encl_handle);
|
||||
if (!enclosure_dev && present) {
|
||||
enclosure_dev =
|
||||
kzalloc(sizeof(struct mpi3mr_enclosure_node),
|
||||
GFP_KERNEL);
|
||||
if (!enclosure_dev)
|
||||
return;
|
||||
list_add_tail(&enclosure_dev->list,
|
||||
&mrioc->enclosure_list);
|
||||
}
|
||||
if (enclosure_dev) {
|
||||
if (!present) {
|
||||
list_del(&enclosure_dev->list);
|
||||
kfree(enclosure_dev);
|
||||
} else
|
||||
memcpy(&enclosure_dev->pg0, encl_pg0,
|
||||
sizeof(enclosure_dev->pg0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_sastopochg_evt_debug - SASTopoChange details
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -1296,8 +1502,9 @@ mpi3mr_sastopochg_evt_debug(struct mpi3mr_ioc *mrioc,
|
||||
ioc_info(mrioc, "%s :sas topology change: (%s)\n",
|
||||
__func__, status_str);
|
||||
ioc_info(mrioc,
|
||||
"%s :\texpander_handle(0x%04x), enclosure_handle(0x%04x) start_phy(%02d), num_entries(%d)\n",
|
||||
"%s :\texpander_handle(0x%04x), port(%d), enclosure_handle(0x%04x) start_phy(%02d), num_entries(%d)\n",
|
||||
__func__, le16_to_cpu(event_data->expander_dev_handle),
|
||||
event_data->io_unit_port,
|
||||
le16_to_cpu(event_data->enclosure_handle),
|
||||
event_data->start_phy_num, event_data->num_entries);
|
||||
for (i = 0; i < event_data->num_entries; i++) {
|
||||
@ -1355,9 +1562,30 @@ static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc,
|
||||
int i;
|
||||
u16 handle;
|
||||
u8 reason_code;
|
||||
u64 exp_sas_address = 0, parent_sas_address = 0;
|
||||
struct mpi3mr_hba_port *hba_port = NULL;
|
||||
struct mpi3mr_tgt_dev *tgtdev = NULL;
|
||||
struct mpi3mr_sas_node *sas_expander = NULL;
|
||||
unsigned long flags;
|
||||
u8 link_rate, prev_link_rate, parent_phy_number;
|
||||
|
||||
mpi3mr_sastopochg_evt_debug(mrioc, event_data);
|
||||
if (mrioc->sas_transport_enabled) {
|
||||
hba_port = mpi3mr_get_hba_port_by_id(mrioc,
|
||||
event_data->io_unit_port);
|
||||
if (le16_to_cpu(event_data->expander_dev_handle)) {
|
||||
spin_lock_irqsave(&mrioc->sas_node_lock, flags);
|
||||
sas_expander = __mpi3mr_expander_find_by_handle(mrioc,
|
||||
le16_to_cpu(event_data->expander_dev_handle));
|
||||
if (sas_expander) {
|
||||
exp_sas_address = sas_expander->sas_address;
|
||||
hba_port = sas_expander->hba_port;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
|
||||
parent_sas_address = exp_sas_address;
|
||||
} else
|
||||
parent_sas_address = mrioc->sas_hba.sas_address;
|
||||
}
|
||||
|
||||
for (i = 0; i < event_data->num_entries; i++) {
|
||||
if (fwevt->discard)
|
||||
@ -1379,12 +1607,37 @@ static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc,
|
||||
mpi3mr_tgtdev_del_from_list(mrioc, tgtdev);
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
break;
|
||||
case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING:
|
||||
case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED:
|
||||
case MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE:
|
||||
{
|
||||
if (!mrioc->sas_transport_enabled || tgtdev->non_stl
|
||||
|| tgtdev->is_hidden)
|
||||
break;
|
||||
link_rate = event_data->phy_entry[i].link_rate >> 4;
|
||||
prev_link_rate = event_data->phy_entry[i].link_rate & 0xF;
|
||||
if (link_rate == prev_link_rate)
|
||||
break;
|
||||
if (!parent_sas_address)
|
||||
break;
|
||||
parent_phy_number = event_data->start_phy_num + i;
|
||||
mpi3mr_update_links(mrioc, parent_sas_address, handle,
|
||||
parent_phy_number, link_rate, hba_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (tgtdev)
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
}
|
||||
|
||||
if (mrioc->sas_transport_enabled && (event_data->exp_status ==
|
||||
MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING)) {
|
||||
if (sas_expander)
|
||||
mpi3mr_expander_remove(mrioc, exp_sas_address,
|
||||
hba_port);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1604,28 +1857,54 @@ static void mpi3mr_set_qd_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
|
||||
static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_fwevt *fwevt)
|
||||
{
|
||||
struct mpi3_device_page0 *dev_pg0 = NULL;
|
||||
u16 perst_id, handle, dev_info;
|
||||
struct mpi3_device0_sas_sata_format *sasinf = NULL;
|
||||
|
||||
mpi3mr_fwevt_del_from_list(mrioc, fwevt);
|
||||
mrioc->current_event = fwevt;
|
||||
|
||||
if (mrioc->stop_drv_processing)
|
||||
goto out;
|
||||
|
||||
if (mrioc->unrecoverable) {
|
||||
dprint_event_bh(mrioc,
|
||||
"ignoring event(0x%02x) in bottom half handler due to unrecoverable controller\n",
|
||||
fwevt->event_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fwevt->process_evt)
|
||||
goto evt_ack;
|
||||
|
||||
switch (fwevt->event_id) {
|
||||
case MPI3_EVENT_DEVICE_ADDED:
|
||||
{
|
||||
struct mpi3_device_page0 *dev_pg0 =
|
||||
(struct mpi3_device_page0 *)fwevt->event_data;
|
||||
mpi3mr_report_tgtdev_to_host(mrioc,
|
||||
le16_to_cpu(dev_pg0->persistent_id));
|
||||
dev_pg0 = (struct mpi3_device_page0 *)fwevt->event_data;
|
||||
perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
handle = le16_to_cpu(dev_pg0->dev_handle);
|
||||
if (perst_id != MPI3_DEVICE0_PERSISTENTID_INVALID)
|
||||
mpi3mr_report_tgtdev_to_host(mrioc, perst_id);
|
||||
else if (mrioc->sas_transport_enabled &&
|
||||
(dev_pg0->device_form == MPI3_DEVICE_DEVFORM_SAS_SATA)) {
|
||||
sasinf = &dev_pg0->device_specific.sas_sata_format;
|
||||
dev_info = le16_to_cpu(sasinf->device_info);
|
||||
if (!mrioc->sas_hba.num_phys)
|
||||
mpi3mr_sas_host_add(mrioc);
|
||||
else
|
||||
mpi3mr_sas_host_refresh(mrioc);
|
||||
|
||||
if (mpi3mr_is_expander_device(dev_info))
|
||||
mpi3mr_expander_add(mrioc, handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DEVICE_INFO_CHANGED:
|
||||
{
|
||||
mpi3mr_devinfochg_evt_bh(mrioc,
|
||||
(struct mpi3_device_page0 *)fwevt->event_data);
|
||||
dev_pg0 = (struct mpi3_device_page0 *)fwevt->event_data;
|
||||
perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
if (perst_id != MPI3_DEVICE0_PERSISTENTID_INVALID)
|
||||
mpi3mr_devinfochg_evt_bh(mrioc, dev_pg0);
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DEVICE_STATUS_CHANGE:
|
||||
@ -1633,6 +1912,13 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
||||
mpi3mr_devstatuschg_evt_bh(mrioc, fwevt);
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_ENCL_DEVICE_ADDED:
|
||||
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
|
||||
{
|
||||
mpi3mr_encldev_add_chg_evt_bh(mrioc, fwevt);
|
||||
break;
|
||||
}
|
||||
|
||||
case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
|
||||
{
|
||||
mpi3mr_sastopochg_evt_bh(mrioc, fwevt);
|
||||
@ -1662,6 +1948,22 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH:
|
||||
{
|
||||
while (mrioc->device_refresh_on)
|
||||
msleep(500);
|
||||
|
||||
dprint_event_bh(mrioc,
|
||||
"scan for non responding and newly added devices after soft reset started\n");
|
||||
if (mrioc->sas_transport_enabled) {
|
||||
mpi3mr_refresh_sas_ports(mrioc);
|
||||
mpi3mr_refresh_expanders(mrioc);
|
||||
}
|
||||
mpi3mr_rfresh_tgtdevs(mrioc);
|
||||
ioc_info(mrioc,
|
||||
"scan for non responding and newly added devices after soft reset completed\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1716,6 +2018,9 @@ static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
u16 perst_id = 0;
|
||||
|
||||
perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
if (perst_id == MPI3_DEVICE0_PERSISTENTID_INVALID)
|
||||
return retval;
|
||||
|
||||
tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id);
|
||||
if (tgtdev) {
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, true);
|
||||
@ -2428,6 +2733,35 @@ static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_add_event_wait_for_device_refresh - Add Wait for Device Refresh Event
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Add driver specific event to make sure that the driver won't process the
|
||||
* events until all the devices are refreshed during soft reset.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3mr_fwevt *fwevt = NULL;
|
||||
|
||||
fwevt = mpi3mr_alloc_fwevt(0);
|
||||
if (!fwevt) {
|
||||
dprint_event_th(mrioc,
|
||||
"failed to schedule bottom half handler for event(0x%02x)\n",
|
||||
MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH);
|
||||
return;
|
||||
}
|
||||
fwevt->mrioc = mrioc;
|
||||
fwevt->event_id = MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH;
|
||||
fwevt->send_ack = 0;
|
||||
fwevt->process_evt = 1;
|
||||
fwevt->evt_ctx = 0;
|
||||
fwevt->event_data_size = 0;
|
||||
mpi3mr_fwevt_add_to_list(mrioc, fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_os_handle_events - Firmware event handler
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -2494,6 +2828,8 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
case MPI3_EVENT_DEVICE_INFO_CHANGED:
|
||||
case MPI3_EVENT_LOG_DATA:
|
||||
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
|
||||
case MPI3_EVENT_ENCL_DEVICE_ADDED:
|
||||
{
|
||||
process_evt_bh = 1;
|
||||
break;
|
||||
@ -2508,7 +2844,6 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
||||
mpi3mr_cablemgmt_evt_th(mrioc, event_reply);
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
|
||||
case MPI3_EVENT_SAS_DISCOVERY:
|
||||
case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
|
||||
case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE:
|
||||
@ -3849,9 +4184,10 @@ static void mpi3mr_slave_destroy(struct scsi_device *sdev)
|
||||
struct Scsi_Host *shost;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data;
|
||||
struct mpi3mr_tgt_dev *tgt_dev;
|
||||
struct mpi3mr_tgt_dev *tgt_dev = NULL;
|
||||
unsigned long flags;
|
||||
struct scsi_target *starget;
|
||||
struct sas_rphy *rphy = NULL;
|
||||
|
||||
if (!sdev->hostdata)
|
||||
return;
|
||||
@ -3864,7 +4200,14 @@ static void mpi3mr_slave_destroy(struct scsi_device *sdev)
|
||||
scsi_tgt_priv_data->num_luns--;
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
if (starget->channel == mrioc->scsi_device_channel)
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
else if (mrioc->sas_transport_enabled && !starget->channel) {
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
|
||||
rphy->identify.sas_address, rphy);
|
||||
}
|
||||
|
||||
if (tgt_dev && (!scsi_tgt_priv_data->num_luns))
|
||||
tgt_dev->starget = NULL;
|
||||
if (tgt_dev)
|
||||
@ -3929,16 +4272,23 @@ static int mpi3mr_slave_configure(struct scsi_device *sdev)
|
||||
struct scsi_target *starget;
|
||||
struct Scsi_Host *shost;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
struct mpi3mr_tgt_dev *tgt_dev;
|
||||
struct mpi3mr_tgt_dev *tgt_dev = NULL;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
struct sas_rphy *rphy = NULL;
|
||||
|
||||
starget = scsi_target(sdev);
|
||||
shost = dev_to_shost(&starget->dev);
|
||||
mrioc = shost_priv(shost);
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
if (starget->channel == mrioc->scsi_device_channel)
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
else if (mrioc->sas_transport_enabled && !starget->channel) {
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
|
||||
rphy->identify.sas_address, rphy);
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
if (!tgt_dev)
|
||||
return -ENXIO;
|
||||
@ -3986,11 +4336,12 @@ static int mpi3mr_slave_alloc(struct scsi_device *sdev)
|
||||
struct Scsi_Host *shost;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data;
|
||||
struct mpi3mr_tgt_dev *tgt_dev;
|
||||
struct mpi3mr_tgt_dev *tgt_dev = NULL;
|
||||
struct mpi3mr_sdev_priv_data *scsi_dev_priv_data;
|
||||
unsigned long flags;
|
||||
struct scsi_target *starget;
|
||||
int retval = 0;
|
||||
struct sas_rphy *rphy = NULL;
|
||||
|
||||
starget = scsi_target(sdev);
|
||||
shost = dev_to_shost(&starget->dev);
|
||||
@ -3998,7 +4349,14 @@ static int mpi3mr_slave_alloc(struct scsi_device *sdev)
|
||||
scsi_tgt_priv_data = starget->hostdata;
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
|
||||
if (starget->channel == mrioc->scsi_device_channel)
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
else if (mrioc->sas_transport_enabled && !starget->channel) {
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
|
||||
rphy->identify.sas_address, rphy);
|
||||
}
|
||||
|
||||
if (tgt_dev) {
|
||||
if (tgt_dev->starget == NULL)
|
||||
@ -4041,6 +4399,8 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
|
||||
struct mpi3mr_tgt_dev *tgt_dev;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
struct sas_rphy *rphy = NULL;
|
||||
bool update_stgt_priv_data = false;
|
||||
|
||||
scsi_tgt_priv_data = kzalloc(sizeof(*scsi_tgt_priv_data), GFP_KERNEL);
|
||||
if (!scsi_tgt_priv_data)
|
||||
@ -4049,8 +4409,25 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
|
||||
starget->hostdata = scsi_tgt_priv_data;
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
if (tgt_dev && !tgt_dev->is_hidden) {
|
||||
|
||||
if (starget->channel == mrioc->scsi_device_channel) {
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id);
|
||||
if (tgt_dev && !tgt_dev->is_hidden)
|
||||
update_stgt_priv_data = true;
|
||||
else
|
||||
retval = -ENXIO;
|
||||
} else if (mrioc->sas_transport_enabled && !starget->channel) {
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
|
||||
rphy->identify.sas_address, rphy);
|
||||
if (tgt_dev && !tgt_dev->is_hidden && !tgt_dev->non_stl &&
|
||||
(tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA))
|
||||
update_stgt_priv_data = true;
|
||||
else
|
||||
retval = -ENXIO;
|
||||
}
|
||||
|
||||
if (update_stgt_priv_data) {
|
||||
scsi_tgt_priv_data->starget = starget;
|
||||
scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle;
|
||||
scsi_tgt_priv_data->perst_id = tgt_dev->perst_id;
|
||||
@ -4064,8 +4441,7 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
|
||||
if (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_VD)
|
||||
scsi_tgt_priv_data->throttle_group =
|
||||
tgt_dev->dev_spec.vd_inf.tg;
|
||||
} else
|
||||
retval = -ENXIO;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
|
||||
return retval;
|
||||
@ -4254,6 +4630,16 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
||||
|
||||
stgt_priv_data = sdev_priv_data->tgt_priv_data;
|
||||
|
||||
if (atomic_read(&stgt_priv_data->block_io)) {
|
||||
if (mrioc->stop_drv_processing) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
scsi_done(scmd);
|
||||
goto out;
|
||||
}
|
||||
retval = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_handle = stgt_priv_data->dev_handle;
|
||||
if (dev_handle == MPI3MR_INVALID_DEV_HANDLE) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
@ -4266,16 +4652,6 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (atomic_read(&stgt_priv_data->block_io)) {
|
||||
if (mrioc->stop_drv_processing) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
scsi_done(scmd);
|
||||
goto out;
|
||||
}
|
||||
retval = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (stgt_priv_data->dev_type == MPI3_DEVICE_DEVFORM_PCIE)
|
||||
is_pcie_dev = 1;
|
||||
if ((scmd->cmnd[0] == UNMAP) && is_pcie_dev &&
|
||||
@ -4553,16 +4929,23 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
spin_lock_init(&mrioc->tgtdev_lock);
|
||||
spin_lock_init(&mrioc->watchdog_lock);
|
||||
spin_lock_init(&mrioc->chain_buf_lock);
|
||||
spin_lock_init(&mrioc->sas_node_lock);
|
||||
|
||||
INIT_LIST_HEAD(&mrioc->fwevt_list);
|
||||
INIT_LIST_HEAD(&mrioc->tgtdev_list);
|
||||
INIT_LIST_HEAD(&mrioc->delayed_rmhs_list);
|
||||
INIT_LIST_HEAD(&mrioc->delayed_evtack_cmds_list);
|
||||
INIT_LIST_HEAD(&mrioc->sas_expander_list);
|
||||
INIT_LIST_HEAD(&mrioc->hba_port_table_list);
|
||||
INIT_LIST_HEAD(&mrioc->enclosure_list);
|
||||
|
||||
mutex_init(&mrioc->reset_mutex);
|
||||
mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS);
|
||||
mpi3mr_init_drv_cmd(&mrioc->host_tm_cmds, MPI3MR_HOSTTAG_BLK_TMS);
|
||||
mpi3mr_init_drv_cmd(&mrioc->bsg_cmds, MPI3MR_HOSTTAG_BSG_CMDS);
|
||||
mpi3mr_init_drv_cmd(&mrioc->cfg_cmds, MPI3MR_HOSTTAG_CFG_CMDS);
|
||||
mpi3mr_init_drv_cmd(&mrioc->transport_cmds,
|
||||
MPI3MR_HOSTTAG_TRANSPORT_CMDS);
|
||||
|
||||
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++)
|
||||
mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i],
|
||||
@ -4697,6 +5080,11 @@ static void mpi3mr_remove(struct pci_dev *pdev)
|
||||
while (mrioc->reset_in_progress || mrioc->is_driver_loading)
|
||||
ssleep(1);
|
||||
|
||||
if (!pci_device_is_present(mrioc->pdev)) {
|
||||
mrioc->unrecoverable = 1;
|
||||
mpi3mr_flush_cmds_for_unrecovered_controller(mrioc);
|
||||
}
|
||||
|
||||
mpi3mr_bsg_exit(mrioc);
|
||||
mrioc->stop_drv_processing = 1;
|
||||
mpi3mr_cleanup_fwevt_list(mrioc);
|
||||
@ -4706,7 +5094,11 @@ static void mpi3mr_remove(struct pci_dev *pdev)
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (wq)
|
||||
destroy_workqueue(wq);
|
||||
scsi_remove_host(shost);
|
||||
|
||||
if (mrioc->sas_transport_enabled)
|
||||
sas_remove_host(shost);
|
||||
else
|
||||
scsi_remove_host(shost);
|
||||
|
||||
list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list,
|
||||
list) {
|
||||
@ -4763,22 +5155,21 @@ static void mpi3mr_shutdown(struct pci_dev *pdev)
|
||||
mpi3mr_cleanup_resources(mrioc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/**
|
||||
* mpi3mr_suspend - PCI power management suspend callback
|
||||
* @pdev: PCI device instance
|
||||
* @state: New power state
|
||||
* @dev: Device struct
|
||||
*
|
||||
* Change the power state to the given value and cleanup the IOC
|
||||
* by issuing MUR and shutdown notification
|
||||
*
|
||||
* Return: 0 always.
|
||||
*/
|
||||
static int mpi3mr_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int __maybe_unused
|
||||
mpi3mr_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
pci_power_t device_state;
|
||||
|
||||
if (!shost)
|
||||
return 0;
|
||||
@ -4792,27 +5183,26 @@ static int mpi3mr_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
mpi3mr_stop_watchdog(mrioc);
|
||||
mpi3mr_cleanup_ioc(mrioc);
|
||||
|
||||
device_state = pci_choose_state(pdev, state);
|
||||
ioc_info(mrioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
|
||||
pdev, pci_name(pdev), device_state);
|
||||
pci_save_state(pdev);
|
||||
ioc_info(mrioc, "pdev=0x%p, slot=%s, entering operating state\n",
|
||||
pdev, pci_name(pdev));
|
||||
mpi3mr_cleanup_resources(mrioc);
|
||||
pci_set_power_state(pdev, device_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_resume - PCI power management resume callback
|
||||
* @pdev: PCI device instance
|
||||
* @dev: Device struct
|
||||
*
|
||||
* Restore the power state to D0 and reinitialize the controller
|
||||
* and resume I/O operations to the target devices
|
||||
*
|
||||
* Return: 0 on success, non-zero on failure
|
||||
*/
|
||||
static int mpi3mr_resume(struct pci_dev *pdev)
|
||||
static int __maybe_unused
|
||||
mpi3mr_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
pci_power_t device_state = pdev->current_state;
|
||||
@ -4825,9 +5215,6 @@ static int mpi3mr_resume(struct pci_dev *pdev)
|
||||
|
||||
ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
|
||||
pdev, pci_name(pdev), device_state);
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_enable_wake(pdev, PCI_D0, 0);
|
||||
pci_restore_state(pdev);
|
||||
mrioc->pdev = pdev;
|
||||
mrioc->cpu_count = num_online_cpus();
|
||||
r = mpi3mr_setup_resources(mrioc);
|
||||
@ -4838,18 +5225,21 @@ static int mpi3mr_resume(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
mrioc->stop_drv_processing = 0;
|
||||
mpi3mr_invalidate_devhandles(mrioc);
|
||||
mpi3mr_free_enclosure_list(mrioc);
|
||||
mpi3mr_memset_buffers(mrioc);
|
||||
r = mpi3mr_reinit_ioc(mrioc, 1);
|
||||
if (r) {
|
||||
ioc_err(mrioc, "resuming controller failed[%d]\n", r);
|
||||
return r;
|
||||
}
|
||||
ssleep(MPI3MR_RESET_TOPOLOGY_SETTLE_TIME);
|
||||
scsi_unblock_requests(shost);
|
||||
mrioc->device_refresh_on = 0;
|
||||
mpi3mr_start_watchdog(mrioc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct pci_device_id mpi3mr_pci_id_table[] = {
|
||||
{
|
||||
@ -4860,16 +5250,15 @@ static const struct pci_device_id mpi3mr_pci_id_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table);
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(mpi3mr_pm_ops, mpi3mr_suspend, mpi3mr_resume);
|
||||
|
||||
static struct pci_driver mpi3mr_pci_driver = {
|
||||
.name = MPI3MR_DRIVER_NAME,
|
||||
.id_table = mpi3mr_pci_id_table,
|
||||
.probe = mpi3mr_probe,
|
||||
.remove = mpi3mr_remove,
|
||||
.shutdown = mpi3mr_shutdown,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mpi3mr_suspend,
|
||||
.resume = mpi3mr_resume,
|
||||
#endif
|
||||
.driver.pm = &mpi3mr_pm_ops,
|
||||
};
|
||||
|
||||
static ssize_t event_counter_show(struct device_driver *dd, char *buf)
|
||||
@ -4885,19 +5274,34 @@ static int __init mpi3mr_init(void)
|
||||
pr_info("Loading %s version %s\n", MPI3MR_DRIVER_NAME,
|
||||
MPI3MR_DRIVER_VERSION);
|
||||
|
||||
mpi3mr_transport_template =
|
||||
sas_attach_transport(&mpi3mr_transport_functions);
|
||||
if (!mpi3mr_transport_template) {
|
||||
pr_err("%s failed to load due to sas transport attach failure\n",
|
||||
MPI3MR_DRIVER_NAME);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret_val = pci_register_driver(&mpi3mr_pci_driver);
|
||||
if (ret_val) {
|
||||
pr_err("%s failed to load due to pci register driver failure\n",
|
||||
MPI3MR_DRIVER_NAME);
|
||||
return ret_val;
|
||||
goto err_pci_reg_fail;
|
||||
}
|
||||
|
||||
ret_val = driver_create_file(&mpi3mr_pci_driver.driver,
|
||||
&driver_attr_event_counter);
|
||||
if (ret_val)
|
||||
pci_unregister_driver(&mpi3mr_pci_driver);
|
||||
goto err_event_counter;
|
||||
|
||||
return ret_val;
|
||||
|
||||
err_event_counter:
|
||||
pci_unregister_driver(&mpi3mr_pci_driver);
|
||||
|
||||
err_pci_reg_fail:
|
||||
sas_release_transport(mpi3mr_transport_template);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static void __exit mpi3mr_exit(void)
|
||||
@ -4913,6 +5317,7 @@ static void __exit mpi3mr_exit(void)
|
||||
driver_remove_file(&mpi3mr_pci_driver.driver,
|
||||
&driver_attr_event_counter);
|
||||
pci_unregister_driver(&mpi3mr_pci_driver);
|
||||
sas_release_transport(mpi3mr_transport_template);
|
||||
}
|
||||
|
||||
module_init(mpi3mr_init);
|
||||
|
3291
drivers/scsi/mpi3mr/mpi3mr_transport.c
Normal file
3291
drivers/scsi/mpi3mr/mpi3mr_transport.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -534,6 +534,7 @@ typedef struct _MPI2_CONFIG_REPLY {
|
||||
****************************************************************************/
|
||||
|
||||
#define MPI2_MFGPAGE_VENDORID_LSI (0x1000)
|
||||
#define MPI2_MFGPAGE_VENDORID_ATTO (0x117C)
|
||||
|
||||
/*MPI v2.0 SAS products */
|
||||
#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070)
|
||||
|
@ -2990,19 +2990,26 @@ static int
|
||||
_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
|
||||
{
|
||||
struct sysinfo s;
|
||||
u64 coherent_dma_mask, dma_mask;
|
||||
|
||||
if (ioc->is_mcpu_endpoint ||
|
||||
sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma ||
|
||||
dma_get_required_mask(&pdev->dev) <= DMA_BIT_MASK(32))
|
||||
if (ioc->is_mcpu_endpoint || sizeof(dma_addr_t) == 4 ||
|
||||
dma_get_required_mask(&pdev->dev) <= 32) {
|
||||
ioc->dma_mask = 32;
|
||||
coherent_dma_mask = dma_mask = DMA_BIT_MASK(32);
|
||||
/* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
|
||||
else if (ioc->hba_mpi_version_belonged > MPI2_VERSION)
|
||||
} else if (ioc->hba_mpi_version_belonged > MPI2_VERSION) {
|
||||
ioc->dma_mask = 63;
|
||||
else
|
||||
coherent_dma_mask = dma_mask = DMA_BIT_MASK(63);
|
||||
} else {
|
||||
ioc->dma_mask = 64;
|
||||
coherent_dma_mask = dma_mask = DMA_BIT_MASK(64);
|
||||
}
|
||||
|
||||
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(ioc->dma_mask)) ||
|
||||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(ioc->dma_mask)))
|
||||
if (ioc->use_32bit_dma)
|
||||
coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
if (dma_set_mask(&pdev->dev, dma_mask) ||
|
||||
dma_set_coherent_mask(&pdev->dev, coherent_dma_mask))
|
||||
return -ENODEV;
|
||||
|
||||
if (ioc->dma_mask > 32) {
|
||||
@ -4313,7 +4320,7 @@ _base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4335,7 +4342,7 @@ _base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4358,7 +4365,7 @@ _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
descriptor.MSIxIndex = msix_task;
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4379,7 +4386,7 @@ _base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5424,6 +5431,151 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_atto_validate_nvram - validate the ATTO nvram read from mfg pg1
|
||||
*
|
||||
* @ioc : per adapter object
|
||||
* @n : ptr to the ATTO nvram structure
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
mpt3sas_atto_validate_nvram(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct ATTO_SAS_NVRAM *n)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
union ATTO_SAS_ADDRESS *s1;
|
||||
u32 len;
|
||||
u8 *pb;
|
||||
u8 ckSum;
|
||||
|
||||
/* validate nvram checksum */
|
||||
pb = (u8 *) n;
|
||||
ckSum = ATTO_SASNVR_CKSUM_SEED;
|
||||
len = sizeof(struct ATTO_SAS_NVRAM);
|
||||
|
||||
while (len--)
|
||||
ckSum = ckSum + pb[len];
|
||||
|
||||
if (ckSum) {
|
||||
ioc_err(ioc, "Invalid ATTO NVRAM checksum\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
s1 = (union ATTO_SAS_ADDRESS *) n->SasAddr;
|
||||
|
||||
if (n->Signature[0] != 'E'
|
||||
|| n->Signature[1] != 'S'
|
||||
|| n->Signature[2] != 'A'
|
||||
|| n->Signature[3] != 'S')
|
||||
ioc_err(ioc, "Invalid ATTO NVRAM signature\n");
|
||||
else if (n->Version > ATTO_SASNVR_VERSION)
|
||||
ioc_info(ioc, "Invalid ATTO NVRAM version");
|
||||
else if ((n->SasAddr[7] & (ATTO_SAS_ADDR_ALIGN - 1))
|
||||
|| s1->b[0] != 0x50
|
||||
|| s1->b[1] != 0x01
|
||||
|| s1->b[2] != 0x08
|
||||
|| (s1->b[3] & 0xF0) != 0x60
|
||||
|| ((s1->b[3] & 0x0F) | le32_to_cpu(s1->d[1])) == 0) {
|
||||
ioc_err(ioc, "Invalid ATTO SAS address\n");
|
||||
} else
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_atto_get_sas_addr - get the ATTO SAS address from mfg page 1
|
||||
*
|
||||
* @ioc : per adapter object
|
||||
* @*sas_addr : return sas address
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
mpt3sas_atto_get_sas_addr(struct MPT3SAS_ADAPTER *ioc, union ATTO_SAS_ADDRESS *sas_addr)
|
||||
{
|
||||
Mpi2ManufacturingPage1_t mfg_pg1;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
struct ATTO_SAS_NVRAM *nvram;
|
||||
int r;
|
||||
__be64 addr;
|
||||
|
||||
r = mpt3sas_config_get_manufacturing_pg1(ioc, &mpi_reply, &mfg_pg1);
|
||||
if (r) {
|
||||
ioc_err(ioc, "Failed to read manufacturing page 1\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* validate nvram */
|
||||
nvram = (struct ATTO_SAS_NVRAM *) mfg_pg1.VPD;
|
||||
r = mpt3sas_atto_validate_nvram(ioc, nvram);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
addr = *((__be64 *) nvram->SasAddr);
|
||||
sas_addr->q = cpu_to_le64(be64_to_cpu(addr));
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_atto_init - perform initializaion for ATTO branded
|
||||
* adapter.
|
||||
* @ioc : per adapter object
|
||||
*5
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
mpt3sas_atto_init(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
int sz = 0;
|
||||
Mpi2BiosPage4_t *bios_pg4 = NULL;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int r;
|
||||
int ix;
|
||||
union ATTO_SAS_ADDRESS sas_addr;
|
||||
union ATTO_SAS_ADDRESS temp;
|
||||
union ATTO_SAS_ADDRESS bias;
|
||||
|
||||
r = mpt3sas_atto_get_sas_addr(ioc, &sas_addr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* get header first to get size */
|
||||
r = mpt3sas_config_get_bios_pg4(ioc, &mpi_reply, NULL, 0);
|
||||
if (r) {
|
||||
ioc_err(ioc, "Failed to read ATTO bios page 4 header.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
sz = mpi_reply.Header.PageLength * sizeof(u32);
|
||||
bios_pg4 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!bios_pg4) {
|
||||
ioc_err(ioc, "Failed to allocate memory for ATTO bios page.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* read bios page 4 */
|
||||
r = mpt3sas_config_get_bios_pg4(ioc, &mpi_reply, bios_pg4, sz);
|
||||
if (r) {
|
||||
ioc_err(ioc, "Failed to read ATTO bios page 4\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update bios page 4 with the ATTO WWID */
|
||||
bias.q = sas_addr.q;
|
||||
bias.b[7] += ATTO_SAS_ADDR_DEVNAME_BIAS;
|
||||
|
||||
for (ix = 0; ix < bios_pg4->NumPhys; ix++) {
|
||||
temp.q = sas_addr.q;
|
||||
temp.b[7] += ix;
|
||||
bios_pg4->Phy[ix].ReassignmentWWID = temp.q;
|
||||
bios_pg4->Phy[ix].ReassignmentDeviceName = bias.q;
|
||||
}
|
||||
r = mpt3sas_config_set_bios_pg4(ioc, &mpi_reply, bios_pg4, sz);
|
||||
|
||||
out:
|
||||
kfree(bios_pg4);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_static_config_pages - static start of day config pages
|
||||
* @ioc: per adapter object
|
||||
@ -5447,6 +5599,13 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ioc->pdev->vendor == MPI2_MFGPAGE_VENDORID_ATTO) {
|
||||
rc = mpt3sas_atto_init(ioc);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure correct T10 PI operation if vendor left EEDPTagMode
|
||||
* flag unset in NVDATA.
|
||||
@ -5496,12 +5655,21 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
rc = _base_assign_fw_reported_qd(ioc);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* ATTO doesn't use bios page 2 and 3 for bios settings.
|
||||
*/
|
||||
if (ioc->pdev->vendor == MPI2_MFGPAGE_VENDORID_ATTO)
|
||||
ioc->bios_pg3.BiosVersion = 0;
|
||||
else {
|
||||
rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -6895,7 +7063,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
|
||||
/* send message 32-bits at a time */
|
||||
for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
|
||||
writel(request[i], &ioc->chip->Doorbell);
|
||||
writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 5)))
|
||||
failed = 1;
|
||||
}
|
||||
@ -6914,16 +7082,16 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
}
|
||||
|
||||
/* read the first two 16-bits, it gives the total length of the reply */
|
||||
reply[0] = ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK;
|
||||
reply[0] = le16_to_cpu(ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK);
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5))) {
|
||||
ioc_err(ioc, "doorbell handshake int failed (line=%d)\n",
|
||||
__LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
reply[1] = ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK;
|
||||
reply[1] = le16_to_cpu(ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK);
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
|
||||
for (i = 2; i < default_reply->MsgLength * 2; i++) {
|
||||
@ -6935,8 +7103,9 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
if (i >= reply_bytes/2) /* overflow case */
|
||||
ioc->base_readl(&ioc->chip->Doorbell);
|
||||
else
|
||||
reply[i] = ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK;
|
||||
reply[i] = le16_to_cpu(
|
||||
ioc->base_readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK);
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,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 "42.100.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 42
|
||||
#define MPT3SAS_DRIVER_VERSION "43.100.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 43
|
||||
#define MPT3SAS_MINOR_VERSION 100
|
||||
#define MPT3SAS_BUILD_VERSION 0
|
||||
#define MPT3SAS_RELEASE_VERSION 00
|
||||
@ -1652,6 +1652,32 @@ struct mpt3sas_debugfs_buffer {
|
||||
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
||||
u32 reply);
|
||||
|
||||
/*
|
||||
* struct ATTO_SAS_NVRAM - ATTO NVRAM settings stored
|
||||
* in Manufacturing page 1 used to get
|
||||
* ATTO SasAddr.
|
||||
*/
|
||||
struct ATTO_SAS_NVRAM {
|
||||
u8 Signature[4];
|
||||
u8 Version;
|
||||
#define ATTO_SASNVR_VERSION 0
|
||||
|
||||
u8 Checksum;
|
||||
#define ATTO_SASNVR_CKSUM_SEED 0x5A
|
||||
u8 Pad[10];
|
||||
u8 SasAddr[8];
|
||||
#define ATTO_SAS_ADDR_ALIGN 64
|
||||
u8 Reserved[232];
|
||||
};
|
||||
|
||||
#define ATTO_SAS_ADDR_DEVNAME_BIAS 63
|
||||
|
||||
union ATTO_SAS_ADDRESS {
|
||||
U8 b[8];
|
||||
U16 w[4];
|
||||
U32 d[2];
|
||||
U64 q;
|
||||
};
|
||||
|
||||
/* base shared API */
|
||||
extern struct list_head mpt3sas_ioc_list;
|
||||
@ -1828,6 +1854,9 @@ int mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc,
|
||||
u8 *num_phys);
|
||||
int mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
|
||||
int mpt3sas_config_get_manufacturing_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage1_t *config_page);
|
||||
|
||||
int mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
|
||||
u16 sz);
|
||||
@ -1846,6 +1875,12 @@ int mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi2BiosPage2_t *config_page);
|
||||
int mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi2BiosPage3_t *config_page);
|
||||
int mpt3sas_config_set_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
|
||||
int sz_config_page);
|
||||
int mpt3sas_config_get_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
|
||||
int sz_config_page);
|
||||
int mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi2IOUnitPage0_t *config_page);
|
||||
int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
@ -540,6 +540,42 @@ mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_manufacturing_pg1 - obtain manufacturing page 1
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_manufacturing_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage1_t *config_page)
|
||||
{
|
||||
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_MANUFACTURING;
|
||||
mpi_request.Header.PageNumber = 1;
|
||||
mpi_request.Header.PageVersion = MPI2_MANUFACTURING1_PAGEVERSION;
|
||||
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.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_manufacturing_pg7 - obtain manufacturing page 7
|
||||
* @ioc: per adapter object
|
||||
@ -757,10 +793,98 @@ mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_bios_pg4 - write out bios page 4
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* @sz_config_pg: sizeof the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_set_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
|
||||
int sz_config_pg)
|
||||
{
|
||||
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_BIOS;
|
||||
mpi_request.Header.PageNumber = 4;
|
||||
mpi_request.Header.PageVersion = MPI2_BIOSPAGE4_PAGEVERSION;
|
||||
|
||||
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.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sz_config_pg);
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_bios_pg4 - read bios page 4
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* @sz_config_pg: sizeof the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
|
||||
int sz_config_pg)
|
||||
{
|
||||
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_BIOS;
|
||||
mpi_request.Header.PageNumber = 4;
|
||||
mpi_request.Header.PageVersion = MPI2_BIOSPAGE4_PAGEVERSION;
|
||||
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;
|
||||
|
||||
/*
|
||||
* The sizeof the page is variable. Allow for just the
|
||||
* size to be returned
|
||||
*/
|
||||
if (config_page && sz_config_pg) {
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sz_config_pg);
|
||||
}
|
||||
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
|
||||
* @ioc: per adapter object
|
||||
|
@ -948,6 +948,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_FW_DOWNLOAD:
|
||||
{
|
||||
if (ioc->pdev->vendor == MPI2_MFGPAGE_VENDORID_ATTO) {
|
||||
ioc_info(ioc, "Firmware download not supported for ATTO HBA.\n");
|
||||
ret = -EPERM;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
}
|
||||
case MPI2_FUNCTION_FW_UPLOAD:
|
||||
{
|
||||
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
|
||||
@ -1686,6 +1694,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||
ioc->ctl_cmds.status = MPT3_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
memset(mpi_request, 0, ioc->request_sz);
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
|
||||
request_data = ioc->diag_buffer[buffer_type];
|
||||
@ -1787,6 +1796,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||
if (rc && request_data) {
|
||||
dma_free_coherent(&ioc->pdev->dev, request_data_sz,
|
||||
request_data, request_data_dma);
|
||||
ioc->diag_buffer[buffer_type] = NULL;
|
||||
ioc->diag_buffer_status[buffer_type] &=
|
||||
~MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
|
||||
}
|
||||
@ -2163,6 +2173,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
||||
ioc->ctl_cmds.status = MPT3_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
memset(mpi_request, 0, ioc->request_sz);
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
|
||||
mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
|
||||
@ -2417,6 +2428,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
ioc->ctl_cmds.status = MPT3_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
memset(mpi_request, 0, ioc->request_sz);
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
|
||||
mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
|
||||
|
@ -5156,6 +5156,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
||||
|
||||
/* invalid device handle */
|
||||
handle = sas_target_priv_data->handle;
|
||||
|
||||
/*
|
||||
* Avoid error handling escallation when device is disconnected
|
||||
*/
|
||||
if (handle == MPT3SAS_INVALID_DEVICE_HANDLE || sas_device_priv_data->block) {
|
||||
if (scmd->device->host->shost_state == SHOST_RECOVERY &&
|
||||
scmd->cmnd[0] == TEST_UNIT_READY) {
|
||||
scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07);
|
||||
scsi_done(scmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
scsi_done(scmd);
|
||||
@ -11974,7 +11987,7 @@ static struct scsi_host_template mpt3sas_driver_template = {
|
||||
.sg_tablesize = MPT3SAS_SG_DEPTH,
|
||||
.max_sectors = 32767,
|
||||
.max_segment_size = 0xffffffff,
|
||||
.cmd_per_lun = 7,
|
||||
.cmd_per_lun = 128,
|
||||
.shost_groups = mpt3sas_host_groups,
|
||||
.sdev_groups = mpt3sas_dev_groups,
|
||||
.track_queue_depth = 1,
|
||||
@ -12731,6 +12744,12 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3816,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
|
||||
/*
|
||||
* ATTO Branded ExpressSAS H12xx GT
|
||||
*/
|
||||
{ MPI2_MFGPAGE_VENDORID_ATTO, MPI26_MFGPAGE_DEVID_HARD_SEC_3816,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
|
||||
/*
|
||||
* Sea SI –> 0x00E4 Invalid, 0x00E7 Tampered
|
||||
*/
|
||||
|
@ -3612,6 +3612,10 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
||||
pm8001_dbg(pm8001_ha, FAIL, " TASK NULL. RETURNING !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (t->task_proto == SAS_PROTOCOL_INTERNAL_ABORT)
|
||||
atomic_dec(&pm8001_dev->running_req);
|
||||
|
||||
ts = &t->task_status;
|
||||
if (status != 0)
|
||||
pm8001_dbg(pm8001_ha, FAIL, "task abort failed status 0x%x ,tag = 0x%x, scp= 0x%x\n",
|
||||
|
@ -612,7 +612,7 @@ struct fw_control_info {
|
||||
operations.*/
|
||||
u32 reserved;/* padding required for 64 bit
|
||||
alignment */
|
||||
u8 buffer[1];/* Start of buffer */
|
||||
u8 buffer[];/* Start of buffer */
|
||||
};
|
||||
struct fw_control_ex {
|
||||
struct fw_control_info *fw_control;
|
||||
|
@ -1921,6 +1921,27 @@ static int qedf_vport_create(struct fc_vport *vport, bool disabled)
|
||||
fc_vport_setlink(vn_port);
|
||||
}
|
||||
|
||||
/* Set symbolic node name */
|
||||
if (base_qedf->pdev->device == QL45xxx)
|
||||
snprintf(fc_host_symbolic_name(vn_port->host), 256,
|
||||
"Marvell FastLinQ 45xxx FCoE v%s", QEDF_VERSION);
|
||||
|
||||
if (base_qedf->pdev->device == QL41xxx)
|
||||
snprintf(fc_host_symbolic_name(vn_port->host), 256,
|
||||
"Marvell FastLinQ 41xxx FCoE v%s", QEDF_VERSION);
|
||||
|
||||
/* Set supported speed */
|
||||
fc_host_supported_speeds(vn_port->host) = n_port->link_supported_speeds;
|
||||
|
||||
/* Set speed */
|
||||
vn_port->link_speed = n_port->link_speed;
|
||||
|
||||
/* Set port type */
|
||||
fc_host_port_type(vn_port->host) = FC_PORTTYPE_NPIV;
|
||||
|
||||
/* Set maxframe size */
|
||||
fc_host_maxframe_size(vn_port->host) = n_port->mfs;
|
||||
|
||||
QEDF_INFO(&(base_qedf->dbg_ctx), QEDF_LOG_NPIV, "vn_port=%p.\n",
|
||||
vn_port);
|
||||
|
||||
|
@ -2519,19 +2519,23 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
|
||||
qla27xx_get_active_image(vha, &active_regions);
|
||||
regions.global_image = active_regions.global;
|
||||
|
||||
if (IS_QLA27XX(ha))
|
||||
regions.nvme_params = QLA27XX_PRIMARY_IMAGE;
|
||||
|
||||
if (IS_QLA28XX(ha)) {
|
||||
qla28xx_get_aux_images(vha, &active_regions);
|
||||
regions.board_config = active_regions.aux.board_config;
|
||||
regions.vpd_nvram = active_regions.aux.vpd_nvram;
|
||||
regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
|
||||
regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
|
||||
regions.nvme_params = active_regions.aux.nvme_params;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_user, vha, 0x70e1,
|
||||
"%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
|
||||
"%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u NVME_PARAMS=%u\n",
|
||||
__func__, vha->host_no, regions.global_image,
|
||||
regions.board_config, regions.vpd_nvram,
|
||||
regions.npiv_config_0_1, regions.npiv_config_2_3);
|
||||
regions.npiv_config_0_1, regions.npiv_config_2_3, regions.nvme_params);
|
||||
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions));
|
||||
|
@ -314,7 +314,8 @@ struct qla_active_regions {
|
||||
uint8_t vpd_nvram;
|
||||
uint8_t npiv_config_0_1;
|
||||
uint8_t npiv_config_2_3;
|
||||
uint8_t reserved[32];
|
||||
uint8_t nvme_params;
|
||||
uint8_t reserved[31];
|
||||
} __packed;
|
||||
|
||||
#include "qla_edif_bsg.h"
|
||||
|
@ -2455,7 +2455,7 @@ qla83xx_fw_dump_failed_0:
|
||||
/****************************************************************************/
|
||||
|
||||
/* Write the debug message prefix into @pbuf. */
|
||||
static void ql_dbg_prefix(char *pbuf, int pbuf_size,
|
||||
static void ql_dbg_prefix(char *pbuf, int pbuf_size, struct pci_dev *pdev,
|
||||
const scsi_qla_host_t *vha, uint msg_id)
|
||||
{
|
||||
if (vha) {
|
||||
@ -2464,6 +2464,9 @@ static void ql_dbg_prefix(char *pbuf, int pbuf_size,
|
||||
/* <module-name> [<dev-name>]-<msg-id>:<host>: */
|
||||
snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%lu: ", QL_MSGHDR,
|
||||
dev_name(&(pdev->dev)), msg_id, vha->host_no);
|
||||
} else if (pdev) {
|
||||
snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR,
|
||||
dev_name(&pdev->dev), msg_id);
|
||||
} else {
|
||||
/* <module-name> [<dev-name>]-<msg-id>: : */
|
||||
snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR,
|
||||
@ -2491,20 +2494,20 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
|
||||
struct va_format vaf;
|
||||
char pbuf[64];
|
||||
|
||||
if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled())
|
||||
ql_ktrace(1, level, pbuf, NULL, vha, id, fmt);
|
||||
|
||||
if (!ql_mask_match(level))
|
||||
return;
|
||||
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, vha, id);
|
||||
|
||||
va_start(va, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &va;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
|
||||
|
||||
if (!ql_mask_match(level))
|
||||
trace_ql_dbg_log(pbuf, &vaf);
|
||||
else
|
||||
pr_warn("%s%pV", pbuf, &vaf);
|
||||
pr_warn("%s%pV", pbuf, &vaf);
|
||||
|
||||
va_end(va);
|
||||
|
||||
@ -2533,6 +2536,9 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
|
||||
|
||||
if (pdev == NULL)
|
||||
return;
|
||||
|
||||
ql_ktrace(1, level, pbuf, pdev, NULL, id, fmt);
|
||||
|
||||
if (!ql_mask_match(level))
|
||||
return;
|
||||
|
||||
@ -2541,7 +2547,9 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &va;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id + ql_dbg_offset);
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, NULL,
|
||||
id + ql_dbg_offset);
|
||||
pr_warn("%s%pV", pbuf, &vaf);
|
||||
|
||||
va_end(va);
|
||||
@ -2570,7 +2578,10 @@ ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
|
||||
if (level > ql_errlev)
|
||||
return;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
|
||||
ql_ktrace(0, level, pbuf, NULL, vha, id, fmt);
|
||||
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, vha, id);
|
||||
|
||||
va_start(va, fmt);
|
||||
|
||||
@ -2621,7 +2632,10 @@ ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
|
||||
if (level > ql_errlev)
|
||||
return;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id);
|
||||
ql_ktrace(0, level, pbuf, pdev, NULL, id, fmt);
|
||||
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, NULL, id);
|
||||
|
||||
va_start(va, fmt);
|
||||
|
||||
@ -2716,7 +2730,11 @@ ql_log_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
|
||||
if (level > ql_errlev)
|
||||
return;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL, id);
|
||||
ql_ktrace(0, level, pbuf, NULL, qpair ? qpair->vha : NULL, id, fmt);
|
||||
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL,
|
||||
qpair ? qpair->vha : NULL, id);
|
||||
|
||||
va_start(va, fmt);
|
||||
|
||||
@ -2762,6 +2780,8 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
|
||||
struct va_format vaf;
|
||||
char pbuf[128];
|
||||
|
||||
ql_ktrace(1, level, pbuf, NULL, qpair ? qpair->vha : NULL, id, fmt);
|
||||
|
||||
if (!ql_mask_match(level))
|
||||
return;
|
||||
|
||||
@ -2770,8 +2790,10 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &va;
|
||||
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL,
|
||||
id + ql_dbg_offset);
|
||||
if (!pbuf[0]) /* set by ql_ktrace */
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL,
|
||||
qpair ? qpair->vha : NULL, id + ql_dbg_offset);
|
||||
|
||||
pr_warn("%s%pV", pbuf, &vaf);
|
||||
|
||||
va_end(va);
|
||||
|
@ -385,3 +385,46 @@ ql_mask_match(uint level)
|
||||
|
||||
return level && ((level & ql2xextended_error_logging) == level);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ql_mask_match_ext(uint level, int *log_tunable)
|
||||
{
|
||||
if (*log_tunable == 1)
|
||||
*log_tunable = QL_DBG_DEFAULT1_MASK;
|
||||
|
||||
return (level & *log_tunable) == level;
|
||||
}
|
||||
|
||||
/* Assumes local variable pbuf and pbuf_ready present. */
|
||||
#define ql_ktrace(dbg_msg, level, pbuf, pdev, vha, id, fmt) do { \
|
||||
struct va_format _vaf; \
|
||||
va_list _va; \
|
||||
u32 dbg_off = dbg_msg ? ql_dbg_offset : 0; \
|
||||
\
|
||||
pbuf[0] = 0; \
|
||||
if (!trace_ql_dbg_log_enabled()) \
|
||||
break; \
|
||||
\
|
||||
if (dbg_msg && !ql_mask_match_ext(level, \
|
||||
&ql2xextended_error_logging_ktrace)) \
|
||||
break; \
|
||||
\
|
||||
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, vha, id + dbg_off); \
|
||||
\
|
||||
va_start(_va, fmt); \
|
||||
_vaf.fmt = fmt; \
|
||||
_vaf.va = &_va; \
|
||||
\
|
||||
trace_ql_dbg_log(pbuf, &_vaf); \
|
||||
\
|
||||
va_end(_va); \
|
||||
} while (0)
|
||||
|
||||
#define QLA_ENABLE_KERNEL_TRACING
|
||||
|
||||
#ifdef QLA_ENABLE_KERNEL_TRACING
|
||||
#define QLA_TRACE_ENABLE(_tr) \
|
||||
trace_array_set_clr_event(_tr, "qla", NULL, true)
|
||||
#else /* QLA_ENABLE_KERNEL_TRACING */
|
||||
#define QLA_TRACE_ENABLE(_tr)
|
||||
#endif /* QLA_ENABLE_KERNEL_TRACING */
|
||||
|
@ -35,6 +35,11 @@
|
||||
|
||||
#include <uapi/scsi/fc/fc_els.h>
|
||||
|
||||
#define QLA_DFS_DEFINE_DENTRY(_debugfs_file_name) \
|
||||
struct dentry *dfs_##_debugfs_file_name
|
||||
#define QLA_DFS_ROOT_DEFINE_DENTRY(_debugfs_file_name) \
|
||||
struct dentry *qla_dfs_##_debugfs_file_name
|
||||
|
||||
/* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */
|
||||
typedef struct {
|
||||
uint8_t domain;
|
||||
@ -4768,6 +4773,7 @@ struct active_regions {
|
||||
uint8_t vpd_nvram;
|
||||
uint8_t npiv_config_0_1;
|
||||
uint8_t npiv_config_2_3;
|
||||
uint8_t nvme_params;
|
||||
} aux;
|
||||
};
|
||||
|
||||
@ -5052,6 +5058,7 @@ struct qla27xx_image_status {
|
||||
#define QLA28XX_AUX_IMG_VPD_NVRAM BIT_1
|
||||
#define QLA28XX_AUX_IMG_NPIV_CONFIG_0_1 BIT_2
|
||||
#define QLA28XX_AUX_IMG_NPIV_CONFIG_2_3 BIT_3
|
||||
#define QLA28XX_AUX_IMG_NVME_PARAMS BIT_4
|
||||
|
||||
#define SET_VP_IDX 1
|
||||
#define SET_AL_PA 2
|
||||
|
@ -489,6 +489,99 @@ qla_dfs_naqp_show(struct seq_file *s, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper macros for setting up debugfs entries.
|
||||
* _name: The name of the debugfs entry
|
||||
* _ctx_struct: The context that was passed when creating the debugfs file
|
||||
*
|
||||
* QLA_DFS_SETUP_RD could be used when there is only a show function.
|
||||
* - show function take the name qla_dfs_<sysfs-name>_show
|
||||
*
|
||||
* QLA_DFS_SETUP_RW could be used when there are both show and write functions.
|
||||
* - show function take the name qla_dfs_<sysfs-name>_show
|
||||
* - write function take the name qla_dfs_<sysfs-name>_write
|
||||
*
|
||||
* To have a new debugfs entry, do:
|
||||
* 1. Create a "struct dentry *" in the appropriate structure in the format
|
||||
* dfs_<sysfs-name>
|
||||
* 2. Setup debugfs entries using QLA_DFS_SETUP_RD / QLA_DFS_SETUP_RW
|
||||
* 3. Create debugfs file in qla2x00_dfs_setup() using QLA_DFS_CREATE_FILE
|
||||
* or QLA_DFS_ROOT_CREATE_FILE
|
||||
* 4. Remove debugfs file in qla2x00_dfs_remove() using QLA_DFS_REMOVE_FILE
|
||||
* or QLA_DFS_ROOT_REMOVE_FILE
|
||||
*
|
||||
* Example for creating "TEST" sysfs file:
|
||||
* 1. struct qla_hw_data { ... struct dentry *dfs_TEST; }
|
||||
* 2. QLA_DFS_SETUP_RD(TEST, scsi_qla_host_t);
|
||||
* 3. In qla2x00_dfs_setup():
|
||||
* QLA_DFS_CREATE_FILE(ha, TEST, 0600, ha->dfs_dir, vha);
|
||||
* 4. In qla2x00_dfs_remove():
|
||||
* QLA_DFS_REMOVE_FILE(ha, TEST);
|
||||
*/
|
||||
#define QLA_DFS_SETUP_RD(_name, _ctx_struct) \
|
||||
static int \
|
||||
qla_dfs_##_name##_open(struct inode *inode, struct file *file) \
|
||||
{ \
|
||||
_ctx_struct *__ctx = inode->i_private; \
|
||||
\
|
||||
return single_open(file, qla_dfs_##_name##_show, __ctx); \
|
||||
} \
|
||||
\
|
||||
static const struct file_operations qla_dfs_##_name##_ops = { \
|
||||
.open = qla_dfs_##_name##_open, \
|
||||
.read = seq_read, \
|
||||
.llseek = seq_lseek, \
|
||||
.release = single_release, \
|
||||
};
|
||||
|
||||
#define QLA_DFS_SETUP_RW(_name, _ctx_struct) \
|
||||
static int \
|
||||
qla_dfs_##_name##_open(struct inode *inode, struct file *file) \
|
||||
{ \
|
||||
_ctx_struct *__ctx = inode->i_private; \
|
||||
\
|
||||
return single_open(file, qla_dfs_##_name##_show, __ctx); \
|
||||
} \
|
||||
\
|
||||
static const struct file_operations qla_dfs_##_name##_ops = { \
|
||||
.open = qla_dfs_##_name##_open, \
|
||||
.read = seq_read, \
|
||||
.llseek = seq_lseek, \
|
||||
.release = single_release, \
|
||||
.write = qla_dfs_##_name##_write, \
|
||||
};
|
||||
|
||||
#define QLA_DFS_ROOT_CREATE_FILE(_name, _perm, _ctx) \
|
||||
do { \
|
||||
if (!qla_dfs_##_name) \
|
||||
qla_dfs_##_name = debugfs_create_file(#_name, \
|
||||
_perm, qla2x00_dfs_root, _ctx, \
|
||||
&qla_dfs_##_name##_ops); \
|
||||
} while (0)
|
||||
|
||||
#define QLA_DFS_ROOT_REMOVE_FILE(_name) \
|
||||
do { \
|
||||
if (qla_dfs_##_name) { \
|
||||
debugfs_remove(qla_dfs_##_name); \
|
||||
qla_dfs_##_name = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define QLA_DFS_CREATE_FILE(_struct, _name, _perm, _parent, _ctx) \
|
||||
do { \
|
||||
(_struct)->dfs_##_name = debugfs_create_file(#_name, \
|
||||
_perm, _parent, _ctx, \
|
||||
&qla_dfs_##_name##_ops) \
|
||||
} while (0)
|
||||
|
||||
#define QLA_DFS_REMOVE_FILE(_struct, _name) \
|
||||
do { \
|
||||
if ((_struct)->dfs_##_name) { \
|
||||
debugfs_remove((_struct)->dfs_##_name); \
|
||||
(_struct)->dfs_##_name = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
qla_dfs_naqp_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
@ -1551,7 +1551,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
|
||||
ql_dbg(ql_dbg_edif, vha, 0x70a3, "Failed to find port= %06x\n",
|
||||
sa_frame.port_id.b24);
|
||||
rval = -EINVAL;
|
||||
SET_DID_STATUS(bsg_reply->result, DID_TARGET_FAILURE);
|
||||
SET_DID_STATUS(bsg_reply->result, DID_NO_CONNECT);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -1675,6 +1675,7 @@ struct qla_flt_location {
|
||||
#define FLT_REG_VPD_SEC_27XX_1 0x52
|
||||
#define FLT_REG_VPD_SEC_27XX_2 0xD8
|
||||
#define FLT_REG_VPD_SEC_27XX_3 0xDA
|
||||
#define FLT_REG_NVME_PARAMS_27XX 0x21
|
||||
|
||||
/* 28xx */
|
||||
#define FLT_REG_AUX_IMG_PRI_28XX 0x125
|
||||
@ -1691,6 +1692,8 @@ struct qla_flt_location {
|
||||
#define FLT_REG_MPI_SEC_28XX 0xF0
|
||||
#define FLT_REG_PEP_PRI_28XX 0xD1
|
||||
#define FLT_REG_PEP_SEC_28XX 0xF1
|
||||
#define FLT_REG_NVME_PARAMS_PRI_28XX 0x14E
|
||||
#define FLT_REG_NVME_PARAMS_SEC_28XX 0x179
|
||||
|
||||
struct qla_flt_region {
|
||||
__le16 code;
|
||||
|
@ -70,8 +70,6 @@ extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
|
||||
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
|
||||
extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
|
||||
enum qla_work_type);
|
||||
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
|
||||
@ -163,6 +161,7 @@ extern int ql2xrdpenable;
|
||||
extern int ql2xsmartsan;
|
||||
extern int ql2xallocfwdump;
|
||||
extern int ql2xextended_error_logging;
|
||||
extern int ql2xextended_error_logging_ktrace;
|
||||
extern int ql2xiidmaenable;
|
||||
extern int ql2xmqsupport;
|
||||
extern int ql2xfwloadbin;
|
||||
@ -193,8 +192,6 @@ extern int ql2xsecenable;
|
||||
extern int ql2xenforce_iocb_limit;
|
||||
extern int ql2xabts_wait_nvme;
|
||||
extern u32 ql2xnvme_queues;
|
||||
extern int ql2xrspq_follow_inptr;
|
||||
extern int ql2xrspq_follow_inptr_legacy;
|
||||
|
||||
extern int qla2x00_loop_reset(scsi_qla_host_t *);
|
||||
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
|
||||
@ -279,7 +276,6 @@ extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
|
||||
extern scsi_qla_host_t *qla24xx_create_vhost(struct fc_vport *);
|
||||
|
||||
extern void qla2x00_sp_free_dma(srb_t *sp);
|
||||
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
|
||||
|
||||
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int);
|
||||
extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *);
|
||||
@ -616,7 +612,6 @@ void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **
|
||||
/*
|
||||
* Global Function Prototypes in qla_sup.c source file.
|
||||
*/
|
||||
extern void qla2x00_release_nvram_protection(scsi_qla_host_t *);
|
||||
extern int qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *,
|
||||
uint32_t, uint32_t);
|
||||
extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t,
|
||||
@ -788,12 +783,6 @@ extern void qla2x00_init_response_q_entries(struct rsp_que *);
|
||||
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
|
||||
extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *);
|
||||
extern int qla25xx_delete_queues(struct scsi_qla_host *);
|
||||
extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t);
|
||||
extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t);
|
||||
extern void qla24xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
|
||||
extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
|
||||
extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
|
||||
extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
|
||||
|
||||
/* qlafx00 related functions */
|
||||
extern int qlafx00_pci_config(struct scsi_qla_host *);
|
||||
@ -878,8 +867,6 @@ extern void qla82xx_init_flags(struct qla_hw_data *);
|
||||
extern void qla82xx_set_drv_active(scsi_qla_host_t *);
|
||||
extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
|
||||
extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
|
||||
extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
|
||||
extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int);
|
||||
|
||||
/* ISP 8021 IDC */
|
||||
extern void qla82xx_clear_drv_active(struct qla_hw_data *);
|
||||
|
@ -7933,6 +7933,9 @@ qla28xx_component_status(
|
||||
|
||||
active_regions->aux.npiv_config_2_3 =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_2_3);
|
||||
|
||||
active_regions->aux.nvme_params =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NVME_PARAMS);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -8041,11 +8044,12 @@ check_valid_image:
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x018f,
|
||||
"aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u\n",
|
||||
"aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u, NVME=%u\n",
|
||||
active_regions->aux.board_config,
|
||||
active_regions->aux.vpd_nvram,
|
||||
active_regions->aux.npiv_config_0_1,
|
||||
active_regions->aux.npiv_config_2_3);
|
||||
active_regions->aux.npiv_config_2_3,
|
||||
active_regions->aux.nvme_params);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3764,7 +3764,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
struct purex_entry_24xx *purex_entry;
|
||||
struct purex_item *pure_item;
|
||||
u16 rsp_in = 0, cur_ring_index;
|
||||
int follow_inptr, is_shadow_hba;
|
||||
int is_shadow_hba;
|
||||
|
||||
if (!ha->flags.fw_started)
|
||||
return;
|
||||
@ -3774,25 +3774,18 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
qla_cpu_update(rsp->qpair, smp_processor_id());
|
||||
}
|
||||
|
||||
#define __update_rsp_in(_update, _is_shadow_hba, _rsp, _rsp_in) \
|
||||
#define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in) \
|
||||
do { \
|
||||
if (_update) { \
|
||||
_rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
|
||||
_rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
|
||||
rd_reg_dword_relaxed((_rsp)->rsp_q_in); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
|
||||
follow_inptr = is_shadow_hba ? ql2xrspq_follow_inptr :
|
||||
ql2xrspq_follow_inptr_legacy;
|
||||
|
||||
__update_rsp_in(follow_inptr, is_shadow_hba, rsp, rsp_in);
|
||||
__update_rsp_in(is_shadow_hba, rsp, rsp_in);
|
||||
|
||||
while ((likely(follow_inptr &&
|
||||
rsp->ring_index != rsp_in &&
|
||||
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) ||
|
||||
(!follow_inptr &&
|
||||
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
|
||||
while (rsp->ring_index != rsp_in &&
|
||||
rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
|
||||
pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
|
||||
cur_ring_index = rsp->ring_index;
|
||||
|
||||
@ -3906,8 +3899,7 @@ process_err:
|
||||
}
|
||||
pure_item = qla27xx_copy_fpin_pkt(vha,
|
||||
(void **)&pkt, &rsp);
|
||||
__update_rsp_in(follow_inptr, is_shadow_hba,
|
||||
rsp, rsp_in);
|
||||
__update_rsp_in(is_shadow_hba, rsp, rsp_in);
|
||||
if (!pure_item)
|
||||
break;
|
||||
qla24xx_queue_purex_item(vha, pure_item,
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <linux/blk-mq-pci.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/crash_dump.h>
|
||||
#include <linux/trace_events.h>
|
||||
#include <linux/trace.h>
|
||||
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsicam.h>
|
||||
@ -35,6 +37,8 @@ static int apidev_major;
|
||||
*/
|
||||
struct kmem_cache *srb_cachep;
|
||||
|
||||
static struct trace_array *qla_trc_array;
|
||||
|
||||
int ql2xfulldump_on_mpifail;
|
||||
module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ql2xfulldump_on_mpifail,
|
||||
@ -117,6 +121,11 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
|
||||
"ql2xextended_error_logging=1).\n"
|
||||
"\t\tDo LOGICAL OR of the value to enable more than one level");
|
||||
|
||||
int ql2xextended_error_logging_ktrace = 1;
|
||||
module_param(ql2xextended_error_logging_ktrace, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(ql2xextended_error_logging_ktrace,
|
||||
"Same BIT definition as ql2xextended_error_logging, but used to control logging to kernel trace buffer (default=1).\n");
|
||||
|
||||
int ql2xshiftctondsd = 6;
|
||||
module_param(ql2xshiftctondsd, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ql2xshiftctondsd,
|
||||
@ -333,21 +342,11 @@ MODULE_PARM_DESC(ql2xabts_wait_nvme,
|
||||
"To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
|
||||
|
||||
|
||||
u32 ql2xdelay_before_pci_error_handling = 5;
|
||||
static u32 ql2xdelay_before_pci_error_handling = 5;
|
||||
module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
|
||||
MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
|
||||
"Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
|
||||
|
||||
int ql2xrspq_follow_inptr = 1;
|
||||
module_param(ql2xrspq_follow_inptr, int, 0644);
|
||||
MODULE_PARM_DESC(ql2xrspq_follow_inptr,
|
||||
"Follow RSP IN pointer for RSP updates for HBAs 27xx and newer (default: 1).");
|
||||
|
||||
int ql2xrspq_follow_inptr_legacy = 1;
|
||||
module_param(ql2xrspq_follow_inptr_legacy, int, 0644);
|
||||
MODULE_PARM_DESC(ql2xrspq_follow_inptr_legacy,
|
||||
"Follow RSP IN pointer for RSP updates for HBAs older than 27XX. (default: 1).");
|
||||
|
||||
static void qla2x00_clear_drv_active(struct qla_hw_data *);
|
||||
static void qla2x00_free_device(scsi_qla_host_t *);
|
||||
static void qla2xxx_map_queues(struct Scsi_Host *shost);
|
||||
@ -2849,6 +2848,27 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
|
||||
spin_unlock_irqrestore(&vha->work_lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
qla_trace_init(void)
|
||||
{
|
||||
qla_trc_array = trace_array_get_by_name("qla2xxx");
|
||||
if (!qla_trc_array) {
|
||||
ql_log(ql_log_fatal, NULL, 0x0001,
|
||||
"Unable to create qla2xxx trace instance, instance logging will be disabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
QLA_TRACE_ENABLE(qla_trc_array);
|
||||
}
|
||||
|
||||
static void
|
||||
qla_trace_uninit(void)
|
||||
{
|
||||
if (!qla_trc_array)
|
||||
return;
|
||||
trace_array_put(qla_trc_array);
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI driver interface
|
||||
*/
|
||||
@ -3530,7 +3550,7 @@ skip_dpc:
|
||||
qla_dual_mode_enabled(base_vha))
|
||||
scsi_scan_host(host);
|
||||
else
|
||||
ql_dbg(ql_dbg_init, base_vha, 0x0122,
|
||||
ql_log(ql_log_info, base_vha, 0x0122,
|
||||
"skipping scsi_scan_host() for non-initiator port\n");
|
||||
|
||||
qla2x00_alloc_sysfs_attr(base_vha);
|
||||
@ -8189,6 +8209,8 @@ qla2x00_module_init(void)
|
||||
BUILD_BUG_ON(sizeof(sw_info_t) != 32);
|
||||
BUILD_BUG_ON(sizeof(target_id_t) != 2);
|
||||
|
||||
qla_trace_init();
|
||||
|
||||
/* Allocate cache for SRBs. */
|
||||
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
@ -8267,6 +8289,8 @@ qlt_exit:
|
||||
|
||||
destroy_cache:
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
|
||||
qla_trace_uninit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -8285,6 +8309,7 @@ qla2x00_module_exit(void)
|
||||
fc_release_transport(qla2xxx_transport_template);
|
||||
qlt_exit();
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
qla_trace_uninit();
|
||||
}
|
||||
|
||||
module_init(qla2x00_module_init);
|
||||
|
@ -1557,11 +1557,11 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf009,
|
||||
"Waiting for sess works (tgt %p)", tgt);
|
||||
spin_lock_irqsave(&tgt->sess_work_lock, flags);
|
||||
while (!list_empty(&tgt->sess_works_list)) {
|
||||
do {
|
||||
spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
|
||||
flush_scheduled_work();
|
||||
flush_work(&tgt->sess_work);
|
||||
spin_lock_irqsave(&tgt->sess_work_lock, flags);
|
||||
}
|
||||
} while (!list_empty(&tgt->sess_works_list));
|
||||
spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
|
||||
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00a,
|
||||
@ -6336,69 +6336,6 @@ out_term:
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
static void qlt_tmr_work(struct qla_tgt *tgt,
|
||||
struct qla_tgt_sess_work_param *prm)
|
||||
{
|
||||
struct atio_from_isp *a = &prm->tm_iocb2;
|
||||
struct scsi_qla_host *vha = tgt->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct fc_port *sess;
|
||||
unsigned long flags;
|
||||
be_id_t s_id;
|
||||
int rc;
|
||||
u64 unpacked_lun;
|
||||
int fn;
|
||||
void *iocb;
|
||||
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
|
||||
if (tgt->tgt_stop)
|
||||
goto out_term2;
|
||||
|
||||
s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id;
|
||||
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
|
||||
if (!sess) {
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
|
||||
sess = qlt_make_local_sess(vha, s_id);
|
||||
/* sess has got an extra creation ref */
|
||||
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
if (!sess)
|
||||
goto out_term2;
|
||||
} else {
|
||||
if (sess->deleted) {
|
||||
goto out_term2;
|
||||
}
|
||||
|
||||
if (!kref_get_unless_zero(&sess->sess_kref)) {
|
||||
ql_dbg(ql_dbg_tgt_tmr, vha, 0xf020,
|
||||
"%s: kref_get fail %8phC\n",
|
||||
__func__, sess->port_name);
|
||||
goto out_term2;
|
||||
}
|
||||
}
|
||||
|
||||
iocb = a;
|
||||
fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
|
||||
unpacked_lun =
|
||||
scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
|
||||
|
||||
rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
|
||||
ha->tgt.tgt_ops->put_sess(sess);
|
||||
|
||||
if (rc != 0)
|
||||
goto out_term;
|
||||
return;
|
||||
|
||||
out_term2:
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
out_term:
|
||||
qlt_send_term_exchange(ha->base_qpair, NULL, &prm->tm_iocb2, 1, 0);
|
||||
}
|
||||
|
||||
static void qlt_sess_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct qla_tgt *tgt = container_of(work, struct qla_tgt, sess_work);
|
||||
@ -6425,9 +6362,6 @@ static void qlt_sess_work_fn(struct work_struct *work)
|
||||
case QLA_TGT_SESS_WORK_ABORT:
|
||||
qlt_abort_work(tgt, prm);
|
||||
break;
|
||||
case QLA_TGT_SESS_WORK_TM:
|
||||
qlt_tmr_work(tgt, prm);
|
||||
break;
|
||||
default:
|
||||
BUG_ON(1);
|
||||
break;
|
||||
@ -6514,7 +6448,6 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
|
||||
tgt->ha = ha;
|
||||
tgt->vha = base_vha;
|
||||
init_waitqueue_head(&tgt->waitQ);
|
||||
INIT_LIST_HEAD(&tgt->del_sess_list);
|
||||
spin_lock_init(&tgt->sess_work_lock);
|
||||
INIT_WORK(&tgt->sess_work, qlt_sess_work_fn);
|
||||
INIT_LIST_HEAD(&tgt->sess_works_list);
|
||||
|
@ -813,9 +813,6 @@ struct qla_tgt {
|
||||
/* Count of sessions refering qla_tgt. Protected by hardware_lock. */
|
||||
int sess_count;
|
||||
|
||||
/* Protected by hardware_lock */
|
||||
struct list_head del_sess_list;
|
||||
|
||||
spinlock_t sess_work_lock;
|
||||
struct list_head sess_works_list;
|
||||
struct work_struct sess_work;
|
||||
@ -945,7 +942,6 @@ struct qla_tgt_sess_work_param {
|
||||
struct list_head sess_works_list_entry;
|
||||
|
||||
#define QLA_TGT_SESS_WORK_ABORT 1
|
||||
#define QLA_TGT_SESS_WORK_TM 2
|
||||
int type;
|
||||
|
||||
union {
|
||||
@ -1079,8 +1075,6 @@ extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *,
|
||||
struct init_cb_81xx *);
|
||||
extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
|
||||
struct nvram_81xx *);
|
||||
extern int qlt_24xx_process_response_error(struct scsi_qla_host *,
|
||||
struct sts_entry_24xx *);
|
||||
extern void qlt_modify_vp_config(struct scsi_qla_host *,
|
||||
struct vp_config_entry_24xx *);
|
||||
extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
|
||||
|
@ -6,9 +6,9 @@
|
||||
/*
|
||||
* Driver version
|
||||
*/
|
||||
#define QLA2XXX_VERSION "10.02.07.800-k"
|
||||
#define QLA2XXX_VERSION "10.02.07.900-k"
|
||||
|
||||
#define QLA_DRIVER_MAJOR_VER 10
|
||||
#define QLA_DRIVER_MINOR_VER 2
|
||||
#define QLA_DRIVER_PATCH_VER 7
|
||||
#define QLA_DRIVER_BETA_VER 800
|
||||
#define QLA_DRIVER_BETA_VER 900
|
||||
|
@ -909,7 +909,8 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
|
||||
sg_count = dma_map_sg(&qpti->op->dev, sg,
|
||||
scsi_sg_count(Cmnd),
|
||||
Cmnd->sc_data_direction);
|
||||
|
||||
if (!sg_count)
|
||||
return -1;
|
||||
ds = cmd->dataseg;
|
||||
cmd->segment_cnt = sg_count;
|
||||
|
||||
|
@ -334,6 +334,7 @@ enum blk_eh_timer_return scsi_timeout(struct request *req)
|
||||
trace_scsi_dispatch_cmd_timeout(scmd);
|
||||
scsi_log_completion(scmd, TIMEOUT_ERROR);
|
||||
|
||||
atomic_inc(&scmd->device->iotmo_cnt);
|
||||
if (host->eh_deadline != -1 && !host->last_reset)
|
||||
host->last_reset = jiffies;
|
||||
|
||||
@ -514,6 +515,11 @@ static void scsi_report_sense(struct scsi_device *sdev,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status)
|
||||
{
|
||||
cmd->result = (cmd->result & 0xffff00ff) | (status << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_check_sense - Examine scsi cmd sense
|
||||
* @scmd: Cmd to have sense checked.
|
||||
@ -644,7 +650,7 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
|
||||
case DATA_PROTECT:
|
||||
if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) {
|
||||
/* Thin provisioning hard threshold reached */
|
||||
set_host_byte(scmd, DID_ALLOC_FAILURE);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_NOSPC);
|
||||
return SUCCESS;
|
||||
}
|
||||
fallthrough;
|
||||
@ -652,14 +658,14 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
|
||||
case VOLUME_OVERFLOW:
|
||||
case MISCOMPARE:
|
||||
case BLANK_CHECK:
|
||||
set_host_byte(scmd, DID_TARGET_FAILURE);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
|
||||
return SUCCESS;
|
||||
|
||||
case MEDIUM_ERROR:
|
||||
if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
|
||||
sshdr.asc == 0x13 || /* AMNF DATA FIELD */
|
||||
sshdr.asc == 0x14) { /* RECORD NOT FOUND */
|
||||
set_host_byte(scmd, DID_MEDIUM_ERROR);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_MED_ERROR);
|
||||
return SUCCESS;
|
||||
}
|
||||
return NEEDS_RETRY;
|
||||
@ -668,7 +674,7 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
|
||||
if (scmd->device->retry_hwerror)
|
||||
return ADD_TO_MLQUEUE;
|
||||
else
|
||||
set_host_byte(scmd, DID_TARGET_FAILURE);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
|
||||
fallthrough;
|
||||
|
||||
case ILLEGAL_REQUEST:
|
||||
@ -678,7 +684,7 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
|
||||
sshdr.asc == 0x24 || /* Invalid field in cdb */
|
||||
sshdr.asc == 0x26 || /* Parameter value invalid */
|
||||
sshdr.asc == 0x27) { /* Write protected */
|
||||
set_host_byte(scmd, DID_TARGET_FAILURE);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
|
||||
}
|
||||
return SUCCESS;
|
||||
|
||||
@ -1983,7 +1989,7 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd)
|
||||
case SAM_STAT_RESERVATION_CONFLICT:
|
||||
sdev_printk(KERN_INFO, scmd->device,
|
||||
"reservation conflict\n");
|
||||
set_host_byte(scmd, DID_NEXUS_FAILURE);
|
||||
set_scsi_ml_byte(scmd, SCSIML_STAT_RESV_CONFLICT);
|
||||
return SUCCESS; /* causes immediate i/o error */
|
||||
}
|
||||
return FAILED;
|
||||
|
@ -581,16 +581,36 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline u8 get_scsi_ml_byte(int result)
|
||||
{
|
||||
return (result >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_result_to_blk_status - translate a SCSI result code into blk_status_t
|
||||
* @cmd: SCSI command
|
||||
* @result: scsi error code
|
||||
*
|
||||
* Translate a SCSI result code into a blk_status_t value. May reset the host
|
||||
* byte of @cmd->result.
|
||||
* Translate a SCSI result code into a blk_status_t value.
|
||||
*/
|
||||
static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
|
||||
static blk_status_t scsi_result_to_blk_status(int result)
|
||||
{
|
||||
/*
|
||||
* Check the scsi-ml byte first in case we converted a host or status
|
||||
* byte.
|
||||
*/
|
||||
switch (get_scsi_ml_byte(result)) {
|
||||
case SCSIML_STAT_OK:
|
||||
break;
|
||||
case SCSIML_STAT_RESV_CONFLICT:
|
||||
return BLK_STS_NEXUS;
|
||||
case SCSIML_STAT_NOSPC:
|
||||
return BLK_STS_NOSPC;
|
||||
case SCSIML_STAT_MED_ERROR:
|
||||
return BLK_STS_MEDIUM;
|
||||
case SCSIML_STAT_TGT_FAILURE:
|
||||
return BLK_STS_TARGET;
|
||||
}
|
||||
|
||||
switch (host_byte(result)) {
|
||||
case DID_OK:
|
||||
if (scsi_status_is_good(result))
|
||||
@ -599,18 +619,6 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
|
||||
case DID_TRANSPORT_FAILFAST:
|
||||
case DID_TRANSPORT_MARGINAL:
|
||||
return BLK_STS_TRANSPORT;
|
||||
case DID_TARGET_FAILURE:
|
||||
set_host_byte(cmd, DID_OK);
|
||||
return BLK_STS_TARGET;
|
||||
case DID_NEXUS_FAILURE:
|
||||
set_host_byte(cmd, DID_OK);
|
||||
return BLK_STS_NEXUS;
|
||||
case DID_ALLOC_FAILURE:
|
||||
set_host_byte(cmd, DID_OK);
|
||||
return BLK_STS_NOSPC;
|
||||
case DID_MEDIUM_ERROR:
|
||||
set_host_byte(cmd, DID_OK);
|
||||
return BLK_STS_MEDIUM;
|
||||
default:
|
||||
return BLK_STS_IOERR;
|
||||
}
|
||||
@ -697,7 +705,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
|
||||
if (sense_valid)
|
||||
sense_current = !scsi_sense_is_deferred(&sshdr);
|
||||
|
||||
blk_stat = scsi_result_to_blk_status(cmd, result);
|
||||
blk_stat = scsi_result_to_blk_status(result);
|
||||
|
||||
if (host_byte(result) == DID_RESET) {
|
||||
/* Third party bus reset or reset for error recovery
|
||||
@ -878,14 +886,14 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
}
|
||||
if (sense_current)
|
||||
*blk_statp = scsi_result_to_blk_status(cmd, result);
|
||||
*blk_statp = scsi_result_to_blk_status(result);
|
||||
} else if (blk_rq_bytes(req) == 0 && sense_current) {
|
||||
/*
|
||||
* Flush commands do not transfers any data, and thus cannot use
|
||||
* good_bytes != blk_rq_bytes(req) as the signal for an error.
|
||||
* This sets *blk_statp explicitly for the problem case.
|
||||
*/
|
||||
*blk_statp = scsi_result_to_blk_status(cmd, result);
|
||||
*blk_statp = scsi_result_to_blk_status(result);
|
||||
}
|
||||
/*
|
||||
* Recovered errors need reporting, but they're always treated as
|
||||
|
@ -18,6 +18,17 @@ struct scsi_nl_hdr;
|
||||
|
||||
#define SCSI_CMD_RETRIES_NO_LIMIT -1
|
||||
|
||||
/*
|
||||
* Error codes used by scsi-ml internally. These must not be used by drivers.
|
||||
*/
|
||||
enum scsi_ml_status {
|
||||
SCSIML_STAT_OK = 0x00,
|
||||
SCSIML_STAT_RESV_CONFLICT = 0x01, /* Reservation conflict */
|
||||
SCSIML_STAT_NOSPC = 0x02, /* Space allocation on the dev failed */
|
||||
SCSIML_STAT_MED_ERROR = 0x03, /* Medium error */
|
||||
SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */
|
||||
};
|
||||
|
||||
/*
|
||||
* Scsi Error Handler Flags
|
||||
*/
|
||||
|
@ -976,6 +976,7 @@ static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
|
||||
show_sdev_iostat(iorequest_cnt);
|
||||
show_sdev_iostat(iodone_cnt);
|
||||
show_sdev_iostat(ioerr_cnt);
|
||||
show_sdev_iostat(iotmo_cnt);
|
||||
|
||||
static ssize_t
|
||||
sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
@ -1295,6 +1296,7 @@ static struct attribute *scsi_sdev_attrs[] = {
|
||||
&dev_attr_iorequest_cnt.attr,
|
||||
&dev_attr_iodone_cnt.attr,
|
||||
&dev_attr_ioerr_cnt.attr,
|
||||
&dev_attr_iotmo_cnt.attr,
|
||||
&dev_attr_modalias.attr,
|
||||
&dev_attr_queue_depth.attr,
|
||||
&dev_attr_queue_type.attr,
|
||||
|
@ -543,7 +543,7 @@ fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,
|
||||
struct nlmsghdr *nlh;
|
||||
struct fc_nl_event *event;
|
||||
const char *name;
|
||||
u32 len;
|
||||
size_t len, padding;
|
||||
int err;
|
||||
|
||||
if (!data_buf || data_len < 4)
|
||||
@ -554,7 +554,7 @@ fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,
|
||||
goto send_fail;
|
||||
}
|
||||
|
||||
len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
|
||||
len = FC_NL_MSGALIGN(sizeof(*event) - sizeof(event->event_data) + data_len);
|
||||
|
||||
skb = nlmsg_new(len, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
@ -578,7 +578,9 @@ fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,
|
||||
event->event_num = event_number;
|
||||
event->event_code = event_code;
|
||||
if (data_len)
|
||||
memcpy(&event->event_data, data_buf, data_len);
|
||||
memcpy(event->event_data_flex, data_buf, data_len);
|
||||
padding = len - offsetof(typeof(*event), event_data_flex) - data_len;
|
||||
memset(event->event_data_flex + data_len, 0, padding);
|
||||
|
||||
nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
|
||||
GFP_KERNEL);
|
||||
@ -1170,7 +1172,7 @@ static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
|
||||
return 0;
|
||||
}
|
||||
|
||||
fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
|
||||
fc_rport_show_function(dev_loss_tmo, "%u\n", 20, )
|
||||
static ssize_t
|
||||
store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
@ -4248,11 +4248,10 @@ static int st_probe(struct device *dev)
|
||||
struct st_partstat *STps;
|
||||
struct st_buffer *buffer;
|
||||
int i, error;
|
||||
char *stp;
|
||||
|
||||
if (SDp->type != TYPE_TAPE)
|
||||
return -ENODEV;
|
||||
if ((stp = st_incompatible(SDp))) {
|
||||
if (st_incompatible(SDp)) {
|
||||
sdev_printk(KERN_INFO, SDp,
|
||||
"OnStream tapes are no longer supported;\n");
|
||||
sdev_printk(KERN_INFO, SDp,
|
||||
|
@ -665,16 +665,17 @@ static int stex_queuecommand_lck(struct scsi_cmnd *cmd)
|
||||
return 0;
|
||||
case PASSTHRU_CMD:
|
||||
if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
|
||||
struct st_drvver ver;
|
||||
const struct st_drvver ver = {
|
||||
.major = ST_VER_MAJOR,
|
||||
.minor = ST_VER_MINOR,
|
||||
.oem = ST_OEM,
|
||||
.build = ST_BUILD_VER,
|
||||
.signature[0] = PASSTHRU_SIGNATURE,
|
||||
.console_id = host->max_id - 1,
|
||||
.host_no = hba->host->host_no,
|
||||
};
|
||||
size_t cp_len = sizeof(ver);
|
||||
|
||||
ver.major = ST_VER_MAJOR;
|
||||
ver.minor = ST_VER_MINOR;
|
||||
ver.oem = ST_OEM;
|
||||
ver.build = ST_BUILD_VER;
|
||||
ver.signature[0] = PASSTHRU_SIGNATURE;
|
||||
ver.console_id = host->max_id - 1;
|
||||
ver.host_no = hba->host->host_no;
|
||||
cp_len = scsi_sg_copy_from_buffer(cmd, &ver, cp_len);
|
||||
if (sizeof(ver) == cp_len)
|
||||
cmd->result = DID_OK << 16;
|
||||
|
@ -1029,7 +1029,7 @@ do_work:
|
||||
*/
|
||||
wrk = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
|
||||
if (!wrk) {
|
||||
set_host_byte(scmnd, DID_TARGET_FAILURE);
|
||||
set_host_byte(scmnd, DID_BAD_TARGET);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -141,10 +141,10 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
|
||||
set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
|
||||
break;
|
||||
case VIRTIO_SCSI_S_TARGET_FAILURE:
|
||||
set_host_byte(sc, DID_TARGET_FAILURE);
|
||||
set_host_byte(sc, DID_BAD_TARGET);
|
||||
break;
|
||||
case VIRTIO_SCSI_S_NEXUS_FAILURE:
|
||||
set_host_byte(sc, DID_NEXUS_FAILURE);
|
||||
set_status_byte(sc, SAM_STAT_RESERVATION_CONFLICT);
|
||||
break;
|
||||
default:
|
||||
scmd_printk(KERN_WARNING, sc, "Unknown response %d",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user