| .. | .. |
|---|
| 15 | 15 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
|---|
| 16 | 16 | #define QDIO_BUSY_BIT_RETRY_DELAY 10 /* 10 milliseconds */ |
|---|
| 17 | 17 | #define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */ |
|---|
| 18 | | -#define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ |
|---|
| 19 | 18 | |
|---|
| 20 | 19 | enum qdio_irq_states { |
|---|
| 21 | 20 | QDIO_IRQ_STATE_INACTIVE, |
|---|
| .. | .. |
|---|
| 82 | 81 | #define QDIO_SIGA_WRITE 0x00 |
|---|
| 83 | 82 | #define QDIO_SIGA_READ 0x01 |
|---|
| 84 | 83 | #define QDIO_SIGA_SYNC 0x02 |
|---|
| 84 | +#define QDIO_SIGA_WRITEM 0x03 |
|---|
| 85 | 85 | #define QDIO_SIGA_WRITEQ 0x04 |
|---|
| 86 | 86 | #define QDIO_SIGA_QEBSM_FLAG 0x80 |
|---|
| 87 | 87 | |
|---|
| 88 | 88 | static inline int do_sqbs(u64 token, unsigned char state, int queue, |
|---|
| 89 | 89 | int *start, int *count) |
|---|
| 90 | 90 | { |
|---|
| 91 | | - register unsigned long _ccq asm ("0") = *count; |
|---|
| 92 | | - register unsigned long _token asm ("1") = token; |
|---|
| 93 | 91 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; |
|---|
| 92 | + unsigned long _ccq = *count; |
|---|
| 94 | 93 | |
|---|
| 95 | 94 | asm volatile( |
|---|
| 96 | | - " .insn rsy,0xeb000000008A,%1,0,0(%2)" |
|---|
| 97 | | - : "+d" (_ccq), "+d" (_queuestart) |
|---|
| 98 | | - : "d" ((unsigned long)state), "d" (_token) |
|---|
| 99 | | - : "memory", "cc"); |
|---|
| 95 | + " lgr 1,%[token]\n" |
|---|
| 96 | + " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" |
|---|
| 97 | + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) |
|---|
| 98 | + : [state] "a" ((unsigned long)state), [token] "d" (token) |
|---|
| 99 | + : "memory", "cc", "1"); |
|---|
| 100 | 100 | *count = _ccq & 0xff; |
|---|
| 101 | 101 | *start = _queuestart & 0xff; |
|---|
| 102 | 102 | |
|---|
| .. | .. |
|---|
| 106 | 106 | static inline int do_eqbs(u64 token, unsigned char *state, int queue, |
|---|
| 107 | 107 | int *start, int *count, int ack) |
|---|
| 108 | 108 | { |
|---|
| 109 | | - register unsigned long _ccq asm ("0") = *count; |
|---|
| 110 | | - register unsigned long _token asm ("1") = token; |
|---|
| 111 | 109 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; |
|---|
| 112 | 110 | unsigned long _state = (unsigned long)ack << 63; |
|---|
| 111 | + unsigned long _ccq = *count; |
|---|
| 113 | 112 | |
|---|
| 114 | 113 | asm volatile( |
|---|
| 115 | | - " .insn rrf,0xB99c0000,%1,%2,0,0" |
|---|
| 116 | | - : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) |
|---|
| 117 | | - : "d" (_token) |
|---|
| 118 | | - : "memory", "cc"); |
|---|
| 114 | + " lgr 1,%[token]\n" |
|---|
| 115 | + " .insn rrf,0xb99c0000,%[qs],%[state],%[ccq],0" |
|---|
| 116 | + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart), |
|---|
| 117 | + [state] "+&d" (_state) |
|---|
| 118 | + : [token] "d" (token) |
|---|
| 119 | + : "memory", "cc", "1"); |
|---|
| 119 | 120 | *count = _ccq & 0xff; |
|---|
| 120 | 121 | *start = _queuestart & 0xff; |
|---|
| 121 | 122 | *state = _state & 0xff; |
|---|
| .. | .. |
|---|
| 165 | 166 | } ____cacheline_aligned; |
|---|
| 166 | 167 | |
|---|
| 167 | 168 | struct qdio_queue_perf_stat { |
|---|
| 168 | | - /* |
|---|
| 169 | | - * Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. |
|---|
| 170 | | - * Since max. 127 SBALs are scanned reuse entry for 128 as queue full |
|---|
| 171 | | - * aka 127 SBALs found. |
|---|
| 172 | | - */ |
|---|
| 169 | + /* Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. */ |
|---|
| 173 | 170 | unsigned int nr_sbals[8]; |
|---|
| 174 | 171 | unsigned int nr_sbal_error; |
|---|
| 175 | 172 | unsigned int nr_sbal_nop; |
|---|
| 176 | 173 | unsigned int nr_sbal_total; |
|---|
| 177 | 174 | }; |
|---|
| 178 | 175 | |
|---|
| 179 | | -enum qdio_queue_irq_states { |
|---|
| 180 | | - QDIO_QUEUE_IRQS_DISABLED, |
|---|
| 176 | +enum qdio_irq_poll_states { |
|---|
| 177 | + QDIO_IRQ_DISABLED, |
|---|
| 181 | 178 | }; |
|---|
| 182 | 179 | |
|---|
| 183 | 180 | struct qdio_input_q { |
|---|
| 184 | | - /* input buffer acknowledgement flag */ |
|---|
| 185 | | - int polling; |
|---|
| 186 | | - /* first ACK'ed buffer */ |
|---|
| 187 | | - int ack_start; |
|---|
| 188 | | - /* how much sbals are acknowledged with qebsm */ |
|---|
| 189 | | - int ack_count; |
|---|
| 190 | | - /* last time of noticing incoming data */ |
|---|
| 191 | | - u64 timestamp; |
|---|
| 192 | | - /* upper-layer polling flag */ |
|---|
| 193 | | - unsigned long queue_irq_state; |
|---|
| 194 | | - /* callback to start upper-layer polling */ |
|---|
| 195 | | - void (*queue_start_poll) (struct ccw_device *, int, unsigned long); |
|---|
| 181 | + /* Batch of SBALs that we processed while polling the queue: */ |
|---|
| 182 | + unsigned int batch_start; |
|---|
| 183 | + unsigned int batch_count; |
|---|
| 196 | 184 | }; |
|---|
| 197 | 185 | |
|---|
| 198 | 186 | struct qdio_output_q { |
|---|
| .. | .. |
|---|
| 206 | 194 | struct qdio_outbuf_state *sbal_state; |
|---|
| 207 | 195 | /* timer to check for more outbound work */ |
|---|
| 208 | 196 | struct timer_list timer; |
|---|
| 209 | | - /* used SBALs before tasklet schedule */ |
|---|
| 210 | | - int scan_threshold; |
|---|
| 211 | 197 | }; |
|---|
| 212 | 198 | |
|---|
| 213 | 199 | /* |
|---|
| .. | .. |
|---|
| 227 | 213 | * outbound: next buffer to check if adapter processed it |
|---|
| 228 | 214 | */ |
|---|
| 229 | 215 | int first_to_check; |
|---|
| 230 | | - |
|---|
| 231 | | - /* first_to_check of the last time */ |
|---|
| 232 | | - int last_move; |
|---|
| 233 | | - |
|---|
| 234 | | - /* beginning position for calling the program */ |
|---|
| 235 | | - int first_to_kick; |
|---|
| 236 | 216 | |
|---|
| 237 | 217 | /* number of buffers in use by the adapter */ |
|---|
| 238 | 218 | atomic_t nr_buf_used; |
|---|
| .. | .. |
|---|
| 257 | 237 | /* input or output queue */ |
|---|
| 258 | 238 | int is_input_q; |
|---|
| 259 | 239 | |
|---|
| 260 | | - /* list of thinint input queues */ |
|---|
| 261 | | - struct list_head entry; |
|---|
| 262 | | - |
|---|
| 263 | 240 | /* upper-layer program handler */ |
|---|
| 264 | 241 | qdio_handler_t (*handler); |
|---|
| 265 | 242 | |
|---|
| 266 | | - struct dentry *debugfs_q; |
|---|
| 267 | 243 | struct qdio_irq *irq_ptr; |
|---|
| 268 | 244 | struct sl *sl; |
|---|
| 269 | 245 | /* |
|---|
| .. | .. |
|---|
| 277 | 253 | struct qib qib; |
|---|
| 278 | 254 | u32 *dsci; /* address of device state change indicator */ |
|---|
| 279 | 255 | struct ccw_device *cdev; |
|---|
| 256 | + struct list_head entry; /* list of thinint devices */ |
|---|
| 280 | 257 | struct dentry *debugfs_dev; |
|---|
| 281 | | - struct dentry *debugfs_perf; |
|---|
| 282 | 258 | |
|---|
| 283 | 259 | unsigned long int_parm; |
|---|
| 284 | 260 | struct subchannel_id schid; |
|---|
| .. | .. |
|---|
| 298 | 274 | struct qdio_ssqd_desc ssqd_desc; |
|---|
| 299 | 275 | void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); |
|---|
| 300 | 276 | |
|---|
| 277 | + unsigned int scan_threshold; /* used SBALs before tasklet schedule */ |
|---|
| 301 | 278 | int perf_stat_enabled; |
|---|
| 302 | 279 | |
|---|
| 303 | 280 | struct qdr *qdr; |
|---|
| .. | .. |
|---|
| 305 | 282 | |
|---|
| 306 | 283 | struct qdio_q *input_qs[QDIO_MAX_QUEUES_PER_IRQ]; |
|---|
| 307 | 284 | struct qdio_q *output_qs[QDIO_MAX_QUEUES_PER_IRQ]; |
|---|
| 285 | + unsigned int max_input_qs; |
|---|
| 286 | + unsigned int max_output_qs; |
|---|
| 287 | + |
|---|
| 288 | + void (*irq_poll)(struct ccw_device *cdev, unsigned long data); |
|---|
| 289 | + unsigned long poll_state; |
|---|
| 308 | 290 | |
|---|
| 309 | 291 | debug_info_t *debug_area; |
|---|
| 310 | 292 | struct mutex setup_mutex; |
|---|
| .. | .. |
|---|
| 321 | 303 | |
|---|
| 322 | 304 | #define qperf(__qdev, __attr) ((__qdev)->perf_stat.(__attr)) |
|---|
| 323 | 305 | |
|---|
| 324 | | -#define qperf_inc(__q, __attr) \ |
|---|
| 306 | +#define QDIO_PERF_STAT_INC(__irq, __attr) \ |
|---|
| 325 | 307 | ({ \ |
|---|
| 326 | | - struct qdio_irq *qdev = (__q)->irq_ptr; \ |
|---|
| 308 | + struct qdio_irq *qdev = __irq; \ |
|---|
| 327 | 309 | if (qdev->perf_stat_enabled) \ |
|---|
| 328 | 310 | (qdev->perf_stat.__attr)++; \ |
|---|
| 329 | 311 | }) |
|---|
| 312 | + |
|---|
| 313 | +#define qperf_inc(__q, __attr) QDIO_PERF_STAT_INC((__q)->irq_ptr, __attr) |
|---|
| 330 | 314 | |
|---|
| 331 | 315 | static inline void account_sbals_error(struct qdio_q *q, int count) |
|---|
| 332 | 316 | { |
|---|
| .. | .. |
|---|
| 341 | 325 | (q->nr == q->irq_ptr->nr_output_qs - 1); |
|---|
| 342 | 326 | } |
|---|
| 343 | 327 | |
|---|
| 344 | | -#define pci_out_supported(q) \ |
|---|
| 345 | | - (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
|---|
| 328 | +#define pci_out_supported(irq) ((irq)->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
|---|
| 346 | 329 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
|---|
| 347 | 330 | |
|---|
| 348 | 331 | #define need_siga_in(q) (q->irq_ptr->siga_flag.input) |
|---|
| .. | .. |
|---|
| 360 | 343 | for (i = 0; i < irq_ptr->nr_output_qs && \ |
|---|
| 361 | 344 | ({ q = irq_ptr->output_qs[i]; 1; }); i++) |
|---|
| 362 | 345 | |
|---|
| 363 | | -#define prev_buf(bufnr) \ |
|---|
| 364 | | - ((bufnr + QDIO_MAX_BUFFERS_MASK) & QDIO_MAX_BUFFERS_MASK) |
|---|
| 365 | | -#define next_buf(bufnr) \ |
|---|
| 366 | | - ((bufnr + 1) & QDIO_MAX_BUFFERS_MASK) |
|---|
| 367 | | -#define add_buf(bufnr, inc) \ |
|---|
| 368 | | - ((bufnr + inc) & QDIO_MAX_BUFFERS_MASK) |
|---|
| 369 | | -#define sub_buf(bufnr, dec) \ |
|---|
| 370 | | - ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK) |
|---|
| 346 | +#define add_buf(bufnr, inc) QDIO_BUFNR((bufnr) + (inc)) |
|---|
| 347 | +#define next_buf(bufnr) add_buf(bufnr, 1) |
|---|
| 348 | +#define sub_buf(bufnr, dec) QDIO_BUFNR((bufnr) - (dec)) |
|---|
| 349 | +#define prev_buf(bufnr) sub_buf(bufnr, 1) |
|---|
| 371 | 350 | |
|---|
| 372 | 351 | #define queue_irqs_enabled(q) \ |
|---|
| 373 | 352 | (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) == 0) |
|---|
| .. | .. |
|---|
| 379 | 358 | /* prototypes for thin interrupt */ |
|---|
| 380 | 359 | int qdio_establish_thinint(struct qdio_irq *irq_ptr); |
|---|
| 381 | 360 | void qdio_shutdown_thinint(struct qdio_irq *irq_ptr); |
|---|
| 382 | | -void tiqdio_add_input_queues(struct qdio_irq *irq_ptr); |
|---|
| 383 | | -void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr); |
|---|
| 361 | +void tiqdio_add_device(struct qdio_irq *irq_ptr); |
|---|
| 362 | +void tiqdio_remove_device(struct qdio_irq *irq_ptr); |
|---|
| 384 | 363 | void tiqdio_inbound_processing(unsigned long q); |
|---|
| 385 | | -int tiqdio_allocate_memory(void); |
|---|
| 386 | | -void tiqdio_free_memory(void); |
|---|
| 387 | | -int tiqdio_register_thinints(void); |
|---|
| 388 | | -void tiqdio_unregister_thinints(void); |
|---|
| 389 | | -void clear_nonshared_ind(struct qdio_irq *); |
|---|
| 364 | +int qdio_thinint_init(void); |
|---|
| 365 | +void qdio_thinint_exit(void); |
|---|
| 390 | 366 | int test_nonshared_ind(struct qdio_irq *); |
|---|
| 391 | 367 | |
|---|
| 392 | 368 | /* prototypes for setup */ |
|---|
| .. | .. |
|---|
| 401 | 377 | int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr, |
|---|
| 402 | 378 | struct subchannel_id *schid, |
|---|
| 403 | 379 | struct qdio_ssqd_desc *data); |
|---|
| 404 | | -int qdio_setup_irq(struct qdio_initialize *init_data); |
|---|
| 405 | | -void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, |
|---|
| 406 | | - struct ccw_device *cdev); |
|---|
| 407 | | -void qdio_release_memory(struct qdio_irq *irq_ptr); |
|---|
| 408 | | -int qdio_setup_create_sysfs(struct ccw_device *cdev); |
|---|
| 409 | | -void qdio_setup_destroy_sysfs(struct ccw_device *cdev); |
|---|
| 380 | +int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data); |
|---|
| 381 | +void qdio_shutdown_irq(struct qdio_irq *irq); |
|---|
| 382 | +void qdio_print_subchannel_info(struct qdio_irq *irq_ptr); |
|---|
| 383 | +void qdio_free_queues(struct qdio_irq *irq_ptr); |
|---|
| 384 | +void qdio_free_async_data(struct qdio_irq *irq_ptr); |
|---|
| 410 | 385 | int qdio_setup_init(void); |
|---|
| 411 | 386 | void qdio_setup_exit(void); |
|---|
| 412 | 387 | int qdio_enable_async_operation(struct qdio_output_q *q); |
|---|