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 @@
#include <acpi/acpi_bus.h>
enum {
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;
unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
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 SATA_ADR(root, pmp) (((root) << 16) | (pmp))
......@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev,
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)
{
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.
* It will only confuse device configuration. Skip.
*/
......@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
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
* features unless the user explicitly said so.
*/
......@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
return 1;
}
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) {
/* inhibit enabling DIPM */
if (tf->command == ATA_CMD_SET_FEATURES &&
tf->feature == SETFEATURES_SATA_ENABLE &&
tf->feature == SETFEATURES_SATA_ENABLE) {
/* inhibit enabling DIPM */
if (dev->gtf_filter & ATA_ACPI_FILTER_DIPM &&
tf->nsect == SATA_DIPM)
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;
......@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev,
pptf = &ptf;
}
if (!ata_acpi_filter_tf(&tf, pptf)) {
if (!ata_acpi_filter_tf(dev, &tf, pptf)) {
rtf = tf;
err_mask = ata_exec_internal(dev, &rtf, NULL,
DMA_NONE, NULL, 0, 0);
......
......@@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
dev->link = link;
dev->devno = dev - link->device;
#ifdef CONFIG_ATA_ACPI
dev->gtf_filter = ata_acpi_gtf_filter;
#endif
ata_dev_init(dev);
}
}
......
......@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
dev->pio_mode = XFER_PIO_0;
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)))
continue;
/* apply class override */
if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_ATA;
else if (lflags & ATA_LFLAG_ASSUME_SEMB)
classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
} else
classes[dev->devno] = ATA_DEV_NONE;
}
/* record current link speed */
......@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
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
* controllers fail to wait while a drive is spinning up after
* being hotplugged causing misdetection. By cross checking
* link onlineness and classification result, those conditions
* can be reliably detected and retried.
* link on/offlineness and classification result, those
* conditions can be reliably detected and retried.
*/
nr_unknown = 0;
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) {
ata_dev_printk(dev, KERN_DEBUG, "link online "
"but device misclassifed\n");
classes[dev->devno] = ATA_DEV_NONE;
if (ata_phys_link_online(ata_dev_phys_link(dev)))
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 (try < max_tries) {
ata_link_printk(link, KERN_WARNING, "link online but "
"device misclassified, retrying\n");
"%d devices misclassified, retrying\n",
nr_unknown);
failed_link = link;
rc = -EAGAIN;
goto fail;
}
ata_link_printk(link, KERN_WARNING,
"link online but device misclassified, "
"device detection might fail\n");
"link online but %d devices misclassified, "
"device detection might fail\n", nr_unknown);
}
/* reset successful, schedule revalidation */
......
......@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
/* libata-acpi.c */
#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(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)
if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
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,
"WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
}
......
......@@ -118,20 +118,13 @@ struct atp867x_priv {
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)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct atp867x_priv *dp = ap->private_data;
u8 speed = adev->dma_mode;
u8 b;
u8 mode;
mode = atp867x_speed_to_mode(speed);
u8 mode = speed - XFER_UDMA_0 + 1;
/*
* 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)
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;
/*
* Doc 6.6.9: increase the clock value by 1 for safer PIO speed
* on 66MHz bus
*/
if (dp->pci66mhz)
clocks++;
switch (clocks) {
case 0:
clocks = 1;
break;
case 1 ... 7:
break;
case 8 ... 12:
clocks = 7;
case 1 ... 6:
break;
default:
printk(KERN_WARNING "ATP867X: active %dclk is invalid. "
"Using default 8clk.\n", clk);
clocks = 0; /* 8 clk */
"Using 12clk.\n", clk);
case 9 ... 12:
clocks = 7; /* 12 clk */
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;
}
......@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk)
break;
case 1 ... 11:
break;
case 12:
clocks = 0;
break;
case 13: case 14:
--clocks;
case 13:
case 14:
--clocks; /* by the spec */
break;
case 15:
break;
default:
printk(KERN_WARNING "ATP867X: recover %dclk is invalid. "
"Using default 15clk.\n", clk);
clocks = 0; /* 12 clk */
"Using default 12clk.\n", clk);
case 12: /* default 12 clk */
clocks = 0;
break;
}
return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT;
}
......@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev)
b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK);
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);
if (dp->pci66mhz)
b += 0x10;
if (adev->devno & 1)
iowrite8(b, dp->slave_piospd);
else
iowrite8(b, dp->mstr_piospd);
/*
* use the same value for comand timing as for PIO timimg
*/
b = atp867x_get_active_clocks_shifted(ap, t.act8b) |
atp867x_get_recover_clocks_shifted(t.rec8b);
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)
{
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 = {
......@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev,
static const struct ata_port_info info_867x = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &atp867x_ops,
};
......@@ -515,6 +533,23 @@ static int atp867x_init_one(struct pci_dev *pdev,
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[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 },
......@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = {
.id_table = atp867x_pci_tbl,
.probe = atp867x_init_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)
......
......@@ -334,9 +334,12 @@ enum {
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
/* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */
SATA_FPDMA_OFFSET = 0x01, /* FPDMA non-zero buffer offsets */
SATA_FPDMA_AA = 0x02, /* FPDMA Setup FIS Auto-Activate */
SATA_DIPM = 0x03, /* Device Initiated Power Management */
SATA_FPDMA_AA = 0x02, /* DMA Setup FIS Auto-Activate */
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 */
ATA_SET_MAX_ADDR = 0x00,
......
......@@ -418,6 +418,17 @@ enum {
ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE |
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 {
......@@ -587,6 +598,7 @@ struct ata_device {
#ifdef CONFIG_ATA_ACPI
acpi_handle acpi_handle;
union acpi_object *gtf_cache;
unsigned int gtf_filter;
#endif
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
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