shpchp_ctrl.c (17833B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Standard Hot Plug Controller Driver 4 * 5 * Copyright (C) 1995,2001 Compaq Computer Corporation 6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 7 * Copyright (C) 2001 IBM Corp. 8 * Copyright (C) 2003-2004 Intel Corporation 9 * 10 * All rights reserved. 11 * 12 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 13 * 14 */ 15 16#include <linux/module.h> 17#include <linux/kernel.h> 18#include <linux/types.h> 19#include <linux/slab.h> 20#include <linux/pci.h> 21#include "../pci.h" 22#include "shpchp.h" 23 24static void interrupt_event_handler(struct work_struct *work); 25static int shpchp_enable_slot(struct slot *p_slot); 26static int shpchp_disable_slot(struct slot *p_slot); 27 28static int queue_interrupt_event(struct slot *p_slot, u32 event_type) 29{ 30 struct event_info *info; 31 32 info = kmalloc(sizeof(*info), GFP_ATOMIC); 33 if (!info) 34 return -ENOMEM; 35 36 info->event_type = event_type; 37 info->p_slot = p_slot; 38 INIT_WORK(&info->work, interrupt_event_handler); 39 40 queue_work(p_slot->wq, &info->work); 41 42 return 0; 43} 44 45u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) 46{ 47 struct slot *p_slot; 48 u32 event_type; 49 50 /* Attention Button Change */ 51 ctrl_dbg(ctrl, "Attention button interrupt received\n"); 52 53 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 54 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 55 56 /* 57 * Button pressed - See if need to TAKE ACTION!!! 58 */ 59 ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot)); 60 event_type = INT_BUTTON_PRESS; 61 62 queue_interrupt_event(p_slot, event_type); 63 64 return 0; 65 66} 67 68u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl) 69{ 70 struct slot *p_slot; 71 u8 getstatus; 72 u32 event_type; 73 74 /* Switch Change */ 75 ctrl_dbg(ctrl, "Switch interrupt received\n"); 76 77 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 78 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 79 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 80 ctrl_dbg(ctrl, "Card present %x Power status %x\n", 81 p_slot->presence_save, p_slot->pwr_save); 82 83 if (getstatus) { 84 /* 85 * Switch opened 86 */ 87 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); 88 event_type = INT_SWITCH_OPEN; 89 if (p_slot->pwr_save && p_slot->presence_save) { 90 event_type = INT_POWER_FAULT; 91 ctrl_err(ctrl, "Surprise Removal of card\n"); 92 } 93 } else { 94 /* 95 * Switch closed 96 */ 97 ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); 98 event_type = INT_SWITCH_CLOSE; 99 } 100 101 queue_interrupt_event(p_slot, event_type); 102 103 return 1; 104} 105 106u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) 107{ 108 struct slot *p_slot; 109 u32 event_type; 110 111 /* Presence Change */ 112 ctrl_dbg(ctrl, "Presence/Notify input change\n"); 113 114 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 115 116 /* 117 * Save the presence state 118 */ 119 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 120 if (p_slot->presence_save) { 121 /* 122 * Card Present 123 */ 124 ctrl_info(ctrl, "Card present on Slot(%s)\n", 125 slot_name(p_slot)); 126 event_type = INT_PRESENCE_ON; 127 } else { 128 /* 129 * Not Present 130 */ 131 ctrl_info(ctrl, "Card not present on Slot(%s)\n", 132 slot_name(p_slot)); 133 event_type = INT_PRESENCE_OFF; 134 } 135 136 queue_interrupt_event(p_slot, event_type); 137 138 return 1; 139} 140 141u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) 142{ 143 struct slot *p_slot; 144 u32 event_type; 145 146 /* Power fault */ 147 ctrl_dbg(ctrl, "Power fault interrupt received\n"); 148 149 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 150 151 if (!(p_slot->hpc_ops->query_power_fault(p_slot))) { 152 /* 153 * Power fault Cleared 154 */ 155 ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", 156 slot_name(p_slot)); 157 p_slot->status = 0x00; 158 event_type = INT_POWER_FAULT_CLEAR; 159 } else { 160 /* 161 * Power fault 162 */ 163 ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); 164 event_type = INT_POWER_FAULT; 165 /* set power fault status for this board */ 166 p_slot->status = 0xFF; 167 ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot); 168 } 169 170 queue_interrupt_event(p_slot, event_type); 171 172 return 1; 173} 174 175/* The following routines constitute the bulk of the 176 hotplug controller logic 177 */ 178static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, 179 enum pci_bus_speed speed) 180{ 181 int rc = 0; 182 183 ctrl_dbg(ctrl, "Change speed to %d\n", speed); 184 rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed); 185 if (rc) { 186 ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", 187 __func__); 188 return WRONG_BUS_FREQUENCY; 189 } 190 return rc; 191} 192 193static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, 194 u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, 195 enum pci_bus_speed msp) 196{ 197 int rc = 0; 198 199 /* 200 * If other slots on the same bus are occupied, we cannot 201 * change the bus speed. 202 */ 203 if (flag) { 204 if (asp < bsp) { 205 ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n", 206 bsp, asp); 207 rc = WRONG_BUS_FREQUENCY; 208 } 209 return rc; 210 } 211 212 if (asp < msp) { 213 if (bsp != asp) 214 rc = change_bus_speed(ctrl, pslot, asp); 215 } else { 216 if (bsp != msp) 217 rc = change_bus_speed(ctrl, pslot, msp); 218 } 219 return rc; 220} 221 222/** 223 * board_added - Called after a board has been added to the system. 224 * @p_slot: target &slot 225 * 226 * Turns power on for the board. 227 * Configures board. 228 */ 229static int board_added(struct slot *p_slot) 230{ 231 u8 hp_slot; 232 u8 slots_not_empty = 0; 233 int rc = 0; 234 enum pci_bus_speed asp, bsp, msp; 235 struct controller *ctrl = p_slot->ctrl; 236 struct pci_bus *parent = ctrl->pci_dev->subordinate; 237 238 hp_slot = p_slot->device - ctrl->slot_device_offset; 239 240 ctrl_dbg(ctrl, "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", 241 __func__, p_slot->device, ctrl->slot_device_offset, hp_slot); 242 243 /* Power on slot without connecting to bus */ 244 rc = p_slot->hpc_ops->power_on_slot(p_slot); 245 if (rc) { 246 ctrl_err(ctrl, "Failed to power on slot\n"); 247 return -1; 248 } 249 250 if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { 251 rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz); 252 if (rc) { 253 ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", 254 __func__); 255 return WRONG_BUS_FREQUENCY; 256 } 257 258 /* turn on board, blink green LED, turn off Amber LED */ 259 rc = p_slot->hpc_ops->slot_enable(p_slot); 260 if (rc) { 261 ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 262 return rc; 263 } 264 } 265 266 rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); 267 if (rc) { 268 ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n"); 269 return WRONG_BUS_FREQUENCY; 270 } 271 272 bsp = ctrl->pci_dev->subordinate->cur_bus_speed; 273 msp = ctrl->pci_dev->subordinate->max_bus_speed; 274 275 /* Check if there are other slots or devices on the same bus */ 276 if (!list_empty(&ctrl->pci_dev->subordinate->devices)) 277 slots_not_empty = 1; 278 279 ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, max_bus_speed %d\n", 280 __func__, slots_not_empty, asp, 281 bsp, msp); 282 283 rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); 284 if (rc) 285 return rc; 286 287 /* turn on board, blink green LED, turn off Amber LED */ 288 rc = p_slot->hpc_ops->slot_enable(p_slot); 289 if (rc) { 290 ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 291 return rc; 292 } 293 294 /* Wait for ~1 second */ 295 msleep(1000); 296 297 ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status); 298 /* Check for a power fault */ 299 if (p_slot->status == 0xFF) { 300 /* power fault occurred, but it was benign */ 301 ctrl_dbg(ctrl, "%s: Power fault\n", __func__); 302 p_slot->status = 0; 303 goto err_exit; 304 } 305 306 if (shpchp_configure_device(p_slot)) { 307 ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", 308 pci_domain_nr(parent), p_slot->bus, p_slot->device); 309 goto err_exit; 310 } 311 312 p_slot->status = 0; 313 p_slot->is_a_board = 0x01; 314 p_slot->pwr_save = 1; 315 316 p_slot->hpc_ops->green_led_on(p_slot); 317 318 return 0; 319 320err_exit: 321 /* turn off slot, turn on Amber LED, turn off Green LED */ 322 rc = p_slot->hpc_ops->slot_disable(p_slot); 323 if (rc) { 324 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 325 __func__); 326 return rc; 327 } 328 329 return(rc); 330} 331 332 333/** 334 * remove_board - Turns off slot and LEDs 335 * @p_slot: target &slot 336 */ 337static int remove_board(struct slot *p_slot) 338{ 339 struct controller *ctrl = p_slot->ctrl; 340 u8 hp_slot; 341 int rc; 342 343 shpchp_unconfigure_device(p_slot); 344 345 hp_slot = p_slot->device - ctrl->slot_device_offset; 346 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 347 348 ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot); 349 350 /* Change status to shutdown */ 351 if (p_slot->is_a_board) 352 p_slot->status = 0x01; 353 354 /* turn off slot, turn on Amber LED, turn off Green LED */ 355 rc = p_slot->hpc_ops->slot_disable(p_slot); 356 if (rc) { 357 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 358 __func__); 359 return rc; 360 } 361 362 rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); 363 if (rc) { 364 ctrl_err(ctrl, "Issue of Set Attention command failed\n"); 365 return rc; 366 } 367 368 p_slot->pwr_save = 0; 369 p_slot->is_a_board = 0; 370 371 return 0; 372} 373 374 375struct pushbutton_work_info { 376 struct slot *p_slot; 377 struct work_struct work; 378}; 379 380/** 381 * shpchp_pushbutton_thread - handle pushbutton events 382 * @work: &struct work_struct to be handled 383 * 384 * Scheduled procedure to handle blocking stuff for the pushbuttons. 385 * Handles all pending events and exits. 386 */ 387static void shpchp_pushbutton_thread(struct work_struct *work) 388{ 389 struct pushbutton_work_info *info = 390 container_of(work, struct pushbutton_work_info, work); 391 struct slot *p_slot = info->p_slot; 392 393 mutex_lock(&p_slot->lock); 394 switch (p_slot->state) { 395 case POWEROFF_STATE: 396 mutex_unlock(&p_slot->lock); 397 shpchp_disable_slot(p_slot); 398 mutex_lock(&p_slot->lock); 399 p_slot->state = STATIC_STATE; 400 break; 401 case POWERON_STATE: 402 mutex_unlock(&p_slot->lock); 403 if (shpchp_enable_slot(p_slot)) 404 p_slot->hpc_ops->green_led_off(p_slot); 405 mutex_lock(&p_slot->lock); 406 p_slot->state = STATIC_STATE; 407 break; 408 default: 409 break; 410 } 411 mutex_unlock(&p_slot->lock); 412 413 kfree(info); 414} 415 416void shpchp_queue_pushbutton_work(struct work_struct *work) 417{ 418 struct slot *p_slot = container_of(work, struct slot, work.work); 419 struct pushbutton_work_info *info; 420 421 info = kmalloc(sizeof(*info), GFP_KERNEL); 422 if (!info) { 423 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", 424 __func__); 425 return; 426 } 427 info->p_slot = p_slot; 428 INIT_WORK(&info->work, shpchp_pushbutton_thread); 429 430 mutex_lock(&p_slot->lock); 431 switch (p_slot->state) { 432 case BLINKINGOFF_STATE: 433 p_slot->state = POWEROFF_STATE; 434 break; 435 case BLINKINGON_STATE: 436 p_slot->state = POWERON_STATE; 437 break; 438 default: 439 kfree(info); 440 goto out; 441 } 442 queue_work(p_slot->wq, &info->work); 443 out: 444 mutex_unlock(&p_slot->lock); 445} 446 447static void update_slot_info(struct slot *slot) 448{ 449 slot->hpc_ops->get_power_status(slot, &slot->pwr_save); 450 slot->hpc_ops->get_attention_status(slot, &slot->attention_save); 451 slot->hpc_ops->get_latch_status(slot, &slot->latch_save); 452 slot->hpc_ops->get_adapter_status(slot, &slot->presence_save); 453} 454 455/* 456 * Note: This function must be called with slot->lock held 457 */ 458static void handle_button_press_event(struct slot *p_slot) 459{ 460 u8 getstatus; 461 struct controller *ctrl = p_slot->ctrl; 462 463 switch (p_slot->state) { 464 case STATIC_STATE: 465 p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 466 if (getstatus) { 467 p_slot->state = BLINKINGOFF_STATE; 468 ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", 469 slot_name(p_slot)); 470 } else { 471 p_slot->state = BLINKINGON_STATE; 472 ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", 473 slot_name(p_slot)); 474 } 475 /* blink green LED and turn off amber */ 476 p_slot->hpc_ops->green_led_blink(p_slot); 477 p_slot->hpc_ops->set_attention_status(p_slot, 0); 478 479 queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); 480 break; 481 case BLINKINGOFF_STATE: 482 case BLINKINGON_STATE: 483 /* 484 * Cancel if we are still blinking; this means that we 485 * press the attention again before the 5 sec. limit 486 * expires to cancel hot-add or hot-remove 487 */ 488 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", 489 slot_name(p_slot)); 490 cancel_delayed_work(&p_slot->work); 491 if (p_slot->state == BLINKINGOFF_STATE) 492 p_slot->hpc_ops->green_led_on(p_slot); 493 else 494 p_slot->hpc_ops->green_led_off(p_slot); 495 p_slot->hpc_ops->set_attention_status(p_slot, 0); 496 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", 497 slot_name(p_slot)); 498 p_slot->state = STATIC_STATE; 499 break; 500 case POWEROFF_STATE: 501 case POWERON_STATE: 502 /* 503 * Ignore if the slot is on power-on or power-off state; 504 * this means that the previous attention button action 505 * to hot-add or hot-remove is undergoing 506 */ 507 ctrl_info(ctrl, "Button ignore on Slot(%s)\n", 508 slot_name(p_slot)); 509 update_slot_info(p_slot); 510 break; 511 default: 512 ctrl_warn(ctrl, "Not a valid state\n"); 513 break; 514 } 515} 516 517static void interrupt_event_handler(struct work_struct *work) 518{ 519 struct event_info *info = container_of(work, struct event_info, work); 520 struct slot *p_slot = info->p_slot; 521 522 mutex_lock(&p_slot->lock); 523 switch (info->event_type) { 524 case INT_BUTTON_PRESS: 525 handle_button_press_event(p_slot); 526 break; 527 case INT_POWER_FAULT: 528 ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__); 529 p_slot->hpc_ops->set_attention_status(p_slot, 1); 530 p_slot->hpc_ops->green_led_off(p_slot); 531 break; 532 default: 533 update_slot_info(p_slot); 534 break; 535 } 536 mutex_unlock(&p_slot->lock); 537 538 kfree(info); 539} 540 541 542static int shpchp_enable_slot (struct slot *p_slot) 543{ 544 u8 getstatus = 0; 545 int rc, retval = -ENODEV; 546 struct controller *ctrl = p_slot->ctrl; 547 548 /* Check to see if (latch closed, card present, power off) */ 549 mutex_lock(&p_slot->ctrl->crit_sect); 550 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 551 if (rc || !getstatus) { 552 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 553 goto out; 554 } 555 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 556 if (rc || getstatus) { 557 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 558 goto out; 559 } 560 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 561 if (rc || getstatus) { 562 ctrl_info(ctrl, "Already enabled on slot(%s)\n", 563 slot_name(p_slot)); 564 goto out; 565 } 566 567 p_slot->is_a_board = 1; 568 569 /* We have to save the presence info for these slots */ 570 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 571 p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); 572 ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save); 573 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 574 575 if ((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD && 576 p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458) 577 && p_slot->ctrl->num_slots == 1) { 578 /* handle AMD POGO errata; this must be done before enable */ 579 amd_pogo_errata_save_misc_reg(p_slot); 580 retval = board_added(p_slot); 581 /* handle AMD POGO errata; this must be done after enable */ 582 amd_pogo_errata_restore_misc_reg(p_slot); 583 } else 584 retval = board_added(p_slot); 585 586 if (retval) { 587 p_slot->hpc_ops->get_adapter_status(p_slot, 588 &(p_slot->presence_save)); 589 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 590 } 591 592 update_slot_info(p_slot); 593 out: 594 mutex_unlock(&p_slot->ctrl->crit_sect); 595 return retval; 596} 597 598 599static int shpchp_disable_slot (struct slot *p_slot) 600{ 601 u8 getstatus = 0; 602 int rc, retval = -ENODEV; 603 struct controller *ctrl = p_slot->ctrl; 604 605 if (!p_slot->ctrl) 606 return -ENODEV; 607 608 /* Check to see if (latch closed, card present, power on) */ 609 mutex_lock(&p_slot->ctrl->crit_sect); 610 611 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 612 if (rc || !getstatus) { 613 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 614 goto out; 615 } 616 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 617 if (rc || getstatus) { 618 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 619 goto out; 620 } 621 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 622 if (rc || !getstatus) { 623 ctrl_info(ctrl, "Already disabled on slot(%s)\n", 624 slot_name(p_slot)); 625 goto out; 626 } 627 628 retval = remove_board(p_slot); 629 update_slot_info(p_slot); 630 out: 631 mutex_unlock(&p_slot->ctrl->crit_sect); 632 return retval; 633} 634 635int shpchp_sysfs_enable_slot(struct slot *p_slot) 636{ 637 int retval = -ENODEV; 638 struct controller *ctrl = p_slot->ctrl; 639 640 mutex_lock(&p_slot->lock); 641 switch (p_slot->state) { 642 case BLINKINGON_STATE: 643 cancel_delayed_work(&p_slot->work); 644 fallthrough; 645 case STATIC_STATE: 646 p_slot->state = POWERON_STATE; 647 mutex_unlock(&p_slot->lock); 648 retval = shpchp_enable_slot(p_slot); 649 mutex_lock(&p_slot->lock); 650 p_slot->state = STATIC_STATE; 651 break; 652 case POWERON_STATE: 653 ctrl_info(ctrl, "Slot %s is already in powering on state\n", 654 slot_name(p_slot)); 655 break; 656 case BLINKINGOFF_STATE: 657 case POWEROFF_STATE: 658 ctrl_info(ctrl, "Already enabled on slot %s\n", 659 slot_name(p_slot)); 660 break; 661 default: 662 ctrl_err(ctrl, "Not a valid state on slot %s\n", 663 slot_name(p_slot)); 664 break; 665 } 666 mutex_unlock(&p_slot->lock); 667 668 return retval; 669} 670 671int shpchp_sysfs_disable_slot(struct slot *p_slot) 672{ 673 int retval = -ENODEV; 674 struct controller *ctrl = p_slot->ctrl; 675 676 mutex_lock(&p_slot->lock); 677 switch (p_slot->state) { 678 case BLINKINGOFF_STATE: 679 cancel_delayed_work(&p_slot->work); 680 fallthrough; 681 case STATIC_STATE: 682 p_slot->state = POWEROFF_STATE; 683 mutex_unlock(&p_slot->lock); 684 retval = shpchp_disable_slot(p_slot); 685 mutex_lock(&p_slot->lock); 686 p_slot->state = STATIC_STATE; 687 break; 688 case POWEROFF_STATE: 689 ctrl_info(ctrl, "Slot %s is already in powering off state\n", 690 slot_name(p_slot)); 691 break; 692 case BLINKINGON_STATE: 693 case POWERON_STATE: 694 ctrl_info(ctrl, "Already disabled on slot %s\n", 695 slot_name(p_slot)); 696 break; 697 default: 698 ctrl_err(ctrl, "Not a valid state on slot %s\n", 699 slot_name(p_slot)); 700 break; 701 } 702 mutex_unlock(&p_slot->lock); 703 704 return retval; 705}