11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Standard Hot Plug Controller Driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995,2001 Compaq Computer Corporation 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 IBM Corp. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003-2004 Intel Corporation 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT. See the GNU General Public License for more 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 268cf4c19523b7694c88bba716d88fb659fa702411Kristen Accardi * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 335a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 35dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah#include "../pci.h" 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "shpchp.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void interrupt_event_handler(struct work_struct *work); 39a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_enable_slot(struct slot *p_slot); 40a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_disable_slot(struct slot *p_slot); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshigestatic int queue_interrupt_event(struct slot *p_slot, u32 event_type) 43f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige{ 44f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige struct event_info *info; 45f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 46f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige info = kmalloc(sizeof(*info), GFP_ATOMIC); 47f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige if (!info) 48f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige return -ENOMEM; 49f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 50f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige info->event_type = event_type; 51f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige info->p_slot = p_slot; 52c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&info->work, interrupt_event_handler); 53f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 54f652e7d2916fe2fcf9e7d709aa5b7476b431e2ddBjorn Helgaas queue_work(p_slot->wq, &info->work); 55f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 56f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige return 0; 57f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige} 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 590abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeu8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct slot *p_slot; 62f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige u32 event_type; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Attention Button Change */ 65be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Attention button interrupt received\n"); 669f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 682178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Button pressed - See if need to TAKE ACTION!!! 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 73f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot)); 74f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_BUTTON_PRESS; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige queue_interrupt_event(p_slot, event_type); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 820abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeu8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct slot *p_slot; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus; 86f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige u32 event_type; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Switch Change */ 89be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Switch interrupt received\n"); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 922178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 94be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Card present %x Power status %x\n", 95be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi p_slot->presence_save, p_slot->pwr_save); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (getstatus) { 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch opened 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); 102f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_SWITCH_OPEN; 1032178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->pwr_save && p_slot->presence_save) { 104f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_POWER_FAULT; 105f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Surprise Removal of card\n"); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch closed 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); 112f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_SWITCH_CLOSE; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige queue_interrupt_event(p_slot, event_type); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige return 1; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1200abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeu8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct slot *p_slot; 123f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige u32 event_type; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Presence Change */ 126be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Presence/Notify input change\n"); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1309f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige /* 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save the presence state 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1332178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 1342178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->presence_save) { 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Card Present 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 138f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Card present on Slot(%s)\n", 139f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 140f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_PRESENCE_ON; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Not Present 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 145f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Card not present on Slot(%s)\n", 146f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 147f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_PRESENCE_OFF; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 150f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige queue_interrupt_event(p_slot, event_type); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 152f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige return 1; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1550abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeu8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct slot *p_slot; 158f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige u32 event_type; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Power fault */ 161be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Power fault interrupt received\n"); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1653c78bc61f5ef3bc87e7f94f67ec737d2273f120bRyan Desfosses if (!(p_slot->hpc_ops->query_power_fault(p_slot))) { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Power fault Cleared 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 169f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", 170f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 1712178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0x00; 172f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_POWER_FAULT_CLEAR; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Power fault 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 177f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); 178f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige event_type = INT_POWER_FAULT; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set power fault status for this board */ 1802178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0xFF; 181be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 184f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige queue_interrupt_event(p_slot, event_type); 185f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 186f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige return 1; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1899f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige/* The following routines constitute the bulk of the 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hotplug controller logic 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 192ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int change_bus_speed(struct controller *ctrl, struct slot *p_slot, 193ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah enum pci_bus_speed speed) 1949f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige{ 195ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc = 0; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Change speed to %d\n", speed); 19879e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed); 19979e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert if (rc) { 200227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", 201227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses __func__); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 207ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int fix_bus_speed(struct controller *ctrl, struct slot *pslot, 208ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, 209ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah enum pci_bus_speed msp) 2109f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige{ 211ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc = 0; 2120afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 2130afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige /* 2140afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige * If other slots on the same bus are occupied, we cannot 2150afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige * change the bus speed. 2160afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige */ 2170afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (flag) { 2180afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (asp < bsp) { 219227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n", 220227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses bsp, asp); 2210afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = WRONG_BUS_FREQUENCY; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2230afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return rc; 2240afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige } 2250afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 2260afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (asp < msp) { 2270afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (bsp != asp) 2280afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = change_bus_speed(ctrl, pslot, asp); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2300afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (bsp != msp) 2310afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = change_bus_speed(ctrl, pslot, msp); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * board_added - Called after a board has been added to the system. 23826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @p_slot: target &slot 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Turns power on for the board. 24126e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Configures board. 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 243ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int board_added(struct slot *p_slot) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 hp_slot; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 slots_not_empty = 0; 247ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc = 0; 2480afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige enum pci_bus_speed asp, bsp, msp; 2492178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah struct controller *ctrl = p_slot->ctrl; 250be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi struct pci_bus *parent = ctrl->pci_dev->subordinate; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2522178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah hp_slot = p_slot->device - ctrl->slot_device_offset; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 254227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_dbg(ctrl, "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", 255f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__, p_slot->device, ctrl->slot_device_offset, hp_slot); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Power on slot without connecting to bus */ 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->power_on_slot(p_slot); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 260be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Failed to power on slot\n"); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2639f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { 26579e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz); 26679e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert if (rc) { 267227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", 268227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses __func__); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2719f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on board, blink green LED, turn off Amber LED */ 27379e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert rc = p_slot->hpc_ops->slot_enable(p_slot); 27479e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert if (rc) { 275be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2799f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2800afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); 2810afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (rc) { 282227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n"); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28693fa9d32670f5592c8e56abc9928fc194e1e72fcMarcel Apfelbaum bsp = ctrl->pci_dev->subordinate->cur_bus_speed; 28793fa9d32670f5592c8e56abc9928fc194e1e72fcMarcel Apfelbaum msp = ctrl->pci_dev->subordinate->max_bus_speed; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if there are other slots or devices on the same bus */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&ctrl->pci_dev->subordinate->devices)) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slots_not_empty = 1; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, max_bus_speed %d\n", 294227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses __func__, slots_not_empty, asp, 295f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi bsp, msp); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2970afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); 2980afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (rc) 2990afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return rc; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on board, blink green LED, turn off Amber LED */ 30279e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert rc = p_slot->hpc_ops->slot_enable(p_slot); 30379e50e72986c9fcb06d707ce587cfd24fefa33e3Quentin Lambert if (rc) { 304be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait for ~1 second */ 30968c0b671491088d79611fa965bbf94b3bc0024a4Kenji Kaneshige msleep(1000); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for a power fault */ 3132178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->status == 0xFF) { 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* power fault occurred, but it was benign */ 315be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "%s: Power fault\n", __func__); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = POWER_FAILURE; 3172178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0; 318dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah goto err_exit; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah if (shpchp_configure_device(p_slot)) { 322be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", 323be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi pci_domain_nr(parent), p_slot->bus, p_slot->device); 324dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah goto err_exit; 325dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah } 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3272178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0; 3282178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 0x01; 3292178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->pwr_save = 1; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah p_slot->hpc_ops->green_led_on(p_slot); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 333dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return 0; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 335dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shaherr_exit: 336dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah /* turn off slot, turn on Amber LED, turn off Green LED */ 337dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah rc = p_slot->hpc_ops->slot_disable(p_slot); 338dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah if (rc) { 339f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 340f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 341dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return rc; 342dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 344dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return(rc); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 34926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * remove_board - Turns off slot and LEDs 35026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @p_slot: target &slot 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 352ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int remove_board(struct slot *p_slot) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3542178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah struct controller *ctrl = p_slot->ctrl; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 hp_slot; 356ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc; 35770b6091946ab486c4dab8abeb4a3fc2bf7d3e7feRajesh Shah 3582178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (shpchp_unconfigure_device(p_slot)) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3612178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah hp_slot = p_slot->device - ctrl->slot_device_offset; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 364be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot); 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Change status to shutdown */ 3672178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->is_a_board) 3682178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0x01; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off slot, turn on Amber LED, turn off Green LED */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->slot_disable(p_slot); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 373f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 374f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3779f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 380be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Set Attention command failed\n"); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3842178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->pwr_save = 0; 3852178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 0; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestruct pushbutton_work_info { 392a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot; 393a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct work_struct work; 394a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige}; 395a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 39726e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * shpchp_pushbutton_thread - handle pushbutton events 39826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @work: &struct work_struct to be handled 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Scheduled procedure to handle blocking stuff for the pushbuttons. 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handles all pending events and exits. 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 403c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void shpchp_pushbutton_thread(struct work_struct *work) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 405c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct pushbutton_work_info *info = 406c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells container_of(work, struct pushbutton_work_info, work); 407a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot = info->p_slot; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 409a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 410a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 411a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 412a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpchp_disable_slot(p_slot); 414a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->state = STATIC_STATE; 416a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 417a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 418a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 419d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige if (shpchp_enable_slot(p_slot)) 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->green_led_off(p_slot); 421a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->state = STATIC_STATE; 423a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 424a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 425a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 426a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 427a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 428a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 429a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige kfree(info); 430a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 431a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 432e325e1f0783382298141c74737712637943c6063Kristen Carlson Accardivoid shpchp_queue_pushbutton_work(struct work_struct *work) 433a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 434c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct slot *p_slot = container_of(work, struct slot, work.work); 435a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct pushbutton_work_info *info; 436a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 437a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige info = kmalloc(sizeof(*info), GFP_KERNEL); 438a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige if (!info) { 439f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", 440f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 441a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return; 442a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 443a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige info->p_slot = p_slot; 444c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&info->work, shpchp_pushbutton_thread); 445a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 446a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 447a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 448a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 449a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWEROFF_STATE; 450a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 451a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 452a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWERON_STATE; 453a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 454a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 4556fcaf17ac7a512227112ac81c0e1a5862bab57a6Jiri Slaby kfree(info); 456a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige goto out; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 458f652e7d2916fe2fcf9e7d709aa5b7476b431e2ddBjorn Helgaas queue_work(p_slot->wq, &info->work); 459a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige out: 460a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int update_slot_info (struct slot *slot) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hotplug_slot_info *info; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!info) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_power_status(slot, &(info->power_status)); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = pci_hp_change_slot_info(slot->hotplug_slot, info); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (info); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 482a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige/* 483a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Note: This function must be called with slot->lock held 484a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 485a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic void handle_button_press_event(struct slot *p_slot) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus; 488f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 490a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 491a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 492f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 493f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige if (getstatus) { 494f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->state = BLINKINGOFF_STATE; 495227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", 496227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses slot_name(p_slot)); 497f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige } else { 498f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->state = BLINKINGON_STATE; 499227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", 500227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses slot_name(p_slot)); 501f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige } 502f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige /* blink green LED and turn off amber */ 503f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->green_led_blink(p_slot); 504f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 0); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 506f652e7d2916fe2fcf9e7d709aa5b7476b431e2ddBjorn Helgaas queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); 507a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 508a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 509a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 510a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige /* 511a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Cancel if we are still blinking; this means that we 512a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * press the attention again before the 5 sec. limit 513a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * expires to cancel hot-add or hot-remove 514a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 515f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Button cancel on Slot(%s)\n", 516f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 517a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 518a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige if (p_slot->state == BLINKINGOFF_STATE) 519a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->green_led_on(p_slot); 520a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige else 521a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->green_led_off(p_slot); 522a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 0); 523227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", 524227f06470502c4fea3d93df1f12a77e3e37f6263Ryan Desfosses slot_name(p_slot)); 525a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 526a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 527a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 528a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 529a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige /* 530a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Ignore if the slot is on power-on or power-off state; 531a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * this means that the previous attention button action 532a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * to hot-add or hot-remove is undergoing 533a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 534f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Button ignore on Slot(%s)\n", 535f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 536a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige update_slot_info(p_slot); 537a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 538a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 539f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_warn(ctrl, "Not a valid state\n"); 540a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 541a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 542a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 543a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 544c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void interrupt_event_handler(struct work_struct *work) 545a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 546c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct event_info *info = container_of(work, struct event_info, work); 547a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot = info->p_slot; 548a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 549a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 550a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (info->event_type) { 551a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case INT_BUTTON_PRESS: 552a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige handle_button_press_event(p_slot); 553f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 554f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige case INT_POWER_FAULT: 555be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__); 556f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 1); 557f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->green_led_off(p_slot); 558f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 559f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige default: 560f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige update_slot_info(p_slot); 561f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 563a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 565f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige kfree(info); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 569a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_enable_slot (struct slot *p_slot) 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus = 0; 572ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige int rc, retval = -ENODEV; 573f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if (latch closed, card present, power off) */ 5766aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar mutex_lock(&p_slot->ctrl->crit_sect); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || !getstatus) { 579f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 580ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || getstatus) { 584f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 585ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || getstatus) { 589f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already enabled on slot(%s)\n", 590f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 591ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5942178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 1; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to save the presence info for these slots */ 5972178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 5982178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); 599f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 602382a9c9adc1cd540f5b714b65db315fc1c0b553dQuentin Lambert if (((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) || 60353044f357448693f218cc4f053affe92ed414f9dKeck, David (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)) 60453044f357448693f218cc4f053affe92ed414f9dKeck, David && p_slot->ctrl->num_slots == 1) { 60553044f357448693f218cc4f053affe92ed414f9dKeck, David /* handle amd pogo errata; this must be done before enable */ 60653044f357448693f218cc4f053affe92ed414f9dKeck, David amd_pogo_errata_save_misc_reg(p_slot); 607ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = board_added(p_slot); 60853044f357448693f218cc4f053affe92ed414f9dKeck, David /* handle amd pogo errata; this must be done after enable */ 60953044f357448693f218cc4f053affe92ed414f9dKeck, David amd_pogo_errata_restore_misc_reg(p_slot); 61053044f357448693f218cc4f053affe92ed414f9dKeck, David } else 611ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = board_added(p_slot); 61253044f357448693f218cc4f053affe92ed414f9dKeck, David 613ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (retval) { 6142178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, 6152178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah &(p_slot->presence_save)); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6192178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah update_slot_info(p_slot); 620ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige out: 621ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige mutex_unlock(&p_slot->ctrl->crit_sect); 622ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige return retval; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 626a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_disable_slot (struct slot *p_slot) 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus = 0; 629ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige int rc, retval = -ENODEV; 630f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p_slot->ctrl) 633ee17fd93a5892c162b0a02d58cdfdb9c50cf8467Dely Sy return -ENODEV; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if (latch closed, card present, power on) */ 6366aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar mutex_lock(&p_slot->ctrl->crit_sect); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 638ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 639ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || !getstatus) { 640f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 641ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 643ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 644ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || getstatus) { 645f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 646ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 648ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 649ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || !getstatus) { 650be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_info(ctrl, "Already disabled on slot(%s)\n", 651f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 652ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 655ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = remove_board(p_slot); 6562178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah update_slot_info(p_slot); 657ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige out: 658ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige mutex_unlock(&p_slot->ctrl->crit_sect); 659ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige return retval; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 662a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigeint shpchp_sysfs_enable_slot(struct slot *p_slot) 663a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 664a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige int retval = -ENODEV; 665f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 666a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 667a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 668a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 669a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 670a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 671a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 672a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWERON_STATE; 673a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 674a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige retval = shpchp_enable_slot(p_slot); 675a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 676a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 677a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 678a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 679f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Slot %s is already in powering on state\n", 680f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 681a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 682a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 683a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 684f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already enabled on slot %s\n", 685f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 686a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 687a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 688f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Not a valid state on slot %s\n", 689f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 690a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 691a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 692a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 693a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 694a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return retval; 695a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 696a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 697a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigeint shpchp_sysfs_disable_slot(struct slot *p_slot) 698a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 699a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige int retval = -ENODEV; 700f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 701a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 702a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 703a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 704a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 705a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 706a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 707a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWEROFF_STATE; 708a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 709a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige retval = shpchp_disable_slot(p_slot); 710a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 711a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 712a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 713a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 714f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Slot %s is already in powering off state\n", 715f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 716a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 717a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 718a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 719f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already disabled on slot %s\n", 720f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 721a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 722a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 723f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Not a valid state on slot %s\n", 724f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 725a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 726a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 727a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 728a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 729a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return retval; 730a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 731