manager.c revision d948a8daa059cf5b3e7f002e7b92acf00fc70c49
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 */ 7 8#include <linux/errno.h> 9#include <linux/module.h> 10#include <linux/init.h> 11#include <linux/kernel.h> 12#include <linux/pnp.h> 13#include <linux/slab.h> 14#include <linux/bitmap.h> 15#include <linux/mutex.h> 16#include "base.h" 17 18DEFINE_MUTEX(pnp_res_mutex); 19 20static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 21{ 22 resource_size_t *start, *end; 23 unsigned long *flags; 24 25 if (idx >= PNP_MAX_PORT) { 26 dev_err(&dev->dev, "too many I/O port resources\n"); 27 /* pretend we were successful so at least the manager won't try again */ 28 return 1; 29 } 30 31 start = &dev->res.port_resource[idx].start; 32 end = &dev->res.port_resource[idx].end; 33 flags = &dev->res.port_resource[idx].flags; 34 35 /* check if this resource has been manually set, if so skip */ 36 if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) { 37 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 38 "flags %#lx\n", idx, (unsigned long long) *start, 39 (unsigned long long) *end, *flags); 40 return 1; 41 } 42 43 /* set the initial values */ 44 *flags |= rule->flags | IORESOURCE_IO; 45 *flags &= ~IORESOURCE_UNSET; 46 47 if (!rule->size) { 48 *flags |= IORESOURCE_DISABLED; 49 dev_dbg(&dev->dev, " io %d disabled\n", idx); 50 return 1; /* skip disabled resource requests */ 51 } 52 53 *start = rule->min; 54 *end = *start + rule->size - 1; 55 56 /* run through until pnp_check_port is happy */ 57 while (!pnp_check_port(dev, idx)) { 58 *start += rule->align; 59 *end = *start + rule->size - 1; 60 if (*start > rule->max || !rule->align) { 61 dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); 62 return 0; 63 } 64 } 65 dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, 66 (unsigned long long) *start, (unsigned long long) *end); 67 return 1; 68} 69 70static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 71{ 72 resource_size_t *start, *end; 73 unsigned long *flags; 74 75 if (idx >= PNP_MAX_MEM) { 76 dev_err(&dev->dev, "too many memory resources\n"); 77 /* pretend we were successful so at least the manager won't try again */ 78 return 1; 79 } 80 81 start = &dev->res.mem_resource[idx].start; 82 end = &dev->res.mem_resource[idx].end; 83 flags = &dev->res.mem_resource[idx].flags; 84 85 /* check if this resource has been manually set, if so skip */ 86 if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) { 87 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 88 "flags %#lx\n", idx, (unsigned long long) *start, 89 (unsigned long long) *end, *flags); 90 return 1; 91 } 92 93 /* set the initial values */ 94 *flags |= rule->flags | IORESOURCE_MEM; 95 *flags &= ~IORESOURCE_UNSET; 96 97 /* convert pnp flags to standard Linux flags */ 98 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 99 *flags |= IORESOURCE_READONLY; 100 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 101 *flags |= IORESOURCE_CACHEABLE; 102 if (rule->flags & IORESOURCE_MEM_RANGELENGTH) 103 *flags |= IORESOURCE_RANGELENGTH; 104 if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 105 *flags |= IORESOURCE_SHADOWABLE; 106 107 if (!rule->size) { 108 *flags |= IORESOURCE_DISABLED; 109 dev_dbg(&dev->dev, " mem %d disabled\n", idx); 110 return 1; /* skip disabled resource requests */ 111 } 112 113 *start = rule->min; 114 *end = *start + rule->size - 1; 115 116 /* run through until pnp_check_mem is happy */ 117 while (!pnp_check_mem(dev, idx)) { 118 *start += rule->align; 119 *end = *start + rule->size - 1; 120 if (*start > rule->max || !rule->align) { 121 dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); 122 return 0; 123 } 124 } 125 dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, 126 (unsigned long long) *start, (unsigned long long) *end); 127 return 1; 128} 129 130static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 131{ 132 resource_size_t *start, *end; 133 unsigned long *flags; 134 int i; 135 136 /* IRQ priority: this table is good for i386 */ 137 static unsigned short xtab[16] = { 138 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 139 }; 140 141 if (idx >= PNP_MAX_IRQ) { 142 dev_err(&dev->dev, "too many IRQ resources\n"); 143 /* pretend we were successful so at least the manager won't try again */ 144 return 1; 145 } 146 147 start = &dev->res.irq_resource[idx].start; 148 end = &dev->res.irq_resource[idx].end; 149 flags = &dev->res.irq_resource[idx].flags; 150 151 /* check if this resource has been manually set, if so skip */ 152 if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) { 153 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 154 idx, (int) *start, *flags); 155 return 1; 156 } 157 158 /* set the initial values */ 159 *flags |= rule->flags | IORESOURCE_IRQ; 160 *flags &= ~IORESOURCE_UNSET; 161 162 if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 163 *flags |= IORESOURCE_DISABLED; 164 dev_dbg(&dev->dev, " irq %d disabled\n", idx); 165 return 1; /* skip disabled resource requests */ 166 } 167 168 /* TBD: need check for >16 IRQ */ 169 *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 170 if (*start < PNP_IRQ_NR) { 171 *end = *start; 172 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, (int) *start); 173 return 1; 174 } 175 for (i = 0; i < 16; i++) { 176 if (test_bit(xtab[i], rule->map)) { 177 *start = *end = xtab[i]; 178 if (pnp_check_irq(dev, idx)) { 179 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, 180 (int) *start); 181 return 1; 182 } 183 } 184 } 185 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 186 return 0; 187} 188 189static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 190{ 191 resource_size_t *start, *end; 192 unsigned long *flags; 193 int i; 194 195 /* DMA priority: this table is good for i386 */ 196 static unsigned short xtab[8] = { 197 1, 3, 5, 6, 7, 0, 2, 4 198 }; 199 200 if (idx >= PNP_MAX_DMA) { 201 dev_err(&dev->dev, "too many DMA resources\n"); 202 return; 203 } 204 205 start = &dev->res.dma_resource[idx].start; 206 end = &dev->res.dma_resource[idx].end; 207 flags = &dev->res.dma_resource[idx].flags; 208 209 /* check if this resource has been manually set, if so skip */ 210 if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) { 211 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 212 idx, (int) *start, *flags); 213 return; 214 } 215 216 /* set the initial values */ 217 *flags |= rule->flags | IORESOURCE_DMA; 218 *flags &= ~IORESOURCE_UNSET; 219 220 for (i = 0; i < 8; i++) { 221 if (rule->map & (1 << xtab[i])) { 222 *start = *end = xtab[i]; 223 if (pnp_check_dma(dev, idx)) { 224 dev_dbg(&dev->dev, " assign dma %d %d\n", idx, 225 (int) *start); 226 return; 227 } 228 } 229 } 230#ifdef MAX_DMA_CHANNELS 231 *start = *end = MAX_DMA_CHANNELS; 232#endif 233 *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; 234 dev_dbg(&dev->dev, " disable dma %d\n", idx); 235} 236 237void pnp_init_resource(struct resource *res) 238{ 239 unsigned long type; 240 241 type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | 242 IORESOURCE_IRQ | IORESOURCE_DMA); 243 244 res->name = NULL; 245 res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; 246 if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { 247 res->start = -1; 248 res->end = -1; 249 } else { 250 res->start = 0; 251 res->end = 0; 252 } 253} 254 255/** 256 * pnp_init_resources - Resets a resource table to default values. 257 * @table: pointer to the desired resource table 258 */ 259void pnp_init_resources(struct pnp_dev *dev) 260{ 261 struct resource *res; 262 int idx; 263 264 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 265 res = &dev->res.irq_resource[idx]; 266 res->flags = IORESOURCE_IRQ; 267 pnp_init_resource(res); 268 } 269 for (idx = 0; idx < PNP_MAX_DMA; idx++) { 270 res = &dev->res.dma_resource[idx]; 271 res->flags = IORESOURCE_DMA; 272 pnp_init_resource(res); 273 } 274 for (idx = 0; idx < PNP_MAX_PORT; idx++) { 275 res = &dev->res.port_resource[idx]; 276 res->flags = IORESOURCE_IO; 277 pnp_init_resource(res); 278 } 279 for (idx = 0; idx < PNP_MAX_MEM; idx++) { 280 res = &dev->res.mem_resource[idx]; 281 res->flags = IORESOURCE_MEM; 282 pnp_init_resource(res); 283 } 284} 285 286/** 287 * pnp_clean_resources - clears resources that were not manually set 288 * @res: the resources to clean 289 */ 290static void pnp_clean_resource_table(struct pnp_dev *dev) 291{ 292 struct resource *res; 293 int idx; 294 295 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 296 res = &dev->res.irq_resource[idx]; 297 if (res->flags & IORESOURCE_AUTO) { 298 res->flags = IORESOURCE_IRQ; 299 pnp_init_resource(res); 300 } 301 } 302 for (idx = 0; idx < PNP_MAX_DMA; idx++) { 303 res = &dev->res.dma_resource[idx]; 304 if (res->flags & IORESOURCE_AUTO) { 305 res->flags = IORESOURCE_DMA; 306 pnp_init_resource(res); 307 } 308 } 309 for (idx = 0; idx < PNP_MAX_PORT; idx++) { 310 res = &dev->res.port_resource[idx]; 311 if (res->flags & IORESOURCE_AUTO) { 312 res->flags = IORESOURCE_IO; 313 pnp_init_resource(res); 314 } 315 } 316 for (idx = 0; idx < PNP_MAX_MEM; idx++) { 317 res = &dev->res.mem_resource[idx]; 318 if (res->flags & IORESOURCE_AUTO) { 319 res->flags = IORESOURCE_MEM; 320 pnp_init_resource(res); 321 } 322 } 323} 324 325/** 326 * pnp_assign_resources - assigns resources to the device based on the specified dependent number 327 * @dev: pointer to the desired device 328 * @depnum: the dependent function number 329 * 330 * Only set depnum to 0 if the device does not have dependent options. 331 */ 332static int pnp_assign_resources(struct pnp_dev *dev, int depnum) 333{ 334 struct pnp_port *port; 335 struct pnp_mem *mem; 336 struct pnp_irq *irq; 337 struct pnp_dma *dma; 338 int nport = 0, nmem = 0, nirq = 0, ndma = 0; 339 340 if (!pnp_can_configure(dev)) 341 return -ENODEV; 342 343 dbg_pnp_show_resources(dev, "before pnp_assign_resources"); 344 mutex_lock(&pnp_res_mutex); 345 pnp_clean_resource_table(dev); 346 if (dev->independent) { 347 dev_dbg(&dev->dev, "assigning independent options\n"); 348 port = dev->independent->port; 349 mem = dev->independent->mem; 350 irq = dev->independent->irq; 351 dma = dev->independent->dma; 352 while (port) { 353 if (!pnp_assign_port(dev, port, nport)) 354 goto fail; 355 nport++; 356 port = port->next; 357 } 358 while (mem) { 359 if (!pnp_assign_mem(dev, mem, nmem)) 360 goto fail; 361 nmem++; 362 mem = mem->next; 363 } 364 while (irq) { 365 if (!pnp_assign_irq(dev, irq, nirq)) 366 goto fail; 367 nirq++; 368 irq = irq->next; 369 } 370 while (dma) { 371 pnp_assign_dma(dev, dma, ndma); 372 ndma++; 373 dma = dma->next; 374 } 375 } 376 377 if (depnum) { 378 struct pnp_option *dep; 379 int i; 380 381 dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); 382 for (i = 1, dep = dev->dependent; i < depnum; 383 i++, dep = dep->next) 384 if (!dep) 385 goto fail; 386 port = dep->port; 387 mem = dep->mem; 388 irq = dep->irq; 389 dma = dep->dma; 390 while (port) { 391 if (!pnp_assign_port(dev, port, nport)) 392 goto fail; 393 nport++; 394 port = port->next; 395 } 396 while (mem) { 397 if (!pnp_assign_mem(dev, mem, nmem)) 398 goto fail; 399 nmem++; 400 mem = mem->next; 401 } 402 while (irq) { 403 if (!pnp_assign_irq(dev, irq, nirq)) 404 goto fail; 405 nirq++; 406 irq = irq->next; 407 } 408 while (dma) { 409 pnp_assign_dma(dev, dma, ndma); 410 ndma++; 411 dma = dma->next; 412 } 413 } else if (dev->dependent) 414 goto fail; 415 416 mutex_unlock(&pnp_res_mutex); 417 dbg_pnp_show_resources(dev, "after pnp_assign_resources"); 418 return 1; 419 420fail: 421 pnp_clean_resource_table(dev); 422 mutex_unlock(&pnp_res_mutex); 423 dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); 424 return 0; 425} 426 427/** 428 * pnp_auto_config_dev - automatically assigns resources to a device 429 * @dev: pointer to the desired device 430 */ 431int pnp_auto_config_dev(struct pnp_dev *dev) 432{ 433 struct pnp_option *dep; 434 int i = 1; 435 436 if (!pnp_can_configure(dev)) { 437 dev_dbg(&dev->dev, "configuration not supported\n"); 438 return -ENODEV; 439 } 440 441 if (!dev->dependent) { 442 if (pnp_assign_resources(dev, 0)) 443 return 0; 444 } else { 445 dep = dev->dependent; 446 do { 447 if (pnp_assign_resources(dev, i)) 448 return 0; 449 dep = dep->next; 450 i++; 451 } while (dep); 452 } 453 454 dev_err(&dev->dev, "unable to assign resources\n"); 455 return -EBUSY; 456} 457 458/** 459 * pnp_start_dev - low-level start of the PnP device 460 * @dev: pointer to the desired device 461 * 462 * assumes that resources have already been allocated 463 */ 464int pnp_start_dev(struct pnp_dev *dev) 465{ 466 if (!pnp_can_write(dev)) { 467 dev_dbg(&dev->dev, "activation not supported\n"); 468 return -EINVAL; 469 } 470 471 dbg_pnp_show_resources(dev, "pnp_start_dev"); 472 if (dev->protocol->set(dev) < 0) { 473 dev_err(&dev->dev, "activation failed\n"); 474 return -EIO; 475 } 476 477 dev_info(&dev->dev, "activated\n"); 478 return 0; 479} 480 481/** 482 * pnp_stop_dev - low-level disable of the PnP device 483 * @dev: pointer to the desired device 484 * 485 * does not free resources 486 */ 487int pnp_stop_dev(struct pnp_dev *dev) 488{ 489 if (!pnp_can_disable(dev)) { 490 dev_dbg(&dev->dev, "disabling not supported\n"); 491 return -EINVAL; 492 } 493 if (dev->protocol->disable(dev) < 0) { 494 dev_err(&dev->dev, "disable failed\n"); 495 return -EIO; 496 } 497 498 dev_info(&dev->dev, "disabled\n"); 499 return 0; 500} 501 502/** 503 * pnp_activate_dev - activates a PnP device for use 504 * @dev: pointer to the desired device 505 * 506 * does not validate or set resources so be careful. 507 */ 508int pnp_activate_dev(struct pnp_dev *dev) 509{ 510 int error; 511 512 if (dev->active) 513 return 0; 514 515 /* ensure resources are allocated */ 516 if (pnp_auto_config_dev(dev)) 517 return -EBUSY; 518 519 error = pnp_start_dev(dev); 520 if (error) 521 return error; 522 523 dev->active = 1; 524 return 0; 525} 526 527/** 528 * pnp_disable_dev - disables device 529 * @dev: pointer to the desired device 530 * 531 * inform the correct pnp protocol so that resources can be used by other devices 532 */ 533int pnp_disable_dev(struct pnp_dev *dev) 534{ 535 int error; 536 537 if (!dev->active) 538 return 0; 539 540 error = pnp_stop_dev(dev); 541 if (error) 542 return error; 543 544 dev->active = 0; 545 546 /* release the resources so that other devices can use them */ 547 mutex_lock(&pnp_res_mutex); 548 pnp_clean_resource_table(dev); 549 mutex_unlock(&pnp_res_mutex); 550 551 return 0; 552} 553 554EXPORT_SYMBOL(pnp_start_dev); 555EXPORT_SYMBOL(pnp_stop_dev); 556EXPORT_SYMBOL(pnp_activate_dev); 557EXPORT_SYMBOL(pnp_disable_dev); 558