Commit bd3d99c1 authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Jesse Barnes

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: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 12983077
......@@ -81,7 +81,6 @@ struct slot {
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
unsigned long last_emi_toggle;
struct delayed_work work; /* work for button event */
struct mutex lock;
};
......@@ -203,8 +202,6 @@ struct hpc_ops {
int (*set_attention_status)(struct slot *slot, u8 status);
int (*get_latch_status)(struct slot *slot, u8 *status);
int (*get_adapter_status)(struct slot *slot, u8 *status);
int (*get_emi_status)(struct slot *slot, u8 *status);
int (*toggle_emi)(struct slot *slot);
int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);
......
......@@ -85,99 +85,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
.get_cur_bus_speed = get_cur_bus_speed,
};
/*
* Check the status of the Electro Mechanical Interlock (EMI)
*/
static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
return (slot->hpc_ops->get_emi_status(slot, value));
}
/*
* sysfs interface for the Electro Mechanical Interlock (EMI)
* 1 == locked, 0 == unlocked
*/
static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
{
int retval;
u8 value;
retval = get_lock_status(slot, &value);
if (retval)
goto lock_read_exit;
retval = sprintf (buf, "%d\n", value);
lock_read_exit:
return retval;
}
/*
* Change the status of the Electro Mechanical Interlock (EMI)
* This is a toggle - in addition there must be at least 1 second
* in between toggles.
*/
static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = hotplug_slot->private;
int retval;
u8 value;
mutex_lock(&slot->ctrl->crit_sect);
/* has it been >1 sec since our last toggle? */
if ((get_seconds() - slot->last_emi_toggle) < 1) {
mutex_unlock(&slot->ctrl->crit_sect);
return -EINVAL;
}
/* see what our current state is */
retval = get_lock_status(hotplug_slot, &value);
if (retval || (value == status))
goto set_lock_exit;
slot->hpc_ops->toggle_emi(slot);
set_lock_exit:
mutex_unlock(&slot->ctrl->crit_sect);
return 0;
}
/*
* sysfs interface which allows the user to toggle the Electro Mechanical
* Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
*/
static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
const char *buf, size_t count)
{
struct slot *slot = hotplug_slot->private;
unsigned long llock;
u8 lock;
int retval = 0;
llock = simple_strtoul(buf, NULL, 10);
lock = (u8)(llock & 0xff);
switch (lock) {
case 0:
case 1:
retval = set_lock_status(hotplug_slot, lock);
break;
default:
ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
lock);
retval = -EINVAL;
}
if (retval)
return retval;
return count;
}
static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
.attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
.show = lock_read_file,
.store = lock_write_file
};
/**
* release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free
......@@ -236,17 +143,6 @@ static int init_slots(struct controller *ctrl)
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status);
/* create additional sysfs entries */
if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
if (retval) {
pci_hp_deregister(hotplug_slot);
ctrl_err(ctrl, "Cannot create additional sysfs "
"entries\n");
goto error_info;
}
}
}
return 0;
......@@ -261,13 +157,8 @@ static int init_slots(struct controller *ctrl)
static void cleanup_slots(struct controller *ctrl)
{
struct slot *slot;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (EMI(ctrl))
sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
list_for_each_entry(slot, &ctrl->slot_list, slot_list)
pci_hp_deregister(slot->hotplug_slot);
}
}
/*
......
......@@ -422,35 +422,6 @@ static int hpc_query_power_fault(struct slot *slot)
return !!(slot_status & PCI_EXP_SLTSTA_PFD);
}
static int hpc_get_emi_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
int retval;
retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "Cannot check EMI status\n");
return retval;
}
*status = !!(slot_status & PCI_EXP_SLTSTA_EIS);
return retval;
}
static int hpc_toggle_emi(struct slot *slot)
{
u16 slot_cmd;
u16 cmd_mask;
int rc;
slot_cmd = PCI_EXP_SLTCTL_EIC;
cmd_mask = PCI_EXP_SLTCTL_EIC;
rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
slot->last_emi_toggle = get_seconds();
return rc;
}
static int hpc_set_attention_status(struct slot *slot, u8 value)
{
struct controller *ctrl = slot->ctrl;
......@@ -874,8 +845,6 @@ static struct hpc_ops pciehp_hpc_ops = {
.get_attention_status = hpc_get_attention_status,
.get_latch_status = hpc_get_latch_status,
.get_adapter_status = hpc_get_adapter_status,
.get_emi_status = hpc_get_emi_status,
.toggle_emi = hpc_toggle_emi,
.get_max_bus_speed = hpc_get_max_lnk_speed,
.get_cur_bus_speed = hpc_get_cur_lnk_speed,
......
......@@ -66,14 +66,6 @@ enum pcie_link_speed {
PCIE_LNK_SPEED_UNKNOWN = 0xFF,
};
struct hotplug_slot;
struct hotplug_slot_attribute {
struct attribute attr;
ssize_t (*show)(struct hotplug_slot *, char *);
ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
};
#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr);
/**
* struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
* @owner: The module owner of this structure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment