* [PATCH 02/14] libata-link: introduce ata_link
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 01/14] libata-link: add PM related ATA constants Tejun Heo
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Introduce ata_link. It abstracts PHY and sits between ata_port and
ata_device. This new level of abstraction is necessary to support
SATA Port Multiplier, which basically adds a bunch of links (PHYs) to
a ATA host port. Fields related to command execution, spd_limit and
EH are per-link and thus moved to ata_link.
Except for the host link, each link can be connected to at most one
device and thus contains one struct ata_device. Slave device (PATA or
emulated SATA) is a special case for the host link and is handled by
struct ata_device storage __dev1 put right after the host link in
struct ata_port.
This patch only defines the host link. Multiple link handling will be
added later. Also, a lot of ap->link derefences are added but many of
them will be removed as each part is converted to deal directly with
ata_link instead of ata_port.
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 20 +++---
drivers/scsi/libata-bmdma.c | 4 +
drivers/scsi/libata-core.c | 134 +++++++++++++++++++++++--------------------
drivers/scsi/libata-eh.c | 68 +++++++++++-----------
drivers/scsi/libata-scsi.c | 20 +++---
drivers/scsi/pdc_adma.c | 4 +
drivers/scsi/sata_mv.c | 6 +-
drivers/scsi/sata_nv.c | 2 -
drivers/scsi/sata_promise.c | 4 +
drivers/scsi/sata_qstor.c | 4 +
drivers/scsi/sata_sil.c | 4 +
drivers/scsi/sata_sil24.c | 10 ++-
drivers/scsi/sata_sx4.c | 4 +
drivers/scsi/sata_vsc.c | 2 -
include/linux/libata.h | 40 ++++++++-----
15 files changed, 174 insertions(+), 152 deletions(-)
14834a330b2a065a120bc776be561f3be32831c1
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index ce8b00a..e3b4fd5 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -617,7 +617,7 @@ static int ahci_softreset(struct ata_por
/* restart engine */
ahci_start_engine(ap);
- ata_tf_init(ap->device, &tf);
+ ata_tf_init(ap->link.device, &tf);
fis = pp->cmd_tbl;
/* issue the first D2H Register FIS */
@@ -709,7 +709,7 @@ static void ahci_postreset(struct ata_po
/* clear stored SError */
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->eh_info.serror = 0;
+ ap->link.eh_info.serror = 0;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
/* Make sure port's ATAPI bit is set appropriately */
@@ -807,7 +807,7 @@ static void ahci_qc_prep(struct ata_queu
static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
{
struct ahci_port_priv *pp = ap->private_data;
- struct ata_eh_info *ehi = &ap->eh_info;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
unsigned int err_mask = 0, action = 0;
struct ata_queued_cmd *qc;
u32 serror;
@@ -855,7 +855,7 @@ static void ahci_error_intr(struct ata_p
ehi->serror |= serror;
ehi->action |= action;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc)
qc->err_mask |= err_mask;
else
@@ -871,7 +871,7 @@ static void ahci_host_intr(struct ata_po
{
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- struct ata_eh_info *ehi = &ap->eh_info;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
u32 status, serror, qc_active;
int rc;
@@ -897,7 +897,7 @@ static void ahci_host_intr(struct ata_po
return;
}
- if (ap->sactive)
+ if (ap->link.sactive)
qc_active = readl(port_mmio + PORT_SCR_ACT);
else
qc_active = readl(port_mmio + PORT_CMD_ISSUE);
@@ -915,13 +915,13 @@ static void ahci_host_intr(struct ata_po
/* hmmm... a spurious interupt */
/* some devices send D2H reg with I bit set during NCQ command phase */
- if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
+ if (ap->link.sactive && status & PORT_IRQ_D2H_REG_FIS)
return;
/* ignore interim PIO setup fis interrupts */
- if (ata_tag_valid(ap->active_tag)) {
+ if (ata_tag_valid(ap->link.active_tag)) {
struct ata_queued_cmd *qc =
- ata_qc_from_tag(ap, ap->active_tag);
+ ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && qc->tf.protocol == ATA_PROT_PIO &&
(status & PORT_IRQ_PIOS_FIS))
@@ -931,7 +931,7 @@ static void ahci_host_intr(struct ata_po
if (ata_ratelimit())
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
- status, ap->active_tag, ap->sactive);
+ status, ap->link.active_tag, ap->link.sactive);
}
static void ahci_irq_clear(struct ata_port *ap)
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index db5a975..b3a4642 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -716,12 +716,12 @@ void ata_bmdma_drive_eh(struct ata_port
ata_postreset_fn_t postreset)
{
struct ata_host_set *host_set = ap->host_set;
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
struct ata_queued_cmd *qc;
unsigned long flags;
int thaw = 0;
- qc = __ata_qc_from_tag(ap, ap->active_tag);
+ qc = __ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
qc = NULL;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index defc6c9..e132e47 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -799,7 +799,7 @@ void ata_dev_select(struct ata_port *ap,
ap->ops->dev_select(ap, device);
if (wait) {
- if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
+ if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
msleep(150);
ata_wait_idle(ap);
}
@@ -997,7 +997,8 @@ unsigned ata_exec_internal(struct ata_de
struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen)
{
- struct ata_port *ap = dev->ap;
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
u8 command = tf->command;
struct ata_queued_cmd *qc;
unsigned int tag, preempted_tag;
@@ -1037,11 +1038,11 @@ unsigned ata_exec_internal(struct ata_de
qc->dev = dev;
ata_qc_reinit(qc);
- preempted_tag = ap->active_tag;
- preempted_sactive = ap->sactive;
+ preempted_tag = link->active_tag;
+ preempted_sactive = link->sactive;
preempted_qc_active = ap->qc_active;
- ap->active_tag = ATA_TAG_POISON;
- ap->sactive = 0;
+ link->active_tag = ATA_TAG_POISON;
+ link->sactive = 0;
ap->qc_active = 0;
/* prepare & issue qc */
@@ -1106,8 +1107,8 @@ unsigned ata_exec_internal(struct ata_de
err_mask = qc->err_mask;
ata_qc_free(qc);
- ap->active_tag = preempted_tag;
- ap->sactive = preempted_sactive;
+ link->active_tag = preempted_tag;
+ link->sactive = preempted_sactive;
ap->qc_active = preempted_qc_active;
/* XXX - Some LLDDs (sata_mv) disable port on command failure.
@@ -1185,7 +1186,7 @@ unsigned int ata_pio_need_iordy(const st
int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int post_reset, u16 *id)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
unsigned int class = *p_class;
struct ata_taskfile tf;
unsigned int err_mask = 0;
@@ -1268,13 +1269,14 @@ int ata_dev_read_id(struct ata_device *d
static inline u8 ata_dev_knobble(struct ata_device *dev)
{
- return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+ struct ata_port *ap = dev->link->ap;
+ return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
}
static void ata_dev_config_ncq(struct ata_device *dev,
char *desc, size_t desc_sz)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
if (!ata_id_has_ncq(dev->id)) {
@@ -1309,7 +1311,7 @@ static void ata_dev_config_ncq(struct at
*/
int ata_dev_configure(struct ata_device *dev, int print_info)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
const u16 *id = dev->id;
unsigned int xfer_mask;
int i, rc;
@@ -1436,7 +1438,7 @@ int ata_dev_configure(struct ata_device
for (i = 0; i < ATA_MAX_DEVICES; i++)
ap->host->max_cmd_len = max_t(unsigned int,
ap->host->max_cmd_len,
- ap->device[i].cdb_len);
+ ap->link.device[i].cdb_len);
/* limit bridge transfers to udma5, 200 sectors */
if (ata_dev_knobble(dev)) {
@@ -1492,7 +1494,7 @@ static int ata_bus_probe(struct ata_port
ap->ops->phy_reset(ap);
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!(ap->flags & ATA_FLAG_DISABLED) &&
dev->class != ATA_DEV_UNKNOWN)
@@ -1507,7 +1509,7 @@ static int ata_bus_probe(struct ata_port
/* read IDENTIFY page and configure devices */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (tries[i])
dev->class = classes[i];
@@ -1532,7 +1534,7 @@ static int ata_bus_probe(struct ata_port
}
for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_enabled(&ap->device[i]))
+ if (ata_dev_enabled(&ap->link.device[i]))
return 0;
/* no device present, disable port */
@@ -1693,8 +1695,8 @@ void sata_phy_reset(struct ata_port *ap)
struct ata_device *ata_dev_pair(struct ata_device *adev)
{
- struct ata_port *ap = adev->ap;
- struct ata_device *pair = &ap->device[1 - adev->devno];
+ struct ata_link *link = adev->link;
+ struct ata_device *pair = &link->device[1 - adev->devno];
if (!ata_dev_enabled(pair))
return NULL;
return pair;
@@ -1715,8 +1717,8 @@ struct ata_device *ata_dev_pair(struct a
void ata_port_disable(struct ata_port *ap)
{
- ap->device[0].class = ATA_DEV_NONE;
- ap->device[1].class = ATA_DEV_NONE;
+ ap->link.device[0].class = ATA_DEV_NONE;
+ ap->link.device[1].class = ATA_DEV_NONE;
ap->flags |= ATA_FLAG_DISABLED;
}
@@ -1743,7 +1745,7 @@ int ata_down_sata_spd_limit(struct ata_p
if (rc)
return rc;
- mask = ap->sata_spd_limit;
+ mask = ap->link.sata_spd_limit;
if (mask <= 1)
return -EINVAL;
highbit = fls(mask) - 1;
@@ -1757,7 +1759,7 @@ int ata_down_sata_spd_limit(struct ata_p
if (!mask)
return -EINVAL;
- ap->sata_spd_limit = mask;
+ ap->link.sata_spd_limit = mask;
ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
sata_spd_string(fls(mask)));
@@ -1769,10 +1771,10 @@ static int __ata_set_sata_spd_needed(str
{
u32 spd, limit;
- if (ap->sata_spd_limit == UINT_MAX)
+ if (ap->link.sata_spd_limit == UINT_MAX)
limit = 0;
else
- limit = fls(ap->sata_spd_limit);
+ limit = fls(ap->link.sata_spd_limit);
spd = (*scontrol >> 4) & 0xf;
*scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
@@ -1785,7 +1787,7 @@ static int __ata_set_sata_spd_needed(str
* @ap: Port in question
*
* Test whether the spd limit in SControl matches
- * @ap->sata_spd_limit. This function is used to determine
+ * @ap->link.sata_spd_limit. This function is used to determine
* whether hardreset is necessary to apply SATA spd
* configuration.
*
@@ -2084,7 +2086,7 @@ int ata_set_mode(struct ata_port *ap, st
* return error code and failing device on failure.
*/
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- if (ata_dev_enabled(&ap->device[i])) {
+ if (ata_dev_enabled(&ap->link.device[i])) {
ap->ops->set_mode(ap);
break;
}
@@ -2096,7 +2098,7 @@ int ata_set_mode(struct ata_port *ap, st
for (i = 0; i < ATA_MAX_DEVICES; i++) {
unsigned int pio_mask, dma_mask;
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!ata_dev_enabled(dev))
continue;
@@ -2117,7 +2119,7 @@ int ata_set_mode(struct ata_port *ap, st
/* step 2: always set host PIO timings */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!ata_dev_enabled(dev))
continue;
@@ -2135,7 +2137,7 @@ int ata_set_mode(struct ata_port *ap, st
/* step 3: set host DMA timings */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!ata_dev_enabled(dev) || !dev->dma_mode)
continue;
@@ -2148,7 +2150,7 @@ int ata_set_mode(struct ata_port *ap, st
/* step 4: update devices' xfer mode */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!ata_dev_enabled(dev))
continue;
@@ -2356,6 +2358,7 @@ static unsigned int ata_bus_softreset(st
void ata_bus_reset(struct ata_port *ap)
{
+ struct ata_device *device = ap->link.device;
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
u8 err;
@@ -2388,23 +2391,23 @@ void ata_bus_reset(struct ata_port *ap)
/*
* determine by signature whether we have ATA or ATAPI devices
*/
- ap->device[0].class = ata_dev_try_classify(ap, 0, &err);
+ device[0].class = ata_dev_try_classify(ap, 0, &err);
if ((slave_possible) && (err != 0x81))
- ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
+ device[1].class = ata_dev_try_classify(ap, 1, &err);
/* re-enable interrupts */
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
ata_irq_on(ap);
/* is double-select really necessary? */
- if (ap->device[1].class != ATA_DEV_NONE)
+ if (device[1].class != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
- if (ap->device[0].class != ATA_DEV_NONE)
+ if (device[0].class != ATA_DEV_NONE)
ap->ops->dev_select(ap, 0);
/* if no devices were detected, disable this port */
- if ((ap->device[0].class == ATA_DEV_NONE) &&
- (ap->device[1].class == ATA_DEV_NONE))
+ if ((device[0].class == ATA_DEV_NONE) &&
+ (device[1].class == ATA_DEV_NONE))
goto err_out;
if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
@@ -2540,7 +2543,7 @@ int ata_std_prereset(struct ata_port *ap
int rc;
/* if we're about to do hardreset, don't bother */
- if (ap->eh_context.i.action & ATA_EH_HARDRESET)
+ if (ap->link.eh_context.i.action & ATA_EH_HARDRESET)
return 0;
/* resume port */
@@ -2822,7 +2825,7 @@ static int ata_dev_same_device(struct at
int ata_dev_revalidate(struct ata_device *dev, int post_reset)
{
unsigned int class = dev->class;
- u16 *id = (void *)dev->ap->sector_buf;
+ u16 *id = (void *)dev->link->ap->sector_buf;
int rc;
if (!ata_dev_enabled(dev)) {
@@ -2941,7 +2944,8 @@ static int ata_dma_blacklisted(const str
*/
static void ata_dev_xfermask(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
struct ata_host_set *hs = ap->host_set;
unsigned long xfer_mask;
int i;
@@ -2957,7 +2961,7 @@ static void ata_dev_xfermask(struct ata_
/* FIXME: Use port-wide xfermask for now */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *d = &ap->device[i];
+ struct ata_device *d = &link->device[i];
if (ata_dev_absent(d))
continue;
@@ -4199,7 +4203,7 @@ static struct ata_queued_cmd *ata_qc_new
struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
qc = ata_qc_new(ap);
@@ -4242,6 +4246,7 @@ void ata_qc_free(struct ata_queued_cmd *
void __ata_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ struct ata_link *link = qc->dev->link;
WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
@@ -4251,9 +4256,9 @@ void __ata_qc_complete(struct ata_queued
/* command should be marked inactive atomically with qc completion */
if (qc->tf.protocol == ATA_PROT_NCQ)
- ap->sactive &= ~(1 << qc->tag);
+ link->sactive &= ~(1 << qc->tag);
else
- ap->active_tag = ATA_TAG_POISON;
+ link->active_tag = ATA_TAG_POISON;
/* atapi: mark qc as inactive to prevent the interrupt handler
* from completing the command twice later, before the error handler
@@ -4416,19 +4421,20 @@ static inline int ata_should_dma_map(str
void ata_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ struct ata_link *link = qc->dev->link;
/* Make sure only one non-NCQ command is outstanding. The
* check is skipped for old EH because it reuses active qc to
* request ATAPI sense.
*/
- WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
+ WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
if (qc->tf.protocol == ATA_PROT_NCQ) {
- WARN_ON(ap->sactive & (1 << qc->tag));
- ap->sactive |= 1 << qc->tag;
+ WARN_ON(link->sactive & (1 << qc->tag));
+ link->sactive |= 1 << qc->tag;
} else {
- WARN_ON(ap->sactive);
- ap->active_tag = qc->tag;
+ WARN_ON(link->sactive);
+ link->active_tag = qc->tag;
}
qc->flags |= ATA_QCFLAG_ACTIVE;
@@ -4719,7 +4725,7 @@ irqreturn_t ata_interrupt (int irq, void
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
(qc->flags & ATA_QCFLAG_ACTIVE))
handled |= ata_host_intr(ap, qc);
@@ -4928,7 +4934,7 @@ static int ata_start_drive(struct ata_de
*/
int ata_device_resume(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
if (ap->flags & ATA_FLAG_SUSPENDED) {
struct ata_device *failed_dev;
@@ -4953,7 +4959,7 @@ int ata_device_resume(struct ata_device
*/
int ata_device_suspend(struct ata_device *dev, pm_message_t state)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
if (!ata_dev_enabled(dev))
return 0;
@@ -5059,11 +5065,12 @@ static void ata_host_remove(struct ata_p
*/
void ata_dev_init(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
unsigned long flags;
/* SATA spd limit is bound to the first device */
- ap->sata_spd_limit = ap->hw_sata_spd_limit;
+ link->sata_spd_limit = link->hw_sata_spd_limit;
/* High bits of dev->flags are used to record warm plug
* requests which occur asynchronously. Synchronize using
@@ -5121,8 +5128,8 @@ static void ata_host_init(struct ata_por
ap->udma_mask = ent->udma_mask;
ap->flags |= ent->host_flags;
ap->ops = ent->port_ops;
- ap->hw_sata_spd_limit = UINT_MAX;
- ap->active_tag = ATA_TAG_POISON;
+ ap->link.hw_sata_spd_limit = UINT_MAX;
+ ap->link.active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
INIT_WORK(&ap->port_task, NULL, NULL);
@@ -5134,9 +5141,11 @@ static void ata_host_init(struct ata_por
if (ap->flags & ATA_FLAG_SATA)
ap->cbl = ATA_CBL_SATA;
+ ap->link.ap = ap;
+
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->device[i];
- dev->ap = ap;
+ struct ata_device *dev = &ap->link.device[i];
+ dev->link = &ap->link;
dev->devno = i;
ata_dev_init(dev);
}
@@ -5298,9 +5307,9 @@ int ata_device_add(const struct ata_prob
/* init sata_spd_limit to the current value */
if (ata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
- ap->hw_sata_spd_limit &= (1 << spd) - 1;
+ ap->link.hw_sata_spd_limit &= (1 << spd) - 1;
}
- ap->sata_spd_limit = ap->hw_sata_spd_limit;
+ ap->link.sata_spd_limit = ap->link.hw_sata_spd_limit;
rc = scsi_add_host(ap->host, dev);
if (rc) {
@@ -5320,8 +5329,9 @@ int ata_device_add(const struct ata_prob
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1;
- ap->eh_info.action |= ATA_EH_SOFTRESET;
+ ap->link.eh_info.probe_mask =
+ (1 << ATA_MAX_DEVICES) - 1;
+ ap->link.eh_info.action |= ATA_EH_SOFTRESET;
set_bit(bit, &ap->flags);
ata_port_schedule_eh(ap);
@@ -5396,7 +5406,7 @@ void ata_port_detach(struct ata_port *ap
ap->flags |= ATA_FLAG_UNLOADING;
for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->device[i].flags |= ATA_DFLAG_DETACH;
+ ap->link.device[i].flags |= ATA_DFLAG_DETACH;
ata_port_schedule_eh(ap);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 88f8bc7..cde769f 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -133,7 +133,7 @@ enum scsi_eh_timer_return ata_scsi_timed
ret = EH_HANDLED;
spin_lock_irqsave(&ap->host_set->lock, flags);
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc) {
WARN_ON(qc->scsicmd != cmd);
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
@@ -238,10 +238,10 @@ void ata_scsi_error(struct Scsi_Host *ho
/* fetch & clear EH info */
spin_lock_irqsave(hs_lock, flags);
- memset(&ap->eh_context, 0, sizeof(ap->eh_context));
+ memset(&ap->link.eh_context, 0, sizeof(ap->link.eh_context));
if (!(ap->flags & ATA_FLAG_UNLOADING))
- ap->eh_context.i = ap->eh_info;
- memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+ ap->link.eh_context.i = ap->link.eh_info;
+ memset(&ap->link.eh_info, 0, sizeof(ap->link.eh_info));
ap->flags &= ~ATA_FLAG_EH_PENDING;
@@ -269,7 +269,7 @@ void ata_scsi_error(struct Scsi_Host *ho
}
/* this run is complete, make sure EH info is clear */
- memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+ memset(&ap->link.eh_info, 0, sizeof(ap->link.eh_info));
/* Clear host_eh_scheduled while holding hs_lock such
* that if exception occurs after this point but
@@ -280,7 +280,7 @@ void ata_scsi_error(struct Scsi_Host *ho
spin_unlock_irqrestore(hs_lock, flags);
} else {
- WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+ WARN_ON(ata_qc_from_tag(ap, ap->link.active_tag) == NULL);
ap->ops->eng_timeout(ap);
}
@@ -401,7 +401,7 @@ void ata_eng_timeout(struct ata_port *ap
{
DPRINTK("ENTER\n");
- ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+ ata_qc_timeout(ata_qc_from_tag(ap, ap->link.active_tag));
DPRINTK("EXIT\n");
}
@@ -654,7 +654,7 @@ void ata_eh_qc_retry(struct ata_queued_c
*/
static void ata_eh_detach_dev(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
unsigned long flags;
ata_dev_disable(dev);
@@ -688,7 +688,7 @@ static void ata_eh_about_to_do(struct at
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->eh_info.action &= ~action;
+ ap->link.eh_info.action &= ~action;
ap->flags |= ATA_FLAG_RECOVERED;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
@@ -784,7 +784,7 @@ static unsigned int ata_read_log_page(st
static int ata_eh_read_log_10h(struct ata_device *dev,
int *tag, struct ata_taskfile *tf)
{
- u8 *buf = dev->ap->sector_buf;
+ u8 *buf = dev->link->ap->sector_buf;
unsigned int err_mask;
u8 csum;
int i;
@@ -837,7 +837,7 @@ static int ata_eh_read_log_10h(struct at
static unsigned int atapi_eh_request_sense(struct ata_device *dev,
unsigned char *sense_buf)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
struct ata_taskfile tf;
u8 cdb[ATAPI_CDB_LEN];
@@ -889,7 +889,7 @@ static unsigned int atapi_eh_request_sen
*/
static void ata_eh_analyze_serror(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
u32 serror = ehc->i.serror;
unsigned int err_mask = 0, action = 0;
@@ -934,8 +934,8 @@ static void ata_eh_analyze_serror(struct
*/
static void ata_eh_analyze_ncq_error(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
- struct ata_device *dev = ap->device;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_device *dev = ap->link.device;
struct ata_queued_cmd *qc;
struct ata_taskfile tf;
int tag, rc;
@@ -945,7 +945,7 @@ static void ata_eh_analyze_ncq_error(str
return;
/* is it NCQ device error? */
- if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+ if (!ap->link.sactive || !(ehc->i.err_mask & AC_ERR_DEV))
return;
/* has LLDD analyzed already? */
@@ -967,7 +967,7 @@ static void ata_eh_analyze_ncq_error(str
return;
}
- if (!(ap->sactive & (1 << tag))) {
+ if (!(ap->link.sactive & (1 << tag))) {
ata_port_printk(ap, KERN_ERR, "log page 10h reported "
"inactive tag %d\n", tag);
return;
@@ -1154,7 +1154,7 @@ static int ata_eh_speed_down(struct ata_
return 0;
/* speed down SATA link speed if possible */
- if (ata_down_sata_spd_limit(dev->ap) == 0)
+ if (ata_down_sata_spd_limit(dev->link->ap) == 0)
return ATA_EH_HARDRESET;
/* lower transfer mode */
@@ -1179,7 +1179,7 @@ static int ata_eh_speed_down(struct ata_
*/
static void ata_eh_autopsy(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
unsigned int action = ehc->i.action;
struct ata_device *failed_dev = NULL;
unsigned int all_err_mask = 0;
@@ -1267,7 +1267,7 @@ static void ata_eh_autopsy(struct ata_po
*/
static void ata_eh_report(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
const char *frozen, *desc;
int tag, nr_failed = 0;
@@ -1296,15 +1296,15 @@ static void ata_eh_report(struct ata_por
if (ehc->i.dev) {
ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s\n",
- ehc->i.err_mask, ap->sactive, ehc->i.serror,
- ehc->i.action, frozen);
+ ehc->i.err_mask, ap->link.sactive,
+ ehc->i.serror, ehc->i.action, frozen);
if (desc)
ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
} else {
ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s\n",
- ehc->i.err_mask, ap->sactive, ehc->i.serror,
- ehc->i.action, frozen);
+ ehc->i.err_mask, ap->link.sactive,
+ ehc->i.serror, ehc->i.action, frozen);
if (desc)
ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
}
@@ -1367,7 +1367,7 @@ static int ata_eh_reset(struct ata_port
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
int verbose = !(ap->flags & ATA_FLAG_LOADING);
@@ -1484,7 +1484,7 @@ static int ata_eh_reset(struct ata_port
static int ata_eh_revalidate_and_attach(struct ata_port *ap,
struct ata_device **r_failed_dev)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
struct ata_device *dev;
unsigned long flags;
int i, rc = 0;
@@ -1492,7 +1492,7 @@ static int ata_eh_revalidate_and_attach(
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) &&
(!ehc->i.dev || ehc->i.dev == dev)) {
@@ -1540,7 +1540,7 @@ static int ata_port_nr_enabled(struct at
int i, cnt = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_enabled(&ap->device[i]))
+ if (ata_dev_enabled(&ap->link.device[i]))
cnt++;
return cnt;
}
@@ -1550,14 +1550,14 @@ static int ata_port_nr_vacant(struct ata
int i, cnt = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ap->device[i].class == ATA_DEV_UNKNOWN)
+ if (ap->link.device[i].class == ATA_DEV_UNKNOWN)
cnt++;
return cnt;
}
static int ata_eh_skip_recovery(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
int i;
if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
@@ -1565,7 +1565,7 @@ static int ata_eh_skip_recovery(struct a
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->device[i];
+ struct ata_device *dev = &ap->link.device[i];
if (dev->class == ATA_DEV_UNKNOWN &&
ehc->classes[dev->devno] != ATA_DEV_NONE)
@@ -1600,7 +1600,7 @@ static int ata_eh_recover(struct ata_por
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
struct ata_device *dev;
int down_xfermask, i, rc;
@@ -1608,7 +1608,7 @@ static int ata_eh_recover(struct ata_por
/* prep for recovery */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
@@ -1725,7 +1725,7 @@ static int ata_eh_recover(struct ata_por
out:
if (rc) {
for (i = 0; i < ATA_MAX_DEVICES; i++)
- ata_dev_disable(&ap->device[i]);
+ ata_dev_disable(&ap->link.device[i]);
}
DPRINTK("EXIT, rc=%d\n", rc);
@@ -1812,7 +1812,7 @@ void ata_eh_scsi_hotplug(void *data)
/* unplug detached devices */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->device[i];
+ struct ata_device *dev = &ap->link.device[i];
unsigned long flags;
if (!(dev->flags & ATA_DFLAG_DETACHED))
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index f5ded5b..6d9384a 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1356,16 +1356,16 @@ static void ata_scsi_qc_complete(struct
*/
static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
{
- struct ata_port *ap = dev->ap;
+ struct ata_link *link = dev->link;
if (!(dev->flags & ATA_DFLAG_NCQ))
return 0;
if (is_io) {
- if (!ata_tag_valid(ap->active_tag))
+ if (!ata_tag_valid(link->active_tag))
return 0;
} else {
- if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
+ if (!ata_tag_valid(link->active_tag) && !link->sactive)
return 0;
}
return 1;
@@ -2348,7 +2348,7 @@ static unsigned int atapi_xlat(struct at
static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
{
if (likely(id == 0 || (id == 1 && ap->flags & ATA_FLAG_SLAVE_POSS)))
- return &ap->device[id];
+ return &ap->link.device[id];
return NULL;
}
@@ -2781,7 +2781,7 @@ void ata_scsi_scan_host(struct ata_port
return;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->device[i];
+ struct ata_device *dev = &ap->link.device[i];
struct scsi_device *sdev;
if (!ata_dev_enabled(dev) || dev->sdev)
@@ -2831,7 +2831,7 @@ int ata_scsi_offline_dev(struct ata_devi
*/
void ata_scsi_remove_dev(struct ata_device *dev)
{
- struct ata_port *ap = dev->ap;
+ struct ata_port *ap = dev->link->ap;
struct scsi_device *sdev;
unsigned long flags;
@@ -2911,14 +2911,14 @@ static int ata_scsi_user_scan(struct Scs
spin_lock_irqsave(&ap->host_set->lock, flags);
if (id == SCAN_WILD_CARD) {
- ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
- ap->eh_info.action |= ATA_EH_SOFTRESET;
+ ap->link.eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+ ap->link.eh_info.action |= ATA_EH_SOFTRESET;
} else {
struct ata_device *dev = ata_find_dev(ap, id);
if (dev) {
- ap->eh_info.probe_mask |= 1 << dev->devno;
- ap->eh_info.action |= ATA_EH_SOFTRESET;
+ ap->link.eh_info.probe_mask |= 1 << dev->devno;
+ ap->link.eh_info.action |= ATA_EH_SOFTRESET;
} else
rc = -EINVAL;
}
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index eb910e4..f771359 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -461,7 +461,7 @@ static inline unsigned int adma_intr_pkt
pp = ap->private_data;
if (!pp || pp->state != adma_state_pkt)
continue;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
if ((status & (aPERR | aPSD | aUIRQ)))
qc->err_mask |= AC_ERR_OTHER;
@@ -486,7 +486,7 @@ static inline unsigned int adma_intr_mmi
struct adma_port_priv *pp = ap->private_data;
if (!pp || pp->state != adma_state_mmio)
continue;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 4e6388f..af4b1f8 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1413,7 +1413,7 @@ static void mv_host_intr(struct ata_host
}
if (handled) {
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status);
@@ -1922,7 +1922,7 @@ static void __mv_phy_reset(struct ata_po
struct mv_host_priv *hpriv = ap->host_set->private_data;
void __iomem *port_mmio = mv_ap_base(ap);
struct ata_taskfile tf;
- struct ata_device *dev = &ap->device[0];
+ struct ata_device *dev = &ap->link.device[0];
unsigned long timeout;
int retry = 5;
u32 sstatus;
@@ -2029,7 +2029,7 @@ static void mv_eng_timeout(struct ata_po
mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
to_pci_dev(ap->host_set->dev));
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
ap->host_set->mmio_base, ap, qc, qc->scsicmd,
&qc->scsicmd->cmnd);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 2a840f5..58e5658 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -283,7 +283,7 @@ static irqreturn_t nv_interrupt (int irq
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += ata_host_intr(ap, qc);
else
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 9c70018..6f598ea 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -432,7 +432,7 @@ static void pdc_eng_timeout(struct ata_p
spin_lock_irqsave(&host_set->lock, flags);
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
@@ -539,7 +539,7 @@ static irqreturn_t pdc_interrupt (int ir
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc_host_intr(ap, qc);
}
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 3fc1003..fe2a6cf 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -400,7 +400,7 @@ static inline unsigned int qs_intr_pkt(s
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_pkt)
continue;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
switch (sHST) {
case 0: /* successful CPB */
@@ -433,7 +433,7 @@ static inline unsigned int qs_intr_mmio(
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio)
continue;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 59c49d3..84756af 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -285,7 +285,7 @@ static void sil_post_set_mode (struct at
unsigned int i;
for (i = 0; i < 2; i++) {
- dev = &ap->device[i];
+ dev = &ap->link.device[i];
if (!ata_dev_enabled(dev))
dev_mode[i] = 0; /* PIO0/1/2 */
else if (dev->flags & ATA_DFLAG_PIO)
@@ -339,7 +339,7 @@ static void sil_scr_write (struct ata_po
static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
{
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
u8 status;
if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ || !qc || qc->tf.ctl & ATA_NIEN))
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 8bbcf69..6e0b74b 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -735,7 +735,7 @@ static void sil24_thaw(struct ata_port *
static void sil24_error_intr(struct ata_port *ap)
{
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
- struct ata_eh_info *ehi = &ap->eh_info;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
int freeze = 0;
u32 irq_stat;
@@ -794,7 +794,7 @@ static void sil24_error_intr(struct ata_
}
/* record error info */
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc) {
sil24_read_tf(ap, sil24_tag(qc->tag), &qc->result_tf);
qc->err_mask |= err_mask;
@@ -838,7 +838,7 @@ static inline void sil24_host_intr(struc
if (rc > 0)
return;
if (rc < 0) {
- struct ata_eh_info *ehi = &ap->eh_info;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_SOFTRESET;
ata_port_freeze(ap);
@@ -848,7 +848,7 @@ static inline void sil24_host_intr(struc
if (ata_ratelimit())
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
- slot_stat, ap->active_tag, ap->sactive);
+ slot_stat, ap->link.active_tag, ap->link.sactive);
}
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -890,7 +890,7 @@ static irqreturn_t sil24_interrupt(int i
static void sil24_error_handler(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->eh_context;
+ struct ata_eh_context *ehc = &ap->link.eh_context;
if (sil24_init_port(ap)) {
ata_eh_freeze_port(ap);
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index fb69fc2..6432cf0 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -837,7 +837,7 @@ static irqreturn_t pdc20621_interrupt (i
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc20621_host_intr(ap, qc, (i > 4),
mmio_base);
@@ -864,7 +864,7 @@ static void pdc_eng_timeout(struct ata_p
spin_lock_irqsave(&host_set->lock, flags);
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index d51c8d6..96700ec 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -232,7 +232,7 @@ static irqreturn_t vsc_sata_interrupt (i
if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += ata_host_intr(ap, qc);
else if (is_vsc_sata_int_err(i, int_status)) {
diff --git a/include/linux/libata.h b/include/linux/libata.h
index db9e84c..fbb3f4c 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -417,7 +417,7 @@ struct ata_ering {
struct ata_ering_entry name_entries[size];
struct ata_device {
- struct ata_port *ap;
+ struct ata_link *link;
unsigned int devno; /* 0 or 1 */
unsigned long flags; /* ATA_DFLAG_xxx */
struct scsi_device *sdev; /* attached SCSI device */
@@ -468,6 +468,24 @@ struct ata_eh_context {
unsigned int did_probe_mask;
};
+struct ata_link {
+ struct ata_port *ap;
+
+ unsigned int active_tag; /* active tag on this link */
+ u32 sactive; /* active NCQ commands */
+
+ unsigned int flags; /* ATA_LFLAG_* */
+ unsigned int hw_sata_spd_limit;
+ unsigned int sata_spd_limit;
+
+ /* record runtime error info, protected by host_set lock */
+ struct ata_eh_info eh_info;
+ /* EH context */
+ struct ata_eh_context eh_context;
+
+ struct ata_device device[1];
+};
+
struct ata_port {
struct Scsi_Host *host; /* our co-allocated scsi host */
const struct ata_port_operations *ops;
@@ -490,22 +508,13 @@ struct ata_port {
unsigned int mwdma_mask;
unsigned int udma_mask;
unsigned int cbl; /* cable type; ATA_CBL_xxx */
- unsigned int hw_sata_spd_limit;
- unsigned int sata_spd_limit; /* SATA PHY speed limit */
-
- /* record runtime error info, protected by host_set lock */
- struct ata_eh_info eh_info;
- /* EH context owned by EH */
- struct ata_eh_context eh_context;
-
- struct ata_device device[ATA_MAX_DEVICES];
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
unsigned long qc_allocated;
unsigned int qc_active;
- unsigned int active_tag;
- u32 sactive;
+ struct ata_link link; /* host default link */
+ struct ata_device __dev1; /* storage for link.device[1] */
struct ata_host_stats stats;
struct ata_host_set *host_set;
@@ -782,8 +791,11 @@ extern void ata_do_eh(struct ata_port *a
#define ata_port_printk(ap, lv, fmt, args...) \
printk(lv"ata%u: "fmt, (ap)->id , ##args)
+#define ata_link_printk(link, lv, fmt, args...) \
+ printk(lv"ata%u: "fmt, (link)->ap->id , ##args)
+
#define ata_dev_printk(dev, lv, fmt, args...) \
- printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
+ printk(lv"ata%u.%02u: "fmt, (dev)->link->ap->id, (dev)->devno , ##args)
/*
* ata_eh_info helpers
@@ -984,7 +996,7 @@ static inline void ata_tf_init(struct at
{
memset(tf, 0, sizeof(*tf));
- tf->ctl = dev->ap->ctl;
+ tf->ctl = dev->link->ap->ctl;
if (dev->devno == 0)
tf->device = ATA_DEVICE_OBS;
else
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 01/14] libata-link: add PM related ATA constants
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
2006-05-11 16:30 ` [PATCH 02/14] libata-link: introduce ata_link Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 05/14] libata-link: linkify reset Tejun Heo
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Add Port Multiplier related ATA constants and macros. Some of these
will be used by ata_link implementation.
---
include/linux/ata.h | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
51b532b3a54ccca372762a5f3cad55e65807df27
diff --git a/include/linux/ata.h b/include/linux/ata.h
index c494e1c..41ea837 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -154,6 +154,8 @@ enum {
ATA_CMD_READ_NATIVE_MAX = 0xF8,
ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
ATA_CMD_READ_LOG_EXT = 0x2f,
+ ATA_CMD_PM_READ = 0xE4,
+ ATA_CMD_PM_WRITE = 0xE8,
/* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10,
@@ -187,6 +189,28 @@ enum {
0=to device, 1=to host */
ATAPI_CDB_LEN = 16,
+ /* PM stuff */
+ ATA_PM_MAX_PORTS = 15,
+ ATA_PM_CTRL_PORT = 15,
+
+ ATA_PM_GSCR_DWORDS = 128,
+ ATA_PM_GSCR_PROD_ID = 0,
+ ATA_PM_GSCR_REV = 1,
+ ATA_PM_GSCR_PORT_INFO = 2,
+ ATA_PM_GSCR_ERROR = 32,
+ ATA_PM_GSCR_ERROR_EN = 33,
+ ATA_PM_GSCR_FEAT = 64,
+ ATA_PM_GSCR_FEAT_EN = 96,
+
+ ATA_PM_PSCR_STATUS = 0,
+ ATA_PM_PSCR_ERROR = 1,
+ ATA_PM_PSCR_CONTROL = 2,
+
+ ATA_PM_FEAT_BIST = (1 << 0),
+ ATA_PM_FEAT_PMREQ = (1 << 1),
+ ATA_PM_FEAT_DYNSSC = (1 << 2),
+ ATA_PM_FEAT_NOTIFY = (1 << 3),
+
/* cable types */
ATA_CBL_NONE = 0,
ATA_CBL_PATA40 = 1,
@@ -363,4 +387,9 @@ static inline int lba_48_ok(u64 block, u
return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
}
+#define ata_pm_gscr_vendor(gscr) ((gscr)[ATA_PM_GSCR_PROD_ID] & 0xffff)
+#define ata_pm_gscr_devid(gscr) ((gscr)[ATA_PM_GSCR_PROD_ID] >> 16)
+#define ata_pm_gscr_rev(gscr) (((gscr)[ATA_PM_GSCR_REV] >> 8) & 0xff)
+#define ata_pm_gscr_ports(gscr) ((gscr)[ATA_PM_GSCR_PORT_INFO] & 0xf)
+
#endif /* __LINUX_ATA_H__ */
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 05/14] libata-link: linkify reset
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
2006-05-11 16:30 ` [PATCH 02/14] libata-link: introduce ata_link Tejun Heo
2006-05-11 16:30 ` [PATCH 01/14] libata-link: add PM related ATA constants Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 07/14] libata-link: separate out link initialization functions Tejun Heo
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Make reset methods and related functions deal with ata_link instead of
ata_port.
* ata_eh_about_to_do()
* ata_do_reset()
* ata_eh_reset()
* all prereset/reset/postreset methods
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 31 ++++++++++++++++-----------
drivers/scsi/ata_piix.c | 14 +++++++-----
drivers/scsi/libata-core.c | 36 +++++++++++++++++---------------
drivers/scsi/libata-eh.c | 50 ++++++++++++++++++++++----------------------
drivers/scsi/sata_sil24.c | 20 ++++++++++--------
include/linux/libata.h | 15 +++++++------
6 files changed, 89 insertions(+), 77 deletions(-)
d3d6129dc940ccbb72c4bb834482456776342b84
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index d4420ac..3254cd2 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -562,19 +562,22 @@ static int ahci_clo(struct ata_port *ap)
return 0;
}
-static int ahci_prereset(struct ata_port *ap)
+static int ahci_prereset(struct ata_link *link)
{
+ struct ata_port *ap = link->ap;
+
if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
(ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
/* ATA_BUSY hasn't cleared, so send a CLO */
ahci_clo(ap);
}
- return ata_std_prereset(ap);
+ return ata_std_prereset(link);
}
-static int ahci_softreset(struct ata_port *ap, unsigned int *class)
+static int ahci_softreset(struct ata_link *link, unsigned int *class)
{
+ struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data;
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
@@ -587,7 +590,7 @@ static int ahci_softreset(struct ata_por
DPRINTK("ENTER\n");
- if (ata_link_offline(&ap->link)) {
+ if (ata_link_offline(link)) {
DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE;
return 0;
@@ -617,7 +620,7 @@ static int ahci_softreset(struct ata_por
/* restart engine */
ahci_start_engine(ap);
- ata_tf_init(ap->link.device, &tf);
+ ata_tf_init(link->device, &tf);
fis = pp->cmd_tbl;
/* issue the first D2H Register FIS */
@@ -661,7 +664,7 @@ static int ahci_softreset(struct ata_por
msleep(150);
*class = ATA_DEV_NONE;
- if (ata_link_online(&ap->link)) {
+ if (ata_link_online(link)) {
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
rc = -EIO;
reason = "device not ready";
@@ -676,21 +679,22 @@ static int ahci_softreset(struct ata_por
fail_restart:
ahci_start_engine(ap);
fail:
- ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+ ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
return rc;
}
-static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
+static int ahci_hardreset(struct ata_link *link, unsigned int *class)
{
+ struct ata_port *ap = link->ap;
int rc;
DPRINTK("ENTER\n");
ahci_stop_engine(ap);
- rc = sata_std_hardreset(ap, class);
+ rc = sata_std_hardreset(link, class);
ahci_start_engine(ap);
- if (rc == 0 && ata_link_online(&ap->link))
+ if (rc == 0 && ata_link_online(link))
*class = ahci_dev_classify(ap);
if (*class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE;
@@ -699,17 +703,18 @@ static int ahci_hardreset(struct ata_por
return rc;
}
-static void ahci_postreset(struct ata_port *ap, unsigned int *class)
+static void ahci_postreset(struct ata_link *link, unsigned int *class)
{
+ struct ata_port *ap = link->ap;
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
unsigned long flags;
u32 new_tmp, tmp;
- ata_std_postreset(ap, class);
+ ata_std_postreset(link, class);
/* clear stored SError */
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->link.eh_info.serror = 0;
+ link->eh_info.serror = 0;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
/* Make sure port's ATAPI bit is set appropriately */
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 47d3fec..11c44ec 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -458,15 +458,16 @@ cbl40:
/**
* piix_pata_prereset - prereset for PATA host controller
- * @ap: Target port
+ * @link: Target link
*
* Prereset including cable detection.
*
* LOCKING:
* None (inherited from caller).
*/
-static int piix_pata_prereset(struct ata_port *ap)
+static int piix_pata_prereset(struct ata_link *link)
{
+ struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
@@ -476,7 +477,7 @@ static int piix_pata_prereset(struct ata
piix_pata_cbl_detect(ap);
- return ata_std_prereset(ap);
+ return ata_std_prereset(link);
}
static void piix_pata_error_handler(struct ata_port *ap)
@@ -487,7 +488,7 @@ static void piix_pata_error_handler(stru
/**
* piix_sata_prereset - prereset for SATA host controller
- * @ap: Target port
+ * @link: Target link
*
* Reads and configures SATA PCI device's PCI config register
* Port Configuration and Status (PCS) to determine port and
@@ -500,8 +501,9 @@ static void piix_pata_error_handler(stru
* RETURNS:
* 0 if device is present, -ENODEV otherwise.
*/
-static int piix_sata_prereset(struct ata_port *ap)
+static int piix_sata_prereset(struct ata_link *link)
{
+ struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
const unsigned int *map = ap->host_set->private_data;
int base = 2 * ap->hard_port_no;
@@ -547,7 +549,7 @@ static int piix_sata_prereset(struct ata
return -ENODEV;
}
- return ata_std_prereset(ap);
+ return ata_std_prereset(link);
}
static void piix_sata_error_handler(struct ata_port *ap)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9680359..6dc370f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2521,9 +2521,9 @@ int sata_link_resume(struct ata_link *li
/**
* ata_std_prereset - prepare for reset
- * @ap: ATA port to be reset
+ * @link: ATA link to be reset
*
- * @ap is about to be reset. Initialize it.
+ * @link is about to be reset. Initialize it.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -2531,20 +2531,21 @@ int sata_link_resume(struct ata_link *li
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_std_prereset(struct ata_port *ap)
+int ata_std_prereset(struct ata_link *link)
{
+ struct ata_port *ap = link->ap;
int boot_probe = ap->flags & ATA_FLAG_LOADING;
int rc;
/* if we're about to do hardreset, don't bother */
- if (ap->link.eh_context.i.action & ATA_EH_HARDRESET)
+ if (link->eh_context.i.action & ATA_EH_HARDRESET)
return 0;
/* resume link */
- rc = sata_link_resume(&ap->link, boot_probe);
+ rc = sata_link_resume(link, boot_probe);
if (rc && rc != -EOPNOTSUPP) {
/* phy resume failed, whine but continue */
- ata_port_printk(ap, KERN_WARNING, "failed to resume link "
+ ata_link_printk(link, KERN_WARNING, "failed to resume link "
"for reset (errno=%d)\n", rc);
}
@@ -2554,7 +2555,7 @@ int ata_std_prereset(struct ata_port *ap
* cases. As we wait for !BSY after resets, this should be
* safe.
*/
- if (boot_probe && !ata_link_offline(&ap->link))
+ if (boot_probe && !ata_link_offline(link))
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
return 0;
@@ -2562,7 +2563,7 @@ int ata_std_prereset(struct ata_port *ap
/**
* ata_std_softreset - reset host port via ATA SRST
- * @ap: port to reset
+ * @link: ATA link to reset
* @classes: resulting classes of attached devices
*
* Reset host port using ATA SRST.
@@ -2573,15 +2574,16 @@ int ata_std_prereset(struct ata_port *ap
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
+int ata_std_softreset(struct ata_link *link, unsigned int *classes)
{
+ struct ata_port *ap = link->ap;
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
unsigned int devmask = 0, err_mask;
u8 err;
DPRINTK("ENTER\n");
- if (ata_link_offline(&ap->link)) {
+ if (ata_link_offline(link)) {
classes[0] = ATA_DEV_NONE;
goto out;
}
@@ -2599,7 +2601,7 @@ int ata_std_softreset(struct ata_port *a
DPRINTK("about to softreset, devmask=%x\n", devmask);
err_mask = ata_bus_softreset(ap, devmask);
if (err_mask) {
- ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
+ ata_link_printk(link, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
err_mask);
return -EIO;
}
@@ -2616,7 +2618,7 @@ int ata_std_softreset(struct ata_port *a
/**
* sata_std_hardreset - reset host port via SATA phy reset
- * @ap: port to reset
+ * @link: link to reset
* @class: resulting class of attached device
*
* SATA phy-reset host port using DET bits of SControl register.
@@ -2627,9 +2629,9 @@ int ata_std_softreset(struct ata_port *a
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+int sata_std_hardreset(struct ata_link *link, unsigned int *class)
{
- struct ata_link *link = &ap->link;
+ struct ata_port *ap = link->ap;
u32 scontrol;
int rc;
@@ -2692,7 +2694,7 @@ int sata_std_hardreset(struct ata_port *
/**
* ata_std_postreset - standard postreset callback
- * @ap: the target ata_port
+ * @link: the target ata_link
* @classes: classes of attached devices
*
* This function is invoked after a successful reset. Note that
@@ -2702,9 +2704,9 @@ int sata_std_hardreset(struct ata_port *
* LOCKING:
* Kernel thread context (may sleep)
*/
-void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
+void ata_std_postreset(struct ata_link *link, unsigned int *classes)
{
- struct ata_link *link = &ap->link;
+ struct ata_port *ap = link->ap;
u32 serror;
DPRINTK("ENTER\n");
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 7ade712..7e5a03a 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -673,22 +673,23 @@ static void ata_eh_detach_dev(struct ata
/**
* ata_eh_about_to_do - about to perform eh_action
- * @ap: target ATA port
+ * @link: target ATA link
* @action: action about to be performed
*
* Called just before performing EH actions to clear related bits
- * in @ap->eh_info such that eh actions are not unnecessarily
+ * in @link->eh_info such that eh actions are not unnecessarily
* repeated.
*
* LOCKING:
* None.
*/
-static void ata_eh_about_to_do(struct ata_port *ap, unsigned int action)
+static void ata_eh_about_to_do(struct ata_link *link, unsigned int action)
{
+ struct ata_port *ap = link->ap;
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->link.eh_info.action &= ~action;
+ link->eh_info.action &= ~action;
ap->flags |= ATA_FLAG_RECOVERED;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
@@ -1324,16 +1325,16 @@ static void ata_eh_report(struct ata_por
}
}
-static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
unsigned int *classes)
{
struct ata_device *dev;
int rc;
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
classes[dev->devno] = ATA_DEV_UNKNOWN;
- rc = reset(ap, classes);
+ rc = reset(link, classes);
if (rc)
return rc;
@@ -1341,12 +1342,12 @@ static int ata_do_reset(struct ata_port
* is complete and convert all ATA_DEV_UNKNOWN to
* ATA_DEV_NONE.
*/
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
if (classes[dev->devno] != ATA_DEV_UNKNOWN)
break;
if (dev)
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
if (classes[dev->devno] == ATA_DEV_UNKNOWN)
classes[dev->devno] = ATA_DEV_NONE;
@@ -1365,15 +1366,14 @@ static int ata_eh_followup_srst_needed(i
return 0;
}
-static int ata_eh_reset(struct ata_port *ap, int classify,
+static int ata_eh_reset(struct ata_link *link, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
- struct ata_link *link = &ap->link;
struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
- int verbose = !(ap->flags & ATA_FLAG_LOADING);
+ int verbose = !(link->ap->flags & ATA_FLAG_LOADING);
unsigned int action;
ata_reset_fn_t reset;
int did_followup_srst, rc;
@@ -1394,7 +1394,7 @@ static int ata_eh_reset(struct ata_port
}
if (prereset) {
- rc = prereset(ap);
+ rc = prereset(link);
/* prereset can short-circuit resetting by returning
* -ENODEV.
@@ -1407,7 +1407,7 @@ static int ata_eh_reset(struct ata_port
}
if (rc) {
- ata_port_printk(ap, KERN_ERR,
+ ata_link_printk(link, KERN_ERR,
"prereset failed (errno=%d)\n", rc);
return rc;
}
@@ -1416,14 +1416,14 @@ static int ata_eh_reset(struct ata_port
retry:
/* shut up during boot probing */
if (verbose)
- ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
+ ata_link_printk(link, KERN_INFO, "%s resetting port\n",
reset == softreset ? "soft" : "hard");
/* reset */
- ata_eh_about_to_do(ap, ATA_EH_RESET_MASK);
+ ata_eh_about_to_do(link, ATA_EH_RESET_MASK);
ehc->flags |= ATA_EHC_DID_RESET;
- rc = ata_do_reset(ap, reset, classes);
+ rc = ata_do_reset(link, reset, classes);
did_followup_srst = 0;
if (reset == hardreset &&
@@ -1433,18 +1433,18 @@ static int ata_eh_reset(struct ata_port
reset = softreset;
if (!reset) {
- ata_port_printk(ap, KERN_ERR,
+ ata_link_printk(link, KERN_ERR,
"follow-up softreset required "
"but no softreset avaliable\n");
return -EINVAL;
}
- ata_eh_about_to_do(ap, ATA_EH_RESET_MASK);
- rc = ata_do_reset(ap, reset, classes);
+ ata_eh_about_to_do(link, ATA_EH_RESET_MASK);
+ rc = ata_do_reset(link, reset, classes);
if (rc == 0 && classify &&
classes[0] == ATA_DEV_UNKNOWN) {
- ata_port_printk(ap, KERN_ERR,
+ ata_link_printk(link, KERN_ERR,
"classification failed\n");
return -EINVAL;
}
@@ -1461,7 +1461,7 @@ static int ata_eh_reset(struct ata_port
} else
type = "hard";
- ata_port_printk(ap, KERN_WARNING,
+ ata_link_printk(link, KERN_WARNING,
"%sreset failed, retrying in 5 secs\n", type);
ssleep(5);
@@ -1474,7 +1474,7 @@ static int ata_eh_reset(struct ata_port
if (rc == 0) {
if (postreset)
- postreset(ap, classes);
+ postreset(link, classes);
/* reset successful, schedule revalidation */
ehc->i.dev = NULL;
@@ -1503,7 +1503,7 @@ static int ata_eh_revalidate_and_attach(
break;
}
- ata_eh_about_to_do(ap, ATA_EH_REVALIDATE);
+ ata_eh_about_to_do(&ap->link, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev,
ehc->flags & ATA_EHC_DID_RESET);
if (rc)
@@ -1641,7 +1641,7 @@ static int ata_eh_recover(struct ata_por
if (ehc->i.action & ATA_EH_RESET_MASK) {
ata_eh_freeze_port(ap);
- rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
+ rc = ata_eh_reset(&ap->link, ata_port_nr_vacant(ap), prereset,
softreset, hardreset, postreset);
if (rc) {
ata_port_printk(ap, KERN_ERR,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 51fceac..103e5d3 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -509,8 +509,9 @@ static int sil24_init_port(struct ata_po
return 0;
}
-static int sil24_softreset(struct ata_port *ap, unsigned int *class)
+static int sil24_softreset(struct ata_link *link, unsigned int *class)
{
+ struct ata_port *ap = link->ap;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
@@ -521,7 +522,7 @@ static int sil24_softreset(struct ata_po
DPRINTK("ENTER\n");
- if (ata_link_offline(&ap->link)) {
+ if (ata_link_offline(link)) {
DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE;
goto out;
@@ -566,22 +567,23 @@ static int sil24_softreset(struct ata_po
return 0;
err:
- ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+ ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
return -EIO;
}
-static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
+static int sil24_hardreset(struct ata_link *link, unsigned int *class)
{
+ struct ata_port *ap = link->ap;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
const char *reason;
int tout_msec, rc;
u32 tmp;
/* sil24 does the right thing(tm) without any protection */
- ata_set_sata_spd(&ap->link);
+ ata_set_sata_spd(link);
tout_msec = 100;
- if (ata_link_online(&ap->link))
+ if (ata_link_online(link))
tout_msec = 5000;
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
@@ -591,7 +593,7 @@ static int sil24_hardreset(struct ata_po
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
*/
- rc = sata_link_debounce(&ap->link, ATA_DEBOUNCE_INTERVAL,
+ rc = sata_link_debounce(link, ATA_DEBOUNCE_INTERVAL,
ATA_DEBOUNCE_DURATION, ATA_DEBOUNCE_TIMEOUT);
if (rc) {
reason = "PHY debouncing failed";
@@ -599,7 +601,7 @@ static int sil24_hardreset(struct ata_po
}
if (tmp & PORT_CS_DEV_RST) {
- if (ata_link_offline(&ap->link))
+ if (ata_link_offline(link))
return 0;
reason = "link not ready";
goto err;
@@ -614,7 +616,7 @@ static int sil24_hardreset(struct ata_po
return -EAGAIN;
err:
- ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
+ ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason);
return -EIO;
}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 67a9054..61fddbf 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -292,13 +292,14 @@ enum ata_completion_errors {
struct scsi_device;
struct ata_port_operations;
struct ata_port;
+struct ata_link;
struct ata_queued_cmd;
/* typedefs */
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
-typedef int (*ata_prereset_fn_t)(struct ata_port *ap);
-typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes);
-typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
+typedef int (*ata_prereset_fn_t)(struct ata_link *link);
+typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes);
+typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
struct ata_ioports {
unsigned long cmd_addr;
@@ -622,10 +623,10 @@ extern int sata_link_debounce(struct ata
unsigned long duration_msec,
unsigned long timeout_msec);
extern int sata_link_resume(struct ata_link *link, int quick);
-extern int ata_std_prereset(struct ata_port *ap);
-extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
-extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
-extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
+extern int ata_std_prereset(struct ata_link *link);
+extern int ata_std_softreset(struct ata_link *link, unsigned int *classes);
+extern int sata_std_hardreset(struct ata_link *link, unsigned int *class);
+extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr);
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 07/14] libata-link: separate out link initialization functions
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (2 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 05/14] libata-link: linkify reset Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 10/14] libata-link: add PM links Tejun Heo
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Separate out link initialization into ata_link_init() and
ata_link_init_sata_spd_limit().
---
drivers/scsi/libata-core.c | 83 ++++++++++++++++++++++++++++++++++----------
1 files changed, 65 insertions(+), 18 deletions(-)
b1520dbca5c449c69ccb6eb54a6449801d044b87
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index dd40909..de0f56f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -65,6 +65,7 @@ static unsigned int ata_dev_init_params(
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 int ata_link_init_sata_spd_limit(struct ata_link *link);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
@@ -5094,6 +5095,68 @@ void ata_dev_init(struct ata_device *dev
}
/**
+ * ata_link_init - Initialize an ata_link structure
+ * @ap: ATA port link is attached to
+ * @link: Link structure to initialize
+ * @pmp: Port multiplier port number
+ *
+ * Initialize @link.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+static void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
+{
+ struct ata_device *dev;
+
+ /* clear everything except for devices */
+ memset(link, 0, offsetof(struct ata_link, device[0]));
+
+ link->ap = ap;
+ link->pmp = pmp;
+ link->active_tag = ATA_TAG_POISON;
+ link->hw_sata_spd_limit = UINT_MAX;
+
+ ata_link_for_each_dev(dev, link) {
+ dev->link = link;
+ dev->devno = dev - link->device;
+ ata_dev_init(dev);
+ }
+}
+
+/**
+ * ata_link_init_sata_spd_limit - Initialize link->sata_spd_limit
+ * @link: Link to configure sata_spd_limit for
+ *
+ * Initialize @link->[orig_]sata_spd_limit to the currently
+ * configured value.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int ata_link_init_sata_spd_limit(struct ata_link *link)
+{
+
+ u32 scontrol, spd;
+ int rc;
+
+ rc = ata_scr_read(link, SCR_CONTROL, &scontrol);
+ if (rc)
+ return rc;
+
+ spd = (scontrol >> 4) & 0xf;
+ if (spd)
+ link->hw_sata_spd_limit &= (1 << spd) - 1;
+
+ link->sata_spd_limit = link->hw_sata_spd_limit;
+
+ return 0;
+}
+
+/**
* ata_host_init - Initialize an ata_port structure
* @ap: Structure to initialize
* @host: associated SCSI mid-layer structure
@@ -5111,8 +5174,6 @@ static void ata_host_init(struct ata_por
struct ata_host_set *host_set,
const struct ata_probe_ent *ent, unsigned int port_no)
{
- unsigned int i;
-
host->max_id = 16;
host->max_lun = 1;
host->max_channel = 1;
@@ -5133,8 +5194,6 @@ static void ata_host_init(struct ata_por
ap->udma_mask = ent->udma_mask;
ap->flags |= ent->host_flags;
ap->ops = ent->port_ops;
- ap->link.hw_sata_spd_limit = UINT_MAX;
- ap->link.active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
INIT_WORK(&ap->port_task, NULL, NULL);
@@ -5146,14 +5205,7 @@ static void ata_host_init(struct ata_por
if (ap->flags & ATA_FLAG_SATA)
ap->cbl = ATA_CBL_SATA;
- ap->link.ap = ap;
-
- for (i = 0; i < ata_link_max_devices(&ap->link); i++) {
- struct ata_device *dev = &ap->link.device[i];
- dev->link = &ap->link;
- dev->devno = i;
- ata_dev_init(dev);
- }
+ ata_link_init(ap, &ap->link, 0);
#ifdef ATA_IRQ_TRAP
ap->stats.unhandled_irq = 1;
@@ -5304,17 +5356,12 @@ int ata_device_add(const struct ata_prob
DPRINTK("probe begin\n");
for (i = 0; i < count; i++) {
struct ata_port *ap;
- u32 scontrol;
int rc;
ap = host_set->ports[i];
/* init sata_spd_limit to the current value */
- if (ata_scr_read(&ap->link, SCR_CONTROL, &scontrol) == 0) {
- int spd = (scontrol >> 4) & 0xf;
- ap->link.hw_sata_spd_limit &= (1 << spd) - 1;
- }
- ap->link.sata_spd_limit = ap->link.hw_sata_spd_limit;
+ ata_link_init_sata_spd_limit(&ap->link);
rc = scsi_add_host(ap->host, dev);
if (rc) {
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 10/14] libata-link: add PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (3 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 07/14] libata-link: separate out link initialization functions Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 06/14] libata-link: linkify config/EH related functions Tejun Heo
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Add link->pmp, ap->nr_pm_links, ap->pm_link[], and implement/update
printk helpers and iterators.
printk helpers are updated such that each component is identified as
follows.
if PM is not attached,
port 'ataP:'
link 'ataP:'
dev 'ataP.DD:'
If PM is attached
port 'ataP:'
dev 'ataP.LL:'
link 'ataP.LL'
ie. link and device are identified their PMP number.
If PM is attached (ap->nr_pm_links != 0), ata_for_each_link() iterates
over PM links, while __ata_for_each_link() iterates over the host link
+ PM links. If PM is not attached (ap->nr_pm_links == 0), both
iterate over the host link only.
---
include/linux/libata.h | 52 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 46 insertions(+), 6 deletions(-)
1b7ba4a43a2a50e0732a8fbcfe99fc64ba2cdffe
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f31c979..7db9b80 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -471,6 +471,7 @@ struct ata_eh_context {
struct ata_link {
struct ata_port *ap;
+ int pmp; /* port multiplier port # */
unsigned int active_tag; /* active tag on this link */
u32 sactive; /* active NCQ commands */
@@ -519,6 +520,9 @@ struct ata_port {
struct ata_link link; /* host default link */
struct ata_device __dev1; /* storage for link.device[1] */
+ int nr_pm_links; /* nr of available PM links */
+ struct ata_link *pm_link; /* array of PM links */
+
struct ata_host_stats stats;
struct ata_host_set *host_set;
struct device *dev;
@@ -796,11 +800,16 @@ extern void ata_do_eh(struct ata_port *a
#define ata_port_printk(ap, lv, fmt, args...) \
printk(lv"ata%u: "fmt, (ap)->id , ##args)
-#define ata_link_printk(link, lv, fmt, args...) \
- printk(lv"ata%u: "fmt, (link)->ap->id , ##args)
+#define ata_link_printk(link, lv, fmt, args...) do { \
+ if ((link)->ap->nr_pm_links) \
+ printk(lv"ata%u.%02u: "fmt, (link)->ap->id, (link)->pmp , ##args); \
+ else \
+ printk(lv"ata%u: "fmt, (link)->ap->id , ##args); \
+ } while(0)
#define ata_dev_printk(dev, lv, fmt, args...) \
- printk(lv"ata%u.%02u: "fmt, (dev)->link->ap->id, (dev)->devno , ##args)
+ printk(lv"ata%u.%02u: "fmt, (dev)->link->ap->id, \
+ (dev)->link->pmp + (dev)->devno , ##args)
/*
* ata_eh_info helpers
@@ -902,15 +911,46 @@ static inline unsigned int ata_dev_absen
/*
* link helpers
*/
+static inline int ata_is_host_link(const struct ata_link *link)
+{
+ return link == &link->ap->link;
+}
+
static inline int ata_link_max_devices(const struct ata_link *link)
{
- if (link->ap->flags & ATA_FLAG_SLAVE_POSS)
+ if (ata_is_host_link(link) && link->ap->flags & ATA_FLAG_SLAVE_POSS)
return 2;
return 1;
}
-#define ata_port_for_each_link(lk, ap) \
- for ((lk) = &(ap)->link; (lk); (lk) = NULL)
+static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
+{
+ if (ap->nr_pm_links)
+ return ap->pm_link;
+ return &ap->link;
+}
+
+static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+{
+ struct ata_port *ap = link->ap;
+
+ if (link == &ap->link) {
+ if (!ap->nr_pm_links)
+ return NULL;
+ return ap->pm_link;
+ }
+
+ if (++link - ap->pm_link < ap->nr_pm_links)
+ return link;
+ return NULL;
+}
+
+#define __ata_port_for_each_link(lk, ap) \
+ for ((lk) = &(ap)->link; (lk); (lk) = ata_port_next_link(lk))
+
+#define ata_port_for_each_link(link, ap) \
+ for ((link) = ata_port_first_link(ap); (link); \
+ (link) = ata_port_next_link(link))
#define ata_link_for_each_dev(dev, link) \
for ((dev) = (link)->device; \
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 06/14] libata-link: linkify config/EH related functions
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (4 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 10/14] libata-link: add PM links Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 11/14] libata-link: update ata_scsi_error() to handle PM links Tejun Heo
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Make the following functions deal with ata_link instead of ata_port.
* ata_set_mode()
* ata_eh_analyze_ncq_error()
* ata_eh_analyze_serror()
* ata_eh_autopsy()
* ata_eh_report()
* ata_eh_attach_and_revalidate()
---
drivers/scsi/libata-core.c | 13 +++--
drivers/scsi/libata-eh.c | 113 +++++++++++++++++++++++---------------------
drivers/scsi/libata.h | 3 +
3 files changed, 68 insertions(+), 61 deletions(-)
222e799fb2ba9ac4c8e0437d5418d6a89fa515b9
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 6dc370f..dd40909 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1525,7 +1525,7 @@ static int ata_bus_probe(struct ata_port
}
/* configure transfer mode */
- rc = ata_set_mode(ap, &dev);
+ rc = ata_set_mode(&ap->link, &dev);
if (rc) {
down_xfermask = 1;
goto fail;
@@ -2062,7 +2062,7 @@ static int ata_dev_set_mode(struct ata_d
/**
* ata_set_mode - Program timings and issue SET FEATURES - XFER
- * @ap: port on which timings will be programmed
+ * @link: link on which timings will be programmed
* @r_failed_dev: out paramter for failed device
*
* Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
@@ -2075,9 +2075,9 @@ static int ata_dev_set_mode(struct ata_d
* RETURNS:
* 0 on success, negative errno otherwise
*/
-int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
+int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
{
- struct ata_link *link = &ap->link;
+ struct ata_port *ap = link->ap;
struct ata_device *dev;
int rc = 0, used_dma = 0, found = 0;
@@ -4938,12 +4938,13 @@ static int ata_start_drive(struct ata_de
*/
int ata_device_resume(struct ata_device *dev)
{
- struct ata_port *ap = dev->link->ap;
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
if (ap->flags & ATA_FLAG_SUSPENDED) {
struct ata_device *failed_dev;
ap->flags &= ~ATA_FLAG_SUSPENDED;
- while (ata_set_mode(ap, &failed_dev))
+ while (ata_set_mode(link, &failed_dev))
ata_dev_disable(failed_dev);
}
if (!ata_dev_enabled(dev))
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 7e5a03a..06e6523 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -880,7 +880,7 @@ static unsigned int atapi_eh_request_sen
/**
* ata_eh_analyze_serror - analyze SError for a failed port
- * @ap: ATA port to analyze SError for
+ * @link: ATA link to analyze SError for
*
* Analyze SError if available and further determine cause of
* failure.
@@ -888,9 +888,9 @@ static unsigned int atapi_eh_request_sen
* LOCKING:
* None.
*/
-static void ata_eh_analyze_serror(struct ata_port *ap)
+static void ata_eh_analyze_serror(struct ata_link *link)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_eh_context *ehc = &link->eh_context;
u32 serror = ehc->i.serror;
unsigned int err_mask = 0, action = 0;
@@ -923,7 +923,7 @@ static void ata_eh_analyze_serror(struct
/**
* ata_eh_analyze_ncq_error - analyze NCQ error
- * @ap: ATA port to analyze NCQ error for
+ * @link: ATA link to analyze NCQ error for
*
* Read log page 10h, determine the offending qc and acquire
* error status TF. For NCQ device errors, all LLDDs have to do
@@ -933,10 +933,11 @@ static void ata_eh_analyze_serror(struct
* LOCKING:
* Kernel thread context (may sleep).
*/
-static void ata_eh_analyze_ncq_error(struct ata_port *ap)
+static void ata_eh_analyze_ncq_error(struct ata_link *link)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
- struct ata_device *dev = ap->link.device;
+ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev = link->device;
struct ata_queued_cmd *qc;
struct ata_taskfile tf;
int tag, rc;
@@ -946,7 +947,7 @@ static void ata_eh_analyze_ncq_error(str
return;
/* is it NCQ device error? */
- if (!ap->link.sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+ if (!link->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
return;
/* has LLDD analyzed already? */
@@ -963,13 +964,13 @@ static void ata_eh_analyze_ncq_error(str
/* okay, this error is ours */
rc = ata_eh_read_log_10h(dev, &tag, &tf);
if (rc) {
- ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
+ ata_link_printk(link, KERN_ERR, "failed to read log page 10h "
"(errno=%d)\n", rc);
return;
}
- if (!(ap->link.sactive & (1 << tag))) {
- ata_port_printk(ap, KERN_ERR, "log page 10h reported "
+ if (!(link->sactive & (1 << tag))) {
+ ata_link_printk(link, KERN_ERR, "log page 10h reported "
"inactive tag %d\n", tag);
return;
}
@@ -1169,18 +1170,18 @@ static int ata_eh_speed_down(struct ata_
/**
* ata_eh_autopsy - analyze error and determine recovery action
- * @ap: ATA port to perform autopsy on
+ * @link: ATA link to perform autopsy on
*
- * Analyze why @ap failed and determine which recovery action is
- * needed. This function also sets more detailed AC_ERR_* values
- * and fills sense data for ATAPI CHECK SENSE.
+ * Analyze why @link failed and determine which recovery actions
+ * are needed. This function also sets more detailed AC_ERR_*
+ * values and fills sense data for ATAPI CHECK SENSE.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
-static void ata_eh_autopsy(struct ata_port *ap)
+static void ata_eh_autopsy(struct ata_link *link)
{
- struct ata_link *link = &ap->link;
+ struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
unsigned int action = ehc->i.action;
struct ata_device *failed_dev = NULL;
@@ -1195,12 +1196,12 @@ static void ata_eh_autopsy(struct ata_po
rc = ata_scr_read(link, SCR_ERROR, &serror);
if (rc == 0) {
ehc->i.serror |= serror;
- ata_eh_analyze_serror(ap);
+ ata_eh_analyze_serror(link);
} else if (rc != -EOPNOTSUPP)
action |= ATA_EH_HARDRESET;
/* analyze NCQ failure */
- ata_eh_analyze_ncq_error(ap);
+ ata_eh_analyze_ncq_error(link);
/* any real error trumps AC_ERR_OTHER */
if (ehc->i.err_mask & ~AC_ERR_OTHER)
@@ -1211,7 +1212,7 @@ static void ata_eh_autopsy(struct ata_po
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED))
+ if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
continue;
/* inherit upper level err_mask */
@@ -1260,16 +1261,17 @@ static void ata_eh_autopsy(struct ata_po
/**
* ata_eh_report - report error handling to user
- * @ap: ATA port EH is going on
+ * @link: ATA link EH is going on
*
* Report EH to user.
*
* LOCKING:
* None.
*/
-static void ata_eh_report(struct ata_port *ap)
+static void ata_eh_report(struct ata_link *link)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
const char *frozen, *desc;
int tag, nr_failed = 0;
@@ -1280,7 +1282,7 @@ static void ata_eh_report(struct ata_por
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED))
+ if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
continue;
if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
continue;
@@ -1298,23 +1300,24 @@ static void ata_eh_report(struct ata_por
if (ehc->i.dev) {
ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s\n",
- ehc->i.err_mask, ap->link.sactive,
+ ehc->i.err_mask, link->sactive,
ehc->i.serror, ehc->i.action, frozen);
if (desc)
ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
} else {
- ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
+ ata_link_printk(link, KERN_ERR, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s\n",
- ehc->i.err_mask, ap->link.sactive,
+ ehc->i.err_mask, link->sactive,
ehc->i.serror, ehc->i.action, frozen);
if (desc)
- ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
+ ata_link_printk(link, KERN_ERR, "(%s)\n", desc);
}
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
+ if (!(qc->flags & ATA_QCFLAG_FAILED) ||
+ qc->dev->link != link || !qc->err_mask)
continue;
ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
@@ -1485,17 +1488,18 @@ static int ata_eh_reset(struct ata_link
return rc;
}
-static int ata_eh_revalidate_and_attach(struct ata_port *ap,
+static int ata_eh_revalidate_and_attach(struct ata_link *link,
struct ata_device **r_failed_dev)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
unsigned long flags;
int rc = 0;
DPRINTK("ENTER\n");
- ata_link_for_each_dev(dev, &ap->link) {
+ ata_link_for_each_dev(dev, link) {
if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) &&
(!ehc->i.dev || ehc->i.dev == dev)) {
if (ata_link_offline(dev->link)) {
@@ -1503,7 +1507,7 @@ static int ata_eh_revalidate_and_attach(
break;
}
- ata_eh_about_to_do(&ap->link, ATA_EH_REVALIDATE);
+ ata_eh_about_to_do(link, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev,
ehc->flags & ATA_EHC_DID_RESET);
if (rc)
@@ -1537,38 +1541,38 @@ static int ata_eh_revalidate_and_attach(
return rc;
}
-static int ata_port_nr_enabled(struct ata_port *ap)
+static int ata_link_nr_enabled(struct ata_link *link)
{
struct ata_device *dev;
int cnt = 0;
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
if (ata_dev_enabled(dev))
cnt++;
return cnt;
}
-static int ata_port_nr_vacant(struct ata_port *ap)
+static int ata_link_nr_vacant(struct ata_link *link)
{
struct ata_device *dev;
int cnt = 0;
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
if (dev->class == ATA_DEV_UNKNOWN)
cnt++;
return cnt;
}
-static int ata_eh_skip_recovery(struct ata_port *ap)
+static int ata_eh_skip_recovery(struct ata_link *link)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
- if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
+ if (link->ap->flags & ATA_FLAG_FROZEN || ata_link_nr_enabled(link))
return 0;
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
- ata_link_for_each_dev(dev, &ap->link) {
+ ata_link_for_each_dev(dev, link) {
if (dev->class == ATA_DEV_UNKNOWN &&
ehc->classes[dev->devno] != ATA_DEV_NONE)
return 0;
@@ -1602,14 +1606,15 @@ static int ata_eh_recover(struct ata_por
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_link *link = &ap->link;
+ struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
int down_xfermask, rc;
DPRINTK("ENTER\n");
/* prep for recovery */
- ata_link_for_each_dev(dev, &ap->link) {
+ ata_link_for_each_dev(dev, link) {
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
/* process hotplug request */
@@ -1631,17 +1636,17 @@ static int ata_eh_recover(struct ata_por
rc = 0;
/* skip EH if possible. */
- if (ata_eh_skip_recovery(ap))
+ if (ata_eh_skip_recovery(link))
ehc->i.action = 0;
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
/* reset */
if (ehc->i.action & ATA_EH_RESET_MASK) {
ata_eh_freeze_port(ap);
- rc = ata_eh_reset(&ap->link, ata_port_nr_vacant(ap), prereset,
+ rc = ata_eh_reset(link, ata_link_nr_vacant(ap), prereset,
softreset, hardreset, postreset);
if (rc) {
ata_port_printk(ap, KERN_ERR,
@@ -1653,13 +1658,13 @@ static int ata_eh_recover(struct ata_por
}
/* revalidate existing devices and attach new ones */
- rc = ata_eh_revalidate_and_attach(ap, &dev);
+ rc = ata_eh_revalidate_and_attach(link, &dev);
if (rc)
goto dev_fail;
/* configure transfer mode if the port has been reset */
if (ehc->flags & ATA_EHC_DID_RESET) {
- rc = ata_set_mode(ap, &dev);
+ rc = ata_set_mode(link, &dev);
if (rc) {
down_xfermask = 1;
goto dev_fail;
@@ -1677,7 +1682,7 @@ static int ata_eh_recover(struct ata_por
ehc->tries[dev->devno] = 0;
break;
case -EIO:
- ata_down_sata_spd_limit(&ap->link);
+ ata_down_sata_spd_limit(link);
default:
ehc->tries[dev->devno]--;
if (down_xfermask &&
@@ -1690,7 +1695,7 @@ static int ata_eh_recover(struct ata_por
ata_dev_disable(dev);
/* detach if offline */
- if (ata_link_offline(&ap->link))
+ if (ata_link_offline(link))
ata_eh_detach_dev(dev);
/* probe if requested */
@@ -1711,7 +1716,7 @@ static int ata_eh_recover(struct ata_por
ehc->i.action |= ATA_EH_SOFTRESET;
}
- if (ata_port_nr_enabled(ap)) {
+ if (ata_link_nr_enabled(ap)) {
ata_port_printk(ap, KERN_WARNING, "failed to recover some "
"devices, retrying in 5 secs\n");
ssleep(5);
@@ -1724,7 +1729,7 @@ static int ata_eh_recover(struct ata_por
out:
if (rc) {
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
ata_dev_disable(dev);
}
@@ -1856,8 +1861,8 @@ void ata_do_eh(struct ata_port *ap, ata_
ata_postreset_fn_t postreset)
{
if (!(ap->flags & (ATA_FLAG_LOADING | ATA_FLAG_UNLOADING))) {
- ata_eh_autopsy(ap);
- ata_eh_report(ap);
+ ata_eh_autopsy(&ap->link);
+ ata_eh_report(&ap->link);
}
ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index bd2e399..f09c23e 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -56,7 +56,8 @@ extern int ata_dev_configure(struct ata_
extern int ata_down_sata_spd_limit(struct ata_link *link);
extern int ata_set_sata_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
-extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
+extern int ata_set_mode(struct ata_link *link,
+ struct ata_device **r_failed_dev);
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);
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 11/14] libata-link: update ata_scsi_error() to handle PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (5 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 06/14] libata-link: linkify config/EH related functions Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 04/14] libata-link: linkify PHY-related functions Tejun Heo
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Update ata_scsi_error() to handle PM links. As error conditions can
occur on both host and PM links, __ata_port_for_each_link() is used.
---
drivers/scsi/libata-eh.c | 15 ++++++++++-----
1 files changed, 10 insertions(+), 5 deletions(-)
48be52e2b9a5f5ec81af8e3da1e784a63f1cde47
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 1bd7d1e..8e89379 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -235,13 +235,17 @@ void ata_scsi_error(struct Scsi_Host *ho
repeat:
/* invoke error handler */
if (ap->ops->error_handler) {
+ struct ata_link *link;
+
/* fetch & clear EH info */
spin_lock_irqsave(hs_lock, flags);
- memset(&ap->link.eh_context, 0, sizeof(ap->link.eh_context));
- if (!(ap->flags & ATA_FLAG_UNLOADING))
- ap->link.eh_context.i = ap->link.eh_info;
- memset(&ap->link.eh_info, 0, sizeof(ap->link.eh_info));
+ __ata_port_for_each_link(link, ap) {
+ memset(&link->eh_context, 0, sizeof(link->eh_context));
+ if (!(ap->flags & ATA_FLAG_UNLOADING))
+ link->eh_context.i = link->eh_info;
+ memset(&link->eh_info, 0, sizeof(link->eh_info));
+ }
ap->flags &= ~ATA_FLAG_EH_PENDING;
@@ -269,7 +273,8 @@ void ata_scsi_error(struct Scsi_Host *ho
}
/* this run is complete, make sure EH info is clear */
- memset(&ap->link.eh_info, 0, sizeof(ap->link.eh_info));
+ __ata_port_for_each_link(link, ap)
+ memset(&link->eh_info, 0, sizeof(link->eh_info));
/* Clear host_eh_scheduled while holding hs_lock such
* that if exception occurs after this point but
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 04/14] libata-link: linkify PHY-related functions
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (6 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 11/14] libata-link: update ata_scsi_error() to handle PM links Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 08/14] libata-link: implement link->reset_tries Tejun Heo
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Make the following PHY-related functions to deal with ata_link instead
of ata_port.
* sata_print_link_status()
* ata_down_sata_spd_limit()
* ata_set_sata_spd_limit() and friends
* sata_link_debounce/resume()
* ata_scr_valid/read/write/write_flush()
* ata_link_on/offline()
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 6 +
drivers/scsi/libata-bmdma.c | 2
drivers/scsi/libata-core.c | 217 +++++++++++++++++++++++--------------------
drivers/scsi/libata-eh.c | 22 ++--
drivers/scsi/libata.h | 4 -
drivers/scsi/sata_mv.c | 14 +--
drivers/scsi/sata_sil24.c | 12 +-
include/linux/libata.h | 23 ++---
8 files changed, 157 insertions(+), 143 deletions(-)
e99ffedfb16c0fae395568f367561a930118e4d1
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index e3b4fd5..d4420ac 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -587,7 +587,7 @@ static int ahci_softreset(struct ata_por
DPRINTK("ENTER\n");
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(&ap->link)) {
DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE;
return 0;
@@ -661,7 +661,7 @@ static int ahci_softreset(struct ata_por
msleep(150);
*class = ATA_DEV_NONE;
- if (ata_port_online(ap)) {
+ if (ata_link_online(&ap->link)) {
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
rc = -EIO;
reason = "device not ready";
@@ -690,7 +690,7 @@ static int ahci_hardreset(struct ata_por
rc = sata_std_hardreset(ap, class);
ahci_start_engine(ap);
- if (rc == 0 && ata_port_online(ap))
+ if (rc == 0 && ata_link_online(&ap->link))
*class = ahci_dev_classify(ap);
if (*class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE;
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index b3a4642..7805f79 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -778,7 +778,7 @@ void ata_bmdma_error_handler(struct ata_
ata_reset_fn_t hardreset;
hardreset = NULL;
- if (ata_scr_valid(ap))
+ if (ata_scr_valid(&ap->link))
hardreset = sata_std_hardreset;
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 501a752..9680359 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1548,7 +1548,7 @@ static int ata_bus_probe(struct ata_port
tries[dev->devno] = 0;
break;
case -EIO:
- ata_down_sata_spd_limit(ap);
+ ata_down_sata_spd_limit(&ap->link);
/* fall through */
default:
tries[dev->devno]--;
@@ -1583,28 +1583,28 @@ void ata_port_probe(struct ata_port *ap)
/**
* sata_print_link_status - Print SATA link status
- * @ap: SATA port to printk link status about
+ * @link: SATA link to printk link status about
*
* This function prints link speed and status of a SATA link.
*
* LOCKING:
* None.
*/
-static void sata_print_link_status(struct ata_port *ap)
+static void sata_print_link_status(struct ata_link *link)
{
u32 sstatus, scontrol, tmp;
- if (ata_scr_read(ap, SCR_STATUS, &sstatus))
+ if (ata_scr_read(link, SCR_STATUS, &sstatus))
return;
- ata_scr_read(ap, SCR_CONTROL, &scontrol);
+ ata_scr_read(link, SCR_CONTROL, &scontrol);
- if (ata_port_online(ap)) {
+ if (ata_link_online(link)) {
tmp = (sstatus >> 4) & 0xf;
- ata_port_printk(ap, KERN_INFO,
+ ata_link_printk(link, KERN_INFO,
"SATA link up %s (SStatus %X SControl %X)\n",
sata_spd_string(tmp), sstatus, scontrol);
} else {
- ata_port_printk(ap, KERN_INFO,
+ ata_link_printk(link, KERN_INFO,
"SATA link down (SStatus %X SControl %X)\n",
sstatus, scontrol);
}
@@ -1624,32 +1624,33 @@ static void sata_print_link_status(struc
*/
void __sata_phy_reset(struct ata_port *ap)
{
- u32 sstatus;
+ struct ata_link *link = &ap->link;
unsigned long timeout = jiffies + (HZ * 5);
+ u32 sstatus;
if (ap->flags & ATA_FLAG_SATA_RESET) {
/* issue phy wake/reset */
- ata_scr_write_flush(ap, SCR_CONTROL, 0x301);
+ ata_scr_write_flush(link, SCR_CONTROL, 0x301);
/* Couldn't find anything in SATA I/II specs, but
* AHCI-1.1 10.4.2 says at least 1 ms. */
mdelay(1);
}
/* phy wake/clear reset */
- ata_scr_write_flush(ap, SCR_CONTROL, 0x300);
+ ata_scr_write_flush(link, SCR_CONTROL, 0x300);
/* wait for phy to become ready, if necessary */
do {
msleep(200);
- ata_scr_read(ap, SCR_STATUS, &sstatus);
+ ata_scr_read(link, SCR_STATUS, &sstatus);
if ((sstatus & 0xf) != 1)
break;
} while (time_before(jiffies, timeout));
/* print link status */
- sata_print_link_status(ap);
+ sata_print_link_status(link);
/* TODO: phy layer with polling, timeouts, etc. */
- if (!ata_port_offline(ap))
+ if (!ata_link_offline(link))
ata_port_probe(ap);
else
ata_port_disable(ap);
@@ -1723,9 +1724,9 @@ void ata_port_disable(struct ata_port *a
/**
* ata_down_sata_spd_limit - adjust SATA spd limit downward
- * @ap: Port to adjust SATA spd limit for
+ * @link: Link to adjust SATA spd limit for
*
- * Adjust SATA spd limit of @ap downward. Note that this
+ * Adjust SATA spd limit of @link downward. Note that this
* function only adjusts the limit. The change must be applied
* using ata_set_sata_spd().
*
@@ -1735,16 +1736,16 @@ void ata_port_disable(struct ata_port *a
* RETURNS:
* 0 on success, negative errno on failure
*/
-int ata_down_sata_spd_limit(struct ata_port *ap)
+int ata_down_sata_spd_limit(struct ata_link *link)
{
u32 sstatus, spd, mask;
int rc, highbit;
- rc = ata_scr_read(ap, SCR_STATUS, &sstatus);
+ rc = ata_scr_read(link, SCR_STATUS, &sstatus);
if (rc)
return rc;
- mask = ap->link.sata_spd_limit;
+ mask = link->sata_spd_limit;
if (mask <= 1)
return -EINVAL;
highbit = fls(mask) - 1;
@@ -1758,22 +1759,22 @@ int ata_down_sata_spd_limit(struct ata_p
if (!mask)
return -EINVAL;
- ap->link.sata_spd_limit = mask;
+ link->sata_spd_limit = mask;
- ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
+ ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
sata_spd_string(fls(mask)));
return 0;
}
-static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol)
+static int __ata_set_sata_spd_needed(struct ata_link *link, u32 *scontrol)
{
u32 spd, limit;
- if (ap->link.sata_spd_limit == UINT_MAX)
+ if (link->sata_spd_limit == UINT_MAX)
limit = 0;
else
- limit = fls(ap->link.sata_spd_limit);
+ limit = fls(link->sata_spd_limit);
spd = (*scontrol >> 4) & 0xf;
*scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
@@ -1783,10 +1784,10 @@ static int __ata_set_sata_spd_needed(str
/**
* ata_set_sata_spd_needed - is SATA spd configuration needed
- * @ap: Port in question
+ * @link: Link in question
*
* Test whether the spd limit in SControl matches
- * @ap->link.sata_spd_limit. This function is used to determine
+ * @link->sata_spd_limit. This function is used to determine
* whether hardreset is necessary to apply SATA spd
* configuration.
*
@@ -1796,21 +1797,21 @@ static int __ata_set_sata_spd_needed(str
* RETURNS:
* 1 if SATA spd configuration is needed, 0 otherwise.
*/
-int ata_set_sata_spd_needed(struct ata_port *ap)
+int ata_set_sata_spd_needed(struct ata_link *link)
{
u32 scontrol;
- if (ata_scr_read(ap, SCR_CONTROL, &scontrol))
+ if (ata_scr_read(link, SCR_CONTROL, &scontrol))
return 0;
- return __ata_set_sata_spd_needed(ap, &scontrol);
+ return __ata_set_sata_spd_needed(link, &scontrol);
}
/**
* ata_set_sata_spd - set SATA spd according to spd limit
- * @ap: Port to set SATA spd for
+ * @link: Link to set SATA spd for
*
- * Set SATA spd of @ap according to sata_spd_limit.
+ * Set SATA spd of @link according to sata_spd_limit.
*
* LOCKING:
* Inherited from caller.
@@ -1819,18 +1820,18 @@ int ata_set_sata_spd_needed(struct ata_p
* 0 if spd doesn't need to be changed, 1 if spd has been
* changed. Negative errno if SCR registers are inaccessible.
*/
-int ata_set_sata_spd(struct ata_port *ap)
+int ata_set_sata_spd(struct ata_link *link)
{
u32 scontrol;
int rc;
- if ((rc = ata_scr_read(ap, SCR_CONTROL, &scontrol)))
+ if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
return rc;
- if (!__ata_set_sata_spd_needed(ap, &scontrol))
+ if (!__ata_set_sata_spd_needed(link, &scontrol))
return 0;
- if ((rc = ata_scr_write(ap, SCR_CONTROL, scontrol)))
+ if ((rc = ata_scr_write(link, SCR_CONTROL, scontrol)))
return rc;
return 1;
}
@@ -2422,13 +2423,13 @@ err_out:
}
/**
- * sata_phy_debounce - debounce SATA phy status
- * @ap: ATA port to debounce SATA phy status for
+ * sata_link_debounce - debounce SATA phy status
+ * @link: ATA link to debounce SATA phy status for
* @interval_msec: polling interval in millisecs
* @duration_msec: debounce duration in millisecs
* @timeout_msec: timeout in millisecs
*
- * Make sure SStatus of @ap reaches stable state, determined by
+ * Make sure SStatus of @link reaches stable state, determined by
* holding the same value where DET is not 1 for @duration_msec
* polled every @interval_msec, before @timeout_msec. Timeout
* constraints the beginning of the stable state. Because, after
@@ -2442,8 +2443,8 @@ err_out:
* RETURNS:
* 0 on success, -errno on failure.
*/
-int sata_phy_debounce(struct ata_port *ap, unsigned long interval_msec,
- unsigned long duration_msec, unsigned long timeout_msec)
+int sata_link_debounce(struct ata_link *link, unsigned long interval_msec,
+ unsigned long duration_msec, unsigned long timeout_msec)
{
unsigned long duration = duration_msec * HZ / 1000;
unsigned long timeout = jiffies + timeout_msec * HZ / 1000;
@@ -2451,7 +2452,7 @@ int sata_phy_debounce(struct ata_port *a
u32 last, cur;
int rc;
- if ((rc = ata_scr_read(ap, SCR_STATUS, &cur)))
+ if ((rc = ata_scr_read(link, SCR_STATUS, &cur)))
return rc;
cur &= 0xf;
@@ -2460,7 +2461,7 @@ int sata_phy_debounce(struct ata_port *a
while (1) {
msleep(interval_msec);
- if ((rc = ata_scr_read(ap, SCR_STATUS, &cur)))
+ if ((rc = ata_scr_read(link, SCR_STATUS, &cur)))
return rc;
cur &= 0xf;
@@ -2484,10 +2485,10 @@ int sata_phy_debounce(struct ata_port *a
}
/**
- * sata_phy_resume - resume SATA phy
- * @ap: ATA port to resume SATA phy for
+ * sata_link_resume - resume SATA link
+ * @link: ATA link to resume SATA
*
- * Resume SATA phy of @ap and debounce it.
+ * Resume SATA phy of @link and debounce it.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -2495,27 +2496,27 @@ int sata_phy_debounce(struct ata_port *a
* RETURNS:
* 0 on success, -errno on failure.
*/
-int sata_phy_resume(struct ata_port *ap, int quick)
+int sata_link_resume(struct ata_link *link, int quick)
{
u32 scontrol;
int rc;
- if ((rc = ata_scr_read(ap, SCR_CONTROL, &scontrol)))
+ if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
return rc;
scontrol = (scontrol & 0x0f0) | 0x300;
- if ((rc = ata_scr_write(ap, SCR_CONTROL, scontrol)))
+ if ((rc = ata_scr_write(link, SCR_CONTROL, scontrol)))
return rc;
if (quick)
- return sata_phy_debounce(ap, ATA_DEBOUNCE_QUICK_INTERVAL,
- ATA_DEBOUNCE_QUICK_DURATION,
- ATA_DEBOUNCE_QUICK_TIMEOUT);
+ return sata_link_debounce(link, ATA_DEBOUNCE_QUICK_INTERVAL,
+ ATA_DEBOUNCE_QUICK_DURATION,
+ ATA_DEBOUNCE_QUICK_TIMEOUT);
else
- return sata_phy_debounce(ap, ATA_DEBOUNCE_INTERVAL,
- ATA_DEBOUNCE_DURATION,
- ATA_DEBOUNCE_TIMEOUT);
+ return sata_link_debounce(link, ATA_DEBOUNCE_INTERVAL,
+ ATA_DEBOUNCE_DURATION,
+ ATA_DEBOUNCE_TIMEOUT);
}
/**
@@ -2539,8 +2540,8 @@ int ata_std_prereset(struct ata_port *ap
if (ap->link.eh_context.i.action & ATA_EH_HARDRESET)
return 0;
- /* resume port */
- rc = sata_phy_resume(ap, boot_probe);
+ /* resume link */
+ rc = sata_link_resume(&ap->link, boot_probe);
if (rc && rc != -EOPNOTSUPP) {
/* phy resume failed, whine but continue */
ata_port_printk(ap, KERN_WARNING, "failed to resume link "
@@ -2553,7 +2554,7 @@ int ata_std_prereset(struct ata_port *ap
* cases. As we wait for !BSY after resets, this should be
* safe.
*/
- if (boot_probe && !ata_port_offline(ap))
+ if (boot_probe && !ata_link_offline(&ap->link))
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
return 0;
@@ -2580,7 +2581,7 @@ int ata_std_softreset(struct ata_port *a
DPRINTK("ENTER\n");
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(&ap->link)) {
classes[0] = ATA_DEV_NONE;
goto out;
}
@@ -2628,35 +2629,36 @@ int ata_std_softreset(struct ata_port *a
*/
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
{
+ struct ata_link *link = &ap->link;
u32 scontrol;
int rc;
DPRINTK("ENTER\n");
- if (ata_set_sata_spd_needed(ap)) {
+ if (ata_set_sata_spd_needed(link)) {
/* SATA spec says nothing about how to reconfigure
* spd. To be on the safe side, turn off phy during
* reconfiguration. This works for at least ICH7 AHCI
* and Sil3124.
*/
- if ((rc = ata_scr_read(ap, SCR_CONTROL, &scontrol)))
+ if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
return rc;
scontrol = (scontrol & 0x0f0) | 0x302;
- if ((rc = ata_scr_write(ap, SCR_CONTROL, scontrol)))
+ if ((rc = ata_scr_write(link, SCR_CONTROL, scontrol)))
return rc;
- ata_set_sata_spd(ap);
+ ata_set_sata_spd(link);
}
/* issue phy wake/reset */
- if ((rc = ata_scr_read(ap, SCR_CONTROL, &scontrol)))
+ if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
return rc;
scontrol = (scontrol & 0x0f0) | 0x301;
- if ((rc = ata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
+ if ((rc = ata_scr_write_flush(link, SCR_CONTROL, scontrol)))
return rc;
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
@@ -2665,17 +2667,17 @@ int sata_std_hardreset(struct ata_port *
msleep(1);
/* bring phy back */
- sata_phy_resume(ap, 0);
+ sata_link_resume(link, 0);
/* TODO: phy layer with polling, timeouts, etc. */
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(link)) {
*class = ATA_DEV_NONE;
DPRINTK("EXIT, link offline\n");
return 0;
}
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
- ata_port_printk(ap, KERN_ERR,
+ ata_link_printk(link, KERN_ERR,
"COMRESET failed (device not ready)\n");
return -EIO;
}
@@ -2702,16 +2704,17 @@ int sata_std_hardreset(struct ata_port *
*/
void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
{
+ struct ata_link *link = &ap->link;
u32 serror;
DPRINTK("ENTER\n");
/* print link status */
- sata_print_link_status(ap);
+ sata_print_link_status(link);
/* clear SError */
- if (ata_scr_read(ap, SCR_ERROR, &serror) == 0)
- ata_scr_write(ap, SCR_ERROR, serror);
+ if (ata_scr_read(link, SCR_ERROR, &serror) == 0)
+ ata_scr_write(link, SCR_ERROR, serror);
/* re-enable interrupts */
if (!ap->ops->error_handler) {
@@ -4730,9 +4733,9 @@ irqreturn_t ata_interrupt (int irq, void
/**
* ata_scr_valid - test whether SCRs are accessible
- * @ap: ATA port to test SCR accessibility for
+ * @link: ATA link to test SCR accessibility for
*
- * Test whether SCRs are accessible for @ap.
+ * Test whether SCRs are accessible for @link.
*
* LOCKING:
* None.
@@ -4740,18 +4743,20 @@ irqreturn_t ata_interrupt (int irq, void
* RETURNS:
* 1 if SCRs are accessible, 0 otherwise.
*/
-int ata_scr_valid(struct ata_port *ap)
+int ata_scr_valid(struct ata_link *link)
{
+ struct ata_port *ap = link->ap;
+
return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
}
/**
* ata_scr_read - read SCR register of the specified port
- * @ap: ATA port to read SCR for
+ * @link: ATA link to read SCR for
* @reg: SCR to read
* @val: Place to store read value
*
- * Read SCR register @reg of @ap into *@val. This function is
+ * Read SCR register @reg of @link into *@val. This function is
* guaranteed to succeed if the cable type of the port is SATA
* and the port implements ->scr_read.
*
@@ -4761,9 +4766,11 @@ int ata_scr_valid(struct ata_port *ap)
* RETURNS:
* 0 on success, negative errno on failure.
*/
-int ata_scr_read(struct ata_port *ap, int reg, u32 *val)
+int ata_scr_read(struct ata_link *link, int reg, u32 *val)
{
- if (ata_scr_valid(ap)) {
+ struct ata_port *ap = link->ap;
+
+ if (ata_scr_valid(link)) {
*val = ap->ops->scr_read(ap, reg);
return 0;
}
@@ -4772,11 +4779,11 @@ int ata_scr_read(struct ata_port *ap, in
/**
* ata_scr_write - write SCR register of the specified port
- * @ap: ATA port to write SCR for
+ * @link: ATA link to write SCR for
* @reg: SCR to write
* @val: value to write
*
- * Write @val to SCR register @reg of @ap. This function is
+ * Write @val to SCR register @reg of @link. This function is
* guaranteed to succeed if the cable type of the port is SATA
* and the port implements ->scr_read.
*
@@ -4786,9 +4793,11 @@ int ata_scr_read(struct ata_port *ap, in
* RETURNS:
* 0 on success, negative errno on failure.
*/
-int ata_scr_write(struct ata_port *ap, int reg, u32 val)
+int ata_scr_write(struct ata_link *link, int reg, u32 val)
{
- if (ata_scr_valid(ap)) {
+ struct ata_port *ap = link->ap;
+
+ if (ata_scr_valid(link)) {
ap->ops->scr_write(ap, reg, val);
return 0;
}
@@ -4797,7 +4806,7 @@ int ata_scr_write(struct ata_port *ap, i
/**
* ata_scr_write_flush - write SCR register of the specified port and flush
- * @ap: ATA port to write SCR for
+ * @link: ATA link to write SCR for
* @reg: SCR to write
* @val: value to write
*
@@ -4810,9 +4819,11 @@ int ata_scr_write(struct ata_port *ap, i
* RETURNS:
* 0 on success, negative errno on failure.
*/
-int ata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
+int ata_scr_write_flush(struct ata_link *link, int reg, u32 val)
{
- if (ata_scr_valid(ap)) {
+ struct ata_port *ap = link->ap;
+
+ if (ata_scr_valid(link)) {
ap->ops->scr_write(ap, reg, val);
ap->ops->scr_read(ap, reg);
return 0;
@@ -4821,12 +4832,12 @@ int ata_scr_write_flush(struct ata_port
}
/**
- * ata_port_online - test whether the given port is online
- * @ap: ATA port to test
+ * ata_link_online - test whether the given link is online
+ * @link: ATA link to test
*
- * Test whether @ap is online. Note that this function returns 0
- * if online status of @ap cannot be obtained, so
- * ata_port_online(ap) != !ata_port_offline(ap).
+ * Test whether @link is online. Note that this function returns
+ * 0 if online status of @link cannot be obtained, so
+ * ata_link_online(link) != !ata_link_offline(link).
*
* LOCKING:
* None.
@@ -4834,22 +4845,22 @@ int ata_scr_write_flush(struct ata_port
* RETURNS:
* 1 if the port online status is available and online.
*/
-int ata_port_online(struct ata_port *ap)
+int ata_link_online(struct ata_link *link)
{
u32 sstatus;
- if (!ata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
+ if (!ata_scr_read(link, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
return 1;
return 0;
}
/**
- * ata_port_offline - test whether the given port is offline
- * @ap: ATA port to test
+ * ata_link_offline - test whether the given link is offline
+ * @link: ATA link to test
*
- * Test whether @ap is offline. Note that this function returns
- * 0 if offline status of @ap cannot be obtained, so
- * ata_port_online(ap) != !ata_port_offline(ap).
+ * Test whether @link is offline. Note that this function returns
+ * 0 if offline status of @link cannot be obtained, so
+ * ata_link_online(link) != !ata_link_offline(link).
*
* LOCKING:
* None.
@@ -4857,11 +4868,11 @@ int ata_port_online(struct ata_port *ap)
* RETURNS:
* 1 if the port offline status is available and offline.
*/
-int ata_port_offline(struct ata_port *ap)
+int ata_link_offline(struct ata_link *link)
{
u32 sstatus;
- if (!ata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
+ if (!ata_scr_read(link, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
return 1;
return 0;
}
@@ -5296,7 +5307,7 @@ int ata_device_add(const struct ata_prob
ap = host_set->ports[i];
/* init sata_spd_limit to the current value */
- if (ata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
+ if (ata_scr_read(&ap->link, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
ap->link.hw_sata_spd_limit &= (1 << spd) - 1;
}
@@ -5748,8 +5759,8 @@ EXPORT_SYMBOL_GPL(ata_set_sata_spd);
EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset);
EXPORT_SYMBOL_GPL(ata_bus_reset);
-EXPORT_SYMBOL_GPL(sata_phy_debounce);
-EXPORT_SYMBOL_GPL(sata_phy_resume);
+EXPORT_SYMBOL_GPL(sata_link_debounce);
+EXPORT_SYMBOL_GPL(sata_link_resume);
EXPORT_SYMBOL_GPL(ata_std_prereset);
EXPORT_SYMBOL_GPL(ata_std_softreset);
EXPORT_SYMBOL_GPL(sata_std_hardreset);
@@ -5773,8 +5784,8 @@ EXPORT_SYMBOL_GPL(ata_scr_valid);
EXPORT_SYMBOL_GPL(ata_scr_read);
EXPORT_SYMBOL_GPL(ata_scr_write);
EXPORT_SYMBOL_GPL(ata_scr_write_flush);
-EXPORT_SYMBOL_GPL(ata_port_online);
-EXPORT_SYMBOL_GPL(ata_port_offline);
+EXPORT_SYMBOL_GPL(ata_link_online);
+EXPORT_SYMBOL_GPL(ata_link_offline);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 4026886..7ade712 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1154,7 +1154,7 @@ static int ata_eh_speed_down(struct ata_
return 0;
/* speed down SATA link speed if possible */
- if (ata_down_sata_spd_limit(dev->link->ap) == 0)
+ if (ata_down_sata_spd_limit(dev->link) == 0)
return ATA_EH_HARDRESET;
/* lower transfer mode */
@@ -1179,7 +1179,8 @@ static int ata_eh_speed_down(struct ata_
*/
static void ata_eh_autopsy(struct ata_port *ap)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_link *link = &ap->link;
+ struct ata_eh_context *ehc = &link->eh_context;
unsigned int action = ehc->i.action;
struct ata_device *failed_dev = NULL;
unsigned int all_err_mask = 0;
@@ -1190,7 +1191,7 @@ static void ata_eh_autopsy(struct ata_po
DPRINTK("ENTER\n");
/* obtain and analyze SError */
- rc = ata_scr_read(ap, SCR_ERROR, &serror);
+ rc = ata_scr_read(link, SCR_ERROR, &serror);
if (rc == 0) {
ehc->i.serror |= serror;
ata_eh_analyze_serror(ap);
@@ -1368,7 +1369,8 @@ static int ata_eh_reset(struct ata_port
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
- struct ata_eh_context *ehc = &ap->link.eh_context;
+ struct ata_link *link = &ap->link;
+ struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
int verbose = !(ap->flags & ATA_FLAG_LOADING);
@@ -1382,7 +1384,7 @@ static int ata_eh_reset(struct ata_port
*/
action = ehc->i.action;
ehc->i.action &= ~ATA_EH_RESET_MASK;
- if (softreset && (!hardreset || (!ata_set_sata_spd_needed(ap) &&
+ if (softreset && (!hardreset || (!ata_set_sata_spd_needed(link) &&
!(action & ATA_EH_HARDRESET)))) {
ehc->i.action |= ATA_EH_SOFTRESET;
reset = softreset;
@@ -1399,7 +1401,7 @@ static int ata_eh_reset(struct ata_port
*/
if (rc == -ENODEV) {
struct ata_device *dev;
- ata_link_for_each_dev(dev, &ap->link)
+ ata_link_for_each_dev(dev, link)
classes[dev->devno] = ATA_DEV_NONE;
return 0;
}
@@ -1464,7 +1466,7 @@ static int ata_eh_reset(struct ata_port
ssleep(5);
if (reset == hardreset)
- ata_down_sata_spd_limit(ap);
+ ata_down_sata_spd_limit(link);
if (hardreset)
reset = hardreset;
goto retry;
@@ -1496,7 +1498,7 @@ static int ata_eh_revalidate_and_attach(
ata_link_for_each_dev(dev, &ap->link) {
if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) &&
(!ehc->i.dev || ehc->i.dev == dev)) {
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(dev->link)) {
rc = -EIO;
break;
}
@@ -1675,7 +1677,7 @@ static int ata_eh_recover(struct ata_por
ehc->tries[dev->devno] = 0;
break;
case -EIO:
- ata_down_sata_spd_limit(ap);
+ ata_down_sata_spd_limit(&ap->link);
default:
ehc->tries[dev->devno]--;
if (down_xfermask &&
@@ -1688,7 +1690,7 @@ static int ata_eh_recover(struct ata_por
ata_dev_disable(dev);
/* detach if offline */
- if (ata_port_offline(ap))
+ if (ata_link_offline(&ap->link))
ata_eh_detach_dev(dev);
/* probe if requested */
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index aee6552..bd2e399 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -53,8 +53,8 @@ extern unsigned ata_exec_internal(struct
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int post_reset, u16 *id);
extern int ata_dev_configure(struct ata_device *dev, int print_info);
-extern int ata_down_sata_spd_limit(struct ata_port *ap);
-extern int ata_set_sata_spd_needed(struct ata_port *ap);
+extern int ata_down_sata_spd_limit(struct ata_link *link);
+extern int ata_set_sata_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
extern void ata_qc_free(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index af4b1f8..1979fee 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1310,8 +1310,8 @@ static void mv_err_intr(struct ata_port
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
if (EDMA_ERR_SERR & edma_err_cause) {
- ata_scr_read(ap, SCR_ERROR, &serr);
- ata_scr_write_flush(ap, SCR_ERROR, serr);
+ ata_scr_read(&ap->link, SCR_ERROR, &serr);
+ ata_scr_write_flush(&ap->link, SCR_ERROR, serr);
}
if (EDMA_ERR_SELF_DIS & edma_err_cause) {
struct mv_port_priv *pp = ap->private_data;
@@ -1935,15 +1935,15 @@ static void __mv_phy_reset(struct ata_po
/* Issue COMRESET via SControl */
comreset_retry:
- ata_scr_write_flush(ap, SCR_CONTROL, 0x301);
+ ata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
__msleep(1, can_sleep);
- ata_scr_write_flush(ap, SCR_CONTROL, 0x300);
+ ata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
__msleep(20, can_sleep);
timeout = jiffies + msecs_to_jiffies(200);
do {
- ata_scr_read(ap, SCR_STATUS, &sstatus);
+ ata_scr_read(&ap->link, SCR_STATUS, &sstatus);
sstatus &= 0x3;
if ((sstatus == 3) || (sstatus == 0))
break;
@@ -1961,10 +1961,10 @@ comreset_retry:
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
- if (ata_port_online(ap)) {
+ if (ata_link_online(&ap->link)) {
ata_port_probe(ap);
} else {
- ata_scr_read(ap, SCR_STATUS, &sstatus);
+ ata_scr_read(&ap->link, SCR_STATUS, &sstatus);
ata_port_printk(ap, KERN_INFO,
"no device found (phy stat %08x)\n", sstatus);
ata_port_disable(ap);
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 6e0b74b..51fceac 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -521,7 +521,7 @@ static int sil24_softreset(struct ata_po
DPRINTK("ENTER\n");
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(&ap->link)) {
DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE;
goto out;
@@ -578,10 +578,10 @@ static int sil24_hardreset(struct ata_po
u32 tmp;
/* sil24 does the right thing(tm) without any protection */
- ata_set_sata_spd(ap);
+ ata_set_sata_spd(&ap->link);
tout_msec = 100;
- if (ata_port_online(ap))
+ if (ata_link_online(&ap->link))
tout_msec = 5000;
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
@@ -591,15 +591,15 @@ static int sil24_hardreset(struct ata_po
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
*/
- rc = sata_phy_debounce(ap, ATA_DEBOUNCE_INTERVAL,
- ATA_DEBOUNCE_DURATION, ATA_DEBOUNCE_TIMEOUT);
+ rc = sata_link_debounce(&ap->link, ATA_DEBOUNCE_INTERVAL,
+ ATA_DEBOUNCE_DURATION, ATA_DEBOUNCE_TIMEOUT);
if (rc) {
reason = "PHY debouncing failed";
goto err;
}
if (tmp & PORT_CS_DEV_RST) {
- if (ata_port_offline(ap))
+ if (ata_link_offline(&ap->link))
return 0;
reason = "link not ready";
goto err;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index c7c904f..67a9054 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -616,11 +616,12 @@ extern void ata_port_probe(struct ata_po
extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap);
extern void ata_bus_reset(struct ata_port *ap);
-extern int ata_set_sata_spd(struct ata_port *ap);
-extern int sata_phy_debounce(struct ata_port *ap, unsigned long interval_msec,
- unsigned long duration_msec,
- unsigned long timeout_msec);
-extern int sata_phy_resume(struct ata_port *ap, int quick);
+extern int ata_set_sata_spd(struct ata_link *link);
+extern int sata_link_debounce(struct ata_link *link,
+ unsigned long interval_msec,
+ unsigned long duration_msec,
+ unsigned long timeout_msec);
+extern int sata_link_resume(struct ata_link *link, int quick);
extern int ata_std_prereset(struct ata_port *ap);
extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
@@ -644,12 +645,12 @@ extern int ata_scsi_ioctl(struct scsi_de
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_release(struct Scsi_Host *host);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
-extern int ata_scr_valid(struct ata_port *ap);
-extern int ata_scr_read(struct ata_port *ap, int reg, u32 *val);
-extern int ata_scr_write(struct ata_port *ap, int reg, u32 val);
-extern int ata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
-extern int ata_port_online(struct ata_port *ap);
-extern int ata_port_offline(struct ata_port *ap);
+extern int ata_scr_valid(struct ata_link *link);
+extern int ata_scr_read(struct ata_link *link, int reg, u32 *val);
+extern int ata_scr_write(struct ata_link *link, int reg, u32 val);
+extern int ata_scr_write_flush(struct ata_link *link, int reg, u32 val);
+extern int ata_link_online(struct ata_link *link);
+extern int ata_link_offline(struct ata_link *link);
extern int ata_scsi_device_resume(struct scsi_device *);
extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
extern int ata_device_resume(struct ata_device *);
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 08/14] libata-link: implement link->reset_tries
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (7 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 04/14] libata-link: linkify PHY-related functions Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 09/14] libata-link: implement ata_link_abort() Tejun Heo
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Make reset_tries per-link property. PM links will use different value
from host links.
---
drivers/scsi/libata-core.c | 1 +
drivers/scsi/libata-eh.c | 2 +-
include/linux/libata.h | 2 ++
3 files changed, 4 insertions(+), 1 deletions(-)
c7399562f682d7f2684a5f8fa95fc74583907031
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index de0f56f..11405a4 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5116,6 +5116,7 @@ static void ata_link_init(struct ata_por
link->pmp = pmp;
link->active_tag = ATA_TAG_POISON;
link->hw_sata_spd_limit = UINT_MAX;
+ link->reset_tries = ATA_EH_RESET_TRIES;
ata_link_for_each_dev(dev, link) {
dev->link = link;
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 06e6523..97a1b4d 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1375,7 +1375,7 @@ static int ata_eh_reset(struct ata_link
{
struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
- int tries = ATA_EH_RESET_TRIES;
+ int tries = link->reset_tries;
int verbose = !(link->ap->flags & ATA_FLAG_LOADING);
unsigned int action;
ata_reset_fn_t reset;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 61fddbf..8feaf04 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -479,6 +479,8 @@ struct ata_link {
unsigned int hw_sata_spd_limit;
unsigned int sata_spd_limit;
+ int reset_tries;
+
/* record runtime error info, protected by host_set lock */
struct ata_eh_info eh_info;
/* EH context */
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 09/14] libata-link: implement ata_link_abort()
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (8 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 08/14] libata-link: implement link->reset_tries Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 13/14] libata-link: update EH to deal with PM links Tejun Heo
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Implement ata_link_abort().
---
drivers/scsi/libata-core.c | 1 +
drivers/scsi/libata-eh.c | 50 ++++++++++++++++++++++++++++++++------------
include/linux/libata.h | 1 +
3 files changed, 38 insertions(+), 14 deletions(-)
77f07c1fd4a3c534664d3591e941489d20d51b85
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 11405a4..740e831 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5864,6 +5864,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_device_resume
EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
+EXPORT_SYMBOL_GPL(ata_link_abort);
EXPORT_SYMBOL_GPL(ata_port_abort);
EXPORT_SYMBOL_GPL(ata_port_freeze);
EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 97a1b4d..1bd7d1e 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -453,19 +453,7 @@ void ata_port_schedule_eh(struct ata_por
DPRINTK("port EH scheduled\n");
}
-/**
- * ata_port_abort - abort all qc's on the port
- * @ap: ATA port to abort qc's for
- *
- * Abort all active qc's of @ap and schedule EH.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- *
- * RETURNS:
- * Number of aborted qc's.
- */
-int ata_port_abort(struct ata_port *ap)
+static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
{
int tag, nr_aborted = 0;
@@ -474,7 +462,7 @@ int ata_port_abort(struct ata_port *ap)
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
- if (qc) {
+ if (qc && (!link || qc->dev->link == link)) {
qc->flags |= ATA_QCFLAG_FAILED;
ata_qc_complete(qc);
nr_aborted++;
@@ -488,6 +476,40 @@ int ata_port_abort(struct ata_port *ap)
}
/**
+ * ata_link_abort - abort all qc's on the link
+ * @link: ATA link to abort qc's for
+ *
+ * Abort all active qc's active on @link and schedule EH.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * Number of aborted qc's.
+ */
+int ata_link_abort(struct ata_link *link)
+{
+ return ata_do_link_abort(link->ap, link);
+}
+
+/**
+ * ata_port_abort - abort all qc's on the port
+ * @ap: ATA port to abort qc's for
+ *
+ * Abort all active qc's of @ap and schedule EH.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * Number of aborted qc's.
+ */
+int ata_port_abort(struct ata_port *ap)
+{
+ return ata_do_link_abort(ap, NULL);
+}
+
+/**
* __ata_port_freeze - freeze port
* @ap: ATA port to freeze
*
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 8feaf04..f31c979 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -776,6 +776,7 @@ extern unsigned long ata_pci_default_fil
extern void ata_eng_timeout(struct ata_port *ap);
extern void ata_port_schedule_eh(struct ata_port *ap);
+extern int ata_link_abort(struct ata_link *link);
extern int ata_port_abort(struct ata_port *ap);
extern int ata_port_freeze(struct ata_port *ap);
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 13/14] libata-link: update EH to deal with PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (9 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 09/14] libata-link: implement ata_link_abort() Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 12/14] libata-link: update ata_dev_configure() " Tejun Heo
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Update ata_eh_autopsy(), ata_eh_report() and ata_eh_recover() to deal
with PM links. ata_eh_autopsy() and ata_eh_report() updates are
straightforward. They just repeat the same operation over all
configured links.
ata_eh_recover() update is more complex as it first processes all
resets and then performs the rest. This is necessary as thawing with
some links in unknown state can be dangerous. ehi->action is cleared
on successful recovery of a link to avoid repeating recovery due to
failures in other links.
ata_eh_recover() iterates over only PM links if PM is attached, and,
on failure, the failing link is returned in @failed_link instead of
disabling devices directly. These are to integrate ata_eh_recover()
into PM EH later.
---
drivers/scsi/libata-eh.c | 192 ++++++++++++++++++++++++++++++++--------------
1 files changed, 135 insertions(+), 57 deletions(-)
e76a448cb0f33855cd17ee65f4a5f5b83e6962af
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 8e89379..24b5dc8 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1196,8 +1196,8 @@ static int ata_eh_speed_down(struct ata_
}
/**
- * ata_eh_autopsy - analyze error and determine recovery action
- * @link: ATA link to perform autopsy on
+ * ata_eh_link_autopsy - analyze error and determine recovery action
+ * @link: host link to perform autopsy on
*
* Analyze why @link failed and determine which recovery actions
* are needed. This function also sets more detailed AC_ERR_*
@@ -1206,7 +1206,7 @@ static int ata_eh_speed_down(struct ata_
* LOCKING:
* Kernel thread context (may sleep).
*/
-static void ata_eh_autopsy(struct ata_link *link)
+static void ata_eh_link_autopsy(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
@@ -1287,7 +1287,25 @@ static void ata_eh_autopsy(struct ata_li
}
/**
- * ata_eh_report - report error handling to user
+ * ata_eh_autopsy - analyze error and determine recovery action
+ * @ap: host port to perform autopsy on
+ *
+ * Analyze all links of @ap and determine why they failed and
+ * which recovery actions are needed.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+static void ata_eh_autopsy(struct ata_port *ap)
+{
+ struct ata_link *link;
+
+ __ata_port_for_each_link(link, ap)
+ ata_eh_link_autopsy(link);
+}
+
+/**
+ * ata_eh_link_report - report error handling to user
* @link: ATA link EH is going on
*
* Report EH to user.
@@ -1295,7 +1313,7 @@ static void ata_eh_autopsy(struct ata_li
* LOCKING:
* None.
*/
-static void ata_eh_report(struct ata_link *link)
+static void ata_eh_link_report(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
@@ -1355,6 +1373,23 @@ static void ata_eh_report(struct ata_lin
}
}
+/**
+ * ata_eh_report - report error handling to user
+ * @ap: ATA port to report EH about
+ *
+ * Report EH to user.
+ *
+ * LOCKING:
+ * None.
+ */
+static void ata_eh_report(struct ata_port *ap)
+{
+ struct ata_link *link;
+
+ __ata_port_for_each_link(link, ap)
+ ata_eh_link_report(link);
+}
+
static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
unsigned int *classes)
{
@@ -1615,12 +1650,13 @@ static int ata_eh_skip_recovery(struct a
* @softreset: softreset method (can be NULL)
* @hardreset: hardreset method (can be NULL)
* @postreset: postreset method (can be NULL)
+ * @r_failed_link: out parameter for failed link
*
* This is the alpha and omega, eum and yang, heart and soul of
* libata exception handling. On entry, actions required to
- * recover the port and hotplug requests are recorded in
- * eh_context. This function executes all the operations with
- * appropriate retrials and fallbacks to resurrect failed
+ * recover each link and hotplug requests are recorded in the
+ * link's eh_context. This function executes all the operations
+ * with appropriate retrials and fallbacks to resurrect failed
* devices, detach goners and greet newcomers.
*
* LOCKING:
@@ -1631,71 +1667,106 @@ static int ata_eh_skip_recovery(struct a
*/
static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
- ata_postreset_fn_t postreset)
+ ata_postreset_fn_t postreset,
+ struct ata_link **r_failed_link)
{
- struct ata_link *link = &ap->link;
- struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_link *link;
+ struct ata_eh_context *ehc;
struct ata_device *dev;
- int down_xfermask, rc;
+ int down_xfermask, reset, rc;
DPRINTK("ENTER\n");
/* prep for recovery */
- ata_link_for_each_dev(dev, link) {
- ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+ ata_port_for_each_link(link, ap) {
+ ehc = &link->eh_context;
- /* process hotplug request */
- if (dev->flags & ATA_DFLAG_DETACH)
- ata_eh_detach_dev(dev);
+ ata_link_for_each_dev(dev, link) {
+ ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
- if (!ata_dev_enabled(dev) &&
- (ehc->i.probe_mask & (1 << dev->devno) &&
- !(ehc->did_probe_mask & (1 << dev->devno)))) {
- ata_eh_detach_dev(dev);
- ata_dev_init(dev);
- ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
+ /* process hotplug request */
+ if (dev->flags & ATA_DFLAG_DETACH)
+ ata_eh_detach_dev(dev);
+
+ if (!ata_dev_enabled(dev) &&
+ (ehc->i.probe_mask & (1 << dev->devno) &&
+ !(ehc->did_probe_mask & (1 << dev->devno)))) {
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+ ehc->did_probe_mask |= (1 << dev->devno);
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
}
}
retry:
down_xfermask = 0;
rc = 0;
+ reset = 0;
- /* skip EH if possible. */
- if (ata_eh_skip_recovery(link))
- ehc->i.action = 0;
+ /* do we need to reset? */
+ ata_port_for_each_link(link, ap) {
+ ehc = &link->eh_context;
- ata_link_for_each_dev(dev, link)
- ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
+ /* skip EH if possible. */
+ if (ata_eh_skip_recovery(link))
+ ehc->i.action = 0;
+
+ if (ehc->i.action & ATA_EH_RESET_MASK)
+ reset = 1;
+ }
+
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link) {
+ ehc = &link->eh_context;
+ ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
+ }
+ }
/* reset */
- if (ehc->i.action & ATA_EH_RESET_MASK) {
- ata_eh_freeze_port(ap);
+ if (reset) {
+ __ata_port_freeze(ap);
- rc = ata_eh_reset(link, ata_link_nr_vacant(ap), prereset,
- softreset, hardreset, postreset);
- if (rc) {
- ata_port_printk(ap, KERN_ERR,
- "reset failed, giving up\n");
- goto out;
+ ata_port_for_each_link(link, ap) {
+ ehc = &link->eh_context;
+
+ if (!(ehc->i.action & ATA_EH_RESET_MASK))
+ continue;
+
+ rc = ata_eh_reset(link, ata_link_nr_vacant(link),
+ prereset, softreset, hardreset,
+ postreset);
+ if (rc) {
+ ata_link_printk(link, KERN_ERR,
+ "reset failed, giving up\n");
+ goto out;
+ }
}
ata_eh_thaw_port(ap);
}
- /* revalidate existing devices and attach new ones */
- rc = ata_eh_revalidate_and_attach(link, &dev);
- if (rc)
- goto dev_fail;
-
- /* configure transfer mode if the port has been reset */
- if (ehc->flags & ATA_EHC_DID_RESET) {
- rc = ata_set_mode(link, &dev);
- if (rc) {
- down_xfermask = 1;
+ /* the rest */
+ ata_port_for_each_link(link, ap) {
+ ehc = &link->eh_context;
+
+ /* revalidate existing devices and attach new ones */
+ rc = ata_eh_revalidate_and_attach(link, &dev);
+ if (rc)
goto dev_fail;
+
+ /* configure transfer mode if the port has been reset */
+ if (ehc->flags & ATA_EHC_DID_RESET) {
+ rc = ata_set_mode(link, &dev);
+ if (rc) {
+ down_xfermask = 1;
+ goto dev_fail;
+ }
}
+
+ /* this link is okay now */
+ ehc->flags &= ~ATA_EHC_DID_RESET;
+ ehc->i.action = 0;
}
goto out;
@@ -1718,7 +1789,7 @@ static int ata_eh_recover(struct ata_por
}
if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
- /* disable device if it has used up all its chances */
+ /* the device has used all its chances, disable */
ata_dev_disable(dev);
/* detach if offline */
@@ -1743,8 +1814,8 @@ static int ata_eh_recover(struct ata_por
ehc->i.action |= ATA_EH_SOFTRESET;
}
- if (ata_link_nr_enabled(ap)) {
- ata_port_printk(ap, KERN_WARNING, "failed to recover some "
+ if (ata_link_nr_enabled(link)) {
+ ata_link_printk(link, KERN_WARNING, "failed to recover some "
"devices, retrying in 5 secs\n");
ssleep(5);
} else {
@@ -1755,10 +1826,8 @@ static int ata_eh_recover(struct ata_por
goto retry;
out:
- if (rc) {
- ata_link_for_each_dev(dev, link)
- ata_dev_disable(dev);
- }
+ if (rc && r_failed_link)
+ *r_failed_link = link;
DPRINTK("EXIT, rc=%d\n", rc);
return rc;
@@ -1887,11 +1956,20 @@ void ata_do_eh(struct ata_port *ap, ata_
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
+ struct ata_device *dev;
+ int rc;
+
if (!(ap->flags & (ATA_FLAG_LOADING | ATA_FLAG_UNLOADING))) {
- ata_eh_autopsy(&ap->link);
- ata_eh_report(&ap->link);
+ ata_eh_autopsy(ap);
+ ata_eh_report(ap);
+ }
+
+ rc = ata_eh_recover(ap, prereset, softreset, hardreset, postreset,
+ NULL);
+ if (rc) {
+ ata_link_for_each_dev(dev, &ap->link)
+ ata_dev_disable(dev);
}
- ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
ata_eh_finish(ap);
}
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 12/14] libata-link: update ata_dev_configure() to deal with PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (10 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 13/14] libata-link: update EH to deal with PM links Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 03/14] libata-link: implement and use link/device iterators Tejun Heo
2006-05-11 16:30 ` [PATCH 14/14] libata-link: update hotplug to handle PM links Tejun Heo
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Update ata_dev_configure() to deal with PM links.
---
drivers/scsi/libata-core.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
17a1cd83a17e3c44a2732ff2e77320f79b8565cd
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 740e831..32ea394 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1314,7 +1314,7 @@ int ata_dev_configure(struct ata_device
{
struct ata_port *ap = dev->link->ap;
const u16 *id = dev->id;
- struct ata_device *tdev;
+ struct ata_link *tlink;
unsigned int xfer_mask;
int rc;
@@ -1437,10 +1437,13 @@ int ata_dev_configure(struct ata_device
}
ap->host->max_cmd_len = 0;
- ata_link_for_each_dev(tdev, dev->link) {
- ap->host->max_cmd_len = max_t(unsigned int,
- ap->host->max_cmd_len,
- tdev->cdb_len);
+ ata_port_for_each_link(tlink, ap) {
+ struct ata_device *tdev;
+ ata_link_for_each_dev(tdev, tlink) {
+ ap->host->max_cmd_len = max_t(unsigned int,
+ ap->host->max_cmd_len,
+ tdev->cdb_len);
+ }
}
/* limit bridge transfers to udma5, 200 sectors */
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 03/14] libata-link: implement and use link/device iterators
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (11 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 12/14] libata-link: update ata_dev_configure() " Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
2006-05-11 16:30 ` [PATCH 14/14] libata-link: update hotplug to handle PM links Tejun Heo
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Multiple links and different number of devices per link should be
considered to iterate over links and devices. This patch implements
and uses link and device iterators - ata_port_for_each_link() and
ata_link_for_each_dev() - and ata_link_max_devices().
This change makes a lot of functions iterate over only possible
devices instead of from dev 0 to dev ATA_MAX_DEVICES. All such
changes have been examined and nothing should be broken.
While at it, add a separating comment before device helpers to
distinguish them better from link helpers and others.
---
drivers/scsi/libata-core.c | 71 +++++++++++++++++++------------------------
drivers/scsi/libata-eh.c | 72 +++++++++++++++++++++-----------------------
drivers/scsi/libata-scsi.c | 10 +++---
include/linux/libata.h | 22 +++++++++++++
4 files changed, 93 insertions(+), 82 deletions(-)
c3d11a19666ed32115710146ec33e24cb9336b7e
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index e132e47..501a752 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1313,8 +1313,9 @@ int ata_dev_configure(struct ata_device
{
struct ata_port *ap = dev->link->ap;
const u16 *id = dev->id;
+ struct ata_device *tdev;
unsigned int xfer_mask;
- int i, rc;
+ int rc;
if (!ata_dev_enabled(dev)) {
DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
@@ -1435,10 +1436,11 @@ int ata_dev_configure(struct ata_device
}
ap->host->max_cmd_len = 0;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
+ ata_link_for_each_dev(tdev, dev->link) {
ap->host->max_cmd_len = max_t(unsigned int,
ap->host->max_cmd_len,
- ap->link.device[i].cdb_len);
+ tdev->cdb_len);
+ }
/* limit bridge transfers to udma5, 200 sectors */
if (ata_dev_knobble(dev)) {
@@ -1479,13 +1481,13 @@ static int ata_bus_probe(struct ata_port
{
unsigned int classes[ATA_MAX_DEVICES];
int tries[ATA_MAX_DEVICES];
- int i, rc, down_xfermask;
+ int rc, down_xfermask;
struct ata_device *dev;
ata_port_probe(ap);
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- tries[i] = ATA_PROBE_MAX_TRIES;
+ ata_link_for_each_dev(dev, &ap->link)
+ tries[dev->devno] = ATA_PROBE_MAX_TRIES;
retry:
down_xfermask = 0;
@@ -1493,9 +1495,7 @@ static int ata_bus_probe(struct ata_port
/* reset and determine device classes */
ap->ops->phy_reset(ap);
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, &ap->link) {
if (!(ap->flags & ATA_FLAG_DISABLED) &&
dev->class != ATA_DEV_UNKNOWN)
classes[dev->devno] = dev->class;
@@ -1508,11 +1508,9 @@ static int ata_bus_probe(struct ata_port
ata_port_probe(ap);
/* read IDENTIFY page and configure devices */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
- if (tries[i])
- dev->class = classes[i];
+ ata_link_for_each_dev(dev, &ap->link) {
+ if (tries[dev->devno])
+ dev->class = classes[dev->devno];
if (!ata_dev_enabled(dev))
continue;
@@ -1533,9 +1531,10 @@ static int ata_bus_probe(struct ata_port
goto fail;
}
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_enabled(&ap->link.device[i]))
+ ata_link_for_each_dev(dev, &ap->link) {
+ if (ata_dev_enabled(dev))
return 0;
+ }
/* no device present, disable port */
ata_port_disable(ap);
@@ -2077,16 +2076,17 @@ static int ata_dev_set_mode(struct ata_d
*/
int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
{
+ struct ata_link *link = &ap->link;
struct ata_device *dev;
- int i, rc = 0, used_dma = 0, found = 0;
+ int rc = 0, used_dma = 0, found = 0;
/* has private set_mode? */
if (ap->ops->set_mode) {
/* FIXME: make ->set_mode handle no device case and
* return error code and failing device on failure.
*/
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- if (ata_dev_enabled(&ap->link.device[i])) {
+ ata_link_for_each_dev(dev, link) {
+ if (ata_dev_enabled(dev)) {
ap->ops->set_mode(ap);
break;
}
@@ -2095,11 +2095,9 @@ int ata_set_mode(struct ata_port *ap, st
}
/* step 1: calculate xfer_mask */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ ata_link_for_each_dev(dev, link) {
unsigned int pio_mask, dma_mask;
- dev = &ap->link.device[i];
-
if (!ata_dev_enabled(dev))
continue;
@@ -2118,8 +2116,7 @@ int ata_set_mode(struct ata_port *ap, st
goto out;
/* step 2: always set host PIO timings */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
+ ata_link_for_each_dev(dev, link) {
if (!ata_dev_enabled(dev))
continue;
@@ -2136,9 +2133,7 @@ int ata_set_mode(struct ata_port *ap, st
}
/* step 3: set host DMA timings */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, link) {
if (!ata_dev_enabled(dev) || !dev->dma_mode)
continue;
@@ -2149,9 +2144,7 @@ int ata_set_mode(struct ata_port *ap, st
}
/* step 4: update devices' xfer mode */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, link) {
if (!ata_dev_enabled(dev))
continue;
@@ -2947,8 +2940,8 @@ static void ata_dev_xfermask(struct ata_
struct ata_link *link = dev->link;
struct ata_port *ap = link->ap;
struct ata_host_set *hs = ap->host_set;
+ struct ata_device *d;
unsigned long xfer_mask;
- int i;
xfer_mask = ata_pack_xfermask(ap->pio_mask,
ap->mwdma_mask, ap->udma_mask);
@@ -2959,10 +2952,8 @@ static void ata_dev_xfermask(struct ata_
if (ap->cbl == ATA_CBL_PATA40)
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
- /* FIXME: Use port-wide xfermask for now */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *d = &link->device[i];
-
+ /* FIXME: Use link-wide xfermask for now */
+ ata_link_for_each_dev(d, link) {
if (ata_dev_absent(d))
continue;
@@ -5143,7 +5134,7 @@ static void ata_host_init(struct ata_por
ap->link.ap = ap;
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ for (i = 0; i < ata_link_max_devices(&ap->link); i++) {
struct ata_device *dev = &ap->link.device[i];
dev->link = &ap->link;
dev->devno = i;
@@ -5330,7 +5321,7 @@ int ata_device_add(const struct ata_prob
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->link.eh_info.probe_mask =
- (1 << ATA_MAX_DEVICES) - 1;
+ (1 << ata_link_max_devices(&ap->link)) - 1;
ap->link.eh_info.action |= ATA_EH_SOFTRESET;
set_bit(bit, &ap->flags);
@@ -5396,7 +5387,7 @@ err_free_ret:
void ata_port_detach(struct ata_port *ap)
{
unsigned long flags;
- int i;
+ struct ata_device *dev;
if (!ap->ops->error_handler)
return;
@@ -5405,8 +5396,8 @@ void ata_port_detach(struct ata_port *ap
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->flags |= ATA_FLAG_UNLOADING;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->link.device[i].flags |= ATA_DFLAG_DETACH;
+ ata_link_for_each_dev(dev, &ap->link)
+ dev->flags |= ATA_DFLAG_DETACH;
ata_port_schedule_eh(ap);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index cde769f..4026886 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1326,10 +1326,11 @@ static void ata_eh_report(struct ata_por
static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
unsigned int *classes)
{
- int i, rc;
+ struct ata_device *dev;
+ int rc;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- classes[i] = ATA_DEV_UNKNOWN;
+ ata_link_for_each_dev(dev, &ap->link)
+ classes[dev->devno] = ATA_DEV_UNKNOWN;
rc = reset(ap, classes);
if (rc)
@@ -1339,14 +1340,14 @@ static int ata_do_reset(struct ata_port
* is complete and convert all ATA_DEV_UNKNOWN to
* ATA_DEV_NONE.
*/
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (classes[i] != ATA_DEV_UNKNOWN)
+ ata_link_for_each_dev(dev, &ap->link)
+ if (classes[dev->devno] != ATA_DEV_UNKNOWN)
break;
- if (i < ATA_MAX_DEVICES)
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (classes[i] == ATA_DEV_UNKNOWN)
- classes[i] = ATA_DEV_NONE;
+ if (dev)
+ ata_link_for_each_dev(dev, &ap->link)
+ if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+ classes[dev->devno] = ATA_DEV_NONE;
return 0;
}
@@ -1373,7 +1374,7 @@ static int ata_eh_reset(struct ata_port
int verbose = !(ap->flags & ATA_FLAG_LOADING);
unsigned int action;
ata_reset_fn_t reset;
- int i, did_followup_srst, rc;
+ int did_followup_srst, rc;
/* Determine which reset to use and record in ehc->i.action.
* prereset() may examine it to determine what kind of
@@ -1397,8 +1398,9 @@ static int ata_eh_reset(struct ata_port
* -ENODEV.
*/
if (rc == -ENODEV) {
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- classes[i] = ATA_DEV_NONE;
+ struct ata_device *dev;
+ ata_link_for_each_dev(dev, &ap->link)
+ classes[dev->devno] = ATA_DEV_NONE;
return 0;
}
@@ -1487,13 +1489,11 @@ static int ata_eh_revalidate_and_attach(
struct ata_eh_context *ehc = &ap->link.eh_context;
struct ata_device *dev;
unsigned long flags;
- int i, rc = 0;
+ int rc = 0;
DPRINTK("ENTER\n");
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, &ap->link) {
if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) &&
(!ehc->i.dev || ehc->i.dev == dev)) {
if (ata_port_offline(ap)) {
@@ -1537,20 +1537,22 @@ static int ata_eh_revalidate_and_attach(
static int ata_port_nr_enabled(struct ata_port *ap)
{
- int i, cnt = 0;
+ struct ata_device *dev;
+ int cnt = 0;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_enabled(&ap->link.device[i]))
+ ata_link_for_each_dev(dev, &ap->link)
+ if (ata_dev_enabled(dev))
cnt++;
return cnt;
}
static int ata_port_nr_vacant(struct ata_port *ap)
{
- int i, cnt = 0;
+ struct ata_device *dev;
+ int cnt = 0;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ap->link.device[i].class == ATA_DEV_UNKNOWN)
+ ata_link_for_each_dev(dev, &ap->link)
+ if (dev->class == ATA_DEV_UNKNOWN)
cnt++;
return cnt;
}
@@ -1558,15 +1560,13 @@ static int ata_port_nr_vacant(struct ata
static int ata_eh_skip_recovery(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->link.eh_context;
- int i;
+ struct ata_device *dev;
if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
return 0;
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, &ap->link) {
if (dev->class == ATA_DEV_UNKNOWN &&
ehc->classes[dev->devno] != ATA_DEV_NONE)
return 0;
@@ -1602,14 +1602,12 @@ static int ata_eh_recover(struct ata_por
{
struct ata_eh_context *ehc = &ap->link.eh_context;
struct ata_device *dev;
- int down_xfermask, i, rc;
+ int down_xfermask, rc;
DPRINTK("ENTER\n");
/* prep for recovery */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- dev = &ap->link.device[i];
-
+ ata_link_for_each_dev(dev, &ap->link) {
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
/* process hotplug request */
@@ -1634,8 +1632,8 @@ static int ata_eh_recover(struct ata_por
if (ata_eh_skip_recovery(ap))
ehc->i.action = 0;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ehc->classes[i] = ATA_DEV_UNKNOWN;
+ ata_link_for_each_dev(dev, &ap->link)
+ ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
/* reset */
if (ehc->i.action & ATA_EH_RESET_MASK) {
@@ -1724,8 +1722,8 @@ static int ata_eh_recover(struct ata_por
out:
if (rc) {
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ata_dev_disable(&ap->link.device[i]);
+ ata_link_for_each_dev(dev, &ap->link)
+ ata_dev_disable(dev);
}
DPRINTK("EXIT, rc=%d\n", rc);
@@ -1790,7 +1788,8 @@ void ata_eh_scsi_hotplug(void *data)
{
struct ata_port *ap = data;
unsigned long timeout;
- int i, requeue = 0;
+ struct ata_device *dev;
+ int requeue = 0;
DPRINTK("ENTER\n");
@@ -1811,8 +1810,7 @@ void ata_eh_scsi_hotplug(void *data)
requeue = 1;
/* unplug detached devices */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->link.device[i];
+ ata_link_for_each_dev(dev, &ap->link) {
unsigned long flags;
if (!(dev->flags & ATA_DFLAG_DETACHED))
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 6d9384a..facde9e 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2775,19 +2775,18 @@ void ata_scsi_simulate(struct ata_device
void ata_scsi_scan_host(struct ata_port *ap)
{
- unsigned int i;
+ struct ata_device *dev;
if (ap->flags & ATA_FLAG_DISABLED)
return;
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *dev = &ap->link.device[i];
+ ata_link_for_each_dev(dev, &ap->link) {
struct scsi_device *sdev;
if (!ata_dev_enabled(dev) || dev->sdev)
continue;
- sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
+ sdev = __scsi_add_device(ap->host, 0, dev->devno, 0, NULL);
if (!IS_ERR(sdev)) {
dev->sdev = sdev;
scsi_device_put(sdev);
@@ -2911,7 +2910,8 @@ static int ata_scsi_user_scan(struct Scs
spin_lock_irqsave(&ap->host_set->lock, flags);
if (id == SCAN_WILD_CARD) {
- ap->link.eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+ ap->link.eh_info.probe_mask |=
+ (1 << ata_link_max_devices(&ap->link)) - 1;
ap->link.eh_info.action |= ATA_EH_SOFTRESET;
} else {
struct ata_device *dev = ata_find_dev(ap, id);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index fbb3f4c..c7c904f 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -861,6 +861,9 @@ static inline unsigned int ata_tag_inter
return tag == ATA_MAX_QUEUE - 1;
}
+/*
+ * device helpers
+ */
static inline unsigned int ata_class_enabled(unsigned int class)
{
return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
@@ -891,6 +894,25 @@ static inline unsigned int ata_dev_absen
return ata_class_absent(dev->class);
}
+/*
+ * link helpers
+ */
+static inline int ata_link_max_devices(const struct ata_link *link)
+{
+ if (link->ap->flags & ATA_FLAG_SLAVE_POSS)
+ return 2;
+ return 1;
+}
+
+#define ata_port_for_each_link(lk, ap) \
+ for ((lk) = &(ap)->link; (lk); (lk) = NULL)
+
+#define ata_link_for_each_dev(dev, link) \
+ for ((dev) = (link)->device; \
+ (dev) - (link)->device < ata_link_max_devices(link) || (dev = NULL); \
+ (dev)++)
+
+
static inline u8 ata_chk_status(struct ata_port *ap)
{
return ap->ops->check_status(ap);
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 14/14] libata-link: update hotplug to handle PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (12 preceding siblings ...)
2006-05-11 16:30 ` [PATCH 03/14] libata-link: implement and use link/device iterators Tejun Heo
@ 2006-05-11 16:30 ` Tejun Heo
13 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2006-05-11 16:30 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Update hotplug to handle PM links. When PM is attached, the PMP
number corresponds to I of SCSI C:H:I:L.
---
drivers/scsi/libata-eh.c | 43 +++++++++++++++++++++++++--------------
drivers/scsi/libata-scsi.c | 49 +++++++++++++++++++++++++++++++-------------
2 files changed, 62 insertions(+), 30 deletions(-)
314e603ad221c11cea7e123706d8c4c492466ab0
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 24b5dc8..ecfb9c5 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1875,6 +1875,25 @@ static void ata_eh_finish(struct ata_por
}
}
+static void ata_eh_scsi_handle_link_detach(struct ata_link *link)
+{
+ struct ata_port *ap = link->ap;
+ struct ata_device *dev;
+
+ ata_link_for_each_dev(dev, link) {
+ unsigned long flags;
+
+ if (!(dev->flags & ATA_DFLAG_DETACHED))
+ continue;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ dev->flags &= ~ATA_DFLAG_DETACHED;
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ ata_scsi_remove_dev(dev);
+ }
+}
+
/**
* ata_eh_scsi_hotplug - SCSI part of hotplug
* @data: Pointer to ATA port to perform SCSI hotplug on
@@ -1891,8 +1910,7 @@ void ata_eh_scsi_hotplug(void *data)
{
struct ata_port *ap = data;
unsigned long timeout;
- struct ata_device *dev;
- int requeue = 0;
+ int i, requeue = 0;
DPRINTK("ENTER\n");
@@ -1912,19 +1930,14 @@ void ata_eh_scsi_hotplug(void *data)
if (scsi_host_in_recovery(ap->host))
requeue = 1;
- /* unplug detached devices */
- ata_link_for_each_dev(dev, &ap->link) {
- unsigned long flags;
-
- if (!(dev->flags & ATA_DFLAG_DETACHED))
- continue;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- dev->flags &= ~ATA_DFLAG_DETACHED;
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- ata_scsi_remove_dev(dev);
- }
+ /* Unplug detached devices. We cannot use link iterator here
+ * because PM links have to be scanned even if PM is currently
+ * not attached. Iterate manually.
+ */
+ ata_eh_scsi_handle_link_detach(&ap->link);
+ if (ap->pm_link)
+ for (i = 0; i < ATA_PM_MAX_PORTS; i++)
+ ata_eh_scsi_handle_link_detach(&ap->pm_link[i]);
/* scan for new ones */
ata_scsi_scan_host(ap);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index facde9e..021e4a3 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2347,8 +2347,14 @@ static unsigned int atapi_xlat(struct at
static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
{
- if (likely(id == 0 || (id == 1 && ap->flags & ATA_FLAG_SLAVE_POSS)))
- return &ap->link.device[id];
+ if (ap->nr_pm_links == 0) {
+ if (likely(id < ata_link_max_devices(&ap->link)))
+ return &ap->link.device[id];
+ } else {
+ if (likely(id < ap->nr_pm_links))
+ return &ap->pm_link[id].device[0];
+ }
+
return NULL;
}
@@ -2775,21 +2781,30 @@ void ata_scsi_simulate(struct ata_device
void ata_scsi_scan_host(struct ata_port *ap)
{
+ struct ata_link *link;
struct ata_device *dev;
if (ap->flags & ATA_FLAG_DISABLED)
return;
- ata_link_for_each_dev(dev, &ap->link) {
- struct scsi_device *sdev;
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link) {
+ struct scsi_device *sdev;
+ int devno;
- if (!ata_dev_enabled(dev) || dev->sdev)
- continue;
+ if (!ata_dev_enabled(dev) || dev->sdev)
+ continue;
- sdev = __scsi_add_device(ap->host, 0, dev->devno, 0, NULL);
- if (!IS_ERR(sdev)) {
- dev->sdev = sdev;
- scsi_device_put(sdev);
+ if (ata_is_host_link(link))
+ devno = dev->devno;
+ else
+ devno = link->pmp;
+
+ sdev = __scsi_add_device(ap->host, 0, devno, 0, NULL);
+ if (!IS_ERR(sdev)) {
+ dev->sdev = sdev;
+ scsi_device_put(sdev);
+ }
}
}
}
@@ -2897,6 +2912,7 @@ static int ata_scsi_user_scan(struct Scs
unsigned int id, unsigned int lun)
{
struct ata_port *ap = ata_shost_to_port(shost);
+ struct ata_link *link;
unsigned long flags;
int rc = 0;
@@ -2910,15 +2926,18 @@ static int ata_scsi_user_scan(struct Scs
spin_lock_irqsave(&ap->host_set->lock, flags);
if (id == SCAN_WILD_CARD) {
- ap->link.eh_info.probe_mask |=
- (1 << ata_link_max_devices(&ap->link)) - 1;
- ap->link.eh_info.action |= ATA_EH_SOFTRESET;
+ ata_port_for_each_link(link, ap) {
+ link->eh_info.probe_mask |=
+ (1 << ata_link_max_devices(link)) - 1;
+ link->eh_info.action |= ATA_EH_SOFTRESET;
+ }
} else {
struct ata_device *dev = ata_find_dev(ap, id);
if (dev) {
- ap->link.eh_info.probe_mask |= 1 << dev->devno;
- ap->link.eh_info.action |= ATA_EH_SOFTRESET;
+ link = dev->link;
+ link->eh_info.probe_mask |= 1 << dev->devno;
+ link->eh_info.action |= ATA_EH_SOFTRESET;
} else
rc = -EINVAL;
}
--
1.2.4
^ permalink raw reply related [flat|nested] 15+ messages in thread