aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2009-06-02 00:52:26 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-16 17:30:10 -0400
commitbd3d99c17039fd05a29587db3f4a180c48da115a (patch)
tree9eb211ae93977297f56f6e09c628de16d26f1bdb
parent1298307736a5882352418b4dc7c65442ab3b8bd4 (diff)
PCI: Remove untested Electromechanical Interlock (EMI) support in pciehp.
The EMI support in pciehp is obviously broken. It is implemented using struct hotplug_slot_attribute, but sysfs_ops for pci_slot_ktype is NOT for struct hotplug_slot_attribute, but for struct pci_slot_attribute. This bug had been there for a long time, maybe it was introduced when PCI slot framework was introduced. The reason why this bug didn't cause any problem is maybe the EMI support is not tested at all because of lack of test environment. As described above, the EMI support in pciehp seems not to be tested at all. So this patch removes EMI support from pciehp, instead of fixing the bug. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/hotplug/pciehp.h3
-rw-r--r--drivers/pci/hotplug/pciehp_core.c111
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c31
-rw-r--r--include/linux/pci_hotplug.h8
4 files changed, 1 insertions, 152 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 0a368547e63..e6cf096498b 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -81,7 +81,6 @@ struct slot {
81 struct hpc_ops *hpc_ops; 81 struct hpc_ops *hpc_ops;
82 struct hotplug_slot *hotplug_slot; 82 struct hotplug_slot *hotplug_slot;
83 struct list_head slot_list; 83 struct list_head slot_list;
84 unsigned long last_emi_toggle;
85 struct delayed_work work; /* work for button event */ 84 struct delayed_work work; /* work for button event */
86 struct mutex lock; 85 struct mutex lock;
87}; 86};
@@ -203,8 +202,6 @@ struct hpc_ops {
203 int (*set_attention_status)(struct slot *slot, u8 status); 202 int (*set_attention_status)(struct slot *slot, u8 status);
204 int (*get_latch_status)(struct slot *slot, u8 *status); 203 int (*get_latch_status)(struct slot *slot, u8 *status);
205 int (*get_adapter_status)(struct slot *slot, u8 *status); 204 int (*get_adapter_status)(struct slot *slot, u8 *status);
206 int (*get_emi_status)(struct slot *slot, u8 *status);
207 int (*toggle_emi)(struct slot *slot);
208 int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); 205 int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
209 int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); 206 int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
210 int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val); 207 int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index fb254b2454d..eb183d1d091 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -85,99 +85,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
85 .get_cur_bus_speed = get_cur_bus_speed, 85 .get_cur_bus_speed = get_cur_bus_speed,
86}; 86};
87 87
88/*
89 * Check the status of the Electro Mechanical Interlock (EMI)
90 */
91static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
92{
93 struct slot *slot = hotplug_slot->private;
94 return (slot->hpc_ops->get_emi_status(slot, value));
95}
96
97/*
98 * sysfs interface for the Electro Mechanical Interlock (EMI)
99 * 1 == locked, 0 == unlocked
100 */
101static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
102{
103 int retval;
104 u8 value;
105
106 retval = get_lock_status(slot, &value);
107 if (retval)
108 goto lock_read_exit;
109 retval = sprintf (buf, "%d\n", value);
110
111lock_read_exit:
112 return retval;
113}
114
115/*
116 * Change the status of the Electro Mechanical Interlock (EMI)
117 * This is a toggle - in addition there must be at least 1 second
118 * in between toggles.
119 */
120static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
121{
122 struct slot *slot = hotplug_slot->private;
123 int retval;
124 u8 value;
125
126 mutex_lock(&slot->ctrl->crit_sect);
127
128 /* has it been >1 sec since our last toggle? */
129 if ((get_seconds() - slot->last_emi_toggle) < 1) {
130 mutex_unlock(&slot->ctrl->crit_sect);
131 return -EINVAL;
132 }
133
134 /* see what our current state is */
135 retval = get_lock_status(hotplug_slot, &value);
136 if (retval || (value == status))
137 goto set_lock_exit;
138
139 slot->hpc_ops->toggle_emi(slot);
140set_lock_exit:
141 mutex_unlock(&slot->ctrl->crit_sect);
142 return 0;
143}
144
145/*
146 * sysfs interface which allows the user to toggle the Electro Mechanical
147 * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
148 */
149static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
150 const char *buf, size_t count)
151{
152 struct slot *slot = hotplug_slot->private;
153 unsigned long llock;
154 u8 lock;
155 int retval = 0;
156
157 llock = simple_strtoul(buf, NULL, 10);
158 lock = (u8)(llock & 0xff);
159
160 switch (lock) {
161 case 0:
162 case 1:
163 retval = set_lock_status(hotplug_slot, lock);
164 break;
165 default:
166 ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
167 lock);
168 retval = -EINVAL;
169 }
170 if (retval)
171 return retval;
172 return count;
173}
174
175static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
176 .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
177 .show = lock_read_file,
178 .store = lock_write_file
179};
180
181/** 88/**
182 * release_slot - free up the memory used by a slot 89 * release_slot - free up the memory used by a slot
183 * @hotplug_slot: slot to free 90 * @hotplug_slot: slot to free
@@ -236,17 +143,6 @@ static int init_slots(struct controller *ctrl)
236 get_attention_status(hotplug_slot, &info->attention_status); 143 get_attention_status(hotplug_slot, &info->attention_status);
237 get_latch_status(hotplug_slot, &info->latch_status); 144 get_latch_status(hotplug_slot, &info->latch_status);
238 get_adapter_status(hotplug_slot, &info->adapter_status); 145 get_adapter_status(hotplug_slot, &info->adapter_status);
239 /* create additional sysfs entries */
240 if (EMI(ctrl)) {
241 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
242 &hotplug_slot_attr_lock.attr);
243 if (retval) {
244 pci_hp_deregister(hotplug_slot);
245 ctrl_err(ctrl, "Cannot create additional sysfs "
246 "entries\n");
247 goto error_info;
248 }
249 }
250 } 146 }
251 147
252 return 0; 148 return 0;
@@ -261,13 +157,8 @@ error:
261static void cleanup_slots(struct controller *ctrl) 157static void cleanup_slots(struct controller *ctrl)
262{ 158{
263 struct slot *slot; 159 struct slot *slot;
264 160 list_for_each_entry(slot, &ctrl->slot_list, slot_list)
265 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
266 if (EMI(ctrl))
267 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
268 &hotplug_slot_attr_lock.attr);
269 pci_hp_deregister(slot->hotplug_slot); 161 pci_hp_deregister(slot->hotplug_slot);
270 }
271} 162}
272 163
273/* 164/*
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 07bd3215114..52813257e5b 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -422,35 +422,6 @@ static int hpc_query_power_fault(struct slot *slot)
422 return !!(slot_status & PCI_EXP_SLTSTA_PFD); 422 return !!(slot_status & PCI_EXP_SLTSTA_PFD);
423} 423}
424 424
425static int hpc_get_emi_status(struct slot *slot, u8 *status)
426{
427 struct controller *ctrl = slot->ctrl;
428 u16 slot_status;
429 int retval;
430
431 retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
432 if (retval) {
433 ctrl_err(ctrl, "Cannot check EMI status\n");
434 return retval;
435 }
436 *status = !!(slot_status & PCI_EXP_SLTSTA_EIS);
437 return retval;
438}
439
440static int hpc_toggle_emi(struct slot *slot)
441{
442 u16 slot_cmd;
443 u16 cmd_mask;
444 int rc;
445
446 slot_cmd = PCI_EXP_SLTCTL_EIC;
447 cmd_mask = PCI_EXP_SLTCTL_EIC;
448 rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
449 slot->last_emi_toggle = get_seconds();
450
451 return rc;
452}
453
454static int hpc_set_attention_status(struct slot *slot, u8 value) 425static int hpc_set_attention_status(struct slot *slot, u8 value)
455{ 426{
456 struct controller *ctrl = slot->ctrl; 427 struct controller *ctrl = slot->ctrl;
@@ -874,8 +845,6 @@ static struct hpc_ops pciehp_hpc_ops = {
874 .get_attention_status = hpc_get_attention_status, 845 .get_attention_status = hpc_get_attention_status,
875 .get_latch_status = hpc_get_latch_status, 846 .get_latch_status = hpc_get_latch_status,
876 .get_adapter_status = hpc_get_adapter_status, 847 .get_adapter_status = hpc_get_adapter_status,
877 .get_emi_status = hpc_get_emi_status,
878 .toggle_emi = hpc_toggle_emi,
879 848
880 .get_max_bus_speed = hpc_get_max_lnk_speed, 849 .get_max_bus_speed = hpc_get_max_lnk_speed,
881 .get_cur_bus_speed = hpc_get_cur_lnk_speed, 850 .get_cur_bus_speed = hpc_get_cur_lnk_speed,
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 20998746518..11936fd0b56 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -66,14 +66,6 @@ enum pcie_link_speed {
66 PCIE_LNK_SPEED_UNKNOWN = 0xFF, 66 PCIE_LNK_SPEED_UNKNOWN = 0xFF,
67}; 67};
68 68
69struct hotplug_slot;
70struct hotplug_slot_attribute {
71 struct attribute attr;
72 ssize_t (*show)(struct hotplug_slot *, char *);
73 ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
74};
75#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr);
76
77/** 69/**
78 * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use 70 * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
79 * @owner: The module owner of this structure 71 * @owner: The module owner of this structure