mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
SCSI misc on 20240110
Updates to the usual drivers (ufs, mpi3mr, mpt3sas, lpfc, fnic, hisi_sas, arcmsr, ) plus the usual assorted minor fixes and updates. This time around there's only a single line update to the core, so nothing major and barely anything minor. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCZZ7roSYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pisha3lAQC5BAGM 7OKk39iOtsKdq8uxYAhYx871sNtwBp8+BSk1FgEAhy1hg7fgCnOvl7chbSNDR6p/ mW11fYi4j2UvxECT2tg= =/tvT -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI updates from James Bottomley: "Updates to the usual drivers (ufs, mpi3mr, mpt3sas, lpfc, fnic, hisi_sas, arcmsr, ) plus the usual assorted minor fixes and updates. This time around there's only a single line update to the core, so nothing major and barely anything minor" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (135 commits) scsi: ufs: core: Simplify ufshcd_auto_hibern8_update() scsi: ufs: core: Rename ufshcd_auto_hibern8_enable() and make it static scsi: ufs: qcom: Fix ESI vector mask scsi: ufs: host: Fix kernel-doc warning scsi: hisi_sas: Correct the number of global debugfs registers scsi: hisi_sas: Rollback some operations if FLR failed scsi: hisi_sas: Check before using pointer variables scsi: hisi_sas: Replace with standard error code return value scsi: hisi_sas: Set .phy_attached before notifing phyup event HISI_PHYE_PHY_UP_PM scsi: ufs: core: Add sysfs node for UFS RTC update scsi: ufs: core: Add UFS RTC support scsi: ufs: core: Add ufshcd_is_ufs_dev_busy() scsi: ufs: qcom: Remove unused definitions scsi: ufs: qcom: Use ufshcd_rmwl() where applicable scsi: ufs: qcom: Remove support for host controllers older than v2.0 scsi: ufs: qcom: Simplify ufs_qcom_{assert/deassert}_reset scsi: ufs: qcom: Initialize cycles_in_1us variable in ufs_qcom_set_core_clk_ctrl() scsi: ufs: qcom: Sort includes alphabetically scsi: ufs: qcom: Remove unused ufs_qcom_hosts struct array scsi: ufs: qcom: Use dev_err_probe() to simplify error handling of devm_gpiod_get_optional() ...
This commit is contained in:
commit
22d29f1112
@ -1223,6 +1223,55 @@ Description: This file shows the total latency (in micro seconds) of write
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/lane
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/lane
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows how many lanes are enabled on the UFS link,
|
||||
i.e., an output 2 means UFS link is operating with 2 lanes.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/mode
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/mode
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows the PA power mode of UFS.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/rate
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/rate
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows the speed rate of UFS link.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/gear
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/gear
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows the gear of UFS link.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/dev_pm
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/dev_pm
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows the UFS device power mode.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_info/link_state
|
||||
What: /sys/bus/platform/devices/*.ufs/power_info/link_state
|
||||
Date: September 2023
|
||||
Contact: Can Guo <quic_cang@quicinc.com>
|
||||
Description: This file shows the state of UFS link.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en
|
||||
What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en
|
||||
Date: June 2020
|
||||
@ -1474,3 +1523,10 @@ Description: Indicates status of Write Booster.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/rtc_update_ms
|
||||
What: /sys/bus/platform/devices/*.ufs/rtc_update_ms
|
||||
Date: November 2023
|
||||
Contact: Bean Huo <beanhuo@micron.com>
|
||||
Description:
|
||||
rtc_update_ms indicates how often the host should synchronize or update the
|
||||
UFS RTC. If set to 0, this will disable UFS RTC periodic update.
|
||||
|
@ -27,6 +27,7 @@ properties:
|
||||
- qcom,msm8996-ufshc
|
||||
- qcom,msm8998-ufshc
|
||||
- qcom,sa8775p-ufshc
|
||||
- qcom,sc7280-ufshc
|
||||
- qcom,sc8280xp-ufshc
|
||||
- qcom,sdm845-ufshc
|
||||
- qcom,sm6115-ufshc
|
||||
@ -118,6 +119,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,msm8998-ufshc
|
||||
- qcom,sa8775p-ufshc
|
||||
- qcom,sc7280-ufshc
|
||||
- qcom,sc8280xp-ufshc
|
||||
- qcom,sm8250-ufshc
|
||||
- qcom,sm8350-ufshc
|
||||
|
@ -87,6 +87,8 @@ properties:
|
||||
description:
|
||||
Specifies max. load that can be drawn from VCCQ2 supply.
|
||||
|
||||
msi-parent: true
|
||||
|
||||
dependencies:
|
||||
freq-table-hz: [ clocks ]
|
||||
operating-points-v2: [ clocks, clock-names ]
|
||||
|
@ -22320,7 +22320,8 @@ S: Maintained
|
||||
F: drivers/ufs/host/ufs-exynos*
|
||||
|
||||
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER MEDIATEK HOOKS
|
||||
M: Stanley Chu <stanley.chu@mediatek.com>
|
||||
M: Peter Wang <peter.wang@mediatek.com>
|
||||
R: Stanley Jhu <chu.stanley@gmail.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
|
@ -900,8 +900,19 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
|
||||
zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
|
||||
FC_SYMBOLIC_NAME_SIZE);
|
||||
hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
|
||||
len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
|
||||
FC_SYMBOLIC_NAME_SIZE);
|
||||
|
||||
BUILD_BUG_ON(sizeof(rspn_req->name) !=
|
||||
sizeof(fc_host_symbolic_name(shost)));
|
||||
BUILD_BUG_ON(sizeof(rspn_req->name) !=
|
||||
type_max(typeof(rspn_req->rspn.fr_name_len)) + 1);
|
||||
len = strscpy(rspn_req->name, fc_host_symbolic_name(shost),
|
||||
sizeof(rspn_req->name));
|
||||
/*
|
||||
* It should be impossible for this to truncate (see BUILD_BUG_ON()
|
||||
* above), but be robust anyway.
|
||||
*/
|
||||
if (WARN_ON(len < 0))
|
||||
len = sizeof(rspn_req->name) - 1;
|
||||
rspn_req->rspn.fr_name_len = len;
|
||||
|
||||
sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));
|
||||
|
@ -1326,7 +1326,8 @@ static int twl_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
|
||||
}
|
||||
|
||||
/* Load rest of compatibility struct */
|
||||
strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
|
||||
strscpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION,
|
||||
sizeof(tw_dev->tw_compat_info.driver_version));
|
||||
tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
|
||||
tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
|
||||
tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
|
||||
|
@ -282,7 +282,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
|
||||
static void __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
struct a3000_hostdata *hdata = shost_priv(instance);
|
||||
@ -293,11 +293,10 @@ static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
|
||||
free_irq(IRQ_AMIGA_PORTS, instance);
|
||||
scsi_host_put(instance);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver amiga_a3000_scsi_driver = {
|
||||
.remove = __exit_p(amiga_a3000_scsi_remove),
|
||||
.remove_new = __exit_p(amiga_a3000_scsi_remove),
|
||||
.driver = {
|
||||
.name = "amiga-a3000-scsi",
|
||||
},
|
||||
|
@ -95,7 +95,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
|
||||
static void __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *host = platform_get_drvdata(pdev);
|
||||
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
|
||||
@ -106,11 +106,10 @@ static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
|
||||
kfree(hostdata);
|
||||
free_irq(host->irq, host);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver amiga_a4000t_scsi_driver = {
|
||||
.remove = __exit_p(amiga_a4000t_scsi_remove),
|
||||
.remove_new = __exit_p(amiga_a4000t_scsi_remove),
|
||||
.driver = {
|
||||
.name = "amiga-a4000t-scsi",
|
||||
},
|
||||
|
@ -87,17 +87,17 @@ aic7770_probe(struct device *dev)
|
||||
sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
|
||||
name = kstrdup(buf, GFP_ATOMIC);
|
||||
if (name == NULL)
|
||||
return (ENOMEM);
|
||||
return -ENOMEM;
|
||||
ahc = ahc_alloc(&aic7xxx_driver_template, name);
|
||||
if (ahc == NULL)
|
||||
return (ENOMEM);
|
||||
return -ENOMEM;
|
||||
ahc->dev = dev;
|
||||
error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
|
||||
eisaBase);
|
||||
if (error != 0) {
|
||||
ahc->bsh.ioport = 0;
|
||||
ahc_free(ahc);
|
||||
return (error);
|
||||
return error < 0 ? error : -error;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, ahc);
|
||||
|
@ -1085,7 +1085,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
|
||||
template->name = ahc->description;
|
||||
host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
|
||||
if (host == NULL)
|
||||
return (ENOMEM);
|
||||
return -ENOMEM;
|
||||
|
||||
*((struct ahc_softc **)host->hostdata) = ahc;
|
||||
ahc->platform_data->host = host;
|
||||
|
@ -241,8 +241,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
ahc_linux_pci_inherit_flags(ahc);
|
||||
|
||||
pci_set_drvdata(pdev, ahc);
|
||||
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
|
||||
return (0);
|
||||
return ahc_linux_register_host(ahc, &aic7xxx_driver_template);
|
||||
}
|
||||
|
||||
/******************************* PCI Routines *********************************/
|
||||
|
@ -50,7 +50,7 @@ struct device_attribute;
|
||||
#define ARCMSR_MAX_OUTSTANDING_CMD 1024
|
||||
#define ARCMSR_DEFAULT_OUTSTANDING_CMD 128
|
||||
#define ARCMSR_MIN_OUTSTANDING_CMD 32
|
||||
#define ARCMSR_DRIVER_VERSION "v1.50.00.13-20230206"
|
||||
#define ARCMSR_DRIVER_VERSION "v1.51.00.14-20230915"
|
||||
#define ARCMSR_SCSI_INITIATOR_ID 255
|
||||
#define ARCMSR_MAX_XFER_SECTORS 512
|
||||
#define ARCMSR_MAX_XFER_SECTORS_B 4096
|
||||
@ -78,9 +78,13 @@ struct device_attribute;
|
||||
#ifndef PCI_DEVICE_ID_ARECA_1203
|
||||
#define PCI_DEVICE_ID_ARECA_1203 0x1203
|
||||
#endif
|
||||
#ifndef PCI_DEVICE_ID_ARECA_1883
|
||||
#define PCI_DEVICE_ID_ARECA_1883 0x1883
|
||||
#endif
|
||||
#ifndef PCI_DEVICE_ID_ARECA_1884
|
||||
#define PCI_DEVICE_ID_ARECA_1884 0x1884
|
||||
#endif
|
||||
#define PCI_DEVICE_ID_ARECA_1886_0 0x1886
|
||||
#define PCI_DEVICE_ID_ARECA_1886 0x188A
|
||||
#define ARCMSR_HOURS (1000 * 60 * 60 * 4)
|
||||
#define ARCMSR_MINUTES (1000 * 60 * 60)
|
||||
@ -818,6 +822,23 @@ typedef struct deliver_completeQ {
|
||||
uint16_t cmdLMID; // reserved (0)
|
||||
uint16_t cmdFlag2; // reserved (0)
|
||||
} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
|
||||
|
||||
#define ARCMSR_XOR_SEG_SIZE (1024 * 1024)
|
||||
struct HostRamBuf {
|
||||
uint32_t hrbSignature; // must be "HRBS"
|
||||
uint32_t hrbSize; // total sg size, be multiples of MB
|
||||
uint32_t hrbRes[2]; // reserved, must be set to 0
|
||||
};
|
||||
struct Xor_sg {
|
||||
dma_addr_t xorPhys;
|
||||
uint64_t xorBufLen;
|
||||
};
|
||||
struct XorHandle {
|
||||
dma_addr_t xorPhys;
|
||||
uint64_t xorBufLen;
|
||||
void *xorVirt;
|
||||
};
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
** Adapter Control Block
|
||||
@ -929,6 +950,7 @@ struct AdapterControlBlock
|
||||
char firm_model[12];
|
||||
char firm_version[20];
|
||||
char device_map[20]; /*21,84-99*/
|
||||
uint32_t firm_PicStatus;
|
||||
struct work_struct arcmsr_do_message_isr_bh;
|
||||
struct timer_list eternal_timer;
|
||||
unsigned short fw_flag;
|
||||
@ -937,6 +959,7 @@ struct AdapterControlBlock
|
||||
#define FW_DEADLOCK 0x0010
|
||||
uint32_t maxOutstanding;
|
||||
int vector_count;
|
||||
int xor_mega;
|
||||
uint32_t maxFreeCCB;
|
||||
struct timer_list refresh_timer;
|
||||
uint32_t doneq_index;
|
||||
@ -946,6 +969,10 @@ struct AdapterControlBlock
|
||||
uint32_t completionQ_entry;
|
||||
pCompletion_Q pCompletionQ;
|
||||
uint32_t completeQ_size;
|
||||
void *xorVirt;
|
||||
dma_addr_t xorPhys;
|
||||
unsigned int init2cfg_size;
|
||||
unsigned int xorVirtOffset;
|
||||
};/* HW_DEVICE_EXTENSION */
|
||||
/*
|
||||
*******************************************************************************
|
||||
|
@ -214,8 +214,12 @@ static struct pci_device_id arcmsr_device_id_table[] = {
|
||||
.driver_data = ACB_ADAPTER_TYPE_A},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1880),
|
||||
.driver_data = ACB_ADAPTER_TYPE_C},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1883),
|
||||
.driver_data = ACB_ADAPTER_TYPE_C},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1884),
|
||||
.driver_data = ACB_ADAPTER_TYPE_E},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1886_0),
|
||||
.driver_data = ACB_ADAPTER_TYPE_F},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1886),
|
||||
.driver_data = ACB_ADAPTER_TYPE_F},
|
||||
{0, 0}, /* Terminating entry */
|
||||
@ -747,6 +751,57 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static int arcmsr_alloc_xor_buffer(struct AdapterControlBlock *acb)
|
||||
{
|
||||
int rc = 0;
|
||||
struct pci_dev *pdev = acb->pdev;
|
||||
void *dma_coherent;
|
||||
dma_addr_t dma_coherent_handle;
|
||||
int i, xor_ram;
|
||||
struct Xor_sg *pXorPhys;
|
||||
void **pXorVirt;
|
||||
struct HostRamBuf *pRamBuf;
|
||||
|
||||
// allocate 1 MB * N physically continuous memory for XOR engine.
|
||||
xor_ram = (acb->firm_PicStatus >> 24) & 0x0f;
|
||||
acb->xor_mega = (xor_ram - 1) * 32 + 128 + 3;
|
||||
acb->init2cfg_size = sizeof(struct HostRamBuf) +
|
||||
(sizeof(struct XorHandle) * acb->xor_mega);
|
||||
dma_coherent = dma_alloc_coherent(&pdev->dev, acb->init2cfg_size,
|
||||
&dma_coherent_handle, GFP_KERNEL);
|
||||
acb->xorVirt = dma_coherent;
|
||||
acb->xorPhys = dma_coherent_handle;
|
||||
pXorPhys = (struct Xor_sg *)((unsigned long)dma_coherent +
|
||||
sizeof(struct HostRamBuf));
|
||||
acb->xorVirtOffset = sizeof(struct HostRamBuf) +
|
||||
(sizeof(struct Xor_sg) * acb->xor_mega);
|
||||
pXorVirt = (void **)((unsigned long)dma_coherent +
|
||||
(unsigned long)acb->xorVirtOffset);
|
||||
for (i = 0; i < acb->xor_mega; i++) {
|
||||
dma_coherent = dma_alloc_coherent(&pdev->dev,
|
||||
ARCMSR_XOR_SEG_SIZE,
|
||||
&dma_coherent_handle, GFP_KERNEL);
|
||||
if (dma_coherent) {
|
||||
pXorPhys->xorPhys = dma_coherent_handle;
|
||||
pXorPhys->xorBufLen = ARCMSR_XOR_SEG_SIZE;
|
||||
*pXorVirt = dma_coherent;
|
||||
pXorPhys++;
|
||||
pXorVirt++;
|
||||
} else {
|
||||
pr_info("arcmsr%d: alloc max XOR buffer = 0x%x MB\n",
|
||||
acb->host->host_no, i);
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pRamBuf = (struct HostRamBuf *)acb->xorVirt;
|
||||
pRamBuf->hrbSignature = 0x53425248; //HRBS
|
||||
pRamBuf->hrbSize = i * ARCMSR_XOR_SEG_SIZE;
|
||||
pRamBuf->hrbRes[0] = 0;
|
||||
pRamBuf->hrbRes[1] = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct pci_dev *pdev = acb->pdev;
|
||||
@ -836,7 +891,11 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
acb->completionQ_entry = acb->ioqueue_size / sizeof(struct deliver_completeQ);
|
||||
acb->doneq_index = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((acb->firm_PicStatus >> 24) & 0x0f) {
|
||||
if (arcmsr_alloc_xor_buffer(acb))
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2022,6 +2081,29 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
|
||||
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
|
||||
{
|
||||
if (acb->xor_mega) {
|
||||
struct Xor_sg *pXorPhys;
|
||||
void **pXorVirt;
|
||||
int i;
|
||||
|
||||
pXorPhys = (struct Xor_sg *)(acb->xorVirt +
|
||||
sizeof(struct HostRamBuf));
|
||||
pXorVirt = (void **)((unsigned long)acb->xorVirt +
|
||||
(unsigned long)acb->xorVirtOffset);
|
||||
for (i = 0; i < acb->xor_mega; i++) {
|
||||
if (pXorPhys->xorPhys) {
|
||||
dma_free_coherent(&acb->pdev->dev,
|
||||
ARCMSR_XOR_SEG_SIZE,
|
||||
*pXorVirt, pXorPhys->xorPhys);
|
||||
pXorPhys->xorPhys = 0;
|
||||
*pXorVirt = NULL;
|
||||
}
|
||||
pXorPhys++;
|
||||
pXorVirt++;
|
||||
}
|
||||
dma_free_coherent(&acb->pdev->dev, acb->init2cfg_size,
|
||||
acb->xorVirt, acb->xorPhys);
|
||||
}
|
||||
dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle);
|
||||
}
|
||||
|
||||
@ -3309,6 +3391,10 @@ static void arcmsr_get_adapter_config(struct AdapterControlBlock *pACB, uint32_t
|
||||
pACB->firm_sdram_size = readl(&rwbuffer[3]);
|
||||
pACB->firm_hd_channels = readl(&rwbuffer[4]);
|
||||
pACB->firm_cfg_version = readl(&rwbuffer[25]);
|
||||
if (pACB->adapter_type == ACB_ADAPTER_TYPE_F)
|
||||
pACB->firm_PicStatus = readl(&rwbuffer[30]);
|
||||
else
|
||||
pACB->firm_PicStatus = 0;
|
||||
pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
|
||||
pACB->host->host_no,
|
||||
pACB->firm_model,
|
||||
@ -4096,6 +4182,12 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
|
||||
acb->msgcode_rwbuffer[5] = lower_32_bits(acb->dma_coherent_handle2);
|
||||
acb->msgcode_rwbuffer[6] = upper_32_bits(acb->dma_coherent_handle2);
|
||||
acb->msgcode_rwbuffer[7] = acb->completeQ_size;
|
||||
if (acb->xor_mega) {
|
||||
acb->msgcode_rwbuffer[8] = 0x455AA; //Linux init 2
|
||||
acb->msgcode_rwbuffer[9] = 0;
|
||||
acb->msgcode_rwbuffer[10] = lower_32_bits(acb->xorPhys);
|
||||
acb->msgcode_rwbuffer[11] = upper_32_bits(acb->xorPhys);
|
||||
}
|
||||
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
@ -4706,9 +4798,11 @@ static const char *arcmsr_info(struct Scsi_Host *host)
|
||||
case PCI_DEVICE_ID_ARECA_1680:
|
||||
case PCI_DEVICE_ID_ARECA_1681:
|
||||
case PCI_DEVICE_ID_ARECA_1880:
|
||||
case PCI_DEVICE_ID_ARECA_1883:
|
||||
case PCI_DEVICE_ID_ARECA_1884:
|
||||
type = "SAS/SATA";
|
||||
break;
|
||||
case PCI_DEVICE_ID_ARECA_1886_0:
|
||||
case PCI_DEVICE_ID_ARECA_1886:
|
||||
type = "NVMe/SAS/SATA";
|
||||
break;
|
||||
|
@ -865,7 +865,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit atari_scsi_remove(struct platform_device *pdev)
|
||||
static void __exit atari_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
|
||||
@ -876,11 +876,10 @@ static int __exit atari_scsi_remove(struct platform_device *pdev)
|
||||
scsi_host_put(instance);
|
||||
if (atari_dma_buffer)
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver atari_scsi_driver = {
|
||||
.remove = __exit_p(atari_scsi_remove),
|
||||
.remove_new = __exit_p(atari_scsi_remove),
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
},
|
||||
|
@ -2550,7 +2550,7 @@ bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd)
|
||||
static void bfad_reset_sdev_bflags(struct bfad_im_port_s *im_port,
|
||||
int lunmask_cfg)
|
||||
{
|
||||
const u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN;
|
||||
const blist_flags_t scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN;
|
||||
struct bfad_itnim_s *itnim;
|
||||
struct scsi_device *sdev;
|
||||
unsigned long flags;
|
||||
|
@ -1734,32 +1734,32 @@ static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
|
||||
|
||||
switch (pdev->device) {
|
||||
case PCI_DEVICE_ID_NX2_57710:
|
||||
strncpy(hba->chip_num, "BCM57710", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57710", sizeof(hba->chip_num));
|
||||
break;
|
||||
case PCI_DEVICE_ID_NX2_57711:
|
||||
strncpy(hba->chip_num, "BCM57711", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57711", sizeof(hba->chip_num));
|
||||
break;
|
||||
case PCI_DEVICE_ID_NX2_57712:
|
||||
case PCI_DEVICE_ID_NX2_57712_MF:
|
||||
case PCI_DEVICE_ID_NX2_57712_VF:
|
||||
strncpy(hba->chip_num, "BCM57712", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57712", sizeof(hba->chip_num));
|
||||
break;
|
||||
case PCI_DEVICE_ID_NX2_57800:
|
||||
case PCI_DEVICE_ID_NX2_57800_MF:
|
||||
case PCI_DEVICE_ID_NX2_57800_VF:
|
||||
strncpy(hba->chip_num, "BCM57800", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57800", sizeof(hba->chip_num));
|
||||
break;
|
||||
case PCI_DEVICE_ID_NX2_57810:
|
||||
case PCI_DEVICE_ID_NX2_57810_MF:
|
||||
case PCI_DEVICE_ID_NX2_57810_VF:
|
||||
strncpy(hba->chip_num, "BCM57810", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57810", sizeof(hba->chip_num));
|
||||
break;
|
||||
case PCI_DEVICE_ID_NX2_57840:
|
||||
case PCI_DEVICE_ID_NX2_57840_MF:
|
||||
case PCI_DEVICE_ID_NX2_57840_VF:
|
||||
case PCI_DEVICE_ID_NX2_57840_2_20:
|
||||
case PCI_DEVICE_ID_NX2_57840_4_10:
|
||||
strncpy(hba->chip_num, "BCM57840", BCM_CHIP_LEN);
|
||||
strscpy(hba->chip_num, "BCM57840", sizeof(hba->chip_num));
|
||||
break;
|
||||
default:
|
||||
pr_err(PFX "Unknown device id 0x%x\n", pdev->device);
|
||||
@ -1797,7 +1797,7 @@ static int bnx2fc_ulp_get_stats(void *handle)
|
||||
if (!stats_addr)
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(stats_addr->version, BNX2FC_VERSION,
|
||||
strscpy(stats_addr->version, BNX2FC_VERSION,
|
||||
sizeof(stats_addr->version));
|
||||
stats_addr->txq_size = BNX2FC_SQ_WQES_MAX;
|
||||
stats_addr->rxq_size = BNX2FC_CQ_WQES_MAX;
|
||||
|
@ -89,7 +89,7 @@ bvme6000_probe(struct platform_device *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
bvme6000_device_remove(struct platform_device *dev)
|
||||
{
|
||||
struct Scsi_Host *host = platform_get_drvdata(dev);
|
||||
@ -99,8 +99,6 @@ bvme6000_device_remove(struct platform_device *dev)
|
||||
NCR_700_release(host);
|
||||
kfree(hostdata);
|
||||
free_irq(host->irq, host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver bvme6000_scsi_driver = {
|
||||
@ -108,7 +106,7 @@ static struct platform_driver bvme6000_scsi_driver = {
|
||||
.name = "bvme6000-scsi",
|
||||
},
|
||||
.probe = bvme6000_probe,
|
||||
.remove = bvme6000_device_remove,
|
||||
.remove_new = bvme6000_device_remove,
|
||||
};
|
||||
|
||||
static int __init bvme6000_scsi_init(void)
|
||||
|
@ -659,19 +659,23 @@ static long ch_ioctl(struct file *file,
|
||||
memset(&vparams,0,sizeof(vparams));
|
||||
if (ch->counts[CHET_V1]) {
|
||||
vparams.cvp_n1 = ch->counts[CHET_V1];
|
||||
strncpy(vparams.cvp_label1,vendor_labels[0],16);
|
||||
strscpy(vparams.cvp_label1, vendor_labels[0],
|
||||
sizeof(vparams.cvp_label1));
|
||||
}
|
||||
if (ch->counts[CHET_V2]) {
|
||||
vparams.cvp_n2 = ch->counts[CHET_V2];
|
||||
strncpy(vparams.cvp_label2,vendor_labels[1],16);
|
||||
strscpy(vparams.cvp_label2, vendor_labels[1],
|
||||
sizeof(vparams.cvp_label2));
|
||||
}
|
||||
if (ch->counts[CHET_V3]) {
|
||||
vparams.cvp_n3 = ch->counts[CHET_V3];
|
||||
strncpy(vparams.cvp_label3,vendor_labels[2],16);
|
||||
strscpy(vparams.cvp_label3, vendor_labels[2],
|
||||
sizeof(vparams.cvp_label3));
|
||||
}
|
||||
if (ch->counts[CHET_V4]) {
|
||||
vparams.cvp_n4 = ch->counts[CHET_V4];
|
||||
strncpy(vparams.cvp_label4,vendor_labels[3],16);
|
||||
strscpy(vparams.cvp_label4, vendor_labels[3],
|
||||
sizeof(vparams.cvp_label4));
|
||||
}
|
||||
if (copy_to_user(argp, &vparams, sizeof(vparams)))
|
||||
return -EFAULT;
|
||||
|
@ -521,7 +521,8 @@ static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev)
|
||||
goto err;
|
||||
|
||||
hw->pdev = pdev;
|
||||
strncpy(hw->drv_version, CSIO_DRV_VERSION, 32);
|
||||
strscpy(hw->drv_version, CSIO_DRV_VERSION,
|
||||
sizeof(hw->drv_version));
|
||||
|
||||
/* memory pool/DMA pool allocation */
|
||||
if (csio_resource_alloc(hw))
|
||||
|
@ -1366,7 +1366,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
|
||||
"command while another command (0x%p) is active.",
|
||||
srb->cmd,
|
||||
acb->active_dcb->active_srb ?
|
||||
acb->active_dcb->active_srb->cmd : 0);
|
||||
acb->active_dcb->active_srb->cmd : NULL);
|
||||
return 1;
|
||||
}
|
||||
if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
|
||||
|
@ -26,13 +26,13 @@ efc_node_evt_set(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
|
||||
struct efc_node *node = ctx->app;
|
||||
|
||||
if (evt == EFC_EVT_ENTER) {
|
||||
strncpy(node->current_state_name, handler,
|
||||
sizeof(node->current_state_name));
|
||||
strscpy_pad(node->current_state_name, handler,
|
||||
sizeof(node->current_state_name));
|
||||
} else if (evt == EFC_EVT_EXIT) {
|
||||
strncpy(node->prev_state_name, node->current_state_name,
|
||||
sizeof(node->prev_state_name));
|
||||
strncpy(node->current_state_name, "invalid",
|
||||
sizeof(node->current_state_name));
|
||||
memcpy(node->prev_state_name, node->current_state_name,
|
||||
sizeof(node->prev_state_name));
|
||||
strscpy_pad(node->current_state_name, "invalid",
|
||||
sizeof(node->current_state_name));
|
||||
}
|
||||
node->prev_evt = node->current_evt;
|
||||
node->current_evt = evt;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <scsi/fcoe_sysfs.h>
|
||||
#include <scsi/libfcoe.h>
|
||||
@ -214,25 +215,13 @@ static const char *get_fcoe_##title##_name(enum table_type table_key) \
|
||||
return table[table_key]; \
|
||||
}
|
||||
|
||||
static char *fip_conn_type_names[] = {
|
||||
static const char * const fip_conn_type_names[] = {
|
||||
[ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
|
||||
[ FIP_CONN_TYPE_FABRIC ] = "Fabric",
|
||||
[ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
|
||||
};
|
||||
fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
|
||||
|
||||
static enum fip_conn_type fcoe_parse_mode(const char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
|
||||
if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return FIP_CONN_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static char *fcf_state_names[] = {
|
||||
[ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
|
||||
[ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
|
||||
@ -274,17 +263,10 @@ static ssize_t store_ctlr_mode(struct device *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
char mode[FCOE_MAX_MODENAME_LEN + 1];
|
||||
|
||||
if (count > FCOE_MAX_MODENAME_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(mode, buf, count);
|
||||
|
||||
if (mode[count - 1] == '\n')
|
||||
mode[count - 1] = '\0';
|
||||
else
|
||||
mode[count] = '\0';
|
||||
|
||||
switch (ctlr->enabled) {
|
||||
case FCOE_CTLR_ENABLED:
|
||||
@ -297,8 +279,8 @@ static ssize_t store_ctlr_mode(struct device *dev,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
ctlr->mode = fcoe_parse_mode(mode);
|
||||
if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
|
||||
ctlr->mode = sysfs_match_string(fip_conn_type_names, buf);
|
||||
if (ctlr->mode < 0 || ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
|
||||
LIBFCOE_SYSFS_DBG(ctlr, "Unknown mode %s provided.\n",
|
||||
buf);
|
||||
return -EINVAL;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#define DRV_NAME "fnic"
|
||||
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
||||
#define DRV_VERSION "1.6.0.57"
|
||||
#define DRV_VERSION "1.7.0.0"
|
||||
#define PFX DRV_NAME ": "
|
||||
#define DFX DRV_NAME "%d: "
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
#define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
|
||||
#define FNIC_MAX_IO_REQ 1024 /* scsi_cmnd tag map entries */
|
||||
#define FNIC_DFLT_IO_REQ 256 /* Default scsi_cmnd tag map entries */
|
||||
#define FNIC_IO_LOCKS 64 /* IO locks: power of 2 */
|
||||
#define FNIC_DFLT_QUEUE_DEPTH 256
|
||||
#define FNIC_STATS_RATE_LIMIT 4 /* limit rate at which stats are pulled up */
|
||||
|
||||
@ -109,7 +108,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
|
||||
#define FNIC_ABT_TERM_DELAY_TIMEOUT 500 /* mSec */
|
||||
|
||||
#define FNIC_MAX_FCP_TARGET 256
|
||||
|
||||
#define FNIC_PCI_OFFSET 2
|
||||
/**
|
||||
* state_flags to identify host state along along with fnic's state
|
||||
**/
|
||||
@ -144,31 +143,48 @@ do { \
|
||||
} while (0); \
|
||||
} while (0)
|
||||
|
||||
#define FNIC_MAIN_DBG(kern_level, host, fmt, args...) \
|
||||
#define FNIC_MAIN_DBG(kern_level, host, fnic_num, fmt, args...) \
|
||||
FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
|
||||
shost_printk(kern_level, host, fmt, ##args);)
|
||||
shost_printk(kern_level, host, \
|
||||
"fnic<%d>: %s: %d: " fmt, fnic_num,\
|
||||
__func__, __LINE__, ##args);)
|
||||
|
||||
#define FNIC_FCS_DBG(kern_level, host, fmt, args...) \
|
||||
#define FNIC_FCS_DBG(kern_level, host, fnic_num, fmt, args...) \
|
||||
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
|
||||
shost_printk(kern_level, host, fmt, ##args);)
|
||||
shost_printk(kern_level, host, \
|
||||
"fnic<%d>: %s: %d: " fmt, fnic_num,\
|
||||
__func__, __LINE__, ##args);)
|
||||
|
||||
#define FNIC_SCSI_DBG(kern_level, host, fmt, args...) \
|
||||
#define FNIC_SCSI_DBG(kern_level, host, fnic_num, fmt, args...) \
|
||||
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
|
||||
shost_printk(kern_level, host, fmt, ##args);)
|
||||
shost_printk(kern_level, host, \
|
||||
"fnic<%d>: %s: %d: " fmt, fnic_num,\
|
||||
__func__, __LINE__, ##args);)
|
||||
|
||||
#define FNIC_ISR_DBG(kern_level, host, fmt, args...) \
|
||||
#define FNIC_ISR_DBG(kern_level, host, fnic_num, fmt, args...) \
|
||||
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
|
||||
shost_printk(kern_level, host, fmt, ##args);)
|
||||
shost_printk(kern_level, host, \
|
||||
"fnic<%d>: %s: %d: " fmt, fnic_num,\
|
||||
__func__, __LINE__, ##args);)
|
||||
|
||||
#define FNIC_MAIN_NOTE(kern_level, host, fmt, args...) \
|
||||
shost_printk(kern_level, host, fmt, ##args)
|
||||
|
||||
#define FNIC_WQ_COPY_MAX 64
|
||||
#define FNIC_WQ_MAX 1
|
||||
#define FNIC_RQ_MAX 1
|
||||
#define FNIC_CQ_MAX (FNIC_WQ_COPY_MAX + FNIC_WQ_MAX + FNIC_RQ_MAX)
|
||||
#define FNIC_DFLT_IO_COMPLETIONS 256
|
||||
|
||||
#define FNIC_MQ_CQ_INDEX 2
|
||||
|
||||
extern const char *fnic_state_str[];
|
||||
|
||||
enum fnic_intx_intr_index {
|
||||
FNIC_INTX_WQ_RQ_COPYWQ,
|
||||
FNIC_INTX_ERR,
|
||||
FNIC_INTX_DUMMY,
|
||||
FNIC_INTX_NOTIFY,
|
||||
FNIC_INTX_ERR,
|
||||
FNIC_INTX_INTR_MAX,
|
||||
};
|
||||
|
||||
@ -176,7 +192,7 @@ enum fnic_msix_intr_index {
|
||||
FNIC_MSIX_RQ,
|
||||
FNIC_MSIX_WQ,
|
||||
FNIC_MSIX_WQ_COPY,
|
||||
FNIC_MSIX_ERR_NOTIFY,
|
||||
FNIC_MSIX_ERR_NOTIFY = FNIC_MSIX_WQ_COPY + FNIC_WQ_COPY_MAX,
|
||||
FNIC_MSIX_INTR_MAX,
|
||||
};
|
||||
|
||||
@ -185,6 +201,7 @@ struct fnic_msix_entry {
|
||||
char devname[IFNAMSIZ + 11];
|
||||
irqreturn_t (*isr)(int, void *);
|
||||
void *devid;
|
||||
int irq_num;
|
||||
};
|
||||
|
||||
enum fnic_state {
|
||||
@ -194,12 +211,6 @@ enum fnic_state {
|
||||
FNIC_IN_ETH_TRANS_FC_MODE,
|
||||
};
|
||||
|
||||
#define FNIC_WQ_COPY_MAX 1
|
||||
#define FNIC_WQ_MAX 1
|
||||
#define FNIC_RQ_MAX 1
|
||||
#define FNIC_CQ_MAX (FNIC_WQ_COPY_MAX + FNIC_WQ_MAX + FNIC_RQ_MAX)
|
||||
#define FNIC_DFLT_IO_COMPLETIONS 256
|
||||
|
||||
struct mempool;
|
||||
|
||||
enum fnic_evt {
|
||||
@ -214,8 +225,16 @@ struct fnic_event {
|
||||
enum fnic_evt event;
|
||||
};
|
||||
|
||||
struct fnic_cpy_wq {
|
||||
unsigned long hw_lock_flags;
|
||||
u16 active_ioreq_count;
|
||||
u16 ioreq_table_size;
|
||||
____cacheline_aligned struct fnic_io_req **io_req_table;
|
||||
};
|
||||
|
||||
/* Per-instance private data structure */
|
||||
struct fnic {
|
||||
int fnic_num;
|
||||
struct fc_lport *lport;
|
||||
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
|
||||
struct vnic_dev_bar bar0;
|
||||
@ -282,8 +301,8 @@ struct fnic {
|
||||
struct fnic_host_tag *tags;
|
||||
mempool_t *io_req_pool;
|
||||
mempool_t *io_sgl_pool[FNIC_SGL_NUM_CACHES];
|
||||
spinlock_t io_req_lock[FNIC_IO_LOCKS]; /* locks for scsi cmnds */
|
||||
|
||||
unsigned int copy_wq_base;
|
||||
struct work_struct link_work;
|
||||
struct work_struct frame_work;
|
||||
struct sk_buff_head frame_queue;
|
||||
@ -302,7 +321,9 @@ struct fnic {
|
||||
/*** FIP related data members -- end ***/
|
||||
|
||||
/* copy work queue cache line section */
|
||||
____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX];
|
||||
____cacheline_aligned struct vnic_wq_copy hw_copy_wq[FNIC_WQ_COPY_MAX];
|
||||
____cacheline_aligned struct fnic_cpy_wq sw_copy_wq[FNIC_WQ_COPY_MAX];
|
||||
|
||||
/* completion queue cache line section */
|
||||
____cacheline_aligned struct vnic_cq cq[FNIC_CQ_MAX];
|
||||
|
||||
@ -330,6 +351,7 @@ extern const struct attribute_group *fnic_host_groups[];
|
||||
|
||||
void fnic_clear_intr_mode(struct fnic *fnic);
|
||||
int fnic_set_intr_mode(struct fnic *fnic);
|
||||
int fnic_set_intr_mode_msix(struct fnic *fnic);
|
||||
void fnic_free_intr(struct fnic *fnic);
|
||||
int fnic_request_intr(struct fnic *fnic);
|
||||
|
||||
@ -356,7 +378,7 @@ void fnic_scsi_cleanup(struct fc_lport *);
|
||||
void fnic_scsi_abort_io(struct fc_lport *);
|
||||
void fnic_empty_scsi_cleanup(struct fc_lport *);
|
||||
void fnic_exch_mgr_reset(struct fc_lport *, u32, u32);
|
||||
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int);
|
||||
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index);
|
||||
int fnic_wq_cmpl_handler(struct fnic *fnic, int);
|
||||
int fnic_flogi_reg_handler(struct fnic *fnic, u32);
|
||||
void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
|
||||
@ -364,7 +386,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
|
||||
int fnic_fw_reset_handler(struct fnic *fnic);
|
||||
void fnic_terminate_rport_io(struct fc_rport *);
|
||||
const char *fnic_state_to_str(unsigned int state);
|
||||
|
||||
void fnic_mq_map_queues_cpus(struct Scsi_Host *host);
|
||||
void fnic_log_q_error(struct fnic *fnic);
|
||||
void fnic_handle_link_event(struct fnic *fnic);
|
||||
|
||||
|
@ -52,9 +52,10 @@ int fnic_debugfs_init(void)
|
||||
fc_trc_flag->fnic_trace = 2;
|
||||
fc_trc_flag->fc_trace = 3;
|
||||
fc_trc_flag->fc_clear = 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -63,8 +63,8 @@ void fnic_handle_link(struct work_struct *work)
|
||||
atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed,
|
||||
new_port_speed);
|
||||
if (old_port_speed != new_port_speed)
|
||||
FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host,
|
||||
"Current vnic speed set to : %llu\n",
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Current vnic speed set to: %llu\n",
|
||||
new_port_speed);
|
||||
|
||||
switch (vnic_dev_port_speed(fnic->vdev)) {
|
||||
@ -102,6 +102,8 @@ void fnic_handle_link(struct work_struct *work)
|
||||
fnic_fc_trace_set_data(fnic->lport->host->host_no,
|
||||
FNIC_FC_LE, "Link Status: DOWN->DOWN",
|
||||
strlen("Link Status: DOWN->DOWN"));
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"down->down\n");
|
||||
} else {
|
||||
if (old_link_down_cnt != fnic->link_down_cnt) {
|
||||
/* UP -> DOWN -> UP */
|
||||
@ -113,7 +115,7 @@ void fnic_handle_link(struct work_struct *work)
|
||||
"Link Status:UP_DOWN_UP",
|
||||
strlen("Link_Status:UP_DOWN_UP")
|
||||
);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"link down\n");
|
||||
fcoe_ctlr_link_down(&fnic->ctlr);
|
||||
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
|
||||
@ -128,8 +130,8 @@ void fnic_handle_link(struct work_struct *work)
|
||||
fnic_fcoe_send_vlan_req(fnic);
|
||||
return;
|
||||
}
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"link up\n");
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"up->down->up: Link up\n");
|
||||
fcoe_ctlr_link_up(&fnic->ctlr);
|
||||
} else {
|
||||
/* UP -> UP */
|
||||
@ -138,6 +140,8 @@ void fnic_handle_link(struct work_struct *work)
|
||||
fnic->lport->host->host_no, FNIC_FC_LE,
|
||||
"Link Status: UP_UP",
|
||||
strlen("Link Status: UP_UP"));
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"up->up\n");
|
||||
}
|
||||
}
|
||||
} else if (fnic->link_status) {
|
||||
@ -153,7 +157,8 @@ void fnic_handle_link(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n");
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"down->up: Link up\n");
|
||||
fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_LE,
|
||||
"Link Status: DOWN_UP", strlen("Link Status: DOWN_UP"));
|
||||
fcoe_ctlr_link_up(&fnic->ctlr);
|
||||
@ -161,13 +166,14 @@ void fnic_handle_link(struct work_struct *work)
|
||||
/* UP -> DOWN */
|
||||
fnic->lport->host_stats.link_failure_count++;
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link down\n");
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"up->down: Link down\n");
|
||||
fnic_fc_trace_set_data(
|
||||
fnic->lport->host->host_no, FNIC_FC_LE,
|
||||
"Link Status: UP_DOWN",
|
||||
strlen("Link Status: UP_DOWN"));
|
||||
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"deleting fip-timer during link-down\n");
|
||||
del_timer_sync(&fnic->fip_timer);
|
||||
}
|
||||
@ -270,12 +276,12 @@ void fnic_handle_event(struct work_struct *work)
|
||||
spin_lock_irqsave(&fnic->fnic_lock, flags);
|
||||
break;
|
||||
case FNIC_EVT_START_FCF_DISC:
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Start FCF Discovery\n");
|
||||
fnic_fcoe_start_fcf_disc(fnic);
|
||||
break;
|
||||
default:
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Unknown event 0x%x\n", fevt->event);
|
||||
break;
|
||||
}
|
||||
@ -370,7 +376,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
||||
fnic->set_vlan(fnic, 0);
|
||||
|
||||
if (printk_ratelimit())
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Sending VLAN request...\n");
|
||||
|
||||
skb = dev_alloc_skb(sizeof(struct fip_vlan));
|
||||
@ -423,12 +429,12 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
|
||||
u64 sol_time;
|
||||
unsigned long flags;
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Received VLAN response...\n");
|
||||
|
||||
fiph = (struct fip_header *) skb->data;
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
|
||||
ntohs(fiph->fip_op), fiph->fip_subcode);
|
||||
|
||||
@ -463,7 +469,7 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
|
||||
if (list_empty(&fnic->vlans)) {
|
||||
/* retry from timer */
|
||||
atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"No VLAN descriptors in FIP VLAN response\n");
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
goto out;
|
||||
@ -721,7 +727,8 @@ void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
|
||||
new = ctl;
|
||||
if (ether_addr_equal(data, new))
|
||||
return;
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "update_mac %pM\n", new);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"update_mac %pM\n", new);
|
||||
if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
|
||||
vnic_dev_del_addr(fnic->vdev, data);
|
||||
memcpy(data, new, ETH_ALEN);
|
||||
@ -763,8 +770,9 @@ void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
|
||||
u8 *mac;
|
||||
int ret;
|
||||
|
||||
FNIC_FCS_DBG(KERN_DEBUG, lport->host, "set port_id %x fp %p\n",
|
||||
port_id, fp);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, lport->host, fnic->fnic_num,
|
||||
"set port_id 0x%x fp 0x%p\n",
|
||||
port_id, fp);
|
||||
|
||||
/*
|
||||
* If we're clearing the FC_ID, change to use the ctl_src_addr.
|
||||
@ -790,10 +798,9 @@ void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
|
||||
if (fnic->state == FNIC_IN_ETH_MODE || fnic->state == FNIC_IN_FC_MODE)
|
||||
fnic->state = FNIC_IN_ETH_TRANS_FC_MODE;
|
||||
else {
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Unexpected fnic state %s while"
|
||||
" processing flogi resp\n",
|
||||
fnic_state_to_str(fnic->state));
|
||||
FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"Unexpected fnic state: %s processing FLOGI response",
|
||||
fnic_state_to_str(fnic->state));
|
||||
spin_unlock_irq(&fnic->fnic_lock);
|
||||
return;
|
||||
}
|
||||
@ -870,7 +877,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
|
||||
skb_trim(skb, bytes_written);
|
||||
if (!fcs_ok) {
|
||||
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fcs error. dropping packet.\n");
|
||||
goto drop;
|
||||
}
|
||||
@ -886,7 +893,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
|
||||
|
||||
if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) {
|
||||
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fnic rq_cmpl fcoe x%x fcsok x%x"
|
||||
" pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err"
|
||||
" x%x\n",
|
||||
@ -967,7 +974,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
|
||||
len = FC_FRAME_HEADROOM + FC_MAX_FRAME + FC_FRAME_TAILROOM;
|
||||
skb = dev_alloc_skb(len);
|
||||
if (!skb) {
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Unable to allocate RQ sk_buff\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -1341,12 +1348,12 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
||||
}
|
||||
|
||||
vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fip_timer: vlan %d state %d sol_count %d\n",
|
||||
vlan->vid, vlan->state, vlan->sol_count);
|
||||
switch (vlan->state) {
|
||||
case FIP_VLAN_USED:
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"FIP VLAN is selected for FC transaction\n");
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
break;
|
||||
@ -1365,7 +1372,7 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
||||
* no response on this vlan, remove from the list.
|
||||
* Try the next vlan
|
||||
*/
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Dequeue this VLAN ID %d from list\n",
|
||||
vlan->vid);
|
||||
list_del(&vlan->list);
|
||||
@ -1375,7 +1382,7 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
||||
/* we exhausted all vlans, restart vlan disc */
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock,
|
||||
flags);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"fip_timer: vlan list empty, "
|
||||
"trigger vlan disc\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
|
@ -38,8 +38,13 @@ static irqreturn_t fnic_isr_legacy(int irq, void *data)
|
||||
fnic_log_q_error(fnic);
|
||||
}
|
||||
|
||||
if (pba & (1 << FNIC_INTX_DUMMY)) {
|
||||
atomic64_inc(&fnic->fnic_stats.misc_stats.intx_dummy);
|
||||
vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_DUMMY]);
|
||||
}
|
||||
|
||||
if (pba & (1 << FNIC_INTX_WQ_RQ_COPYWQ)) {
|
||||
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
|
||||
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
|
||||
work_done += fnic_wq_cmpl_handler(fnic, -1);
|
||||
work_done += fnic_rq_cmpl_handler(fnic, -1);
|
||||
|
||||
@ -60,7 +65,7 @@ static irqreturn_t fnic_isr_msi(int irq, void *data)
|
||||
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
|
||||
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
|
||||
|
||||
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
|
||||
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
|
||||
work_done += fnic_wq_cmpl_handler(fnic, -1);
|
||||
work_done += fnic_rq_cmpl_handler(fnic, -1);
|
||||
|
||||
@ -109,12 +114,22 @@ static irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data)
|
||||
{
|
||||
struct fnic *fnic = data;
|
||||
unsigned long wq_copy_work_done = 0;
|
||||
int i;
|
||||
|
||||
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
|
||||
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
|
||||
|
||||
wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions);
|
||||
vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY],
|
||||
i = irq - fnic->msix[0].irq_num;
|
||||
if (i >= fnic->wq_copy_count + fnic->copy_wq_base ||
|
||||
i < 0 || fnic->msix[i].irq_num != irq) {
|
||||
for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base ; i++) {
|
||||
if (fnic->msix[i].irq_num == irq)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions, i);
|
||||
vnic_intr_return_credits(&fnic->intr[i],
|
||||
wq_copy_work_done,
|
||||
1 /* unmask intr */,
|
||||
1 /* reset intr timer */);
|
||||
@ -128,7 +143,7 @@ static irqreturn_t fnic_isr_msix_err_notify(int irq, void *data)
|
||||
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
|
||||
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
|
||||
|
||||
vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]);
|
||||
vnic_intr_return_all_credits(&fnic->intr[fnic->err_intr_offset]);
|
||||
fnic_log_q_error(fnic);
|
||||
fnic_handle_link_event(fnic);
|
||||
|
||||
@ -186,26 +201,30 @@ int fnic_request_intr(struct fnic *fnic)
|
||||
fnic->msix[FNIC_MSIX_WQ].isr = fnic_isr_msix_wq;
|
||||
fnic->msix[FNIC_MSIX_WQ].devid = fnic;
|
||||
|
||||
sprintf(fnic->msix[FNIC_MSIX_WQ_COPY].devname,
|
||||
"%.11s-scsi-wq", fnic->name);
|
||||
fnic->msix[FNIC_MSIX_WQ_COPY].isr = fnic_isr_msix_wq_copy;
|
||||
fnic->msix[FNIC_MSIX_WQ_COPY].devid = fnic;
|
||||
for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base; i++) {
|
||||
sprintf(fnic->msix[i].devname,
|
||||
"%.11s-scsi-wq-%d", fnic->name, i-FNIC_MSIX_WQ_COPY);
|
||||
fnic->msix[i].isr = fnic_isr_msix_wq_copy;
|
||||
fnic->msix[i].devid = fnic;
|
||||
}
|
||||
|
||||
sprintf(fnic->msix[FNIC_MSIX_ERR_NOTIFY].devname,
|
||||
sprintf(fnic->msix[fnic->err_intr_offset].devname,
|
||||
"%.11s-err-notify", fnic->name);
|
||||
fnic->msix[FNIC_MSIX_ERR_NOTIFY].isr =
|
||||
fnic->msix[fnic->err_intr_offset].isr =
|
||||
fnic_isr_msix_err_notify;
|
||||
fnic->msix[FNIC_MSIX_ERR_NOTIFY].devid = fnic;
|
||||
fnic->msix[fnic->err_intr_offset].devid = fnic;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fnic->msix); i++) {
|
||||
err = request_irq(pci_irq_vector(fnic->pdev, i),
|
||||
fnic->msix[i].isr, 0,
|
||||
fnic->msix[i].devname,
|
||||
fnic->msix[i].devid);
|
||||
for (i = 0; i < fnic->intr_count; i++) {
|
||||
fnic->msix[i].irq_num = pci_irq_vector(fnic->pdev, i);
|
||||
|
||||
err = request_irq(fnic->msix[i].irq_num,
|
||||
fnic->msix[i].isr, 0,
|
||||
fnic->msix[i].devname,
|
||||
fnic->msix[i].devid);
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"MSIX: request_irq"
|
||||
" failed %d\n", err);
|
||||
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"request_irq failed with error: %d\n",
|
||||
err);
|
||||
fnic_free_intr(fnic);
|
||||
break;
|
||||
}
|
||||
@ -220,44 +239,99 @@ int fnic_request_intr(struct fnic *fnic)
|
||||
return err;
|
||||
}
|
||||
|
||||
int fnic_set_intr_mode(struct fnic *fnic)
|
||||
int fnic_set_intr_mode_msix(struct fnic *fnic)
|
||||
{
|
||||
unsigned int n = ARRAY_SIZE(fnic->rq);
|
||||
unsigned int m = ARRAY_SIZE(fnic->wq);
|
||||
unsigned int o = ARRAY_SIZE(fnic->wq_copy);
|
||||
unsigned int o = ARRAY_SIZE(fnic->hw_copy_wq);
|
||||
unsigned int min_irqs = n + m + 1 + 1; /*rq, raw wq, wq, err*/
|
||||
|
||||
/*
|
||||
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
|
||||
* (last INTR is used for WQ/RQ errors and notification area)
|
||||
*/
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"rq-array size: %d wq-array size: %d copy-wq array size: %d\n",
|
||||
n, m, o);
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"rq_count: %d raw_wq_count: %d wq_copy_count: %d cq_count: %d\n",
|
||||
fnic->rq_count, fnic->raw_wq_count,
|
||||
fnic->wq_copy_count, fnic->cq_count);
|
||||
|
||||
if (fnic->rq_count <= n && fnic->raw_wq_count <= m &&
|
||||
fnic->wq_copy_count <= o) {
|
||||
int vec_count = 0;
|
||||
int vecs = fnic->rq_count + fnic->raw_wq_count + fnic->wq_copy_count + 1;
|
||||
|
||||
vec_count = pci_alloc_irq_vectors(fnic->pdev, min_irqs, vecs,
|
||||
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"allocated %d MSI-X vectors\n",
|
||||
vec_count);
|
||||
|
||||
if (vec_count > 0) {
|
||||
if (vec_count < vecs) {
|
||||
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"interrupts number mismatch: vec_count: %d vecs: %d\n",
|
||||
vec_count, vecs);
|
||||
if (vec_count < min_irqs) {
|
||||
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"no interrupts for copy wq\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fnic->rq_count = n;
|
||||
fnic->raw_wq_count = m;
|
||||
fnic->copy_wq_base = fnic->rq_count + fnic->raw_wq_count;
|
||||
fnic->wq_copy_count = vec_count - n - m - 1;
|
||||
fnic->wq_count = fnic->raw_wq_count + fnic->wq_copy_count;
|
||||
if (fnic->cq_count != vec_count - 1) {
|
||||
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"CQ count: %d does not match MSI-X vector count: %d\n",
|
||||
fnic->cq_count, vec_count);
|
||||
fnic->cq_count = vec_count - 1;
|
||||
}
|
||||
fnic->intr_count = vec_count;
|
||||
fnic->err_intr_offset = fnic->rq_count + fnic->wq_count;
|
||||
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"rq_count: %d raw_wq_count: %d copy_wq_base: %d\n",
|
||||
fnic->rq_count,
|
||||
fnic->raw_wq_count, fnic->copy_wq_base);
|
||||
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"wq_copy_count: %d wq_count: %d cq_count: %d\n",
|
||||
fnic->wq_copy_count,
|
||||
fnic->wq_count, fnic->cq_count);
|
||||
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"intr_count: %d err_intr_offset: %u",
|
||||
fnic->intr_count,
|
||||
fnic->err_intr_offset);
|
||||
|
||||
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSIX);
|
||||
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"fnic using MSI-X\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fnic_set_intr_mode(struct fnic *fnic)
|
||||
{
|
||||
int ret_status = 0;
|
||||
|
||||
/*
|
||||
* Set interrupt mode (INTx, MSI, MSI-X) depending
|
||||
* system capabilities.
|
||||
*
|
||||
* Try MSI-X first
|
||||
*
|
||||
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
|
||||
* (last INTR is used for WQ/RQ errors and notification area)
|
||||
*/
|
||||
if (fnic->rq_count >= n &&
|
||||
fnic->raw_wq_count >= m &&
|
||||
fnic->wq_copy_count >= o &&
|
||||
fnic->cq_count >= n + m + o) {
|
||||
int vecs = n + m + o + 1;
|
||||
|
||||
if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs,
|
||||
PCI_IRQ_MSIX) == vecs) {
|
||||
fnic->rq_count = n;
|
||||
fnic->raw_wq_count = m;
|
||||
fnic->wq_copy_count = o;
|
||||
fnic->wq_count = m + o;
|
||||
fnic->cq_count = n + m + o;
|
||||
fnic->intr_count = vecs;
|
||||
fnic->err_intr_offset = FNIC_MSIX_ERR_NOTIFY;
|
||||
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Using MSI-X Interrupts\n");
|
||||
vnic_dev_set_intr_mode(fnic->vdev,
|
||||
VNIC_DEV_INTR_MODE_MSIX);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret_status = fnic_set_intr_mode_msix(fnic);
|
||||
if (ret_status == 0)
|
||||
return ret_status;
|
||||
|
||||
/*
|
||||
* Next try MSI
|
||||
@ -277,7 +351,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
||||
fnic->intr_count = 1;
|
||||
fnic->err_intr_offset = 0;
|
||||
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Using MSI Interrupts\n");
|
||||
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSI);
|
||||
|
||||
@ -303,7 +377,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
||||
fnic->cq_count = 3;
|
||||
fnic->intr_count = 3;
|
||||
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Using Legacy Interrupts\n");
|
||||
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
|
||||
|
||||
|
@ -12,9 +12,11 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/blk-mq-pci.h>
|
||||
#include <scsi/fc/fc_fip.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
@ -39,6 +41,7 @@ static struct kmem_cache *fnic_sgl_cache[FNIC_SGL_NUM_CACHES];
|
||||
static struct kmem_cache *fnic_io_req_cache;
|
||||
static LIST_HEAD(fnic_list);
|
||||
static DEFINE_SPINLOCK(fnic_list_lock);
|
||||
static DEFINE_IDA(fnic_ida);
|
||||
|
||||
/* Supported devices by fnic module */
|
||||
static struct pci_device_id fnic_id_table[] = {
|
||||
@ -113,6 +116,7 @@ static const struct scsi_host_template fnic_host_template = {
|
||||
.shost_groups = fnic_host_groups,
|
||||
.track_queue_depth = 1,
|
||||
.cmd_size = sizeof(struct fnic_cmd_priv),
|
||||
.map_queues = fnic_mq_map_queues_cpus,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -209,7 +213,7 @@ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
|
||||
if (ret) {
|
||||
FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fnic: Get vnic stats failed"
|
||||
" 0x%x", ret);
|
||||
return stats;
|
||||
@ -321,7 +325,7 @@ static void fnic_reset_host_stats(struct Scsi_Host *host)
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
|
||||
if (ret) {
|
||||
FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fnic: Reset vnic stats failed"
|
||||
" 0x%x", ret);
|
||||
return;
|
||||
@ -354,7 +358,7 @@ void fnic_log_q_error(struct fnic *fnic)
|
||||
}
|
||||
|
||||
for (i = 0; i < fnic->wq_copy_count; i++) {
|
||||
error_status = ioread32(&fnic->wq_copy[i].ctrl->error_status);
|
||||
error_status = ioread32(&fnic->hw_copy_wq[i].ctrl->error_status);
|
||||
if (error_status)
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"CWQ[%d] error_status"
|
||||
@ -389,7 +393,7 @@ static int fnic_notify_set(struct fnic *fnic)
|
||||
err = vnic_dev_notify_set(fnic->vdev, -1);
|
||||
break;
|
||||
case VNIC_DEV_INTR_MODE_MSIX:
|
||||
err = vnic_dev_notify_set(fnic->vdev, FNIC_MSIX_ERR_NOTIFY);
|
||||
err = vnic_dev_notify_set(fnic->vdev, fnic->wq_copy_count + fnic->copy_wq_base);
|
||||
break;
|
||||
default:
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
@ -475,6 +479,7 @@ static int fnic_cleanup(struct fnic *fnic)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
int raw_wq_rq_counts;
|
||||
|
||||
vnic_dev_disable(fnic->vdev);
|
||||
for (i = 0; i < fnic->intr_count; i++)
|
||||
@ -491,13 +496,14 @@ static int fnic_cleanup(struct fnic *fnic)
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < fnic->wq_copy_count; i++) {
|
||||
err = vnic_wq_copy_disable(&fnic->wq_copy[i]);
|
||||
err = vnic_wq_copy_disable(&fnic->hw_copy_wq[i]);
|
||||
if (err)
|
||||
return err;
|
||||
raw_wq_rq_counts = fnic->raw_wq_count + fnic->rq_count;
|
||||
fnic_wq_copy_cmpl_handler(fnic, -1, i + raw_wq_rq_counts);
|
||||
}
|
||||
|
||||
/* Clean up completed IOs and FCS frames */
|
||||
fnic_wq_copy_cmpl_handler(fnic, io_completions);
|
||||
fnic_wq_cmpl_handler(fnic, -1);
|
||||
fnic_rq_cmpl_handler(fnic, -1);
|
||||
|
||||
@ -507,7 +513,7 @@ static int fnic_cleanup(struct fnic *fnic)
|
||||
for (i = 0; i < fnic->rq_count; i++)
|
||||
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
|
||||
for (i = 0; i < fnic->wq_copy_count; i++)
|
||||
vnic_wq_copy_clean(&fnic->wq_copy[i],
|
||||
vnic_wq_copy_clean(&fnic->hw_copy_wq[i],
|
||||
fnic_wq_copy_cleanup_handler);
|
||||
|
||||
for (i = 0; i < fnic->cq_count; i++)
|
||||
@ -560,11 +566,6 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
|
||||
host->max_cmd_len = FCOE_MAX_CMD_LEN;
|
||||
|
||||
host->nr_hw_queues = fnic->wq_copy_count;
|
||||
if (host->nr_hw_queues > 1)
|
||||
shost_printk(KERN_ERR, host,
|
||||
"fnic: blk-mq is not supported");
|
||||
|
||||
host->nr_hw_queues = fnic->wq_copy_count = 1;
|
||||
|
||||
shost_printk(KERN_INFO, host,
|
||||
"fnic: can_queue: %d max_lun: %llu",
|
||||
@ -577,15 +578,43 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fnic_mq_map_queues_cpus(struct Scsi_Host *host)
|
||||
{
|
||||
struct fc_lport *lp = shost_priv(host);
|
||||
struct fnic *fnic = lport_priv(lp);
|
||||
struct pci_dev *l_pdev = fnic->pdev;
|
||||
int intr_mode = fnic->config.intr_mode;
|
||||
struct blk_mq_queue_map *qmap = &host->tag_set.map[HCTX_TYPE_DEFAULT];
|
||||
|
||||
if (intr_mode == VNIC_DEV_INTR_MODE_MSI || intr_mode == VNIC_DEV_INTR_MODE_INTX) {
|
||||
FNIC_MAIN_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"intr_mode is not msix\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"qmap->nr_queues: %d\n", qmap->nr_queues);
|
||||
|
||||
if (l_pdev == NULL) {
|
||||
FNIC_MAIN_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
|
||||
"l_pdev is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
blk_mq_pci_map_queues(qmap, l_pdev, FNIC_PCI_OFFSET);
|
||||
}
|
||||
|
||||
static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct Scsi_Host *host;
|
||||
struct fc_lport *lp;
|
||||
struct fnic *fnic;
|
||||
mempool_t *pool;
|
||||
int err;
|
||||
int err = 0;
|
||||
int fnic_id = 0;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
int hwq;
|
||||
|
||||
/*
|
||||
* Allocate SCSI Host and set up association between host,
|
||||
@ -597,25 +626,28 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
host = lp->host;
|
||||
fnic = lport_priv(lp);
|
||||
|
||||
fnic_id = ida_alloc(&fnic_ida, GFP_KERNEL);
|
||||
if (fnic_id < 0) {
|
||||
pr_err("Unable to alloc fnic ID\n");
|
||||
err = fnic_id;
|
||||
goto err_out_ida_alloc;
|
||||
}
|
||||
fnic->lport = lp;
|
||||
fnic->ctlr.lp = lp;
|
||||
|
||||
fnic->link_events = 0;
|
||||
fnic->pdev = pdev;
|
||||
|
||||
snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME,
|
||||
host->host_no);
|
||||
|
||||
host->transportt = fnic_fc_transport;
|
||||
|
||||
fnic->fnic_num = fnic_id;
|
||||
fnic_stats_debugfs_init(fnic);
|
||||
|
||||
/* Setup PCI resources */
|
||||
pci_set_drvdata(pdev, fnic);
|
||||
|
||||
fnic->pdev = pdev;
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
@ -717,7 +749,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto err_out_dev_close;
|
||||
}
|
||||
|
||||
fnic_scsi_drv_init(fnic);
|
||||
/* Setup PCI resources */
|
||||
pci_set_drvdata(pdev, fnic);
|
||||
|
||||
fnic_get_res_counts(fnic);
|
||||
|
||||
@ -737,6 +770,16 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto err_out_clear_intr;
|
||||
}
|
||||
|
||||
fnic_scsi_drv_init(fnic);
|
||||
|
||||
for (hwq = 0; hwq < fnic->wq_copy_count; hwq++) {
|
||||
fnic->sw_copy_wq[hwq].ioreq_table_size = fnic->fnic_max_tag_id;
|
||||
fnic->sw_copy_wq[hwq].io_req_table =
|
||||
kzalloc((fnic->sw_copy_wq[hwq].ioreq_table_size + 1) *
|
||||
sizeof(struct fnic_io_req *), GFP_KERNEL);
|
||||
}
|
||||
shost_printk(KERN_INFO, fnic->lport->host, "fnic copy wqs: %d, Q0 ioreq table size: %d\n",
|
||||
fnic->wq_copy_count, fnic->sw_copy_wq[0].ioreq_table_size);
|
||||
|
||||
/* initialize all fnic locks */
|
||||
spin_lock_init(&fnic->fnic_lock);
|
||||
@ -751,11 +794,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
fnic->fw_ack_index[i] = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < FNIC_IO_LOCKS; i++)
|
||||
spin_lock_init(&fnic->io_req_lock[i]);
|
||||
|
||||
spin_lock_init(&fnic->sgreset_lock);
|
||||
|
||||
err = -ENOMEM;
|
||||
fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
|
||||
if (!fnic->io_req_pool)
|
||||
@ -823,16 +861,32 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
/* allocate RQ buffers and post them to RQ*/
|
||||
for (i = 0; i < fnic->rq_count; i++) {
|
||||
vnic_rq_enable(&fnic->rq[i]);
|
||||
err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame);
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"fnic_alloc_rq_frame can't alloc "
|
||||
"frame\n");
|
||||
goto err_out_free_rq_buf;
|
||||
goto err_out_rq_buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable all queues */
|
||||
for (i = 0; i < fnic->raw_wq_count; i++)
|
||||
vnic_wq_enable(&fnic->wq[i]);
|
||||
for (i = 0; i < fnic->rq_count; i++) {
|
||||
if (!ioread32(&fnic->rq[i].ctrl->enable))
|
||||
vnic_rq_enable(&fnic->rq[i]);
|
||||
}
|
||||
for (i = 0; i < fnic->wq_copy_count; i++)
|
||||
vnic_wq_copy_enable(&fnic->hw_copy_wq[i]);
|
||||
|
||||
err = fnic_request_intr(fnic);
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"Unable to request irq.\n");
|
||||
goto err_out_request_intr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization done with PCI system, hardware, firmware.
|
||||
* Add host to SCSI
|
||||
@ -841,9 +895,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"fnic: scsi_add_host failed...exiting\n");
|
||||
goto err_out_free_rq_buf;
|
||||
goto err_out_scsi_add_host;
|
||||
}
|
||||
|
||||
|
||||
/* Start local port initiatialization */
|
||||
|
||||
lp->link_up = 0;
|
||||
@ -867,7 +922,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
|
||||
FCPIO_HOST_EXCH_RANGE_END, NULL)) {
|
||||
err = -ENOMEM;
|
||||
goto err_out_remove_scsi_host;
|
||||
goto err_out_fc_exch_mgr_alloc;
|
||||
}
|
||||
|
||||
fc_lport_init_stats(lp);
|
||||
@ -895,21 +950,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
skb_queue_head_init(&fnic->frame_queue);
|
||||
skb_queue_head_init(&fnic->tx_queue);
|
||||
|
||||
/* Enable all queues */
|
||||
for (i = 0; i < fnic->raw_wq_count; i++)
|
||||
vnic_wq_enable(&fnic->wq[i]);
|
||||
for (i = 0; i < fnic->wq_copy_count; i++)
|
||||
vnic_wq_copy_enable(&fnic->wq_copy[i]);
|
||||
|
||||
fc_fabric_login(lp);
|
||||
|
||||
err = fnic_request_intr(fnic);
|
||||
if (err) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"Unable to request irq.\n");
|
||||
goto err_out_free_exch_mgr;
|
||||
}
|
||||
|
||||
vnic_dev_enable(fnic->vdev);
|
||||
|
||||
for (i = 0; i < fnic->intr_count; i++)
|
||||
@ -921,12 +963,15 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
err_out_free_exch_mgr:
|
||||
fc_exch_mgr_free(lp);
|
||||
err_out_remove_scsi_host:
|
||||
err_out_fc_exch_mgr_alloc:
|
||||
fc_remove_host(lp->host);
|
||||
scsi_remove_host(lp->host);
|
||||
err_out_free_rq_buf:
|
||||
err_out_scsi_add_host:
|
||||
fnic_free_intr(fnic);
|
||||
err_out_request_intr:
|
||||
for (i = 0; i < fnic->rq_count; i++)
|
||||
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
|
||||
err_out_rq_buf:
|
||||
vnic_dev_notify_unset(fnic->vdev);
|
||||
err_out_free_max_pool:
|
||||
mempool_destroy(fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX]);
|
||||
@ -935,6 +980,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
err_out_free_ioreq_pool:
|
||||
mempool_destroy(fnic->io_req_pool);
|
||||
err_out_free_resources:
|
||||
for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
|
||||
kfree(fnic->sw_copy_wq[hwq].io_req_table);
|
||||
fnic_free_vnic_resources(fnic);
|
||||
err_out_clear_intr:
|
||||
fnic_clear_intr_mode(fnic);
|
||||
@ -951,6 +998,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
pci_disable_device(pdev);
|
||||
err_out_free_hba:
|
||||
fnic_stats_debugfs_remove(fnic);
|
||||
ida_free(&fnic_ida, fnic->fnic_num);
|
||||
err_out_ida_alloc:
|
||||
scsi_host_put(lp->host);
|
||||
err_out:
|
||||
return err;
|
||||
@ -961,6 +1010,7 @@ static void fnic_remove(struct pci_dev *pdev)
|
||||
struct fnic *fnic = pci_get_drvdata(pdev);
|
||||
struct fc_lport *lp = fnic->lport;
|
||||
unsigned long flags;
|
||||
int hwq;
|
||||
|
||||
/*
|
||||
* Mark state so that the workqueue thread stops forwarding
|
||||
@ -1021,6 +1071,8 @@ static void fnic_remove(struct pci_dev *pdev)
|
||||
|
||||
fc_remove_host(fnic->lport->host);
|
||||
scsi_remove_host(fnic->lport->host);
|
||||
for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
|
||||
kfree(fnic->sw_copy_wq[hwq].io_req_table);
|
||||
fc_exch_mgr_free(fnic->lport);
|
||||
vnic_dev_notify_unset(fnic->vdev);
|
||||
fnic_free_intr(fnic);
|
||||
@ -1031,6 +1083,7 @@ static void fnic_remove(struct pci_dev *pdev)
|
||||
fnic_iounmap(fnic);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
ida_free(&fnic_ida, fnic->fnic_num);
|
||||
scsi_host_put(lp->host);
|
||||
}
|
||||
|
||||
@ -1168,6 +1221,7 @@ static void __exit fnic_cleanup_module(void)
|
||||
fnic_trace_free();
|
||||
fnic_fc_trace_free();
|
||||
fnic_debugfs_terminate();
|
||||
ida_destroy(&fnic_ida);
|
||||
}
|
||||
|
||||
module_init(fnic_init_module);
|
||||
|
@ -57,6 +57,8 @@ int fnic_get_vnic_config(struct fnic *fnic)
|
||||
GET_CONFIG(port_down_timeout);
|
||||
GET_CONFIG(port_down_io_retries);
|
||||
GET_CONFIG(luns_per_tgt);
|
||||
GET_CONFIG(intr_mode);
|
||||
GET_CONFIG(wq_copy_count);
|
||||
|
||||
c->wq_enet_desc_count =
|
||||
min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,
|
||||
@ -131,6 +133,12 @@ int fnic_get_vnic_config(struct fnic *fnic)
|
||||
c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
|
||||
c->intr_timer_type = c->intr_timer_type;
|
||||
|
||||
/* for older firmware, GET_CONFIG will not return anything */
|
||||
if (c->wq_copy_count == 0)
|
||||
c->wq_copy_count = 1;
|
||||
|
||||
c->wq_copy_count = min_t(u16, FNIC_WQ_COPY_MAX, c->wq_copy_count);
|
||||
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC MAC addr %pM "
|
||||
"wq/wq_copy/rq %d/%d/%d\n",
|
||||
@ -161,6 +169,10 @@ int fnic_get_vnic_config(struct fnic *fnic)
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC port dn io retries %d port dn timeout %d\n",
|
||||
c->port_down_io_retries, c->port_down_timeout);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC wq_copy_count: %d\n", c->wq_copy_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC intr mode: %d\n", c->intr_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -187,12 +199,25 @@ int fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu,
|
||||
void fnic_get_res_counts(struct fnic *fnic)
|
||||
{
|
||||
fnic->wq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_WQ);
|
||||
fnic->raw_wq_count = fnic->wq_count - 1;
|
||||
fnic->wq_copy_count = fnic->wq_count - fnic->raw_wq_count;
|
||||
fnic->raw_wq_count = 1;
|
||||
fnic->wq_copy_count = fnic->config.wq_copy_count;
|
||||
fnic->rq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_RQ);
|
||||
fnic->cq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_CQ);
|
||||
fnic->intr_count = vnic_dev_get_res_count(fnic->vdev,
|
||||
RES_TYPE_INTR_CTRL);
|
||||
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources wq_count: %d\n", fnic->wq_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources raw_wq_count: %d\n", fnic->raw_wq_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources wq_copy_count: %d\n", fnic->wq_copy_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources rq_count: %d\n", fnic->rq_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources cq_count: %d\n", fnic->cq_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC fw resources intr_count: %d\n", fnic->intr_count);
|
||||
}
|
||||
|
||||
void fnic_free_vnic_resources(struct fnic *fnic)
|
||||
@ -203,7 +228,7 @@ void fnic_free_vnic_resources(struct fnic *fnic)
|
||||
vnic_wq_free(&fnic->wq[i]);
|
||||
|
||||
for (i = 0; i < fnic->wq_copy_count; i++)
|
||||
vnic_wq_copy_free(&fnic->wq_copy[i]);
|
||||
vnic_wq_copy_free(&fnic->hw_copy_wq[i]);
|
||||
|
||||
for (i = 0; i < fnic->rq_count; i++)
|
||||
vnic_rq_free(&fnic->rq[i]);
|
||||
@ -234,10 +259,15 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
|
||||
intr_mode == VNIC_DEV_INTR_MODE_MSIX ?
|
||||
"MSI-X" : "unknown");
|
||||
|
||||
shost_printk(KERN_INFO, fnic->lport->host, "vNIC resources avail: "
|
||||
"wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
|
||||
fnic->wq_count, fnic->wq_copy_count, fnic->raw_wq_count,
|
||||
fnic->rq_count, fnic->cq_count, fnic->intr_count);
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC resources avail: wq %d cp_wq %d raw_wq %d rq %d",
|
||||
fnic->wq_count, fnic->wq_copy_count,
|
||||
fnic->raw_wq_count, fnic->rq_count);
|
||||
|
||||
shost_printk(KERN_INFO, fnic->lport->host,
|
||||
"vNIC resources avail: cq %d intr %d cpy-wq desc count %d\n",
|
||||
fnic->cq_count, fnic->intr_count,
|
||||
fnic->config.wq_copy_desc_count);
|
||||
|
||||
/* Allocate Raw WQ used for FCS frames */
|
||||
for (i = 0; i < fnic->raw_wq_count; i++) {
|
||||
@ -250,7 +280,7 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
|
||||
|
||||
/* Allocate Copy WQs used for SCSI IOs */
|
||||
for (i = 0; i < fnic->wq_copy_count; i++) {
|
||||
err = vnic_wq_copy_alloc(fnic->vdev, &fnic->wq_copy[i],
|
||||
err = vnic_wq_copy_alloc(fnic->vdev, &fnic->hw_copy_wq[i],
|
||||
(fnic->raw_wq_count + i),
|
||||
fnic->config.wq_copy_desc_count,
|
||||
sizeof(struct fcpio_host_req));
|
||||
@ -357,7 +387,7 @@ int fnic_alloc_vnic_resources(struct fnic *fnic)
|
||||
}
|
||||
|
||||
for (i = 0; i < fnic->wq_copy_count; i++) {
|
||||
vnic_wq_copy_init(&fnic->wq_copy[i],
|
||||
vnic_wq_copy_init(&fnic->hw_copy_wq[i],
|
||||
0 /* cq_index 0 - always */,
|
||||
error_interrupt_enable,
|
||||
error_interrupt_offset);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
/* Copyright 2013 Cisco Systems, Inc. All rights reserved. */
|
||||
#ifndef _FNIC_STATS_H_
|
||||
#define _FNIC_STATS_H_
|
||||
#define FNIC_MQ_MAX_QUEUES 64
|
||||
|
||||
struct stats_timestamps {
|
||||
struct timespec64 last_reset_time;
|
||||
@ -26,6 +27,7 @@ struct io_path_stats {
|
||||
atomic64_t io_btw_10000_to_30000_msec;
|
||||
atomic64_t io_greater_than_30000_msec;
|
||||
atomic64_t current_max_io_time;
|
||||
atomic64_t ios[FNIC_MQ_MAX_QUEUES];
|
||||
};
|
||||
|
||||
struct abort_stats {
|
||||
@ -103,6 +105,7 @@ struct misc_stats {
|
||||
atomic64_t rport_not_ready;
|
||||
atomic64_t frame_errors;
|
||||
atomic64_t current_port_speed;
|
||||
atomic64_t intx_dummy;
|
||||
};
|
||||
|
||||
struct fnic_stats {
|
||||
|
@ -204,6 +204,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
||||
int len = 0;
|
||||
int buf_size = debug->buf_size;
|
||||
struct timespec64 val1, val2;
|
||||
int i = 0;
|
||||
|
||||
ktime_get_real_ts64(&val1);
|
||||
len = scnprintf(debug->debug_buffer + len, buf_size - len,
|
||||
@ -266,6 +267,16 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
|
||||
|
||||
len += scnprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"------------------------------------------\n"
|
||||
"\t\tIO Queues and cumulative IOs\n"
|
||||
"------------------------------------------\n");
|
||||
|
||||
for (i = 0; i < FNIC_MQ_MAX_QUEUES; i++) {
|
||||
len += scnprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"Q:%d -> %lld\n", i, (u64)atomic64_read(&stats->io_stats.ios[i]));
|
||||
}
|
||||
|
||||
len += scnprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"\nCurrent Max IO time : %lld\n",
|
||||
(u64)atomic64_read(&stats->io_stats.current_max_io_time));
|
||||
|
@ -143,6 +143,10 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
|
||||
vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
|
||||
}
|
||||
|
||||
pr_info("res_type_wq: %d res_type_rq: %d res_type_cq: %d res_type_intr_ctrl: %d\n",
|
||||
vdev->res[RES_TYPE_WQ].count, vdev->res[RES_TYPE_RQ].count,
|
||||
vdev->res[RES_TYPE_CQ].count, vdev->res[RES_TYPE_INTR_CTRL].count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define VNIC_FNIC_RATOV_MAX 255000
|
||||
|
||||
#define VNIC_FNIC_MAXDATAFIELDSIZE_MIN 256
|
||||
#define VNIC_FNIC_MAXDATAFIELDSIZE_MAX 2112
|
||||
#define VNIC_FNIC_MAXDATAFIELDSIZE_MAX 2048
|
||||
|
||||
#define VNIC_FNIC_FLOGI_RETRIES_MIN 0
|
||||
#define VNIC_FNIC_FLOGI_RETRIES_MAX 0xffffffff
|
||||
@ -55,7 +55,7 @@
|
||||
#define VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX 255
|
||||
|
||||
#define VNIC_FNIC_LUNS_PER_TARGET_MIN 1
|
||||
#define VNIC_FNIC_LUNS_PER_TARGET_MAX 1024
|
||||
#define VNIC_FNIC_LUNS_PER_TARGET_MAX 4096
|
||||
|
||||
/* Device-specific region: scsi configuration */
|
||||
struct vnic_fc_config {
|
||||
@ -79,10 +79,19 @@ struct vnic_fc_config {
|
||||
u16 ra_tov;
|
||||
u16 intr_timer;
|
||||
u8 intr_timer_type;
|
||||
u8 intr_mode;
|
||||
u8 lun_queue_depth;
|
||||
u8 io_timeout_retry;
|
||||
u16 wq_copy_count;
|
||||
};
|
||||
|
||||
#define VFCF_FCP_SEQ_LVL_ERR 0x1 /* Enable FCP-2 Error Recovery */
|
||||
#define VFCF_PERBI 0x2 /* persistent binding info available */
|
||||
#define VFCF_FIP_CAPABLE 0x4 /* firmware can handle FIP */
|
||||
|
||||
#define VFCF_FC_INITIATOR 0x20 /* FC Initiator Mode */
|
||||
#define VFCF_FC_TARGET 0x40 /* FC Target Mode */
|
||||
#define VFCF_FC_NVME_INITIATOR 0x80 /* FC-NVMe Initiator Mode */
|
||||
#define VFCF_FC_NVME_TARGET 0x100 /* FC-NVMe Target Mode */
|
||||
|
||||
#endif /* _VNIC_SCSI_H_ */
|
||||
|
@ -1565,12 +1565,12 @@ EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done);
|
||||
static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
if (!hisi_hba->hw->soft_reset)
|
||||
return -1;
|
||||
return -ENOENT;
|
||||
|
||||
down(&hisi_hba->sem);
|
||||
if (test_and_set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags)) {
|
||||
up(&hisi_hba->sem);
|
||||
return -1;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
|
||||
@ -1641,7 +1641,10 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
||||
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
if (slot && task->task_proto & SAS_PROTOCOL_SSP) {
|
||||
if (!slot)
|
||||
goto out;
|
||||
|
||||
if (task->task_proto & SAS_PROTOCOL_SSP) {
|
||||
u16 tag = slot->idx;
|
||||
int rc2;
|
||||
|
||||
@ -1688,7 +1691,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
||||
rc = hisi_sas_softreset_ata_disk(device);
|
||||
}
|
||||
}
|
||||
} else if (slot && task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
/* SMP */
|
||||
u32 tag = slot->idx;
|
||||
struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
|
||||
|
@ -1605,6 +1605,11 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
}
|
||||
|
||||
phy->port_id = port_id;
|
||||
spin_lock(&phy->lock);
|
||||
/* Delete timer and set phy_attached atomically */
|
||||
del_timer(&phy->timer);
|
||||
phy->phy_attached = 1;
|
||||
spin_unlock(&phy->lock);
|
||||
|
||||
/*
|
||||
* Call pm_runtime_get_noresume() which pairs with
|
||||
@ -1618,11 +1623,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
|
||||
res = IRQ_HANDLED;
|
||||
|
||||
spin_lock(&phy->lock);
|
||||
/* Delete timer and set phy_attached atomically */
|
||||
del_timer(&phy->timer);
|
||||
phy->phy_attached = 1;
|
||||
spin_unlock(&phy->lock);
|
||||
end:
|
||||
if (phy->reset_completion)
|
||||
complete(phy->reset_completion);
|
||||
@ -3476,7 +3476,7 @@ static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba)
|
||||
u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < debugfs_axi_reg.count; i++, databuf++)
|
||||
for (i = 0; i < debugfs_global_reg.count; i++, databuf++)
|
||||
*databuf = hisi_sas_read32(hisi_hba, 4 * i);
|
||||
}
|
||||
|
||||
@ -4968,6 +4968,7 @@ static void hisi_sas_reset_done_v3_hw(struct pci_dev *pdev)
|
||||
{
|
||||
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
|
||||
struct hisi_hba *hisi_hba = sha->lldd_ha;
|
||||
struct Scsi_Host *shost = hisi_hba->shost;
|
||||
struct device *dev = hisi_hba->dev;
|
||||
int rc;
|
||||
|
||||
@ -4976,6 +4977,10 @@ static void hisi_sas_reset_done_v3_hw(struct pci_dev *pdev)
|
||||
rc = hw_init_v3_hw(hisi_hba);
|
||||
if (rc) {
|
||||
dev_err(dev, "FLR: hw init failed rc=%d\n", rc);
|
||||
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
|
||||
scsi_unblock_requests(shost);
|
||||
clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags);
|
||||
up(&hisi_hba->sem);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5018,7 +5023,7 @@ static int _suspend_v3_hw(struct device *device)
|
||||
}
|
||||
|
||||
if (test_and_set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags))
|
||||
return -1;
|
||||
return -EPERM;
|
||||
|
||||
dev_warn(dev, "entering suspend state\n");
|
||||
|
||||
|
@ -1464,7 +1464,7 @@ static void ibmvfc_gather_partition_info(struct ibmvfc_host *vhost)
|
||||
|
||||
name = of_get_property(rootdn, "ibm,partition-name", NULL);
|
||||
if (name)
|
||||
strncpy(vhost->partition_name, name, sizeof(vhost->partition_name));
|
||||
strscpy(vhost->partition_name, name, sizeof(vhost->partition_name));
|
||||
num = of_get_property(rootdn, "ibm,partition-no", NULL);
|
||||
if (num)
|
||||
vhost->partition_number = *num;
|
||||
@ -1513,13 +1513,15 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
|
||||
login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
|
||||
login_info->async.len = cpu_to_be32(async_crq->size *
|
||||
sizeof(*async_crq->msgs.async));
|
||||
strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
|
||||
strncpy(login_info->device_name,
|
||||
dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
|
||||
strscpy(login_info->partition_name, vhost->partition_name,
|
||||
sizeof(login_info->partition_name));
|
||||
|
||||
strscpy(login_info->device_name,
|
||||
dev_name(&vhost->host->shost_gendev), sizeof(login_info->device_name));
|
||||
|
||||
location = of_get_property(of_node, "ibm,loc-code", NULL);
|
||||
location = location ? location : dev_name(vhost->dev);
|
||||
strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME);
|
||||
strscpy(login_info->drc_name, location, sizeof(login_info->drc_name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -266,7 +266,7 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
|
||||
dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
|
||||
strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
|
||||
|
||||
strncpy(hostdata->madapter_info.partition_name, partition_name,
|
||||
strscpy(hostdata->madapter_info.partition_name, partition_name,
|
||||
sizeof(hostdata->madapter_info.partition_name));
|
||||
|
||||
hostdata->madapter_info.partition_number =
|
||||
|
@ -77,7 +77,6 @@
|
||||
static LIST_HEAD(ipr_ioa_head);
|
||||
static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
|
||||
static unsigned int ipr_max_speed = 1;
|
||||
static int ipr_testmode = 0;
|
||||
static unsigned int ipr_fastfail = 0;
|
||||
static unsigned int ipr_transop_timeout = 0;
|
||||
static unsigned int ipr_debug = 0;
|
||||
@ -193,8 +192,6 @@ module_param_named(max_speed, ipr_max_speed, uint, 0);
|
||||
MODULE_PARM_DESC(max_speed, "Maximum bus speed (0-2). Default: 1=U160. Speeds: 0=80 MB/s, 1=U160, 2=U320");
|
||||
module_param_named(log_level, ipr_log_level, uint, 0);
|
||||
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
|
||||
module_param_named(testmode, ipr_testmode, int, 0);
|
||||
MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
|
||||
module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
|
||||
module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
|
||||
@ -6416,45 +6413,6 @@ static const struct scsi_host_template driver_template = {
|
||||
.proc_name = IPR_NAME,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
static const u16 ipr_blocked_processors[] = {
|
||||
PVR_NORTHSTAR,
|
||||
PVR_PULSAR,
|
||||
PVR_POWER4,
|
||||
PVR_ICESTAR,
|
||||
PVR_SSTAR,
|
||||
PVR_POWER4p,
|
||||
PVR_630,
|
||||
PVR_630p
|
||||
};
|
||||
|
||||
/**
|
||||
* ipr_invalid_adapter - Determine if this adapter is supported on this hardware
|
||||
* @ioa_cfg: ioa cfg struct
|
||||
*
|
||||
* Adapters that use Gemstone revision < 3.1 do not work reliably on
|
||||
* certain pSeries hardware. This function determines if the given
|
||||
* adapter is in one of these confgurations or not.
|
||||
*
|
||||
* Return value:
|
||||
* 1 if adapter is not supported / 0 if adapter is supported
|
||||
**/
|
||||
static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
|
||||
for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++) {
|
||||
if (pvr_version_is(ipr_blocked_processors[i]))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define ipr_invalid_adapter(ioa_cfg) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ipr_ioa_bringdown_done - IOA bring down completion.
|
||||
* @ipr_cmd: ipr command struct
|
||||
@ -7385,19 +7343,6 @@ static int ipr_ioafp_page0_inquiry(struct ipr_cmnd *ipr_cmd)
|
||||
type[4] = '\0';
|
||||
ioa_cfg->type = simple_strtoul((char *)type, NULL, 16);
|
||||
|
||||
if (ipr_invalid_adapter(ioa_cfg)) {
|
||||
dev_err(&ioa_cfg->pdev->dev,
|
||||
"Adapter not supported in this hardware configuration.\n");
|
||||
|
||||
if (!ipr_testmode) {
|
||||
ioa_cfg->reset_retries += IPR_NUM_RESET_RELOAD_RETRIES;
|
||||
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
|
||||
list_add_tail(&ipr_cmd->queue,
|
||||
&ioa_cfg->hrrq->hrrq_free_q);
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
ipr_cmd->job_step = ipr_ioafp_page3_inquiry;
|
||||
|
||||
ipr_ioafp_inquiry(ipr_cmd, 1, 0,
|
||||
|
@ -738,8 +738,7 @@ static enum sci_status sci_io_request_construct_basic_ssp(struct isci_request *i
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
enum sci_status sci_task_request_construct_ssp(
|
||||
struct isci_request *ireq)
|
||||
void sci_task_request_construct_ssp(struct isci_request *ireq)
|
||||
{
|
||||
/* Construct the SSP Task SCU Task Context */
|
||||
scu_ssp_task_request_construct_task_context(ireq);
|
||||
@ -748,8 +747,6 @@ enum sci_status sci_task_request_construct_ssp(
|
||||
sci_task_request_build_ssp_task_iu(ireq);
|
||||
|
||||
sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
static enum sci_status sci_io_request_construct_basic_sata(struct isci_request *ireq)
|
||||
|
@ -300,7 +300,7 @@ sci_task_request_construct(struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
u16 io_tag,
|
||||
struct isci_request *ireq);
|
||||
enum sci_status sci_task_request_construct_ssp(struct isci_request *ireq);
|
||||
void sci_task_request_construct_ssp(struct isci_request *ireq);
|
||||
void sci_smp_request_copy_response(struct isci_request *ireq);
|
||||
|
||||
static inline int isci_task_is_ncq_recovery(struct sas_task *task)
|
||||
|
@ -243,9 +243,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
|
||||
/* XXX convert to get this from task->tproto like other drivers */
|
||||
if (dev->dev_type == SAS_END_DEVICE) {
|
||||
isci_tmf->proto = SAS_PROTOCOL_SSP;
|
||||
status = sci_task_request_construct_ssp(ireq);
|
||||
if (status != SCI_SUCCESS)
|
||||
return NULL;
|
||||
sci_task_request_construct_ssp(ireq);
|
||||
}
|
||||
|
||||
return ireq;
|
||||
|
@ -176,7 +176,7 @@ static int esp_jazz_probe(struct platform_device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_jazz_remove(struct platform_device *dev)
|
||||
static void esp_jazz_remove(struct platform_device *dev)
|
||||
{
|
||||
struct esp *esp = dev_get_drvdata(&dev->dev);
|
||||
unsigned int irq = esp->host->irq;
|
||||
@ -189,8 +189,6 @@ static int esp_jazz_remove(struct platform_device *dev)
|
||||
esp->command_block_dma);
|
||||
|
||||
scsi_host_put(esp->host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
@ -198,7 +196,7 @@ MODULE_ALIAS("platform:jazz_esp");
|
||||
|
||||
static struct platform_driver esp_jazz_driver = {
|
||||
.probe = esp_jazz_probe,
|
||||
.remove = esp_jazz_remove,
|
||||
.remove_new = esp_jazz_remove,
|
||||
.driver = {
|
||||
.name = "jazz_esp",
|
||||
},
|
||||
|
@ -265,6 +265,11 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
|
||||
if (!fsp->seq_ptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (fsp->state & FC_SRB_ABORT_PENDING) {
|
||||
FC_FCP_DBG(fsp, "abort already pending\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
this_cpu_inc(fsp->lp->stats->FcpPktAborts);
|
||||
|
||||
fsp->state |= FC_SRB_ABORT_PENDING;
|
||||
@ -1671,7 +1676,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
|
||||
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
|
||||
fc_fcp_rec(fsp);
|
||||
else
|
||||
fc_fcp_recovery(fsp, FC_ERROR);
|
||||
fc_fcp_recovery(fsp, FC_TIMED_OUT);
|
||||
break;
|
||||
}
|
||||
fc_fcp_unlock_pkt(fsp);
|
||||
@ -1690,11 +1695,12 @@ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
|
||||
fsp->status_code = code;
|
||||
fsp->cdb_status = 0;
|
||||
fsp->io_status = 0;
|
||||
/*
|
||||
* if this fails then we let the scsi command timer fire and
|
||||
* scsi-ml escalate.
|
||||
*/
|
||||
fc_fcp_send_abort(fsp);
|
||||
if (!fsp->cmd)
|
||||
/*
|
||||
* Only abort non-scsi commands; otherwise let the
|
||||
* scsi command timer fire and scsi-ml escalate.
|
||||
*/
|
||||
fc_fcp_send_abort(fsp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2056,9 +2062,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
|
||||
sc_cmd->result = (DID_PARITY << 16);
|
||||
break;
|
||||
case FC_TIMED_OUT:
|
||||
FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml "
|
||||
FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml "
|
||||
"due to FC_TIMED_OUT\n");
|
||||
sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
|
||||
sc_cmd->result = (DID_TIME_OUT << 16);
|
||||
break;
|
||||
default:
|
||||
FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
|
||||
|
@ -33,6 +33,7 @@
|
||||
struct lpfc_sli2_slim;
|
||||
|
||||
#define ELX_MODEL_NAME_SIZE 80
|
||||
#define ELX_FW_NAME_SIZE 84
|
||||
|
||||
#define LPFC_PCI_DEV_LP 0x1
|
||||
#define LPFC_PCI_DEV_OC 0x2
|
||||
|
@ -5905,11 +5905,11 @@ LPFC_ATTR_RW(ras_fwlog_level, 0, 0, 4, "Firmware Logging Level");
|
||||
/*
|
||||
* lpfc_ras_fwlog_func: Firmware logging enabled on function number
|
||||
* Default function which has RAS support : 0
|
||||
* Value Range is [0..7].
|
||||
* Value Range is [0..3].
|
||||
* FW logging is a global action and enablement is via a specific
|
||||
* port.
|
||||
*/
|
||||
LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
|
||||
LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 3, "Firmware Logging Enabled on Function");
|
||||
|
||||
/*
|
||||
* lpfc_enable_bbcr: Enable BB Credit Recovery
|
||||
@ -5954,7 +5954,7 @@ LPFC_ATTR_R(enable_mi, 1, 0, 1, "Enable MI");
|
||||
* 4 - 255 = vmid support enabled for 4-255 VMs
|
||||
* Value range is [4,255].
|
||||
*/
|
||||
LPFC_ATTR_RW(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
|
||||
LPFC_ATTR_R(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
|
||||
"Maximum number of VMs supported");
|
||||
|
||||
/*
|
||||
@ -5962,7 +5962,7 @@ LPFC_ATTR_RW(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID,
|
||||
* 0 = Timeout is disabled
|
||||
* Value range is [0,24].
|
||||
*/
|
||||
LPFC_ATTR_RW(vmid_inactivity_timeout, 4, 0, 24,
|
||||
LPFC_ATTR_R(vmid_inactivity_timeout, 4, 0, 24,
|
||||
"Inactivity timeout in hours");
|
||||
|
||||
/*
|
||||
@ -5971,7 +5971,7 @@ LPFC_ATTR_RW(vmid_inactivity_timeout, 4, 0, 24,
|
||||
* 1 = Support is enabled
|
||||
* Value range is [0,1].
|
||||
*/
|
||||
LPFC_ATTR_RW(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
|
||||
LPFC_ATTR_R(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
|
||||
LPFC_VMID_APP_HEADER_DISABLE, LPFC_VMID_APP_HEADER_ENABLE,
|
||||
"Enable App Header VMID support");
|
||||
|
||||
@ -5982,7 +5982,7 @@ LPFC_ATTR_RW(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE,
|
||||
* 2 = Allow all targets
|
||||
* Value range is [0,2].
|
||||
*/
|
||||
LPFC_ATTR_RW(vmid_priority_tagging, LPFC_VMID_PRIO_TAG_DISABLE,
|
||||
LPFC_ATTR_R(vmid_priority_tagging, LPFC_VMID_PRIO_TAG_DISABLE,
|
||||
LPFC_VMID_PRIO_TAG_DISABLE,
|
||||
LPFC_VMID_PRIO_TAG_ALL_TARGETS,
|
||||
"Enable Priority Tagging VMID support");
|
||||
|
@ -1130,12 +1130,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
vport->port_state, vport->fc_flag,
|
||||
sp->cmn.priority_tagging, kref_read(&ndlp->kref));
|
||||
|
||||
if (sp->cmn.priority_tagging)
|
||||
vport->phba->pport->vmid_flag |= (LPFC_VMID_ISSUE_QFPA |
|
||||
LPFC_VMID_TYPE_PRIO);
|
||||
/* reinitialize the VMID datastructure before returning */
|
||||
if (lpfc_is_vmid_enabled(phba))
|
||||
lpfc_reinit_vmid(vport);
|
||||
if (sp->cmn.priority_tagging)
|
||||
vport->phba->pport->vmid_flag |= (LPFC_VMID_ISSUE_QFPA |
|
||||
LPFC_VMID_TYPE_PRIO);
|
||||
|
||||
/*
|
||||
* Address a timing race with dev_loss. If dev_loss is active on
|
||||
@ -2062,8 +2062,9 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* PLOGI completes to NPort <nlp_DID> */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0102 PLOGI completes to NPort x%06x "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, ndlp->nlp_fc4_type,
|
||||
"IoTag x%x Data: x%x x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, iotag,
|
||||
ndlp->nlp_fc4_type,
|
||||
ulp_status, ulp_word4,
|
||||
disc, vport->num_disc_nodes);
|
||||
|
||||
@ -2128,8 +2129,8 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
NLP_EVT_DEVICE_RM);
|
||||
} else {
|
||||
/* Good status, call state machine */
|
||||
prsp = list_entry(cmdiocb->cmd_dmabuf->list.next,
|
||||
struct lpfc_dmabuf, list);
|
||||
prsp = list_get_first(&cmdiocb->cmd_dmabuf->list,
|
||||
struct lpfc_dmabuf, list);
|
||||
if (!prsp)
|
||||
goto out;
|
||||
if (!lpfc_is_els_acc_rsp(prsp))
|
||||
@ -2362,9 +2363,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* PRLI completes to NPort <nlp_DID> */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0103 PRLI completes to NPort x%06x "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, ulp_status, ulp_word4,
|
||||
vport->num_disc_nodes, ndlp->fc4_prli_sent);
|
||||
vport->num_disc_nodes, ndlp->fc4_prli_sent,
|
||||
ndlp->fc4_xpt_flags);
|
||||
|
||||
/* Check to see if link went down during discovery */
|
||||
if (lpfc_els_chk_latt(vport))
|
||||
@ -2805,7 +2807,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
int disc;
|
||||
u32 ulp_status, ulp_word4, tmo;
|
||||
u32 ulp_status, ulp_word4, tmo, iotag;
|
||||
bool release_node = false;
|
||||
|
||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||
@ -2818,9 +2820,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
tmo = get_wqe_tmo(cmdiocb);
|
||||
iotag = get_wqe_reqtag(cmdiocb);
|
||||
} else {
|
||||
irsp = &rspiocb->iocb;
|
||||
tmo = irsp->ulpTimeout;
|
||||
iotag = irsp->ulpIoTag;
|
||||
}
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||
@ -2838,9 +2842,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* ADISC completes to NPort <nlp_DID> */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0104 ADISC completes to NPort x%x "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, ulp_status, ulp_word4,
|
||||
"IoTag x%x Data: x%x x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, iotag,
|
||||
ulp_status, ulp_word4,
|
||||
tmo, disc, vport->num_disc_nodes);
|
||||
|
||||
/* Check to see if link went down during discovery */
|
||||
if (lpfc_els_chk_latt(vport)) {
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
@ -3001,7 +3007,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
int wake_up_waiter = 0;
|
||||
u32 ulp_status;
|
||||
u32 ulp_word4;
|
||||
u32 tmo;
|
||||
u32 tmo, iotag;
|
||||
|
||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||
cmdiocb->rsp_iocb = rspiocb;
|
||||
@ -3011,9 +3017,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
tmo = get_wqe_tmo(cmdiocb);
|
||||
iotag = get_wqe_reqtag(cmdiocb);
|
||||
} else {
|
||||
irsp = &rspiocb->iocb;
|
||||
tmo = irsp->ulpTimeout;
|
||||
iotag = irsp->ulpIoTag;
|
||||
}
|
||||
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
@ -3032,9 +3040,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* LOGO completes to NPort <nlp_DID> */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0105 LOGO completes to NPort x%x "
|
||||
"refcnt %d nflags x%x Data: x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
|
||||
ulp_status, ulp_word4,
|
||||
"IoTag x%x refcnt %d nflags x%x xflags x%x "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, iotag,
|
||||
kref_read(&ndlp->kref), ndlp->nlp_flag,
|
||||
ndlp->fc4_xpt_flags, ulp_status, ulp_word4,
|
||||
tmo, vport->num_disc_nodes);
|
||||
|
||||
if (lpfc_els_chk_latt(vport)) {
|
||||
@ -5075,16 +5085,19 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
if (logerr) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0137 No retry ELS command x%x to remote "
|
||||
"NPORT x%x: Out of Resources: Error:x%x/%x\n",
|
||||
cmd, did, ulp_status,
|
||||
ulp_word4);
|
||||
"NPORT x%x: Out of Resources: Error:x%x/%x "
|
||||
"IoTag x%x\n",
|
||||
cmd, did, ulp_status, ulp_word4,
|
||||
cmdiocb->iotag);
|
||||
}
|
||||
else {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0108 No retry ELS command x%x to remote "
|
||||
"NPORT x%x Retried:%d Error:x%x/%x\n",
|
||||
cmd, did, cmdiocb->retry, ulp_status,
|
||||
ulp_word4);
|
||||
"0108 No retry ELS command x%x to remote "
|
||||
"NPORT x%x Retried:%d Error:x%x/%x "
|
||||
"IoTag x%x nflags x%x\n",
|
||||
cmd, did, cmdiocb->retry, ulp_status,
|
||||
ulp_word4, cmdiocb->iotag,
|
||||
(ndlp ? ndlp->nlp_flag : 0));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -11130,6 +11143,14 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
lpfc_nlp_put(ndlp);
|
||||
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
|
||||
/* reinitialize the VMID datastructure before returning.
|
||||
* this is specifically for vport
|
||||
*/
|
||||
if (lpfc_is_vmid_enabled(phba))
|
||||
lpfc_reinit_vmid(vport);
|
||||
vport->vmid_flag = vport->phba->pport->vmid_flag;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
|
||||
"port_state = x%x\n",
|
||||
ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp,
|
||||
ndlp->nlp_flag, vport->port_state);
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
}
|
||||
|
@ -14721,7 +14721,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
|
||||
int
|
||||
lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
|
||||
{
|
||||
uint8_t file_name[ELX_MODEL_NAME_SIZE];
|
||||
char file_name[ELX_FW_NAME_SIZE] = {0};
|
||||
int ret;
|
||||
const struct firmware *fw;
|
||||
|
||||
@ -14730,7 +14730,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
|
||||
LPFC_SLI_INTF_IF_TYPE_2)
|
||||
return -EPERM;
|
||||
|
||||
snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName);
|
||||
scnprintf(file_name, sizeof(file_name), "%s.grp", phba->ModelName);
|
||||
|
||||
if (fw_upgrade == INT_FW_UPGRADE) {
|
||||
ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2023 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. *
|
||||
@ -1814,7 +1814,9 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
|
||||
dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
|
||||
mbox->sge_array->addr[sgentry], phyaddr);
|
||||
}
|
||||
/* Free the sge address array memory */
|
||||
/* Reinitialize the context pointers to avoid stale usage. */
|
||||
mbox->ctx_buf = NULL;
|
||||
mbox->context3 = NULL;
|
||||
kfree(mbox->sge_array);
|
||||
/* Finally, free the mailbox command itself */
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2023 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. *
|
||||
@ -48,6 +48,29 @@
|
||||
#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */
|
||||
#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */
|
||||
|
||||
/* lpfc_mbox_free_sli_mbox
|
||||
*
|
||||
* @phba: HBA to free memory for
|
||||
* @mbox: mailbox command to free
|
||||
*
|
||||
* This routine detects the mbox type and calls the correct
|
||||
* free routine to fully release all associated memory.
|
||||
*/
|
||||
static void
|
||||
lpfc_mem_free_sli_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
|
||||
{
|
||||
/* Detect if the caller's mbox is an SLI4_CONFIG type. If so, this
|
||||
* mailbox type requires a different cleanup routine. Otherwise, the
|
||||
* mailbox is just an mbuf and mem_pool release.
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
bf_get(lpfc_mqe_command, &mbox->u.mqe) == MBX_SLI4_CONFIG) {
|
||||
lpfc_sli4_mbox_cmd_free(phba, mbox);
|
||||
} else {
|
||||
lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) {
|
||||
size_t bytes;
|
||||
@ -288,27 +311,16 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
LPFC_MBOXQ_t *mbox, *next_mbox;
|
||||
struct lpfc_dmabuf *mp;
|
||||
|
||||
/* Free memory used in mailbox queue back to mailbox memory pool */
|
||||
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
|
||||
mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
list_del(&mbox->list);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
lpfc_mem_free_sli_mbox(phba, mbox);
|
||||
}
|
||||
/* Free memory used in mailbox cmpl list back to mailbox memory pool */
|
||||
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
|
||||
mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
list_del(&mbox->list);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
lpfc_mem_free_sli_mbox(phba, mbox);
|
||||
}
|
||||
/* Free the active mailbox command back to the mailbox memory pool */
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
@ -316,12 +328,7 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
if (psli->mbox_active) {
|
||||
mbox = psli->mbox_active;
|
||||
mp = (struct lpfc_dmabuf *)(mbox->ctx_buf);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
lpfc_mem_free_sli_mbox(phba, mbox);
|
||||
psli->mbox_active = NULL;
|
||||
}
|
||||
|
||||
|
@ -2995,8 +2995,9 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
LPFC_SLI_INTF_IF_TYPE_2)) {
|
||||
if (ndlp) {
|
||||
lpfc_printf_vlog(
|
||||
vport, KERN_INFO, LOG_MBOX | LOG_SLI,
|
||||
"0010 UNREG_LOGIN vpi:%x "
|
||||
vport, KERN_INFO,
|
||||
LOG_MBOX | LOG_SLI | LOG_NODE,
|
||||
"0010 UNREG_LOGIN vpi:x%x "
|
||||
"rpi:%x DID:%x defer x%x flg x%x "
|
||||
"x%px\n",
|
||||
vport->vpi, ndlp->nlp_rpi,
|
||||
@ -3012,7 +3013,8 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
(ndlp->nlp_defer_did !=
|
||||
NLP_EVT_NOTHING_PENDING)) {
|
||||
lpfc_printf_vlog(
|
||||
vport, KERN_INFO, LOG_DISCOVERY,
|
||||
vport, KERN_INFO,
|
||||
LOG_MBOX | LOG_SLI | LOG_NODE,
|
||||
"4111 UNREG cmpl deferred "
|
||||
"clr x%x on "
|
||||
"NPort x%x Data: x%x x%px\n",
|
||||
@ -3938,6 +3940,9 @@ void lpfc_poll_eratt(struct timer_list *t)
|
||||
if (!(phba->hba_flag & HBA_SETUP))
|
||||
return;
|
||||
|
||||
if (phba->pport->load_flag & FC_UNLOADING)
|
||||
return;
|
||||
|
||||
/* Here we will also keep track of interrupts per sec of the hba */
|
||||
sli_intr = phba->sli.slistat.sli_intr;
|
||||
|
||||
@ -10141,11 +10146,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
|
||||
"(%d):0354 Mbox cmd issue - Enqueue Data: "
|
||||
"x%x (x%x/x%x) x%x x%x x%x\n",
|
||||
"x%x (x%x/x%x) x%x x%x x%x x%x\n",
|
||||
mboxq->vport ? mboxq->vport->vpi : 0xffffff,
|
||||
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
|
||||
lpfc_sli_config_mbox_subsys_get(phba, mboxq),
|
||||
lpfc_sli_config_mbox_opcode_get(phba, mboxq),
|
||||
mboxq->u.mb.un.varUnregLogin.rpi,
|
||||
phba->pport->port_state,
|
||||
psli->sli_flag, MBX_NOWAIT);
|
||||
/* Wake up worker thread to transport mailbox command from head */
|
||||
@ -22167,6 +22173,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
|
||||
* The data will be truncated if datasz is not large enough.
|
||||
* Version 1 is not supported with Embedded mbox cmd, so we must use version 0.
|
||||
* Returns the actual bytes read from the object.
|
||||
*
|
||||
* This routine is hard coded to use a poll completion. Unlike other
|
||||
* sli4_config mailboxes, it uses lpfc_mbuf memory which is not
|
||||
* cleaned up in lpfc_sli4_cmd_mbox_free. If this routine is modified
|
||||
* to use interrupt-based completions, code is needed to fully cleanup
|
||||
* the memory.
|
||||
*/
|
||||
int
|
||||
lpfc_read_object(struct lpfc_hba *phba, char *rdobject, uint32_t *datap,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2023 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. *
|
||||
@ -182,9 +182,11 @@ typedef struct lpfcMboxq {
|
||||
struct lpfc_mqe mqe;
|
||||
} u;
|
||||
struct lpfc_vport *vport; /* virtual port pointer */
|
||||
void *ctx_ndlp; /* caller ndlp information */
|
||||
void *ctx_buf; /* caller buffer information */
|
||||
void *context3;
|
||||
void *ctx_ndlp; /* an lpfc_nodelist pointer */
|
||||
void *ctx_buf; /* an lpfc_dmabuf pointer */
|
||||
void *context3; /* a generic pointer. Code must
|
||||
* accommodate the actual datatype.
|
||||
*/
|
||||
|
||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||
uint8_t mbox_flag;
|
||||
|
@ -20,7 +20,7 @@
|
||||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.15"
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.17"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
@ -321,5 +321,6 @@ lpfc_reinit_vmid(struct lpfc_vport *vport)
|
||||
if (!hash_empty(vport->hash_table))
|
||||
hash_for_each_safe(vport->hash_table, bucket, tmp, cur, hnode)
|
||||
hash_del(&cur->hnode);
|
||||
vport->vmid_flag = 0;
|
||||
write_unlock(&vport->vmid_lock);
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ static int esp_mac_probe(struct platform_device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_mac_remove(struct platform_device *dev)
|
||||
static void esp_mac_remove(struct platform_device *dev)
|
||||
{
|
||||
struct mac_esp_priv *mep = platform_get_drvdata(dev);
|
||||
struct esp *esp = mep->esp;
|
||||
@ -428,13 +428,11 @@ static int esp_mac_remove(struct platform_device *dev)
|
||||
kfree(esp->command_block);
|
||||
|
||||
scsi_host_put(esp->host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver esp_mac_driver = {
|
||||
.probe = esp_mac_probe,
|
||||
.remove = esp_mac_remove,
|
||||
.remove_new = esp_mac_remove,
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
},
|
||||
|
@ -523,7 +523,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit mac_scsi_remove(struct platform_device *pdev)
|
||||
static void __exit mac_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
|
||||
@ -532,11 +532,10 @@ static int __exit mac_scsi_remove(struct platform_device *pdev)
|
||||
free_irq(instance->irq, instance);
|
||||
NCR5380_exit(instance);
|
||||
scsi_host_put(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mac_scsi_driver = {
|
||||
.remove = __exit_p(mac_scsi_remove),
|
||||
.remove_new = __exit_p(mac_scsi_remove),
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
},
|
||||
|
@ -28,6 +28,7 @@ struct mpi3_ioc_init_request {
|
||||
__le64 driver_information_address;
|
||||
};
|
||||
|
||||
#define MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED (0x04)
|
||||
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03)
|
||||
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00)
|
||||
#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01)
|
||||
|
@ -55,8 +55,8 @@ extern struct list_head mrioc_list;
|
||||
extern int prot_mask;
|
||||
extern atomic64_t event_counter;
|
||||
|
||||
#define MPI3MR_DRIVER_VERSION "8.5.0.0.0"
|
||||
#define MPI3MR_DRIVER_RELDATE "24-July-2023"
|
||||
#define MPI3MR_DRIVER_VERSION "8.5.1.0.0"
|
||||
#define MPI3MR_DRIVER_RELDATE "5-December-2023"
|
||||
|
||||
#define MPI3MR_DRIVER_NAME "mpi3mr"
|
||||
#define MPI3MR_DRIVER_LICENSE "GPL"
|
||||
@ -218,14 +218,16 @@ extern atomic64_t event_counter;
|
||||
* @length: SGE length
|
||||
* @rsvd: Reserved
|
||||
* @rsvd1: Reserved
|
||||
* @sgl_type: sgl type
|
||||
* @sub_type: sgl sub type
|
||||
* @type: sgl type
|
||||
*/
|
||||
struct mpi3mr_nvme_pt_sge {
|
||||
u64 base_addr;
|
||||
u32 length;
|
||||
__le64 base_addr;
|
||||
__le32 length;
|
||||
u16 rsvd;
|
||||
u8 rsvd1;
|
||||
u8 sgl_type;
|
||||
u8 sub_type:4;
|
||||
u8 type:4;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -247,6 +249,8 @@ struct mpi3mr_buf_map {
|
||||
u32 kern_buf_len;
|
||||
dma_addr_t kern_buf_dma;
|
||||
u8 data_dir;
|
||||
u16 num_dma_desc;
|
||||
struct dma_memory_desc *dma_desc;
|
||||
};
|
||||
|
||||
/* IOC State definitions */
|
||||
@ -477,6 +481,10 @@ struct mpi3mr_throttle_group_info {
|
||||
/* HBA port flags */
|
||||
#define MPI3MR_HBA_PORT_FLAG_DIRTY 0x01
|
||||
|
||||
/* IOCTL data transfer sge*/
|
||||
#define MPI3MR_NUM_IOCTL_SGE 256
|
||||
#define MPI3MR_IOCTL_SGE_SIZE (8 * 1024)
|
||||
|
||||
/**
|
||||
* struct mpi3mr_hba_port - HBA's port information
|
||||
* @port_id: Port number
|
||||
@ -506,7 +514,7 @@ struct mpi3mr_sas_port {
|
||||
u8 num_phys;
|
||||
u8 marked_responding;
|
||||
int lowest_phy;
|
||||
u32 phy_mask;
|
||||
u64 phy_mask;
|
||||
struct mpi3mr_hba_port *hba_port;
|
||||
struct sas_identify remote_identify;
|
||||
struct sas_rphy *rphy;
|
||||
@ -1042,6 +1050,11 @@ struct scmd_priv {
|
||||
* @sas_node_lock: Lock to protect SAS node list
|
||||
* @hba_port_table_list: List of HBA Ports
|
||||
* @enclosure_list: List of Enclosure objects
|
||||
* @ioctl_dma_pool: DMA pool for IOCTL data buffers
|
||||
* @ioctl_sge: DMA buffer descriptors for IOCTL data
|
||||
* @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain
|
||||
* @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
|
||||
* @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not
|
||||
*/
|
||||
struct mpi3mr_ioc {
|
||||
struct list_head list;
|
||||
@ -1227,6 +1240,12 @@ struct mpi3mr_ioc {
|
||||
spinlock_t sas_node_lock;
|
||||
struct list_head hba_port_table_list;
|
||||
struct list_head enclosure_list;
|
||||
|
||||
struct dma_pool *ioctl_dma_pool;
|
||||
struct dma_memory_desc ioctl_sge[MPI3MR_NUM_IOCTL_SGE];
|
||||
struct dma_memory_desc ioctl_chain_sge;
|
||||
struct dma_memory_desc ioctl_resp_sge;
|
||||
bool ioctl_sges_allocated;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -223,6 +223,22 @@ static long mpi3mr_bsg_pel_enable(struct mpi3mr_ioc *mrioc,
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (mrioc->unrecoverable) {
|
||||
dprint_bsg_err(mrioc, "%s: unrecoverable controller\n",
|
||||
__func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (mrioc->reset_in_progress) {
|
||||
dprint_bsg_err(mrioc, "%s: reset in progress\n", __func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (mrioc->stop_bsgs) {
|
||||
dprint_bsg_err(mrioc, "%s: bsgs are blocked\n", __func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
sg_copy_to_buffer(job->request_payload.sg_list,
|
||||
job->request_payload.sg_cnt,
|
||||
&pel_enable, sizeof(pel_enable));
|
||||
@ -547,8 +563,37 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_total_num_ioctl_sges - Count number of SGEs required
|
||||
* @drv_bufs: DMA address of the buffers to be placed in sgl
|
||||
* @bufcnt: Number of DMA buffers
|
||||
*
|
||||
* This function returns total number of data SGEs required
|
||||
* including zero length SGEs and excluding management request
|
||||
* and response buffer for the given list of data buffer
|
||||
* descriptors
|
||||
*
|
||||
* Return: Number of SGE elements needed
|
||||
*/
|
||||
static inline u16 mpi3mr_total_num_ioctl_sges(struct mpi3mr_buf_map *drv_bufs,
|
||||
u8 bufcnt)
|
||||
{
|
||||
u16 i, sge_count = 0;
|
||||
|
||||
for (i = 0; i < bufcnt; i++, drv_bufs++) {
|
||||
if (drv_bufs->data_dir == DMA_NONE ||
|
||||
drv_bufs->kern_buf)
|
||||
continue;
|
||||
sge_count += drv_bufs->num_dma_desc;
|
||||
if (!drv_bufs->num_dma_desc)
|
||||
sge_count++;
|
||||
}
|
||||
return sge_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_bsg_build_sgl - SGL construction for MPI commands
|
||||
* @mrioc: Adapter instance reference
|
||||
* @mpi_req: MPI request
|
||||
* @sgl_offset: offset to start sgl in the MPI request
|
||||
* @drv_bufs: DMA address of the buffers to be placed in sgl
|
||||
@ -560,27 +605,45 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
|
||||
* This function places the DMA address of the given buffers in
|
||||
* proper format as SGEs in the given MPI request.
|
||||
*
|
||||
* Return: Nothing
|
||||
* Return: 0 on success,-1 on failure
|
||||
*/
|
||||
static void mpi3mr_bsg_build_sgl(u8 *mpi_req, uint32_t sgl_offset,
|
||||
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt, u8 is_rmc,
|
||||
u8 is_rmr, u8 num_datasges)
|
||||
static int mpi3mr_bsg_build_sgl(struct mpi3mr_ioc *mrioc, u8 *mpi_req,
|
||||
u32 sgl_offset, struct mpi3mr_buf_map *drv_bufs,
|
||||
u8 bufcnt, u8 is_rmc, u8 is_rmr, u8 num_datasges)
|
||||
{
|
||||
struct mpi3_request_header *mpi_header =
|
||||
(struct mpi3_request_header *)mpi_req;
|
||||
u8 *sgl = (mpi_req + sgl_offset), count = 0;
|
||||
struct mpi3_mgmt_passthrough_request *rmgmt_req =
|
||||
(struct mpi3_mgmt_passthrough_request *)mpi_req;
|
||||
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
|
||||
u8 sgl_flags, sgl_flags_last;
|
||||
u8 flag, sgl_flags, sgl_flag_eob, sgl_flags_last, last_chain_sgl_flag;
|
||||
u16 available_sges, i, sges_needed;
|
||||
u32 sge_element_size = sizeof(struct mpi3_sge_common);
|
||||
bool chain_used = false;
|
||||
|
||||
sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
|
||||
MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_BUFFER;
|
||||
sgl_flags_last = sgl_flags | MPI3_SGE_FLAGS_END_OF_LIST;
|
||||
MPI3_SGE_FLAGS_DLAS_SYSTEM;
|
||||
sgl_flag_eob = sgl_flags | MPI3_SGE_FLAGS_END_OF_BUFFER;
|
||||
sgl_flags_last = sgl_flag_eob | MPI3_SGE_FLAGS_END_OF_LIST;
|
||||
last_chain_sgl_flag = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN |
|
||||
MPI3_SGE_FLAGS_DLAS_SYSTEM;
|
||||
|
||||
sges_needed = mpi3mr_total_num_ioctl_sges(drv_bufs, bufcnt);
|
||||
|
||||
if (is_rmc) {
|
||||
mpi3mr_add_sg_single(&rmgmt_req->command_sgl,
|
||||
sgl_flags_last, drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->kern_buf_dma);
|
||||
sgl = (u8 *)drv_buf_iter->kern_buf + drv_buf_iter->bsg_buf_len;
|
||||
sgl = (u8 *)drv_buf_iter->kern_buf +
|
||||
drv_buf_iter->bsg_buf_len;
|
||||
available_sges = (drv_buf_iter->kern_buf_len -
|
||||
drv_buf_iter->bsg_buf_len) / sge_element_size;
|
||||
|
||||
if (sges_needed > available_sges)
|
||||
return -1;
|
||||
|
||||
chain_used = true;
|
||||
drv_buf_iter++;
|
||||
count++;
|
||||
if (is_rmr) {
|
||||
@ -592,23 +655,95 @@ static void mpi3mr_bsg_build_sgl(u8 *mpi_req, uint32_t sgl_offset,
|
||||
} else
|
||||
mpi3mr_build_zero_len_sge(
|
||||
&rmgmt_req->response_sgl);
|
||||
if (num_datasges) {
|
||||
i = 0;
|
||||
goto build_sges;
|
||||
}
|
||||
} else {
|
||||
if (sgl_offset >= MPI3MR_ADMIN_REQ_FRAME_SZ)
|
||||
return -1;
|
||||
available_sges = (MPI3MR_ADMIN_REQ_FRAME_SZ - sgl_offset) /
|
||||
sge_element_size;
|
||||
if (!available_sges)
|
||||
return -1;
|
||||
}
|
||||
if (!num_datasges) {
|
||||
mpi3mr_build_zero_len_sge(sgl);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (mpi_header->function == MPI3_BSG_FUNCTION_SMP_PASSTHROUGH) {
|
||||
if ((sges_needed > 2) || (sges_needed > available_sges))
|
||||
return -1;
|
||||
for (; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE ||
|
||||
!drv_buf_iter->num_dma_desc)
|
||||
continue;
|
||||
mpi3mr_add_sg_single(sgl, sgl_flags_last,
|
||||
drv_buf_iter->dma_desc[0].size,
|
||||
drv_buf_iter->dma_desc[0].dma_addr);
|
||||
sgl += sge_element_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
i = 0;
|
||||
|
||||
build_sges:
|
||||
for (; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE)
|
||||
continue;
|
||||
if (num_datasges == 1 || !is_rmc)
|
||||
mpi3mr_add_sg_single(sgl, sgl_flags_last,
|
||||
drv_buf_iter->kern_buf_len, drv_buf_iter->kern_buf_dma);
|
||||
else
|
||||
mpi3mr_add_sg_single(sgl, sgl_flags,
|
||||
drv_buf_iter->kern_buf_len, drv_buf_iter->kern_buf_dma);
|
||||
sgl += sizeof(struct mpi3_sge_common);
|
||||
if (!drv_buf_iter->num_dma_desc) {
|
||||
if (chain_used && !available_sges)
|
||||
return -1;
|
||||
if (!chain_used && (available_sges == 1) &&
|
||||
(sges_needed > 1))
|
||||
goto setup_chain;
|
||||
flag = sgl_flag_eob;
|
||||
if (num_datasges == 1)
|
||||
flag = sgl_flags_last;
|
||||
mpi3mr_add_sg_single(sgl, flag, 0, 0);
|
||||
sgl += sge_element_size;
|
||||
sges_needed--;
|
||||
available_sges--;
|
||||
num_datasges--;
|
||||
continue;
|
||||
}
|
||||
for (; i < drv_buf_iter->num_dma_desc; i++) {
|
||||
if (chain_used && !available_sges)
|
||||
return -1;
|
||||
if (!chain_used && (available_sges == 1) &&
|
||||
(sges_needed > 1))
|
||||
goto setup_chain;
|
||||
flag = sgl_flags;
|
||||
if (i == (drv_buf_iter->num_dma_desc - 1)) {
|
||||
if (num_datasges == 1)
|
||||
flag = sgl_flags_last;
|
||||
else
|
||||
flag = sgl_flag_eob;
|
||||
}
|
||||
|
||||
mpi3mr_add_sg_single(sgl, flag,
|
||||
drv_buf_iter->dma_desc[i].size,
|
||||
drv_buf_iter->dma_desc[i].dma_addr);
|
||||
sgl += sge_element_size;
|
||||
available_sges--;
|
||||
sges_needed--;
|
||||
}
|
||||
num_datasges--;
|
||||
i = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
setup_chain:
|
||||
available_sges = mrioc->ioctl_chain_sge.size / sge_element_size;
|
||||
if (sges_needed > available_sges)
|
||||
return -1;
|
||||
mpi3mr_add_sg_single(sgl, last_chain_sgl_flag,
|
||||
(sges_needed * sge_element_size),
|
||||
mrioc->ioctl_chain_sge.dma_addr);
|
||||
memset(mrioc->ioctl_chain_sge.addr, 0, mrioc->ioctl_chain_sge.size);
|
||||
sgl = (u8 *)mrioc->ioctl_chain_sge.addr;
|
||||
chain_used = true;
|
||||
goto build_sges;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -648,14 +783,20 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt)
|
||||
{
|
||||
struct mpi3mr_nvme_pt_sge *nvme_sgl;
|
||||
u64 sgl_ptr;
|
||||
__le64 sgl_dma;
|
||||
u8 count;
|
||||
size_t length = 0;
|
||||
u16 available_sges = 0, i;
|
||||
u32 sge_element_size = sizeof(struct mpi3mr_nvme_pt_sge);
|
||||
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
|
||||
u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
|
||||
mrioc->facts.sge_mod_shift) << 32);
|
||||
u64 sgemod_val = ((u64)(mrioc->facts.sge_mod_value) <<
|
||||
mrioc->facts.sge_mod_shift) << 32;
|
||||
u32 size;
|
||||
|
||||
nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
|
||||
((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
|
||||
|
||||
/*
|
||||
* Not all commands require a data transfer. If no data, just return
|
||||
@ -664,27 +805,59 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE)
|
||||
continue;
|
||||
sgl_ptr = (u64)drv_buf_iter->kern_buf_dma;
|
||||
length = drv_buf_iter->kern_buf_len;
|
||||
break;
|
||||
}
|
||||
if (!length)
|
||||
if (!length || !drv_buf_iter->num_dma_desc)
|
||||
return 0;
|
||||
|
||||
if (sgl_ptr & sgemod_mask) {
|
||||
if (drv_buf_iter->num_dma_desc == 1) {
|
||||
available_sges = 1;
|
||||
goto build_sges;
|
||||
}
|
||||
|
||||
sgl_dma = cpu_to_le64(mrioc->ioctl_chain_sge.dma_addr);
|
||||
if (sgl_dma & sgemod_mask) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s: SGL address collides with SGE modifier\n",
|
||||
"%s: SGL chain address collides with SGE modifier\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sgl_ptr &= ~sgemod_mask;
|
||||
sgl_ptr |= sgemod_val;
|
||||
nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
|
||||
((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
|
||||
sgl_dma &= ~sgemod_mask;
|
||||
sgl_dma |= sgemod_val;
|
||||
|
||||
memset(mrioc->ioctl_chain_sge.addr, 0, mrioc->ioctl_chain_sge.size);
|
||||
available_sges = mrioc->ioctl_chain_sge.size / sge_element_size;
|
||||
if (available_sges < drv_buf_iter->num_dma_desc)
|
||||
return -1;
|
||||
memset(nvme_sgl, 0, sizeof(struct mpi3mr_nvme_pt_sge));
|
||||
nvme_sgl->base_addr = sgl_ptr;
|
||||
nvme_sgl->length = length;
|
||||
nvme_sgl->base_addr = sgl_dma;
|
||||
size = drv_buf_iter->num_dma_desc * sizeof(struct mpi3mr_nvme_pt_sge);
|
||||
nvme_sgl->length = cpu_to_le32(size);
|
||||
nvme_sgl->type = MPI3MR_NVMESGL_LAST_SEGMENT;
|
||||
nvme_sgl = (struct mpi3mr_nvme_pt_sge *)mrioc->ioctl_chain_sge.addr;
|
||||
|
||||
build_sges:
|
||||
for (i = 0; i < drv_buf_iter->num_dma_desc; i++) {
|
||||
sgl_dma = cpu_to_le64(drv_buf_iter->dma_desc[i].dma_addr);
|
||||
if (sgl_dma & sgemod_mask) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s: SGL address collides with SGE modifier\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sgl_dma &= ~sgemod_mask;
|
||||
sgl_dma |= sgemod_val;
|
||||
|
||||
nvme_sgl->base_addr = sgl_dma;
|
||||
nvme_sgl->length = cpu_to_le32(drv_buf_iter->dma_desc[i].size);
|
||||
nvme_sgl->type = MPI3MR_NVMESGL_DATA_SEGMENT;
|
||||
nvme_sgl++;
|
||||
available_sges--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -712,7 +885,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
dma_addr_t prp_entry_dma, prp_page_dma, dma_addr;
|
||||
u32 offset, entry_len, dev_pgsz;
|
||||
u32 page_mask_result, page_mask;
|
||||
size_t length = 0;
|
||||
size_t length = 0, desc_len;
|
||||
u8 count;
|
||||
struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
|
||||
u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
|
||||
@ -721,6 +894,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
mrioc->facts.sge_mod_shift) << 32;
|
||||
u16 dev_handle = nvme_encap_request->dev_handle;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
u16 desc_count = 0;
|
||||
|
||||
tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle);
|
||||
if (!tgtdev) {
|
||||
@ -739,6 +913,21 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
|
||||
dev_pgsz = 1 << (tgtdev->dev_spec.pcie_inf.pgsz);
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
page_mask = dev_pgsz - 1;
|
||||
|
||||
if (dev_pgsz > MPI3MR_IOCTL_SGE_SIZE) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s: NVMe device page size(%d) is greater than ioctl data sge size(%d) for handle 0x%04x\n",
|
||||
__func__, dev_pgsz, MPI3MR_IOCTL_SGE_SIZE, dev_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (MPI3MR_IOCTL_SGE_SIZE % dev_pgsz) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s: ioctl data sge size(%d) is not a multiple of NVMe device page size(%d) for handle 0x%04x\n",
|
||||
__func__, MPI3MR_IOCTL_SGE_SIZE, dev_pgsz, dev_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not all commands require a data transfer. If no data, just return
|
||||
@ -747,14 +936,26 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE)
|
||||
continue;
|
||||
dma_addr = drv_buf_iter->kern_buf_dma;
|
||||
length = drv_buf_iter->kern_buf_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
if (!length || !drv_buf_iter->num_dma_desc)
|
||||
return 0;
|
||||
|
||||
for (count = 0; count < drv_buf_iter->num_dma_desc; count++) {
|
||||
dma_addr = drv_buf_iter->dma_desc[count].dma_addr;
|
||||
if (dma_addr & page_mask) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s:dma_addr %pad is not aligned with page size 0x%x\n",
|
||||
__func__, &dma_addr, dev_pgsz);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dma_addr = drv_buf_iter->dma_desc[0].dma_addr;
|
||||
desc_len = drv_buf_iter->dma_desc[0].size;
|
||||
|
||||
mrioc->prp_sz = 0;
|
||||
mrioc->prp_list_virt = dma_alloc_coherent(&mrioc->pdev->dev,
|
||||
dev_pgsz, &mrioc->prp_list_dma, GFP_KERNEL);
|
||||
@ -784,7 +985,6 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
* Check if we are within 1 entry of a page boundary we don't
|
||||
* want our first entry to be a PRP List entry.
|
||||
*/
|
||||
page_mask = dev_pgsz - 1;
|
||||
page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask;
|
||||
if (!page_mask_result) {
|
||||
dprint_bsg_err(mrioc, "%s: PRP page is not page aligned\n",
|
||||
@ -898,18 +1098,31 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
prp_entry_dma += prp_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bump the phys address of the command's data buffer by the
|
||||
* entry_len.
|
||||
*/
|
||||
dma_addr += entry_len;
|
||||
|
||||
/* decrement length accounting for last partial page. */
|
||||
if (entry_len > length)
|
||||
if (entry_len >= length) {
|
||||
length = 0;
|
||||
else
|
||||
} else {
|
||||
if (entry_len <= desc_len) {
|
||||
dma_addr += entry_len;
|
||||
desc_len -= entry_len;
|
||||
}
|
||||
if (!desc_len) {
|
||||
if ((++desc_count) >=
|
||||
drv_buf_iter->num_dma_desc) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s: Invalid len %zd while building PRP\n",
|
||||
__func__, length);
|
||||
goto err_out;
|
||||
}
|
||||
dma_addr =
|
||||
drv_buf_iter->dma_desc[desc_count].dma_addr;
|
||||
desc_len =
|
||||
drv_buf_iter->dma_desc[desc_count].size;
|
||||
}
|
||||
length -= entry_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_out:
|
||||
if (mrioc->prp_list_virt) {
|
||||
@ -919,10 +1132,66 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_map_data_buffer_dma - build dma descriptors for data
|
||||
* buffers
|
||||
* @mrioc: Adapter instance reference
|
||||
* @drv_buf: buffer map descriptor
|
||||
* @desc_count: Number of already consumed dma descriptors
|
||||
*
|
||||
* This function computes how many pre-allocated DMA descriptors
|
||||
* are required for the given data buffer and if those number of
|
||||
* descriptors are free, then setup the mapping of the scattered
|
||||
* DMA address to the given data buffer, if the data direction
|
||||
* of the buffer is DMA_TO_DEVICE then the actual data is copied to
|
||||
* the DMA buffers
|
||||
*
|
||||
* Return: 0 on success, -1 on failure
|
||||
*/
|
||||
static int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_buf_map *drv_buf,
|
||||
u16 desc_count)
|
||||
{
|
||||
u16 i, needed_desc = drv_buf->kern_buf_len / MPI3MR_IOCTL_SGE_SIZE;
|
||||
u32 buf_len = drv_buf->kern_buf_len, copied_len = 0;
|
||||
|
||||
if (drv_buf->kern_buf_len % MPI3MR_IOCTL_SGE_SIZE)
|
||||
needed_desc++;
|
||||
if ((needed_desc + desc_count) > MPI3MR_NUM_IOCTL_SGE) {
|
||||
dprint_bsg_err(mrioc, "%s: DMA descriptor mapping error %d:%d:%d\n",
|
||||
__func__, needed_desc, desc_count, MPI3MR_NUM_IOCTL_SGE);
|
||||
return -1;
|
||||
}
|
||||
drv_buf->dma_desc = kzalloc(sizeof(*drv_buf->dma_desc) * needed_desc,
|
||||
GFP_KERNEL);
|
||||
if (!drv_buf->dma_desc)
|
||||
return -1;
|
||||
for (i = 0; i < needed_desc; i++, desc_count++) {
|
||||
drv_buf->dma_desc[i].addr = mrioc->ioctl_sge[desc_count].addr;
|
||||
drv_buf->dma_desc[i].dma_addr =
|
||||
mrioc->ioctl_sge[desc_count].dma_addr;
|
||||
if (buf_len < mrioc->ioctl_sge[desc_count].size)
|
||||
drv_buf->dma_desc[i].size = buf_len;
|
||||
else
|
||||
drv_buf->dma_desc[i].size =
|
||||
mrioc->ioctl_sge[desc_count].size;
|
||||
buf_len -= drv_buf->dma_desc[i].size;
|
||||
memset(drv_buf->dma_desc[i].addr, 0,
|
||||
mrioc->ioctl_sge[desc_count].size);
|
||||
if (drv_buf->data_dir == DMA_TO_DEVICE) {
|
||||
memcpy(drv_buf->dma_desc[i].addr,
|
||||
drv_buf->bsg_buf + copied_len,
|
||||
drv_buf->dma_desc[i].size);
|
||||
copied_len += drv_buf->dma_desc[i].size;
|
||||
}
|
||||
}
|
||||
drv_buf->num_dma_desc = needed_desc;
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* mpi3mr_bsg_process_mpt_cmds - MPI Pass through BSG handler
|
||||
* @job: BSG job reference
|
||||
* @reply_payload_rcv_len: length of payload recvd
|
||||
*
|
||||
* This function is the top level handler for MPI Pass through
|
||||
* command, this does basic validation of the input data buffers,
|
||||
@ -938,10 +1207,9 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
|
||||
* Return: 0 on success and proper error codes on failure
|
||||
*/
|
||||
|
||||
static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply_payload_rcv_len)
|
||||
static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
|
||||
{
|
||||
long rval = -EINVAL;
|
||||
|
||||
struct mpi3mr_ioc *mrioc = NULL;
|
||||
u8 *mpi_req = NULL, *sense_buff_k = NULL;
|
||||
u8 mpi_msg_size = 0;
|
||||
@ -949,9 +1217,10 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
struct mpi3mr_bsg_mptcmd *karg;
|
||||
struct mpi3mr_buf_entry *buf_entries = NULL;
|
||||
struct mpi3mr_buf_map *drv_bufs = NULL, *drv_buf_iter = NULL;
|
||||
u8 count, bufcnt = 0, is_rmcb = 0, is_rmrb = 0, din_cnt = 0, dout_cnt = 0;
|
||||
u8 invalid_be = 0, erb_offset = 0xFF, mpirep_offset = 0xFF, sg_entries = 0;
|
||||
u8 block_io = 0, resp_code = 0, nvme_fmt = 0;
|
||||
u8 count, bufcnt = 0, is_rmcb = 0, is_rmrb = 0;
|
||||
u8 din_cnt = 0, dout_cnt = 0;
|
||||
u8 invalid_be = 0, erb_offset = 0xFF, mpirep_offset = 0xFF;
|
||||
u8 block_io = 0, nvme_fmt = 0, resp_code = 0;
|
||||
struct mpi3_request_header *mpi_header = NULL;
|
||||
struct mpi3_status_reply_descriptor *status_desc;
|
||||
struct mpi3_scsi_task_mgmt_request *tm_req;
|
||||
@ -963,6 +1232,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
u32 din_size = 0, dout_size = 0;
|
||||
u8 *din_buf = NULL, *dout_buf = NULL;
|
||||
u8 *sgl_iter = NULL, *sgl_din_iter = NULL, *sgl_dout_iter = NULL;
|
||||
u16 rmc_size = 0, desc_count = 0;
|
||||
|
||||
bsg_req = job->request;
|
||||
karg = (struct mpi3mr_bsg_mptcmd *)&bsg_req->cmd.mptcmd;
|
||||
@ -971,6 +1241,12 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
if (!mrioc)
|
||||
return -ENODEV;
|
||||
|
||||
if (!mrioc->ioctl_sges_allocated) {
|
||||
dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (karg->timeout < MPI3MR_APP_DEFAULT_TIMEOUT)
|
||||
karg->timeout = MPI3MR_APP_DEFAULT_TIMEOUT;
|
||||
|
||||
@ -1011,26 +1287,13 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
|
||||
for (count = 0; count < bufcnt; count++, buf_entries++, drv_buf_iter++) {
|
||||
|
||||
if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
|
||||
dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
|
||||
__func__);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
|
||||
dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
|
||||
__func__);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (buf_entries->buf_type) {
|
||||
case MPI3MR_BSG_BUFTYPE_RAIDMGMT_CMD:
|
||||
sgl_iter = sgl_dout_iter;
|
||||
sgl_dout_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_TO_DEVICE;
|
||||
is_rmcb = 1;
|
||||
if (count != 0)
|
||||
if ((count != 0) || !buf_entries->buf_len)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
case MPI3MR_BSG_BUFTYPE_RAIDMGMT_RESP:
|
||||
@ -1038,7 +1301,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
sgl_din_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_FROM_DEVICE;
|
||||
is_rmrb = 1;
|
||||
if (count != 1 || !is_rmcb)
|
||||
if (count != 1 || !is_rmcb || !buf_entries->buf_len)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
case MPI3MR_BSG_BUFTYPE_DATA_IN:
|
||||
@ -1046,7 +1309,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
sgl_din_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_FROM_DEVICE;
|
||||
din_cnt++;
|
||||
din_size += drv_buf_iter->bsg_buf_len;
|
||||
din_size += buf_entries->buf_len;
|
||||
if ((din_cnt > 1) && !is_rmcb)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
@ -1055,7 +1318,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
sgl_dout_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_TO_DEVICE;
|
||||
dout_cnt++;
|
||||
dout_size += drv_buf_iter->bsg_buf_len;
|
||||
dout_size += buf_entries->buf_len;
|
||||
if ((dout_cnt > 1) && !is_rmcb)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
@ -1064,12 +1327,16 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
sgl_din_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_NONE;
|
||||
mpirep_offset = count;
|
||||
if (!buf_entries->buf_len)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
case MPI3MR_BSG_BUFTYPE_ERR_RESPONSE:
|
||||
sgl_iter = sgl_din_iter;
|
||||
sgl_din_iter += buf_entries->buf_len;
|
||||
drv_buf_iter->data_dir = DMA_NONE;
|
||||
erb_offset = count;
|
||||
if (!buf_entries->buf_len)
|
||||
invalid_be = 1;
|
||||
break;
|
||||
case MPI3MR_BSG_BUFTYPE_MPI_REQUEST:
|
||||
sgl_iter = sgl_dout_iter;
|
||||
@ -1096,21 +1363,31 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
goto out;
|
||||
}
|
||||
|
||||
drv_buf_iter->bsg_buf = sgl_iter;
|
||||
drv_buf_iter->bsg_buf_len = buf_entries->buf_len;
|
||||
|
||||
}
|
||||
if (!is_rmcb && (dout_cnt || din_cnt)) {
|
||||
sg_entries = dout_cnt + din_cnt;
|
||||
if (((mpi_msg_size) + (sg_entries *
|
||||
sizeof(struct mpi3_sge_common))) > MPI3MR_ADMIN_REQ_FRAME_SZ) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s:%d: invalid message size passed\n",
|
||||
__func__, __LINE__);
|
||||
if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
|
||||
dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
|
||||
__func__);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
|
||||
dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
|
||||
__func__);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drv_buf_iter->bsg_buf = sgl_iter;
|
||||
drv_buf_iter->bsg_buf_len = buf_entries->buf_len;
|
||||
}
|
||||
|
||||
if (is_rmcb && ((din_size + dout_size) > MPI3MR_MAX_APP_XFER_SIZE)) {
|
||||
dprint_bsg_err(mrioc, "%s:%d: invalid data transfer size passed for function 0x%x din_size = %d, dout_size = %d\n",
|
||||
__func__, __LINE__, mpi_header->function, din_size,
|
||||
dout_size);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (din_size > MPI3MR_MAX_APP_XFER_SIZE) {
|
||||
dprint_bsg_err(mrioc,
|
||||
"%s:%d: invalid data transfer size passed for function 0x%x din_size=%d\n",
|
||||
@ -1126,30 +1403,64 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mpi_header->function == MPI3_BSG_FUNCTION_SMP_PASSTHROUGH) {
|
||||
if (din_size > MPI3MR_IOCTL_SGE_SIZE ||
|
||||
dout_size > MPI3MR_IOCTL_SGE_SIZE) {
|
||||
dprint_bsg_err(mrioc, "%s:%d: invalid message size passed:%d:%d:%d:%d\n",
|
||||
__func__, __LINE__, din_cnt, dout_cnt, din_size,
|
||||
dout_size);
|
||||
rval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
drv_buf_iter = drv_bufs;
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE)
|
||||
continue;
|
||||
|
||||
drv_buf_iter->kern_buf_len = drv_buf_iter->bsg_buf_len;
|
||||
if (is_rmcb && !count)
|
||||
drv_buf_iter->kern_buf_len += ((dout_cnt + din_cnt) *
|
||||
sizeof(struct mpi3_sge_common));
|
||||
|
||||
if (!drv_buf_iter->kern_buf_len)
|
||||
continue;
|
||||
|
||||
drv_buf_iter->kern_buf = dma_alloc_coherent(&mrioc->pdev->dev,
|
||||
drv_buf_iter->kern_buf_len, &drv_buf_iter->kern_buf_dma,
|
||||
GFP_KERNEL);
|
||||
if (!drv_buf_iter->kern_buf) {
|
||||
rval = -ENOMEM;
|
||||
if (is_rmcb && !count) {
|
||||
drv_buf_iter->kern_buf_len =
|
||||
mrioc->ioctl_chain_sge.size;
|
||||
drv_buf_iter->kern_buf =
|
||||
mrioc->ioctl_chain_sge.addr;
|
||||
drv_buf_iter->kern_buf_dma =
|
||||
mrioc->ioctl_chain_sge.dma_addr;
|
||||
drv_buf_iter->dma_desc = NULL;
|
||||
drv_buf_iter->num_dma_desc = 0;
|
||||
memset(drv_buf_iter->kern_buf, 0,
|
||||
drv_buf_iter->kern_buf_len);
|
||||
tmplen = min(drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->bsg_buf_len);
|
||||
rmc_size = tmplen;
|
||||
memcpy(drv_buf_iter->kern_buf, drv_buf_iter->bsg_buf, tmplen);
|
||||
} else if (is_rmrb && (count == 1)) {
|
||||
drv_buf_iter->kern_buf_len =
|
||||
mrioc->ioctl_resp_sge.size;
|
||||
drv_buf_iter->kern_buf =
|
||||
mrioc->ioctl_resp_sge.addr;
|
||||
drv_buf_iter->kern_buf_dma =
|
||||
mrioc->ioctl_resp_sge.dma_addr;
|
||||
drv_buf_iter->dma_desc = NULL;
|
||||
drv_buf_iter->num_dma_desc = 0;
|
||||
memset(drv_buf_iter->kern_buf, 0,
|
||||
drv_buf_iter->kern_buf_len);
|
||||
tmplen = min(drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->bsg_buf_len);
|
||||
drv_buf_iter->kern_buf_len = tmplen;
|
||||
memset(drv_buf_iter->bsg_buf, 0,
|
||||
drv_buf_iter->bsg_buf_len);
|
||||
} else {
|
||||
if (!drv_buf_iter->kern_buf_len)
|
||||
continue;
|
||||
if (mpi3mr_map_data_buffer_dma(mrioc, drv_buf_iter, desc_count)) {
|
||||
rval = -ENOMEM;
|
||||
dprint_bsg_err(mrioc, "%s:%d: mapping data buffers failed\n",
|
||||
__func__, __LINE__);
|
||||
goto out;
|
||||
}
|
||||
if (drv_buf_iter->data_dir == DMA_TO_DEVICE) {
|
||||
tmplen = min(drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->bsg_buf_len);
|
||||
memcpy(drv_buf_iter->kern_buf, drv_buf_iter->bsg_buf, tmplen);
|
||||
desc_count += drv_buf_iter->num_dma_desc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1219,9 +1530,14 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
mpi3mr_bsg_build_sgl(mpi_req, (mpi_msg_size),
|
||||
drv_bufs, bufcnt, is_rmcb, is_rmrb,
|
||||
(dout_cnt + din_cnt));
|
||||
if (mpi3mr_bsg_build_sgl(mrioc, mpi_req, mpi_msg_size,
|
||||
drv_bufs, bufcnt, is_rmcb, is_rmrb,
|
||||
(dout_cnt + din_cnt))) {
|
||||
dprint_bsg_err(mrioc, "%s: sgl build failed\n", __func__);
|
||||
rval = -EAGAIN;
|
||||
mutex_unlock(&mrioc->bsg_cmds.mutex);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (mpi_header->function == MPI3_BSG_FUNCTION_SCSI_TASK_MGMT) {
|
||||
@ -1257,7 +1573,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
if (mpi_header->function == MPI3_BSG_FUNCTION_MGMT_PASSTHROUGH) {
|
||||
drv_buf_iter = &drv_bufs[0];
|
||||
dprint_dump(drv_buf_iter->kern_buf,
|
||||
drv_buf_iter->kern_buf_len, "mpi3_mgmt_req");
|
||||
rmc_size, "mpi3_mgmt_req");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1292,10 +1608,9 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
MPI3_BSG_FUNCTION_MGMT_PASSTHROUGH) {
|
||||
drv_buf_iter = &drv_bufs[0];
|
||||
dprint_dump(drv_buf_iter->kern_buf,
|
||||
drv_buf_iter->kern_buf_len, "mpi3_mgmt_req");
|
||||
rmc_size, "mpi3_mgmt_req");
|
||||
}
|
||||
}
|
||||
|
||||
if ((mpi_header->function == MPI3_BSG_FUNCTION_NVME_ENCAPSULATED) ||
|
||||
(mpi_header->function == MPI3_BSG_FUNCTION_SCSI_IO))
|
||||
mpi3mr_issue_tm(mrioc,
|
||||
@ -1366,17 +1681,27 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->data_dir == DMA_NONE)
|
||||
continue;
|
||||
if (drv_buf_iter->data_dir == DMA_FROM_DEVICE) {
|
||||
tmplen = min(drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->bsg_buf_len);
|
||||
if ((count == 1) && is_rmrb) {
|
||||
memcpy(drv_buf_iter->bsg_buf,
|
||||
drv_buf_iter->kern_buf, tmplen);
|
||||
drv_buf_iter->kern_buf,
|
||||
drv_buf_iter->kern_buf_len);
|
||||
} else if (drv_buf_iter->data_dir == DMA_FROM_DEVICE) {
|
||||
tmplen = 0;
|
||||
for (desc_count = 0;
|
||||
desc_count < drv_buf_iter->num_dma_desc;
|
||||
desc_count++) {
|
||||
memcpy(((u8 *)drv_buf_iter->bsg_buf + tmplen),
|
||||
drv_buf_iter->dma_desc[desc_count].addr,
|
||||
drv_buf_iter->dma_desc[desc_count].size);
|
||||
tmplen +=
|
||||
drv_buf_iter->dma_desc[desc_count].size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
if (din_buf) {
|
||||
*reply_payload_rcv_len =
|
||||
job->reply_payload_rcv_len =
|
||||
sg_copy_from_buffer(job->reply_payload.sg_list,
|
||||
job->reply_payload.sg_cnt,
|
||||
din_buf, job->reply_payload.payload_len);
|
||||
@ -1392,13 +1717,8 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
|
||||
kfree(mpi_req);
|
||||
if (drv_bufs) {
|
||||
drv_buf_iter = drv_bufs;
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
|
||||
if (drv_buf_iter->kern_buf && drv_buf_iter->kern_buf_dma)
|
||||
dma_free_coherent(&mrioc->pdev->dev,
|
||||
drv_buf_iter->kern_buf_len,
|
||||
drv_buf_iter->kern_buf,
|
||||
drv_buf_iter->kern_buf_dma);
|
||||
}
|
||||
for (count = 0; count < bufcnt; count++, drv_buf_iter++)
|
||||
kfree(drv_buf_iter->dma_desc);
|
||||
kfree(drv_bufs);
|
||||
}
|
||||
kfree(bsg_reply_buf);
|
||||
@ -1457,7 +1777,7 @@ static int mpi3mr_bsg_request(struct bsg_job *job)
|
||||
rval = mpi3mr_bsg_process_drv_cmds(job);
|
||||
break;
|
||||
case MPI3MR_MPT_CMD:
|
||||
rval = mpi3mr_bsg_process_mpt_cmds(job, &reply_payload_rcv_len);
|
||||
rval = mpi3mr_bsg_process_mpt_cmds(job);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unsupported BSG command(0x%08x)\n",
|
||||
|
@ -1058,6 +1058,114 @@ enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc)
|
||||
return MRIOC_STATE_RESET_REQUESTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Free the DMA memory allocated for IOCTL handling purpose.
|
||||
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct dma_memory_desc *mem_desc;
|
||||
u16 i;
|
||||
|
||||
if (!mrioc->ioctl_dma_pool)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MPI3MR_NUM_IOCTL_SGE; i++) {
|
||||
mem_desc = &mrioc->ioctl_sge[i];
|
||||
if (mem_desc->addr) {
|
||||
dma_pool_free(mrioc->ioctl_dma_pool,
|
||||
mem_desc->addr,
|
||||
mem_desc->dma_addr);
|
||||
mem_desc->addr = NULL;
|
||||
}
|
||||
}
|
||||
dma_pool_destroy(mrioc->ioctl_dma_pool);
|
||||
mrioc->ioctl_dma_pool = NULL;
|
||||
mem_desc = &mrioc->ioctl_chain_sge;
|
||||
|
||||
if (mem_desc->addr) {
|
||||
dma_free_coherent(&mrioc->pdev->dev, mem_desc->size,
|
||||
mem_desc->addr, mem_desc->dma_addr);
|
||||
mem_desc->addr = NULL;
|
||||
}
|
||||
mem_desc = &mrioc->ioctl_resp_sge;
|
||||
if (mem_desc->addr) {
|
||||
dma_free_coherent(&mrioc->pdev->dev, mem_desc->size,
|
||||
mem_desc->addr, mem_desc->dma_addr);
|
||||
mem_desc->addr = NULL;
|
||||
}
|
||||
|
||||
mrioc->ioctl_sges_allocated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma
|
||||
* @mrioc: Adapter instance reference
|
||||
|
||||
*
|
||||
* This function allocates dmaable memory required to handle the
|
||||
* application issued MPI3 IOCTL requests.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_ioc *mrioc)
|
||||
|
||||
{
|
||||
struct dma_memory_desc *mem_desc;
|
||||
u16 i;
|
||||
|
||||
mrioc->ioctl_dma_pool = dma_pool_create("ioctl dma pool",
|
||||
&mrioc->pdev->dev,
|
||||
MPI3MR_IOCTL_SGE_SIZE,
|
||||
MPI3MR_PAGE_SIZE_4K, 0);
|
||||
|
||||
if (!mrioc->ioctl_dma_pool) {
|
||||
ioc_err(mrioc, "ioctl_dma_pool: dma_pool_create failed\n");
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < MPI3MR_NUM_IOCTL_SGE; i++) {
|
||||
mem_desc = &mrioc->ioctl_sge[i];
|
||||
mem_desc->size = MPI3MR_IOCTL_SGE_SIZE;
|
||||
mem_desc->addr = dma_pool_zalloc(mrioc->ioctl_dma_pool,
|
||||
GFP_KERNEL,
|
||||
&mem_desc->dma_addr);
|
||||
if (!mem_desc->addr)
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
mem_desc = &mrioc->ioctl_chain_sge;
|
||||
mem_desc->size = MPI3MR_PAGE_SIZE_4K;
|
||||
mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev,
|
||||
mem_desc->size,
|
||||
&mem_desc->dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!mem_desc->addr)
|
||||
goto out_failed;
|
||||
|
||||
mem_desc = &mrioc->ioctl_resp_sge;
|
||||
mem_desc->size = MPI3MR_PAGE_SIZE_4K;
|
||||
mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev,
|
||||
mem_desc->size,
|
||||
&mem_desc->dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!mem_desc->addr)
|
||||
goto out_failed;
|
||||
|
||||
mrioc->ioctl_sges_allocated = true;
|
||||
|
||||
return;
|
||||
out_failed:
|
||||
ioc_warn(mrioc, "cannot allocate DMA memory for the mpt commands\n"
|
||||
"from the applications, application interface for MPT command is disabled\n");
|
||||
mpi3mr_free_ioctl_dma_memory(mrioc);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_clear_reset_history - clear reset history
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -1892,7 +2000,8 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
|
||||
|
||||
reply_qid = qidx + 1;
|
||||
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
|
||||
if (!mrioc->pdev->revision)
|
||||
if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) &&
|
||||
!mrioc->pdev->revision)
|
||||
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
|
||||
op_reply_q->ci = 0;
|
||||
op_reply_q->ephase = 1;
|
||||
@ -3193,6 +3302,9 @@ static int mpi3mr_issue_iocinit(struct mpi3mr_ioc *mrioc)
|
||||
current_time = ktime_get_real();
|
||||
iocinit_req.time_stamp = cpu_to_le64(ktime_to_ms(current_time));
|
||||
|
||||
iocinit_req.msg_flags |=
|
||||
MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED;
|
||||
|
||||
init_completion(&mrioc->init_cmds.done);
|
||||
retval = mpi3mr_admin_request_post(mrioc, &iocinit_req,
|
||||
sizeof(iocinit_req), 1);
|
||||
@ -3870,6 +3982,9 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
||||
}
|
||||
}
|
||||
|
||||
dprint_init(mrioc, "allocating ioctl dma buffers\n");
|
||||
mpi3mr_alloc_ioctl_dma_memory(mrioc);
|
||||
|
||||
if (!mrioc->init_cmds.reply) {
|
||||
retval = mpi3mr_alloc_reply_sense_bufs(mrioc);
|
||||
if (retval) {
|
||||
@ -4289,6 +4404,7 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
|
||||
struct mpi3mr_intr_info *intr_info;
|
||||
|
||||
mpi3mr_free_enclosure_list(mrioc);
|
||||
mpi3mr_free_ioctl_dma_memory(mrioc);
|
||||
|
||||
if (mrioc->sense_buf_pool) {
|
||||
if (mrioc->sense_buf)
|
||||
|
@ -1047,8 +1047,9 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc)
|
||||
list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list,
|
||||
list) {
|
||||
if ((tgtdev->dev_handle == MPI3MR_INVALID_DEV_HANDLE) &&
|
||||
tgtdev->host_exposed && tgtdev->starget &&
|
||||
tgtdev->starget->hostdata) {
|
||||
tgtdev->is_hidden &&
|
||||
tgtdev->host_exposed && tgtdev->starget &&
|
||||
tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
tgt_priv->dev_removed = 1;
|
||||
atomic_set(&tgt_priv->block_io, 0);
|
||||
@ -1064,14 +1065,24 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc)
|
||||
mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
|
||||
mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, true);
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
} else if (tgtdev->is_hidden & tgtdev->host_exposed) {
|
||||
dprint_reset(mrioc, "hiding target device with perst_id(%d)\n",
|
||||
tgtdev->perst_id);
|
||||
mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
|
||||
}
|
||||
}
|
||||
|
||||
tgtdev = NULL;
|
||||
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
|
||||
if ((tgtdev->dev_handle != MPI3MR_INVALID_DEV_HANDLE) &&
|
||||
!tgtdev->is_hidden && !tgtdev->host_exposed)
|
||||
mpi3mr_report_tgtdev_to_host(mrioc, tgtdev->perst_id);
|
||||
!tgtdev->is_hidden) {
|
||||
if (!tgtdev->host_exposed)
|
||||
mpi3mr_report_tgtdev_to_host(mrioc,
|
||||
tgtdev->perst_id);
|
||||
else if (tgtdev->starget)
|
||||
starget_for_each_device(tgtdev->starget,
|
||||
(void *)tgtdev, mpi3mr_update_sdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3194,6 +3205,7 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
tg = stgt_priv_data->throttle_group;
|
||||
throttle_enabled_dev =
|
||||
stgt_priv_data->io_throttle_enabled;
|
||||
dev_handle = stgt_priv_data->dev_handle;
|
||||
}
|
||||
}
|
||||
if (unlikely((data_len_blks >= mrioc->io_throttle_data_length) &&
|
||||
@ -5101,7 +5113,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
mpi3mr_init_drv_cmd(&mrioc->evtack_cmds[i],
|
||||
MPI3MR_HOSTTAG_EVTACKCMD_MIN + i);
|
||||
|
||||
if (pdev->revision)
|
||||
if ((pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) &&
|
||||
!pdev->revision)
|
||||
mrioc->enable_segqueue = false;
|
||||
else
|
||||
mrioc->enable_segqueue = true;
|
||||
|
||||
init_waitqueue_head(&mrioc->reset_waitq);
|
||||
@ -5430,6 +5445,14 @@ static const struct pci_device_id mpi3mr_pci_id_table[] = {
|
||||
PCI_DEVICE_SUB(MPI3_MFGPAGE_VENDORID_BROADCOM,
|
||||
MPI3_MFGPAGE_DEVID_SAS4116, PCI_ANY_ID, PCI_ANY_ID)
|
||||
},
|
||||
{
|
||||
PCI_DEVICE_SUB(MPI3_MFGPAGE_VENDORID_BROADCOM,
|
||||
MPI3_MFGPAGE_DEVID_SAS5116_MPI, PCI_ANY_ID, PCI_ANY_ID)
|
||||
},
|
||||
{
|
||||
PCI_DEVICE_SUB(MPI3_MFGPAGE_VENDORID_BROADCOM,
|
||||
MPI3_MFGPAGE_DEVID_SAS5116_MPI_MGMT, PCI_ANY_ID, PCI_ANY_ID)
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table);
|
||||
|
@ -1587,7 +1587,7 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
|
||||
*/
|
||||
struct host_port {
|
||||
u64 sas_address;
|
||||
u32 phy_mask;
|
||||
u64 phy_mask;
|
||||
u16 handle;
|
||||
u8 iounit_port_id;
|
||||
u8 used;
|
||||
@ -1611,7 +1611,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
|
||||
struct mpi3mr_sas_port *mr_sas_port)
|
||||
{
|
||||
struct mpi3mr_sas_phy *mr_sas_phy;
|
||||
u32 phy_mask_xor;
|
||||
u64 phy_mask_xor;
|
||||
u64 phys_to_be_added, phys_to_be_removed;
|
||||
int i;
|
||||
|
||||
@ -1619,7 +1619,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
|
||||
mr_sas_port->marked_responding = 1;
|
||||
|
||||
dev_info(&mr_sas_port->port->dev,
|
||||
"sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n",
|
||||
"sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
|
||||
mr_sas_port->remote_identify.sas_address,
|
||||
mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
|
||||
h_port->iounit_port_id, h_port->phy_mask);
|
||||
@ -1637,7 +1637,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
|
||||
* if these phys are previously registered with another port
|
||||
* then delete these phys from that port first.
|
||||
*/
|
||||
for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) {
|
||||
for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
|
||||
mr_sas_phy = &mrioc->sas_hba.phy[i];
|
||||
if (mr_sas_phy->phy_belongs_to_port)
|
||||
mpi3mr_del_phy_from_an_existing_port(mrioc,
|
||||
@ -1649,7 +1649,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
|
||||
}
|
||||
|
||||
/* Delete the phys which are not part of current mr_sas_port's port. */
|
||||
for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) {
|
||||
for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
|
||||
mr_sas_phy = &mrioc->sas_hba.phy[i];
|
||||
if (mr_sas_phy->phy_belongs_to_port)
|
||||
mpi3mr_del_phy_from_an_existing_port(mrioc,
|
||||
@ -1671,7 +1671,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
|
||||
void
|
||||
mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct host_port h_port[32];
|
||||
struct host_port h_port[64];
|
||||
int i, j, found, host_port_count = 0, port_idx;
|
||||
u16 sz, attached_handle, ioc_status;
|
||||
struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
|
||||
@ -1742,7 +1742,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
|
||||
list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
|
||||
port_list) {
|
||||
ioc_info(mrioc,
|
||||
"port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
|
||||
"port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
|
||||
mr_sas_port->hba_port->port_id,
|
||||
mr_sas_port->remote_identify.sas_address,
|
||||
mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
|
||||
@ -1751,7 +1751,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
|
||||
ioc_info(mrioc, "Host port details after reset\n");
|
||||
for (i = 0; i < host_port_count; i++) {
|
||||
ioc_info(mrioc,
|
||||
"port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
|
||||
"port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
|
||||
h_port[i].iounit_port_id, h_port[i].sas_address,
|
||||
h_port[i].phy_mask, h_port[i].lowest_phy);
|
||||
}
|
||||
|
@ -643,18 +643,14 @@ typedef struct _MPI2_CHIP_REVISION_ID {
|
||||
/*Manufacturing Page 2 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check Header.PageLength at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check Header.PageLength at
|
||||
*runtime before using HwSettings[].
|
||||
*/
|
||||
#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
|
||||
#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
|
||||
U32
|
||||
HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */
|
||||
U32 HwSettings[]; /*0x08 */
|
||||
} MPI2_CONFIG_PAGE_MAN_2,
|
||||
*PTR_MPI2_CONFIG_PAGE_MAN_2,
|
||||
Mpi2ManufacturingPage2_t,
|
||||
@ -666,18 +662,14 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
|
||||
/*Manufacturing Page 3 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check Header.PageLength at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check Header.PageLength at
|
||||
*runtime before using Info[].
|
||||
*/
|
||||
#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
|
||||
#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_MAN_3 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
|
||||
U32
|
||||
Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */
|
||||
U32 Info[]; /*0x08 */
|
||||
} MPI2_CONFIG_PAGE_MAN_3,
|
||||
*PTR_MPI2_CONFIG_PAGE_MAN_3,
|
||||
Mpi2ManufacturingPage3_t,
|
||||
@ -765,12 +757,9 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_4 {
|
||||
/*Manufacturing Page 5 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using Phy[].
|
||||
*/
|
||||
#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
|
||||
#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_MANUFACTURING5_ENTRY {
|
||||
U64 WWID; /*0x00 */
|
||||
@ -787,8 +776,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_5 {
|
||||
U16 Reserved2; /*0x06 */
|
||||
U32 Reserved3; /*0x08 */
|
||||
U32 Reserved4; /*0x0C */
|
||||
MPI2_MANUFACTURING5_ENTRY
|
||||
Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */
|
||||
MPI2_MANUFACTURING5_ENTRY Phy[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_MAN_5,
|
||||
*PTR_MPI2_CONFIG_PAGE_MAN_5,
|
||||
Mpi2ManufacturingPage5_t,
|
||||
@ -864,12 +852,9 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
|
||||
#define MPI2_MANPAGE7_SLOT_UNKNOWN (0xFFFF)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using ConnectorInfo[].
|
||||
*/
|
||||
#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
|
||||
#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -880,8 +865,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
|
||||
U8 NumPhys; /*0x20 */
|
||||
U8 Reserved3; /*0x21 */
|
||||
U16 Reserved4; /*0x22 */
|
||||
MPI2_MANPAGE7_CONNECTOR_INFO
|
||||
ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */
|
||||
MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[]; /*0x24 */
|
||||
} MPI2_CONFIG_PAGE_MAN_7,
|
||||
*PTR_MPI2_CONFIG_PAGE_MAN_7,
|
||||
Mpi2ManufacturingPage7_t,
|
||||
@ -990,7 +974,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for GPIOCount at runtime.
|
||||
*36 and check the value returned for GPIOCount at runtime.
|
||||
*/
|
||||
#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
|
||||
#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (36)
|
||||
@ -1019,12 +1003,9 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
|
||||
/*IO Unit Page 5 */
|
||||
|
||||
/*
|
||||
*Upper layer code (drivers, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumDmaEngines at runtime.
|
||||
*Upper layer code (drivers, utilities, etc.) should check the value returned
|
||||
*for NumDmaEngines at runtime before using DmaEngineCapabilities[].
|
||||
*/
|
||||
#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
|
||||
#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -1042,7 +1023,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
|
||||
U32 Reserved2; /*0x24 */
|
||||
U32 Reserved3; /*0x28 */
|
||||
U32
|
||||
DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */
|
||||
DmaEngineCapabilities[]; /*0x2C */
|
||||
} MPI2_CONFIG_PAGE_IO_UNIT_5,
|
||||
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
|
||||
Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t;
|
||||
@ -1219,12 +1200,9 @@ typedef struct _MPI2_IOUNIT8_SENSOR {
|
||||
#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumSensors at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumSensors at runtime before using Sensor[].
|
||||
*/
|
||||
#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
|
||||
#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -1233,8 +1211,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
|
||||
U8 NumSensors; /*0x0C */
|
||||
U8 PollingInterval; /*0x0D */
|
||||
U16 Reserved3; /*0x0E */
|
||||
MPI2_IOUNIT8_SENSOR
|
||||
Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */
|
||||
MPI2_IOUNIT8_SENSOR Sensor[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_IO_UNIT_8,
|
||||
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
|
||||
Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t;
|
||||
@ -1259,12 +1236,9 @@ typedef struct _MPI2_IOUNIT9_SENSOR {
|
||||
#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumSensors at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumSensors at runtime before using Sensor[].
|
||||
*/
|
||||
#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
|
||||
#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -1273,8 +1247,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
|
||||
U8 NumSensors; /*0x0C */
|
||||
U8 Reserved4; /*0x0D */
|
||||
U16 Reserved3; /*0x0E */
|
||||
MPI2_IOUNIT9_SENSOR
|
||||
Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */
|
||||
MPI2_IOUNIT9_SENSOR Sensor[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_IO_UNIT_9,
|
||||
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
|
||||
Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t;
|
||||
@ -1294,12 +1267,9 @@ typedef struct _MPI2_IOUNIT10_FUNCTION {
|
||||
*pMpi2IOUnit10Function_t;
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumFunctions at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumFunctions at runtime before using Function[].
|
||||
*/
|
||||
#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
|
||||
#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -1308,8 +1278,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
|
||||
U16 Reserved2; /*0x06 */
|
||||
U32 Reserved3; /*0x08 */
|
||||
U32 Reserved4; /*0x0C */
|
||||
MPI2_IOUNIT10_FUNCTION
|
||||
Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */
|
||||
MPI2_IOUNIT10_FUNCTION Function[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_IO_UNIT_10,
|
||||
*PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
|
||||
Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t;
|
||||
@ -1764,12 +1733,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_3 {
|
||||
/*BIOS Page 4 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using Phy[].
|
||||
*/
|
||||
#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
|
||||
#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_BIOS4_ENTRY {
|
||||
U64 ReassignmentWWID; /*0x00 */
|
||||
@ -1782,8 +1748,7 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_4 {
|
||||
U8 NumPhys; /*0x04 */
|
||||
U8 Reserved1; /*0x05 */
|
||||
U16 Reserved2; /*0x06 */
|
||||
MPI2_BIOS4_ENTRY
|
||||
Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /*0x08 */
|
||||
MPI2_BIOS4_ENTRY Phy[]; /*0x08 */
|
||||
} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4,
|
||||
Mpi2BiosPage4_t, *pMpi2BiosPage4_t;
|
||||
|
||||
@ -1836,12 +1801,9 @@ typedef struct _MPI2_RAIDVOL0_SETTINGS {
|
||||
#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhysDisks at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhysDisks at runtime before using PhysDisk[].
|
||||
*/
|
||||
#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
|
||||
#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
|
||||
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
|
||||
@ -1861,8 +1823,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
|
||||
U8 Reserved2; /*0x25 */
|
||||
U8 Reserved3; /*0x26 */
|
||||
U8 InactiveStatus; /*0x27 */
|
||||
MPI2_RAIDVOL0_PHYS_DISK
|
||||
PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */
|
||||
MPI2_RAIDVOL0_PHYS_DISK PhysDisk[]; /*0x28 */
|
||||
} MPI2_CONFIG_PAGE_RAID_VOL_0,
|
||||
*PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
|
||||
Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t;
|
||||
@ -2045,12 +2006,9 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 {
|
||||
/*RAID Physical Disk Page 1 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhysDiskPaths at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhysDiskPaths at runtime before using PhysicalDiskPath[].
|
||||
*/
|
||||
#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
|
||||
#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_RAIDPHYSDISK1_PATH {
|
||||
U16 DevHandle; /*0x00 */
|
||||
@ -2075,8 +2033,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
|
||||
U8 PhysDiskNum; /*0x05 */
|
||||
U16 Reserved1; /*0x06 */
|
||||
U32 Reserved2; /*0x08 */
|
||||
MPI2_RAIDPHYSDISK1_PATH
|
||||
PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */
|
||||
MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[]; /*0x0C */
|
||||
} MPI2_CONFIG_PAGE_RD_PDISK_1,
|
||||
*PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
|
||||
Mpi2RaidPhysDiskPage1_t,
|
||||
@ -2221,12 +2178,9 @@ typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA {
|
||||
*pMpi2SasIOUnit0PhyData_t;
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using PhyData[].
|
||||
*/
|
||||
#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
|
||||
#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -2234,8 +2188,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
|
||||
U8 NumPhys; /*0x0C */
|
||||
U8 Reserved2;/*0x0D */
|
||||
U16 Reserved3;/*0x0E */
|
||||
MPI2_SAS_IO_UNIT0_PHY_DATA
|
||||
PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /*0x10 */
|
||||
MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[];/*0x10 */
|
||||
} MPI2_CONFIG_PAGE_SASIOUNIT_0,
|
||||
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
|
||||
Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t;
|
||||
@ -2296,12 +2249,9 @@ typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA {
|
||||
*pMpi2SasIOUnit1PhyData_t;
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using PhyData[].
|
||||
*/
|
||||
#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
|
||||
#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -2322,7 +2272,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
|
||||
U8
|
||||
IODeviceMissingDelay; /*0x13 */
|
||||
MPI2_SAS_IO_UNIT1_PHY_DATA
|
||||
PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /*0x14 */
|
||||
PhyData[]; /*0x14 */
|
||||
} MPI2_CONFIG_PAGE_SASIOUNIT_1,
|
||||
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
|
||||
Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t;
|
||||
@ -2502,12 +2452,9 @@ typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
|
||||
#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using SASPhyPowerManagementSettings[].
|
||||
*/
|
||||
#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
|
||||
#define MPI2_SAS_IOUNIT5_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -2516,7 +2463,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
|
||||
U16 Reserved2;/*0x0A */
|
||||
U32 Reserved3;/*0x0C */
|
||||
MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS
|
||||
SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */
|
||||
SASPhyPowerManagementSettings[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_SASIOUNIT_5,
|
||||
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
|
||||
Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t;
|
||||
@ -2554,12 +2501,9 @@ typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
|
||||
#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumGroups at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumGroups at runtime before using PortWidthModulationGroupStatus[].
|
||||
*/
|
||||
#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
|
||||
#define MPI2_SAS_IOUNIT6_GROUP_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -2569,7 +2513,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
|
||||
U8 Reserved3; /*0x11 */
|
||||
U16 Reserved4; /*0x12 */
|
||||
MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
|
||||
PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */
|
||||
PortWidthModulationGroupStatus[]; /*0x14 */
|
||||
} MPI2_CONFIG_PAGE_SASIOUNIT_6,
|
||||
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
|
||||
Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t;
|
||||
@ -2597,12 +2541,9 @@ typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
|
||||
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumGroups at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumGroups at runtime before using PortWidthModulationGroupSettings[].
|
||||
*/
|
||||
#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
|
||||
#define MPI2_SAS_IOUNIT7_GROUP_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -2615,7 +2556,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
|
||||
U8 Reserved4; /*0x15 */
|
||||
U16 Reserved5; /*0x16 */
|
||||
MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
|
||||
PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */
|
||||
PortWidthModulationGroupSettings[]; /*0x18 */
|
||||
} MPI2_CONFIG_PAGE_SASIOUNIT_7,
|
||||
*PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
|
||||
Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t;
|
||||
@ -3086,12 +3027,9 @@ typedef struct _MPI2_SASPHY2_PHY_EVENT {
|
||||
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhyEvents at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhyEvents at runtime before using PhyEvent[].
|
||||
*/
|
||||
#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
|
||||
#define MPI2_SASPHY2_PHY_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER
|
||||
@ -3105,7 +3043,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
|
||||
U16
|
||||
Reserved3; /*0x0E */
|
||||
MPI2_SASPHY2_PHY_EVENT
|
||||
PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */
|
||||
PhyEvent[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_SAS_PHY_2,
|
||||
*PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
|
||||
Mpi2SasPhyPage2_t,
|
||||
@ -3200,12 +3138,9 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
|
||||
#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhyEvents at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhyEvents at runtime before using PhyEventConfig[].
|
||||
*/
|
||||
#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
|
||||
#define MPI2_SASPHY3_PHY_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER
|
||||
@ -3219,7 +3154,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
|
||||
U16
|
||||
Reserved3; /*0x0E */
|
||||
MPI2_SASPHY3_PHY_EVENT_CONFIG
|
||||
PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */
|
||||
PhyEventConfig[]; /*0x10 */
|
||||
} MPI2_CONFIG_PAGE_SAS_PHY_3,
|
||||
*PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
|
||||
Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t;
|
||||
@ -3358,12 +3293,9 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
|
||||
/*Log Page 0 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumLogEntries at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumLogEntries at runtime before using LogEntry[].
|
||||
*/
|
||||
#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
|
||||
#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
|
||||
#endif
|
||||
|
||||
#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
|
||||
|
||||
@ -3393,8 +3325,7 @@ typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
|
||||
U32 Reserved2; /*0x0C */
|
||||
U16 NumLogEntries;/*0x10 */
|
||||
U16 Reserved3; /*0x12 */
|
||||
MPI2_LOG_0_ENTRY
|
||||
LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */
|
||||
MPI2_LOG_0_ENTRY LogEntry[]; /*0x14 */
|
||||
} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0,
|
||||
Mpi2LogPage0_t, *pMpi2LogPage0_t;
|
||||
|
||||
@ -3408,12 +3339,9 @@ typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
|
||||
/*RAID Page 0 */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumElements at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumElements at runtime before using ConfigElement[].
|
||||
*/
|
||||
#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
|
||||
#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT {
|
||||
U16 ElementFlags; /*0x00 */
|
||||
@ -3446,8 +3374,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 {
|
||||
U8 NumElements; /*0x2C */
|
||||
U8 Reserved2; /*0x2D */
|
||||
U16 Reserved3; /*0x2E */
|
||||
MPI2_RAIDCONFIG0_CONFIG_ELEMENT
|
||||
ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */
|
||||
MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[];/*0x30 */
|
||||
} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
|
||||
*PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
|
||||
Mpi2RaidConfigurationPage0_t,
|
||||
@ -3687,12 +3614,9 @@ typedef struct _MPI26_PCIE_IO_UNIT0_PHY_DATA {
|
||||
Mpi26PCIeIOUnit0PhyData_t, *pMpi26PCIeIOUnit0PhyData_t;
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using PhyData[].
|
||||
*/
|
||||
#ifndef MPI26_PCIE_IOUNIT0_PHY_MAX
|
||||
#define MPI26_PCIE_IOUNIT0_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -3701,7 +3625,7 @@ typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0 {
|
||||
U8 InitStatus; /*0x0D */
|
||||
U16 Reserved3; /*0x0E */
|
||||
MPI26_PCIE_IO_UNIT0_PHY_DATA
|
||||
PhyData[MPI26_PCIE_IOUNIT0_PHY_MAX]; /*0x10 */
|
||||
PhyData[]; /*0x10 */
|
||||
} MPI26_CONFIG_PAGE_PIOUNIT_0,
|
||||
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_0,
|
||||
Mpi26PCIeIOUnitPage0_t, *pMpi26PCIeIOUnitPage0_t;
|
||||
@ -3744,12 +3668,9 @@ typedef struct _MPI26_PCIE_IO_UNIT1_PHY_DATA {
|
||||
#define MPI26_PCIEIOUNIT1_LINKFLAGS_SRNS_EN (0x02)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumPhys at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumPhys at runtime before using PhyData[].
|
||||
*/
|
||||
#ifndef MPI26_PCIE_IOUNIT1_PHY_MAX
|
||||
#define MPI26_PCIE_IOUNIT1_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -3761,7 +3682,7 @@ typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
|
||||
U8 DMDReportPCIe; /*0x11 */
|
||||
U16 Reserved2; /*0x12 */
|
||||
MPI26_PCIE_IO_UNIT1_PHY_DATA
|
||||
PhyData[MPI26_PCIE_IOUNIT1_PHY_MAX];/*0x14 */
|
||||
PhyData[]; /*0x14 */
|
||||
} MPI26_CONFIG_PAGE_PIOUNIT_1,
|
||||
*PTR_MPI26_CONFIG_PAGE_PIOUNIT_1,
|
||||
Mpi26PCIeIOUnitPage1_t, *pMpi26PCIeIOUnitPage1_t;
|
||||
@ -3993,12 +3914,9 @@ typedef struct _MPI26_PCIELINK2_LINK_EVENT {
|
||||
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumLinkEvents at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumLinkEvents at runtime before using LinkEvent[].
|
||||
*/
|
||||
#ifndef MPI26_PCIELINK2_LINK_EVENT_MAX
|
||||
#define MPI26_PCIELINK2_LINK_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -4009,7 +3927,7 @@ typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2 {
|
||||
U8 Reserved3; /*0x0D */
|
||||
U16 Reserved4; /*0x0E */
|
||||
MPI26_PCIELINK2_LINK_EVENT
|
||||
LinkEvent[MPI26_PCIELINK2_LINK_EVENT_MAX]; /*0x10 */
|
||||
LinkEvent[]; /*0x10 */
|
||||
} MPI26_CONFIG_PAGE_PCIELINK_2, *PTR_MPI26_CONFIG_PAGE_PCIELINK_2,
|
||||
Mpi26PcieLinkPage2_t, *pMpi26PcieLinkPage2_t;
|
||||
|
||||
@ -4067,12 +3985,9 @@ typedef struct _MPI26_PCIELINK3_LINK_EVENT_CONFIG {
|
||||
#define MPI26_PCIELINK3_TFLAGS_EVENT_NOTIFY (0x0001)
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check the value returned for NumLinkEvents at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check the value returned
|
||||
*for NumLinkEvents at runtime before using LinkEventConfig[].
|
||||
*/
|
||||
#ifndef MPI26_PCIELINK3_LINK_EVENT_MAX
|
||||
#define MPI26_PCIELINK3_LINK_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
|
||||
@ -4083,7 +3998,7 @@ typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3 {
|
||||
U8 Reserved3; /*0x0D */
|
||||
U16 Reserved4; /*0x0E */
|
||||
MPI26_PCIELINK3_LINK_EVENT_CONFIG
|
||||
LinkEventConfig[MPI26_PCIELINK3_LINK_EVENT_MAX]; /*0x10 */
|
||||
LinkEventConfig[]; /*0x10 */
|
||||
} MPI26_CONFIG_PAGE_PCIELINK_3, *PTR_MPI26_CONFIG_PAGE_PCIELINK_3,
|
||||
Mpi26PcieLinkPage3_t, *pMpi26PcieLinkPage3_t;
|
||||
|
||||
|
@ -295,20 +295,9 @@ typedef struct _MPI2_EXT_IMAGE_HEADER {
|
||||
/*FLASH Layout Extended Image Data */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check RegionsPerLayout at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check NumberOfLayouts and
|
||||
*RegionsPerLayout at runtime before using Layout[] and Region[].
|
||||
*/
|
||||
#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
|
||||
#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check NumberOfLayouts at runtime.
|
||||
*/
|
||||
#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
|
||||
#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_FLASH_REGION {
|
||||
U8 RegionType; /*0x00 */
|
||||
@ -325,7 +314,7 @@ typedef struct _MPI2_FLASH_LAYOUT {
|
||||
U32 Reserved1; /*0x04 */
|
||||
U32 Reserved2; /*0x08 */
|
||||
U32 Reserved3; /*0x0C */
|
||||
MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */
|
||||
MPI2_FLASH_REGION Region[]; /*0x10 */
|
||||
} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT,
|
||||
Mpi2FlashLayout_t, *pMpi2FlashLayout_t;
|
||||
|
||||
@ -339,7 +328,7 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
|
||||
U16 MinimumSectorAlignment; /*0x08 */
|
||||
U16 Reserved3; /*0x0A */
|
||||
U32 Reserved4; /*0x0C */
|
||||
MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */
|
||||
MPI2_FLASH_LAYOUT Layout[]; /*0x10 */
|
||||
} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA,
|
||||
Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t;
|
||||
|
||||
@ -373,12 +362,9 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
|
||||
/*Supported Devices Extended Image Data */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check NumberOfDevices at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check NumberOfDevices at
|
||||
*runtime before using SupportedDevice[].
|
||||
*/
|
||||
#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
|
||||
#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_SUPPORTED_DEVICE {
|
||||
U16 DeviceID; /*0x00 */
|
||||
@ -399,7 +385,7 @@ typedef struct _MPI2_SUPPORTED_DEVICES_DATA {
|
||||
U8 Reserved2; /*0x03 */
|
||||
U32 Reserved3; /*0x04 */
|
||||
MPI2_SUPPORTED_DEVICE
|
||||
SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */
|
||||
SupportedDevice[]; /*0x08 */
|
||||
} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA,
|
||||
Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t;
|
||||
|
||||
@ -464,7 +450,7 @@ typedef struct _MPI25_ENCRYPTED_HASH_ENTRY {
|
||||
U8 EncryptionAlgorithm; /*0x02 */
|
||||
U8 Reserved1; /*0x03 */
|
||||
U32 Reserved2; /*0x04 */
|
||||
U32 EncryptedHash[1]; /*0x08 */ /* variable length */
|
||||
U32 EncryptedHash[]; /*0x08 */
|
||||
} MPI25_ENCRYPTED_HASH_ENTRY, *PTR_MPI25_ENCRYPTED_HASH_ENTRY,
|
||||
Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t;
|
||||
|
||||
@ -508,7 +494,7 @@ typedef struct _MPI25_ENCRYPTED_HASH_DATA {
|
||||
U8 NumHash; /*0x01 */
|
||||
U16 Reserved1; /*0x02 */
|
||||
U32 Reserved2; /*0x04 */
|
||||
MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /*0x08 */
|
||||
MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[]; /*0x08 */
|
||||
} MPI25_ENCRYPTED_HASH_DATA, *PTR_MPI25_ENCRYPTED_HASH_DATA,
|
||||
Mpi25EncryptedHashData_t, *pMpi25EncryptedHashData_t;
|
||||
|
||||
|
@ -808,12 +808,9 @@ typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK {
|
||||
/*Integrated RAID Configuration Change List Event data */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check NumElements at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check NumElements at
|
||||
*runtime before using ConfigElement[].
|
||||
*/
|
||||
#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
|
||||
#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT {
|
||||
U16 ElementFlags; /*0x00 */
|
||||
@ -848,7 +845,7 @@ typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST {
|
||||
U8 ConfigNum; /*0x03 */
|
||||
U32 Flags; /*0x04 */
|
||||
MPI2_EVENT_IR_CONFIG_ELEMENT
|
||||
ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */
|
||||
ConfigElement[];/*0x08 */
|
||||
} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
|
||||
*PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
|
||||
Mpi2EventDataIrConfigChangeList_t,
|
||||
@ -969,12 +966,9 @@ typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW {
|
||||
/*SAS Topology Change List Event data */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check NumEntries at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check NumEntries at
|
||||
*runtime before using PHY[].
|
||||
*/
|
||||
#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
|
||||
#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY {
|
||||
U16 AttachedDevHandle; /*0x00 */
|
||||
@ -994,7 +988,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST {
|
||||
U8 ExpStatus; /*0x0A */
|
||||
U8 PhysicalPort; /*0x0B */
|
||||
MPI2_EVENT_SAS_TOPO_PHY_ENTRY
|
||||
PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /*0x0C */
|
||||
PHY[]; /*0x0C */
|
||||
} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
|
||||
*PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
|
||||
Mpi2EventDataSasTopologyChangeList_t,
|
||||
@ -1229,12 +1223,9 @@ typedef struct _MPI26_EVENT_DATA_PCIE_ENUMERATION {
|
||||
/*PCIe Topology Change List Event data (MPI v2.6 and later) */
|
||||
|
||||
/*
|
||||
*Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
*one and check NumEntries at runtime.
|
||||
*Host code (drivers, BIOS, utilities, etc.) should check NumEntries at
|
||||
*runtime before using PortEntry[].
|
||||
*/
|
||||
#ifndef MPI26_EVENT_PCIE_TOPO_PORT_COUNT
|
||||
#define MPI26_EVENT_PCIE_TOPO_PORT_COUNT (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_EVENT_PCIE_TOPO_PORT_ENTRY {
|
||||
U16 AttachedDevHandle; /*0x00 */
|
||||
@ -1286,7 +1277,7 @@ typedef struct _MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST {
|
||||
U8 SwitchStatus; /*0x0A */
|
||||
U8 PhysicalPort; /*0x0B */
|
||||
MPI26_EVENT_PCIE_TOPO_PORT_ENTRY
|
||||
PortEntry[MPI26_EVENT_PCIE_TOPO_PORT_COUNT]; /*0x0C */
|
||||
PortEntry[]; /*0x0C */
|
||||
} MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
|
||||
*PTR_MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
|
||||
Mpi26EventDataPCIeTopologyChangeList_t,
|
||||
|
@ -4893,8 +4893,7 @@ mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
|
||||
if (!num_phys)
|
||||
return;
|
||||
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
|
||||
sizeof(Mpi2SasIOUnit1PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg1, PhyData, num_phys);
|
||||
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -5044,7 +5043,7 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi26DriverTriggerPage2_t trigger_pg2;
|
||||
struct SL_WH_EVENT_TRIGGER_T *event_tg;
|
||||
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY *mpi_event_tg;
|
||||
MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY *mpi_event_tg;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int r = 0, i = 0;
|
||||
u16 count = 0;
|
||||
@ -5096,7 +5095,7 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi26DriverTriggerPage3_t trigger_pg3;
|
||||
struct SL_WH_SCSI_TRIGGER_T *scsi_tg;
|
||||
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY *mpi_scsi_tg;
|
||||
MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY *mpi_scsi_tg;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int r = 0, i = 0;
|
||||
u16 count = 0;
|
||||
@ -5148,7 +5147,7 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi26DriverTriggerPage4_t trigger_pg4;
|
||||
struct SL_WH_MPI_TRIGGER_T *status_tg;
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY *mpi_status_tg;
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY *mpi_status_tg;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int r = 0, i = 0;
|
||||
u16 count = 0;
|
||||
@ -5379,10 +5378,9 @@ _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
|
||||
Mpi2SasIOUnitPage1_t sas_iounit_pg1;
|
||||
Mpi26PCIeIOUnitPage1_t pcie_iounit_pg1;
|
||||
u16 depth;
|
||||
int sz;
|
||||
int rc = 0;
|
||||
|
||||
ioc->max_wideport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
@ -5392,28 +5390,21 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (!ioc->is_gen35_ioc)
|
||||
goto out;
|
||||
/* sas iounit page 1 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData);
|
||||
sas_iounit_pg1 = kzalloc(sizeof(Mpi2SasIOUnitPage1_t), GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
return rc;
|
||||
}
|
||||
rc = mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
|
||||
sas_iounit_pg1, sz);
|
||||
&sas_iounit_pg1, sizeof(Mpi2SasIOUnitPage1_t));
|
||||
if (rc) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
depth = le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth);
|
||||
depth = le16_to_cpu(sas_iounit_pg1.SASWideMaxQueueDepth);
|
||||
ioc->max_wideport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH);
|
||||
|
||||
depth = le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth);
|
||||
depth = le16_to_cpu(sas_iounit_pg1.SASNarrowMaxQueueDepth);
|
||||
ioc->max_narrowport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH);
|
||||
|
||||
depth = sas_iounit_pg1->SATAMaxQDepth;
|
||||
depth = sas_iounit_pg1.SATAMaxQDepth;
|
||||
ioc->max_sata_qd = (depth ? depth : MPT3SAS_SATA_QUEUE_DEPTH);
|
||||
|
||||
/* pcie iounit page 1 */
|
||||
@ -5432,7 +5423,6 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
|
||||
"MaxWidePortQD: 0x%x MaxNarrowPortQD: 0x%x MaxSataQD: 0x%x MaxNvmeQD: 0x%x\n",
|
||||
ioc->max_wideport_qd, ioc->max_narrowport_qd,
|
||||
ioc->max_sata_qd, ioc->max_nvme_qd));
|
||||
kfree(sas_iounit_pg1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -5588,6 +5578,7 @@ mpt3sas_atto_init(struct MPT3SAS_ADAPTER *ioc)
|
||||
static int
|
||||
_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2IOUnitPage8_t iounit_pg8;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
u32 iounit_pg1_flags;
|
||||
int tg_flags = 0;
|
||||
@ -5684,7 +5675,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
rc = mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8);
|
||||
rc = mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &iounit_pg8);
|
||||
if (rc)
|
||||
return rc;
|
||||
_base_display_ioc_capabilities(ioc);
|
||||
@ -5706,8 +5697,8 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (ioc->iounit_pg8.NumSensors)
|
||||
ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
|
||||
if (iounit_pg8.NumSensors)
|
||||
ioc->temp_sensors_count = iounit_pg8.NumSensors;
|
||||
if (ioc->is_aero_ioc) {
|
||||
rc = _base_update_ioc_page1_inlinewith_perf_mode(ioc);
|
||||
if (rc)
|
||||
|
@ -1237,7 +1237,6 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
||||
* @ioc_pg8: static ioc page 8
|
||||
* @iounit_pg0: static iounit page 0
|
||||
* @iounit_pg1: static iounit page 1
|
||||
* @iounit_pg8: static iounit page 8
|
||||
* @sas_hba: sas host object
|
||||
* @sas_expander_list: expander object list
|
||||
* @enclosure_list: enclosure object list
|
||||
@ -1465,7 +1464,6 @@ struct MPT3SAS_ADAPTER {
|
||||
Mpi2IOCPage8_t ioc_pg8;
|
||||
Mpi2IOUnitPage0_t iounit_pg0;
|
||||
Mpi2IOUnitPage1_t iounit_pg1;
|
||||
Mpi2IOUnitPage8_t iounit_pg8;
|
||||
Mpi2IOCPage1_t ioc_pg1_copy;
|
||||
|
||||
struct _boot_device req_boot_device;
|
||||
@ -1983,6 +1981,7 @@ extern const struct attribute_group *mpt3sas_host_groups[];
|
||||
extern const struct attribute_group *mpt3sas_dev_groups[];
|
||||
void mpt3sas_ctl_init(ushort hbas_to_enumerate);
|
||||
void mpt3sas_ctl_exit(ushort hbas_to_enumerate);
|
||||
void mpt3sas_ctl_release(struct MPT3SAS_ADAPTER *ioc);
|
||||
u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
||||
u32 reply);
|
||||
void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
@ -2334,7 +2334,7 @@ mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
tg_pg2.NumMPIEventTrigger = 0;
|
||||
memset(&tg_pg2.MPIEventTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
|
||||
MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
|
||||
@ -2493,7 +2493,7 @@ mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
tg_pg3.NumSCSISenseTrigger = 0;
|
||||
memset(&tg_pg3.SCSISenseTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
|
||||
MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
|
||||
@ -2649,7 +2649,7 @@ mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
tg_pg4.NumIOCStatusLogInfoTrigger = 0;
|
||||
memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
|
||||
|
@ -4156,6 +4156,30 @@ mpt3sas_ctl_init(ushort hbas_to_enumerate)
|
||||
init_waitqueue_head(&ctl_poll_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_ctl_release - release dma for ctl
|
||||
* @ioc: per adapter object
|
||||
*/
|
||||
void
|
||||
mpt3sas_ctl_release(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* free memory associated to diag buffers */
|
||||
for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
|
||||
if (!ioc->diag_buffer[i])
|
||||
continue;
|
||||
dma_free_coherent(&ioc->pdev->dev,
|
||||
ioc->diag_buffer_sz[i],
|
||||
ioc->diag_buffer[i],
|
||||
ioc->diag_buffer_dma[i]);
|
||||
ioc->diag_buffer[i] = NULL;
|
||||
ioc->diag_buffer_status[i] = 0;
|
||||
}
|
||||
|
||||
kfree(ioc->event_log);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_ctl_exit - exit point for ctl
|
||||
* @hbas_to_enumerate: ?
|
||||
@ -4163,25 +4187,7 @@ mpt3sas_ctl_init(ushort hbas_to_enumerate)
|
||||
void
|
||||
mpt3sas_ctl_exit(ushort hbas_to_enumerate)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
|
||||
|
||||
/* free memory associated to diag buffers */
|
||||
for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
|
||||
if (!ioc->diag_buffer[i])
|
||||
continue;
|
||||
dma_free_coherent(&ioc->pdev->dev,
|
||||
ioc->diag_buffer_sz[i],
|
||||
ioc->diag_buffer[i],
|
||||
ioc->diag_buffer_dma[i]);
|
||||
ioc->diag_buffer[i] = NULL;
|
||||
ioc->diag_buffer_status[i] = 0;
|
||||
}
|
||||
|
||||
kfree(ioc->event_log);
|
||||
}
|
||||
if (hbas_to_enumerate != 1)
|
||||
misc_deregister(&ctl_dev);
|
||||
if (hbas_to_enumerate != 2)
|
||||
|
@ -2431,8 +2431,7 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
|
||||
}
|
||||
|
||||
raid_device->num_pds = num_pds;
|
||||
sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
|
||||
sizeof(Mpi2RaidVol0PhysDisk_t));
|
||||
sz = struct_size(vol_pg0, PhysDisk, num_pds);
|
||||
vol_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!vol_pg0) {
|
||||
dfailprintk(ioc,
|
||||
@ -5966,8 +5965,7 @@ _scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
/*
|
||||
* Read SASIOUnitPage0 to get each HBA Phy's data.
|
||||
*/
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) +
|
||||
(ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit0PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg0) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -6145,8 +6143,7 @@ _scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc,
|
||||
u64 attached_sas_addr;
|
||||
u8 found = 0, port_count = 0, port_id;
|
||||
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
|
||||
* sizeof(Mpi2SasIOUnit0PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg0) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -6579,8 +6576,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n",
|
||||
(u64)ioc->sas_hba.sas_address));
|
||||
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
|
||||
* sizeof(Mpi2SasIOUnit0PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg0) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -6731,8 +6727,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc->sas_hba.num_phys = num_phys;
|
||||
|
||||
/* sas_iounit page 0 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
sizeof(Mpi2SasIOUnit0PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg0) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -6754,8 +6749,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
|
||||
}
|
||||
|
||||
/* sas_iounit page 1 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
sizeof(Mpi2SasIOUnit1PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -10376,8 +10370,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
Mpi2ExpanderPage0_t expander_pg0;
|
||||
Mpi2SasDevicePage0_t sas_device_pg0;
|
||||
Mpi26PCIeDevicePage0_t pcie_device_pg0;
|
||||
Mpi2RaidVolPage1_t *volume_pg1;
|
||||
Mpi2RaidVolPage0_t *volume_pg0;
|
||||
Mpi2RaidVolPage1_t volume_pg1;
|
||||
Mpi2RaidVolPage0_t volume_pg0;
|
||||
Mpi2RaidPhysDiskPage0_t pd_pg0;
|
||||
Mpi2EventIrConfigElement_t element;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
@ -10392,16 +10386,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
u8 retry_count;
|
||||
unsigned long flags;
|
||||
|
||||
volume_pg0 = kzalloc(sizeof(*volume_pg0), GFP_KERNEL);
|
||||
if (!volume_pg0)
|
||||
return;
|
||||
|
||||
volume_pg1 = kzalloc(sizeof(*volume_pg1), GFP_KERNEL);
|
||||
if (!volume_pg1) {
|
||||
kfree(volume_pg0);
|
||||
return;
|
||||
}
|
||||
|
||||
ioc_info(ioc, "scan devices: start\n");
|
||||
|
||||
_scsih_sas_host_refresh(ioc);
|
||||
@ -10511,7 +10495,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
/* volumes */
|
||||
handle = 0xFFFF;
|
||||
while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
|
||||
volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
|
||||
&volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
@ -10519,15 +10503,15 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo));
|
||||
break;
|
||||
}
|
||||
handle = le16_to_cpu(volume_pg1->DevHandle);
|
||||
handle = le16_to_cpu(volume_pg1.DevHandle);
|
||||
spin_lock_irqsave(&ioc->raid_device_lock, flags);
|
||||
raid_device = _scsih_raid_device_find_by_wwid(ioc,
|
||||
le64_to_cpu(volume_pg1->WWID));
|
||||
le64_to_cpu(volume_pg1.WWID));
|
||||
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
|
||||
if (raid_device)
|
||||
continue;
|
||||
if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
|
||||
volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
|
||||
&volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
|
||||
sizeof(Mpi2RaidVolPage0_t)))
|
||||
continue;
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
@ -10537,17 +10521,17 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo));
|
||||
break;
|
||||
}
|
||||
if (volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
|
||||
volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
|
||||
volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
|
||||
if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
|
||||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
|
||||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
|
||||
memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
|
||||
element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
|
||||
element.VolDevHandle = volume_pg1->DevHandle;
|
||||
element.VolDevHandle = volume_pg1.DevHandle;
|
||||
ioc_info(ioc, "\tBEFORE adding volume: handle (0x%04x)\n",
|
||||
volume_pg1->DevHandle);
|
||||
volume_pg1.DevHandle);
|
||||
_scsih_sas_volume_add(ioc, &element);
|
||||
ioc_info(ioc, "\tAFTER adding volume: handle (0x%04x)\n",
|
||||
volume_pg1->DevHandle);
|
||||
volume_pg1.DevHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10636,9 +10620,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
handle, (u64)le64_to_cpu(pcie_device_pg0.WWID));
|
||||
}
|
||||
|
||||
kfree(volume_pg0);
|
||||
kfree(volume_pg1);
|
||||
|
||||
ioc_info(ioc, "\tpcie devices: pcie end devices complete\n");
|
||||
ioc_info(ioc, "scan devices: complete\n");
|
||||
}
|
||||
@ -11350,6 +11331,7 @@ static void scsih_remove(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
mpt3sas_base_detach(ioc);
|
||||
mpt3sas_ctl_release(ioc);
|
||||
spin_lock(&gioc_lock);
|
||||
list_del(&ioc->list);
|
||||
spin_unlock(&gioc_lock);
|
||||
|
@ -1792,8 +1792,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
|
||||
/* handle hba phys */
|
||||
|
||||
/* read sas_iounit page 0 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
sizeof(Mpi2SasIOUnit0PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg0) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -1833,8 +1832,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
|
||||
}
|
||||
|
||||
/* read sas_iounit page 1 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
sizeof(Mpi2SasIOUnit1PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
@ -1944,8 +1942,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
|
||||
/* handle hba phys */
|
||||
|
||||
/* sas_iounit page 1 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
sizeof(Mpi2SasIOUnit1PhyData_t));
|
||||
sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys);
|
||||
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||
|
@ -20,12 +20,12 @@
|
||||
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER (0xE0)
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 {
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_0 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 TriggerFlags; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
U32 Reserved0xC[61]; /* 0x0C */
|
||||
} _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0, Mpi26DriverTriggerPage0_t;
|
||||
} _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_0, Mpi26DriverTriggerPage0_t;
|
||||
|
||||
/* Trigger Flags */
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID (0x0001)
|
||||
@ -34,61 +34,61 @@ typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 {
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID (0x0008)
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_MASTER_TIGGER_ENTRY {
|
||||
typedef struct _MPI26_DRIVER_MASTER_TRIGGER_ENTRY {
|
||||
U32 MasterTriggerFlags;
|
||||
} MPI26_DRIVER_MASTER_TIGGER_ENTRY;
|
||||
} MPI26_DRIVER_MASTER_TRIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_MASTER_TRIGGERS (1)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_1 {
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_1 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumMasterTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_MASTER_TIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_1, Mpi26DriverTriggerPage1_t;
|
||||
MPI26_DRIVER_MASTER_TRIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_1, Mpi26DriverTriggerPage1_t;
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY {
|
||||
typedef struct _MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY {
|
||||
U16 MPIEventCode; /* 0x00 */
|
||||
U16 MPIEventCodeSpecific; /* 0x02 */
|
||||
} MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY;
|
||||
} MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_MPI_EVENT_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_2 {
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_2 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumMPIEventTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_2, Mpi26DriverTriggerPage2_t;
|
||||
MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_2, Mpi26DriverTriggerPage2_t;
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY {
|
||||
typedef struct _MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY {
|
||||
U8 ASCQ; /* 0x00 */
|
||||
U8 ASC; /* 0x01 */
|
||||
U8 SenseKey; /* 0x02 */
|
||||
U8 Reserved; /* 0x03 */
|
||||
} MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY;
|
||||
} MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_SCSI_SENSE_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_3 {
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_3 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumSCSISenseTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_3, Mpi26DriverTriggerPage3_t;
|
||||
MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_3, Mpi26DriverTriggerPage3_t;
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY {
|
||||
typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY {
|
||||
U16 IOCStatus; /* 0x00 */
|
||||
U16 Reserved; /* 0x02 */
|
||||
U32 LogInfo; /* 0x04 */
|
||||
} MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY;
|
||||
} MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_LOGINFO_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_4 {
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TRIGGER_4 {
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumIOCStatusLogInfoTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_4, Mpi26DriverTriggerPage4_t;
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TRIGGER_4, Mpi26DriverTriggerPage4_t;
|
||||
|
||||
#endif
|
||||
|
@ -141,8 +141,7 @@ mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
|
||||
return;
|
||||
}
|
||||
|
||||
sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
|
||||
sizeof(Mpi2RaidVol0PhysDisk_t));
|
||||
sz = struct_size(vol_pg0, PhysDisk, num_pds);
|
||||
vol_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!vol_pg0) {
|
||||
ioc_info(ioc, "WarpDrive : Direct IO is disabled Memory allocation failure for RVPG0\n");
|
||||
|
@ -103,7 +103,7 @@ static int mvme16x_probe(struct platform_device *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int mvme16x_device_remove(struct platform_device *dev)
|
||||
static void mvme16x_device_remove(struct platform_device *dev)
|
||||
{
|
||||
struct Scsi_Host *host = platform_get_drvdata(dev);
|
||||
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
|
||||
@ -120,8 +120,6 @@ static int mvme16x_device_remove(struct platform_device *dev)
|
||||
NCR_700_release(host);
|
||||
kfree(hostdata);
|
||||
free_irq(host->irq, host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mvme16x_scsi_driver = {
|
||||
@ -129,7 +127,7 @@ static struct platform_driver mvme16x_scsi_driver = {
|
||||
.name = "mvme16x-scsi",
|
||||
},
|
||||
.probe = mvme16x_probe,
|
||||
.remove = mvme16x_device_remove,
|
||||
.remove_new = mvme16x_device_remove,
|
||||
};
|
||||
|
||||
static int __init mvme16x_scsi_init(void)
|
||||
|
@ -1409,7 +1409,7 @@ static int qpti_sbus_probe(struct platform_device *op)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int qpti_sbus_remove(struct platform_device *op)
|
||||
static void qpti_sbus_remove(struct platform_device *op)
|
||||
{
|
||||
struct qlogicpti *qpti = dev_get_drvdata(&op->dev);
|
||||
|
||||
@ -1438,8 +1438,6 @@ static int qpti_sbus_remove(struct platform_device *op)
|
||||
of_iounmap(&op->resource[0], qpti->sreg, sizeof(unsigned char));
|
||||
|
||||
scsi_host_put(qpti->qhost);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qpti_match[] = {
|
||||
@ -1465,7 +1463,7 @@ static struct platform_driver qpti_sbus_driver = {
|
||||
.of_match_table = qpti_match,
|
||||
},
|
||||
.probe = qpti_sbus_probe,
|
||||
.remove = qpti_sbus_remove,
|
||||
.remove_new = qpti_sbus_remove,
|
||||
};
|
||||
module_platform_driver(qpti_sbus_driver);
|
||||
|
||||
|
@ -301,6 +301,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(!shost->ehandler);
|
||||
WARN_ON_ONCE(!test_bit(SCMD_STATE_INFLIGHT, &scmd->state));
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (scsi_host_set_state(shost, SHOST_RECOVERY)) {
|
||||
|
@ -291,7 +291,7 @@ static int sgiwd93_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sgiwd93_remove(struct platform_device *pdev)
|
||||
static void sgiwd93_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *host = platform_get_drvdata(pdev);
|
||||
struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata;
|
||||
@ -302,12 +302,11 @@ static int sgiwd93_remove(struct platform_device *pdev)
|
||||
dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
|
||||
DMA_TO_DEVICE);
|
||||
scsi_host_put(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sgiwd93_driver = {
|
||||
.probe = sgiwd93_probe,
|
||||
.remove = sgiwd93_remove,
|
||||
.remove_new = sgiwd93_remove,
|
||||
.driver = {
|
||||
.name = "sgiwd93",
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ static int snirm710_probe(struct platform_device *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int snirm710_driver_remove(struct platform_device *dev)
|
||||
static void snirm710_driver_remove(struct platform_device *dev)
|
||||
{
|
||||
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
|
||||
struct NCR_700_Host_Parameters *hostdata =
|
||||
@ -115,13 +115,11 @@ static int snirm710_driver_remove(struct platform_device *dev)
|
||||
free_irq(host->irq, host);
|
||||
iounmap(hostdata->base);
|
||||
kfree(hostdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver snirm710_driver = {
|
||||
.probe = snirm710_probe,
|
||||
.remove = snirm710_driver_remove,
|
||||
.remove_new = snirm710_driver_remove,
|
||||
.driver = {
|
||||
.name = "snirm_53c710",
|
||||
},
|
||||
|
@ -641,7 +641,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit sun3_scsi_remove(struct platform_device *pdev)
|
||||
static void __exit sun3_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
@ -654,11 +654,10 @@ static int __exit sun3_scsi_remove(struct platform_device *pdev)
|
||||
if (udc_regs)
|
||||
dvma_free(udc_regs);
|
||||
iounmap(ioaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sun3_scsi_driver = {
|
||||
.remove = __exit_p(sun3_scsi_remove),
|
||||
.remove_new = __exit_p(sun3_scsi_remove),
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
},
|
||||
|
@ -243,7 +243,7 @@ static int esp_sun3x_probe(struct platform_device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_sun3x_remove(struct platform_device *dev)
|
||||
static void esp_sun3x_remove(struct platform_device *dev)
|
||||
{
|
||||
struct esp *esp = dev_get_drvdata(&dev->dev);
|
||||
unsigned int irq = esp->host->irq;
|
||||
@ -261,13 +261,11 @@ static int esp_sun3x_remove(struct platform_device *dev)
|
||||
esp->command_block_dma);
|
||||
|
||||
scsi_host_put(esp->host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver esp_sun3x_driver = {
|
||||
.probe = esp_sun3x_probe,
|
||||
.remove = esp_sun3x_remove,
|
||||
.remove_new = esp_sun3x_remove,
|
||||
.driver = {
|
||||
.name = "sun3x_esp",
|
||||
},
|
||||
|
@ -550,7 +550,7 @@ static int esp_sbus_probe(struct platform_device *op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int esp_sbus_remove(struct platform_device *op)
|
||||
static void esp_sbus_remove(struct platform_device *op)
|
||||
{
|
||||
struct esp *esp = dev_get_drvdata(&op->dev);
|
||||
struct platform_device *dma_of = esp->dma;
|
||||
@ -581,8 +581,6 @@ static int esp_sbus_remove(struct platform_device *op)
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
put_device(&dma_of->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id esp_match[] = {
|
||||
@ -605,7 +603,7 @@ static struct platform_driver esp_sbus_driver = {
|
||||
.of_match_table = esp_match,
|
||||
},
|
||||
.probe = esp_sbus_probe,
|
||||
.remove = esp_sbus_remove,
|
||||
.remove_new = esp_sbus_remove,
|
||||
};
|
||||
module_platform_driver(esp_sbus_driver);
|
||||
|
||||
|
@ -470,6 +470,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type,
|
||||
case INQUIRY:
|
||||
case LOG_SENSE:
|
||||
case SERVICE_ACTION_IN_12:
|
||||
case READ_CAPACITY:
|
||||
case REPORT_LUNS:
|
||||
case REQUEST_SENSE:
|
||||
case PERSISTENT_RESERVE_IN:
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/fault-inject.h>
|
||||
#include <linux/module.h>
|
||||
#include <ufs/ufshcd.h>
|
||||
#include "ufs-fault-injection.h"
|
||||
|
||||
static int ufs_fault_get(char *buffer, const struct kernel_param *kp);
|
||||
@ -59,12 +60,22 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ufs_trigger_eh(void)
|
||||
void ufs_fault_inject_hba_init(struct ufs_hba *hba)
|
||||
{
|
||||
return should_fail(&ufs_trigger_eh_attr, 1);
|
||||
hba->trigger_eh_attr = ufs_trigger_eh_attr;
|
||||
hba->timeout_attr = ufs_timeout_attr;
|
||||
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
|
||||
fault_create_debugfs_attr("trigger_eh_inject", hba->debugfs_root, &hba->trigger_eh_attr);
|
||||
fault_create_debugfs_attr("timeout_inject", hba->debugfs_root, &hba->timeout_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ufs_fail_completion(void)
|
||||
bool ufs_trigger_eh(struct ufs_hba *hba)
|
||||
{
|
||||
return should_fail(&ufs_timeout_attr, 1);
|
||||
return should_fail(&hba->trigger_eh_attr, 1);
|
||||
}
|
||||
|
||||
bool ufs_fail_completion(struct ufs_hba *hba)
|
||||
{
|
||||
return should_fail(&hba->timeout_attr, 1);
|
||||
}
|
||||
|
@ -7,15 +7,20 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
|
||||
bool ufs_trigger_eh(void);
|
||||
bool ufs_fail_completion(void);
|
||||
void ufs_fault_inject_hba_init(struct ufs_hba *hba);
|
||||
bool ufs_trigger_eh(struct ufs_hba *hba);
|
||||
bool ufs_fail_completion(struct ufs_hba *hba);
|
||||
#else
|
||||
static inline bool ufs_trigger_eh(void)
|
||||
static inline void ufs_fault_inject_hba_init(struct ufs_hba *hba)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool ufs_trigger_eh(struct ufs_hba *hba)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool ufs_fail_completion(void)
|
||||
static inline bool ufs_fail_completion(struct ufs_hba *hba)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -7,9 +7,56 @@
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <ufs/ufs.h>
|
||||
#include <ufs/unipro.h>
|
||||
#include "ufs-sysfs.h"
|
||||
#include "ufshcd-priv.h"
|
||||
|
||||
static const char *ufs_pa_pwr_mode_to_string(enum ufs_pa_pwr_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case FAST_MODE: return "FAST_MODE";
|
||||
case SLOW_MODE: return "SLOW_MODE";
|
||||
case FASTAUTO_MODE: return "FASTAUTO_MODE";
|
||||
case SLOWAUTO_MODE: return "SLOWAUTO_MODE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ufs_hs_gear_rate_to_string(enum ufs_hs_gear_rate rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case PA_HS_MODE_A: return "HS_RATE_A";
|
||||
case PA_HS_MODE_B: return "HS_RATE_B";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ufs_pwm_gear_to_string(enum ufs_pwm_gear_tag gear)
|
||||
{
|
||||
switch (gear) {
|
||||
case UFS_PWM_G1: return "PWM_GEAR1";
|
||||
case UFS_PWM_G2: return "PWM_GEAR2";
|
||||
case UFS_PWM_G3: return "PWM_GEAR3";
|
||||
case UFS_PWM_G4: return "PWM_GEAR4";
|
||||
case UFS_PWM_G5: return "PWM_GEAR5";
|
||||
case UFS_PWM_G6: return "PWM_GEAR6";
|
||||
case UFS_PWM_G7: return "PWM_GEAR7";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ufs_hs_gear_to_string(enum ufs_hs_gear_tag gear)
|
||||
{
|
||||
switch (gear) {
|
||||
case UFS_HS_G1: return "HS_GEAR1";
|
||||
case UFS_HS_G2: return "HS_GEAR2";
|
||||
case UFS_HS_G3: return "HS_GEAR3";
|
||||
case UFS_HS_G4: return "HS_GEAR4";
|
||||
case UFS_HS_G5: return "HS_GEAR5";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ufshcd_uic_link_state_to_string(
|
||||
enum uic_link_state state)
|
||||
{
|
||||
@ -255,6 +302,35 @@ static ssize_t wb_on_store(struct device *dev, struct device_attribute *attr,
|
||||
return res < 0 ? res : count;
|
||||
}
|
||||
|
||||
static ssize_t rtc_update_ms_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", hba->dev_info.rtc_update_period);
|
||||
}
|
||||
|
||||
static ssize_t rtc_update_ms_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
unsigned int ms;
|
||||
bool resume_period_update = false;
|
||||
|
||||
if (kstrtouint(buf, 0, &ms))
|
||||
return -EINVAL;
|
||||
|
||||
if (!hba->dev_info.rtc_update_period && ms > 0)
|
||||
resume_period_update = true;
|
||||
/* Minimum and maximum update frequency should be synchronized with all UFS vendors */
|
||||
hba->dev_info.rtc_update_period = ms;
|
||||
|
||||
if (resume_period_update)
|
||||
schedule_delayed_work(&hba->ufs_rtc_update_work,
|
||||
msecs_to_jiffies(hba->dev_info.rtc_update_period));
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t enable_wb_buf_flush_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@ -339,6 +415,7 @@ static DEVICE_ATTR_RW(auto_hibern8);
|
||||
static DEVICE_ATTR_RW(wb_on);
|
||||
static DEVICE_ATTR_RW(enable_wb_buf_flush);
|
||||
static DEVICE_ATTR_RW(wb_flush_threshold);
|
||||
static DEVICE_ATTR_RW(rtc_update_ms);
|
||||
|
||||
static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
|
||||
&dev_attr_rpm_lvl.attr,
|
||||
@ -351,6 +428,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
|
||||
&dev_attr_wb_on.attr,
|
||||
&dev_attr_enable_wb_buf_flush.attr,
|
||||
&dev_attr_wb_flush_threshold.attr,
|
||||
&dev_attr_rtc_update_ms.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -628,6 +706,78 @@ static const struct attribute_group ufs_sysfs_monitor_group = {
|
||||
.attrs = ufs_sysfs_monitor_attrs,
|
||||
};
|
||||
|
||||
static ssize_t lane_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%u\n", hba->pwr_info.lane_rx);
|
||||
}
|
||||
|
||||
static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufs_pa_pwr_mode_to_string(hba->pwr_info.pwr_rx));
|
||||
}
|
||||
|
||||
static ssize_t rate_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufs_hs_gear_rate_to_string(hba->pwr_info.hs_rate));
|
||||
}
|
||||
|
||||
static ssize_t gear_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", hba->pwr_info.hs_rate ?
|
||||
ufs_hs_gear_to_string(hba->pwr_info.gear_rx) :
|
||||
ufs_pwm_gear_to_string(hba->pwr_info.gear_rx));
|
||||
}
|
||||
|
||||
static ssize_t dev_pm_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(hba->curr_dev_pwr_mode));
|
||||
}
|
||||
|
||||
static ssize_t link_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(hba->uic_link_state));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(lane);
|
||||
static DEVICE_ATTR_RO(mode);
|
||||
static DEVICE_ATTR_RO(rate);
|
||||
static DEVICE_ATTR_RO(gear);
|
||||
static DEVICE_ATTR_RO(dev_pm);
|
||||
static DEVICE_ATTR_RO(link_state);
|
||||
|
||||
static struct attribute *ufs_power_info_attrs[] = {
|
||||
&dev_attr_lane.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_rate.attr,
|
||||
&dev_attr_gear.attr,
|
||||
&dev_attr_dev_pm.attr,
|
||||
&dev_attr_link_state.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group ufs_sysfs_power_info_group = {
|
||||
.name = "power_info",
|
||||
.attrs = ufs_power_info_attrs,
|
||||
};
|
||||
|
||||
static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
|
||||
enum desc_idn desc_id,
|
||||
u8 desc_index,
|
||||
@ -1233,6 +1383,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
|
||||
&ufs_sysfs_default_group,
|
||||
&ufs_sysfs_capabilities_group,
|
||||
&ufs_sysfs_monitor_group,
|
||||
&ufs_sysfs_power_info_group,
|
||||
&ufs_sysfs_device_descriptor_group,
|
||||
&ufs_sysfs_interconnect_descriptor_group,
|
||||
&ufs_sysfs_geometry_descriptor_group,
|
||||
|
@ -99,6 +99,9 @@
|
||||
/* Polling time to wait for fDeviceInit */
|
||||
#define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */
|
||||
|
||||
/* Default RTC update every 10 seconds */
|
||||
#define UFS_RTC_UPDATE_INTERVAL_MS (10 * MSEC_PER_SEC)
|
||||
|
||||
/* UFSHC 4.0 compliant HC support this mode. */
|
||||
static bool use_mcq_mode = true;
|
||||
|
||||
@ -235,6 +238,12 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
|
||||
return UFS_PM_LVL_0;
|
||||
}
|
||||
|
||||
static bool ufshcd_is_ufs_dev_busy(struct ufs_hba *hba)
|
||||
{
|
||||
return (hba->clk_gating.active_reqs || hba->outstanding_reqs || hba->outstanding_tasks ||
|
||||
hba->active_uic_cmd || hba->uic_async_done);
|
||||
}
|
||||
|
||||
static const struct ufs_dev_quirk ufs_fixups[] = {
|
||||
/* UFS cards deviations table */
|
||||
{ .wmanufacturerid = UFS_VENDOR_MICRON,
|
||||
@ -289,21 +298,23 @@ static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba,
|
||||
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
|
||||
static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
|
||||
|
||||
static inline void ufshcd_enable_irq(struct ufs_hba *hba)
|
||||
void ufshcd_enable_irq(struct ufs_hba *hba)
|
||||
{
|
||||
if (!hba->is_irq_enabled) {
|
||||
enable_irq(hba->irq);
|
||||
hba->is_irq_enabled = true;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_enable_irq);
|
||||
|
||||
static inline void ufshcd_disable_irq(struct ufs_hba *hba)
|
||||
void ufshcd_disable_irq(struct ufs_hba *hba)
|
||||
{
|
||||
if (hba->is_irq_enabled) {
|
||||
disable_irq(hba->irq);
|
||||
hba->is_irq_enabled = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_disable_irq);
|
||||
|
||||
static void ufshcd_configure_wb(struct ufs_hba *hba)
|
||||
{
|
||||
@ -677,6 +688,8 @@ static void ufshcd_device_reset(struct ufs_hba *hba)
|
||||
hba->dev_info.wb_enabled = false;
|
||||
hba->dev_info.wb_buf_flush_enabled = false;
|
||||
}
|
||||
if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE)
|
||||
hba->dev_info.rtc_time_baseline = 0;
|
||||
}
|
||||
if (err != -EOPNOTSUPP)
|
||||
ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err);
|
||||
@ -1917,10 +1930,7 @@ static void ufshcd_gate_work(struct work_struct *work)
|
||||
goto rel_lock;
|
||||
}
|
||||
|
||||
if (hba->clk_gating.active_reqs
|
||||
|| hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
|
||||
|| hba->outstanding_reqs || hba->outstanding_tasks
|
||||
|| hba->active_uic_cmd || hba->uic_async_done)
|
||||
if (ufshcd_is_ufs_dev_busy(hba) || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)
|
||||
goto rel_lock;
|
||||
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
@ -2721,6 +2731,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags)
|
||||
.command_set_type = UPIU_COMMAND_SET_TYPE_SCSI,
|
||||
};
|
||||
|
||||
WARN_ON_ONCE(ucd_req_ptr->header.task_tag != lrbp->task_tag);
|
||||
|
||||
ucd_req_ptr->sc.exp_data_transfer_len = cpu_to_be32(cmd->sdb.length);
|
||||
|
||||
cdb_len = min_t(unsigned short, cmd->cmd_len, UFS_CDB_SIZE);
|
||||
@ -2993,7 +3005,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||
ufshcd_send_command(hba, tag, hwq);
|
||||
|
||||
out:
|
||||
if (ufs_trigger_eh()) {
|
||||
if (ufs_trigger_eh(hba)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
@ -4402,33 +4414,7 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit);
|
||||
|
||||
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool update = false;
|
||||
|
||||
if (!ufshcd_is_auto_hibern8_supported(hba))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
if (hba->ahit != ahit) {
|
||||
hba->ahit = ahit;
|
||||
update = true;
|
||||
}
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
if (update &&
|
||||
!pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) {
|
||||
ufshcd_rpm_get_sync(hba);
|
||||
ufshcd_hold(hba);
|
||||
ufshcd_auto_hibern8_enable(hba);
|
||||
ufshcd_release(hba);
|
||||
ufshcd_rpm_put_sync(hba);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update);
|
||||
|
||||
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba)
|
||||
static void ufshcd_configure_auto_hibern8(struct ufs_hba *hba)
|
||||
{
|
||||
if (!ufshcd_is_auto_hibern8_supported(hba))
|
||||
return;
|
||||
@ -4436,6 +4422,24 @@ void ufshcd_auto_hibern8_enable(struct ufs_hba *hba)
|
||||
ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER);
|
||||
}
|
||||
|
||||
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
|
||||
{
|
||||
const u32 cur_ahit = READ_ONCE(hba->ahit);
|
||||
|
||||
if (!ufshcd_is_auto_hibern8_supported(hba) || cur_ahit == ahit)
|
||||
return;
|
||||
|
||||
WRITE_ONCE(hba->ahit, ahit);
|
||||
if (!pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) {
|
||||
ufshcd_rpm_get_sync(hba);
|
||||
ufshcd_hold(hba);
|
||||
ufshcd_configure_auto_hibern8(hba);
|
||||
ufshcd_release(hba);
|
||||
ufshcd_rpm_put_sync(hba);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update);
|
||||
|
||||
/**
|
||||
* ufshcd_init_pwr_info - setting the POR (power on reset)
|
||||
* values in hba power info
|
||||
@ -5650,7 +5654,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba)
|
||||
!(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR))
|
||||
ufshcd_reset_intr_aggr(hba);
|
||||
|
||||
if (ufs_fail_completion())
|
||||
if (ufs_fail_completion(hba))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
@ -8199,6 +8203,79 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba)
|
||||
ufshcd_vops_fixup_dev_quirks(hba);
|
||||
}
|
||||
|
||||
static void ufshcd_update_rtc(struct ufs_hba *hba)
|
||||
{
|
||||
struct timespec64 ts64;
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
ktime_get_real_ts64(&ts64);
|
||||
|
||||
if (ts64.tv_sec < hba->dev_info.rtc_time_baseline) {
|
||||
dev_warn_once(hba->dev, "%s: Current time precedes previous setting!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Absolute RTC mode has a 136-year limit, spanning from 2010 to 2146. If a time beyond
|
||||
* 2146 is required, it is recommended to choose the relative RTC mode.
|
||||
*/
|
||||
val = ts64.tv_sec - hba->dev_info.rtc_time_baseline;
|
||||
|
||||
ufshcd_rpm_get_sync(hba);
|
||||
err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED,
|
||||
0, 0, &val);
|
||||
ufshcd_rpm_put_sync(hba);
|
||||
|
||||
if (err)
|
||||
dev_err(hba->dev, "%s: Failed to update rtc %d\n", __func__, err);
|
||||
else if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE)
|
||||
hba->dev_info.rtc_time_baseline = ts64.tv_sec;
|
||||
}
|
||||
|
||||
static void ufshcd_rtc_work(struct work_struct *work)
|
||||
{
|
||||
struct ufs_hba *hba;
|
||||
|
||||
hba = container_of(to_delayed_work(work), struct ufs_hba, ufs_rtc_update_work);
|
||||
|
||||
/* Update RTC only when there are no requests in progress and UFSHCI is operational */
|
||||
if (!ufshcd_is_ufs_dev_busy(hba) && hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL)
|
||||
ufshcd_update_rtc(hba);
|
||||
|
||||
if (ufshcd_is_ufs_dev_active(hba) && hba->dev_info.rtc_update_period)
|
||||
schedule_delayed_work(&hba->ufs_rtc_update_work,
|
||||
msecs_to_jiffies(hba->dev_info.rtc_update_period));
|
||||
}
|
||||
|
||||
static void ufs_init_rtc(struct ufs_hba *hba, u8 *desc_buf)
|
||||
{
|
||||
u16 periodic_rtc_update = get_unaligned_be16(&desc_buf[DEVICE_DESC_PARAM_FRQ_RTC]);
|
||||
struct ufs_dev_info *dev_info = &hba->dev_info;
|
||||
|
||||
if (periodic_rtc_update & UFS_RTC_TIME_BASELINE) {
|
||||
dev_info->rtc_type = UFS_RTC_ABSOLUTE;
|
||||
|
||||
/*
|
||||
* The concept of measuring time in Linux as the number of seconds elapsed since
|
||||
* 00:00:00 UTC on January 1, 1970, and UFS ABS RTC is elapsed from January 1st
|
||||
* 2010 00:00, here we need to adjust ABS baseline.
|
||||
*/
|
||||
dev_info->rtc_time_baseline = mktime64(2010, 1, 1, 0, 0, 0) -
|
||||
mktime64(1970, 1, 1, 0, 0, 0);
|
||||
} else {
|
||||
dev_info->rtc_type = UFS_RTC_RELATIVE;
|
||||
dev_info->rtc_time_baseline = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We ignore TIME_PERIOD defined in wPeriodicRTCUpdate because Spec does not clearly state
|
||||
* how to calculate the specific update period for each time unit. And we disable periodic
|
||||
* RTC update work, let user configure by sysfs node according to specific circumstance.
|
||||
*/
|
||||
dev_info->rtc_update_period = 0;
|
||||
}
|
||||
|
||||
static int ufs_get_device_desc(struct ufs_hba *hba)
|
||||
{
|
||||
int err;
|
||||
@ -8251,6 +8328,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
|
||||
|
||||
ufshcd_temp_notif_probe(hba, desc_buf);
|
||||
|
||||
ufs_init_rtc(hba, desc_buf);
|
||||
|
||||
if (hba->ext_iid_sup)
|
||||
ufshcd_ext_iid_probe(hba, desc_buf);
|
||||
|
||||
@ -8804,6 +8883,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
|
||||
ufshcd_force_reset_auto_bkops(hba);
|
||||
|
||||
ufshcd_set_timestamp_attr(hba);
|
||||
schedule_delayed_work(&hba->ufs_rtc_update_work,
|
||||
msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
|
||||
|
||||
/* Gear up to HS gear if supported */
|
||||
if (hba->max_pwr_info.is_valid) {
|
||||
@ -8878,8 +8959,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
|
||||
|
||||
if (hba->ee_usr_mask)
|
||||
ufshcd_write_ee_control(hba);
|
||||
/* Enable Auto-Hibernate if configured */
|
||||
ufshcd_auto_hibern8_enable(hba);
|
||||
ufshcd_configure_auto_hibern8(hba);
|
||||
|
||||
out:
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
@ -9362,6 +9442,7 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
|
||||
goto out_disable_vreg;
|
||||
|
||||
ufs_debugfs_hba_init(hba);
|
||||
ufs_fault_inject_hba_init(hba);
|
||||
|
||||
hba->is_powered = true;
|
||||
goto out;
|
||||
@ -9760,6 +9841,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
ret = ufshcd_vops_suspend(hba, pm_op, POST_CHANGE);
|
||||
if (ret)
|
||||
goto set_link_active;
|
||||
|
||||
cancel_delayed_work_sync(&hba->ufs_rtc_update_work);
|
||||
goto out;
|
||||
|
||||
set_link_active:
|
||||
@ -9854,6 +9937,8 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
if (ret)
|
||||
goto set_old_link_state;
|
||||
ufshcd_set_timestamp_attr(hba);
|
||||
schedule_delayed_work(&hba->ufs_rtc_update_work,
|
||||
msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
|
||||
}
|
||||
|
||||
if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
|
||||
@ -9876,8 +9961,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
cancel_delayed_work(&hba->rpm_dev_flush_recheck_work);
|
||||
}
|
||||
|
||||
/* Enable Auto-Hibernate if configured */
|
||||
ufshcd_auto_hibern8_enable(hba);
|
||||
ufshcd_configure_auto_hibern8(hba);
|
||||
|
||||
goto out;
|
||||
|
||||
@ -10550,8 +10634,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
|
||||
UFS_SLEEP_PWR_MODE,
|
||||
UIC_LINK_HIBERN8_STATE);
|
||||
|
||||
INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work,
|
||||
ufshcd_rpm_dev_flush_recheck_work);
|
||||
INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, ufshcd_rpm_dev_flush_recheck_work);
|
||||
INIT_DELAYED_WORK(&hba->ufs_rtc_update_work, ufshcd_rtc_work);
|
||||
|
||||
/* Set the default auto-hiberate idle timer value to 150 ms */
|
||||
if (ufshcd_is_auto_hibern8_supported(hba) && !hba->ahit) {
|
||||
|
@ -765,7 +765,7 @@ static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba,
|
||||
{
|
||||
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
|
||||
struct phy *generic_phy = ufs->phy;
|
||||
struct ufs_dev_params ufs_exynos_cap;
|
||||
struct ufs_host_params host_params;
|
||||
int ret;
|
||||
|
||||
if (!dev_req_params) {
|
||||
@ -774,10 +774,9 @@ static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ufshcd_init_pwr_dev_param(&ufs_exynos_cap);
|
||||
ufshcd_init_host_params(&host_params);
|
||||
|
||||
ret = ufshcd_get_pwr_dev_param(&ufs_exynos_cap,
|
||||
dev_max_params, dev_req_params);
|
||||
ret = ufshcd_negotiate_pwr_params(&host_params, dev_max_params, dev_req_params);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to determine capabilities\n", __func__);
|
||||
goto out;
|
||||
|
@ -293,9 +293,9 @@ static int ufs_hisi_link_startup_notify(struct ufs_hba *hba,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ufs_hisi_set_dev_cap(struct ufs_dev_params *hisi_param)
|
||||
static void ufs_hisi_set_dev_cap(struct ufs_host_params *host_params)
|
||||
{
|
||||
ufshcd_init_pwr_dev_param(hisi_param);
|
||||
ufshcd_init_host_params(host_params);
|
||||
}
|
||||
|
||||
static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
|
||||
@ -365,7 +365,7 @@ static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba,
|
||||
struct ufs_pa_layer_attr *dev_max_params,
|
||||
struct ufs_pa_layer_attr *dev_req_params)
|
||||
{
|
||||
struct ufs_dev_params ufs_hisi_cap;
|
||||
struct ufs_host_params host_params;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_req_params) {
|
||||
@ -377,9 +377,8 @@ static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba,
|
||||
|
||||
switch (status) {
|
||||
case PRE_CHANGE:
|
||||
ufs_hisi_set_dev_cap(&ufs_hisi_cap);
|
||||
ret = ufshcd_get_pwr_dev_param(&ufs_hisi_cap,
|
||||
dev_max_params, dev_req_params);
|
||||
ufs_hisi_set_dev_cap(&host_params);
|
||||
ret = ufshcd_negotiate_pwr_params(&host_params, dev_max_params, dev_req_params);
|
||||
if (ret) {
|
||||
dev_err(hba->dev,
|
||||
"%s: failed to determine capabilities\n", __func__);
|
||||
|
@ -996,16 +996,14 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
|
||||
struct ufs_pa_layer_attr *dev_req_params)
|
||||
{
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_dev_params host_cap;
|
||||
struct ufs_host_params host_params;
|
||||
int ret;
|
||||
|
||||
ufshcd_init_pwr_dev_param(&host_cap);
|
||||
host_cap.hs_rx_gear = UFS_HS_G5;
|
||||
host_cap.hs_tx_gear = UFS_HS_G5;
|
||||
ufshcd_init_host_params(&host_params);
|
||||
host_params.hs_rx_gear = UFS_HS_G5;
|
||||
host_params.hs_tx_gear = UFS_HS_G5;
|
||||
|
||||
ret = ufshcd_get_pwr_dev_param(&host_cap,
|
||||
dev_max_params,
|
||||
dev_req_params);
|
||||
ret = ufshcd_negotiate_pwr_params(&host_params, dev_max_params, dev_req_params);
|
||||
if (ret) {
|
||||
pr_info("%s: failed to determine capabilities\n",
|
||||
__func__);
|
||||
|
@ -4,26 +4,26 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#include <soc/qcom/ice.h>
|
||||
|
||||
#include <ufs/ufshcd.h>
|
||||
#include "ufshcd-pltfrm.h"
|
||||
#include <ufs/unipro.h>
|
||||
#include "ufs-qcom.h"
|
||||
#include <ufs/ufshci.h>
|
||||
#include <ufs/ufs_quirks.h>
|
||||
#include <ufs/unipro.h>
|
||||
#include "ufshcd-pltfrm.h"
|
||||
#include "ufs-qcom.h"
|
||||
|
||||
#define MCQ_QCFGPTR_MASK GENMASK(7, 0)
|
||||
#define MCQ_QCFGPTR_UNIT 0x200
|
||||
@ -90,8 +90,6 @@ static const struct __ufs_qcom_bw_table {
|
||||
[MODE_MAX][0][0] = { 7643136, 307200 },
|
||||
};
|
||||
|
||||
static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
|
||||
|
||||
static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
|
||||
static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up);
|
||||
|
||||
@ -158,7 +156,7 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
|
||||
cap = hba->crypto_cap_array[cfg->crypto_cap_idx];
|
||||
if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS ||
|
||||
cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
|
||||
return -EINVAL;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (config_enable)
|
||||
return qcom_ice_program_key(host->ice,
|
||||
@ -194,52 +192,12 @@ static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ufs_qcom_host_clk_get(struct device *dev,
|
||||
const char *name, struct clk **clk_out, bool optional)
|
||||
{
|
||||
struct clk *clk;
|
||||
int err = 0;
|
||||
|
||||
clk = devm_clk_get(dev, name);
|
||||
if (!IS_ERR(clk)) {
|
||||
*clk_out = clk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = PTR_ERR(clk);
|
||||
|
||||
if (optional && err == -ENOENT) {
|
||||
*clk_out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get %s err %d\n", name, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_host_clk_enable(struct device *dev,
|
||||
const char *name, struct clk *clk)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = clk_prepare_enable(clk);
|
||||
if (err)
|
||||
dev_err(dev, "%s: %s enable failed %d\n", __func__, name, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
|
||||
{
|
||||
if (!host->is_lane_clks_enabled)
|
||||
return;
|
||||
|
||||
clk_disable_unprepare(host->tx_l1_sync_clk);
|
||||
clk_disable_unprepare(host->tx_l0_sync_clk);
|
||||
clk_disable_unprepare(host->rx_l1_sync_clk);
|
||||
clk_disable_unprepare(host->rx_l0_sync_clk);
|
||||
clk_bulk_disable_unprepare(host->num_clks, host->clks);
|
||||
|
||||
host->is_lane_clks_enabled = false;
|
||||
}
|
||||
@ -247,73 +205,29 @@ static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
|
||||
static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host)
|
||||
{
|
||||
int err;
|
||||
struct device *dev = host->hba->dev;
|
||||
|
||||
if (host->is_lane_clks_enabled)
|
||||
return 0;
|
||||
|
||||
err = ufs_qcom_host_clk_enable(dev, "rx_lane0_sync_clk",
|
||||
host->rx_l0_sync_clk);
|
||||
err = clk_bulk_prepare_enable(host->num_clks, host->clks);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ufs_qcom_host_clk_enable(dev, "tx_lane0_sync_clk",
|
||||
host->tx_l0_sync_clk);
|
||||
if (err)
|
||||
goto disable_rx_l0;
|
||||
|
||||
err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk",
|
||||
host->rx_l1_sync_clk);
|
||||
if (err)
|
||||
goto disable_tx_l0;
|
||||
|
||||
err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk",
|
||||
host->tx_l1_sync_clk);
|
||||
if (err)
|
||||
goto disable_rx_l1;
|
||||
|
||||
host->is_lane_clks_enabled = true;
|
||||
|
||||
return 0;
|
||||
|
||||
disable_rx_l1:
|
||||
clk_disable_unprepare(host->rx_l1_sync_clk);
|
||||
disable_tx_l0:
|
||||
clk_disable_unprepare(host->tx_l0_sync_clk);
|
||||
disable_rx_l0:
|
||||
clk_disable_unprepare(host->rx_l0_sync_clk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
int err;
|
||||
struct device *dev = host->hba->dev;
|
||||
|
||||
if (has_acpi_companion(dev))
|
||||
return 0;
|
||||
|
||||
err = ufs_qcom_host_clk_get(dev, "rx_lane0_sync_clk",
|
||||
&host->rx_l0_sync_clk, false);
|
||||
if (err)
|
||||
err = devm_clk_bulk_get_all(dev, &host->clks);
|
||||
if (err <= 0)
|
||||
return err;
|
||||
|
||||
err = ufs_qcom_host_clk_get(dev, "tx_lane0_sync_clk",
|
||||
&host->tx_l0_sync_clk, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* In case of single lane per direction, don't read lane1 clocks */
|
||||
if (host->hba->lanes_per_direction > 1) {
|
||||
err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk",
|
||||
&host->rx_l1_sync_clk, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
|
||||
&host->tx_l1_sync_clk, true);
|
||||
}
|
||||
host->num_clks = err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -321,7 +235,7 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host)
|
||||
static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
|
||||
{
|
||||
int err;
|
||||
u32 tx_fsm_val = 0;
|
||||
u32 tx_fsm_val;
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS);
|
||||
|
||||
do {
|
||||
@ -360,9 +274,7 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
|
||||
|
||||
static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
|
||||
{
|
||||
ufshcd_rmwl(host->hba, QUNIPRO_SEL,
|
||||
ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
|
||||
REG_UFS_CFG1);
|
||||
ufshcd_rmwl(host->hba, QUNIPRO_SEL, QUNIPRO_SEL, REG_UFS_CFG1);
|
||||
|
||||
if (host->hw_ver.major >= 0x05)
|
||||
ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0);
|
||||
@ -376,18 +288,15 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
|
||||
*/
|
||||
static int ufs_qcom_host_reset(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
bool reenable_intr = false;
|
||||
bool reenable_intr;
|
||||
|
||||
if (!host->core_reset) {
|
||||
dev_warn(hba->dev, "%s: reset control not set\n", __func__);
|
||||
if (!host->core_reset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
reenable_intr = hba->is_irq_enabled;
|
||||
disable_irq(hba->irq);
|
||||
hba->is_irq_enabled = false;
|
||||
ufshcd_disable_irq(hba);
|
||||
|
||||
ret = reset_control_assert(host->core_reset);
|
||||
if (ret) {
|
||||
@ -404,16 +313,16 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba)
|
||||
usleep_range(200, 210);
|
||||
|
||||
ret = reset_control_deassert(host->core_reset);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s: core_reset deassert failed, err = %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
if (reenable_intr) {
|
||||
enable_irq(hba->irq);
|
||||
hba->is_irq_enabled = true;
|
||||
}
|
||||
if (reenable_intr)
|
||||
ufshcd_enable_irq(hba);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -422,18 +331,8 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
if (host->hw_ver.major == 0x1) {
|
||||
/*
|
||||
* HS-G3 operations may not reliably work on legacy QCOM
|
||||
* UFS host controller hardware even though capability
|
||||
* exchange during link startup phase may end up
|
||||
* negotiating maximum supported gear as G3.
|
||||
* Hence downgrade the maximum supported gear to HS-G2.
|
||||
*/
|
||||
return UFS_HS_G2;
|
||||
} else if (host->hw_ver.major >= 0x4) {
|
||||
if (host->hw_ver.major >= 0x4)
|
||||
return UFS_QCOM_MAX_GEAR(ufshcd_readl(hba, REG_UFS_PARAM0));
|
||||
}
|
||||
|
||||
/* Default is HS-G3 */
|
||||
return UFS_HS_G3;
|
||||
@ -442,14 +341,29 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
|
||||
static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_host_params *host_params = &host->host_params;
|
||||
struct phy *phy = host->generic_phy;
|
||||
enum phy_mode mode;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* HW ver 5 can only support up to HS-G5 Rate-A due to HW limitations.
|
||||
* If the HS-G5 PHY gear is used, update host_params->hs_rate to Rate-A,
|
||||
* so that the subsequent power mode change shall stick to Rate-A.
|
||||
*/
|
||||
if (host->hw_ver.major == 0x5) {
|
||||
if (host->phy_gear == UFS_HS_G5)
|
||||
host_params->hs_rate = PA_HS_MODE_A;
|
||||
else
|
||||
host_params->hs_rate = PA_HS_MODE_B;
|
||||
}
|
||||
|
||||
mode = host_params->hs_rate == PA_HS_MODE_B ? PHY_MODE_UFS_HS_B : PHY_MODE_UFS_HS_A;
|
||||
|
||||
/* Reset UFS Host Controller and PHY */
|
||||
ret = ufs_qcom_host_reset(hba);
|
||||
if (ret)
|
||||
dev_warn(hba->dev, "%s: host reset returned %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
|
||||
/* phy initialization - calibrate the phy */
|
||||
ret = phy_init(phy);
|
||||
@ -459,7 +373,9 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_set_mode_ext(phy, PHY_MODE_UFS_HS_B, host->phy_gear);
|
||||
ret = phy_set_mode_ext(phy, mode, host->phy_gear);
|
||||
if (ret)
|
||||
goto out_disable_phy;
|
||||
|
||||
/* power on phy - start serdes and phy's power and clocks */
|
||||
ret = phy_power_on(phy);
|
||||
@ -489,9 +405,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
||||
*/
|
||||
static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
|
||||
{
|
||||
ufshcd_writel(hba,
|
||||
ufshcd_readl(hba, REG_UFS_CFG2) | REG_UFS_CFG2_CGC_EN_ALL,
|
||||
REG_UFS_CFG2);
|
||||
ufshcd_rmwl(hba, REG_UFS_CFG2_CGC_EN_ALL, REG_UFS_CFG2_CGC_EN_ALL,
|
||||
REG_UFS_CFG2);
|
||||
|
||||
/* Ensure that HW clock gating is enabled before next operations */
|
||||
mb();
|
||||
@ -501,11 +416,14 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
|
||||
enum ufs_notify_change_status status)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
switch (status) {
|
||||
case PRE_CHANGE:
|
||||
ufs_qcom_power_up_sequence(hba);
|
||||
err = ufs_qcom_power_up_sequence(hba);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* The PHY PLL output is the source of tx/rx lane symbol
|
||||
* clocks, hence, enable the lane clocks only after PHY
|
||||
@ -544,41 +462,16 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_clk_info *clki;
|
||||
u32 core_clk_period_in_ns;
|
||||
u32 tx_clk_cycles_per_us = 0;
|
||||
unsigned long core_clk_rate = 0;
|
||||
u32 core_clk_cycles_per_us = 0;
|
||||
|
||||
static u32 pwm_fr_table[][2] = {
|
||||
{UFS_PWM_G1, 0x1},
|
||||
{UFS_PWM_G2, 0x1},
|
||||
{UFS_PWM_G3, 0x1},
|
||||
{UFS_PWM_G4, 0x1},
|
||||
};
|
||||
|
||||
static u32 hs_fr_table_rA[][2] = {
|
||||
{UFS_HS_G1, 0x1F},
|
||||
{UFS_HS_G2, 0x3e},
|
||||
{UFS_HS_G3, 0x7D},
|
||||
};
|
||||
|
||||
static u32 hs_fr_table_rB[][2] = {
|
||||
{UFS_HS_G1, 0x24},
|
||||
{UFS_HS_G2, 0x49},
|
||||
{UFS_HS_G3, 0x92},
|
||||
};
|
||||
u32 core_clk_cycles_per_us;
|
||||
|
||||
/*
|
||||
* The Qunipro controller does not use following registers:
|
||||
* SYS1CLK_1US_REG, TX_SYMBOL_CLK_1US_REG, CLK_NS_REG &
|
||||
* UFS_REG_PA_LINK_STARTUP_TIMER.
|
||||
* However UTP controller uses SYS1CLK_1US_REG register for Interrupt
|
||||
* UTP controller uses SYS1CLK_1US_REG register for Interrupt
|
||||
* Aggregation logic.
|
||||
* It is mandatory to write SYS1CLK_1US_REG register on UFS host
|
||||
* controller V4.0.0 onwards.
|
||||
*/
|
||||
if (host->hw_ver.major < 4 && ufs_qcom_cap_qunipro(host) &&
|
||||
!ufshcd_is_intr_aggr_allowed(hba))
|
||||
if (host->hw_ver.major < 4 && !ufshcd_is_intr_aggr_allowed(hba))
|
||||
return 0;
|
||||
|
||||
if (gear == 0) {
|
||||
@ -611,79 +504,6 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
|
||||
mb();
|
||||
}
|
||||
|
||||
if (ufs_qcom_cap_qunipro(host))
|
||||
return 0;
|
||||
|
||||
core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate;
|
||||
core_clk_period_in_ns <<= OFFSET_CLK_NS_REG;
|
||||
core_clk_period_in_ns &= MASK_CLK_NS_REG;
|
||||
|
||||
switch (hs) {
|
||||
case FASTAUTO_MODE:
|
||||
case FAST_MODE:
|
||||
if (rate == PA_HS_MODE_A) {
|
||||
if (gear > ARRAY_SIZE(hs_fr_table_rA)) {
|
||||
dev_err(hba->dev,
|
||||
"%s: index %d exceeds table size %zu\n",
|
||||
__func__, gear,
|
||||
ARRAY_SIZE(hs_fr_table_rA));
|
||||
return -EINVAL;
|
||||
}
|
||||
tx_clk_cycles_per_us = hs_fr_table_rA[gear-1][1];
|
||||
} else if (rate == PA_HS_MODE_B) {
|
||||
if (gear > ARRAY_SIZE(hs_fr_table_rB)) {
|
||||
dev_err(hba->dev,
|
||||
"%s: index %d exceeds table size %zu\n",
|
||||
__func__, gear,
|
||||
ARRAY_SIZE(hs_fr_table_rB));
|
||||
return -EINVAL;
|
||||
}
|
||||
tx_clk_cycles_per_us = hs_fr_table_rB[gear-1][1];
|
||||
} else {
|
||||
dev_err(hba->dev, "%s: invalid rate = %d\n",
|
||||
__func__, rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SLOWAUTO_MODE:
|
||||
case SLOW_MODE:
|
||||
if (gear > ARRAY_SIZE(pwm_fr_table)) {
|
||||
dev_err(hba->dev,
|
||||
"%s: index %d exceeds table size %zu\n",
|
||||
__func__, gear,
|
||||
ARRAY_SIZE(pwm_fr_table));
|
||||
return -EINVAL;
|
||||
}
|
||||
tx_clk_cycles_per_us = pwm_fr_table[gear-1][1];
|
||||
break;
|
||||
case UNCHANGED:
|
||||
default:
|
||||
dev_err(hba->dev, "%s: invalid mode = %d\n", __func__, hs);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) !=
|
||||
(core_clk_period_in_ns | tx_clk_cycles_per_us)) {
|
||||
/* this register 2 fields shall be written at once */
|
||||
ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us,
|
||||
REG_UFS_TX_SYMBOL_CLK_NS_US);
|
||||
/*
|
||||
* make sure above write gets applied before we return from
|
||||
* this function.
|
||||
*/
|
||||
mb();
|
||||
}
|
||||
|
||||
if (update_link_startup_timer && host->hw_ver.major != 0x5) {
|
||||
ufshcd_writel(hba, ((core_clk_rate / MSEC_PER_SEC) * 100),
|
||||
REG_UFS_CFG0);
|
||||
/*
|
||||
* make sure that this configuration is applied before
|
||||
* we return
|
||||
*/
|
||||
mb();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -691,7 +511,6 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
|
||||
enum ufs_notify_change_status status)
|
||||
{
|
||||
int err = 0;
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
switch (status) {
|
||||
case PRE_CHANGE:
|
||||
@ -702,11 +521,9 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ufs_qcom_cap_qunipro(host)) {
|
||||
err = ufs_qcom_set_core_clk_ctrl(hba, true);
|
||||
if (err)
|
||||
dev_err(hba->dev, "cfg core clk ctrl failed\n");
|
||||
}
|
||||
err = ufs_qcom_set_core_clk_ctrl(hba, true);
|
||||
if (err)
|
||||
dev_err(hba->dev, "cfg core clk ctrl failed\n");
|
||||
/*
|
||||
* Some UFS devices (and may be host) have issues if LCC is
|
||||
* enabled. So we are setting PA_Local_TX_LCC_Enable to 0
|
||||
@ -898,7 +715,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
|
||||
struct ufs_pa_layer_attr *dev_req_params)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_dev_params ufs_qcom_cap;
|
||||
struct ufs_host_params *host_params = &host->host_params;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_req_params) {
|
||||
@ -908,15 +725,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
|
||||
|
||||
switch (status) {
|
||||
case PRE_CHANGE:
|
||||
ufshcd_init_pwr_dev_param(&ufs_qcom_cap);
|
||||
ufs_qcom_cap.hs_rate = UFS_QCOM_LIMIT_HS_RATE;
|
||||
|
||||
/* This driver only supports symmetic gear setting i.e., hs_tx_gear == hs_rx_gear */
|
||||
ufs_qcom_cap.hs_tx_gear = ufs_qcom_cap.hs_rx_gear = ufs_qcom_get_hs_gear(hba);
|
||||
|
||||
ret = ufshcd_get_pwr_dev_param(&ufs_qcom_cap,
|
||||
dev_max_params,
|
||||
dev_req_params);
|
||||
ret = ufshcd_negotiate_pwr_params(host_params, dev_max_params, dev_req_params);
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s: failed to determine capabilities\n",
|
||||
__func__);
|
||||
@ -924,11 +733,12 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
|
||||
}
|
||||
|
||||
/*
|
||||
* Update phy_gear only when the gears are scaled to a higher value. This is
|
||||
* because, the PHY gear settings are backwards compatible and we only need to
|
||||
* change the PHY gear settings while scaling to higher gears.
|
||||
* During UFS driver probe, always update the PHY gear to match the negotiated
|
||||
* gear, so that, if quirk UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH is enabled,
|
||||
* the second init can program the optimal PHY settings. This allows one to start
|
||||
* the first init with either the minimum or the maximum support gear.
|
||||
*/
|
||||
if (dev_req_params->gear_tx > host->phy_gear)
|
||||
if (hba->ufshcd_state == UFSHCD_STATE_RESET)
|
||||
host->phy_gear = dev_req_params->gear_tx;
|
||||
|
||||
/* enable the device ref clock before changing to HS mode */
|
||||
@ -1005,12 +815,7 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
|
||||
|
||||
static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
if (host->hw_ver.major == 0x1)
|
||||
return ufshci_version(1, 1);
|
||||
else
|
||||
return ufshci_version(2, 0);
|
||||
return ufshci_version(2, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1026,46 +831,69 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
if (host->hw_ver.major == 0x01) {
|
||||
hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
|
||||
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP
|
||||
| UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE;
|
||||
|
||||
if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001)
|
||||
hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR;
|
||||
|
||||
hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
|
||||
}
|
||||
|
||||
if (host->hw_ver.major == 0x2) {
|
||||
if (host->hw_ver.major == 0x2)
|
||||
hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
|
||||
|
||||
if (!ufs_qcom_cap_qunipro(host))
|
||||
/* Legacy UniPro mode still need following quirks */
|
||||
hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
|
||||
| UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE
|
||||
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP);
|
||||
}
|
||||
|
||||
if (host->hw_ver.major > 0x3)
|
||||
hba->quirks |= UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
|
||||
}
|
||||
|
||||
static void ufs_qcom_set_caps(struct ufs_hba *hba)
|
||||
static void ufs_qcom_set_phy_gear(struct ufs_qcom_host *host)
|
||||
{
|
||||
struct ufs_host_params *host_params = &host->host_params;
|
||||
u32 val, dev_major;
|
||||
|
||||
host->phy_gear = host_params->hs_tx_gear;
|
||||
|
||||
if (host->hw_ver.major < 0x4) {
|
||||
/*
|
||||
* For controllers whose major HW version is < 4, power up the
|
||||
* PHY using minimum supported gear (UFS_HS_G2). Switching to
|
||||
* max gear will be performed during reinit if supported.
|
||||
* For newer controllers, whose major HW version is >= 4, power
|
||||
* up the PHY using max supported gear.
|
||||
*/
|
||||
host->phy_gear = UFS_HS_G2;
|
||||
} else if (host->hw_ver.major >= 0x5) {
|
||||
val = ufshcd_readl(host->hba, REG_UFS_DEBUG_SPARE_CFG);
|
||||
dev_major = FIELD_GET(UFS_DEV_VER_MAJOR_MASK, val);
|
||||
|
||||
/*
|
||||
* Since the UFS device version is populated, let's remove the
|
||||
* REINIT quirk as the negotiated gear won't change during boot.
|
||||
* So there is no need to do reinit.
|
||||
*/
|
||||
if (dev_major != 0x0)
|
||||
host->hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
|
||||
|
||||
/*
|
||||
* For UFS 3.1 device and older, power up the PHY using HS-G4
|
||||
* PHY gear to save power.
|
||||
*/
|
||||
if (dev_major > 0x0 && dev_major < 0x4)
|
||||
host->phy_gear = UFS_HS_G4;
|
||||
}
|
||||
}
|
||||
|
||||
static void ufs_qcom_set_host_params(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_host_params *host_params = &host->host_params;
|
||||
|
||||
ufshcd_init_host_params(host_params);
|
||||
|
||||
/* This driver only supports symmetic gear setting i.e., hs_tx_gear == hs_rx_gear */
|
||||
host_params->hs_tx_gear = host_params->hs_rx_gear = ufs_qcom_get_hs_gear(hba);
|
||||
}
|
||||
|
||||
static void ufs_qcom_set_caps(struct ufs_hba *hba)
|
||||
{
|
||||
hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
|
||||
hba->caps |= UFSHCD_CAP_CLK_SCALING | UFSHCD_CAP_WB_WITH_CLK_SCALING;
|
||||
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
|
||||
hba->caps |= UFSHCD_CAP_WB_EN;
|
||||
hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE;
|
||||
hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
|
||||
|
||||
if (host->hw_ver.major >= 0x2) {
|
||||
host->caps = UFS_QCOM_CAP_QUNIPRO |
|
||||
UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1188,16 +1016,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
||||
{
|
||||
int err;
|
||||
struct device *dev = hba->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct ufs_qcom_host *host;
|
||||
struct resource *res;
|
||||
struct ufs_clk_info *clki;
|
||||
|
||||
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host) {
|
||||
dev_err(dev, "%s: no memory for qcom ufs host\n", __func__);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Make a two way bind between the qcom host and the hba */
|
||||
host->hba = hba;
|
||||
@ -1235,34 +1059,16 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
||||
host->device_reset = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(host->device_reset)) {
|
||||
err = PTR_ERR(host->device_reset);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to acquire reset gpio: %d\n", err);
|
||||
err = dev_err_probe(dev, PTR_ERR(host->device_reset),
|
||||
"Failed to acquire device reset gpio\n");
|
||||
goto out_variant_clear;
|
||||
}
|
||||
|
||||
ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
|
||||
&host->hw_ver.minor, &host->hw_ver.step);
|
||||
|
||||
/*
|
||||
* for newer controllers, device reference clock control bit has
|
||||
* moved inside UFS controller register address space itself.
|
||||
*/
|
||||
if (host->hw_ver.major >= 0x02) {
|
||||
host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1;
|
||||
host->dev_ref_clk_en_mask = BIT(26);
|
||||
} else {
|
||||
/* "dev_ref_clk_ctrl_mem" is optional resource */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"dev_ref_clk_ctrl_mem");
|
||||
if (res) {
|
||||
host->dev_ref_clk_ctrl_mmio =
|
||||
devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(host->dev_ref_clk_ctrl_mmio))
|
||||
host->dev_ref_clk_ctrl_mmio = NULL;
|
||||
host->dev_ref_clk_en_mask = BIT(5);
|
||||
}
|
||||
}
|
||||
host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1;
|
||||
host->dev_ref_clk_en_mask = BIT(26);
|
||||
|
||||
list_for_each_entry(clki, &hba->clk_list_head, list) {
|
||||
if (!strcmp(clki->name, "core_clk_unipro"))
|
||||
@ -1275,6 +1081,8 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
||||
|
||||
ufs_qcom_set_caps(hba);
|
||||
ufs_qcom_advertise_quirks(hba);
|
||||
ufs_qcom_set_host_params(hba);
|
||||
ufs_qcom_set_phy_gear(host);
|
||||
|
||||
err = ufs_qcom_ice_init(host);
|
||||
if (err)
|
||||
@ -1282,9 +1090,6 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
||||
|
||||
ufs_qcom_setup_clocks(hba, true, POST_CHANGE);
|
||||
|
||||
if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
|
||||
ufs_qcom_hosts[hba->dev->id] = host;
|
||||
|
||||
ufs_qcom_get_default_testbus_cfg(host);
|
||||
err = ufs_qcom_testbus_config(host);
|
||||
if (err)
|
||||
@ -1292,12 +1097,6 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
||||
dev_warn(dev, "%s: failed to configure the testbus %d\n",
|
||||
__func__, err);
|
||||
|
||||
/*
|
||||
* Power up the PHY using the minimum supported gear (UFS_HS_G2).
|
||||
* Switching to max gear will be performed during reinit if supported.
|
||||
*/
|
||||
host->phy_gear = UFS_HS_G2;
|
||||
|
||||
return 0;
|
||||
|
||||
out_variant_clear:
|
||||
@ -1391,7 +1190,7 @@ static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up)
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct list_head *head = &hba->clk_list_head;
|
||||
struct ufs_clk_info *clki;
|
||||
u32 cycles_in_1us;
|
||||
u32 cycles_in_1us = 0;
|
||||
u32 core_clk_ctrl_reg;
|
||||
int err;
|
||||
|
||||
@ -1444,9 +1243,6 @@ static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)
|
||||
struct ufs_pa_layer_attr *attr = &host->dev_req_params;
|
||||
int ret;
|
||||
|
||||
if (!ufs_qcom_cap_qunipro(host))
|
||||
return 0;
|
||||
|
||||
ret = ufs_qcom_cfg_timers(hba, attr->gear_rx, attr->pwr_rx,
|
||||
attr->hs_rate, false, true);
|
||||
if (ret) {
|
||||
@ -1464,13 +1260,9 @@ static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba)
|
||||
|
||||
static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
int err;
|
||||
u32 core_clk_ctrl_reg;
|
||||
|
||||
if (!ufs_qcom_cap_qunipro(host))
|
||||
return 0;
|
||||
|
||||
err = ufshcd_dme_get(hba,
|
||||
UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
|
||||
&core_clk_ctrl_reg);
|
||||
@ -1489,11 +1281,6 @@ static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
|
||||
|
||||
static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
if (!ufs_qcom_cap_qunipro(host))
|
||||
return 0;
|
||||
|
||||
/* set unipro core clock attributes and clear clock divider */
|
||||
return ufs_qcom_set_core_clk_ctrl(hba, false);
|
||||
}
|
||||
@ -1502,7 +1289,7 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
|
||||
bool scale_up, enum ufs_notify_change_status status)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
/* check the host controller state before sending hibern8 cmd */
|
||||
if (!ufshcd_is_hba_active(hba))
|
||||
@ -1775,7 +1562,7 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba)
|
||||
struct platform_device *pdev = to_platform_device(hba->dev);
|
||||
struct ufshcd_res_info *res;
|
||||
struct resource *res_mem, *res_mcq;
|
||||
int i, ret = 0;
|
||||
int i, ret;
|
||||
|
||||
memcpy(hba->res, ufs_res_info, sizeof(ufs_res_info));
|
||||
|
||||
@ -1787,7 +1574,7 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba)
|
||||
if (!res->resource) {
|
||||
dev_info(hba->dev, "Resource %s not provided\n", res->name);
|
||||
if (i == RES_UFS)
|
||||
return -ENOMEM;
|
||||
return -ENODEV;
|
||||
continue;
|
||||
} else if (i == RES_UFS) {
|
||||
res_mem = res->resource;
|
||||
@ -1958,11 +1745,10 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
|
||||
platform_msi_domain_free_irqs(hba->dev);
|
||||
} else {
|
||||
if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 &&
|
||||
host->hw_ver.step == 0) {
|
||||
ufshcd_writel(hba,
|
||||
ufshcd_readl(hba, REG_UFS_CFG3) | 0x1F000,
|
||||
REG_UFS_CFG3);
|
||||
}
|
||||
host->hw_ver.step == 0)
|
||||
ufshcd_rmwl(hba, ESI_VEC_MASK,
|
||||
FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1),
|
||||
REG_UFS_CFG3);
|
||||
ufshcd_mcq_enable_esi(hba);
|
||||
}
|
||||
|
||||
|
@ -10,22 +10,17 @@
|
||||
#include <soc/qcom/ice.h>
|
||||
#include <ufs/ufshcd.h>
|
||||
|
||||
#define MAX_UFS_QCOM_HOSTS 1
|
||||
#define MAX_U32 (~(u32)0)
|
||||
#define MPHY_TX_FSM_STATE 0x41
|
||||
#define TX_FSM_HIBERN8 0x1
|
||||
#define HBRN8_POLL_TOUT_MS 100
|
||||
#define DEFAULT_CLK_RATE_HZ 1000000
|
||||
#define BUS_VECTOR_NAME_LEN 32
|
||||
#define MAX_SUPP_MAC 64
|
||||
#define MAX_ESI_VEC 32
|
||||
|
||||
#define UFS_HW_VER_MAJOR_MASK GENMASK(31, 28)
|
||||
#define UFS_HW_VER_MINOR_MASK GENMASK(27, 16)
|
||||
#define UFS_HW_VER_STEP_MASK GENMASK(15, 0)
|
||||
|
||||
/* vendor specific pre-defined parameters */
|
||||
#define SLOW 1
|
||||
#define FAST 2
|
||||
#define UFS_DEV_VER_MAJOR_MASK GENMASK(7, 4)
|
||||
|
||||
#define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B
|
||||
|
||||
@ -56,6 +51,8 @@ enum {
|
||||
UFS_AH8_CFG = 0xFC,
|
||||
|
||||
REG_UFS_CFG3 = 0x271C,
|
||||
|
||||
REG_UFS_DEBUG_SPARE_CFG = 0x284C,
|
||||
};
|
||||
|
||||
/* QCOM UFS host controller vendor specific debug registers */
|
||||
@ -93,9 +90,6 @@ enum {
|
||||
#define TEST_BUS_SEL GENMASK(22, 19)
|
||||
#define UFS_REG_TEST_BUS_EN BIT(30)
|
||||
|
||||
#define UFS_PHY_RESET_ENABLE 1
|
||||
#define UFS_PHY_RESET_DISABLE 0
|
||||
|
||||
/* bit definitions for REG_UFS_CFG2 register */
|
||||
#define UAWM_HW_CGC_EN BIT(0)
|
||||
#define UARM_HW_CGC_EN BIT(1)
|
||||
@ -106,6 +100,9 @@ enum {
|
||||
#define TMRLUT_HW_CGC_EN BIT(6)
|
||||
#define OCSC_HW_CGC_EN BIT(7)
|
||||
|
||||
/* bit definitions for REG_UFS_CFG3 register */
|
||||
#define ESI_VEC_MASK GENMASK(22, 12)
|
||||
|
||||
/* bit definitions for REG_UFS_PARAM0 */
|
||||
#define MAX_HS_GEAR_MASK GENMASK(6, 4)
|
||||
#define UFS_QCOM_MAX_GEAR(x) FIELD_GET(MAX_HS_GEAR_MASK, (x))
|
||||
@ -118,13 +115,6 @@ enum {
|
||||
DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\
|
||||
TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN)
|
||||
|
||||
/* bit offset */
|
||||
#define OFFSET_CLK_NS_REG 0xa
|
||||
|
||||
/* bit masks */
|
||||
#define MASK_TX_SYMBOL_CLK_1US_REG GENMASK(9, 0)
|
||||
#define MASK_CLK_NS_REG GENMASK(23, 10)
|
||||
|
||||
/* QUniPro Vendor specific attributes */
|
||||
#define PA_VS_CONFIG_REG1 0x9000
|
||||
#define DME_VS_CORE_CLK_CTRL 0xD002
|
||||
@ -158,8 +148,7 @@ ufs_qcom_get_controller_revision(struct ufs_hba *hba,
|
||||
|
||||
static inline void ufs_qcom_assert_reset(struct ufs_hba *hba)
|
||||
{
|
||||
ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, FIELD_PREP(UFS_PHY_SOFT_RESET, UFS_PHY_RESET_ENABLE),
|
||||
REG_UFS_CFG1);
|
||||
ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, UFS_PHY_SOFT_RESET, REG_UFS_CFG1);
|
||||
|
||||
/*
|
||||
* Make sure assertion of ufs phy reset is written to
|
||||
@ -170,8 +159,7 @@ static inline void ufs_qcom_assert_reset(struct ufs_hba *hba)
|
||||
|
||||
static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba)
|
||||
{
|
||||
ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, FIELD_PREP(UFS_PHY_SOFT_RESET, UFS_PHY_RESET_DISABLE),
|
||||
REG_UFS_CFG1);
|
||||
ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, 0, REG_UFS_CFG1);
|
||||
|
||||
/*
|
||||
* Make sure de-assertion of ufs phy reset is written to
|
||||
@ -195,28 +183,11 @@ struct ufs_qcom_testbus {
|
||||
struct gpio_desc;
|
||||
|
||||
struct ufs_qcom_host {
|
||||
/*
|
||||
* Set this capability if host controller supports the QUniPro mode
|
||||
* and if driver wants the Host controller to operate in QUniPro mode.
|
||||
* Note: By default this capability will be kept enabled if host
|
||||
* controller supports the QUniPro mode.
|
||||
*/
|
||||
#define UFS_QCOM_CAP_QUNIPRO 0x1
|
||||
|
||||
/*
|
||||
* Set this capability if host controller can retain the secure
|
||||
* configuration even after UFS controller core power collapse.
|
||||
*/
|
||||
#define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE 0x2
|
||||
u32 caps;
|
||||
|
||||
struct phy *generic_phy;
|
||||
struct ufs_hba *hba;
|
||||
struct ufs_pa_layer_attr dev_req_params;
|
||||
struct clk *rx_l0_sync_clk;
|
||||
struct clk *tx_l0_sync_clk;
|
||||
struct clk *rx_l1_sync_clk;
|
||||
struct clk *tx_l1_sync_clk;
|
||||
struct clk_bulk_data *clks;
|
||||
u32 num_clks;
|
||||
bool is_lane_clks_enabled;
|
||||
|
||||
struct icc_path *icc_ddr;
|
||||
@ -240,6 +211,7 @@ struct ufs_qcom_host {
|
||||
|
||||
struct gpio_desc *device_reset;
|
||||
|
||||
struct ufs_host_params host_params;
|
||||
u32 phy_gear;
|
||||
|
||||
bool esi_enabled;
|
||||
@ -261,9 +233,4 @@ ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg)
|
||||
|
||||
int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
|
||||
|
||||
static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
|
||||
{
|
||||
return host->caps & UFS_QCOM_CAP_QUNIPRO;
|
||||
}
|
||||
|
||||
#endif /* UFS_QCOM_H_ */
|
||||
|
@ -339,61 +339,60 @@ static int ufshcd_parse_operating_points(struct ufs_hba *hba)
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_pwr_dev_param - get finally agreed attributes for
|
||||
* power mode change
|
||||
* @pltfrm_param: pointer to platform parameters
|
||||
* ufshcd_negotiate_pwr_params - find power mode settings that are supported by
|
||||
* both the controller and the device
|
||||
* @host_params: pointer to host parameters
|
||||
* @dev_max: pointer to device attributes
|
||||
* @agreed_pwr: returned agreed attributes
|
||||
*
|
||||
* Return: 0 on success, non-zero value on failure.
|
||||
*/
|
||||
int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *pltfrm_param,
|
||||
const struct ufs_pa_layer_attr *dev_max,
|
||||
struct ufs_pa_layer_attr *agreed_pwr)
|
||||
int ufshcd_negotiate_pwr_params(const struct ufs_host_params *host_params,
|
||||
const struct ufs_pa_layer_attr *dev_max,
|
||||
struct ufs_pa_layer_attr *agreed_pwr)
|
||||
{
|
||||
int min_pltfrm_gear;
|
||||
int min_host_gear;
|
||||
int min_dev_gear;
|
||||
bool is_dev_sup_hs = false;
|
||||
bool is_pltfrm_max_hs = false;
|
||||
bool is_host_max_hs = false;
|
||||
|
||||
if (dev_max->pwr_rx == FAST_MODE)
|
||||
is_dev_sup_hs = true;
|
||||
|
||||
if (pltfrm_param->desired_working_mode == UFS_HS_MODE) {
|
||||
is_pltfrm_max_hs = true;
|
||||
min_pltfrm_gear = min_t(u32, pltfrm_param->hs_rx_gear,
|
||||
pltfrm_param->hs_tx_gear);
|
||||
if (host_params->desired_working_mode == UFS_HS_MODE) {
|
||||
is_host_max_hs = true;
|
||||
min_host_gear = min_t(u32, host_params->hs_rx_gear,
|
||||
host_params->hs_tx_gear);
|
||||
} else {
|
||||
min_pltfrm_gear = min_t(u32, pltfrm_param->pwm_rx_gear,
|
||||
pltfrm_param->pwm_tx_gear);
|
||||
min_host_gear = min_t(u32, host_params->pwm_rx_gear,
|
||||
host_params->pwm_tx_gear);
|
||||
}
|
||||
|
||||
/*
|
||||
* device doesn't support HS but
|
||||
* pltfrm_param->desired_working_mode is HS,
|
||||
* thus device and pltfrm_param don't agree
|
||||
* device doesn't support HS but host_params->desired_working_mode is HS,
|
||||
* thus device and host_params don't agree
|
||||
*/
|
||||
if (!is_dev_sup_hs && is_pltfrm_max_hs) {
|
||||
if (!is_dev_sup_hs && is_host_max_hs) {
|
||||
pr_info("%s: device doesn't support HS\n",
|
||||
__func__);
|
||||
return -ENOTSUPP;
|
||||
} else if (is_dev_sup_hs && is_pltfrm_max_hs) {
|
||||
} else if (is_dev_sup_hs && is_host_max_hs) {
|
||||
/*
|
||||
* since device supports HS, it supports FAST_MODE.
|
||||
* since pltfrm_param->desired_working_mode is also HS
|
||||
* since host_params->desired_working_mode is also HS
|
||||
* then final decision (FAST/FASTAUTO) is done according
|
||||
* to pltfrm_params as it is the restricting factor
|
||||
*/
|
||||
agreed_pwr->pwr_rx = pltfrm_param->rx_pwr_hs;
|
||||
agreed_pwr->pwr_rx = host_params->rx_pwr_hs;
|
||||
agreed_pwr->pwr_tx = agreed_pwr->pwr_rx;
|
||||
} else {
|
||||
/*
|
||||
* here pltfrm_param->desired_working_mode is PWM.
|
||||
* here host_params->desired_working_mode is PWM.
|
||||
* it doesn't matter whether device supports HS or PWM,
|
||||
* in both cases pltfrm_param->desired_working_mode will
|
||||
* in both cases host_params->desired_working_mode will
|
||||
* determine the mode
|
||||
*/
|
||||
agreed_pwr->pwr_rx = pltfrm_param->rx_pwr_pwm;
|
||||
agreed_pwr->pwr_rx = host_params->rx_pwr_pwm;
|
||||
agreed_pwr->pwr_tx = agreed_pwr->pwr_rx;
|
||||
}
|
||||
|
||||
@ -403,9 +402,9 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *pltfrm_param,
|
||||
* the same decision will be made for rx
|
||||
*/
|
||||
agreed_pwr->lane_tx = min_t(u32, dev_max->lane_tx,
|
||||
pltfrm_param->tx_lanes);
|
||||
host_params->tx_lanes);
|
||||
agreed_pwr->lane_rx = min_t(u32, dev_max->lane_rx,
|
||||
pltfrm_param->rx_lanes);
|
||||
host_params->rx_lanes);
|
||||
|
||||
/* device maximum gear is the minimum between device rx and tx gears */
|
||||
min_dev_gear = min_t(u32, dev_max->gear_rx, dev_max->gear_tx);
|
||||
@ -418,26 +417,26 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *pltfrm_param,
|
||||
* what is the gear, as it is the one that also decided previously what
|
||||
* pwr the device will be configured to.
|
||||
*/
|
||||
if ((is_dev_sup_hs && is_pltfrm_max_hs) ||
|
||||
(!is_dev_sup_hs && !is_pltfrm_max_hs)) {
|
||||
if ((is_dev_sup_hs && is_host_max_hs) ||
|
||||
(!is_dev_sup_hs && !is_host_max_hs)) {
|
||||
agreed_pwr->gear_rx =
|
||||
min_t(u32, min_dev_gear, min_pltfrm_gear);
|
||||
min_t(u32, min_dev_gear, min_host_gear);
|
||||
} else if (!is_dev_sup_hs) {
|
||||
agreed_pwr->gear_rx = min_dev_gear;
|
||||
} else {
|
||||
agreed_pwr->gear_rx = min_pltfrm_gear;
|
||||
agreed_pwr->gear_rx = min_host_gear;
|
||||
}
|
||||
agreed_pwr->gear_tx = agreed_pwr->gear_rx;
|
||||
|
||||
agreed_pwr->hs_rate = pltfrm_param->hs_rate;
|
||||
agreed_pwr->hs_rate = host_params->hs_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param);
|
||||
EXPORT_SYMBOL_GPL(ufshcd_negotiate_pwr_params);
|
||||
|
||||
void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param)
|
||||
void ufshcd_init_host_params(struct ufs_host_params *host_params)
|
||||
{
|
||||
*dev_param = (struct ufs_dev_params){
|
||||
*host_params = (struct ufs_host_params){
|
||||
.tx_lanes = UFS_LANE_2,
|
||||
.rx_lanes = UFS_LANE_2,
|
||||
.hs_rx_gear = UFS_HS_G3,
|
||||
@ -452,7 +451,7 @@ void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param)
|
||||
.desired_working_mode = UFS_HS_MODE,
|
||||
};
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_init_pwr_dev_param);
|
||||
EXPORT_SYMBOL_GPL(ufshcd_init_host_params);
|
||||
|
||||
/**
|
||||
* ufshcd_pltfrm_init - probe routine of the driver
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define UFS_PWM_MODE 1
|
||||
#define UFS_HS_MODE 2
|
||||
|
||||
struct ufs_dev_params {
|
||||
struct ufs_host_params {
|
||||
u32 pwm_rx_gear; /* pwm rx gear to work in */
|
||||
u32 pwm_tx_gear; /* pwm tx gear to work in */
|
||||
u32 hs_rx_gear; /* hs rx gear to work in */
|
||||
@ -25,10 +25,10 @@ struct ufs_dev_params {
|
||||
u32 desired_working_mode;
|
||||
};
|
||||
|
||||
int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *dev_param,
|
||||
const struct ufs_pa_layer_attr *dev_max,
|
||||
struct ufs_pa_layer_attr *agreed_pwr);
|
||||
void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param);
|
||||
int ufshcd_negotiate_pwr_params(const struct ufs_host_params *host_params,
|
||||
const struct ufs_pa_layer_attr *dev_max,
|
||||
struct ufs_pa_layer_attr *agreed_pwr);
|
||||
void ufshcd_init_host_params(struct ufs_host_params *host_params);
|
||||
int ufshcd_pltfrm_init(struct platform_device *pdev,
|
||||
const struct ufs_hba_variant_ops *vops);
|
||||
int ufshcd_populate_vreg(struct device *dev, const char *name,
|
||||
|
@ -491,6 +491,8 @@ struct mpi3_nvme_encapsulated_error_reply {
|
||||
#define MPI3MR_NVME_DATA_FORMAT_PRP 0
|
||||
#define MPI3MR_NVME_DATA_FORMAT_SGL1 1
|
||||
#define MPI3MR_NVME_DATA_FORMAT_SGL2 2
|
||||
#define MPI3MR_NVMESGL_DATA_SEGMENT 0x00
|
||||
#define MPI3MR_NVMESGL_LAST_SEGMENT 0x03
|
||||
|
||||
/* MPI3: task management related definitions */
|
||||
struct mpi3_scsi_task_mgmt_request {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
#include <uapi/scsi/scsi_bsg_ufs.h>
|
||||
#include <linux/time64.h>
|
||||
|
||||
/*
|
||||
* Using static_assert() is not allowed in UAPI header files. Hence the check
|
||||
@ -551,6 +552,14 @@ struct ufs_vreg_info {
|
||||
struct ufs_vreg *vdd_hba;
|
||||
};
|
||||
|
||||
/* UFS device descriptor wPeriodicRTCUpdate bit9 defines RTC time baseline */
|
||||
#define UFS_RTC_TIME_BASELINE BIT(9)
|
||||
|
||||
enum ufs_rtc_time {
|
||||
UFS_RTC_RELATIVE,
|
||||
UFS_RTC_ABSOLUTE
|
||||
};
|
||||
|
||||
struct ufs_dev_info {
|
||||
bool f_power_on_wp_en;
|
||||
/* Keeps information if any of the LU is power on write protected */
|
||||
@ -578,6 +587,11 @@ struct ufs_dev_info {
|
||||
|
||||
/* UFS EXT_IID Enable */
|
||||
bool b_ext_iid_en;
|
||||
|
||||
/* UFS RTC */
|
||||
enum ufs_rtc_time rtc_type;
|
||||
time64_t rtc_time_baseline;
|
||||
u32 rtc_update_period;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/blk-crypto-profile.h>
|
||||
#include <linux/blk-mq.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/fault-inject.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/dma-direction.h>
|
||||
@ -911,6 +912,8 @@ enum ufshcd_mcq_opr {
|
||||
* @mcq_base: Multi circular queue registers base address
|
||||
* @uhq: array of supported hardware queues
|
||||
* @dev_cmd_queue: Queue for issuing device management commands
|
||||
* @mcq_opr: MCQ operation and runtime registers
|
||||
* @ufs_rtc_update_work: A work for UFS RTC periodic update
|
||||
*/
|
||||
struct ufs_hba {
|
||||
void __iomem *mmio_base;
|
||||
@ -1057,6 +1060,10 @@ struct ufs_hba {
|
||||
struct dentry *debugfs_root;
|
||||
struct delayed_work debugfs_ee_work;
|
||||
u32 debugfs_ee_rate_limit_ms;
|
||||
#endif
|
||||
#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
|
||||
struct fault_attr trigger_eh_attr;
|
||||
struct fault_attr timeout_attr;
|
||||
#endif
|
||||
u32 luns_avail;
|
||||
unsigned int nr_hw_queues;
|
||||
@ -1071,6 +1078,8 @@ struct ufs_hba {
|
||||
struct ufs_hw_queue *uhq;
|
||||
struct ufs_hw_queue *dev_cmd_queue;
|
||||
struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX];
|
||||
|
||||
struct delayed_work ufs_rtc_update_work;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1231,6 +1240,8 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
|
||||
ufshcd_writel(hba, tmp, reg);
|
||||
}
|
||||
|
||||
void ufshcd_enable_irq(struct ufs_hba *hba);
|
||||
void ufshcd_disable_irq(struct ufs_hba *hba);
|
||||
int ufshcd_alloc_host(struct device *, struct ufs_hba **);
|
||||
void ufshcd_dealloc_host(struct ufs_hba *);
|
||||
int ufshcd_hba_enable(struct ufs_hba *hba);
|
||||
@ -1360,7 +1371,6 @@ static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba)
|
||||
return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
|
||||
}
|
||||
|
||||
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
|
||||
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
|
||||
void ufshcd_fixup_dev_quirks(struct ufs_hba *hba,
|
||||
const struct ufs_dev_quirk *fixups);
|
||||
|
@ -193,7 +193,7 @@
|
||||
#define DME_LocalAFC0ReqTimeOutVal 0xD043
|
||||
|
||||
/* PA power modes */
|
||||
enum {
|
||||
enum ufs_pa_pwr_mode {
|
||||
FAST_MODE = 1,
|
||||
SLOW_MODE = 2,
|
||||
FASTAUTO_MODE = 4,
|
||||
@ -205,7 +205,7 @@ enum {
|
||||
#define PWRMODE_RX_OFFSET 4
|
||||
|
||||
/* PA TX/RX Frequency Series */
|
||||
enum {
|
||||
enum ufs_hs_gear_rate {
|
||||
PA_HS_MODE_A = 1,
|
||||
PA_HS_MODE_B = 2,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user