]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/ata/sata_mv.c
[SCSI] libata: fix eh locking
[linux-2.6.git] / drivers / ata / sata_mv.c
index 81982594a014b603aa2ebd8b5944ed13049c929b..bf74a36d3cc3b4904363e97d4656c9e48fbe1a6f 100644 (file)
@@ -2284,7 +2284,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
        }
 
        if (qc->tf.flags & ATA_TFLAG_POLLING)
-               ata_sff_queue_pio_task(ap, 0);
+               ata_sff_queue_pio_task(link, 0);
        return 0;
 }
 
@@ -2743,18 +2743,11 @@ static void mv_err_intr(struct ata_port *ap)
        }
 }
 
-static void mv_process_crpb_response(struct ata_port *ap,
+static bool mv_process_crpb_response(struct ata_port *ap,
                struct mv_crpb *response, unsigned int tag, int ncq_enabled)
 {
        u8 ata_status;
        u16 edma_status = le16_to_cpu(response->flags);
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
-
-       if (unlikely(!qc)) {
-               ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
-                               __func__, tag);
-               return;
-       }
 
        /*
         * edma_status from a response queue entry:
@@ -2768,13 +2761,14 @@ static void mv_process_crpb_response(struct ata_port *ap,
                         * Error will be seen/handled by
                         * mv_err_intr().  So do nothing at all here.
                         */
-                       return;
+                       return false;
                }
        }
        ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
        if (!ac_err_mask(ata_status))
-               ata_qc_complete(qc);
+               return true;
        /* else: leave it for mv_err_intr() */
+       return false;
 }
 
 static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
@@ -2783,6 +2777,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
        struct mv_host_priv *hpriv = ap->host->private_data;
        u32 in_index;
        bool work_done = false;
+       u32 done_mask = 0;
        int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
 
        /* Get the hardware queue position index */
@@ -2803,15 +2798,19 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
                        /* Gen II/IIE: get command tag from CRPB entry */
                        tag = le16_to_cpu(response->id) & 0x1f;
                }
-               mv_process_crpb_response(ap, response, tag, ncq_enabled);
+               if (mv_process_crpb_response(ap, response, tag, ncq_enabled))
+                       done_mask |= 1 << tag;
                work_done = true;
        }
 
-       /* Update the software queue position index in hardware */
-       if (work_done)
+       if (work_done) {
+               ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+
+               /* Update the software queue position index in hardware */
                writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
                         (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
                         port_mmio + EDMA_RSP_Q_OUT_PTR);
+       }
 }
 
 static void mv_port_intr(struct ata_port *ap, u32 port_cause)