diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-23 18:49:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-23 18:49:57 -0500 |
commit | a3ea9b584ed2acdeae817f0dc91a5880e0828a05 (patch) | |
tree | 5b4ef9b10c05aa84419a6ba6187d0dcd14654c97 /drivers/pci/hotplug | |
parent | 554f593d6c411e717a71ffdcb0cfb46bb2394502 (diff) | |
parent | b2e6e3ba7deb525f180df64f32f3fcb214538bea (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (49 commits)
[PATCH] acpiphp: fix acpi_path_name
[PATCH] ibmphp: remove TRUE and FALSE
[PATCH] PCI Hotplug: add common acpi functions to core
[PATCH] PCI: kzalloc() conversion in drivers/pci
[PATCH] acpiphp: Scan slots under the nested P2P bridge
[PATCH] PCI Hotplug: SN: Fix cleanup on hotplug removal of PPB
[PATCH] shpchp: cleanup bus speed handling
[PATCH] PCI: fix pci_request_region[s] arg
[PATCH] PCI: Provide a boot parameter to disable MSI
[PATCH] PCI: the scheduled removal of PCI_LEGACY_PROC
[PATCH] PCI: cpqphp_ctrl.c: board_replaced(): remove dead code
[PATCH] acpiphp: fix bridge handle
[PATCH] acpiphp - slot management fix - V4
[PATCH] acpi: remove dock event handling from ibm_acpi
[PATCH] acpiphp: add dock event handling
[PATCH] acpi: export acpi_bus_trim
[PATCH] acpiphp: add new bus to acpi
[PATCH] PCI: Move pci_dev_put outside a spinlock
[PATCH] PCI: PCI/Cardbus cards hidden, needs pci=assign-busses to fix
[PATCH] PCI: fix problems with MSI-X on ia64
...
Diffstat (limited to 'drivers/pci/hotplug')
34 files changed, 1879 insertions, 2240 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3c71e3077ff1..421cfffb1756 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
@@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI | |||
22 | pci_hotplug-objs += cpci_hotplug_core.o \ | 22 | pci_hotplug-objs += cpci_hotplug_core.o \ |
23 | cpci_hotplug_pci.o | 23 | cpci_hotplug_pci.o |
24 | endif | 24 | endif |
25 | ifdef CONFIG_ACPI | ||
26 | pci_hotplug-objs += acpi_pcihp.o | ||
27 | endif | ||
25 | 28 | ||
26 | cpqphp-objs := cpqphp_core.o \ | 29 | cpqphp-objs := cpqphp_core.o \ |
27 | cpqphp_ctrl.o \ | 30 | cpqphp_ctrl.o \ |
@@ -37,7 +40,8 @@ ibmphp-objs := ibmphp_core.o \ | |||
37 | ibmphp_hpc.o | 40 | ibmphp_hpc.o |
38 | 41 | ||
39 | acpiphp-objs := acpiphp_core.o \ | 42 | acpiphp-objs := acpiphp_core.o \ |
40 | acpiphp_glue.o | 43 | acpiphp_glue.o \ |
44 | acpiphp_dock.o | ||
41 | 45 | ||
42 | rpaphp-objs := rpaphp_core.o \ | 46 | rpaphp-objs := rpaphp_core.o \ |
43 | rpaphp_pci.o \ | 47 | rpaphp_pci.o \ |
@@ -50,23 +54,9 @@ pciehp-objs := pciehp_core.o \ | |||
50 | pciehp_ctrl.o \ | 54 | pciehp_ctrl.o \ |
51 | pciehp_pci.o \ | 55 | pciehp_pci.o \ |
52 | pciehp_hpc.o | 56 | pciehp_hpc.o |
53 | ifdef CONFIG_ACPI | ||
54 | pciehp-objs += pciehprm_acpi.o | ||
55 | else | ||
56 | pciehp-objs += pciehprm_nonacpi.o | ||
57 | endif | ||
58 | 57 | ||
59 | shpchp-objs := shpchp_core.o \ | 58 | shpchp-objs := shpchp_core.o \ |
60 | shpchp_ctrl.o \ | 59 | shpchp_ctrl.o \ |
61 | shpchp_pci.o \ | 60 | shpchp_pci.o \ |
62 | shpchp_sysfs.o \ | 61 | shpchp_sysfs.o \ |
63 | shpchp_hpc.o | 62 | shpchp_hpc.o |
64 | ifdef CONFIG_ACPI | ||
65 | shpchp-objs += shpchprm_acpi.o | ||
66 | else | ||
67 | ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY | ||
68 | shpchp-objs += shpchprm_legacy.o | ||
69 | else | ||
70 | shpchp-objs += shpchprm_nonacpi.o | ||
71 | endif | ||
72 | endif | ||
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/acpi_pcihp.c index 17145e52223a..39af9c325f35 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform | 2 | * Common ACPI functions for hot plug platforms |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2004 Intel Corporation | 4 | * Copyright (C) 2006 Intel Corporation |
5 | * | 5 | * |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -31,26 +31,12 @@ | |||
31 | #include <acpi/acpi.h> | 31 | #include <acpi/acpi.h> |
32 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
33 | #include <acpi/actypes.h> | 33 | #include <acpi/actypes.h> |
34 | #include "shpchp.h" | 34 | #include "pci_hotplug.h" |
35 | 35 | ||
36 | #define METHOD_NAME__SUN "_SUN" | 36 | #define METHOD_NAME__SUN "_SUN" |
37 | #define METHOD_NAME__HPP "_HPP" | 37 | #define METHOD_NAME__HPP "_HPP" |
38 | #define METHOD_NAME_OSHP "OSHP" | 38 | #define METHOD_NAME_OSHP "OSHP" |
39 | 39 | ||
40 | static u8 * acpi_path_name( acpi_handle handle) | ||
41 | { | ||
42 | acpi_status status; | ||
43 | static u8 path_name[ACPI_PATHNAME_MAX]; | ||
44 | struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; | ||
45 | |||
46 | memset(path_name, 0, sizeof (path_name)); | ||
47 | status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); | ||
48 | |||
49 | if (ACPI_FAILURE(status)) | ||
50 | return NULL; | ||
51 | else | ||
52 | return path_name; | ||
53 | } | ||
54 | 40 | ||
55 | static acpi_status | 41 | static acpi_status |
56 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | 42 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
@@ -58,18 +44,21 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | |||
58 | acpi_status status; | 44 | acpi_status status; |
59 | u8 nui[4]; | 45 | u8 nui[4]; |
60 | struct acpi_buffer ret_buf = { 0, NULL}; | 46 | struct acpi_buffer ret_buf = { 0, NULL}; |
47 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
61 | union acpi_object *ext_obj, *package; | 48 | union acpi_object *ext_obj, *package; |
62 | u8 *path_name = acpi_path_name(handle); | ||
63 | int i, len = 0; | 49 | int i, len = 0; |
64 | 50 | ||
51 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
52 | |||
65 | /* get _hpp */ | 53 | /* get _hpp */ |
66 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | 54 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); |
67 | switch (status) { | 55 | switch (status) { |
68 | case AE_BUFFER_OVERFLOW: | 56 | case AE_BUFFER_OVERFLOW: |
69 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | 57 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); |
70 | if (!ret_buf.pointer) { | 58 | if (!ret_buf.pointer) { |
71 | err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, | 59 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", |
72 | path_name); | 60 | __FUNCTION__, (char *)string.pointer); |
61 | acpi_os_free(string.pointer); | ||
73 | return AE_NO_MEMORY; | 62 | return AE_NO_MEMORY; |
74 | } | 63 | } |
75 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | 64 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, |
@@ -78,16 +67,17 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | |||
78 | break; | 67 | break; |
79 | default: | 68 | default: |
80 | if (ACPI_FAILURE(status)) { | 69 | if (ACPI_FAILURE(status)) { |
81 | dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, | 70 | pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, |
82 | path_name, status); | 71 | (char *)string.pointer, status); |
72 | acpi_os_free(string.pointer); | ||
83 | return status; | 73 | return status; |
84 | } | 74 | } |
85 | } | 75 | } |
86 | 76 | ||
87 | ext_obj = (union acpi_object *) ret_buf.pointer; | 77 | ext_obj = (union acpi_object *) ret_buf.pointer; |
88 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 78 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { |
89 | err ("%s:%s _HPP obj not a package\n", __FUNCTION__, | 79 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, |
90 | path_name); | 80 | (char *)string.pointer); |
91 | status = AE_ERROR; | 81 | status = AE_ERROR; |
92 | goto free_and_return; | 82 | goto free_and_return; |
93 | } | 83 | } |
@@ -101,8 +91,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | |||
101 | nui[i] = (u8)ext_obj->integer.value; | 91 | nui[i] = (u8)ext_obj->integer.value; |
102 | break; | 92 | break; |
103 | default: | 93 | default: |
104 | err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, | 94 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", |
105 | path_name); | 95 | __FUNCTION__, (char *)string.pointer); |
106 | status = AE_ERROR; | 96 | status = AE_ERROR; |
107 | goto free_and_return; | 97 | goto free_and_return; |
108 | } | 98 | } |
@@ -113,54 +103,52 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | |||
113 | hpp->enable_serr = nui[2]; | 103 | hpp->enable_serr = nui[2]; |
114 | hpp->enable_perr = nui[3]; | 104 | hpp->enable_perr = nui[3]; |
115 | 105 | ||
116 | dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); | 106 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); |
117 | dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); | 107 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); |
118 | dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); | 108 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); |
119 | dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); | 109 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); |
120 | 110 | ||
121 | free_and_return: | 111 | free_and_return: |
122 | kfree(ret_buf.pointer); | 112 | acpi_os_free(string.pointer); |
113 | acpi_os_free(ret_buf.pointer); | ||
123 | return status; | 114 | return status; |
124 | } | 115 | } |
125 | 116 | ||
126 | static void acpi_run_oshp(acpi_handle handle) | 117 | |
118 | |||
119 | /* acpi_run_oshp - get control of hotplug from the firmware | ||
120 | * | ||
121 | * @handle - the handle of the hotplug controller. | ||
122 | */ | ||
123 | acpi_status acpi_run_oshp(acpi_handle handle) | ||
127 | { | 124 | { |
128 | acpi_status status; | 125 | acpi_status status; |
129 | u8 *path_name = acpi_path_name(handle); | 126 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
127 | |||
128 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
130 | 129 | ||
131 | /* run OSHP */ | 130 | /* run OSHP */ |
132 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); | 131 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); |
133 | if (ACPI_FAILURE(status)) { | 132 | if (ACPI_FAILURE(status)) |
134 | err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, | 133 | printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, |
135 | status); | 134 | (char *)string.pointer, status); |
136 | } else { | 135 | else |
137 | dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); | 136 | pr_debug("%s:%s OSHP passes\n", __FUNCTION__, |
138 | } | 137 | (char *)string.pointer); |
139 | } | ||
140 | |||
141 | int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | ||
142 | { | ||
143 | int offset = devnum - ctrl->slot_device_offset; | ||
144 | 138 | ||
145 | dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); | 139 | acpi_os_free(string.pointer); |
146 | *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); | 140 | return status; |
147 | return 0; | ||
148 | } | 141 | } |
142 | EXPORT_SYMBOL_GPL(acpi_run_oshp); | ||
143 | |||
149 | 144 | ||
150 | void get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
151 | { | ||
152 | /* | ||
153 | * OSHP is an optional ACPI firmware control method. If present, | ||
154 | * we need to run it to inform BIOS that we will control SHPC | ||
155 | * hardware from now on. | ||
156 | */ | ||
157 | acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | ||
158 | if (!handle) | ||
159 | return; | ||
160 | acpi_run_oshp(handle); | ||
161 | } | ||
162 | 145 | ||
163 | void get_hp_params_from_firmware(struct pci_dev *dev, | 146 | /* acpi_get_hp_params_from_firmware |
147 | * | ||
148 | * @dev - the pci_dev of the newly added device | ||
149 | * @hpp - allocated by the caller | ||
150 | */ | ||
151 | acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, | ||
164 | struct hotplug_params *hpp) | 152 | struct hotplug_params *hpp) |
165 | { | 153 | { |
166 | acpi_status status = AE_NOT_FOUND; | 154 | acpi_status status = AE_NOT_FOUND; |
@@ -182,5 +170,42 @@ void get_hp_params_from_firmware(struct pci_dev *dev, | |||
182 | /* Check if a parent object supports _HPP */ | 170 | /* Check if a parent object supports _HPP */ |
183 | pdev = pdev->bus->parent->self; | 171 | pdev = pdev->bus->parent->self; |
184 | } | 172 | } |
173 | return status; | ||
185 | } | 174 | } |
175 | EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | ||
186 | 176 | ||
177 | |||
178 | /* acpi_root_bridge - check to see if this acpi object is a root bridge | ||
179 | * | ||
180 | * @handle - the acpi object in question. | ||
181 | */ | ||
182 | int acpi_root_bridge(acpi_handle handle) | ||
183 | { | ||
184 | acpi_status status; | ||
185 | struct acpi_device_info *info; | ||
186 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
187 | int i; | ||
188 | |||
189 | status = acpi_get_object_info(handle, &buffer); | ||
190 | if (ACPI_SUCCESS(status)) { | ||
191 | info = buffer.pointer; | ||
192 | if ((info->valid & ACPI_VALID_HID) && | ||
193 | !strcmp(PCI_ROOT_HID_STRING, | ||
194 | info->hardware_id.value)) { | ||
195 | acpi_os_free(buffer.pointer); | ||
196 | return 1; | ||
197 | } | ||
198 | if (info->valid & ACPI_VALID_CID) { | ||
199 | for (i=0; i < info->compatibility_id.count; i++) { | ||
200 | if (!strcmp(PCI_ROOT_HID_STRING, | ||
201 | info->compatibility_id.id[i].value)) { | ||
202 | acpi_os_free(buffer.pointer); | ||
203 | return 1; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | acpi_os_free(buffer.pointer); | ||
208 | } | ||
209 | return 0; | ||
210 | } | ||
211 | EXPORT_SYMBOL_GPL(acpi_root_bridge); | ||
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 293603e1b7c3..467ac70a46ff 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ | 39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ |
40 | #include <linux/mutex.h> | ||
40 | #include "pci_hotplug.h" | 41 | #include "pci_hotplug.h" |
41 | 42 | ||
42 | #define dbg(format, arg...) \ | 43 | #define dbg(format, arg...) \ |
@@ -59,26 +60,10 @@ struct acpiphp_slot; | |||
59 | * struct slot - slot information for each *physical* slot | 60 | * struct slot - slot information for each *physical* slot |
60 | */ | 61 | */ |
61 | struct slot { | 62 | struct slot { |
62 | u8 number; | ||
63 | struct hotplug_slot *hotplug_slot; | 63 | struct hotplug_slot *hotplug_slot; |
64 | struct list_head slot_list; | ||
65 | |||
66 | struct acpiphp_slot *acpi_slot; | 64 | struct acpiphp_slot *acpi_slot; |
67 | }; | 65 | }; |
68 | 66 | ||
69 | /** | ||
70 | * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters | ||
71 | * @cache_line_size in DWORD | ||
72 | * @latency_timer in PCI clock | ||
73 | * @enable_SERR 0 or 1 | ||
74 | * @enable_PERR 0 or 1 | ||
75 | */ | ||
76 | struct hpp_param { | ||
77 | u8 cache_line_size; | ||
78 | u8 latency_timer; | ||
79 | u8 enable_SERR; | ||
80 | u8 enable_PERR; | ||
81 | }; | ||
82 | 67 | ||
83 | 68 | ||
84 | /** | 69 | /** |
@@ -102,7 +87,7 @@ struct acpiphp_bridge { | |||
102 | struct pci_dev *pci_dev; | 87 | struct pci_dev *pci_dev; |
103 | 88 | ||
104 | /* ACPI 2.0 _HPP parameters */ | 89 | /* ACPI 2.0 _HPP parameters */ |
105 | struct hpp_param hpp; | 90 | struct hotplug_params hpp; |
106 | 91 | ||
107 | spinlock_t res_lock; | 92 | spinlock_t res_lock; |
108 | }; | 93 | }; |
@@ -118,9 +103,9 @@ struct acpiphp_slot { | |||
118 | struct acpiphp_bridge *bridge; /* parent */ | 103 | struct acpiphp_bridge *bridge; /* parent */ |
119 | struct list_head funcs; /* one slot may have different | 104 | struct list_head funcs; /* one slot may have different |
120 | objects (i.e. for each function) */ | 105 | objects (i.e. for each function) */ |
121 | struct semaphore crit_sect; | 106 | struct slot *slot; |
107 | struct mutex crit_sect; | ||
122 | 108 | ||
123 | u32 id; /* slot id (serial #) for hotplug core */ | ||
124 | u8 device; /* pci device# */ | 109 | u8 device; /* pci device# */ |
125 | 110 | ||
126 | u32 sun; /* ACPI _SUN (slot unique number) */ | 111 | u32 sun; /* ACPI _SUN (slot unique number) */ |
@@ -160,6 +145,25 @@ struct acpiphp_attention_info | |||
160 | struct module *owner; | 145 | struct module *owner; |
161 | }; | 146 | }; |
162 | 147 | ||
148 | |||
149 | struct dependent_device { | ||
150 | struct list_head device_list; | ||
151 | struct list_head pci_list; | ||
152 | acpi_handle handle; | ||
153 | struct acpiphp_func *func; | ||
154 | }; | ||
155 | |||
156 | |||
157 | struct acpiphp_dock_station { | ||
158 | acpi_handle handle; | ||
159 | u32 last_dock_time; | ||
160 | u32 flags; | ||
161 | struct acpiphp_func *dock_bridge; | ||
162 | struct list_head dependent_devices; | ||
163 | struct list_head pci_dependent_devices; | ||
164 | }; | ||
165 | |||
166 | |||
163 | /* PCI bus bridge HID */ | 167 | /* PCI bus bridge HID */ |
164 | #define ACPI_PCI_HOST_HID "PNP0A03" | 168 | #define ACPI_PCI_HOST_HID "PNP0A03" |
165 | 169 | ||
@@ -197,19 +201,27 @@ struct acpiphp_attention_info | |||
197 | #define FUNC_HAS_PS1 (0x00000020) | 201 | #define FUNC_HAS_PS1 (0x00000020) |
198 | #define FUNC_HAS_PS2 (0x00000040) | 202 | #define FUNC_HAS_PS2 (0x00000040) |
199 | #define FUNC_HAS_PS3 (0x00000080) | 203 | #define FUNC_HAS_PS3 (0x00000080) |
204 | #define FUNC_HAS_DCK (0x00000100) | ||
205 | #define FUNC_IS_DD (0x00000200) | ||
206 | |||
207 | /* dock station flags */ | ||
208 | #define DOCK_DOCKING (0x00000001) | ||
209 | #define DOCK_HAS_BRIDGE (0x00000002) | ||
200 | 210 | ||
201 | /* function prototypes */ | 211 | /* function prototypes */ |
202 | 212 | ||
203 | /* acpiphp_core.c */ | 213 | /* acpiphp_core.c */ |
204 | extern int acpiphp_register_attention(struct acpiphp_attention_info*info); | 214 | extern int acpiphp_register_attention(struct acpiphp_attention_info*info); |
205 | extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); | 215 | extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); |
216 | extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); | ||
217 | extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | ||
206 | 218 | ||
207 | /* acpiphp_glue.c */ | 219 | /* acpiphp_glue.c */ |
208 | extern int acpiphp_glue_init (void); | 220 | extern int acpiphp_glue_init (void); |
209 | extern void acpiphp_glue_exit (void); | 221 | extern void acpiphp_glue_exit (void); |
210 | extern int acpiphp_get_num_slots (void); | 222 | extern int acpiphp_get_num_slots (void); |
211 | extern struct acpiphp_slot *get_slot_from_id (int id); | ||
212 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 223 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
224 | void handle_hotplug_event_func(acpi_handle, u32, void*); | ||
213 | 225 | ||
214 | extern int acpiphp_enable_slot (struct acpiphp_slot *slot); | 226 | extern int acpiphp_enable_slot (struct acpiphp_slot *slot); |
215 | extern int acpiphp_disable_slot (struct acpiphp_slot *slot); | 227 | extern int acpiphp_disable_slot (struct acpiphp_slot *slot); |
@@ -219,6 +231,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); | |||
219 | extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); | 231 | extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); |
220 | extern u32 acpiphp_get_address (struct acpiphp_slot *slot); | 232 | extern u32 acpiphp_get_address (struct acpiphp_slot *slot); |
221 | 233 | ||
234 | /* acpiphp_dock.c */ | ||
235 | extern int find_dock_station(void); | ||
236 | extern void remove_dock_station(void); | ||
237 | extern void add_dependent_device(struct dependent_device *new_dd); | ||
238 | extern void add_pci_dependent_device(struct dependent_device *new_dd); | ||
239 | extern struct dependent_device *get_dependent_device(acpi_handle handle); | ||
240 | extern int is_dependent_device(acpi_handle handle); | ||
241 | extern int detect_dependent_devices(acpi_handle *bridge_handle); | ||
242 | extern struct dependent_device *alloc_dependent_device(acpi_handle handle); | ||
243 | |||
222 | /* variables */ | 244 | /* variables */ |
223 | extern int acpiphp_debug; | 245 | extern int acpiphp_debug; |
224 | 246 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 60c4c38047a3..4f1b0da8e47e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -44,8 +44,6 @@ | |||
44 | #include "pci_hotplug.h" | 44 | #include "pci_hotplug.h" |
45 | #include "acpiphp.h" | 45 | #include "acpiphp.h" |
46 | 46 | ||
47 | static LIST_HEAD(slot_list); | ||
48 | |||
49 | #define MY_NAME "acpiphp" | 47 | #define MY_NAME "acpiphp" |
50 | 48 | ||
51 | static int debug; | 49 | static int debug; |
@@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
341 | kfree(slot); | 339 | kfree(slot); |
342 | } | 340 | } |
343 | 341 | ||
344 | /** | 342 | /* callback routine to initialize 'struct slot' for each slot */ |
345 | * init_slots - initialize 'struct slot' structures for each slot | 343 | int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) |
346 | * | ||
347 | */ | ||
348 | static int __init init_slots(void) | ||
349 | { | 344 | { |
350 | struct slot *slot; | 345 | struct slot *slot; |
346 | struct hotplug_slot *hotplug_slot; | ||
347 | struct hotplug_slot_info *hotplug_slot_info; | ||
351 | int retval = -ENOMEM; | 348 | int retval = -ENOMEM; |
352 | int i; | 349 | |
353 | 350 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | |
354 | for (i = 0; i < num_slots; ++i) { | 351 | if (!slot) |
355 | slot = kmalloc(sizeof(struct slot), GFP_KERNEL); | 352 | goto error; |
356 | if (!slot) | 353 | |
357 | goto error; | 354 | slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); |
358 | memset(slot, 0, sizeof(struct slot)); | 355 | if (!slot->hotplug_slot) |
359 | 356 | goto error_slot; | |
360 | slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | 357 | |
361 | if (!slot->hotplug_slot) | 358 | slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), |
362 | goto error_slot; | 359 | GFP_KERNEL); |
363 | memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); | 360 | if (!slot->hotplug_slot->info) |
364 | 361 | goto error_hpslot; | |
365 | slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); | 362 | |
366 | if (!slot->hotplug_slot->info) | 363 | slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
367 | goto error_hpslot; | 364 | if (!slot->hotplug_slot->name) |
368 | memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); | 365 | goto error_info; |
369 | 366 | ||
370 | slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | 367 | slot->hotplug_slot->private = slot; |
371 | if (!slot->hotplug_slot->name) | 368 | slot->hotplug_slot->release = &release_slot; |
372 | goto error_info; | 369 | slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; |
373 | 370 | ||
374 | slot->number = i; | 371 | slot->acpi_slot = acpiphp_slot; |
375 | 372 | slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); | |
376 | slot->hotplug_slot->private = slot; | 373 | slot->hotplug_slot->info->attention_status = 0; |
377 | slot->hotplug_slot->release = &release_slot; | 374 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); |
378 | slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; | 375 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); |
379 | 376 | slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | |
380 | slot->acpi_slot = get_slot_from_id(i); | 377 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; |
381 | slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); | 378 | |
382 | slot->hotplug_slot->info->attention_status = 0; | 379 | acpiphp_slot->slot = slot; |
383 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); | 380 | make_slot_name(slot); |
384 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); | 381 | |
385 | slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | 382 | retval = pci_hp_register(slot->hotplug_slot); |
386 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | 383 | if (retval) { |
387 | 384 | err("pci_hp_register failed with error %d\n", retval); | |
388 | make_slot_name(slot); | 385 | goto error_name; |
389 | 386 | } | |
390 | retval = pci_hp_register(slot->hotplug_slot); | 387 | |
391 | if (retval) { | 388 | info("Slot [%s] registered\n", slot->hotplug_slot->name); |
392 | err("pci_hp_register failed with error %d\n", retval); | ||
393 | goto error_name; | ||
394 | } | ||
395 | |||
396 | /* add slot to our internal list */ | ||
397 | list_add(&slot->slot_list, &slot_list); | ||
398 | info("Slot [%s] registered\n", slot->hotplug_slot->name); | ||
399 | } | ||
400 | 389 | ||
401 | return 0; | 390 | return 0; |
402 | error_name: | 391 | error_name: |
@@ -412,42 +401,51 @@ error: | |||
412 | } | 401 | } |
413 | 402 | ||
414 | 403 | ||
415 | static void __exit cleanup_slots (void) | 404 | void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) |
416 | { | 405 | { |
417 | struct list_head *tmp, *n; | 406 | struct slot *slot = acpiphp_slot->slot; |
418 | struct slot *slot; | 407 | int retval = 0; |
419 | 408 | ||
420 | list_for_each_safe (tmp, n, &slot_list) { | 409 | info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); |
421 | /* memory will be freed in release_slot callback */ | 410 | |
422 | slot = list_entry(tmp, struct slot, slot_list); | 411 | retval = pci_hp_deregister(slot->hotplug_slot); |
423 | list_del(&slot->slot_list); | 412 | if (retval) |
424 | pci_hp_deregister(slot->hotplug_slot); | 413 | err("pci_hp_deregister failed with error %d\n", retval); |
425 | } | ||
426 | } | 414 | } |
427 | 415 | ||
428 | 416 | ||
429 | static int __init acpiphp_init(void) | 417 | static int __init acpiphp_init(void) |
430 | { | 418 | { |
431 | int retval; | 419 | int retval; |
420 | int docking_station; | ||
432 | 421 | ||
433 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 422 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
434 | 423 | ||
435 | acpiphp_debug = debug; | 424 | acpiphp_debug = debug; |
436 | 425 | ||
426 | docking_station = find_dock_station(); | ||
427 | |||
437 | /* read all the ACPI info from the system */ | 428 | /* read all the ACPI info from the system */ |
438 | retval = init_acpi(); | 429 | retval = init_acpi(); |
439 | if (retval) | ||
440 | return retval; | ||
441 | 430 | ||
442 | return init_slots(); | 431 | /* if we have found a docking station, we should |
432 | * go ahead and load even if init_acpi has found | ||
433 | * no slots. This handles the case when the _DCK | ||
434 | * method not defined under the actual dock bridge | ||
435 | */ | ||
436 | if (docking_station) | ||
437 | return 0; | ||
438 | else | ||
439 | return retval; | ||
443 | } | 440 | } |
444 | 441 | ||
445 | 442 | ||
446 | static void __exit acpiphp_exit(void) | 443 | static void __exit acpiphp_exit(void) |
447 | { | 444 | { |
448 | cleanup_slots(); | ||
449 | /* deallocate internal data structures etc. */ | 445 | /* deallocate internal data structures etc. */ |
450 | acpiphp_glue_exit(); | 446 | acpiphp_glue_exit(); |
447 | |||
448 | remove_dock_station(); | ||
451 | } | 449 | } |
452 | 450 | ||
453 | module_init(acpiphp_init); | 451 | module_init(acpiphp_init); |
diff --git a/drivers/pci/hotplug/acpiphp_dock.c b/drivers/pci/hotplug/acpiphp_dock.c new file mode 100644 index 000000000000..4f1aaf128312 --- /dev/null +++ b/drivers/pci/hotplug/acpiphp_dock.c | |||
@@ -0,0 +1,438 @@ | |||
1 | /* | ||
2 | * ACPI PCI HotPlug dock functions to ACPI CA subsystem | ||
3 | * | ||
4 | * Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com) | ||
5 | * Copyright (C) 2006 Intel Corporation | ||
6 | * | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
17 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
18 | * details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Send feedback to <kristen.c.accardi@intel.com> | ||
25 | * | ||
26 | */ | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/module.h> | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/mutex.h> | ||
34 | |||
35 | #include "../pci.h" | ||
36 | #include "pci_hotplug.h" | ||
37 | #include "acpiphp.h" | ||
38 | |||
39 | static struct acpiphp_dock_station *ds; | ||
40 | #define MY_NAME "acpiphp_dock" | ||
41 | |||
42 | |||
43 | int is_dependent_device(acpi_handle handle) | ||
44 | { | ||
45 | return (get_dependent_device(handle) ? 1 : 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | static acpi_status | ||
50 | find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
51 | { | ||
52 | int *count = (int *)context; | ||
53 | |||
54 | if (is_dependent_device(handle)) { | ||
55 | (*count)++; | ||
56 | return AE_CTRL_TERMINATE; | ||
57 | } else { | ||
58 | return AE_OK; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | |||
63 | |||
64 | |||
65 | void add_dependent_device(struct dependent_device *new_dd) | ||
66 | { | ||
67 | list_add_tail(&new_dd->device_list, &ds->dependent_devices); | ||
68 | } | ||
69 | |||
70 | |||
71 | void add_pci_dependent_device(struct dependent_device *new_dd) | ||
72 | { | ||
73 | list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices); | ||
74 | } | ||
75 | |||
76 | |||
77 | |||
78 | struct dependent_device * get_dependent_device(acpi_handle handle) | ||
79 | { | ||
80 | struct dependent_device *dd; | ||
81 | |||
82 | if (!ds) | ||
83 | return NULL; | ||
84 | |||
85 | list_for_each_entry(dd, &ds->dependent_devices, device_list) { | ||
86 | if (handle == dd->handle) | ||
87 | return dd; | ||
88 | } | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | |||
93 | |||
94 | struct dependent_device *alloc_dependent_device(acpi_handle handle) | ||
95 | { | ||
96 | struct dependent_device *dd; | ||
97 | |||
98 | dd = kzalloc(sizeof(*dd), GFP_KERNEL); | ||
99 | if (dd) { | ||
100 | INIT_LIST_HEAD(&dd->pci_list); | ||
101 | INIT_LIST_HEAD(&dd->device_list); | ||
102 | dd->handle = handle; | ||
103 | } | ||
104 | return dd; | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | static int is_dock(acpi_handle handle) | ||
110 | { | ||
111 | acpi_status status; | ||
112 | acpi_handle tmp; | ||
113 | |||
114 | status = acpi_get_handle(handle, "_DCK", &tmp); | ||
115 | if (ACPI_FAILURE(status)) { | ||
116 | return 0; | ||
117 | } | ||
118 | return 1; | ||
119 | } | ||
120 | |||
121 | |||
122 | |||
123 | static int dock_present(void) | ||
124 | { | ||
125 | unsigned long sta; | ||
126 | acpi_status status; | ||
127 | |||
128 | if (ds) { | ||
129 | status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); | ||
130 | if (ACPI_SUCCESS(status) && sta) | ||
131 | return 1; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | |||
137 | |||
138 | static void eject_dock(void) | ||
139 | { | ||
140 | struct acpi_object_list arg_list; | ||
141 | union acpi_object arg; | ||
142 | |||
143 | arg_list.count = 1; | ||
144 | arg_list.pointer = &arg; | ||
145 | arg.type = ACPI_TYPE_INTEGER; | ||
146 | arg.integer.value = 1; | ||
147 | |||
148 | if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", | ||
149 | &arg_list, NULL)) || dock_present()) | ||
150 | warn("%s: failed to eject dock!\n", __FUNCTION__); | ||
151 | |||
152 | return; | ||
153 | } | ||
154 | |||
155 | |||
156 | |||
157 | |||
158 | static acpi_status handle_dock(int dock) | ||
159 | { | ||
160 | acpi_status status; | ||
161 | struct acpi_object_list arg_list; | ||
162 | union acpi_object arg; | ||
163 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
164 | |||
165 | dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking"); | ||
166 | |||
167 | /* _DCK method has one argument */ | ||
168 | arg_list.count = 1; | ||
169 | arg_list.pointer = &arg; | ||
170 | arg.type = ACPI_TYPE_INTEGER; | ||
171 | arg.integer.value = dock; | ||
172 | status = acpi_evaluate_object(ds->handle, "_DCK", | ||
173 | &arg_list, &buffer); | ||
174 | if (ACPI_FAILURE(status)) | ||
175 | err("%s: failed to execute _DCK\n", __FUNCTION__); | ||
176 | acpi_os_free(buffer.pointer); | ||
177 | |||
178 | return status; | ||
179 | } | ||
180 | |||
181 | |||
182 | |||
183 | static inline void dock(void) | ||
184 | { | ||
185 | handle_dock(1); | ||
186 | } | ||
187 | |||
188 | |||
189 | |||
190 | static inline void undock(void) | ||
191 | { | ||
192 | handle_dock(0); | ||
193 | } | ||
194 | |||
195 | |||
196 | |||
197 | /* | ||
198 | * the _DCK method can do funny things... and sometimes not | ||
199 | * hah-hah funny. | ||
200 | * | ||
201 | * TBD - figure out a way to only call fixups for | ||
202 | * systems that require them. | ||
203 | */ | ||
204 | static void post_dock_fixups(void) | ||
205 | { | ||
206 | struct pci_bus *bus; | ||
207 | u32 buses; | ||
208 | struct dependent_device *dd; | ||
209 | |||
210 | list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) { | ||
211 | bus = dd->func->slot->bridge->pci_bus; | ||
212 | |||
213 | /* fixup bad _DCK function that rewrites | ||
214 | * secondary bridge on slot | ||
215 | */ | ||
216 | pci_read_config_dword(bus->self, | ||
217 | PCI_PRIMARY_BUS, | ||
218 | &buses); | ||
219 | |||
220 | if (((buses >> 8) & 0xff) != bus->secondary) { | ||
221 | buses = (buses & 0xff000000) | ||
222 | | ((unsigned int)(bus->primary) << 0) | ||
223 | | ((unsigned int)(bus->secondary) << 8) | ||
224 | | ((unsigned int)(bus->subordinate) << 16); | ||
225 | pci_write_config_dword(bus->self, | ||
226 | PCI_PRIMARY_BUS, | ||
227 | buses); | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | |||
234 | static void hotplug_pci(u32 type) | ||
235 | { | ||
236 | struct dependent_device *dd; | ||
237 | |||
238 | list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) | ||
239 | handle_hotplug_event_func(dd->handle, type, dd->func); | ||
240 | } | ||
241 | |||
242 | |||
243 | |||
244 | static inline void begin_dock(void) | ||
245 | { | ||
246 | ds->flags |= DOCK_DOCKING; | ||
247 | } | ||
248 | |||
249 | |||
250 | static inline void complete_dock(void) | ||
251 | { | ||
252 | ds->flags &= ~(DOCK_DOCKING); | ||
253 | ds->last_dock_time = jiffies; | ||
254 | } | ||
255 | |||
256 | |||
257 | static int dock_in_progress(void) | ||
258 | { | ||
259 | if (ds->flags & DOCK_DOCKING || | ||
260 | ds->last_dock_time == jiffies) { | ||
261 | dbg("dock in progress\n"); | ||
262 | return 1; | ||
263 | } | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | |||
268 | |||
269 | static void | ||
270 | handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context) | ||
271 | { | ||
272 | dbg("%s: enter\n", __FUNCTION__); | ||
273 | |||
274 | switch (type) { | ||
275 | case ACPI_NOTIFY_BUS_CHECK: | ||
276 | dbg("BUS Check\n"); | ||
277 | if (!dock_in_progress() && dock_present()) { | ||
278 | begin_dock(); | ||
279 | dock(); | ||
280 | if (!dock_present()) { | ||
281 | err("Unable to dock!\n"); | ||
282 | break; | ||
283 | } | ||
284 | post_dock_fixups(); | ||
285 | hotplug_pci(type); | ||
286 | complete_dock(); | ||
287 | } | ||
288 | break; | ||
289 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
290 | dbg("EJECT request\n"); | ||
291 | if (!dock_in_progress() && dock_present()) { | ||
292 | hotplug_pci(type); | ||
293 | undock(); | ||
294 | eject_dock(); | ||
295 | if (dock_present()) | ||
296 | err("Unable to undock!\n"); | ||
297 | } | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | |||
304 | |||
305 | static acpi_status | ||
306 | find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
307 | { | ||
308 | acpi_status status; | ||
309 | acpi_handle tmp; | ||
310 | acpi_handle dck_handle = (acpi_handle) context; | ||
311 | char objname[64]; | ||
312 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
313 | .pointer = objname }; | ||
314 | struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
315 | union acpi_object *ejd_obj; | ||
316 | |||
317 | status = acpi_get_handle(handle, "_EJD", &tmp); | ||
318 | if (ACPI_FAILURE(status)) | ||
319 | return AE_OK; | ||
320 | |||
321 | /* make sure we are dependent on the dock device, | ||
322 | * by executing the _EJD method, then getting a handle | ||
323 | * to the device referenced by that name. If that | ||
324 | * device handle is the same handle as the dock station | ||
325 | * handle, then we are a device dependent on the dock station | ||
326 | */ | ||
327 | acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer); | ||
328 | status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer); | ||
329 | if (ACPI_FAILURE(status)) { | ||
330 | err("Unable to execute _EJD!\n"); | ||
331 | goto find_ejd_out; | ||
332 | } | ||
333 | ejd_obj = ejd_buffer.pointer; | ||
334 | status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp); | ||
335 | if (ACPI_FAILURE(status)) | ||
336 | goto find_ejd_out; | ||
337 | |||
338 | if (tmp == dck_handle) { | ||
339 | struct dependent_device *dd; | ||
340 | dbg("%s: found device dependent on dock\n", __FUNCTION__); | ||
341 | dd = alloc_dependent_device(handle); | ||
342 | if (!dd) { | ||
343 | err("Can't allocate memory for dependent device!\n"); | ||
344 | goto find_ejd_out; | ||
345 | } | ||
346 | add_dependent_device(dd); | ||
347 | } | ||
348 | |||
349 | find_ejd_out: | ||
350 | acpi_os_free(ejd_buffer.pointer); | ||
351 | return AE_OK; | ||
352 | } | ||
353 | |||
354 | |||
355 | |||
356 | int detect_dependent_devices(acpi_handle *bridge_handle) | ||
357 | { | ||
358 | acpi_status status; | ||
359 | int count; | ||
360 | |||
361 | count = 0; | ||
362 | |||
363 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, | ||
364 | (u32)1, find_dependent_device, | ||
365 | (void *)&count, NULL); | ||
366 | |||
367 | return count; | ||
368 | } | ||
369 | |||
370 | |||
371 | |||
372 | |||
373 | |||
374 | static acpi_status | ||
375 | find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
376 | { | ||
377 | int *count = (int *)context; | ||
378 | |||
379 | if (is_dock(handle)) { | ||
380 | dbg("%s: found dock\n", __FUNCTION__); | ||
381 | ds = kzalloc(sizeof(*ds), GFP_KERNEL); | ||
382 | ds->handle = handle; | ||
383 | INIT_LIST_HEAD(&ds->dependent_devices); | ||
384 | INIT_LIST_HEAD(&ds->pci_dependent_devices); | ||
385 | |||
386 | /* look for devices dependent on dock station */ | ||
387 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
388 | ACPI_UINT32_MAX, find_dock_ejd, handle, NULL); | ||
389 | |||
390 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
391 | handle_hotplug_event_dock, ds); | ||
392 | (*count)++; | ||
393 | } | ||
394 | |||
395 | return AE_OK; | ||
396 | } | ||
397 | |||
398 | |||
399 | |||
400 | |||
401 | int find_dock_station(void) | ||
402 | { | ||
403 | int num = 0; | ||
404 | |||
405 | ds = NULL; | ||
406 | |||
407 | /* start from the root object, because some laptops define | ||
408 | * _DCK methods outside the scope of PCI (IBM x-series laptop) | ||
409 | */ | ||
410 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
411 | ACPI_UINT32_MAX, find_dock, &num, NULL); | ||
412 | |||
413 | return num; | ||
414 | } | ||
415 | |||
416 | |||
417 | |||
418 | void remove_dock_station(void) | ||
419 | { | ||
420 | struct dependent_device *dd, *tmp; | ||
421 | if (ds) { | ||
422 | if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle, | ||
423 | ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock))) | ||
424 | err("failed to remove dock notify handler\n"); | ||
425 | |||
426 | /* free all dependent devices */ | ||
427 | list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, | ||
428 | device_list) | ||
429 | kfree(dd); | ||
430 | |||
431 | /* no need to touch the pci_dependent_device list, | ||
432 | * cause all memory was freed above | ||
433 | */ | ||
434 | kfree(ds); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 509a5b3ae998..053ee843863c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <linux/smp_lock.h> | 48 | #include <linux/smp_lock.h> |
49 | #include <asm/semaphore.h> | 49 | #include <linux/mutex.h> |
50 | 50 | ||
51 | #include "../pci.h" | 51 | #include "../pci.h" |
52 | #include "pci_hotplug.h" | 52 | #include "pci_hotplug.h" |
@@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list); | |||
57 | #define MY_NAME "acpiphp_glue" | 57 | #define MY_NAME "acpiphp_glue" |
58 | 58 | ||
59 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); | 59 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); |
60 | static void handle_hotplug_event_func (acpi_handle, u32, void *); | ||
61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 60 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
62 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); | 61 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); |
63 | 62 | ||
@@ -125,11 +124,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
125 | struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; | 124 | struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; |
126 | struct acpiphp_slot *slot; | 125 | struct acpiphp_slot *slot; |
127 | struct acpiphp_func *newfunc; | 126 | struct acpiphp_func *newfunc; |
127 | struct dependent_device *dd; | ||
128 | acpi_handle tmp; | 128 | acpi_handle tmp; |
129 | acpi_status status = AE_OK; | 129 | acpi_status status = AE_OK; |
130 | unsigned long adr, sun; | 130 | unsigned long adr, sun; |
131 | int device, function; | 131 | int device, function, retval; |
132 | static int num_slots = 0; /* XXX if we support I/O node hotplug... */ | ||
133 | 132 | ||
134 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 133 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
135 | 134 | ||
@@ -138,21 +137,21 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
138 | 137 | ||
139 | status = acpi_get_handle(handle, "_EJ0", &tmp); | 138 | status = acpi_get_handle(handle, "_EJ0", &tmp); |
140 | 139 | ||
141 | if (ACPI_FAILURE(status)) | 140 | if (ACPI_FAILURE(status) && !(is_dependent_device(handle))) |
142 | return AE_OK; | 141 | return AE_OK; |
143 | 142 | ||
144 | device = (adr >> 16) & 0xffff; | 143 | device = (adr >> 16) & 0xffff; |
145 | function = adr & 0xffff; | 144 | function = adr & 0xffff; |
146 | 145 | ||
147 | newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL); | 146 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); |
148 | if (!newfunc) | 147 | if (!newfunc) |
149 | return AE_NO_MEMORY; | 148 | return AE_NO_MEMORY; |
150 | memset(newfunc, 0, sizeof(struct acpiphp_func)); | ||
151 | 149 | ||
152 | INIT_LIST_HEAD(&newfunc->sibling); | 150 | INIT_LIST_HEAD(&newfunc->sibling); |
153 | newfunc->handle = handle; | 151 | newfunc->handle = handle; |
154 | newfunc->function = function; | 152 | newfunc->function = function; |
155 | newfunc->flags = FUNC_HAS_EJ0; | 153 | if (ACPI_SUCCESS(status)) |
154 | newfunc->flags = FUNC_HAS_EJ0; | ||
156 | 155 | ||
157 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) | 156 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) |
158 | newfunc->flags |= FUNC_HAS_STA; | 157 | newfunc->flags |= FUNC_HAS_STA; |
@@ -163,6 +162,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
163 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) | 162 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) |
164 | newfunc->flags |= FUNC_HAS_PS3; | 163 | newfunc->flags |= FUNC_HAS_PS3; |
165 | 164 | ||
165 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) { | ||
166 | newfunc->flags |= FUNC_HAS_DCK; | ||
167 | /* add to devices dependent on dock station, | ||
168 | * because this may actually be the dock bridge | ||
169 | */ | ||
170 | dd = alloc_dependent_device(handle); | ||
171 | if (!dd) | ||
172 | err("Can't allocate memory for " | ||
173 | "new dependent device!\n"); | ||
174 | else | ||
175 | add_dependent_device(dd); | ||
176 | } | ||
177 | |||
166 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); | 178 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); |
167 | if (ACPI_FAILURE(status)) | 179 | if (ACPI_FAILURE(status)) |
168 | sun = -1; | 180 | sun = -1; |
@@ -176,19 +188,17 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
176 | } | 188 | } |
177 | 189 | ||
178 | if (!slot) { | 190 | if (!slot) { |
179 | slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); | 191 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); |
180 | if (!slot) { | 192 | if (!slot) { |
181 | kfree(newfunc); | 193 | kfree(newfunc); |
182 | return AE_NO_MEMORY; | 194 | return AE_NO_MEMORY; |
183 | } | 195 | } |
184 | 196 | ||
185 | memset(slot, 0, sizeof(struct acpiphp_slot)); | ||
186 | slot->bridge = bridge; | 197 | slot->bridge = bridge; |
187 | slot->id = num_slots++; | ||
188 | slot->device = device; | 198 | slot->device = device; |
189 | slot->sun = sun; | 199 | slot->sun = sun; |
190 | INIT_LIST_HEAD(&slot->funcs); | 200 | INIT_LIST_HEAD(&slot->funcs); |
191 | init_MUTEX(&slot->crit_sect); | 201 | mutex_init(&slot->crit_sect); |
192 | 202 | ||
193 | slot->next = bridge->slots; | 203 | slot->next = bridge->slots; |
194 | bridge->slots = slot; | 204 | bridge->slots = slot; |
@@ -198,6 +208,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
198 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", | 208 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", |
199 | slot->sun, pci_domain_nr(bridge->pci_bus), | 209 | slot->sun, pci_domain_nr(bridge->pci_bus), |
200 | bridge->pci_bus->number, slot->device); | 210 | bridge->pci_bus->number, slot->device); |
211 | retval = acpiphp_register_hotplug_slot(slot); | ||
212 | if (retval) { | ||
213 | warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); | ||
214 | goto err_exit; | ||
215 | } | ||
201 | } | 216 | } |
202 | 217 | ||
203 | newfunc->slot = slot; | 218 | newfunc->slot = slot; |
@@ -210,16 +225,41 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
210 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 225 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
211 | } | 226 | } |
212 | 227 | ||
228 | /* if this is a device dependent on a dock station, | ||
229 | * associate the acpiphp_func to the dependent_device | ||
230 | * struct. | ||
231 | */ | ||
232 | if ((dd = get_dependent_device(handle))) { | ||
233 | newfunc->flags |= FUNC_IS_DD; | ||
234 | /* | ||
235 | * we don't want any devices which is dependent | ||
236 | * on the dock to have it's _EJ0 method executed. | ||
237 | * because we need to run _DCK first. | ||
238 | */ | ||
239 | newfunc->flags &= ~FUNC_HAS_EJ0; | ||
240 | dd->func = newfunc; | ||
241 | add_pci_dependent_device(dd); | ||
242 | } | ||
243 | |||
213 | /* install notify handler */ | 244 | /* install notify handler */ |
214 | status = acpi_install_notify_handler(handle, | 245 | if (!(newfunc->flags & FUNC_HAS_DCK)) { |
246 | status = acpi_install_notify_handler(handle, | ||
215 | ACPI_SYSTEM_NOTIFY, | 247 | ACPI_SYSTEM_NOTIFY, |
216 | handle_hotplug_event_func, | 248 | handle_hotplug_event_func, |
217 | newfunc); | 249 | newfunc); |
218 | 250 | ||
219 | if (ACPI_FAILURE(status)) { | 251 | if (ACPI_FAILURE(status)) |
220 | err("failed to register interrupt notify handler\n"); | 252 | err("failed to register interrupt notify handler\n"); |
221 | return status; | 253 | } else |
222 | } | 254 | status = AE_OK; |
255 | |||
256 | return status; | ||
257 | |||
258 | err_exit: | ||
259 | bridge->nr_slots--; | ||
260 | bridge->slots = slot->next; | ||
261 | kfree(slot); | ||
262 | kfree(newfunc); | ||
223 | 263 | ||
224 | return AE_OK; | 264 | return AE_OK; |
225 | } | 265 | } |
@@ -245,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle) | |||
245 | static void decode_hpp(struct acpiphp_bridge *bridge) | 285 | static void decode_hpp(struct acpiphp_bridge *bridge) |
246 | { | 286 | { |
247 | acpi_status status; | 287 | acpi_status status; |
248 | struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, | ||
249 | .pointer = NULL}; | ||
250 | union acpi_object *package; | ||
251 | int i; | ||
252 | |||
253 | /* default numbers */ | ||
254 | bridge->hpp.cache_line_size = 0x10; | ||
255 | bridge->hpp.latency_timer = 0x40; | ||
256 | bridge->hpp.enable_SERR = 0; | ||
257 | bridge->hpp.enable_PERR = 0; | ||
258 | |||
259 | status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); | ||
260 | 288 | ||
289 | status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); | ||
261 | if (ACPI_FAILURE(status)) { | 290 | if (ACPI_FAILURE(status)) { |
262 | dbg("_HPP evaluation failed\n"); | 291 | /* use default numbers */ |
263 | return; | 292 | bridge->hpp.cache_line_size = 0x10; |
293 | bridge->hpp.latency_timer = 0x40; | ||
294 | bridge->hpp.enable_serr = 0; | ||
295 | bridge->hpp.enable_perr = 0; | ||
264 | } | 296 | } |
265 | |||
266 | package = (union acpi_object *) buffer.pointer; | ||
267 | |||
268 | if (!package || package->type != ACPI_TYPE_PACKAGE || | ||
269 | package->package.count != 4 || !package->package.elements) { | ||
270 | err("invalid _HPP object; ignoring\n"); | ||
271 | goto err_exit; | ||
272 | } | ||
273 | |||
274 | for (i = 0; i < 4; i++) { | ||
275 | if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { | ||
276 | err("invalid _HPP parameter type; ignoring\n"); | ||
277 | goto err_exit; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | bridge->hpp.cache_line_size = package->package.elements[0].integer.value; | ||
282 | bridge->hpp.latency_timer = package->package.elements[1].integer.value; | ||
283 | bridge->hpp.enable_SERR = package->package.elements[2].integer.value; | ||
284 | bridge->hpp.enable_PERR = package->package.elements[3].integer.value; | ||
285 | |||
286 | dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", | ||
287 | bridge->hpp.cache_line_size, | ||
288 | bridge->hpp.latency_timer, | ||
289 | bridge->hpp.enable_SERR, | ||
290 | bridge->hpp.enable_PERR); | ||
291 | |||
292 | bridge->flags |= BRIDGE_HAS_HPP; | ||
293 | |||
294 | err_exit: | ||
295 | kfree(buffer.pointer); | ||
296 | } | 297 | } |
297 | 298 | ||
298 | 299 | ||
300 | |||
299 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ | 301 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ |
300 | static void init_bridge_misc(struct acpiphp_bridge *bridge) | 302 | static void init_bridge_misc(struct acpiphp_bridge *bridge) |
301 | { | 303 | { |
@@ -304,9 +306,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
304 | /* decode ACPI 2.0 _HPP (hot plug parameters) */ | 306 | /* decode ACPI 2.0 _HPP (hot plug parameters) */ |
305 | decode_hpp(bridge); | 307 | decode_hpp(bridge); |
306 | 308 | ||
309 | /* must be added to the list prior to calling register_slot */ | ||
310 | list_add(&bridge->list, &bridge_list); | ||
311 | |||
307 | /* register all slot objects under this bridge */ | 312 | /* register all slot objects under this bridge */ |
308 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | 313 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, |
309 | register_slot, bridge, NULL); | 314 | register_slot, bridge, NULL); |
315 | if (ACPI_FAILURE(status)) { | ||
316 | list_del(&bridge->list); | ||
317 | return; | ||
318 | } | ||
310 | 319 | ||
311 | /* install notify handler */ | 320 | /* install notify handler */ |
312 | if (bridge->type != BRIDGE_TYPE_HOST) { | 321 | if (bridge->type != BRIDGE_TYPE_HOST) { |
@@ -319,8 +328,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
319 | err("failed to register interrupt notify handler\n"); | 328 | err("failed to register interrupt notify handler\n"); |
320 | } | 329 | } |
321 | } | 330 | } |
322 | |||
323 | list_add(&bridge->list, &bridge_list); | ||
324 | } | 331 | } |
325 | 332 | ||
326 | 333 | ||
@@ -329,12 +336,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | |||
329 | { | 336 | { |
330 | struct acpiphp_bridge *bridge; | 337 | struct acpiphp_bridge *bridge; |
331 | 338 | ||
332 | bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 339 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
333 | if (bridge == NULL) | 340 | if (bridge == NULL) |
334 | return; | 341 | return; |
335 | 342 | ||
336 | memset(bridge, 0, sizeof(struct acpiphp_bridge)); | ||
337 | |||
338 | bridge->type = BRIDGE_TYPE_HOST; | 343 | bridge->type = BRIDGE_TYPE_HOST; |
339 | bridge->handle = handle; | 344 | bridge->handle = handle; |
340 | 345 | ||
@@ -351,14 +356,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | |||
351 | { | 356 | { |
352 | struct acpiphp_bridge *bridge; | 357 | struct acpiphp_bridge *bridge; |
353 | 358 | ||
354 | bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 359 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
355 | if (bridge == NULL) { | 360 | if (bridge == NULL) { |
356 | err("out of memory\n"); | 361 | err("out of memory\n"); |
357 | return; | 362 | return; |
358 | } | 363 | } |
359 | 364 | ||
360 | memset(bridge, 0, sizeof(struct acpiphp_bridge)); | ||
361 | |||
362 | bridge->type = BRIDGE_TYPE_P2P; | 365 | bridge->type = BRIDGE_TYPE_P2P; |
363 | bridge->handle = handle; | 366 | bridge->handle = handle; |
364 | 367 | ||
@@ -410,11 +413,18 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
410 | goto out; | 413 | goto out; |
411 | 414 | ||
412 | /* check if this bridge has ejectable slots */ | 415 | /* check if this bridge has ejectable slots */ |
413 | if (detect_ejectable_slots(handle) > 0) { | 416 | if ((detect_ejectable_slots(handle) > 0) || |
417 | (detect_dependent_devices(handle) > 0)) { | ||
414 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | 418 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); |
415 | add_p2p_bridge(handle, dev); | 419 | add_p2p_bridge(handle, dev); |
416 | } | 420 | } |
417 | 421 | ||
422 | /* search P2P bridges under this p2p bridge */ | ||
423 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
424 | find_p2p_bridge, dev->subordinate, NULL); | ||
425 | if (ACPI_FAILURE(status)) | ||
426 | warn("find_p2p_bridge faied (error code = 0x%x)\n", status); | ||
427 | |||
418 | out: | 428 | out: |
419 | pci_dev_put(dev); | 429 | pci_dev_put(dev); |
420 | return AE_OK; | 430 | return AE_OK; |
@@ -512,15 +522,19 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
512 | list_for_each_safe (list, tmp, &slot->funcs) { | 522 | list_for_each_safe (list, tmp, &slot->funcs) { |
513 | struct acpiphp_func *func; | 523 | struct acpiphp_func *func; |
514 | func = list_entry(list, struct acpiphp_func, sibling); | 524 | func = list_entry(list, struct acpiphp_func, sibling); |
515 | status = acpi_remove_notify_handler(func->handle, | 525 | if (!(func->flags & FUNC_HAS_DCK)) { |
526 | status = acpi_remove_notify_handler(func->handle, | ||
516 | ACPI_SYSTEM_NOTIFY, | 527 | ACPI_SYSTEM_NOTIFY, |
517 | handle_hotplug_event_func); | 528 | handle_hotplug_event_func); |
518 | if (ACPI_FAILURE(status)) | 529 | if (ACPI_FAILURE(status)) |
519 | err("failed to remove notify handler\n"); | 530 | err("failed to remove notify handler\n"); |
531 | } | ||
520 | pci_dev_put(func->pci_dev); | 532 | pci_dev_put(func->pci_dev); |
521 | list_del(list); | 533 | list_del(list); |
522 | kfree(func); | 534 | kfree(func); |
523 | } | 535 | } |
536 | acpiphp_unregister_hotplug_slot(slot); | ||
537 | list_del(&slot->funcs); | ||
524 | kfree(slot); | 538 | kfree(slot); |
525 | slot = next; | 539 | slot = next; |
526 | } | 540 | } |
@@ -551,7 +565,8 @@ static void remove_bridge(acpi_handle handle) | |||
551 | } else { | 565 | } else { |
552 | /* clean-up p2p bridges under this host bridge */ | 566 | /* clean-up p2p bridges under this host bridge */ |
553 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 567 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
554 | (u32)1, cleanup_p2p_bridge, NULL, NULL); | 568 | ACPI_UINT32_MAX, cleanup_p2p_bridge, |
569 | NULL, NULL); | ||
555 | } | 570 | } |
556 | } | 571 | } |
557 | 572 | ||
@@ -751,6 +766,113 @@ static int power_off_slot(struct acpiphp_slot *slot) | |||
751 | } | 766 | } |
752 | 767 | ||
753 | 768 | ||
769 | |||
770 | /** | ||
771 | * acpiphp_max_busnr - return the highest reserved bus number under | ||
772 | * the given bus. | ||
773 | * @bus: bus to start search with | ||
774 | * | ||
775 | */ | ||
776 | static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | ||
777 | { | ||
778 | struct list_head *tmp; | ||
779 | unsigned char max, n; | ||
780 | |||
781 | /* | ||
782 | * pci_bus_max_busnr will return the highest | ||
783 | * reserved busnr for all these children. | ||
784 | * that is equivalent to the bus->subordinate | ||
785 | * value. We don't want to use the parent's | ||
786 | * bus->subordinate value because it could have | ||
787 | * padding in it. | ||
788 | */ | ||
789 | max = bus->secondary; | ||
790 | |||
791 | list_for_each(tmp, &bus->children) { | ||
792 | n = pci_bus_max_busnr(pci_bus_b(tmp)); | ||
793 | if (n > max) | ||
794 | max = n; | ||
795 | } | ||
796 | return max; | ||
797 | } | ||
798 | |||
799 | |||
800 | |||
801 | /** | ||
802 | * get_func - get a pointer to acpiphp_func given a slot, device | ||
803 | * @slot: slot to search | ||
804 | * @dev: pci_dev struct to match. | ||
805 | * | ||
806 | * This function will increase the reference count of pci_dev, | ||
807 | * so callers should call pci_dev_put when complete. | ||
808 | * | ||
809 | */ | ||
810 | static struct acpiphp_func * | ||
811 | get_func(struct acpiphp_slot *slot, struct pci_dev *dev) | ||
812 | { | ||
813 | struct acpiphp_func *func = NULL; | ||
814 | struct pci_bus *bus = slot->bridge->pci_bus; | ||
815 | struct pci_dev *pdev; | ||
816 | |||
817 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
818 | pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, | ||
819 | func->function)); | ||
820 | if (pdev) { | ||
821 | if (pdev == dev) | ||
822 | break; | ||
823 | pci_dev_put(pdev); | ||
824 | } | ||
825 | } | ||
826 | return func; | ||
827 | } | ||
828 | |||
829 | |||
830 | /** | ||
831 | * acpiphp_bus_add - add a new bus to acpi subsystem | ||
832 | * @func: acpiphp_func of the bridge | ||
833 | * | ||
834 | */ | ||
835 | static int acpiphp_bus_add(struct acpiphp_func *func) | ||
836 | { | ||
837 | acpi_handle phandle; | ||
838 | struct acpi_device *device, *pdevice; | ||
839 | int ret_val; | ||
840 | |||
841 | acpi_get_parent(func->handle, &phandle); | ||
842 | if (acpi_bus_get_device(phandle, &pdevice)) { | ||
843 | dbg("no parent device, assuming NULL\n"); | ||
844 | pdevice = NULL; | ||
845 | } | ||
846 | if (!acpi_bus_get_device(func->handle, &device)) { | ||
847 | dbg("bus exists... trim\n"); | ||
848 | /* this shouldn't be in here, so remove | ||
849 | * the bus then re-add it... | ||
850 | */ | ||
851 | ret_val = acpi_bus_trim(device, 1); | ||
852 | dbg("acpi_bus_trim return %x\n", ret_val); | ||
853 | } | ||
854 | |||
855 | ret_val = acpi_bus_add(&device, pdevice, func->handle, | ||
856 | ACPI_BUS_TYPE_DEVICE); | ||
857 | if (ret_val) { | ||
858 | dbg("error adding bus, %x\n", | ||
859 | -ret_val); | ||
860 | goto acpiphp_bus_add_out; | ||
861 | } | ||
862 | /* | ||
863 | * try to start anyway. We could have failed to add | ||
864 | * simply because this bus had previously been added | ||
865 | * on another add. Don't bother with the return value | ||
866 | * we just keep going. | ||
867 | */ | ||
868 | ret_val = acpi_bus_start(device); | ||
869 | |||
870 | acpiphp_bus_add_out: | ||
871 | return ret_val; | ||
872 | } | ||
873 | |||
874 | |||
875 | |||
754 | /** | 876 | /** |
755 | * enable_device - enable, configure a slot | 877 | * enable_device - enable, configure a slot |
756 | * @slot: slot to be enabled | 878 | * @slot: slot to be enabled |
@@ -788,7 +910,7 @@ static int enable_device(struct acpiphp_slot *slot) | |||
788 | goto err_exit; | 910 | goto err_exit; |
789 | } | 911 | } |
790 | 912 | ||
791 | max = bus->secondary; | 913 | max = acpiphp_max_busnr(bus); |
792 | for (pass = 0; pass < 2; pass++) { | 914 | for (pass = 0; pass < 2; pass++) { |
793 | list_for_each_entry(dev, &bus->devices, bus_list) { | 915 | list_for_each_entry(dev, &bus->devices, bus_list) { |
794 | if (PCI_SLOT(dev->devfn) != slot->device) | 916 | if (PCI_SLOT(dev->devfn) != slot->device) |
@@ -796,8 +918,15 @@ static int enable_device(struct acpiphp_slot *slot) | |||
796 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 918 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
797 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | 919 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
798 | max = pci_scan_bridge(bus, dev, max, pass); | 920 | max = pci_scan_bridge(bus, dev, max, pass); |
799 | if (pass && dev->subordinate) | 921 | if (pass && dev->subordinate) { |
800 | pci_bus_size_bridges(dev->subordinate); | 922 | pci_bus_size_bridges(dev->subordinate); |
923 | func = get_func(slot, dev); | ||
924 | if (func) { | ||
925 | acpiphp_bus_add(func); | ||
926 | /* side effect of get_func */ | ||
927 | pci_dev_put(dev); | ||
928 | } | ||
929 | } | ||
801 | } | 930 | } |
802 | } | 931 | } |
803 | } | 932 | } |
@@ -806,8 +935,8 @@ static int enable_device(struct acpiphp_slot *slot) | |||
806 | acpiphp_sanitize_bus(bus); | 935 | acpiphp_sanitize_bus(bus); |
807 | pci_enable_bridges(bus); | 936 | pci_enable_bridges(bus); |
808 | pci_bus_add_devices(bus); | 937 | pci_bus_add_devices(bus); |
809 | acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus); | 938 | acpiphp_set_hpp_values(slot->bridge->handle, bus); |
810 | acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev)); | 939 | acpiphp_configure_ioapics(slot->bridge->handle); |
811 | 940 | ||
812 | /* associate pci_dev to our representation */ | 941 | /* associate pci_dev to our representation */ |
813 | list_for_each (l, &slot->funcs) { | 942 | list_for_each (l, &slot->funcs) { |
@@ -987,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) | |||
987 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, | 1116 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, |
988 | bridge->hpp.latency_timer); | 1117 | bridge->hpp.latency_timer); |
989 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | 1118 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); |
990 | if (bridge->hpp.enable_SERR) | 1119 | if (bridge->hpp.enable_serr) |
991 | pci_cmd |= PCI_COMMAND_SERR; | 1120 | pci_cmd |= PCI_COMMAND_SERR; |
992 | else | 1121 | else |
993 | pci_cmd &= ~PCI_COMMAND_SERR; | 1122 | pci_cmd &= ~PCI_COMMAND_SERR; |
994 | if (bridge->hpp.enable_PERR) | 1123 | if (bridge->hpp.enable_perr) |
995 | pci_cmd |= PCI_COMMAND_PARITY; | 1124 | pci_cmd |= PCI_COMMAND_PARITY; |
996 | else | 1125 | else |
997 | pci_cmd &= ~PCI_COMMAND_PARITY; | 1126 | pci_cmd &= ~PCI_COMMAND_PARITY; |
@@ -1002,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) | |||
1002 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | 1131 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, |
1003 | bridge->hpp.latency_timer); | 1132 | bridge->hpp.latency_timer); |
1004 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | 1133 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); |
1005 | if (bridge->hpp.enable_SERR) | 1134 | if (bridge->hpp.enable_serr) |
1006 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | 1135 | pci_bctl |= PCI_BRIDGE_CTL_SERR; |
1007 | else | 1136 | else |
1008 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | 1137 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; |
1009 | if (bridge->hpp.enable_PERR) | 1138 | if (bridge->hpp.enable_perr) |
1010 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | 1139 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; |
1011 | else | 1140 | else |
1012 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | 1141 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; |
@@ -1026,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) | |||
1026 | 1155 | ||
1027 | memset(&bridge, 0, sizeof(bridge)); | 1156 | memset(&bridge, 0, sizeof(bridge)); |
1028 | bridge.handle = handle; | 1157 | bridge.handle = handle; |
1158 | bridge.pci_dev = bus->self; | ||
1029 | decode_hpp(&bridge); | 1159 | decode_hpp(&bridge); |
1030 | list_for_each_entry(dev, &bus->devices, bus_list) | 1160 | list_for_each_entry(dev, &bus->devices, bus_list) |
1031 | program_hpp(dev, &bridge); | 1161 | program_hpp(dev, &bridge); |
@@ -1200,7 +1330,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1200 | * handles ACPI event notification on slots | 1330 | * handles ACPI event notification on slots |
1201 | * | 1331 | * |
1202 | */ | 1332 | */ |
1203 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) | 1333 | void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) |
1204 | { | 1334 | { |
1205 | struct acpiphp_func *func; | 1335 | struct acpiphp_func *func; |
1206 | char objname[64]; | 1336 | char objname[64]; |
@@ -1242,41 +1372,13 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex | |||
1242 | } | 1372 | } |
1243 | } | 1373 | } |
1244 | 1374 | ||
1245 | static int is_root_bridge(acpi_handle handle) | ||
1246 | { | ||
1247 | acpi_status status; | ||
1248 | struct acpi_device_info *info; | ||
1249 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
1250 | int i; | ||
1251 | |||
1252 | status = acpi_get_object_info(handle, &buffer); | ||
1253 | if (ACPI_SUCCESS(status)) { | ||
1254 | info = buffer.pointer; | ||
1255 | if ((info->valid & ACPI_VALID_HID) && | ||
1256 | !strcmp(PCI_ROOT_HID_STRING, | ||
1257 | info->hardware_id.value)) { | ||
1258 | acpi_os_free(buffer.pointer); | ||
1259 | return 1; | ||
1260 | } | ||
1261 | if (info->valid & ACPI_VALID_CID) { | ||
1262 | for (i=0; i < info->compatibility_id.count; i++) { | ||
1263 | if (!strcmp(PCI_ROOT_HID_STRING, | ||
1264 | info->compatibility_id.id[i].value)) { | ||
1265 | acpi_os_free(buffer.pointer); | ||
1266 | return 1; | ||
1267 | } | ||
1268 | } | ||
1269 | } | ||
1270 | } | ||
1271 | return 0; | ||
1272 | } | ||
1273 | 1375 | ||
1274 | static acpi_status | 1376 | static acpi_status |
1275 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | 1377 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) |
1276 | { | 1378 | { |
1277 | int *count = (int *)context; | 1379 | int *count = (int *)context; |
1278 | 1380 | ||
1279 | if (is_root_bridge(handle)) { | 1381 | if (acpi_root_bridge(handle)) { |
1280 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1382 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1281 | handle_hotplug_event_bridge, NULL); | 1383 | handle_hotplug_event_bridge, NULL); |
1282 | (*count)++; | 1384 | (*count)++; |
@@ -1373,26 +1475,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) | |||
1373 | } | 1475 | } |
1374 | #endif | 1476 | #endif |
1375 | 1477 | ||
1376 | /* search matching slot from id */ | ||
1377 | struct acpiphp_slot *get_slot_from_id(int id) | ||
1378 | { | ||
1379 | struct list_head *node; | ||
1380 | struct acpiphp_bridge *bridge; | ||
1381 | struct acpiphp_slot *slot; | ||
1382 | |||
1383 | list_for_each (node, &bridge_list) { | ||
1384 | bridge = (struct acpiphp_bridge *)node; | ||
1385 | for (slot = bridge->slots; slot; slot = slot->next) | ||
1386 | if (slot->id == id) | ||
1387 | return slot; | ||
1388 | } | ||
1389 | |||
1390 | /* should never happen! */ | ||
1391 | err("%s: no object for id %d\n", __FUNCTION__, id); | ||
1392 | WARN_ON(1); | ||
1393 | return NULL; | ||
1394 | } | ||
1395 | |||
1396 | 1478 | ||
1397 | /** | 1479 | /** |
1398 | * acpiphp_enable_slot - power on slot | 1480 | * acpiphp_enable_slot - power on slot |
@@ -1401,7 +1483,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
1401 | { | 1483 | { |
1402 | int retval; | 1484 | int retval; |
1403 | 1485 | ||
1404 | down(&slot->crit_sect); | 1486 | mutex_lock(&slot->crit_sect); |
1405 | 1487 | ||
1406 | /* wake up all functions */ | 1488 | /* wake up all functions */ |
1407 | retval = power_on_slot(slot); | 1489 | retval = power_on_slot(slot); |
@@ -1413,7 +1495,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
1413 | retval = enable_device(slot); | 1495 | retval = enable_device(slot); |
1414 | 1496 | ||
1415 | err_exit: | 1497 | err_exit: |
1416 | up(&slot->crit_sect); | 1498 | mutex_unlock(&slot->crit_sect); |
1417 | return retval; | 1499 | return retval; |
1418 | } | 1500 | } |
1419 | 1501 | ||
@@ -1424,7 +1506,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) | |||
1424 | { | 1506 | { |
1425 | int retval = 0; | 1507 | int retval = 0; |
1426 | 1508 | ||
1427 | down(&slot->crit_sect); | 1509 | mutex_lock(&slot->crit_sect); |
1428 | 1510 | ||
1429 | /* unconfigure all functions */ | 1511 | /* unconfigure all functions */ |
1430 | retval = disable_device(slot); | 1512 | retval = disable_device(slot); |
@@ -1437,7 +1519,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) | |||
1437 | goto err_exit; | 1519 | goto err_exit; |
1438 | 1520 | ||
1439 | err_exit: | 1521 | err_exit: |
1440 | up(&slot->crit_sect); | 1522 | mutex_unlock(&slot->crit_sect); |
1441 | return retval; | 1523 | return retval; |
1442 | } | 1524 | } |
1443 | 1525 | ||
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 30af105271a2..037ce4c91687 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
@@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) | |||
248 | * with the pci_hotplug subsystem. | 248 | * with the pci_hotplug subsystem. |
249 | */ | 249 | */ |
250 | for (i = first; i <= last; ++i) { | 250 | for (i = first; i <= last; ++i) { |
251 | slot = kmalloc(sizeof (struct slot), GFP_KERNEL); | 251 | slot = kzalloc(sizeof (struct slot), GFP_KERNEL); |
252 | if (!slot) | 252 | if (!slot) |
253 | goto error; | 253 | goto error; |
254 | memset(slot, 0, sizeof (struct slot)); | ||
255 | 254 | ||
256 | hotplug_slot = | 255 | hotplug_slot = |
257 | kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); | 256 | kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); |
258 | if (!hotplug_slot) | 257 | if (!hotplug_slot) |
259 | goto error_slot; | 258 | goto error_slot; |
260 | memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); | ||
261 | slot->hotplug_slot = hotplug_slot; | 259 | slot->hotplug_slot = hotplug_slot; |
262 | 260 | ||
263 | info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); | 261 | info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); |
264 | if (!info) | 262 | if (!info) |
265 | goto error_hpslot; | 263 | goto error_hpslot; |
266 | memset(info, 0, sizeof (struct hotplug_slot_info)); | ||
267 | hotplug_slot->info = info; | 264 | hotplug_slot->info = info; |
268 | 265 | ||
269 | name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | 266 | name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index cb88404c89fe..c74e9e37e76b 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <asm/io.h> /* for read? and write? functions */ | 33 | #include <asm/io.h> /* for read? and write? functions */ |
34 | #include <linux/delay.h> /* for delays */ | 34 | #include <linux/delay.h> /* for delays */ |
35 | #include <linux/mutex.h> | ||
35 | 36 | ||
36 | #define MY_NAME "cpqphp" | 37 | #define MY_NAME "cpqphp" |
37 | 38 | ||
@@ -286,7 +287,7 @@ struct event_info { | |||
286 | struct controller { | 287 | struct controller { |
287 | struct controller *next; | 288 | struct controller *next; |
288 | u32 ctrl_int_comp; | 289 | u32 ctrl_int_comp; |
289 | struct semaphore crit_sect; /* critical section semaphore */ | 290 | struct mutex crit_sect; /* critical section mutex */ |
290 | void __iomem *hpc_reg; /* cookie for our pci controller location */ | 291 | void __iomem *hpc_reg; /* cookie for our pci controller location */ |
291 | struct pci_resource *mem_head; | 292 | struct pci_resource *mem_head; |
292 | struct pci_resource *p_mem_head; | 293 | struct pci_resource *p_mem_head; |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b3659ffccac9..9bc1deb8df52 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
347 | slot_number = ctrl->first_slot; | 347 | slot_number = ctrl->first_slot; |
348 | 348 | ||
349 | while (number_of_slots) { | 349 | while (number_of_slots) { |
350 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); | 350 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
351 | if (!slot) | 351 | if (!slot) |
352 | goto error; | 352 | goto error; |
353 | 353 | ||
354 | memset(slot, 0, sizeof(struct slot)); | 354 | slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), |
355 | slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)), | ||
356 | GFP_KERNEL); | 355 | GFP_KERNEL); |
357 | if (!slot->hotplug_slot) | 356 | if (!slot->hotplug_slot) |
358 | goto error_slot; | 357 | goto error_slot; |
359 | hotplug_slot = slot->hotplug_slot; | 358 | hotplug_slot = slot->hotplug_slot; |
360 | memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); | ||
361 | 359 | ||
362 | hotplug_slot->info = | 360 | hotplug_slot->info = |
363 | kmalloc(sizeof(*(hotplug_slot->info)), | 361 | kzalloc(sizeof(*(hotplug_slot->info)), |
364 | GFP_KERNEL); | 362 | GFP_KERNEL); |
365 | if (!hotplug_slot->info) | 363 | if (!hotplug_slot->info) |
366 | goto error_hpslot; | 364 | goto error_hpslot; |
367 | hotplug_slot_info = hotplug_slot->info; | 365 | hotplug_slot_info = hotplug_slot->info; |
368 | memset(hotplug_slot_info, 0, | ||
369 | sizeof(struct hotplug_slot_info)); | ||
370 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | 366 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
371 | 367 | ||
372 | if (!hotplug_slot->name) | 368 | if (!hotplug_slot->name) |
@@ -599,7 +595,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, | |||
599 | hp_slot = func->device - ctrl->slot_device_offset; | 595 | hp_slot = func->device - ctrl->slot_device_offset; |
600 | 596 | ||
601 | // Wait for exclusive access to hardware | 597 | // Wait for exclusive access to hardware |
602 | down(&ctrl->crit_sect); | 598 | mutex_lock(&ctrl->crit_sect); |
603 | 599 | ||
604 | if (status == 1) { | 600 | if (status == 1) { |
605 | amber_LED_on (ctrl, hp_slot); | 601 | amber_LED_on (ctrl, hp_slot); |
@@ -607,7 +603,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, | |||
607 | amber_LED_off (ctrl, hp_slot); | 603 | amber_LED_off (ctrl, hp_slot); |
608 | } else { | 604 | } else { |
609 | // Done with exclusive hardware access | 605 | // Done with exclusive hardware access |
610 | up(&ctrl->crit_sect); | 606 | mutex_unlock(&ctrl->crit_sect); |
611 | return(1); | 607 | return(1); |
612 | } | 608 | } |
613 | 609 | ||
@@ -617,7 +613,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, | |||
617 | wait_for_ctrl_irq (ctrl); | 613 | wait_for_ctrl_irq (ctrl); |
618 | 614 | ||
619 | // Done with exclusive hardware access | 615 | // Done with exclusive hardware access |
620 | up(&ctrl->crit_sect); | 616 | mutex_unlock(&ctrl->crit_sect); |
621 | 617 | ||
622 | return(0); | 618 | return(0); |
623 | } | 619 | } |
@@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
854 | goto err_disable_device; | 850 | goto err_disable_device; |
855 | } | 851 | } |
856 | 852 | ||
857 | ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); | 853 | ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); |
858 | if (!ctrl) { | 854 | if (!ctrl) { |
859 | err("%s : out of memory\n", __FUNCTION__); | 855 | err("%s : out of memory\n", __FUNCTION__); |
860 | rc = -ENOMEM; | 856 | rc = -ENOMEM; |
861 | goto err_disable_device; | 857 | goto err_disable_device; |
862 | } | 858 | } |
863 | memset(ctrl, 0, sizeof(struct controller)); | ||
864 | 859 | ||
865 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); | 860 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); |
866 | if (rc) { | 861 | if (rc) { |
@@ -1084,7 +1079,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1084 | dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, | 1079 | dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, |
1085 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); | 1080 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); |
1086 | 1081 | ||
1087 | init_MUTEX(&ctrl->crit_sect); | 1082 | mutex_init(&ctrl->crit_sect); |
1088 | init_waitqueue_head(&ctrl->queue); | 1083 | init_waitqueue_head(&ctrl->queue); |
1089 | 1084 | ||
1090 | /* initialize our threads if they haven't already been started up */ | 1085 | /* initialize our threads if they haven't already been started up */ |
@@ -1223,7 +1218,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1223 | 1218 | ||
1224 | // turn off empty slots here unless command line option "ON" set | 1219 | // turn off empty slots here unless command line option "ON" set |
1225 | // Wait for exclusive access to hardware | 1220 | // Wait for exclusive access to hardware |
1226 | down(&ctrl->crit_sect); | 1221 | mutex_lock(&ctrl->crit_sect); |
1227 | 1222 | ||
1228 | num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; | 1223 | num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; |
1229 | 1224 | ||
@@ -1270,12 +1265,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1270 | rc = init_SERR(ctrl); | 1265 | rc = init_SERR(ctrl); |
1271 | if (rc) { | 1266 | if (rc) { |
1272 | err("init_SERR failed\n"); | 1267 | err("init_SERR failed\n"); |
1273 | up(&ctrl->crit_sect); | 1268 | mutex_unlock(&ctrl->crit_sect); |
1274 | goto err_free_irq; | 1269 | goto err_free_irq; |
1275 | } | 1270 | } |
1276 | 1271 | ||
1277 | // Done with exclusive hardware access | 1272 | // Done with exclusive hardware access |
1278 | up(&ctrl->crit_sect); | 1273 | mutex_unlock(&ctrl->crit_sect); |
1279 | 1274 | ||
1280 | cpqhp_create_debugfs_files(ctrl); | 1275 | cpqhp_create_debugfs_files(ctrl); |
1281 | 1276 | ||
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 771ed34b1819..55d2dc7e39ca 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1282 | u8 hp_slot; | 1282 | u8 hp_slot; |
1283 | u8 temp_byte; | 1283 | u8 temp_byte; |
1284 | u8 adapter_speed; | 1284 | u8 adapter_speed; |
1285 | u32 index; | ||
1286 | u32 rc = 0; | 1285 | u32 rc = 0; |
1287 | u32 src = 8; | ||
1288 | 1286 | ||
1289 | hp_slot = func->device - ctrl->slot_device_offset; | 1287 | hp_slot = func->device - ctrl->slot_device_offset; |
1290 | 1288 | ||
@@ -1299,7 +1297,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1299 | **********************************/ | 1297 | **********************************/ |
1300 | rc = CARD_FUNCTIONING; | 1298 | rc = CARD_FUNCTIONING; |
1301 | } else { | 1299 | } else { |
1302 | down(&ctrl->crit_sect); | 1300 | mutex_lock(&ctrl->crit_sect); |
1303 | 1301 | ||
1304 | /* turn on board without attaching to the bus */ | 1302 | /* turn on board without attaching to the bus */ |
1305 | enable_slot_power (ctrl, hp_slot); | 1303 | enable_slot_power (ctrl, hp_slot); |
@@ -1333,12 +1331,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1333 | /* Wait for SOBS to be unset */ | 1331 | /* Wait for SOBS to be unset */ |
1334 | wait_for_ctrl_irq (ctrl); | 1332 | wait_for_ctrl_irq (ctrl); |
1335 | 1333 | ||
1336 | up(&ctrl->crit_sect); | 1334 | mutex_unlock(&ctrl->crit_sect); |
1337 | 1335 | ||
1338 | if (rc) | 1336 | if (rc) |
1339 | return rc; | 1337 | return rc; |
1340 | 1338 | ||
1341 | down(&ctrl->crit_sect); | 1339 | mutex_lock(&ctrl->crit_sect); |
1342 | 1340 | ||
1343 | slot_enable (ctrl, hp_slot); | 1341 | slot_enable (ctrl, hp_slot); |
1344 | green_LED_blink (ctrl, hp_slot); | 1342 | green_LED_blink (ctrl, hp_slot); |
@@ -1350,7 +1348,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1350 | /* Wait for SOBS to be unset */ | 1348 | /* Wait for SOBS to be unset */ |
1351 | wait_for_ctrl_irq (ctrl); | 1349 | wait_for_ctrl_irq (ctrl); |
1352 | 1350 | ||
1353 | up(&ctrl->crit_sect); | 1351 | mutex_unlock(&ctrl->crit_sect); |
1354 | 1352 | ||
1355 | /* Wait for ~1 second because of hot plug spec */ | 1353 | /* Wait for ~1 second because of hot plug spec */ |
1356 | long_delay(1*HZ); | 1354 | long_delay(1*HZ); |
@@ -1368,76 +1366,30 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1368 | 1366 | ||
1369 | rc = cpqhp_configure_board(ctrl, func); | 1367 | rc = cpqhp_configure_board(ctrl, func); |
1370 | 1368 | ||
1371 | if (rc || src) { | 1369 | /* If configuration fails, turn it off |
1372 | /* If configuration fails, turn it off | 1370 | * Get slot won't work for devices behind |
1373 | * Get slot won't work for devices behind | 1371 | * bridges, but in this case it will always be |
1374 | * bridges, but in this case it will always be | 1372 | * called for the "base" bus/dev/func of an |
1375 | * called for the "base" bus/dev/func of an | 1373 | * adapter. */ |
1376 | * adapter. */ | ||
1377 | 1374 | ||
1378 | down(&ctrl->crit_sect); | 1375 | mutex_lock(&ctrl->crit_sect); |
1379 | 1376 | ||
1380 | amber_LED_on (ctrl, hp_slot); | 1377 | amber_LED_on (ctrl, hp_slot); |
1381 | green_LED_off (ctrl, hp_slot); | 1378 | green_LED_off (ctrl, hp_slot); |
1382 | slot_disable (ctrl, hp_slot); | 1379 | slot_disable (ctrl, hp_slot); |
1383 | |||
1384 | set_SOGO(ctrl); | ||
1385 | |||
1386 | /* Wait for SOBS to be unset */ | ||
1387 | wait_for_ctrl_irq (ctrl); | ||
1388 | |||
1389 | up(&ctrl->crit_sect); | ||
1390 | |||
1391 | if (rc) | ||
1392 | return rc; | ||
1393 | else | ||
1394 | return 1; | ||
1395 | } | ||
1396 | |||
1397 | func->status = 0; | ||
1398 | func->switch_save = 0x10; | ||
1399 | |||
1400 | index = 1; | ||
1401 | while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { | ||
1402 | rc |= cpqhp_configure_board(ctrl, func); | ||
1403 | index++; | ||
1404 | } | ||
1405 | |||
1406 | if (rc) { | ||
1407 | /* If configuration fails, turn it off | ||
1408 | * Get slot won't work for devices behind | ||
1409 | * bridges, but in this case it will always be | ||
1410 | * called for the "base" bus/dev/func of an | ||
1411 | * adapter. */ | ||
1412 | |||
1413 | down(&ctrl->crit_sect); | ||
1414 | |||
1415 | amber_LED_on (ctrl, hp_slot); | ||
1416 | green_LED_off (ctrl, hp_slot); | ||
1417 | slot_disable (ctrl, hp_slot); | ||
1418 | |||
1419 | set_SOGO(ctrl); | ||
1420 | |||
1421 | /* Wait for SOBS to be unset */ | ||
1422 | wait_for_ctrl_irq (ctrl); | ||
1423 | |||
1424 | up(&ctrl->crit_sect); | ||
1425 | |||
1426 | return rc; | ||
1427 | } | ||
1428 | /* Done configuring so turn LED on full time */ | ||
1429 | |||
1430 | down(&ctrl->crit_sect); | ||
1431 | |||
1432 | green_LED_on (ctrl, hp_slot); | ||
1433 | 1380 | ||
1434 | set_SOGO(ctrl); | 1381 | set_SOGO(ctrl); |
1435 | 1382 | ||
1436 | /* Wait for SOBS to be unset */ | 1383 | /* Wait for SOBS to be unset */ |
1437 | wait_for_ctrl_irq (ctrl); | 1384 | wait_for_ctrl_irq (ctrl); |
1438 | 1385 | ||
1439 | up(&ctrl->crit_sect); | 1386 | mutex_unlock(&ctrl->crit_sect); |
1440 | rc = 0; | 1387 | |
1388 | if (rc) | ||
1389 | return rc; | ||
1390 | else | ||
1391 | return 1; | ||
1392 | |||
1441 | } else { | 1393 | } else { |
1442 | /* Something is wrong | 1394 | /* Something is wrong |
1443 | 1395 | ||
@@ -1445,7 +1397,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1445 | * in this case it will always be called for the "base" | 1397 | * in this case it will always be called for the "base" |
1446 | * bus/dev/func of an adapter. */ | 1398 | * bus/dev/func of an adapter. */ |
1447 | 1399 | ||
1448 | down(&ctrl->crit_sect); | 1400 | mutex_lock(&ctrl->crit_sect); |
1449 | 1401 | ||
1450 | amber_LED_on (ctrl, hp_slot); | 1402 | amber_LED_on (ctrl, hp_slot); |
1451 | green_LED_off (ctrl, hp_slot); | 1403 | green_LED_off (ctrl, hp_slot); |
@@ -1456,7 +1408,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1456 | /* Wait for SOBS to be unset */ | 1408 | /* Wait for SOBS to be unset */ |
1457 | wait_for_ctrl_irq (ctrl); | 1409 | wait_for_ctrl_irq (ctrl); |
1458 | 1410 | ||
1459 | up(&ctrl->crit_sect); | 1411 | mutex_unlock(&ctrl->crit_sect); |
1460 | } | 1412 | } |
1461 | 1413 | ||
1462 | } | 1414 | } |
@@ -1488,7 +1440,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1488 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", | 1440 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", |
1489 | __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); | 1441 | __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); |
1490 | 1442 | ||
1491 | down(&ctrl->crit_sect); | 1443 | mutex_lock(&ctrl->crit_sect); |
1492 | 1444 | ||
1493 | /* turn on board without attaching to the bus */ | 1445 | /* turn on board without attaching to the bus */ |
1494 | enable_slot_power(ctrl, hp_slot); | 1446 | enable_slot_power(ctrl, hp_slot); |
@@ -1522,7 +1474,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1522 | /* Wait for SOBS to be unset */ | 1474 | /* Wait for SOBS to be unset */ |
1523 | wait_for_ctrl_irq(ctrl); | 1475 | wait_for_ctrl_irq(ctrl); |
1524 | 1476 | ||
1525 | up(&ctrl->crit_sect); | 1477 | mutex_unlock(&ctrl->crit_sect); |
1526 | 1478 | ||
1527 | if (rc) | 1479 | if (rc) |
1528 | return rc; | 1480 | return rc; |
@@ -1532,7 +1484,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1532 | /* turn on board and blink green LED */ | 1484 | /* turn on board and blink green LED */ |
1533 | 1485 | ||
1534 | dbg("%s: before down\n", __FUNCTION__); | 1486 | dbg("%s: before down\n", __FUNCTION__); |
1535 | down(&ctrl->crit_sect); | 1487 | mutex_lock(&ctrl->crit_sect); |
1536 | dbg("%s: after down\n", __FUNCTION__); | 1488 | dbg("%s: after down\n", __FUNCTION__); |
1537 | 1489 | ||
1538 | dbg("%s: before slot_enable\n", __FUNCTION__); | 1490 | dbg("%s: before slot_enable\n", __FUNCTION__); |
@@ -1553,7 +1505,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1553 | dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); | 1505 | dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); |
1554 | 1506 | ||
1555 | dbg("%s: before up\n", __FUNCTION__); | 1507 | dbg("%s: before up\n", __FUNCTION__); |
1556 | up(&ctrl->crit_sect); | 1508 | mutex_unlock(&ctrl->crit_sect); |
1557 | dbg("%s: after up\n", __FUNCTION__); | 1509 | dbg("%s: after up\n", __FUNCTION__); |
1558 | 1510 | ||
1559 | /* Wait for ~1 second because of hot plug spec */ | 1511 | /* Wait for ~1 second because of hot plug spec */ |
@@ -1607,7 +1559,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1607 | cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); | 1559 | cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); |
1608 | 1560 | ||
1609 | if (rc) { | 1561 | if (rc) { |
1610 | down(&ctrl->crit_sect); | 1562 | mutex_lock(&ctrl->crit_sect); |
1611 | 1563 | ||
1612 | amber_LED_on (ctrl, hp_slot); | 1564 | amber_LED_on (ctrl, hp_slot); |
1613 | green_LED_off (ctrl, hp_slot); | 1565 | green_LED_off (ctrl, hp_slot); |
@@ -1618,7 +1570,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1618 | /* Wait for SOBS to be unset */ | 1570 | /* Wait for SOBS to be unset */ |
1619 | wait_for_ctrl_irq (ctrl); | 1571 | wait_for_ctrl_irq (ctrl); |
1620 | 1572 | ||
1621 | up(&ctrl->crit_sect); | 1573 | mutex_unlock(&ctrl->crit_sect); |
1622 | return rc; | 1574 | return rc; |
1623 | } else { | 1575 | } else { |
1624 | cpqhp_save_slot_config(ctrl, func); | 1576 | cpqhp_save_slot_config(ctrl, func); |
@@ -1640,7 +1592,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1640 | } | 1592 | } |
1641 | } while (new_slot); | 1593 | } while (new_slot); |
1642 | 1594 | ||
1643 | down(&ctrl->crit_sect); | 1595 | mutex_lock(&ctrl->crit_sect); |
1644 | 1596 | ||
1645 | green_LED_on (ctrl, hp_slot); | 1597 | green_LED_on (ctrl, hp_slot); |
1646 | 1598 | ||
@@ -1649,9 +1601,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1649 | /* Wait for SOBS to be unset */ | 1601 | /* Wait for SOBS to be unset */ |
1650 | wait_for_ctrl_irq (ctrl); | 1602 | wait_for_ctrl_irq (ctrl); |
1651 | 1603 | ||
1652 | up(&ctrl->crit_sect); | 1604 | mutex_unlock(&ctrl->crit_sect); |
1653 | } else { | 1605 | } else { |
1654 | down(&ctrl->crit_sect); | 1606 | mutex_lock(&ctrl->crit_sect); |
1655 | 1607 | ||
1656 | amber_LED_on (ctrl, hp_slot); | 1608 | amber_LED_on (ctrl, hp_slot); |
1657 | green_LED_off (ctrl, hp_slot); | 1609 | green_LED_off (ctrl, hp_slot); |
@@ -1662,7 +1614,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1662 | /* Wait for SOBS to be unset */ | 1614 | /* Wait for SOBS to be unset */ |
1663 | wait_for_ctrl_irq (ctrl); | 1615 | wait_for_ctrl_irq (ctrl); |
1664 | 1616 | ||
1665 | up(&ctrl->crit_sect); | 1617 | mutex_unlock(&ctrl->crit_sect); |
1666 | 1618 | ||
1667 | return rc; | 1619 | return rc; |
1668 | } | 1620 | } |
@@ -1721,7 +1673,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control | |||
1721 | func->status = 0x01; | 1673 | func->status = 0x01; |
1722 | func->configured = 0; | 1674 | func->configured = 0; |
1723 | 1675 | ||
1724 | down(&ctrl->crit_sect); | 1676 | mutex_lock(&ctrl->crit_sect); |
1725 | 1677 | ||
1726 | green_LED_off (ctrl, hp_slot); | 1678 | green_LED_off (ctrl, hp_slot); |
1727 | slot_disable (ctrl, hp_slot); | 1679 | slot_disable (ctrl, hp_slot); |
@@ -1736,7 +1688,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control | |||
1736 | /* Wait for SOBS to be unset */ | 1688 | /* Wait for SOBS to be unset */ |
1737 | wait_for_ctrl_irq (ctrl); | 1689 | wait_for_ctrl_irq (ctrl); |
1738 | 1690 | ||
1739 | up(&ctrl->crit_sect); | 1691 | mutex_unlock(&ctrl->crit_sect); |
1740 | 1692 | ||
1741 | if (!replace_flag && ctrl->add_support) { | 1693 | if (!replace_flag && ctrl->add_support) { |
1742 | while (func) { | 1694 | while (func) { |
@@ -1899,7 +1851,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1899 | dbg("button cancel\n"); | 1851 | dbg("button cancel\n"); |
1900 | del_timer(&p_slot->task_event); | 1852 | del_timer(&p_slot->task_event); |
1901 | 1853 | ||
1902 | down(&ctrl->crit_sect); | 1854 | mutex_lock(&ctrl->crit_sect); |
1903 | 1855 | ||
1904 | if (p_slot->state == BLINKINGOFF_STATE) { | 1856 | if (p_slot->state == BLINKINGOFF_STATE) { |
1905 | /* slot is on */ | 1857 | /* slot is on */ |
@@ -1922,7 +1874,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1922 | /* Wait for SOBS to be unset */ | 1874 | /* Wait for SOBS to be unset */ |
1923 | wait_for_ctrl_irq (ctrl); | 1875 | wait_for_ctrl_irq (ctrl); |
1924 | 1876 | ||
1925 | up(&ctrl->crit_sect); | 1877 | mutex_unlock(&ctrl->crit_sect); |
1926 | } | 1878 | } |
1927 | /*** button Released (No action on press...) */ | 1879 | /*** button Released (No action on press...) */ |
1928 | else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { | 1880 | else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { |
@@ -1937,7 +1889,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1937 | p_slot->state = BLINKINGON_STATE; | 1889 | p_slot->state = BLINKINGON_STATE; |
1938 | info(msg_button_on, p_slot->number); | 1890 | info(msg_button_on, p_slot->number); |
1939 | } | 1891 | } |
1940 | down(&ctrl->crit_sect); | 1892 | mutex_lock(&ctrl->crit_sect); |
1941 | 1893 | ||
1942 | dbg("blink green LED and turn off amber\n"); | 1894 | dbg("blink green LED and turn off amber\n"); |
1943 | 1895 | ||
@@ -1949,7 +1901,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1949 | /* Wait for SOBS to be unset */ | 1901 | /* Wait for SOBS to be unset */ |
1950 | wait_for_ctrl_irq (ctrl); | 1902 | wait_for_ctrl_irq (ctrl); |
1951 | 1903 | ||
1952 | up(&ctrl->crit_sect); | 1904 | mutex_unlock(&ctrl->crit_sect); |
1953 | init_timer(&p_slot->task_event); | 1905 | init_timer(&p_slot->task_event); |
1954 | p_slot->hp_slot = hp_slot; | 1906 | p_slot->hp_slot = hp_slot; |
1955 | p_slot->ctrl = ctrl; | 1907 | p_slot->ctrl = ctrl; |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 060d74775d7b..71b80c23e8ce 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev) | |||
95 | struct hotplug_slot *slot; | 95 | struct hotplug_slot *slot; |
96 | int retval = -ENOMEM; | 96 | int retval = -ENOMEM; |
97 | 97 | ||
98 | slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | 98 | slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); |
99 | if (!slot) | 99 | if (!slot) |
100 | goto error; | 100 | goto error; |
101 | memset(slot, 0, sizeof(*slot)); | ||
102 | 101 | ||
103 | slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); | 102 | slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); |
104 | if (!slot->info) | 103 | if (!slot->info) |
105 | goto error_slot; | 104 | goto error_slot; |
106 | memset(slot->info, 0, sizeof(struct hotplug_slot_info)); | ||
107 | 105 | ||
108 | slot->info->power_status = 1; | 106 | slot->info->power_status = 1; |
109 | slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | 107 | slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; |
@@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
227 | { | 225 | { |
228 | unsigned int devfn; | 226 | unsigned int devfn; |
229 | struct pci_dev *dev; | 227 | struct pci_dev *dev; |
230 | dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | 228 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); |
231 | if (!dev) | 229 | if (!dev) |
232 | return; | 230 | return; |
233 | 231 | ||
234 | memset(dev, 0, sizeof(dev)); | ||
235 | dev->bus = (struct pci_bus*)bus; | 232 | dev->bus = (struct pci_bus*)bus; |
236 | dev->sysdata = bus->sysdata; | 233 | dev->sysdata = bus->sysdata; |
237 | for (devfn = 0; devfn < 0x100; devfn += 8) { | 234 | for (devfn = 0; devfn < 0x100; devfn += 8) { |
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index c22e0284d7b1..dba6d8ca9bda 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h | |||
@@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void); | |||
406 | //---------------------------------------------------------------------------- | 406 | //---------------------------------------------------------------------------- |
407 | // HPC return codes | 407 | // HPC return codes |
408 | //---------------------------------------------------------------------------- | 408 | //---------------------------------------------------------------------------- |
409 | #define FALSE 0x00 | ||
410 | #define TRUE 0x01 | ||
411 | #define HPC_ERROR 0xFF | 409 | #define HPC_ERROR 0xFF |
412 | 410 | ||
413 | //----------------------------------------------------------------------------- | 411 | //----------------------------------------------------------------------------- |
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index dc59da675c08..e13d5b87241a 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs) | |||
1141 | goto error_power; | 1141 | goto error_power; |
1142 | } | 1142 | } |
1143 | 1143 | ||
1144 | slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); | 1144 | slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); |
1145 | if (!slot_cur->func) { | 1145 | if (!slot_cur->func) { |
1146 | /* We cannot do update_slot_info here, since no memory for | 1146 | /* We cannot do update_slot_info here, since no memory for |
1147 | * kmalloc n.e.ways, and update_slot_info allocates some */ | 1147 | * kmalloc n.e.ways, and update_slot_info allocates some */ |
@@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs) | |||
1149 | rc = -ENOMEM; | 1149 | rc = -ENOMEM; |
1150 | goto error_power; | 1150 | goto error_power; |
1151 | } | 1151 | } |
1152 | memset(slot_cur->func, 0, sizeof(struct pci_func)); | ||
1153 | slot_cur->func->busno = slot_cur->bus; | 1152 | slot_cur->func->busno = slot_cur->bus; |
1154 | slot_cur->func->device = slot_cur->device; | 1153 | slot_cur->func->device = slot_cur->device; |
1155 | for (i = 0; i < 4; i++) | 1154 | for (i = 0; i < 4; i++) |
@@ -1240,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) | |||
1240 | } | 1239 | } |
1241 | 1240 | ||
1242 | flag = slot_cur->flag; | 1241 | flag = slot_cur->flag; |
1243 | slot_cur->flag = TRUE; | 1242 | slot_cur->flag = 1; |
1244 | 1243 | ||
1245 | if (flag == TRUE) { | 1244 | if (flag == 1) { |
1246 | rc = validate(slot_cur, DISABLE); | 1245 | rc = validate(slot_cur, DISABLE); |
1247 | /* checking if powered off already & valid slot # */ | 1246 | /* checking if powered off already & valid slot # */ |
1248 | if (rc) | 1247 | if (rc) |
@@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) | |||
1252 | 1251 | ||
1253 | if (slot_cur->func == NULL) { | 1252 | if (slot_cur->func == NULL) { |
1254 | /* We need this for fncs's that were there on bootup */ | 1253 | /* We need this for fncs's that were there on bootup */ |
1255 | slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); | 1254 | slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); |
1256 | if (!slot_cur->func) { | 1255 | if (!slot_cur->func) { |
1257 | err("out of system memory\n"); | 1256 | err("out of system memory\n"); |
1258 | rc = -ENOMEM; | 1257 | rc = -ENOMEM; |
1259 | goto error; | 1258 | goto error; |
1260 | } | 1259 | } |
1261 | memset(slot_cur->func, 0, sizeof(struct pci_func)); | ||
1262 | slot_cur->func->busno = slot_cur->bus; | 1260 | slot_cur->func->busno = slot_cur->bus; |
1263 | slot_cur->func->device = slot_cur->device; | 1261 | slot_cur->func->device = slot_cur->device; |
1264 | } | 1262 | } |
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index aea1187c73ad..05e4f5a1927a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c | |||
@@ -72,13 +72,7 @@ static int ebda_rio_table (void); | |||
72 | 72 | ||
73 | static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) | 73 | static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) |
74 | { | 74 | { |
75 | struct ebda_hpc_list *list; | 75 | return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL); |
76 | |||
77 | list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL); | ||
78 | if (!list) | ||
79 | return NULL; | ||
80 | memset (list, 0, sizeof (*list)); | ||
81 | return list; | ||
82 | } | 76 | } |
83 | 77 | ||
84 | static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) | 78 | static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) |
@@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) | |||
87 | struct ebda_hpc_slot *slots; | 81 | struct ebda_hpc_slot *slots; |
88 | struct ebda_hpc_bus *buses; | 82 | struct ebda_hpc_bus *buses; |
89 | 83 | ||
90 | controller = kmalloc (sizeof (struct controller), GFP_KERNEL); | 84 | controller = kzalloc(sizeof(struct controller), GFP_KERNEL); |
91 | if (!controller) | 85 | if (!controller) |
92 | goto error; | 86 | goto error; |
93 | memset (controller, 0, sizeof (*controller)); | ||
94 | 87 | ||
95 | slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL); | 88 | slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL); |
96 | if (!slots) | 89 | if (!slots) |
97 | goto error_contr; | 90 | goto error_contr; |
98 | memset (slots, 0, sizeof (*slots) * slot_count); | ||
99 | controller->slots = slots; | 91 | controller->slots = slots; |
100 | 92 | ||
101 | buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL); | 93 | buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL); |
102 | if (!buses) | 94 | if (!buses) |
103 | goto error_slots; | 95 | goto error_slots; |
104 | memset (buses, 0, sizeof (*buses) * bus_count); | ||
105 | controller->buses = buses; | 96 | controller->buses = buses; |
106 | 97 | ||
107 | return controller; | 98 | return controller; |
@@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller) | |||
122 | 113 | ||
123 | static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void) | 114 | static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void) |
124 | { | 115 | { |
125 | struct ebda_rsrc_list *list; | 116 | return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL); |
126 | |||
127 | list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL); | ||
128 | if (!list) | ||
129 | return NULL; | ||
130 | memset (list, 0, sizeof (*list)); | ||
131 | return list; | ||
132 | } | 117 | } |
133 | 118 | ||
134 | static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void) | 119 | static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void) |
135 | { | 120 | { |
136 | struct ebda_pci_rsrc *resource; | 121 | return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL); |
137 | |||
138 | resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL); | ||
139 | if (!resource) | ||
140 | return NULL; | ||
141 | memset (resource, 0, sizeof (*resource)); | ||
142 | return resource; | ||
143 | } | 122 | } |
144 | 123 | ||
145 | static void __init print_bus_info (void) | 124 | static void __init print_bus_info (void) |
@@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void) | |||
390 | debug ("now enter io table ---\n"); | 369 | debug ("now enter io table ---\n"); |
391 | debug ("rio blk id: %x\n", blk_id); | 370 | debug ("rio blk id: %x\n", blk_id); |
392 | 371 | ||
393 | rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL); | 372 | rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL); |
394 | if (!rio_table_ptr) | 373 | if (!rio_table_ptr) |
395 | return -ENOMEM; | 374 | return -ENOMEM; |
396 | memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) ); | ||
397 | rio_table_ptr->ver_num = readb (io_mem + offset); | 375 | rio_table_ptr->ver_num = readb (io_mem + offset); |
398 | rio_table_ptr->scal_count = readb (io_mem + offset + 1); | 376 | rio_table_ptr->scal_count = readb (io_mem + offset + 1); |
399 | rio_table_ptr->riodev_count = readb (io_mem + offset + 2); | 377 | rio_table_ptr->riodev_count = readb (io_mem + offset + 2); |
@@ -445,10 +423,9 @@ static int __init ebda_rio_table (void) | |||
445 | 423 | ||
446 | // we do concern about rio details | 424 | // we do concern about rio details |
447 | for (i = 0; i < rio_table_ptr->riodev_count; i++) { | 425 | for (i = 0; i < rio_table_ptr->riodev_count; i++) { |
448 | rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); | 426 | rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL); |
449 | if (!rio_detail_ptr) | 427 | if (!rio_detail_ptr) |
450 | return -ENOMEM; | 428 | return -ENOMEM; |
451 | memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); | ||
452 | rio_detail_ptr->rio_node_id = readb (io_mem + offset); | 429 | rio_detail_ptr->rio_node_id = readb (io_mem + offset); |
453 | rio_detail_ptr->bbar = readl (io_mem + offset + 1); | 430 | rio_detail_ptr->bbar = readl (io_mem + offset + 1); |
454 | rio_detail_ptr->rio_type = readb (io_mem + offset + 5); | 431 | rio_detail_ptr->rio_type = readb (io_mem + offset + 5); |
@@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void) | |||
503 | rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); | 480 | rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); |
504 | opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); | 481 | opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); |
505 | if (!opt_rio_ptr) { | 482 | if (!opt_rio_ptr) { |
506 | opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); | 483 | opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL); |
507 | if (!opt_rio_ptr) | 484 | if (!opt_rio_ptr) |
508 | return -ENOMEM; | 485 | return -ENOMEM; |
509 | memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); | ||
510 | opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; | 486 | opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; |
511 | opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; | 487 | opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; |
512 | opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; | 488 | opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; |
@@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void) | |||
546 | rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); | 522 | rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); |
547 | opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); | 523 | opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); |
548 | if (!opt_rio_lo_ptr) { | 524 | if (!opt_rio_lo_ptr) { |
549 | opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); | 525 | opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL); |
550 | if (!opt_rio_lo_ptr) | 526 | if (!opt_rio_lo_ptr) |
551 | return -ENOMEM; | 527 | return -ENOMEM; |
552 | memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); | ||
553 | opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; | 528 | opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; |
554 | opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; | 529 | opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; |
555 | opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; | 530 | opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; |
@@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void) | |||
842 | 817 | ||
843 | bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num); | 818 | bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num); |
844 | if (!bus_info_ptr2) { | 819 | if (!bus_info_ptr2) { |
845 | bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL); | 820 | bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL); |
846 | if (!bus_info_ptr1) { | 821 | if (!bus_info_ptr1) { |
847 | rc = -ENOMEM; | 822 | rc = -ENOMEM; |
848 | goto error_no_hp_slot; | 823 | goto error_no_hp_slot; |
849 | } | 824 | } |
850 | memset (bus_info_ptr1, 0, sizeof (struct bus_info)); | ||
851 | bus_info_ptr1->slot_min = slot_ptr->slot_num; | 825 | bus_info_ptr1->slot_min = slot_ptr->slot_num; |
852 | bus_info_ptr1->slot_max = slot_ptr->slot_num; | 826 | bus_info_ptr1->slot_max = slot_ptr->slot_num; |
853 | bus_info_ptr1->slot_count += 1; | 827 | bus_info_ptr1->slot_count += 1; |
@@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void) | |||
946 | // register slots with hpc core as well as create linked list of ibm slot | 920 | // register slots with hpc core as well as create linked list of ibm slot |
947 | for (index = 0; index < hpc_ptr->slot_count; index++) { | 921 | for (index = 0; index < hpc_ptr->slot_count; index++) { |
948 | 922 | ||
949 | hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); | 923 | hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); |
950 | if (!hp_slot_ptr) { | 924 | if (!hp_slot_ptr) { |
951 | rc = -ENOMEM; | 925 | rc = -ENOMEM; |
952 | goto error_no_hp_slot; | 926 | goto error_no_hp_slot; |
953 | } | 927 | } |
954 | memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr)); | ||
955 | 928 | ||
956 | hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL); | 929 | hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); |
957 | if (!hp_slot_ptr->info) { | 930 | if (!hp_slot_ptr->info) { |
958 | rc = -ENOMEM; | 931 | rc = -ENOMEM; |
959 | goto error_no_hp_info; | 932 | goto error_no_hp_info; |
960 | } | 933 | } |
961 | memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info)); | ||
962 | 934 | ||
963 | hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); | 935 | hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); |
964 | if (!hp_slot_ptr->name) { | 936 | if (!hp_slot_ptr->name) { |
@@ -966,14 +938,13 @@ static int __init ebda_rsrc_controller (void) | |||
966 | goto error_no_hp_name; | 938 | goto error_no_hp_name; |
967 | } | 939 | } |
968 | 940 | ||
969 | tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL); | 941 | tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL); |
970 | if (!tmp_slot) { | 942 | if (!tmp_slot) { |
971 | rc = -ENOMEM; | 943 | rc = -ENOMEM; |
972 | goto error_no_slot; | 944 | goto error_no_slot; |
973 | } | 945 | } |
974 | memset(tmp_slot, 0, sizeof(*tmp_slot)); | ||
975 | 946 | ||
976 | tmp_slot->flag = TRUE; | 947 | tmp_slot->flag = 1; |
977 | 948 | ||
978 | tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; | 949 | tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; |
979 | if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) | 950 | if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) |
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 1a3eb8d3d4cb..c3ac98a0a6a6 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c | |||
@@ -34,9 +34,11 @@ | |||
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/mutex.h> | ||
38 | |||
37 | #include "ibmphp.h" | 39 | #include "ibmphp.h" |
38 | 40 | ||
39 | static int to_debug = FALSE; | 41 | static int to_debug = 0; |
40 | #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) | 42 | #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) |
41 | 43 | ||
42 | //---------------------------------------------------------------------------- | 44 | //---------------------------------------------------------------------------- |
@@ -93,15 +95,15 @@ static int to_debug = FALSE; | |||
93 | //---------------------------------------------------------------------------- | 95 | //---------------------------------------------------------------------------- |
94 | // macro utilities | 96 | // macro utilities |
95 | //---------------------------------------------------------------------------- | 97 | //---------------------------------------------------------------------------- |
96 | // if bits 20,22,25,26,27,29,30 are OFF return TRUE | 98 | // if bits 20,22,25,26,27,29,30 are OFF return 1 |
97 | #define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) | 99 | #define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1)) |
98 | 100 | ||
99 | //---------------------------------------------------------------------------- | 101 | //---------------------------------------------------------------------------- |
100 | // global variables | 102 | // global variables |
101 | //---------------------------------------------------------------------------- | 103 | //---------------------------------------------------------------------------- |
102 | static int ibmphp_shutdown; | 104 | static int ibmphp_shutdown; |
103 | static int tid_poll; | 105 | static int tid_poll; |
104 | static struct semaphore sem_hpcaccess; // lock access to HPC | 106 | static struct mutex sem_hpcaccess; // lock access to HPC |
105 | static struct semaphore semOperations; // lock all operations and | 107 | static struct semaphore semOperations; // lock all operations and |
106 | // access to data structures | 108 | // access to data structures |
107 | static struct semaphore sem_exit; // make sure polling thread goes away | 109 | static struct semaphore sem_exit; // make sure polling thread goes away |
@@ -131,11 +133,11 @@ void __init ibmphp_hpc_initvars (void) | |||
131 | { | 133 | { |
132 | debug ("%s - Entry\n", __FUNCTION__); | 134 | debug ("%s - Entry\n", __FUNCTION__); |
133 | 135 | ||
134 | init_MUTEX (&sem_hpcaccess); | 136 | mutex_init(&sem_hpcaccess); |
135 | init_MUTEX (&semOperations); | 137 | init_MUTEX (&semOperations); |
136 | init_MUTEX_LOCKED (&sem_exit); | 138 | init_MUTEX_LOCKED (&sem_exit); |
137 | to_debug = FALSE; | 139 | to_debug = 0; |
138 | ibmphp_shutdown = FALSE; | 140 | ibmphp_shutdown = 0; |
139 | tid_poll = 0; | 141 | tid_poll = 0; |
140 | 142 | ||
141 | debug ("%s - Exit\n", __FUNCTION__); | 143 | debug ("%s - Exit\n", __FUNCTION__); |
@@ -737,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) | |||
737 | // check controller is still not working on the command | 739 | // check controller is still not working on the command |
738 | //-------------------------------------------------------------------- | 740 | //-------------------------------------------------------------------- |
739 | timeout = CMD_COMPLETE_TOUT_SEC; | 741 | timeout = CMD_COMPLETE_TOUT_SEC; |
740 | done = FALSE; | 742 | done = 0; |
741 | while (!done) { | 743 | while (!done) { |
742 | rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, | 744 | rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, |
743 | &status); | 745 | &status); |
744 | if (!rc) { | 746 | if (!rc) { |
745 | if (NEEDTOCHECK_CMDSTATUS (cmd)) { | 747 | if (NEEDTOCHECK_CMDSTATUS (cmd)) { |
746 | if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES) | 748 | if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES) |
747 | done = TRUE; | 749 | done = 1; |
748 | } else | 750 | } else |
749 | done = TRUE; | 751 | done = 1; |
750 | } | 752 | } |
751 | if (!done) { | 753 | if (!done) { |
752 | msleep(1000); | 754 | msleep(1000); |
753 | if (timeout < 1) { | 755 | if (timeout < 1) { |
754 | done = TRUE; | 756 | done = 1; |
755 | err ("%s - Error command complete timeout\n", __FUNCTION__); | 757 | err ("%s - Error command complete timeout\n", __FUNCTION__); |
756 | rc = -EFAULT; | 758 | rc = -EFAULT; |
757 | } else | 759 | } else |
@@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) | |||
778 | *---------------------------------------------------------------------*/ | 780 | *---------------------------------------------------------------------*/ |
779 | static void get_hpc_access (void) | 781 | static void get_hpc_access (void) |
780 | { | 782 | { |
781 | down (&sem_hpcaccess); | 783 | mutex_lock(&sem_hpcaccess); |
782 | } | 784 | } |
783 | 785 | ||
784 | /*---------------------------------------------------------------------- | 786 | /*---------------------------------------------------------------------- |
@@ -786,7 +788,7 @@ static void get_hpc_access (void) | |||
786 | *---------------------------------------------------------------------*/ | 788 | *---------------------------------------------------------------------*/ |
787 | void free_hpc_access (void) | 789 | void free_hpc_access (void) |
788 | { | 790 | { |
789 | up (&sem_hpcaccess); | 791 | mutex_unlock(&sem_hpcaccess); |
790 | } | 792 | } |
791 | 793 | ||
792 | /*---------------------------------------------------------------------- | 794 | /*---------------------------------------------------------------------- |
@@ -797,7 +799,7 @@ void free_hpc_access (void) | |||
797 | void ibmphp_lock_operations (void) | 799 | void ibmphp_lock_operations (void) |
798 | { | 800 | { |
799 | down (&semOperations); | 801 | down (&semOperations); |
800 | to_debug = TRUE; | 802 | to_debug = 1; |
801 | } | 803 | } |
802 | 804 | ||
803 | /*---------------------------------------------------------------------- | 805 | /*---------------------------------------------------------------------- |
@@ -807,7 +809,7 @@ void ibmphp_unlock_operations (void) | |||
807 | { | 809 | { |
808 | debug ("%s - Entry\n", __FUNCTION__); | 810 | debug ("%s - Entry\n", __FUNCTION__); |
809 | up (&semOperations); | 811 | up (&semOperations); |
810 | to_debug = FALSE; | 812 | to_debug = 0; |
811 | debug ("%s - Exit\n", __FUNCTION__); | 813 | debug ("%s - Exit\n", __FUNCTION__); |
812 | } | 814 | } |
813 | 815 | ||
@@ -935,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) | |||
935 | { | 937 | { |
936 | u8 status; | 938 | u8 status; |
937 | int rc = 0; | 939 | int rc = 0; |
938 | u8 disable = FALSE; | 940 | u8 disable = 0; |
939 | u8 update = FALSE; | 941 | u8 update = 0; |
940 | 942 | ||
941 | debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); | 943 | debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); |
942 | 944 | ||
943 | // bit 0 - HPC_SLOT_POWER | 945 | // bit 0 - HPC_SLOT_POWER |
944 | if ((pslot->status & 0x01) != (poldslot->status & 0x01)) | 946 | if ((pslot->status & 0x01) != (poldslot->status & 0x01)) |
945 | update = TRUE; | 947 | update = 1; |
946 | 948 | ||
947 | // bit 1 - HPC_SLOT_CONNECT | 949 | // bit 1 - HPC_SLOT_CONNECT |
948 | // ignore | 950 | // ignore |
949 | 951 | ||
950 | // bit 2 - HPC_SLOT_ATTN | 952 | // bit 2 - HPC_SLOT_ATTN |
951 | if ((pslot->status & 0x04) != (poldslot->status & 0x04)) | 953 | if ((pslot->status & 0x04) != (poldslot->status & 0x04)) |
952 | update = TRUE; | 954 | update = 1; |
953 | 955 | ||
954 | // bit 3 - HPC_SLOT_PRSNT2 | 956 | // bit 3 - HPC_SLOT_PRSNT2 |
955 | // bit 4 - HPC_SLOT_PRSNT1 | 957 | // bit 4 - HPC_SLOT_PRSNT1 |
956 | if (((pslot->status & 0x08) != (poldslot->status & 0x08)) | 958 | if (((pslot->status & 0x08) != (poldslot->status & 0x08)) |
957 | || ((pslot->status & 0x10) != (poldslot->status & 0x10))) | 959 | || ((pslot->status & 0x10) != (poldslot->status & 0x10))) |
958 | update = TRUE; | 960 | update = 1; |
959 | 961 | ||
960 | // bit 5 - HPC_SLOT_PWRGD | 962 | // bit 5 - HPC_SLOT_PWRGD |
961 | if ((pslot->status & 0x20) != (poldslot->status & 0x20)) | 963 | if ((pslot->status & 0x20) != (poldslot->status & 0x20)) |
962 | // OFF -> ON: ignore, ON -> OFF: disable slot | 964 | // OFF -> ON: ignore, ON -> OFF: disable slot |
963 | if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) | 965 | if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) |
964 | disable = TRUE; | 966 | disable = 1; |
965 | 967 | ||
966 | // bit 6 - HPC_SLOT_BUS_SPEED | 968 | // bit 6 - HPC_SLOT_BUS_SPEED |
967 | // ignore | 969 | // ignore |
968 | 970 | ||
969 | // bit 7 - HPC_SLOT_LATCH | 971 | // bit 7 - HPC_SLOT_LATCH |
970 | if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { | 972 | if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { |
971 | update = TRUE; | 973 | update = 1; |
972 | // OPEN -> CLOSE | 974 | // OPEN -> CLOSE |
973 | if (pslot->status & 0x80) { | 975 | if (pslot->status & 0x80) { |
974 | if (SLOT_PWRGD (pslot->status)) { | 976 | if (SLOT_PWRGD (pslot->status)) { |
@@ -977,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) | |||
977 | msleep(1000); | 979 | msleep(1000); |
978 | rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); | 980 | rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); |
979 | if (SLOT_PWRGD (status)) | 981 | if (SLOT_PWRGD (status)) |
980 | update = TRUE; | 982 | update = 1; |
981 | else // overwrite power in pslot to OFF | 983 | else // overwrite power in pslot to OFF |
982 | pslot->status &= ~HPC_SLOT_POWER; | 984 | pslot->status &= ~HPC_SLOT_POWER; |
983 | } | 985 | } |
@@ -985,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) | |||
985 | // CLOSE -> OPEN | 987 | // CLOSE -> OPEN |
986 | else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) | 988 | else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) |
987 | && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { | 989 | && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { |
988 | disable = TRUE; | 990 | disable = 1; |
989 | } | 991 | } |
990 | // else - ignore | 992 | // else - ignore |
991 | } | 993 | } |
992 | // bit 4 - HPC_SLOT_BLINK_ATTN | 994 | // bit 4 - HPC_SLOT_BLINK_ATTN |
993 | if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) | 995 | if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) |
994 | update = TRUE; | 996 | update = 1; |
995 | 997 | ||
996 | if (disable) { | 998 | if (disable) { |
997 | debug ("process_changeinstatus - disable slot\n"); | 999 | debug ("process_changeinstatus - disable slot\n"); |
998 | pslot->flag = FALSE; | 1000 | pslot->flag = 0; |
999 | rc = ibmphp_do_disable_slot (pslot); | 1001 | rc = ibmphp_do_disable_slot (pslot); |
1000 | } | 1002 | } |
1001 | 1003 | ||
@@ -1100,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void) | |||
1100 | { | 1102 | { |
1101 | debug ("%s - Entry\n", __FUNCTION__); | 1103 | debug ("%s - Entry\n", __FUNCTION__); |
1102 | 1104 | ||
1103 | ibmphp_shutdown = TRUE; | 1105 | ibmphp_shutdown = 1; |
1104 | debug ("before locking operations \n"); | 1106 | debug ("before locking operations \n"); |
1105 | ibmphp_lock_operations (); | 1107 | ibmphp_lock_operations (); |
1106 | debug ("after locking operations \n"); | 1108 | debug ("after locking operations \n"); |
@@ -1134,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v | |||
1134 | u8 * pstatus) | 1136 | u8 * pstatus) |
1135 | { | 1137 | { |
1136 | int rc = 0; | 1138 | int rc = 0; |
1137 | u8 done = FALSE; | 1139 | u8 done = 0; |
1138 | 1140 | ||
1139 | debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); | 1141 | debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); |
1140 | 1142 | ||
@@ -1142,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v | |||
1142 | *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); | 1144 | *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); |
1143 | if (*pstatus == HPC_ERROR) { | 1145 | if (*pstatus == HPC_ERROR) { |
1144 | rc = HPC_ERROR; | 1146 | rc = HPC_ERROR; |
1145 | done = TRUE; | 1147 | done = 1; |
1146 | } | 1148 | } |
1147 | if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) | 1149 | if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) |
1148 | done = TRUE; | 1150 | done = 1; |
1149 | if (!done) { | 1151 | if (!done) { |
1150 | msleep(1000); | 1152 | msleep(1000); |
1151 | if (timeout < 1) { | 1153 | if (timeout < 1) { |
1152 | done = TRUE; | 1154 | done = 1; |
1153 | err ("HPCreadslot - Error ctlr timeout\n"); | 1155 | err ("HPCreadslot - Error ctlr timeout\n"); |
1154 | rc = HPC_ERROR; | 1156 | rc = HPC_ERROR; |
1155 | } else | 1157 | } else |
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 155133fe5c12..d87a9e3eaeeb 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c | |||
@@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) | |||
164 | cleanup_count = 6; | 164 | cleanup_count = 6; |
165 | goto error; | 165 | goto error; |
166 | } | 166 | } |
167 | newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); | 167 | newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); |
168 | if (!newfunc) { | 168 | if (!newfunc) { |
169 | err ("out of system memory\n"); | 169 | err ("out of system memory\n"); |
170 | return -ENOMEM; | 170 | return -ENOMEM; |
171 | } | 171 | } |
172 | memset (newfunc, 0, sizeof (struct pci_func)); | ||
173 | newfunc->busno = cur_func->busno; | 172 | newfunc->busno = cur_func->busno; |
174 | newfunc->device = device; | 173 | newfunc->device = device; |
175 | cur_func->next = newfunc; | 174 | cur_func->next = newfunc; |
@@ -200,15 +199,14 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) | |||
200 | } | 199 | } |
201 | 200 | ||
202 | pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); | 201 | pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); |
203 | flag = FALSE; | 202 | flag = 0; |
204 | for (i = 0; i < 32; i++) { | 203 | for (i = 0; i < 32; i++) { |
205 | if (func->devices[i]) { | 204 | if (func->devices[i]) { |
206 | newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); | 205 | newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); |
207 | if (!newfunc) { | 206 | if (!newfunc) { |
208 | err ("out of system memory\n"); | 207 | err ("out of system memory\n"); |
209 | return -ENOMEM; | 208 | return -ENOMEM; |
210 | } | 209 | } |
211 | memset (newfunc, 0, sizeof (struct pci_func)); | ||
212 | newfunc->busno = sec_number; | 210 | newfunc->busno = sec_number; |
213 | newfunc->device = (u8) i; | 211 | newfunc->device = (u8) i; |
214 | for (j = 0; j < 4; j++) | 212 | for (j = 0; j < 4; j++) |
@@ -228,16 +226,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) | |||
228 | cleanup_count = 2; | 226 | cleanup_count = 2; |
229 | goto error; | 227 | goto error; |
230 | } | 228 | } |
231 | flag = TRUE; | 229 | flag = 1; |
232 | } | 230 | } |
233 | } | 231 | } |
234 | 232 | ||
235 | newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); | 233 | newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); |
236 | if (!newfunc) { | 234 | if (!newfunc) { |
237 | err ("out of system memory\n"); | 235 | err ("out of system memory\n"); |
238 | return -ENOMEM; | 236 | return -ENOMEM; |
239 | } | 237 | } |
240 | memset (newfunc, 0, sizeof (struct pci_func)); | ||
241 | newfunc->busno = cur_func->busno; | 238 | newfunc->busno = cur_func->busno; |
242 | newfunc->device = device; | 239 | newfunc->device = device; |
243 | for (j = 0; j < 4; j++) | 240 | for (j = 0; j < 4; j++) |
@@ -275,16 +272,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) | |||
275 | cur_func->busno, device, function); | 272 | cur_func->busno, device, function); |
276 | pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); | 273 | pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); |
277 | debug ("after configuring bridge..., sec_number = %x\n", sec_number); | 274 | debug ("after configuring bridge..., sec_number = %x\n", sec_number); |
278 | flag = FALSE; | 275 | flag = 0; |
279 | for (i = 0; i < 32; i++) { | 276 | for (i = 0; i < 32; i++) { |
280 | if (func->devices[i]) { | 277 | if (func->devices[i]) { |
281 | debug ("inside for loop, device is %x\n", i); | 278 | debug ("inside for loop, device is %x\n", i); |
282 | newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); | 279 | newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); |
283 | if (!newfunc) { | 280 | if (!newfunc) { |
284 | err (" out of system memory\n"); | 281 | err (" out of system memory\n"); |
285 | return -ENOMEM; | 282 | return -ENOMEM; |
286 | } | 283 | } |
287 | memset (newfunc, 0, sizeof (struct pci_func)); | ||
288 | newfunc->busno = sec_number; | 284 | newfunc->busno = sec_number; |
289 | newfunc->device = (u8) i; | 285 | newfunc->device = (u8) i; |
290 | for (j = 0; j < 4; j++) | 286 | for (j = 0; j < 4; j++) |
@@ -305,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) | |||
305 | cleanup_count = 2; | 301 | cleanup_count = 2; |
306 | goto error; | 302 | goto error; |
307 | } | 303 | } |
308 | flag = TRUE; | 304 | flag = 1; |
309 | } | 305 | } |
310 | } | 306 | } |
311 | 307 | ||
@@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func) | |||
405 | 401 | ||
406 | debug ("len[count] in IO %x, count %d\n", len[count], count); | 402 | debug ("len[count] in IO %x, count %d\n", len[count], count); |
407 | 403 | ||
408 | io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 404 | io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
409 | 405 | ||
410 | if (!io[count]) { | 406 | if (!io[count]) { |
411 | err ("out of system memory\n"); | 407 | err ("out of system memory\n"); |
412 | return -ENOMEM; | 408 | return -ENOMEM; |
413 | } | 409 | } |
414 | memset (io[count], 0, sizeof (struct resource_node)); | ||
415 | io[count]->type = IO; | 410 | io[count]->type = IO; |
416 | io[count]->busno = func->busno; | 411 | io[count]->busno = func->busno; |
417 | io[count]->devfunc = PCI_DEVFN(func->device, func->function); | 412 | io[count]->devfunc = PCI_DEVFN(func->device, func->function); |
@@ -444,29 +439,27 @@ static int configure_device (struct pci_func *func) | |||
444 | 439 | ||
445 | debug ("len[count] in PFMEM %x, count %d\n", len[count], count); | 440 | debug ("len[count] in PFMEM %x, count %d\n", len[count], count); |
446 | 441 | ||
447 | pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 442 | pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
448 | if (!pfmem[count]) { | 443 | if (!pfmem[count]) { |
449 | err ("out of system memory\n"); | 444 | err ("out of system memory\n"); |
450 | return -ENOMEM; | 445 | return -ENOMEM; |
451 | } | 446 | } |
452 | memset (pfmem[count], 0, sizeof (struct resource_node)); | ||
453 | pfmem[count]->type = PFMEM; | 447 | pfmem[count]->type = PFMEM; |
454 | pfmem[count]->busno = func->busno; | 448 | pfmem[count]->busno = func->busno; |
455 | pfmem[count]->devfunc = PCI_DEVFN(func->device, | 449 | pfmem[count]->devfunc = PCI_DEVFN(func->device, |
456 | func->function); | 450 | func->function); |
457 | pfmem[count]->len = len[count]; | 451 | pfmem[count]->len = len[count]; |
458 | pfmem[count]->fromMem = FALSE; | 452 | pfmem[count]->fromMem = 0; |
459 | if (ibmphp_check_resource (pfmem[count], 0) == 0) { | 453 | if (ibmphp_check_resource (pfmem[count], 0) == 0) { |
460 | ibmphp_add_resource (pfmem[count]); | 454 | ibmphp_add_resource (pfmem[count]); |
461 | func->pfmem[count] = pfmem[count]; | 455 | func->pfmem[count] = pfmem[count]; |
462 | } else { | 456 | } else { |
463 | mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); | 457 | mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); |
464 | if (!mem_tmp) { | 458 | if (!mem_tmp) { |
465 | err ("out of system memory\n"); | 459 | err ("out of system memory\n"); |
466 | kfree (pfmem[count]); | 460 | kfree (pfmem[count]); |
467 | return -ENOMEM; | 461 | return -ENOMEM; |
468 | } | 462 | } |
469 | memset (mem_tmp, 0, sizeof (struct resource_node)); | ||
470 | mem_tmp->type = MEM; | 463 | mem_tmp->type = MEM; |
471 | mem_tmp->busno = pfmem[count]->busno; | 464 | mem_tmp->busno = pfmem[count]->busno; |
472 | mem_tmp->devfunc = pfmem[count]->devfunc; | 465 | mem_tmp->devfunc = pfmem[count]->devfunc; |
@@ -474,7 +467,7 @@ static int configure_device (struct pci_func *func) | |||
474 | debug ("there's no pfmem... going into mem.\n"); | 467 | debug ("there's no pfmem... going into mem.\n"); |
475 | if (ibmphp_check_resource (mem_tmp, 0) == 0) { | 468 | if (ibmphp_check_resource (mem_tmp, 0) == 0) { |
476 | ibmphp_add_resource (mem_tmp); | 469 | ibmphp_add_resource (mem_tmp); |
477 | pfmem[count]->fromMem = TRUE; | 470 | pfmem[count]->fromMem = 1; |
478 | pfmem[count]->rangeno = mem_tmp->rangeno; | 471 | pfmem[count]->rangeno = mem_tmp->rangeno; |
479 | pfmem[count]->start = mem_tmp->start; | 472 | pfmem[count]->start = mem_tmp->start; |
480 | pfmem[count]->end = mem_tmp->end; | 473 | pfmem[count]->end = mem_tmp->end; |
@@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func) | |||
512 | 505 | ||
513 | debug ("len[count] in Mem %x, count %d\n", len[count], count); | 506 | debug ("len[count] in Mem %x, count %d\n", len[count], count); |
514 | 507 | ||
515 | mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 508 | mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
516 | if (!mem[count]) { | 509 | if (!mem[count]) { |
517 | err ("out of system memory\n"); | 510 | err ("out of system memory\n"); |
518 | return -ENOMEM; | 511 | return -ENOMEM; |
519 | } | 512 | } |
520 | memset (mem[count], 0, sizeof (struct resource_node)); | ||
521 | mem[count]->type = MEM; | 513 | mem[count]->type = MEM; |
522 | mem[count]->busno = func->busno; | 514 | mem[count]->busno = func->busno; |
523 | mem[count]->devfunc = PCI_DEVFN(func->device, | 515 | mem[count]->devfunc = PCI_DEVFN(func->device, |
@@ -579,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
579 | u16 pfmem_base; | 571 | u16 pfmem_base; |
580 | u32 bar[2]; | 572 | u32 bar[2]; |
581 | u32 len[2]; | 573 | u32 len[2]; |
582 | u8 flag_io = FALSE; | 574 | u8 flag_io = 0; |
583 | u8 flag_mem = FALSE; | 575 | u8 flag_mem = 0; |
584 | u8 flag_pfmem = FALSE; | 576 | u8 flag_pfmem = 0; |
585 | u8 need_io_upper = FALSE; | 577 | u8 need_io_upper = 0; |
586 | u8 need_pfmem_upper = FALSE; | 578 | u8 need_pfmem_upper = 0; |
587 | struct res_needed *amount_needed = NULL; | 579 | struct res_needed *amount_needed = NULL; |
588 | struct resource_node *io = NULL; | 580 | struct resource_node *io = NULL; |
589 | struct resource_node *bus_io[2] = {NULL, NULL}; | 581 | struct resource_node *bus_io[2] = {NULL, NULL}; |
@@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
677 | 669 | ||
678 | debug ("len[count] in IO = %x\n", len[count]); | 670 | debug ("len[count] in IO = %x\n", len[count]); |
679 | 671 | ||
680 | bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 672 | bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
681 | 673 | ||
682 | if (!bus_io[count]) { | 674 | if (!bus_io[count]) { |
683 | err ("out of system memory\n"); | 675 | err ("out of system memory\n"); |
684 | retval = -ENOMEM; | 676 | retval = -ENOMEM; |
685 | goto error; | 677 | goto error; |
686 | } | 678 | } |
687 | memset (bus_io[count], 0, sizeof (struct resource_node)); | ||
688 | bus_io[count]->type = IO; | 679 | bus_io[count]->type = IO; |
689 | bus_io[count]->busno = func->busno; | 680 | bus_io[count]->busno = func->busno; |
690 | bus_io[count]->devfunc = PCI_DEVFN(func->device, | 681 | bus_io[count]->devfunc = PCI_DEVFN(func->device, |
@@ -711,37 +702,35 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
711 | 702 | ||
712 | debug ("len[count] in PFMEM = %x\n", len[count]); | 703 | debug ("len[count] in PFMEM = %x\n", len[count]); |
713 | 704 | ||
714 | bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 705 | bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
715 | if (!bus_pfmem[count]) { | 706 | if (!bus_pfmem[count]) { |
716 | err ("out of system memory\n"); | 707 | err ("out of system memory\n"); |
717 | retval = -ENOMEM; | 708 | retval = -ENOMEM; |
718 | goto error; | 709 | goto error; |
719 | } | 710 | } |
720 | memset (bus_pfmem[count], 0, sizeof (struct resource_node)); | ||
721 | bus_pfmem[count]->type = PFMEM; | 711 | bus_pfmem[count]->type = PFMEM; |
722 | bus_pfmem[count]->busno = func->busno; | 712 | bus_pfmem[count]->busno = func->busno; |
723 | bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, | 713 | bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, |
724 | func->function); | 714 | func->function); |
725 | bus_pfmem[count]->len = len[count]; | 715 | bus_pfmem[count]->len = len[count]; |
726 | bus_pfmem[count]->fromMem = FALSE; | 716 | bus_pfmem[count]->fromMem = 0; |
727 | if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { | 717 | if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { |
728 | ibmphp_add_resource (bus_pfmem[count]); | 718 | ibmphp_add_resource (bus_pfmem[count]); |
729 | func->pfmem[count] = bus_pfmem[count]; | 719 | func->pfmem[count] = bus_pfmem[count]; |
730 | } else { | 720 | } else { |
731 | mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); | 721 | mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); |
732 | if (!mem_tmp) { | 722 | if (!mem_tmp) { |
733 | err ("out of system memory\n"); | 723 | err ("out of system memory\n"); |
734 | retval = -ENOMEM; | 724 | retval = -ENOMEM; |
735 | goto error; | 725 | goto error; |
736 | } | 726 | } |
737 | memset (mem_tmp, 0, sizeof (struct resource_node)); | ||
738 | mem_tmp->type = MEM; | 727 | mem_tmp->type = MEM; |
739 | mem_tmp->busno = bus_pfmem[count]->busno; | 728 | mem_tmp->busno = bus_pfmem[count]->busno; |
740 | mem_tmp->devfunc = bus_pfmem[count]->devfunc; | 729 | mem_tmp->devfunc = bus_pfmem[count]->devfunc; |
741 | mem_tmp->len = bus_pfmem[count]->len; | 730 | mem_tmp->len = bus_pfmem[count]->len; |
742 | if (ibmphp_check_resource (mem_tmp, 0) == 0) { | 731 | if (ibmphp_check_resource (mem_tmp, 0) == 0) { |
743 | ibmphp_add_resource (mem_tmp); | 732 | ibmphp_add_resource (mem_tmp); |
744 | bus_pfmem[count]->fromMem = TRUE; | 733 | bus_pfmem[count]->fromMem = 1; |
745 | bus_pfmem[count]->rangeno = mem_tmp->rangeno; | 734 | bus_pfmem[count]->rangeno = mem_tmp->rangeno; |
746 | ibmphp_add_pfmem_from_mem (bus_pfmem[count]); | 735 | ibmphp_add_pfmem_from_mem (bus_pfmem[count]); |
747 | func->pfmem[count] = bus_pfmem[count]; | 736 | func->pfmem[count] = bus_pfmem[count]; |
@@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
770 | 759 | ||
771 | debug ("len[count] in Memory is %x\n", len[count]); | 760 | debug ("len[count] in Memory is %x\n", len[count]); |
772 | 761 | ||
773 | bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 762 | bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
774 | if (!bus_mem[count]) { | 763 | if (!bus_mem[count]) { |
775 | err ("out of system memory\n"); | 764 | err ("out of system memory\n"); |
776 | retval = -ENOMEM; | 765 | retval = -ENOMEM; |
777 | goto error; | 766 | goto error; |
778 | } | 767 | } |
779 | memset (bus_mem[count], 0, sizeof (struct resource_node)); | ||
780 | bus_mem[count]->type = MEM; | 768 | bus_mem[count]->type = MEM; |
781 | bus_mem[count]->busno = func->busno; | 769 | bus_mem[count]->busno = func->busno; |
782 | bus_mem[count]->devfunc = PCI_DEVFN(func->device, | 770 | bus_mem[count]->devfunc = PCI_DEVFN(func->device, |
@@ -838,17 +826,16 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
838 | 826 | ||
839 | if (!amount_needed->io) { | 827 | if (!amount_needed->io) { |
840 | debug ("it doesn't want IO?\n"); | 828 | debug ("it doesn't want IO?\n"); |
841 | flag_io = TRUE; | 829 | flag_io = 1; |
842 | } else { | 830 | } else { |
843 | debug ("it wants %x IO behind the bridge\n", amount_needed->io); | 831 | debug ("it wants %x IO behind the bridge\n", amount_needed->io); |
844 | io = kmalloc(sizeof(*io), GFP_KERNEL); | 832 | io = kzalloc(sizeof(*io), GFP_KERNEL); |
845 | 833 | ||
846 | if (!io) { | 834 | if (!io) { |
847 | err ("out of system memory\n"); | 835 | err ("out of system memory\n"); |
848 | retval = -ENOMEM; | 836 | retval = -ENOMEM; |
849 | goto error; | 837 | goto error; |
850 | } | 838 | } |
851 | memset (io, 0, sizeof (struct resource_node)); | ||
852 | io->type = IO; | 839 | io->type = IO; |
853 | io->busno = func->busno; | 840 | io->busno = func->busno; |
854 | io->devfunc = PCI_DEVFN(func->device, func->function); | 841 | io->devfunc = PCI_DEVFN(func->device, func->function); |
@@ -856,71 +843,68 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
856 | if (ibmphp_check_resource (io, 1) == 0) { | 843 | if (ibmphp_check_resource (io, 1) == 0) { |
857 | debug ("were we able to add io\n"); | 844 | debug ("were we able to add io\n"); |
858 | ibmphp_add_resource (io); | 845 | ibmphp_add_resource (io); |
859 | flag_io = TRUE; | 846 | flag_io = 1; |
860 | } | 847 | } |
861 | } | 848 | } |
862 | 849 | ||
863 | if (!amount_needed->mem) { | 850 | if (!amount_needed->mem) { |
864 | debug ("it doesn't want n.e.memory?\n"); | 851 | debug ("it doesn't want n.e.memory?\n"); |
865 | flag_mem = TRUE; | 852 | flag_mem = 1; |
866 | } else { | 853 | } else { |
867 | debug ("it wants %x memory behind the bridge\n", amount_needed->mem); | 854 | debug ("it wants %x memory behind the bridge\n", amount_needed->mem); |
868 | mem = kmalloc(sizeof(*mem), GFP_KERNEL); | 855 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); |
869 | if (!mem) { | 856 | if (!mem) { |
870 | err ("out of system memory\n"); | 857 | err ("out of system memory\n"); |
871 | retval = -ENOMEM; | 858 | retval = -ENOMEM; |
872 | goto error; | 859 | goto error; |
873 | } | 860 | } |
874 | memset (mem, 0, sizeof (struct resource_node)); | ||
875 | mem->type = MEM; | 861 | mem->type = MEM; |
876 | mem->busno = func->busno; | 862 | mem->busno = func->busno; |
877 | mem->devfunc = PCI_DEVFN(func->device, func->function); | 863 | mem->devfunc = PCI_DEVFN(func->device, func->function); |
878 | mem->len = amount_needed->mem; | 864 | mem->len = amount_needed->mem; |
879 | if (ibmphp_check_resource (mem, 1) == 0) { | 865 | if (ibmphp_check_resource (mem, 1) == 0) { |
880 | ibmphp_add_resource (mem); | 866 | ibmphp_add_resource (mem); |
881 | flag_mem = TRUE; | 867 | flag_mem = 1; |
882 | debug ("were we able to add mem\n"); | 868 | debug ("were we able to add mem\n"); |
883 | } | 869 | } |
884 | } | 870 | } |
885 | 871 | ||
886 | if (!amount_needed->pfmem) { | 872 | if (!amount_needed->pfmem) { |
887 | debug ("it doesn't want n.e.pfmem mem?\n"); | 873 | debug ("it doesn't want n.e.pfmem mem?\n"); |
888 | flag_pfmem = TRUE; | 874 | flag_pfmem = 1; |
889 | } else { | 875 | } else { |
890 | debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); | 876 | debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); |
891 | pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL); | 877 | pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); |
892 | if (!pfmem) { | 878 | if (!pfmem) { |
893 | err ("out of system memory\n"); | 879 | err ("out of system memory\n"); |
894 | retval = -ENOMEM; | 880 | retval = -ENOMEM; |
895 | goto error; | 881 | goto error; |
896 | } | 882 | } |
897 | memset (pfmem, 0, sizeof (struct resource_node)); | ||
898 | pfmem->type = PFMEM; | 883 | pfmem->type = PFMEM; |
899 | pfmem->busno = func->busno; | 884 | pfmem->busno = func->busno; |
900 | pfmem->devfunc = PCI_DEVFN(func->device, func->function); | 885 | pfmem->devfunc = PCI_DEVFN(func->device, func->function); |
901 | pfmem->len = amount_needed->pfmem; | 886 | pfmem->len = amount_needed->pfmem; |
902 | pfmem->fromMem = FALSE; | 887 | pfmem->fromMem = 0; |
903 | if (ibmphp_check_resource (pfmem, 1) == 0) { | 888 | if (ibmphp_check_resource (pfmem, 1) == 0) { |
904 | ibmphp_add_resource (pfmem); | 889 | ibmphp_add_resource (pfmem); |
905 | flag_pfmem = TRUE; | 890 | flag_pfmem = 1; |
906 | } else { | 891 | } else { |
907 | mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); | 892 | mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); |
908 | if (!mem_tmp) { | 893 | if (!mem_tmp) { |
909 | err ("out of system memory\n"); | 894 | err ("out of system memory\n"); |
910 | retval = -ENOMEM; | 895 | retval = -ENOMEM; |
911 | goto error; | 896 | goto error; |
912 | } | 897 | } |
913 | memset (mem_tmp, 0, sizeof (struct resource_node)); | ||
914 | mem_tmp->type = MEM; | 898 | mem_tmp->type = MEM; |
915 | mem_tmp->busno = pfmem->busno; | 899 | mem_tmp->busno = pfmem->busno; |
916 | mem_tmp->devfunc = pfmem->devfunc; | 900 | mem_tmp->devfunc = pfmem->devfunc; |
917 | mem_tmp->len = pfmem->len; | 901 | mem_tmp->len = pfmem->len; |
918 | if (ibmphp_check_resource (mem_tmp, 1) == 0) { | 902 | if (ibmphp_check_resource (mem_tmp, 1) == 0) { |
919 | ibmphp_add_resource (mem_tmp); | 903 | ibmphp_add_resource (mem_tmp); |
920 | pfmem->fromMem = TRUE; | 904 | pfmem->fromMem = 1; |
921 | pfmem->rangeno = mem_tmp->rangeno; | 905 | pfmem->rangeno = mem_tmp->rangeno; |
922 | ibmphp_add_pfmem_from_mem (pfmem); | 906 | ibmphp_add_pfmem_from_mem (pfmem); |
923 | flag_pfmem = TRUE; | 907 | flag_pfmem = 1; |
924 | } | 908 | } |
925 | } | 909 | } |
926 | } | 910 | } |
@@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
936 | */ | 920 | */ |
937 | bus = ibmphp_find_res_bus (sec_number); | 921 | bus = ibmphp_find_res_bus (sec_number); |
938 | if (!bus) { | 922 | if (!bus) { |
939 | bus = kmalloc(sizeof(*bus), GFP_KERNEL); | 923 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
940 | if (!bus) { | 924 | if (!bus) { |
941 | err ("out of system memory\n"); | 925 | err ("out of system memory\n"); |
942 | retval = -ENOMEM; | 926 | retval = -ENOMEM; |
943 | goto error; | 927 | goto error; |
944 | } | 928 | } |
945 | memset (bus, 0, sizeof (struct bus_node)); | ||
946 | bus->busno = sec_number; | 929 | bus->busno = sec_number; |
947 | debug ("b4 adding new bus\n"); | 930 | debug ("b4 adding new bus\n"); |
948 | rc = add_new_bus (bus, io, mem, pfmem, func->busno); | 931 | rc = add_new_bus (bus, io, mem, pfmem, func->busno); |
@@ -967,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) | |||
967 | 950 | ||
968 | if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { | 951 | if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { |
969 | debug ("io 32\n"); | 952 | debug ("io 32\n"); |
970 | need_io_upper = TRUE; | 953 | need_io_upper = 1; |
971 | } | 954 | } |
972 | if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { | 955 | if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { |
973 | debug ("pfmem 64\n"); | 956 | debug ("pfmem 64\n"); |
974 | need_pfmem_upper = TRUE; | 957 | need_pfmem_upper = 1; |
975 | } | 958 | } |
976 | 959 | ||
977 | if (bus->noIORanges) { | 960 | if (bus->noIORanges) { |
@@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) | |||
1111 | }; | 1094 | }; |
1112 | struct res_needed *amount; | 1095 | struct res_needed *amount; |
1113 | 1096 | ||
1114 | amount = kmalloc(sizeof(*amount), GFP_KERNEL); | 1097 | amount = kzalloc(sizeof(*amount), GFP_KERNEL); |
1115 | if (amount == NULL) | 1098 | if (amount == NULL) |
1116 | return NULL; | 1099 | return NULL; |
1117 | memset (amount, 0, sizeof (struct res_needed)); | ||
1118 | 1100 | ||
1119 | ibmphp_pci_bus->number = busno; | 1101 | ibmphp_pci_bus->number = busno; |
1120 | 1102 | ||
@@ -1137,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) | |||
1137 | debug ("hdr_type behind the bridge is %x\n", hdr_type); | 1119 | debug ("hdr_type behind the bridge is %x\n", hdr_type); |
1138 | if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { | 1120 | if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { |
1139 | err ("embedded bridges not supported for hot-plugging.\n"); | 1121 | err ("embedded bridges not supported for hot-plugging.\n"); |
1140 | amount->not_correct = TRUE; | 1122 | amount->not_correct = 1; |
1141 | return amount; | 1123 | return amount; |
1142 | } | 1124 | } |
1143 | 1125 | ||
@@ -1145,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) | |||
1145 | if (class == PCI_CLASS_NOT_DEFINED_VGA) { | 1127 | if (class == PCI_CLASS_NOT_DEFINED_VGA) { |
1146 | err ("The device %x is VGA compatible and as is not supported for hot plugging. " | 1128 | err ("The device %x is VGA compatible and as is not supported for hot plugging. " |
1147 | "Please choose another device.\n", device); | 1129 | "Please choose another device.\n", device); |
1148 | amount->not_correct = TRUE; | 1130 | amount->not_correct = 1; |
1149 | return amount; | 1131 | return amount; |
1150 | } else if (class == PCI_CLASS_DISPLAY_VGA) { | 1132 | } else if (class == PCI_CLASS_DISPLAY_VGA) { |
1151 | err ("The device %x is not supported for hot plugging. " | 1133 | err ("The device %x is not supported for hot plugging. " |
1152 | "Please choose another device.\n", device); | 1134 | "Please choose another device.\n", device); |
1153 | amount->not_correct = TRUE; | 1135 | amount->not_correct = 1; |
1154 | return amount; | 1136 | return amount; |
1155 | } | 1137 | } |
1156 | 1138 | ||
@@ -1210,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) | |||
1210 | } /* end for */ | 1192 | } /* end for */ |
1211 | 1193 | ||
1212 | if (!howmany) | 1194 | if (!howmany) |
1213 | amount->not_correct = TRUE; | 1195 | amount->not_correct = 1; |
1214 | else | 1196 | else |
1215 | amount->not_correct = FALSE; | 1197 | amount->not_correct = 0; |
1216 | if ((amount->io) && (amount->io < IOBRIDGE)) | 1198 | if ((amount->io) && (amount->io < IOBRIDGE)) |
1217 | amount->io = IOBRIDGE; | 1199 | amount->io = IOBRIDGE; |
1218 | if ((amount->mem) && (amount->mem < MEMBRIDGE)) | 1200 | if ((amount->mem) && (amount->mem < MEMBRIDGE)) |
@@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r | |||
1672 | list_add (&bus->bus_list, &cur_bus->bus_list); | 1654 | list_add (&bus->bus_list, &cur_bus->bus_list); |
1673 | } | 1655 | } |
1674 | if (io) { | 1656 | if (io) { |
1675 | io_range = kmalloc(sizeof(*io_range), GFP_KERNEL); | 1657 | io_range = kzalloc(sizeof(*io_range), GFP_KERNEL); |
1676 | if (!io_range) { | 1658 | if (!io_range) { |
1677 | err ("out of system memory\n"); | 1659 | err ("out of system memory\n"); |
1678 | return -ENOMEM; | 1660 | return -ENOMEM; |
1679 | } | 1661 | } |
1680 | memset (io_range, 0, sizeof (struct range_node)); | ||
1681 | io_range->start = io->start; | 1662 | io_range->start = io->start; |
1682 | io_range->end = io->end; | 1663 | io_range->end = io->end; |
1683 | io_range->rangeno = 1; | 1664 | io_range->rangeno = 1; |
@@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r | |||
1685 | bus->rangeIO = io_range; | 1666 | bus->rangeIO = io_range; |
1686 | } | 1667 | } |
1687 | if (mem) { | 1668 | if (mem) { |
1688 | mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL); | 1669 | mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL); |
1689 | if (!mem_range) { | 1670 | if (!mem_range) { |
1690 | err ("out of system memory\n"); | 1671 | err ("out of system memory\n"); |
1691 | return -ENOMEM; | 1672 | return -ENOMEM; |
1692 | } | 1673 | } |
1693 | memset (mem_range, 0, sizeof (struct range_node)); | ||
1694 | mem_range->start = mem->start; | 1674 | mem_range->start = mem->start; |
1695 | mem_range->end = mem->end; | 1675 | mem_range->end = mem->end; |
1696 | mem_range->rangeno = 1; | 1676 | mem_range->rangeno = 1; |
@@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r | |||
1698 | bus->rangeMem = mem_range; | 1678 | bus->rangeMem = mem_range; |
1699 | } | 1679 | } |
1700 | if (pfmem) { | 1680 | if (pfmem) { |
1701 | pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL); | 1681 | pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL); |
1702 | if (!pfmem_range) { | 1682 | if (!pfmem_range) { |
1703 | err ("out of system memory\n"); | 1683 | err ("out of system memory\n"); |
1704 | return -ENOMEM; | 1684 | return -ENOMEM; |
1705 | } | 1685 | } |
1706 | memset (pfmem_range, 0, sizeof (struct range_node)); | ||
1707 | pfmem_range->start = pfmem->start; | 1686 | pfmem_range->start = pfmem->start; |
1708 | pfmem_range->end = pfmem->end; | 1687 | pfmem_range->end = pfmem->end; |
1709 | pfmem_range->rangeno = 1; | 1688 | pfmem_range->rangeno = 1; |
diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 9c224c94d698..5636b1ac2a2e 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c | |||
@@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 | |||
55 | return NULL; | 55 | return NULL; |
56 | } | 56 | } |
57 | 57 | ||
58 | newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); | 58 | newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); |
59 | if (!newbus) { | 59 | if (!newbus) { |
60 | err ("out of system memory\n"); | 60 | err ("out of system memory\n"); |
61 | return NULL; | 61 | return NULL; |
62 | } | 62 | } |
63 | 63 | ||
64 | memset (newbus, 0, sizeof (struct bus_node)); | ||
65 | if (flag) | 64 | if (flag) |
66 | newbus->busno = busno; | 65 | newbus->busno = busno; |
67 | else | 66 | else |
@@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur | |||
79 | return NULL; | 78 | return NULL; |
80 | } | 79 | } |
81 | 80 | ||
82 | rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 81 | rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
83 | if (!rs) { | 82 | if (!rs) { |
84 | err ("out of system memory\n"); | 83 | err ("out of system memory\n"); |
85 | return NULL; | 84 | return NULL; |
86 | } | 85 | } |
87 | memset (rs, 0, sizeof (struct resource_node)); | ||
88 | rs->busno = curr->bus_num; | 86 | rs->busno = curr->bus_num; |
89 | rs->devfunc = curr->dev_fun; | 87 | rs->devfunc = curr->dev_fun; |
90 | rs->start = curr->start_addr; | 88 | rs->start = curr->start_addr; |
@@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node | |||
100 | u8 num_ranges = 0; | 98 | u8 num_ranges = 0; |
101 | 99 | ||
102 | if (first_bus) { | 100 | if (first_bus) { |
103 | newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); | 101 | newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); |
104 | if (!newbus) { | 102 | if (!newbus) { |
105 | err ("out of system memory.\n"); | 103 | err ("out of system memory.\n"); |
106 | return -ENOMEM; | 104 | return -ENOMEM; |
107 | } | 105 | } |
108 | memset (newbus, 0, sizeof (struct bus_node)); | ||
109 | newbus->busno = curr->bus_num; | 106 | newbus->busno = curr->bus_num; |
110 | } else { | 107 | } else { |
111 | newbus = *new_bus; | 108 | newbus = *new_bus; |
@@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node | |||
122 | } | 119 | } |
123 | } | 120 | } |
124 | 121 | ||
125 | newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL); | 122 | newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL); |
126 | if (!newrange) { | 123 | if (!newrange) { |
127 | if (first_bus) | 124 | if (first_bus) |
128 | kfree (newbus); | 125 | kfree (newbus); |
129 | err ("out of system memory\n"); | 126 | err ("out of system memory\n"); |
130 | return -ENOMEM; | 127 | return -ENOMEM; |
131 | } | 128 | } |
132 | memset (newrange, 0, sizeof (struct range_node)); | ||
133 | newrange->start = curr->start_addr; | 129 | newrange->start = curr->start_addr; |
134 | newrange->end = curr->end_addr; | 130 | newrange->end = curr->end_addr; |
135 | 131 | ||
@@ -329,7 +325,7 @@ int __init ibmphp_rsrc_init (void) | |||
329 | if (!new_pfmem) | 325 | if (!new_pfmem) |
330 | return -ENOMEM; | 326 | return -ENOMEM; |
331 | new_pfmem->type = PFMEM; | 327 | new_pfmem->type = PFMEM; |
332 | new_pfmem->fromMem = FALSE; | 328 | new_pfmem->fromMem = 0; |
333 | if (ibmphp_add_resource (new_pfmem) < 0) { | 329 | if (ibmphp_add_resource (new_pfmem) < 0) { |
334 | newbus = alloc_error_bus (curr, 0, 0); | 330 | newbus = alloc_error_bus (curr, 0, 0); |
335 | if (!newbus) | 331 | if (!newbus) |
@@ -466,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c | |||
466 | static void update_resources (struct bus_node *bus_cur, int type, int rangeno) | 462 | static void update_resources (struct bus_node *bus_cur, int type, int rangeno) |
467 | { | 463 | { |
468 | struct resource_node *res = NULL; | 464 | struct resource_node *res = NULL; |
469 | u8 eol = FALSE; /* end of list indicator */ | 465 | u8 eol = 0; /* end of list indicator */ |
470 | 466 | ||
471 | switch (type) { | 467 | switch (type) { |
472 | case MEM: | 468 | case MEM: |
@@ -492,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno) | |||
492 | else if (res->nextRange) | 488 | else if (res->nextRange) |
493 | res = res->nextRange; | 489 | res = res->nextRange; |
494 | else { | 490 | else { |
495 | eol = TRUE; | 491 | eol = 1; |
496 | break; | 492 | break; |
497 | } | 493 | } |
498 | } | 494 | } |
@@ -983,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
983 | int noranges = 0; | 979 | int noranges = 0; |
984 | u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ | 980 | u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ |
985 | u32 tmp_divide; | 981 | u32 tmp_divide; |
986 | u8 flag = FALSE; | 982 | u8 flag = 0; |
987 | 983 | ||
988 | if (!res) | 984 | if (!res) |
989 | return -EINVAL; | 985 | return -EINVAL; |
@@ -1050,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1050 | 1046 | ||
1051 | if ((range->start % tmp_divide) == 0) { | 1047 | if ((range->start % tmp_divide) == 0) { |
1052 | /* just perfect, starting address is divisible by length */ | 1048 | /* just perfect, starting address is divisible by length */ |
1053 | flag = TRUE; | 1049 | flag = 1; |
1054 | len_cur = len_tmp; | 1050 | len_cur = len_tmp; |
1055 | start_cur = range->start; | 1051 | start_cur = range->start; |
1056 | } else { | 1052 | } else { |
1057 | /* Needs adjusting */ | 1053 | /* Needs adjusting */ |
1058 | tmp_start = range->start; | 1054 | tmp_start = range->start; |
1059 | flag = FALSE; | 1055 | flag = 0; |
1060 | 1056 | ||
1061 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { | 1057 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { |
1062 | if ((tmp_start % tmp_divide) == 0) { | 1058 | if ((tmp_start % tmp_divide) == 0) { |
1063 | flag = TRUE; | 1059 | flag = 1; |
1064 | len_cur = len_tmp; | 1060 | len_cur = len_tmp; |
1065 | start_cur = tmp_start; | 1061 | start_cur = tmp_start; |
1066 | break; | 1062 | break; |
@@ -1089,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1089 | 1085 | ||
1090 | if (((res_cur->end + 1) % tmp_divide) == 0) { | 1086 | if (((res_cur->end + 1) % tmp_divide) == 0) { |
1091 | /* just perfect, starting address is divisible by length */ | 1087 | /* just perfect, starting address is divisible by length */ |
1092 | flag = TRUE; | 1088 | flag = 1; |
1093 | len_cur = len_tmp; | 1089 | len_cur = len_tmp; |
1094 | start_cur = res_cur->end + 1; | 1090 | start_cur = res_cur->end + 1; |
1095 | } else { | 1091 | } else { |
1096 | /* Needs adjusting */ | 1092 | /* Needs adjusting */ |
1097 | tmp_start = res_cur->end + 1; | 1093 | tmp_start = res_cur->end + 1; |
1098 | flag = FALSE; | 1094 | flag = 0; |
1099 | 1095 | ||
1100 | while ((len_tmp = range->end - tmp_start) >= res->len) { | 1096 | while ((len_tmp = range->end - tmp_start) >= res->len) { |
1101 | if ((tmp_start % tmp_divide) == 0) { | 1097 | if ((tmp_start % tmp_divide) == 0) { |
1102 | flag = TRUE; | 1098 | flag = 1; |
1103 | len_cur = len_tmp; | 1099 | len_cur = len_tmp; |
1104 | start_cur = tmp_start; | 1100 | start_cur = tmp_start; |
1105 | break; | 1101 | break; |
@@ -1127,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1127 | if ((len_tmp < len_cur) || (len_cur == 0)) { | 1123 | if ((len_tmp < len_cur) || (len_cur == 0)) { |
1128 | if ((range->start % tmp_divide) == 0) { | 1124 | if ((range->start % tmp_divide) == 0) { |
1129 | /* just perfect, starting address is divisible by length */ | 1125 | /* just perfect, starting address is divisible by length */ |
1130 | flag = TRUE; | 1126 | flag = 1; |
1131 | len_cur = len_tmp; | 1127 | len_cur = len_tmp; |
1132 | start_cur = range->start; | 1128 | start_cur = range->start; |
1133 | } else { | 1129 | } else { |
1134 | /* Needs adjusting */ | 1130 | /* Needs adjusting */ |
1135 | tmp_start = range->start; | 1131 | tmp_start = range->start; |
1136 | flag = FALSE; | 1132 | flag = 0; |
1137 | 1133 | ||
1138 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { | 1134 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { |
1139 | if ((tmp_start % tmp_divide) == 0) { | 1135 | if ((tmp_start % tmp_divide) == 0) { |
1140 | flag = TRUE; | 1136 | flag = 1; |
1141 | len_cur = len_tmp; | 1137 | len_cur = len_tmp; |
1142 | start_cur = tmp_start; | 1138 | start_cur = tmp_start; |
1143 | break; | 1139 | break; |
@@ -1162,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1162 | if ((len_tmp < len_cur) || (len_cur == 0)) { | 1158 | if ((len_tmp < len_cur) || (len_cur == 0)) { |
1163 | if (((res_prev->end + 1) % tmp_divide) == 0) { | 1159 | if (((res_prev->end + 1) % tmp_divide) == 0) { |
1164 | /* just perfect, starting address's divisible by length */ | 1160 | /* just perfect, starting address's divisible by length */ |
1165 | flag = TRUE; | 1161 | flag = 1; |
1166 | len_cur = len_tmp; | 1162 | len_cur = len_tmp; |
1167 | start_cur = res_prev->end + 1; | 1163 | start_cur = res_prev->end + 1; |
1168 | } else { | 1164 | } else { |
1169 | /* Needs adjusting */ | 1165 | /* Needs adjusting */ |
1170 | tmp_start = res_prev->end + 1; | 1166 | tmp_start = res_prev->end + 1; |
1171 | flag = FALSE; | 1167 | flag = 0; |
1172 | 1168 | ||
1173 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { | 1169 | while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { |
1174 | if ((tmp_start % tmp_divide) == 0) { | 1170 | if ((tmp_start % tmp_divide) == 0) { |
1175 | flag = TRUE; | 1171 | flag = 1; |
1176 | len_cur = len_tmp; | 1172 | len_cur = len_tmp; |
1177 | start_cur = tmp_start; | 1173 | start_cur = tmp_start; |
1178 | break; | 1174 | break; |
@@ -1221,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1221 | if ((len_tmp < len_cur) || (len_cur == 0)) { | 1217 | if ((len_tmp < len_cur) || (len_cur == 0)) { |
1222 | if ((range->start % tmp_divide) == 0) { | 1218 | if ((range->start % tmp_divide) == 0) { |
1223 | /* just perfect, starting address's divisible by length */ | 1219 | /* just perfect, starting address's divisible by length */ |
1224 | flag = TRUE; | 1220 | flag = 1; |
1225 | len_cur = len_tmp; | 1221 | len_cur = len_tmp; |
1226 | start_cur = range->start; | 1222 | start_cur = range->start; |
1227 | } else { | 1223 | } else { |
1228 | /* Needs adjusting */ | 1224 | /* Needs adjusting */ |
1229 | tmp_start = range->start; | 1225 | tmp_start = range->start; |
1230 | flag = FALSE; | 1226 | flag = 0; |
1231 | 1227 | ||
1232 | while ((len_tmp = range->end - tmp_start) >= res->len) { | 1228 | while ((len_tmp = range->end - tmp_start) >= res->len) { |
1233 | if ((tmp_start % tmp_divide) == 0) { | 1229 | if ((tmp_start % tmp_divide) == 0) { |
1234 | flag = TRUE; | 1230 | flag = 1; |
1235 | len_cur = len_tmp; | 1231 | len_cur = len_tmp; |
1236 | start_cur = tmp_start; | 1232 | start_cur = tmp_start; |
1237 | break; | 1233 | break; |
@@ -1285,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) | |||
1285 | if ((len_tmp < len_cur) || (len_cur == 0)) { | 1281 | if ((len_tmp < len_cur) || (len_cur == 0)) { |
1286 | if ((range->start % tmp_divide) == 0) { | 1282 | if ((range->start % tmp_divide) == 0) { |
1287 | /* just perfect, starting address's divisible by length */ | 1283 | /* just perfect, starting address's divisible by length */ |
1288 | flag = TRUE; | 1284 | flag = 1; |
1289 | len_cur = len_tmp; | 1285 | len_cur = len_tmp; |
1290 | start_cur = range->start; | 1286 | start_cur = range->start; |
1291 | } else { | 1287 | } else { |
1292 | /* Needs adjusting */ | 1288 | /* Needs adjusting */ |
1293 | tmp_start = range->start; | 1289 | tmp_start = range->start; |
1294 | flag = FALSE; | 1290 | flag = 0; |
1295 | 1291 | ||
1296 | while ((len_tmp = range->end - tmp_start) >= res->len) { | 1292 | while ((len_tmp = range->end - tmp_start) >= res->len) { |
1297 | if ((tmp_start % tmp_divide) == 0) { | 1293 | if ((tmp_start % tmp_divide) == 0) { |
1298 | flag = TRUE; | 1294 | flag = 1; |
1299 | len_cur = len_tmp; | 1295 | len_cur = len_tmp; |
1300 | start_cur = tmp_start; | 1296 | start_cur = tmp_start; |
1301 | break; | 1297 | break; |
@@ -1688,7 +1684,7 @@ static int __init once_over (void) | |||
1688 | bus_cur = list_entry (tmp, struct bus_node, bus_list); | 1684 | bus_cur = list_entry (tmp, struct bus_node, bus_list); |
1689 | if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { | 1685 | if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { |
1690 | for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { | 1686 | for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { |
1691 | pfmem_cur->fromMem = TRUE; | 1687 | pfmem_cur->fromMem = 1; |
1692 | if (pfmem_prev) | 1688 | if (pfmem_prev) |
1693 | pfmem_prev->next = pfmem_cur->next; | 1689 | pfmem_prev->next = pfmem_cur->next; |
1694 | else | 1690 | else |
@@ -1705,12 +1701,11 @@ static int __init once_over (void) | |||
1705 | 1701 | ||
1706 | bus_cur->firstPFMemFromMem = pfmem_cur; | 1702 | bus_cur->firstPFMemFromMem = pfmem_cur; |
1707 | 1703 | ||
1708 | mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 1704 | mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
1709 | if (!mem) { | 1705 | if (!mem) { |
1710 | err ("out of system memory\n"); | 1706 | err ("out of system memory\n"); |
1711 | return -ENOMEM; | 1707 | return -ENOMEM; |
1712 | } | 1708 | } |
1713 | memset (mem, 0, sizeof (struct resource_node)); | ||
1714 | mem->type = MEM; | 1709 | mem->type = MEM; |
1715 | mem->busno = pfmem_cur->busno; | 1710 | mem->busno = pfmem_cur->busno; |
1716 | mem->devfunc = pfmem_cur->devfunc; | 1711 | mem->devfunc = pfmem_cur->devfunc; |
@@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
1994 | end_address |= (upper_io_end << 16); | 1989 | end_address |= (upper_io_end << 16); |
1995 | 1990 | ||
1996 | if ((start_address) && (start_address <= end_address)) { | 1991 | if ((start_address) && (start_address <= end_address)) { |
1997 | range = kmalloc (sizeof (struct range_node), GFP_KERNEL); | 1992 | range = kzalloc(sizeof(struct range_node), GFP_KERNEL); |
1998 | if (!range) { | 1993 | if (!range) { |
1999 | err ("out of system memory\n"); | 1994 | err ("out of system memory\n"); |
2000 | return -ENOMEM; | 1995 | return -ENOMEM; |
2001 | } | 1996 | } |
2002 | memset (range, 0, sizeof (struct range_node)); | ||
2003 | range->start = start_address; | 1997 | range->start = start_address; |
2004 | range->end = end_address + 0xfff; | 1998 | range->end = end_address + 0xfff; |
2005 | 1999 | ||
@@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2020 | fix_resources (bus_sec); | 2014 | fix_resources (bus_sec); |
2021 | 2015 | ||
2022 | if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { | 2016 | if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { |
2023 | io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 2017 | io = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
2024 | if (!io) { | 2018 | if (!io) { |
2025 | kfree (range); | 2019 | kfree (range); |
2026 | err ("out of system memory\n"); | 2020 | err ("out of system memory\n"); |
2027 | return -ENOMEM; | 2021 | return -ENOMEM; |
2028 | } | 2022 | } |
2029 | memset (io, 0, sizeof (struct resource_node)); | ||
2030 | io->type = IO; | 2023 | io->type = IO; |
2031 | io->busno = bus_cur->busno; | 2024 | io->busno = bus_cur->busno; |
2032 | io->devfunc = ((device << 3) | (function & 0x7)); | 2025 | io->devfunc = ((device << 3) | (function & 0x7)); |
@@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2045 | 2038 | ||
2046 | if ((start_address) && (start_address <= end_address)) { | 2039 | if ((start_address) && (start_address <= end_address)) { |
2047 | 2040 | ||
2048 | range = kmalloc (sizeof (struct range_node), GFP_KERNEL); | 2041 | range = kzalloc(sizeof(struct range_node), GFP_KERNEL); |
2049 | if (!range) { | 2042 | if (!range) { |
2050 | err ("out of system memory\n"); | 2043 | err ("out of system memory\n"); |
2051 | return -ENOMEM; | 2044 | return -ENOMEM; |
2052 | } | 2045 | } |
2053 | memset (range, 0, sizeof (struct range_node)); | ||
2054 | range->start = start_address; | 2046 | range->start = start_address; |
2055 | range->end = end_address + 0xfffff; | 2047 | range->end = end_address + 0xfffff; |
2056 | 2048 | ||
@@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2072 | fix_resources (bus_sec); | 2064 | fix_resources (bus_sec); |
2073 | 2065 | ||
2074 | if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { | 2066 | if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { |
2075 | mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 2067 | mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
2076 | if (!mem) { | 2068 | if (!mem) { |
2077 | kfree (range); | 2069 | kfree (range); |
2078 | err ("out of system memory\n"); | 2070 | err ("out of system memory\n"); |
2079 | return -ENOMEM; | 2071 | return -ENOMEM; |
2080 | } | 2072 | } |
2081 | memset (mem, 0, sizeof (struct resource_node)); | ||
2082 | mem->type = MEM; | 2073 | mem->type = MEM; |
2083 | mem->busno = bus_cur->busno; | 2074 | mem->busno = bus_cur->busno; |
2084 | mem->devfunc = ((device << 3) | (function & 0x7)); | 2075 | mem->devfunc = ((device << 3) | (function & 0x7)); |
@@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2101 | 2092 | ||
2102 | if ((start_address) && (start_address <= end_address)) { | 2093 | if ((start_address) && (start_address <= end_address)) { |
2103 | 2094 | ||
2104 | range = kmalloc (sizeof (struct range_node), GFP_KERNEL); | 2095 | range = kzalloc(sizeof(struct range_node), GFP_KERNEL); |
2105 | if (!range) { | 2096 | if (!range) { |
2106 | err ("out of system memory\n"); | 2097 | err ("out of system memory\n"); |
2107 | return -ENOMEM; | 2098 | return -ENOMEM; |
2108 | } | 2099 | } |
2109 | memset (range, 0, sizeof (struct range_node)); | ||
2110 | range->start = start_address; | 2100 | range->start = start_address; |
2111 | range->end = end_address + 0xfffff; | 2101 | range->end = end_address + 0xfffff; |
2112 | 2102 | ||
@@ -2127,20 +2117,19 @@ static int __init update_bridge_ranges (struct bus_node **bus) | |||
2127 | 2117 | ||
2128 | fix_resources (bus_sec); | 2118 | fix_resources (bus_sec); |
2129 | if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { | 2119 | if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { |
2130 | pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); | 2120 | pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); |
2131 | if (!pfmem) { | 2121 | if (!pfmem) { |
2132 | kfree (range); | 2122 | kfree (range); |
2133 | err ("out of system memory\n"); | 2123 | err ("out of system memory\n"); |
2134 | return -ENOMEM; | 2124 | return -ENOMEM; |
2135 | } | 2125 | } |
2136 | memset (pfmem, 0, sizeof (struct resource_node)); | ||
2137 | pfmem->type = PFMEM; | 2126 | pfmem->type = PFMEM; |
2138 | pfmem->busno = bus_cur->busno; | 2127 | pfmem->busno = bus_cur->busno; |
2139 | pfmem->devfunc = ((device << 3) | (function & 0x7)); | 2128 | pfmem->devfunc = ((device << 3) | (function & 0x7)); |
2140 | pfmem->start = start_address; | 2129 | pfmem->start = start_address; |
2141 | pfmem->end = end_address + 0xfffff; | 2130 | pfmem->end = end_address + 0xfffff; |
2142 | pfmem->len = pfmem->end - pfmem->start + 1; | 2131 | pfmem->len = pfmem->end - pfmem->start + 1; |
2143 | pfmem->fromMem = FALSE; | 2132 | pfmem->fromMem = 0; |
2144 | 2133 | ||
2145 | ibmphp_add_resource (pfmem); | 2134 | ibmphp_add_resource (pfmem); |
2146 | } | 2135 | } |
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 88d44f7fef29..eb0d01d47236 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h | |||
@@ -176,5 +176,21 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot, | |||
176 | struct hotplug_slot_info *info); | 176 | struct hotplug_slot_info *info); |
177 | extern struct subsystem pci_hotplug_slots_subsys; | 177 | extern struct subsystem pci_hotplug_slots_subsys; |
178 | 178 | ||
179 | struct hotplug_params { | ||
180 | u8 cache_line_size; | ||
181 | u8 latency_timer; | ||
182 | u8 enable_serr; | ||
183 | u8 enable_perr; | ||
184 | }; | ||
185 | |||
186 | #ifdef CONFIG_ACPI | ||
187 | #include <acpi/acpi.h> | ||
188 | #include <acpi/acpi_bus.h> | ||
189 | #include <acpi/actypes.h> | ||
190 | extern acpi_status acpi_run_oshp(acpi_handle handle); | ||
191 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, | ||
192 | struct hotplug_params *hpp); | ||
193 | int acpi_root_bridge(acpi_handle handle); | ||
194 | #endif | ||
179 | #endif | 195 | #endif |
180 | 196 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 0aac6a61337d..92c1f0f1e1ad 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/sched.h> /* signal_pending() */ | 35 | #include <linux/sched.h> /* signal_pending() */ |
36 | #include <linux/pcieport_if.h> | 36 | #include <linux/pcieport_if.h> |
37 | #include <linux/mutex.h> | ||
37 | #include "pci_hotplug.h" | 38 | #include "pci_hotplug.h" |
38 | 39 | ||
39 | #define MY_NAME "pciehp" | 40 | #define MY_NAME "pciehp" |
@@ -49,12 +50,6 @@ extern int pciehp_force; | |||
49 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 50 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
50 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 51 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
51 | 52 | ||
52 | struct hotplug_params { | ||
53 | u8 cache_line_size; | ||
54 | u8 latency_timer; | ||
55 | u8 enable_serr; | ||
56 | u8 enable_perr; | ||
57 | }; | ||
58 | 53 | ||
59 | struct slot { | 54 | struct slot { |
60 | struct slot *next; | 55 | struct slot *next; |
@@ -96,7 +91,7 @@ struct php_ctlr_state_s { | |||
96 | #define MAX_EVENTS 10 | 91 | #define MAX_EVENTS 10 |
97 | struct controller { | 92 | struct controller { |
98 | struct controller *next; | 93 | struct controller *next; |
99 | struct semaphore crit_sect; /* critical section semaphore */ | 94 | struct mutex crit_sect; /* critical section mutex */ |
100 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | 95 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
101 | int num_slots; /* Number of slots on ctlr */ | 96 | int num_slots; /* Number of slots on ctlr */ |
102 | int slot_num_inc; /* 1 or -1 */ | 97 | int slot_num_inc; /* 1 or -1 */ |
@@ -191,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); | |||
191 | /* pci functions */ | 186 | /* pci functions */ |
192 | extern int pciehp_configure_device (struct slot *p_slot); | 187 | extern int pciehp_configure_device (struct slot *p_slot); |
193 | extern int pciehp_unconfigure_device (struct slot *p_slot); | 188 | extern int pciehp_unconfigure_device (struct slot *p_slot); |
194 | extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); | ||
195 | extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | ||
196 | struct hotplug_params *hpp); | ||
197 | 189 | ||
198 | 190 | ||
199 | 191 | ||
@@ -285,4 +277,19 @@ struct hpc_ops { | |||
285 | int (*check_lnk_status) (struct controller *ctrl); | 277 | int (*check_lnk_status) (struct controller *ctrl); |
286 | }; | 278 | }; |
287 | 279 | ||
280 | |||
281 | #ifdef CONFIG_ACPI | ||
282 | #define pciehp_get_hp_hw_control_from_firmware(dev) \ | ||
283 | pciehp_acpi_get_hp_hw_control_from_firmware(dev) | ||
284 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | ||
285 | struct hotplug_params *hpp) | ||
286 | { | ||
287 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) | ||
288 | return -ENODEV; | ||
289 | return 0; | ||
290 | } | ||
291 | #else | ||
292 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 | ||
293 | #define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) | ||
294 | #endif /* CONFIG_ACPI */ | ||
288 | #endif /* _PCIEHP_H */ | 295 | #endif /* _PCIEHP_H */ |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4fb569018a24..601cf9045b20 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl) | |||
117 | slot_number = ctrl->first_slot; | 117 | slot_number = ctrl->first_slot; |
118 | 118 | ||
119 | while (number_of_slots) { | 119 | while (number_of_slots) { |
120 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); | 120 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
121 | if (!slot) | 121 | if (!slot) |
122 | goto error; | 122 | goto error; |
123 | 123 | ||
124 | memset(slot, 0, sizeof(struct slot)); | ||
125 | slot->hotplug_slot = | 124 | slot->hotplug_slot = |
126 | kmalloc(sizeof(*(slot->hotplug_slot)), | 125 | kzalloc(sizeof(*(slot->hotplug_slot)), |
127 | GFP_KERNEL); | 126 | GFP_KERNEL); |
128 | if (!slot->hotplug_slot) | 127 | if (!slot->hotplug_slot) |
129 | goto error_slot; | 128 | goto error_slot; |
130 | hotplug_slot = slot->hotplug_slot; | 129 | hotplug_slot = slot->hotplug_slot; |
131 | memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); | ||
132 | 130 | ||
133 | hotplug_slot->info = | 131 | hotplug_slot->info = |
134 | kmalloc(sizeof(*(hotplug_slot->info)), | 132 | kzalloc(sizeof(*(hotplug_slot->info)), |
135 | GFP_KERNEL); | 133 | GFP_KERNEL); |
136 | if (!hotplug_slot->info) | 134 | if (!hotplug_slot->info) |
137 | goto error_hpslot; | 135 | goto error_hpslot; |
138 | hotplug_slot_info = hotplug_slot->info; | 136 | hotplug_slot_info = hotplug_slot->info; |
139 | memset(hotplug_slot_info, 0, | ||
140 | sizeof(struct hotplug_slot_info)); | ||
141 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | 137 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); |
142 | if (!hotplug_slot->name) | 138 | if (!hotplug_slot->name) |
143 | goto error_info; | 139 | goto error_info; |
@@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
373 | u8 value; | 369 | u8 value; |
374 | struct pci_dev *pdev; | 370 | struct pci_dev *pdev; |
375 | 371 | ||
376 | ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); | 372 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); |
377 | if (!ctrl) { | 373 | if (!ctrl) { |
378 | err("%s : out of memory\n", __FUNCTION__); | 374 | err("%s : out of memory\n", __FUNCTION__); |
379 | goto err_out_none; | 375 | goto err_out_none; |
380 | } | 376 | } |
381 | memset(ctrl, 0, sizeof(struct controller)); | ||
382 | 377 | ||
383 | pdev = dev->port; | 378 | pdev = dev->port; |
384 | ctrl->pci_dev = pdev; | 379 | ctrl->pci_dev = pdev; |
@@ -439,7 +434,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
439 | } | 434 | } |
440 | 435 | ||
441 | /* Wait for exclusive access to hardware */ | 436 | /* Wait for exclusive access to hardware */ |
442 | down(&ctrl->crit_sect); | 437 | mutex_lock(&ctrl->crit_sect); |
443 | 438 | ||
444 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 439 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
445 | 440 | ||
@@ -447,7 +442,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
447 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 442 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
448 | if (rc) { | 443 | if (rc) { |
449 | /* Done with exclusive hardware access */ | 444 | /* Done with exclusive hardware access */ |
450 | up(&ctrl->crit_sect); | 445 | mutex_unlock(&ctrl->crit_sect); |
451 | goto err_out_free_ctrl_slot; | 446 | goto err_out_free_ctrl_slot; |
452 | } else | 447 | } else |
453 | /* Wait for the command to complete */ | 448 | /* Wait for the command to complete */ |
@@ -455,7 +450,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
455 | } | 450 | } |
456 | 451 | ||
457 | /* Done with exclusive hardware access */ | 452 | /* Done with exclusive hardware access */ |
458 | up(&ctrl->crit_sect); | 453 | mutex_unlock(&ctrl->crit_sect); |
459 | 454 | ||
460 | return 0; | 455 | return 0; |
461 | 456 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 83c4b865718a..33d198768356 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
229 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) | 229 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) |
230 | { | 230 | { |
231 | /* Wait for exclusive access to hardware */ | 231 | /* Wait for exclusive access to hardware */ |
232 | down(&ctrl->crit_sect); | 232 | mutex_lock(&ctrl->crit_sect); |
233 | 233 | ||
234 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 234 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
235 | if (POWER_CTRL(ctrl->ctrlcap)) { | 235 | if (POWER_CTRL(ctrl->ctrlcap)) { |
236 | if (pslot->hpc_ops->power_off_slot(pslot)) { | 236 | if (pslot->hpc_ops->power_off_slot(pslot)) { |
237 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); | 237 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); |
238 | up(&ctrl->crit_sect); | 238 | mutex_unlock(&ctrl->crit_sect); |
239 | return; | 239 | return; |
240 | } | 240 | } |
241 | wait_for_ctrl_irq (ctrl); | 241 | wait_for_ctrl_irq (ctrl); |
@@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
249 | if (ATTN_LED(ctrl->ctrlcap)) { | 249 | if (ATTN_LED(ctrl->ctrlcap)) { |
250 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { | 250 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { |
251 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); | 251 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); |
252 | up(&ctrl->crit_sect); | 252 | mutex_unlock(&ctrl->crit_sect); |
253 | return; | 253 | return; |
254 | } | 254 | } |
255 | wait_for_ctrl_irq (ctrl); | 255 | wait_for_ctrl_irq (ctrl); |
256 | } | 256 | } |
257 | 257 | ||
258 | /* Done with exclusive hardware access */ | 258 | /* Done with exclusive hardware access */ |
259 | up(&ctrl->crit_sect); | 259 | mutex_unlock(&ctrl->crit_sect); |
260 | } | 260 | } |
261 | 261 | ||
262 | /** | 262 | /** |
@@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot) | |||
279 | ctrl->slot_device_offset, hp_slot); | 279 | ctrl->slot_device_offset, hp_slot); |
280 | 280 | ||
281 | /* Wait for exclusive access to hardware */ | 281 | /* Wait for exclusive access to hardware */ |
282 | down(&ctrl->crit_sect); | 282 | mutex_lock(&ctrl->crit_sect); |
283 | 283 | ||
284 | if (POWER_CTRL(ctrl->ctrlcap)) { | 284 | if (POWER_CTRL(ctrl->ctrlcap)) { |
285 | /* Power on slot */ | 285 | /* Power on slot */ |
286 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 286 | rc = p_slot->hpc_ops->power_on_slot(p_slot); |
287 | if (rc) { | 287 | if (rc) { |
288 | up(&ctrl->crit_sect); | 288 | mutex_unlock(&ctrl->crit_sect); |
289 | return -1; | 289 | return -1; |
290 | } | 290 | } |
291 | 291 | ||
@@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | /* Done with exclusive hardware access */ | 303 | /* Done with exclusive hardware access */ |
304 | up(&ctrl->crit_sect); | 304 | mutex_unlock(&ctrl->crit_sect); |
305 | 305 | ||
306 | /* Wait for ~1 second */ | 306 | /* Wait for ~1 second */ |
307 | wait_for_ctrl_irq (ctrl); | 307 | wait_for_ctrl_irq (ctrl); |
@@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot) | |||
335 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | 335 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
336 | if (PWR_LED(ctrl->ctrlcap)) { | 336 | if (PWR_LED(ctrl->ctrlcap)) { |
337 | /* Wait for exclusive access to hardware */ | 337 | /* Wait for exclusive access to hardware */ |
338 | down(&ctrl->crit_sect); | 338 | mutex_lock(&ctrl->crit_sect); |
339 | 339 | ||
340 | p_slot->hpc_ops->green_led_on(p_slot); | 340 | p_slot->hpc_ops->green_led_on(p_slot); |
341 | 341 | ||
@@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot) | |||
343 | wait_for_ctrl_irq (ctrl); | 343 | wait_for_ctrl_irq (ctrl); |
344 | 344 | ||
345 | /* Done with exclusive hardware access */ | 345 | /* Done with exclusive hardware access */ |
346 | up(&ctrl->crit_sect); | 346 | mutex_unlock(&ctrl->crit_sect); |
347 | } | 347 | } |
348 | return 0; | 348 | return 0; |
349 | 349 | ||
@@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot) | |||
375 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 375 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
376 | 376 | ||
377 | /* Wait for exclusive access to hardware */ | 377 | /* Wait for exclusive access to hardware */ |
378 | down(&ctrl->crit_sect); | 378 | mutex_lock(&ctrl->crit_sect); |
379 | 379 | ||
380 | if (POWER_CTRL(ctrl->ctrlcap)) { | 380 | if (POWER_CTRL(ctrl->ctrlcap)) { |
381 | /* power off slot */ | 381 | /* power off slot */ |
382 | rc = p_slot->hpc_ops->power_off_slot(p_slot); | 382 | rc = p_slot->hpc_ops->power_off_slot(p_slot); |
383 | if (rc) { | 383 | if (rc) { |
384 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 384 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
385 | up(&ctrl->crit_sect); | 385 | mutex_unlock(&ctrl->crit_sect); |
386 | return rc; | 386 | return rc; |
387 | } | 387 | } |
388 | /* Wait for the command to complete */ | 388 | /* Wait for the command to complete */ |
@@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot) | |||
398 | } | 398 | } |
399 | 399 | ||
400 | /* Done with exclusive hardware access */ | 400 | /* Done with exclusive hardware access */ |
401 | up(&ctrl->crit_sect); | 401 | mutex_unlock(&ctrl->crit_sect); |
402 | 402 | ||
403 | return 0; | 403 | return 0; |
404 | } | 404 | } |
@@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
445 | 445 | ||
446 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 446 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
447 | /* Wait for exclusive access to hardware */ | 447 | /* Wait for exclusive access to hardware */ |
448 | down(&p_slot->ctrl->crit_sect); | 448 | mutex_lock(&p_slot->ctrl->crit_sect); |
449 | 449 | ||
450 | p_slot->hpc_ops->green_led_off(p_slot); | 450 | p_slot->hpc_ops->green_led_off(p_slot); |
451 | 451 | ||
@@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
453 | wait_for_ctrl_irq (p_slot->ctrl); | 453 | wait_for_ctrl_irq (p_slot->ctrl); |
454 | 454 | ||
455 | /* Done with exclusive hardware access */ | 455 | /* Done with exclusive hardware access */ |
456 | up(&p_slot->ctrl->crit_sect); | 456 | mutex_unlock(&p_slot->ctrl->crit_sect); |
457 | } | 457 | } |
458 | p_slot->state = STATIC_STATE; | 458 | p_slot->state = STATIC_STATE; |
459 | } | 459 | } |
@@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
495 | 495 | ||
496 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 496 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
497 | /* Wait for exclusive access to hardware */ | 497 | /* Wait for exclusive access to hardware */ |
498 | down(&p_slot->ctrl->crit_sect); | 498 | mutex_lock(&p_slot->ctrl->crit_sect); |
499 | 499 | ||
500 | p_slot->hpc_ops->green_led_off(p_slot); | 500 | p_slot->hpc_ops->green_led_off(p_slot); |
501 | 501 | ||
@@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
503 | wait_for_ctrl_irq (p_slot->ctrl); | 503 | wait_for_ctrl_irq (p_slot->ctrl); |
504 | 504 | ||
505 | /* Done with exclusive hardware access */ | 505 | /* Done with exclusive hardware access */ |
506 | up(&p_slot->ctrl->crit_sect); | 506 | mutex_unlock(&p_slot->ctrl->crit_sect); |
507 | } | 507 | } |
508 | p_slot->state = STATIC_STATE; | 508 | p_slot->state = STATIC_STATE; |
509 | } | 509 | } |
@@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
616 | switch (p_slot->state) { | 616 | switch (p_slot->state) { |
617 | case BLINKINGOFF_STATE: | 617 | case BLINKINGOFF_STATE: |
618 | /* Wait for exclusive access to hardware */ | 618 | /* Wait for exclusive access to hardware */ |
619 | down(&ctrl->crit_sect); | 619 | mutex_lock(&ctrl->crit_sect); |
620 | 620 | ||
621 | if (PWR_LED(ctrl->ctrlcap)) { | 621 | if (PWR_LED(ctrl->ctrlcap)) { |
622 | p_slot->hpc_ops->green_led_on(p_slot); | 622 | p_slot->hpc_ops->green_led_on(p_slot); |
@@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
630 | wait_for_ctrl_irq (ctrl); | 630 | wait_for_ctrl_irq (ctrl); |
631 | } | 631 | } |
632 | /* Done with exclusive hardware access */ | 632 | /* Done with exclusive hardware access */ |
633 | up(&ctrl->crit_sect); | 633 | mutex_unlock(&ctrl->crit_sect); |
634 | break; | 634 | break; |
635 | case BLINKINGON_STATE: | 635 | case BLINKINGON_STATE: |
636 | /* Wait for exclusive access to hardware */ | 636 | /* Wait for exclusive access to hardware */ |
637 | down(&ctrl->crit_sect); | 637 | mutex_lock(&ctrl->crit_sect); |
638 | 638 | ||
639 | if (PWR_LED(ctrl->ctrlcap)) { | 639 | if (PWR_LED(ctrl->ctrlcap)) { |
640 | p_slot->hpc_ops->green_led_off(p_slot); | 640 | p_slot->hpc_ops->green_led_off(p_slot); |
@@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
647 | wait_for_ctrl_irq (ctrl); | 647 | wait_for_ctrl_irq (ctrl); |
648 | } | 648 | } |
649 | /* Done with exclusive hardware access */ | 649 | /* Done with exclusive hardware access */ |
650 | up(&ctrl->crit_sect); | 650 | mutex_unlock(&ctrl->crit_sect); |
651 | 651 | ||
652 | break; | 652 | break; |
653 | default: | 653 | default: |
@@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
676 | } | 676 | } |
677 | 677 | ||
678 | /* Wait for exclusive access to hardware */ | 678 | /* Wait for exclusive access to hardware */ |
679 | down(&ctrl->crit_sect); | 679 | mutex_lock(&ctrl->crit_sect); |
680 | 680 | ||
681 | /* blink green LED and turn off amber */ | 681 | /* blink green LED and turn off amber */ |
682 | if (PWR_LED(ctrl->ctrlcap)) { | 682 | if (PWR_LED(ctrl->ctrlcap)) { |
@@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
693 | } | 693 | } |
694 | 694 | ||
695 | /* Done with exclusive hardware access */ | 695 | /* Done with exclusive hardware access */ |
696 | up(&ctrl->crit_sect); | 696 | mutex_unlock(&ctrl->crit_sect); |
697 | 697 | ||
698 | init_timer(&p_slot->task_event); | 698 | init_timer(&p_slot->task_event); |
699 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 699 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
@@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
708 | if (POWER_CTRL(ctrl->ctrlcap)) { | 708 | if (POWER_CTRL(ctrl->ctrlcap)) { |
709 | dbg("power fault\n"); | 709 | dbg("power fault\n"); |
710 | /* Wait for exclusive access to hardware */ | 710 | /* Wait for exclusive access to hardware */ |
711 | down(&ctrl->crit_sect); | 711 | mutex_lock(&ctrl->crit_sect); |
712 | 712 | ||
713 | if (ATTN_LED(ctrl->ctrlcap)) { | 713 | if (ATTN_LED(ctrl->ctrlcap)) { |
714 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 714 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
@@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
721 | } | 721 | } |
722 | 722 | ||
723 | /* Done with exclusive hardware access */ | 723 | /* Done with exclusive hardware access */ |
724 | up(&ctrl->crit_sect); | 724 | mutex_unlock(&ctrl->crit_sect); |
725 | } | 725 | } |
726 | } | 726 | } |
727 | /***********SURPRISE REMOVAL********************/ | 727 | /***********SURPRISE REMOVAL********************/ |
@@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
756 | int rc; | 756 | int rc; |
757 | 757 | ||
758 | /* Check to see if (latch closed, card present, power off) */ | 758 | /* Check to see if (latch closed, card present, power off) */ |
759 | down(&p_slot->ctrl->crit_sect); | 759 | mutex_lock(&p_slot->ctrl->crit_sect); |
760 | 760 | ||
761 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 761 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
762 | if (rc || !getstatus) { | 762 | if (rc || !getstatus) { |
763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
764 | up(&p_slot->ctrl->crit_sect); | 764 | mutex_unlock(&p_slot->ctrl->crit_sect); |
765 | return 1; | 765 | return 1; |
766 | } | 766 | } |
767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
769 | if (rc || getstatus) { | 769 | if (rc || getstatus) { |
770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
771 | up(&p_slot->ctrl->crit_sect); | 771 | mutex_unlock(&p_slot->ctrl->crit_sect); |
772 | return 1; | 772 | return 1; |
773 | } | 773 | } |
774 | } | 774 | } |
@@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
777 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 777 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
778 | if (rc || getstatus) { | 778 | if (rc || getstatus) { |
779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); |
780 | up(&p_slot->ctrl->crit_sect); | 780 | mutex_unlock(&p_slot->ctrl->crit_sect); |
781 | return 1; | 781 | return 1; |
782 | } | 782 | } |
783 | } | 783 | } |
784 | up(&p_slot->ctrl->crit_sect); | 784 | mutex_unlock(&p_slot->ctrl->crit_sect); |
785 | 785 | ||
786 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 786 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
787 | 787 | ||
@@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
806 | return 1; | 806 | return 1; |
807 | 807 | ||
808 | /* Check to see if (latch closed, card present, power on) */ | 808 | /* Check to see if (latch closed, card present, power on) */ |
809 | down(&p_slot->ctrl->crit_sect); | 809 | mutex_lock(&p_slot->ctrl->crit_sect); |
810 | 810 | ||
811 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { | 811 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { |
812 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 812 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
813 | if (ret || !getstatus) { | 813 | if (ret || !getstatus) { |
814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
815 | up(&p_slot->ctrl->crit_sect); | 815 | mutex_unlock(&p_slot->ctrl->crit_sect); |
816 | return 1; | 816 | return 1; |
817 | } | 817 | } |
818 | } | 818 | } |
@@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
821 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 821 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
822 | if (ret || getstatus) { | 822 | if (ret || getstatus) { |
823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
824 | up(&p_slot->ctrl->crit_sect); | 824 | mutex_unlock(&p_slot->ctrl->crit_sect); |
825 | return 1; | 825 | return 1; |
826 | } | 826 | } |
827 | } | 827 | } |
@@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
830 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 830 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
831 | if (ret || !getstatus) { | 831 | if (ret || !getstatus) { |
832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); |
833 | up(&p_slot->ctrl->crit_sect); | 833 | mutex_unlock(&p_slot->ctrl->crit_sect); |
834 | return 1; | 834 | return 1; |
835 | } | 835 | } |
836 | } | 836 | } |
837 | 837 | ||
838 | up(&p_slot->ctrl->crit_sect); | 838 | mutex_unlock(&p_slot->ctrl->crit_sect); |
839 | 839 | ||
840 | ret = remove_board(p_slot); | 840 | ret = remove_board(p_slot); |
841 | update_slot_info(p_slot); | 841 | update_slot_info(p_slot); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 77e530321de2..6c14d9e46b2e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -38,7 +38,10 @@ | |||
38 | 38 | ||
39 | #include "../pci.h" | 39 | #include "../pci.h" |
40 | #include "pciehp.h" | 40 | #include "pciehp.h" |
41 | 41 | #include <acpi/acpi.h> | |
42 | #include <acpi/acpi_bus.h> | ||
43 | #include <acpi/actypes.h> | ||
44 | #include <linux/pci-acpi.h> | ||
42 | #ifdef DEBUG | 45 | #ifdef DEBUG |
43 | #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ | 46 | #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ |
44 | #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ | 47 | #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ |
@@ -1236,6 +1239,76 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
1236 | .check_lnk_status = hpc_check_lnk_status, | 1239 | .check_lnk_status = hpc_check_lnk_status, |
1237 | }; | 1240 | }; |
1238 | 1241 | ||
1242 | #ifdef CONFIG_ACPI | ||
1243 | int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
1244 | { | ||
1245 | acpi_status status; | ||
1246 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | ||
1247 | struct pci_dev *pdev = dev; | ||
1248 | struct pci_bus *parent; | ||
1249 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1250 | |||
1251 | /* | ||
1252 | * Per PCI firmware specification, we should run the ACPI _OSC | ||
1253 | * method to get control of hotplug hardware before using it. | ||
1254 | * If an _OSC is missing, we look for an OSHP to do the same thing. | ||
1255 | * To handle different BIOS behavior, we look for _OSC and OSHP | ||
1256 | * within the scope of the hotplug controller and its parents, upto | ||
1257 | * the host bridge under which this controller exists. | ||
1258 | */ | ||
1259 | while (!handle) { | ||
1260 | /* | ||
1261 | * This hotplug controller was not listed in the ACPI name | ||
1262 | * space at all. Try to get acpi handle of parent pci bus. | ||
1263 | */ | ||
1264 | if (!pdev || !pdev->bus->parent) | ||
1265 | break; | ||
1266 | parent = pdev->bus->parent; | ||
1267 | dbg("Could not find %s in acpi namespace, trying parent\n", | ||
1268 | pci_name(pdev)); | ||
1269 | if (!parent->self) | ||
1270 | /* Parent must be a host bridge */ | ||
1271 | handle = acpi_get_pci_rootbridge_handle( | ||
1272 | pci_domain_nr(parent), | ||
1273 | parent->number); | ||
1274 | else | ||
1275 | handle = DEVICE_ACPI_HANDLE( | ||
1276 | &(parent->self->dev)); | ||
1277 | pdev = parent->self; | ||
1278 | } | ||
1279 | |||
1280 | while (handle) { | ||
1281 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
1282 | dbg("Trying to get hotplug control for %s \n", | ||
1283 | (char *)string.pointer); | ||
1284 | status = pci_osc_control_set(handle, | ||
1285 | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); | ||
1286 | if (status == AE_NOT_FOUND) | ||
1287 | status = acpi_run_oshp(handle); | ||
1288 | if (ACPI_SUCCESS(status)) { | ||
1289 | dbg("Gained control for hotplug HW for pci %s (%s)\n", | ||
1290 | pci_name(dev), (char *)string.pointer); | ||
1291 | acpi_os_free(string.pointer); | ||
1292 | return 0; | ||
1293 | } | ||
1294 | if (acpi_root_bridge(handle)) | ||
1295 | break; | ||
1296 | chandle = handle; | ||
1297 | status = acpi_get_parent(chandle, &handle); | ||
1298 | if (ACPI_FAILURE(status)) | ||
1299 | break; | ||
1300 | } | ||
1301 | |||
1302 | err("Cannot get control of hotplug hardware for pci %s\n", | ||
1303 | pci_name(dev)); | ||
1304 | |||
1305 | acpi_os_free(string.pointer); | ||
1306 | return -1; | ||
1307 | } | ||
1308 | #endif | ||
1309 | |||
1310 | |||
1311 | |||
1239 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) | 1312 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) |
1240 | { | 1313 | { |
1241 | struct php_ctlr_state_s *php_ctlr, *p; | 1314 | struct php_ctlr_state_s *php_ctlr, *p; |
@@ -1334,7 +1407,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1334 | if (pci_enable_device(pdev)) | 1407 | if (pci_enable_device(pdev)) |
1335 | goto abort_free_ctlr; | 1408 | goto abort_free_ctlr; |
1336 | 1409 | ||
1337 | init_MUTEX(&ctrl->crit_sect); | 1410 | mutex_init(&ctrl->crit_sect); |
1338 | /* setup wait queue */ | 1411 | /* setup wait queue */ |
1339 | init_waitqueue_head(&ctrl->queue); | 1412 | init_waitqueue_head(&ctrl->queue); |
1340 | 1413 | ||
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c deleted file mode 100644 index 2bdb30f68bf8..000000000000 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ /dev/null | |||
@@ -1,257 +0,0 @@ | |||
1 | /* | ||
2 | * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform | ||
3 | * | ||
4 | * Copyright (C) 2003-2004 Intel Corporation | ||
5 | * | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or (at | ||
11 | * your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
16 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
17 | * details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * Send feedback to <kristen.c.accardi@intel.com> | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/acpi.h> | ||
32 | #include <linux/pci-acpi.h> | ||
33 | #include <acpi/acpi_bus.h> | ||
34 | #include <acpi/actypes.h> | ||
35 | #include "pciehp.h" | ||
36 | |||
37 | #define METHOD_NAME__SUN "_SUN" | ||
38 | #define METHOD_NAME__HPP "_HPP" | ||
39 | #define METHOD_NAME_OSHP "OSHP" | ||
40 | |||
41 | static u8 * acpi_path_name( acpi_handle handle) | ||
42 | { | ||
43 | acpi_status status; | ||
44 | static u8 path_name[ACPI_PATHNAME_MAX]; | ||
45 | struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; | ||
46 | |||
47 | memset(path_name, 0, sizeof (path_name)); | ||
48 | status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); | ||
49 | |||
50 | if (ACPI_FAILURE(status)) | ||
51 | return NULL; | ||
52 | else | ||
53 | return path_name; | ||
54 | } | ||
55 | |||
56 | static acpi_status | ||
57 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | ||
58 | { | ||
59 | acpi_status status; | ||
60 | u8 nui[4]; | ||
61 | struct acpi_buffer ret_buf = { 0, NULL}; | ||
62 | union acpi_object *ext_obj, *package; | ||
63 | u8 *path_name = acpi_path_name(handle); | ||
64 | int i, len = 0; | ||
65 | |||
66 | /* get _hpp */ | ||
67 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | ||
68 | switch (status) { | ||
69 | case AE_BUFFER_OVERFLOW: | ||
70 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | ||
71 | if (!ret_buf.pointer) { | ||
72 | err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, | ||
73 | path_name); | ||
74 | return AE_NO_MEMORY; | ||
75 | } | ||
76 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | ||
77 | NULL, &ret_buf); | ||
78 | if (ACPI_SUCCESS(status)) | ||
79 | break; | ||
80 | default: | ||
81 | if (ACPI_FAILURE(status)) { | ||
82 | dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, | ||
83 | path_name, status); | ||
84 | return status; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | ext_obj = (union acpi_object *) ret_buf.pointer; | ||
89 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | ||
90 | err ("%s:%s _HPP obj not a package\n", __FUNCTION__, | ||
91 | path_name); | ||
92 | status = AE_ERROR; | ||
93 | goto free_and_return; | ||
94 | } | ||
95 | |||
96 | len = ext_obj->package.count; | ||
97 | package = (union acpi_object *) ret_buf.pointer; | ||
98 | for ( i = 0; (i < len) || (i < 4); i++) { | ||
99 | ext_obj = (union acpi_object *) &package->package.elements[i]; | ||
100 | switch (ext_obj->type) { | ||
101 | case ACPI_TYPE_INTEGER: | ||
102 | nui[i] = (u8)ext_obj->integer.value; | ||
103 | break; | ||
104 | default: | ||
105 | err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, | ||
106 | path_name); | ||
107 | status = AE_ERROR; | ||
108 | goto free_and_return; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | hpp->cache_line_size = nui[0]; | ||
113 | hpp->latency_timer = nui[1]; | ||
114 | hpp->enable_serr = nui[2]; | ||
115 | hpp->enable_perr = nui[3]; | ||
116 | |||
117 | dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); | ||
118 | dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); | ||
119 | dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); | ||
120 | dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); | ||
121 | |||
122 | free_and_return: | ||
123 | kfree(ret_buf.pointer); | ||
124 | return status; | ||
125 | } | ||
126 | |||
127 | static acpi_status acpi_run_oshp(acpi_handle handle) | ||
128 | { | ||
129 | acpi_status status; | ||
130 | u8 *path_name = acpi_path_name(handle); | ||
131 | |||
132 | /* run OSHP */ | ||
133 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); | ||
134 | if (ACPI_FAILURE(status)) { | ||
135 | dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, | ||
136 | status); | ||
137 | } else { | ||
138 | dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); | ||
139 | } | ||
140 | return status; | ||
141 | } | ||
142 | |||
143 | static int is_root_bridge(acpi_handle handle) | ||
144 | { | ||
145 | acpi_status status; | ||
146 | struct acpi_device_info *info; | ||
147 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
148 | int i; | ||
149 | |||
150 | status = acpi_get_object_info(handle, &buffer); | ||
151 | if (ACPI_SUCCESS(status)) { | ||
152 | info = buffer.pointer; | ||
153 | if ((info->valid & ACPI_VALID_HID) && | ||
154 | !strcmp(PCI_ROOT_HID_STRING, | ||
155 | info->hardware_id.value)) { | ||
156 | acpi_os_free(buffer.pointer); | ||
157 | return 1; | ||
158 | } | ||
159 | if (info->valid & ACPI_VALID_CID) { | ||
160 | for (i=0; i < info->compatibility_id.count; i++) { | ||
161 | if (!strcmp(PCI_ROOT_HID_STRING, | ||
162 | info->compatibility_id.id[i].value)) { | ||
163 | acpi_os_free(buffer.pointer); | ||
164 | return 1; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
173 | { | ||
174 | acpi_status status; | ||
175 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | ||
176 | struct pci_dev *pdev = dev; | ||
177 | struct pci_bus *parent; | ||
178 | u8 *path_name; | ||
179 | |||
180 | /* | ||
181 | * Per PCI firmware specification, we should run the ACPI _OSC | ||
182 | * method to get control of hotplug hardware before using it. | ||
183 | * If an _OSC is missing, we look for an OSHP to do the same thing. | ||
184 | * To handle different BIOS behavior, we look for _OSC and OSHP | ||
185 | * within the scope of the hotplug controller and its parents, upto | ||
186 | * the host bridge under which this controller exists. | ||
187 | */ | ||
188 | while (!handle) { | ||
189 | /* | ||
190 | * This hotplug controller was not listed in the ACPI name | ||
191 | * space at all. Try to get acpi handle of parent pci bus. | ||
192 | */ | ||
193 | if (!pdev || !pdev->bus->parent) | ||
194 | break; | ||
195 | parent = pdev->bus->parent; | ||
196 | dbg("Could not find %s in acpi namespace, trying parent\n", | ||
197 | pci_name(pdev)); | ||
198 | if (!parent->self) | ||
199 | /* Parent must be a host bridge */ | ||
200 | handle = acpi_get_pci_rootbridge_handle( | ||
201 | pci_domain_nr(parent), | ||
202 | parent->number); | ||
203 | else | ||
204 | handle = DEVICE_ACPI_HANDLE( | ||
205 | &(parent->self->dev)); | ||
206 | pdev = parent->self; | ||
207 | } | ||
208 | |||
209 | while (handle) { | ||
210 | path_name = acpi_path_name(handle); | ||
211 | dbg("Trying to get hotplug control for %s \n", path_name); | ||
212 | status = pci_osc_control_set(handle, | ||
213 | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); | ||
214 | if (status == AE_NOT_FOUND) | ||
215 | status = acpi_run_oshp(handle); | ||
216 | if (ACPI_SUCCESS(status)) { | ||
217 | dbg("Gained control for hotplug HW for pci %s (%s)\n", | ||
218 | pci_name(dev), path_name); | ||
219 | return 0; | ||
220 | } | ||
221 | if (is_root_bridge(handle)) | ||
222 | break; | ||
223 | chandle = handle; | ||
224 | status = acpi_get_parent(chandle, &handle); | ||
225 | if (ACPI_FAILURE(status)) | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | err("Cannot get control of hotplug hardware for pci %s\n", | ||
230 | pci_name(dev)); | ||
231 | return -1; | ||
232 | } | ||
233 | |||
234 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | ||
235 | struct hotplug_params *hpp) | ||
236 | { | ||
237 | acpi_status status = AE_NOT_FOUND; | ||
238 | struct pci_dev *pdev = dev; | ||
239 | |||
240 | /* | ||
241 | * _HPP settings apply to all child buses, until another _HPP is | ||
242 | * encountered. If we don't find an _HPP for the input pci dev, | ||
243 | * look for it in the parent device scope since that would apply to | ||
244 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | ||
245 | */ | ||
246 | while (pdev && (ACPI_FAILURE(status))) { | ||
247 | acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); | ||
248 | if (!handle) | ||
249 | break; | ||
250 | status = acpi_run_hpp(handle, hpp); | ||
251 | if (!(pdev->bus->parent)) | ||
252 | break; | ||
253 | /* Check if a parent object supports _HPP */ | ||
254 | pdev = pdev->bus->parent->self; | ||
255 | } | ||
256 | } | ||
257 | |||
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c deleted file mode 100644 index 29180dfe8493..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform | ||
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/kernel.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include "pciehp.h" | ||
37 | |||
38 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | ||
39 | struct hotplug_params *hpp) | ||
40 | { | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 3194d51c6ec9..0a46f549676a 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c | |||
@@ -37,10 +37,12 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include "pci_hotplug.h" | 38 | #include "pci_hotplug.h" |
39 | 39 | ||
40 | #define SLOT_NAME_SIZE 10 | ||
40 | struct slot { | 41 | struct slot { |
41 | u8 number; | 42 | u8 number; |
42 | struct hotplug_slot *hotplug_slot; | 43 | struct hotplug_slot *hotplug_slot; |
43 | struct list_head slot_list; | 44 | struct list_head slot_list; |
45 | char name[SLOT_NAME_SIZE]; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | static LIST_HEAD(slot_list); | 48 | static LIST_HEAD(slot_list); |
@@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
233 | 235 | ||
234 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 236 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
235 | kfree(slot->hotplug_slot->info); | 237 | kfree(slot->hotplug_slot->info); |
236 | kfree(slot->hotplug_slot->name); | ||
237 | kfree(slot->hotplug_slot); | 238 | kfree(slot->hotplug_slot); |
238 | kfree(slot); | 239 | kfree(slot); |
239 | } | 240 | } |
240 | 241 | ||
241 | #define SLOT_NAME_SIZE 10 | ||
242 | static void make_slot_name(struct slot *slot) | 242 | static void make_slot_name(struct slot *slot) |
243 | { | 243 | { |
244 | /* | 244 | /* |
@@ -257,7 +257,6 @@ static int __init init_slots(void) | |||
257 | struct slot *slot; | 257 | struct slot *slot; |
258 | struct hotplug_slot *hotplug_slot; | 258 | struct hotplug_slot *hotplug_slot; |
259 | struct hotplug_slot_info *info; | 259 | struct hotplug_slot_info *info; |
260 | char *name; | ||
261 | int retval = -ENOMEM; | 260 | int retval = -ENOMEM; |
262 | int i; | 261 | int i; |
263 | 262 | ||
@@ -266,31 +265,23 @@ static int __init init_slots(void) | |||
266 | * with the pci_hotplug subsystem. | 265 | * with the pci_hotplug subsystem. |
267 | */ | 266 | */ |
268 | for (i = 0; i < num_slots; ++i) { | 267 | for (i = 0; i < num_slots; ++i) { |
269 | slot = kmalloc(sizeof(struct slot), GFP_KERNEL); | 268 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
270 | if (!slot) | 269 | if (!slot) |
271 | goto error; | 270 | goto error; |
272 | memset(slot, 0, sizeof(struct slot)); | ||
273 | 271 | ||
274 | hotplug_slot = kmalloc(sizeof(struct hotplug_slot), | 272 | hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); |
275 | GFP_KERNEL); | ||
276 | if (!hotplug_slot) | 273 | if (!hotplug_slot) |
277 | goto error_slot; | 274 | goto error_slot; |
278 | memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); | ||
279 | slot->hotplug_slot = hotplug_slot; | 275 | slot->hotplug_slot = hotplug_slot; |
280 | 276 | ||
281 | info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); | 277 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
282 | if (!info) | 278 | if (!info) |
283 | goto error_hpslot; | 279 | goto error_hpslot; |
284 | memset(info, 0, sizeof (struct hotplug_slot_info)); | ||
285 | hotplug_slot->info = info; | 280 | hotplug_slot->info = info; |
286 | 281 | ||
287 | name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | ||
288 | if (!name) | ||
289 | goto error_info; | ||
290 | hotplug_slot->name = name; | ||
291 | |||
292 | slot->number = i; | 282 | slot->number = i; |
293 | 283 | ||
284 | hotplug_slot->name = slot->name; | ||
294 | hotplug_slot->private = slot; | 285 | hotplug_slot->private = slot; |
295 | hotplug_slot->release = &release_slot; | 286 | hotplug_slot->release = &release_slot; |
296 | make_slot_name(slot); | 287 | make_slot_name(slot); |
@@ -300,16 +291,16 @@ static int __init init_slots(void) | |||
300 | * Initialize the slot info structure with some known | 291 | * Initialize the slot info structure with some known |
301 | * good values. | 292 | * good values. |
302 | */ | 293 | */ |
303 | info->power_status = get_power_status(slot); | 294 | get_power_status(hotplug_slot, &info->power_status); |
304 | info->attention_status = get_attention_status(slot); | 295 | get_attention_status(hotplug_slot, &info->attention_status); |
305 | info->latch_status = get_latch_status(slot); | 296 | get_latch_status(hotplug_slot, &info->latch_status); |
306 | info->adapter_status = get_adapter_status(slot); | 297 | get_adapter_status(hotplug_slot, &info->adapter_status); |
307 | 298 | ||
308 | dbg("registering slot %d\n", i); | 299 | dbg("registering slot %d\n", i); |
309 | retval = pci_hp_register(slot->hotplug_slot); | 300 | retval = pci_hp_register(slot->hotplug_slot); |
310 | if (retval) { | 301 | if (retval) { |
311 | err("pci_hp_register failed with error %d\n", retval); | 302 | err("pci_hp_register failed with error %d\n", retval); |
312 | goto error_name; | 303 | goto error_info; |
313 | } | 304 | } |
314 | 305 | ||
315 | /* add slot to our internal list */ | 306 | /* add slot to our internal list */ |
@@ -317,8 +308,6 @@ static int __init init_slots(void) | |||
317 | } | 308 | } |
318 | 309 | ||
319 | return 0; | 310 | return 0; |
320 | error_name: | ||
321 | kfree(name); | ||
322 | error_info: | 311 | error_info: |
323 | kfree(info); | 312 | kfree(info); |
324 | error_hpslot: | 313 | error_hpslot: |
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 78943e064b59..b771196a654e 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c | |||
@@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_ | |||
84 | { | 84 | { |
85 | struct slot *slot; | 85 | struct slot *slot; |
86 | 86 | ||
87 | slot = kmalloc(sizeof (struct slot), GFP_KERNEL); | 87 | slot = kzalloc(sizeof(struct slot), GFP_KERNEL); |
88 | if (!slot) | 88 | if (!slot) |
89 | goto error_nomem; | 89 | goto error_nomem; |
90 | memset(slot, 0, sizeof (struct slot)); | 90 | slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); |
91 | slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); | ||
92 | if (!slot->hotplug_slot) | 91 | if (!slot->hotplug_slot) |
93 | goto error_slot; | 92 | goto error_slot; |
94 | memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); | 93 | slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), |
95 | slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), | ||
96 | GFP_KERNEL); | 94 | GFP_KERNEL); |
97 | if (!slot->hotplug_slot->info) | 95 | if (!slot->hotplug_slot->info) |
98 | goto error_hpslot; | 96 | goto error_hpslot; |
99 | memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); | ||
100 | slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); | 97 | slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); |
101 | if (!slot->hotplug_slot->name) | 98 | if (!slot->hotplug_slot->name) |
102 | goto error_info; | 99 | goto error_info; |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index a32ae82e5922..c402da8e78ae 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved. |
7 | * | 7 | * |
8 | * This work was based on the 2.4/2.6 kernel development by Dick Reigner. | 8 | * This work was based on the 2.4/2.6 kernel development by Dick Reigner. |
9 | * Work to add BIOS PROM support was completed by Mike Habeck. | 9 | * Work to add BIOS PROM support was completed by Mike Habeck. |
@@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev) | |||
230 | list_for_each_entry(child, &subordinate_bus->devices, bus_list) | 230 | list_for_each_entry(child, &subordinate_bus->devices, bus_list) |
231 | sn_bus_free_data(child); | 231 | sn_bus_free_data(child); |
232 | } | 232 | } |
233 | /* | ||
234 | * Some drivers may use dma accesses during the | ||
235 | * driver remove function. We release the sysdata | ||
236 | * areas after the driver remove functions have | ||
237 | * been called. | ||
238 | */ | ||
239 | sn_bus_store_sysdata(dev); | ||
233 | sn_pci_unfixup_slot(dev); | 240 | sn_pci_unfixup_slot(dev); |
234 | } | 241 | } |
235 | 242 | ||
@@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
429 | PCI_DEVFN(slot->device_num + 1, | 436 | PCI_DEVFN(slot->device_num + 1, |
430 | PCI_FUNC(func))); | 437 | PCI_FUNC(func))); |
431 | if (dev) { | 438 | if (dev) { |
432 | /* | ||
433 | * Some drivers may use dma accesses during the | ||
434 | * driver remove function. We release the sysdata | ||
435 | * areas after the driver remove functions have | ||
436 | * been called. | ||
437 | */ | ||
438 | sn_bus_store_sysdata(dev); | ||
439 | sn_bus_free_data(dev); | 439 | sn_bus_free_data(dev); |
440 | pci_remove_bus_device(dev); | 440 | pci_remove_bus_device(dev); |
441 | pci_dev_put(dev); | 441 | pci_dev_put(dev); |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7d6f521d02ea..5c70f43908c4 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ | 35 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ |
36 | #include <linux/mutex.h> | ||
36 | 37 | ||
37 | #include "pci_hotplug.h" | 38 | #include "pci_hotplug.h" |
38 | 39 | ||
@@ -45,6 +46,7 @@ | |||
45 | extern int shpchp_poll_mode; | 46 | extern int shpchp_poll_mode; |
46 | extern int shpchp_poll_time; | 47 | extern int shpchp_poll_time; |
47 | extern int shpchp_debug; | 48 | extern int shpchp_debug; |
49 | extern struct workqueue_struct *shpchp_wq; | ||
48 | 50 | ||
49 | /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ | 51 | /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ |
50 | #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) | 52 | #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) |
@@ -52,10 +54,8 @@ extern int shpchp_debug; | |||
52 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 54 | #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) | 55 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
54 | 56 | ||
55 | #define SLOT_MAGIC 0x67267321 | 57 | #define SLOT_NAME_SIZE 10 |
56 | struct slot { | 58 | struct slot { |
57 | u32 magic; | ||
58 | struct slot *next; | ||
59 | u8 bus; | 59 | u8 bus; |
60 | u8 device; | 60 | u8 device; |
61 | u16 status; | 61 | u16 status; |
@@ -70,26 +70,27 @@ struct slot { | |||
70 | struct hpc_ops *hpc_ops; | 70 | struct hpc_ops *hpc_ops; |
71 | struct hotplug_slot *hotplug_slot; | 71 | struct hotplug_slot *hotplug_slot; |
72 | struct list_head slot_list; | 72 | struct list_head slot_list; |
73 | char name[SLOT_NAME_SIZE]; | ||
74 | struct work_struct work; /* work for button event */ | ||
75 | struct mutex lock; | ||
73 | }; | 76 | }; |
74 | 77 | ||
75 | struct event_info { | 78 | struct event_info { |
76 | u32 event_type; | 79 | u32 event_type; |
77 | u8 hp_slot; | 80 | struct slot *p_slot; |
81 | struct work_struct work; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | struct controller { | 84 | struct controller { |
81 | struct controller *next; | 85 | struct mutex crit_sect; /* critical section mutex */ |
82 | struct semaphore crit_sect; /* critical section semaphore */ | 86 | struct mutex cmd_lock; /* command lock */ |
83 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | 87 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
84 | int num_slots; /* Number of slots on ctlr */ | 88 | int num_slots; /* Number of slots on ctlr */ |
85 | int slot_num_inc; /* 1 or -1 */ | 89 | int slot_num_inc; /* 1 or -1 */ |
86 | struct pci_dev *pci_dev; | 90 | struct pci_dev *pci_dev; |
87 | struct pci_bus *pci_bus; | 91 | struct list_head slot_list; |
88 | struct event_info event_queue[10]; | ||
89 | struct slot *slot; | ||
90 | struct hpc_ops *hpc_ops; | 92 | struct hpc_ops *hpc_ops; |
91 | wait_queue_head_t queue; /* sleep & wake process */ | 93 | wait_queue_head_t queue; /* sleep & wake process */ |
92 | u8 next_event; | ||
93 | u8 bus; | 94 | u8 bus; |
94 | u8 device; | 95 | u8 device; |
95 | u8 function; | 96 | u8 function; |
@@ -105,12 +106,6 @@ struct controller { | |||
105 | volatile int cmd_busy; | 106 | volatile int cmd_busy; |
106 | }; | 107 | }; |
107 | 108 | ||
108 | struct hotplug_params { | ||
109 | u8 cache_line_size; | ||
110 | u8 latency_timer; | ||
111 | u8 enable_serr; | ||
112 | u8 enable_perr; | ||
113 | }; | ||
114 | 109 | ||
115 | /* Define AMD SHPC ID */ | 110 | /* Define AMD SHPC ID */ |
116 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 | 111 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 |
@@ -180,11 +175,8 @@ struct hotplug_params { | |||
180 | /* sysfs functions for the hotplug controller info */ | 175 | /* sysfs functions for the hotplug controller info */ |
181 | extern void shpchp_create_ctrl_files (struct controller *ctrl); | 176 | extern void shpchp_create_ctrl_files (struct controller *ctrl); |
182 | 177 | ||
183 | /* controller functions */ | 178 | extern int shpchp_sysfs_enable_slot(struct slot *slot); |
184 | extern int shpchp_event_start_thread(void); | 179 | extern int shpchp_sysfs_disable_slot(struct slot *slot); |
185 | extern void shpchp_event_stop_thread(void); | ||
186 | extern int shpchp_enable_slot(struct slot *slot); | ||
187 | extern int shpchp_disable_slot(struct slot *slot); | ||
188 | 180 | ||
189 | extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); | 181 | extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); |
190 | extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); | 182 | extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); |
@@ -195,16 +187,28 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); | |||
195 | extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); | 187 | extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); |
196 | extern int shpchp_configure_device(struct slot *p_slot); | 188 | extern int shpchp_configure_device(struct slot *p_slot); |
197 | extern int shpchp_unconfigure_device(struct slot *p_slot); | 189 | extern int shpchp_unconfigure_device(struct slot *p_slot); |
198 | extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); | ||
199 | extern void get_hp_params_from_firmware(struct pci_dev *dev, | ||
200 | struct hotplug_params *hpp); | ||
201 | extern int shpchprm_get_physical_slot_number(struct controller *ctrl, | ||
202 | u32 *sun, u8 busnum, u8 devnum); | ||
203 | extern void shpchp_remove_ctrl_files(struct controller *ctrl); | 190 | extern void shpchp_remove_ctrl_files(struct controller *ctrl); |
191 | extern void cleanup_slots(struct controller *ctrl); | ||
192 | extern void queue_pushbutton_work(void *data); | ||
204 | 193 | ||
205 | 194 | ||
206 | /* Global variables */ | 195 | #ifdef CONFIG_ACPI |
207 | extern struct controller *shpchp_ctrl_list; | 196 | static inline int get_hp_params_from_firmware(struct pci_dev *dev, |
197 | struct hotplug_params *hpp) | ||
198 | { | ||
199 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) | ||
200 | return -ENODEV; | ||
201 | return 0; | ||
202 | } | ||
203 | #define get_hp_hw_control_from_firmware(pdev) \ | ||
204 | do { \ | ||
205 | if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ | ||
206 | acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ | ||
207 | } while (0) | ||
208 | #else | ||
209 | #define get_hp_params_from_firmware(dev, hpp) (-ENODEV) | ||
210 | #define get_hp_hw_control_from_firmware(dev) do { } while (0) | ||
211 | #endif | ||
208 | 212 | ||
209 | struct ctrl_reg { | 213 | struct ctrl_reg { |
210 | volatile u32 base_offset; | 214 | volatile u32 base_offset; |
@@ -286,10 +290,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function) | |||
286 | dbg("%s - slot == NULL", function); | 290 | dbg("%s - slot == NULL", function); |
287 | return -1; | 291 | return -1; |
288 | } | 292 | } |
289 | if (slot->magic != SLOT_MAGIC) { | ||
290 | dbg("%s - bad magic number for slot", function); | ||
291 | return -1; | ||
292 | } | ||
293 | if (!slot->hotplug_slot) { | 293 | if (!slot->hotplug_slot) { |
294 | dbg("%s - slot->hotplug_slot == NULL!", function); | 294 | dbg("%s - slot->hotplug_slot == NULL!", function); |
295 | return -1; | 295 | return -1; |
@@ -314,44 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch | |||
314 | 314 | ||
315 | static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) | 315 | static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) |
316 | { | 316 | { |
317 | struct slot *p_slot, *tmp_slot = NULL; | 317 | struct slot *slot; |
318 | 318 | ||
319 | if (!ctrl) | 319 | if (!ctrl) |
320 | return NULL; | 320 | return NULL; |
321 | 321 | ||
322 | p_slot = ctrl->slot; | 322 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { |
323 | 323 | if (slot->device == device) | |
324 | while (p_slot && (p_slot->device != device)) { | 324 | return slot; |
325 | tmp_slot = p_slot; | ||
326 | p_slot = p_slot->next; | ||
327 | } | 325 | } |
328 | if (p_slot == NULL) { | ||
329 | err("ERROR: shpchp_find_slot device=0x%x\n", device); | ||
330 | p_slot = tmp_slot; | ||
331 | } | ||
332 | |||
333 | return (p_slot); | ||
334 | } | ||
335 | |||
336 | static inline int wait_for_ctrl_irq (struct controller *ctrl) | ||
337 | { | ||
338 | DECLARE_WAITQUEUE(wait, current); | ||
339 | int retval = 0; | ||
340 | |||
341 | add_wait_queue(&ctrl->queue, &wait); | ||
342 | 326 | ||
343 | if (!shpchp_poll_mode) { | 327 | err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); |
344 | /* Sleep for up to 1 second */ | ||
345 | msleep_interruptible(1000); | ||
346 | } else { | ||
347 | /* Sleep for up to 2 seconds */ | ||
348 | msleep_interruptible(2000); | ||
349 | } | ||
350 | remove_wait_queue(&ctrl->queue, &wait); | ||
351 | if (signal_pending(current)) | ||
352 | retval = -EINTR; | ||
353 | 328 | ||
354 | return retval; | 329 | return NULL; |
355 | } | 330 | } |
356 | 331 | ||
357 | static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) | 332 | static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) |
@@ -427,13 +402,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) | |||
427 | pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); | 402 | pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); |
428 | } | 403 | } |
429 | 404 | ||
430 | #define SLOT_NAME_SIZE 10 | ||
431 | |||
432 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) | ||
433 | { | ||
434 | snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); | ||
435 | } | ||
436 | |||
437 | enum php_ctlr_type { | 405 | enum php_ctlr_type { |
438 | PCI, | 406 | PCI, |
439 | ISA, | 407 | ISA, |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a2b3f0010cec..3be4d492ccc2 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -32,13 +32,14 @@ | |||
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/workqueue.h> | ||
35 | #include "shpchp.h" | 36 | #include "shpchp.h" |
36 | 37 | ||
37 | /* Global variables */ | 38 | /* Global variables */ |
38 | int shpchp_debug; | 39 | int shpchp_debug; |
39 | int shpchp_poll_mode; | 40 | int shpchp_poll_mode; |
40 | int shpchp_poll_time; | 41 | int shpchp_poll_time; |
41 | struct controller *shpchp_ctrl_list; /* = NULL */ | 42 | struct workqueue_struct *shpchp_wq; |
42 | 43 | ||
43 | #define DRIVER_VERSION "0.4" | 44 | #define DRIVER_VERSION "0.4" |
44 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 45 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -57,7 +58,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); | |||
57 | 58 | ||
58 | #define SHPC_MODULE_NAME "shpchp" | 59 | #define SHPC_MODULE_NAME "shpchp" |
59 | 60 | ||
60 | static int shpc_start_thread (void); | ||
61 | static int set_attention_status (struct hotplug_slot *slot, u8 value); | 61 | static int set_attention_status (struct hotplug_slot *slot, u8 value); |
62 | static int enable_slot (struct hotplug_slot *slot); | 62 | static int enable_slot (struct hotplug_slot *slot); |
63 | static int disable_slot (struct hotplug_slot *slot); | 63 | static int disable_slot (struct hotplug_slot *slot); |
@@ -94,107 +94,120 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
94 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 94 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
95 | 95 | ||
96 | kfree(slot->hotplug_slot->info); | 96 | kfree(slot->hotplug_slot->info); |
97 | kfree(slot->hotplug_slot->name); | ||
98 | kfree(slot->hotplug_slot); | 97 | kfree(slot->hotplug_slot); |
99 | kfree(slot); | 98 | kfree(slot); |
100 | } | 99 | } |
101 | 100 | ||
101 | static void make_slot_name(struct slot *slot) | ||
102 | { | ||
103 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
104 | slot->bus, slot->number); | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | |||
110 | static int | ||
111 | shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, | ||
112 | u8 busnum, u8 devnum) | ||
113 | { | ||
114 | int offset = devnum - ctrl->slot_device_offset; | ||
115 | |||
116 | dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, | ||
117 | ctrl->slot_num_inc, offset); | ||
118 | *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | |||
123 | |||
102 | static int init_slots(struct controller *ctrl) | 124 | static int init_slots(struct controller *ctrl) |
103 | { | 125 | { |
104 | struct slot *new_slot; | 126 | struct slot *slot; |
105 | u8 number_of_slots; | 127 | struct hotplug_slot *hotplug_slot; |
106 | u8 slot_device; | 128 | struct hotplug_slot_info *info; |
107 | u32 slot_number, sun; | 129 | int retval = -ENOMEM; |
108 | int result = -ENOMEM; | 130 | int i; |
109 | 131 | u32 sun; | |
110 | number_of_slots = ctrl->num_slots; | 132 | |
111 | slot_device = ctrl->slot_device_offset; | 133 | for (i = 0; i < ctrl->num_slots; i++) { |
112 | slot_number = ctrl->first_slot; | 134 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
113 | 135 | if (!slot) | |
114 | while (number_of_slots) { | ||
115 | new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); | ||
116 | if (!new_slot) | ||
117 | goto error; | 136 | goto error; |
118 | 137 | ||
119 | memset(new_slot, 0, sizeof(struct slot)); | 138 | hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); |
120 | new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); | 139 | if (!hotplug_slot) |
121 | if (!new_slot->hotplug_slot) | ||
122 | goto error_slot; | 140 | goto error_slot; |
123 | memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); | 141 | slot->hotplug_slot = hotplug_slot; |
124 | 142 | ||
125 | new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); | 143 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
126 | if (!new_slot->hotplug_slot->info) | 144 | if (!info) |
127 | goto error_hpslot; | 145 | goto error_hpslot; |
128 | memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); | 146 | hotplug_slot->info = info; |
129 | new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); | 147 | |
130 | if (!new_slot->hotplug_slot->name) | 148 | hotplug_slot->name = slot->name; |
131 | goto error_info; | ||
132 | 149 | ||
133 | new_slot->magic = SLOT_MAGIC; | 150 | slot->hp_slot = i; |
134 | new_slot->ctrl = ctrl; | 151 | slot->ctrl = ctrl; |
135 | new_slot->bus = ctrl->slot_bus; | 152 | slot->bus = ctrl->slot_bus; |
136 | new_slot->device = slot_device; | 153 | slot->device = ctrl->slot_device_offset + i; |
137 | new_slot->hpc_ops = ctrl->hpc_ops; | 154 | slot->hpc_ops = ctrl->hpc_ops; |
155 | mutex_init(&slot->lock); | ||
138 | 156 | ||
139 | if (shpchprm_get_physical_slot_number(ctrl, &sun, | 157 | if (shpchprm_get_physical_slot_number(ctrl, &sun, |
140 | new_slot->bus, new_slot->device)) | 158 | slot->bus, slot->device)) |
141 | goto error_name; | 159 | goto error_info; |
142 | 160 | ||
143 | new_slot->number = sun; | 161 | slot->number = sun; |
144 | new_slot->hp_slot = slot_device - ctrl->slot_device_offset; | 162 | INIT_WORK(&slot->work, queue_pushbutton_work, slot); |
145 | 163 | ||
146 | /* register this slot with the hotplug pci core */ | 164 | /* register this slot with the hotplug pci core */ |
147 | new_slot->hotplug_slot->private = new_slot; | 165 | hotplug_slot->private = slot; |
148 | new_slot->hotplug_slot->release = &release_slot; | 166 | hotplug_slot->release = &release_slot; |
149 | make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); | 167 | make_slot_name(slot); |
150 | new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; | 168 | hotplug_slot->ops = &shpchp_hotplug_slot_ops; |
151 | 169 | ||
152 | new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); | 170 | get_power_status(hotplug_slot, &info->power_status); |
153 | new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); | 171 | get_attention_status(hotplug_slot, &info->attention_status); |
154 | new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); | 172 | get_latch_status(hotplug_slot, &info->latch_status); |
155 | new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); | 173 | get_adapter_status(hotplug_slot, &info->adapter_status); |
156 | 174 | ||
157 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, | 175 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " |
158 | new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); | 176 | "slot_device_offset=%x\n", slot->bus, slot->device, |
159 | result = pci_hp_register (new_slot->hotplug_slot); | 177 | slot->hp_slot, slot->number, ctrl->slot_device_offset); |
160 | if (result) { | 178 | retval = pci_hp_register(slot->hotplug_slot); |
161 | err ("pci_hp_register failed with error %d\n", result); | 179 | if (retval) { |
162 | goto error_name; | 180 | err("pci_hp_register failed with error %d\n", retval); |
181 | goto error_info; | ||
163 | } | 182 | } |
164 | 183 | ||
165 | new_slot->next = ctrl->slot; | 184 | list_add(&slot->slot_list, &ctrl->slot_list); |
166 | ctrl->slot = new_slot; | ||
167 | |||
168 | number_of_slots--; | ||
169 | slot_device++; | ||
170 | slot_number += ctrl->slot_num_inc; | ||
171 | } | 185 | } |
172 | 186 | ||
173 | return 0; | 187 | return 0; |
174 | |||
175 | error_name: | ||
176 | kfree(new_slot->hotplug_slot->name); | ||
177 | error_info: | 188 | error_info: |
178 | kfree(new_slot->hotplug_slot->info); | 189 | kfree(info); |
179 | error_hpslot: | 190 | error_hpslot: |
180 | kfree(new_slot->hotplug_slot); | 191 | kfree(hotplug_slot); |
181 | error_slot: | 192 | error_slot: |
182 | kfree(new_slot); | 193 | kfree(slot); |
183 | error: | 194 | error: |
184 | return result; | 195 | return retval; |
185 | } | 196 | } |
186 | 197 | ||
187 | static void cleanup_slots(struct controller *ctrl) | 198 | void cleanup_slots(struct controller *ctrl) |
188 | { | 199 | { |
189 | struct slot *old_slot, *next_slot; | 200 | struct list_head *tmp; |
190 | 201 | struct list_head *next; | |
191 | old_slot = ctrl->slot; | 202 | struct slot *slot; |
192 | ctrl->slot = NULL; | 203 | |
193 | 204 | list_for_each_safe(tmp, next, &ctrl->slot_list) { | |
194 | while (old_slot) { | 205 | slot = list_entry(tmp, struct slot, slot_list); |
195 | next_slot = old_slot->next; | 206 | list_del(&slot->slot_list); |
196 | pci_hp_deregister(old_slot->hotplug_slot); | 207 | cancel_delayed_work(&slot->work); |
197 | old_slot = next_slot; | 208 | flush_scheduled_work(); |
209 | flush_workqueue(shpchp_wq); | ||
210 | pci_hp_deregister(slot->hotplug_slot); | ||
198 | } | 211 | } |
199 | } | 212 | } |
200 | 213 | ||
@@ -207,9 +220,12 @@ static int get_ctlr_slot_config(struct controller *ctrl) | |||
207 | int rc; | 220 | int rc; |
208 | int flags; | 221 | int flags; |
209 | 222 | ||
210 | rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); | 223 | rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, |
224 | &first_device_num, &physical_slot_num, | ||
225 | &updown, &flags); | ||
211 | if (rc) { | 226 | if (rc) { |
212 | err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); | 227 | err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", |
228 | __FUNCTION__, ctrl->bus, ctrl->device); | ||
213 | return -1; | 229 | return -1; |
214 | } | 230 | } |
215 | 231 | ||
@@ -218,19 +234,19 @@ static int get_ctlr_slot_config(struct controller *ctrl) | |||
218 | ctrl->first_slot = physical_slot_num; | 234 | ctrl->first_slot = physical_slot_num; |
219 | ctrl->slot_num_inc = updown; /* either -1 or 1 */ | 235 | ctrl->slot_num_inc = updown; /* either -1 or 1 */ |
220 | 236 | ||
221 | dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", | 237 | dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d " |
222 | __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); | 238 | "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, |
239 | physical_slot_num, updown, ctrl->bus, ctrl->device); | ||
223 | 240 | ||
224 | return 0; | 241 | return 0; |
225 | } | 242 | } |
226 | 243 | ||
227 | |||
228 | /* | 244 | /* |
229 | * set_attention_status - Turns the Amber LED for a slot on, off or blink | 245 | * set_attention_status - Turns the Amber LED for a slot on, off or blink |
230 | */ | 246 | */ |
231 | static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) | 247 | static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) |
232 | { | 248 | { |
233 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 249 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
234 | 250 | ||
235 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 251 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
236 | 252 | ||
@@ -240,29 +256,27 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) | |||
240 | return 0; | 256 | return 0; |
241 | } | 257 | } |
242 | 258 | ||
243 | |||
244 | static int enable_slot (struct hotplug_slot *hotplug_slot) | 259 | static int enable_slot (struct hotplug_slot *hotplug_slot) |
245 | { | 260 | { |
246 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 261 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
247 | 262 | ||
248 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 263 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
249 | 264 | ||
250 | return shpchp_enable_slot(slot); | 265 | return shpchp_sysfs_enable_slot(slot); |
251 | } | 266 | } |
252 | 267 | ||
253 | |||
254 | static int disable_slot (struct hotplug_slot *hotplug_slot) | 268 | static int disable_slot (struct hotplug_slot *hotplug_slot) |
255 | { | 269 | { |
256 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 270 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
257 | 271 | ||
258 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 272 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
259 | 273 | ||
260 | return shpchp_disable_slot(slot); | 274 | return shpchp_sysfs_disable_slot(slot); |
261 | } | 275 | } |
262 | 276 | ||
263 | static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) | 277 | static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) |
264 | { | 278 | { |
265 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 279 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
266 | int retval; | 280 | int retval; |
267 | 281 | ||
268 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 282 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
@@ -276,7 +290,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
276 | 290 | ||
277 | static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) | 291 | static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) |
278 | { | 292 | { |
279 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 293 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
280 | int retval; | 294 | int retval; |
281 | 295 | ||
282 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 296 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
@@ -290,7 +304,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
290 | 304 | ||
291 | static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) | 305 | static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) |
292 | { | 306 | { |
293 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 307 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
294 | int retval; | 308 | int retval; |
295 | 309 | ||
296 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 310 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
@@ -304,7 +318,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
304 | 318 | ||
305 | static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | 319 | static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) |
306 | { | 320 | { |
307 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 321 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
308 | int retval; | 322 | int retval; |
309 | 323 | ||
310 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 324 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
@@ -318,7 +332,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
318 | 332 | ||
319 | static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) | 333 | static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) |
320 | { | 334 | { |
321 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 335 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
322 | struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; | 336 | struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; |
323 | 337 | ||
324 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 338 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
@@ -330,11 +344,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) | |||
330 | 344 | ||
331 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 345 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) |
332 | { | 346 | { |
333 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 347 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
334 | int retval; | 348 | int retval; |
335 | 349 | ||
336 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 350 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
337 | 351 | ||
338 | retval = slot->hpc_ops->get_max_bus_speed(slot, value); | 352 | retval = slot->hpc_ops->get_max_bus_speed(slot, value); |
339 | if (retval < 0) | 353 | if (retval < 0) |
340 | *value = PCI_SPEED_UNKNOWN; | 354 | *value = PCI_SPEED_UNKNOWN; |
@@ -344,11 +358,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp | |||
344 | 358 | ||
345 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 359 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) |
346 | { | 360 | { |
347 | struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); | 361 | struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); |
348 | int retval; | 362 | int retval; |
349 | 363 | ||
350 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 364 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
351 | 365 | ||
352 | retval = slot->hpc_ops->get_cur_bus_speed(slot, value); | 366 | retval = slot->hpc_ops->get_cur_bus_speed(slot, value); |
353 | if (retval < 0) | 367 | if (retval < 0) |
354 | *value = PCI_SPEED_UNKNOWN; | 368 | *value = PCI_SPEED_UNKNOWN; |
@@ -372,61 +386,54 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
372 | int rc; | 386 | int rc; |
373 | struct controller *ctrl; | 387 | struct controller *ctrl; |
374 | struct slot *t_slot; | 388 | struct slot *t_slot; |
375 | int first_device_num; /* first PCI device number supported by this SHPC */ | 389 | int first_device_num; /* first PCI device number */ |
376 | int num_ctlr_slots; /* number of slots supported by this SHPC */ | 390 | int num_ctlr_slots; /* number of slots implemented */ |
377 | 391 | ||
378 | if (!is_shpc_capable(pdev)) | 392 | if (!is_shpc_capable(pdev)) |
379 | return -ENODEV; | 393 | return -ENODEV; |
380 | 394 | ||
381 | ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); | 395 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); |
382 | if (!ctrl) { | 396 | if (!ctrl) { |
383 | err("%s : out of memory\n", __FUNCTION__); | 397 | err("%s : out of memory\n", __FUNCTION__); |
384 | goto err_out_none; | 398 | goto err_out_none; |
385 | } | 399 | } |
386 | memset(ctrl, 0, sizeof(struct controller)); | 400 | INIT_LIST_HEAD(&ctrl->slot_list); |
387 | 401 | ||
388 | rc = shpc_init(ctrl, pdev); | 402 | rc = shpc_init(ctrl, pdev); |
389 | if (rc) { | 403 | if (rc) { |
390 | dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); | 404 | dbg("%s: controller initialization failed\n", |
405 | SHPC_MODULE_NAME); | ||
391 | goto err_out_free_ctrl; | 406 | goto err_out_free_ctrl; |
392 | } | 407 | } |
393 | 408 | ||
394 | pci_set_drvdata(pdev, ctrl); | 409 | pci_set_drvdata(pdev, ctrl); |
395 | 410 | ||
396 | ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); | ||
397 | if (!ctrl->pci_bus) { | ||
398 | err("out of memory\n"); | ||
399 | rc = -ENOMEM; | ||
400 | goto err_out_unmap_mmio_region; | ||
401 | } | ||
402 | |||
403 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); | ||
404 | ctrl->bus = pdev->bus->number; | 411 | ctrl->bus = pdev->bus->number; |
405 | ctrl->slot_bus = pdev->subordinate->number; | 412 | ctrl->slot_bus = pdev->subordinate->number; |
406 | |||
407 | ctrl->device = PCI_SLOT(pdev->devfn); | 413 | ctrl->device = PCI_SLOT(pdev->devfn); |
408 | ctrl->function = PCI_FUNC(pdev->devfn); | 414 | ctrl->function = PCI_FUNC(pdev->devfn); |
409 | dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); | 415 | |
416 | dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", | ||
417 | ctrl->bus, ctrl->device, ctrl->function, pdev->irq); | ||
410 | 418 | ||
411 | /* | 419 | /* |
412 | * Save configuration headers for this and subordinate PCI buses | 420 | * Save configuration headers for this and subordinate PCI buses |
413 | */ | 421 | */ |
414 | |||
415 | rc = get_ctlr_slot_config(ctrl); | 422 | rc = get_ctlr_slot_config(ctrl); |
416 | if (rc) { | 423 | if (rc) { |
417 | err(msg_initialization_err, rc); | 424 | err(msg_initialization_err, rc); |
418 | goto err_out_free_ctrl_bus; | 425 | goto err_out_release_ctlr; |
419 | } | 426 | } |
420 | first_device_num = ctrl->slot_device_offset; | 427 | first_device_num = ctrl->slot_device_offset; |
421 | num_ctlr_slots = ctrl->num_slots; | 428 | num_ctlr_slots = ctrl->num_slots; |
422 | 429 | ||
423 | ctrl->add_support = 1; | 430 | ctrl->add_support = 1; |
424 | 431 | ||
425 | /* Setup the slot information structures */ | 432 | /* Setup the slot information structures */ |
426 | rc = init_slots(ctrl); | 433 | rc = init_slots(ctrl); |
427 | if (rc) { | 434 | if (rc) { |
428 | err(msg_initialization_err, 6); | 435 | err(msg_initialization_err, 6); |
429 | goto err_out_free_ctrl_slot; | 436 | goto err_out_release_ctlr; |
430 | } | 437 | } |
431 | 438 | ||
432 | /* Now hpc_functions (slot->hpc_ops->functions) are ready */ | 439 | /* Now hpc_functions (slot->hpc_ops->functions) are ready */ |
@@ -437,30 +444,16 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
437 | dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); | 444 | dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); |
438 | 445 | ||
439 | if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { | 446 | if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { |
440 | err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); | 447 | err(SHPC_MODULE_NAME ": Can't get current bus speed. " |
448 | "Set to 33MHz PCI.\n"); | ||
441 | ctrl->speed = PCI_SPEED_33MHz; | 449 | ctrl->speed = PCI_SPEED_33MHz; |
442 | } | 450 | } |
443 | 451 | ||
444 | /* Finish setting up the hot plug ctrl device */ | ||
445 | ctrl->next_event = 0; | ||
446 | |||
447 | if (!shpchp_ctrl_list) { | ||
448 | shpchp_ctrl_list = ctrl; | ||
449 | ctrl->next = NULL; | ||
450 | } else { | ||
451 | ctrl->next = shpchp_ctrl_list; | ||
452 | shpchp_ctrl_list = ctrl; | ||
453 | } | ||
454 | |||
455 | shpchp_create_ctrl_files(ctrl); | 452 | shpchp_create_ctrl_files(ctrl); |
456 | 453 | ||
457 | return 0; | 454 | return 0; |
458 | 455 | ||
459 | err_out_free_ctrl_slot: | 456 | err_out_release_ctlr: |
460 | cleanup_slots(ctrl); | ||
461 | err_out_free_ctrl_bus: | ||
462 | kfree(ctrl->pci_bus); | ||
463 | err_out_unmap_mmio_region: | ||
464 | ctrl->hpc_ops->release_ctlr(ctrl); | 457 | ctrl->hpc_ops->release_ctlr(ctrl); |
465 | err_out_free_ctrl: | 458 | err_out_free_ctrl: |
466 | kfree(ctrl); | 459 | kfree(ctrl); |
@@ -468,74 +461,28 @@ err_out_none: | |||
468 | return -ENODEV; | 461 | return -ENODEV; |
469 | } | 462 | } |
470 | 463 | ||
471 | 464 | static void shpc_remove(struct pci_dev *dev) | |
472 | static int shpc_start_thread(void) | ||
473 | { | ||
474 | int retval = 0; | ||
475 | |||
476 | dbg("Initialize + Start the notification/polling mechanism \n"); | ||
477 | |||
478 | retval = shpchp_event_start_thread(); | ||
479 | if (retval) { | ||
480 | dbg("shpchp_event_start_thread() failed\n"); | ||
481 | return retval; | ||
482 | } | ||
483 | |||
484 | return retval; | ||
485 | } | ||
486 | |||
487 | static void __exit unload_shpchpd(void) | ||
488 | { | 465 | { |
489 | struct controller *ctrl; | 466 | struct controller *ctrl = pci_get_drvdata(dev); |
490 | struct controller *tctrl; | ||
491 | |||
492 | ctrl = shpchp_ctrl_list; | ||
493 | |||
494 | while (ctrl) { | ||
495 | shpchp_remove_ctrl_files(ctrl); | ||
496 | cleanup_slots(ctrl); | ||
497 | |||
498 | kfree (ctrl->pci_bus); | ||
499 | ctrl->hpc_ops->release_ctlr(ctrl); | ||
500 | |||
501 | tctrl = ctrl; | ||
502 | ctrl = ctrl->next; | ||
503 | |||
504 | kfree(tctrl); | ||
505 | } | ||
506 | |||
507 | /* Stop the notification mechanism */ | ||
508 | shpchp_event_stop_thread(); | ||
509 | 467 | ||
468 | shpchp_remove_ctrl_files(ctrl); | ||
469 | ctrl->hpc_ops->release_ctlr(ctrl); | ||
470 | kfree(ctrl); | ||
510 | } | 471 | } |
511 | 472 | ||
512 | |||
513 | static struct pci_device_id shpcd_pci_tbl[] = { | 473 | static struct pci_device_id shpcd_pci_tbl[] = { |
514 | { | 474 | {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, |
515 | .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), | ||
516 | .class_mask = ~0, | ||
517 | .vendor = PCI_ANY_ID, | ||
518 | .device = PCI_ANY_ID, | ||
519 | .subvendor = PCI_ANY_ID, | ||
520 | .subdevice = PCI_ANY_ID, | ||
521 | }, | ||
522 | |||
523 | { /* end: all zeroes */ } | 475 | { /* end: all zeroes */ } |
524 | }; | 476 | }; |
525 | |||
526 | MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); | 477 | MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); |
527 | 478 | ||
528 | |||
529 | |||
530 | static struct pci_driver shpc_driver = { | 479 | static struct pci_driver shpc_driver = { |
531 | .name = SHPC_MODULE_NAME, | 480 | .name = SHPC_MODULE_NAME, |
532 | .id_table = shpcd_pci_tbl, | 481 | .id_table = shpcd_pci_tbl, |
533 | .probe = shpc_probe, | 482 | .probe = shpc_probe, |
534 | /* remove: shpc_remove_one, */ | 483 | .remove = shpc_remove, |
535 | }; | 484 | }; |
536 | 485 | ||
537 | |||
538 | |||
539 | static int __init shpcd_init(void) | 486 | static int __init shpcd_init(void) |
540 | { | 487 | { |
541 | int retval = 0; | 488 | int retval = 0; |
@@ -544,17 +491,15 @@ static int __init shpcd_init(void) | |||
544 | shpchp_poll_mode = 1; | 491 | shpchp_poll_mode = 1; |
545 | #endif | 492 | #endif |
546 | 493 | ||
547 | retval = shpc_start_thread(); | 494 | shpchp_wq = create_singlethread_workqueue("shpchpd"); |
548 | if (retval) | 495 | if (!shpchp_wq) |
549 | goto error_hpc_init; | 496 | return -ENOMEM; |
550 | 497 | ||
551 | retval = pci_register_driver(&shpc_driver); | 498 | retval = pci_register_driver(&shpc_driver); |
552 | dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); | 499 | dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); |
553 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 500 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
554 | |||
555 | error_hpc_init: | ||
556 | if (retval) { | 501 | if (retval) { |
557 | shpchp_event_stop_thread(); | 502 | destroy_workqueue(shpchp_wq); |
558 | } | 503 | } |
559 | return retval; | 504 | return retval; |
560 | } | 505 | } |
@@ -562,10 +507,8 @@ error_hpc_init: | |||
562 | static void __exit shpcd_cleanup(void) | 507 | static void __exit shpcd_cleanup(void) |
563 | { | 508 | { |
564 | dbg("unload_shpchpd()\n"); | 509 | dbg("unload_shpchpd()\n"); |
565 | unload_shpchpd(); | ||
566 | |||
567 | pci_unregister_driver(&shpc_driver); | 510 | pci_unregister_driver(&shpc_driver); |
568 | 511 | destroy_workqueue(shpchp_wq); | |
569 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 512 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
570 | } | 513 | } |
571 | 514 | ||
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 643252d9bf3b..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -32,65 +32,50 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/workqueue.h> | ||
35 | #include "../pci.h" | 36 | #include "../pci.h" |
36 | #include "shpchp.h" | 37 | #include "shpchp.h" |
37 | 38 | ||
38 | static void interrupt_event_handler(struct controller *ctrl); | 39 | static void interrupt_event_handler(void *data); |
40 | static int shpchp_enable_slot(struct slot *p_slot); | ||
41 | static int shpchp_disable_slot(struct slot *p_slot); | ||
39 | 42 | ||
40 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 43 | static int queue_interrupt_event(struct slot *p_slot, u32 event_type) |
41 | static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ | 44 | { |
42 | static int event_finished; | 45 | struct event_info *info; |
43 | static unsigned long pushbutton_pending; /* = 0 */ | 46 | |
47 | info = kmalloc(sizeof(*info), GFP_ATOMIC); | ||
48 | if (!info) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | info->event_type = event_type; | ||
52 | info->p_slot = p_slot; | ||
53 | INIT_WORK(&info->work, interrupt_event_handler, info); | ||
54 | |||
55 | schedule_work(&info->work); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
44 | 59 | ||
45 | u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | 60 | u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) |
46 | { | 61 | { |
47 | struct controller *ctrl = (struct controller *) inst_id; | 62 | struct controller *ctrl = (struct controller *) inst_id; |
48 | struct slot *p_slot; | 63 | struct slot *p_slot; |
49 | u8 rc = 0; | 64 | u32 event_type; |
50 | u8 getstatus; | ||
51 | struct event_info *taskInfo; | ||
52 | 65 | ||
53 | /* Attention Button Change */ | 66 | /* Attention Button Change */ |
54 | dbg("shpchp: Attention button interrupt received.\n"); | 67 | dbg("shpchp: Attention button interrupt received.\n"); |
55 | 68 | ||
56 | /* This is the structure that tells the worker thread what to do */ | ||
57 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
58 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 69 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
59 | |||
60 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 70 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
61 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | ||
62 | |||
63 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
64 | taskInfo->hp_slot = hp_slot; | ||
65 | |||
66 | rc++; | ||
67 | 71 | ||
68 | /* | 72 | /* |
69 | * Button pressed - See if need to TAKE ACTION!!! | 73 | * Button pressed - See if need to TAKE ACTION!!! |
70 | */ | 74 | */ |
71 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); | 75 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); |
72 | taskInfo->event_type = INT_BUTTON_PRESS; | 76 | event_type = INT_BUTTON_PRESS; |
73 | |||
74 | if ((p_slot->state == BLINKINGON_STATE) | ||
75 | || (p_slot->state == BLINKINGOFF_STATE)) { | ||
76 | /* Cancel if we are still blinking; this means that we press the | ||
77 | * attention again before the 5 sec. limit expires to cancel hot-add | ||
78 | * or hot-remove | ||
79 | */ | ||
80 | taskInfo->event_type = INT_BUTTON_CANCEL; | ||
81 | info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); | ||
82 | } else if ((p_slot->state == POWERON_STATE) | ||
83 | || (p_slot->state == POWEROFF_STATE)) { | ||
84 | /* Ignore if the slot is on power-on or power-off state; this | ||
85 | * means that the previous attention button action to hot-add or | ||
86 | * hot-remove is undergoing | ||
87 | */ | ||
88 | taskInfo->event_type = INT_BUTTON_IGNORE; | ||
89 | info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); | ||
90 | } | ||
91 | 77 | ||
92 | if (rc) | 78 | queue_interrupt_event(p_slot, event_type); |
93 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
94 | 79 | ||
95 | return 0; | 80 | return 0; |
96 | 81 | ||
@@ -100,21 +85,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
100 | { | 85 | { |
101 | struct controller *ctrl = (struct controller *) inst_id; | 86 | struct controller *ctrl = (struct controller *) inst_id; |
102 | struct slot *p_slot; | 87 | struct slot *p_slot; |
103 | u8 rc = 0; | ||
104 | u8 getstatus; | 88 | u8 getstatus; |
105 | struct event_info *taskInfo; | 89 | u32 event_type; |
106 | 90 | ||
107 | /* Switch Change */ | 91 | /* Switch Change */ |
108 | dbg("shpchp: Switch interrupt received.\n"); | 92 | dbg("shpchp: Switch interrupt received.\n"); |
109 | 93 | ||
110 | /* This is the structure that tells the worker thread | ||
111 | * what to do | ||
112 | */ | ||
113 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
114 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
115 | taskInfo->hp_slot = hp_slot; | ||
116 | |||
117 | rc++; | ||
118 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 94 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
119 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 95 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
120 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 96 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
@@ -126,9 +102,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
126 | * Switch opened | 102 | * Switch opened |
127 | */ | 103 | */ |
128 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 104 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
129 | taskInfo->event_type = INT_SWITCH_OPEN; | 105 | event_type = INT_SWITCH_OPEN; |
130 | if (p_slot->pwr_save && p_slot->presence_save) { | 106 | if (p_slot->pwr_save && p_slot->presence_save) { |
131 | taskInfo->event_type = INT_POWER_FAULT; | 107 | event_type = INT_POWER_FAULT; |
132 | err("Surprise Removal of card\n"); | 108 | err("Surprise Removal of card\n"); |
133 | } | 109 | } |
134 | } else { | 110 | } else { |
@@ -136,34 +112,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
136 | * Switch closed | 112 | * Switch closed |
137 | */ | 113 | */ |
138 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 114 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
139 | taskInfo->event_type = INT_SWITCH_CLOSE; | 115 | event_type = INT_SWITCH_CLOSE; |
140 | } | 116 | } |
141 | 117 | ||
142 | if (rc) | 118 | queue_interrupt_event(p_slot, event_type); |
143 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
144 | 119 | ||
145 | return rc; | 120 | return 1; |
146 | } | 121 | } |
147 | 122 | ||
148 | u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | 123 | u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) |
149 | { | 124 | { |
150 | struct controller *ctrl = (struct controller *) inst_id; | 125 | struct controller *ctrl = (struct controller *) inst_id; |
151 | struct slot *p_slot; | 126 | struct slot *p_slot; |
152 | u8 rc = 0; | 127 | u32 event_type; |
153 | /*u8 temp_byte;*/ | ||
154 | struct event_info *taskInfo; | ||
155 | 128 | ||
156 | /* Presence Change */ | 129 | /* Presence Change */ |
157 | dbg("shpchp: Presence/Notify input change.\n"); | 130 | dbg("shpchp: Presence/Notify input change.\n"); |
158 | 131 | ||
159 | /* This is the structure that tells the worker thread | ||
160 | * what to do | ||
161 | */ | ||
162 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
163 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
164 | taskInfo->hp_slot = hp_slot; | ||
165 | |||
166 | rc++; | ||
167 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 132 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
168 | 133 | ||
169 | /* | 134 | /* |
@@ -175,39 +140,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
175 | * Card Present | 140 | * Card Present |
176 | */ | 141 | */ |
177 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 142 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); |
178 | taskInfo->event_type = INT_PRESENCE_ON; | 143 | event_type = INT_PRESENCE_ON; |
179 | } else { | 144 | } else { |
180 | /* | 145 | /* |
181 | * Not Present | 146 | * Not Present |
182 | */ | 147 | */ |
183 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 148 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); |
184 | taskInfo->event_type = INT_PRESENCE_OFF; | 149 | event_type = INT_PRESENCE_OFF; |
185 | } | 150 | } |
186 | 151 | ||
187 | if (rc) | 152 | queue_interrupt_event(p_slot, event_type); |
188 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
189 | 153 | ||
190 | return rc; | 154 | return 1; |
191 | } | 155 | } |
192 | 156 | ||
193 | u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | 157 | u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) |
194 | { | 158 | { |
195 | struct controller *ctrl = (struct controller *) inst_id; | 159 | struct controller *ctrl = (struct controller *) inst_id; |
196 | struct slot *p_slot; | 160 | struct slot *p_slot; |
197 | u8 rc = 0; | 161 | u32 event_type; |
198 | struct event_info *taskInfo; | ||
199 | 162 | ||
200 | /* Power fault */ | 163 | /* Power fault */ |
201 | dbg("shpchp: Power fault interrupt received.\n"); | 164 | dbg("shpchp: Power fault interrupt received.\n"); |
202 | 165 | ||
203 | /* This is the structure that tells the worker thread | ||
204 | * what to do | ||
205 | */ | ||
206 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
207 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
208 | taskInfo->hp_slot = hp_slot; | ||
209 | |||
210 | rc++; | ||
211 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 166 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
212 | 167 | ||
213 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { | 168 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { |
@@ -216,21 +171,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
216 | */ | 171 | */ |
217 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 172 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
218 | p_slot->status = 0x00; | 173 | p_slot->status = 0x00; |
219 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 174 | event_type = INT_POWER_FAULT_CLEAR; |
220 | } else { | 175 | } else { |
221 | /* | 176 | /* |
222 | * Power fault | 177 | * Power fault |
223 | */ | 178 | */ |
224 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 179 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
225 | taskInfo->event_type = INT_POWER_FAULT; | 180 | event_type = INT_POWER_FAULT; |
226 | /* set power fault status for this board */ | 181 | /* set power fault status for this board */ |
227 | p_slot->status = 0xFF; | 182 | p_slot->status = 0xFF; |
228 | info("power fault bit %x set\n", hp_slot); | 183 | info("power fault bit %x set\n", hp_slot); |
229 | } | 184 | } |
230 | if (rc) | ||
231 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
232 | 185 | ||
233 | return rc; | 186 | queue_interrupt_event(p_slot, event_type); |
187 | |||
188 | return 1; | ||
234 | } | 189 | } |
235 | 190 | ||
236 | /* The following routines constitute the bulk of the | 191 | /* The following routines constitute the bulk of the |
@@ -242,21 +197,11 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
242 | int rc = 0; | 197 | int rc = 0; |
243 | 198 | ||
244 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); | 199 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); |
245 | down(&ctrl->crit_sect); | ||
246 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { | 200 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { |
247 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); | 201 | err("%s: Issue of set bus speed mode command failed\n", |
248 | up(&ctrl->crit_sect); | 202 | __FUNCTION__); |
249 | return WRONG_BUS_FREQUENCY; | 203 | return WRONG_BUS_FREQUENCY; |
250 | } | 204 | } |
251 | |||
252 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
253 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | ||
254 | __FUNCTION__); | ||
255 | err("%s: Error code (%d)\n", __FUNCTION__, rc); | ||
256 | up(&ctrl->crit_sect); | ||
257 | return WRONG_BUS_FREQUENCY; | ||
258 | } | ||
259 | up(&ctrl->crit_sect); | ||
260 | return rc; | 205 | return rc; |
261 | } | 206 | } |
262 | 207 | ||
@@ -265,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, | |||
265 | enum pci_bus_speed msp) | 210 | enum pci_bus_speed msp) |
266 | { | 211 | { |
267 | int rc = 0; | 212 | int rc = 0; |
268 | 213 | ||
269 | if (flag != 0) { /* Other slots on the same bus are occupied */ | 214 | /* |
270 | if ( asp < bsp ) { | 215 | * If other slots on the same bus are occupied, we cannot |
271 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); | 216 | * change the bus speed. |
272 | return WRONG_BUS_FREQUENCY; | 217 | */ |
218 | if (flag) { | ||
219 | if (asp < bsp) { | ||
220 | err("%s: speed of bus %x and adapter %x mismatch\n", | ||
221 | __FUNCTION__, bsp, asp); | ||
222 | rc = WRONG_BUS_FREQUENCY; | ||
273 | } | 223 | } |
224 | return rc; | ||
225 | } | ||
226 | |||
227 | if (asp < msp) { | ||
228 | if (bsp != asp) | ||
229 | rc = change_bus_speed(ctrl, pslot, asp); | ||
274 | } else { | 230 | } else { |
275 | /* Other slots on the same bus are empty */ | 231 | if (bsp != msp) |
276 | if (msp == bsp) { | 232 | rc = change_bus_speed(ctrl, pslot, msp); |
277 | /* if adapter_speed >= bus_speed, do nothing */ | ||
278 | if (asp < bsp) { | ||
279 | /* | ||
280 | * Try to lower bus speed to accommodate the adapter if other slots | ||
281 | * on the same controller are empty | ||
282 | */ | ||
283 | if ((rc = change_bus_speed(ctrl, pslot, asp))) | ||
284 | return rc; | ||
285 | } | ||
286 | } else { | ||
287 | if (asp < msp) { | ||
288 | if ((rc = change_bus_speed(ctrl, pslot, asp))) | ||
289 | return rc; | ||
290 | } else { | ||
291 | if ((rc = change_bus_speed(ctrl, pslot, msp))) | ||
292 | return rc; | ||
293 | } | ||
294 | } | ||
295 | } | 233 | } |
296 | return rc; | 234 | return rc; |
297 | } | 235 | } |
@@ -308,8 +246,7 @@ static int board_added(struct slot *p_slot) | |||
308 | u8 hp_slot; | 246 | u8 hp_slot; |
309 | u8 slots_not_empty = 0; | 247 | u8 slots_not_empty = 0; |
310 | int rc = 0; | 248 | int rc = 0; |
311 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; | 249 | enum pci_bus_speed asp, bsp, msp; |
312 | u8 pi, mode; | ||
313 | struct controller *ctrl = p_slot->ctrl; | 250 | struct controller *ctrl = p_slot->ctrl; |
314 | 251 | ||
315 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 252 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
@@ -318,187 +255,68 @@ static int board_added(struct slot *p_slot) | |||
318 | __FUNCTION__, p_slot->device, | 255 | __FUNCTION__, p_slot->device, |
319 | ctrl->slot_device_offset, hp_slot); | 256 | ctrl->slot_device_offset, hp_slot); |
320 | 257 | ||
321 | /* Wait for exclusive access to hardware */ | ||
322 | down(&ctrl->crit_sect); | ||
323 | |||
324 | /* Power on slot without connecting to bus */ | 258 | /* Power on slot without connecting to bus */ |
325 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 259 | rc = p_slot->hpc_ops->power_on_slot(p_slot); |
326 | if (rc) { | 260 | if (rc) { |
327 | err("%s: Failed to power on slot\n", __FUNCTION__); | 261 | err("%s: Failed to power on slot\n", __FUNCTION__); |
328 | /* Done with exclusive hardware access */ | ||
329 | up(&ctrl->crit_sect); | ||
330 | return -1; | 262 | return -1; |
331 | } | 263 | } |
332 | 264 | ||
333 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
334 | if (rc) { | ||
335 | err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); | ||
336 | /* Done with exclusive hardware access */ | ||
337 | up(&ctrl->crit_sect); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | |||
342 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { | 265 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { |
343 | if (slots_not_empty) | 266 | if (slots_not_empty) |
344 | return WRONG_BUS_FREQUENCY; | 267 | return WRONG_BUS_FREQUENCY; |
345 | 268 | ||
346 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { | 269 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { |
347 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); | 270 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); |
348 | up(&ctrl->crit_sect); | ||
349 | return WRONG_BUS_FREQUENCY; | 271 | return WRONG_BUS_FREQUENCY; |
350 | } | 272 | } |
351 | 273 | ||
352 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
353 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | ||
354 | __FUNCTION__); | ||
355 | err("%s: Error code (%d)\n", __FUNCTION__, rc); | ||
356 | up(&ctrl->crit_sect); | ||
357 | return WRONG_BUS_FREQUENCY; | ||
358 | } | ||
359 | /* turn on board, blink green LED, turn off Amber LED */ | 274 | /* turn on board, blink green LED, turn off Amber LED */ |
360 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 275 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |
361 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); | 276 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); |
362 | up(&ctrl->crit_sect); | ||
363 | return rc; | 277 | return rc; |
364 | } | 278 | } |
365 | |||
366 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
367 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | ||
368 | up(&ctrl->crit_sect); | ||
369 | return rc; | ||
370 | } | ||
371 | } | 279 | } |
372 | 280 | ||
373 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); | 281 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); |
374 | /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ | 282 | if (rc) { |
375 | /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ | 283 | err("%s: Can't get adapter speed or bus mode mismatch\n", |
376 | /* 0xd = PCI-X 133 Mhz 533 */ | 284 | __FUNCTION__); |
377 | /* This encoding is different from the one used in cur_bus_speed & */ | ||
378 | /* max_bus_speed */ | ||
379 | |||
380 | if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { | ||
381 | err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); | ||
382 | /* Done with exclusive hardware access */ | ||
383 | up(&ctrl->crit_sect); | ||
384 | return WRONG_BUS_FREQUENCY; | 285 | return WRONG_BUS_FREQUENCY; |
385 | } | 286 | } |
386 | 287 | ||
387 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); | 288 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); |
388 | if (rc || bus_speed == PCI_SPEED_UNKNOWN) { | 289 | if (rc) { |
389 | err("%s: Can't get bus operation speed\n", __FUNCTION__); | 290 | err("%s: Can't get bus operation speed\n", __FUNCTION__); |
390 | /* Done with exclusive hardware access */ | ||
391 | up(&ctrl->crit_sect); | ||
392 | return WRONG_BUS_FREQUENCY; | 291 | return WRONG_BUS_FREQUENCY; |
393 | } | 292 | } |
394 | 293 | ||
395 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); | 294 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); |
396 | if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { | 295 | if (rc) { |
397 | err("%s: Can't get max bus operation speed\n", __FUNCTION__); | 296 | err("%s: Can't get max bus operation speed\n", __FUNCTION__); |
398 | max_bus_speed = bus_speed; | 297 | msp = bsp; |
399 | } | ||
400 | |||
401 | /* Done with exclusive hardware access */ | ||
402 | up(&ctrl->crit_sect); | ||
403 | |||
404 | if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { | ||
405 | err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); | ||
406 | pi = 1; | ||
407 | } | 298 | } |
408 | 299 | ||
409 | /* Check if there are other slots or devices on the same bus */ | 300 | /* Check if there are other slots or devices on the same bus */ |
410 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) | 301 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) |
411 | slots_not_empty = 1; | 302 | slots_not_empty = 1; |
412 | 303 | ||
413 | dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, | 304 | dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " |
414 | slots_not_empty, pi); | 305 | "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, |
415 | dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", | 306 | bsp, msp); |
416 | adapter_speed, bus_speed, max_bus_speed); | ||
417 | |||
418 | if (pi == 2) { | ||
419 | dbg("%s: In PI = %d\n", __FUNCTION__, pi); | ||
420 | if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { | ||
421 | err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); | ||
422 | mode = 0; | ||
423 | } | ||
424 | 307 | ||
425 | switch (adapter_speed) { | 308 | rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); |
426 | case PCI_SPEED_133MHz_PCIX_533: | 309 | if (rc) |
427 | case PCI_SPEED_133MHz_PCIX_266: | 310 | return rc; |
428 | if ((bus_speed != adapter_speed) && | ||
429 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
430 | return rc; | ||
431 | break; | ||
432 | case PCI_SPEED_133MHz_PCIX_ECC: | ||
433 | case PCI_SPEED_133MHz_PCIX: | ||
434 | if (mode) { /* Bus - Mode 1 ECC */ | ||
435 | if ((bus_speed != 0x7) && | ||
436 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
437 | return rc; | ||
438 | } else { | ||
439 | if ((bus_speed != 0x4) && | ||
440 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
441 | return rc; | ||
442 | } | ||
443 | break; | ||
444 | case PCI_SPEED_66MHz_PCIX_ECC: | ||
445 | case PCI_SPEED_66MHz_PCIX: | ||
446 | if (mode) { /* Bus - Mode 1 ECC */ | ||
447 | if ((bus_speed != 0x5) && | ||
448 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
449 | return rc; | ||
450 | } else { | ||
451 | if ((bus_speed != 0x2) && | ||
452 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
453 | return rc; | ||
454 | } | ||
455 | break; | ||
456 | case PCI_SPEED_66MHz: | ||
457 | if ((bus_speed != 0x1) && | ||
458 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
459 | return rc; | ||
460 | break; | ||
461 | case PCI_SPEED_33MHz: | ||
462 | if (bus_speed > 0x0) { | ||
463 | if (slots_not_empty == 0) { | ||
464 | if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) | ||
465 | return rc; | ||
466 | } else { | ||
467 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); | ||
468 | return WRONG_BUS_FREQUENCY; | ||
469 | } | ||
470 | } | ||
471 | break; | ||
472 | default: | ||
473 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); | ||
474 | return WRONG_BUS_FREQUENCY; | ||
475 | } | ||
476 | } else { | ||
477 | /* If adpater_speed == bus_speed, nothing to do here */ | ||
478 | dbg("%s: In PI = %d\n", __FUNCTION__, pi); | ||
479 | if ((adapter_speed != bus_speed) && | ||
480 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
481 | return rc; | ||
482 | } | ||
483 | 311 | ||
484 | down(&ctrl->crit_sect); | ||
485 | /* turn on board, blink green LED, turn off Amber LED */ | 312 | /* turn on board, blink green LED, turn off Amber LED */ |
486 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 313 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |
487 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); | 314 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); |
488 | up(&ctrl->crit_sect); | ||
489 | return rc; | 315 | return rc; |
490 | } | 316 | } |
491 | 317 | ||
492 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
493 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | ||
494 | up(&ctrl->crit_sect); | ||
495 | return rc; | ||
496 | } | ||
497 | |||
498 | up(&ctrl->crit_sect); | ||
499 | |||
500 | /* Wait for ~1 second */ | 318 | /* Wait for ~1 second */ |
501 | wait_for_ctrl_irq (ctrl); | 319 | msleep(1000); |
502 | 320 | ||
503 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); | 321 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); |
504 | /* Check for a power fault */ | 322 | /* Check for a power fault */ |
@@ -520,40 +338,18 @@ static int board_added(struct slot *p_slot) | |||
520 | p_slot->is_a_board = 0x01; | 338 | p_slot->is_a_board = 0x01; |
521 | p_slot->pwr_save = 1; | 339 | p_slot->pwr_save = 1; |
522 | 340 | ||
523 | /* Wait for exclusive access to hardware */ | ||
524 | down(&ctrl->crit_sect); | ||
525 | |||
526 | p_slot->hpc_ops->green_led_on(p_slot); | 341 | p_slot->hpc_ops->green_led_on(p_slot); |
527 | 342 | ||
528 | /* Done with exclusive hardware access */ | ||
529 | up(&ctrl->crit_sect); | ||
530 | |||
531 | return 0; | 343 | return 0; |
532 | 344 | ||
533 | err_exit: | 345 | err_exit: |
534 | /* Wait for exclusive access to hardware */ | ||
535 | down(&ctrl->crit_sect); | ||
536 | |||
537 | /* turn off slot, turn on Amber LED, turn off Green LED */ | 346 | /* turn off slot, turn on Amber LED, turn off Green LED */ |
538 | rc = p_slot->hpc_ops->slot_disable(p_slot); | 347 | rc = p_slot->hpc_ops->slot_disable(p_slot); |
539 | if (rc) { | 348 | if (rc) { |
540 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 349 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
541 | /* Done with exclusive hardware access */ | ||
542 | up(&ctrl->crit_sect); | ||
543 | return rc; | ||
544 | } | ||
545 | |||
546 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
547 | if (rc) { | ||
548 | err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); | ||
549 | /* Done with exclusive hardware access */ | ||
550 | up(&ctrl->crit_sect); | ||
551 | return rc; | 350 | return rc; |
552 | } | 351 | } |
553 | 352 | ||
554 | /* Done with exclusive hardware access */ | ||
555 | up(&ctrl->crit_sect); | ||
556 | |||
557 | return(rc); | 353 | return(rc); |
558 | } | 354 | } |
559 | 355 | ||
@@ -580,37 +376,19 @@ static int remove_board(struct slot *p_slot) | |||
580 | if (p_slot->is_a_board) | 376 | if (p_slot->is_a_board) |
581 | p_slot->status = 0x01; | 377 | p_slot->status = 0x01; |
582 | 378 | ||
583 | /* Wait for exclusive access to hardware */ | ||
584 | down(&ctrl->crit_sect); | ||
585 | |||
586 | /* turn off slot, turn on Amber LED, turn off Green LED */ | 379 | /* turn off slot, turn on Amber LED, turn off Green LED */ |
587 | rc = p_slot->hpc_ops->slot_disable(p_slot); | 380 | rc = p_slot->hpc_ops->slot_disable(p_slot); |
588 | if (rc) { | 381 | if (rc) { |
589 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 382 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
590 | /* Done with exclusive hardware access */ | ||
591 | up(&ctrl->crit_sect); | ||
592 | return rc; | 383 | return rc; |
593 | } | 384 | } |
594 | |||
595 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
596 | if (rc) { | ||
597 | err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); | ||
598 | /* Done with exclusive hardware access */ | ||
599 | up(&ctrl->crit_sect); | ||
600 | return rc; | ||
601 | } | ||
602 | 385 | ||
603 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); | 386 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); |
604 | if (rc) { | 387 | if (rc) { |
605 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); | 388 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); |
606 | /* Done with exclusive hardware access */ | ||
607 | up(&ctrl->crit_sect); | ||
608 | return rc; | 389 | return rc; |
609 | } | 390 | } |
610 | 391 | ||
611 | /* Done with exclusive hardware access */ | ||
612 | up(&ctrl->crit_sect); | ||
613 | |||
614 | p_slot->pwr_save = 0; | 392 | p_slot->pwr_save = 0; |
615 | p_slot->is_a_board = 0; | 393 | p_slot->is_a_board = 0; |
616 | 394 | ||
@@ -618,13 +396,10 @@ static int remove_board(struct slot *p_slot) | |||
618 | } | 396 | } |
619 | 397 | ||
620 | 398 | ||
621 | static void pushbutton_helper_thread (unsigned long data) | 399 | struct pushbutton_work_info { |
622 | { | 400 | struct slot *p_slot; |
623 | pushbutton_pending = data; | 401 | struct work_struct work; |
624 | 402 | }; | |
625 | up(&event_semaphore); | ||
626 | } | ||
627 | |||
628 | 403 | ||
629 | /** | 404 | /** |
630 | * shpchp_pushbutton_thread | 405 | * shpchp_pushbutton_thread |
@@ -633,96 +408,63 @@ static void pushbutton_helper_thread (unsigned long data) | |||
633 | * Handles all pending events and exits. | 408 | * Handles all pending events and exits. |
634 | * | 409 | * |
635 | */ | 410 | */ |
636 | static void shpchp_pushbutton_thread (unsigned long slot) | 411 | static void shpchp_pushbutton_thread(void *data) |
637 | { | 412 | { |
638 | struct slot *p_slot = (struct slot *) slot; | 413 | struct pushbutton_work_info *info = data; |
639 | u8 getstatus; | 414 | struct slot *p_slot = info->p_slot; |
640 | |||
641 | pushbutton_pending = 0; | ||
642 | |||
643 | if (!p_slot) { | ||
644 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | ||
645 | return; | ||
646 | } | ||
647 | |||
648 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | ||
649 | if (getstatus) { | ||
650 | p_slot->state = POWEROFF_STATE; | ||
651 | 415 | ||
416 | mutex_lock(&p_slot->lock); | ||
417 | switch (p_slot->state) { | ||
418 | case POWEROFF_STATE: | ||
419 | mutex_unlock(&p_slot->lock); | ||
652 | shpchp_disable_slot(p_slot); | 420 | shpchp_disable_slot(p_slot); |
421 | mutex_lock(&p_slot->lock); | ||
653 | p_slot->state = STATIC_STATE; | 422 | p_slot->state = STATIC_STATE; |
654 | } else { | 423 | break; |
655 | p_slot->state = POWERON_STATE; | 424 | case POWERON_STATE: |
656 | 425 | mutex_unlock(&p_slot->lock); | |
657 | if (shpchp_enable_slot(p_slot)) { | 426 | if (shpchp_enable_slot(p_slot)) |
658 | /* Wait for exclusive access to hardware */ | ||
659 | down(&p_slot->ctrl->crit_sect); | ||
660 | |||
661 | p_slot->hpc_ops->green_led_off(p_slot); | 427 | p_slot->hpc_ops->green_led_off(p_slot); |
662 | 428 | mutex_lock(&p_slot->lock); | |
663 | /* Done with exclusive hardware access */ | ||
664 | up(&p_slot->ctrl->crit_sect); | ||
665 | } | ||
666 | p_slot->state = STATIC_STATE; | 429 | p_slot->state = STATIC_STATE; |
430 | break; | ||
431 | default: | ||
432 | break; | ||
667 | } | 433 | } |
434 | mutex_unlock(&p_slot->lock); | ||
668 | 435 | ||
669 | return; | 436 | kfree(info); |
670 | } | ||
671 | |||
672 | |||
673 | /* this is the main worker thread */ | ||
674 | static int event_thread(void* data) | ||
675 | { | ||
676 | struct controller *ctrl; | ||
677 | lock_kernel(); | ||
678 | daemonize("shpchpd_event"); | ||
679 | unlock_kernel(); | ||
680 | |||
681 | while (1) { | ||
682 | dbg("!!!!event_thread sleeping\n"); | ||
683 | down_interruptible (&event_semaphore); | ||
684 | dbg("event_thread woken finished = %d\n", event_finished); | ||
685 | if (event_finished || signal_pending(current)) | ||
686 | break; | ||
687 | /* Do stuff here */ | ||
688 | if (pushbutton_pending) | ||
689 | shpchp_pushbutton_thread(pushbutton_pending); | ||
690 | else | ||
691 | for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) | ||
692 | interrupt_event_handler(ctrl); | ||
693 | } | ||
694 | dbg("event_thread signals exit\n"); | ||
695 | up(&event_exit); | ||
696 | return 0; | ||
697 | } | 437 | } |
698 | 438 | ||
699 | int shpchp_event_start_thread (void) | 439 | void queue_pushbutton_work(void *data) |
700 | { | 440 | { |
701 | int pid; | 441 | struct slot *p_slot = data; |
442 | struct pushbutton_work_info *info; | ||
702 | 443 | ||
703 | /* initialize our semaphores */ | 444 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
704 | init_MUTEX_LOCKED(&event_exit); | 445 | if (!info) { |
705 | event_finished=0; | 446 | err("%s: Cannot allocate memory\n", __FUNCTION__); |
706 | 447 | return; | |
707 | init_MUTEX_LOCKED(&event_semaphore); | ||
708 | pid = kernel_thread(event_thread, NULL, 0); | ||
709 | |||
710 | if (pid < 0) { | ||
711 | err ("Can't start up our event thread\n"); | ||
712 | return -1; | ||
713 | } | 448 | } |
714 | return 0; | 449 | info->p_slot = p_slot; |
715 | } | 450 | INIT_WORK(&info->work, shpchp_pushbutton_thread, info); |
716 | |||
717 | 451 | ||
718 | void shpchp_event_stop_thread (void) | 452 | mutex_lock(&p_slot->lock); |
719 | { | 453 | switch (p_slot->state) { |
720 | event_finished = 1; | 454 | case BLINKINGOFF_STATE: |
721 | up(&event_semaphore); | 455 | p_slot->state = POWEROFF_STATE; |
722 | down(&event_exit); | 456 | break; |
457 | case BLINKINGON_STATE: | ||
458 | p_slot->state = POWERON_STATE; | ||
459 | break; | ||
460 | default: | ||
461 | goto out; | ||
462 | } | ||
463 | queue_work(shpchp_wq, &info->work); | ||
464 | out: | ||
465 | mutex_unlock(&p_slot->lock); | ||
723 | } | 466 | } |
724 | 467 | ||
725 | |||
726 | static int update_slot_info (struct slot *slot) | 468 | static int update_slot_info (struct slot *slot) |
727 | { | 469 | { |
728 | struct hotplug_slot_info *info; | 470 | struct hotplug_slot_info *info; |
@@ -742,149 +484,110 @@ static int update_slot_info (struct slot *slot) | |||
742 | return result; | 484 | return result; |
743 | } | 485 | } |
744 | 486 | ||
745 | static void interrupt_event_handler(struct controller *ctrl) | 487 | /* |
488 | * Note: This function must be called with slot->lock held | ||
489 | */ | ||
490 | static void handle_button_press_event(struct slot *p_slot) | ||
746 | { | 491 | { |
747 | int loop = 0; | ||
748 | int change = 1; | ||
749 | u8 hp_slot; | ||
750 | u8 getstatus; | 492 | u8 getstatus; |
751 | struct slot *p_slot; | ||
752 | 493 | ||
753 | while (change) { | 494 | switch (p_slot->state) { |
754 | change = 0; | 495 | case STATIC_STATE: |
755 | 496 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | |
756 | for (loop = 0; loop < 10; loop++) { | 497 | if (getstatus) { |
757 | if (ctrl->event_queue[loop].event_type != 0) { | 498 | p_slot->state = BLINKINGOFF_STATE; |
758 | dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, | 499 | info(msg_button_off, p_slot->number); |
759 | ctrl->event_queue[loop].event_type); | 500 | } else { |
760 | hp_slot = ctrl->event_queue[loop].hp_slot; | 501 | p_slot->state = BLINKINGON_STATE; |
761 | 502 | info(msg_button_on, p_slot->number); | |
762 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 503 | } |
763 | 504 | /* blink green LED and turn off amber */ | |
764 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 505 | p_slot->hpc_ops->green_led_blink(p_slot); |
765 | dbg("%s: button cancel\n", __FUNCTION__); | 506 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
766 | del_timer(&p_slot->task_event); | 507 | |
767 | 508 | schedule_delayed_work(&p_slot->work, 5*HZ); | |
768 | switch (p_slot->state) { | 509 | break; |
769 | case BLINKINGOFF_STATE: | 510 | case BLINKINGOFF_STATE: |
770 | /* Wait for exclusive access to hardware */ | 511 | case BLINKINGON_STATE: |
771 | down(&ctrl->crit_sect); | 512 | /* |
772 | 513 | * Cancel if we are still blinking; this means that we | |
773 | p_slot->hpc_ops->green_led_on(p_slot); | 514 | * press the attention again before the 5 sec. limit |
774 | 515 | * expires to cancel hot-add or hot-remove | |
775 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 516 | */ |
776 | 517 | info("Button cancel on Slot(%s)\n", p_slot->name); | |
777 | /* Done with exclusive hardware access */ | 518 | dbg("%s: button cancel\n", __FUNCTION__); |
778 | up(&ctrl->crit_sect); | 519 | cancel_delayed_work(&p_slot->work); |
779 | break; | 520 | if (p_slot->state == BLINKINGOFF_STATE) |
780 | case BLINKINGON_STATE: | 521 | p_slot->hpc_ops->green_led_on(p_slot); |
781 | /* Wait for exclusive access to hardware */ | 522 | else |
782 | down(&ctrl->crit_sect); | 523 | p_slot->hpc_ops->green_led_off(p_slot); |
783 | 524 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | |
784 | p_slot->hpc_ops->green_led_off(p_slot); | 525 | info(msg_button_cancel, p_slot->number); |
785 | 526 | p_slot->state = STATIC_STATE; | |
786 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 527 | break; |
787 | 528 | case POWEROFF_STATE: | |
788 | /* Done with exclusive hardware access */ | 529 | case POWERON_STATE: |
789 | up(&ctrl->crit_sect); | 530 | /* |
790 | 531 | * Ignore if the slot is on power-on or power-off state; | |
791 | break; | 532 | * this means that the previous attention button action |
792 | default: | 533 | * to hot-add or hot-remove is undergoing |
793 | warn("Not a valid state\n"); | 534 | */ |
794 | return; | 535 | info("Button ignore on Slot(%s)\n", p_slot->name); |
795 | } | 536 | update_slot_info(p_slot); |
796 | info(msg_button_cancel, p_slot->number); | 537 | break; |
797 | p_slot->state = STATIC_STATE; | 538 | default: |
798 | } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { | 539 | warn("Not a valid state\n"); |
799 | /* Button Pressed (No action on 1st press...) */ | 540 | break; |
800 | dbg("%s: Button pressed\n", __FUNCTION__); | ||
801 | |||
802 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | ||
803 | if (getstatus) { | ||
804 | /* slot is on */ | ||
805 | dbg("%s: slot is on\n", __FUNCTION__); | ||
806 | p_slot->state = BLINKINGOFF_STATE; | ||
807 | info(msg_button_off, p_slot->number); | ||
808 | } else { | ||
809 | /* slot is off */ | ||
810 | dbg("%s: slot is off\n", __FUNCTION__); | ||
811 | p_slot->state = BLINKINGON_STATE; | ||
812 | info(msg_button_on, p_slot->number); | ||
813 | } | ||
814 | |||
815 | /* Wait for exclusive access to hardware */ | ||
816 | down(&ctrl->crit_sect); | ||
817 | |||
818 | /* blink green LED and turn off amber */ | ||
819 | p_slot->hpc_ops->green_led_blink(p_slot); | ||
820 | |||
821 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
822 | |||
823 | /* Done with exclusive hardware access */ | ||
824 | up(&ctrl->crit_sect); | ||
825 | |||
826 | init_timer(&p_slot->task_event); | ||
827 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | ||
828 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | ||
829 | p_slot->task_event.data = (unsigned long) p_slot; | ||
830 | |||
831 | dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); | ||
832 | add_timer(&p_slot->task_event); | ||
833 | } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | ||
834 | /***********POWER FAULT********************/ | ||
835 | dbg("%s: power fault\n", __FUNCTION__); | ||
836 | /* Wait for exclusive access to hardware */ | ||
837 | down(&ctrl->crit_sect); | ||
838 | |||
839 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
840 | |||
841 | p_slot->hpc_ops->green_led_off(p_slot); | ||
842 | |||
843 | /* Done with exclusive hardware access */ | ||
844 | up(&ctrl->crit_sect); | ||
845 | } else { | ||
846 | /* refresh notification */ | ||
847 | if (p_slot) | ||
848 | update_slot_info(p_slot); | ||
849 | } | ||
850 | |||
851 | ctrl->event_queue[loop].event_type = 0; | ||
852 | |||
853 | change = 1; | ||
854 | } | ||
855 | } /* End of FOR loop */ | ||
856 | } | 541 | } |
542 | } | ||
543 | |||
544 | static void interrupt_event_handler(void *data) | ||
545 | { | ||
546 | struct event_info *info = data; | ||
547 | struct slot *p_slot = info->p_slot; | ||
548 | |||
549 | mutex_lock(&p_slot->lock); | ||
550 | switch (info->event_type) { | ||
551 | case INT_BUTTON_PRESS: | ||
552 | handle_button_press_event(p_slot); | ||
553 | break; | ||
554 | case INT_POWER_FAULT: | ||
555 | dbg("%s: power fault\n", __FUNCTION__); | ||
556 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
557 | p_slot->hpc_ops->green_led_off(p_slot); | ||
558 | break; | ||
559 | default: | ||
560 | update_slot_info(p_slot); | ||
561 | break; | ||
562 | } | ||
563 | mutex_unlock(&p_slot->lock); | ||
857 | 564 | ||
858 | return; | 565 | kfree(info); |
859 | } | 566 | } |
860 | 567 | ||
861 | 568 | ||
862 | int shpchp_enable_slot (struct slot *p_slot) | 569 | static int shpchp_enable_slot (struct slot *p_slot) |
863 | { | 570 | { |
864 | u8 getstatus = 0; | 571 | u8 getstatus = 0; |
865 | int rc; | 572 | int rc, retval = -ENODEV; |
866 | 573 | ||
867 | /* Check to see if (latch closed, card present, power off) */ | 574 | /* Check to see if (latch closed, card present, power off) */ |
868 | down(&p_slot->ctrl->crit_sect); | 575 | mutex_lock(&p_slot->ctrl->crit_sect); |
869 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 576 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
870 | if (rc || !getstatus) { | 577 | if (rc || !getstatus) { |
871 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 578 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
872 | up(&p_slot->ctrl->crit_sect); | 579 | goto out; |
873 | return -ENODEV; | ||
874 | } | 580 | } |
875 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 581 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
876 | if (rc || getstatus) { | 582 | if (rc || getstatus) { |
877 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 583 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
878 | up(&p_slot->ctrl->crit_sect); | 584 | goto out; |
879 | return -ENODEV; | ||
880 | } | 585 | } |
881 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 586 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
882 | if (rc || getstatus) { | 587 | if (rc || getstatus) { |
883 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 588 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); |
884 | up(&p_slot->ctrl->crit_sect); | 589 | goto out; |
885 | return -ENODEV; | ||
886 | } | 590 | } |
887 | up(&p_slot->ctrl->crit_sect); | ||
888 | 591 | ||
889 | p_slot->is_a_board = 1; | 592 | p_slot->is_a_board = 1; |
890 | 593 | ||
@@ -899,56 +602,119 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
899 | && p_slot->ctrl->num_slots == 1) { | 602 | && p_slot->ctrl->num_slots == 1) { |
900 | /* handle amd pogo errata; this must be done before enable */ | 603 | /* handle amd pogo errata; this must be done before enable */ |
901 | amd_pogo_errata_save_misc_reg(p_slot); | 604 | amd_pogo_errata_save_misc_reg(p_slot); |
902 | rc = board_added(p_slot); | 605 | retval = board_added(p_slot); |
903 | /* handle amd pogo errata; this must be done after enable */ | 606 | /* handle amd pogo errata; this must be done after enable */ |
904 | amd_pogo_errata_restore_misc_reg(p_slot); | 607 | amd_pogo_errata_restore_misc_reg(p_slot); |
905 | } else | 608 | } else |
906 | rc = board_added(p_slot); | 609 | retval = board_added(p_slot); |
907 | 610 | ||
908 | if (rc) { | 611 | if (retval) { |
909 | p_slot->hpc_ops->get_adapter_status(p_slot, | 612 | p_slot->hpc_ops->get_adapter_status(p_slot, |
910 | &(p_slot->presence_save)); | 613 | &(p_slot->presence_save)); |
911 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 614 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
912 | } | 615 | } |
913 | 616 | ||
914 | update_slot_info(p_slot); | 617 | update_slot_info(p_slot); |
915 | return rc; | 618 | out: |
619 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
620 | return retval; | ||
916 | } | 621 | } |
917 | 622 | ||
918 | 623 | ||
919 | int shpchp_disable_slot (struct slot *p_slot) | 624 | static int shpchp_disable_slot (struct slot *p_slot) |
920 | { | 625 | { |
921 | u8 getstatus = 0; | 626 | u8 getstatus = 0; |
922 | int ret = 0; | 627 | int rc, retval = -ENODEV; |
923 | 628 | ||
924 | if (!p_slot->ctrl) | 629 | if (!p_slot->ctrl) |
925 | return -ENODEV; | 630 | return -ENODEV; |
926 | 631 | ||
927 | /* Check to see if (latch closed, card present, power on) */ | 632 | /* Check to see if (latch closed, card present, power on) */ |
928 | down(&p_slot->ctrl->crit_sect); | 633 | mutex_lock(&p_slot->ctrl->crit_sect); |
929 | 634 | ||
930 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 635 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
931 | if (ret || !getstatus) { | 636 | if (rc || !getstatus) { |
932 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 637 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
933 | up(&p_slot->ctrl->crit_sect); | 638 | goto out; |
934 | return -ENODEV; | ||
935 | } | 639 | } |
936 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 640 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
937 | if (ret || getstatus) { | 641 | if (rc || getstatus) { |
938 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 642 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
939 | up(&p_slot->ctrl->crit_sect); | 643 | goto out; |
940 | return -ENODEV; | ||
941 | } | 644 | } |
942 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 645 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
943 | if (ret || !getstatus) { | 646 | if (rc || !getstatus) { |
944 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 647 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); |
945 | up(&p_slot->ctrl->crit_sect); | 648 | goto out; |
946 | return -ENODEV; | ||
947 | } | 649 | } |
948 | up(&p_slot->ctrl->crit_sect); | ||
949 | 650 | ||
950 | ret = remove_board(p_slot); | 651 | retval = remove_board(p_slot); |
951 | update_slot_info(p_slot); | 652 | update_slot_info(p_slot); |
952 | return ret; | 653 | out: |
654 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
655 | return retval; | ||
953 | } | 656 | } |
954 | 657 | ||
658 | int shpchp_sysfs_enable_slot(struct slot *p_slot) | ||
659 | { | ||
660 | int retval = -ENODEV; | ||
661 | |||
662 | mutex_lock(&p_slot->lock); | ||
663 | switch (p_slot->state) { | ||
664 | case BLINKINGON_STATE: | ||
665 | cancel_delayed_work(&p_slot->work); | ||
666 | case STATIC_STATE: | ||
667 | p_slot->state = POWERON_STATE; | ||
668 | mutex_unlock(&p_slot->lock); | ||
669 | retval = shpchp_enable_slot(p_slot); | ||
670 | mutex_lock(&p_slot->lock); | ||
671 | p_slot->state = STATIC_STATE; | ||
672 | break; | ||
673 | case POWERON_STATE: | ||
674 | info("Slot %s is already in powering on state\n", | ||
675 | p_slot->name); | ||
676 | break; | ||
677 | case BLINKINGOFF_STATE: | ||
678 | case POWEROFF_STATE: | ||
679 | info("Already enabled on slot %s\n", p_slot->name); | ||
680 | break; | ||
681 | default: | ||
682 | err("Not a valid state on slot %s\n", p_slot->name); | ||
683 | break; | ||
684 | } | ||
685 | mutex_unlock(&p_slot->lock); | ||
686 | |||
687 | return retval; | ||
688 | } | ||
689 | |||
690 | int shpchp_sysfs_disable_slot(struct slot *p_slot) | ||
691 | { | ||
692 | int retval = -ENODEV; | ||
693 | |||
694 | mutex_lock(&p_slot->lock); | ||
695 | switch (p_slot->state) { | ||
696 | case BLINKINGOFF_STATE: | ||
697 | cancel_delayed_work(&p_slot->work); | ||
698 | case STATIC_STATE: | ||
699 | p_slot->state = POWEROFF_STATE; | ||
700 | mutex_unlock(&p_slot->lock); | ||
701 | retval = shpchp_disable_slot(p_slot); | ||
702 | mutex_lock(&p_slot->lock); | ||
703 | p_slot->state = STATIC_STATE; | ||
704 | break; | ||
705 | case POWEROFF_STATE: | ||
706 | info("Slot %s is already in powering off state\n", | ||
707 | p_slot->name); | ||
708 | break; | ||
709 | case BLINKINGON_STATE: | ||
710 | case POWERON_STATE: | ||
711 | info("Already disabled on slot %s\n", p_slot->name); | ||
712 | break; | ||
713 | default: | ||
714 | err("Not a valid state on slot %s\n", p_slot->name); | ||
715 | break; | ||
716 | } | ||
717 | mutex_unlock(&p_slot->lock); | ||
718 | |||
719 | return retval; | ||
720 | } | ||
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b4226ff3a854..66123cf4deaa 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -82,31 +82,6 @@ | |||
82 | #define SLOT_100MHZ_PCIX_533 0x0f000000 | 82 | #define SLOT_100MHZ_PCIX_533 0x0f000000 |
83 | #define SLOT_133MHZ_PCIX_533 0xf0000000 | 83 | #define SLOT_133MHZ_PCIX_533 0xf0000000 |
84 | 84 | ||
85 | |||
86 | /* Secondary Bus Configuration Register */ | ||
87 | /* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */ | ||
88 | #define PCI_33MHZ 0x0 | ||
89 | #define PCI_66MHZ 0x1 | ||
90 | #define PCIX_66MHZ 0x2 | ||
91 | #define PCIX_100MHZ 0x3 | ||
92 | #define PCIX_133MHZ 0x4 | ||
93 | |||
94 | /* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */ | ||
95 | #define PCI_33MHZ 0x0 | ||
96 | #define PCI_66MHZ 0x1 | ||
97 | #define PCIX_66MHZ 0x2 | ||
98 | #define PCIX_100MHZ 0x3 | ||
99 | #define PCIX_133MHZ 0x4 | ||
100 | #define PCIX_66MHZ_ECC 0x5 | ||
101 | #define PCIX_100MHZ_ECC 0x6 | ||
102 | #define PCIX_133MHZ_ECC 0x7 | ||
103 | #define PCIX_66MHZ_266 0x9 | ||
104 | #define PCIX_100MHZ_266 0xa | ||
105 | #define PCIX_133MHZ_266 0xb | ||
106 | #define PCIX_66MHZ_533 0x11 | ||
107 | #define PCIX_100MHZ_533 0x12 | ||
108 | #define PCIX_133MHZ_533 0x13 | ||
109 | |||
110 | /* Slot Configuration */ | 85 | /* Slot Configuration */ |
111 | #define SLOT_NUM 0x0000001F | 86 | #define SLOT_NUM 0x0000001F |
112 | #define FIRST_DEV_NUM 0x00001F00 | 87 | #define FIRST_DEV_NUM 0x00001F00 |
@@ -231,6 +206,7 @@ static spinlock_t list_lock; | |||
231 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); | 206 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); |
232 | 207 | ||
233 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); | 208 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); |
209 | static int hpc_check_cmd_status(struct controller *ctrl); | ||
234 | 210 | ||
235 | /* This is the interrupt polling timeout function. */ | 211 | /* This is the interrupt polling timeout function. */ |
236 | static void int_poll_timeout(unsigned long lphp_ctlr) | 212 | static void int_poll_timeout(unsigned long lphp_ctlr) |
@@ -303,10 +279,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
303 | int i; | 279 | int i; |
304 | 280 | ||
305 | DBG_ENTER_ROUTINE | 281 | DBG_ENTER_ROUTINE |
306 | 282 | ||
283 | mutex_lock(&slot->ctrl->cmd_lock); | ||
284 | |||
307 | if (!php_ctlr) { | 285 | if (!php_ctlr) { |
308 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 286 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
309 | return -1; | 287 | retval = -EINVAL; |
288 | goto out; | ||
310 | } | 289 | } |
311 | 290 | ||
312 | for (i = 0; i < 10; i++) { | 291 | for (i = 0; i < 10; i++) { |
@@ -323,7 +302,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
323 | if (cmd_status & 0x1) { | 302 | if (cmd_status & 0x1) { |
324 | /* After 1 sec and and the controller is still busy */ | 303 | /* After 1 sec and and the controller is still busy */ |
325 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); | 304 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); |
326 | return -1; | 305 | retval = -EBUSY; |
306 | goto out; | ||
327 | } | 307 | } |
328 | 308 | ||
329 | ++t_slot; | 309 | ++t_slot; |
@@ -340,6 +320,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
340 | * Wait for command completion. | 320 | * Wait for command completion. |
341 | */ | 321 | */ |
342 | retval = shpc_wait_cmd(slot->ctrl); | 322 | retval = shpc_wait_cmd(slot->ctrl); |
323 | if (retval) | ||
324 | goto out; | ||
325 | |||
326 | cmd_status = hpc_check_cmd_status(slot->ctrl); | ||
327 | if (cmd_status) { | ||
328 | err("%s: Failed to issued command 0x%x (error code = %d)\n", | ||
329 | __FUNCTION__, cmd, cmd_status); | ||
330 | retval = -EIO; | ||
331 | } | ||
332 | out: | ||
333 | mutex_unlock(&slot->ctrl->cmd_lock); | ||
343 | 334 | ||
344 | DBG_LEAVE_ROUTINE | 335 | DBG_LEAVE_ROUTINE |
345 | return retval; | 336 | return retval; |
@@ -532,81 +523,41 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) | |||
532 | 523 | ||
533 | static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) | 524 | static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) |
534 | { | 525 | { |
535 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | ||
536 | u32 slot_reg; | ||
537 | u16 slot_status, sec_bus_status; | ||
538 | u8 m66_cap, pcix_cap, pi; | ||
539 | int retval = 0; | 526 | int retval = 0; |
527 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | ||
528 | u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); | ||
529 | u8 pcix_cap = (slot_reg >> 12) & 7; | ||
530 | u8 m66_cap = (slot_reg >> 9) & 1; | ||
540 | 531 | ||
541 | DBG_ENTER_ROUTINE | 532 | DBG_ENTER_ROUTINE |
542 | 533 | ||
543 | if (!slot->ctrl->hpc_ctlr_handle) { | 534 | dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", |
544 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 535 | __FUNCTION__, slot_reg, pcix_cap, m66_cap); |
545 | return -1; | ||
546 | } | ||
547 | |||
548 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
549 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
550 | return -1; | ||
551 | } | ||
552 | |||
553 | pi = readb(php_ctlr->creg + PROG_INTERFACE); | ||
554 | slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); | ||
555 | dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg); | ||
556 | slot_status = (u16) slot_reg; | ||
557 | dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status); | ||
558 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); | ||
559 | |||
560 | pcix_cap = (u8) ((slot_status & 0x3000) >> 12); | ||
561 | dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap); | ||
562 | m66_cap = (u8) ((slot_status & 0x0200) >> 9); | ||
563 | dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap); | ||
564 | |||
565 | 536 | ||
566 | if (pi == 2) { | 537 | switch (pcix_cap) { |
567 | switch (pcix_cap) { | 538 | case 0x0: |
568 | case 0: | 539 | *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; |
569 | *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; | 540 | break; |
570 | break; | 541 | case 0x1: |
571 | case 1: | 542 | *value = PCI_SPEED_66MHz_PCIX; |
572 | *value = PCI_SPEED_66MHz_PCIX; | 543 | break; |
573 | break; | 544 | case 0x3: |
574 | case 3: | 545 | *value = PCI_SPEED_133MHz_PCIX; |
575 | *value = PCI_SPEED_133MHz_PCIX; | 546 | break; |
576 | break; | 547 | case 0x4: |
577 | case 4: | 548 | *value = PCI_SPEED_133MHz_PCIX_266; |
578 | *value = PCI_SPEED_133MHz_PCIX_266; | 549 | break; |
579 | break; | 550 | case 0x5: |
580 | case 5: | 551 | *value = PCI_SPEED_133MHz_PCIX_533; |
581 | *value = PCI_SPEED_133MHz_PCIX_533; | 552 | break; |
582 | break; | 553 | case 0x2: |
583 | case 2: /* Reserved */ | 554 | default: |
584 | default: | 555 | *value = PCI_SPEED_UNKNOWN; |
585 | *value = PCI_SPEED_UNKNOWN; | 556 | retval = -ENODEV; |
586 | retval = -ENODEV; | 557 | break; |
587 | break; | ||
588 | } | ||
589 | } else { | ||
590 | switch (pcix_cap) { | ||
591 | case 0: | ||
592 | *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; | ||
593 | break; | ||
594 | case 1: | ||
595 | *value = PCI_SPEED_66MHz_PCIX; | ||
596 | break; | ||
597 | case 3: | ||
598 | *value = PCI_SPEED_133MHz_PCIX; | ||
599 | break; | ||
600 | case 2: /* Reserved */ | ||
601 | default: | ||
602 | *value = PCI_SPEED_UNKNOWN; | ||
603 | retval = -ENODEV; | ||
604 | break; | ||
605 | } | ||
606 | } | 558 | } |
607 | 559 | ||
608 | dbg("Adapter speed = %d\n", *value); | 560 | dbg("Adapter speed = %d\n", *value); |
609 | |||
610 | DBG_LEAVE_ROUTINE | 561 | DBG_LEAVE_ROUTINE |
611 | return retval; | 562 | return retval; |
612 | } | 563 | } |
@@ -797,6 +748,7 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
797 | { | 748 | { |
798 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; | 749 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; |
799 | struct php_ctlr_state_s *p, *p_prev; | 750 | struct php_ctlr_state_s *p, *p_prev; |
751 | int i; | ||
800 | 752 | ||
801 | DBG_ENTER_ROUTINE | 753 | DBG_ENTER_ROUTINE |
802 | 754 | ||
@@ -805,6 +757,14 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
805 | return ; | 757 | return ; |
806 | } | 758 | } |
807 | 759 | ||
760 | /* | ||
761 | * Mask all slot event interrupts | ||
762 | */ | ||
763 | for (i = 0; i < ctrl->num_slots; i++) | ||
764 | writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); | ||
765 | |||
766 | cleanup_slots(ctrl); | ||
767 | |||
808 | if (shpchp_poll_mode) { | 768 | if (shpchp_poll_mode) { |
809 | del_timer(&php_ctlr->int_poll_timer); | 769 | del_timer(&php_ctlr->int_poll_timer); |
810 | } else { | 770 | } else { |
@@ -814,6 +774,7 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
814 | pci_disable_msi(php_ctlr->pci_dev); | 774 | pci_disable_msi(php_ctlr->pci_dev); |
815 | } | 775 | } |
816 | } | 776 | } |
777 | |||
817 | if (php_ctlr->pci_dev) { | 778 | if (php_ctlr->pci_dev) { |
818 | iounmap(php_ctlr->creg); | 779 | iounmap(php_ctlr->creg); |
819 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); | 780 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
@@ -939,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot) | |||
939 | 900 | ||
940 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | 901 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) |
941 | { | 902 | { |
942 | u8 slot_cmd; | 903 | int retval; |
943 | u8 pi; | ||
944 | int retval = 0; | ||
945 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 904 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
905 | u8 pi, cmd; | ||
946 | 906 | ||
947 | DBG_ENTER_ROUTINE | 907 | DBG_ENTER_ROUTINE |
948 | |||
949 | if (!slot->ctrl->hpc_ctlr_handle) { | ||
950 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
951 | return -1; | ||
952 | } | ||
953 | 908 | ||
954 | pi = readb(php_ctlr->creg + PROG_INTERFACE); | 909 | pi = readb(php_ctlr->creg + PROG_INTERFACE); |
955 | 910 | if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) | |
956 | if (pi == 1) { | 911 | return -EINVAL; |
957 | switch (value) { | ||
958 | case 0: | ||
959 | slot_cmd = SETA_PCI_33MHZ; | ||
960 | break; | ||
961 | case 1: | ||
962 | slot_cmd = SETA_PCI_66MHZ; | ||
963 | break; | ||
964 | case 2: | ||
965 | slot_cmd = SETA_PCIX_66MHZ; | ||
966 | break; | ||
967 | case 3: | ||
968 | slot_cmd = SETA_PCIX_100MHZ; | ||
969 | break; | ||
970 | case 4: | ||
971 | slot_cmd = SETA_PCIX_133MHZ; | ||
972 | break; | ||
973 | default: | ||
974 | slot_cmd = PCI_SPEED_UNKNOWN; | ||
975 | retval = -ENODEV; | ||
976 | return retval; | ||
977 | } | ||
978 | } else { | ||
979 | switch (value) { | ||
980 | case 0: | ||
981 | slot_cmd = SETB_PCI_33MHZ; | ||
982 | break; | ||
983 | case 1: | ||
984 | slot_cmd = SETB_PCI_66MHZ; | ||
985 | break; | ||
986 | case 2: | ||
987 | slot_cmd = SETB_PCIX_66MHZ_PM; | ||
988 | break; | ||
989 | case 3: | ||
990 | slot_cmd = SETB_PCIX_100MHZ_PM; | ||
991 | break; | ||
992 | case 4: | ||
993 | slot_cmd = SETB_PCIX_133MHZ_PM; | ||
994 | break; | ||
995 | case 5: | ||
996 | slot_cmd = SETB_PCIX_66MHZ_EM; | ||
997 | break; | ||
998 | case 6: | ||
999 | slot_cmd = SETB_PCIX_100MHZ_EM; | ||
1000 | break; | ||
1001 | case 7: | ||
1002 | slot_cmd = SETB_PCIX_133MHZ_EM; | ||
1003 | break; | ||
1004 | case 8: | ||
1005 | slot_cmd = SETB_PCIX_66MHZ_266; | ||
1006 | break; | ||
1007 | case 0x9: | ||
1008 | slot_cmd = SETB_PCIX_100MHZ_266; | ||
1009 | break; | ||
1010 | case 0xa: | ||
1011 | slot_cmd = SETB_PCIX_133MHZ_266; | ||
1012 | break; | ||
1013 | case 0xb: | ||
1014 | slot_cmd = SETB_PCIX_66MHZ_533; | ||
1015 | break; | ||
1016 | case 0xc: | ||
1017 | slot_cmd = SETB_PCIX_100MHZ_533; | ||
1018 | break; | ||
1019 | case 0xd: | ||
1020 | slot_cmd = SETB_PCIX_133MHZ_533; | ||
1021 | break; | ||
1022 | default: | ||
1023 | slot_cmd = PCI_SPEED_UNKNOWN; | ||
1024 | retval = -ENODEV; | ||
1025 | return retval; | ||
1026 | } | ||
1027 | 912 | ||
913 | switch (value) { | ||
914 | case PCI_SPEED_33MHz: | ||
915 | cmd = SETA_PCI_33MHZ; | ||
916 | break; | ||
917 | case PCI_SPEED_66MHz: | ||
918 | cmd = SETA_PCI_66MHZ; | ||
919 | break; | ||
920 | case PCI_SPEED_66MHz_PCIX: | ||
921 | cmd = SETA_PCIX_66MHZ; | ||
922 | break; | ||
923 | case PCI_SPEED_100MHz_PCIX: | ||
924 | cmd = SETA_PCIX_100MHZ; | ||
925 | break; | ||
926 | case PCI_SPEED_133MHz_PCIX: | ||
927 | cmd = SETA_PCIX_133MHZ; | ||
928 | break; | ||
929 | case PCI_SPEED_66MHz_PCIX_ECC: | ||
930 | cmd = SETB_PCIX_66MHZ_EM; | ||
931 | break; | ||
932 | case PCI_SPEED_100MHz_PCIX_ECC: | ||
933 | cmd = SETB_PCIX_100MHZ_EM; | ||
934 | break; | ||
935 | case PCI_SPEED_133MHz_PCIX_ECC: | ||
936 | cmd = SETB_PCIX_133MHZ_EM; | ||
937 | break; | ||
938 | case PCI_SPEED_66MHz_PCIX_266: | ||
939 | cmd = SETB_PCIX_66MHZ_266; | ||
940 | break; | ||
941 | case PCI_SPEED_100MHz_PCIX_266: | ||
942 | cmd = SETB_PCIX_100MHZ_266; | ||
943 | break; | ||
944 | case PCI_SPEED_133MHz_PCIX_266: | ||
945 | cmd = SETB_PCIX_133MHZ_266; | ||
946 | break; | ||
947 | case PCI_SPEED_66MHz_PCIX_533: | ||
948 | cmd = SETB_PCIX_66MHZ_533; | ||
949 | break; | ||
950 | case PCI_SPEED_100MHz_PCIX_533: | ||
951 | cmd = SETB_PCIX_100MHZ_533; | ||
952 | break; | ||
953 | case PCI_SPEED_133MHz_PCIX_533: | ||
954 | cmd = SETB_PCIX_133MHZ_533; | ||
955 | break; | ||
956 | default: | ||
957 | return -EINVAL; | ||
1028 | } | 958 | } |
1029 | retval = shpc_write_cmd(slot, 0, slot_cmd); | 959 | |
1030 | if (retval) { | 960 | retval = shpc_write_cmd(slot, 0, cmd); |
961 | if (retval) | ||
1031 | err("%s: Write command failed!\n", __FUNCTION__); | 962 | err("%s: Write command failed!\n", __FUNCTION__); |
1032 | return -1; | ||
1033 | } | ||
1034 | 963 | ||
1035 | DBG_LEAVE_ROUTINE | 964 | DBG_LEAVE_ROUTINE |
1036 | return retval; | 965 | return retval; |
@@ -1093,14 +1022,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1093 | wake_up_interruptible(&ctrl->queue); | 1022 | wake_up_interruptible(&ctrl->queue); |
1094 | } | 1023 | } |
1095 | 1024 | ||
1096 | if ((intr_loc = (intr_loc >> 1)) == 0) { | 1025 | if ((intr_loc = (intr_loc >> 1)) == 0) |
1097 | /* Unmask Global Interrupt Mask */ | 1026 | goto out; |
1098 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); | ||
1099 | temp_dword &= 0xfffffffe; | ||
1100 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); | ||
1101 | |||
1102 | return IRQ_NONE; | ||
1103 | } | ||
1104 | 1027 | ||
1105 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { | 1028 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { |
1106 | /* To find out which slot has interrupt pending */ | 1029 | /* To find out which slot has interrupt pending */ |
@@ -1130,6 +1053,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1130 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); | 1053 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); |
1131 | } | 1054 | } |
1132 | } | 1055 | } |
1056 | out: | ||
1133 | if (!shpchp_poll_mode) { | 1057 | if (!shpchp_poll_mode) { |
1134 | /* Unmask Global Interrupt Mask */ | 1058 | /* Unmask Global Interrupt Mask */ |
1135 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); | 1059 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); |
@@ -1142,64 +1066,43 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1142 | 1066 | ||
1143 | static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | 1067 | static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) |
1144 | { | 1068 | { |
1069 | int retval = 0; | ||
1145 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 1070 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
1146 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | 1071 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; |
1147 | int retval = 0; | 1072 | u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); |
1148 | u8 pi; | 1073 | u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); |
1149 | u32 slot_avail1, slot_avail2; | 1074 | u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); |
1150 | 1075 | ||
1151 | DBG_ENTER_ROUTINE | 1076 | DBG_ENTER_ROUTINE |
1152 | 1077 | ||
1153 | if (!slot->ctrl->hpc_ctlr_handle) { | ||
1154 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
1155 | return -1; | ||
1156 | } | ||
1157 | |||
1158 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
1159 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
1160 | return -1; | ||
1161 | } | ||
1162 | |||
1163 | pi = readb(php_ctlr->creg + PROG_INTERFACE); | ||
1164 | slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); | ||
1165 | slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); | ||
1166 | |||
1167 | if (pi == 2) { | 1078 | if (pi == 2) { |
1168 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) | 1079 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) |
1169 | bus_speed = PCIX_133MHZ_533; | 1080 | bus_speed = PCI_SPEED_133MHz_PCIX_533; |
1170 | else if (slot_avail2 & SLOT_100MHZ_PCIX_533) | 1081 | else if (slot_avail2 & SLOT_100MHZ_PCIX_533) |
1171 | bus_speed = PCIX_100MHZ_533; | 1082 | bus_speed = PCI_SPEED_100MHz_PCIX_533; |
1172 | else if (slot_avail2 & SLOT_66MHZ_PCIX_533) | 1083 | else if (slot_avail2 & SLOT_66MHZ_PCIX_533) |
1173 | bus_speed = PCIX_66MHZ_533; | 1084 | bus_speed = PCI_SPEED_66MHz_PCIX_533; |
1174 | else if (slot_avail2 & SLOT_133MHZ_PCIX_266) | 1085 | else if (slot_avail2 & SLOT_133MHZ_PCIX_266) |
1175 | bus_speed = PCIX_133MHZ_266; | 1086 | bus_speed = PCI_SPEED_133MHz_PCIX_266; |
1176 | else if (slot_avail2 & SLOT_100MHZ_PCIX_266) | 1087 | else if (slot_avail2 & SLOT_100MHZ_PCIX_266) |
1177 | bus_speed = PCIX_100MHZ_266; | 1088 | bus_speed = PCI_SPEED_100MHz_PCIX_266; |
1178 | else if (slot_avail2 & SLOT_66MHZ_PCIX_266) | 1089 | else if (slot_avail2 & SLOT_66MHZ_PCIX_266) |
1179 | bus_speed = PCIX_66MHZ_266; | 1090 | bus_speed = PCI_SPEED_66MHz_PCIX_266; |
1180 | else if (slot_avail1 & SLOT_133MHZ_PCIX) | 1091 | } |
1181 | bus_speed = PCIX_133MHZ; | 1092 | |
1182 | else if (slot_avail1 & SLOT_100MHZ_PCIX) | 1093 | if (bus_speed == PCI_SPEED_UNKNOWN) { |
1183 | bus_speed = PCIX_100MHZ; | ||
1184 | else if (slot_avail1 & SLOT_66MHZ_PCIX) | ||
1185 | bus_speed = PCIX_66MHZ; | ||
1186 | else if (slot_avail2 & SLOT_66MHZ) | ||
1187 | bus_speed = PCI_66MHZ; | ||
1188 | else if (slot_avail1 & SLOT_33MHZ) | ||
1189 | bus_speed = PCI_33MHZ; | ||
1190 | else bus_speed = PCI_SPEED_UNKNOWN; | ||
1191 | } else { | ||
1192 | if (slot_avail1 & SLOT_133MHZ_PCIX) | 1094 | if (slot_avail1 & SLOT_133MHZ_PCIX) |
1193 | bus_speed = PCIX_133MHZ; | 1095 | bus_speed = PCI_SPEED_133MHz_PCIX; |
1194 | else if (slot_avail1 & SLOT_100MHZ_PCIX) | 1096 | else if (slot_avail1 & SLOT_100MHZ_PCIX) |
1195 | bus_speed = PCIX_100MHZ; | 1097 | bus_speed = PCI_SPEED_100MHz_PCIX; |
1196 | else if (slot_avail1 & SLOT_66MHZ_PCIX) | 1098 | else if (slot_avail1 & SLOT_66MHZ_PCIX) |
1197 | bus_speed = PCIX_66MHZ; | 1099 | bus_speed = PCI_SPEED_66MHz_PCIX; |
1198 | else if (slot_avail2 & SLOT_66MHZ) | 1100 | else if (slot_avail2 & SLOT_66MHZ) |
1199 | bus_speed = PCI_66MHZ; | 1101 | bus_speed = PCI_SPEED_66MHz; |
1200 | else if (slot_avail1 & SLOT_33MHZ) | 1102 | else if (slot_avail1 & SLOT_33MHZ) |
1201 | bus_speed = PCI_33MHZ; | 1103 | bus_speed = PCI_SPEED_33MHz; |
1202 | else bus_speed = PCI_SPEED_UNKNOWN; | 1104 | else |
1105 | retval = -ENODEV; | ||
1203 | } | 1106 | } |
1204 | 1107 | ||
1205 | *value = bus_speed; | 1108 | *value = bus_speed; |
@@ -1210,111 +1113,69 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
1210 | 1113 | ||
1211 | static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | 1114 | static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) |
1212 | { | 1115 | { |
1116 | int retval = 0; | ||
1213 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 1117 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
1214 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | 1118 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; |
1215 | u16 sec_bus_status; | 1119 | u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); |
1216 | int retval = 0; | 1120 | u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); |
1217 | u8 pi; | 1121 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); |
1218 | 1122 | ||
1219 | DBG_ENTER_ROUTINE | 1123 | DBG_ENTER_ROUTINE |
1220 | 1124 | ||
1221 | if (!slot->ctrl->hpc_ctlr_handle) { | 1125 | if ((pi == 1) && (speed_mode > 4)) { |
1222 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 1126 | *value = PCI_SPEED_UNKNOWN; |
1223 | return -1; | 1127 | return -ENODEV; |
1224 | } | ||
1225 | |||
1226 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
1227 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
1228 | return -1; | ||
1229 | } | 1128 | } |
1230 | 1129 | ||
1231 | pi = readb(php_ctlr->creg + PROG_INTERFACE); | 1130 | switch (speed_mode) { |
1232 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); | 1131 | case 0x0: |
1233 | 1132 | *value = PCI_SPEED_33MHz; | |
1234 | if (pi == 2) { | 1133 | break; |
1235 | switch (sec_bus_status & 0x000f) { | 1134 | case 0x1: |
1236 | case 0: | 1135 | *value = PCI_SPEED_66MHz; |
1237 | bus_speed = PCI_SPEED_33MHz; | 1136 | break; |
1238 | break; | 1137 | case 0x2: |
1239 | case 1: | 1138 | *value = PCI_SPEED_66MHz_PCIX; |
1240 | bus_speed = PCI_SPEED_66MHz; | 1139 | break; |
1241 | break; | 1140 | case 0x3: |
1242 | case 2: | 1141 | *value = PCI_SPEED_100MHz_PCIX; |
1243 | bus_speed = PCI_SPEED_66MHz_PCIX; | 1142 | break; |
1244 | break; | 1143 | case 0x4: |
1245 | case 3: | 1144 | *value = PCI_SPEED_133MHz_PCIX; |
1246 | bus_speed = PCI_SPEED_100MHz_PCIX; | 1145 | break; |
1247 | break; | 1146 | case 0x5: |
1248 | case 4: | 1147 | *value = PCI_SPEED_66MHz_PCIX_ECC; |
1249 | bus_speed = PCI_SPEED_133MHz_PCIX; | 1148 | break; |
1250 | break; | 1149 | case 0x6: |
1251 | case 5: | 1150 | *value = PCI_SPEED_100MHz_PCIX_ECC; |
1252 | bus_speed = PCI_SPEED_66MHz_PCIX_ECC; | 1151 | break; |
1253 | break; | 1152 | case 0x7: |
1254 | case 6: | 1153 | *value = PCI_SPEED_133MHz_PCIX_ECC; |
1255 | bus_speed = PCI_SPEED_100MHz_PCIX_ECC; | 1154 | break; |
1256 | break; | 1155 | case 0x8: |
1257 | case 7: | 1156 | *value = PCI_SPEED_66MHz_PCIX_266; |
1258 | bus_speed = PCI_SPEED_133MHz_PCIX_ECC; | 1157 | break; |
1259 | break; | 1158 | case 0x9: |
1260 | case 8: | 1159 | *value = PCI_SPEED_100MHz_PCIX_266; |
1261 | bus_speed = PCI_SPEED_66MHz_PCIX_266; | 1160 | break; |
1262 | break; | 1161 | case 0xa: |
1263 | case 9: | 1162 | *value = PCI_SPEED_133MHz_PCIX_266; |
1264 | bus_speed = PCI_SPEED_100MHz_PCIX_266; | 1163 | break; |
1265 | break; | 1164 | case 0xb: |
1266 | case 0xa: | 1165 | *value = PCI_SPEED_66MHz_PCIX_533; |
1267 | bus_speed = PCI_SPEED_133MHz_PCIX_266; | 1166 | break; |
1268 | break; | 1167 | case 0xc: |
1269 | case 0xb: | 1168 | *value = PCI_SPEED_100MHz_PCIX_533; |
1270 | bus_speed = PCI_SPEED_66MHz_PCIX_533; | 1169 | break; |
1271 | break; | 1170 | case 0xd: |
1272 | case 0xc: | 1171 | *value = PCI_SPEED_133MHz_PCIX_533; |
1273 | bus_speed = PCI_SPEED_100MHz_PCIX_533; | 1172 | break; |
1274 | break; | 1173 | default: |
1275 | case 0xd: | 1174 | *value = PCI_SPEED_UNKNOWN; |
1276 | bus_speed = PCI_SPEED_133MHz_PCIX_533; | 1175 | retval = -ENODEV; |
1277 | break; | 1176 | break; |
1278 | case 0xe: | ||
1279 | case 0xf: | ||
1280 | default: | ||
1281 | bus_speed = PCI_SPEED_UNKNOWN; | ||
1282 | break; | ||
1283 | } | ||
1284 | } else { | ||
1285 | /* In the case where pi is undefined, default it to 1 */ | ||
1286 | switch (sec_bus_status & 0x0007) { | ||
1287 | case 0: | ||
1288 | bus_speed = PCI_SPEED_33MHz; | ||
1289 | break; | ||
1290 | case 1: | ||
1291 | bus_speed = PCI_SPEED_66MHz; | ||
1292 | break; | ||
1293 | case 2: | ||
1294 | bus_speed = PCI_SPEED_66MHz_PCIX; | ||
1295 | break; | ||
1296 | case 3: | ||
1297 | bus_speed = PCI_SPEED_100MHz_PCIX; | ||
1298 | break; | ||
1299 | case 4: | ||
1300 | bus_speed = PCI_SPEED_133MHz_PCIX; | ||
1301 | break; | ||
1302 | case 5: | ||
1303 | bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ | ||
1304 | break; | ||
1305 | case 6: | ||
1306 | bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ | ||
1307 | break; | ||
1308 | case 7: | ||
1309 | bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ | ||
1310 | break; | ||
1311 | default: | ||
1312 | bus_speed = PCI_SPEED_UNKNOWN; | ||
1313 | break; | ||
1314 | } | ||
1315 | } | 1177 | } |
1316 | 1178 | ||
1317 | *value = bus_speed; | ||
1318 | dbg("Current bus speed = %d\n", bus_speed); | 1179 | dbg("Current bus speed = %d\n", bus_speed); |
1319 | DBG_LEAVE_ROUTINE | 1180 | DBG_LEAVE_ROUTINE |
1320 | return retval; | 1181 | return retval; |
@@ -1343,7 +1204,6 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
1343 | .green_led_blink = hpc_set_green_led_blink, | 1204 | .green_led_blink = hpc_set_green_led_blink, |
1344 | 1205 | ||
1345 | .release_ctlr = hpc_release_ctlr, | 1206 | .release_ctlr = hpc_release_ctlr, |
1346 | .check_cmd_status = hpc_check_cmd_status, | ||
1347 | }; | 1207 | }; |
1348 | 1208 | ||
1349 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, | 1209 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, |
@@ -1375,15 +1235,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1375 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ | 1235 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ |
1376 | 1236 | ||
1377 | spin_lock_init(&list_lock); | 1237 | spin_lock_init(&list_lock); |
1378 | php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); | 1238 | php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); |
1379 | 1239 | ||
1380 | if (!php_ctlr) { /* allocate controller state data */ | 1240 | if (!php_ctlr) { /* allocate controller state data */ |
1381 | err("%s: HPC controller memory allocation error!\n", __FUNCTION__); | 1241 | err("%s: HPC controller memory allocation error!\n", __FUNCTION__); |
1382 | goto abort; | 1242 | goto abort; |
1383 | } | 1243 | } |
1384 | 1244 | ||
1385 | memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); | ||
1386 | |||
1387 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ | 1245 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ |
1388 | 1246 | ||
1389 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == | 1247 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == |
@@ -1454,7 +1312,9 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1454 | } | 1312 | } |
1455 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1313 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
1456 | 1314 | ||
1457 | init_MUTEX(&ctrl->crit_sect); | 1315 | mutex_init(&ctrl->crit_sect); |
1316 | mutex_init(&ctrl->cmd_lock); | ||
1317 | |||
1458 | /* Setup wait queue */ | 1318 | /* Setup wait queue */ |
1459 | init_waitqueue_head(&ctrl->queue); | 1319 | init_waitqueue_head(&ctrl->queue); |
1460 | 1320 | ||
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 19e1a5e1e30b..257adc233996 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev) | |||
38 | { | 38 | { |
39 | u16 pci_cmd, pci_bctl; | 39 | u16 pci_cmd, pci_bctl; |
40 | struct pci_dev *cdev; | 40 | struct pci_dev *cdev; |
41 | struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */ | 41 | struct hotplug_params hpp; |
42 | 42 | ||
43 | /* Program hpp values for this device */ | 43 | /* Program hpp values for this device */ |
44 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | 44 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || |
@@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev) | |||
46 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | 46 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) |
47 | return; | 47 | return; |
48 | 48 | ||
49 | get_hp_params_from_firmware(dev, &hpp); | 49 | /* use default values if we can't get them from firmware */ |
50 | if (get_hp_params_from_firmware(dev, &hpp)) { | ||
51 | hpp.cache_line_size = 8; | ||
52 | hpp.latency_timer = 0x40; | ||
53 | hpp.enable_serr = 0; | ||
54 | hpp.enable_perr = 0; | ||
55 | } | ||
50 | 56 | ||
51 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); | 57 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); |
52 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); | 58 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); |
diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c deleted file mode 100644 index ed6c1254bf6f..000000000000 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | /* | ||
2 | * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform | ||
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/kernel.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include "shpchp.h" | ||
35 | |||
36 | int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | ||
37 | { | ||
38 | int offset = devnum - ctrl->slot_device_offset; | ||
39 | |||
40 | *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | void get_hp_params_from_firmware(struct pci_dev *dev, | ||
45 | struct hotplug_params *hpp) | ||
46 | { | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | void get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
51 | { | ||
52 | return; | ||
53 | } | ||
54 | |||
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c deleted file mode 100644 index c6b40998eeb3..000000000000 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /* | ||
2 | * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform | ||
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/config.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/types.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #include "shpchp.h" | ||
38 | |||
39 | int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | ||
40 | { | ||
41 | int offset = devnum - ctrl->slot_device_offset; | ||
42 | |||
43 | dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); | ||
44 | *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | void get_hp_params_from_firmware(struct pci_dev *dev, | ||
49 | struct hotplug_params *hpp) | ||
50 | { | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | void get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
55 | { | ||
56 | return; | ||
57 | } | ||