diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/pcmcia/ds.c | 38 | ||||
| -rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 122 |
2 files changed, 104 insertions, 56 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4c40db8889d9..83b51ddd3da3 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -835,6 +835,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
| 835 | } | 835 | } |
| 836 | 836 | ||
| 837 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | 837 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { |
| 838 | int ret; | ||
| 839 | |||
| 838 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) | 840 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) |
| 839 | return 0; | 841 | return 0; |
| 840 | 842 | ||
| @@ -849,10 +851,15 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
| 849 | * after it has re-checked that there is no possible module | 851 | * after it has re-checked that there is no possible module |
| 850 | * with a prod_id/manf_id/card_id match. | 852 | * with a prod_id/manf_id/card_id match. |
| 851 | */ | 853 | */ |
| 852 | dev_dbg(&dev->dev, | 854 | mutex_lock(&dev->socket->ops_mutex); |
| 853 | "skipping FUNC_ID match until userspace interaction\n"); | 855 | ret = dev->allow_func_id_match; |
| 854 | if (!dev->allow_func_id_match) | 856 | mutex_unlock(&dev->socket->ops_mutex); |
| 857 | |||
| 858 | if (!ret) { | ||
| 859 | dev_dbg(&dev->dev, | ||
| 860 | "skipping FUNC_ID match until userspace ACK\n"); | ||
| 855 | return 0; | 861 | return 0; |
| 862 | } | ||
| 856 | } | 863 | } |
| 857 | 864 | ||
| 858 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { | 865 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { |
| @@ -1079,9 +1086,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
| 1079 | if (!count) | 1086 | if (!count) |
| 1080 | return -EINVAL; | 1087 | return -EINVAL; |
| 1081 | 1088 | ||
| 1082 | mutex_lock(&p_dev->socket->skt_mutex); | 1089 | mutex_lock(&p_dev->socket->ops_mutex); |
| 1083 | p_dev->allow_func_id_match = 1; | 1090 | p_dev->allow_func_id_match = 1; |
| 1084 | mutex_unlock(&p_dev->socket->skt_mutex); | 1091 | mutex_unlock(&p_dev->socket->ops_mutex); |
| 1085 | 1092 | ||
| 1086 | ret = bus_rescan_devices(&pcmcia_bus_type); | 1093 | ret = bus_rescan_devices(&pcmcia_bus_type); |
| 1087 | if (ret) | 1094 | if (ret) |
| @@ -1114,8 +1121,13 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
| 1114 | struct pcmcia_driver *p_drv = NULL; | 1121 | struct pcmcia_driver *p_drv = NULL; |
| 1115 | int ret = 0; | 1122 | int ret = 0; |
| 1116 | 1123 | ||
| 1117 | if (p_dev->suspended) | 1124 | mutex_lock(&p_dev->socket->ops_mutex); |
| 1125 | if (p_dev->suspended) { | ||
| 1126 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 1118 | return 0; | 1127 | return 0; |
| 1128 | } | ||
| 1129 | p_dev->suspended = 1; | ||
| 1130 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 1119 | 1131 | ||
| 1120 | dev_dbg(dev, "suspending\n"); | 1132 | dev_dbg(dev, "suspending\n"); |
| 1121 | 1133 | ||
| @@ -1132,6 +1144,9 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
| 1132 | "pcmcia: device %s (driver %s) did " | 1144 | "pcmcia: device %s (driver %s) did " |
| 1133 | "not want to go to sleep (%d)\n", | 1145 | "not want to go to sleep (%d)\n", |
| 1134 | p_dev->devname, p_drv->drv.name, ret); | 1146 | p_dev->devname, p_drv->drv.name, ret); |
| 1147 | mutex_lock(&p_dev->socket->ops_mutex); | ||
| 1148 | p_dev->suspended = 0; | ||
| 1149 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 1135 | goto out; | 1150 | goto out; |
| 1136 | } | 1151 | } |
| 1137 | } | 1152 | } |
| @@ -1142,8 +1157,6 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
| 1142 | } | 1157 | } |
| 1143 | 1158 | ||
| 1144 | out: | 1159 | out: |
| 1145 | if (!ret) | ||
| 1146 | p_dev->suspended = 1; | ||
| 1147 | return ret; | 1160 | return ret; |
| 1148 | } | 1161 | } |
| 1149 | 1162 | ||
| @@ -1154,8 +1167,13 @@ static int pcmcia_dev_resume(struct device *dev) | |||
| 1154 | struct pcmcia_driver *p_drv = NULL; | 1167 | struct pcmcia_driver *p_drv = NULL; |
| 1155 | int ret = 0; | 1168 | int ret = 0; |
| 1156 | 1169 | ||
| 1157 | if (!p_dev->suspended) | 1170 | mutex_lock(&p_dev->socket->ops_mutex); |
| 1171 | if (!p_dev->suspended) { | ||
| 1172 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 1158 | return 0; | 1173 | return 0; |
| 1174 | } | ||
| 1175 | p_dev->suspended = 0; | ||
| 1176 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 1159 | 1177 | ||
| 1160 | dev_dbg(dev, "resuming\n"); | 1178 | dev_dbg(dev, "resuming\n"); |
| 1161 | 1179 | ||
| @@ -1176,8 +1194,6 @@ static int pcmcia_dev_resume(struct device *dev) | |||
| 1176 | ret = p_drv->resume(p_dev); | 1194 | ret = p_drv->resume(p_dev); |
| 1177 | 1195 | ||
| 1178 | out: | 1196 | out: |
| 1179 | if (!ret) | ||
| 1180 | p_dev->suspended = 0; | ||
| 1181 | return ret; | 1197 | return ret; |
| 1182 | } | 1198 | } |
| 1183 | 1199 | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f0de7b8b123b..b2df04199a21 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
| @@ -191,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
| 191 | return -EINVAL; | 191 | return -EINVAL; |
| 192 | 192 | ||
| 193 | s = p_dev->socket; | 193 | s = p_dev->socket; |
| 194 | |||
| 195 | mutex_lock(&s->ops_mutex); | ||
| 194 | c = p_dev->function_config; | 196 | c = p_dev->function_config; |
| 195 | 197 | ||
| 196 | if (!(c->state & CONFIG_LOCKED)) { | 198 | if (!(c->state & CONFIG_LOCKED)) { |
| 197 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 199 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); |
| 200 | mutex_unlock(&s->ops_mutex); | ||
| 198 | return -EACCES; | 201 | return -EACCES; |
| 199 | } | 202 | } |
| 200 | 203 | ||
| 201 | addr = (c->ConfigBase + reg->Offset) >> 1; | 204 | addr = (c->ConfigBase + reg->Offset) >> 1; |
| 205 | mutex_unlock(&s->ops_mutex); | ||
| 202 | 206 | ||
| 203 | switch (reg->Action) { | 207 | switch (reg->Action) { |
| 204 | case CS_READ: | 208 | case CS_READ: |
| @@ -254,19 +258,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 254 | config_t *c; | 258 | config_t *c; |
| 255 | 259 | ||
| 256 | s = p_dev->socket; | 260 | s = p_dev->socket; |
| 261 | |||
| 262 | mutex_lock(&s->ops_mutex); | ||
| 257 | c = p_dev->function_config; | 263 | c = p_dev->function_config; |
| 258 | 264 | ||
| 259 | if (!(s->state & SOCKET_PRESENT)) { | 265 | if (!(s->state & SOCKET_PRESENT)) { |
| 260 | dev_dbg(&s->dev, "No card present\n"); | 266 | dev_dbg(&s->dev, "No card present\n"); |
| 267 | mutex_unlock(&s->ops_mutex); | ||
| 261 | return -ENODEV; | 268 | return -ENODEV; |
| 262 | } | 269 | } |
| 263 | if (!(c->state & CONFIG_LOCKED)) { | 270 | if (!(c->state & CONFIG_LOCKED)) { |
| 264 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 271 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); |
| 272 | mutex_unlock(&s->ops_mutex); | ||
| 265 | return -EACCES; | 273 | return -EACCES; |
| 266 | } | 274 | } |
| 267 | 275 | ||
| 268 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | 276 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { |
| 269 | mutex_lock(&s->ops_mutex); | ||
| 270 | if (mod->Attributes & CONF_ENABLE_IRQ) { | 277 | if (mod->Attributes & CONF_ENABLE_IRQ) { |
| 271 | c->Attributes |= CONF_ENABLE_IRQ; | 278 | c->Attributes |= CONF_ENABLE_IRQ; |
| 272 | s->socket.io_irq = s->irq.AssignedIRQ; | 279 | s->socket.io_irq = s->irq.AssignedIRQ; |
| @@ -275,7 +282,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 275 | s->socket.io_irq = 0; | 282 | s->socket.io_irq = 0; |
| 276 | } | 283 | } |
| 277 | s->ops->set_socket(s, &s->socket); | 284 | s->ops->set_socket(s, &s->socket); |
| 278 | mutex_unlock(&s->ops_mutex); | ||
| 279 | } | 285 | } |
| 280 | 286 | ||
| 281 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { | 287 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { |
| @@ -288,9 +294,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 288 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 294 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 289 | if (mod->Vpp1 != mod->Vpp2) { | 295 | if (mod->Vpp1 != mod->Vpp2) { |
| 290 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); | 296 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); |
| 297 | mutex_unlock(&s->ops_mutex); | ||
| 291 | return -EINVAL; | 298 | return -EINVAL; |
| 292 | } | 299 | } |
| 293 | mutex_lock(&s->ops_mutex); | ||
| 294 | s->socket.Vpp = mod->Vpp1; | 300 | s->socket.Vpp = mod->Vpp1; |
| 295 | if (s->ops->set_socket(s, &s->socket)) { | 301 | if (s->ops->set_socket(s, &s->socket)) { |
| 296 | mutex_unlock(&s->ops_mutex); | 302 | mutex_unlock(&s->ops_mutex); |
| @@ -298,10 +304,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 298 | "Unable to set VPP\n"); | 304 | "Unable to set VPP\n"); |
| 299 | return -EIO; | 305 | return -EIO; |
| 300 | } | 306 | } |
| 301 | mutex_unlock(&s->ops_mutex); | ||
| 302 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 307 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
| 303 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 308 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 304 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | 309 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); |
| 310 | mutex_unlock(&s->ops_mutex); | ||
| 305 | return -EINVAL; | 311 | return -EINVAL; |
| 306 | } | 312 | } |
| 307 | 313 | ||
| @@ -311,7 +317,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 311 | int i; | 317 | int i; |
| 312 | 318 | ||
| 313 | io_on.speed = io_speed; | 319 | io_on.speed = io_speed; |
| 314 | mutex_lock(&s->ops_mutex); | ||
| 315 | for (i = 0; i < MAX_IO_WIN; i++) { | 320 | for (i = 0; i < MAX_IO_WIN; i++) { |
| 316 | if (!s->io[i].res) | 321 | if (!s->io[i].res) |
| 317 | continue; | 322 | continue; |
| @@ -326,8 +331,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 326 | mdelay(40); | 331 | mdelay(40); |
| 327 | s->ops->set_io_map(s, &io_on); | 332 | s->ops->set_io_map(s, &io_on); |
| 328 | } | 333 | } |
| 329 | mutex_unlock(&s->ops_mutex); | ||
| 330 | } | 334 | } |
| 335 | mutex_unlock(&s->ops_mutex); | ||
| 331 | 336 | ||
| 332 | return 0; | 337 | return 0; |
| 333 | } /* modify_configuration */ | 338 | } /* modify_configuration */ |
| @@ -338,10 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
| 338 | { | 343 | { |
| 339 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 344 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
| 340 | struct pcmcia_socket *s = p_dev->socket; | 345 | struct pcmcia_socket *s = p_dev->socket; |
| 341 | config_t *c = p_dev->function_config; | 346 | config_t *c; |
| 342 | int i; | 347 | int i; |
| 343 | 348 | ||
| 344 | mutex_lock(&s->ops_mutex); | 349 | mutex_lock(&s->ops_mutex); |
| 350 | c = p_dev->function_config; | ||
| 345 | if (p_dev->_locked) { | 351 | if (p_dev->_locked) { |
| 346 | p_dev->_locked = 0; | 352 | p_dev->_locked = 0; |
| 347 | if (--(s->lock_count) == 0) { | 353 | if (--(s->lock_count) == 0) { |
| @@ -381,10 +387,14 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
| 381 | static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | 387 | static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) |
| 382 | { | 388 | { |
| 383 | struct pcmcia_socket *s = p_dev->socket; | 389 | struct pcmcia_socket *s = p_dev->socket; |
| 384 | config_t *c = p_dev->function_config; | 390 | int ret = -EINVAL; |
| 391 | config_t *c; | ||
| 392 | |||
| 393 | mutex_lock(&s->ops_mutex); | ||
| 394 | c = p_dev->function_config; | ||
| 385 | 395 | ||
| 386 | if (!p_dev->_io) | 396 | if (!p_dev->_io) |
| 387 | return -EINVAL; | 397 | goto out; |
| 388 | 398 | ||
| 389 | p_dev->_io = 0; | 399 | p_dev->_io = 0; |
| 390 | 400 | ||
| @@ -392,7 +402,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
| 392 | (c->io.NumPorts1 != req->NumPorts1) || | 402 | (c->io.NumPorts1 != req->NumPorts1) || |
| 393 | (c->io.BasePort2 != req->BasePort2) || | 403 | (c->io.BasePort2 != req->BasePort2) || |
| 394 | (c->io.NumPorts2 != req->NumPorts2)) | 404 | (c->io.NumPorts2 != req->NumPorts2)) |
| 395 | return -EINVAL; | 405 | goto out; |
| 396 | 406 | ||
| 397 | c->state &= ~CONFIG_IO_REQ; | 407 | c->state &= ~CONFIG_IO_REQ; |
| 398 | 408 | ||
| @@ -400,30 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
| 400 | if (req->NumPorts2) | 410 | if (req->NumPorts2) |
| 401 | release_io_space(s, req->BasePort2, req->NumPorts2); | 411 | release_io_space(s, req->BasePort2, req->NumPorts2); |
| 402 | 412 | ||
| 403 | return 0; | 413 | out: |
| 414 | mutex_unlock(&s->ops_mutex); | ||
| 415 | |||
| 416 | return ret; | ||
| 404 | } /* pcmcia_release_io */ | 417 | } /* pcmcia_release_io */ |
| 405 | 418 | ||
| 406 | 419 | ||
| 407 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 420 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) |
| 408 | { | 421 | { |
| 409 | struct pcmcia_socket *s = p_dev->socket; | 422 | struct pcmcia_socket *s = p_dev->socket; |
| 410 | config_t *c = p_dev->function_config; | 423 | config_t *c; |
| 424 | int ret = -EINVAL; | ||
| 425 | |||
| 426 | mutex_lock(&s->ops_mutex); | ||
| 427 | |||
| 428 | c = p_dev->function_config; | ||
| 411 | 429 | ||
| 412 | if (!p_dev->_irq) | 430 | if (!p_dev->_irq) |
| 413 | return -EINVAL; | 431 | goto out; |
| 432 | |||
| 414 | p_dev->_irq = 0; | 433 | p_dev->_irq = 0; |
| 415 | 434 | ||
| 416 | if (c->state & CONFIG_LOCKED) | 435 | if (c->state & CONFIG_LOCKED) |
| 417 | return -EACCES; | 436 | goto out; |
| 437 | |||
| 418 | if (c->irq.Attributes != req->Attributes) { | 438 | if (c->irq.Attributes != req->Attributes) { |
| 419 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); | 439 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); |
| 420 | return -EINVAL; | 440 | goto out; |
| 421 | } | 441 | } |
| 422 | mutex_lock(&s->ops_mutex); | ||
| 423 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | 442 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { |
| 424 | mutex_unlock(&s->ops_mutex); | ||
| 425 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); | 443 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); |
| 426 | return -EINVAL; | 444 | goto out; |
| 427 | } | 445 | } |
| 428 | if (--s->irq.Config == 0) { | 446 | if (--s->irq.Config == 0) { |
| 429 | c->state &= ~CONFIG_IRQ_REQ; | 447 | c->state &= ~CONFIG_IRQ_REQ; |
| @@ -436,9 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
| 436 | #ifdef CONFIG_PCMCIA_PROBE | 454 | #ifdef CONFIG_PCMCIA_PROBE |
| 437 | pcmcia_used_irq[req->AssignedIRQ]--; | 455 | pcmcia_used_irq[req->AssignedIRQ]--; |
| 438 | #endif | 456 | #endif |
| 457 | ret = 0; | ||
| 458 | |||
| 459 | out: | ||
| 439 | mutex_unlock(&s->ops_mutex); | 460 | mutex_unlock(&s->ops_mutex); |
| 440 | 461 | ||
| 441 | return 0; | 462 | return ret; |
| 442 | } /* pcmcia_release_irq */ | 463 | } /* pcmcia_release_irq */ |
| 443 | 464 | ||
| 444 | 465 | ||
| @@ -495,13 +516,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
| 495 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); | 516 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); |
| 496 | return -EINVAL; | 517 | return -EINVAL; |
| 497 | } | 518 | } |
| 519 | |||
| 520 | mutex_lock(&s->ops_mutex); | ||
| 498 | c = p_dev->function_config; | 521 | c = p_dev->function_config; |
| 499 | if (c->state & CONFIG_LOCKED) { | 522 | if (c->state & CONFIG_LOCKED) { |
| 523 | mutex_unlock(&s->ops_mutex); | ||
| 500 | dev_dbg(&s->dev, "Configuration is locked\n"); | 524 | dev_dbg(&s->dev, "Configuration is locked\n"); |
| 501 | return -EACCES; | 525 | return -EACCES; |
| 502 | } | 526 | } |
| 503 | 527 | ||
| 504 | mutex_lock(&s->ops_mutex); | ||
| 505 | /* Do power control. We don't allow changes in Vcc. */ | 528 | /* Do power control. We don't allow changes in Vcc. */ |
| 506 | s->socket.Vpp = req->Vpp; | 529 | s->socket.Vpp = req->Vpp; |
| 507 | if (s->ops->set_socket(s, &s->socket)) { | 530 | if (s->ops->set_socket(s, &s->socket)) { |
| @@ -615,58 +638,65 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
| 615 | { | 638 | { |
| 616 | struct pcmcia_socket *s = p_dev->socket; | 639 | struct pcmcia_socket *s = p_dev->socket; |
| 617 | config_t *c; | 640 | config_t *c; |
| 641 | int ret = -EINVAL; | ||
| 642 | |||
| 643 | mutex_lock(&s->ops_mutex); | ||
| 618 | 644 | ||
| 619 | if (!(s->state & SOCKET_PRESENT)) { | 645 | if (!(s->state & SOCKET_PRESENT)) { |
| 620 | dev_dbg(&s->dev, "No card present\n"); | 646 | dev_dbg(&s->dev, "No card present\n"); |
| 621 | return -ENODEV; | 647 | goto out; |
| 622 | } | 648 | } |
| 623 | 649 | ||
| 624 | if (!req) | 650 | if (!req) |
| 625 | return -EINVAL; | 651 | goto out; |
| 652 | |||
| 626 | c = p_dev->function_config; | 653 | c = p_dev->function_config; |
| 627 | if (c->state & CONFIG_LOCKED) { | 654 | if (c->state & CONFIG_LOCKED) { |
| 628 | dev_dbg(&s->dev, "Configuration is locked\n"); | 655 | dev_dbg(&s->dev, "Configuration is locked\n"); |
| 629 | return -EACCES; | 656 | goto out; |
| 630 | } | 657 | } |
| 631 | if (c->state & CONFIG_IO_REQ) { | 658 | if (c->state & CONFIG_IO_REQ) { |
| 632 | dev_dbg(&s->dev, "IO already configured\n"); | 659 | dev_dbg(&s->dev, "IO already configured\n"); |
| 633 | return -EBUSY; | 660 | goto out; |
| 634 | } | 661 | } |
| 635 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { | 662 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { |
| 636 | dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); | 663 | dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); |
| 637 | return -EINVAL; | 664 | goto out; |
| 638 | } | 665 | } |
| 639 | if ((req->NumPorts2 > 0) && | 666 | if ((req->NumPorts2 > 0) && |
| 640 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { | 667 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { |
| 641 | dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); | 668 | dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); |
| 642 | return -EINVAL; | 669 | goto out; |
| 643 | } | 670 | } |
| 644 | 671 | ||
| 645 | mutex_lock(&s->ops_mutex); | ||
| 646 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); | 672 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); |
| 647 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | 673 | ret = alloc_io_space(s, req->Attributes1, &req->BasePort1, |
| 648 | req->NumPorts1, req->IOAddrLines)) { | 674 | req->NumPorts1, req->IOAddrLines); |
| 675 | if (ret) { | ||
| 649 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); | 676 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); |
| 650 | mutex_unlock(&s->ops_mutex); | 677 | goto out; |
| 651 | return -EBUSY; | ||
| 652 | } | 678 | } |
| 653 | 679 | ||
| 654 | if (req->NumPorts2) { | 680 | if (req->NumPorts2) { |
| 655 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); | 681 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); |
| 656 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | 682 | ret = alloc_io_space(s, req->Attributes2, &req->BasePort2, |
| 657 | req->NumPorts2, req->IOAddrLines)) { | 683 | req->NumPorts2, req->IOAddrLines); |
| 684 | if (ret) { | ||
| 658 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); | 685 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); |
| 659 | release_io_space(s, req->BasePort1, req->NumPorts1); | 686 | release_io_space(s, req->BasePort1, req->NumPorts1); |
| 660 | mutex_unlock(&s->ops_mutex); | 687 | goto out; |
| 661 | return -EBUSY; | ||
| 662 | } | 688 | } |
| 663 | } | 689 | } |
| 664 | mutex_unlock(&s->ops_mutex); | ||
| 665 | 690 | ||
| 666 | c->io = *req; | 691 | c->io = *req; |
| 667 | c->state |= CONFIG_IO_REQ; | 692 | c->state |= CONFIG_IO_REQ; |
| 668 | p_dev->_io = 1; | 693 | p_dev->_io = 1; |
| 669 | return 0; | 694 | dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret); |
| 695 | |||
| 696 | out: | ||
| 697 | mutex_unlock(&s->ops_mutex); | ||
| 698 | |||
| 699 | return ret; | ||
| 670 | } /* pcmcia_request_io */ | 700 | } /* pcmcia_request_io */ |
| 671 | EXPORT_SYMBOL(pcmcia_request_io); | 701 | EXPORT_SYMBOL(pcmcia_request_io); |
| 672 | 702 | ||
| @@ -695,21 +725,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
| 695 | int ret = -EINVAL, irq = 0; | 725 | int ret = -EINVAL, irq = 0; |
| 696 | int type; | 726 | int type; |
| 697 | 727 | ||
| 728 | mutex_lock(&s->ops_mutex); | ||
| 729 | |||
| 698 | if (!(s->state & SOCKET_PRESENT)) { | 730 | if (!(s->state & SOCKET_PRESENT)) { |
| 699 | dev_dbg(&s->dev, "No card present\n"); | 731 | dev_dbg(&s->dev, "No card present\n"); |
| 700 | return -ENODEV; | 732 | goto out; |
| 701 | } | 733 | } |
| 702 | c = p_dev->function_config; | 734 | c = p_dev->function_config; |
| 703 | if (c->state & CONFIG_LOCKED) { | 735 | if (c->state & CONFIG_LOCKED) { |
| 704 | dev_dbg(&s->dev, "Configuration is locked\n"); | 736 | dev_dbg(&s->dev, "Configuration is locked\n"); |
| 705 | return -EACCES; | 737 | goto out; |
| 706 | } | 738 | } |
| 707 | if (c->state & CONFIG_IRQ_REQ) { | 739 | if (c->state & CONFIG_IRQ_REQ) { |
| 708 | dev_dbg(&s->dev, "IRQ already configured\n"); | 740 | dev_dbg(&s->dev, "IRQ already configured\n"); |
| 709 | return -EBUSY; | 741 | goto out; |
| 710 | } | 742 | } |
| 711 | 743 | ||
| 712 | mutex_lock(&s->ops_mutex); | ||
| 713 | /* Decide what type of interrupt we are registering */ | 744 | /* Decide what type of interrupt we are registering */ |
| 714 | type = 0; | 745 | type = 0; |
| 715 | if (s->functions > 1) /* All of this ought to be handled higher up */ | 746 | if (s->functions > 1) /* All of this ought to be handled higher up */ |
| @@ -768,7 +799,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
| 768 | if (ret && !s->irq.AssignedIRQ) { | 799 | if (ret && !s->irq.AssignedIRQ) { |
| 769 | if (!s->pci_irq) { | 800 | if (!s->pci_irq) { |
| 770 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | 801 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); |
| 771 | return ret; | 802 | goto out; |
| 772 | } | 803 | } |
| 773 | type = IRQF_SHARED; | 804 | type = IRQF_SHARED; |
| 774 | irq = s->pci_irq; | 805 | irq = s->pci_irq; |
| @@ -780,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
| 780 | if (ret) { | 811 | if (ret) { |
| 781 | dev_printk(KERN_INFO, &s->dev, | 812 | dev_printk(KERN_INFO, &s->dev, |
| 782 | "request_irq() failed\n"); | 813 | "request_irq() failed\n"); |
| 783 | return ret; | 814 | goto out; |
| 784 | } | 815 | } |
| 785 | } | 816 | } |
| 786 | 817 | ||
| @@ -803,9 +834,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
| 803 | pcmcia_used_irq[irq]++; | 834 | pcmcia_used_irq[irq]++; |
| 804 | #endif | 835 | #endif |
| 805 | 836 | ||
| 837 | ret = 0; | ||
| 838 | out: | ||
| 806 | mutex_unlock(&s->ops_mutex); | 839 | mutex_unlock(&s->ops_mutex); |
| 807 | 840 | return ret; | |
| 808 | return 0; | ||
| 809 | } /* pcmcia_request_irq */ | 841 | } /* pcmcia_request_irq */ |
| 810 | EXPORT_SYMBOL(pcmcia_request_irq); | 842 | EXPORT_SYMBOL(pcmcia_request_irq); |
| 811 | 843 | ||
