aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-05-15 08:03:43 -0400
committerTejun Heo <htejun@gmail.com>2006-05-15 08:03:43 -0400
commitdedaf2b0365ccec50714fbde0b3215e7e94fa47c (patch)
treed98e2a928793e6072d4ff65b0e2ceedaa600e25d /drivers
parent6cec4a3943bdfe46e2952bc246f17670f747be8d (diff)
[PATCH] libata-ncq: implement ap->qc_active, ap->sactive and complete helper
Add ap->qc_active and ap->sactive, mask of all active qcs and libata's view of the SActive register, respectively. Also, implement ata_qc_complete_multiple() which takes new qc_active mask and complete multiple qcs according to the mask. These will be used to track NCQ commands and complete them. The distinction between ap->qc_active and ap->sactive is also useful for later PM implementation. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libata-core.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index f8401800dc1a..eea1fe9c8b79 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -981,6 +981,7 @@ unsigned ata_exec_internal(struct ata_device *dev,
981 u8 command = tf->command; 981 u8 command = tf->command;
982 struct ata_queued_cmd *qc; 982 struct ata_queued_cmd *qc;
983 unsigned int tag, preempted_tag; 983 unsigned int tag, preempted_tag;
984 u32 preempted_sactive, preempted_qc_active;
984 DECLARE_COMPLETION(wait); 985 DECLARE_COMPLETION(wait);
985 unsigned long flags; 986 unsigned long flags;
986 unsigned int err_mask; 987 unsigned int err_mask;
@@ -1017,7 +1018,11 @@ unsigned ata_exec_internal(struct ata_device *dev,
1017 ata_qc_reinit(qc); 1018 ata_qc_reinit(qc);
1018 1019
1019 preempted_tag = ap->active_tag; 1020 preempted_tag = ap->active_tag;
1021 preempted_sactive = ap->sactive;
1022 preempted_qc_active = ap->qc_active;
1020 ap->active_tag = ATA_TAG_POISON; 1023 ap->active_tag = ATA_TAG_POISON;
1024 ap->sactive = 0;
1025 ap->qc_active = 0;
1021 1026
1022 /* prepare & issue qc */ 1027 /* prepare & issue qc */
1023 qc->tf = *tf; 1028 qc->tf = *tf;
@@ -1082,6 +1087,8 @@ unsigned ata_exec_internal(struct ata_device *dev,
1082 1087
1083 ata_qc_free(qc); 1088 ata_qc_free(qc);
1084 ap->active_tag = preempted_tag; 1089 ap->active_tag = preempted_tag;
1090 ap->sactive = preempted_sactive;
1091 ap->qc_active = preempted_qc_active;
1085 1092
1086 /* XXX - Some LLDDs (sata_mv) disable port on command failure. 1093 /* XXX - Some LLDDs (sata_mv) disable port on command failure.
1087 * Until those drivers are fixed, we detect the condition 1094 * Until those drivers are fixed, we detect the condition
@@ -4270,6 +4277,8 @@ void ata_qc_free(struct ata_queued_cmd *qc)
4270 4277
4271void __ata_qc_complete(struct ata_queued_cmd *qc) 4278void __ata_qc_complete(struct ata_queued_cmd *qc)
4272{ 4279{
4280 struct ata_port *ap = qc->ap;
4281
4273 WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ 4282 WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
4274 WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); 4283 WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
4275 4284
@@ -4277,13 +4286,17 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
4277 ata_sg_clean(qc); 4286 ata_sg_clean(qc);
4278 4287
4279 /* command should be marked inactive atomically with qc completion */ 4288 /* command should be marked inactive atomically with qc completion */
4280 qc->ap->active_tag = ATA_TAG_POISON; 4289 if (qc->tf.protocol == ATA_PROT_NCQ)
4290 ap->sactive &= ~(1 << qc->tag);
4291 else
4292 ap->active_tag = ATA_TAG_POISON;
4281 4293
4282 /* atapi: mark qc as inactive to prevent the interrupt handler 4294 /* atapi: mark qc as inactive to prevent the interrupt handler
4283 * from completing the command twice later, before the error handler 4295 * from completing the command twice later, before the error handler
4284 * is called. (when rc != 0 and atapi request sense is needed) 4296 * is called. (when rc != 0 and atapi request sense is needed)
4285 */ 4297 */
4286 qc->flags &= ~ATA_QCFLAG_ACTIVE; 4298 qc->flags &= ~ATA_QCFLAG_ACTIVE;
4299 ap->qc_active &= ~(1 << qc->tag);
4287 4300
4288 /* call completion callback */ 4301 /* call completion callback */
4289 qc->complete_fn(qc); 4302 qc->complete_fn(qc);
@@ -4349,6 +4362,55 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
4349 } 4362 }
4350} 4363}
4351 4364
4365/**
4366 * ata_qc_complete_multiple - Complete multiple qcs successfully
4367 * @ap: port in question
4368 * @qc_active: new qc_active mask
4369 * @finish_qc: LLDD callback invoked before completing a qc
4370 *
4371 * Complete in-flight commands. This functions is meant to be
4372 * called from low-level driver's interrupt routine to complete
4373 * requests normally. ap->qc_active and @qc_active is compared
4374 * and commands are completed accordingly.
4375 *
4376 * LOCKING:
4377 * spin_lock_irqsave(host_set lock)
4378 *
4379 * RETURNS:
4380 * Number of completed commands on success, -errno otherwise.
4381 */
4382int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
4383 void (*finish_qc)(struct ata_queued_cmd *))
4384{
4385 int nr_done = 0;
4386 u32 done_mask;
4387 int i;
4388
4389 done_mask = ap->qc_active ^ qc_active;
4390
4391 if (unlikely(done_mask & qc_active)) {
4392 ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
4393 "(%08x->%08x)\n", ap->qc_active, qc_active);
4394 return -EINVAL;
4395 }
4396
4397 for (i = 0; i < ATA_MAX_QUEUE; i++) {
4398 struct ata_queued_cmd *qc;
4399
4400 if (!(done_mask & (1 << i)))
4401 continue;
4402
4403 if ((qc = ata_qc_from_tag(ap, i))) {
4404 if (finish_qc)
4405 finish_qc(qc);
4406 ata_qc_complete(qc);
4407 nr_done++;
4408 }
4409 }
4410
4411 return nr_done;
4412}
4413
4352static inline int ata_should_dma_map(struct ata_queued_cmd *qc) 4414static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
4353{ 4415{
4354 struct ata_port *ap = qc->ap; 4416 struct ata_port *ap = qc->ap;
@@ -4388,8 +4450,22 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
4388{ 4450{
4389 struct ata_port *ap = qc->ap; 4451 struct ata_port *ap = qc->ap;
4390 4452
4391 qc->ap->active_tag = qc->tag; 4453 /* Make sure only one non-NCQ command is outstanding. The
4454 * check is skipped for old EH because it reuses active qc to
4455 * request ATAPI sense.
4456 */
4457 WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
4458
4459 if (qc->tf.protocol == ATA_PROT_NCQ) {
4460 WARN_ON(ap->sactive & (1 << qc->tag));
4461 ap->sactive |= 1 << qc->tag;
4462 } else {
4463 WARN_ON(ap->sactive);
4464 ap->active_tag = qc->tag;
4465 }
4466
4392 qc->flags |= ATA_QCFLAG_ACTIVE; 4467 qc->flags |= ATA_QCFLAG_ACTIVE;
4468 ap->qc_active |= 1 << qc->tag;
4393 4469
4394 if (ata_should_dma_map(qc)) { 4470 if (ata_should_dma_map(qc)) {
4395 if (qc->flags & ATA_QCFLAG_SG) { 4471 if (qc->flags & ATA_QCFLAG_SG) {
@@ -5549,6 +5625,7 @@ EXPORT_SYMBOL_GPL(ata_host_set_remove);
5549EXPORT_SYMBOL_GPL(ata_sg_init); 5625EXPORT_SYMBOL_GPL(ata_sg_init);
5550EXPORT_SYMBOL_GPL(ata_sg_init_one); 5626EXPORT_SYMBOL_GPL(ata_sg_init_one);
5551EXPORT_SYMBOL_GPL(ata_qc_complete); 5627EXPORT_SYMBOL_GPL(ata_qc_complete);
5628EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
5552EXPORT_SYMBOL_GPL(ata_qc_issue_prot); 5629EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
5553EXPORT_SYMBOL_GPL(ata_tf_load); 5630EXPORT_SYMBOL_GPL(ata_tf_load);
5554EXPORT_SYMBOL_GPL(ata_tf_read); 5631EXPORT_SYMBOL_GPL(ata_tf_read);