Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/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 ...
This commit is contained in:
commit
57399ec907
|
@ -309,7 +309,7 @@ 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
|
||||
|
@ -317,6 +317,14 @@ config PATA_HPT3X3
|
|||
|
||||
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
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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__);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 },
|
||||
|
@ -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
|
||||
|
@ -3796,6 +3768,7 @@ 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 */
|
||||
|
||||
|
@ -3803,7 +3776,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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 "
|
||||
|
|
|
@ -604,13 +604,17 @@ int ata_pci_init_bmdma(struct ata_host *host)
|
|||
}
|
||||
|
||||
/**
|
||||
* ata_pci_init_native_host - acquire native ATA resources and init host
|
||||
* ata_pci_init_sff_host - acquire native PCI ATA resources and init host
|
||||
* @host: target ATA host
|
||||
*
|
||||
* Acquire native PCI ATA resources for @host and initialize the
|
||||
* first two ports of @host accordingly. Ports marked dummy are
|
||||
* skipped and allocation failure makes the port dummy.
|
||||
*
|
||||
* Note that native PCI resources are valid even for legacy hosts
|
||||
* as we fix up pdev resources array early in boot, so this
|
||||
* function can be used for both native and legacy SFF hosts.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from calling layer (may sleep).
|
||||
*
|
||||
|
@ -618,7 +622,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
|
|||
* 0 if at least one port is initialized, -ENODEV if no port is
|
||||
* available.
|
||||
*/
|
||||
int ata_pci_init_native_host(struct ata_host *host)
|
||||
int ata_pci_init_sff_host(struct ata_host *host)
|
||||
{
|
||||
struct device *gdev = host->dev;
|
||||
struct pci_dev *pdev = to_pci_dev(gdev);
|
||||
|
@ -673,7 +677,7 @@ int ata_pci_init_native_host(struct ata_host *host)
|
|||
}
|
||||
|
||||
/**
|
||||
* ata_pci_prepare_native_host - helper to prepare native PCI ATA host
|
||||
* ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
|
||||
* @pdev: target PCI device
|
||||
* @ppi: array of port_info, must be enough for two ports
|
||||
* @r_host: out argument for the initialized ATA host
|
||||
|
@ -687,9 +691,9 @@ int ata_pci_init_native_host(struct ata_host *host)
|
|||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
int ata_pci_prepare_native_host(struct pci_dev *pdev,
|
||||
const struct ata_port_info * const * ppi,
|
||||
struct ata_host **r_host)
|
||||
int ata_pci_prepare_sff_host(struct pci_dev *pdev,
|
||||
const struct ata_port_info * const * ppi,
|
||||
struct ata_host **r_host)
|
||||
{
|
||||
struct ata_host *host;
|
||||
int rc;
|
||||
|
@ -705,7 +709,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
rc = ata_pci_init_native_host(host);
|
||||
rc = ata_pci_init_sff_host(host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
|
@ -730,221 +734,6 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
struct ata_legacy_devres {
|
||||
unsigned int mask;
|
||||
unsigned long cmd_port[2];
|
||||
void __iomem * cmd_addr[2];
|
||||
void __iomem * ctl_addr[2];
|
||||
unsigned int irq[2];
|
||||
void * irq_dev_id[2];
|
||||
};
|
||||
|
||||
static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (!legacy_dr->irq[i])
|
||||
continue;
|
||||
|
||||
free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
|
||||
legacy_dr->irq[i] = 0;
|
||||
legacy_dr->irq_dev_id[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ata_legacy_release(struct device *gdev, void *res)
|
||||
{
|
||||
struct ata_legacy_devres *this = res;
|
||||
int i;
|
||||
|
||||
ata_legacy_free_irqs(this);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (this->cmd_addr[i])
|
||||
ioport_unmap(this->cmd_addr[i]);
|
||||
if (this->ctl_addr[i])
|
||||
ioport_unmap(this->ctl_addr[i]);
|
||||
if (this->cmd_port[i])
|
||||
release_region(this->cmd_port[i], 8);
|
||||
}
|
||||
}
|
||||
|
||||
static int ata_init_legacy_port(struct ata_port *ap,
|
||||
struct ata_legacy_devres *legacy_dr)
|
||||
{
|
||||
struct ata_host *host = ap->host;
|
||||
int port_no = ap->port_no;
|
||||
unsigned long cmd_port, ctl_port;
|
||||
|
||||
if (port_no == 0) {
|
||||
cmd_port = ATA_PRIMARY_CMD;
|
||||
ctl_port = ATA_PRIMARY_CTL;
|
||||
} else {
|
||||
cmd_port = ATA_SECONDARY_CMD;
|
||||
ctl_port = ATA_SECONDARY_CTL;
|
||||
}
|
||||
|
||||
/* request cmd_port */
|
||||
if (request_region(cmd_port, 8, "libata"))
|
||||
legacy_dr->cmd_port[port_no] = cmd_port;
|
||||
else {
|
||||
dev_printk(KERN_WARNING, host->dev,
|
||||
"0x%0lX IDE port busy\n", cmd_port);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* iomap cmd and ctl ports */
|
||||
legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
|
||||
legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
|
||||
if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) {
|
||||
dev_printk(KERN_WARNING, host->dev,
|
||||
"failed to map cmd/ctl ports\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* init IO addresses */
|
||||
ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
|
||||
ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
|
||||
ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
|
||||
ata_std_ports(&ap->ioaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_init_legacy_host - acquire legacy ATA resources and init ATA host
|
||||
* @host: target ATA host
|
||||
* @was_busy: out parameter, indicates whether any port was busy
|
||||
*
|
||||
* Acquire legacy ATA resources for the first two ports of @host
|
||||
* and initialize it accordingly. Ports marked dummy are skipped
|
||||
* and resource acquistion failure makes the port dummy.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from calling layer (may sleep).
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 if at least one port is initialized, -ENODEV if no port is
|
||||
* available.
|
||||
*/
|
||||
static int ata_init_legacy_host(struct ata_host *host, int *was_busy)
|
||||
{
|
||||
struct device *gdev = host->dev;
|
||||
struct ata_legacy_devres *legacy_dr;
|
||||
int i, rc;
|
||||
|
||||
if (!devres_open_group(gdev, NULL, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
rc = -ENOMEM;
|
||||
legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
|
||||
GFP_KERNEL);
|
||||
if (!legacy_dr)
|
||||
goto err_out;
|
||||
devres_add(gdev, legacy_dr);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (ata_port_is_dummy(host->ports[i]))
|
||||
continue;
|
||||
|
||||
rc = ata_init_legacy_port(host->ports[i], legacy_dr);
|
||||
if (rc == 0)
|
||||
legacy_dr->mask |= 1 << i;
|
||||
else {
|
||||
if (rc == -EBUSY)
|
||||
(*was_busy)++;
|
||||
host->ports[i]->ops = &ata_dummy_port_ops;
|
||||
}
|
||||
}
|
||||
|
||||
if (!legacy_dr->mask) {
|
||||
dev_printk(KERN_ERR, gdev, "no available legacy port\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
devres_remove_group(gdev, NULL);
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
devres_release_group(gdev, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_request_legacy_irqs - request legacy ATA IRQs
|
||||
* @host: target ATA host
|
||||
* @handler: array of IRQ handlers
|
||||
* @irq_flags: array of IRQ flags
|
||||
* @dev_id: array of IRQ dev_ids
|
||||
*
|
||||
* Request legacy IRQs for non-dummy legacy ports in @host. All
|
||||
* IRQ parameters are passed as array to allow ports to have
|
||||
* separate IRQ handlers.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from calling layer (may sleep).
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int ata_request_legacy_irqs(struct ata_host *host,
|
||||
irq_handler_t const *handler,
|
||||
const unsigned int *irq_flags,
|
||||
void * const *dev_id)
|
||||
{
|
||||
struct device *gdev = host->dev;
|
||||
struct ata_legacy_devres *legacy_dr;
|
||||
int i, rc;
|
||||
|
||||
legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
|
||||
BUG_ON(!legacy_dr);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
unsigned int irq;
|
||||
|
||||
/* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
|
||||
if (i == 0)
|
||||
irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
|
||||
else
|
||||
irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));
|
||||
|
||||
if (!(legacy_dr->mask & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (!handler[i]) {
|
||||
dev_printk(KERN_ERR, gdev,
|
||||
"NULL handler specified for port %d\n", i);
|
||||
rc = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
|
||||
dev_id[i]);
|
||||
if (rc) {
|
||||
dev_printk(KERN_ERR, gdev,
|
||||
"irq %u request failed (errno=%d)\n", irq, rc);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* record irq allocation in legacy_dr */
|
||||
legacy_dr->irq[i] = irq;
|
||||
legacy_dr->irq_dev_id[i] = dev_id[i];
|
||||
|
||||
/* only used to print info */
|
||||
if (i == 0)
|
||||
host->irq = irq;
|
||||
else
|
||||
host->irq2 = irq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ata_legacy_free_irqs(legacy_dr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_pci_init_one - Initialize/register PCI IDE host controller
|
||||
* @pdev: Controller to be initialized
|
||||
|
@ -1029,35 +818,11 @@ int ata_pci_init_one(struct pci_dev *pdev,
|
|||
#endif
|
||||
}
|
||||
|
||||
/* alloc and init host */
|
||||
host = ata_host_alloc_pinfo(dev, ppi, 2);
|
||||
if (!host) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"failed to allocate ATA host\n");
|
||||
rc = -ENOMEM;
|
||||
/* prepare host */
|
||||
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!legacy_mode) {
|
||||
rc = ata_pci_init_native_host(host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
} else {
|
||||
int was_busy = 0;
|
||||
|
||||
rc = ata_init_legacy_host(host, &was_busy);
|
||||
if (was_busy)
|
||||
pcim_pin_device(pdev);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
/* request respective PCI regions, may fail */
|
||||
rc = pci_request_region(pdev, 1, DRV_NAME);
|
||||
rc = pci_request_region(pdev, 3, DRV_NAME);
|
||||
}
|
||||
|
||||
/* init BMDMA, may fail */
|
||||
ata_pci_init_bmdma(host);
|
||||
pci_set_master(pdev);
|
||||
|
||||
/* start host and request IRQ */
|
||||
|
@ -1068,17 +833,28 @@ int ata_pci_init_one(struct pci_dev *pdev,
|
|||
if (!legacy_mode) {
|
||||
rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
host->irq = pdev->irq;
|
||||
} else {
|
||||
irq_handler_t handler[2] = { host->ops->irq_handler,
|
||||
host->ops->irq_handler };
|
||||
unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
|
||||
void *dev_id[2] = { host, host };
|
||||
if (!ata_port_is_dummy(host->ports[0])) {
|
||||
host->irq = ATA_PRIMARY_IRQ(pdev);
|
||||
rc = devm_request_irq(dev, host->irq,
|
||||
pi->port_ops->irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
|
||||
if (!ata_port_is_dummy(host->ports[1])) {
|
||||
host->irq2 = ATA_SECONDARY_IRQ(pdev);
|
||||
rc = devm_request_irq(dev, host->irq2,
|
||||
pi->port_ops->irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, host);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
/* register */
|
||||
rc = ata_host_register(host, pi->sht);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt3x3"
|
||||
#define DRV_VERSION "0.4.3"
|
||||
#define DRV_VERSION "0.5.3"
|
||||
|
||||
/**
|
||||
* hpt3x3_set_piomode - PIO setup
|
||||
|
@ -52,6 +52,7 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||
pci_write_config_dword(pdev, 0x48, r2);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PATA_HPT3X3_DMA)
|
||||
/**
|
||||
* hpt3x3_set_dmamode - DMA timing setup
|
||||
* @ap: ATA interface
|
||||
|
@ -59,6 +60,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||
*
|
||||
* Set up the channel for MWDMA or UDMA modes. Much the same as with
|
||||
* PIO, load the mode number and then set MWDMA or UDMA flag.
|
||||
*
|
||||
* 0x44 : bit 0-2 master mode, 3-5 slave mode, etc
|
||||
* 0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc
|
||||
*/
|
||||
|
||||
static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
|
@ -76,13 +80,26 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
|||
r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */
|
||||
|
||||
if (adev->dma_mode >= XFER_UDMA_0)
|
||||
r2 |= 0x01 << dn; /* Ultra mode */
|
||||
r2 |= (0x10 << dn); /* Ultra mode */
|
||||
else
|
||||
r2 |= 0x10 << dn; /* MWDMA */
|
||||
r2 |= (0x01 << dn); /* MWDMA */
|
||||
|
||||
pci_write_config_dword(pdev, 0x44, r1);
|
||||
pci_write_config_dword(pdev, 0x48, r2);
|
||||
}
|
||||
#endif /* CONFIG_PATA_HPT3X3_DMA */
|
||||
|
||||
/**
|
||||
* hpt3x3_atapi_dma - ATAPI DMA check
|
||||
* @qc: Queued command
|
||||
*
|
||||
* Just say no - we don't do ATAPI DMA
|
||||
*/
|
||||
|
||||
static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct scsi_host_template hpt3x3_sht = {
|
||||
.module = THIS_MODULE,
|
||||
|
@ -105,7 +122,9 @@ static struct scsi_host_template hpt3x3_sht = {
|
|||
static struct ata_port_operations hpt3x3_port_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
.set_piomode = hpt3x3_set_piomode,
|
||||
#if defined(CONFIG_PATA_HPT3X3_DMA)
|
||||
.set_dmamode = hpt3x3_set_dmamode,
|
||||
#endif
|
||||
.mode_filter = ata_pci_default_filter,
|
||||
|
||||
.tf_load = ata_tf_load,
|
||||
|
@ -124,6 +143,7 @@ static struct ata_port_operations hpt3x3_port_ops = {
|
|||
.bmdma_start = ata_bmdma_start,
|
||||
.bmdma_stop = ata_bmdma_stop,
|
||||
.bmdma_status = ata_bmdma_status,
|
||||
.check_atapi_dma= hpt3x3_atapi_dma,
|
||||
|
||||
.qc_prep = ata_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
|
@ -158,32 +178,79 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)
|
|||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hpt3x3_init_one - Initialise an HPT343/363
|
||||
* @dev: PCI device
|
||||
* @pdev: PCI device
|
||||
* @id: Entry in match table
|
||||
*
|
||||
* Perform basic initialisation. The chip has a quirk that it won't
|
||||
* function unless it is at XX00. The old ATA driver touched this up
|
||||
* but we leave it for pci quirks to do properly.
|
||||
* Perform basic initialisation. We set the device up so we access all
|
||||
* ports via BAR4. This is neccessary to work around errata.
|
||||
*/
|
||||
|
||||
static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
static int printed_version;
|
||||
static const struct ata_port_info info = {
|
||||
.sht = &hpt3x3_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = 0x1f,
|
||||
#if defined(CONFIG_PATA_HPT3X3_DMA)
|
||||
/* Further debug needed */
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x07,
|
||||
#endif
|
||||
.port_ops = &hpt3x3_port_ops
|
||||
};
|
||||
/* Register offsets of taskfiles in BAR4 area */
|
||||
static const u8 offset_cmd[2] = { 0x20, 0x28 };
|
||||
static const u8 offset_ctl[2] = { 0x36, 0x3E };
|
||||
const struct ata_port_info *ppi[] = { &info, NULL };
|
||||
struct ata_host *host;
|
||||
int i, rc;
|
||||
void __iomem *base;
|
||||
|
||||
hpt3x3_init_chipset(dev);
|
||||
/* Now kick off ATA set up */
|
||||
return ata_pci_init_one(dev, ppi);
|
||||
hpt3x3_init_chipset(pdev);
|
||||
|
||||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
/* acquire resources and fill host */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Everything is relative to BAR4 if we set up this way */
|
||||
rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
|
||||
if (rc == -EBUSY)
|
||||
pcim_pin_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
host->iomap = pcim_iomap_table(pdev);
|
||||
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
base = host->iomap[4]; /* Bus mastering base */
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_ioports *ioaddr = &host->ports[i]->ioaddr;
|
||||
|
||||
ioaddr->cmd_addr = base + offset_cmd[i];
|
||||
ioaddr->altstatus_addr =
|
||||
ioaddr->ctl_addr = base + offset_ctl[i];
|
||||
ioaddr->scr_addr = NULL;
|
||||
ata_std_ports(ioaddr);
|
||||
ioaddr->bmdma_addr = base + 8 * i;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
|
||||
&hpt3x3_sht);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -467,13 +467,27 @@ mpc52xx_ata_remove(struct of_device *op)
|
|||
static int
|
||||
mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
|
||||
{
|
||||
return 0; /* FIXME : What to do here ? */
|
||||
struct ata_host *host = dev_get_drvdata(&op->dev);
|
||||
|
||||
return ata_host_suspend(host, state);
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_ata_resume(struct of_device *op)
|
||||
{
|
||||
return 0; /* FIXME : What to do here ? */
|
||||
struct ata_host *host = dev_get_drvdata(&op->dev);
|
||||
struct mpc52xx_ata_priv *priv = host->private_data;
|
||||
int rv;
|
||||
|
||||
rv = mpc52xx_ata_hw_init(priv);
|
||||
if (rv) {
|
||||
printk(KERN_ERR DRV_NAME ": Error during HW init\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
ata_host_resume(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -238,6 +238,12 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
|
|||
else
|
||||
offset = 0; /* 100MHz */
|
||||
|
||||
/* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
|
||||
if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) {
|
||||
printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
|
||||
speed = XFER_UDMA_4;
|
||||
}
|
||||
|
||||
if (speed >= XFER_UDMA_0)
|
||||
idx = speed - XFER_UDMA_0;
|
||||
else
|
||||
|
@ -724,22 +730,36 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
|
|||
|
||||
static u8 scc_bmdma_status (struct ata_port *ap)
|
||||
{
|
||||
u8 host_stat;
|
||||
void __iomem *mmio = ap->ioaddr.bmdma_addr;
|
||||
u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
|
||||
u32 int_status = in_be32(mmio + SCC_DMA_INTST);
|
||||
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
static int retry = 0;
|
||||
|
||||
host_stat = in_be32(mmio + SCC_DMA_STATUS);
|
||||
/* return if IOS_SS is cleared */
|
||||
if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START))
|
||||
return host_stat;
|
||||
|
||||
/* Workaround for PTERADD: emulate DMA_INTR when
|
||||
* - IDE_STATUS[ERR] = 1
|
||||
* - INT_STATUS[INTRQ] = 1
|
||||
* - DMA_STATUS[IORACTA] = 1
|
||||
*/
|
||||
if (!(host_stat & ATA_DMA_INTR)) {
|
||||
u32 int_status = in_be32(mmio + SCC_DMA_INTST);
|
||||
if (ata_altstatus(ap) & ATA_ERR &&
|
||||
int_status & INTSTS_INTRQ &&
|
||||
host_stat & ATA_DMA_ACTIVE)
|
||||
host_stat |= ATA_DMA_INTR;
|
||||
/* errata A252,A308 workaround: Step4 */
|
||||
if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ)
|
||||
return (host_stat | ATA_DMA_INTR);
|
||||
|
||||
/* errata A308 workaround Step5 */
|
||||
if (int_status & INTSTS_IOIRQS) {
|
||||
host_stat |= ATA_DMA_INTR;
|
||||
|
||||
/* We don't check ATAPI DMA because it is limited to UDMA4 */
|
||||
if ((qc->tf.protocol == ATA_PROT_DMA &&
|
||||
qc->dev->xfer_mode > XFER_UDMA_4)) {
|
||||
if (!(int_status & INTSTS_ACTEINT)) {
|
||||
printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n",
|
||||
ap->print_id, retry);
|
||||
host_stat |= ATA_DMA_ERR;
|
||||
if (retry++)
|
||||
ap->udma_mask >>= 1;
|
||||
} else
|
||||
retry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return host_stat;
|
||||
|
@ -892,10 +912,6 @@ static void scc_std_postreset (struct ata_port *ap, unsigned int *classes)
|
|||
{
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -149,6 +149,9 @@ static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
|
|||
if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
|
||||
return -ENOENT;
|
||||
|
||||
/* Clear the FIFO settings. We can't enable the FIFO until
|
||||
we know we are poking at a disk */
|
||||
pci_write_config_byte(pdev, 0x4B, 0);
|
||||
return ata_std_prereset(ap, deadline);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1560,7 +1560,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
}
|
||||
|
||||
ppi[0] = &nv_port_info[type];
|
||||
rc = ata_pci_prepare_native_host(pdev, ppi, &host);
|
||||
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "sata_promise.h"
|
||||
|
||||
#define DRV_NAME "sata_promise"
|
||||
#define DRV_VERSION "2.08"
|
||||
#define DRV_VERSION "2.09"
|
||||
|
||||
enum {
|
||||
PDC_MAX_PORTS = 4,
|
||||
|
@ -716,6 +716,9 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
|
|||
unsigned int i, tmp;
|
||||
unsigned int handled = 0;
|
||||
void __iomem *mmio_base;
|
||||
unsigned int hotplug_offset, ata_no;
|
||||
u32 hotplug_status;
|
||||
int is_sataii_tx4;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
|
@ -726,10 +729,20 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
|
|||
|
||||
mmio_base = host->iomap[PDC_MMIO_BAR];
|
||||
|
||||
/* read and clear hotplug flags for all ports */
|
||||
if (host->ports[0]->flags & PDC_FLAG_GEN_II)
|
||||
hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
else
|
||||
hotplug_offset = PDC_SATA_PLUG_CSR;
|
||||
hotplug_status = readl(mmio_base + hotplug_offset);
|
||||
if (hotplug_status & 0xff)
|
||||
writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
|
||||
hotplug_status &= 0xff; /* clear uninteresting bits */
|
||||
|
||||
/* reading should also clear interrupts */
|
||||
mask = readl(mmio_base + PDC_INT_SEQMASK);
|
||||
|
||||
if (mask == 0xffffffff) {
|
||||
if (mask == 0xffffffff && hotplug_status == 0) {
|
||||
VPRINTK("QUICK EXIT 2\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
@ -737,16 +750,34 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
|
|||
spin_lock(&host->lock);
|
||||
|
||||
mask &= 0xffff; /* only 16 tags possible */
|
||||
if (!mask) {
|
||||
if (mask == 0 && hotplug_status == 0) {
|
||||
VPRINTK("QUICK EXIT 3\n");
|
||||
goto done_irq;
|
||||
}
|
||||
|
||||
writel(mask, mmio_base + PDC_INT_SEQMASK);
|
||||
|
||||
is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
VPRINTK("port %u\n", i);
|
||||
ap = host->ports[i];
|
||||
|
||||
/* check for a plug or unplug event */
|
||||
ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
|
||||
tmp = hotplug_status & (0x11 << ata_no);
|
||||
if (tmp && ap &&
|
||||
!(ap->flags & ATA_FLAG_DISABLED)) {
|
||||
struct ata_eh_info *ehi = &ap->eh_info;
|
||||
ata_ehi_clear_desc(ehi);
|
||||
ata_ehi_hotplugged(ehi);
|
||||
ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
|
||||
ata_port_freeze(ap);
|
||||
++handled;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for a packet interrupt */
|
||||
tmp = mask & (1 << (i + 1));
|
||||
if (tmp && ap &&
|
||||
!(ap->flags & ATA_FLAG_DISABLED)) {
|
||||
|
@ -902,9 +933,9 @@ static void pdc_host_init(struct ata_host *host)
|
|||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff, mmio + hotplug_offset);
|
||||
|
||||
/* mask plug/unplug ints */
|
||||
/* unmask plug/unplug ints */
|
||||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff0000, mmio + hotplug_offset);
|
||||
writel(tmp & ~0xff0000, mmio + hotplug_offset);
|
||||
|
||||
/* don't initialise TBG or SLEW on 2nd generation chips */
|
||||
if (is_gen2)
|
||||
|
|
|
@ -334,7 +334,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
break;
|
||||
}
|
||||
|
||||
rc = ata_pci_prepare_native_host(pdev, ppi, &host);
|
||||
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
host->private_data = hpriv;
|
||||
|
||||
/* the first two ports are standard SFF */
|
||||
rc = ata_pci_init_native_host(host);
|
||||
rc = ata_pci_init_sff_host(host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
|
|||
struct ata_host *host;
|
||||
int rc;
|
||||
|
||||
rc = ata_pci_prepare_native_host(pdev, ppi, &host);
|
||||
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||
if (rc)
|
||||
return rc;
|
||||
*r_host = host;
|
||||
|
|
|
@ -164,6 +164,8 @@ enum {
|
|||
ATA_CMD_SET_MAX = 0xF9,
|
||||
ATA_CMD_SET_MAX_EXT = 0x37,
|
||||
ATA_CMD_READ_LOG_EXT = 0x2f,
|
||||
ATA_CMD_PMP_READ = 0xE4,
|
||||
ATA_CMD_PMP_WRITE = 0xE8,
|
||||
|
||||
/* READ_LOG_EXT pages */
|
||||
ATA_LOG_SATA_NCQ = 0x10,
|
||||
|
@ -212,6 +214,28 @@ enum {
|
|||
0=to device, 1=to host */
|
||||
ATAPI_CDB_LEN = 16,
|
||||
|
||||
/* PMP stuff */
|
||||
SATA_PMP_MAX_PORTS = 15,
|
||||
SATA_PMP_CTRL_PORT = 15,
|
||||
|
||||
SATA_PMP_GSCR_DWORDS = 128,
|
||||
SATA_PMP_GSCR_PROD_ID = 0,
|
||||
SATA_PMP_GSCR_REV = 1,
|
||||
SATA_PMP_GSCR_PORT_INFO = 2,
|
||||
SATA_PMP_GSCR_ERROR = 32,
|
||||
SATA_PMP_GSCR_ERROR_EN = 33,
|
||||
SATA_PMP_GSCR_FEAT = 64,
|
||||
SATA_PMP_GSCR_FEAT_EN = 96,
|
||||
|
||||
SATA_PMP_PSCR_STATUS = 0,
|
||||
SATA_PMP_PSCR_ERROR = 1,
|
||||
SATA_PMP_PSCR_CONTROL = 2,
|
||||
|
||||
SATA_PMP_FEAT_BIST = (1 << 0),
|
||||
SATA_PMP_FEAT_PMREQ = (1 << 1),
|
||||
SATA_PMP_FEAT_DYNSSC = (1 << 2),
|
||||
SATA_PMP_FEAT_NOTIFY = (1 << 3),
|
||||
|
||||
/* cable types */
|
||||
ATA_CBL_NONE = 0,
|
||||
ATA_CBL_PATA40 = 1,
|
||||
|
@ -418,4 +442,9 @@ static inline int lba_48_ok(u64 block, u32 n_block)
|
|||
return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
|
||||
}
|
||||
|
||||
#define sata_pmp_gscr_vendor(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff)
|
||||
#define sata_pmp_gscr_devid(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16)
|
||||
#define sata_pmp_gscr_rev(gscr) (((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff)
|
||||
#define sata_pmp_gscr_ports(gscr) ((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf)
|
||||
|
||||
#endif /* __LINUX_ATA_H__ */
|
||||
|
|
|
@ -196,7 +196,6 @@ enum {
|
|||
ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */
|
||||
ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */
|
||||
|
||||
ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
|
||||
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
|
||||
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
|
||||
ATA_PFLAG_GTM_VALID = (1 << 19), /* acpi_gtm data valid */
|
||||
|
@ -435,6 +434,7 @@ struct ata_device {
|
|||
struct ata_port *ap;
|
||||
unsigned int devno; /* 0 or 1 */
|
||||
unsigned long flags; /* ATA_DFLAG_xxx */
|
||||
unsigned int horkage; /* List of broken features */
|
||||
struct scsi_device *sdev; /* attached SCSI device */
|
||||
#ifdef CONFIG_ATA_ACPI
|
||||
acpi_handle acpi_handle;
|
||||
|
@ -466,7 +466,6 @@ struct ata_device {
|
|||
/* error history */
|
||||
struct ata_ering ering;
|
||||
int spdn_cnt;
|
||||
unsigned int horkage; /* List of broken features */
|
||||
};
|
||||
|
||||
/* Offset into struct ata_device. Fields above it are maintained
|
||||
|
@ -794,7 +793,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
|
|||
extern void ata_id_c_string(const u16 *id, unsigned char *s,
|
||||
unsigned int ofs, unsigned int len);
|
||||
extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
|
||||
extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
|
||||
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
|
||||
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
|
||||
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
|
||||
|
@ -871,11 +869,11 @@ struct pci_bits {
|
|||
unsigned long val;
|
||||
};
|
||||
|
||||
extern int ata_pci_init_native_host(struct ata_host *host);
|
||||
extern int ata_pci_init_sff_host(struct ata_host *host);
|
||||
extern int ata_pci_init_bmdma(struct ata_host *host);
|
||||
extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
|
||||
const struct ata_port_info * const * ppi,
|
||||
struct ata_host **r_host);
|
||||
extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
|
||||
const struct ata_port_info * const * ppi,
|
||||
struct ata_host **r_host);
|
||||
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
|
||||
extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
|
Loading…
Reference in New Issue