Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/include/scsi/scsi_tcq.h
10820 views
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
177