mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-21 23:16:50 +08:00
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "All changes in drivers (well technically SES is enclosure services, but its change is minor). The biggest is the write combining change in lpfc followed by the additional NULL checks in mpi3mr" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: ufs: core: Fix shift out of bounds when MAXQ=32 scsi: ufs: core: Move link recovery for hibern8 exit failure to wl_resume scsi: ufs: core: Fix possible NULL pointer dereference in ufshcd_add_command_trace() scsi: snic: MAINTAINERS: Update snic maintainers scsi: snic: Remove unused linkstatus scsi: pm8001: Fix use-after-free in pm8001_queue_command() scsi: mpi3mr: Add NULL checks when resetting request and reply queues scsi: ufs: core: Reset urgent_bkops_lvl to allow runtime PM power mode scsi: ses: Fix devices attaching to different hosts scsi: ufs: core: Fix RPMB region size detection for UFS 2.2 scsi: storvsc: Fix scheduling while atomic on PREEMPT_RT scsi: lpfc: Properly set WC for DPP mapping
This commit is contained in:
@@ -6212,6 +6212,7 @@ F: drivers/scsi/fnic/
|
||||
|
||||
CISCO SCSI HBA DRIVER
|
||||
M: Karan Tilak Kumar <kartilak@cisco.com>
|
||||
M: Narsimhulu Musini <nmusini@cisco.com>
|
||||
M: Sesidhar Baddela <sebaddel@cisco.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
@@ -12025,6 +12025,8 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
|
||||
iounmap(phba->sli4_hba.conf_regs_memmap_p);
|
||||
if (phba->sli4_hba.dpp_regs_memmap_p)
|
||||
iounmap(phba->sli4_hba.dpp_regs_memmap_p);
|
||||
if (phba->sli4_hba.dpp_regs_memmap_wc_p)
|
||||
iounmap(phba->sli4_hba.dpp_regs_memmap_wc_p);
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_1:
|
||||
break;
|
||||
|
||||
@@ -15977,6 +15977,32 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __maybe_unused void __iomem *
|
||||
lpfc_dpp_wc_map(struct lpfc_hba *phba, uint8_t dpp_barset)
|
||||
{
|
||||
|
||||
/* DPP region is supposed to cover 64-bit BAR2 */
|
||||
if (dpp_barset != WQ_PCI_BAR_4_AND_5) {
|
||||
lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
|
||||
"3273 dpp_barset x%x != WQ_PCI_BAR_4_AND_5\n",
|
||||
dpp_barset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!phba->sli4_hba.dpp_regs_memmap_wc_p) {
|
||||
void __iomem *dpp_map;
|
||||
|
||||
dpp_map = ioremap_wc(phba->pci_bar2_map,
|
||||
pci_resource_len(phba->pcidev,
|
||||
PCI_64BIT_BAR4));
|
||||
|
||||
if (dpp_map)
|
||||
phba->sli4_hba.dpp_regs_memmap_wc_p = dpp_map;
|
||||
}
|
||||
|
||||
return phba->sli4_hba.dpp_regs_memmap_wc_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_modify_hba_eq_delay - Modify Delay Multiplier on EQs
|
||||
* @phba: HBA structure that EQs are on.
|
||||
@@ -16940,9 +16966,6 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
||||
uint8_t dpp_barset;
|
||||
uint32_t dpp_offset;
|
||||
uint8_t wq_create_version;
|
||||
#ifdef CONFIG_X86
|
||||
unsigned long pg_addr;
|
||||
#endif
|
||||
|
||||
/* sanity check on queue memory */
|
||||
if (!wq || !cq)
|
||||
@@ -17128,14 +17151,15 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/* Enable combined writes for DPP aperture */
|
||||
pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK;
|
||||
rc = set_memory_wc(pg_addr, 1);
|
||||
if (rc) {
|
||||
bar_memmap_p = lpfc_dpp_wc_map(phba, dpp_barset);
|
||||
if (!bar_memmap_p) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3272 Cannot setup Combined "
|
||||
"Write on WQ[%d] - disable DPP\n",
|
||||
wq->queue_id);
|
||||
phba->cfg_enable_dpp = 0;
|
||||
} else {
|
||||
wq->dpp_regaddr = bar_memmap_p + dpp_offset;
|
||||
}
|
||||
#else
|
||||
phba->cfg_enable_dpp = 0;
|
||||
|
||||
@@ -785,6 +785,9 @@ struct lpfc_sli4_hba {
|
||||
void __iomem *dpp_regs_memmap_p; /* Kernel memory mapped address for
|
||||
* dpp registers
|
||||
*/
|
||||
void __iomem *dpp_regs_memmap_wc_p;/* Kernel memory mapped address for
|
||||
* dpp registers with write combining
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/* IF Type 0, BAR 0 PCI cfg space reg mem map */
|
||||
|
||||
@@ -4807,21 +4807,25 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
|
||||
}
|
||||
|
||||
for (i = 0; i < mrioc->num_queues; i++) {
|
||||
mrioc->op_reply_qinfo[i].qid = 0;
|
||||
mrioc->op_reply_qinfo[i].ci = 0;
|
||||
mrioc->op_reply_qinfo[i].num_replies = 0;
|
||||
mrioc->op_reply_qinfo[i].ephase = 0;
|
||||
atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0);
|
||||
atomic_set(&mrioc->op_reply_qinfo[i].in_use, 0);
|
||||
mpi3mr_memset_op_reply_q_buffers(mrioc, i);
|
||||
if (mrioc->op_reply_qinfo) {
|
||||
mrioc->op_reply_qinfo[i].qid = 0;
|
||||
mrioc->op_reply_qinfo[i].ci = 0;
|
||||
mrioc->op_reply_qinfo[i].num_replies = 0;
|
||||
mrioc->op_reply_qinfo[i].ephase = 0;
|
||||
atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0);
|
||||
atomic_set(&mrioc->op_reply_qinfo[i].in_use, 0);
|
||||
mpi3mr_memset_op_reply_q_buffers(mrioc, i);
|
||||
}
|
||||
|
||||
mrioc->req_qinfo[i].ci = 0;
|
||||
mrioc->req_qinfo[i].pi = 0;
|
||||
mrioc->req_qinfo[i].num_requests = 0;
|
||||
mrioc->req_qinfo[i].qid = 0;
|
||||
mrioc->req_qinfo[i].reply_qid = 0;
|
||||
spin_lock_init(&mrioc->req_qinfo[i].q_lock);
|
||||
mpi3mr_memset_op_req_q_buffers(mrioc, i);
|
||||
if (mrioc->req_qinfo) {
|
||||
mrioc->req_qinfo[i].ci = 0;
|
||||
mrioc->req_qinfo[i].pi = 0;
|
||||
mrioc->req_qinfo[i].num_requests = 0;
|
||||
mrioc->req_qinfo[i].qid = 0;
|
||||
mrioc->req_qinfo[i].reply_qid = 0;
|
||||
spin_lock_init(&mrioc->req_qinfo[i].q_lock);
|
||||
mpi3mr_memset_op_req_q_buffers(mrioc, i);
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&mrioc->pend_large_data_sz, 0);
|
||||
|
||||
@@ -525,8 +525,9 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
||||
} else {
|
||||
task->task_done(task);
|
||||
}
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
|
||||
pm8001_dbg(pm8001_ha, IO, "pm8001_task_exec device gone\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
|
||||
|
||||
@@ -528,9 +528,8 @@ struct efd {
|
||||
};
|
||||
|
||||
static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
|
||||
void *data)
|
||||
struct efd *efd)
|
||||
{
|
||||
struct efd *efd = data;
|
||||
int i;
|
||||
struct ses_component *scomp;
|
||||
|
||||
@@ -683,7 +682,7 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
|
||||
if (efd.addr) {
|
||||
efd.dev = &sdev->sdev_gendev;
|
||||
|
||||
enclosure_for_each_device(ses_enclosure_find_by_addr, &efd);
|
||||
ses_enclosure_find_by_addr(edev, &efd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ struct vnic_dev {
|
||||
struct vnic_devcmd_notify *notify;
|
||||
struct vnic_devcmd_notify notify_copy;
|
||||
dma_addr_t notify_pa;
|
||||
u32 *linkstatus;
|
||||
dma_addr_t linkstatus_pa;
|
||||
struct vnic_stats *stats;
|
||||
dma_addr_t stats_pa;
|
||||
struct vnic_devcmd_fw_info *fw_info;
|
||||
@@ -650,8 +648,6 @@ int svnic_dev_init(struct vnic_dev *vdev, int arg)
|
||||
|
||||
int svnic_dev_link_status(struct vnic_dev *vdev)
|
||||
{
|
||||
if (vdev->linkstatus)
|
||||
return *vdev->linkstatus;
|
||||
|
||||
if (!vnic_dev_notify_ready(vdev))
|
||||
return 0;
|
||||
@@ -686,11 +682,6 @@ void svnic_dev_unregister(struct vnic_dev *vdev)
|
||||
sizeof(struct vnic_devcmd_notify),
|
||||
vdev->notify,
|
||||
vdev->notify_pa);
|
||||
if (vdev->linkstatus)
|
||||
dma_free_coherent(&vdev->pdev->dev,
|
||||
sizeof(u32),
|
||||
vdev->linkstatus,
|
||||
vdev->linkstatus_pa);
|
||||
if (vdev->stats)
|
||||
dma_free_coherent(&vdev->pdev->dev,
|
||||
sizeof(struct vnic_stats),
|
||||
|
||||
@@ -1856,8 +1856,9 @@ static enum scsi_qc_status storvsc_queuecommand(struct Scsi_Host *host,
|
||||
cmd_request->payload_sz = payload_sz;
|
||||
|
||||
/* Invokes the vsc to start an IO */
|
||||
ret = storvsc_do_io(dev, cmd_request, get_cpu());
|
||||
put_cpu();
|
||||
migrate_disable();
|
||||
ret = storvsc_do_io(dev, cmd_request, smp_processor_id());
|
||||
migrate_enable();
|
||||
|
||||
if (ret)
|
||||
scsi_dma_unmap(scmnd);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/sched/clock.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_dbg.h>
|
||||
@@ -517,8 +518,8 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, struct scsi_cmnd *cmd,
|
||||
|
||||
if (hba->mcq_enabled) {
|
||||
struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq);
|
||||
|
||||
hwq_id = hwq->id;
|
||||
if (hwq)
|
||||
hwq_id = hwq->id;
|
||||
} else {
|
||||
doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
|
||||
}
|
||||
@@ -4389,14 +4390,6 @@ out_unlock:
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
mutex_unlock(&hba->uic_cmd_mutex);
|
||||
|
||||
/*
|
||||
* If the h8 exit fails during the runtime resume process, it becomes
|
||||
* stuck and cannot be recovered through the error handler. To fix
|
||||
* this, use link recovery instead of the error handler.
|
||||
*/
|
||||
if (ret && hba->pm_op_in_progress)
|
||||
ret = ufshcd_link_recovery(hba);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5249,6 +5242,25 @@ static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev)
|
||||
hba->dev_info.rpmb_region_size[1] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION1_SIZE];
|
||||
hba->dev_info.rpmb_region_size[2] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION2_SIZE];
|
||||
hba->dev_info.rpmb_region_size[3] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION3_SIZE];
|
||||
|
||||
if (hba->dev_info.wspecversion <= 0x0220) {
|
||||
/*
|
||||
* These older spec chips have only one RPMB region,
|
||||
* sized between 128 kB minimum and 16 MB maximum.
|
||||
* No per region size fields are provided (respective
|
||||
* REGIONX_SIZE fields always contain zeros), so get
|
||||
* it from the logical block count and size fields for
|
||||
* compatibility
|
||||
*
|
||||
* (See JESD220C-2_2 Section 14.1.4.6
|
||||
* RPMB Unit Descriptor,* offset 13h, 4 bytes)
|
||||
*/
|
||||
hba->dev_info.rpmb_region_size[0] =
|
||||
(get_unaligned_be64(desc_buf
|
||||
+ RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_COUNT)
|
||||
<< desc_buf[RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_SIZE])
|
||||
/ SZ_128K;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5963,6 +5975,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
|
||||
|
||||
hba->auto_bkops_enabled = false;
|
||||
trace_ufshcd_auto_bkops_state(hba, "Disabled");
|
||||
hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
|
||||
hba->is_urgent_bkops_lvl_checked = false;
|
||||
out:
|
||||
return err;
|
||||
@@ -6066,7 +6079,7 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
|
||||
* impacted or critical. Handle these device by determining their urgent
|
||||
* bkops status at runtime.
|
||||
*/
|
||||
if (curr_status < BKOPS_STATUS_PERF_IMPACT) {
|
||||
if ((curr_status > BKOPS_STATUS_NO_OP) && (curr_status < BKOPS_STATUS_PERF_IMPACT)) {
|
||||
dev_err(hba->dev, "%s: device raised urgent BKOPS exception for bkops status %d\n",
|
||||
__func__, curr_status);
|
||||
/* update the current status as the urgent bkops level */
|
||||
@@ -7097,7 +7110,7 @@ static irqreturn_t ufshcd_handle_mcq_cq_events(struct ufs_hba *hba)
|
||||
|
||||
ret = ufshcd_vops_get_outstanding_cqs(hba, &outstanding_cqs);
|
||||
if (ret)
|
||||
outstanding_cqs = (1U << hba->nr_hw_queues) - 1;
|
||||
outstanding_cqs = (1ULL << hba->nr_hw_queues) - 1;
|
||||
|
||||
/* Exclude the poll queues */
|
||||
nr_queues = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL];
|
||||
@@ -10179,7 +10192,15 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
} else {
|
||||
dev_err(hba->dev, "%s: hibern8 exit failed %d\n",
|
||||
__func__, ret);
|
||||
goto vendor_suspend;
|
||||
/*
|
||||
* If the h8 exit fails during the runtime resume
|
||||
* process, it becomes stuck and cannot be recovered
|
||||
* through the error handler. To fix this, use link
|
||||
* recovery instead of the error handler.
|
||||
*/
|
||||
ret = ufshcd_link_recovery(hba);
|
||||
if (ret)
|
||||
goto vendor_suspend;
|
||||
}
|
||||
} else if (ufshcd_is_link_off(hba)) {
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user