1 /*
2 *
3 * linux/drivers/s390/qdio.c
4 *
5 * Linux for S/390 QDIO base support, Hipersocket base support
6 * version 2
7 *
8 * Copyright 2000,2002 IBM Corporation
9 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
10 *
11 * Restriction: only 63 iqdio subchannels would have its own indicator,
12 * after that, subsequent subchannels share one indicator
13 *
14 *
15 *
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2, or (at your option)
20 * any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 */
31
32 /* we want the eyecatcher to be at the top of the code */
qdio_eyecatcher(void)33 void volatile qdio_eyecatcher(void)
34 {
35 return;
36 }
37
38 #include <linux/config.h>
39
40 #include <linux/module.h>
41
42 #include <linux/version.h>
43 #include <linux/slab.h>
44 #include <linux/kernel.h>
45 #include <linux/proc_fs.h>
46 #include <linux/init.h>
47 #include <linux/timer.h>
48 #include <linux/mm.h>
49
50 #include <asm/irq.h>
51 #include <asm/io.h>
52 #include <asm/atomic.h>
53 #include <asm/semaphore.h>
54 #include <asm/page.h>
55
56 #include <asm/debug.h>
57
58 #include <asm/qdio.h>
59
60 #define VERSION_QDIO_C "$Revision: 1.145.4.9 $"
61
62 /****************** MODULE PARAMETER VARIABLES ********************/
63 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
64 MODULE_DESCRIPTION("QDIO base support version 2, " \
65 "Copyright 2000 IBM Corporation");
66 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12))
67 MODULE_LICENSE("GPL");
68 #endif
69
70 /******************** HERE WE GO ***********************************/
71
72 static const char *version="QDIO base support version 2 ("
73 VERSION_QDIO_C "/" VERSION_QDIO_H ")";
74
75 #ifdef QDIO_PERFORMANCE_STATS
76 static int proc_perf_file_registration;
77 unsigned long i_p_c=0,i_p_nc=0,o_p_c=0,o_p_nc=0,ii_p_c=0,ii_p_nc=0;
78
79 static struct {
80 unsigned int tl_runs;
81
82 unsigned int siga_outs;
83 unsigned int siga_ins;
84 unsigned int siga_syncs;
85 unsigned int pcis;
86 unsigned int thinints;
87 unsigned int fast_reqs;
88
89 __u64 start_time_outbound;
90 unsigned int outbound_cnt;
91 unsigned int outbound_time;
92 __u64 start_time_inbound;
93 unsigned int inbound_cnt;
94 unsigned int inbound_time;
95 } perf_stats;
96
97 #endif /* QDIO_PERFORMANCE_STATS */
98
99 static int hydra_thinints=0;
100 static int omit_svs=0;
101
102 static int indicator_used[INDICATORS_PER_CACHELINE];
103 static __u32 * volatile indicators;
104 static __u32 volatile spare_indicator;
105 static atomic_t spare_indicator_usecount;
106
107 static debug_info_t *qdio_dbf_setup=NULL;
108 static debug_info_t *qdio_dbf_sbal=NULL;
109 static debug_info_t *qdio_dbf_trace=NULL;
110 static debug_info_t *qdio_dbf_sense=NULL;
111 #ifdef QDIO_DBF_LIKE_HELL
112 static debug_info_t *qdio_dbf_slsb_out=NULL;
113 static debug_info_t *qdio_dbf_slsb_in=NULL;
114 #endif /* QDIO_DBF_LIKE_HELL */
115
116 static qdio_irq_t *first_irq[QDIO_IRQ_BUCKETS]={
117 [0 ... (QDIO_IRQ_BUCKETS-1)] = NULL
118 };
119 static rwlock_t irq_list_lock[QDIO_IRQ_BUCKETS]={
120 [0 ... (QDIO_IRQ_BUCKETS-1)] = RW_LOCK_UNLOCKED
121 };
122
123 static struct semaphore init_sema;
124
125 static qdio_chsc_area_t *chsc_area;
126 static spinlock_t chsc_area_lock=SPIN_LOCK_UNLOCKED;
127 /* iQDIO stuff: */
128 static volatile qdio_q_t *tiq_list=NULL; /* volatile as it could change
129 during a while loop */
130 static spinlock_t ttiq_list_lock=SPIN_LOCK_UNLOCKED;
131 static int register_thinint_result;
132 static void tiqdio_tl(unsigned long);
133 static DECLARE_TASKLET(tiqdio_tasklet,tiqdio_tl,0);
134
135 #define HEXDUMP16(importance,header,ptr) \
136 QDIO_PRINT_##importance(header "%02x %02x %02x %02x " \
137 "%02x %02x %02x %02x %02x %02x %02x %02x " \
138 "%02x %02x %02x %02x\n",*(((char*)ptr)), \
139 *(((char*)ptr)+1),*(((char*)ptr)+2), \
140 *(((char*)ptr)+3),*(((char*)ptr)+4), \
141 *(((char*)ptr)+5),*(((char*)ptr)+6), \
142 *(((char*)ptr)+7),*(((char*)ptr)+8), \
143 *(((char*)ptr)+9),*(((char*)ptr)+10), \
144 *(((char*)ptr)+11),*(((char*)ptr)+12), \
145 *(((char*)ptr)+13),*(((char*)ptr)+14), \
146 *(((char*)ptr)+15)); \
147 QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
148 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
149 *(((char*)ptr)+16),*(((char*)ptr)+17), \
150 *(((char*)ptr)+18),*(((char*)ptr)+19), \
151 *(((char*)ptr)+20),*(((char*)ptr)+21), \
152 *(((char*)ptr)+22),*(((char*)ptr)+23), \
153 *(((char*)ptr)+24),*(((char*)ptr)+25), \
154 *(((char*)ptr)+26),*(((char*)ptr)+27), \
155 *(((char*)ptr)+28),*(((char*)ptr)+29), \
156 *(((char*)ptr)+30),*(((char*)ptr)+31));
157
158 #define atomic_swap(a,b) xchg((int*)a.counter,b)
159
160 /* not a macro, as one of the arguments is atomic_read */
qdio_min(int a,int b)161 static inline int qdio_min(int a,int b)
162 {
163 if (a<b)
164 return a;
165 else
166 return b;
167 }
168
169 /* unlikely as the later the better */
170 #define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
171 #define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \
172 qdio_siga_sync(q,~0U,~0U)
173 #define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \
174 qdio_siga_sync(q,~0U,0)
175
176 #define NOW qdio_get_micros()
177 #define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW
178 #define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time)
179 #define SAVE_FRONTIER(q,val) q->last_move_ftc=val
180 #define GET_SAVED_FRONTIER(q) (q->last_move_ftc)
181
182 #define MY_MODULE_STRING(x) #x
183
184 #ifdef QDIO_32_BIT
185 #define QDIO_GET_32BIT_ADDR(x) ((__u32)(long)x)
186 #else /* QDIO_32_BIT */
187 #define QDIO_GET_32BIT_ADDR(x) ((__u32)(unsigned long)x)
188 #endif /* QDIO_32_BIT */
189
190 #define QDIO_PFIX_GET_ADDR(x) ((flags&QDIO_PFIX) ? \
191 pfix_get_addr(x):((unsigned long)x))
192
193 /***************** SCRUBBER HELPER ROUTINES **********************/
194
qdio_get_micros(void)195 static inline volatile __u64 qdio_get_micros(void)
196 {
197 __u64 time;
198
199 asm volatile ("STCK %0" : "=m" (time));
200 return time>>12; /* time>>12 is microseconds*/
201 }
qdio_get_millis(void)202 static inline unsigned long qdio_get_millis(void)
203 {
204 return (unsigned long)(qdio_get_micros()>>10);
205 }
206
atomic_return_add(int i,atomic_t * v)207 static __inline__ int atomic_return_add (int i, atomic_t *v)
208 {
209 int old, new;
210 __CS_LOOP(old, new, v, i, "ar");
211 return old;
212 }
213
qdio_wait_nonbusy(unsigned int timeout)214 static void qdio_wait_nonbusy(unsigned int timeout)
215 {
216 unsigned int start;
217 char dbf_text[15];
218
219 sprintf(dbf_text,"wtnb%4x",timeout);
220 QDIO_DBF_TEXT3(0,trace,dbf_text);
221
222 start=qdio_get_millis();
223 for (;;) {
224 set_task_state(current,TASK_INTERRUPTIBLE);
225 if (qdio_get_millis()-start>timeout) {
226 goto out;
227 }
228 schedule_timeout(((start+timeout-qdio_get_millis())>>10)*HZ);
229 }
230 out:
231 set_task_state(current,TASK_RUNNING);
232 }
233
qdio_wait_for_no_use_count(atomic_t * use_count)234 static int qdio_wait_for_no_use_count(atomic_t *use_count)
235 {
236 unsigned long start;
237
238 QDIO_DBF_TEXT3(0,trace,"wtnousec");
239 start=qdio_get_millis();
240 for (;;) {
241 if (qdio_get_millis()-start>QDIO_NO_USE_COUNT_TIMEOUT) {
242 QDIO_DBF_TEXT1(1,trace,"WTNOUSTO");
243 return -ETIME;
244 }
245 if (!atomic_read(use_count)) {
246 QDIO_DBF_TEXT3(0,trace,"wtnoused");
247 return 0;
248 }
249 qdio_wait_nonbusy(QDIO_NO_USE_COUNT_TIME);
250 }
251 }
252
253 /* unfortunately, we can't just xchg the values; in do_QDIO we want to reserve
254 * the q in any case, so that we'll not be interrupted when we are in
255 * qdio_mark_tiq... shouldn't have a really bad impact, as reserving almost
256 * ever works (last famous words) */
qdio_reserve_q(qdio_q_t * q)257 static inline int qdio_reserve_q(qdio_q_t *q)
258 {
259 return atomic_return_add(1,&q->use_count);
260 }
261
qdio_release_q(qdio_q_t * q)262 static inline void qdio_release_q(qdio_q_t *q)
263 {
264 atomic_dec(&q->use_count);
265 }
266 #ifdef QDIO_DBF_LIKE_HELL
267 #define set_slsb(x,y) \
268 if(q->queue_type==QDIO_TRACE_QTYPE) { \
269 if(q->is_input_q) { \
270 QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
271 } else { \
272 QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
273 } \
274 } \
275 qdio_set_slsb(x,y); \
276 if(q->queue_type==QDIO_TRACE_QTYPE) { \
277 if(q->is_input_q) { \
278 QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
279 } else { \
280 QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
281 } \
282 }
283 #else /* QDIO_DBF_LIKE_HELL */
284 #define set_slsb(x,y) qdio_set_slsb(x,y)
285 #endif /* QDIO_DBF_LIKE_HELL */
qdio_set_slsb(volatile char * slsb,unsigned char value)286 static volatile inline void qdio_set_slsb(volatile char *slsb,
287 unsigned char value)
288 {
289 xchg((char*)slsb,value);
290 }
291
qdio_siga_sync(qdio_q_t * q,unsigned int gpr2,unsigned int gpr3)292 static inline int qdio_siga_sync(qdio_q_t *q,
293 unsigned int gpr2,
294 unsigned int gpr3)
295 {
296 int cc;
297
298 #ifdef QDIO_DBF_LIKE_HELL
299 QDIO_DBF_TEXT4(0,trace,"sigasync");
300 QDIO_DBF_HEX4(0,trace,&q,sizeof(int));
301 QDIO_DBF_HEX4(0,trace,&gpr2,sizeof(int));
302 QDIO_DBF_HEX4(0,trace,&gpr3,sizeof(int));
303 #endif /* QDIO_DBF_LIKE_HELL */
304
305 #ifdef QDIO_PERFORMANCE_STATS
306 perf_stats.siga_syncs++;
307 #endif /* QDIO_PERFORMANCE_STATS */
308
309 #ifdef QDIO_32_BIT
310 asm volatile (
311 "lhi 0,2 \n\t"
312 "lr 1,%1 \n\t"
313 "lr 2,%2 \n\t"
314 "lr 3,%3 \n\t"
315 "siga 0 \n\t"
316 "ipm %0 \n\t"
317 "srl %0,28 \n\t"
318 : "=d" (cc)
319 : "d" (0x10000|q->irq), "d" (gpr2), "d" (gpr3)
320 : "cc", "0", "1", "2", "3"
321 );
322 #else /* QDIO_32_BIT */
323 asm volatile (
324 "lghi 0,2 \n\t"
325 "llgfr 1,%1 \n\t"
326 "llgfr 2,%2 \n\t"
327 "llgfr 3,%3 \n\t"
328 "siga 0 \n\t"
329 "ipm %0 \n\t"
330 "srl %0,28 \n\t"
331 : "=d" (cc)
332 : "d" (0x10000|q->irq), "d" (gpr2), "d" (gpr3)
333 : "cc", "0", "1", "2", "3"
334 );
335 #endif /* QDIO_32_BIT */
336
337 if (cc) {
338 #ifndef QDIO_DBF_LIKE_HELL
339 /* when QDIO_DBF_LIKE_HELL, we put that already out */
340 QDIO_DBF_TEXT3(0,trace,"sigasync");
341 QDIO_DBF_HEX3(0,trace,&q,sizeof(void*));
342 #endif /* QDIO_DBF_LIKE_HELL */
343 QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
344 }
345
346 return cc;
347 }
348
qdio_siga_sync_q(qdio_q_t * q)349 static inline int qdio_siga_sync_q(qdio_q_t *q)
350 {
351 if (q->is_input_q) {
352 return qdio_siga_sync(q,0,q->mask);
353 } else {
354 return qdio_siga_sync(q,q->mask,0);
355 }
356 }
357
358 /* returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
359 an access exception */
qdio_siga_output(qdio_q_t * q)360 static inline int qdio_siga_output(qdio_q_t *q)
361 {
362 int cc;
363 __u32 busy_bit;
364 __u64 start_time=0;
365
366 #ifdef QDIO_PERFORMANCE_STATS
367 perf_stats.siga_outs++;
368 #endif /* QDIO_PERFORMANCE_STATS */
369
370 #ifdef QDIO_DBF_LIKE_HELL
371 QDIO_DBF_TEXT4(0,trace,"sigaout");
372 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
373 #endif /* QDIO_DBF_LIKE_HELL */
374
375 for (;;) {
376
377 #ifdef QDIO_32_BIT
378 asm volatile (
379 "lhi 0,0 \n\t"
380 "lr 1,%2 \n\t"
381 "lr 2,%3 \n\t"
382 "siga 0 \n\t"
383 "0:"
384 "ipm %0 \n\t"
385 "srl %0,28 \n\t"
386 "srl 0,31 \n\t"
387 "lr %1,0 \n\t"
388 "1: \n\t"
389 ".section .fixup,\"ax\"\n\t"
390 "2: \n\t"
391 "lhi %0,%4 \n\t"
392 "bras 1,3f \n\t"
393 ".long 1b \n\t"
394 "3: \n\t"
395 "l 1,0(1) \n\t"
396 "br 1 \n\t"
397 ".previous \n\t"
398 ".section __ex_table,\"a\"\n\t"
399 ".align 4 \n\t"
400 ".long 0b,2b \n\t"
401 ".previous \n\t"
402 : "=d" (cc), "=d" (busy_bit)
403 : "d" (0x10000|q->irq), "d" (q->mask),
404 "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
405 : "cc", "0", "1", "2", "memory"
406 );
407 #else /* QDIO_32_BIT */
408 asm volatile (
409 "lghi 0,0 \n\t"
410 "llgfr 1,%2 \n\t"
411 "llgfr 2,%3 \n\t"
412 "siga 0 \n\t"
413 "0:"
414 "ipm %0 \n\t"
415 "srl %0,28 \n\t"
416 "srl 0,31 \n\t"
417 "llgfr %1,0 \n\t"
418 "1: \n\t"
419 ".section .fixup,\"ax\"\n\t"
420 "lghi %0,%4 \n\t"
421 "jg 1b \n\t"
422 ".previous\n\t"
423 ".section __ex_table,\"a\"\n\t"
424 ".align 8 \n\t"
425 ".quad 0b,1b \n\t"
426 ".previous \n\t"
427 : "=d" (cc), "=d" (busy_bit)
428 : "d" (0x10000|q->irq), "d" (q->mask),
429 "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
430 : "cc", "0", "1", "2", "memory"
431 );
432 #endif /* QDIO_32_BIT */
433
434 //QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit);
435 if ( (cc==2) && (busy_bit) &&
436 (q->is_iqdio_q) ) {
437 if (!start_time) start_time=NOW;
438 if ((NOW-start_time)>QDIO_BUSY_BIT_PATIENCE)
439 break;
440 } else
441 break;
442 }
443
444 if ((cc==2) && (busy_bit)) cc|=QDIO_SIGA_ERROR_B_BIT_SET;
445
446 if (cc) {
447 #ifndef QDIO_DBF_LIKE_HELL
448 QDIO_DBF_TEXT3(0,trace,"sigaout");
449 QDIO_DBF_HEX3(0,trace,&q,sizeof(void*));
450 #endif /* QDIO_DBF_LIKE_HELL */
451 QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
452 }
453
454 return cc;
455 }
456
qdio_siga_input(qdio_q_t * q)457 static inline int qdio_siga_input(qdio_q_t *q)
458 {
459 int cc;
460
461 #ifdef QDIO_DBF_LIKE_HELL
462 QDIO_DBF_TEXT4(0,trace,"sigain");
463 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
464 #endif /* QDIO_DBF_LIKE_HELL */
465
466 #ifdef QDIO_PERFORMANCE_STATS
467 perf_stats.siga_ins++;
468 #endif /* QDIO_PERFORMANCE_STATS */
469
470 #ifdef QDIO_32_BIT
471 asm volatile (
472 "lhi 0,1 \n\t"
473 "lr 1,%1 \n\t"
474 "lr 2,%2 \n\t"
475 "siga 0 \n\t"
476 "ipm %0 \n\t"
477 "srl %0,28 \n\t"
478 : "=d" (cc)
479 : "d" (0x10000|q->irq), "d" (q->mask)
480 : "cc", "0", "1", "2", "memory"
481 );
482 #else /* QDIO_32_BIT */
483 asm volatile (
484 "lghi 0,1 \n\t"
485 "llgfr 1,%1 \n\t"
486 "llgfr 2,%2 \n\t"
487 "siga 0 \n\t"
488 "ipm %0 \n\t"
489 "srl %0,28 \n\t"
490 : "=d" (cc)
491 : "d" (0x10000|q->irq), "d" (q->mask)
492 : "cc", "0", "1", "2", "memory"
493 );
494 #endif /* QDIO_32_BIT */
495
496 if (cc) {
497 #ifndef QDIO_DBF_LIKE_HELL
498 QDIO_DBF_TEXT3(0,trace,"sigain");
499 QDIO_DBF_HEX3(0,trace,&q,sizeof(void*));
500 #endif /* QDIO_DBF_LIKE_HELL */
501 QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
502 }
503
504 return cc;
505 }
506
507 /* locked by the locks in qdio_activate and qdio_cleanup */
qdio_get_indicator(void)508 static __u32 * volatile qdio_get_indicator(void)
509 {
510 int i=1;
511 int found=0;
512
513 while (i<INDICATORS_PER_CACHELINE) {
514 if (!indicator_used[i]) {
515 indicator_used[i]=1;
516 found=1;
517 break;
518 }
519 i++;
520 }
521
522 if (found)
523 return indicators+i;
524 else {
525 atomic_inc(&spare_indicator_usecount);
526 return (__u32 * volatile) &spare_indicator;
527 }
528 }
529
530 /* locked by the locks in qdio_activate and qdio_cleanup */
qdio_put_indicator(__u32 * addr)531 static void qdio_put_indicator(__u32 *addr)
532 {
533 int i;
534
535 if ( (addr) && (addr!=&spare_indicator) ) {
536 i=addr-indicators;
537 indicator_used[i]=0;
538 }
539 if (addr==&spare_indicator) {
540 atomic_dec(&spare_indicator_usecount);
541 }
542 }
543
tiqdio_clear_summary_bit(__u32 * location)544 static inline volatile void tiqdio_clear_summary_bit(__u32 *location)
545 {
546 #ifdef QDIO_DBF_LIKE_HELL
547 QDIO_DBF_TEXT5(0,trace,"clrsummb");
548 QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
549 #endif /* QDIO_DBF_LIKE_HELL */
550 xchg(location,0);
551 }
552
tiqdio_set_summary_bit(__u32 * location)553 static inline volatile void tiqdio_set_summary_bit(__u32 *location)
554 {
555 #ifdef QDIO_DBF_LIKE_HELL
556 QDIO_DBF_TEXT5(0,trace,"setsummb");
557 QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
558 #endif /* QDIO_DBF_LIKE_HELL */
559 xchg(location,-1);
560 }
561
tiqdio_sched_tl(void)562 static inline void tiqdio_sched_tl(void)
563 {
564 tasklet_hi_schedule(&tiqdio_tasklet);
565 }
566
qdio_mark_tiq(qdio_q_t * q)567 static inline void qdio_mark_tiq(qdio_q_t *q)
568 {
569 unsigned long flags;
570 #ifdef QDIO_DBF_LIKE_HELL
571 QDIO_DBF_TEXT4(0,trace,"mark iq");
572 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
573 #endif /* QDIO_DBF_LIKE_HELL */
574
575 spin_lock_irqsave(&ttiq_list_lock,flags);
576 if (unlikely(atomic_read(&q->is_in_shutdown))) goto out_unlock;
577
578 if (q->is_input_q) {
579 if ((q->list_prev) || (q->list_next)) goto out_unlock;
580
581 if (!tiq_list) {
582 tiq_list=q;
583 q->list_prev=q;
584 q->list_next=q;
585 } else {
586 q->list_next=tiq_list;
587 q->list_prev=tiq_list->list_prev;
588 tiq_list->list_prev->list_next=q;
589 tiq_list->list_prev=q;
590 }
591 spin_unlock_irqrestore(&ttiq_list_lock,flags);
592
593 tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
594 tiqdio_sched_tl();
595 }
596 return;
597 out_unlock:
598 spin_unlock_irqrestore(&ttiq_list_lock,flags);
599 return;
600 }
601
qdio_mark_q(qdio_q_t * q)602 static inline void qdio_mark_q(qdio_q_t *q)
603 {
604 #ifdef QDIO_DBF_LIKE_HELL
605 QDIO_DBF_TEXT4(0,trace,"mark q");
606 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
607 #endif /* QDIO_DBF_LIKE_HELL */
608
609 if (unlikely(atomic_read(&q->is_in_shutdown))) return;
610
611 tasklet_schedule(&q->tasklet);
612 }
613
qdio_stop_polling(qdio_q_t * q)614 static inline int qdio_stop_polling(qdio_q_t *q)
615 {
616 #ifdef QDIO_USE_PROCESSING_STATE
617 int gsf;
618
619 if (!atomic_swap(&q->polling,0)) return 1;
620
621 #ifdef QDIO_DBF_LIKE_HELL
622 QDIO_DBF_TEXT4(0,trace,"stoppoll");
623 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
624 #endif /* QDIO_DBF_LIKE_HELL */
625
626 /* show the card that we are not polling anymore */
627 if (q->is_input_q) {
628 gsf=GET_SAVED_FRONTIER(q);
629 set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)&
630 (QDIO_MAX_BUFFERS_PER_Q-1)],SLSB_P_INPUT_NOT_INIT);
631 /* we don't issue this SYNC_MEMORY, as we trust Rick T and
632 * moreover will not use the PROCESSING state under VM,
633 * so q->polling was 0 anyway.
634 SYNC_MEMORY;*/
635 if (q->slsb.acc.val[gsf]==SLSB_P_INPUT_PRIMED) {
636 /* set our summary bit again, as otherwise there is a
637 * small window we can miss between resetting it and
638 * checking for PRIMED state */
639 if (q->is_thinint_q)
640 tiqdio_set_summary_bit
641 ((__u32*)q->dev_st_chg_ind);
642 return 0;
643 }
644 }
645 #endif /* QDIO_USE_PROCESSING_STATE */
646 return 1;
647 }
648
649 /* see the comment in do_QDIO and before qdio_reserve_q about the
650 * sophisticated locking outside of unmark_q, so that we don't need to
651 * disable the interrupts :-) */
qdio_unmark_q(qdio_q_t * q)652 static inline void qdio_unmark_q(qdio_q_t *q)
653 {
654 unsigned long flags;
655
656 #ifdef QDIO_DBF_LIKE_HELL
657 QDIO_DBF_TEXT4(0,trace,"unmark q");
658 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
659 #endif /* QDIO_DBF_LIKE_HELL */
660
661 if ((!q->list_prev)||(!q->list_next)) return;
662
663 if ((q->is_thinint_q)&&(q->is_input_q)) {
664 /* iQDIO */
665 spin_lock_irqsave(&ttiq_list_lock,flags);
666 /* in case cleanup has done this already and simultanously
667 * qdio_unmark_q is called from the interrupt handler, we've
668 * got to check this in this specific case again */
669 if ((!q->list_prev)||(!q->list_next))
670 goto out;
671 if (q->list_next==q) {
672 /* q was the only interesting q */
673 tiq_list=NULL;
674 q->list_next=NULL;
675 q->list_prev=NULL;
676 } else {
677 q->list_next->list_prev=q->list_prev;
678 q->list_prev->list_next=q->list_next;
679 tiq_list=q->list_next;
680 q->list_next=NULL;
681 q->list_prev=NULL;
682 }
683 out:
684 spin_unlock_irqrestore(&ttiq_list_lock,flags);
685 }
686 }
687
tiqdio_clear_global_summary(void)688 static inline volatile unsigned long tiqdio_clear_global_summary(void)
689 {
690 unsigned long time;
691
692 #ifdef QDIO_DBF_LIKE_HELL
693 QDIO_DBF_TEXT5(0,trace,"clrglobl");
694 #endif /* QDIO_DBF_LIKE_HELL */
695
696 #ifdef QDIO_32_BIT
697 asm volatile (
698 "lhi 1,3 \n\t"
699 ".insn rre,0xb2650000,2,0 \n\t"
700 "lr %0,3 \n\t"
701 : "=d" (time) : : "cc", "1", "2", "3"
702 );
703 #else /* QDIO_32_BIT */
704 asm volatile (
705 "lghi 1,3 \n\t"
706 ".insn rre,0xb2650000,2,0 \n\t"
707 "lgr %0,3 \n\t"
708 : "=d" (time) : : "cc", "1", "2", "3"
709 );
710 #endif /* QDIO_32_BIT */
711
712 #ifdef QDIO_DBF_LIKE_HELL
713 QDIO_DBF_HEX5(0,trace,&time,sizeof(unsigned long));
714 #endif /* QDIO_DBF_LIKE_HELL */
715 return time;
716 }
717
718 /************************* OUTBOUND ROUTINES *******************************/
719
qdio_translate_buffer_back(qdio_q_t * q,int bufno)720 static inline void qdio_translate_buffer_back(qdio_q_t *q,int bufno)
721 {
722 if (unlikely(!q->is_0copy_sbals_q))
723 memcpy(q->qdio_buffers[bufno],
724 (void*)q->sbal[bufno],SBAL_SIZE);
725 }
726
qdio_get_outbound_buffer_frontier(qdio_q_t * q)727 static inline int qdio_get_outbound_buffer_frontier(qdio_q_t *q)
728 {
729 int f,f_mod_no;
730 volatile char *slsb;
731 int first_not_to_check;
732 char dbf_text[15];
733 char slsbyte;
734
735 #ifdef QDIO_DBF_LIKE_HELL
736 QDIO_DBF_TEXT4(0,trace,"getobfro");
737 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
738 #endif /* QDIO_DBF_LIKE_HELL */
739
740 slsb=&q->slsb.acc.val[0];
741 f_mod_no=f=q->first_to_check;
742 /* f point to already processed elements, so f+no_used is correct...
743 * ... but: we don't check 128 buffers, as otherwise
744 * qdio_has_outbound_q_moved would return 0 */
745 first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
746 (QDIO_MAX_BUFFERS_PER_Q-1));
747
748 if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) {
749 SYNC_MEMORY;
750 }
751
752 check_next:
753 if (f==first_not_to_check) goto out;
754 slsbyte=slsb[f_mod_no];
755
756 /* the card has not fetched the output yet */
757 if (slsbyte==SLSB_CU_OUTPUT_PRIMED) {
758 #ifdef QDIO_DBF_LIKE_HELL
759 QDIO_DBF_TEXT5(0,trace,"outpprim");
760 #endif /* QDIO_DBF_LIKE_HELL */
761 goto out;
762 }
763
764 /* the card got it */
765 if (slsbyte==SLSB_P_OUTPUT_EMPTY) {
766 atomic_dec(&q->number_of_buffers_used);
767 f++;
768 f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
769 #ifdef QDIO_DBF_LIKE_HELL
770 QDIO_DBF_TEXT5(0,trace,"outpempt");
771 #endif /* QDIO_DBF_LIKE_HELL */
772 goto check_next;
773 }
774
775 if (slsbyte==SLSB_P_OUTPUT_ERROR) {
776 QDIO_DBF_TEXT3(0,trace,"outperr");
777 sprintf(dbf_text,"%x-%x-%x",f_mod_no,
778 q->sbal[f_mod_no]->element[14].sbalf.value,
779 q->sbal[f_mod_no]->element[15].sbalf.value);
780 QDIO_DBF_TEXT3(1,trace,dbf_text);
781 QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
782
783 /* kind of process the buffer */
784 set_slsb(&q->slsb.acc.val[f_mod_no],
785 SLSB_P_OUTPUT_NOT_INIT);
786
787 qdio_translate_buffer_back(q,f_mod_no);
788
789 /* we increment the frontier, as this buffer
790 * was processed obviously */
791 atomic_dec(&q->number_of_buffers_used);
792 f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
793
794 if (q->qdio_error)
795 q->error_status_flags|=
796 QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
797 q->qdio_error=SLSB_P_OUTPUT_ERROR;
798 q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
799
800 goto out;
801 }
802
803 /* no new buffers */
804 #ifdef QDIO_DBF_LIKE_HELL
805 QDIO_DBF_TEXT5(0,trace,"outpni");
806 #endif /* QDIO_DBF_LIKE_HELL */
807 goto out;
808
809 out:
810 return (q->first_to_check=f_mod_no);
811 }
812
813 /* all buffers are processed */
qdio_is_outbound_q_done(qdio_q_t * q)814 static inline int qdio_is_outbound_q_done(qdio_q_t *q)
815 {
816 int no_used;
817 #ifdef QDIO_DBF_LIKE_HELL
818 char dbf_text[15];
819 #endif /* QDIO_DBF_LIKE_HELL */
820
821 no_used=atomic_read(&q->number_of_buffers_used);
822
823 #ifdef QDIO_DBF_LIKE_HELL
824 if (no_used) {
825 sprintf(dbf_text,"oqisnt%02x",no_used);
826 QDIO_DBF_TEXT4(0,trace,dbf_text);
827 } else {
828 QDIO_DBF_TEXT4(0,trace,"oqisdone");
829 }
830 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
831 #endif /* QDIO_DBF_LIKE_HELL */
832 return (no_used==0);
833 }
834
qdio_has_outbound_q_moved(qdio_q_t * q)835 static inline int qdio_has_outbound_q_moved(qdio_q_t *q)
836 {
837 int i;
838
839 i=qdio_get_outbound_buffer_frontier(q);
840
841 if ( (i!=GET_SAVED_FRONTIER(q)) ||
842 (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
843 SAVE_FRONTIER(q,i);
844 #ifdef QDIO_DBF_LIKE_HELL
845 QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
846 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
847 #endif /* QDIO_DBF_LIKE_HELL */
848 return 1;
849 } else {
850 #ifdef QDIO_DBF_LIKE_HELL
851 QDIO_DBF_TEXT4(0,trace,"oqhsntmv");
852 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
853 #endif /* QDIO_DBF_LIKE_HELL */
854 return 0;
855 }
856 }
857
qdio_kick_outbound_q(qdio_q_t * q)858 static inline void qdio_kick_outbound_q(qdio_q_t *q)
859 {
860 int result;
861 char dbf_text[15];
862 #ifdef QDIO_DBF_LIKE_HELL
863 QDIO_DBF_TEXT4(0,trace,"kickoutq");
864 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
865 #endif /* QDIO_DBF_LIKE_HELL */
866
867 if (!q->siga_out) return;
868
869 /* here's the story with cc=2 and busy bit set (thanks, Rick):
870 * VM's CP could present us cc=2 and busy bit set on SIGA-write
871 * during reconfiguration of their Guest LAN (only in HIPERS mode,
872 * QDIO mode is asynchronous -- cc=2 and busy bit there will take
873 * the queues down immediately; and not being under VM we have a
874 * problem on cc=2 and busy bit set right away).
875 *
876 * Therefore qdio_siga_output will try for a short time constantly,
877 * if such a condition occurs. If it doesn't change, it will
878 * increase the busy_siga_counter and save the timestamp, and
879 * schedule the queue for later processing (via mark_q, using the
880 * queue tasklet). __qdio_outbound_processing will check out the
881 * counter. If non-zero, it will call qdio_kick_outbound_q as often
882 * as the value of the counter. This will attempt further SIGA
883 * instructions.
884 * Every successful SIGA instruction will decrease the counter.
885 * After some time of no movement, qdio_kick_outbound_q will
886 * finally fail and reflect corresponding error codes to call
887 * the upper layer module and have it take the queues down.
888 *
889 * Note that this is a change from the original HiperSockets design
890 * (saying cc=2 and busy bit means take the queues down), but in
891 * these days Guest LAN didn't exist... excessive cc=2 with busy bit
892 * conditions will still take the queues down, but the threshold is
893 * higher due to the Guest LAN environment.
894 */
895
896 result=qdio_siga_output(q);
897
898 switch (result) {
899 case 0:
900 /* went smooth this time, reset timestamp */
901 QDIO_DBF_TEXT3(0,trace,"cc2reslv");
902 sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
903 atomic_read(&q->busy_siga_counter));
904 QDIO_DBF_TEXT3(0,trace,dbf_text);
905 q->timing.busy_start=0;
906 break;
907 case (2|QDIO_SIGA_ERROR_B_BIT_SET):
908 /* cc=2 and busy bit: */
909 atomic_inc(&q->busy_siga_counter);
910
911 /* if the last siga was successful, save
912 * timestamp here */
913 if (!q->timing.busy_start)
914 q->timing.busy_start=NOW;
915
916 /* if we're in time, don't touch error_status_flags
917 * and siga_error */
918 if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
919 qdio_mark_q(q);
920 break;
921 }
922 QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
923 sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
924 atomic_read(&q->busy_siga_counter));
925 QDIO_DBF_TEXT3(0,trace,dbf_text);
926 /* else fallthrough and report error */
927 default:
928 /* for plain cc=1, 2 or 3: */
929 if (q->siga_error)
930 q->error_status_flags|=
931 QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
932 q->error_status_flags|=
933 QDIO_STATUS_LOOK_FOR_ERROR;
934 q->siga_error=result;
935 }
936 }
937
qdio_kick_outbound_handler(qdio_q_t * q)938 static inline void qdio_kick_outbound_handler(qdio_q_t *q)
939 {
940 #ifdef QDIO_DBF_LIKE_HELL
941 char dbf_text[15];
942 #endif /* QDIO_DBF_LIKE_HELL */
943
944 int start=q->first_element_to_kick;
945 /* last_move_ftc was just updated */
946 int real_end=GET_SAVED_FRONTIER(q);
947 int end=(real_end+QDIO_MAX_BUFFERS_PER_Q-1)&
948 (QDIO_MAX_BUFFERS_PER_Q-1);
949 int count=(end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
950 (QDIO_MAX_BUFFERS_PER_Q-1);
951
952 #ifdef QDIO_DBF_LIKE_HELL
953 QDIO_DBF_TEXT4(0,trace,"kickouth");
954 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
955 #endif /* QDIO_DBF_LIKE_HELL */
956
957 #ifdef QDIO_DBF_LIKE_HELL
958 sprintf(dbf_text,"s=%2xc=%2x",start,count);
959 QDIO_DBF_TEXT4(0,trace,dbf_text);
960 #endif /* QDIO_DBF_LIKE_HELL */
961
962 if (q->state==QDIO_IRQ_STATE_ACTIVE)
963 q->handler(q->irq,QDIO_STATUS_OUTBOUND_INT|
964 q->error_status_flags,
965 q->qdio_error,q->siga_error,q->q_no,start,count,
966 q->int_parm);
967
968 /* for the next time: */
969 q->first_element_to_kick=real_end;
970 q->qdio_error=0;
971 q->siga_error=0;
972 q->error_status_flags=0;
973 }
974
__qdio_outbound_processing(qdio_q_t * q)975 static inline void __qdio_outbound_processing(qdio_q_t *q)
976 {
977 int siga_attempts;
978 #ifdef QDIO_DBF_LIKE_HELL
979 QDIO_DBF_TEXT4(0,trace,"qoutproc");
980 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
981 #endif /* QDIO_DBF_LIKE_HELL */
982
983 if (unlikely(qdio_reserve_q(q))) {
984 qdio_release_q(q);
985 #ifdef QDIO_PERFORMANCE_STATS
986 o_p_c++;
987 #endif /* QDIO_PERFORMANCE_STATS */
988 /* as we're sissies, we'll check next time */
989 if (likely(!atomic_read(&q->is_in_shutdown))) {
990 qdio_mark_q(q);
991 #ifdef QDIO_DBF_LIKE_HELL
992 QDIO_DBF_TEXT4(0,trace,"busy,agn");
993 #endif /* QDIO_DBF_LIKE_HELL */
994 }
995 return;
996 }
997 #ifdef QDIO_PERFORMANCE_STATS
998 o_p_nc++;
999 #endif /* QDIO_PERFORMANCE_STATS */
1000
1001 /* see comment in qdio_kick_outbound_q */
1002 siga_attempts=atomic_read(&q->busy_siga_counter);
1003 while (siga_attempts) {
1004 atomic_dec(&q->busy_siga_counter);
1005 qdio_kick_outbound_q(q);
1006 siga_attempts--;
1007 }
1008
1009 #ifdef QDIO_PERFORMANCE_STATS
1010 perf_stats.tl_runs++;
1011 #endif /* QDIO_PERFORMANCE_STATS */
1012
1013 if (qdio_has_outbound_q_moved(q)) {
1014 qdio_kick_outbound_handler(q);
1015 }
1016
1017 if (q->is_iqdio_q) {
1018 /* for asynchronous queues, we better check, if the fill
1019 * level is too high. for synchronous queues, the fill
1020 * level will never be that high. */
1021 if (atomic_read(&q->number_of_buffers_used)>
1022 IQDIO_FILL_LEVEL_TO_POLL) {
1023 qdio_mark_q(q);
1024 }
1025 } else if (!q->hydra_gives_outbound_pcis) {
1026 if (!qdio_is_outbound_q_done(q)) {
1027 qdio_mark_q(q);
1028 }
1029 }
1030
1031 qdio_release_q(q);
1032 }
1033
qdio_outbound_processing(qdio_q_t * q)1034 static void qdio_outbound_processing(qdio_q_t *q)
1035 {
1036 __qdio_outbound_processing(q);
1037 }
1038
1039 /************************* INBOUND ROUTINES *******************************/
1040
1041
qdio_get_inbound_buffer_frontier(qdio_q_t * q)1042 static inline int qdio_get_inbound_buffer_frontier(qdio_q_t *q)
1043 {
1044 int f,f_mod_no;
1045 volatile char *slsb;
1046 char slsbyte;
1047 int first_not_to_check;
1048 char dbf_text[15];
1049 #ifdef QDIO_USE_PROCESSING_STATE
1050 int last_position=-1;
1051 #endif /* QDIO_USE_PROCESSING_STATE */
1052
1053 #ifdef QDIO_DBF_LIKE_HELL
1054 QDIO_DBF_TEXT4(0,trace,"getibfro");
1055 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1056 #endif /* QDIO_DBF_LIKE_HELL */
1057
1058 slsb=&q->slsb.acc.val[0];
1059 f_mod_no=f=q->first_to_check;
1060 /* we don't check 128 buffers, as otherwise qdio_has_inbound_q_moved
1061 * would return 0 */
1062 first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
1063 (QDIO_MAX_BUFFERS_PER_Q-1));
1064
1065 /* we don't use this one, as a PCI or we after a thin interrupt
1066 * will sync the queues
1067 SYNC_MEMORY;*/
1068
1069 check_next:
1070 f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
1071 if (f==first_not_to_check) goto out;
1072 slsbyte=slsb[f_mod_no];
1073
1074 /* CU_EMPTY means frontier is reached */
1075 if (slsbyte==SLSB_CU_INPUT_EMPTY) {
1076 #ifdef QDIO_DBF_LIKE_HELL
1077 QDIO_DBF_TEXT5(0,trace,"inptempt");
1078 #endif /* QDIO_DBF_LIKE_HELL */
1079 goto out;
1080 }
1081
1082 /* P_PRIMED means set slsb to P_PROCESSING and move on */
1083 if (slsbyte==SLSB_P_INPUT_PRIMED) {
1084 #ifdef QDIO_DBF_LIKE_HELL
1085 QDIO_DBF_TEXT5(0,trace,"inptprim");
1086 #endif /* QDIO_DBF_LIKE_HELL */
1087
1088 #ifdef QDIO_USE_PROCESSING_STATE
1089 /* as soon as running under VM, polling the input queues will
1090 * kill VM in terms of CP overhead */
1091 if (q->siga_sync) {
1092 set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
1093 } else {
1094 /* set the previous buffer to NOT_INIT. The current
1095 * buffer will be set to PROCESSING at the end of
1096 * this function to avoid further interrupts. */
1097 if (last_position>=0)
1098 set_slsb(&slsb[last_position],
1099 SLSB_P_INPUT_NOT_INIT);
1100 atomic_set(&q->polling,1);
1101 last_position=f_mod_no;
1102 }
1103 #else /* QDIO_USE_PROCESSING_STATE */
1104 set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
1105 #endif /* QDIO_USE_PROCESSING_STATE */
1106 /* not needed, as the inbound queue will be synced on the next
1107 * siga-r
1108 SYNC_MEMORY;*/
1109 f++;
1110 atomic_dec(&q->number_of_buffers_used);
1111 goto check_next;
1112 }
1113
1114 if ( (slsbyte==SLSB_P_INPUT_NOT_INIT) ||
1115 (slsbyte==SLSB_P_INPUT_PROCESSING) ) {
1116 #ifdef QDIO_DBF_LIKE_HELL
1117 QDIO_DBF_TEXT5(0,trace,"inpnipro");
1118 #endif /* QDIO_DBF_LIKE_HELL */
1119 goto out;
1120 }
1121
1122 /* P_ERROR means frontier is reached, break and report error */
1123 if (slsbyte==SLSB_P_INPUT_ERROR) {
1124 sprintf(dbf_text,"inperr%2x",f_mod_no);
1125 QDIO_DBF_TEXT3(1,trace,dbf_text);
1126 QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
1127
1128 /* kind of process the buffer */
1129 set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
1130
1131 if (q->qdio_error)
1132 q->error_status_flags|=
1133 QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
1134 q->qdio_error=SLSB_P_INPUT_ERROR;
1135 q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
1136
1137 /* we increment the frontier, as this buffer
1138 * was processed obviously */
1139 f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
1140 atomic_dec(&q->number_of_buffers_used);
1141
1142 #ifdef QDIO_USE_PROCESSING_STATE
1143 last_position=-1;
1144 #endif /* QDIO_USE_PROCESSING_STATE */
1145
1146 goto out;
1147 }
1148
1149 /* everything else means frontier not changed (HALTED or so) */
1150 out:
1151 q->first_to_check=f_mod_no;
1152
1153 #ifdef QDIO_USE_PROCESSING_STATE
1154 if (last_position>=0)
1155 set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
1156 #endif /* QDIO_USE_PROCESSING_STATE */
1157
1158 #ifdef QDIO_DBF_LIKE_HELL
1159 QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
1160 #endif /* QDIO_DBF_LIKE_HELL */
1161
1162 return q->first_to_check;
1163 }
1164
qdio_has_inbound_q_moved(qdio_q_t * q)1165 static inline int qdio_has_inbound_q_moved(qdio_q_t *q)
1166 {
1167 int i;
1168
1169 #ifdef QDIO_PERFORMANCE_STATS
1170 static int old_pcis=0;
1171 static int old_thinints=0;
1172
1173 if ((old_pcis==perf_stats.pcis)&&(old_thinints==perf_stats.thinints))
1174 perf_stats.start_time_inbound=NOW;
1175 else
1176 old_pcis=perf_stats.pcis;
1177 #endif /* QDIO_PERFORMANCE_STATS */
1178
1179 i=qdio_get_inbound_buffer_frontier(q);
1180 if ( (i!=GET_SAVED_FRONTIER(q)) ||
1181 (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
1182 SAVE_FRONTIER(q,i);
1183 if ((!q->siga_sync)&&(!q->hydra_gives_outbound_pcis)) {
1184 SAVE_TIMESTAMP(q);
1185 }
1186
1187 #ifdef QDIO_DBF_LIKE_HELL
1188 QDIO_DBF_TEXT4(0,trace,"inhasmvd");
1189 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1190 #endif /* QDIO_DBF_LIKE_HELL */
1191 return 1;
1192 } else {
1193 #ifdef QDIO_DBF_LIKE_HELL
1194 QDIO_DBF_TEXT4(0,trace,"inhsntmv");
1195 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1196 #endif /* QDIO_DBF_LIKE_HELL */
1197 return 0;
1198 }
1199 }
1200
1201 /* means, no more buffers to be filled */
iqdio_is_inbound_q_done(qdio_q_t * q)1202 static inline int iqdio_is_inbound_q_done(qdio_q_t *q)
1203 {
1204 int no_used;
1205 #ifdef QDIO_DBF_LIKE_HELL
1206 char dbf_text[15];
1207 #endif /* QDIO_DBF_LIKE_HELL */
1208
1209 no_used=atomic_read(&q->number_of_buffers_used);
1210
1211 /* propagate the change from 82 to 80 through VM */
1212 SYNC_MEMORY;
1213
1214 #ifdef QDIO_DBF_LIKE_HELL
1215 if (no_used) {
1216 sprintf(dbf_text,"iqisnt%02x",no_used);
1217 QDIO_DBF_TEXT4(0,trace,dbf_text);
1218 } else {
1219 QDIO_DBF_TEXT4(0,trace,"iniqisdo");
1220 }
1221 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1222 #endif /* QDIO_DBF_LIKE_HELL */
1223
1224 if (!no_used) {
1225 return 1;
1226 }
1227
1228 if (q->siga_sync) {
1229 if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) {
1230 /* ok, the next input buffer is primed. that means,
1231 * that device state change indicator and adapter
1232 * local summary are set, so we will find it next
1233 * time.
1234 * we will return 0 below, as there is nothing to
1235 * do, except of scheduling ourselves for the next
1236 * time. */
1237 tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
1238 tiqdio_sched_tl();
1239 } else {
1240 /* nothing more to do, if next buffer is not PRIMED.
1241 * note that we did a SYNC_MEMORY before, that there
1242 * has been a sychnronization.
1243 * we will return 0 below, as there is nothing to do
1244 * (stop_polling not necessary, as we have not been
1245 * using the PROCESSING state */
1246 }
1247 } else {
1248 /* we'll check for more primed buffers
1249 * in qeth_stop_polling */
1250 }
1251
1252 return 0;
1253 }
1254
qdio_is_inbound_q_done(qdio_q_t * q)1255 static inline int qdio_is_inbound_q_done(qdio_q_t *q)
1256 {
1257 int no_used;
1258 #ifdef QDIO_DBF_LIKE_HELL
1259 char dbf_text[15];
1260 #endif /* QDIO_DBF_LIKE_HELL */
1261
1262 no_used=atomic_read(&q->number_of_buffers_used);
1263
1264 /* we need that one for synchronization with the OSA/FCP card, as it
1265 * does a kind of PCI avoidance */
1266 SYNC_MEMORY;
1267
1268 if (!no_used) {
1269 #ifdef QDIO_DBF_LIKE_HELL
1270 QDIO_DBF_TEXT4(0,trace,"inqisdnA");
1271 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1272 QDIO_DBF_TEXT4(0,trace,dbf_text);
1273 #endif /* QDIO_DBF_LIKE_HELL */
1274 return 1;
1275 }
1276
1277 if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) {
1278 /* we got something to do */
1279 #ifdef QDIO_DBF_LIKE_HELL
1280 QDIO_DBF_TEXT4(0,trace,"inqisntA");
1281 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1282 #endif /* QDIO_DBF_LIKE_HELL */
1283 return 0;
1284 }
1285
1286 /* on VM, we don't poll, so the q is always done here */
1287 if (q->siga_sync) return 1;
1288 if (q->hydra_gives_outbound_pcis) return 1;
1289
1290 /* at this point we know, that inbound first_to_check
1291 has (probably) not moved (see qdio_inbound_processing) */
1292 if (NOW>GET_SAVED_TIMESTAMP(q)+q->timing.threshold) {
1293 #ifdef QDIO_DBF_LIKE_HELL
1294 QDIO_DBF_TEXT4(0,trace,"inqisdon");
1295 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1296 sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used);
1297 QDIO_DBF_TEXT4(0,trace,dbf_text);
1298 #endif /* QDIO_DBF_LIKE_HELL */
1299 return 1;
1300 } else {
1301 #ifdef QDIO_DBF_LIKE_HELL
1302 QDIO_DBF_TEXT4(0,trace,"inqisntd");
1303 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1304 sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used);
1305 QDIO_DBF_TEXT4(0,trace,dbf_text);
1306 #endif /* QDIO_DBF_LIKE_HELL */
1307 return 0;
1308 }
1309 }
1310
qdio_kick_inbound_handler(qdio_q_t * q)1311 static inline void qdio_kick_inbound_handler(qdio_q_t *q)
1312 {
1313 int count=0;
1314 int start,end,real_end,i;
1315 #ifdef QDIO_DBF_LIKE_HELL
1316 char dbf_text[15];
1317
1318 QDIO_DBF_TEXT4(0,trace,"kickinh");
1319 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1320 #endif /* QDIO_DBF_LIKE_HELL */
1321
1322 start=q->first_element_to_kick;
1323 real_end=q->first_to_check;
1324 end=(real_end+QDIO_MAX_BUFFERS_PER_Q-1)&(QDIO_MAX_BUFFERS_PER_Q-1);
1325
1326 i=start;
1327 while (1) {
1328 count++;
1329 qdio_translate_buffer_back(q,i);
1330 if (i==end) break;
1331 i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
1332 }
1333
1334 #ifdef QDIO_DBF_LIKE_HELL
1335 sprintf(dbf_text,"s=%2xc=%2x",start,count);
1336 QDIO_DBF_TEXT4(0,trace,dbf_text);
1337 #endif /* QDIO_DBF_LIKE_HELL */
1338
1339 if (likely(q->state==QDIO_IRQ_STATE_ACTIVE))
1340 q->handler(q->irq,
1341 QDIO_STATUS_INBOUND_INT|q->error_status_flags,
1342 q->qdio_error,q->siga_error,q->q_no,start,count,
1343 q->int_parm);
1344
1345 /* for the next time: */
1346 q->first_element_to_kick=real_end;
1347 q->qdio_error=0;
1348 q->siga_error=0;
1349 q->error_status_flags=0;
1350
1351 #ifdef QDIO_PERFORMANCE_STATS
1352 perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
1353 perf_stats.inbound_cnt++;
1354 #endif /* QDIO_PERFORMANCE_STATS */
1355 }
1356
__tiqdio_inbound_processing(qdio_q_t * q,int spare_ind_was_set)1357 static inline void __tiqdio_inbound_processing(qdio_q_t *q,
1358 int spare_ind_was_set)
1359 {
1360 qdio_irq_t *irq_ptr;
1361 qdio_q_t *oq;
1362 int i;
1363
1364 #ifdef QDIO_DBF_LIKE_HELL
1365 QDIO_DBF_TEXT4(0,trace,"iqinproc");
1366 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1367 #endif /* QDIO_DBF_LIKE_HELL */
1368
1369 /* we first want to reserve the q, so that we know, that we don't
1370 * interrupt ourselves and call qdio_unmark_q, as is_in_shutdown might
1371 * be set */
1372 if (unlikely(qdio_reserve_q(q))) {
1373 qdio_release_q(q);
1374 #ifdef QDIO_PERFORMANCE_STATS
1375 ii_p_c++;
1376 #endif /* QDIO_PERFORMANCE_STATS */
1377 /* as we might just be about to stop polling, we make
1378 * sure that we check again at least once more */
1379 tiqdio_sched_tl();
1380 return;
1381 }
1382 #ifdef QDIO_PERFORMANCE_STATS
1383 ii_p_nc++;
1384 #endif /* QDIO_PERFORMANCE_STATS */
1385 if (unlikely(atomic_read(&q->is_in_shutdown))) {
1386 qdio_unmark_q(q);
1387 goto out;
1388 }
1389
1390 /* we reset spare_ind_was_set, when the queue does not use the
1391 * spare indicator */
1392 if (spare_ind_was_set) {
1393 spare_ind_was_set==(q->dev_st_chg_ind==&spare_indicator);
1394 }
1395
1396 if ( (*(q->dev_st_chg_ind)) || (spare_ind_was_set) ) {
1397 /* q->dev_st_chg_ind is the indicator, be it shared or not.
1398 * only clear it, if indicator is non-shared */
1399 if (!spare_ind_was_set) {
1400 tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
1401 }
1402
1403 if (q->hydra_gives_outbound_pcis) {
1404 if (!q->siga_sync_done_on_thinints) {
1405 SYNC_MEMORY_ALL;
1406 } else if ((!q->siga_sync_done_on_outb_tis)&&
1407 (q->hydra_gives_outbound_pcis)) {
1408 SYNC_MEMORY_ALL_OUTB;
1409 }
1410 } else {
1411 SYNC_MEMORY;
1412 }
1413
1414 /* maybe we have to do work on our outbound queues... at least
1415 * we have to check for outbound-int-capable thinint-capable
1416 * queues */
1417 if (q->hydra_gives_outbound_pcis) {
1418 irq_ptr=(qdio_irq_t*)q->irq_ptr;
1419 for (i=0;i<irq_ptr->no_output_qs;i++) {
1420 oq=irq_ptr->output_qs[i];
1421 #ifdef QDIO_PERFORMANCE_STATS
1422 perf_stats.tl_runs--;
1423 #endif /* QDIO_PERFORMANCE_STATS */
1424 if (!qdio_is_outbound_q_done(oq)) {
1425 __qdio_outbound_processing(oq);
1426 }
1427 }
1428 }
1429
1430 if (qdio_has_inbound_q_moved(q)) {
1431 qdio_kick_inbound_handler(q);
1432 if (iqdio_is_inbound_q_done(q)) {
1433 if (!qdio_stop_polling(q)) {
1434 /* we set the flags to get into
1435 * the stuff next time, see also
1436 * comment in qdio_stop_polling */
1437 tiqdio_set_summary_bit
1438 ((__u32*)q->dev_st_chg_ind);
1439 tiqdio_sched_tl();
1440 }
1441 }
1442 }
1443 }
1444 out:
1445 qdio_release_q(q);
1446 }
1447
tiqdio_inbound_processing(qdio_q_t * q)1448 static void tiqdio_inbound_processing(qdio_q_t *q)
1449 {
1450 __tiqdio_inbound_processing(q,atomic_read(&spare_indicator_usecount));
1451 }
1452
__qdio_inbound_processing(qdio_q_t * q)1453 static inline void __qdio_inbound_processing(qdio_q_t *q)
1454 {
1455 int q_laps=0;
1456
1457 #ifdef QDIO_DBF_LIKE_HELL
1458 QDIO_DBF_TEXT4(0,trace,"qinproc");
1459 QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
1460 #endif /* QDIO_DBF_LIKE_HELL */
1461
1462 if (unlikely(qdio_reserve_q(q))) {
1463 qdio_release_q(q);
1464 #ifdef QDIO_PERFORMANCE_STATS
1465 i_p_c++;
1466 #endif /* QDIO_PERFORMANCE_STATS */
1467 /* as we're sissies, we'll check next time */
1468 if (likely(!atomic_read(&q->is_in_shutdown))) {
1469 qdio_mark_q(q);
1470 #ifdef QDIO_DBF_LIKE_HELL
1471 QDIO_DBF_TEXT4(0,trace,"busy,agn");
1472 #endif /* QDIO_DBF_LIKE_HELL */
1473 }
1474 return;
1475 }
1476 #ifdef QDIO_PERFORMANCE_STATS
1477 i_p_nc++;
1478 perf_stats.tl_runs++;
1479 #endif /* QDIO_PERFORMANCE_STATS */
1480
1481 again:
1482 if (qdio_has_inbound_q_moved(q)) {
1483 qdio_kick_inbound_handler(q);
1484 if (!qdio_stop_polling(q)) {
1485 q_laps++;
1486 if (q_laps<QDIO_Q_LAPS) goto again;
1487 }
1488 qdio_mark_q(q);
1489 } else {
1490 if (!qdio_is_inbound_q_done(q)) /* means poll time is
1491 not yet over */
1492 qdio_mark_q(q);
1493 }
1494
1495 qdio_release_q(q);
1496 }
1497
qdio_inbound_processing(qdio_q_t * q)1498 static void qdio_inbound_processing(qdio_q_t *q)
1499 {
1500 __qdio_inbound_processing(q);
1501 }
1502
1503 /************************* MAIN ROUTINES *******************************/
1504
tiqdio_inbound_checks(void)1505 static inline void tiqdio_inbound_checks(void)
1506 {
1507 qdio_q_t *q;
1508 int spare_ind_was_set=0;
1509 #ifdef QDIO_USE_PROCESSING_STATE
1510 int q_laps=0;
1511 #endif /* QDIO_USE_PROCESSING_STATE */
1512
1513 #ifdef QDIO_DBF_LIKE_HELL
1514 char dbf_text[15];
1515
1516 QDIO_DBF_TEXT4(0,trace,"iqdinbck");
1517 #endif /* QDIO_DBF_LIKE_HELL */
1518
1519 #ifdef QDIO_DBF_LIKE_HELL
1520 QDIO_DBF_TEXT5(0,trace,"iqlocsum");
1521 #endif /* QDIO_DBF_LIKE_HELL */
1522
1523 #ifdef QDIO_USE_PROCESSING_STATE
1524 again:
1525 #endif /* QDIO_USE_PROCESSING_STATE */
1526
1527 /* when the spare indicator is used and set, save that and clear it */
1528 if ( (atomic_read(&spare_indicator_usecount)) && (spare_indicator) ) {
1529 spare_ind_was_set=1;
1530 tiqdio_clear_summary_bit((__u32*)&spare_indicator);
1531 }
1532
1533 q=(qdio_q_t*)tiq_list;
1534 /* switch all active queues to processing state */
1535 do {
1536 if (!q) break;
1537 __tiqdio_inbound_processing(q,spare_ind_was_set);
1538 q=(qdio_q_t*)q->list_next;
1539 } while (q!=(qdio_q_t*)tiq_list);
1540
1541 /* switch off all queues' processing state, see comments in
1542 * qdio_get_inbound_buffer_frontier */
1543 #ifdef QDIO_USE_PROCESSING_STATE
1544 q=(qdio_q_t*)tiq_list;
1545 do {
1546 if (!q) {
1547 tiqdio_sched_tl();
1548 break;
1549 }
1550 /* under VM, we have not used the PROCESSING state, so no
1551 * need to stop polling */
1552 if (q->siga_sync) {
1553 q=(qdio_q_t*)q->list_next;
1554 continue;
1555 }
1556
1557 if (unlikely(qdio_reserve_q(q))) {
1558 qdio_release_q(q);
1559 #ifdef QDIO_PERFORMANCE_STATS
1560 ii_p_c++;
1561 #endif /* QDIO_PERFORMANCE_STATS */
1562 /* as we might just be about to stop polling, we make
1563 * sure that we check again at least once more */
1564
1565 /* sanity -- we'd get here without setting the
1566 * dev st chg ind */
1567 tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
1568 tiqdio_sched_tl();
1569 break;
1570 }
1571 if (!qdio_stop_polling(q)) {
1572 q_laps++;
1573 if (q_laps<QDIO_Q_LAPS) {
1574 qdio_release_q(q);
1575 goto again;
1576 } else {
1577 /* we set the flags to get into the stuff
1578 * next time, see also comment in
1579 * qdio_stop_polling */
1580 tiqdio_set_summary_bit((__u32*)
1581 q->dev_st_chg_ind);
1582 tiqdio_sched_tl();
1583 }
1584 }
1585 qdio_release_q(q);
1586 q=(qdio_q_t*)q->list_next;
1587 } while (q!=(qdio_q_t*)tiq_list);
1588 #endif /* QDIO_USE_PROCESSING_STATE */
1589 }
1590
tiqdio_tl(unsigned long data)1591 static void tiqdio_tl(unsigned long data)
1592 {
1593 #ifdef QDIO_DBF_LIKE_HELL
1594 QDIO_DBF_TEXT4(0,trace,"tiqdio_tl");
1595 #endif /* QDIO_DBF_LIKE_HELL */
1596 #ifdef QDIO_PERFORMANCE_STATS
1597 perf_stats.tl_runs++;
1598 #endif /* QDIO_PERFORMANCE_STATS */
1599
1600 tiqdio_inbound_checks();
1601 }
1602
1603 /********************* GENERAL HELPER_ROUTINES ***********************/
1604
qdio_get_irq_ptr(int irq)1605 static qdio_irq_t *qdio_get_irq_ptr(int irq)
1606 {
1607 qdio_irq_t *irq_ptr;
1608 int bucket=irq&(QDIO_IRQ_BUCKETS-1);
1609
1610 read_lock(&irq_list_lock[bucket]);
1611 irq_ptr=first_irq[bucket];
1612 while (irq_ptr) {
1613 if (irq_ptr->irq==irq) break;
1614 irq_ptr=irq_ptr->next;
1615 }
1616 read_unlock(&irq_list_lock[bucket]);
1617 return irq_ptr;
1618 }
1619
qdio_get_irq_ptr_wolock(int irq)1620 static qdio_irq_t *qdio_get_irq_ptr_wolock(int irq)
1621 {
1622 qdio_irq_t *irq_ptr=first_irq[irq&(QDIO_IRQ_BUCKETS-1)];
1623
1624 while (irq_ptr) {
1625 if (irq_ptr->irq==irq) break;
1626 irq_ptr=irq_ptr->next;
1627 }
1628 return irq_ptr;
1629 }
1630
1631 /* irq_ptr->irq should be set already! */
qdio_insert_irq_ptr(qdio_irq_t * irq_ptr)1632 static void qdio_insert_irq_ptr(qdio_irq_t *irq_ptr)
1633 {
1634 qdio_irq_t *i_p;
1635 int irq,bucket;
1636
1637 if (!irq_ptr) return;
1638
1639 irq=irq_ptr->irq;
1640 bucket=irq&(QDIO_IRQ_BUCKETS-1);
1641
1642 write_lock(&irq_list_lock[bucket]);
1643
1644 if (irq_ptr==qdio_get_irq_ptr_wolock(irq)) goto out;
1645
1646 if (!first_irq[bucket]) {
1647 first_irq[bucket]=irq_ptr;
1648 } else {
1649 i_p=first_irq[bucket];
1650 while (i_p->next)
1651 i_p=i_p->next;
1652 i_p->next=irq_ptr;
1653 }
1654 irq_ptr->next=NULL;
1655 out:
1656 write_unlock(&irq_list_lock[bucket]);
1657 }
1658
qdio_remove_irq_ptr(qdio_irq_t * irq_ptr)1659 static void qdio_remove_irq_ptr(qdio_irq_t *irq_ptr)
1660 {
1661 qdio_irq_t *i_p;
1662 int irq,bucket;
1663
1664 if (!irq_ptr) return;
1665
1666 irq=irq_ptr->irq;
1667 bucket=irq&(QDIO_IRQ_BUCKETS-1);
1668
1669 write_lock(&irq_list_lock[bucket]);
1670
1671 if (!qdio_get_irq_ptr_wolock(irq)) goto out;
1672
1673 if (first_irq[irq&(QDIO_IRQ_BUCKETS-1)]==irq_ptr) {
1674 first_irq[irq&(QDIO_IRQ_BUCKETS-1)]=irq_ptr->next;
1675 } else {
1676 for (i_p=first_irq[irq&(QDIO_IRQ_BUCKETS-1)];
1677 i_p->next!=irq_ptr;i_p=i_p->next);
1678 i_p->next=irq_ptr->next;
1679 }
1680 irq_ptr->next=NULL;
1681 out:
1682 write_unlock(&irq_list_lock[bucket]);
1683 }
1684
qdio_release_irq_memory(qdio_irq_t * irq_ptr)1685 static void qdio_release_irq_memory(qdio_irq_t *irq_ptr)
1686 {
1687 int i,j;
1688 int available;
1689
1690 for (i=0;i<QDIO_MAX_QUEUES_PER_IRQ;i++) {
1691 if (!irq_ptr->input_qs[i]) goto next;
1692 available=0;
1693 if (!irq_ptr->input_qs[i]->is_0copy_sbals_q)
1694 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1695 if (!available) {
1696 if (irq_ptr->input_qs[i]->sbal[j])
1697 kfree((void*)irq_ptr->
1698 input_qs[i]->sbal[j]);
1699 available=PAGE_SIZE;
1700 }
1701 available-=sizeof(sbal_t);
1702 }
1703 if (irq_ptr->input_qs[i]->slib)
1704 kfree(irq_ptr->input_qs[i]->slib);
1705 kfree(irq_ptr->input_qs[i]);
1706
1707 next:
1708 if (!irq_ptr->output_qs[i]) continue;
1709 available=0;
1710 if (!irq_ptr->output_qs[i]->is_0copy_sbals_q)
1711 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1712 if (!available) {
1713 if (irq_ptr->output_qs[i]->sbal[j])
1714 kfree((void*)irq_ptr->
1715 output_qs[i]->sbal[j]);
1716 available=PAGE_SIZE;
1717 }
1718 available-=sizeof(sbal_t);
1719 }
1720 if (irq_ptr->output_qs[i]->slib)
1721 kfree(irq_ptr->output_qs[i]->slib);
1722 kfree(irq_ptr->output_qs[i]);
1723
1724 }
1725 kfree(irq_ptr->qdr);
1726 kfree(irq_ptr);
1727 }
1728
qdio_wakeup(atomic_t * var,qdio_irq_t * irq_ptr)1729 static inline void qdio_wakeup(atomic_t *var,qdio_irq_t *irq_ptr)
1730 {
1731 wait_queue_head_t *wait_q;
1732
1733 #ifdef QDIO_DBF_LIKE_HELL
1734 char dbf_text[20];
1735 sprintf(dbf_text,"qwkp%4x",irq_ptr->irq);
1736 QDIO_DBF_TEXT3(0,trace,dbf_text);
1737 #endif /* QDIO_DBF_LIKE_HELL */
1738
1739 atomic_set(var,1);
1740 if ((wait_q=&irq_ptr->wait_q))
1741 wake_up(wait_q);
1742 }
1743
qdio_sleepon(atomic_t * var,int timeout,qdio_irq_t * irq_ptr)1744 static int qdio_sleepon(atomic_t *var,int timeout,qdio_irq_t *irq_ptr)
1745 {
1746 __u64 stop;
1747 int retval;
1748 DECLARE_WAITQUEUE (current_wait_q,current);
1749
1750 #ifdef QDIO_DBF_LIKE_HELL
1751 char dbf_text[20];
1752 sprintf(dbf_text,"qslp%4x",irq_ptr->irq);
1753 QDIO_DBF_TEXT3(0,trace,dbf_text);
1754 #endif /* QDIO_DBF_LIKE_HELL */
1755
1756 add_wait_queue(&irq_ptr->wait_q,¤t_wait_q);
1757 stop=(qdio_get_micros()>>10)+timeout;
1758 for (;;) {
1759 set_task_state(current,TASK_INTERRUPTIBLE);
1760 if (atomic_read(var)) {
1761 atomic_set(var,0);
1762 retval=0;
1763 goto out;
1764 }
1765 if (qdio_get_micros()>>10>stop) {
1766 #ifdef QDIO_DBF_LIKE_HELL
1767 sprintf(dbf_text,"%xtime",irq_ptr->irq);
1768 QDIO_DBF_TEXT3(0,trace,dbf_text);
1769 #endif /* QDIO_DBF_LIKE_HELL */
1770 retval=-ETIME;
1771 goto out;
1772 }
1773 schedule_timeout(((stop-(qdio_get_micros()>>10))>>10)*HZ);
1774 }
1775 out:
1776 set_task_state(current,TASK_RUNNING);
1777 remove_wait_queue(&irq_ptr->wait_q,¤t_wait_q);
1778 return retval;
1779 }
1780
qdio_set_impl_params(qdio_irq_t * irq_ptr,unsigned int qib_param_field_format,unsigned char * qib_param_field,unsigned int no_input_qs,unsigned int no_output_qs,unsigned long * input_slib_elements,unsigned long * output_slib_elements)1781 static void qdio_set_impl_params(qdio_irq_t *irq_ptr,
1782 unsigned int qib_param_field_format,
1783 /* pointer to 128 bytes or NULL, if no param field */
1784 unsigned char *qib_param_field,
1785 unsigned int no_input_qs,
1786 unsigned int no_output_qs,
1787 /* pointer to no_queues*128 words of data or NULL */
1788 unsigned long *input_slib_elements,
1789 unsigned long *output_slib_elements)
1790 {
1791 int i,j;
1792
1793 if (!irq_ptr) return;
1794
1795 irq_ptr->qib.pfmt=qib_param_field_format;
1796 if (qib_param_field)
1797 memcpy(irq_ptr->qib.parm,qib_param_field,
1798 QDIO_MAX_BUFFERS_PER_Q);
1799
1800 if (input_slib_elements)
1801 for (i=0;i<no_input_qs;i++) {
1802 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)
1803 irq_ptr->input_qs[i]->slib->slibe[j].parms=
1804 input_slib_elements[
1805 i*QDIO_MAX_BUFFERS_PER_Q+j];
1806 }
1807 if (output_slib_elements)
1808 for (i=0;i<no_output_qs;i++) {
1809 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)
1810 irq_ptr->output_qs[i]->slib->slibe[j].parms=
1811 output_slib_elements[
1812 i*QDIO_MAX_BUFFERS_PER_Q+j];
1813 }
1814 }
1815
1816
1817
qdio_alloc_qs(qdio_irq_t * irq_ptr,int no_input_qs,int no_output_qs,qdio_handler_t * input_handler,qdio_handler_t * output_handler,unsigned long int_parm,int q_format,unsigned long flags,void ** inbound_sbals_array,void ** outbound_sbals_array)1818 static int qdio_alloc_qs(qdio_irq_t *irq_ptr,int no_input_qs,int no_output_qs,
1819 qdio_handler_t *input_handler,
1820 qdio_handler_t *output_handler,
1821 unsigned long int_parm,int q_format,
1822 unsigned long flags,
1823 void **inbound_sbals_array,
1824 void **outbound_sbals_array)
1825 {
1826 qdio_q_t *q;
1827 int i,j,result=0;
1828 char dbf_text[20]; /* see qdio_initialize */
1829 void *ptr;
1830 int available;
1831
1832 for (i=0;i<no_input_qs;i++) {
1833 q=kmalloc(sizeof(qdio_q_t),GFP_KERNEL);
1834
1835 if (!q) {
1836 QDIO_PRINT_ERR("kmalloc of q failed!\n");
1837 goto out;
1838 }
1839 memset(q,0,sizeof(qdio_q_t));
1840
1841 sprintf(dbf_text,"in-q%4x",i);
1842 QDIO_DBF_TEXT0(0,setup,dbf_text);
1843 QDIO_DBF_HEX0(0,setup,&q,sizeof(void*));
1844
1845 q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);
1846 if (!q->slib) {
1847 QDIO_PRINT_ERR("kmalloc of slib failed!\n");
1848 goto out;
1849 }
1850 memset(q->slib,0,PAGE_SIZE);
1851 q->sl=(sl_t*)(((char*)q->slib)+PAGE_SIZE/2);
1852
1853 available=0;
1854 if (flags&QDIO_INBOUND_0COPY_SBALS) {
1855 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1856 q->sbal[j]=*(inbound_sbals_array++);
1857 }
1858 } else for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1859 if (!available) {
1860 q->sbal[j]=kmalloc(PAGE_SIZE,GFP_KERNEL);
1861 if (!q->sbal[j]) {
1862 goto out;
1863 }
1864 available=PAGE_SIZE;
1865 memset((void*)q->sbal[j],0,PAGE_SIZE);
1866 } else {
1867 q->sbal[j]=(volatile sbal_t *)
1868 (((char*)q->sbal[j-1])+sizeof(sbal_t));
1869 }
1870 available-=sizeof(sbal_t);
1871 }
1872
1873 q->queue_type=q_format;
1874 q->int_parm=int_parm;
1875 irq_ptr->input_qs[i]=q;
1876 q->irq=irq_ptr->irq;
1877 q->irq_ptr=irq_ptr;
1878 q->mask=1<<(31-i);
1879 q->q_no=i;
1880 q->is_input_q=1;
1881 q->is_0copy_sbals_q=flags&QDIO_INBOUND_0COPY_SBALS;
1882 q->first_to_check=0;
1883 q->last_move_ftc=0;
1884 q->handler=input_handler;
1885 q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind;
1886
1887 q->tasklet.data=(unsigned long)q;
1888 /* q->is_thinint_q isn't valid at this time, but
1889 * irq_ptr->is_thinint_irq is */
1890 q->tasklet.func=(void(*)(unsigned long))
1891 ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
1892 &qdio_inbound_processing);
1893
1894 /* actually this is not used for inbound queues. yet. */
1895 atomic_set(&q->busy_siga_counter,0);
1896 q->timing.busy_start=0;
1897
1898 /* for (j=0;j<QDIO_STATS_NUMBER;j++)
1899 q->timing.last_transfer_times[j]=(qdio_get_micros()/
1900 QDIO_STATS_NUMBER)*j;
1901 q->timing.last_transfer_index=QDIO_STATS_NUMBER-1;
1902 */
1903
1904 /* fill in slib */
1905 if (i>0) irq_ptr->input_qs[i-1]->slib->nsliba=
1906 QDIO_PFIX_GET_ADDR(q->slib);
1907 q->slib->sla=QDIO_PFIX_GET_ADDR(q->sl);
1908 q->slib->slsba=QDIO_PFIX_GET_ADDR((void *)&q->slsb.acc.val[0]);
1909
1910 /* fill in sl */
1911 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)
1912 q->sl->element[j].sbal=
1913 QDIO_PFIX_GET_ADDR((void *)q->sbal[j]);
1914
1915 QDIO_DBF_TEXT2(0,setup,"sl-sb-b0");
1916 ptr=(void*)q->sl;
1917 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
1918 ptr=(void*)&q->slsb;
1919 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
1920 ptr=(void*)q->sbal[0];
1921 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
1922
1923 /* fill in slsb */
1924 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1925 set_slsb(&q->slsb.acc.val[j],
1926 SLSB_P_INPUT_NOT_INIT);
1927 q->sbal[j]->element[1].sbalf.i1.key=
1928 QDIO_STORAGE_ACC_KEY;
1929 }
1930 }
1931
1932 for (i=0;i<no_output_qs;i++) {
1933 q=kmalloc(sizeof(qdio_q_t),GFP_KERNEL);
1934
1935 if (!q) {
1936 goto out;
1937 }
1938 memset(q,0,sizeof(qdio_q_t));
1939
1940 sprintf(dbf_text,"outq%4x",i);
1941 QDIO_DBF_TEXT0(0,setup,dbf_text);
1942 QDIO_DBF_HEX0(0,setup,&q,sizeof(void*));
1943
1944 q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);
1945 if (!q->slib) {
1946 QDIO_PRINT_ERR("kmalloc of slib failed!\n");
1947 goto out;
1948 }
1949 memset(q->slib,0,PAGE_SIZE);
1950 q->sl=(sl_t*)(((char*)q->slib)+PAGE_SIZE/2);
1951
1952 available=0;
1953 if (flags&QDIO_OUTBOUND_0COPY_SBALS) {
1954 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1955 q->sbal[j]=*(outbound_sbals_array++);
1956 }
1957 } else for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
1958 if (!available) {
1959 q->sbal[j]=kmalloc(PAGE_SIZE,GFP_KERNEL);
1960 if (!q->sbal[j]) {
1961 goto out;
1962 }
1963 available=PAGE_SIZE;
1964 memset((void*)q->sbal[j],0,PAGE_SIZE);
1965 } else {
1966 q->sbal[j]=(volatile sbal_t *)
1967 (((char*)q->sbal[j-1])+sizeof(sbal_t));
1968 }
1969 available-=sizeof(sbal_t);
1970 }
1971
1972 q->queue_type=q_format;
1973 q->int_parm=int_parm;
1974 irq_ptr->output_qs[i]=q;
1975 q->is_input_q=0;
1976 q->is_0copy_sbals_q=flags&QDIO_OUTBOUND_0COPY_SBALS;
1977 q->irq=irq_ptr->irq;
1978 q->irq_ptr=irq_ptr;
1979 q->mask=1<<(31-i);
1980 q->q_no=i;
1981 q->first_to_check=0;
1982 q->last_move_ftc=0;
1983 q->handler=output_handler;
1984
1985 q->tasklet.data=(unsigned long)q;
1986 q->tasklet.func=(void(*)(unsigned long))
1987 &qdio_outbound_processing;
1988
1989 atomic_set(&q->busy_siga_counter,0);
1990 q->timing.busy_start=0;
1991
1992 /* fill in slib */
1993 if (i>0) irq_ptr->output_qs[i-1]->slib->nsliba=
1994 QDIO_PFIX_GET_ADDR(q->slib);
1995 q->slib->sla=QDIO_PFIX_GET_ADDR(q->sl);
1996 q->slib->slsba=QDIO_PFIX_GET_ADDR((void *)&q->slsb.acc.val[0]);
1997
1998 /* fill in sl */
1999 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)
2000 q->sl->element[j].sbal=
2001 QDIO_PFIX_GET_ADDR((void *)q->sbal[j]);
2002
2003 QDIO_DBF_TEXT2(0,setup,"sl-sb-b0");
2004 ptr=(void*)q->sl;
2005 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
2006 ptr=(void*)&q->slsb;
2007 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
2008 ptr=(void*)q->sbal[0];
2009 QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
2010
2011 /* fill in slsb */
2012 for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
2013 set_slsb(&q->slsb.acc.val[j],
2014 SLSB_P_OUTPUT_NOT_INIT);
2015 q->sbal[j]->element[1].sbalf.i1.key=
2016 QDIO_STORAGE_ACC_KEY;
2017 }
2018 }
2019
2020 result=1;
2021 out:
2022 return result;
2023 }
2024
qdio_fill_thresholds(qdio_irq_t * irq_ptr,unsigned int no_input_qs,unsigned int no_output_qs,unsigned int min_input_threshold,unsigned int max_input_threshold,unsigned int min_output_threshold,unsigned int max_output_threshold)2025 static void qdio_fill_thresholds(qdio_irq_t *irq_ptr,
2026 unsigned int no_input_qs,
2027 unsigned int no_output_qs,
2028 unsigned int min_input_threshold,
2029 unsigned int max_input_threshold,
2030 unsigned int min_output_threshold,
2031 unsigned int max_output_threshold)
2032 {
2033 int i;
2034 qdio_q_t *q;
2035
2036 for (i=0;i<no_input_qs;i++) {
2037 q=irq_ptr->input_qs[i];
2038 q->timing.threshold=max_input_threshold;
2039 /* for (j=0;j<QDIO_STATS_CLASSES;j++) {
2040 q->threshold_classes[j].threshold=
2041 min_input_threshold+
2042 (max_input_threshold-min_input_threshold)/
2043 QDIO_STATS_CLASSES;
2044 }
2045 qdio_use_thresholds(q,QDIO_STATS_CLASSES/2);*/
2046 }
2047 for (i=0;i<no_output_qs;i++) {
2048 q=irq_ptr->output_qs[i];
2049 q->timing.threshold=max_output_threshold;
2050 /* for (j=0;j<QDIO_STATS_CLASSES;j++) {
2051 q->threshold_classes[j].threshold=
2052 min_output_threshold+
2053 (max_output_threshold-min_output_threshold)/
2054 QDIO_STATS_CLASSES;
2055 }
2056 qdio_use_thresholds(q,QDIO_STATS_CLASSES/2);*/
2057 }
2058 }
2059
tiqdio_thinint_handler(__u32 intparm)2060 static int tiqdio_thinint_handler(__u32 intparm)
2061 {
2062 #ifdef QDIO_DBF_LIKE_HELL
2063 QDIO_DBF_TEXT4(0,trace,"thin_int");
2064 #endif /* QDIO_DBF_LIKE_HELL */
2065
2066 #ifdef QDIO_PERFORMANCE_STATS
2067 perf_stats.thinints++;
2068 perf_stats.start_time_inbound=NOW;
2069 #endif /* QDIO_PERFORMANCE_STATS */
2070
2071 /* SVS only when needed:
2072 * issue SVS to benefit from iqdio interrupt avoidance
2073 * (SVS clears AISOI)*/
2074 if (!omit_svs) {
2075 tiqdio_clear_global_summary();
2076 }
2077
2078 tiqdio_inbound_checks();
2079 return 0;
2080 }
2081
qdio_set_state(qdio_irq_t * irq_ptr,int state)2082 static void qdio_set_state(qdio_irq_t *irq_ptr,int state)
2083 {
2084 int i;
2085 char dbf_text[15];
2086
2087 QDIO_DBF_TEXT5(0,trace,"newstate");
2088 sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state);
2089 QDIO_DBF_TEXT5(0,trace,dbf_text);
2090
2091 irq_ptr->state=state;
2092 for (i=0;i<irq_ptr->no_input_qs;i++)
2093 irq_ptr->input_qs[i]->state=state;
2094 for (i=0;i<irq_ptr->no_output_qs;i++)
2095 irq_ptr->output_qs[i]->state=state;
2096 mb();
2097 }
2098
qdio_handler(int irq,devstat_t * devstat,struct pt_regs * p)2099 static void qdio_handler(int irq,devstat_t *devstat,struct pt_regs *p)
2100 {
2101 qdio_irq_t *irq_ptr;
2102 qdio_q_t *q;
2103 int i;
2104 int cstat,dstat;
2105 int rqparam;
2106 char dbf_text[15]="qintXXXX";
2107
2108 cstat = devstat->cstat;
2109 dstat = devstat->dstat;
2110 rqparam=devstat->intparm;
2111
2112 *((int*)(&dbf_text[4]))=irq;
2113 QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
2114
2115 if (!rqparam) {
2116 QDIO_PRINT_STUPID("got unsolicited interrupt in qdio " \
2117 "handler, irq 0x%x\n",irq);
2118 return;
2119 }
2120
2121 irq_ptr=qdio_get_irq_ptr(irq);
2122 if (!irq_ptr) {
2123 sprintf(dbf_text,"uint%4x",irq);
2124 QDIO_DBF_TEXT2(1,trace,dbf_text);
2125 QDIO_PRINT_ERR("received interrupt on unused irq 0x%04x!\n",
2126 irq);
2127 return;
2128 }
2129
2130 if (devstat->flag&DEVSTAT_FLAG_SENSE_AVAIL) {
2131 sprintf(dbf_text,"sens%4x",irq);
2132 QDIO_DBF_TEXT2(1,trace,dbf_text);
2133 QDIO_DBF_HEX0(0,sense,&devstat->ii.irb,QDIO_DBF_SENSE_LEN);
2134
2135 QDIO_PRINT_WARN("sense data available on qdio channel.\n");
2136 HEXDUMP16(WARN,"irb: ",&devstat->ii.irb);
2137 HEXDUMP16(WARN,"sense data: ",&devstat->ii.sense.data[0]);
2138 }
2139
2140 irq_ptr->io_result_cstat=ioinfo[irq]->devstat.cstat;
2141 irq_ptr->io_result_dstat=ioinfo[irq]->devstat.dstat;
2142 irq_ptr->io_result_flags=ioinfo[irq]->devstat.flag;
2143
2144 if ( (rqparam==QDIO_DOING_ACTIVATE) &&
2145 (cstat & SCHN_STAT_PCI) ) {
2146 #ifdef QDIO_PERFORMANCE_STATS
2147 perf_stats.pcis++;
2148 perf_stats.start_time_inbound=NOW;
2149 #endif /* QDIO_PERFORMANCE_STATS */
2150 for (i=0;i<irq_ptr->no_input_qs;i++) {
2151 q=irq_ptr->input_qs[i];
2152 if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
2153 qdio_mark_q(q);
2154 else {
2155 #ifdef QDIO_PERFORMANCE_STATS
2156 perf_stats.tl_runs--;
2157 #endif /* QDIO_PERFORMANCE_STATS */
2158 __qdio_inbound_processing(q);
2159 }
2160 }
2161 if (irq_ptr->hydra_gives_outbound_pcis) {
2162 for (i=0;i<irq_ptr->no_output_qs;i++) {
2163 q=irq_ptr->output_qs[i];
2164 #ifdef QDIO_PERFORMANCE_STATS
2165 perf_stats.tl_runs--;
2166 #endif /* QDIO_PERFORMANCE_STATS */
2167 if (!qdio_is_outbound_q_done(q)) {
2168 if (!irq_ptr->sync_done_on_outb_pcis) {
2169 SYNC_MEMORY;
2170 }
2171 __qdio_outbound_processing(q);
2172 }
2173 }
2174 }
2175 return;
2176 }
2177
2178 if ( (rqparam==QDIO_DOING_ACTIVATE) &&
2179 (!cstat) &&
2180 (!dstat) ) {
2181 rqparam=QDIO_DOING_CLEANUP;
2182 }
2183
2184 if ( (rqparam==QDIO_DOING_ESTABLISH) &&
2185 ( (cstat) ||
2186 (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ) ) {
2187 sprintf(dbf_text,"ick1%4x",irq);
2188 QDIO_DBF_TEXT2(1,trace,dbf_text);
2189 QDIO_DBF_HEX2(0,trace,&rqparam,sizeof(int));
2190 QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
2191 QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
2192 QDIO_PRINT_ERR("received check condition on establish " \
2193 "queues on irq 0x%x (cs=x%x, ds=x%x).\n",
2194 irq,cstat,dstat);
2195 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_STOPPED);
2196 return;
2197 }
2198
2199 if ( ( (rqparam==QDIO_DOING_ACTIVATE) &&
2200 (dstat==(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ) ||
2201 ( (rqparam==QDIO_DOING_CLEANUP) || (!rqparam) ) ) {
2202 qdio_wakeup(&irq_ptr->interrupt_has_been_cleaned,irq_ptr);
2203 return;
2204 }
2205
2206 if ( (rqparam==QDIO_DOING_ACTIVATE) &&
2207 ( (cstat & ~SCHN_STAT_PCI) ||
2208 (dstat) ) ) {
2209 sprintf(dbf_text,"ick2%4x",irq);
2210 QDIO_DBF_TEXT2(1,trace,dbf_text);
2211 QDIO_DBF_HEX2(0,trace,&rqparam,sizeof(int));
2212 QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
2213 QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
2214 QDIO_PRINT_ERR("received check condition on activate " \
2215 "queues on irq 0x%x (cs=x%x, ds=x%x).\n",
2216 irq,cstat,dstat);
2217 if (irq_ptr->no_input_qs) {
2218 q=irq_ptr->input_qs[0];
2219 } else if (irq_ptr->no_output_qs) {
2220 q=irq_ptr->output_qs[0];
2221 } else {
2222 QDIO_PRINT_ERR("oops... no queue registered on irq " \
2223 "0x%x!?\n",irq);
2224 goto omit_handler_call;
2225 }
2226 q->handler(q->irq,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
2227 QDIO_STATUS_LOOK_FOR_ERROR,
2228 0,0,0,-1,-1,q->int_parm);
2229 omit_handler_call:
2230 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_STOPPED);
2231 return;
2232 }
2233
2234 qdio_wakeup(&irq_ptr->interrupt_has_arrived,irq_ptr);
2235 }
2236
2237 /* this is for mp3 */
qdio_synchronize(int irq,unsigned int flags,unsigned int queue_number)2238 int qdio_synchronize(int irq,unsigned int flags,
2239 unsigned int queue_number)
2240 {
2241 unsigned int gpr2,gpr3;
2242 int cc;
2243 qdio_q_t *q;
2244 qdio_irq_t *irq_ptr;
2245 char dbf_text[15]="SyncXXXX";
2246 void *ptr;
2247
2248 *((int*)(&dbf_text[4]))=irq;
2249 QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
2250 *((int*)(&dbf_text[0]))=flags;
2251 *((int*)(&dbf_text[4]))=queue_number;
2252 QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
2253
2254 irq_ptr=qdio_get_irq_ptr(irq);
2255 if (!irq_ptr) return -ENODEV;
2256
2257 if (flags&QDIO_FLAG_SYNC_INPUT) {
2258 q=irq_ptr->input_qs[queue_number];
2259 if (!q) return -EINVAL;
2260
2261 gpr2=0;
2262 gpr3=q->mask;
2263 } else if (flags&QDIO_FLAG_SYNC_OUTPUT) {
2264 q=irq_ptr->output_qs[queue_number];
2265 if (!q) return -EINVAL;
2266
2267 gpr2=q->mask;
2268 gpr3=0;
2269 } else return -EINVAL;
2270
2271 #ifdef QDIO_32_BIT
2272 asm volatile (
2273 "lhi 0,2 \n\t"
2274 "lr 1,%1 \n\t"
2275 "lr 2,%2 \n\t"
2276 "lr 3,%3 \n\t"
2277 "siga 0 \n\t"
2278 "ipm %0 \n\t"
2279 "srl %0,28 \n\t"
2280 : "=d" (cc)
2281 : "d" (0x10000|q->irq), "d" (gpr2), "d" (gpr3)
2282 : "cc", "0", "1", "2", "3"
2283 );
2284 #else /* QDIO_32_BIT */
2285 asm volatile (
2286 "lghi 0,2 \n\t"
2287 "llgfr 1,%1 \n\t"
2288 "llgfr 2,%2 \n\t"
2289 "llgfr 3,%3 \n\t"
2290 "siga 0 \n\t"
2291 "ipm %0 \n\t"
2292 "srl %0,28 \n\t"
2293 : "=d" (cc)
2294 : "d" (0x10000|q->irq), "d" (gpr2), "d" (gpr3)
2295 : "cc", "0", "1", "2", "3"
2296 );
2297 #endif /* QDIO_32_BIT */
2298
2299 ptr=&cc;
2300 if (cc) QDIO_DBF_HEX3(0,trace,&ptr,sizeof(int));
2301
2302 return cc;
2303 }
2304
qdio_get_slsb_state(int irq,unsigned int flag,unsigned int queue_number,unsigned int qidx)2305 unsigned char qdio_get_slsb_state(int irq,unsigned int flag,
2306 unsigned int queue_number,
2307 unsigned int qidx)
2308 {
2309 qdio_irq_t *irq_ptr;
2310 qdio_q_t *q;
2311
2312 irq_ptr=qdio_get_irq_ptr(irq);
2313 if (!irq_ptr) return SLSB_ERROR_DURING_LOOKUP;
2314
2315 if (flag&QDIO_FLAG_SYNC_INPUT) {
2316 q=irq_ptr->input_qs[queue_number];
2317 } else if (flag&QDIO_FLAG_SYNC_OUTPUT) {
2318 q=irq_ptr->output_qs[queue_number];
2319 } else return SLSB_ERROR_DURING_LOOKUP;
2320
2321 return q->slsb.acc.val[qidx&(QDIO_MAX_BUFFERS_PER_Q-1)];
2322 }
2323
qdio_chsc(qdio_chsc_area_t * chsc_area)2324 static int qdio_chsc(qdio_chsc_area_t *chsc_area)
2325 {
2326 int cc;
2327
2328 #ifdef QDIO_32_BIT
2329 asm volatile (
2330 ".insn rre,0xb25f0000,%1,0 \n\t"
2331 "ipm %0 \n\t"
2332 "srl %0,28 \n\t"
2333 : "=d" (cc) : "d" (chsc_area) : "cc"
2334 );
2335 #else /* QDIO_32_BIT */
2336 asm volatile (
2337 ".insn rre,0xb25f0000,%1,0 \n\t"
2338 "ipm %0 \n\t"
2339 "srl %0,28 \n\t"
2340 : "=d" (cc) : "d" (chsc_area) : "cc"
2341 );
2342 #endif /* QDIO_32_BIT */
2343
2344 return cc;
2345 }
2346
qdio_check_siga_needs(int sch)2347 static unsigned char qdio_check_siga_needs(int sch)
2348 {
2349 int resp_code,result;
2350 unsigned long flags;
2351
2352 spin_lock_irqsave(&chsc_area_lock,flags);
2353
2354 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
2355 chsc_area->request_block.command_code1=0x0010; /* length */
2356 chsc_area->request_block.command_code2=0x0024; /* op code */
2357 chsc_area->request_block.first_sch=sch;
2358 chsc_area->request_block.last_sch=sch;
2359
2360 result=qdio_chsc(chsc_area);
2361
2362 if (result) {
2363 QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
2364 "SIGAs for sch x%x.\n",
2365 result,sch);
2366 result=-1; /* all flags set */
2367 goto out;
2368 }
2369
2370 resp_code=chsc_area->request_block.operation_data_area.
2371 store_qdio_data_response.response_code;
2372 if (resp_code!=QDIO_CHSC_RESPONSE_CODE_OK) {
2373 QDIO_PRINT_WARN("response upon checking SIGA needs " \
2374 "is 0x%x. Using all SIGAs for sch x%x.\n",
2375 resp_code,sch);
2376 result=-1; /* all flags set */
2377 goto out;
2378 }
2379 if (
2380 (!(chsc_area->request_block.operation_data_area.
2381 store_qdio_data_response.flags&CHSC_FLAG_QDIO_CAPABILITY)) ||
2382 (!(chsc_area->request_block.operation_data_area.
2383 store_qdio_data_response.flags&CHSC_FLAG_VALIDITY)) ||
2384 (chsc_area->request_block.operation_data_area.
2385 store_qdio_data_response.sch!=sch)
2386 ) {
2387 QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \
2388 "using all SIGAs.\n",sch);
2389 result=CHSC_FLAG_SIGA_INPUT_NECESSARY |
2390 CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
2391 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
2392 goto out;
2393 }
2394
2395 result=chsc_area->request_block.operation_data_area.
2396 store_qdio_data_response.qdioac;
2397 out:
2398 spin_unlock_irqrestore(&chsc_area_lock,flags);
2399 return result;
2400 }
2401
qdio_check_for_machine_features(void)2402 static void qdio_check_for_machine_features(void)
2403 {
2404 int i,result;
2405 unsigned long flags;
2406
2407 spin_lock_irqsave(&chsc_area_lock,flags);
2408
2409 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
2410 chsc_area->request_block.command_code1=0x0010;
2411 chsc_area->request_block.command_code2=0x0010;
2412 result=qdio_chsc(chsc_area);
2413
2414 if (result) {
2415 QDIO_PRINT_WARN("CHSC returned cc %i. Won't use adapter " \
2416 "interrupts for any QDIO device.\n",result);
2417 result=0;
2418 goto out;
2419 }
2420
2421 i=chsc_area->request_block.operation_data_area.
2422 store_qdio_data_response.response_code;
2423 if (i!=1) {
2424 QDIO_PRINT_WARN("Was not able to determine general " \
2425 "characteristics of all QDIO devices " \
2426 "aboard.\n");
2427 result=0;
2428 goto out;
2429 }
2430
2431 /* 4: request block
2432 * 2: general char
2433 * 512: chsc char */
2434 /* check for bit 67 */
2435 if ( (*(((unsigned int*)(chsc_area))+4+2+2)&0x10000000)!=0x10000000) {
2436 hydra_thinints=0;
2437 } else {
2438 hydra_thinints=1;
2439 }
2440
2441 /* check for bit 56: if aif time delay disablement fac installed,
2442 * omit svs even under lpar (good point by rick again) */
2443 if ( (*(((unsigned int*)(chsc_area))+4+2+1)&0x00000080)!=0x00000080) {
2444 omit_svs=1;
2445 } else {
2446 omit_svs=0;
2447 }
2448 out:
2449 spin_unlock_irqrestore(&chsc_area_lock,flags);
2450 }
2451
2452 /* the chsc_area is locked by the lock in qdio_activate */
tiqdio_check_chsc_availability(void)2453 static unsigned int tiqdio_check_chsc_availability(void) {
2454 int result;
2455 int i;
2456 unsigned long flags;
2457
2458 spin_lock_irqsave(&chsc_area_lock,flags);
2459
2460 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
2461 chsc_area->request_block.command_code1=0x0010;
2462 chsc_area->request_block.command_code2=0x0010;
2463 result=qdio_chsc(chsc_area);
2464 if (result) {
2465 QDIO_PRINT_WARN("Was not able to determine " \
2466 "available CHSCs, cc=%i.\n",
2467 result);
2468 result=-EIO;
2469 goto exit;
2470 }
2471 result=0;
2472 i=chsc_area->request_block.operation_data_area.
2473 store_qdio_data_response.response_code;
2474 if (i!=1) {
2475 QDIO_PRINT_WARN("Was not able to determine " \
2476 "available CHSCs.\n");
2477 result=-EIO;
2478 goto exit;
2479 }
2480 /* 4: request block
2481 * 2: general char
2482 * 512: chsc char */
2483 /* check for bit 41 */
2484 if ( (*(((unsigned int*)(chsc_area))+4+2+1)&0x00400000)!=0x00400000) {
2485 QDIO_PRINT_WARN("Adapter interruption facility not " \
2486 "installed.\n");
2487 result=-ENOENT;
2488 goto exit;
2489 }
2490 /* check for bits 107 and 108 */
2491 if ( (*(((unsigned int*)(chsc_area))+4+512+3)&0x00180000)!=
2492 0x00180000 ) {
2493 QDIO_PRINT_WARN("Set Chan Subsys. Char. & Fast-CHSCs " \
2494 "not available.\n");
2495 result=-ENOENT;
2496 goto exit;
2497 }
2498 exit:
2499 spin_unlock_irqrestore(&chsc_area_lock,flags);
2500 return result;
2501 }
2502
2503 /* the chsc_area is locked by the lock in qdio_activate */
tiqdio_set_subchannel_ind(qdio_irq_t * irq_ptr,int reset_to_zero)2504 static unsigned int tiqdio_set_subchannel_ind(qdio_irq_t *irq_ptr,
2505 int reset_to_zero)
2506 {
2507 unsigned long real_addr_local_summary_bit;
2508 unsigned long real_addr_dev_st_chg_ind;
2509 void *ptr;
2510 unsigned long flags;
2511 char dbf_text[15];
2512
2513 unsigned int resp_code;
2514 int result;
2515
2516 if (!irq_ptr->is_thinint_irq) return -ENODEV;
2517
2518 if (reset_to_zero) {
2519 real_addr_local_summary_bit=0;
2520 real_addr_dev_st_chg_ind=0;
2521 } else {
2522 real_addr_local_summary_bit=
2523 virt_to_phys((volatile void *)indicators);
2524 real_addr_dev_st_chg_ind=
2525 virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
2526 }
2527
2528 spin_lock_irqsave(&chsc_area_lock,flags);
2529
2530 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
2531 chsc_area->request_block.command_code1=0x0fe0;
2532 chsc_area->request_block.command_code2=0x0021;
2533 chsc_area->request_block.operation_code=0;
2534 chsc_area->request_block.image_id=0;
2535
2536 chsc_area->request_block.operation_data_area.set_chsc.
2537 summary_indicator_addr=real_addr_local_summary_bit;
2538 chsc_area->request_block.operation_data_area.set_chsc.
2539 subchannel_indicator_addr=real_addr_dev_st_chg_ind;
2540 chsc_area->request_block.operation_data_area.set_chsc.
2541 ks=QDIO_STORAGE_ACC_KEY;
2542 chsc_area->request_block.operation_data_area.set_chsc.
2543 kc=QDIO_STORAGE_ACC_KEY;
2544 chsc_area->request_block.operation_data_area.set_chsc.
2545 isc=TIQDIO_THININT_ISC;
2546 chsc_area->request_block.operation_data_area.set_chsc.
2547 subsystem_id=(1<<16)+irq_ptr->irq;
2548
2549 result=qdio_chsc(chsc_area);
2550 if (result) {
2551 QDIO_PRINT_WARN("could not set indicators on irq x%x, " \
2552 "cc=%i.\n",irq_ptr->irq,result);
2553 result=-EIO;
2554 goto out;
2555 }
2556
2557 resp_code=chsc_area->response_block.response_code;
2558 if (resp_code!=QDIO_CHSC_RESPONSE_CODE_OK) {
2559 QDIO_PRINT_WARN("response upon setting indicators " \
2560 "is 0x%x.\n",resp_code);
2561 sprintf(dbf_text,"sidR%4x",resp_code);
2562 QDIO_DBF_TEXT1(0,trace,dbf_text);
2563 QDIO_DBF_TEXT1(0,setup,dbf_text);
2564 ptr=&chsc_area->response_block;
2565 QDIO_DBF_HEX2(1,setup,&ptr,QDIO_DBF_SETUP_LEN);
2566 result=-EIO;
2567 goto out;
2568 }
2569
2570 QDIO_DBF_TEXT2(0,setup,"setscind");
2571 QDIO_DBF_HEX2(0,setup,&real_addr_local_summary_bit,
2572 sizeof(unsigned long));
2573 QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
2574 result=0;
2575 out:
2576 spin_unlock_irqrestore(&chsc_area_lock,flags);
2577 return result;
2578 }
2579
2580 /* chsc_area would have to be locked if called from outside qdio_activate */
tiqdio_set_delay_target(qdio_irq_t * irq_ptr,unsigned long delay_target)2581 static unsigned int tiqdio_set_delay_target(qdio_irq_t *irq_ptr,
2582 unsigned long delay_target)
2583 {
2584 unsigned int resp_code;
2585 int result;
2586 void *ptr;
2587 unsigned long flags;
2588 char dbf_text[15];
2589
2590 if (!irq_ptr->is_thinint_irq) return -ENODEV;
2591
2592 spin_lock_irqsave(&chsc_area_lock,flags);
2593
2594 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
2595 chsc_area->request_block.command_code1=0x0fe0;
2596 chsc_area->request_block.command_code2=0x1027;
2597 chsc_area->request_block.operation_data_area.set_chsc_fast.
2598 delay_target=delay_target<<16;
2599
2600 result=qdio_chsc(chsc_area);
2601 if (result) {
2602 QDIO_PRINT_WARN("could not set delay target on irq x%x, " \
2603 "cc=%i. Continuing.\n",irq_ptr->irq,result);
2604 result=-EIO;
2605 goto out;
2606 }
2607
2608 resp_code=chsc_area->response_block.response_code;
2609 if (resp_code!=QDIO_CHSC_RESPONSE_CODE_OK) {
2610 QDIO_PRINT_WARN("response upon setting delay target " \
2611 "is 0x%x. Continuing.\n",resp_code);
2612 sprintf(dbf_text,"sdtR%4x",resp_code);
2613 QDIO_DBF_TEXT1(0,trace,dbf_text);
2614 QDIO_DBF_TEXT1(0,setup,dbf_text);
2615 ptr=&chsc_area->response_block;
2616 QDIO_DBF_HEX2(1,trace,&ptr,QDIO_DBF_TRACE_LEN);
2617 }
2618 QDIO_DBF_TEXT2(0,trace,"delytrgt");
2619 QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
2620 result=0;
2621 out:
2622 spin_unlock_irqrestore(&chsc_area_lock,flags);
2623 return result;
2624 }
2625
qdio_cleanup(int irq,int how)2626 int qdio_cleanup(int irq,int how)
2627 {
2628 qdio_irq_t *irq_ptr;
2629 int i,result;
2630 int do_an_irqrestore=0;
2631 unsigned long flags;
2632 int timeout;
2633 char dbf_text[15];
2634
2635 result=0;
2636 sprintf(dbf_text,"qcln%4x",irq);
2637 QDIO_DBF_TEXT1(0,trace,dbf_text);
2638 QDIO_DBF_TEXT0(0,setup,dbf_text);
2639
2640 irq_ptr=qdio_get_irq_ptr(irq);
2641 if (!irq_ptr) return -ENODEV;
2642
2643 down(&irq_ptr->setting_up_lock);
2644
2645 /* mark all qs as uninteresting */
2646 for (i=0;i<irq_ptr->no_input_qs;i++) {
2647 atomic_set(&irq_ptr->input_qs[i]->is_in_shutdown,1);
2648 }
2649 for (i=0;i<irq_ptr->no_output_qs;i++) {
2650 atomic_set(&irq_ptr->output_qs[i]->is_in_shutdown,1);
2651 }
2652
2653 tasklet_kill(&tiqdio_tasklet);
2654
2655 for (i=0;i<irq_ptr->no_input_qs;i++) {
2656 qdio_unmark_q(irq_ptr->input_qs[i]);
2657 tasklet_kill(&irq_ptr->input_qs[i]->tasklet);
2658 if (qdio_wait_for_no_use_count(&irq_ptr->input_qs[i]->
2659 use_count))
2660 result=-EINPROGRESS;
2661 }
2662
2663 for (i=0;i<irq_ptr->no_output_qs;i++) {
2664 tasklet_kill(&irq_ptr->output_qs[i]->tasklet);
2665 if (qdio_wait_for_no_use_count(&irq_ptr->output_qs[i]->
2666 use_count))
2667 result=-EINPROGRESS;
2668 }
2669
2670 atomic_set(&irq_ptr->interrupt_has_been_cleaned,0);
2671
2672 /* cleanup subchannel */
2673 s390irq_spin_lock_irqsave(irq,flags);
2674 if (how&QDIO_FLAG_CLEANUP_USING_CLEAR) {
2675 clear_IO(irq_ptr->irq,QDIO_DOING_CLEANUP,0);
2676 timeout=QDIO_CLEANUP_CLEAR_TIMEOUT;
2677 } else if (how&QDIO_FLAG_CLEANUP_USING_HALT) {
2678 halt_IO(irq_ptr->irq,QDIO_DOING_CLEANUP,0);
2679 timeout=QDIO_CLEANUP_HALT_TIMEOUT;
2680 } else { /* default behaviour */
2681 halt_IO(irq_ptr->irq,QDIO_DOING_CLEANUP,0);
2682 timeout=QDIO_CLEANUP_HALT_TIMEOUT;
2683 }
2684 s390irq_spin_unlock_irqrestore(irq,flags);
2685
2686 if (qdio_sleepon(&irq_ptr->interrupt_has_been_cleaned,
2687 timeout,irq_ptr)==-ETIME) {
2688 s390irq_spin_lock_irqsave(irq,flags);
2689 QDIO_PRINT_INFO("Did not get interrupt on %s_IO, " \
2690 "irq=0x%x.\n",
2691 (how==QDIO_FLAG_CLEANUP_USING_CLEAR)?
2692 "clear":"halt",irq);
2693 do_an_irqrestore=1;
2694 }
2695
2696 if (irq_ptr->is_thinint_irq) {
2697 qdio_put_indicator((__u32*)irq_ptr->dev_st_chg_ind);
2698 tiqdio_set_subchannel_ind(irq_ptr,1); /* reset adapter
2699 interrupt indicators */
2700 }
2701
2702 /* exchange int handlers, if necessary */
2703 if ((void*)ioinfo[irq]->irq_desc.handler
2704 ==(void*)qdio_handler) {
2705 ioinfo[irq]->irq_desc.handler=
2706 irq_ptr->original_int_handler;
2707 /* irq_ptr->original_int_handler=NULL; */
2708 }
2709
2710 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE);
2711
2712 if (do_an_irqrestore)
2713 s390irq_spin_unlock_irqrestore(irq,flags);
2714
2715 up(&irq_ptr->setting_up_lock);
2716
2717 qdio_remove_irq_ptr(irq_ptr);
2718 qdio_release_irq_memory(irq_ptr);
2719
2720 QDIO_DBF_TEXT3(0,setup,"MOD_DEC_");
2721 MOD_DEC_USE_COUNT;
2722
2723 return result;
2724 }
2725
qdio_get_characteristics(int irq)2726 unsigned long qdio_get_characteristics(int irq)
2727 {
2728 qdio_irq_t *irq_ptr;
2729 int result=0;
2730
2731 irq_ptr=qdio_get_irq_ptr(irq);
2732 if (!irq_ptr) return -ENODEV;
2733
2734 if (irq_ptr->state!=QDIO_IRQ_STATE_ACTIVE) {
2735 return -EBUSY;
2736 }
2737
2738 if (irq_ptr->state==QDIO_IRQ_STATE_INACTIVE) {
2739 result|=QDIO_STATE_INACTIVE;
2740 } else if (irq_ptr->state==QDIO_IRQ_STATE_ESTABLISHED) {
2741 result|=QDIO_STATE_ESTABLISHED;
2742 } else if (irq_ptr->state==QDIO_IRQ_STATE_ACTIVE) {
2743 result|=QDIO_STATE_ACTIVE;
2744 } else if (irq_ptr->state==QDIO_IRQ_STATE_STOPPED) {
2745 result|=QDIO_STATE_STOPPED;
2746 }
2747
2748 if (irq_ptr->hydra_gives_outbound_pcis)
2749 result|=QDIO_STATE_MUST_USE_OUTB_PCI;
2750
2751 return result;
2752 }
2753
qdio_initialize(qdio_initialize_t * init_data)2754 int qdio_initialize(qdio_initialize_t *init_data)
2755 {
2756 int i,ciw_cnt;
2757 unsigned long saveflags;
2758 qdio_irq_t *irq_ptr=NULL;
2759 int result,result2;
2760 int found;
2761 unsigned long flags;
2762 char dbf_text[20]; /* if a printf printed out more than 8 chars */
2763
2764 down(&init_sema);
2765
2766 sprintf(dbf_text,"qini%4x",init_data->irq);
2767 QDIO_DBF_TEXT0(0,setup,dbf_text);
2768 QDIO_DBF_TEXT0(0,trace,dbf_text);
2769 sprintf(dbf_text,"qfmt:%x",init_data->q_format);
2770 QDIO_DBF_TEXT0(0,setup,dbf_text);
2771 QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8);
2772 sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format);
2773 QDIO_DBF_TEXT0(0,setup,dbf_text);
2774 QDIO_DBF_HEX0(0,setup,&init_data->qib_param_field,sizeof(char*));
2775 QDIO_DBF_HEX0(0,setup,&init_data->input_slib_elements,sizeof(long*));
2776 QDIO_DBF_HEX0(0,setup,&init_data->output_slib_elements,sizeof(long*));
2777 sprintf(dbf_text,"miit%4x",init_data->min_input_threshold);
2778 QDIO_DBF_TEXT0(0,setup,dbf_text);
2779 sprintf(dbf_text,"mait%4x",init_data->min_input_threshold);
2780 QDIO_DBF_TEXT0(0,setup,dbf_text);
2781 sprintf(dbf_text,"miot%4x",init_data->max_output_threshold);
2782 QDIO_DBF_TEXT0(0,setup,dbf_text);
2783 sprintf(dbf_text,"maot%4x",init_data->max_output_threshold);
2784 QDIO_DBF_TEXT0(0,setup,dbf_text);
2785 sprintf(dbf_text,"niq:%4x",init_data->no_input_qs);
2786 QDIO_DBF_TEXT0(0,setup,dbf_text);
2787 sprintf(dbf_text,"noq:%4x",init_data->no_output_qs);
2788 QDIO_DBF_TEXT0(0,setup,dbf_text);
2789 QDIO_DBF_HEX0(0,setup,&init_data->input_handler,sizeof(void*));
2790 QDIO_DBF_HEX0(0,setup,&init_data->output_handler,sizeof(void*));
2791 QDIO_DBF_HEX0(0,setup,&init_data->int_parm,sizeof(long));
2792 QDIO_DBF_HEX0(0,setup,&init_data->flags,sizeof(long));
2793 QDIO_DBF_HEX0(0,setup,&init_data->input_sbal_addr_array,sizeof(void*));
2794 QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*));
2795 flags=init_data->flags;
2796
2797 /* sanity checks */
2798 if (qdio_get_irq_ptr(init_data->irq)) {
2799 result=-EBUSY;
2800 goto out;
2801 }
2802
2803 if (ioinfo[init_data->irq]==INVALID_STORAGE_AREA) {
2804 result=-ENODEV;
2805 goto out;
2806 }
2807
2808 if (!ioinfo[init_data->irq]) {
2809 QDIO_PRINT_WARN("ioinfo[%i] is NULL!\n",init_data->irq);
2810 result=-ENODEV;
2811 goto out;
2812 }
2813
2814 #define DEVSTAT_FLAG_IRQ_QDIO ~0UL
2815 if (!(ioinfo[init_data->irq]->devstat.flag&DEVSTAT_FLAG_IRQ_QDIO)) {
2816 QDIO_PRINT_WARN("ioinfo[%i]->devstat.flag=0x%08x\n",
2817 init_data->irq,
2818 ioinfo[init_data->irq]->devstat.flag);
2819 result=-ENODEV;
2820 goto out;
2821 }
2822
2823 if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
2824 (init_data->no_output_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
2825 ((init_data->no_input_qs) && (!init_data->input_handler)) ||
2826 ((init_data->no_output_qs) && (!init_data->output_handler)) ) {
2827 result=-EINVAL;
2828 goto out;
2829 }
2830
2831 if ( (init_data->flags&QDIO_INBOUND_0COPY_SBALS)&&
2832 (!init_data->input_sbal_addr_array) ) {
2833 result=-EINVAL;
2834 goto out;
2835 }
2836 if ( (init_data->flags&QDIO_OUTBOUND_0COPY_SBALS)&&
2837 (!init_data->output_sbal_addr_array) ) {
2838 result=-EINVAL;
2839 goto out;
2840 }
2841
2842 /* create irq */
2843 irq_ptr=kmalloc(sizeof(qdio_irq_t),GFP_DMA);
2844
2845 QDIO_DBF_TEXT0(0,setup,"irq_ptr:");
2846 QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
2847
2848 if (!irq_ptr) {
2849 QDIO_PRINT_ERR("kmalloc of irq_ptr failed!\n");
2850 result=-ENOMEM;
2851 goto out;
2852 }
2853
2854 memset(irq_ptr,0,sizeof(qdio_irq_t)); /* wipes qib.ac,
2855 required by ar7063 */
2856
2857 irq_ptr->qdr=kmalloc(sizeof(qdr_t),GFP_DMA);
2858 if (!(irq_ptr->qdr)) {
2859 kfree(irq_ptr);
2860 QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
2861 result=-ENOMEM;
2862 goto out;
2863 }
2864 memset(irq_ptr->qdr,0,sizeof(qdr_t));
2865 QDIO_DBF_TEXT0(0,setup,"qdr:");
2866 QDIO_DBF_HEX0(0,setup,&irq_ptr->qdr,sizeof(void*));
2867
2868 init_waitqueue_head(&irq_ptr->wait_q);
2869
2870 irq_ptr->int_parm=init_data->int_parm;
2871
2872 irq_ptr->irq=init_data->irq;
2873 irq_ptr->no_input_qs=init_data->no_input_qs;
2874 irq_ptr->no_output_qs=init_data->no_output_qs;
2875
2876 if (init_data->q_format==QDIO_IQDIO_QFMT) {
2877 irq_ptr->is_iqdio_irq=1;
2878 irq_ptr->is_thinint_irq=1;
2879 } else {
2880 irq_ptr->is_iqdio_irq=0;
2881 irq_ptr->is_thinint_irq=hydra_thinints;
2882 }
2883 sprintf(dbf_text,"is_i_t%1x%1x",
2884 irq_ptr->is_iqdio_irq,irq_ptr->is_thinint_irq);
2885 QDIO_DBF_TEXT2(0,setup,dbf_text);
2886
2887 if (irq_ptr->is_thinint_irq) {
2888 irq_ptr->dev_st_chg_ind=qdio_get_indicator();
2889 QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
2890 if (!irq_ptr->dev_st_chg_ind) {
2891 QDIO_PRINT_WARN("no indicator location available " \
2892 "for irq 0x%x\n",irq_ptr->irq);
2893 qdio_release_irq_memory(irq_ptr);
2894 result=-ENOBUFS;
2895 goto out;
2896 }
2897 }
2898
2899 if (flags&QDIO_PFIX)
2900 irq_ptr->other_flags |= QDIO_PFIX;
2901
2902 /* defaults */
2903 irq_ptr->commands.eq=DEFAULT_ESTABLISH_QS_CMD;
2904 irq_ptr->commands.count_eq=DEFAULT_ESTABLISH_QS_COUNT;
2905 irq_ptr->commands.aq=DEFAULT_ACTIVATE_QS_CMD;
2906 irq_ptr->commands.count_aq=DEFAULT_ACTIVATE_QS_COUNT;
2907
2908 if (!qdio_alloc_qs(irq_ptr,init_data->no_input_qs,
2909 init_data->no_output_qs,
2910 init_data->input_handler,
2911 init_data->output_handler,init_data->int_parm,
2912 init_data->q_format,init_data->flags,
2913 init_data->input_sbal_addr_array,
2914 init_data->output_sbal_addr_array)) {
2915 qdio_release_irq_memory(irq_ptr);
2916 result=-ENOMEM;
2917 goto out;
2918 }
2919
2920 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE);
2921
2922 sema_init(&irq_ptr->setting_up_lock,1);
2923
2924 MOD_INC_USE_COUNT;
2925 QDIO_DBF_TEXT3(0,setup,"MOD_INC_");
2926
2927 down(&irq_ptr->setting_up_lock);
2928
2929 qdio_insert_irq_ptr(irq_ptr);
2930
2931 qdio_fill_thresholds(irq_ptr,init_data->no_input_qs,
2932 init_data->no_output_qs,
2933 init_data->min_input_threshold,
2934 init_data->max_input_threshold,
2935 init_data->min_output_threshold,
2936 init_data->max_output_threshold);
2937
2938 /* fill in qdr */
2939 irq_ptr->qdr->qfmt=init_data->q_format;
2940 irq_ptr->qdr->iqdcnt=init_data->no_input_qs;
2941 irq_ptr->qdr->oqdcnt=init_data->no_output_qs;
2942 irq_ptr->qdr->iqdsz=sizeof(qdesfmt0_t)/4; /* size in words */
2943 irq_ptr->qdr->oqdsz=sizeof(qdesfmt0_t)/4;
2944
2945 irq_ptr->qdr->qiba=QDIO_PFIX_GET_ADDR(&irq_ptr->qib);
2946 irq_ptr->qdr->qkey=QDIO_STORAGE_ACC_KEY;
2947
2948 /* fill in qib */
2949 irq_ptr->qib.qfmt=init_data->q_format;
2950 if (init_data->no_input_qs) irq_ptr->qib.isliba=
2951 QDIO_PFIX_GET_ADDR(irq_ptr->input_qs[0]->slib);
2952 if (init_data->no_output_qs) irq_ptr->qib.osliba=(unsigned long)
2953 QDIO_PFIX_GET_ADDR(irq_ptr->output_qs[0]->slib);
2954 memcpy(irq_ptr->qib.ebcnam,init_data->adapter_name,8);
2955
2956 qdio_set_impl_params(irq_ptr,init_data->qib_param_field_format,
2957 init_data->qib_param_field,
2958 init_data->no_input_qs,
2959 init_data->no_output_qs,
2960 init_data->input_slib_elements,
2961 init_data->output_slib_elements);
2962
2963 /* first input descriptors, then output descriptors */
2964 for (i=0;i<init_data->no_input_qs;i++) {
2965 irq_ptr->input_qs[i]->is_iqdio_q=
2966 (init_data->q_format==QDIO_IQDIO_QFMT)?1:0;
2967 irq_ptr->input_qs[i]->is_thinint_q=irq_ptr->is_thinint_irq;
2968
2969 irq_ptr->qdr->qdf0[i].sliba=
2970 QDIO_PFIX_GET_ADDR(irq_ptr->input_qs[i]->slib);
2971
2972 irq_ptr->qdr->qdf0[i].sla=
2973 QDIO_PFIX_GET_ADDR(irq_ptr->input_qs[i]->sl);
2974
2975 irq_ptr->qdr->qdf0[i].slsba=
2976 QDIO_PFIX_GET_ADDR
2977 ((void *)&irq_ptr->input_qs[i]->slsb.acc.val[0]);
2978
2979 irq_ptr->qdr->qdf0[i].akey=QDIO_STORAGE_ACC_KEY;
2980 irq_ptr->qdr->qdf0[i].bkey=QDIO_STORAGE_ACC_KEY;
2981 irq_ptr->qdr->qdf0[i].ckey=QDIO_STORAGE_ACC_KEY;
2982 irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_ACC_KEY;
2983 }
2984
2985 for (i=0;i<init_data->no_output_qs;i++) {
2986 irq_ptr->output_qs[i]->is_iqdio_q=
2987 (init_data->q_format==QDIO_IQDIO_QFMT)?1:0;
2988 irq_ptr->output_qs[i]->is_thinint_q=irq_ptr->is_thinint_irq;
2989
2990 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].sliba=
2991 QDIO_PFIX_GET_ADDR(irq_ptr->output_qs[i]->slib);
2992
2993 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].sla=
2994 QDIO_PFIX_GET_ADDR(irq_ptr->output_qs[i]->sl);
2995
2996 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].slsba=
2997 QDIO_PFIX_GET_ADDR
2998 ((void *)&irq_ptr->output_qs[i]->slsb.acc.val[0]);
2999
3000 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].akey=
3001 QDIO_STORAGE_ACC_KEY;
3002 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].bkey=
3003 QDIO_STORAGE_ACC_KEY;
3004 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].ckey=
3005 QDIO_STORAGE_ACC_KEY;
3006 irq_ptr->qdr->qdf0[i+init_data->no_input_qs].dkey=
3007 QDIO_STORAGE_ACC_KEY;
3008 }
3009 /* qdr, qib, sls, slsbs, slibs, sbales filled. */
3010
3011 s390irq_spin_lock_irqsave(irq_ptr->irq,saveflags);
3012 /* keep track of original int handler */
3013 irq_ptr->original_int_handler=ioinfo[irq_ptr->irq]->irq_desc.handler;
3014
3015 /* insert qdio int handler */
3016 ioinfo[irq_ptr->irq]->irq_desc.handler=(void*)qdio_handler;
3017
3018 s390irq_spin_unlock_irqrestore(irq_ptr->irq,saveflags);
3019
3020 #define TAKEOVER_CIW(x) irq_ptr->commands.x=ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].cmd; irq_ptr->commands.count_##x=ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].count
3021 /* get qdio commands */
3022 found=0;
3023 for (ciw_cnt=0;ciw_cnt<MAX_CIWS;ciw_cnt++) {
3024 switch (ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].ct) {
3025 case CIW_TYPE_RCD: TAKEOVER_CIW(rcd); break;
3026 case CIW_TYPE_SII: TAKEOVER_CIW(sii); break;
3027 case CIW_TYPE_RNI: TAKEOVER_CIW(rni); break;
3028 case CIW_TYPE_EQUEUE: TAKEOVER_CIW(eq); found++; break;
3029 case CIW_TYPE_AQUEUE: TAKEOVER_CIW(aq); found++; break;
3030 }
3031 if ( (ciw_cnt>0) &&
3032 (ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].ct==0) &&
3033 (ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].cmd==0) &&
3034 (ioinfo[irq_ptr->irq]->senseid.ciw[ciw_cnt].count) )
3035 break;
3036 }
3037 if (found<2) {
3038 QDIO_DBF_TEXT2(1,setup,"no ciws");
3039 QDIO_PRINT_INFO("No CIWs found for QDIO commands. Trying to " \
3040 "use defaults.\n");
3041 }
3042
3043 /* the thinint CHSC stuff */
3044 if (irq_ptr->is_thinint_irq) {
3045 /* iqdio_enable_adapter_int_facility(irq_ptr);*/
3046
3047 if (tiqdio_check_chsc_availability()) {
3048 QDIO_PRINT_ERR("Not all CHSCs supported. " \
3049 "Continuing.\n");
3050 }
3051 result=tiqdio_set_subchannel_ind(irq_ptr,0);
3052 if (result) {
3053 up(&irq_ptr->setting_up_lock);
3054 qdio_cleanup(irq_ptr->irq,
3055 QDIO_FLAG_CLEANUP_USING_CLEAR);
3056 goto out;
3057 }
3058 tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
3059 }
3060
3061 /* establish q */
3062 irq_ptr->ccw.cmd_code=irq_ptr->commands.eq;
3063 irq_ptr->ccw.flags=CCW_FLAG_SLI;
3064 irq_ptr->ccw.count=irq_ptr->commands.count_eq;
3065 irq_ptr->ccw.cda=QDIO_GET_32BIT_ADDR(QDIO_PFIX_GET_ADDR(irq_ptr->qdr));
3066
3067 s390irq_spin_lock_irqsave(irq_ptr->irq,saveflags);
3068 atomic_set(&irq_ptr->interrupt_has_arrived,0);
3069
3070 result=do_IO(irq_ptr->irq,&irq_ptr->ccw,QDIO_DOING_ESTABLISH,0,
3071 ((irq_ptr->other_flags&QDIO_PFIX)?DOIO_USE_DIAG98:0));
3072 if (result) {
3073 result2=do_IO(irq_ptr->irq,&irq_ptr->ccw,
3074 QDIO_DOING_ESTABLISH,0,
3075 ((irq_ptr->other_flags&QDIO_PFIX)?
3076 DOIO_USE_DIAG98:0));
3077 sprintf(dbf_text,"eq:io%4x",result);
3078 QDIO_DBF_TEXT2(1,setup,dbf_text);
3079 if (result2) {
3080 sprintf(dbf_text,"eq:io%4x",result);
3081 QDIO_DBF_TEXT2(1,setup,dbf_text);
3082 }
3083 QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \
3084 "returned %i, next try returned %i\n",
3085 irq_ptr->irq,result,result2);
3086 result=result2;
3087 }
3088
3089 s390irq_spin_unlock_irqrestore(irq_ptr->irq,saveflags);
3090
3091 if (result) {
3092 up(&irq_ptr->setting_up_lock);
3093 qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
3094 goto out;
3095 }
3096
3097 result=qdio_sleepon(&irq_ptr->interrupt_has_arrived,
3098 QDIO_ESTABLISH_TIMEOUT,irq_ptr);
3099
3100 if (result) {
3101 QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n",
3102 irq_ptr->irq);
3103 QDIO_DBF_TEXT2(1,setup,"eq:timeo");
3104 up(&irq_ptr->setting_up_lock);
3105 qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
3106 goto out;
3107 }
3108
3109 if (!(irq_ptr->io_result_dstat & DEV_STAT_DEV_END)) {
3110 QDIO_DBF_TEXT2(1,setup,"eq:no de");
3111 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_dstat,
3112 sizeof(irq_ptr->io_result_dstat));
3113 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_cstat,
3114 sizeof(irq_ptr->io_result_cstat));
3115 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_flags,
3116 sizeof(irq_ptr->io_result_flags));
3117 QDIO_PRINT_ERR("establish queues on irq %04x: didn't get " \
3118 "device end: dstat=%02x, cstat=%02x, " \
3119 "flags=%02x\n",
3120 irq_ptr->irq,irq_ptr->io_result_dstat,
3121 irq_ptr->io_result_cstat,
3122 irq_ptr->io_result_flags);
3123 up(&irq_ptr->setting_up_lock);
3124 qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
3125 result=-EIO;
3126 goto out;
3127 }
3128
3129 if (irq_ptr->io_result_dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) {
3130 QDIO_DBF_TEXT2(1,setup,"eq:badio");
3131 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_dstat,
3132 sizeof(irq_ptr->io_result_dstat));
3133 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_cstat,
3134 sizeof(irq_ptr->io_result_cstat));
3135 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_flags,
3136 sizeof(irq_ptr->io_result_flags));
3137 QDIO_PRINT_ERR("establish queues on irq %04x: got " \
3138 "the following devstat: dstat=%02x, " \
3139 "cstat=%02x, flags=%02x\n",
3140 irq_ptr->irq,irq_ptr->io_result_dstat,
3141 irq_ptr->io_result_cstat,
3142 irq_ptr->io_result_flags);
3143 result=-EIO;
3144 up(&irq_ptr->setting_up_lock);
3145 goto out;
3146 }
3147
3148 irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
3149 sprintf(dbf_text,"qdioac%2x",irq_ptr->qdioac);
3150 QDIO_DBF_TEXT2(0,setup,dbf_text);
3151
3152 /* if this gets set once, we're running under VM and can omit SVSes */
3153 if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) {
3154 omit_svs=1;
3155 }
3156
3157 sprintf(dbf_text,"qib ac%2x",irq_ptr->qib.ac);
3158 QDIO_DBF_TEXT2(0,setup,dbf_text);
3159
3160 if (init_data->flags&QDIO_USE_OUTBOUND_PCIS) {
3161 irq_ptr->hydra_gives_outbound_pcis=
3162 irq_ptr->qib.ac&QIB_AC_OUTBOUND_PCI_SUPPORTED;
3163 } else {
3164 irq_ptr->hydra_gives_outbound_pcis=0;
3165 }
3166 irq_ptr->sync_done_on_outb_pcis=
3167 irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS;
3168
3169 for (i=0;i<init_data->no_input_qs;i++) {
3170 irq_ptr->input_qs[i]->siga_sync=
3171 irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY;
3172 irq_ptr->input_qs[i]->siga_in=
3173 irq_ptr->qdioac&CHSC_FLAG_SIGA_INPUT_NECESSARY;
3174 irq_ptr->input_qs[i]->siga_out=
3175 irq_ptr->qdioac&CHSC_FLAG_SIGA_OUTPUT_NECESSARY;
3176 irq_ptr->input_qs[i]->siga_sync_done_on_thinints=
3177 irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
3178 irq_ptr->input_qs[i]->hydra_gives_outbound_pcis=
3179 irq_ptr->hydra_gives_outbound_pcis;
3180 irq_ptr->input_qs[i]->siga_sync_done_on_outb_tis=
3181 ( (irq_ptr->qdioac&
3182 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
3183 CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
3184 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
3185 CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS) );
3186 }
3187
3188 for (i=0;i<init_data->no_output_qs;i++) {
3189 irq_ptr->output_qs[i]->siga_sync=
3190 irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY;
3191 irq_ptr->output_qs[i]->siga_in=
3192 irq_ptr->qdioac&CHSC_FLAG_SIGA_INPUT_NECESSARY;
3193 irq_ptr->output_qs[i]->siga_out=
3194 irq_ptr->qdioac&CHSC_FLAG_SIGA_OUTPUT_NECESSARY;
3195 irq_ptr->output_qs[i]->siga_sync_done_on_thinints=
3196 irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
3197 irq_ptr->output_qs[i]->hydra_gives_outbound_pcis=
3198 irq_ptr->hydra_gives_outbound_pcis;
3199 irq_ptr->output_qs[i]->siga_sync_done_on_outb_tis=
3200 ( (irq_ptr->qdioac&
3201 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
3202 CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
3203 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
3204 CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS) );
3205 }
3206
3207 if (init_data->qib_param_field)
3208 memcpy(init_data->qib_param_field,irq_ptr->qib.parm,
3209 QDIO_MAX_BUFFERS_PER_Q);
3210
3211 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
3212
3213 if (irq_ptr) {
3214 up(&irq_ptr->setting_up_lock);
3215 }
3216 out:
3217 up(&init_sema);
3218
3219 return result;
3220 }
3221
qdio_activate(int irq,int flags)3222 int qdio_activate(int irq,int flags)
3223 {
3224 qdio_irq_t *irq_ptr;
3225 int i,result=0,result2;
3226 unsigned long saveflags;
3227 char dbf_text[20]; /* see qdio_initialize */
3228
3229 irq_ptr=qdio_get_irq_ptr(irq);
3230 if (!irq_ptr) return -ENODEV;
3231
3232 down(&irq_ptr->setting_up_lock);
3233 if (irq_ptr->state==QDIO_IRQ_STATE_INACTIVE) {
3234 result=-EBUSY;
3235 goto out;
3236 }
3237
3238 sprintf(dbf_text,"qact%4x",irq);
3239 QDIO_DBF_TEXT2(0,setup,dbf_text);
3240 QDIO_DBF_TEXT2(0,trace,dbf_text);
3241
3242 /* activate q */
3243 irq_ptr->ccw.cmd_code=irq_ptr->commands.aq;
3244 irq_ptr->ccw.flags=CCW_FLAG_SLI;
3245 irq_ptr->ccw.count=irq_ptr->commands.count_aq;
3246 irq_ptr->ccw.cda=QDIO_GET_32BIT_ADDR(0); /* no QDIO_PFIX_GET_ADDR here,
3247 not needed */
3248
3249 s390irq_spin_lock_irqsave(irq_ptr->irq,saveflags);
3250 atomic_set(&irq_ptr->interrupt_has_arrived,0);
3251
3252 result=do_IO(irq_ptr->irq,&irq_ptr->ccw,QDIO_DOING_ACTIVATE,
3253 0,DOIO_REPORT_ALL|DOIO_DENY_PREFETCH|
3254 ((irq_ptr->other_flags&QDIO_PFIX)?DOIO_USE_DIAG98:0));
3255 if (result) {
3256 result2=do_IO(irq_ptr->irq,&irq_ptr->ccw,
3257 QDIO_DOING_ACTIVATE,0,DOIO_REPORT_ALL|
3258 ((irq_ptr->other_flags&QDIO_PFIX) ?
3259 DOIO_USE_DIAG98:0));
3260 sprintf(dbf_text,"aq:io%4x",result);
3261 QDIO_DBF_TEXT2(1,setup,dbf_text);
3262 if (result2) {
3263 sprintf(dbf_text,"aq:io%4x",result);
3264 QDIO_DBF_TEXT2(1,setup,dbf_text);
3265 }
3266 QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \
3267 "returned %i, next try returned %i\n",
3268 irq_ptr->irq,result,result2);
3269 result=result2;
3270 }
3271
3272 s390irq_spin_unlock_irqrestore(irq_ptr->irq,saveflags);
3273 if (result) {
3274 goto out;
3275 }
3276
3277 if (!(flags&QDIO_FLAG_UNDER_INTERRUPT)) {
3278 result=qdio_sleepon(&irq_ptr->interrupt_has_arrived,
3279 QDIO_ACTIVATE_TIMEOUT,irq_ptr);
3280
3281 if (result!=-ETIME) {
3282 QDIO_DBF_TEXT2(1,setup,"aq:badio");
3283 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_dstat,
3284 sizeof(irq_ptr->io_result_dstat));
3285 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_cstat,
3286 sizeof(irq_ptr->io_result_cstat));
3287 QDIO_DBF_HEX2(0,setup,&irq_ptr->io_result_flags,
3288 sizeof(irq_ptr->io_result_flags));
3289 QDIO_PRINT_ERR("activate queues on irq %04x: got " \
3290 "the following devstat: dstat=%02x, " \
3291 "cstat=%02x, flags=%02x\n",
3292 irq_ptr->irq,irq_ptr->io_result_dstat,
3293 irq_ptr->io_result_cstat,
3294 irq_ptr->io_result_flags);
3295 result=-EIO;
3296 goto out;
3297 } else { /* result is -ETIME, but timeout is ok for us */
3298 result=0;
3299 }
3300 } else result=0;
3301
3302 for (i=0;i<irq_ptr->no_input_qs;i++) {
3303 if (irq_ptr->is_thinint_irq) {
3304 /* that way we know, that, if we will
3305 * get interrupted
3306 * by tiqdio_inbound_processing,
3307 * qdio_unmark_q will
3308 * not be called */
3309 qdio_reserve_q(irq_ptr->input_qs[i]);
3310 qdio_mark_tiq(irq_ptr->input_qs[i]);
3311 qdio_release_q(irq_ptr->input_qs[i]);
3312 }
3313 }
3314
3315 if (flags&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) {
3316 for (i=0;i<irq_ptr->no_input_qs;i++) {
3317 irq_ptr->input_qs[i]->is_input_q|=
3318 QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT;
3319 }
3320 }
3321
3322 qdio_wait_nonbusy(QDIO_ACTIVATE_DELAY);
3323
3324 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ACTIVE);
3325
3326 out:
3327 up(&irq_ptr->setting_up_lock);
3328
3329 return result;
3330 }
3331
3332 /* buffers filled forwards again to make Rick happy */
qdio_do_qdio_fill_input(qdio_q_t * q,unsigned int qidx,unsigned int count,qdio_buffer_t * buffers)3333 static inline void qdio_do_qdio_fill_input(qdio_q_t *q,unsigned int qidx,
3334 unsigned int count,
3335 qdio_buffer_t *buffers)
3336 {
3337 for (;;) {
3338 if (!q->is_0copy_sbals_q) {
3339 memcpy((void*)q->sbal[qidx],buffers,SBAL_SIZE);
3340 q->qdio_buffers[qidx]=buffers;
3341 buffers++;
3342 }
3343 set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY);
3344 count--;
3345 if (!count) break;
3346 qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
3347 }
3348
3349 /* not necessary, as the queues are synced during the SIGA read
3350 SYNC_MEMORY;*/
3351 }
3352
qdio_do_qdio_fill_output(qdio_q_t * q,unsigned int qidx,unsigned int count,qdio_buffer_t * buffers)3353 static inline void qdio_do_qdio_fill_output(qdio_q_t *q,unsigned int qidx,
3354 unsigned int count,
3355 qdio_buffer_t *buffers)
3356 {
3357 for (;;) {
3358 if (!q->is_0copy_sbals_q) {
3359 memcpy((void*)q->sbal[qidx],buffers,SBAL_SIZE);
3360 q->qdio_buffers[qidx]=buffers;
3361 buffers++;
3362 }
3363 set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED);
3364 count--;
3365 if (!count) break;
3366 qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
3367 }
3368
3369 /* SIGA write will sync the queues
3370 SYNC_MEMORY;*/
3371 }
3372
3373 /* count must be 1 in iqdio */
do_QDIO(int irq,unsigned int callflags,unsigned int queue_number,unsigned int qidx,unsigned int count,qdio_buffer_t * buffers)3374 int do_QDIO(int irq,unsigned int callflags,unsigned int queue_number,
3375 unsigned int qidx,unsigned int count,qdio_buffer_t *buffers)
3376 {
3377 qdio_q_t *q;
3378 qdio_irq_t *irq_ptr;
3379 int result;
3380 int used_elements;
3381
3382 #ifdef QDIO_DBF_LIKE_HELL
3383 char dbf_text[20];
3384
3385 sprintf(dbf_text,"doQD%04x",irq);
3386 QDIO_DBF_TEXT3(0,trace,dbf_text);
3387 #endif /* QDIO_DBF_LIKE_HELL */
3388
3389 if ( (qidx>QDIO_MAX_BUFFERS_PER_Q) ||
3390 (count>QDIO_MAX_BUFFERS_PER_Q) ||
3391 (queue_number>QDIO_MAX_QUEUES_PER_IRQ) )
3392 return -EINVAL;
3393
3394 if (count==0) return 0;
3395
3396 irq_ptr=qdio_get_irq_ptr(irq);
3397 if (!irq_ptr) return -ENODEV;
3398
3399 #ifdef QDIO_DBF_LIKE_HELL
3400 if (callflags&QDIO_FLAG_SYNC_INPUT)
3401 QDIO_DBF_HEX3(0,trace,&irq_ptr->input_qs[queue_number],
3402 sizeof(void*));
3403 else
3404 QDIO_DBF_HEX3(0,trace,&irq_ptr->output_qs[queue_number],
3405 sizeof(void*));
3406 sprintf(dbf_text,"flag%04x",callflags);
3407 QDIO_DBF_TEXT3(0,trace,dbf_text);
3408 sprintf(dbf_text,"qi%02xct%02x",qidx,count);
3409 QDIO_DBF_TEXT3(0,trace,dbf_text);
3410 if ( ((callflags&QDIO_FLAG_SYNC_INPUT)&&
3411 (!irq_ptr->input_qs[queue_number]->is_0copy_sbals_q)) ||
3412 ((callflags&QDIO_FLAG_SYNC_OUTPUT)&&
3413 (!irq_ptr->output_qs[queue_number]->is_0copy_sbals_q)) )
3414 QDIO_DBF_HEX5(0,sbal,buffers,256);
3415 #endif /* QDIO_DBF_LIKE_HELL */
3416
3417 if (irq_ptr->state!=QDIO_IRQ_STATE_ACTIVE) {
3418 return -EBUSY;
3419 }
3420
3421 if (callflags&QDIO_FLAG_SYNC_INPUT) {
3422 /* This is the inbound handling of queues */
3423 q=irq_ptr->input_qs[queue_number];
3424
3425 used_elements=atomic_return_add(count,
3426 &q->number_of_buffers_used);
3427
3428 qdio_do_qdio_fill_input(q,qidx,count,buffers);
3429
3430 if ((used_elements+count==QDIO_MAX_BUFFERS_PER_Q)&&
3431 (callflags&QDIO_FLAG_UNDER_INTERRUPT))
3432 atomic_swap(&q->polling,0);
3433
3434 if (!used_elements) if (!(callflags&QDIO_FLAG_DONT_SIGA)) {
3435 if (q->siga_in) {
3436 result=qdio_siga_input(q);
3437 if (result) {
3438 if (q->siga_error)
3439 q->error_status_flags|=
3440 QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
3441 q->error_status_flags|=
3442 QDIO_STATUS_LOOK_FOR_ERROR;
3443 q->siga_error=result;
3444 }
3445 }
3446
3447 qdio_mark_q(q);
3448 }
3449 } else if (callflags&QDIO_FLAG_SYNC_OUTPUT) {
3450 /* This is the outbound handling of queues */
3451 #ifdef QDIO_PERFORMANCE_STATS
3452 perf_stats.start_time_outbound=NOW;
3453 #endif /* QDIO_PERFORMANCE_STATS */
3454 q=irq_ptr->output_qs[queue_number];
3455
3456 qdio_do_qdio_fill_output(q,qidx,count,buffers);
3457
3458 used_elements=atomic_return_add(count,
3459 &q->number_of_buffers_used);
3460
3461 if (!(callflags&QDIO_FLAG_DONT_SIGA)) {
3462 if (q->is_iqdio_q) {
3463 /* one siga for every sbal */
3464 while (count--) {
3465 qdio_kick_outbound_q(q);
3466 }
3467
3468 __qdio_outbound_processing(q);
3469 } else {
3470 /* under VM, we do a SIGA sync
3471 * unconditionally */
3472 SYNC_MEMORY;
3473 else {
3474 /* w/o shadow queues (else branch of
3475 * SYNC_MEMORY :-/ ), we try to
3476 * fast-requeue buffers */
3477 if (q->slsb.acc.val
3478 [(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
3479 &(QDIO_MAX_BUFFERS_PER_Q-1)]!=
3480 SLSB_CU_OUTPUT_PRIMED) {
3481 qdio_kick_outbound_q(q);
3482 } else {
3483 #ifdef QDIO_DBF_LIKE_HELL
3484 QDIO_DBF_TEXT3(0,trace,
3485 "fast-req");
3486 #endif /* QDIO_DBF_LIKE_HELL */
3487 #ifdef QDIO_PERFORMANCE_STATS
3488 perf_stats.fast_reqs++;
3489 #endif /* QDIO_PERFORMANCE_STATS */
3490 }
3491 }
3492 /* only marking the q could take
3493 * too long, the upper layer
3494 * module could do a lot of
3495 * traffic in that time */
3496 __qdio_outbound_processing(q);
3497 }
3498 }
3499
3500 #ifdef QDIO_PERFORMANCE_STATS
3501 perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
3502 perf_stats.outbound_cnt++;
3503 #endif /* QDIO_PERFORMANCE_STATS */
3504 } else {
3505 QDIO_DBF_TEXT3(1,trace,"doQD:inv");
3506 return -EINVAL;
3507 }
3508 return 0;
3509 }
3510
3511 #ifdef QDIO_PERFORMANCE_STATS
qdio_perf_procfile_read(char * buffer,char ** buffer_location,off_t offset,int buffer_length,int * eof,void * data)3512 static int qdio_perf_procfile_read(char *buffer,char **buffer_location,
3513 off_t offset,int buffer_length,int *eof,
3514 void *data)
3515 {
3516 int c=0,bucket;
3517 qdio_irq_t *irq_ptr;
3518
3519 /* we are always called with buffer_length=4k, so we all
3520 deliver on the first read */
3521 if (offset>0) return 0;
3522
3523 #define _OUTP_IT(x...) c+=sprintf(buffer+c,x)
3524 _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
3525 _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
3526 _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
3527 _OUTP_IT("Number of tasklet runs (total) : %u\n",
3528 perf_stats.tl_runs);
3529 _OUTP_IT("\n");
3530 _OUTP_IT("Number of SIGA sync's issued : %u\n",
3531 perf_stats.siga_syncs);
3532 _OUTP_IT("Number of SIGA in's issued : %u\n",
3533 perf_stats.siga_ins);
3534 _OUTP_IT("Number of SIGA out's issued : %u\n",
3535 perf_stats.siga_outs);
3536 _OUTP_IT("Number of PCIs caught : %u\n",
3537 perf_stats.pcis);
3538 _OUTP_IT("Number of adapter interrupts caught : %u\n",
3539 perf_stats.thinints);
3540 _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %u\n",
3541 perf_stats.fast_reqs);
3542 _OUTP_IT("\n");
3543 _OUTP_IT("Total time of all inbound actions (us) incl. UL : %u\n",
3544 perf_stats.inbound_time);
3545 _OUTP_IT("Number of inbound transfers : %u\n",
3546 perf_stats.inbound_cnt);
3547 _OUTP_IT("Total time of all outbound do_QDIOs (us) : %u\n",
3548 perf_stats.outbound_time);
3549 _OUTP_IT("Number of do_QDIOs outbound : %u\n",
3550 perf_stats.outbound_cnt);
3551 _OUTP_IT("\n");
3552
3553 for (bucket=0;bucket<QDIO_IRQ_BUCKETS;bucket++) {
3554 irq_ptr=first_irq[bucket];
3555
3556 while (irq_ptr) {
3557 _OUTP_IT("Polling time on irq %4x" \
3558 " : %u\n",
3559 irq_ptr->irq,irq_ptr->input_qs[0]->
3560 timing.threshold);
3561 irq_ptr=irq_ptr->next;
3562 }
3563 }
3564
3565 return c;
3566 }
3567
3568 static struct proc_dir_entry *qdio_perf_proc_file;
3569 #endif /* QDIO_PERFORMANCE_STATS */
3570
qdio_add_procfs_entry(void)3571 static void qdio_add_procfs_entry(void)
3572 {
3573 #ifdef QDIO_PERFORMANCE_STATS
3574 proc_perf_file_registration=0;
3575 qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
3576 S_IFREG|0444,&proc_root);
3577 if (qdio_perf_proc_file) {
3578 qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read;
3579 } else proc_perf_file_registration=-1;
3580
3581 if (proc_perf_file_registration)
3582 QDIO_PRINT_WARN("was not able to register perf. " \
3583 "proc-file (%i).\n",
3584 proc_perf_file_registration);
3585 #endif /* QDIO_PERFORMANCE_STATS */
3586 }
3587 #ifdef MODULE
qdio_remove_procfs_entry(void)3588 static void qdio_remove_procfs_entry(void)
3589 {
3590 #ifdef QDIO_PERFORMANCE_STATS
3591 perf_stats.tl_runs=0;
3592
3593 if (!proc_perf_file_registration) /* means if it went ok earlier */
3594 remove_proc_entry(QDIO_PERF,&proc_root);
3595 #endif /* QDIO_PERFORMANCE_STATS */
3596 }
3597 #endif /* MODULE */
3598
tiqdio_register_thinints(void)3599 static void tiqdio_register_thinints(void)
3600 {
3601 char dbf_text[20];
3602 register_thinint_result=
3603 s390_register_adapter_interrupt(&tiqdio_thinint_handler);
3604 if (register_thinint_result) {
3605 sprintf(dbf_text,"regthn%x",(register_thinint_result&0xff));
3606 QDIO_DBF_TEXT0(0,setup,dbf_text);
3607 QDIO_PRINT_ERR("failed to register adapter handler " \
3608 "(rc=%i).\nAdapter interrupts might " \
3609 "not work. Continuing.\n",
3610 register_thinint_result);
3611 }
3612 }
3613
3614 #ifdef MODULE
tiqdio_unregister_thinints(void)3615 static void tiqdio_unregister_thinints(void)
3616 {
3617 if (!register_thinint_result)
3618 s390_unregister_adapter_interrupt(&tiqdio_thinint_handler);
3619 }
3620 #endif /* MODULE */
3621
qdio_get_qdio_memory(void)3622 static int qdio_get_qdio_memory(void)
3623 {
3624 int i;
3625 indicator_used[0]=1;
3626
3627 for (i=1;i<INDICATORS_PER_CACHELINE;i++)
3628 indicator_used[i]=0;
3629 indicators=(__u32*)kmalloc(sizeof(__u32)*(INDICATORS_PER_CACHELINE),
3630 GFP_KERNEL);
3631 if (!indicators) return -ENOMEM;
3632 memset(indicators,0,sizeof(__u32)*(INDICATORS_PER_CACHELINE));
3633
3634 chsc_area=(qdio_chsc_area_t *)
3635 kmalloc(sizeof(qdio_chsc_area_t),GFP_KERNEL);
3636 QDIO_DBF_TEXT3(0,trace,"chscarea"); \
3637 QDIO_DBF_HEX3(0,trace,&chsc_area,sizeof(void*)); \
3638 if (!chsc_area) {
3639 /* ahem... let's call it data area */
3640 QDIO_PRINT_ERR("not enough memory for data area. Cannot " \
3641 "initialize QDIO.\n");
3642 kfree(indicators);
3643 return -ENOMEM;
3644 }
3645 memset(chsc_area,0,sizeof(qdio_chsc_area_t));
3646 return 0;
3647 }
3648
3649 #ifdef MODULE
qdio_release_qdio_memory(void)3650 static void qdio_release_qdio_memory(void)
3651 {
3652 kfree(chsc_area);
3653 if (indicators) kfree(indicators);
3654 }
3655 #endif /* MODULE */
3656
3657 int init_module(void); /* we want to use it in init_QDIO */
3658
qdio_unregister_dbf_views(void)3659 static void qdio_unregister_dbf_views(void)
3660 {
3661 if (qdio_dbf_setup)
3662 debug_unregister(qdio_dbf_setup);
3663 if (qdio_dbf_sbal)
3664 debug_unregister(qdio_dbf_sbal);
3665 if (qdio_dbf_sense)
3666 debug_unregister(qdio_dbf_sense);
3667 if (qdio_dbf_trace)
3668 debug_unregister(qdio_dbf_trace);
3669 #ifdef QDIO_DBF_LIKE_HELL
3670 if (qdio_dbf_slsb_out)
3671 debug_unregister(qdio_dbf_slsb_out);
3672 if (qdio_dbf_slsb_in)
3673 debug_unregister(qdio_dbf_slsb_in);
3674 #endif /* QDIO_DBF_LIKE_HELL */
3675 }
3676
3677 /* this is not __initfunc, as it is called from init_module */
init_QDIO(void)3678 int init_QDIO(void)
3679 {
3680 char dbf_text[20];
3681 int res;
3682 #if defined(MODULE)||defined(QDIO_PERFORMANCE_STATS)
3683 void *ptr;
3684 #endif /* defined(MODULE)||defined(QDIO_PERFORMANCE_STATS) */
3685
3686 qdio_eyecatcher();
3687
3688 printk("qdio: loading %s\n",version);
3689
3690 res=qdio_get_qdio_memory();
3691 if (res) return res;
3692
3693 sema_init(&init_sema,1);
3694
3695 qdio_dbf_setup=debug_register(QDIO_DBF_SETUP_NAME,
3696 QDIO_DBF_SETUP_INDEX,
3697 QDIO_DBF_SETUP_NR_AREAS,
3698 QDIO_DBF_SETUP_LEN);
3699 if (!qdio_dbf_setup) goto oom;
3700 debug_register_view(qdio_dbf_setup,&debug_hex_ascii_view);
3701 debug_set_level(qdio_dbf_setup,QDIO_DBF_SETUP_LEVEL);
3702
3703 qdio_dbf_sbal=debug_register(QDIO_DBF_SBAL_NAME,
3704 QDIO_DBF_SBAL_INDEX,
3705 QDIO_DBF_SBAL_NR_AREAS,
3706 QDIO_DBF_SBAL_LEN);
3707 if (!qdio_dbf_sbal) goto oom;
3708
3709 debug_register_view(qdio_dbf_sbal,&debug_hex_ascii_view);
3710 debug_set_level(qdio_dbf_sbal,QDIO_DBF_SBAL_LEVEL);
3711
3712 qdio_dbf_sense=debug_register(QDIO_DBF_SENSE_NAME,
3713 QDIO_DBF_SENSE_INDEX,
3714 QDIO_DBF_SENSE_NR_AREAS,
3715 QDIO_DBF_SENSE_LEN);
3716 if (!qdio_dbf_sense) goto oom;
3717
3718 debug_register_view(qdio_dbf_sense,&debug_hex_ascii_view);
3719 debug_set_level(qdio_dbf_sense,QDIO_DBF_SENSE_LEVEL);
3720
3721 qdio_dbf_trace=debug_register(QDIO_DBF_TRACE_NAME,
3722 QDIO_DBF_TRACE_INDEX,
3723 QDIO_DBF_TRACE_NR_AREAS,
3724 QDIO_DBF_TRACE_LEN);
3725 if (!qdio_dbf_trace) goto oom;
3726
3727 debug_register_view(qdio_dbf_trace,&debug_hex_ascii_view);
3728 debug_set_level(qdio_dbf_trace,QDIO_DBF_TRACE_LEVEL);
3729
3730 #ifdef QDIO_DBF_LIKE_HELL
3731 qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME,
3732 QDIO_DBF_SLSB_OUT_INDEX,
3733 QDIO_DBF_SLSB_OUT_NR_AREAS,
3734 QDIO_DBF_SLSB_OUT_LEN);
3735 if (!qdio_dbf_slsb_out) goto oom;
3736 debug_register_view(qdio_dbf_slsb_out,&debug_hex_ascii_view);
3737 debug_set_level(qdio_dbf_slsb_out,QDIO_DBF_SLSB_OUT_LEVEL);
3738
3739 qdio_dbf_slsb_in=debug_register(QDIO_DBF_SLSB_IN_NAME,
3740 QDIO_DBF_SLSB_IN_INDEX,
3741 QDIO_DBF_SLSB_IN_NR_AREAS,
3742 QDIO_DBF_SLSB_IN_LEN);
3743 if (!qdio_dbf_slsb_in) goto oom;
3744 debug_register_view(qdio_dbf_slsb_in,&debug_hex_ascii_view);
3745 debug_set_level(qdio_dbf_slsb_in,QDIO_DBF_SLSB_IN_LEVEL);
3746 #endif /* QDIO_DBF_LIKE_HELL */
3747
3748 #ifdef QDIO_PERFORMANCE_STATS
3749 memset((void*)&perf_stats,0,sizeof(perf_stats));
3750 QDIO_DBF_TEXT0(0,setup,"perfstat");
3751 ptr=&perf_stats;
3752 QDIO_DBF_HEX0(0,setup,&ptr,sizeof(void*));
3753 #endif /* QDIO_PERFORMANCE_STATS */
3754
3755 #ifdef MODULE
3756 QDIO_DBF_TEXT0(0,setup,"initmodl");
3757 ptr=&init_module;
3758 QDIO_DBF_HEX0(0,setup,&ptr,sizeof(void*));
3759 #endif /* MODULE */
3760
3761 qdio_add_procfs_entry();
3762
3763 qdio_check_for_machine_features();
3764
3765 sprintf(dbf_text,"hydrati%1x",hydra_thinints);
3766 QDIO_DBF_TEXT0(0,setup,dbf_text);
3767 sprintf(dbf_text,"omitsvs%1x",omit_svs);
3768 QDIO_DBF_TEXT0(0,setup,dbf_text);
3769
3770 tiqdio_register_thinints();
3771
3772 return 0;
3773 oom:
3774 QDIO_PRINT_ERR("not enough memory for dbf.\n");
3775 qdio_unregister_dbf_views();
3776 return -ENOMEM;
3777 }
3778
3779 #ifdef MODULE
init_module(void)3780 int init_module(void)
3781 {
3782 return init_QDIO();
3783 }
3784
cleanup_module(void)3785 void cleanup_module(void)
3786 {
3787 tiqdio_unregister_thinints();
3788
3789 qdio_remove_procfs_entry();
3790
3791 qdio_release_qdio_memory();
3792
3793 qdio_unregister_dbf_views();
3794
3795 printk("qdio: %s: module removed\n",version);
3796 }
3797 #else /* MODULE */
initcall_QDIO(void)3798 static int __init initcall_QDIO(void)
3799 {
3800 return init_QDIO();
3801 }
3802 __initcall(initcall_QDIO);
3803 #endif /* MODULE */
3804
3805 EXPORT_SYMBOL(qdio_initialize);
3806 EXPORT_SYMBOL(qdio_activate);
3807 EXPORT_SYMBOL(do_QDIO);
3808 EXPORT_SYMBOL(qdio_cleanup);
3809 EXPORT_SYMBOL(qdio_eyecatcher);
3810 EXPORT_SYMBOL(qdio_synchronize);
3811
3812