Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (21 commits)
  libata: remove irq_on from ata_bus_reset() and ata_std_postreset()
  ata_piix: kill incorrect invalid map value warning
  libata: add another Maxtor drive with broken NCQ to the list
  [libata] sata_mv: Fix and clean up per-chip-generation tests
  [libata] sata_mv: Convert to new exception handling (EH) infrastructure
  [libata] sata_mv: minor bug fixes, enhancements, and cleanups (prep for new EH)
  [libata] sata_mv: Minor cleanups and renaming, preparing for new EH & NCQ
  libata-link: add PMP related ATA constants
  libata-link: separate out ata_eh_handle_dev_fail()
  pata_hpt3x3: fix DMA Kconfig option to actually have a hope of working
  Add Hitachi HDS7250SASUN500G 0621KTAWSD to NCQ blacklist
  pata_scc.c: Workaround for errata A308
  libata: add FUJITSU MHV2080BH to NCQ blacklist
  pata_hpt3x3: major reworking and testing
  libata: clean up horkage handling
  libata: quirk IOMEGA ZIP 250 ATAPI FLOPPY
  libata: simplify PCI legacy SFF host handling
  pata_mpc52xx: suspend/resume support
  sata_promise: SATA hotplug support, take 2
  pata_sis: FIFO whack
  ...
  • Loading branch information
Linus Torvalds committed Jul 12, 2007
2 parents e1bd2ac + c6e54a5 commit 57399ec
Show file tree
Hide file tree
Showing 17 changed files with 890 additions and 725 deletions.
10 changes: 9 additions & 1 deletion drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,22 @@ config PATA_HPT3X2N
If unsure, say N.

config PATA_HPT3X3
tristate "HPT 343/363 PATA support (Experimental)"
tristate "HPT 343/363 PATA support"
depends on PCI
help
This option enables support for the HPT 343/363
PATA controllers via the new ATA layer

If unsure, say N.

config PATA_HPT3X3_DMA
bool "HPT 343/363 DMA support (Experimental)"
depends on PATA_HPT3X3
help
This option enables DMA support for the HPT343/363
controllers. Enable with care as there are still some
problems with DMA on this chipset.

config PATA_ISAPNP
tristate "ISA Plug and Play PATA support (Experimental)"
depends on EXPERIMENTAL && ISAPNP
Expand Down
2 changes: 1 addition & 1 deletion drivers/ata/ata_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ static const struct piix_map_db ich6m_map_db = {
*/
.map = {
/* PM PS SM SS MAP */
{ P0, P2, RV, RV }, /* 00b */
{ P0, P2, NA, NA }, /* 00b */
{ IDE, IDE, P1, P3 }, /* 01b */
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
Expand Down
74 changes: 20 additions & 54 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);

unsigned int ata_print_id = 1;
static struct workqueue_struct *ata_wq;
Expand Down Expand Up @@ -1283,18 +1284,11 @@ static unsigned int ata_id_xfermask(const u16 *id)
void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
unsigned long delay)
{
int rc;

if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
return;

PREPARE_DELAYED_WORK(&ap->port_task, fn);
ap->port_task_data = data;

rc = queue_delayed_work(ata_wq, &ap->port_task, delay);

/* rc == 0 means that another user is using port task */
WARN_ON(rc == 0);
/* may fail if ata_port_flush_task() in progress */
queue_delayed_work(ata_wq, &ap->port_task, delay);
}

/**
Expand All @@ -1309,32 +1303,9 @@ void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
*/
void ata_port_flush_task(struct ata_port *ap)
{
unsigned long flags;

DPRINTK("ENTER\n");

spin_lock_irqsave(ap->lock, flags);
ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(ap->lock, flags);

DPRINTK("flush #1\n");
cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */

/*
* At this point, if a task is running, it's guaranteed to see
* the FLUSH flag; thus, it will never queue pio tasks again.
* Cancel and flush.
*/
if (!cancel_delayed_work(&ap->port_task)) {
if (ata_msg_ctl(ap))
ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
__FUNCTION__);
cancel_work_sync(&ap->port_task.work);
}

spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(ap->lock, flags);
cancel_rearming_delayed_work(&ap->port_task);

if (ata_msg_ctl(ap))
ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
Expand Down Expand Up @@ -1814,7 +1785,7 @@ static void ata_dev_config_ncq(struct ata_device *dev,
desc[0] = '\0';
return;
}
if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
if (dev->horkage & ATA_HORKAGE_NONCQ) {
snprintf(desc, desc_sz, "NCQ (not used)");
return;
}
Expand Down Expand Up @@ -1863,6 +1834,9 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);

/* set horkage */
dev->horkage |= ata_dev_blacklisted(dev);

/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
Expand Down Expand Up @@ -2038,7 +2012,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = ATA_MAX_SECTORS;
}

if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);

Expand Down Expand Up @@ -3190,9 +3164,6 @@ void ata_bus_reset(struct ata_port *ap)
if ((slave_possible) && (err != 0x81))
ap->device[1].class = ata_dev_try_classify(ap, 1, &err);

/* re-enable interrupts */
ap->ops->irq_on(ap);

/* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
Expand Down Expand Up @@ -3577,10 +3548,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
sata_scr_write(ap, SCR_ERROR, serror);

/* re-enable interrupts */
if (!ap->ops->error_handler)
ap->ops->irq_on(ap);

/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
Expand Down Expand Up @@ -3770,6 +3737,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
{ "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
{ "IOMEGA ZIP 250 ATAPI Floppy",
NULL, ATA_HORKAGE_NODMA },

/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
Expand All @@ -3783,7 +3752,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
/* NCQ is broken */
{ "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ },
{ "Maxtor 6B200M0", "BANC1BM0", ATA_HORKAGE_NONCQ },
{ "Maxtor 6B200M0", "BANC1B10", ATA_HORKAGE_NONCQ },
{ "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
ATA_HORKAGE_NONCQ },
/* NCQ hard hangs device under heavier load, needs hard power cycle */
{ "Maxtor 6B250S0", "BANC1B70", ATA_HORKAGE_NONCQ },
/* Blacklist entries taken from Silicon Image 3124/3132
Expand All @@ -3796,14 +3768,15 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, },
{ "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
{ "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
{ "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },

/* Devices with NCQ limits */

/* End Marker */
{ }
};

unsigned long ata_device_blacklisted(const struct ata_device *dev)
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[ATA_ID_PROD_LEN + 1];
unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
Expand Down Expand Up @@ -3833,7 +3806,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
(dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
}

/**
Expand Down Expand Up @@ -6557,13 +6530,7 @@ void ata_port_detach(struct ata_port *ap)
spin_unlock_irqrestore(ap->lock, flags);

ata_port_wait_eh(ap);

/* Flush hotplug task. The sequence is similar to
* ata_port_flush_task().
*/
cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
cancel_delayed_work(&ap->hotplug_task);
cancel_work_sync(&ap->hotplug_task.work);
cancel_rearming_delayed_work(&ap->hotplug_task);

skip_eh:
/* remove the associated SCSI host */
Expand Down Expand Up @@ -6952,7 +6919,6 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
EXPORT_SYMBOL_GPL(ata_device_blacklisted);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);

EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
Expand All @@ -6961,9 +6927,9 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);

#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
Expand Down
96 changes: 52 additions & 44 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
return 1;
}

static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
struct ata_port *ap = dev->ap;
struct ata_eh_context *ehc = &ap->eh_context;

ehc->tries[dev->devno]--;

switch (err) {
case -ENODEV:
/* device missing or wrong IDENTIFY data, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
case -EINVAL:
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
if (ehc->tries[dev->devno] == 1) {
/* This is the last chance, better to slow
* down than lose it.
*/
sata_down_spd_limit(ap);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}

if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
/* disable device if it has used up all its chances */
ata_dev_disable(dev);

/* detach if offline */
if (ata_port_offline(ap))
ata_eh_detach_dev(dev);

/* probe if requested */
if ((ehc->i.probe_mask & (1 << dev->devno)) &&
!(ehc->did_probe_mask & (1 << dev->devno))) {
ata_eh_detach_dev(dev);
ata_dev_init(dev);

ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
ehc->did_probe_mask |= (1 << dev->devno);
ehc->i.action |= ATA_EH_SOFTRESET;
}
} else {
/* soft didn't work? be haaaaard */
if (ehc->i.flags & ATA_EHI_DID_RESET)
ehc->i.action |= ATA_EH_HARDRESET;
else
ehc->i.action |= ATA_EH_SOFTRESET;
}
}

/**
* ata_eh_recover - recover host port after error
* @ap: host port to recover
Expand Down Expand Up @@ -1997,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
goto out;

dev_fail:
ehc->tries[dev->devno]--;

switch (rc) {
case -ENODEV:
/* device missing or wrong IDENTIFY data, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
case -EINVAL:
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
if (ehc->tries[dev->devno] == 1) {
/* This is the last chance, better to slow
* down than lose it.
*/
sata_down_spd_limit(ap);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}

if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
/* disable device if it has used up all its chances */
ata_dev_disable(dev);

/* detach if offline */
if (ata_port_offline(ap))
ata_eh_detach_dev(dev);

/* probe if requested */
if ((ehc->i.probe_mask & (1 << dev->devno)) &&
!(ehc->did_probe_mask & (1 << dev->devno))) {
ata_eh_detach_dev(dev);
ata_dev_init(dev);

ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
ehc->did_probe_mask |= (1 << dev->devno);
ehc->i.action |= ATA_EH_SOFTRESET;
}
} else {
/* soft didn't work? be haaaaard */
if (ehc->i.flags & ATA_EHI_DID_RESET)
ehc->i.action |= ATA_EH_HARDRESET;
else
ehc->i.action |= ATA_EH_SOFTRESET;
}
ata_eh_handle_dev_fail(dev, rc);

if (ata_port_nr_enabled(ap)) {
ata_port_printk(ap, KERN_WARNING, "failed to recover some "
Expand Down
Loading

0 comments on commit 57399ec

Please sign in to comment.