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_RANGELENGTH) 101 res->flags |= IORESOURCE_RANGELENGTH; 102 if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 103 res->flags |= IORESOURCE_SHADOWABLE; 104 105 if (!rule->size) { 106 res->flags |= IORESOURCE_DISABLED; 107 pnp_dbg(&dev->dev, " mem %d disabled\n", idx); 108 goto __add; 109 } 110 111 res->start = rule->min; 112 res->end = res->start + rule->size - 1; 113 114 while (!pnp_check_mem(dev, res)) { 115 res->start += rule->align; 116 res->end = res->start + rule->size - 1; 117 if (res->start > rule->max || !rule->align) { 118 pnp_dbg(&dev->dev, " couldn't assign mem %d " 119 "(min %#llx max %#llx)\n", idx, 120 (unsigned long long) rule->min, 121 (unsigned long long) rule->max); 122 return -EBUSY; 123 } 124 } 125 126 __add: 127 pnp_add_mem_resource(dev, res->start, res->end, res->flags); 128 return 0; 129 } 130 131 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 132 { 133 struct resource *res, local_res; 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 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IRQ, idx); 142 if (res) { 143 pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 144 idx, (int) res->start, res->flags); 145 return 0; 146 } 147 148 res = &local_res; 149 res->flags = rule->flags | IORESOURCE_AUTO; 150 res->start = -1; 151 res->end = -1; 152 153 if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) { 154 res->flags |= IORESOURCE_DISABLED; 155 pnp_dbg(&dev->dev, " irq %d disabled\n", idx); 156 goto __add; 157 } 158 159 /* TBD: need check for >16 IRQ */ 160 res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16); 161 if (res->start < PNP_IRQ_NR) { 162 res->end = res->start; 163 goto __add; 164 } 165 for (i = 0; i < 16; i++) { 166 if (test_bit(xtab[i], rule->map.bits)) { 167 res->start = res->end = xtab[i]; 168 if (pnp_check_irq(dev, res)) 169 goto __add; 170 } 171 } 172 173 if (rule->flags & IORESOURCE_IRQ_OPTIONAL) { 174 res->start = -1; 175 res->end = -1; 176 res->flags |= IORESOURCE_DISABLED; 177 pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); 178 goto __add; 179 } 180 181 pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 182 return -EBUSY; 183 184 __add: 185 pnp_add_irq_resource(dev, res->start, res->flags); 186 return 0; 187 } 188 189 #ifdef CONFIG_ISA_DMA_API 190 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 191 { 192 struct resource *res, local_res; 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 res = pnp_find_resource(dev, rule->flags, IORESOURCE_DMA, idx); 201 if (res) { 202 pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 203 idx, (int) res->start, res->flags); 204 return 0; 205 } 206 207 res = &local_res; 208 res->flags = rule->flags | IORESOURCE_AUTO; 209 res->start = -1; 210 res->end = -1; 211 212 if (!rule->map) { 213 res->flags |= IORESOURCE_DISABLED; 214 pnp_dbg(&dev->dev, " dma %d disabled\n", idx); 215 goto __add; 216 } 217 218 for (i = 0; i < 8; i++) { 219 if (rule->map & (1 << xtab[i])) { 220 res->start = res->end = xtab[i]; 221 if (pnp_check_dma(dev, res)) 222 goto __add; 223 } 224 } 225 226 pnp_dbg(&dev->dev, " couldn't assign dma %d\n", idx); 227 return -EBUSY; 228 229 __add: 230 pnp_add_dma_resource(dev, res->start, res->flags); 231 return 0; 232 } 233 #endif /* CONFIG_ISA_DMA_API */ 234 235 void pnp_init_resources(struct pnp_dev *dev) 236 { 237 pnp_free_resources(dev); 238 } 239 240 static void pnp_clean_resource_table(struct pnp_dev *dev) 241 { 242 struct pnp_resource *pnp_res, *tmp; 243 244 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) { 245 if (pnp_res->res.flags & IORESOURCE_AUTO) 246 pnp_free_resource(pnp_res); 247 } 248 } 249 250 /** 251 * pnp_assign_resources - assigns resources to the device based on the specified dependent number 252 * @dev: pointer to the desired device 253 * @set: the dependent function number 254 */ 255 static int pnp_assign_resources(struct pnp_dev *dev, int set) 256 { 257 struct pnp_option *option; 258 int nport = 0, nmem = 0, nirq = 0; 259 int ndma __maybe_unused = 0; 260 int ret = 0; 261 262 pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); 263 mutex_lock(&pnp_res_mutex); 264 pnp_clean_resource_table(dev); 265 266 list_for_each_entry(option, &dev->options, list) { 267 if (pnp_option_is_dependent(option) && 268 pnp_option_set(option) != set) 269 continue; 270 271 switch (option->type) { 272 case IORESOURCE_IO: 273 ret = pnp_assign_port(dev, &option->u.port, nport++); 274 break; 275 case IORESOURCE_MEM: 276 ret = pnp_assign_mem(dev, &option->u.mem, nmem++); 277 break; 278 case IORESOURCE_IRQ: 279 ret = pnp_assign_irq(dev, &option->u.irq, nirq++); 280 break; 281 #ifdef CONFIG_ISA_DMA_API 282 case IORESOURCE_DMA: 283 ret = pnp_assign_dma(dev, &option->u.dma, ndma++); 284 break; 285 #endif 286 default: 287 ret = -EINVAL; 288 break; 289 } 290 if (ret < 0) 291 break; 292 } 293 294 mutex_unlock(&pnp_res_mutex); 295 if (ret < 0) { 296 pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret); 297 pnp_clean_resource_table(dev); 298 } else 299 dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded"); 300 return ret; 301 } 302 303 /** 304 * pnp_auto_config_dev - automatically assigns resources to a device 305 * @dev: pointer to the desired device 306 */ 307 int pnp_auto_config_dev(struct pnp_dev *dev) 308 { 309 int i, ret; 310 311 if (!pnp_can_configure(dev)) { 312 pnp_dbg(&dev->dev, "configuration not supported\n"); 313 return -ENODEV; 314 } 315 316 ret = pnp_assign_resources(dev, 0); 317 if (ret == 0) 318 return 0; 319 320 for (i = 1; i < dev->num_dependent_sets; i++) { 321 ret = pnp_assign_resources(dev, i); 322 if (ret == 0) 323 return 0; 324 } 325 326 dev_err(&dev->dev, "unable to assign resources\n"); 327 return ret; 328 } 329 330 /** 331 * pnp_start_dev - low-level start of the PnP device 332 * @dev: pointer to the desired device 333 * 334 * assumes that resources have already been allocated 335 */ 336 int pnp_start_dev(struct pnp_dev *dev) 337 { 338 if (!pnp_can_write(dev)) { 339 pnp_dbg(&dev->dev, "activation not supported\n"); 340 return -EINVAL; 341 } 342 343 dbg_pnp_show_resources(dev, "pnp_start_dev"); 344 if (dev->protocol->set(dev) < 0) { 345 dev_err(&dev->dev, "activation failed\n"); 346 return -EIO; 347 } 348 349 dev_info(&dev->dev, "activated\n"); 350 return 0; 351 } 352 353 /** 354 * pnp_stop_dev - low-level disable of the PnP device 355 * @dev: pointer to the desired device 356 * 357 * does not free resources 358 */ 359 int pnp_stop_dev(struct pnp_dev *dev) 360 { 361 if (!pnp_can_disable(dev)) { 362 pnp_dbg(&dev->dev, "disabling not supported\n"); 363 return -EINVAL; 364 } 365 if (dev->protocol->disable(dev) < 0) { 366 dev_err(&dev->dev, "disable failed\n"); 367 return -EIO; 368 } 369 370 dev_info(&dev->dev, "disabled\n"); 371 return 0; 372 } 373 374 /** 375 * pnp_activate_dev - activates a PnP device for use 376 * @dev: pointer to the desired device 377 * 378 * does not validate or set resources so be careful. 379 */ 380 int pnp_activate_dev(struct pnp_dev *dev) 381 { 382 int error; 383 384 if (dev->active) 385 return 0; 386 387 /* ensure resources are allocated */ 388 if (pnp_auto_config_dev(dev)) 389 return -EBUSY; 390 391 error = pnp_start_dev(dev); 392 if (error) 393 return error; 394 395 dev->active = 1; 396 return 0; 397 } 398 399 /** 400 * pnp_disable_dev - disables device 401 * @dev: pointer to the desired device 402 * 403 * inform the correct pnp protocol so that resources can be used by other devices 404 */ 405 int pnp_disable_dev(struct pnp_dev *dev) 406 { 407 int error; 408 409 if (!dev->active) 410 return 0; 411 412 error = pnp_stop_dev(dev); 413 if (error) 414 return error; 415 416 dev->active = 0; 417 418 /* release the resources so that other devices can use them */ 419 mutex_lock(&pnp_res_mutex); 420 pnp_clean_resource_table(dev); 421 mutex_unlock(&pnp_res_mutex); 422 423 return 0; 424 } 425 426 EXPORT_SYMBOL(pnp_start_dev); 427 EXPORT_SYMBOL(pnp_stop_dev); 428 EXPORT_SYMBOL(pnp_activate_dev); 429 EXPORT_SYMBOL(pnp_disable_dev); 430