Merge tag 'pinctrl-v3.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[cascardo/linux.git] / include / scsi / scsi_tcq.h
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 int scsi_change_queue_type(struct scsi_device *sdev, int tag_type);
20
21 /**
22  * scsi_get_tag_type - get the type of tag the device supports
23  * @sdev:       the scsi device
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->simple_tags)
30                 return MSG_SIMPLE_TAG;
31         return 0;
32 }
33
34 static inline void scsi_set_tag_type(struct scsi_device *sdev, int tag)
35 {
36         switch (tag) {
37         case MSG_ORDERED_TAG:
38         case MSG_SIMPLE_TAG:
39                 sdev->simple_tags = 1;
40                 break;
41         case 0:
42                 /* fall through */
43         default:
44                 sdev->simple_tags = 0;
45                 break;
46         }
47 }
48
49 static inline struct scsi_cmnd *scsi_mq_find_tag(struct Scsi_Host *shost,
50                                                  int unique_tag)
51 {
52         u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag);
53         struct request *req = NULL;
54
55         if (hwq < shost->tag_set.nr_hw_queues)
56                 req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
57                                        blk_mq_unique_tag_to_tag(unique_tag));
58         return req ? (struct scsi_cmnd *)req->special : NULL;
59 }
60
61 /**
62  * scsi_find_tag - find a tagged command by device
63  * @SDpnt:      pointer to the ScSI device
64  * @tag:        tag generated by blk_mq_unique_tag()
65  *
66  * Notes:
67  *      Only works with tags allocated by the generic blk layer.
68  **/
69 static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
70 {
71         struct request *req;
72
73         if (tag != SCSI_NO_TAG) {
74                 if (shost_use_blk_mq(sdev->host))
75                         return scsi_mq_find_tag(sdev->host, tag);
76
77                 req = blk_queue_find_tag(sdev->request_queue, tag);
78                 return req ? (struct scsi_cmnd *)req->special : NULL;
79         }
80
81         /* single command, look in space */
82         return sdev->current_cmnd;
83 }
84
85
86 /**
87  * scsi_init_shared_tag_map - create a shared tag map
88  * @shost:      the host to share the tag map among all devices
89  * @depth:      the total depth of the map
90  */
91 static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
92 {
93         /*
94          * We always have a shared tag map around when using blk-mq.
95          */
96         if (shost_use_blk_mq(shost))
97                 return 0;
98
99         /*
100          * If the shared tag map isn't already initialized, do it now.
101          * This saves callers from having to check ->bqt when setting up
102          * devices on the shared host (for libata)
103          */
104         if (!shost->bqt) {
105                 shost->bqt = blk_init_tags(depth);
106                 if (!shost->bqt)
107                         return -ENOMEM;
108         }
109
110         return 0;
111 }
112
113 /**
114  * scsi_host_find_tag - find the tagged command by host
115  * @shost:      pointer to scsi_host
116  * @tag:        tag generated by blk_mq_unique_tag()
117  *
118  * Notes:
119  *      Only works with tags allocated by the generic blk layer.
120  **/
121 static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost,
122                                                 int tag)
123 {
124         struct request *req;
125
126         if (tag != SCSI_NO_TAG) {
127                 if (shost_use_blk_mq(shost))
128                         return scsi_mq_find_tag(shost, tag);
129                 req = blk_map_queue_find_tag(shost->bqt, tag);
130                 return req ? (struct scsi_cmnd *)req->special : NULL;
131         }
132         return NULL;
133 }
134
135 #endif /* CONFIG_BLOCK */
136 #endif /* _SCSI_SCSI_TCQ_H */