diff options
author | Tejun Heo <htejun@gmail.com> | 2007-09-23 00:14:12 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-12 14:55:41 -0400 |
commit | da917d69d0ea63f5390716cba6e77f490ce96df9 (patch) | |
tree | 214670f42be4c140bbd05226adc8f86db51ee725 /drivers/ata/libata-core.c | |
parent | 31cc23b34913bc173680bdc87af79e551bf8cc0d (diff) |
libata-pmp-prep: implement qc_defer helpers
Implement ap->nr_active_links (the number of links with active qcs),
ap->excl_link (pointer to link which can be used by ->qc_defer and is
cleared when a qc with ATA_QCFLAG_CLEAR_EXCL completes), and
ata_link_active().
These can be used by ->qc_defer() to implement proper command
exclusion. This set of helpers seem enough for both sil24 (ATAPI
exclusion needed) and cmd-switching PMP.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b666f51da7ed..376dbd80cc93 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1390,6 +1390,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, | |||
1390 | struct ata_queued_cmd *qc; | 1390 | struct ata_queued_cmd *qc; |
1391 | unsigned int tag, preempted_tag; | 1391 | unsigned int tag, preempted_tag; |
1392 | u32 preempted_sactive, preempted_qc_active; | 1392 | u32 preempted_sactive, preempted_qc_active; |
1393 | int preempted_nr_active_links; | ||
1393 | DECLARE_COMPLETION_ONSTACK(wait); | 1394 | DECLARE_COMPLETION_ONSTACK(wait); |
1394 | unsigned long flags; | 1395 | unsigned long flags; |
1395 | unsigned int err_mask; | 1396 | unsigned int err_mask; |
@@ -1428,9 +1429,11 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, | |||
1428 | preempted_tag = link->active_tag; | 1429 | preempted_tag = link->active_tag; |
1429 | preempted_sactive = link->sactive; | 1430 | preempted_sactive = link->sactive; |
1430 | preempted_qc_active = ap->qc_active; | 1431 | preempted_qc_active = ap->qc_active; |
1432 | preempted_nr_active_links = ap->nr_active_links; | ||
1431 | link->active_tag = ATA_TAG_POISON; | 1433 | link->active_tag = ATA_TAG_POISON; |
1432 | link->sactive = 0; | 1434 | link->sactive = 0; |
1433 | ap->qc_active = 0; | 1435 | ap->qc_active = 0; |
1436 | ap->nr_active_links = 0; | ||
1434 | 1437 | ||
1435 | /* prepare & issue qc */ | 1438 | /* prepare & issue qc */ |
1436 | qc->tf = *tf; | 1439 | qc->tf = *tf; |
@@ -1509,6 +1512,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, | |||
1509 | link->active_tag = preempted_tag; | 1512 | link->active_tag = preempted_tag; |
1510 | link->sactive = preempted_sactive; | 1513 | link->sactive = preempted_sactive; |
1511 | ap->qc_active = preempted_qc_active; | 1514 | ap->qc_active = preempted_qc_active; |
1515 | ap->nr_active_links = preempted_nr_active_links; | ||
1512 | 1516 | ||
1513 | /* XXX - Some LLDDs (sata_mv) disable port on command failure. | 1517 | /* XXX - Some LLDDs (sata_mv) disable port on command failure. |
1514 | * Until those drivers are fixed, we detect the condition | 1518 | * Until those drivers are fixed, we detect the condition |
@@ -5408,10 +5412,19 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) | |||
5408 | ata_sg_clean(qc); | 5412 | ata_sg_clean(qc); |
5409 | 5413 | ||
5410 | /* command should be marked inactive atomically with qc completion */ | 5414 | /* command should be marked inactive atomically with qc completion */ |
5411 | if (qc->tf.protocol == ATA_PROT_NCQ) | 5415 | if (qc->tf.protocol == ATA_PROT_NCQ) { |
5412 | link->sactive &= ~(1 << qc->tag); | 5416 | link->sactive &= ~(1 << qc->tag); |
5413 | else | 5417 | if (!link->sactive) |
5418 | ap->nr_active_links--; | ||
5419 | } else { | ||
5414 | link->active_tag = ATA_TAG_POISON; | 5420 | link->active_tag = ATA_TAG_POISON; |
5421 | ap->nr_active_links--; | ||
5422 | } | ||
5423 | |||
5424 | /* clear exclusive status */ | ||
5425 | if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL && | ||
5426 | ap->excl_link == link)) | ||
5427 | ap->excl_link = NULL; | ||
5415 | 5428 | ||
5416 | /* atapi: mark qc as inactive to prevent the interrupt handler | 5429 | /* atapi: mark qc as inactive to prevent the interrupt handler |
5417 | * from completing the command twice later, before the error handler | 5430 | * from completing the command twice later, before the error handler |
@@ -5590,9 +5603,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc) | |||
5590 | 5603 | ||
5591 | if (qc->tf.protocol == ATA_PROT_NCQ) { | 5604 | if (qc->tf.protocol == ATA_PROT_NCQ) { |
5592 | WARN_ON(link->sactive & (1 << qc->tag)); | 5605 | WARN_ON(link->sactive & (1 << qc->tag)); |
5606 | |||
5607 | if (!link->sactive) | ||
5608 | ap->nr_active_links++; | ||
5593 | link->sactive |= 1 << qc->tag; | 5609 | link->sactive |= 1 << qc->tag; |
5594 | } else { | 5610 | } else { |
5595 | WARN_ON(link->sactive); | 5611 | WARN_ON(link->sactive); |
5612 | |||
5613 | ap->nr_active_links++; | ||
5596 | link->active_tag = qc->tag; | 5614 | link->active_tag = qc->tag; |
5597 | } | 5615 | } |
5598 | 5616 | ||