diff options
| author | rajesh.shah@intel.com <rajesh.shah@intel.com> | 2005-10-13 15:05:41 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 18:37:00 -0400 |
| commit | 2178bfad9ccb0cbeb79599dd1dc349dd4567aa49 (patch) | |
| tree | 9a58ee4a73e36b31edd8b5660966403d7c6c5562 | |
| parent | 70b6091946ab486c4dab8abeb4a3fc2bf7d3e7fe (diff) | |
[PATCH] shpchp: remove redundant data structures
State information is currently stored in per-slot as well as
per-pci-function data structures in shpchp. There's a lot of
overlap in the information kept, and some of it is never used.
This patch consolidates the state information to per-slot and
eliminates unused data structures. The biggest change is to
eliminate the pci_func structure and the code around managing
its lists.
Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/pci/hotplug/shpchp.h | 35 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 20 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 405 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 27 |
4 files changed, 63 insertions, 424 deletions
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5e99260987e8..052c11f14a79 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -52,34 +52,18 @@ extern int shpchp_debug; | |||
| 52 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 52 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
| 53 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 53 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
| 54 | 54 | ||
| 55 | struct pci_func { | ||
| 56 | struct pci_func *next; | ||
| 57 | u8 bus; | ||
| 58 | u8 device; | ||
| 59 | u8 function; | ||
| 60 | u8 is_a_board; | ||
| 61 | u16 status; | ||
| 62 | u8 configured; | ||
| 63 | u8 switch_save; | ||
| 64 | u8 presence_save; | ||
| 65 | u8 pwr_save; | ||
| 66 | struct pci_dev* pci_dev; | ||
| 67 | }; | ||
| 68 | |||
| 69 | #define SLOT_MAGIC 0x67267321 | 55 | #define SLOT_MAGIC 0x67267321 |
| 70 | struct slot { | 56 | struct slot { |
| 71 | u32 magic; | 57 | u32 magic; |
| 72 | struct slot *next; | 58 | struct slot *next; |
| 73 | u8 bus; | 59 | u8 bus; |
| 74 | u8 device; | 60 | u8 device; |
| 61 | u16 status; | ||
| 75 | u32 number; | 62 | u32 number; |
| 76 | u8 is_a_board; | 63 | u8 is_a_board; |
| 77 | u8 configured; | ||
| 78 | u8 state; | 64 | u8 state; |
| 79 | u8 switch_save; | ||
| 80 | u8 presence_save; | 65 | u8 presence_save; |
| 81 | u32 capabilities; | 66 | u8 pwr_save; |
| 82 | u16 reserved2; | ||
| 83 | struct timer_list task_event; | 67 | struct timer_list task_event; |
| 84 | u8 hp_slot; | 68 | u8 hp_slot; |
| 85 | struct controller *ctrl; | 69 | struct controller *ctrl; |
| @@ -106,19 +90,14 @@ struct controller { | |||
| 106 | struct hpc_ops *hpc_ops; | 90 | struct hpc_ops *hpc_ops; |
| 107 | wait_queue_head_t queue; /* sleep & wake process */ | 91 | wait_queue_head_t queue; /* sleep & wake process */ |
| 108 | u8 next_event; | 92 | u8 next_event; |
| 109 | u8 seg; | ||
| 110 | u8 bus; | 93 | u8 bus; |
| 111 | u8 device; | 94 | u8 device; |
| 112 | u8 function; | 95 | u8 function; |
| 113 | u8 rev; | ||
| 114 | u8 slot_device_offset; | 96 | u8 slot_device_offset; |
| 115 | u8 add_support; | 97 | u8 add_support; |
| 116 | enum pci_bus_speed speed; | 98 | enum pci_bus_speed speed; |
| 117 | u32 first_slot; /* First physical slot number */ | 99 | u32 first_slot; /* First physical slot number */ |
| 118 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ | 100 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ |
| 119 | u8 push_flag; | ||
| 120 | u16 ctlrcap; | ||
| 121 | u16 vendor_id; | ||
| 122 | }; | 101 | }; |
| 123 | 102 | ||
| 124 | struct hotplug_params { | 103 | struct hotplug_params { |
| @@ -169,13 +148,9 @@ struct hotplug_params { | |||
| 169 | * error Messages | 148 | * error Messages |
| 170 | */ | 149 | */ |
| 171 | #define msg_initialization_err "Initialization failure, error=%d\n" | 150 | #define msg_initialization_err "Initialization failure, error=%d\n" |
| 172 | #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" | ||
| 173 | #define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n" | ||
| 174 | #define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n" | ||
| 175 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" | 151 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" |
| 176 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" | 152 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" |
| 177 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" | 153 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" |
| 178 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | ||
| 179 | 154 | ||
| 180 | /* sysfs functions for the hotplug controller info */ | 155 | /* sysfs functions for the hotplug controller info */ |
| 181 | extern void shpchp_create_ctrl_files (struct controller *ctrl); | 156 | extern void shpchp_create_ctrl_files (struct controller *ctrl); |
| @@ -183,8 +158,6 @@ extern void shpchp_create_ctrl_files (struct controller *ctrl); | |||
| 183 | /* controller functions */ | 158 | /* controller functions */ |
| 184 | extern int shpchp_event_start_thread(void); | 159 | extern int shpchp_event_start_thread(void); |
| 185 | extern void shpchp_event_stop_thread(void); | 160 | extern void shpchp_event_stop_thread(void); |
| 186 | extern struct pci_func *shpchp_slot_create(unsigned char busnumber); | ||
| 187 | extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index); | ||
| 188 | extern int shpchp_enable_slot(struct slot *slot); | 161 | extern int shpchp_enable_slot(struct slot *slot); |
| 189 | extern int shpchp_disable_slot(struct slot *slot); | 162 | extern int shpchp_disable_slot(struct slot *slot); |
| 190 | 163 | ||
| @@ -195,9 +168,8 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); | |||
| 195 | 168 | ||
| 196 | /* pci functions */ | 169 | /* pci functions */ |
| 197 | extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); | 170 | extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); |
| 198 | extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot); | ||
| 199 | extern int shpchp_configure_device(struct slot *p_slot); | 171 | extern int shpchp_configure_device(struct slot *p_slot); |
| 200 | extern int shpchp_unconfigure_device(struct pci_func* func); | 172 | extern int shpchp_unconfigure_device(struct slot *p_slot); |
| 201 | extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); | 173 | extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); |
| 202 | extern void get_hp_params_from_firmware(struct pci_dev *dev, | 174 | extern void get_hp_params_from_firmware(struct pci_dev *dev, |
| 203 | struct hotplug_params *hpp); | 175 | struct hotplug_params *hpp); |
| @@ -207,7 +179,6 @@ extern int shpchprm_get_physical_slot_number(struct controller *ctrl, | |||
| 207 | 179 | ||
| 208 | /* Global variables */ | 180 | /* Global variables */ |
| 209 | extern struct controller *shpchp_ctrl_list; | 181 | extern struct controller *shpchp_ctrl_list; |
| 210 | extern struct pci_func *shpchp_slot_list[256]; | ||
| 211 | 182 | ||
| 212 | struct ctrl_reg { | 183 | struct ctrl_reg { |
| 213 | volatile u32 base_offset; | 184 | volatile u32 base_offset; |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 5d4fc28969d0..b54edccbf2cc 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
| @@ -45,7 +45,6 @@ int shpchp_debug; | |||
| 45 | int shpchp_poll_mode; | 45 | int shpchp_poll_mode; |
| 46 | int shpchp_poll_time; | 46 | int shpchp_poll_time; |
| 47 | struct controller *shpchp_ctrl_list; /* = NULL */ | 47 | struct controller *shpchp_ctrl_list; /* = NULL */ |
| 48 | struct pci_func *shpchp_slot_list[256]; | ||
| 49 | 48 | ||
| 50 | #define DRIVER_VERSION "0.4" | 49 | #define DRIVER_VERSION "0.4" |
| 51 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 50 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
| @@ -475,7 +474,6 @@ err_out_none: | |||
| 475 | 474 | ||
| 476 | static int shpc_start_thread(void) | 475 | static int shpc_start_thread(void) |
| 477 | { | 476 | { |
| 478 | int loop; | ||
| 479 | int retval = 0; | 477 | int retval = 0; |
| 480 | 478 | ||
| 481 | dbg("Initialize + Start the notification/polling mechanism \n"); | 479 | dbg("Initialize + Start the notification/polling mechanism \n"); |
| @@ -486,20 +484,11 @@ static int shpc_start_thread(void) | |||
| 486 | return retval; | 484 | return retval; |
| 487 | } | 485 | } |
| 488 | 486 | ||
| 489 | dbg("Initialize slot lists\n"); | ||
| 490 | /* One slot list for each bus in the system */ | ||
| 491 | for (loop = 0; loop < 256; loop++) { | ||
| 492 | shpchp_slot_list[loop] = NULL; | ||
| 493 | } | ||
| 494 | |||
| 495 | return retval; | 487 | return retval; |
| 496 | } | 488 | } |
| 497 | 489 | ||
| 498 | static void __exit unload_shpchpd(void) | 490 | static void __exit unload_shpchpd(void) |
| 499 | { | 491 | { |
| 500 | struct pci_func *next; | ||
| 501 | struct pci_func *TempSlot; | ||
| 502 | int loop; | ||
| 503 | struct controller *ctrl; | 492 | struct controller *ctrl; |
| 504 | struct controller *tctrl; | 493 | struct controller *tctrl; |
| 505 | 494 | ||
| @@ -519,15 +508,6 @@ static void __exit unload_shpchpd(void) | |||
| 519 | kfree(tctrl); | 508 | kfree(tctrl); |
| 520 | } | 509 | } |
| 521 | 510 | ||
| 522 | for (loop = 0; loop < 256; loop++) { | ||
| 523 | next = shpchp_slot_list[loop]; | ||
| 524 | while (next != NULL) { | ||
| 525 | TempSlot = next; | ||
| 526 | next = next->next; | ||
| 527 | kfree(TempSlot); | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | /* Stop the notification mechanism */ | 511 | /* Stop the notification mechanism */ |
| 532 | shpchp_event_stop_thread(); | 512 | shpchp_event_stop_thread(); |
| 533 | 513 | ||
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index c55103f3cebd..b6fde3565e55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
| @@ -54,19 +54,16 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 54 | struct slot *p_slot; | 54 | struct slot *p_slot; |
| 55 | u8 rc = 0; | 55 | u8 rc = 0; |
| 56 | u8 getstatus; | 56 | u8 getstatus; |
| 57 | struct pci_func *func; | ||
| 58 | struct event_info *taskInfo; | 57 | struct event_info *taskInfo; |
| 59 | 58 | ||
| 60 | /* Attention Button Change */ | 59 | /* Attention Button Change */ |
| 61 | dbg("shpchp: Attention button interrupt received.\n"); | 60 | dbg("shpchp: Attention button interrupt received.\n"); |
| 62 | 61 | ||
| 63 | func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 64 | |||
| 65 | /* This is the structure that tells the worker thread what to do */ | 62 | /* This is the structure that tells the worker thread what to do */ |
| 66 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 63 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
| 67 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 64 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 68 | 65 | ||
| 69 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 66 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| 70 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 67 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 71 | 68 | ||
| 72 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 69 | ctrl->next_event = (ctrl->next_event + 1) % 10; |
| @@ -111,14 +108,11 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 111 | struct slot *p_slot; | 108 | struct slot *p_slot; |
| 112 | u8 rc = 0; | 109 | u8 rc = 0; |
| 113 | u8 getstatus; | 110 | u8 getstatus; |
| 114 | struct pci_func *func; | ||
| 115 | struct event_info *taskInfo; | 111 | struct event_info *taskInfo; |
| 116 | 112 | ||
| 117 | /* Switch Change */ | 113 | /* Switch Change */ |
| 118 | dbg("shpchp: Switch interrupt received.\n"); | 114 | dbg("shpchp: Switch interrupt received.\n"); |
| 119 | 115 | ||
| 120 | func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 121 | |||
| 122 | /* This is the structure that tells the worker thread | 116 | /* This is the structure that tells the worker thread |
| 123 | * what to do | 117 | * what to do |
| 124 | */ | 118 | */ |
| @@ -128,19 +122,18 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 128 | 122 | ||
| 129 | rc++; | 123 | rc++; |
| 130 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 124 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 131 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 125 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| 132 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 126 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 133 | dbg("%s: Card present %x Power status %x\n", __FUNCTION__, | 127 | dbg("%s: Card present %x Power status %x\n", __FUNCTION__, |
| 134 | func->presence_save, func->pwr_save); | 128 | p_slot->presence_save, p_slot->pwr_save); |
| 135 | 129 | ||
| 136 | if (getstatus) { | 130 | if (getstatus) { |
| 137 | /* | 131 | /* |
| 138 | * Switch opened | 132 | * Switch opened |
| 139 | */ | 133 | */ |
| 140 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 134 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 141 | func->switch_save = 0; | ||
| 142 | taskInfo->event_type = INT_SWITCH_OPEN; | 135 | taskInfo->event_type = INT_SWITCH_OPEN; |
| 143 | if (func->pwr_save && func->presence_save) { | 136 | if (p_slot->pwr_save && p_slot->presence_save) { |
| 144 | taskInfo->event_type = INT_POWER_FAULT; | 137 | taskInfo->event_type = INT_POWER_FAULT; |
| 145 | err("Surprise Removal of card\n"); | 138 | err("Surprise Removal of card\n"); |
| 146 | } | 139 | } |
| @@ -149,7 +142,6 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 149 | * Switch closed | 142 | * Switch closed |
| 150 | */ | 143 | */ |
| 151 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 144 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 152 | func->switch_save = 0x10; | ||
| 153 | taskInfo->event_type = INT_SWITCH_CLOSE; | 145 | taskInfo->event_type = INT_SWITCH_CLOSE; |
| 154 | } | 146 | } |
| 155 | 147 | ||
| @@ -165,14 +157,11 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 165 | struct slot *p_slot; | 157 | struct slot *p_slot; |
| 166 | u8 rc = 0; | 158 | u8 rc = 0; |
| 167 | /*u8 temp_byte;*/ | 159 | /*u8 temp_byte;*/ |
| 168 | struct pci_func *func; | ||
| 169 | struct event_info *taskInfo; | 160 | struct event_info *taskInfo; |
| 170 | 161 | ||
| 171 | /* Presence Change */ | 162 | /* Presence Change */ |
| 172 | dbg("shpchp: Presence/Notify input change.\n"); | 163 | dbg("shpchp: Presence/Notify input change.\n"); |
| 173 | 164 | ||
| 174 | func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 175 | |||
| 176 | /* This is the structure that tells the worker thread | 165 | /* This is the structure that tells the worker thread |
| 177 | * what to do | 166 | * what to do |
| 178 | */ | 167 | */ |
| @@ -186,8 +175,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 186 | /* | 175 | /* |
| 187 | * Save the presence state | 176 | * Save the presence state |
| 188 | */ | 177 | */ |
| 189 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 178 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| 190 | if (func->presence_save) { | 179 | if (p_slot->presence_save) { |
| 191 | /* | 180 | /* |
| 192 | * Card Present | 181 | * Card Present |
| 193 | */ | 182 | */ |
| @@ -212,14 +201,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 212 | struct controller *ctrl = (struct controller *) inst_id; | 201 | struct controller *ctrl = (struct controller *) inst_id; |
| 213 | struct slot *p_slot; | 202 | struct slot *p_slot; |
| 214 | u8 rc = 0; | 203 | u8 rc = 0; |
| 215 | struct pci_func *func; | ||
| 216 | struct event_info *taskInfo; | 204 | struct event_info *taskInfo; |
| 217 | 205 | ||
| 218 | /* Power fault */ | 206 | /* Power fault */ |
| 219 | dbg("shpchp: Power fault interrupt received.\n"); | 207 | dbg("shpchp: Power fault interrupt received.\n"); |
| 220 | 208 | ||
| 221 | func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 222 | |||
| 223 | /* This is the structure that tells the worker thread | 209 | /* This is the structure that tells the worker thread |
| 224 | * what to do | 210 | * what to do |
| 225 | */ | 211 | */ |
| @@ -235,7 +221,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 235 | * Power fault Cleared | 221 | * Power fault Cleared |
| 236 | */ | 222 | */ |
| 237 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 223 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 238 | func->status = 0x00; | 224 | p_slot->status = 0x00; |
| 239 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 225 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
| 240 | } else { | 226 | } else { |
| 241 | /* | 227 | /* |
| @@ -244,7 +230,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 244 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 230 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 245 | taskInfo->event_type = INT_POWER_FAULT; | 231 | taskInfo->event_type = INT_POWER_FAULT; |
| 246 | /* set power fault status for this board */ | 232 | /* set power fault status for this board */ |
| 247 | func->status = 0xFF; | 233 | p_slot->status = 0xFF; |
| 248 | info("power fault bit %x set\n", hp_slot); | 234 | info("power fault bit %x set\n", hp_slot); |
| 249 | } | 235 | } |
| 250 | if (rc) | 236 | if (rc) |
| @@ -253,179 +239,6 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 253 | return rc; | 239 | return rc; |
| 254 | } | 240 | } |
| 255 | 241 | ||
| 256 | /** | ||
| 257 | * shpchp_slot_create - Creates a node and adds it to the proper bus. | ||
| 258 | * @busnumber - bus where new node is to be located | ||
| 259 | * | ||
| 260 | * Returns pointer to the new node or NULL if unsuccessful | ||
| 261 | */ | ||
| 262 | struct pci_func *shpchp_slot_create(u8 busnumber) | ||
| 263 | { | ||
| 264 | struct pci_func *new_slot; | ||
| 265 | struct pci_func *next; | ||
| 266 | |||
| 267 | new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); | ||
| 268 | |||
| 269 | if (new_slot == NULL) { | ||
| 270 | return(new_slot); | ||
| 271 | } | ||
| 272 | |||
| 273 | memset(new_slot, 0, sizeof(struct pci_func)); | ||
| 274 | |||
| 275 | new_slot->next = NULL; | ||
| 276 | new_slot->configured = 1; | ||
| 277 | |||
| 278 | if (shpchp_slot_list[busnumber] == NULL) { | ||
| 279 | shpchp_slot_list[busnumber] = new_slot; | ||
| 280 | } else { | ||
| 281 | next = shpchp_slot_list[busnumber]; | ||
| 282 | while (next->next != NULL) | ||
| 283 | next = next->next; | ||
| 284 | next->next = new_slot; | ||
| 285 | } | ||
| 286 | return(new_slot); | ||
| 287 | } | ||
| 288 | |||
| 289 | |||
| 290 | /* | ||
| 291 | * slot_remove - Removes a node from the linked list of slots. | ||
| 292 | * @old_slot: slot to remove | ||
| 293 | * | ||
| 294 | * Returns 0 if successful, !0 otherwise. | ||
| 295 | */ | ||
| 296 | static int slot_remove(struct pci_func * old_slot) | ||
| 297 | { | ||
| 298 | struct pci_func *next; | ||
| 299 | |||
| 300 | if (old_slot == NULL) | ||
| 301 | return(1); | ||
| 302 | |||
| 303 | next = shpchp_slot_list[old_slot->bus]; | ||
| 304 | |||
| 305 | if (next == NULL) { | ||
| 306 | return(1); | ||
| 307 | } | ||
| 308 | |||
| 309 | if (next == old_slot) { | ||
| 310 | shpchp_slot_list[old_slot->bus] = old_slot->next; | ||
| 311 | kfree(old_slot); | ||
| 312 | return(0); | ||
| 313 | } | ||
| 314 | |||
| 315 | while ((next->next != old_slot) && (next->next != NULL)) { | ||
| 316 | next = next->next; | ||
| 317 | } | ||
| 318 | |||
| 319 | if (next->next == old_slot) { | ||
| 320 | next->next = old_slot->next; | ||
| 321 | kfree(old_slot); | ||
| 322 | return(0); | ||
| 323 | } else | ||
| 324 | return(2); | ||
| 325 | } | ||
| 326 | |||
| 327 | |||
| 328 | /** | ||
| 329 | * bridge_slot_remove - Removes a node from the linked list of slots. | ||
| 330 | * @bridge: bridge to remove | ||
| 331 | * @secondaryBus: secondary PCI bus number for bridge being removed | ||
| 332 | * @subordinateBus: subordinate PCI bus number for bridge being removed | ||
| 333 | * | ||
| 334 | * Returns 0 if successful, !0 otherwise. | ||
| 335 | */ | ||
| 336 | static int bridge_slot_remove(struct pci_func *bridge, u8 secondaryBus, | ||
| 337 | u8 subordinateBus) | ||
| 338 | { | ||
| 339 | u8 tempBus; | ||
| 340 | struct pci_func *next; | ||
| 341 | |||
| 342 | if (bridge == NULL) | ||
| 343 | return(1); | ||
| 344 | |||
| 345 | for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { | ||
| 346 | next = shpchp_slot_list[tempBus]; | ||
| 347 | |||
| 348 | while (!slot_remove(next)) { | ||
| 349 | next = shpchp_slot_list[tempBus]; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | next = shpchp_slot_list[bridge->bus]; | ||
| 354 | |||
| 355 | if (next == NULL) { | ||
| 356 | return(1); | ||
| 357 | } | ||
| 358 | |||
| 359 | if (next == bridge) { | ||
| 360 | shpchp_slot_list[bridge->bus] = bridge->next; | ||
| 361 | kfree(bridge); | ||
| 362 | return(0); | ||
| 363 | } | ||
| 364 | |||
| 365 | while ((next->next != bridge) && (next->next != NULL)) { | ||
| 366 | next = next->next; | ||
| 367 | } | ||
| 368 | |||
| 369 | if (next->next == bridge) { | ||
| 370 | next->next = bridge->next; | ||
| 371 | kfree(bridge); | ||
| 372 | return(0); | ||
| 373 | } else | ||
| 374 | return(2); | ||
| 375 | } | ||
| 376 | |||
| 377 | |||
| 378 | /** | ||
| 379 | * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed | ||
| 380 | * @bus: bus to find | ||
| 381 | * @device: device to find | ||
| 382 | * @index: is 0 for first function found, 1 for the second... | ||
| 383 | * | ||
| 384 | * Returns pointer to the node if successful, %NULL otherwise. | ||
| 385 | */ | ||
| 386 | struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index) | ||
| 387 | { | ||
| 388 | int found = -1; | ||
| 389 | struct pci_func *func; | ||
| 390 | |||
| 391 | func = shpchp_slot_list[bus]; | ||
| 392 | |||
| 393 | if ((func == NULL) || ((func->device == device) && (index == 0))) | ||
| 394 | return(func); | ||
| 395 | |||
| 396 | if (func->device == device) | ||
| 397 | found++; | ||
| 398 | |||
| 399 | while (func->next != NULL) { | ||
| 400 | func = func->next; | ||
| 401 | |||
| 402 | if (func->device == device) | ||
| 403 | found++; | ||
| 404 | |||
| 405 | if (found == index) | ||
| 406 | return(func); | ||
| 407 | } | ||
| 408 | |||
| 409 | return(NULL); | ||
| 410 | } | ||
| 411 | |||
| 412 | static int is_bridge(struct pci_func *func, struct controller *ctrl) | ||
| 413 | { | ||
| 414 | u8 hdr_type; | ||
| 415 | struct pci_bus *bus = ctrl->pci_dev->subordinate; | ||
| 416 | |||
| 417 | /* | ||
| 418 | * Note: device may have just been hot-added and not yet scanned | ||
| 419 | * by the pci core, so its pci_dev structure may not exist yet | ||
| 420 | */ | ||
| 421 | pci_bus_read_config_byte(bus, PCI_DEVFN(func->device, func->function), | ||
| 422 | PCI_HEADER_TYPE, &hdr_type); | ||
| 423 | if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) | ||
| 424 | return 1; | ||
| 425 | else | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | /* The following routines constitute the bulk of the | 242 | /* The following routines constitute the bulk of the |
| 430 | hotplug controller logic | 243 | hotplug controller logic |
| 431 | */ | 244 | */ |
| @@ -495,19 +308,20 @@ enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp) | |||
| 495 | * Configures board | 308 | * Configures board |
| 496 | * | 309 | * |
| 497 | */ | 310 | */ |
| 498 | static u32 board_added(struct pci_func * func, struct controller * ctrl) | 311 | static u32 board_added(struct slot *p_slot) |
| 499 | { | 312 | { |
| 500 | u8 hp_slot; | 313 | u8 hp_slot; |
| 501 | u8 slots_not_empty = 0; | 314 | u8 slots_not_empty = 0; |
| 502 | u32 rc = 0; | 315 | u32 rc = 0; |
| 503 | struct slot *p_slot; | ||
| 504 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; | 316 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; |
| 505 | u8 pi, mode; | 317 | u8 pi, mode; |
| 318 | struct controller *ctrl = p_slot->ctrl; | ||
| 506 | 319 | ||
| 507 | p_slot = shpchp_find_slot(ctrl, func->device); | 320 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| 508 | hp_slot = func->device - ctrl->slot_device_offset; | ||
| 509 | 321 | ||
| 510 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); | 322 | dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", |
| 323 | __FUNCTION__, p_slot->device, | ||
| 324 | ctrl->slot_device_offset, hp_slot); | ||
| 511 | 325 | ||
| 512 | /* Wait for exclusive access to hardware */ | 326 | /* Wait for exclusive access to hardware */ |
| 513 | down(&ctrl->crit_sect); | 327 | down(&ctrl->crit_sect); |
| @@ -699,13 +513,13 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
| 699 | wait_for_ctrl_irq (ctrl); | 513 | wait_for_ctrl_irq (ctrl); |
| 700 | dbg("%s: after long_delay\n", __FUNCTION__); | 514 | dbg("%s: after long_delay\n", __FUNCTION__); |
| 701 | 515 | ||
| 702 | dbg("%s: func status = %x\n", __FUNCTION__, func->status); | 516 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); |
| 703 | /* Check for a power fault */ | 517 | /* Check for a power fault */ |
| 704 | if (func->status == 0xFF) { | 518 | if (p_slot->status == 0xFF) { |
| 705 | /* power fault occurred, but it was benign */ | 519 | /* power fault occurred, but it was benign */ |
| 706 | dbg("%s: power fault\n", __FUNCTION__); | 520 | dbg("%s: power fault\n", __FUNCTION__); |
| 707 | rc = POWER_FAILURE; | 521 | rc = POWER_FAILURE; |
| 708 | func->status = 0; | 522 | p_slot->status = 0; |
| 709 | goto err_exit; | 523 | goto err_exit; |
| 710 | } | 524 | } |
| 711 | 525 | ||
| @@ -715,10 +529,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
| 715 | goto err_exit; | 529 | goto err_exit; |
| 716 | } | 530 | } |
| 717 | 531 | ||
| 718 | func->status = 0; | 532 | p_slot->status = 0; |
| 719 | func->switch_save = 0x10; | 533 | p_slot->is_a_board = 0x01; |
| 720 | func->is_a_board = 0x01; | 534 | p_slot->pwr_save = 1; |
| 721 | func->pwr_save = 1; | ||
| 722 | 535 | ||
| 723 | /* Wait for exclusive access to hardware */ | 536 | /* Wait for exclusive access to hardware */ |
| 724 | down(&ctrl->crit_sect); | 537 | down(&ctrl->crit_sect); |
| @@ -767,38 +580,23 @@ err_exit: | |||
| 767 | * remove_board - Turns off slot and LED's | 580 | * remove_board - Turns off slot and LED's |
| 768 | * | 581 | * |
| 769 | */ | 582 | */ |
| 770 | static u32 remove_board(struct pci_func *func, struct controller *ctrl) | 583 | static u32 remove_board(struct slot *p_slot) |
| 771 | { | 584 | { |
| 772 | u8 device; | 585 | struct controller *ctrl = p_slot->ctrl; |
| 773 | u8 hp_slot; | 586 | u8 hp_slot; |
| 774 | u32 rc; | 587 | u32 rc; |
| 775 | struct slot *p_slot; | ||
| 776 | u8 secondary = 0, subordinate = 0; | ||
| 777 | int remove_bridge; | ||
| 778 | |||
| 779 | if (func == NULL) | ||
| 780 | return(1); | ||
| 781 | |||
| 782 | if ((remove_bridge = is_bridge(func, ctrl))) { | ||
| 783 | /* Stash away bus information before we destroy it */ | ||
| 784 | secondary = func->pci_dev->subordinate->secondary; | ||
| 785 | subordinate = func->pci_dev->subordinate->subordinate; | ||
| 786 | } | ||
| 787 | 588 | ||
| 788 | if (shpchp_unconfigure_device(func)) | 589 | if (shpchp_unconfigure_device(p_slot)) |
| 789 | return(1); | 590 | return(1); |
| 790 | 591 | ||
| 791 | device = func->device; | 592 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| 792 | |||
| 793 | hp_slot = func->device - ctrl->slot_device_offset; | ||
| 794 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 593 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 795 | 594 | ||
| 796 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 595 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
| 797 | 596 | ||
| 798 | /* Change status to shutdown */ | 597 | /* Change status to shutdown */ |
| 799 | if (func->is_a_board) | 598 | if (p_slot->is_a_board) |
| 800 | func->status = 0x01; | 599 | p_slot->status = 0x01; |
| 801 | func->configured = 0; | ||
| 802 | 600 | ||
| 803 | /* Wait for exclusive access to hardware */ | 601 | /* Wait for exclusive access to hardware */ |
| 804 | down(&ctrl->crit_sect); | 602 | down(&ctrl->crit_sect); |
| @@ -835,36 +633,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) | |||
| 835 | /* Done with exclusive hardware access */ | 633 | /* Done with exclusive hardware access */ |
| 836 | up(&ctrl->crit_sect); | 634 | up(&ctrl->crit_sect); |
| 837 | 635 | ||
| 838 | if (ctrl->add_support) { | 636 | p_slot->pwr_save = 0; |
| 839 | while (func) { | 637 | p_slot->is_a_board = 0; |
| 840 | if (remove_bridge) { | ||
| 841 | dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, | ||
| 842 | func->device, func->function); | ||
| 843 | bridge_slot_remove(func, secondary, | ||
| 844 | subordinate); | ||
| 845 | } else | ||
| 846 | dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, | ||
| 847 | func->device, func->function); | ||
| 848 | slot_remove(func); | ||
| 849 | |||
| 850 | func = shpchp_slot_find(ctrl->slot_bus, device, 0); | ||
| 851 | } | ||
| 852 | |||
| 853 | /* Setup slot structure with entry for empty slot */ | ||
| 854 | func = shpchp_slot_create(ctrl->slot_bus); | ||
| 855 | |||
| 856 | if (func == NULL) { | ||
| 857 | return(1); | ||
| 858 | } | ||
| 859 | |||
| 860 | func->bus = ctrl->slot_bus; | ||
| 861 | func->device = device; | ||
| 862 | func->function = 0; | ||
| 863 | func->configured = 0; | ||
| 864 | func->switch_save = 0x10; | ||
| 865 | func->pwr_save = 0; | ||
| 866 | func->is_a_board = 0; | ||
| 867 | } | ||
| 868 | 638 | ||
| 869 | return 0; | 639 | return 0; |
| 870 | } | 640 | } |
| @@ -1006,7 +776,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 1006 | { | 776 | { |
| 1007 | int loop = 0; | 777 | int loop = 0; |
| 1008 | int change = 1; | 778 | int change = 1; |
| 1009 | struct pci_func *func; | ||
| 1010 | u8 hp_slot; | 779 | u8 hp_slot; |
| 1011 | u8 getstatus; | 780 | u8 getstatus; |
| 1012 | struct slot *p_slot; | 781 | struct slot *p_slot; |
| @@ -1021,11 +790,10 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 1021 | ctrl->event_queue[loop].event_type); | 790 | ctrl->event_queue[loop].event_type); |
| 1022 | hp_slot = ctrl->event_queue[loop].hp_slot; | 791 | hp_slot = ctrl->event_queue[loop].hp_slot; |
| 1023 | 792 | ||
| 1024 | func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 1025 | |||
| 1026 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 793 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 1027 | 794 | ||
| 1028 | dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot); | 795 | dbg("%s: hp_slot %d, p_slot %p\n", |
| 796 | __FUNCTION__, hp_slot, p_slot); | ||
| 1029 | 797 | ||
| 1030 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 798 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { |
| 1031 | dbg("%s: button cancel\n", __FUNCTION__); | 799 | dbg("%s: button cancel\n", __FUNCTION__); |
| @@ -1147,13 +915,6 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
| 1147 | { | 915 | { |
| 1148 | u8 getstatus = 0; | 916 | u8 getstatus = 0; |
| 1149 | int rc; | 917 | int rc; |
| 1150 | struct pci_func *func; | ||
| 1151 | |||
| 1152 | func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); | ||
| 1153 | if (!func) { | ||
| 1154 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | ||
| 1155 | return -ENODEV; | ||
| 1156 | } | ||
| 1157 | 918 | ||
| 1158 | /* Check to see if (latch closed, card present, power off) */ | 919 | /* Check to see if (latch closed, card present, power off) */ |
| 1159 | down(&p_slot->ctrl->crit_sect); | 920 | down(&p_slot->ctrl->crit_sect); |
| @@ -1177,75 +938,35 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
| 1177 | } | 938 | } |
| 1178 | up(&p_slot->ctrl->crit_sect); | 939 | up(&p_slot->ctrl->crit_sect); |
| 1179 | 940 | ||
| 1180 | slot_remove(func); | 941 | p_slot->is_a_board = 1; |
| 1181 | |||
| 1182 | func = shpchp_slot_create(p_slot->bus); | ||
| 1183 | if (func == NULL) | ||
| 1184 | return -ENOMEM; | ||
| 1185 | |||
| 1186 | func->bus = p_slot->bus; | ||
| 1187 | func->device = p_slot->device; | ||
| 1188 | func->function = 0; | ||
| 1189 | func->configured = 0; | ||
| 1190 | func->is_a_board = 1; | ||
| 1191 | 942 | ||
| 1192 | /* We have to save the presence info for these slots */ | 943 | /* We have to save the presence info for these slots */ |
| 1193 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 944 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| 1194 | p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save)); | 945 | p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); |
| 1195 | dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save); | 946 | dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save); |
| 1196 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 947 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1197 | func->switch_save = !getstatus? 0x10:0; | ||
| 1198 | 948 | ||
| 1199 | rc = board_added(func, p_slot->ctrl); | 949 | rc = board_added(p_slot); |
| 1200 | if (rc) { | 950 | if (rc) { |
| 1201 | if (is_bridge(func, p_slot->ctrl)) { | 951 | p_slot->hpc_ops->get_adapter_status(p_slot, |
| 1202 | u8 secondary = func->pci_dev->subordinate->secondary; | 952 | &(p_slot->presence_save)); |
| 1203 | u8 subordinate = | ||
| 1204 | func->pci_dev->subordinate->subordinate; | ||
| 1205 | bridge_slot_remove(func, secondary, subordinate); | ||
| 1206 | } else | ||
| 1207 | slot_remove(func); | ||
| 1208 | |||
| 1209 | /* Setup slot structure with entry for empty slot */ | ||
| 1210 | func = shpchp_slot_create(p_slot->bus); | ||
| 1211 | if (func == NULL) | ||
| 1212 | return -ENOMEM; /* Out of memory */ | ||
| 1213 | |||
| 1214 | func->bus = p_slot->bus; | ||
| 1215 | func->device = p_slot->device; | ||
| 1216 | func->function = 0; | ||
| 1217 | func->configured = 0; | ||
| 1218 | func->is_a_board = 1; | ||
| 1219 | |||
| 1220 | /* We have to save the presence info for these slots */ | ||
| 1221 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
| 1222 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 953 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1223 | func->switch_save = !getstatus? 0x10:0; | ||
| 1224 | } | 954 | } |
| 1225 | 955 | ||
| 1226 | if (p_slot) | 956 | update_slot_info(p_slot); |
| 1227 | update_slot_info(p_slot); | ||
| 1228 | |||
| 1229 | return rc; | 957 | return rc; |
| 1230 | } | 958 | } |
| 1231 | 959 | ||
| 1232 | 960 | ||
| 1233 | int shpchp_disable_slot (struct slot *p_slot) | 961 | int shpchp_disable_slot (struct slot *p_slot) |
| 1234 | { | 962 | { |
| 1235 | u8 class_code, header_type, BCR; | ||
| 1236 | u8 index = 0; | ||
| 1237 | u8 getstatus = 0; | 963 | u8 getstatus = 0; |
| 1238 | u32 rc = 0; | 964 | u32 rc = 0; |
| 1239 | int ret = 0; | 965 | int ret = 0; |
| 1240 | unsigned int devfn; | ||
| 1241 | struct pci_bus *pci_bus; | ||
| 1242 | struct pci_func *func; | ||
| 1243 | 966 | ||
| 1244 | if (!p_slot->ctrl) | 967 | if (!p_slot->ctrl) |
| 1245 | return -ENODEV; | 968 | return -ENODEV; |
| 1246 | 969 | ||
| 1247 | pci_bus = p_slot->ctrl->pci_dev->subordinate; | ||
| 1248 | |||
| 1249 | /* Check to see if (latch closed, card present, power on) */ | 970 | /* Check to see if (latch closed, card present, power on) */ |
| 1250 | down(&p_slot->ctrl->crit_sect); | 971 | down(&p_slot->ctrl->crit_sect); |
| 1251 | 972 | ||
| @@ -1269,54 +990,8 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 1269 | } | 990 | } |
| 1270 | up(&p_slot->ctrl->crit_sect); | 991 | up(&p_slot->ctrl->crit_sect); |
| 1271 | 992 | ||
| 1272 | func = shpchp_slot_find(p_slot->bus, p_slot->device, index++); | 993 | rc = remove_board(p_slot); |
| 1273 | 994 | update_slot_info(p_slot); | |
| 1274 | /* Make sure there are no video controllers here | ||
| 1275 | * for all func of p_slot | ||
| 1276 | */ | ||
| 1277 | while (func && !rc) { | ||
| 1278 | pci_bus->number = func->bus; | ||
| 1279 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 1280 | |||
| 1281 | /* Check the Class Code */ | ||
| 1282 | rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); | ||
| 1283 | if (rc) | ||
| 1284 | return -ENODEV; | ||
| 1285 | |||
| 1286 | if (class_code == PCI_BASE_CLASS_DISPLAY) { | ||
| 1287 | /* Display/Video adapter (not supported) */ | ||
| 1288 | rc = REMOVE_NOT_SUPPORTED; | ||
| 1289 | } else { | ||
| 1290 | /* See if it's a bridge */ | ||
| 1291 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | ||
| 1292 | if (rc) | ||
| 1293 | return -ENODEV; | ||
| 1294 | |||
| 1295 | /* If it's a bridge, check the VGA Enable bit */ | ||
| 1296 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
| 1297 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); | ||
| 1298 | if (rc) | ||
| 1299 | return -ENODEV; | ||
| 1300 | |||
| 1301 | /* If the VGA Enable bit is set, remove isn't supported */ | ||
| 1302 | if (BCR & PCI_BRIDGE_CTL_VGA) { | ||
| 1303 | rc = REMOVE_NOT_SUPPORTED; | ||
| 1304 | } | ||
| 1305 | } | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | func = shpchp_slot_find(p_slot->bus, p_slot->device, index++); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); | ||
| 1312 | if ((func != NULL) && !rc) { | ||
| 1313 | rc = remove_board(func, p_slot->ctrl); | ||
| 1314 | } else if (!rc) | ||
| 1315 | rc = -ENODEV; | ||
| 1316 | |||
| 1317 | if (p_slot) | ||
| 1318 | update_slot_info(p_slot); | ||
| 1319 | |||
| 1320 | return rc; | 995 | return rc; |
| 1321 | } | 996 | } |
| 1322 | 997 | ||
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index f51a97d7611f..8f0a1667f2e6 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
| @@ -148,20 +148,33 @@ int shpchp_configure_device(struct slot *p_slot) | |||
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | int shpchp_unconfigure_device(struct pci_func* func) | 151 | int shpchp_unconfigure_device(struct slot *p_slot) |
| 152 | { | 152 | { |
| 153 | int rc = 0; | 153 | int rc = 0; |
| 154 | int j; | 154 | int j; |
| 155 | u8 bctl = 0; | ||
| 155 | 156 | ||
| 156 | dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, | 157 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); |
| 157 | func->device, func->function); | ||
| 158 | 158 | ||
| 159 | for (j=0; j<8 ; j++) { | 159 | for (j=0; j<8 ; j++) { |
| 160 | struct pci_dev* temp = pci_find_slot(func->bus, | 160 | struct pci_dev* temp = pci_find_slot(p_slot->bus, |
| 161 | (func->device << 3) | j); | 161 | (p_slot->device << 3) | j); |
| 162 | if (temp) { | 162 | if (!temp) |
| 163 | pci_remove_bus_device(temp); | 163 | continue; |
| 164 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
| 165 | err("Cannot remove display device %s\n", | ||
| 166 | pci_name(temp)); | ||
| 167 | continue; | ||
| 168 | } | ||
| 169 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 170 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | ||
| 171 | if (bctl & PCI_BRIDGE_CTL_VGA) { | ||
| 172 | err("Cannot remove display device %s\n", | ||
| 173 | pci_name(temp)); | ||
| 174 | continue; | ||
| 175 | } | ||
| 164 | } | 176 | } |
| 177 | pci_remove_bus_device(temp); | ||
| 165 | } | 178 | } |
| 166 | return rc; | 179 | return rc; |
| 167 | } | 180 | } |
