linux/include/scsi/scsi_tcq.h
<<
>>
Prefs
   1#ifndef _SCSI_SCSI_TCQ_H
   2#define _SCSI_SCSI_TCQ_H
   3
   4#include <linux/blkdev.h>
   5#include <scsi/scsi_cmnd.h>
   6#include <scsi/scsi_device.h>
   7#include <scsi/scsi_host.h>
   8
   9#define MSG_SIMPLE_TAG  0x20
  10#define MSG_HEAD_TAG    0x21
  11#define MSG_ORDERED_TAG 0x22
  12#define MSG_ACA_TAG     0x24    /* unsupported */
  13
  14#define SCSI_NO_TAG     (-1)    /* identify no tag in use */
  15
  16
  17#ifdef CONFIG_BLOCK
  18
  19/**
  20 * scsi_get_tag_type - get the type of tag the device supports
  21 * @sdev:       the scsi device
  22 *
  23 * Notes:
  24 *      If the drive only supports simple tags, returns MSG_SIMPLE_TAG
  25 *      if it supports all tag types, returns MSG_ORDERED_TAG.
  26 */
  27static inline int scsi_get_tag_type(struct scsi_device *sdev)
  28{
  29        if (!sdev->tagged_supported)
  30                return 0;
  31        if (sdev->ordered_tags)
  32                return MSG_ORDERED_TAG;
  33        if (sdev->simple_tags)
  34                return MSG_SIMPLE_TAG;
  35        return 0;
  36}
  37
  38static inline void scsi_set_tag_type(struct scsi_device *sdev, int tag)
  39{
  40        switch (tag) {
  41        case MSG_ORDERED_TAG:
  42                sdev->ordered_tags = 1;
  43                /* fall through */
  44        case MSG_SIMPLE_TAG:
  45                sdev->simple_tags = 1;
  46                break;
  47        case 0:
  48                /* fall through */
  49        default:
  50                sdev->ordered_tags = 0;
  51                sdev->simple_tags = 0;
  52                break;
  53        }
  54}
  55/**
  56 * scsi_activate_tcq - turn on tag command queueing
  57 * @SDpnt:      device to turn on TCQ for
  58 * @depth:      queue depth
  59 *
  60 * Notes:
  61 *      Eventually, I hope depth would be the maximum depth
  62 *      the device could cope with and the real queue depth
  63 *      would be adjustable from 0 to depth.
  64 **/
  65static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth)
  66{
  67        if (!sdev->tagged_supported)
  68                return;
  69
  70        if (!blk_queue_tagged(sdev->request_queue))
  71                blk_queue_init_tags(sdev->request_queue, depth,
  72                                    sdev->host->bqt);
  73
  74        scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
  75}
  76
  77/**
  78 * scsi_deactivate_tcq - turn off tag command queueing
  79 * @SDpnt:      device to turn off TCQ for
  80 **/
  81static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
  82{
  83        if (blk_queue_tagged(sdev->request_queue))
  84                blk_queue_free_tags(sdev->request_queue);
  85        scsi_adjust_queue_depth(sdev, 0, depth);
  86}
  87
  88/**
  89 * scsi_populate_tag_msg - place a tag message in a buffer
  90 * @SCpnt:      pointer to the Scsi_Cmnd for the tag
  91 * @msg:        pointer to the area to place the tag
  92 *
  93 * Notes:
  94 *      designed to create the correct type of tag message for the 
  95 *      particular request.  Returns the size of the tag message.
  96 *      May return 0 if TCQ is disabled for this device.
  97 **/
  98static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
  99{
 100        struct request *req = cmd->request;
 101
 102        if (blk_rq_tagged(req)) {
 103                *msg++ = MSG_SIMPLE_TAG;
 104                *msg++ = req->tag;
 105                return 2;
 106        }
 107
 108        return 0;
 109}
 110
 111/**
 112 * scsi_find_tag - find a tagged command by device
 113 * @SDpnt:      pointer to the ScSI device
 114 * @tag:        the tag number
 115 *
 116 * Notes:
 117 *      Only works with tags allocated by the generic blk layer.
 118 **/
 119static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
 120{
 121
 122        struct request *req;
 123
 124        if (tag != SCSI_NO_TAG) {
 125                req = blk_queue_find_tag(sdev->request_queue, tag);
 126                return req ? (struct scsi_cmnd *)req->special : NULL;
 127        }
 128
 129        /* single command, look in space */
 130        return sdev->current_cmnd;
 131}
 132
 133/**
 134 * scsi_init_shared_tag_map - create a shared tag map
 135 * @shost:      the host to share the tag map among all devices
 136 * @depth:      the total depth of the map
 137 */
 138static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
 139{
 140        /*
 141         * If the shared tag map isn't already initialized, do it now.
 142         * This saves callers from having to check ->bqt when setting up
 143         * devices on the shared host (for libata)
 144         */
 145        if (!shost->bqt) {
 146                shost->bqt = blk_init_tags(depth);
 147                if (!shost->bqt)
 148                        return -ENOMEM;
 149        }
 150
 151        return 0;
 152}
 153
 154/**
 155 * scsi_host_find_tag - find the tagged command by host
 156 * @shost:      pointer to scsi_host
 157 * @tag:        tag of the scsi_cmnd
 158 *
 159 * Notes:
 160 *      Only works with tags allocated by the generic blk layer.
 161 **/
 162static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost,
 163                                                int tag)
 164{
 165        struct request *req;
 166
 167        if (tag != SCSI_NO_TAG) {
 168                req = blk_map_queue_find_tag(shost->bqt, tag);
 169                return req ? (struct scsi_cmnd *)req->special : NULL;
 170        }
 171        return NULL;
 172}
 173
 174#endif /* CONFIG_BLOCK */
 175#endif /* _SCSI_SCSI_TCQ_H */
 176