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