Commit 36a07902 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  pata_atp867x: add Power Management support
  pata_atp867x: PIO support fixes
  pata_atp867x: clarifications in timings calculations and cable detection
  pata_atp867x: fix it to not claim MWDMA support
  libata: fix incorrect link online check during probe
  ahci: filter FPDMA non-zero offset enable for Aspire 3810T
  libata: make gtf_filter per-dev
  libata: implement more acpi filtering options
  libata: cosmetic updates
  ahci: display all AHCI 1.3 HBA capability flags (v2)
  pata_ali: trivial fix of a very frequent spelling mistake
  ahci: disable 64bit DMA by default on SB600s
parents f579bbcd 7affb32a
This diff is collapsed.
...@@ -20,19 +20,9 @@ ...@@ -20,19 +20,9 @@
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
enum { unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
ATA_ACPI_FILTER_SETXFER = 1 << 0,
ATA_ACPI_FILTER_LOCK = 1 << 1,
ATA_ACPI_FILTER_DIPM = 1 << 2,
ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
ATA_ACPI_FILTER_LOCK |
ATA_ACPI_FILTER_DIPM,
};
static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);
MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)"); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)");
#define NO_PORT_MULT 0xffff #define NO_PORT_MULT 0xffff
#define SATA_ADR(root, pmp) (((root) << 16) | (pmp)) #define SATA_ADR(root, pmp) (((root) << 16) | (pmp))
...@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev, ...@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev,
tf->command = gtf->tf[6]; /* 0x1f7 */ tf->command = gtf->tf[6]; /* 0x1f7 */
} }
static int ata_acpi_filter_tf(const struct ata_taskfile *tf, static int ata_acpi_filter_tf(struct ata_device *dev,
const struct ata_taskfile *tf,
const struct ata_taskfile *ptf) const struct ata_taskfile *ptf)
{ {
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) { if (dev->gtf_filter & ATA_ACPI_FILTER_SETXFER) {
/* libata doesn't use ACPI to configure transfer mode. /* libata doesn't use ACPI to configure transfer mode.
* It will only confuse device configuration. Skip. * It will only confuse device configuration. Skip.
*/ */
...@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, ...@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
return 1; return 1;
} }
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) { if (dev->gtf_filter & ATA_ACPI_FILTER_LOCK) {
/* BIOS writers, sorry but we don't wanna lock /* BIOS writers, sorry but we don't wanna lock
* features unless the user explicitly said so. * features unless the user explicitly said so.
*/ */
...@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, ...@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
return 1; return 1;
} }
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) { if (tf->command == ATA_CMD_SET_FEATURES &&
tf->feature == SETFEATURES_SATA_ENABLE) {
/* inhibit enabling DIPM */ /* inhibit enabling DIPM */
if (tf->command == ATA_CMD_SET_FEATURES && if (dev->gtf_filter & ATA_ACPI_FILTER_DIPM &&
tf->feature == SETFEATURES_SATA_ENABLE &&
tf->nsect == SATA_DIPM) tf->nsect == SATA_DIPM)
return 1; return 1;
/* inhibit FPDMA non-zero offset */
if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET &&
(tf->nsect == SATA_FPDMA_OFFSET ||
tf->nsect == SATA_FPDMA_IN_ORDER))
return 1;
/* inhibit FPDMA auto activation */
if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_AA &&
tf->nsect == SATA_FPDMA_AA)
return 1;
} }
return 0; return 0;
...@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, ...@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev,
pptf = &ptf; pptf = &ptf;
} }
if (!ata_acpi_filter_tf(&tf, pptf)) { if (!ata_acpi_filter_tf(dev, &tf, pptf)) {
rtf = tf; rtf = tf;
err_mask = ata_exec_internal(dev, &rtf, NULL, err_mask = ata_exec_internal(dev, &rtf, NULL,
DMA_NONE, NULL, 0, 0); DMA_NONE, NULL, 0, 0);
......
...@@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) ...@@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
dev->link = link; dev->link = link;
dev->devno = dev - link->device; dev->devno = dev - link->device;
#ifdef CONFIG_ATA_ACPI
dev->gtf_filter = ata_acpi_gtf_filter;
#endif
ata_dev_init(dev); ata_dev_init(dev);
} }
} }
......
...@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->flags &= ~ATA_DFLAG_SLEEPING; dev->flags &= ~ATA_DFLAG_SLEEPING;
if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { if (ata_phys_link_offline(ata_dev_phys_link(dev)))
/* apply class override */ continue;
if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_ATA; /* apply class override */
else if (lflags & ATA_LFLAG_ASSUME_SEMB) if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_SEMB_UNSUP; classes[dev->devno] = ATA_DEV_ATA;
} else else if (lflags & ATA_LFLAG_ASSUME_SEMB)
classes[dev->devno] = ATA_DEV_NONE; classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
} }
/* record current link speed */ /* record current link speed */
...@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
ap->pflags &= ~ATA_PFLAG_EH_PENDING; ap->pflags &= ~ATA_PFLAG_EH_PENDING;
spin_unlock_irqrestore(link->ap->lock, flags); spin_unlock_irqrestore(link->ap->lock, flags);
/* Make sure onlineness and classification result correspond. /*
* Make sure onlineness and classification result correspond.
* Hotplug could have happened during reset and some * Hotplug could have happened during reset and some
* controllers fail to wait while a drive is spinning up after * controllers fail to wait while a drive is spinning up after
* being hotplugged causing misdetection. By cross checking * being hotplugged causing misdetection. By cross checking
* link onlineness and classification result, those conditions * link on/offlineness and classification result, those
* can be reliably detected and retried. * conditions can be reliably detected and retried.
*/ */
nr_unknown = 0; nr_unknown = 0;
ata_for_each_dev(dev, link, ALL) { ata_for_each_dev(dev, link, ALL) {
/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ if (ata_phys_link_online(ata_dev_phys_link(dev))) {
if (classes[dev->devno] == ATA_DEV_UNKNOWN) { if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
classes[dev->devno] = ATA_DEV_NONE; ata_dev_printk(dev, KERN_DEBUG, "link online "
if (ata_phys_link_online(ata_dev_phys_link(dev))) "but device misclassifed\n");
classes[dev->devno] = ATA_DEV_NONE;
nr_unknown++; nr_unknown++;
}
} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
if (ata_class_enabled(classes[dev->devno]))
ata_dev_printk(dev, KERN_DEBUG, "link offline, "
"clearing class %d to NONE\n",
classes[dev->devno]);
classes[dev->devno] = ATA_DEV_NONE;
} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
"clearing UNKNOWN to NONE\n");
classes[dev->devno] = ATA_DEV_NONE;
} }
} }
if (classify && nr_unknown) { if (classify && nr_unknown) {
if (try < max_tries) { if (try < max_tries) {
ata_link_printk(link, KERN_WARNING, "link online but " ata_link_printk(link, KERN_WARNING, "link online but "
"device misclassified, retrying\n"); "%d devices misclassified, retrying\n",
nr_unknown);
failed_link = link; failed_link = link;
rc = -EAGAIN; rc = -EAGAIN;
goto fail; goto fail;
} }
ata_link_printk(link, KERN_WARNING, ata_link_printk(link, KERN_WARNING,
"link online but device misclassified, " "link online but %d devices misclassified, "
"device detection might fail\n"); "device detection might fail\n", nr_unknown);
} }
/* reset successful, schedule revalidation */ /* reset successful, schedule revalidation */
......
...@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); ...@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
/* libata-acpi.c */ /* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
extern unsigned int ata_acpi_gtf_filter;
extern void ata_acpi_associate_sata_port(struct ata_port *ap); extern void ata_acpi_associate_sata_port(struct ata_port *ap);
extern void ata_acpi_associate(struct ata_host *host); extern void ata_acpi_associate(struct ata_host *host);
extern void ata_acpi_dissociate(struct ata_host *host); extern void ata_acpi_dissociate(struct ata_host *host);
......
...@@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev) ...@@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev)
if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
ata_dev_printk(adev, KERN_WARNING, ata_dev_printk(adev, KERN_WARNING,
"WARNING: ATAPI DMA disabled for reliablity issues. It can be enabled\n"); "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
ata_dev_printk(adev, KERN_WARNING, ata_dev_printk(adev, KERN_WARNING,
"WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
} }
......
...@@ -118,20 +118,13 @@ struct atp867x_priv { ...@@ -118,20 +118,13 @@ struct atp867x_priv {
int pci66mhz; int pci66mhz;
}; };
static inline u8 atp867x_speed_to_mode(u8 speed)
{
return speed - XFER_UDMA_0 + 1;
}
static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct atp867x_priv *dp = ap->private_data; struct atp867x_priv *dp = ap->private_data;
u8 speed = adev->dma_mode; u8 speed = adev->dma_mode;
u8 b; u8 b;
u8 mode; u8 mode = speed - XFER_UDMA_0 + 1;
mode = atp867x_speed_to_mode(speed);
/* /*
* Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed
...@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) ...@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
iowrite8(b, dp->dma_mode); iowrite8(b, dp->dma_mode);
} }
static int atp867x_get_active_clocks_shifted(unsigned int clk) static int atp867x_get_active_clocks_shifted(struct ata_port *ap,
unsigned int clk)
{ {
struct atp867x_priv *dp = ap->private_data;
unsigned char clocks = clk; unsigned char clocks = clk;
/*
* Doc 6.6.9: increase the clock value by 1 for safer PIO speed
* on 66MHz bus
*/
if (dp->pci66mhz)
clocks++;
switch (clocks) { switch (clocks) {
case 0: case 0:
clocks = 1; clocks = 1;
break; break;
case 1 ... 7: case 1 ... 6:
break;
case 8 ... 12:
clocks = 7;
break; break;
default: default:
printk(KERN_WARNING "ATP867X: active %dclk is invalid. " printk(KERN_WARNING "ATP867X: active %dclk is invalid. "
"Using default 8clk.\n", clk); "Using 12clk.\n", clk);
clocks = 0; /* 8 clk */ case 9 ... 12:
clocks = 7; /* 12 clk */
break; break;
case 7:
case 8: /* default 8 clk */
clocks = 0;
goto active_clock_shift_done;
} }
active_clock_shift_done:
return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT;
} }
...@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) ...@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk)
break; break;
case 1 ... 11: case 1 ... 11:
break; break;
case 12: case 13:
clocks = 0; case 14:
break; --clocks; /* by the spec */
case 13: case 14:
--clocks;
break; break;
case 15: case 15:
break; break;
default: default:
printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " printk(KERN_WARNING "ATP867X: recover %dclk is invalid. "
"Using default 15clk.\n", clk); "Using default 12clk.\n", clk);
clocks = 0; /* 12 clk */ case 12: /* default 12 clk */
clocks = 0;
break; break;
} }
return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT; return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT;
} }
...@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) ...@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev)
b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK); b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK);
iowrite8(b, dp->dma_mode); iowrite8(b, dp->dma_mode);
b = atp867x_get_active_clocks_shifted(t.active) | b = atp867x_get_active_clocks_shifted(ap, t.active) |
atp867x_get_recover_clocks_shifted(t.recover); atp867x_get_recover_clocks_shifted(t.recover);
if (dp->pci66mhz)
b += 0x10;
if (adev->devno & 1) if (adev->devno & 1)
iowrite8(b, dp->slave_piospd); iowrite8(b, dp->slave_piospd);
else else
iowrite8(b, dp->mstr_piospd); iowrite8(b, dp->mstr_piospd);
/* b = atp867x_get_active_clocks_shifted(ap, t.act8b) |
* use the same value for comand timing as for PIO timimg atp867x_get_recover_clocks_shifted(t.rec8b);
*/
iowrite8(b, dp->eightb_piospd); iowrite8(b, dp->eightb_piospd);
} }
static int atp867x_cable_override(struct pci_dev *pdev)
{
if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP &&
(pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A ||
pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) {
return 1;
}
return 0;
}
static int atp867x_cable_detect(struct ata_port *ap) static int atp867x_cable_detect(struct ata_port *ap)
{ {
return ATA_CBL_PATA40_SHORT; struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (atp867x_cable_override(pdev))
return ATA_CBL_PATA40_SHORT;
return ATA_CBL_PATA_UNK;
} }
static struct scsi_host_template atp867x_sht = { static struct scsi_host_template atp867x_sht = {
...@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev, ...@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev,
static const struct ata_port_info info_867x = { static const struct ata_port_info info_867x = {
.flags = ATA_FLAG_SLAVE_POSS, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &atp867x_ops, .port_ops = &atp867x_ops,
}; };
...@@ -515,6 +533,23 @@ static int atp867x_init_one(struct pci_dev *pdev, ...@@ -515,6 +533,23 @@ static int atp867x_init_one(struct pci_dev *pdev,
return rc; return rc;
} }
#ifdef CONFIG_PM
static int atp867x_reinit_one(struct pci_dev *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
int rc;
rc = ata_pci_device_do_resume(pdev);
if (rc)
return rc;
atp867x_fixup(host);
ata_host_resume(host);
return 0;
}
#endif
static struct pci_device_id atp867x_pci_tbl[] = { static struct pci_device_id atp867x_pci_tbl[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 }, { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 }, { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 },
...@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = { ...@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = {
.id_table = atp867x_pci_tbl, .id_table = atp867x_pci_tbl,
.probe = atp867x_init_one, .probe = atp867x_init_one,
.remove = ata_pci_remove_one, .remove = ata_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ata_pci_device_suspend,
.resume = atp867x_reinit_one,
#endif
}; };
static int __init atp867x_init(void) static int __init atp867x_init(void)
......
...@@ -334,9 +334,12 @@ enum { ...@@ -334,9 +334,12 @@ enum {
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */ SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
/* SETFEATURE Sector counts for SATA features */ /* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */ SATA_FPDMA_OFFSET = 0x01, /* FPDMA non-zero buffer offsets */
SATA_DIPM = 0x03, /* Device Initiated Power Management */ SATA_FPDMA_AA = 0x02, /* FPDMA Setup FIS Auto-Activate */
SATA_FPDMA_AA = 0x02, /* DMA Setup FIS Auto-Activate */ SATA_DIPM = 0x03, /* Device Initiated Power Management */
SATA_FPDMA_IN_ORDER = 0x04, /* FPDMA in-order data delivery */
SATA_AN = 0x05, /* Asynchronous Notification */
SATA_SSP = 0x06, /* Software Settings Preservation */
/* feature values for SET_MAX */ /* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00, ATA_SET_MAX_ADDR = 0x00,
......
...@@ -418,6 +418,17 @@ enum { ...@@ -418,6 +418,17 @@ enum {
ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER | ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE | ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE |
ATA_TIMING_UDMA, ATA_TIMING_UDMA,
/* ACPI constants */
ATA_ACPI_FILTER_SETXFER = 1 << 0,
ATA_ACPI_FILTER_LOCK = 1 << 1,
ATA_ACPI_FILTER_DIPM = 1 << 2,
ATA_ACPI_FILTER_FPDMA_OFFSET = 1 << 3, /* FPDMA non-zero offset */
ATA_ACPI_FILTER_FPDMA_AA = 1 << 4, /* FPDMA auto activate */
ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
ATA_ACPI_FILTER_LOCK |
ATA_ACPI_FILTER_DIPM,
}; };
enum ata_xfer_mask { enum ata_xfer_mask {
...@@ -587,6 +598,7 @@ struct ata_device { ...@@ -587,6 +598,7 @@ struct ata_device {
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
acpi_handle acpi_handle; acpi_handle acpi_handle;
union acpi_object *gtf_cache; union acpi_object *gtf_cache;
unsigned int gtf_filter;
#endif #endif
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
u64 n_sectors; /* size of device, if ATA */ u64 n_sectors; /* size of device, if ATA */
......
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