diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.h')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 8cca54631e1..138fba577b4 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h | |||
@@ -11,6 +11,14 @@ | |||
11 | 11 | ||
12 | #include <asm/qdio.h> | 12 | #include <asm/qdio.h> |
13 | 13 | ||
14 | #define ZFCP_QDIO_SBALE_LEN PAGE_SIZE | ||
15 | |||
16 | /* DMQ bug workaround: don't use last SBALE */ | ||
17 | #define ZFCP_QDIO_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1) | ||
18 | |||
19 | /* index of last SBALE (with respect to DMQ bug workaround) */ | ||
20 | #define ZFCP_QDIO_LAST_SBALE_PER_SBAL (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1) | ||
21 | |||
14 | /** | 22 | /** |
15 | * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count | 23 | * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count |
16 | * @sbal: qdio buffers | 24 | * @sbal: qdio buffers |
@@ -49,6 +57,7 @@ struct zfcp_qdio { | |||
49 | 57 | ||
50 | /** | 58 | /** |
51 | * struct zfcp_qdio_req - qdio queue related values for a request | 59 | * struct zfcp_qdio_req - qdio queue related values for a request |
60 | * @sbtype: sbal type flags for sbale 0 | ||
52 | * @sbal_number: number of free sbals | 61 | * @sbal_number: number of free sbals |
53 | * @sbal_first: first sbal for this request | 62 | * @sbal_first: first sbal for this request |
54 | * @sbal_last: last sbal for this request | 63 | * @sbal_last: last sbal for this request |
@@ -59,6 +68,7 @@ struct zfcp_qdio { | |||
59 | * @qdio_inb_usage: usage of inbound queue | 68 | * @qdio_inb_usage: usage of inbound queue |
60 | */ | 69 | */ |
61 | struct zfcp_qdio_req { | 70 | struct zfcp_qdio_req { |
71 | u32 sbtype; | ||
62 | u8 sbal_number; | 72 | u8 sbal_number; |
63 | u8 sbal_first; | 73 | u8 sbal_first; |
64 | u8 sbal_last; | 74 | u8 sbal_last; |
@@ -106,4 +116,98 @@ zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
106 | q_req->sbale_curr); | 116 | q_req->sbale_curr); |
107 | } | 117 | } |
108 | 118 | ||
119 | /** | ||
120 | * zfcp_qdio_req_init - initialize qdio request | ||
121 | * @qdio: request queue where to start putting the request | ||
122 | * @q_req: the qdio request to start | ||
123 | * @req_id: The request id | ||
124 | * @sbtype: type flags to set for all sbals | ||
125 | * @data: First data block | ||
126 | * @len: Length of first data block | ||
127 | * | ||
128 | * This is the start of putting the request into the queue, the last | ||
129 | * step is passing the request to zfcp_qdio_send. The request queue | ||
130 | * lock must be held during the whole process from init to send. | ||
131 | */ | ||
132 | static inline | ||
133 | void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | ||
134 | unsigned long req_id, u32 sbtype, void *data, u32 len) | ||
135 | { | ||
136 | struct qdio_buffer_element *sbale; | ||
137 | |||
138 | q_req->sbal_first = q_req->sbal_last = qdio->req_q.first; | ||
139 | q_req->sbal_number = 1; | ||
140 | q_req->sbtype = sbtype; | ||
141 | |||
142 | sbale = zfcp_qdio_sbale_req(qdio, q_req); | ||
143 | sbale->addr = (void *) req_id; | ||
144 | sbale->flags |= SBAL_FLAGS0_COMMAND; | ||
145 | sbale->flags |= sbtype; | ||
146 | |||
147 | q_req->sbale_curr = 1; | ||
148 | sbale++; | ||
149 | sbale->addr = data; | ||
150 | if (likely(data)) | ||
151 | sbale->length = len; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * zfcp_qdio_fill_next - Fill next sbale, only for single sbal requests | ||
156 | * @qdio: pointer to struct zfcp_qdio | ||
157 | * @q_req: pointer to struct zfcp_queue_req | ||
158 | * | ||
159 | * This is only required for single sbal requests, calling it when | ||
160 | * wrapping around to the next sbal is a bug. | ||
161 | */ | ||
162 | static inline | ||
163 | void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | ||
164 | void *data, u32 len) | ||
165 | { | ||
166 | struct qdio_buffer_element *sbale; | ||
167 | |||
168 | BUG_ON(q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL); | ||
169 | q_req->sbale_curr++; | ||
170 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | ||
171 | sbale->addr = data; | ||
172 | sbale->length = len; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * zfcp_qdio_set_sbale_last - set last entry flag in current sbale | ||
177 | * @qdio: pointer to struct zfcp_qdio | ||
178 | * @q_req: pointer to struct zfcp_queue_req | ||
179 | */ | ||
180 | static inline | ||
181 | void zfcp_qdio_set_sbale_last(struct zfcp_qdio *qdio, | ||
182 | struct zfcp_qdio_req *q_req) | ||
183 | { | ||
184 | struct qdio_buffer_element *sbale; | ||
185 | |||
186 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | ||
187 | sbale->flags |= SBAL_FLAGS_LAST_ENTRY; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * zfcp_qdio_sg_one_sbal - check if one sbale is enough for sg data | ||
192 | * @sg: The scatterlist where to check the data size | ||
193 | * | ||
194 | * Returns: 1 when one sbale is enough for the data in the scatterlist, | ||
195 | * 0 if not. | ||
196 | */ | ||
197 | static inline | ||
198 | int zfcp_qdio_sg_one_sbale(struct scatterlist *sg) | ||
199 | { | ||
200 | return sg_is_last(sg) && sg->length <= ZFCP_QDIO_SBALE_LEN; | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * zfcp_qdio_skip_to_last_sbale - skip to last sbale in sbal | ||
205 | * @q_req: The current zfcp_qdio_req | ||
206 | */ | ||
207 | static inline | ||
208 | void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio_req *q_req) | ||
209 | { | ||
210 | q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL; | ||
211 | } | ||
212 | |||
109 | #endif /* ZFCP_QDIO_H */ | 213 | #endif /* ZFCP_QDIO_H */ |