libata: use blk taging
authorShaohua Li <shli@fb.com>
Fri, 16 Jan 2015 01:32:27 +0000 (17:32 -0800)
committerJens Axboe <axboe@fb.com>
Fri, 23 Jan 2015 21:19:04 +0000 (14:19 -0700)
libata uses its own tag management which is duplication and the
implementation is poor. And if we switch to blk-mq, tag is build-in.
It's time to switch to generic taging.

The SAS driver has its own tag management, and looks we can't directly
map the host controler tag to SATA tag. So I just bypassed the SAS case.

I changed the code/variable name for the tag management of libata to
make it self contained. Only sas will use it. Later if libsas implements
its tag management, the tag management code in libata can be deleted
easily.

Cc: Jens Axboe <axboe@fb.com>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
include/linux/libata.h

index 5c84fb5c33720d5b83ba52d407656445a1dbe0ae..695d33df3df58bc42aa4a6605e017fbb1fcf1309 100644 (file)
@@ -1525,6 +1525,15 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
        complete(waiting);
 }
 
+static bool ata_valid_internal_tag(struct ata_port *ap, struct ata_device *dev,
+                                  unsigned int tag)
+{
+       if (!ap->scsi_host)
+               return !test_and_set_bit(tag, &ap->sas_tag_allocated);
+       return !dev->sdev ||
+              !blk_queue_find_tag(dev->sdev->request_queue, tag);
+}
+
 /**
  *     ata_exec_internal_sg - execute libata internal command
  *     @dev: Device to which the command is sent
@@ -1585,8 +1594,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        else
                tag = 0;
 
-       if (test_and_set_bit(tag, &ap->qc_allocated))
-               BUG();
+       BUG_ON(!ata_valid_internal_tag(ap, dev, tag));
        qc = __ata_qc_from_tag(ap, tag);
 
        qc->tag = tag;
@@ -4737,27 +4745,23 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
  *     None.
  */
 
-static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
+static struct ata_queued_cmd *sas_ata_qc_new(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc = NULL;
        unsigned int max_queue = ap->host->n_tags;
        unsigned int i, tag;
 
-       /* no command while frozen */
-       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
-               return NULL;
-
-       for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) {
+       for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) {
                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->qc_allocated)) {
+               if (!test_and_set_bit(tag, &ap->sas_tag_allocated)) {
                        qc = __ata_qc_from_tag(ap, tag);
                        qc->tag = tag;
-                       ap->last_tag = tag;
+                       ap->sas_last_tag = tag;
                        break;
                }
        }
@@ -4765,6 +4769,24 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
        return qc;
 }
 
+static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap, int blktag)
+{
+       struct ata_queued_cmd *qc;
+
+       /* no command while frozen */
+       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+               return NULL;
+
+       /* SATA will directly use block tag. libsas need its own tag management */
+       if (ap->scsi_host) {
+               qc = __ata_qc_from_tag(ap, blktag);
+               qc->tag = blktag;
+               return qc;
+       }
+
+       return sas_ata_qc_new(ap);
+}
+
 /**
  *     ata_qc_new_init - Request an available ATA command, and initialize it
  *     @dev: Device from whom we request an available command structure
@@ -4773,12 +4795,12 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
  *     None.
  */
 
-struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int blktag)
 {
        struct ata_port *ap = dev->link->ap;
        struct ata_queued_cmd *qc;
 
-       qc = ata_qc_new(ap);
+       qc = ata_qc_new(ap, blktag);
        if (qc) {
                qc->scsicmd = NULL;
                qc->ap = ap;
@@ -4800,6 +4822,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
+static void sas_ata_qc_free(unsigned int tag, struct ata_port *ap)
+{
+       if (!ap->scsi_host)
+               clear_bit(tag, &ap->sas_tag_allocated);
+}
+
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap;
@@ -4812,7 +4840,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
        tag = qc->tag;
        if (likely(ata_tag_valid(tag))) {
                qc->tag = ATA_TAG_POISON;
-               clear_bit(tag, &ap->qc_allocated);
+               sas_ata_qc_free(tag, ap);
        }
 }
 
index e364e86e84d75b7d4ec8f18bba0eb4fc2b21a43c..94339c2aed1bcf159de4d66f4ed325852e136b1e 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;
@@ -3666,6 +3666,8 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                 */
                shost->max_host_blocked = 1;
 
+               scsi_init_shared_tag_map(shost, host->n_tags);
+
                rc = scsi_add_host_with_dma(ap->scsi_host,
                                                &ap->tdev, ap->host->dev);
                if (rc)
index 5f4e0cca56ec5fdc2cf539e3052bd9e2d51bca76..40405135bbb6a30c9e038a0625bc584cc018a1de 100644 (file)
@@ -63,7 +63,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
 extern void ata_force_cbl(struct ata_port *ap);
 extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
 extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
                           u64 block, u32 n_block, unsigned int tf_flags,
                           unsigned int tag);
index 2d182413b1db5bbf3b9afa2c15dd674d2b817b4e..f23454762717fa8b17434ce1c814b69d93ce2e39 100644 (file)
@@ -821,10 +821,10 @@ struct ata_port {
        unsigned int            cbl;    /* cable type; ATA_CBL_xxx */
 
        struct ata_queued_cmd   qcmd[ATA_MAX_QUEUE];
-       unsigned long           qc_allocated;
+       unsigned long           sas_tag_allocated; /* for sas tag allocation only */
        unsigned int            qc_active;
        int                     nr_active_links; /* #links with active qcs */
-       unsigned int            last_tag;       /* track next tag hw expects */
+       unsigned int            sas_last_tag;   /* track next tag hw expects */
 
        struct ata_link         link;           /* host default link */
        struct ata_link         *slave_link;    /* see ata_slave_link_init() */
@@ -1344,6 +1344,7 @@ extern struct device_attribute *ata_common_sdev_attrs[];
        .ioctl                  = ata_scsi_ioctl,               \
        .queuecommand           = ata_scsi_queuecmd,            \
        .can_queue              = ATA_DEF_QUEUE,                \
+       .tag_alloc_policy       = BLK_TAG_ALLOC_RR,             \
        .this_id                = ATA_SHT_THIS_ID,              \
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,          \
        .emulated               = ATA_SHT_EMULATED,             \