aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pnp/interface.c2
-rw-r--r--drivers/pnp/manager.c9
-rw-r--r--drivers/pnp/quirks.c71
-rw-r--r--include/linux/ioport.h1
4 files changed, 39 insertions, 44 deletions
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index b09f67de13d0..7a9fb5544b80 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -90,6 +90,8 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
90 pnp_printf(buffer, " High-Level"); 90 pnp_printf(buffer, " High-Level");
91 if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) 91 if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
92 pnp_printf(buffer, " Low-Level"); 92 pnp_printf(buffer, " Low-Level");
93 if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
94 pnp_printf(buffer, " (optional)");
93 pnp_printf(buffer, "\n"); 95 pnp_printf(buffer, "\n");
94} 96}
95 97
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 7ea9e1e28003..a20accb5ef8f 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -153,6 +153,15 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
153 goto __add; 153 goto __add;
154 } 154 }
155 } 155 }
156
157 if (rule->flags & IORESOURCE_IRQ_OPTIONAL) {
158 res->start = -1;
159 res->end = -1;
160 res->flags |= IORESOURCE_DISABLED;
161 dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
162 goto __add;
163 }
164
156 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 165 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
157 return -EBUSY; 166 return -EBUSY;
158 167
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 48e60171b3ba..e8515ce0d296 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -121,34 +121,46 @@ static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev)
121 struct pnp_option *res; 121 struct pnp_option *res;
122 122
123 /* 123 /*
124 * Build a functional IRQ-less variant of each MPU option. 124 * Build a functional IRQ-optional variant of each MPU option.
125 */ 125 */
126 126
127 for (res = dev->dependent; res; res = res->next) { 127 for (res = dev->dependent; res; res = res->next) {
128 struct pnp_option *curr; 128 struct pnp_option *curr;
129 struct pnp_port *port; 129 struct pnp_port *port;
130 struct pnp_port *copy; 130 struct pnp_port *copy_port;
131 struct pnp_irq *irq;
132 struct pnp_irq *copy_irq;
131 133
132 port = res->port; 134 port = res->port;
133 if (!port || !res->irq) 135 irq = res->irq;
136 if (!port || !irq)
134 continue; 137 continue;
135 138
136 copy = pnp_alloc(sizeof *copy); 139 copy_port = pnp_alloc(sizeof *copy_port);
137 if (!copy) 140 if (!copy_port)
141 break;
142
143 copy_irq = pnp_alloc(sizeof *copy_irq);
144 if (!copy_irq) {
145 kfree(copy_port);
138 break; 146 break;
147 }
148
149 *copy_port = *port;
150 copy_port->next = NULL;
139 151
140 copy->min = port->min; 152 *copy_irq = *irq;
141 copy->max = port->max; 153 copy_irq->flags |= IORESOURCE_IRQ_OPTIONAL;
142 copy->align = port->align; 154 copy_irq->next = NULL;
143 copy->size = port->size;
144 copy->flags = port->flags;
145 155
146 curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); 156 curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
147 if (!curr) { 157 if (!curr) {
148 kfree(copy); 158 kfree(copy_port);
159 kfree(copy_irq);
149 break; 160 break;
150 } 161 }
151 curr->port = copy; 162 curr->port = copy_port;
163 curr->irq = copy_irq;
152 164
153 if (prev) 165 if (prev)
154 prev->next = curr; 166 prev->next = curr;
@@ -157,7 +169,7 @@ static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev)
157 prev = curr; 169 prev = curr;
158 } 170 }
159 if (head) 171 if (head)
160 dev_info(&dev->dev, "adding IRQ-less MPU options\n"); 172 dev_info(&dev->dev, "adding IRQ-optional MPU options\n");
161 173
162 return head; 174 return head;
163} 175}
@@ -167,10 +179,6 @@ static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
167 struct pnp_option *res; 179 struct pnp_option *res;
168 struct pnp_irq *irq; 180 struct pnp_irq *irq;
169 181
170 /*
171 * Distribute the independent IRQ over the dependent options
172 */
173
174 res = dev->independent; 182 res = dev->independent;
175 if (!res) 183 if (!res)
176 return; 184 return;
@@ -179,33 +187,8 @@ static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
179 if (!irq || irq->next) 187 if (!irq || irq->next)
180 return; 188 return;
181 189
182 res = dev->dependent; 190 irq->flags |= IORESOURCE_IRQ_OPTIONAL;
183 if (!res) 191 dev_info(&dev->dev, "made independent IRQ optional\n");
184 return;
185
186 while (1) {
187 struct pnp_irq *copy;
188
189 copy = pnp_alloc(sizeof *copy);
190 if (!copy)
191 break;
192
193 bitmap_copy(copy->map.bits, irq->map.bits, PNP_IRQ_NR);
194 copy->flags = irq->flags;
195
196 copy->next = res->irq; /* Yes, this is NULL */
197 res->irq = copy;
198
199 if (!res->next)
200 break;
201 res = res->next;
202 }
203 kfree(irq);
204
205 res->next = quirk_isapnp_mpu_options(dev);
206
207 res = dev->independent;
208 res->irq = NULL;
209} 192}
210 193
211static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) 194static void quirk_isapnp_mpu_resources(struct pnp_dev *dev)
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 39db059ffb8b..2cd07cc29687 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -59,6 +59,7 @@ struct resource_list {
59#define IORESOURCE_IRQ_HIGHLEVEL (1<<2) 59#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
60#define IORESOURCE_IRQ_LOWLEVEL (1<<3) 60#define IORESOURCE_IRQ_LOWLEVEL (1<<3)
61#define IORESOURCE_IRQ_SHAREABLE (1<<4) 61#define IORESOURCE_IRQ_SHAREABLE (1<<4)
62#define IORESOURCE_IRQ_OPTIONAL (1<<5)
62 63
63/* PnP DMA specific bits (IORESOURCE_BITS) */ 64/* PnP DMA specific bits (IORESOURCE_BITS) */
64#define IORESOURCE_DMA_TYPE_MASK (3<<0) 65#define IORESOURCE_DMA_TYPE_MASK (3<<0)