Merge branch 'for-4.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata fixes from Tejun Heo: - Jens's patches to expand the usable command depth from 31 to 32 broke sata_fsl due to a subtle command iteration bug. Fixed by introducing explicit iteration helpers and using the correct variant. - On some laptops, enabling LPM by default reportedly led to occasional hard hangs. Blacklist the affected cases. - Other misc fixes / changes. * 'for-4.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: ata: Remove depends on HAS_DMA in case of platform dependency ata: Fix ZBC_OUT all bit handling ata: Fix ZBC_OUT command block check ahci: Add Intel Ice Lake LP PCI ID ahci: Disable LPM on Lenovo 50 series laptops with a too old BIOS sata_nv: remove redundant pointers sdev0 and sdev1 sata_fsl: remove dead code in tag retrieval sata_fsl: convert to command iterator libata: convert eh to command iterators libata: add command iterator helpers ata: ahci_mvebu: ahci_mvebu_stop_engine() can be static libahci: Fix possible Spectre-v1 pmp indexing in ahci_led_store()
This commit is contained in:
commit
86125df731
|
@ -398,7 +398,6 @@ config SATA_DWC_VDEBUG
|
|||
|
||||
config SATA_HIGHBANK
|
||||
tristate "Calxeda Highbank SATA support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_HIGHBANK || COMPILE_TEST
|
||||
help
|
||||
This option enables support for the Calxeda Highbank SoC's
|
||||
|
@ -408,7 +407,6 @@ config SATA_HIGHBANK
|
|||
|
||||
config SATA_MV
|
||||
tristate "Marvell SATA support"
|
||||
depends on HAS_DMA
|
||||
depends on PCI || ARCH_DOVE || ARCH_MV78XX0 || \
|
||||
ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST
|
||||
select GENERIC_PHY
|
||||
|
|
|
@ -400,6 +400,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
|
@ -1280,6 +1281,59 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
|
|||
return strcmp(buf, dmi->driver_data) < 0;
|
||||
}
|
||||
|
||||
static bool ahci_broken_lpm(struct pci_dev *pdev)
|
||||
{
|
||||
static const struct dmi_system_id sysids[] = {
|
||||
/* Various Lenovo 50 series have LPM issues with older BIOSen */
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
|
||||
},
|
||||
.driver_data = "20180406", /* 1.31 */
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
|
||||
},
|
||||
.driver_data = "20180420", /* 1.28 */
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
|
||||
},
|
||||
.driver_data = "20180315", /* 1.33 */
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
|
||||
},
|
||||
/*
|
||||
* Note date based on release notes, 2.35 has been
|
||||
* reported to be good, but I've been unable to get
|
||||
* a hold of the reporter to get the DMI BIOS date.
|
||||
* TODO: fix this.
|
||||
*/
|
||||
.driver_data = "20180310", /* 2.35 */
|
||||
},
|
||||
{ } /* terminate list */
|
||||
};
|
||||
const struct dmi_system_id *dmi = dmi_first_match(sysids);
|
||||
int year, month, date;
|
||||
char buf[9];
|
||||
|
||||
if (!dmi)
|
||||
return false;
|
||||
|
||||
dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
|
||||
snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
|
||||
|
||||
return strcmp(buf, dmi->driver_data) < 0;
|
||||
}
|
||||
|
||||
static bool ahci_broken_online(struct pci_dev *pdev)
|
||||
{
|
||||
#define ENCODE_BUSDEVFN(bus, slot, func) \
|
||||
|
@ -1694,6 +1748,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
"quirky BIOS, skipping spindown on poweroff\n");
|
||||
}
|
||||
|
||||
if (ahci_broken_lpm(pdev)) {
|
||||
pi.flags |= ATA_FLAG_NO_LPM;
|
||||
dev_warn(&pdev->dev,
|
||||
"BIOS update required for Link Power Management support\n");
|
||||
}
|
||||
|
||||
if (ahci_broken_suspend(pdev)) {
|
||||
hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
|
||||
dev_warn(&pdev->dev,
|
||||
|
|
|
@ -82,7 +82,7 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
|
|||
*
|
||||
* Return: 0 on success; Error code otherwise.
|
||||
*/
|
||||
int ahci_mvebu_stop_engine(struct ata_port *ap)
|
||||
static int ahci_mvebu_stop_engine(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = ahci_port_base(ap);
|
||||
u32 tmp, port_fbs;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -1146,10 +1147,12 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
|
|||
|
||||
/* get the slot number from the message */
|
||||
pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
|
||||
if (pmp < EM_MAX_SLOTS)
|
||||
if (pmp < EM_MAX_SLOTS) {
|
||||
pmp = array_index_nospec(pmp, EM_MAX_SLOTS);
|
||||
emp = &pp->em_priv[pmp];
|
||||
else
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* mask off the activity bits if we are in sw_activity
|
||||
* mode, user should turn off sw_activity before setting
|
||||
|
|
|
@ -2493,6 +2493,9 @@ int ata_dev_configure(struct ata_device *dev)
|
|||
(id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
|
||||
dev->horkage |= ATA_HORKAGE_NOLPM;
|
||||
|
||||
if (ap->flags & ATA_FLAG_NO_LPM)
|
||||
dev->horkage |= ATA_HORKAGE_NOLPM;
|
||||
|
||||
if (dev->horkage & ATA_HORKAGE_NOLPM) {
|
||||
ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
|
||||
dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
|
||||
|
|
|
@ -614,8 +614,7 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
|
|||
list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
|
||||
struct ata_queued_cmd *qc;
|
||||
|
||||
for (i = 0; i < ATA_MAX_QUEUE; i++) {
|
||||
qc = __ata_qc_from_tag(ap, i);
|
||||
ata_qc_for_each_raw(ap, qc, i) {
|
||||
if (qc->flags & ATA_QCFLAG_ACTIVE &&
|
||||
qc->scsicmd == scmd)
|
||||
break;
|
||||
|
@ -818,14 +817,13 @@ EXPORT_SYMBOL_GPL(ata_port_wait_eh);
|
|||
|
||||
static int ata_eh_nr_in_flight(struct ata_port *ap)
|
||||
{
|
||||
struct ata_queued_cmd *qc;
|
||||
unsigned int tag;
|
||||
int nr = 0;
|
||||
|
||||
/* count only non-internal commands */
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
if (ata_tag_internal(tag))
|
||||
continue;
|
||||
if (ata_qc_from_tag(ap, tag))
|
||||
ata_qc_for_each(ap, qc, tag) {
|
||||
if (qc)
|
||||
nr++;
|
||||
}
|
||||
|
||||
|
@ -847,13 +845,13 @@ void ata_eh_fastdrain_timerfn(struct timer_list *t)
|
|||
goto out_unlock;
|
||||
|
||||
if (cnt == ap->fastdrain_cnt) {
|
||||
struct ata_queued_cmd *qc;
|
||||
unsigned int tag;
|
||||
|
||||
/* No progress during the last interval, tag all
|
||||
* in-flight qcs as timed out and freeze the port.
|
||||
*/
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
|
||||
ata_qc_for_each(ap, qc, tag) {
|
||||
if (qc)
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
}
|
||||
|
@ -999,6 +997,7 @@ void ata_port_schedule_eh(struct ata_port *ap)
|
|||
|
||||
static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
|
||||
{
|
||||
struct ata_queued_cmd *qc;
|
||||
int tag, nr_aborted = 0;
|
||||
|
||||
WARN_ON(!ap->ops->error_handler);
|
||||
|
@ -1007,9 +1006,7 @@ static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
|
|||
ata_eh_set_pending(ap, 0);
|
||||
|
||||
/* include internal tag in iteration */
|
||||
for (tag = 0; tag <= ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
|
||||
|
||||
ata_qc_for_each_with_internal(ap, qc, tag) {
|
||||
if (qc && (!link || qc->dev->link == link)) {
|
||||
qc->flags |= ATA_QCFLAG_FAILED;
|
||||
ata_qc_complete(qc);
|
||||
|
@ -1712,9 +1709,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
|
|||
return;
|
||||
|
||||
/* has LLDD analyzed already? */
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
qc = __ata_qc_from_tag(ap, tag);
|
||||
|
||||
ata_qc_for_each_raw(ap, qc, tag) {
|
||||
if (!(qc->flags & ATA_QCFLAG_FAILED))
|
||||
continue;
|
||||
|
||||
|
@ -2136,6 +2131,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
|||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
struct ata_queued_cmd *qc;
|
||||
struct ata_device *dev;
|
||||
unsigned int all_err_mask = 0, eflags = 0;
|
||||
int tag, nr_failed = 0, nr_quiet = 0;
|
||||
|
@ -2168,9 +2164,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
|||
|
||||
all_err_mask |= ehc->i.err_mask;
|
||||
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
|
||||
|
||||
ata_qc_for_each_raw(ap, qc, tag) {
|
||||
if (!(qc->flags & ATA_QCFLAG_FAILED) ||
|
||||
ata_dev_phys_link(qc->dev) != link)
|
||||
continue;
|
||||
|
@ -2436,6 +2430,7 @@ static void ata_eh_link_report(struct ata_link *link)
|
|||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
struct ata_queued_cmd *qc;
|
||||
const char *frozen, *desc;
|
||||
char tries_buf[6] = "";
|
||||
int tag, nr_failed = 0;
|
||||
|
@ -2447,9 +2442,7 @@ static void ata_eh_link_report(struct ata_link *link)
|
|||
if (ehc->i.desc[0] != '\0')
|
||||
desc = ehc->i.desc;
|
||||
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
|
||||
|
||||
ata_qc_for_each_raw(ap, qc, tag) {
|
||||
if (!(qc->flags & ATA_QCFLAG_FAILED) ||
|
||||
ata_dev_phys_link(qc->dev) != link ||
|
||||
((qc->flags & ATA_QCFLAG_QUIET) &&
|
||||
|
@ -2511,8 +2504,7 @@ static void ata_eh_link_report(struct ata_link *link)
|
|||
ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
|
||||
#endif
|
||||
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
|
||||
ata_qc_for_each_raw(ap, qc, tag) {
|
||||
struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
|
||||
char data_buf[20] = "";
|
||||
char cdb_buf[70] = "";
|
||||
|
@ -3992,12 +3984,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||
*/
|
||||
void ata_eh_finish(struct ata_port *ap)
|
||||
{
|
||||
struct ata_queued_cmd *qc;
|
||||
int tag;
|
||||
|
||||
/* retry or finish qcs */
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
|
||||
|
||||
ata_qc_for_each_raw(ap, qc, tag) {
|
||||
if (!(qc->flags & ATA_QCFLAG_FAILED))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -3805,10 +3805,20 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
|
|||
*/
|
||||
goto invalid_param_len;
|
||||
}
|
||||
if (block > dev->n_sectors)
|
||||
goto out_of_range;
|
||||
|
||||
all = cdb[14] & 0x1;
|
||||
if (all) {
|
||||
/*
|
||||
* Ignore the block address (zone ID) as defined by ZBC.
|
||||
*/
|
||||
block = 0;
|
||||
} else if (block >= dev->n_sectors) {
|
||||
/*
|
||||
* Block must be a valid zone ID (a zone start LBA).
|
||||
*/
|
||||
fp = 2;
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
if (ata_ncq_enabled(qc->dev) &&
|
||||
ata_fpdma_zac_mgmt_out_supported(qc->dev)) {
|
||||
|
@ -3837,10 +3847,6 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
|
|||
invalid_fld:
|
||||
ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
|
||||
return 1;
|
||||
out_of_range:
|
||||
/* "Logical Block Address out of range" */
|
||||
ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x00);
|
||||
return 1;
|
||||
invalid_param_len:
|
||||
/* "Parameter list length error" */
|
||||
ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
|
||||
|
|
|
@ -395,12 +395,6 @@ static inline unsigned int sata_fsl_tag(unsigned int tag,
|
|||
{
|
||||
/* We let libATA core do actual (queue) tag allocation */
|
||||
|
||||
/* all non NCQ/queued commands should have tag#0 */
|
||||
if (ata_tag_internal(tag)) {
|
||||
DPRINTK("mapping internal cmds to tag#0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(tag >= SATA_FSL_QUEUE_DEPTH)) {
|
||||
DPRINTK("tag %d invalid : out of range\n", tag);
|
||||
return 0;
|
||||
|
@ -1229,8 +1223,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
|||
|
||||
/* Workaround for data length mismatch errata */
|
||||
if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
qc = ata_qc_from_tag(ap, tag);
|
||||
ata_qc_for_each_with_internal(ap, qc, tag) {
|
||||
if (qc && ata_is_atapi(qc->tf.protocol)) {
|
||||
u32 hcontrol;
|
||||
/* Set HControl[27] to clear error registers */
|
||||
|
|
|
@ -675,7 +675,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
|
|||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct nv_adma_port_priv *pp = ap->private_data;
|
||||
struct nv_adma_port_priv *port0, *port1;
|
||||
struct scsi_device *sdev0, *sdev1;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
unsigned long segment_boundary, flags;
|
||||
unsigned short sg_tablesize;
|
||||
|
@ -736,8 +735,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
|
|||
|
||||
port0 = ap->host->ports[0]->private_data;
|
||||
port1 = ap->host->ports[1]->private_data;
|
||||
sdev0 = ap->host->ports[0]->link.device[0].sdev;
|
||||
sdev1 = ap->host->ports[1]->link.device[0].sdev;
|
||||
if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
|
||||
(port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
|
||||
/*
|
||||
|
|
|
@ -210,6 +210,7 @@ enum {
|
|||
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
|
||||
/* (doesn't imply presence) */
|
||||
ATA_FLAG_SATA = (1 << 1),
|
||||
ATA_FLAG_NO_LPM = (1 << 2), /* host not happy with LPM */
|
||||
ATA_FLAG_NO_LOG_PAGE = (1 << 5), /* do not issue log page read */
|
||||
ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */
|
||||
ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */
|
||||
|
@ -1495,6 +1496,29 @@ static inline bool ata_tag_valid(unsigned int tag)
|
|||
return tag < ATA_MAX_QUEUE || ata_tag_internal(tag);
|
||||
}
|
||||
|
||||
#define __ata_qc_for_each(ap, qc, tag, max_tag, fn) \
|
||||
for ((tag) = 0; (tag) < (max_tag) && \
|
||||
({ qc = fn((ap), (tag)); 1; }); (tag)++) \
|
||||
|
||||
/*
|
||||
* Internal use only, iterate commands ignoring error handling and
|
||||
* status of 'qc'.
|
||||
*/
|
||||
#define ata_qc_for_each_raw(ap, qc, tag) \
|
||||
__ata_qc_for_each(ap, qc, tag, ATA_MAX_QUEUE, __ata_qc_from_tag)
|
||||
|
||||
/*
|
||||
* Iterate all potential commands that can be queued
|
||||
*/
|
||||
#define ata_qc_for_each(ap, qc, tag) \
|
||||
__ata_qc_for_each(ap, qc, tag, ATA_MAX_QUEUE, ata_qc_from_tag)
|
||||
|
||||
/*
|
||||
* Like ata_qc_for_each, but with the internal tag included
|
||||
*/
|
||||
#define ata_qc_for_each_with_internal(ap, qc, tag) \
|
||||
__ata_qc_for_each(ap, qc, tag, ATA_MAX_QUEUE + 1, ata_qc_from_tag)
|
||||
|
||||
/*
|
||||
* device helpers
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue