summaryrefslogtreecommitdiff
path: root/drivers/ata
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c41
-rw-r--r--drivers/ata/ata_generic.c2
-rw-r--r--drivers/ata/ata_piix.c3
-rw-r--r--drivers/ata/libata-acpi.c135
-rw-r--r--drivers/ata/libata-core.c120
-rw-r--r--drivers/ata/libata-eh.c40
-rw-r--r--drivers/ata/libata-scsi.c30
-rw-r--r--drivers/ata/libata-sff.c11
-rw-r--r--drivers/ata/libata.h19
-rw-r--r--drivers/ata/pata_acpi.c2
-rw-r--r--drivers/ata/pata_ali.c1
-rw-r--r--drivers/ata/pata_amd.c1
-rw-r--r--drivers/ata/pata_artop.c2
-rw-r--r--drivers/ata/pata_atiixp.c1
-rw-r--r--drivers/ata/pata_cmd640.c1
-rw-r--r--drivers/ata/pata_cmd64x.c2
-rw-r--r--drivers/ata/pata_cs5530.c1
-rw-r--r--drivers/ata/pata_cs5535.c2
-rw-r--r--drivers/ata/pata_cypress.c2
-rw-r--r--drivers/ata/pata_efar.c2
-rw-r--r--drivers/ata/pata_isapnp.c2
-rw-r--r--drivers/ata/pata_it821x.c7
-rw-r--r--drivers/ata/pata_jmicron.c2
-rw-r--r--drivers/ata/pata_legacy.c2
-rw-r--r--drivers/ata/pata_marvell.c2
-rw-r--r--drivers/ata/pata_mpiix.c2
-rw-r--r--drivers/ata/pata_netcell.c2
-rw-r--r--drivers/ata/pata_ninja32.c44
-rw-r--r--drivers/ata/pata_ns87410.c1
-rw-r--r--drivers/ata/pata_ns87415.c2
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_opti.c1
-rw-r--r--drivers/ata/pata_optidma.c1
-rw-r--r--drivers/ata/pata_pcmcia.c2
-rw-r--r--drivers/ata/pata_pdc202xx_old.c2
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/pata_qdi.c2
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_sc1200.c2
-rw-r--r--drivers/ata/pata_scc.c2
-rw-r--r--drivers/ata/pata_serverworks.c1
-rw-r--r--drivers/ata/pata_sil680.c1
-rw-r--r--drivers/ata/pata_sis.c2
-rw-r--r--drivers/ata/pata_sl82c105.c1
-rw-r--r--drivers/ata/pata_triflex.c2
-rw-r--r--drivers/ata/pata_via.c1
-rw-r--r--drivers/ata/pata_winbond.c2
-rw-r--r--drivers/ata/sata_nv.c53
-rw-r--r--drivers/ata/sata_promise.c20
-rw-r--r--drivers/ata/sata_sil24.c5
-rw-r--r--drivers/ata/sata_via.c188
51 files changed, 487 insertions, 291 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index aeadd00411a1..a67b8e7c712d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -49,6 +49,17 @@
#define DRV_NAME "ahci"
#define DRV_VERSION "3.0"
+/* Enclosure Management Control */
+#define EM_CTRL_MSG_TYPE 0x000f0000
+
+/* Enclosure Management LED Message Type */
+#define EM_MSG_LED_HBA_PORT 0x0000000f
+#define EM_MSG_LED_PMP_SLOT 0x0000ff00
+#define EM_MSG_LED_VALUE 0xffff0000
+#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000
+#define EM_MSG_LED_VALUE_OFF 0xfff80000
+#define EM_MSG_LED_VALUE_ON 0x00010000
+
static int ahci_skip_host_reset;
module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
@@ -588,6 +599,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
+ /* Promise */
+ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
+
/* Generic, PCI class code for AHCI */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -1220,18 +1234,20 @@ static void ahci_sw_activity_blink(unsigned long arg)
struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
unsigned long led_message = emp->led_state;
u32 activity_led_state;
+ unsigned long flags;
- led_message &= 0xffff0000;
+ led_message &= EM_MSG_LED_VALUE;
led_message |= ap->port_no | (link->pmp << 8);
/* check to see if we've had activity. If so,
* toggle state of LED and reset timer. If not,
* turn LED to desired idle state.
*/
+ spin_lock_irqsave(ap->lock, flags);
if (emp->saved_activity != emp->activity) {
emp->saved_activity = emp->activity;
/* get the current LED state */
- activity_led_state = led_message & 0x00010000;
+ activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
if (activity_led_state)
activity_led_state = 0;
@@ -1239,17 +1255,18 @@ static void ahci_sw_activity_blink(unsigned long arg)
activity_led_state = 1;
/* clear old state */
- led_message &= 0xfff8ffff;
+ led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
/* toggle state */
led_message |= (activity_led_state << 16);
mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
} else {
/* switch to idle */
- led_message &= 0xfff8ffff;
+ led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
if (emp->blink_policy == BLINK_OFF)
led_message |= (1 << 16);
}
+ spin_unlock_irqrestore(ap->lock, flags);
ahci_transmit_led_message(ap, led_message, 4);
}
@@ -1294,7 +1311,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
struct ahci_em_priv *emp;
/* get the slot number from the message */
- pmp = (state & 0x0000ff00) >> 8;
+ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
if (pmp < MAX_SLOTS)
emp = &pp->em_priv[pmp];
else
@@ -1319,7 +1336,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
message[0] |= (4 << 8);
/* ignore 0:4 of byte zero, fill in port info yourself */
- message[1] = ((state & 0xfffffff0) | ap->port_no);
+ message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
/* write message to EM_LOC */
writel(message[0], mmio + hpriv->em_loc);
@@ -1362,7 +1379,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
state = simple_strtoul(buf, NULL, 0);
/* get the slot number from the message */
- pmp = (state & 0x0000ff00) >> 8;
+ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
if (pmp < MAX_SLOTS)
emp = &pp->em_priv[pmp];
else
@@ -1373,7 +1390,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
* activity led through em_message
*/
if (emp->blink_policy)
- state &= 0xfff8ffff;
+ state &= ~EM_MSG_LED_VALUE_ACTIVITY;
return ahci_transmit_led_message(ap, state, size);
}
@@ -1392,16 +1409,16 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
/* set the LED to OFF */
- port_led_state &= 0xfff80000;
+ port_led_state &= EM_MSG_LED_VALUE_OFF;
port_led_state |= (ap->port_no | (link->pmp << 8));
ahci_transmit_led_message(ap, port_led_state, 4);
} else {
link->flags |= ATA_LFLAG_SW_ACTIVITY;
if (val == BLINK_OFF) {
/* set LED to ON for idle */
- port_led_state &= 0xfff80000;
+ port_led_state &= EM_MSG_LED_VALUE_OFF;
port_led_state |= (ap->port_no | (link->pmp << 8));
- port_led_state |= 0x00010000; /* check this */
+ port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
ahci_transmit_led_message(ap, port_led_state, 4);
}
}
@@ -2612,7 +2629,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u32 em_loc = readl(mmio + HOST_EM_LOC);
u32 em_ctl = readl(mmio + HOST_EM_CTL);
- messages = (em_ctl & 0x000f0000) >> 16;
+ messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
/* we only support LED message type right now */
if ((messages & 0x01) && (ahci_em_messages == 1)) {
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 75a406f5e694..5c33767e66de 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -1,6 +1,6 @@
/*
* ata_generic.c - Generic PATA/SATA controller driver.
- * Copyright 2005 Red Hat Inc <alan@redhat.com>, all rights reserved.
+ * Copyright 2005 Red Hat Inc, all rights reserved.
*
* Elements from ide/pci/generic.c
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index e9e32ed6b1a3..8e37be19bbf5 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -14,7 +14,7 @@
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ * Copyright (C) 2003 Red Hat Inc
*
*
* This program is free software; you can redistribute it and/or modify
@@ -738,7 +738,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
* do_pata_set_dmamode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Drive in question
- * @udma: udma mode, 0 - 6
* @isich: set if the chip is an ICH device
*
* Set UDMA mode for device, in host controller PCI config space.
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9330b7922f62..c012307d0ba6 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -120,21 +120,6 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
}
-static void ata_acpi_eject_device(acpi_handle handle)
-{
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
- &arg_list, NULL)))
- printk(KERN_ERR "Failed to evaluate _EJ0!\n");
-}
-
/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
{
@@ -157,7 +142,6 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* @ap: ATA port ACPI event occurred
* @dev: ATA device ACPI event occurred (can be NULL)
* @event: ACPI event which occurred
- * @is_dock_event: boolean indicating whether the event was a dock one
*
* All ACPI bay / device realted events end up in this function. If
* the event is port-wide @dev is NULL. If the event is specific to a
@@ -171,117 +155,100 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* ACPI notify handler context. May sleep.
*/
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
- u32 event, int is_dock_event)
+ u32 event)
{
- char event_string[12];
- char *envp[] = { event_string, NULL };
struct ata_eh_info *ehi = &ap->link.eh_info;
- struct kobject *kobj = NULL;
int wait = 0;
unsigned long flags;
- acpi_handle handle, tmphandle;
- unsigned long sta;
- acpi_status status;
+ acpi_handle handle;
- if (dev) {
- if (dev->sdev)
- kobj = &dev->sdev->sdev_gendev.kobj;
+ if (dev)
handle = dev->acpi_handle;
- } else {
- kobj = &ap->dev->kobj;
+ else
handle = ap->acpi_handle;
- }
-
- status = acpi_get_handle(handle, "_EJ0", &tmphandle);
- if (ACPI_FAILURE(status))
- /* This device does not support hotplug */
- return;
-
- if (event == ACPI_NOTIFY_BUS_CHECK ||
- event == ACPI_NOTIFY_DEVICE_CHECK)
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
spin_lock_irqsave(ap->lock, flags);
-
+ /*
+ * When dock driver calls into the routine, it will always use
+ * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
+ * ACPI_NOTIFY_EJECT_REQUEST for remove
+ */
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
ata_ehi_push_desc(ehi, "ACPI event");
- if (ACPI_FAILURE(status)) {
- ata_port_printk(ap, KERN_ERR,
- "acpi: failed to determine bay status (0x%x)\n",
- status);
- break;
- }
-
- if (sta) {
- ata_ehi_hotplugged(ehi);
- ata_port_freeze(ap);
- } else {
- /* The device has gone - unplug it */
- ata_acpi_detach_device(ap, dev);
- wait = 1;
- }
+ ata_ehi_hotplugged(ehi);
+ ata_port_freeze(ap);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ata_ehi_push_desc(ehi, "ACPI event");
- if (!is_dock_event)
- break;
-
- /* undock event - immediate unplug */
ata_acpi_detach_device(ap, dev);
wait = 1;
break;
}
- /* make sure kobj doesn't go away while ap->lock is released */
- kobject_get(kobj);
-
spin_unlock_irqrestore(ap->lock, flags);
- if (wait) {
+ if (wait)
ata_port_wait_eh(ap);
- ata_acpi_eject_device(handle);
- }
-
- if (kobj && !is_dock_event) {
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
- }
-
- kobject_put(kobj);
}
static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1);
+ ata_acpi_handle_hotplug(dev->link->ap, dev, event);
}
static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug(ap, NULL, event, 1);
+ ata_acpi_handle_hotplug(ap, NULL, event);
}
-static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
+ u32 event)
{
- struct ata_device *dev = data;
+ struct kobject *kobj = NULL;
+ char event_string[20];
+ char *envp[] = { event_string, NULL };
+
+ if (dev) {
+ if (dev->sdev)
+ kobj = &dev->sdev->sdev_gendev.kobj;
+ } else
+ kobj = &ap->dev->kobj;
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0);
+ if (kobj) {
+ snprintf(event_string, 20, "BAY_EVENT=%d", event);
+ kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ }
}
-static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
{
- struct ata_port *ap = data;
+ ata_acpi_uevent(data, NULL, event);
+}
- ata_acpi_handle_hotplug(ap, NULL, event, 0);
+static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_device *dev = data;
+ ata_acpi_uevent(dev->link->ap, dev, event);
}
+static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
+ .handler = ata_acpi_dev_notify_dock,
+ .uevent = ata_acpi_dev_uevent,
+};
+
+static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
+ .handler = ata_acpi_ap_notify_dock,
+ .uevent = ata_acpi_ap_uevent,
+};
+
/**
* ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host
@@ -315,24 +282,18 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_associate_ide_port(ap);
if (ap->acpi_handle) {
- acpi_install_notify_handler(ap->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_ap_notify, ap);
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
- ata_acpi_ap_notify_dock, ap);
+ &ata_acpi_ap_dock_ops, ap);
}
for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
struct ata_device *dev = &ap->link.device[j];
if (dev->acpi_handle) {
- acpi_install_notify_handler(dev->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_dev_notify, dev);
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
- ata_acpi_dev_notify_dock, dev);
+ &ata_acpi_dev_dock_ops, dev);
}
}
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1ee9499bd343..622350d9b2e3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1268,7 +1268,7 @@ u64 ata_tf_to_lba48(const struct ata_taskfile *tf)
sectors |= ((u64)(tf->hob_lbah & 0xff)) << 40;
sectors |= ((u64)(tf->hob_lbam & 0xff)) << 32;
- sectors |= (tf->hob_lbal & 0xff) << 24;
+ sectors |= ((u64)(tf->hob_lbal & 0xff)) << 24;
sectors |= (tf->lbah & 0xff) << 16;
sectors |= (tf->lbam & 0xff) << 8;
sectors |= (tf->lbal & 0xff);
@@ -1602,7 +1602,6 @@ unsigned long ata_id_xfermask(const u16 *id)
/**
* ata_pio_queue_task - Queue port_task
* @ap: The ata_port to queue port_task for
- * @fn: workqueue function to be scheduled
* @data: data for @fn to use
* @delay: delay time in msecs for workqueue function
*
@@ -1713,8 +1712,6 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
else
tag = 0;
- if (test_and_set_bit(tag, &ap->qc_allocated))
- BUG();
qc = __ata_qc_from_tag(ap, tag);
qc->tag = tag;
@@ -2161,6 +2158,10 @@ retry:
static inline u8 ata_dev_knobble(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
+
+ if (ata_dev_blacklisted(dev) & ATA_HORKAGE_BRIDGE_OK)
+ return 0;
+
return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
}
@@ -4023,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
+ { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA },
/* Devices we expect to fail diagnostics */
@@ -4065,6 +4067,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, },
{ "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, },
+ /* Devices that do not need bridging limits applied */
+ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
+
/* End Marker */
{ }
};
@@ -4158,29 +4163,33 @@ static int cable_is_40wire(struct ata_port *ap)
struct ata_link *link;
struct ata_device *dev;
- /* If the controller thinks we are 40 wire, we are */
+ /* If the controller thinks we are 40 wire, we are. */
if (ap->cbl == ATA_CBL_PATA40)
return 1;
- /* If the controller thinks we are 80 wire, we are */
+
+ /* If the controller thinks we are 80 wire, we are. */
if (ap->cbl == ATA_CBL_PATA80 || ap->cbl == ATA_CBL_SATA)
return 0;
- /* If the system is known to be 40 wire short cable (eg laptop),
- then we allow 80 wire modes even if the drive isn't sure */
+
+ /* If the system is known to be 40 wire short cable (eg
+ * laptop), then we allow 80 wire modes even if the drive
+ * isn't sure.
+ */
if (ap->cbl == ATA_CBL_PATA40_SHORT)
return 0;
- /* If the controller doesn't know we scan
-
- - Note: We look for all 40 wire detects at this point.
- Any 80 wire detect is taken to be 80 wire cable
- because
- - In many setups only the one drive (slave if present)
- will give a valid detect
- - If you have a non detect capable drive you don't
- want it to colour the choice
- */
+
+ /* If the controller doesn't know, we scan.
+ *
+ * Note: We look for all 40 wire detects at this point. Any
+ * 80 wire detect is taken to be 80 wire cable because
+ * - in many setups only the one drive (slave if present) will
+ * give a valid detect
+ * - if you have a non detect capable drive you don't want it
+ * to colour the choice
+ */
ata_port_for_each_link(link, ap) {
ata_link_for_each_dev(dev, link) {
- if (!ata_is_40wire(dev))
+ if (ata_dev_enabled(dev) && !ata_is_40wire(dev))
return 0;
}
}
@@ -4436,7 +4445,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc)
/* Don't allow DMA if it isn't multiple of 16 bytes. Quite a
* few ATAPI devices choke on such DMA requests.
*/
- if (unlikely(qc->nbytes & 15))
+ if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) &&
+ unlikely(qc->nbytes & 15))
return 1;
if (ap->ops->check_atapi_dma)
@@ -4553,54 +4563,28 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
}
/**
- * ata_qc_new - Request an available ATA command, for queueing
- * @ap: Port associated with device @dev
- * @dev: Device from whom we request an available command structure
- *
- * LOCKING:
- * None.
- */
-
-static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
-{
- struct ata_queued_cmd *qc = NULL;
- unsigned int i;
-
- /* no command while frozen */
- if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
- return NULL;
-
- /* the last tag is reserved for internal command. */
- for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
- if (!test_and_set_bit(i, &ap->qc_allocated)) {
- qc = __ata_qc_from_tag(ap, i);
- break;
- }
-
- if (qc)
- qc->tag = i;
-
- return qc;
-}
-
-/**
* ata_qc_new_init - Request an available ATA command, and initialize it
* @dev: Device from whom we request an available command structure
+ * @tag: command tag
*
* LOCKING:
* None.
*/
-struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
{
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
- qc = ata_qc_new(ap);
+ if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+ return NULL;
+
+ qc = __ata_qc_from_tag(ap, tag);
if (qc) {
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
+ qc->tag = tag;
ata_qc_reinit(qc);
}
@@ -4608,31 +4592,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
return qc;
}
-/**
- * ata_qc_free - free unused ata_queued_cmd
- * @qc: Command to complete
- *
- * Designed to free unused ata_queued_cmd object
- * in case something prevents using it.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- */
-void ata_qc_free(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- unsigned int tag;
-
- WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-
- qc->flags = 0;
- tag = qc->tag;
- if (likely(ata_tag_valid(tag))) {
- qc->tag = ATA_TAG_POISON;
- clear_bit(tag, &ap->qc_allocated);
- }
-}
-
void __ata_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -4697,7 +4656,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
- * @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
@@ -5373,6 +5331,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
#ifdef CONFIG_ATA_SFF
INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
+#else
+ INIT_DELAYED_WORK(&ap->port_task, NULL);
#endif
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
@@ -5976,7 +5936,7 @@ static void ata_port_detach(struct ata_port *ap)
* to us. Restore SControl and disable all existing devices.
*/
__ata_port_for_each_link(link, ap) {
- sata_scr_write(link, SCR_CONTROL, link->saved_scontrol);
+ sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
ata_link_for_each_dev(dev, link)
ata_dev_disable(dev);
}
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index a93247cc395a..8077bdf5d30d 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -603,6 +603,9 @@ void ata_scsi_error(struct Scsi_Host *host)
ata_link_for_each_dev(dev, link) {
int devno = dev->devno;
+ if (!ata_dev_enabled(dev))
+ continue;
+
ehc->saved_xfer_mode[devno] = dev->xfer_mode;
if (ata_ncq_enabled(dev))
ehc->saved_ncq_enabled |= 1 << devno;
@@ -1161,6 +1164,7 @@ void ata_eh_detach_dev(struct ata_device *dev)
{
struct ata_link *link = dev->link;
struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
unsigned long flags;
ata_dev_disable(dev);
@@ -1174,9 +1178,11 @@ void ata_eh_detach_dev(struct ata_device *dev)
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
}
- /* clear per-dev EH actions */
+ /* clear per-dev EH info */
ata_eh_clear_action(link, dev, &link->eh_info, ATA_EH_PERDEV_MASK);
ata_eh_clear_action(link, dev, &link->eh_context.i, ATA_EH_PERDEV_MASK);
+ ehc->saved_xfer_mode[dev->devno] = 0;
+ ehc->saved_ncq_enabled &= ~(1 << dev->devno);
spin_unlock_irqrestore(ap->lock, flags);
}
@@ -1206,7 +1212,10 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
ata_eh_clear_action(link, dev, ehi, action);
- if (!(ehc->i.flags & ATA_EHI_QUIET))
+ /* About to take EH action, set RECOVERED. Ignore actions on
+ * slave links as master will do them again.
+ */
+ if (!(ehc->i.flags & ATA_EHI_QUIET) && link != ap->slave_link)
ap->pflags |= ATA_PFLAG_RECOVERED;
spin_unlock_irqrestore(ap->lock, flags);
@@ -2010,8 +2019,13 @@ void ata_eh_autopsy(struct ata_port *ap)
struct ata_eh_context *mehc = &ap->link.eh_context;
struct ata_eh_context *sehc = &ap->slave_link->eh_context;
+ /* transfer control flags from master to slave */
+ sehc->i.flags |= mehc->i.flags & ATA_EHI_TO_SLAVE_MASK;
+
+ /* perform autopsy on the slave link */
ata_eh_link_autopsy(ap->slave_link);
+ /* transfer actions from slave to master and clear slave */
ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
mehc->i.action |= sehc->i.action;
mehc->i.dev_action[1] |= sehc->i.dev_action[1];
@@ -2447,14 +2461,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)))
- 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; /* not yet */
+ if (!ata_phys_link_offline(ata_dev_phys_link(dev))) {
+ /* 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 */
@@ -2779,6 +2793,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
/* if data transfer is verified, clear DUBIOUS_XFER on ering top */
ata_link_for_each_dev(dev, link) {
+ if (!ata_dev_enabled(dev))
+ continue;
+
if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
struct ata_ering_entry *ent;
@@ -2800,6 +2817,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
+ if (!ata_dev_enabled(dev))
+ continue;
+
if (dev->xfer_mode != saved_xfer_mode ||
ata_ncq_enabled(dev) != saved_ncq)
dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 5d312dc9be9f..3fa75eac135d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -190,7 +190,7 @@ static ssize_t ata_scsi_park_show(struct device *device,
struct ata_port *ap;
struct ata_link *link;
struct ata_device *dev;
- unsigned long flags;
+ unsigned long flags, now;
unsigned int uninitialized_var(msecs);
int rc = 0;
@@ -208,10 +208,11 @@ static ssize_t ata_scsi_park_show(struct device *device,
}
link = dev->link;
+ now = jiffies;
if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS &&
link->eh_context.unloaded_mask & (1 << dev->devno) &&
- time_after(dev->unpark_deadline, jiffies))
- msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies);
+ time_after(dev->unpark_deadline, now))
+ msecs = jiffies_to_msecs(dev->unpark_deadline - now);
else
msecs = 0;
@@ -708,7 +709,11 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
{
struct ata_queued_cmd *qc;
- qc = ata_qc_new_init(dev);
+ if (cmd->request->tag != -1)
+ qc = ata_qc_new_init(dev, cmd->request->tag);
+ else
+ qc = ata_qc_new_init(dev, 0);
+
if (qc) {
qc->scsicmd = cmd;
qc->scsidone = done;
@@ -1103,7 +1108,17 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
depth = min(ATA_MAX_QUEUE - 1, depth);
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+
+ /*
+ * If this device is behind a port multiplier, we have
+ * to share the tag map between all devices on that PMP.
+ * Set up the shared tag map here and we get automatic.
+ */
+ if (dev->link->ap->pmp_link)
+ scsi_init_shared_tag_map(sdev->host, ATA_MAX_QUEUE - 1);
+
+ scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
+ scsi_activate_tcq(sdev, depth);
}
return 0;
@@ -1943,6 +1958,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
hdr[1] |= (1 << 7);
memcpy(rbuf, hdr, sizeof(hdr));
+
+ /* if ncq, set tags supported */
+ if (ata_id_has_ncq(args->id))
+ rbuf[7] |= (1 << 1);
+
memcpy(&rbuf[8], "ATA ", 8);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 2a4c516894f0..4b4739486327 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -2153,8 +2153,17 @@ void ata_sff_error_handler(struct ata_port *ap)
*/
void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
{
- if (qc->ap->ioaddr.bmdma_addr)
+ struct ata_port *ap = qc->ap;
+ unsigned long flags;
+
+ spin_lock_irqsave(ap->lock, flags);
+
+ ap->hsm_task_state = HSM_ST_IDLE;
+
+ if (ap->ioaddr.bmdma_addr)
ata_bmdma_stop(qc);
+
+ spin_unlock_irqrestore(ap->lock, flags);
}
/**
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index fe2839e58774..d3831d39bdaa 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -74,7 +74,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
extern void ata_force_cbl(struct ata_port *ap);
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag);
@@ -103,7 +103,6 @@ extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
-extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc);
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int atapi_check_dma(struct ata_queued_cmd *qc);
@@ -119,6 +118,22 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
+/**
+ * ata_qc_free - free unused ata_queued_cmd
+ * @qc: Command to complete
+ *
+ * Designed to free unused ata_queued_cmd object
+ * in case something prevents using it.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static inline void ata_qc_free(struct ata_queued_cmd *qc)
+{
+ qc->flags = 0;
+ qc->tag = ATA_TAG_POISON;
+}
+
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index eb919c16a03e..e2e332d8ff95 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -1,7 +1,7 @@
/*
* ACPI PATA driver
*
- * (c) 2007 Red Hat <alan@redhat.com>
+ * (c) 2007 Red Hat
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 5ca70fa1f587..73c466e452ca 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -1,7 +1,6 @@
/*
* pata_ali.c - ALI 15x3 PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* based in part upon
* linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 57dd00f463d3..0ec9c7d9fe9d 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -1,7 +1,6 @@
/*
* pata_amd.c - AMD PATA for new ATA layer
* (C) 2005-2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Based on pata-sil680. Errata information is taken from data sheets
* and the amd74xx.c driver by Vojtech Pavlik. Nvidia SATA devices are
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 0f513bc11193..6b3092c75ffe 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -1,7 +1,7 @@
/*
* pata_artop.c - ARTOP ATA controller driver
*
- * (C) 2006 Red Hat <alan@redhat.com>
+ * (C) 2006 Red Hat
* (C) 2007 Bartlomiej Zolnierkiewicz
*
* Based in part on drivers/ide/pci/aec62xx.c
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index e8a0d99d7356..0e2cde8f9973 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -1,7 +1,6 @@
/*
* pata_atiixp.c - ATI PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Based on
*
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 2de30b990278..34a394264c3d 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -1,7 +1,6 @@
/*
* pata_cmd640.c - CMD640 PCI PATA for new ATA layer
* (C) 2007 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Based upon
* linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index ddd09b7d98c9..3167d8fed2f2 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -1,7 +1,7 @@
/*
* pata_cmd64x.c - CMD64x PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* Based upon
* linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 0c4b271a9d5a..bba453381f44 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -1,7 +1,6 @@
/*
* pata-cs5530.c - CS5530 PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* based upon cs5530.c by Mark Lord.
*
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index f1b6556f0483..1b2d4a0f5f74 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -1,7 +1,7 @@
/*
* pata-cs5535.c - CS5535 PATA for new ATA layer
* (C) 2005-2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* based upon cs5535.c from AMD <Jens.Altmann@amd.com> as cleaned up and
* made readable and Linux style by Wolfgang Zuleger <wolfgang.zuleger@gmx.de
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 2ff62608ae37..d546425cd380 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -1,7 +1,7 @@
/*
* pata_cypress.c - Cypress PATA for new ATA layer
* (C) 2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox
*
* Based heavily on
* linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 9fba82976ba6..ac6392ea35b0 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -1,7 +1,7 @@
/*
* pata_efar.c - EFAR PIIX clone controller driver
*
- * (C) 2005 Red Hat <alan@redhat.com>
+ * (C) 2005 Red Hat
*
* Some parts based on ata_piix.c by Jeff Garzik and others.
*
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 6a111baab523..15cdb9148aab 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -1,7 +1,7 @@
/*
* pata-isapnp.c - ISA PnP PATA controller driver.
- * Copyright 2005/2006 Red Hat Inc <alan@redhat.com>, all rights reserved.
+ * Copyright 2005/2006 Red Hat Inc, all rights reserved.
*
* Based in part on ide-pnp.c by Andrey Panin <pazke@donpac.ru>
*/
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 0221c9a46769..860ede526282 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -1,7 +1,7 @@
/*
* pata_it821x.c - IT821x PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
* (C) 2007 Bartlomiej Zolnierkiewicz
*
* based upon
@@ -10,7 +10,7 @@
*
* linux/drivers/ide/pci/it821x.c Version 0.09 December 2004
*
- * Copyright (C) 2004 Red Hat <alan@redhat.com>
+ * Copyright (C) 2004 Red Hat
*
* May be copied or modified under the terms of the GNU General Public License
* Based in part on the ITE vendor provided SCSI driver.
@@ -557,9 +557,8 @@ static unsigned int it821x_read_id(struct ata_device *adev,
if (strstr(model_num, "Integrated Technology Express")) {
/* Set feature bits the firmware neglects */
id[49] |= 0x0300; /* LBA, DMA */
- id[82] |= 0x0400; /* LBA48 */
id[83] &= 0x7FFF;
- id[83] |= 0x4000; /* Word 83 is valid */
+ id[83] |= 0x4400; /* Word 83 is valid and LBA48 */
id[86] |= 0x0400; /* LBA48 on */
id[ATA_ID_MAJOR_VER] |= 0x1F;
}
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 73b7596816b4..38cf1ab2d289 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -4,7 +4,7 @@
* driven by AHCI in the usual configuration although
* this driver can handle other setups if we need it.
*
- * (c) 2006 Red Hat <alan@redhat.com>
+ * (c) 2006 Red Hat
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index bc037ffce200..930c2208640b 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -1,6 +1,6 @@
/*
* pata-legacy.c - Legacy port PATA/SATA controller driver.
- * Copyright 2005/2006 Red Hat <alan@redhat.com>, all rights reserved.
+ * Copyright 2005/2006 Red Hat, all rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 0d87eec84966..76e399bf8c1b 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -5,7 +5,7 @@
* isn't making full use of the device functionality but it is
* easy to get working.
*
- * (c) 2006 Red Hat <alan@redhat.com>
+ * (c) 2006 Red Hat
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 7d7e3fdab71f..7c8faa48b5f3 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -1,7 +1,7 @@
/*
* pata_mpiix.c - Intel MPIIX PATA for new ATA layer
* (C) 2005-2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* The MPIIX is different enough to the PIIX4 and friends that we give it
* a separate driver. The old ide/pci code handles this by just not tuning
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index d9719c8b9dbe..9dc05e1656a8 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -1,7 +1,7 @@
/*
* pata_netcell.c - Netcell PATA driver
*
- * (c) 2006 Red Hat <alan@redhat.com>
+ * (c) 2006 Red Hat
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 565e67cd13fa..4e466eae8b46 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -1,7 +1,6 @@
/*
* pata_ninja32.c - Ninja32 PATA for new ATA layer
* (C) 2007 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Note: The controller like many controllers has shared timings for
* PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
@@ -45,7 +44,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_ninja32"
-#define DRV_VERSION "0.0.1"
+#define DRV_VERSION "0.1.1"
/**
@@ -89,6 +88,17 @@ static struct ata_port_operations ninja32_port_ops = {
.set_piomode = ninja32_set_piomode,
};
+static void ninja32_program(void __iomem *base)
+{
+ iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
+ iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */
+ iowrite8(0x01, base + 0x03); /* Unknown */
+ iowrite8(0x20, base + 0x04); /* WAIT0 */
+ iowrite8(0x8f, base + 0x05); /* Unknown */
+ iowrite8(0xa4, base + 0x1c); /* Unknown */
+ iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */
+}
+
static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
struct ata_host *host;
@@ -134,18 +144,28 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
ap->ioaddr.bmdma_addr = base;
ata_sff_std_ports(&ap->ioaddr);
- iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
- iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */
- iowrite8(0x01, base + 0x03); /* Unknown */
- iowrite8(0x20, base + 0x04); /* WAIT0 */
- iowrite8(0x8f, base + 0x05); /* Unknown */
- iowrite8(0xa4, base + 0x1c); /* Unknown */
- iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */
+ ninja32_program(base);
/* FIXME: Should we disable them at remove ? */
return ata_host_activate(host, dev->irq, ata_sff_interrupt,
IRQF_SHARED, &ninja32_sht);
}
+#ifdef CONFIG_PM
+
+static int ninja32_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;
+ ninja32_program(host->iomap[0]);
+ ata_host_resume(host);
+ return 0;
+}
+#endif
+
static const struct pci_device_id ninja32[] = {
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -156,7 +176,11 @@ static struct pci_driver ninja32_pci_driver = {
.name = DRV_NAME,
.id_table = ninja32,
.probe = ninja32_init_one,
- .remove = ata_pci_remove_one
+ .remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = ninja32_reinit_one,
+#endif
};
static int __init ninja32_init(void)
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index be756b7ef07e..40d411c460de 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -1,7 +1,6 @@
/*
* pata_ns87410.c - National Semiconductor 87410 PATA for new ATA layer
* (C) 2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index e0aa7eaaee0a..89bf5f865d6a 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -1,7 +1,7 @@
/*
* pata_ns87415.c - NS87415 (non PARISC) PATA
*
- * (C) 2005 Red Hat <alan@redhat.com>
+ * (C) 2005 Red Hat <alan@lxorguk.ukuu.org.uk>
*
* This is a fairly generic MWDMA controller. It has some limitations
* as it requires timing reloads on PIO/DMA transitions but it is otherwise
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index df64f2443001..c0dbc46a348e 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -1,7 +1,7 @@
/*
* pata_oldpiix.c - Intel PATA/SATA controllers
*
- * (C) 2005 Red Hat <alan@redhat.com>
+ * (C) 2005 Red Hat
*
* Some parts based on ata_piix.c by Jeff Garzik and others.
*
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index fb2cf661b0e8..e4fa4d565e96 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -1,7 +1,6 @@
/*
* pata_opti.c - ATI PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Based on
* linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 4cd744456313..93bb6e91973f 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -1,7 +1,6 @@
/*
* pata_optidma.c - Opti DMA PATA for new ATA layer
* (C) 2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* The Opti DMA controllers are related to the older PIO PCI controllers
* and indeed the VLB ones. The main differences are that the timing
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 02b596b9cf6a..271cb64d429e 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -1,6 +1,6 @@
/*
* pata_pcmcia.c - PCMCIA PATA controller driver.
- * Copyright 2005-2006 Red Hat Inc <alan@redhat.com>, all rights reserved.
+ * Copyright 2005-2006 Red Hat Inc, all rights reserved.
* PCMCIA ident update Copyright 2006 Marcin Juszkiewicz
* <openembedded@hrw.one.pl>
*
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index d2673060bc8d..799a6a098712 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -1,7 +1,7 @@
/*
* pata_pdc202xx_old.c - Promise PDC202xx PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
* (C) 2007 Bartlomiej Zolnierkiewicz
*
* Based in part on linux/drivers/ide/pci/pdc202xx_old.c
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 8f65ad61b8af..77e4e3b17f54 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -5,7 +5,7 @@
*
* Based on pata_pcmcia:
*
- * Copyright 2005-2006 Red Hat Inc <alan@redhat.com>, all rights reserved.
+ * Copyright 2005-2006 Red Hat Inc, all rights reserved.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 63b7a1c165a5..3080f371222c 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -1,6 +1,6 @@
/*
* pata_qdi.c - QDI VLB ATA controllers
- * (C) 2006 Red Hat <alan@redhat.com>
+ * (C) 2006 Red Hat
*
* This driver mostly exists as a proof of concept for non PCI devices under
* libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 1c0d9fa7ee54..0b0aa452de14 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -1,7 +1,7 @@
/*
* pata_radisys.c - Intel PATA/SATA controllers
*
- * (C) 2006 Red Hat <alan@redhat.com>
+ * (C) 2006 Red Hat <alan@lxorguk.ukuu.org.uk>
*
* Some parts based on ata_piix.c by Jeff Garzik and others.
*
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 0278fd2b8fb1..9a4bdca54616 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -1,5 +1,5 @@
/*
- * New ATA layer SC1200 driver Alan Cox <alan@redhat.com>
+ * New ATA layer SC1200 driver Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* TODO: Mode selection filtering
* TODO: Can't enable second channel until ATA core has serialize
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 16673d168573..cf3707e516a2 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -8,7 +8,7 @@
* Copyright 2003-2005 Jeff Garzik
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ * Copyright (C) 2003 Red Hat Inc
*
* and drivers/ata/ahci.c:
* Copyright 2004-2005 Red Hat, Inc.
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index ffd26d0dc50d..72e41c9f969b 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -1,7 +1,6 @@
/*
* pata_serverworks.c - Serverworks PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* based upon
*
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index a598bb36aafc..83580a59db58 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -1,7 +1,6 @@
/*
* pata_sil680.c - SIL680 PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* based upon
*
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 26345d7b531c..d34236611752 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -1,7 +1,7 @@
/*
* pata_sis.c - SiS ATA driver
*
- * (C) 2005 Red Hat <alan@redhat.com>
+ * (C) 2005 Red Hat
* (C) 2007 Bartlomiej Zolnierkiewicz
*
* Based upon linux/drivers/ide/pci/sis5513.c
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 69877bd81815..1b0e7b6d8ef5 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -1,7 +1,6 @@
/*
* pata_sl82c105.c - SL82C105 PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Based in part on linux/drivers/ide/pci/sl82c105.c
* SL82C105/Winbond 553 IDE driver
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b181261f2743..ef9597517cdd 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -1,7 +1,7 @@
/*
* pata_triflex.c - Compaq PATA for new ATA layer
* (C) 2005 Red Hat Inc
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* based upon
*
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 8fdb2ce73210..681169c9c640 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -1,7 +1,6 @@
/*
* pata_via.c - VIA PATA for new ATA layer
* (C) 2005-2006 Red Hat Inc
- * Alan Cox <alan@redhat.com>
*
* Documentation
* Most chipset documentation available under NDA only
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index a7606b044a61..319e164a3d74 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -1,6 +1,6 @@
/*
* pata_winbond.c - Winbond VLB ATA controllers
- * (C) 2006 Red Hat <alan@redhat.com>
+ * (C) 2006 Red Hat
*
* Support for the Winbond 83759A when operating in advanced mode.
* Multichip mode is not currently supported.
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index fae3841de0d8..6f1460614325 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -307,10 +307,10 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
+static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void nv_ck804_freeze(struct ata_port *ap);
static void nv_ck804_thaw(struct ata_port *ap);
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
static int nv_adma_slave_config(struct scsi_device *sdev);
static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
@@ -405,17 +405,8 @@ static struct scsi_host_template nv_swncq_sht = {
.slave_configure = nv_swncq_slave_config,
};
-/* OSDL bz3352 reports that some nv controllers can't determine device
- * signature reliably and nv_hardreset is implemented to work around
- * the problem. This was reported on nf3 and it's unclear whether any
- * other controllers are affected. However, the workaround has been
- * applied to all variants and there isn't much to gain by trying to
- * find out exactly which ones are affected at this point especially
- * because NV has moved over to ahci for newer controllers.
- */
static struct ata_port_operations nv_common_ops = {
.inherits = &ata_bmdma_port_ops,
- .hardreset = nv_hardreset,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
};
@@ -429,12 +420,22 @@ static struct ata_port_operations nv_generic_ops = {
.hardreset = ATA_OP_NULL,
};
+/* OSDL bz3352 reports that nf2/3 controllers can't determine device
+ * signature reliably. Also, the following thread reports detection
+ * failure on cold boot with the standard debouncing timing.
+ *
+ * http://thread.gmane.org/gmane.linux.ide/34098
+ *
+ * Debounce with hotplug timing and request follow-up SRST.
+ */
static struct ata_port_operations nv_nf2_ops = {
.inherits = &nv_common_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
+ .hardreset = nv_nf2_hardreset,
};
+/* CK804 finally gets hardreset right */
static struct ata_port_operations nv_ck804_ops = {
.inherits = &nv_common_ops,
.freeze = nv_ck804_freeze,
@@ -443,7 +444,7 @@ static struct ata_port_operations nv_ck804_ops = {
};
static struct ata_port_operations nv_adma_ops = {
- .inherits = &nv_common_ops,
+ .inherits = &nv_ck804_ops,
.check_atapi_dma = nv_adma_check_atapi_dma,
.sff_tf_read = nv_adma_tf_read,
@@ -467,7 +468,7 @@ static struct ata_port_operations nv_adma_ops = {
};
static struct ata_port_operations nv_swncq_ops = {
- .inherits = &nv_common_ops,
+ .inherits = &nv_generic_ops,
.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
@@ -1553,6 +1554,17 @@ static void nv_nf2_thaw(struct ata_port *ap)
iowrite8(mask, scr_addr + NV_INT_ENABLE);
}
+static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ bool online;
+ int rc;
+
+ rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+ &online, NULL);
+ return online ? -EAGAIN : rc;
+}
+
static void nv_ck804_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
@@ -1605,21 +1617,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
ata_sff_thaw(ap);
}
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- int rc;
-
- /* SATA hardreset fails to retrieve proper device signature on
- * some controllers. Request follow up SRST. For more info,
- * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
- */
- rc = sata_sff_hardreset(link, class, deadline);
- if (rc)
- return rc;
- return -EAGAIN;
-}
-
static void nv_adma_error_handler(struct ata_port *ap)
{
struct nv_adma_port_priv *pp = ap->private_data;
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 750d8cdc00cd..ba9a2570a742 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -153,6 +153,10 @@ static void pdc_freeze(struct ata_port *ap);
static void pdc_sata_freeze(struct ata_port *ap);
static void pdc_thaw(struct ata_port *ap);
static void pdc_sata_thaw(struct ata_port *ap);
+static int pdc_pata_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void pdc_error_handler(struct ata_port *ap);
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
static int pdc_pata_cable_detect(struct ata_port *ap);
@@ -186,6 +190,7 @@ static struct ata_port_operations pdc_sata_ops = {
.scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write,
.port_start = pdc_sata_port_start,
+ .hardreset = pdc_sata_hardreset,
};
/* First-generation chips need a more restrictive ->check_atapi_dma op */
@@ -200,6 +205,7 @@ static struct ata_port_operations pdc_pata_ops = {
.freeze = pdc_freeze,
.thaw = pdc_thaw,
.port_start = pdc_common_port_start,
+ .softreset = pdc_pata_softreset,
};
static const struct ata_port_info pdc_port_info[] = {
@@ -693,6 +699,20 @@ static void pdc_sata_thaw(struct ata_port *ap)
readl(host_mmio + hotplug_offset); /* flush */
}
+static int pdc_pata_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ pdc_reset_port(link->ap);
+ return ata_sff_softreset(link, class, deadline);
+}
+
+static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ pdc_reset_port(link->ap);
+ return sata_sff_hardreset(link, class, deadline);
+}
+
static void pdc_error_handler(struct ata_port *ap)
{
if (!(ap->pflags & ATA_PFLAG_FROZEN))
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 4621807a1a6a..ccee930f1e12 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -1329,6 +1329,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+ /* Set max read request size to 4096. This slightly increases
+ * write throughput for pci-e variants.
+ */
+ pcie_set_readrq(pdev, 4096);
+
sil24_init_controller(host);
pci_set_master(pdev);
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1cfa74535d91..c18935f0bda2 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -44,11 +44,16 @@
#include <linux/libata.h>
#define DRV_NAME "sata_via"
-#define DRV_VERSION "2.3"
+#define DRV_VERSION "2.4"
+/*
+ * vt8251 is different from other sata controllers of VIA. It has two
+ * channels, each channel has both Master and Slave slot.
+ */
enum board_ids_enum {
vt6420,
vt6421,
+ vt8251,
};
enum {
@@ -70,6 +75,9 @@ enum {
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
+static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val);
+static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
+static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
static void svia_noop_freeze(struct ata_port *ap);
static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
static int vt6421_pata_cable_detect(struct ata_port *ap);
@@ -78,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
- { PCI_VDEVICE(VIA, 0x0591), vt6420 },
- { PCI_VDEVICE(VIA, 0x3149), vt6420 },
- { PCI_VDEVICE(VIA, 0x3249), vt6421 },
- { PCI_VDEVICE(VIA, 0x5287), vt6420 },
+ { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */
+ { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */
+ { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */
{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
+ { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
{ } /* terminate list */
};
@@ -103,25 +111,37 @@ static struct scsi_host_template svia_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
-static struct ata_port_operations vt6420_sata_ops = {
+static struct ata_port_operations svia_base_ops = {
.inherits = &ata_bmdma_port_ops,
+ .sff_tf_load = svia_tf_load,
+};
+
+static struct ata_port_operations vt6420_sata_ops = {
+ .inherits = &svia_base_ops,
.freeze = svia_noop_freeze,
.prereset = vt6420_prereset,
};
static struct ata_port_operations vt6421_pata_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &svia_base_ops,
.cable_detect = vt6421_pata_cable_detect,
.set_piomode = vt6421_set_pio_mode,
.set_dmamode = vt6421_set_dma_mode,
};
static struct ata_port_operations vt6421_sata_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &svia_base_ops,
.scr_read = svia_scr_read,
.scr_write = svia_scr_write,
};
+static struct ata_port_operations vt8251_ops = {
+ .inherits = &svia_base_ops,
+ .hardreset = sata_std_hardreset,
+ .scr_read = vt8251_scr_read,
+ .scr_write = vt8251_scr_write,
+};
+
static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
@@ -146,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = {
.port_ops = &vt6421_pata_ops,
};
+static struct ata_port_info vt8251_port_info = {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
+ ATA_FLAG_NO_LEGACY,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &vt8251_ops,
+};
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
MODULE_LICENSE("GPL");
@@ -168,6 +197,106 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
return 0;
}
+static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
+{
+ static const u8 ipm_tbl[] = { 1, 2, 6, 0 };
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ int slot = 2 * link->ap->port_no + link->pmp;
+ u32 v = 0;
+ u8 raw;
+
+ switch (scr) {
+ case SCR_STATUS:
+ pci_read_config_byte(pdev, 0xA0 + slot, &raw);
+
+ /* read the DET field, bit0 and 1 of the config byte */
+ v |= raw & 0x03;
+
+ /* read the SPD field, bit4 of the configure byte */
+ if (raw & (1 << 4))
+ v |= 0x02 << 4;
+ else
+ v |= 0x01 << 4;
+
+ /* read the IPM field, bit2 and 3 of the config byte */
+ v |= ipm_tbl[(raw >> 2) & 0x3];
+ break;
+
+ case SCR_ERROR:
+ /* devices other than 5287 uses 0xA8 as base */
+ WARN_ON(pdev->device != 0x5287);
+ pci_read_config_dword(pdev, 0xB0 + slot * 4, &v);
+ break;
+
+ case SCR_CONTROL:
+ pci_read_config_byte(pdev, 0xA4 + slot, &raw);
+
+ /* read the DET field, bit0 and bit1 */
+ v |= ((raw & 0x02) << 1) | (raw & 0x01);
+
+ /* read the IPM field, bit2 and bit3 */
+ v |= ((raw >> 2) & 0x03) << 8;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ *val = v;
+ return 0;
+}
+
+static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val)
+{
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ int slot = 2 * link->ap->port_no + link->pmp;
+ u32 v = 0;
+
+ switch (scr) {
+ case SCR_ERROR:
+ /* devices other than 5287 uses 0xA8 as base */
+ WARN_ON(pdev->device != 0x5287);
+ pci_write_config_dword(pdev, 0xB0 + slot * 4, val);
+ return 0;
+
+ case SCR_CONTROL:
+ /* set the DET field */
+ v |= ((val & 0x4) >> 1) | (val & 0x1);
+
+ /* set the IPM field */
+ v |= ((val >> 8) & 0x3) << 2;
+
+ pci_write_config_byte(pdev, 0xA4 + slot, v);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * svia_tf_load - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+ * Outputs ATA taskfile to standard ATA host controller.
+ *
+ * This is to fix the internal bug of via chipsets, which will
+ * reset the device register after changing the IEN bit on ctl
+ * register.
+ */
+static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+ struct ata_taskfile ttf;
+
+ if (tf->ctl != ap->last_ctl) {
+ ttf = *tf;
+ ttf.flags |= ATA_TFLAG_DEVICE;
+ tf = &ttf;
+ }
+ ata_sff_tf_load(ap, tf);
+}
+
static void svia_noop_freeze(struct ata_port *ap)
{
/* Some VIA controllers choke if ATA_NIEN is manipulated in
@@ -367,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
return 0;
}
+static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
+{
+ const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL };
+ struct ata_host *host;
+ int i, rc;
+
+ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ return rc;
+ *r_host = host;
+
+ rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+ return rc;
+ }
+
+ /* 8251 hosts four sata ports as M/S of the two channels */
+ for (i = 0; i < host->n_ports; i++)
+ ata_slave_link_init(host->ports[i]);
+
+ return 0;
+}
+
static void svia_configure(struct pci_dev *pdev)
{
u8 tmp8;
@@ -422,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- if (board_id == vt6420)
- bar_sizes = &svia_bar_sizes[0];
- else
+ if (board_id == vt6421)
bar_sizes = &vt6421_bar_sizes[0];
+ else
+ bar_sizes = &svia_bar_sizes[0];
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) ||
@@ -438,10 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
- if (board_id == vt6420)
+ switch (board_id) {
+ case vt6420:
rc = vt6420_prepare_host(pdev, &host);
- else
+ break;
+ case vt6421:
rc = vt6421_prepare_host(pdev, &host);
+ break;
+ case vt8251:
+ rc = vt8251_prepare_host(pdev, &host);
+ break;
+ default:
+ rc = -EINVAL;
+ }
if (rc)
return rc;