Merge branch 'for-3.20/drivers' of git://git.kernel.dk/linux-block
[linux-drm-fsl-dcu.git] / drivers / ata / libata-scsi.c
index 6abd17a85b1369d4515302090c6eb57a2d1d088b..b061ba2c31d8f51408a15f2e019a3c328e882815 100644 (file)
@@ -756,7 +756,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
 {
        struct ata_queued_cmd *qc;
 
-       qc = ata_qc_new_init(dev);
+       qc = ata_qc_new_init(dev, cmd->request->tag);
        if (qc) {
                qc->scsicmd = cmd;
                qc->scsidone = cmd->scsi_done;
@@ -1995,8 +1995,8 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
 
        VPRINTK("ENTER\n");
 
-       /* set scsi removeable (RMB) bit per ata bit */
-       if (ata_id_removeable(args->id))
+       /* set scsi removable (RMB) bit per ata bit */
+       if (ata_id_removable(args->id))
                hdr[1] |= (1 << 7);
 
        if (args->dev->class == ATA_DEV_ZAC) {
@@ -3668,6 +3668,9 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                 */
                shost->max_host_blocked = 1;
 
+               if (scsi_init_shared_tag_map(shost, host->n_tags))
+                       goto err_add;
+
                rc = scsi_add_host_with_dma(ap->scsi_host,
                                                &ap->tdev, ap->host->dev);
                if (rc)
@@ -4230,3 +4233,31 @@ int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap)
        return rc;
 }
 EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
+
+int ata_sas_allocate_tag(struct ata_port *ap)
+{
+       unsigned int max_queue = ap->host->n_tags;
+       unsigned int i, tag;
+
+       for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) {
+               if (ap->flags & ATA_FLAG_LOWTAG)
+                       tag = 1;
+               else
+                       tag = tag < max_queue ? tag : 0;
+
+               /* the last tag is reserved for internal command. */
+               if (tag == ATA_TAG_INTERNAL)
+                       continue;
+
+               if (!test_and_set_bit(tag, &ap->sas_tag_allocated)) {
+                       ap->sas_last_tag = tag;
+                       return tag;
+               }
+       }
+       return -1;
+}
+
+void ata_sas_free_tag(unsigned int tag, struct ata_port *ap)
+{
+       clear_bit(tag, &ap->sas_tag_allocated);
+}