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 8 9 #define MSG_SIMPLE_TAG 0x20 10 #define MSG_HEAD_TAG 0x21 11 #define MSG_ORDERED_TAG 0x22 12 13 #define SCSI_NO_TAG (-1) /* identify no tag in use */ 14 15 16 17 /** 18 * scsi_get_tag_type - get the type of tag the device supports 19 * @sdev: the scsi device 20 * 21 * Notes: 22 * If the drive only supports simple tags, returns MSG_SIMPLE_TAG 23 * if it supports all tag types, returns MSG_ORDERED_TAG. 24 */ 25 static inline int scsi_get_tag_type(struct scsi_device *sdev) 26 { 27 if (!sdev->tagged_supported) 28 return 0; 29 if (sdev->ordered_tags) 30 return MSG_ORDERED_TAG; 31 if (sdev->simple_tags) 32 return MSG_SIMPLE_TAG; 33 return 0; 34 } 35 36 static inline void scsi_set_tag_type(struct scsi_device *sdev, int tag) 37 { 38 switch (tag) { 39 case MSG_ORDERED_TAG: 40 sdev->ordered_tags = 1; 41 /* fall through */ 42 case MSG_SIMPLE_TAG: 43 sdev->simple_tags = 1; 44 break; 45 case 0: 46 /* fall through */ 47 default: 48 sdev->ordered_tags = 0; 49 sdev->simple_tags = 0; 50 break; 51 } 52 } 53 /** 54 * scsi_activate_tcq - turn on tag command queueing 55 * @SDpnt: device to turn on TCQ for 56 * @depth: queue depth 57 * 58 * Notes: 59 * Eventually, I hope depth would be the maximum depth 60 * the device could cope with and the real queue depth 61 * would be adjustable from 0 to depth. 62 **/ 63 static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth) 64 { 65 if (!sdev->tagged_supported) 66 return; 67 68 if (!blk_queue_tagged(sdev->request_queue)) 69 blk_queue_init_tags(sdev->request_queue, depth, NULL); 70 71 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); 72 } 73 74 /** 75 * scsi_deactivate_tcq - turn off tag command queueing 76 * @SDpnt: device to turn off TCQ for 77 **/ 78 static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) 79 { 80 if (blk_queue_tagged(sdev->request_queue)) 81 blk_queue_free_tags(sdev->request_queue); 82 scsi_adjust_queue_depth(sdev, 0, depth); 83 } 84 85 /** 86 * scsi_populate_tag_msg - place a tag message in a buffer 87 * @SCpnt: pointer to the Scsi_Cmnd for the tag 88 * @msg: pointer to the area to place the tag 89 * 90 * Notes: 91 * designed to create the correct type of tag message for the 92 * particular request. Returns the size of the tag message. 93 * May return 0 if TCQ is disabled for this device. 94 **/ 95 static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) 96 { 97 struct request *req = cmd->request; 98 struct scsi_device *sdev = cmd->device; 99 100 if (blk_rq_tagged(req)) { 101 if (sdev->ordered_tags && req->flags & REQ_HARDBARRIER) 102 *msg++ = MSG_ORDERED_TAG; 103 else 104 *msg++ = MSG_SIMPLE_TAG; 105 *msg++ = req->tag; 106 return 2; 107 } 108 109 return 0; 110 } 111 112 /** 113 * scsi_find_tag - find a tagged command by device 114 * @SDpnt: pointer to the ScSI device 115 * @tag: the tag number 116 * 117 * Notes: 118 * Only works with tags allocated by the generic blk layer. 119 **/ 120 static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) 121 { 122 123 struct request *req; 124 125 if (tag != SCSI_NO_TAG) { 126 req = blk_queue_find_tag(sdev->request_queue, tag); 127 return req ? (struct scsi_cmnd *)req->special : NULL; 128 } 129 130 /* single command, look in space */ 131 return sdev->current_cmnd; 132 } 133 134 #endif /* _SCSI_SCSI_TCQ_H */ 135