diff options
Diffstat (limited to 'drivers/s390/cio/qdio.h')
-rw-r--r-- | drivers/s390/cio/qdio.h | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 44f2f6a97f33..48aa0647432b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -208,18 +208,27 @@ struct qdio_dev_perf_stat { | |||
208 | unsigned int eqbs_partial; | 208 | unsigned int eqbs_partial; |
209 | unsigned int sqbs; | 209 | unsigned int sqbs; |
210 | unsigned int sqbs_partial; | 210 | unsigned int sqbs_partial; |
211 | } ____cacheline_aligned; | ||
212 | |||
213 | struct qdio_queue_perf_stat { | ||
214 | /* | ||
215 | * Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. | ||
216 | * Since max. 127 SBALs are scanned reuse entry for 128 as queue full | ||
217 | * aka 127 SBALs found. | ||
218 | */ | ||
219 | unsigned int nr_sbals[8]; | ||
220 | unsigned int nr_sbal_error; | ||
221 | unsigned int nr_sbal_nop; | ||
222 | unsigned int nr_sbal_total; | ||
211 | }; | 223 | }; |
212 | 224 | ||
213 | struct qdio_input_q { | 225 | struct qdio_input_q { |
214 | /* input buffer acknowledgement flag */ | 226 | /* input buffer acknowledgement flag */ |
215 | int polling; | 227 | int polling; |
216 | |||
217 | /* first ACK'ed buffer */ | 228 | /* first ACK'ed buffer */ |
218 | int ack_start; | 229 | int ack_start; |
219 | |||
220 | /* how much sbals are acknowledged with qebsm */ | 230 | /* how much sbals are acknowledged with qebsm */ |
221 | int ack_count; | 231 | int ack_count; |
222 | |||
223 | /* last time of noticing incoming data */ | 232 | /* last time of noticing incoming data */ |
224 | u64 timestamp; | 233 | u64 timestamp; |
225 | }; | 234 | }; |
@@ -227,40 +236,27 @@ struct qdio_input_q { | |||
227 | struct qdio_output_q { | 236 | struct qdio_output_q { |
228 | /* PCIs are enabled for the queue */ | 237 | /* PCIs are enabled for the queue */ |
229 | int pci_out_enabled; | 238 | int pci_out_enabled; |
230 | |||
231 | /* IQDIO: output multiple buffers (enhanced SIGA) */ | 239 | /* IQDIO: output multiple buffers (enhanced SIGA) */ |
232 | int use_enh_siga; | 240 | int use_enh_siga; |
233 | |||
234 | /* timer to check for more outbound work */ | 241 | /* timer to check for more outbound work */ |
235 | struct timer_list timer; | 242 | struct timer_list timer; |
236 | }; | 243 | }; |
237 | 244 | ||
245 | /* | ||
246 | * Note on cache alignment: grouped slsb and write mostly data at the beginning | ||
247 | * sbal[] is read-only and starts on a new cacheline followed by read mostly. | ||
248 | */ | ||
238 | struct qdio_q { | 249 | struct qdio_q { |
239 | struct slsb slsb; | 250 | struct slsb slsb; |
251 | |||
240 | union { | 252 | union { |
241 | struct qdio_input_q in; | 253 | struct qdio_input_q in; |
242 | struct qdio_output_q out; | 254 | struct qdio_output_q out; |
243 | } u; | 255 | } u; |
244 | 256 | ||
245 | /* queue number */ | ||
246 | int nr; | ||
247 | |||
248 | /* bitmask of queue number */ | ||
249 | int mask; | ||
250 | |||
251 | /* input or output queue */ | ||
252 | int is_input_q; | ||
253 | |||
254 | /* list of thinint input queues */ | ||
255 | struct list_head entry; | ||
256 | |||
257 | /* upper-layer program handler */ | ||
258 | qdio_handler_t (*handler); | ||
259 | |||
260 | /* | 257 | /* |
261 | * inbound: next buffer the program should check for | 258 | * inbound: next buffer the program should check for |
262 | * outbound: next buffer to check for having been processed | 259 | * outbound: next buffer to check if adapter processed it |
263 | * by the card | ||
264 | */ | 260 | */ |
265 | int first_to_check; | 261 | int first_to_check; |
266 | 262 | ||
@@ -273,16 +269,32 @@ struct qdio_q { | |||
273 | /* number of buffers in use by the adapter */ | 269 | /* number of buffers in use by the adapter */ |
274 | atomic_t nr_buf_used; | 270 | atomic_t nr_buf_used; |
275 | 271 | ||
276 | struct qdio_irq *irq_ptr; | ||
277 | struct dentry *debugfs_q; | ||
278 | struct tasklet_struct tasklet; | ||
279 | |||
280 | /* error condition during a data transfer */ | 272 | /* error condition during a data transfer */ |
281 | unsigned int qdio_error; | 273 | unsigned int qdio_error; |
282 | 274 | ||
283 | struct sl *sl; | 275 | struct tasklet_struct tasklet; |
284 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | 276 | struct qdio_queue_perf_stat q_stats; |
277 | |||
278 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q] ____cacheline_aligned; | ||
279 | |||
280 | /* queue number */ | ||
281 | int nr; | ||
282 | |||
283 | /* bitmask of queue number */ | ||
284 | int mask; | ||
285 | |||
286 | /* input or output queue */ | ||
287 | int is_input_q; | ||
288 | |||
289 | /* list of thinint input queues */ | ||
290 | struct list_head entry; | ||
285 | 291 | ||
292 | /* upper-layer program handler */ | ||
293 | qdio_handler_t (*handler); | ||
294 | |||
295 | struct dentry *debugfs_q; | ||
296 | struct qdio_irq *irq_ptr; | ||
297 | struct sl *sl; | ||
286 | /* | 298 | /* |
287 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * Warning: Leave this member at the end so it won't be cleared in |
288 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * qdio_fill_qs. A page is allocated under this pointer and used for |
@@ -317,12 +329,8 @@ struct qdio_irq { | |||
317 | struct qdio_ssqd_desc ssqd_desc; | 329 | struct qdio_ssqd_desc ssqd_desc; |
318 | void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); | 330 | void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); |
319 | 331 | ||
320 | struct qdio_dev_perf_stat perf_stat; | ||
321 | int perf_stat_enabled; | 332 | int perf_stat_enabled; |
322 | /* | 333 | |
323 | * Warning: Leave these members together at the end so they won't be | ||
324 | * cleared in qdio_setup_irq. | ||
325 | */ | ||
326 | struct qdr *qdr; | 334 | struct qdr *qdr; |
327 | unsigned long chsc_page; | 335 | unsigned long chsc_page; |
328 | 336 | ||
@@ -331,6 +339,7 @@ struct qdio_irq { | |||
331 | 339 | ||
332 | debug_info_t *debug_area; | 340 | debug_info_t *debug_area; |
333 | struct mutex setup_mutex; | 341 | struct mutex setup_mutex; |
342 | struct qdio_dev_perf_stat perf_stat; | ||
334 | }; | 343 | }; |
335 | 344 | ||
336 | /* helper functions */ | 345 | /* helper functions */ |
@@ -341,9 +350,20 @@ struct qdio_irq { | |||
341 | (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ | 350 | (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ |
342 | css_general_characteristics.aif_osa) | 351 | css_general_characteristics.aif_osa) |
343 | 352 | ||
344 | #define qperf(qdev,attr) qdev->perf_stat.attr | 353 | #define qperf(__qdev, __attr) ((__qdev)->perf_stat.(__attr)) |
345 | #define qperf_inc(q,attr) if (q->irq_ptr->perf_stat_enabled) \ | 354 | |
346 | q->irq_ptr->perf_stat.attr++ | 355 | #define qperf_inc(__q, __attr) \ |
356 | ({ \ | ||
357 | struct qdio_irq *qdev = (__q)->irq_ptr; \ | ||
358 | if (qdev->perf_stat_enabled) \ | ||
359 | (qdev->perf_stat.__attr)++; \ | ||
360 | }) | ||
361 | |||
362 | static inline void account_sbals_error(struct qdio_q *q, int count) | ||
363 | { | ||
364 | q->q_stats.nr_sbal_error += count; | ||
365 | q->q_stats.nr_sbal_total += count; | ||
366 | } | ||
347 | 367 | ||
348 | /* the highest iqdio queue is used for multicast */ | 368 | /* the highest iqdio queue is used for multicast */ |
349 | static inline int multicast_outbound(struct qdio_q *q) | 369 | static inline int multicast_outbound(struct qdio_q *q) |