1 /* 2 * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices 3 * 4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> 5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. 7 * Bjorn Helgaas <bjorn.helgaas@hp.com> 8 */ 9 10 #include <linux/errno.h> 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/pnp.h> 15 #include <linux/bitmap.h> 16 #include <linux/mutex.h> 17 #include "base.h" 18 19 DEFINE_MUTEX(pnp_res_mutex); 20 21 static struct resource *pnp_find_resource(struct pnp_dev *dev, 22 unsigned char rule, 23 unsigned long type, 24 unsigned int bar) 25 { 26 struct resource *res = pnp_get_resource(dev, type, bar); 27 28 /* when the resource already exists, set its resource bits from rule */ 29 if (res) { 30 res->flags &= ~IORESOURCE_BITS; 31 res->flags |= rule & IORESOURCE_BITS; 32 } 33 34 return res; 35 } 36 37 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 38 { 39 struct resource *res, local_res; 40 41 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IO, idx); 42 if (res) { 43 pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 44 "flags %#lx\n", idx, (unsigned long long) res->start, 45 (unsigned long long) res->end, res->flags); 46 return 0; 47 } 48 49 res = &local_res; 50 res->flags = rule->flags | IORESOURCE_AUTO; 51 res->start = 0; 52 res->end = 0; 53 54 if (!rule->size) { 55 res->flags |= IORESOURCE_DISABLED; 56 pnp_dbg(&dev->dev, " io %d disabled\n", idx); 57 goto __add; 58 } 59 60 res->start = rule->min; 61 res->end = res->start + rule->size - 1; 62 63 while (!pnp_check_port(dev, res)) { 64 res->start += rule->align; 65 res->end = res->start + rule->size - 1; 66 if (res->start > rule->max || !rule->align) { 67 pnp_dbg(&dev->dev, " couldn't assign io %d " 68 "(min %#llx max %#llx)\n", idx, 69 (unsigned long long) rule->min, 70 (unsigned long long) rule->max); 71 return -EBUSY; 72 } 73 } 74 75 __add: 76 pnp_add_io_resource(dev, res->start, res->end, res->flags); 77 return 0; 78 } 79 80 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 81 { 82 struct resource *res, local_res; 83 84 res = pnp_find_resource(dev, rule->flags, IORESOURCE_MEM, idx); 85 if (res) { 86 pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 87 "flags %#lx\n", idx, (unsigned long long) res->start, 88 (unsigned long long) res->end, res->flags); 89 return 0; 90 } 91 92 res = &local_res; 93 res->flags = rule->flags | IORESOURCE_AUTO; 94 res->start = 0; 95 res->end = 0; 96 97 /* ??? rule->flags restricted to 8 bits, all tests bogus ??? */ 98 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 99 res->flags |= IORESOURCE_READONLY; 100 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 101 res->flags |= IORESOURCE_CACHEABLE; 102 if (rule->flags & IORESOURCE_MEM_RANGELENGTH) 103 res->flags |= IORESOURCE_RANGELENGTH; 104 if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 105 res->flags |= IORESOURCE_SHADOWABLE; 106 107 if (!rule->size) { 108 res->flags |= IORESOURCE_DISABLED; 109 pnp_dbg(&dev->dev, " mem %d disabled\n", idx); 110 goto __add; 111 } 112 113 res->start = rule->min; 114 res->end = res->start + rule->size - 1; 115 116 while (!pnp_check_mem(dev, res)) { 117 res->start += rule->align; 118 res->end = res->start + rule->size - 1; 119 if (res->start > rule->max || !rule->align) { 120 pnp_dbg(&dev->dev, " couldn't assign mem %d " 121 "(min %#llx max %#llx)\n", idx, 122 (unsigned long long) rule->min, 123 (unsigned long long) rule->max); 124 return -EBUSY; 125 } 126 } 127 128 __add: 129 pnp_add_mem_resource(dev, res->start, res->end, res->flags); 130 return 0; 131 } 132 133 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 134 { 135 struct resource *res, local_res; 136 int i; 137 138 /* IRQ priority: this table is good for i386 */ 139 static unsigned short xtab[16] = { 140 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 141 }; 142 143 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IRQ, idx); 144 if (res) { 145 pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 146 idx, (int) res->start, res->flags); 147 return 0; 148 } 149 150 res = &local_res; 151 res->flags = rule->flags | IORESOURCE_AUTO; 152 res->start = -1; 153 res->end = -1; 154 155 if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) { 156 res->flags |= IORESOURCE_DISABLED; 157 pnp_dbg(&dev->dev, " irq %d disabled\n", idx); 158 goto __add; 159 } 160 161 /* TBD: need check for >16 IRQ */ 162 res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16); 163 if (res->start < PNP_IRQ_NR) { 164 res->end = res->start; 165 goto __add; 166 } 167 for (i = 0; i < 16; i++) { 168 if (test_bit(xtab[i], rule->map.bits)) { 169 res->start = res->end = xtab[i]; 170 if (pnp_check_irq(dev, res)) 171 goto __add; 172 } 173 } 174 175 if (rule->flags & IORESOURCE_IRQ_OPTIONAL) { 176 res->start = -1; 177 res->end = -1; 178 res->flags |= IORESOURCE_DISABLED; 179 pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); 180 goto __add; 181 } 182 183 pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 184 return -EBUSY; 185 186 __add: 187 pnp_add_irq_resource(dev, res->start, res->flags); 188 return 0; 189 } 190 191 #ifdef CONFIG_ISA_DMA_API 192 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 193 { 194 struct resource *res, local_res; 195 int i; 196 197 /* DMA priority: this table is good for i386 */ 198 static unsigned short xtab[8] = { 199 1, 3, 5, 6, 7, 0, 2, 4 200 }; 201 202 res = pnp_find_resource(dev, rule->flags, IORESOURCE_DMA, idx); 203 if (res) { 204 pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 205 idx, (int) res->start, res->flags); 206 return 0; 207 } 208 209 res = &local_res; 210 res->flags = rule->flags | IORESOURCE_AUTO; 211 res->start = -1; 212 res->end = -1; 213 214 for (i = 0; i < 8; i++) { 215 if (rule->map & (1 << xtab[i])) { 216 res->start = res->end = xtab[i]; 217 if (pnp_check_dma(dev, res)) 218 goto __add; 219 } 220 } 221 #ifdef MAX_DMA_CHANNELS 222 res->start = res->end = MAX_DMA_CHANNELS; 223 #endif 224 res->flags |= IORESOURCE_DISABLED; 225 pnp_dbg(&dev->dev, " disable dma %d\n", idx); 226 227 __add: 228 pnp_add_dma_resource(dev, res->start, res->flags); 229 return 0; 230 } 231 #endif /* CONFIG_ISA_DMA_API */ 232 233 void pnp_init_resources(struct pnp_dev *dev) 234 { 235 pnp_free_resources(dev); 236 } 237 238 static void pnp_clean_resource_table(struct pnp_dev *dev) 239 { 240 struct pnp_resource *pnp_res, *tmp; 241 242 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) { 243 if (pnp_res->res.flags & IORESOURCE_AUTO) 244 pnp_free_resource(pnp_res); 245 } 246 } 247 248 /** 249 * pnp_assign_resources - assigns resources to the device based on the specified dependent number 250 * @dev: pointer to the desired device 251 * @set: the dependent function number 252 */ 253 static int pnp_assign_resources(struct pnp_dev *dev, int set) 254 { 255 struct pnp_option *option; 256 int nport = 0, nmem = 0, nirq = 0; 257 int ndma __maybe_unused = 0; 258 int ret = 0; 259 260 pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); 261 mutex_lock(&pnp_res_mutex); 262 pnp_clean_resource_table(dev); 263 264 list_for_each_entry(option, &dev->options, list) { 265 if (pnp_option_is_dependent(option) && 266 pnp_option_set(option) != set) 267 continue; 268 269 switch (option->type) { 270 case IORESOURCE_IO: 271 ret = pnp_assign_port(dev, &option->u.port, nport++); 272 break; 273 case IORESOURCE_MEM: 274 ret = pnp_assign_mem(dev, &option->u.mem, nmem++); 275 break; 276 case IORESOURCE_IRQ: 277 ret = pnp_assign_irq(dev, &option->u.irq, nirq++); 278 break; 279 #ifdef CONFIG_ISA_DMA_API 280 case IORESOURCE_DMA: 281 ret = pnp_assign_dma(dev, &option->u.dma, ndma++); 282 break; 283 #endif 284 default: 285 ret = -EINVAL; 286 break; 287 } 288 if (ret < 0) 289 break; 290 } 291 292 mutex_unlock(&pnp_res_mutex); 293 if (ret < 0) { 294 pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret); 295 pnp_clean_resource_table(dev); 296 } else 297 dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded"); 298 return ret; 299 } 300 301 /** 302 * pnp_auto_config_dev - automatically assigns resources to a device 303 * @dev: pointer to the desired device 304 */ 305 int pnp_auto_config_dev(struct pnp_dev *dev) 306 { 307 int i, ret; 308 309 if (!pnp_can_configure(dev)) { 310 pnp_dbg(&dev->dev, "configuration not supported\n"); 311 return -ENODEV; 312 } 313 314 ret = pnp_assign_resources(dev, 0); 315 if (ret == 0) 316 return 0; 317 318 for (i = 1; i < dev->num_dependent_sets; i++) { 319 ret = pnp_assign_resources(dev, i); 320 if (ret == 0) 321 return 0; 322 } 323 324 dev_err(&dev->dev, "unable to assign resources\n"); 325 return ret; 326 } 327 328 /** 329 * pnp_start_dev - low-level start of the PnP device 330 * @dev: pointer to the desired device 331 * 332 * assumes that resources have already been allocated 333 */ 334 int pnp_start_dev(struct pnp_dev *dev) 335 { 336 if (!pnp_can_write(dev)) { 337 pnp_dbg(&dev->dev, "activation not supported\n"); 338 return -EINVAL; 339 } 340 341 dbg_pnp_show_resources(dev, "pnp_start_dev"); 342 if (dev->protocol->set(dev) < 0) { 343 dev_err(&dev->dev, "activation failed\n"); 344 return -EIO; 345 } 346 347 dev_info(&dev->dev, "activated\n"); 348 return 0; 349 } 350 351 /** 352 * pnp_stop_dev - low-level disable of the PnP device 353 * @dev: pointer to the desired device 354 * 355 * does not free resources 356 */ 357 int pnp_stop_dev(struct pnp_dev *dev) 358 { 359 if (!pnp_can_disable(dev)) { 360 pnp_dbg(&dev->dev, "disabling not supported\n"); 361 return -EINVAL; 362 } 363 if (dev->protocol->disable(dev) < 0) { 364 dev_err(&dev->dev, "disable failed\n"); 365 return -EIO; 366 } 367 368 dev_info(&dev->dev, "disabled\n"); 369 return 0; 370 } 371 372 /** 373 * pnp_activate_dev - activates a PnP device for use 374 * @dev: pointer to the desired device 375 * 376 * does not validate or set resources so be careful. 377 */ 378 int pnp_activate_dev(struct pnp_dev *dev) 379 { 380 int error; 381 382 if (dev->active) 383 return 0; 384 385 /* ensure resources are allocated */ 386 if (pnp_auto_config_dev(dev)) 387 return -EBUSY; 388 389 error = pnp_start_dev(dev); 390 if (error) 391 return error; 392 393 dev->active = 1; 394 return 0; 395 } 396 397 /** 398 * pnp_disable_dev - disables device 399 * @dev: pointer to the desired device 400 * 401 * inform the correct pnp protocol so that resources can be used by other devices 402 */ 403 int pnp_disable_dev(struct pnp_dev *dev) 404 { 405 int error; 406 407 if (!dev->active) 408 return 0; 409 410 error = pnp_stop_dev(dev); 411 if (error) 412 return error; 413 414 dev->active = 0; 415 416 /* release the resources so that other devices can use them */ 417 mutex_lock(&pnp_res_mutex); 418 pnp_clean_resource_table(dev); 419 mutex_unlock(&pnp_res_mutex); 420 421 return 0; 422 } 423 424 EXPORT_SYMBOL(pnp_start_dev); 425 EXPORT_SYMBOL(pnp_stop_dev); 426 EXPORT_SYMBOL(pnp_activate_dev); 427 EXPORT_SYMBOL(pnp_disable_dev); 428