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 54e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0Tejun Heo queue_work(shpchp_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 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { 199f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of set bus speed mode command " 200f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "failed\n", __func__); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 206ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int fix_bus_speed(struct controller *ctrl, struct slot *pslot, 207ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, 208ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah enum pci_bus_speed msp) 2099f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige{ 210ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc = 0; 2110afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 2120afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige /* 2130afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige * If other slots on the same bus are occupied, we cannot 2140afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige * change the bus speed. 2150afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige */ 2160afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (flag) { 2170afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (asp < bsp) { 218be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Speed of bus %x and adapter %x " 219be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi "mismatch\n", bsp, asp); 2200afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = WRONG_BUS_FREQUENCY; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2220afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return rc; 2230afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige } 2240afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 2250afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (asp < msp) { 2260afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (bsp != asp) 2270afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = change_bus_speed(ctrl, pslot, asp); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2290afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (bsp != msp) 2300afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = change_bus_speed(ctrl, pslot, msp); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * board_added - Called after a board has been added to the system. 23726e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @p_slot: target &slot 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Turns power on for the board. 24026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Configures board. 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 242ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int board_added(struct slot *p_slot) 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 hp_slot; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 slots_not_empty = 0; 246ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc = 0; 2470afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige enum pci_bus_speed asp, bsp, msp; 2482178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah struct controller *ctrl = p_slot->ctrl; 249be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi struct pci_bus *parent = ctrl->pci_dev->subordinate; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2512178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah hp_slot = p_slot->device - ctrl->slot_device_offset; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, 254f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "%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)) { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (slots_not_empty) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2679f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { 269f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of set bus speed mode command" 270f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi " failed\n", __func__); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2739f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on board, blink green LED, turn off Amber LED */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { 276be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2809f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 2810afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); 2820afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (rc) { 283be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Can't get adapter speed or " 284be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi "bus mode mismatch\n"); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return WRONG_BUS_FREQUENCY; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2883749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bsp = ctrl->pci_dev->bus->cur_bus_speed; 2893749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox msp = ctrl->pci_dev->bus->max_bus_speed; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if there are other slots or devices on the same bus */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&ctrl->pci_dev->subordinate->devices)) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slots_not_empty = 1; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 295f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d," 296f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi " max_bus_speed %d\n", __func__, slots_not_empty, asp, 297f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi bsp, msp); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2990afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); 3000afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (rc) 3010afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return rc; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on board, blink green LED, turn off Amber LED */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { 305be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait for ~1 second */ 31068c0b671491088d79611fa965bbf94b3bc0024a4Kenji Kaneshige msleep(1000); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 312f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for a power fault */ 3142178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->status == 0xFF) { 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* power fault occurred, but it was benign */ 316be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "%s: Power fault\n", __func__); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = POWER_FAILURE; 3182178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0; 319dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah goto err_exit; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 322dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah if (shpchp_configure_device(p_slot)) { 323be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", 324be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi pci_domain_nr(parent), p_slot->bus, p_slot->device); 325dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah goto err_exit; 326dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah } 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3282178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0; 3292178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 0x01; 3302178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->pwr_save = 1; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 332dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah p_slot->hpc_ops->green_led_on(p_slot); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 334dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return 0; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 336dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shaherr_exit: 337dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah /* turn off slot, turn on Amber LED, turn off Green LED */ 338dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah rc = p_slot->hpc_ops->slot_disable(p_slot); 339dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah if (rc) { 340f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 341f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 342dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return rc; 343dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah } 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 345dbd7a78818d125a0ebd5507d4edb4dd5900006abRajesh Shah return(rc); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 35026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * remove_board - Turns off slot and LEDs 35126e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @p_slot: target &slot 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 353ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shahstatic int remove_board(struct slot *p_slot) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3552178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah struct controller *ctrl = p_slot->ctrl; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 hp_slot; 357ee138334d5eb5ca662b2d69228420c1ccc051e0eRajesh Shah int rc; 35870b6091946ab486c4dab8abeb4a3fc2bf7d3e7feRajesh Shah 3592178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (shpchp_unconfigure_device(p_slot)) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3622178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah hp_slot = p_slot->device - ctrl->slot_device_offset; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 365be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Change status to shutdown */ 3682178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah if (p_slot->is_a_board) 3692178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->status = 0x01; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off slot, turn on Amber LED, turn off Green LED */ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->slot_disable(p_slot); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 374f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", 375f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3789f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 381be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Issue of Set Attention command failed\n"); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3852178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->pwr_save = 0; 3862178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 0; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 392a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestruct pushbutton_work_info { 393a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot; 394a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct work_struct work; 395a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige}; 396a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 39826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * shpchp_pushbutton_thread - handle pushbutton events 39926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @work: &struct work_struct to be handled 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40126e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Scheduled procedure to handle blocking stuff for the pushbuttons. 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handles all pending events and exits. 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 404c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void shpchp_pushbutton_thread(struct work_struct *work) 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 406c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct pushbutton_work_info *info = 407c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells container_of(work, struct pushbutton_work_info, work); 408a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot = info->p_slot; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 411a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 412a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 413a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpchp_disable_slot(p_slot); 415a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->state = STATIC_STATE; 417a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 418a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 419a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 420d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige if (shpchp_enable_slot(p_slot)) 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->green_led_off(p_slot); 422a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->state = STATIC_STATE; 424a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 425a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 426a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 427a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 428a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 429a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 430a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige kfree(info); 431a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 432a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 433e325e1f0783382298141c74737712637943c6063Kristen Carlson Accardivoid shpchp_queue_pushbutton_work(struct work_struct *work) 434a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 435c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct slot *p_slot = container_of(work, struct slot, work.work); 436a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct pushbutton_work_info *info; 437a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 438a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige info = kmalloc(sizeof(*info), GFP_KERNEL); 439a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige if (!info) { 440f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", 441f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__); 442a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return; 443a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 444a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige info->p_slot = p_slot; 445c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&info->work, shpchp_pushbutton_thread); 446a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 447a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 448a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 449a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 450a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWEROFF_STATE; 451a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 452a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 453a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWERON_STATE; 454a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 455a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 4566fcaf17ac7a512227112ac81c0e1a5862bab57a6Jiri Slaby kfree(info); 457a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige goto out; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 459e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0Tejun Heo queue_work(shpchp_ordered_wq, &info->work); 460a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige out: 461a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int update_slot_info (struct slot *slot) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hotplug_slot_info *info; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!info) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_power_status(slot, &(info->power_status)); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = pci_hp_change_slot_info(slot->hotplug_slot, info); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (info); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 483a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige/* 484a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Note: This function must be called with slot->lock held 485a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 486a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic void handle_button_press_event(struct slot *p_slot) 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus; 489f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 492a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 493f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 494f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige if (getstatus) { 495f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->state = BLINKINGOFF_STATE; 496f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "PCI slot #%s - powering off due to " 497f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "button press.\n", slot_name(p_slot)); 498f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige } else { 499f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->state = BLINKINGON_STATE; 500f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "PCI slot #%s - powering on due to " 501f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "button press.\n", slot_name(p_slot)); 502f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige } 503f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige /* blink green LED and turn off amber */ 504f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->green_led_blink(p_slot); 505f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 0); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 507e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0Tejun Heo queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); 508a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 509a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 510a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 511a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige /* 512a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Cancel if we are still blinking; this means that we 513a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * press the attention again before the 5 sec. limit 514a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * expires to cancel hot-add or hot-remove 515a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 516f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Button cancel on Slot(%s)\n", 517f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 518a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 519a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige if (p_slot->state == BLINKINGOFF_STATE) 520a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->green_led_on(p_slot); 521a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige else 522a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->green_led_off(p_slot); 523a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 0); 524f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "PCI slot #%s - action canceled due to " 525f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "button press\n", slot_name(p_slot)); 526a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 527a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 528a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 529a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 530a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige /* 531a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * Ignore if the slot is on power-on or power-off state; 532a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * this means that the previous attention button action 533a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige * to hot-add or hot-remove is undergoing 534a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige */ 535f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Button ignore on Slot(%s)\n", 536f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 537a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige update_slot_info(p_slot); 538a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 539a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 540f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_warn(ctrl, "Not a valid state\n"); 541a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 542a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 543a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 544a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 545c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void interrupt_event_handler(struct work_struct *work) 546a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 547c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct event_info *info = container_of(work, struct event_info, work); 548a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige struct slot *p_slot = info->p_slot; 549a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 550a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 551a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (info->event_type) { 552a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case INT_BUTTON_PRESS: 553a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige handle_button_press_event(p_slot); 554f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 555f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige case INT_POWER_FAULT: 556be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__); 557f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->set_attention_status(p_slot, 1); 558f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige p_slot->hpc_ops->green_led_off(p_slot); 559f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 560f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige default: 561f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige update_slot_info(p_slot); 562f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige break; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 564a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 566f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige kfree(info); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 570a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_enable_slot (struct slot *p_slot) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus = 0; 573ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige int rc, retval = -ENODEV; 574f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if (latch closed, card present, power off) */ 5776aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar mutex_lock(&p_slot->ctrl->crit_sect); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || !getstatus) { 580f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 581ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || getstatus) { 585f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 586ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc || getstatus) { 590f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already enabled on slot(%s)\n", 591f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 592ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5952178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->is_a_board = 1; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to save the presence info for these slots */ 5982178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); 5992178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); 600f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 60353044f357448693f218cc4f053affe92ed414f9dKeck, David if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) || 60453044f357448693f218cc4f053affe92ed414f9dKeck, David (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)) 60553044f357448693f218cc4f053affe92ed414f9dKeck, David && p_slot->ctrl->num_slots == 1) { 60653044f357448693f218cc4f053affe92ed414f9dKeck, David /* handle amd pogo errata; this must be done before enable */ 60753044f357448693f218cc4f053affe92ed414f9dKeck, David amd_pogo_errata_save_misc_reg(p_slot); 608ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = board_added(p_slot); 60953044f357448693f218cc4f053affe92ed414f9dKeck, David /* handle amd pogo errata; this must be done after enable */ 61053044f357448693f218cc4f053affe92ed414f9dKeck, David amd_pogo_errata_restore_misc_reg(p_slot); 61153044f357448693f218cc4f053affe92ed414f9dKeck, David } else 612ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = board_added(p_slot); 61353044f357448693f218cc4f053affe92ed414f9dKeck, David 614ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (retval) { 6152178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah p_slot->hpc_ops->get_adapter_status(p_slot, 6162178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah &(p_slot->presence_save)); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6202178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah update_slot_info(p_slot); 621ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige out: 622ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige mutex_unlock(&p_slot->ctrl->crit_sect); 623ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige return retval; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 627a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigestatic int shpchp_disable_slot (struct slot *p_slot) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 getstatus = 0; 630ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige int rc, retval = -ENODEV; 631f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p_slot->ctrl) 634ee17fd93a5892c162b0a02d58cdfdb9c50cf8467Dely Sy return -ENODEV; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if (latch closed, card present, power on) */ 6376aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar mutex_lock(&p_slot->ctrl->crit_sect); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 639ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 640ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || !getstatus) { 641f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 642ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 644ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 645ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || getstatus) { 646f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); 647ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 649ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 650ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige if (rc || !getstatus) { 651be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_info(ctrl, "Already disabled on slot(%s)\n", 652f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 653ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige goto out; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 656ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige retval = remove_board(p_slot); 6572178bfad9ccb0cbeb79599dd1dc349dd4567aa49Rajesh Shah update_slot_info(p_slot); 658ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige out: 659ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige mutex_unlock(&p_slot->ctrl->crit_sect); 660ef3be54777901e570185089f21fbe4498453f67eKenji Kaneshige return retval; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 663a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigeint shpchp_sysfs_enable_slot(struct slot *p_slot) 664a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 665a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige int retval = -ENODEV; 666f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 667a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 668a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 669a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 670a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 671a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 672a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 673a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWERON_STATE; 674a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 675a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige retval = shpchp_enable_slot(p_slot); 676a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 677a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 678a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 679a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 680f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Slot %s is already in powering on state\n", 681f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 682a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 683a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 684a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 685f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already enabled on slot %s\n", 686f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 687a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 688a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 689f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Not a valid state on slot %s\n", 690f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 691a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 692a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 693a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 694a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 695a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return retval; 696a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 697a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 698a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshigeint shpchp_sysfs_disable_slot(struct slot *p_slot) 699a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige{ 700a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige int retval = -ENODEV; 701f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi struct controller *ctrl = p_slot->ctrl; 702a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 703a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 704a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige switch (p_slot->state) { 705a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGOFF_STATE: 706a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige cancel_delayed_work(&p_slot->work); 707a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case STATIC_STATE: 708a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = POWEROFF_STATE; 709a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 710a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige retval = shpchp_disable_slot(p_slot); 711a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_lock(&p_slot->lock); 712a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige p_slot->state = STATIC_STATE; 713a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 714a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWEROFF_STATE: 715f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Slot %s is already in powering off state\n", 716f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 717a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 718a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case BLINKINGON_STATE: 719a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige case POWERON_STATE: 720f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Already disabled on slot %s\n", 721f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 722a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 723a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige default: 724f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Not a valid state on slot %s\n", 725f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi slot_name(p_slot)); 726a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige break; 727a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige } 728a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige mutex_unlock(&p_slot->lock); 729a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige 730a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige return retval; 731a246fa4e9f0f1b5096a1cad0659d22fb10fb3732Kenji Kaneshige} 732