All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiang Liu <jiang.liu@huawei.com>
To: Yinghai Lu <yinghai@kernel.org>,
	Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>,
	Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>,
	Wen Congyang <wency@cn.fujitsu.com>,
	Tang Chen <tangchen@cn.fujitsu.com>,
	Taku Izumi <izumi.taku@jp.fujitsu.com>
Cc: Jiang Liu <jiang.liu@huawei.com>, Tony Luck <tony.luck@intel.com>,
	Huang Ying <ying.huang@intel.com>,
	Bob Moore <robert.moore@intel.com>, Len Brown <lenb@kernel.org>,
	"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-pci@vger.kernel.org, Jiang Liu <liuj97@gmail.com>
Subject: [RFC PATCH v2 15/16] ACPIHP: implement ACPI hotplug sysfs interfaces
Date: Sat, 4 Aug 2012 20:14:02 +0800	[thread overview]
Message-ID: <1344082443-4608-16-git-send-email-jiang.liu@huawei.com> (raw)
In-Reply-To: <1344082443-4608-1-git-send-email-jiang.liu@huawei.com>

From: Jiang Liu <jiang.liu@huawei.com>

This patch implements ACPI hotplug sysfs interfaces for system device hotplug.

enable: (It should be named 'power', but that causes name conflicts.)
echo 1 > enable: power on the hotplug slot.
echo 0 > enable: power off the hotplug slot.

connect:
echo 1 > connect: create ACPI devices for system devices connecting to a slot
echo 0 > connect: remove ACPI devices for system devices connecting to a slot

configure:
echo 1 > configure: add system devices into running system
echo 0 > configure: remove system devices from running system

dependency:
cat dependency: show slots have dependency on this slot if the slot is powered,
		otherwise show slots this slot depends on.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
---
 drivers/acpi/hotplug/Makefile     |    1 +
 drivers/acpi/hotplug/acpihp_drv.h |    3 +
 drivers/acpi/hotplug/drv_main.c   |    6 +
 drivers/acpi/hotplug/sysfs.c      |  246 +++++++++++++++++++++++++++++++++++++
 4 files changed, 256 insertions(+)
 create mode 100644 drivers/acpi/hotplug/sysfs.c

diff --git a/drivers/acpi/hotplug/Makefile b/drivers/acpi/hotplug/Makefile
index 9383320..88c7595 100644
--- a/drivers/acpi/hotplug/Makefile
+++ b/drivers/acpi/hotplug/Makefile
@@ -15,3 +15,4 @@ acpihp_drv-y					+= dependency.o
 acpihp_drv-y					+= cancel.o
 acpihp_drv-y					+= configure.o
 acpihp_drv-y					+= state_machine.o
+acpihp_drv-y					+= sysfs.o
diff --git a/drivers/acpi/hotplug/acpihp_drv.h b/drivers/acpi/hotplug/acpihp_drv.h
index 3b6dbdd..d339f9a 100644
--- a/drivers/acpi/hotplug/acpihp_drv.h
+++ b/drivers/acpi/hotplug/acpihp_drv.h
@@ -101,4 +101,7 @@ int acpihp_drv_unconfigure(struct list_head *list);
 /* The heart of the ACPI system device hotplug driver */
 int acpihp_drv_change_state(struct acpihp_slot *slot, enum acpihp_drv_cmd cmd);
 
+int acpihp_drv_create_sysfs(struct acpihp_slot *slot);
+void acpihp_drv_remove_sysfs(struct acpihp_slot *slot);
+
 #endif	/* __ACPIHP_DRV_H__ */
diff --git a/drivers/acpi/hotplug/drv_main.c b/drivers/acpi/hotplug/drv_main.c
index 538772d..9858fdd 100644
--- a/drivers/acpi/hotplug/drv_main.c
+++ b/drivers/acpi/hotplug/drv_main.c
@@ -280,6 +280,11 @@ static int acpihp_drv_slot_add(struct device *dev, struct class_interface *intf)
 		return -ENOMEM;
 	}
 
+	if (acpihp_drv_create_sysfs(slot))
+		ACPIHP_DEBUG("fails to create sysfs interfaces for slot %s, "
+			     "some function will not be available to user.\n",
+			     slot->name);
+
 	ACPIHP_INFO("found hotplug slot %s.\n", slot->full_path);
 
 	return 0;
@@ -294,6 +299,7 @@ static void acpihp_drv_intf_remove(struct device *dev,
 
 	ACPIHP_INFO("remove hotplug slot %s.\n", slot->full_path);
 
+	acpihp_drv_remove_sysfs(slot);
 	acpihp_drv_uninstall_handler(slot);
 	acpihp_drv_remove_devices(slot);
 	acpihp_slot_detach_drv_data(slot, intf, (void **)&drv_data);
diff --git a/drivers/acpi/hotplug/sysfs.c b/drivers/acpi/hotplug/sysfs.c
new file mode 100644
index 0000000..62c1892
--- /dev/null
+++ b/drivers/acpi/hotplug/sysfs.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2011 Huawei Tech. Co., Ltd.
+ * Copyright (C) 2011 Jiang Liu <jiang.liu@huawei.com>
+ * Copyright (C) 2011 Hanjun Guo <guohanjun@huawei.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <acpi/acpi_hotplug.h>
+#include "acpihp_drv.h"
+
+static ssize_t acpihp_drv_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count,
+		enum acpihp_drv_cmd op_set, enum acpihp_drv_cmd op_clr)
+{
+	unsigned long val;
+	ssize_t result = kstrtoul(buf, 0, &val);
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	if (result < 0)
+		return result;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (val)
+		result = acpihp_drv_change_state(slot, op_set);
+	else
+		result = acpihp_drv_change_state(slot, op_clr);
+
+	return result < 0 ? result : count;
+}
+
+static inline ssize_t acpihp_drv_print_bool(char *page, bool flag)
+{
+	return snprintf(page, PAGE_SIZE, flag ? "1\n" : "0\n");
+}
+
+static ssize_t acpihp_drv_power_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_POWERED:
+	case ACPIHP_SLOT_STATE_CONNECTED:
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_POWERING_ON:
+	case ACPIHP_SLOT_STATE_POWERING_OFF:
+	case ACPIHP_SLOT_STATE_CONNECTING:
+	case ACPIHP_SLOT_STATE_DISCONNECTING:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_power_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_POWERON, ACPIHP_DRV_CMD_POWEROFF);
+}
+
+/* It should be named as 'power', but that will cause name conflics. */
+DEVICE_ATTR(enable, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_power_show, &acpihp_drv_power_store);
+
+static ssize_t acpihp_drv_connect_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_CONNECTED:
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_CONNECTING:
+	case ACPIHP_SLOT_STATE_DISCONNECTING:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_connect_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_CONNECT, ACPIHP_DRV_CMD_DISCONNECT);
+}
+
+DEVICE_ATTR(connect, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_connect_show, &acpihp_drv_connect_store);
+
+static ssize_t acpihp_drv_configure_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_configure_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_CONFIGURE, ACPIHP_DRV_CMD_UNCONFIGURE);
+}
+
+DEVICE_ATTR(configure, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_configure_show, &acpihp_drv_configure_store);
+
+static ssize_t acpihp_drv_dependency_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	int ret;
+	char *p, *end;
+	struct list_head list;
+	enum acpihp_drv_cmd cmd;
+	struct acpihp_slot_dependency *dep;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	INIT_LIST_HEAD(&list);
+	mutex_lock(&state_machine_mutex);
+	cmd = acpihp_slot_powered(slot) ? ACPIHP_DRV_CMD_POWEROFF :
+					  ACPIHP_DRV_CMD_POWERON;
+	ret = acpihp_drv_generate_dependency_list(slot, &list, cmd);
+	if (ret) {
+		ret = -ENXIO;
+	} else {
+		p = page;
+		end = page + PAGE_SIZE;
+
+		list_for_each_entry(dep, &list, node) {
+			if (dep->slot == slot)
+				continue;
+			if (p + strlen(dep->slot->full_path) + 2 >= end)
+				break;
+			p += snprintf(p, end - p, "%s\n", dep->slot->full_path);
+		}
+
+		acpihp_drv_destroy_dependency_list(&list);
+		ret = p - page;
+	}
+	mutex_unlock(&state_machine_mutex);
+
+	return ret;
+}
+
+static DEVICE_ATTR(dependency, S_IRUSR | S_IWUSR,
+		   &acpihp_drv_dependency_show, NULL);
+
+int acpihp_drv_create_sysfs(struct acpihp_slot *slot)
+{
+	int retval;
+	struct device *dev = &slot->dev;
+
+	retval = device_create_file(dev, &dev_attr_enable);
+	if (retval)
+		goto out;
+	retval = device_create_file(dev, &dev_attr_connect);
+	if (retval)
+		goto out1;
+	retval = device_create_file(dev, &dev_attr_configure);
+	if (retval)
+		goto out2;
+	retval = device_create_file(dev, &dev_attr_dependency);
+	if (retval)
+		goto out3;
+
+	return 0;
+
+out3:
+	device_remove_file(dev, &dev_attr_configure);
+out2:
+	device_remove_file(dev, &dev_attr_connect);
+out1:
+	device_remove_file(dev, &dev_attr_enable);
+out:
+	ACPIHP_DEBUG("fails to create sysfs interfaces for slot %s.\n",
+		     slot->name);
+	return retval;
+}
+
+void acpihp_drv_remove_sysfs(struct acpihp_slot *slot)
+{
+	struct device *dev = &slot->dev;
+
+	device_remove_file(dev, &dev_attr_dependency);
+	device_remove_file(dev, &dev_attr_configure);
+	device_remove_file(dev, &dev_attr_connect);
+	device_remove_file(dev, &dev_attr_enable);
+}
-- 
1.7.9.5



WARNING: multiple messages have this Message-ID (diff)
From: Jiang Liu <jiang.liu@huawei.com>
To: Yinghai Lu <yinghai@kernel.org>,
	Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>,
	Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>,
	Wen Congyang <wency@cn.fujitsu.com>,
	Tang Chen <tangchen@cn.fujitsu.com>,
	Taku Izumi <izumi.taku@jp.fujitsu.com>
Cc: Jiang Liu <jiang.liu@huawei.com>, Tony Luck <tony.luck@intel.com>,
	Huang Ying <ying.huang@intel.com>,
	Bob Moore <robert.moore@intel.com>, Len Brown <lenb@kernel.org>,
	"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	<linux-kernel@vger.kernel.org>, <linux-acpi@vger.kernel.org>,
	<linux-pci@vger.kernel.org>, Jiang Liu <liuj97@gmail.com>
Subject: [RFC PATCH v2 15/16] ACPIHP: implement ACPI hotplug sysfs interfaces
Date: Sat, 4 Aug 2012 20:14:02 +0800	[thread overview]
Message-ID: <1344082443-4608-16-git-send-email-jiang.liu@huawei.com> (raw)
In-Reply-To: <1344082443-4608-1-git-send-email-jiang.liu@huawei.com>

From: Jiang Liu <jiang.liu@huawei.com>

This patch implements ACPI hotplug sysfs interfaces for system device hotplug.

enable: (It should be named 'power', but that causes name conflicts.)
echo 1 > enable: power on the hotplug slot.
echo 0 > enable: power off the hotplug slot.

connect:
echo 1 > connect: create ACPI devices for system devices connecting to a slot
echo 0 > connect: remove ACPI devices for system devices connecting to a slot

configure:
echo 1 > configure: add system devices into running system
echo 0 > configure: remove system devices from running system

dependency:
cat dependency: show slots have dependency on this slot if the slot is powered,
		otherwise show slots this slot depends on.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
---
 drivers/acpi/hotplug/Makefile     |    1 +
 drivers/acpi/hotplug/acpihp_drv.h |    3 +
 drivers/acpi/hotplug/drv_main.c   |    6 +
 drivers/acpi/hotplug/sysfs.c      |  246 +++++++++++++++++++++++++++++++++++++
 4 files changed, 256 insertions(+)
 create mode 100644 drivers/acpi/hotplug/sysfs.c

diff --git a/drivers/acpi/hotplug/Makefile b/drivers/acpi/hotplug/Makefile
index 9383320..88c7595 100644
--- a/drivers/acpi/hotplug/Makefile
+++ b/drivers/acpi/hotplug/Makefile
@@ -15,3 +15,4 @@ acpihp_drv-y					+= dependency.o
 acpihp_drv-y					+= cancel.o
 acpihp_drv-y					+= configure.o
 acpihp_drv-y					+= state_machine.o
+acpihp_drv-y					+= sysfs.o
diff --git a/drivers/acpi/hotplug/acpihp_drv.h b/drivers/acpi/hotplug/acpihp_drv.h
index 3b6dbdd..d339f9a 100644
--- a/drivers/acpi/hotplug/acpihp_drv.h
+++ b/drivers/acpi/hotplug/acpihp_drv.h
@@ -101,4 +101,7 @@ int acpihp_drv_unconfigure(struct list_head *list);
 /* The heart of the ACPI system device hotplug driver */
 int acpihp_drv_change_state(struct acpihp_slot *slot, enum acpihp_drv_cmd cmd);
 
+int acpihp_drv_create_sysfs(struct acpihp_slot *slot);
+void acpihp_drv_remove_sysfs(struct acpihp_slot *slot);
+
 #endif	/* __ACPIHP_DRV_H__ */
diff --git a/drivers/acpi/hotplug/drv_main.c b/drivers/acpi/hotplug/drv_main.c
index 538772d..9858fdd 100644
--- a/drivers/acpi/hotplug/drv_main.c
+++ b/drivers/acpi/hotplug/drv_main.c
@@ -280,6 +280,11 @@ static int acpihp_drv_slot_add(struct device *dev, struct class_interface *intf)
 		return -ENOMEM;
 	}
 
+	if (acpihp_drv_create_sysfs(slot))
+		ACPIHP_DEBUG("fails to create sysfs interfaces for slot %s, "
+			     "some function will not be available to user.\n",
+			     slot->name);
+
 	ACPIHP_INFO("found hotplug slot %s.\n", slot->full_path);
 
 	return 0;
@@ -294,6 +299,7 @@ static void acpihp_drv_intf_remove(struct device *dev,
 
 	ACPIHP_INFO("remove hotplug slot %s.\n", slot->full_path);
 
+	acpihp_drv_remove_sysfs(slot);
 	acpihp_drv_uninstall_handler(slot);
 	acpihp_drv_remove_devices(slot);
 	acpihp_slot_detach_drv_data(slot, intf, (void **)&drv_data);
diff --git a/drivers/acpi/hotplug/sysfs.c b/drivers/acpi/hotplug/sysfs.c
new file mode 100644
index 0000000..62c1892
--- /dev/null
+++ b/drivers/acpi/hotplug/sysfs.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2011 Huawei Tech. Co., Ltd.
+ * Copyright (C) 2011 Jiang Liu <jiang.liu@huawei.com>
+ * Copyright (C) 2011 Hanjun Guo <guohanjun@huawei.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <acpi/acpi_hotplug.h>
+#include "acpihp_drv.h"
+
+static ssize_t acpihp_drv_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count,
+		enum acpihp_drv_cmd op_set, enum acpihp_drv_cmd op_clr)
+{
+	unsigned long val;
+	ssize_t result = kstrtoul(buf, 0, &val);
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	if (result < 0)
+		return result;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (val)
+		result = acpihp_drv_change_state(slot, op_set);
+	else
+		result = acpihp_drv_change_state(slot, op_clr);
+
+	return result < 0 ? result : count;
+}
+
+static inline ssize_t acpihp_drv_print_bool(char *page, bool flag)
+{
+	return snprintf(page, PAGE_SIZE, flag ? "1\n" : "0\n");
+}
+
+static ssize_t acpihp_drv_power_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_POWERED:
+	case ACPIHP_SLOT_STATE_CONNECTED:
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_POWERING_ON:
+	case ACPIHP_SLOT_STATE_POWERING_OFF:
+	case ACPIHP_SLOT_STATE_CONNECTING:
+	case ACPIHP_SLOT_STATE_DISCONNECTING:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_power_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_POWERON, ACPIHP_DRV_CMD_POWEROFF);
+}
+
+/* It should be named as 'power', but that will cause name conflics. */
+DEVICE_ATTR(enable, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_power_show, &acpihp_drv_power_store);
+
+static ssize_t acpihp_drv_connect_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_CONNECTED:
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_CONNECTING:
+	case ACPIHP_SLOT_STATE_DISCONNECTING:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_connect_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_CONNECT, ACPIHP_DRV_CMD_DISCONNECT);
+}
+
+DEVICE_ATTR(connect, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_connect_show, &acpihp_drv_connect_store);
+
+static ssize_t acpihp_drv_configure_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	bool flag;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	acpihp_drv_update_slot_state(slot);
+	mutex_lock(&slot->slot_mutex);
+	switch (slot->state) {
+	case ACPIHP_SLOT_STATE_CONFIGURED:
+	case ACPIHP_SLOT_STATE_CONFIGURING:
+	case ACPIHP_SLOT_STATE_UNCONFIGURING:
+		flag = true;
+		break;
+	default:
+		flag = false;
+		break;
+	}
+	mutex_unlock(&slot->slot_mutex);
+
+	return acpihp_drv_print_bool(page, flag);
+}
+
+static ssize_t acpihp_drv_configure_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return acpihp_drv_store(dev, attr, buf, count,
+			ACPIHP_DRV_CMD_CONFIGURE, ACPIHP_DRV_CMD_UNCONFIGURE);
+}
+
+DEVICE_ATTR(configure, S_IRUSR | S_IWUSR,
+	    &acpihp_drv_configure_show, &acpihp_drv_configure_store);
+
+static ssize_t acpihp_drv_dependency_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	int ret;
+	char *p, *end;
+	struct list_head list;
+	enum acpihp_drv_cmd cmd;
+	struct acpihp_slot_dependency *dep;
+	struct acpihp_slot *slot = container_of(dev, struct acpihp_slot, dev);
+
+	INIT_LIST_HEAD(&list);
+	mutex_lock(&state_machine_mutex);
+	cmd = acpihp_slot_powered(slot) ? ACPIHP_DRV_CMD_POWEROFF :
+					  ACPIHP_DRV_CMD_POWERON;
+	ret = acpihp_drv_generate_dependency_list(slot, &list, cmd);
+	if (ret) {
+		ret = -ENXIO;
+	} else {
+		p = page;
+		end = page + PAGE_SIZE;
+
+		list_for_each_entry(dep, &list, node) {
+			if (dep->slot == slot)
+				continue;
+			if (p + strlen(dep->slot->full_path) + 2 >= end)
+				break;
+			p += snprintf(p, end - p, "%s\n", dep->slot->full_path);
+		}
+
+		acpihp_drv_destroy_dependency_list(&list);
+		ret = p - page;
+	}
+	mutex_unlock(&state_machine_mutex);
+
+	return ret;
+}
+
+static DEVICE_ATTR(dependency, S_IRUSR | S_IWUSR,
+		   &acpihp_drv_dependency_show, NULL);
+
+int acpihp_drv_create_sysfs(struct acpihp_slot *slot)
+{
+	int retval;
+	struct device *dev = &slot->dev;
+
+	retval = device_create_file(dev, &dev_attr_enable);
+	if (retval)
+		goto out;
+	retval = device_create_file(dev, &dev_attr_connect);
+	if (retval)
+		goto out1;
+	retval = device_create_file(dev, &dev_attr_configure);
+	if (retval)
+		goto out2;
+	retval = device_create_file(dev, &dev_attr_dependency);
+	if (retval)
+		goto out3;
+
+	return 0;
+
+out3:
+	device_remove_file(dev, &dev_attr_configure);
+out2:
+	device_remove_file(dev, &dev_attr_connect);
+out1:
+	device_remove_file(dev, &dev_attr_enable);
+out:
+	ACPIHP_DEBUG("fails to create sysfs interfaces for slot %s.\n",
+		     slot->name);
+	return retval;
+}
+
+void acpihp_drv_remove_sysfs(struct acpihp_slot *slot)
+{
+	struct device *dev = &slot->dev;
+
+	device_remove_file(dev, &dev_attr_dependency);
+	device_remove_file(dev, &dev_attr_configure);
+	device_remove_file(dev, &dev_attr_connect);
+	device_remove_file(dev, &dev_attr_enable);
+}
-- 
1.7.9.5



  parent reply	other threads:[~2012-08-04 12:15 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-04 12:13 [RFC PATCH v2 00/16] ACPI based system device hotplug framework Jiang Liu
2012-08-04 12:13 ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 01/16] ACPIHP: introduce a framework for ACPI based system device hotplug Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 02/16] ACPIHP: ACPI system device hotplug slot enumerator Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 03/16] ACPIHP: detect ACPI hotplug slots by checking ACPI _EJ0 method Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 04/16] ACPI: introduce interfaces to manage ACPI device reference count Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 05/16] ACPIHP: scan and walk ACPI devices connecting to an ACPI hotplug slot Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 06/16] ACPIHP: group devices connecting to a hotplug slot according to device types Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 07/16] ACPIHP: add callbacks into acpi_device_ops to support new hotplug framework Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 08/16] ACPIHP: provide interfaces to associate driver specific data to hotplug slots Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 09/16] ACPIHP: implement utility functions to support system device hotplug Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 10/16] ACPIHP: system device hotplug driver skeleton Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-09  7:12   ` Tang Chen
2012-08-09  7:40     ` Jiang Liu
2012-08-09  7:40       ` Jiang Liu
2012-08-09  8:41       ` Tang Chen
2012-08-09  9:36         ` Jiang Liu
2012-08-09  9:36           ` Jiang Liu
2012-08-10  4:39           ` Tang Chen
2012-08-04 12:13 ` [RFC PATCH v2 11/16] ACPIHP: analyse dependences among ACPI system device hotplug slots Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:13 ` [RFC PATCH v2 12/16] ACPIHP: cancel inprogress ACPI system device hotplug operations Jiang Liu
2012-08-04 12:13   ` Jiang Liu
2012-08-04 12:14 ` [RFC PATCH v2 13/16] ACPIHP: configure/unconfigure system devices connecting to a hotplug slot Jiang Liu
2012-08-04 12:14   ` Jiang Liu
2012-08-04 12:14 ` [RFC PATCH v2 14/16] ACPIHP: implement the state machine for ACPI hotplug slots Jiang Liu
2012-08-04 12:14   ` Jiang Liu
2012-08-04 12:14 ` Jiang Liu [this message]
2012-08-04 12:14   ` [RFC PATCH v2 15/16] ACPIHP: implement ACPI hotplug sysfs interfaces Jiang Liu
2012-08-04 12:14 ` [RFC PATCH v2 16/16] ACPIHP: enhance ACPI container driver to support new hotplug framework Jiang Liu
2012-08-04 12:14   ` Jiang Liu
2012-08-07 23:38 ` [RFC PATCH v2 00/16] ACPI based system device " Toshi Kani
2012-08-08 15:44   ` Jiang Liu
2012-08-08 16:27     ` Bjorn Helgaas
2012-08-09 15:24       ` Jiang Liu
2012-08-08 21:05     ` Toshi Kani

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1344082443-4608-16-git-send-email-jiang.liu@huawei.com \
    --to=jiang.liu@huawei.com \
    --cc=bhelgaas@google.com \
    --cc=isimatu.yasuaki@jp.fujitsu.com \
    --cc=izumi.taku@jp.fujitsu.com \
    --cc=kaneshige.kenji@jp.fujitsu.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=liuj97@gmail.com \
    --cc=robert.moore@intel.com \
    --cc=srivatsa.bhat@linux.vnet.ibm.com \
    --cc=tangchen@cn.fujitsu.com \
    --cc=tony.luck@intel.com \
    --cc=wency@cn.fujitsu.com \
    --cc=ying.huang@intel.com \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.