1 /* 2 * Standard Hot Plug Controller Driver 3 * 4 * Copyright (C) 1995,2001 Compaq Computer Corporation 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * Copyright (C) 2003-2004 Intel Corporation 8 * 9 * All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 19 * NON INFRINGEMENT. See the GNU General Public License for more 20 * details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 27 * 28 */ 29 30 #include <linux/module.h> 31 #include <linux/moduleparam.h> 32 #include <linux/kernel.h> 33 #include <linux/types.h> 34 #include <linux/pci.h> 35 #include <linux/workqueue.h> 36 #include "shpchp.h" 37 38 /* Global variables */ 39 int shpchp_debug; 40 int shpchp_poll_mode; 41 int shpchp_poll_time; 42 struct workqueue_struct *shpchp_wq; 43 44 #define DRIVER_VERSION "0.4" 45 #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 46 #define DRIVER_DESC "Standard Hot Plug PCI Controller Driver" 47 48 MODULE_AUTHOR(DRIVER_AUTHOR); 49 MODULE_DESCRIPTION(DRIVER_DESC); 50 MODULE_LICENSE("GPL"); 51 52 module_param(shpchp_debug, bool, 0644); 53 module_param(shpchp_poll_mode, bool, 0644); 54 module_param(shpchp_poll_time, int, 0644); 55 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); 56 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); 57 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); 58 59 #define SHPC_MODULE_NAME "shpchp" 60 61 static int set_attention_status (struct hotplug_slot *slot, u8 value); 62 static int enable_slot (struct hotplug_slot *slot); 63 static int disable_slot (struct hotplug_slot *slot); 64 static int get_power_status (struct hotplug_slot *slot, u8 *value); 65 static int get_attention_status (struct hotplug_slot *slot, u8 *value); 66 static int get_latch_status (struct hotplug_slot *slot, u8 *value); 67 static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 68 static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 69 static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 70 71 static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { 72 .owner = THIS_MODULE, 73 .set_attention_status = set_attention_status, 74 .enable_slot = enable_slot, 75 .disable_slot = disable_slot, 76 .get_power_status = get_power_status, 77 .get_attention_status = get_attention_status, 78 .get_latch_status = get_latch_status, 79 .get_adapter_status = get_adapter_status, 80 .get_max_bus_speed = get_max_bus_speed, 81 .get_cur_bus_speed = get_cur_bus_speed, 82 }; 83 84 /** 85 * release_slot - free up the memory used by a slot 86 * @hotplug_slot: slot to free 87 */ 88 static void release_slot(struct hotplug_slot *hotplug_slot) 89 { 90 struct slot *slot = hotplug_slot->private; 91 92 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 93 __func__, slot_name(slot)); 94 95 kfree(slot->hotplug_slot->info); 96 kfree(slot->hotplug_slot); 97 kfree(slot); 98 } 99 100 static int init_slots(struct controller *ctrl) 101 { 102 struct slot *slot; 103 struct hotplug_slot *hotplug_slot; 104 struct hotplug_slot_info *info; 105 char name[SLOT_NAME_SIZE]; 106 int retval = -ENOMEM; 107 int i; 108 109 for (i = 0; i < ctrl->num_slots; i++) { 110 slot = kzalloc(sizeof(*slot), GFP_KERNEL); 111 if (!slot) 112 goto error; 113 114 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 115 if (!hotplug_slot) 116 goto error_slot; 117 slot->hotplug_slot = hotplug_slot; 118 119 info = kzalloc(sizeof(*info), GFP_KERNEL); 120 if (!info) 121 goto error_hpslot; 122 hotplug_slot->info = info; 123 124 slot->hp_slot = i; 125 slot->ctrl = ctrl; 126 slot->bus = ctrl->pci_dev->subordinate->number; 127 slot->device = ctrl->slot_device_offset + i; 128 slot->hpc_ops = ctrl->hpc_ops; 129 slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); 130 mutex_init(&slot->lock); 131 INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); 132 133 /* register this slot with the hotplug pci core */ 134 hotplug_slot->private = slot; 135 hotplug_slot->release = &release_slot; 136 snprintf(name, SLOT_NAME_SIZE, "%d", slot->number); 137 hotplug_slot->ops = &shpchp_hotplug_slot_ops; 138 139 ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " 140 "hp_slot=%x sun=%x slot_device_offset=%x\n", 141 pci_domain_nr(ctrl->pci_dev->subordinate), 142 slot->bus, slot->device, slot->hp_slot, slot->number, 143 ctrl->slot_device_offset); 144 retval = pci_hp_register(slot->hotplug_slot, 145 ctrl->pci_dev->subordinate, slot->device, name); 146 if (retval) { 147 ctrl_err(ctrl, "pci_hp_register failed with error %d\n", 148 retval); 149 goto error_info; 150 } 151 152 get_power_status(hotplug_slot, &info->power_status); 153 get_attention_status(hotplug_slot, &info->attention_status); 154 get_latch_status(hotplug_slot, &info->latch_status); 155 get_adapter_status(hotplug_slot, &info->adapter_status); 156 157 list_add(&slot->slot_list, &ctrl->slot_list); 158 } 159 160 return 0; 161 error_info: 162 kfree(info); 163 error_hpslot: 164 kfree(hotplug_slot); 165 error_slot: 166 kfree(slot); 167 error: 168 return retval; 169 } 170 171 void cleanup_slots(struct controller *ctrl) 172 { 173 struct list_head *tmp; 174 struct list_head *next; 175 struct slot *slot; 176 177 list_for_each_safe(tmp, next, &ctrl->slot_list) { 178 slot = list_entry(tmp, struct slot, slot_list); 179 list_del(&slot->slot_list); 180 cancel_delayed_work(&slot->work); 181 flush_scheduled_work(); 182 flush_workqueue(shpchp_wq); 183 pci_hp_deregister(slot->hotplug_slot); 184 } 185 } 186 187 /* 188 * set_attention_status - Turns the Amber LED for a slot on, off or blink 189 */ 190 static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) 191 { 192 struct slot *slot = get_slot(hotplug_slot); 193 194 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 195 __func__, slot_name(slot)); 196 197 hotplug_slot->info->attention_status = status; 198 slot->hpc_ops->set_attention_status(slot, status); 199 200 return 0; 201 } 202 203 static int enable_slot (struct hotplug_slot *hotplug_slot) 204 { 205 struct slot *slot = get_slot(hotplug_slot); 206 207 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 208 __func__, slot_name(slot)); 209 210 return shpchp_sysfs_enable_slot(slot); 211 } 212 213 static int disable_slot (struct hotplug_slot *hotplug_slot) 214 { 215 struct slot *slot = get_slot(hotplug_slot); 216 217 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 218 __func__, slot_name(slot)); 219 220 return shpchp_sysfs_disable_slot(slot); 221 } 222 223 static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) 224 { 225 struct slot *slot = get_slot(hotplug_slot); 226 int retval; 227 228 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 229 __func__, slot_name(slot)); 230 231 retval = slot->hpc_ops->get_power_status(slot, value); 232 if (retval < 0) 233 *value = hotplug_slot->info->power_status; 234 235 return 0; 236 } 237 238 static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) 239 { 240 struct slot *slot = get_slot(hotplug_slot); 241 int retval; 242 243 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 244 __func__, slot_name(slot)); 245 246 retval = slot->hpc_ops->get_attention_status(slot, value); 247 if (retval < 0) 248 *value = hotplug_slot->info->attention_status; 249 250 return 0; 251 } 252 253 static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) 254 { 255 struct slot *slot = get_slot(hotplug_slot); 256 int retval; 257 258 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 259 __func__, slot_name(slot)); 260 261 retval = slot->hpc_ops->get_latch_status(slot, value); 262 if (retval < 0) 263 *value = hotplug_slot->info->latch_status; 264 265 return 0; 266 } 267 268 static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) 269 { 270 struct slot *slot = get_slot(hotplug_slot); 271 int retval; 272 273 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 274 __func__, slot_name(slot)); 275 276 retval = slot->hpc_ops->get_adapter_status(slot, value); 277 if (retval < 0) 278 *value = hotplug_slot->info->adapter_status; 279 280 return 0; 281 } 282 283 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, 284 enum pci_bus_speed *value) 285 { 286 struct slot *slot = get_slot(hotplug_slot); 287 int retval; 288 289 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 290 __func__, slot_name(slot)); 291 292 retval = slot->hpc_ops->get_max_bus_speed(slot, value); 293 if (retval < 0) 294 *value = PCI_SPEED_UNKNOWN; 295 296 return 0; 297 } 298 299 static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 300 { 301 struct slot *slot = get_slot(hotplug_slot); 302 int retval; 303 304 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 305 __func__, slot_name(slot)); 306 307 retval = slot->hpc_ops->get_cur_bus_speed(slot, value); 308 if (retval < 0) 309 *value = PCI_SPEED_UNKNOWN; 310 311 return 0; 312 } 313 314 static int is_shpc_capable(struct pci_dev *dev) 315 { 316 if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == 317 PCI_DEVICE_ID_AMD_GOLAM_7450)) 318 return 1; 319 if (!pci_find_capability(dev, PCI_CAP_ID_SHPC)) 320 return 0; 321 if (get_hp_hw_control_from_firmware(dev)) 322 return 0; 323 return 1; 324 } 325 326 static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 327 { 328 int rc; 329 struct controller *ctrl; 330 331 if (!is_shpc_capable(pdev)) 332 return -ENODEV; 333 334 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 335 if (!ctrl) { 336 dev_err(&pdev->dev, "%s: Out of memory\n", __func__); 337 goto err_out_none; 338 } 339 INIT_LIST_HEAD(&ctrl->slot_list); 340 341 rc = shpc_init(ctrl, pdev); 342 if (rc) { 343 ctrl_dbg(ctrl, "Controller initialization failed\n"); 344 goto err_out_free_ctrl; 345 } 346 347 pci_set_drvdata(pdev, ctrl); 348 349 /* Setup the slot information structures */ 350 rc = init_slots(ctrl); 351 if (rc) { 352 ctrl_err(ctrl, "Slot initialization failed\n"); 353 goto err_out_release_ctlr; 354 } 355 356 rc = shpchp_create_ctrl_files(ctrl); 357 if (rc) 358 goto err_cleanup_slots; 359 360 return 0; 361 362 err_cleanup_slots: 363 cleanup_slots(ctrl); 364 err_out_release_ctlr: 365 ctrl->hpc_ops->release_ctlr(ctrl); 366 err_out_free_ctrl: 367 kfree(ctrl); 368 err_out_none: 369 return -ENODEV; 370 } 371 372 static void shpc_remove(struct pci_dev *dev) 373 { 374 struct controller *ctrl = pci_get_drvdata(dev); 375 376 shpchp_remove_ctrl_files(ctrl); 377 ctrl->hpc_ops->release_ctlr(ctrl); 378 kfree(ctrl); 379 } 380 381 static struct pci_device_id shpcd_pci_tbl[] = { 382 {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, 383 { /* end: all zeroes */ } 384 }; 385 MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); 386 387 static struct pci_driver shpc_driver = { 388 .name = SHPC_MODULE_NAME, 389 .id_table = shpcd_pci_tbl, 390 .probe = shpc_probe, 391 .remove = shpc_remove, 392 }; 393 394 static int __init shpcd_init(void) 395 { 396 int retval = 0; 397 398 retval = pci_register_driver(&shpc_driver); 399 dbg("%s: pci_register_driver = %d\n", __func__, retval); 400 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 401 return retval; 402 } 403 404 static void __exit shpcd_cleanup(void) 405 { 406 dbg("unload_shpchpd()\n"); 407 pci_unregister_driver(&shpc_driver); 408 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 409 } 410 411 module_init(shpcd_init); 412 module_exit(shpcd_cleanup); 413