* [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 13/14] libata-link: update EH to deal with PM links 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 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
* [PATCHSET 09/11] implement ata_link
@ 2006-05-11 16:30 Tejun Heo
2006-05-11 16:30 ` [PATCH 02/14] libata-link: introduce ata_link Tejun Heo
` (13 more replies)
0 siblings, 14 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,
htejun
Hellooo.
This is part of patchset series described in [T].
This is the first take of implement-ata_link patchset. This patchset
contains 14 patches which can be categorized as follows.
#01 : prep
#02-03: implement ata_link
#04-06: make parts of libata deal with link instead of port
#07-09: misc link stuff (link init, reset_tries, ata_link_abort())
#10-14: add ap->pm_link[] and update parts of libata to deal with
multiple links
ata_link abstracts PHY and sits between ata_port and ata_device. The
following attributes are moved to ata_link from ata_port.
- active command state (active_tag, sactive)
- [hw_]sata_spd_limit
- eh_info and eh_context
- device array
With above and a few extra fields, a link can fully host attached
devices including qc management and EH/hotplug. This patchset makes
libata ready to handle PM links.
This patchset is against
upstream (acc696d93dcf993dec123d69d599979e1456ffec)
+ [1] prep-for-new-EH patchset
+ [2] new-EH-framework patchset, take 3
+ [3] new-EH-implementation patchset, take 3
+ [4] merge-irq-pio patchset
+ [5] add-NCQ-support patchset, take 3
+ [6] prep-for-hotplug support, take 2
+ [7] prep-LLDDs-for-hotplug-support, take 1
+ [8] add-hotplug-support, take 2
--
tejun
[T] http://article.gmane.org/gmane.linux.ide/9957
[1] http://article.gmane.org/gmane.linux.ide/9959
[2] http://article.gmane.org/gmane.linux.ide/9984
[3] http://article.gmane.org/gmane.linux.ide/9995
[4] http://article.gmane.org/gmane.linux.ide/10005
[5] http://article.gmane.org/gmane.linux.ide/10011
[6] http://article.gmane.org/gmane.linux.ide/10028
[7] http://article.gmane.org/gmane.linux.ide/10063
[8] http://article.gmane.org/gmane.linux.ide/10073
^ permalink raw reply [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
` (2 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 11/14] libata-link: update ata_scsi_error() to handle 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
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 03/14] libata-link: implement and use link/device iterators
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (4 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 05/14] libata-link: linkify reset 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
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 06/14] libata-link: linkify config/EH related functions
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (8 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 09/14] libata-link: implement ata_link_abort() 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
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 04/14] libata-link: linkify PHY-related functions
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() to deal with PM links 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
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 09/14] libata-link: implement ata_link_abort()
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (9 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 12/14] libata-link: update ata_dev_configure() to deal with PM links 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
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 10/14] libata-link: add PM links
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (6 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 07/14] libata-link: separate out link initialization functions 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
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 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 09/14] libata-link: implement ata_link_abort() 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
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 05/14] libata-link: linkify reset
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (5 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
2006-05-11 16:30 ` [PATCH 10/14] libata-link: add PM links 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
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 13/14] libata-link: update EH to deal with PM links
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 08/14] libata-link: implement link->reset_tries 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
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 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
` (3 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 03/14] libata-link: implement and use link/device iterators 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
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 07/14] libata-link: separate out link initialization functions
2006-05-11 16:30 [PATCHSET 09/11] implement ata_link Tejun Heo
` (7 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 06/14] libata-link: linkify config/EH related functions 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
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 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 04/14] libata-link: linkify PHY-related functions 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
end of thread, other threads:[~2006-05-11 16:30 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 13/14] libata-link: update EH to deal with PM links Tejun Heo
2006-05-11 16:30 ` [PATCH 08/14] libata-link: implement link->reset_tries Tejun Heo
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 ` [PATCH 03/14] libata-link: implement and use link/device iterators Tejun Heo
2006-05-11 16:30 ` [PATCH 05/14] libata-link: linkify reset Tejun Heo
2006-05-11 16:30 ` [PATCH 10/14] libata-link: add PM links Tejun Heo
2006-05-11 16:30 ` [PATCH 07/14] libata-link: separate out link initialization functions Tejun Heo
2006-05-11 16:30 ` [PATCH 06/14] libata-link: linkify config/EH related functions Tejun Heo
2006-05-11 16:30 ` [PATCH 09/14] libata-link: implement ata_link_abort() Tejun Heo
2006-05-11 16:30 ` [PATCH 12/14] libata-link: update ata_dev_configure() to deal with PM links Tejun Heo
2006-05-11 16:30 ` [PATCH 04/14] libata-link: linkify PHY-related functions Tejun Heo
2006-05-11 16:30 ` [PATCH 14/14] libata-link: update hotplug to handle PM links Tejun Heo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.