annotate cp/nucleus/io.c @ 618:535aec703236

cp: define a FIXME macro that leaves a sclp message There are far too many fixmes in the code. Sadly, the compiler simply discards them. This usually isn't an issue until one accidentally hits a "weird" bug which just turns out to be an unhandled (but documented) case in another part of the code. Using a macro instead of a comment will let the compiler string-ify the text, and then at runtime use SCLP to print it out. This will immediatelly point at problem areas. So, keep an eye on SCLP from now on :) Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 13 Dec 2011 22:20:50 -0500
parents 9bbe38598c2f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
1 /*
417
bd6f5cdfac97 Happy New Year! - Add copyright notices
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 415
diff changeset
2 * (C) Copyright 2007-2010 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
bd6f5cdfac97 Happy New Year! - Add copyright notices
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 415
diff changeset
3 *
bd6f5cdfac97 Happy New Year! - Add copyright notices
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 415
diff changeset
4 * This file is released under the GPLv2. See the COPYING file for more
bd6f5cdfac97 Happy New Year! - Add copyright notices
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 415
diff changeset
5 * details.
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
6 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
7
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
8 #include <channel.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
9 #include <io.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
10 #include <interrupt.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
11 #include <device.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
12 #include <sched.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
13 #include <atomic.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
14 #include <spinlock.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
15 #include <buddy.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
16 #include <sched.h>
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
17
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
18 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
19 * Helper function to make sure the io_op has everything set right
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
20 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
21 static int __verify_io_op(struct io_op *ioop)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
22 {
618
535aec703236 cp: define a FIXME macro that leaves a sclp message
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 614
diff changeset
23 FIXME("check everything that makes sense to check");
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
24 return 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
25 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
26
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
27 static void __reset_reserved_fields(struct io_op *ioop)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
28 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
29 ioop->orb.__zero1 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
30
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
31 ioop->orb.__reserved1 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
32 ioop->orb.__reserved2 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
33 ioop->orb.__reserved3 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
34 ioop->orb.__reserved4 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
35 ioop->orb.__reserved5 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
36 ioop->orb.__reserved6 = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
37 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
38
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
39 /* NOTE: assumes dev->q_lock is held */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
40 static void __submit_io(struct device *dev)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
41 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
42 struct io_op *ioop;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
43 int err;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
44
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
45 if (dev->q_cur)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
46 return;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
47
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
48 if (list_empty(&dev->q_out))
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
49 return;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
50
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
51 ioop = list_entry(dev->q_out.next, struct io_op, list);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
52
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
53 err = start_sch(dev->sch, &ioop->orb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
54 if (!err) {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
55 list_del(&ioop->list);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
56 dev->q_cur = ioop;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
57 } else
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
58 ioop->err = err;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
59 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
60
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
61 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
62 * Submit an I/O request to a subchannel, and set up everything needed to
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
63 * handle the operation
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
64 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
65 int submit_io(struct device *dev, struct io_op *ioop, int flags)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
66 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
67 static atomic_t op_id_counter;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
68 unsigned long intmask;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
69 int err = -EBUSY;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
70
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
71 err = __verify_io_op(ioop);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
72 if (err)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
73 return 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
74
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
75 /* make sure all reserved fields have the right values */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
76 __reset_reserved_fields(ioop);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
77
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
78 ioop->err = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
79 ioop->orb.param = atomic_inc_return(&op_id_counter);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
80 atomic_set(&ioop->done, 0);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
81
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
82 /* add it to the list of ops */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
83 spin_lock_intsave(&dev->q_lock, &intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
84 list_add_tail(&ioop->list, &dev->q_out);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
85
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
86 __submit_io(dev); /* try to submit an IO right now */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
87 spin_unlock_intrestore(&dev->q_lock, intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
88
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
89 if (flags & CAN_LOOP) {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
90 while(!atomic_read(&ioop->done))
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
91 ;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
92 } else if (flags & CAN_SLEEP) {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
93 while(!atomic_read(&ioop->done))
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
94 schedule();
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
95 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
96
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
97 return 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
98 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
99
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
100 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
101 * Initialize the channel I/O subsystem
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
102 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
103 void init_io(void)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
104 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
105 u64 cr6;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
106
614
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
107 cr6 = get_cr(6);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
108
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
109 /* enable all I/O interrupt classes */
614
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
110 cr6 |= BIT64(32);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
111 cr6 |= BIT64(33);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
112 cr6 |= BIT64(34);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
113 cr6 |= BIT64(35);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
114 cr6 |= BIT64(36);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
115 cr6 |= BIT64(37);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
116 cr6 |= BIT64(38);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
117 cr6 |= BIT64(39);
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
118
9bbe38598c2f cp & login NSS: use {get,set}_cr to enable I/O subclasses
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 495
diff changeset
119 set_cr(6, cr6);
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
120 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
121
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
122 static int default_io_handler(struct device *dev, struct io_op *ioop, struct irb *irb)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
123 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
124 ioop->err = -EAGAIN;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
125
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
126 /* Unit check? */
618
535aec703236 cp: define a FIXME macro that leaves a sclp message
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 614
diff changeset
127 if (irb->scsw.dev_status & 0x02) {
535aec703236 cp: define a FIXME macro that leaves a sclp message
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 614
diff changeset
128 FIXME("we should bail");
535aec703236 cp: define a FIXME macro that leaves a sclp message
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 614
diff changeset
129 ioop->err = -EUCHECK;
535aec703236 cp: define a FIXME macro that leaves a sclp message
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 614
diff changeset
130 }
415
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
131
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
132 /* Device End is set, we're done */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
133 if (irb->scsw.dev_status & 0x04)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
134 ioop->err = 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
135
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
136 return 0;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
137 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
138
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
139 static void __cpu_initiated_io(struct device *dev, struct io_op *ioop, struct irb *irb)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
140 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
141 unsigned long intmask;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
142
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
143 ioop->err = test_sch(dev->sch, irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
144
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
145 if (!ioop->err && ioop->handler)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
146 ioop->handler(dev, ioop, irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
147 else if (!ioop->err)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
148 default_io_handler(dev, ioop, irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
149
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
150 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
151 * We can do this, because the test_sch function sets ->err, and
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
152 * therefore regardless of ->handler being defined, ->err will have
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
153 * a reasonable value
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
154 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
155 if (ioop->err == -EAGAIN)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
156 return; /* leave handler registered */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
157
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
158 /* ...and remove it form the list */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
159 spin_lock_intsave(&dev->q_lock, &intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
160 dev->q_cur = NULL;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
161
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
162 __submit_io(dev); /* try to submit another IO */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
163 spin_unlock_intrestore(&dev->q_lock, intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
164
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
165 /* flag io_op as done... */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
166 atomic_set(&ioop->done, 1);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
167
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
168 /* call the destructor if there is one */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
169 if (ioop->dtor)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
170 ioop->dtor(dev, ioop);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
171 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
172
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
173 static void __dev_initiated_io(struct device *dev, struct irb *irb)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
174 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
175 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
176
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
177 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
178 * I/O Interrupt handler (C portion)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
179 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
180 void __io_int_handler(void)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
181 {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
182 unsigned long intmask;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
183 struct io_op *ioop;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
184 struct device *dev;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
185 struct irb irb;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
186
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
187 dev = find_device_by_sch(IO_INT_CODE->ssid);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
188 BUG_ON(IS_ERR(dev));
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
189
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
190 spin_lock_intsave(&dev->q_lock, &intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
191 ioop = dev->q_cur;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
192 spin_unlock_intrestore(&dev->q_lock, intmask);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
193
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
194 if (ioop && ioop->orb.param == IO_INT_CODE->param &&
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
195 dev->sch == IO_INT_CODE->ssid) {
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
196 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
197 * CPU-initiated operation
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
198 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
199
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
200 __cpu_initiated_io(dev, ioop, &irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
201 dev_put(dev);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
202 return;
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
203 }
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
204
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
205 /*
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
206 * device-initiated operation
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
207 */
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
208 BUG_ON(test_sch(dev->sch, &irb));
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
209
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
210 atomic_inc(&dev->attention);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
211
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
212 if (dev->dev->interrupt)
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
213 dev->dev->interrupt(dev, &irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
214 else
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
215 __dev_initiated_io(dev, &irb);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
216 dev_put(dev);
159ddb984288 repo reorganization
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
217 }