.. | .. |
---|
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); |
---|