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 (!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 **/ 81 static 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 **/ 98 static 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 **/ 119 static 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 */ 138 static 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 **/ 162 static 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