mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 12:11:59 +02:00
Merge 62e6e5940c ("Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi") into android-mainline
Steps on the way to 6.1-rc1 Resolves conflicts in: drivers/ufs/core/ufshcd.c include/ufs/ufshcd.h Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ic4a9c1e9a22a8aae818bf726e5fd8433f3a80dfa
This commit is contained in:
commit
74fe3fdd12
|
|
@ -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 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev, u32 board_id)
|
|||
|
||||
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 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
|
|||
|
||||
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 @@ lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
|
|||
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 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
|
||||
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 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|||
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(struct lpfc_hba *phba)
|
|||
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 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
|
|||
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 @@ lpfc_cmf_setup(struct lpfc_hba *phba)
|
|||
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 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
|||
|
||||
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 @@ static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc,
|
|||
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 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
|
|||
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(scsi_qla_host_t *vha)
|
|||
/****************************************************************************/
|
||||
|
||||
/* 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 @@ qla28xx_get_aux_images(
|
|||
}
|
||||
|
||||
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 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
|||
}
|
||||
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 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
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 @@ qla2x00_module_init(void)
|
|||
|
||||
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 @@ static void qlt_abort_work(struct qla_tgt *tgt,
|
|||
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 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
|
|||
*/
|
||||
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