blob: fa385e761fe177034551ab5a82038d8ff38f3693 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#ifndef _CIO_QDIO_H
2#define _CIO_QDIO_H
3
Peter Oberparleiter0b642ed2005-05-01 08:58:58 -07004#include <asm/page.h>
5
Cornelia Hucka8237fc2006-01-06 00:19:21 -08006#include "schid.h"
7
8#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
10#ifdef CONFIG_QDIO_DEBUG
11#define QDIO_VERBOSE_LEVEL 9
12#else /* CONFIG_QDIO_DEBUG */
13#define QDIO_VERBOSE_LEVEL 5
14#endif /* CONFIG_QDIO_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#define QDIO_USE_PROCESSING_STATE
16
17#ifdef CONFIG_QDIO_PERF_STATS
18#define QDIO_PERFORMANCE_STATS
19#endif /* CONFIG_QDIO_PERF_STATS */
20
21#define QDIO_MINIMAL_BH_RELIEF_TIME 16
22#define QDIO_TIMER_POLL_VALUE 1
23#define IQDIO_TIMER_POLL_VALUE 1
24
25/*
26 * unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as
27 * we never know, whether we'll get initiative again, e.g. to give the
28 * transmit skb's back to the stack, however the stack may be waiting for
29 * them... therefore we define 4 as threshold to start polling (which
30 * will stop as soon as the asynchronous queue catches up)
31 * btw, this only applies to the asynchronous HiperSockets queue
32 */
33#define IQDIO_FILL_LEVEL_TO_POLL 4
34
35#define TIQDIO_THININT_ISC 3
36#define TIQDIO_DELAY_TARGET 0
37#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
38#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
39#define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
40#define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */
41#define IQDIO_LOCAL_LAPS 4
42#define IQDIO_LOCAL_LAPS_INT 1
43#define IQDIO_GLOBAL_SUMMARY_CC_MASK 2
44/*#define IQDIO_IQDC_INT_PARM 0x1234*/
45
46#define QDIO_Q_LAPS 5
47
Peter Oberparleiter0b642ed2005-05-01 08:58:58 -070048#define QDIO_STORAGE_KEY PAGE_DEFAULT_KEY
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#define L2_CACHELINE_SIZE 256
51#define INDICATORS_PER_CACHELINE (L2_CACHELINE_SIZE/sizeof(__u32))
52
53#define QDIO_PERF "qdio_perf"
54
55/* must be a power of 2 */
56/*#define QDIO_STATS_NUMBER 4
57
58#define QDIO_STATS_CLASSES 2
59#define QDIO_STATS_COUNT_NEEDED 2*/
60
61#define QDIO_NO_USE_COUNT_TIMEOUT (1*HZ) /* wait for 1 sec on each q before
62 exiting without having use_count
63 of the queue to 0 */
64
65#define QDIO_ESTABLISH_TIMEOUT (1*HZ)
66#define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10)
67#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
68#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
69
70enum qdio_irq_states {
71 QDIO_IRQ_STATE_INACTIVE,
72 QDIO_IRQ_STATE_ESTABLISHED,
73 QDIO_IRQ_STATE_ACTIVE,
74 QDIO_IRQ_STATE_STOPPED,
75 QDIO_IRQ_STATE_CLEANUP,
76 QDIO_IRQ_STATE_ERR,
77 NR_QDIO_IRQ_STATES,
78};
79
80/* used as intparm in do_IO: */
81#define QDIO_DOING_SENSEID 0
82#define QDIO_DOING_ESTABLISH 1
83#define QDIO_DOING_ACTIVATE 2
84#define QDIO_DOING_CLEANUP 3
85
86/************************* DEBUG FACILITY STUFF *********************/
87
88#define QDIO_DBF_HEX(ex,name,level,addr,len) \
89 do { \
90 if (ex) \
91 debug_exception(qdio_dbf_##name,level,(void*)(addr),len); \
92 else \
93 debug_event(qdio_dbf_##name,level,(void*)(addr),len); \
94 } while (0)
95#define QDIO_DBF_TEXT(ex,name,level,text) \
96 do { \
97 if (ex) \
98 debug_text_exception(qdio_dbf_##name,level,text); \
99 else \
100 debug_text_event(qdio_dbf_##name,level,text); \
101 } while (0)
102
103
104#define QDIO_DBF_HEX0(ex,name,addr,len) QDIO_DBF_HEX(ex,name,0,addr,len)
105#define QDIO_DBF_HEX1(ex,name,addr,len) QDIO_DBF_HEX(ex,name,1,addr,len)
106#define QDIO_DBF_HEX2(ex,name,addr,len) QDIO_DBF_HEX(ex,name,2,addr,len)
107#ifdef CONFIG_QDIO_DEBUG
108#define QDIO_DBF_HEX3(ex,name,addr,len) QDIO_DBF_HEX(ex,name,3,addr,len)
109#define QDIO_DBF_HEX4(ex,name,addr,len) QDIO_DBF_HEX(ex,name,4,addr,len)
110#define QDIO_DBF_HEX5(ex,name,addr,len) QDIO_DBF_HEX(ex,name,5,addr,len)
111#define QDIO_DBF_HEX6(ex,name,addr,len) QDIO_DBF_HEX(ex,name,6,addr,len)
112#else /* CONFIG_QDIO_DEBUG */
113#define QDIO_DBF_HEX3(ex,name,addr,len) do {} while (0)
114#define QDIO_DBF_HEX4(ex,name,addr,len) do {} while (0)
115#define QDIO_DBF_HEX5(ex,name,addr,len) do {} while (0)
116#define QDIO_DBF_HEX6(ex,name,addr,len) do {} while (0)
117#endif /* CONFIG_QDIO_DEBUG */
118
119#define QDIO_DBF_TEXT0(ex,name,text) QDIO_DBF_TEXT(ex,name,0,text)
120#define QDIO_DBF_TEXT1(ex,name,text) QDIO_DBF_TEXT(ex,name,1,text)
121#define QDIO_DBF_TEXT2(ex,name,text) QDIO_DBF_TEXT(ex,name,2,text)
122#ifdef CONFIG_QDIO_DEBUG
123#define QDIO_DBF_TEXT3(ex,name,text) QDIO_DBF_TEXT(ex,name,3,text)
124#define QDIO_DBF_TEXT4(ex,name,text) QDIO_DBF_TEXT(ex,name,4,text)
125#define QDIO_DBF_TEXT5(ex,name,text) QDIO_DBF_TEXT(ex,name,5,text)
126#define QDIO_DBF_TEXT6(ex,name,text) QDIO_DBF_TEXT(ex,name,6,text)
127#else /* CONFIG_QDIO_DEBUG */
128#define QDIO_DBF_TEXT3(ex,name,text) do {} while (0)
129#define QDIO_DBF_TEXT4(ex,name,text) do {} while (0)
130#define QDIO_DBF_TEXT5(ex,name,text) do {} while (0)
131#define QDIO_DBF_TEXT6(ex,name,text) do {} while (0)
132#endif /* CONFIG_QDIO_DEBUG */
133
134#define QDIO_DBF_SETUP_NAME "qdio_setup"
135#define QDIO_DBF_SETUP_LEN 8
Michael Holzheu66a464d2005-06-25 14:55:33 -0700136#define QDIO_DBF_SETUP_PAGES 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define QDIO_DBF_SETUP_NR_AREAS 1
138#ifdef CONFIG_QDIO_DEBUG
139#define QDIO_DBF_SETUP_LEVEL 6
140#else /* CONFIG_QDIO_DEBUG */
141#define QDIO_DBF_SETUP_LEVEL 2
142#endif /* CONFIG_QDIO_DEBUG */
143
144#define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */
145#define QDIO_DBF_SBAL_LEN 256
Michael Holzheu66a464d2005-06-25 14:55:33 -0700146#define QDIO_DBF_SBAL_PAGES 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147#define QDIO_DBF_SBAL_NR_AREAS 2
148#ifdef CONFIG_QDIO_DEBUG
149#define QDIO_DBF_SBAL_LEVEL 6
150#else /* CONFIG_QDIO_DEBUG */
151#define QDIO_DBF_SBAL_LEVEL 2
152#endif /* CONFIG_QDIO_DEBUG */
153
154#define QDIO_DBF_TRACE_NAME "qdio_trace"
155#define QDIO_DBF_TRACE_LEN 8
156#define QDIO_DBF_TRACE_NR_AREAS 2
157#ifdef CONFIG_QDIO_DEBUG
Michael Holzheu66a464d2005-06-25 14:55:33 -0700158#define QDIO_DBF_TRACE_PAGES 16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159#define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */
160#else /* CONFIG_QDIO_DEBUG */
Michael Holzheu66a464d2005-06-25 14:55:33 -0700161#define QDIO_DBF_TRACE_PAGES 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162#define QDIO_DBF_TRACE_LEVEL 2
163#endif /* CONFIG_QDIO_DEBUG */
164
165#define QDIO_DBF_SENSE_NAME "qdio_sense"
166#define QDIO_DBF_SENSE_LEN 64
Michael Holzheu66a464d2005-06-25 14:55:33 -0700167#define QDIO_DBF_SENSE_PAGES 2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168#define QDIO_DBF_SENSE_NR_AREAS 1
169#ifdef CONFIG_QDIO_DEBUG
170#define QDIO_DBF_SENSE_LEVEL 6
171#else /* CONFIG_QDIO_DEBUG */
172#define QDIO_DBF_SENSE_LEVEL 2
173#endif /* CONFIG_QDIO_DEBUG */
174
175#ifdef CONFIG_QDIO_DEBUG
176#define QDIO_TRACE_QTYPE QDIO_ZFCP_QFMT
177
178#define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out"
179#define QDIO_DBF_SLSB_OUT_LEN QDIO_MAX_BUFFERS_PER_Q
Michael Holzheu66a464d2005-06-25 14:55:33 -0700180#define QDIO_DBF_SLSB_OUT_PAGES 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#define QDIO_DBF_SLSB_OUT_NR_AREAS 1
182#define QDIO_DBF_SLSB_OUT_LEVEL 6
183
184#define QDIO_DBF_SLSB_IN_NAME "qdio_slsb_in"
185#define QDIO_DBF_SLSB_IN_LEN QDIO_MAX_BUFFERS_PER_Q
Michael Holzheu66a464d2005-06-25 14:55:33 -0700186#define QDIO_DBF_SLSB_IN_PAGES 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187#define QDIO_DBF_SLSB_IN_NR_AREAS 1
188#define QDIO_DBF_SLSB_IN_LEVEL 6
189#endif /* CONFIG_QDIO_DEBUG */
190
191#define QDIO_PRINTK_HEADER QDIO_NAME ": "
192
193#if QDIO_VERBOSE_LEVEL>8
194#define QDIO_PRINT_STUPID(x...) printk( KERN_DEBUG QDIO_PRINTK_HEADER x)
195#else
196#define QDIO_PRINT_STUPID(x...)
197#endif
198
199#if QDIO_VERBOSE_LEVEL>7
200#define QDIO_PRINT_ALL(x...) printk( QDIO_PRINTK_HEADER x)
201#else
202#define QDIO_PRINT_ALL(x...)
203#endif
204
205#if QDIO_VERBOSE_LEVEL>6
206#define QDIO_PRINT_INFO(x...) printk( QDIO_PRINTK_HEADER x)
207#else
208#define QDIO_PRINT_INFO(x...)
209#endif
210
211#if QDIO_VERBOSE_LEVEL>5
212#define QDIO_PRINT_WARN(x...) printk( QDIO_PRINTK_HEADER x)
213#else
214#define QDIO_PRINT_WARN(x...)
215#endif
216
217#if QDIO_VERBOSE_LEVEL>4
218#define QDIO_PRINT_ERR(x...) printk( QDIO_PRINTK_HEADER x)
219#else
220#define QDIO_PRINT_ERR(x...)
221#endif
222
223#if QDIO_VERBOSE_LEVEL>3
224#define QDIO_PRINT_CRIT(x...) printk( QDIO_PRINTK_HEADER x)
225#else
226#define QDIO_PRINT_CRIT(x...)
227#endif
228
229#if QDIO_VERBOSE_LEVEL>2
230#define QDIO_PRINT_ALERT(x...) printk( QDIO_PRINTK_HEADER x)
231#else
232#define QDIO_PRINT_ALERT(x...)
233#endif
234
235#if QDIO_VERBOSE_LEVEL>1
236#define QDIO_PRINT_EMERG(x...) printk( QDIO_PRINTK_HEADER x)
237#else
238#define QDIO_PRINT_EMERG(x...)
239#endif
240
241#define HEXDUMP16(importance,header,ptr) \
242QDIO_PRINT_##importance(header "%02x %02x %02x %02x " \
243 "%02x %02x %02x %02x %02x %02x %02x %02x " \
244 "%02x %02x %02x %02x\n",*(((char*)ptr)), \
245 *(((char*)ptr)+1),*(((char*)ptr)+2), \
246 *(((char*)ptr)+3),*(((char*)ptr)+4), \
247 *(((char*)ptr)+5),*(((char*)ptr)+6), \
248 *(((char*)ptr)+7),*(((char*)ptr)+8), \
249 *(((char*)ptr)+9),*(((char*)ptr)+10), \
250 *(((char*)ptr)+11),*(((char*)ptr)+12), \
251 *(((char*)ptr)+13),*(((char*)ptr)+14), \
252 *(((char*)ptr)+15)); \
253QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
254 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
255 *(((char*)ptr)+16),*(((char*)ptr)+17), \
256 *(((char*)ptr)+18),*(((char*)ptr)+19), \
257 *(((char*)ptr)+20),*(((char*)ptr)+21), \
258 *(((char*)ptr)+22),*(((char*)ptr)+23), \
259 *(((char*)ptr)+24),*(((char*)ptr)+25), \
260 *(((char*)ptr)+26),*(((char*)ptr)+27), \
261 *(((char*)ptr)+28),*(((char*)ptr)+29), \
262 *(((char*)ptr)+30),*(((char*)ptr)+31));
263
264/****************** END OF DEBUG FACILITY STUFF *********************/
265
266/*
267 * Some instructions as assembly
268 */
Frank Pavlic8129ee12006-01-06 00:19:20 -0800269
270static inline int
271do_sqbs(unsigned long sch, unsigned char state, int queue,
272 unsigned int *start, unsigned int *count)
273{
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800274#ifdef CONFIG_64BIT
Frank Pavlic8129ee12006-01-06 00:19:20 -0800275 register unsigned long _ccq asm ("0") = *count;
276 register unsigned long _sch asm ("1") = sch;
277 unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
278
279 asm volatile (
280 " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
281 : "+d" (_ccq), "+d" (_queuestart)
282 : "d" ((unsigned long)state), "d" (_sch)
283 : "memory", "cc"
284 );
285 *count = _ccq & 0xff;
286 *start = _queuestart & 0xff;
287
288 return (_ccq >> 32) & 0xff;
289#else
290 return 0;
291#endif
292}
293
294static inline int
295do_eqbs(unsigned long sch, unsigned char *state, int queue,
296 unsigned int *start, unsigned int *count)
297{
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800298#ifdef CONFIG_64BIT
Frank Pavlic8129ee12006-01-06 00:19:20 -0800299 register unsigned long _ccq asm ("0") = *count;
300 register unsigned long _sch asm ("1") = sch;
301 unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
302 unsigned long _state = 0;
303
304 asm volatile (
305 " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t"
306 : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
307 : "d" (_sch)
308 : "memory", "cc"
309 );
310 *count = _ccq & 0xff;
311 *start = _queuestart & 0xff;
312 *state = _state & 0xff;
313
314 return (_ccq >> 32) & 0xff;
315#else
316 return 0;
317#endif
318}
319
320
Adrian Bunk4448aaf2005-11-08 21:34:42 -0800321static inline int
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800322do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
324 int cc;
325
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800326#ifndef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 asm volatile (
328 "lhi 0,2 \n\t"
329 "lr 1,%1 \n\t"
330 "lr 2,%2 \n\t"
331 "lr 3,%3 \n\t"
332 "siga 0 \n\t"
333 "ipm %0 \n\t"
334 "srl %0,28 \n\t"
335 : "=d" (cc)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800336 : "d" (schid), "d" (mask1), "d" (mask2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 : "cc", "0", "1", "2", "3"
338 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800339#else /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 asm volatile (
341 "lghi 0,2 \n\t"
342 "llgfr 1,%1 \n\t"
343 "llgfr 2,%2 \n\t"
344 "llgfr 3,%3 \n\t"
345 "siga 0 \n\t"
346 "ipm %0 \n\t"
347 "srl %0,28 \n\t"
348 : "=d" (cc)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800349 : "d" (schid), "d" (mask1), "d" (mask2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 : "cc", "0", "1", "2", "3"
351 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800352#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return cc;
354}
355
Adrian Bunk4448aaf2005-11-08 21:34:42 -0800356static inline int
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800357do_siga_input(struct subchannel_id schid, unsigned int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
359 int cc;
360
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800361#ifndef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 asm volatile (
363 "lhi 0,1 \n\t"
364 "lr 1,%1 \n\t"
365 "lr 2,%2 \n\t"
366 "siga 0 \n\t"
367 "ipm %0 \n\t"
368 "srl %0,28 \n\t"
369 : "=d" (cc)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800370 : "d" (schid), "d" (mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 : "cc", "0", "1", "2", "memory"
372 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800373#else /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 asm volatile (
375 "lghi 0,1 \n\t"
376 "llgfr 1,%1 \n\t"
377 "llgfr 2,%2 \n\t"
378 "siga 0 \n\t"
379 "ipm %0 \n\t"
380 "srl %0,28 \n\t"
381 : "=d" (cc)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800382 : "d" (schid), "d" (mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 : "cc", "0", "1", "2", "memory"
384 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800385#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 return cc;
388}
389
Adrian Bunk4448aaf2005-11-08 21:34:42 -0800390static inline int
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800391do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
Frank Pavlic8129ee12006-01-06 00:19:20 -0800392 unsigned int fc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
394 int cc;
395 __u32 busy_bit;
396
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800397#ifndef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 asm volatile (
399 "lhi 0,0 \n\t"
400 "lr 1,%2 \n\t"
401 "lr 2,%3 \n\t"
402 "siga 0 \n\t"
403 "0:"
404 "ipm %0 \n\t"
405 "srl %0,28 \n\t"
406 "srl 0,31 \n\t"
407 "lr %1,0 \n\t"
408 "1: \n\t"
409 ".section .fixup,\"ax\"\n\t"
410 "2: \n\t"
411 "lhi %0,%4 \n\t"
412 "bras 1,3f \n\t"
413 ".long 1b \n\t"
414 "3: \n\t"
415 "l 1,0(1) \n\t"
416 "br 1 \n\t"
417 ".previous \n\t"
418 ".section __ex_table,\"a\"\n\t"
419 ".align 4 \n\t"
420 ".long 0b,2b \n\t"
421 ".previous \n\t"
422 : "=d" (cc), "=d" (busy_bit)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800423 : "d" (schid), "d" (mask),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
425 : "cc", "0", "1", "2", "memory"
426 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800427#else /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 asm volatile (
Frank Pavlic8129ee12006-01-06 00:19:20 -0800429 "llgfr 0,%5 \n\t"
430 "lgr 1,%2 \n\t"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 "llgfr 2,%3 \n\t"
432 "siga 0 \n\t"
433 "0:"
434 "ipm %0 \n\t"
435 "srl %0,28 \n\t"
436 "srl 0,31 \n\t"
437 "llgfr %1,0 \n\t"
438 "1: \n\t"
439 ".section .fixup,\"ax\"\n\t"
440 "lghi %0,%4 \n\t"
441 "jg 1b \n\t"
442 ".previous\n\t"
443 ".section __ex_table,\"a\"\n\t"
444 ".align 8 \n\t"
445 ".quad 0b,1b \n\t"
446 ".previous \n\t"
447 : "=d" (cc), "=d" (busy_bit)
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800448 : "d" (schid), "d" (mask),
Frank Pavlic8129ee12006-01-06 00:19:20 -0800449 "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 : "cc", "0", "1", "2", "memory"
451 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800452#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
454 (*bb) = busy_bit;
455 return cc;
456}
457
Adrian Bunk4448aaf2005-11-08 21:34:42 -0800458static inline unsigned long
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459do_clear_global_summary(void)
460{
461
462 unsigned long time;
463
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800464#ifndef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 asm volatile (
466 "lhi 1,3 \n\t"
467 ".insn rre,0xb2650000,2,0 \n\t"
468 "lr %0,3 \n\t"
469 : "=d" (time) : : "cc", "1", "2", "3"
470 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800471#else /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 asm volatile (
473 "lghi 1,3 \n\t"
474 ".insn rre,0xb2650000,2,0 \n\t"
475 "lgr %0,3 \n\t"
476 : "=d" (time) : : "cc", "1", "2", "3"
477 );
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800478#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 return time;
481}
482
483/*
484 * QDIO device commands returned by extended Sense-ID
485 */
486#define DEFAULT_ESTABLISH_QS_CMD 0x1b
487#define DEFAULT_ESTABLISH_QS_COUNT 0x1000
488#define DEFAULT_ACTIVATE_QS_CMD 0x1f
489#define DEFAULT_ACTIVATE_QS_COUNT 0
490
491/*
492 * additional CIWs returned by extended Sense-ID
493 */
494#define CIW_TYPE_EQUEUE 0x3 /* establish QDIO queues */
495#define CIW_TYPE_AQUEUE 0x4 /* activate QDIO queues */
496
497#define QDIO_CHSC_RESPONSE_CODE_OK 1
498/* flags for st qdio sch data */
499#define CHSC_FLAG_QDIO_CAPABILITY 0x80
500#define CHSC_FLAG_VALIDITY 0x40
501
502#define CHSC_FLAG_SIGA_INPUT_NECESSARY 0x40
503#define CHSC_FLAG_SIGA_OUTPUT_NECESSARY 0x20
504#define CHSC_FLAG_SIGA_SYNC_NECESSARY 0x10
505#define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
506#define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
507
508#ifdef QDIO_PERFORMANCE_STATS
509struct qdio_perf_stats {
510 unsigned int tl_runs;
511
512 unsigned int siga_outs;
513 unsigned int siga_ins;
514 unsigned int siga_syncs;
515 unsigned int pcis;
516 unsigned int thinints;
517 unsigned int fast_reqs;
518
519 __u64 start_time_outbound;
520 unsigned int outbound_cnt;
521 unsigned int outbound_time;
522 __u64 start_time_inbound;
523 unsigned int inbound_cnt;
524 unsigned int inbound_time;
525};
526#endif /* QDIO_PERFORMANCE_STATS */
527
528#define atomic_swap(a,b) xchg((int*)a.counter,b)
529
530/* unlikely as the later the better */
531#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
532#define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \
533 qdio_siga_sync(q,~0U,~0U)
534#define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \
535 qdio_siga_sync(q,~0U,0)
536
537#define NOW qdio_get_micros()
538#define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW
539#define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time)
540#define SAVE_FRONTIER(q,val) q->last_move_ftc=val
541#define GET_SAVED_FRONTIER(q) (q->last_move_ftc)
542
543#define MY_MODULE_STRING(x) #x
544
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800545#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546#define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x)
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800547#else /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548#define QDIO_GET_ADDR(x) ((__u32)(long)x)
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800549#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551struct qdio_q {
552 volatile struct slsb slsb;
553
554 char unused[QDIO_MAX_BUFFERS_PER_Q];
555
Frank Pavlic8129ee12006-01-06 00:19:20 -0800556 __u32 * dev_st_chg_ind;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
558 int is_input_q;
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800559 struct subchannel_id schid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 struct ccw_device *cdev;
561
562 unsigned int is_iqdio_q;
563 unsigned int is_thinint_q;
564
565 /* bit 0 means queue 0, bit 1 means queue 1, ... */
566 unsigned int mask;
567 unsigned int q_no;
568
569 qdio_handler_t (*handler);
570
571 /* points to the next buffer to be checked for having
572 * been processed by the card (outbound)
573 * or to the next buffer the program should check for (inbound) */
574 volatile int first_to_check;
575 /* and the last time it was: */
576 volatile int last_move_ftc;
577
578 atomic_t number_of_buffers_used;
579 atomic_t polling;
580
581 unsigned int siga_in;
582 unsigned int siga_out;
583 unsigned int siga_sync;
584 unsigned int siga_sync_done_on_thinints;
585 unsigned int siga_sync_done_on_outb_tis;
586 unsigned int hydra_gives_outbound_pcis;
587
588 /* used to save beginning position when calling dd_handlers */
589 int first_element_to_kick;
590
591 atomic_t use_count;
592 atomic_t is_in_shutdown;
593
594 void *irq_ptr;
595
596#ifdef QDIO_USE_TIMERS_FOR_POLLING
597 struct timer_list timer;
598 atomic_t timer_already_set;
599 spinlock_t timer_lock;
600#else /* QDIO_USE_TIMERS_FOR_POLLING */
601 struct tasklet_struct tasklet;
602#endif /* QDIO_USE_TIMERS_FOR_POLLING */
603
Frank Pavlic8129ee12006-01-06 00:19:20 -0800604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 enum qdio_irq_states state;
606
607 /* used to store the error condition during a data transfer */
608 unsigned int qdio_error;
609 unsigned int siga_error;
610 unsigned int error_status_flags;
611
612 /* list of interesting queues */
613 volatile struct qdio_q *list_next;
614 volatile struct qdio_q *list_prev;
615
616 struct sl *sl;
617 volatile struct sbal *sbal[QDIO_MAX_BUFFERS_PER_Q];
618
619 struct qdio_buffer *qdio_buffers[QDIO_MAX_BUFFERS_PER_Q];
620
621 unsigned long int_parm;
622
623 /*struct {
624 int in_bh_check_limit;
625 int threshold;
626 } threshold_classes[QDIO_STATS_CLASSES];*/
627
628 struct {
629 /* inbound: the time to stop polling
630 outbound: the time to kick peer */
631 int threshold; /* the real value */
632
633 /* outbound: last time of do_QDIO
634 inbound: last time of noticing incoming data */
635 /*__u64 last_transfer_times[QDIO_STATS_NUMBER];
636 int last_transfer_index; */
637
638 __u64 last_transfer_time;
639 __u64 busy_start;
640 } timing;
641 atomic_t busy_siga_counter;
642 unsigned int queue_type;
643
644 /* leave this member at the end. won't be cleared in qdio_fill_qs */
645 struct slib *slib; /* a page is allocated under this pointer,
646 sl points into this page, offset PAGE_SIZE/2
647 (after slib) */
648} __attribute__ ((aligned(256)));
649
650struct qdio_irq {
651 __u32 * volatile dev_st_chg_ind;
652
653 unsigned long int_parm;
Cornelia Hucka8237fc2006-01-06 00:19:21 -0800654 struct subchannel_id schid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656 unsigned int is_iqdio_irq;
657 unsigned int is_thinint_irq;
658 unsigned int hydra_gives_outbound_pcis;
659 unsigned int sync_done_on_outb_pcis;
660
Frank Pavlic8129ee12006-01-06 00:19:20 -0800661 /* QEBSM facility */
662 unsigned int is_qebsm;
663 unsigned long sch_token;
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 enum qdio_irq_states state;
666
667 unsigned int no_input_qs;
668 unsigned int no_output_qs;
669
670 unsigned char qdioac;
671
672 struct ccw1 ccw;
673
674 struct ciw equeue;
675 struct ciw aqueue;
676
677 struct qib qib;
678
679 void (*original_int_handler) (struct ccw_device *,
680 unsigned long, struct irb *);
681
682 /* leave these four members together at the end. won't be cleared in qdio_fill_irq */
683 struct qdr *qdr;
684 struct qdio_q *input_qs[QDIO_MAX_QUEUES_PER_IRQ];
685 struct qdio_q *output_qs[QDIO_MAX_QUEUES_PER_IRQ];
686 struct semaphore setting_up_sema;
687};
688#endif