Commit 86125df7 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents a74aa967 d55bac27
...@@ -398,7 +398,6 @@ config SATA_DWC_VDEBUG ...@@ -398,7 +398,6 @@ config SATA_DWC_VDEBUG
config SATA_HIGHBANK config SATA_HIGHBANK
tristate "Calxeda Highbank SATA support" tristate "Calxeda Highbank SATA support"
depends on HAS_DMA
depends on ARCH_HIGHBANK || COMPILE_TEST depends on ARCH_HIGHBANK || COMPILE_TEST
help help
This option enables support for the Calxeda Highbank SoC's This option enables support for the Calxeda Highbank SoC's
...@@ -408,7 +407,6 @@ config SATA_HIGHBANK ...@@ -408,7 +407,6 @@ config SATA_HIGHBANK
config SATA_MV config SATA_MV
tristate "Marvell SATA support" tristate "Marvell SATA support"
depends on HAS_DMA
depends on PCI || ARCH_DOVE || ARCH_MV78XX0 || \ depends on PCI || ARCH_DOVE || ARCH_MV78XX0 || \
ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST
select GENERIC_PHY select GENERIC_PHY
......
...@@ -400,6 +400,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { ...@@ -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, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake 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 */ /* 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, { 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) ...@@ -1280,6 +1281,59 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
return strcmp(buf, dmi->driver_data) < 0; 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) static bool ahci_broken_online(struct pci_dev *pdev)
{ {
#define ENCODE_BUSDEVFN(bus, slot, func) \ #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) ...@@ -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"); "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)) { if (ahci_broken_suspend(pdev)) {
hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
......
...@@ -82,7 +82,7 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv) ...@@ -82,7 +82,7 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
* *
* Return: 0 on success; Error code otherwise. * 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); void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp, port_fbs; u32 tmp, port_fbs;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nospec.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -1146,10 +1147,12 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, ...@@ -1146,10 +1147,12 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
/* get the slot number from the message */ /* get the slot number from the message */
pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; 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]; emp = &pp->em_priv[pmp];
else } else {
return -EINVAL; return -EINVAL;
}
/* mask off the activity bits if we are in sw_activity /* mask off the activity bits if we are in sw_activity
* mode, user should turn off sw_activity before setting * mode, user should turn off sw_activity before setting
......
...@@ -2493,6 +2493,9 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -2493,6 +2493,9 @@ int ata_dev_configure(struct ata_device *dev)
(id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2) (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
dev->horkage |= ATA_HORKAGE_NOLPM; dev->horkage |= ATA_HORKAGE_NOLPM;
if (ap->flags & ATA_FLAG_NO_LPM)
dev->horkage |= ATA_HORKAGE_NOLPM;
if (dev->horkage & ATA_HORKAGE_NOLPM) { if (dev->horkage & ATA_HORKAGE_NOLPM) {
ata_dev_warn(dev, "LPM support broken, forcing max_power\n"); ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER; 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, ...@@ -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) { list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
for (i = 0; i < ATA_MAX_QUEUE; i++) { ata_qc_for_each_raw(ap, qc, i) {
qc = __ata_qc_from_tag(ap, i);
if (qc->flags & ATA_QCFLAG_ACTIVE && if (qc->flags & ATA_QCFLAG_ACTIVE &&
qc->scsicmd == scmd) qc->scsicmd == scmd)
break; break;
...@@ -818,14 +817,13 @@ EXPORT_SYMBOL_GPL(ata_port_wait_eh); ...@@ -818,14 +817,13 @@ EXPORT_SYMBOL_GPL(ata_port_wait_eh);
static int ata_eh_nr_in_flight(struct ata_port *ap) static int ata_eh_nr_in_flight(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc;
unsigned int tag; unsigned int tag;
int nr = 0; int nr = 0;
/* count only non-internal commands */ /* count only non-internal commands */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each(ap, qc, tag) {
if (ata_tag_internal(tag)) if (qc)
continue;
if (ata_qc_from_tag(ap, tag))
nr++; nr++;
} }
...@@ -847,13 +845,13 @@ void ata_eh_fastdrain_timerfn(struct timer_list *t) ...@@ -847,13 +845,13 @@ void ata_eh_fastdrain_timerfn(struct timer_list *t)
goto out_unlock; goto out_unlock;
if (cnt == ap->fastdrain_cnt) { if (cnt == ap->fastdrain_cnt) {
struct ata_queued_cmd *qc;
unsigned int tag; unsigned int tag;
/* No progress during the last interval, tag all /* No progress during the last interval, tag all
* in-flight qcs as timed out and freeze the port. * in-flight qcs as timed out and freeze the port.
*/ */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each(ap, qc, tag) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
if (qc) if (qc)
qc->err_mask |= AC_ERR_TIMEOUT; qc->err_mask |= AC_ERR_TIMEOUT;
} }
...@@ -999,6 +997,7 @@ void ata_port_schedule_eh(struct ata_port *ap) ...@@ -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) static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
{ {
struct ata_queued_cmd *qc;
int tag, nr_aborted = 0; int tag, nr_aborted = 0;
WARN_ON(!ap->ops->error_handler); WARN_ON(!ap->ops->error_handler);
...@@ -1007,9 +1006,7 @@ static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) ...@@ -1007,9 +1006,7 @@ static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
ata_eh_set_pending(ap, 0); ata_eh_set_pending(ap, 0);
/* include internal tag in iteration */ /* include internal tag in iteration */
for (tag = 0; tag <= ATA_MAX_QUEUE; tag++) { ata_qc_for_each_with_internal(ap, qc, tag) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
if (qc && (!link || qc->dev->link == link)) { if (qc && (!link || qc->dev->link == link)) {
qc->flags |= ATA_QCFLAG_FAILED; qc->flags |= ATA_QCFLAG_FAILED;
ata_qc_complete(qc); ata_qc_complete(qc);
...@@ -1712,9 +1709,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ...@@ -1712,9 +1709,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
return; return;
/* has LLDD analyzed already? */ /* has LLDD analyzed already? */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_raw(ap, qc, tag) {
qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED)) if (!(qc->flags & ATA_QCFLAG_FAILED))
continue; continue;
...@@ -2136,6 +2131,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ...@@ -2136,6 +2131,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
{ {
struct ata_port *ap = link->ap; struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context; struct ata_eh_context *ehc = &link->eh_context;
struct ata_queued_cmd *qc;
struct ata_device *dev; struct ata_device *dev;
unsigned int all_err_mask = 0, eflags = 0; unsigned int all_err_mask = 0, eflags = 0;
int tag, nr_failed = 0, nr_quiet = 0; int tag, nr_failed = 0, nr_quiet = 0;
...@@ -2168,9 +2164,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ...@@ -2168,9 +2164,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
all_err_mask |= ehc->i.err_mask; all_err_mask |= ehc->i.err_mask;
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_raw(ap, qc, tag) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED) || if (!(qc->flags & ATA_QCFLAG_FAILED) ||
ata_dev_phys_link(qc->dev) != link) ata_dev_phys_link(qc->dev) != link)
continue; continue;
...@@ -2436,6 +2430,7 @@ static void ata_eh_link_report(struct ata_link *link) ...@@ -2436,6 +2430,7 @@ static void ata_eh_link_report(struct ata_link *link)
{ {
struct ata_port *ap = link->ap; struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context; struct ata_eh_context *ehc = &link->eh_context;
struct ata_queued_cmd *qc;
const char *frozen, *desc; const char *frozen, *desc;
char tries_buf[6] = ""; char tries_buf[6] = "";
int tag, nr_failed = 0; int tag, nr_failed = 0;
...@@ -2447,9 +2442,7 @@ static void ata_eh_link_report(struct ata_link *link) ...@@ -2447,9 +2442,7 @@ static void ata_eh_link_report(struct ata_link *link)
if (ehc->i.desc[0] != '\0') if (ehc->i.desc[0] != '\0')
desc = ehc->i.desc; desc = ehc->i.desc;
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_raw(ap, qc, tag) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED) || if (!(qc->flags & ATA_QCFLAG_FAILED) ||
ata_dev_phys_link(qc->dev) != link || ata_dev_phys_link(qc->dev) != link ||
((qc->flags & ATA_QCFLAG_QUIET) && ((qc->flags & ATA_QCFLAG_QUIET) &&
...@@ -2511,8 +2504,7 @@ static void ata_eh_link_report(struct ata_link *link) ...@@ -2511,8 +2504,7 @@ static void ata_eh_link_report(struct ata_link *link)
ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
#endif #endif
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_raw(ap, qc, tag) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
char data_buf[20] = ""; char data_buf[20] = "";
char cdb_buf[70] = ""; char cdb_buf[70] = "";
...@@ -3992,12 +3984,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ...@@ -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) void ata_eh_finish(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc;
int tag; int tag;
/* retry or finish qcs */ /* retry or finish qcs */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_raw(ap, qc, tag) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED)) if (!(qc->flags & ATA_QCFLAG_FAILED))
continue; continue;
......
...@@ -3805,10 +3805,20 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) ...@@ -3805,10 +3805,20 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
*/ */
goto invalid_param_len; goto invalid_param_len;
} }
if (block > dev->n_sectors)
goto out_of_range;
all = cdb[14] & 0x1; 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) && if (ata_ncq_enabled(qc->dev) &&
ata_fpdma_zac_mgmt_out_supported(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) ...@@ -3837,10 +3847,6 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
invalid_fld: invalid_fld:
ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
return 1; 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: invalid_param_len:
/* "Parameter list length error" */ /* "Parameter list length error" */
ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); 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, ...@@ -395,12 +395,6 @@ static inline unsigned int sata_fsl_tag(unsigned int tag,
{ {
/* We let libATA core do actual (queue) tag allocation */ /* 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)) { if (unlikely(tag >= SATA_FSL_QUEUE_DEPTH)) {
DPRINTK("tag %d invalid : out of range\n", tag); DPRINTK("tag %d invalid : out of range\n", tag);
return 0; return 0;
...@@ -1229,8 +1223,7 @@ static void sata_fsl_host_intr(struct ata_port *ap) ...@@ -1229,8 +1223,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
/* Workaround for data length mismatch errata */ /* Workaround for data length mismatch errata */
if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) { if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { ata_qc_for_each_with_internal(ap, qc, tag) {
qc = ata_qc_from_tag(ap, tag);
if (qc && ata_is_atapi(qc->tf.protocol)) { if (qc && ata_is_atapi(qc->tf.protocol)) {
u32 hcontrol; u32 hcontrol;
/* Set HControl[27] to clear error registers */ /* Set HControl[27] to clear error registers */
......
...@@ -675,7 +675,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev) ...@@ -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 ata_port *ap = ata_shost_to_port(sdev->host);
struct nv_adma_port_priv *pp = ap->private_data; struct nv_adma_port_priv *pp = ap->private_data;
struct nv_adma_port_priv *port0, *port1; struct nv_adma_port_priv *port0, *port1;
struct scsi_device *sdev0, *sdev1;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long segment_boundary, flags; unsigned long segment_boundary, flags;
unsigned short sg_tablesize; unsigned short sg_tablesize;
...@@ -736,8 +735,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev) ...@@ -736,8 +735,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
port0 = ap->host->ports[0]->private_data; port0 = ap->host->ports[0]->private_data;
port1 = ap->host->ports[1]->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) || if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
(port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
/* /*
......
...@@ -210,6 +210,7 @@ enum { ...@@ -210,6 +210,7 @@ enum {
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
/* (doesn't imply presence) */ /* (doesn't imply presence) */
ATA_FLAG_SATA = (1 << 1), 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_LOG_PAGE = (1 << 5), /* do not issue log page read */
ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */
ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */
...@@ -1495,6 +1496,29 @@ static inline bool ata_tag_valid(unsigned int tag) ...@@ -1495,6 +1496,29 @@ static inline bool ata_tag_valid(unsigned int tag)
return tag < ATA_MAX_QUEUE || ata_tag_internal(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 * device helpers
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment