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 */ 27 static 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 38 static 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 **/ 65 static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth) 66 { 67 if (!sdev->tagged_supported) 68 return; 69 70 if (!shost_use_blk_mq(sdev->host) && 71 blk_queue_tagged(sdev->request_queue)) 72 blk_queue_init_tags(sdev->request_queue, depth, 73 sdev->host->bqt); 74 75 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); 76 } 77 78 /** 79 * scsi_deactivate_tcq - turn off tag command queueing 80 * @SDpnt: device to turn off TCQ for 81 **/ 82 static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) 83 { 84 if (!shost_use_blk_mq(sdev->host) && 85 blk_queue_tagged(sdev->request_queue)) 86 blk_queue_free_tags(sdev->request_queue); 87 scsi_adjust_queue_depth(sdev, 0, depth); 88 } 89 90 /** 91 * scsi_populate_tag_msg - place a tag message in a buffer 92 * @SCpnt: pointer to the Scsi_Cmnd for the tag 93 * @msg: pointer to the area to place the tag 94 * 95 * Notes: 96 * designed to create the correct type of tag message for the 97 * particular request. Returns the size of the tag message. 98 * May return 0 if TCQ is disabled for this device. 99 **/ 100 static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) 101 { 102 struct request *req = cmd->request; 103 104 if (blk_rq_tagged(req)) { 105 *msg++ = MSG_SIMPLE_TAG; 106 *msg++ = req->tag; 107 return 2; 108 } 109 110 return 0; 111 } 112 113 static inline struct scsi_cmnd *scsi_mq_find_tag(struct Scsi_Host *shost, 114 unsigned int hw_ctx, int tag) 115 { 116 struct request *req; 117 118 req = blk_mq_tag_to_rq(shost->tag_set.tags[hw_ctx], tag); 119 return req ? (struct scsi_cmnd *)req->special : NULL; 120 } 121 122 /** 123 * scsi_find_tag - find a tagged command by device 124 * @SDpnt: pointer to the ScSI device 125 * @tag: the tag number 126 * 127 * Notes: 128 * Only works with tags allocated by the generic blk layer. 129 **/ 130 static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) 131 { 132 struct request *req; 133 134 if (tag != SCSI_NO_TAG) { 135 if (shost_use_blk_mq(sdev->host)) 136 return scsi_mq_find_tag(sdev->host, 0, tag); 137 138 req = blk_queue_find_tag(sdev->request_queue, tag); 139 return req ? (struct scsi_cmnd *)req->special : NULL; 140 } 141 142 /* single command, look in space */ 143 return sdev->current_cmnd; 144 } 145 146 147 /** 148 * scsi_init_shared_tag_map - create a shared tag map 149 * @shost: the host to share the tag map among all devices 150 * @depth: the total depth of the map 151 */ 152 static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth) 153 { 154 /* 155 * We always have a shared tag map around when using blk-mq. 156 */ 157 if (shost_use_blk_mq(shost)) 158 return 0; 159 160 /* 161 * If the shared tag map isn't already initialized, do it now. 162 * This saves callers from having to check ->bqt when setting up 163 * devices on the shared host (for libata) 164 */ 165 if (!shost->bqt) { 166 shost->bqt = blk_init_tags(depth); 167 if (!shost->bqt) 168 return -ENOMEM; 169 } 170 171 return 0; 172 } 173 174 /** 175 * scsi_host_find_tag - find the tagged command by host 176 * @shost: pointer to scsi_host 177 * @tag: tag of the scsi_cmnd 178 * 179 * Notes: 180 * Only works with tags allocated by the generic blk layer. 181 **/ 182 static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost, 183 int tag) 184 { 185 struct request *req; 186 187 if (tag != SCSI_NO_TAG) { 188 if (shost_use_blk_mq(shost)) 189 return scsi_mq_find_tag(shost, 0, tag); 190 req = blk_map_queue_find_tag(shost->bqt, tag); 191 return req ? (struct scsi_cmnd *)req->special : NULL; 192 } 193 return NULL; 194 } 195 196 #endif /* CONFIG_BLOCK */ 197 #endif /* _SCSI_SCSI_TCQ_H */ 198