Driver core patches for 3.12-rc1
Here's the big driver core pull request for 3.12-rc1. Lots of tiny changes here fixing up the way sysfs attributes are created, to try to make drivers simpler, and fix a whole class race conditions with creations of device attributes after the device was announced to userspace. All the various pieces are acked by the different subsystem maintainers. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.21 (GNU/Linux) iEYEABECAAYFAlIlIPcACgkQMUfUDdst+ynUMwCaAnITsxyDXYQ4DqEsz8EcOtMk 718AoLrgnUZs3B+70AT34DVktg4HSThk =USl9 -----END PGP SIGNATURE----- Merge tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core patches from Greg KH: "Here's the big driver core pull request for 3.12-rc1. Lots of tiny changes here fixing up the way sysfs attributes are created, to try to make drivers simpler, and fix a whole class race conditions with creations of device attributes after the device was announced to userspace. All the various pieces are acked by the different subsystem maintainers" * tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (119 commits) firmware loader: fix pending_fw_head list corruption drivers/base/memory.c: introduce help macro to_memory_block dynamic debug: line queries failing due to uninitialized local variable sysfs: sysfs_create_groups returns a value. debugfs: provide debugfs_create_x64() when disabled rbd: convert bus code to use bus_groups firmware: dcdbas: use binary attribute groups sysfs: add sysfs_create/remove_groups for when SYSFS is not enabled driver core: add #include <linux/sysfs.h> to core files. HID: convert bus code to use dev_groups Input: serio: convert bus code to use drv_groups Input: gameport: convert bus code to use drv_groups driver core: firmware: use __ATTR_RW() driver core: core: use DEVICE_ATTR_RO driver core: bus: use DRIVER_ATTR_WO() driver core: create write-only attribute macros for devices and drivers sysfs: create __ATTR_WO() driver-core: platform: convert bus code to use dev_groups workqueue: convert bus code to use dev_groups MEI: convert bus code to use dev_groups ...
This commit is contained in:
commit
542a086ac7
|
@ -182,8 +182,8 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H
|
|||
프로젝트를 봐야 한다.
|
||||
http://kernelnewbies.org
|
||||
그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저
|
||||
아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할수있는 도움이
|
||||
될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할수 있는 IRC 채널도
|
||||
아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할 수 있는 도움이
|
||||
될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할 수 있는 IRC 채널도
|
||||
가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다.
|
||||
|
||||
웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들
|
||||
|
@ -245,7 +245,7 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H
|
|||
것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가
|
||||
드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은
|
||||
회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해
|
||||
생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
|
||||
생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
|
||||
배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은
|
||||
공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다.
|
||||
- 새로운 -rc는 Linus가 현재 git tree가 테스트 하기에 충분히 안정된 상태에
|
||||
|
@ -455,7 +455,7 @@ bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메
|
|||
- 의견
|
||||
- 변경을 위한 요구
|
||||
- 당위성을 위한 요구
|
||||
- 고요
|
||||
- 침묵
|
||||
|
||||
기억하라. 이것들은 여러분의 패치가 커널로 들어가기 위한 과정이다. 여러분의
|
||||
패치들은 비판과 다른 의견을 받을 수 있고 그것들을 기술적인 레벨로 평가하고
|
||||
|
@ -472,7 +472,7 @@ bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메
|
|||
가능한한 가장 좋은 기술적인 해답을 찾고 있는 커뮤니티에서는 항상
|
||||
어떤 패치가 얼마나 좋은지에 관하여 다른 의견들이 있을 수 있다. 여러분은
|
||||
협조적이어야 하고 기꺼이 여러분의 생각을 커널 내에 맞추어야 한다. 아니면
|
||||
적어도 여러분의 것이 가치있다는 것을 중명하여야 한다. 잘못된 것도 여러분이
|
||||
적어도 여러분의 것이 가치있다는 것을 증명하여야 한다. 잘못된 것도 여러분이
|
||||
올바른 방향의 해결책으로 이끌어갈 의지가 있다면 받아들여질 것이라는 점을
|
||||
기억하라.
|
||||
|
||||
|
@ -488,21 +488,21 @@ bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메
|
|||
커널 커뮤니티는 가장 전통적인 회사의 개발 환경과는 다르다. 여기에 여러분들의
|
||||
문제를 피하기 위한 목록이 있다.
|
||||
여러분들이 제안한 변경들에 관하여 말할 때 좋은 것들 :
|
||||
- "이것은 여러 문제들을 해겹합니다."
|
||||
- "이것은 2000 라인의 코드를 제거합니다."
|
||||
- "이것은 여러 문제들을 해결합니다."
|
||||
- "이것은 2000 라인의 코드를 줄입니다."
|
||||
- "이것은 내가 말하려는 것에 관해 설명하는 패치입니다."
|
||||
- "나는 5개의 다른 아키텍쳐에서 그것을 테스트했슴으로..."
|
||||
- "여기에 일련의 작은 패치들이 있슴음로..."
|
||||
- "이것은 일반적인 머신에서 성능을 향상시킴으로..."
|
||||
- "나는 5개의 다른 아키텍쳐에서 그것을 테스트 했으므로..."
|
||||
- "여기에 일련의 작은 패치들이 있으므로..."
|
||||
- "이것은 일반적인 머신에서 성능을 향상함으로..."
|
||||
|
||||
여러분들이 말할 때 피해야 할 좋지 않은 것들 :
|
||||
- "우리를 그것을 AIT/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀립없다..."
|
||||
- "우리는 그것을 AIX/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀림없다..."
|
||||
- "나는 20년동안 이것을 해왔다. 그러므로..."
|
||||
- "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다."
|
||||
- "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다."
|
||||
- "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다."
|
||||
- "나는 6달동안 이것을 했으니..."
|
||||
- "여기에 5000라인 짜리 패치가 있으니..."
|
||||
- "여기에 5000 라인 짜리 패치가 있으니..."
|
||||
- "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..."
|
||||
- "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다."
|
||||
|
||||
|
@ -574,6 +574,7 @@ Pat이라는 이름을 가진 여자가 있을 수도 있는 것이다. 리눅
|
|||
또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는
|
||||
패치들은 받아들여지지 않을 것이라는 점을 유념하라.
|
||||
|
||||
|
||||
변경을 정당화해라
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -106,12 +106,12 @@ Greg Kroah-Hartman <greg@kroah.com>
|
|||
---------------------------------
|
||||
|
||||
리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고
|
||||
유지보수하려고 하는 사름들과 이 문제를 논의하게 되면 훨씬 더
|
||||
유지보수하려고 하는 사람들과 이 문제를 논의하게 되면 훨씬 더
|
||||
"논란의 여지가 많은" 주제가 될 것이다.
|
||||
|
||||
리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코
|
||||
느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를
|
||||
발견하거나 무엇인가 할수 있는 더 좋은 방법을 찾게 되었다고 하자.
|
||||
발견하거나 무엇인가 할 수 있는 더 좋은 방법을 찾게 되었다고 하자.
|
||||
그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을
|
||||
수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고,
|
||||
구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다.
|
||||
|
@ -174,7 +174,7 @@ GPL을 따르는 배포 드라이버에 관해 얘기하고 있다는 것을 상
|
|||
동작하는 것을 보장한다.
|
||||
|
||||
메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다.
|
||||
- 관리의 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
|
||||
- 관리에 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
|
||||
- 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다.
|
||||
- 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다.
|
||||
- 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다.
|
||||
|
|
|
@ -2064,8 +2064,7 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support.
|
||||
initially work for you.
|
||||
|
||||
config ATAGS_PROC
|
||||
bool "Export atags in procfs"
|
||||
|
|
|
@ -565,9 +565,9 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
initially work for you. As of this writing the exact hardware
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "kernel crash dumps"
|
||||
|
|
|
@ -2305,9 +2305,9 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
initially work for you. As of this writing the exact hardware
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "Kernel crash dumps"
|
||||
|
|
|
@ -1335,8 +1335,9 @@ static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
|
||||
|
||||
static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
|
||||
static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct vpe *vpe = get_vpe(tclimit);
|
||||
|
@ -1344,7 +1345,7 @@ static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
|
|||
return sprintf(buf, "%d\n", vpe->ntcs);
|
||||
}
|
||||
|
||||
static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct vpe *vpe = get_vpe(tclimit);
|
||||
|
@ -1365,12 +1366,14 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
|
|||
out_einval:
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_RW(ntcs);
|
||||
|
||||
static struct device_attribute vpe_class_attributes[] = {
|
||||
__ATTR(kill, S_IWUSR, NULL, store_kill),
|
||||
__ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs),
|
||||
{}
|
||||
static struct attribute vpe_attrs[] = {
|
||||
&dev_attr_kill.attr,
|
||||
&dev_attr_ntcs.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(vpe);
|
||||
|
||||
static void vpe_device_release(struct device *cd)
|
||||
{
|
||||
|
@ -1381,7 +1384,7 @@ struct class vpe_class = {
|
|||
.name = "vpe",
|
||||
.owner = THIS_MODULE,
|
||||
.dev_release = vpe_device_release,
|
||||
.dev_attrs = vpe_class_attributes,
|
||||
.dev_groups = vpe_groups,
|
||||
};
|
||||
|
||||
struct device vpe_device;
|
||||
|
|
|
@ -369,9 +369,9 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
initially work for you. As of this writing the exact hardware
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "Build a kdump crash kernel"
|
||||
|
|
|
@ -643,9 +643,9 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
initially work for you. As of this writing the exact hardware
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "kernel crash dumps (EXPERIMENTAL)"
|
||||
|
|
|
@ -89,9 +89,6 @@ static inline const struct cpumask *cpumask_of_node(int node)
|
|||
#define topology_core_id(cpu) (cpu)
|
||||
#define topology_core_cpumask(cpu) ((void)(cpu), cpu_online_mask)
|
||||
#define topology_thread_cpumask(cpu) cpumask_of(cpu)
|
||||
|
||||
/* indicates that pointers to the topology struct cpumask maps are valid */
|
||||
#define arch_provides_topology_pointers yes
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_TILE_TOPOLOGY_H */
|
||||
|
|
|
@ -1628,9 +1628,9 @@ config KEXEC
|
|||
|
||||
It is an ongoing process to be certain the hardware in a machine
|
||||
is properly shutdown, so do not be surprised if this code does not
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support. As of this writing the exact hardware interface is
|
||||
strongly in flux, so no good recommendation can be made.
|
||||
initially work for you. As of this writing the exact hardware
|
||||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "kernel crash dumps"
|
||||
|
|
|
@ -124,9 +124,6 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);
|
|||
#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
|
||||
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
|
||||
#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
|
||||
|
||||
/* indicates that pointers to the topology cpumask_t maps are valid */
|
||||
#define arch_provides_topology_pointers yes
|
||||
#endif
|
||||
|
||||
static inline void arch_fix_phys_package_id(int num, u32 slot)
|
||||
|
|
|
@ -51,20 +51,14 @@ static ssize_t show_yoffset(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
|
||||
|
||||
static ssize_t show_image(struct file *file, struct kobject *kobj,
|
||||
static ssize_t image_read(struct file *file, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
memcpy(buf, attr->private + off, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute image_attr = {
|
||||
.attr = {
|
||||
.name = "image",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.read = show_image,
|
||||
};
|
||||
static BIN_ATTR_RO(image, 0); /* size gets filled in later */
|
||||
|
||||
static struct attribute *bgrt_attributes[] = {
|
||||
&dev_attr_version.attr,
|
||||
|
@ -75,8 +69,14 @@ static struct attribute *bgrt_attributes[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute *bgrt_bin_attributes[] = {
|
||||
&bin_attr_image,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group bgrt_attribute_group = {
|
||||
.attrs = bgrt_attributes,
|
||||
.bin_attrs = bgrt_bin_attributes,
|
||||
};
|
||||
|
||||
static int __init bgrt_init(void)
|
||||
|
@ -86,9 +86,8 @@ static int __init bgrt_init(void)
|
|||
if (!bgrt_image)
|
||||
return -ENODEV;
|
||||
|
||||
sysfs_bin_attr_init(&image_attr);
|
||||
image_attr.private = bgrt_image;
|
||||
image_attr.size = bgrt_image_size;
|
||||
bin_attr_image.private = bgrt_image;
|
||||
bin_attr_image.size = bgrt_image_size;
|
||||
|
||||
bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
|
||||
if (!bgrt_kobj)
|
||||
|
@ -98,14 +97,8 @@ static int __init bgrt_init(void)
|
|||
if (ret)
|
||||
goto out_kobject;
|
||||
|
||||
ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
|
||||
if (ret)
|
||||
goto out_group;
|
||||
|
||||
return 0;
|
||||
|
||||
out_group:
|
||||
sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
|
||||
out_kobject:
|
||||
kobject_put(bgrt_kobj);
|
||||
return ret;
|
||||
|
|
|
@ -119,6 +119,16 @@ static inline int driver_match_device(struct device_driver *drv,
|
|||
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
|
||||
}
|
||||
|
||||
extern int driver_add_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups);
|
||||
extern void driver_remove_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups);
|
||||
|
||||
extern int device_add_groups(struct device *dev,
|
||||
const struct attribute_group **groups);
|
||||
extern void device_remove_groups(struct device *dev,
|
||||
const struct attribute_group **groups);
|
||||
|
||||
extern char *make_class_name(const char *name, struct kobject *kobj);
|
||||
|
||||
extern int devres_release_all(struct device *dev);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
||||
|
@ -165,8 +166,8 @@ static const struct kset_uevent_ops bus_uevent_ops = {
|
|||
static struct kset *bus_kset;
|
||||
|
||||
/* Manually detach a device from its associated driver. */
|
||||
static ssize_t driver_unbind(struct device_driver *drv,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t unbind_store(struct device_driver *drv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct bus_type *bus = bus_get(drv->bus);
|
||||
struct device *dev;
|
||||
|
@ -185,15 +186,15 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
|||
bus_put(bus);
|
||||
return err;
|
||||
}
|
||||
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
||||
static DRIVER_ATTR_WO(unbind);
|
||||
|
||||
/*
|
||||
* Manually attach a device to a driver.
|
||||
* Note: the driver must want to bind to the device,
|
||||
* it is not possible to override the driver's id table.
|
||||
*/
|
||||
static ssize_t driver_bind(struct device_driver *drv,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t bind_store(struct device_driver *drv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct bus_type *bus = bus_get(drv->bus);
|
||||
struct device *dev;
|
||||
|
@ -221,7 +222,7 @@ static ssize_t driver_bind(struct device_driver *drv,
|
|||
bus_put(bus);
|
||||
return err;
|
||||
}
|
||||
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
|
||||
static DRIVER_ATTR_WO(bind);
|
||||
|
||||
static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
|
||||
{
|
||||
|
@ -460,7 +461,7 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
|
|||
if (!bus->dev_attrs)
|
||||
return 0;
|
||||
|
||||
for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
|
||||
for (i = 0; bus->dev_attrs[i].attr.name; i++) {
|
||||
error = device_create_file(dev, &bus->dev_attrs[i]);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
|
@ -476,7 +477,7 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev)
|
|||
int i;
|
||||
|
||||
if (bus->dev_attrs) {
|
||||
for (i = 0; attr_name(bus->dev_attrs[i]); i++)
|
||||
for (i = 0; bus->dev_attrs[i].attr.name; i++)
|
||||
device_remove_file(dev, &bus->dev_attrs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -499,6 +500,9 @@ int bus_add_device(struct device *dev)
|
|||
error = device_add_attrs(bus, dev);
|
||||
if (error)
|
||||
goto out_put;
|
||||
error = device_add_groups(dev, bus->dev_groups);
|
||||
if (error)
|
||||
goto out_groups;
|
||||
error = sysfs_create_link(&bus->p->devices_kset->kobj,
|
||||
&dev->kobj, dev_name(dev));
|
||||
if (error)
|
||||
|
@ -513,6 +517,8 @@ int bus_add_device(struct device *dev)
|
|||
|
||||
out_subsys:
|
||||
sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
|
||||
out_groups:
|
||||
device_remove_groups(dev, bus->dev_groups);
|
||||
out_id:
|
||||
device_remove_attrs(bus, dev);
|
||||
out_put:
|
||||
|
@ -575,6 +581,7 @@ void bus_remove_device(struct device *dev)
|
|||
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
|
||||
dev_name(dev));
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
device_remove_groups(dev, dev->bus->dev_groups);
|
||||
if (klist_node_attached(&dev->p->knode_bus))
|
||||
klist_del(&dev->p->knode_bus);
|
||||
|
||||
|
@ -590,7 +597,7 @@ static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
|
|||
int i;
|
||||
|
||||
if (bus->drv_attrs) {
|
||||
for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
|
||||
for (i = 0; bus->drv_attrs[i].attr.name; i++) {
|
||||
error = driver_create_file(drv, &bus->drv_attrs[i]);
|
||||
if (error)
|
||||
goto err;
|
||||
|
@ -610,7 +617,7 @@ static void driver_remove_attrs(struct bus_type *bus,
|
|||
int i;
|
||||
|
||||
if (bus->drv_attrs) {
|
||||
for (i = 0; attr_name(bus->drv_attrs[i]); i++)
|
||||
for (i = 0; bus->drv_attrs[i].attr.name; i++)
|
||||
driver_remove_file(drv, &bus->drv_attrs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -659,8 +666,8 @@ static void remove_probe_files(struct bus_type *bus)
|
|||
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||
}
|
||||
|
||||
static ssize_t driver_uevent_store(struct device_driver *drv,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t uevent_store(struct device_driver *drv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
enum kobject_action action;
|
||||
|
||||
|
@ -668,7 +675,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv,
|
|||
kobject_uevent(&drv->p->kobj, action);
|
||||
return count;
|
||||
}
|
||||
static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
|
||||
static DRIVER_ATTR_WO(uevent);
|
||||
|
||||
/**
|
||||
* bus_add_driver - Add a driver to the bus.
|
||||
|
@ -719,6 +726,10 @@ int bus_add_driver(struct device_driver *drv)
|
|||
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
|
||||
__func__, drv->name);
|
||||
}
|
||||
error = driver_add_groups(drv, bus->drv_groups);
|
||||
if (error)
|
||||
printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
|
||||
__func__, drv->name);
|
||||
|
||||
if (!drv->suppress_bind_attrs) {
|
||||
error = add_bind_files(drv);
|
||||
|
@ -756,6 +767,7 @@ void bus_remove_driver(struct device_driver *drv)
|
|||
if (!drv->suppress_bind_attrs)
|
||||
remove_bind_files(drv);
|
||||
driver_remove_attrs(drv->bus, drv);
|
||||
driver_remove_groups(drv, drv->bus->drv_groups);
|
||||
driver_remove_file(drv, &driver_attr_uevent);
|
||||
klist_remove(&drv->p->knode_bus);
|
||||
pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
|
||||
|
@ -846,7 +858,7 @@ static int bus_add_attrs(struct bus_type *bus)
|
|||
int i;
|
||||
|
||||
if (bus->bus_attrs) {
|
||||
for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
|
||||
for (i = 0; bus->bus_attrs[i].attr.name; i++) {
|
||||
error = bus_create_file(bus, &bus->bus_attrs[i]);
|
||||
if (error)
|
||||
goto err;
|
||||
|
@ -865,11 +877,23 @@ static void bus_remove_attrs(struct bus_type *bus)
|
|||
int i;
|
||||
|
||||
if (bus->bus_attrs) {
|
||||
for (i = 0; attr_name(bus->bus_attrs[i]); i++)
|
||||
for (i = 0; bus->bus_attrs[i].attr.name; i++)
|
||||
bus_remove_file(bus, &bus->bus_attrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int bus_add_groups(struct bus_type *bus,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
return sysfs_create_groups(&bus->p->subsys.kobj, groups);
|
||||
}
|
||||
|
||||
static void bus_remove_groups(struct bus_type *bus,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
sysfs_remove_groups(&bus->p->subsys.kobj, groups);
|
||||
}
|
||||
|
||||
static void klist_devices_get(struct klist_node *n)
|
||||
{
|
||||
struct device_private *dev_prv = to_device_private_bus(n);
|
||||
|
@ -962,10 +986,15 @@ int bus_register(struct bus_type *bus)
|
|||
retval = bus_add_attrs(bus);
|
||||
if (retval)
|
||||
goto bus_attrs_fail;
|
||||
retval = bus_add_groups(bus, bus->bus_groups);
|
||||
if (retval)
|
||||
goto bus_groups_fail;
|
||||
|
||||
pr_debug("bus: '%s': registered\n", bus->name);
|
||||
return 0;
|
||||
|
||||
bus_groups_fail:
|
||||
bus_remove_attrs(bus);
|
||||
bus_attrs_fail:
|
||||
remove_probe_files(bus);
|
||||
bus_probe_files_fail:
|
||||
|
@ -996,6 +1025,7 @@ void bus_unregister(struct bus_type *bus)
|
|||
if (bus->dev_root)
|
||||
device_unregister(bus->dev_root);
|
||||
bus_remove_attrs(bus);
|
||||
bus_remove_groups(bus, bus->bus_groups);
|
||||
remove_probe_files(bus);
|
||||
kset_unregister(bus->p->drivers_kset);
|
||||
kset_unregister(bus->p->devices_kset);
|
||||
|
|
|
@ -135,7 +135,7 @@ static int add_class_attrs(struct class *cls)
|
|||
int error = 0;
|
||||
|
||||
if (cls->class_attrs) {
|
||||
for (i = 0; attr_name(cls->class_attrs[i]); i++) {
|
||||
for (i = 0; cls->class_attrs[i].attr.name; i++) {
|
||||
error = class_create_file(cls, &cls->class_attrs[i]);
|
||||
if (error)
|
||||
goto error;
|
||||
|
@ -154,7 +154,7 @@ static void remove_class_attrs(struct class *cls)
|
|||
int i;
|
||||
|
||||
if (cls->class_attrs) {
|
||||
for (i = 0; attr_name(cls->class_attrs[i]); i++)
|
||||
for (i = 0; cls->class_attrs[i].attr.name; i++)
|
||||
class_remove_file(cls, &cls->class_attrs[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/async.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
@ -36,9 +37,9 @@ long sysfs_deprecated = 1;
|
|||
#else
|
||||
long sysfs_deprecated = 0;
|
||||
#endif
|
||||
static __init int sysfs_deprecated_setup(char *arg)
|
||||
static int __init sysfs_deprecated_setup(char *arg)
|
||||
{
|
||||
return strict_strtol(arg, 10, &sysfs_deprecated);
|
||||
return kstrtol(arg, 10, &sysfs_deprecated);
|
||||
}
|
||||
early_param("sysfs.deprecated", sysfs_deprecated_setup);
|
||||
#endif
|
||||
|
@ -345,7 +346,7 @@ static const struct kset_uevent_ops device_uevent_ops = {
|
|||
.uevent = dev_uevent,
|
||||
};
|
||||
|
||||
static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct kobject *top_kobj;
|
||||
|
@ -388,7 +389,7 @@ out:
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
enum kobject_action action;
|
||||
|
@ -399,11 +400,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
|||
dev_err(dev, "uevent: unknown action-string\n");
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(uevent);
|
||||
|
||||
static struct device_attribute uevent_attr =
|
||||
__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
|
||||
|
||||
static ssize_t show_online(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t online_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
bool val;
|
||||
|
@ -414,7 +413,7 @@ static ssize_t show_online(struct device *dev, struct device_attribute *attr,
|
|||
return sprintf(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t store_online(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t online_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
bool val;
|
||||
|
@ -429,9 +428,7 @@ static ssize_t store_online(struct device *dev, struct device_attribute *attr,
|
|||
unlock_device_hotplug();
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static struct device_attribute online_attr =
|
||||
__ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online);
|
||||
static DEVICE_ATTR_RW(online);
|
||||
|
||||
static int device_add_attributes(struct device *dev,
|
||||
struct device_attribute *attrs)
|
||||
|
@ -440,7 +437,7 @@ static int device_add_attributes(struct device *dev,
|
|||
int i;
|
||||
|
||||
if (attrs) {
|
||||
for (i = 0; attr_name(attrs[i]); i++) {
|
||||
for (i = 0; attrs[i].attr.name; i++) {
|
||||
error = device_create_file(dev, &attrs[i]);
|
||||
if (error)
|
||||
break;
|
||||
|
@ -458,7 +455,7 @@ static void device_remove_attributes(struct device *dev,
|
|||
int i;
|
||||
|
||||
if (attrs)
|
||||
for (i = 0; attr_name(attrs[i]); i++)
|
||||
for (i = 0; attrs[i].attr.name; i++)
|
||||
device_remove_file(dev, &attrs[i]);
|
||||
}
|
||||
|
||||
|
@ -469,7 +466,7 @@ static int device_add_bin_attributes(struct device *dev,
|
|||
int i;
|
||||
|
||||
if (attrs) {
|
||||
for (i = 0; attr_name(attrs[i]); i++) {
|
||||
for (i = 0; attrs[i].attr.name; i++) {
|
||||
error = device_create_bin_file(dev, &attrs[i]);
|
||||
if (error)
|
||||
break;
|
||||
|
@ -487,38 +484,19 @@ static void device_remove_bin_attributes(struct device *dev,
|
|||
int i;
|
||||
|
||||
if (attrs)
|
||||
for (i = 0; attr_name(attrs[i]); i++)
|
||||
for (i = 0; attrs[i].attr.name; i++)
|
||||
device_remove_bin_file(dev, &attrs[i]);
|
||||
}
|
||||
|
||||
static int device_add_groups(struct device *dev,
|
||||
const struct attribute_group **groups)
|
||||
int device_add_groups(struct device *dev, const struct attribute_group **groups)
|
||||
{
|
||||
int error = 0;
|
||||
int i;
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; groups[i]; i++) {
|
||||
error = sysfs_create_group(&dev->kobj, groups[i]);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
sysfs_remove_group(&dev->kobj,
|
||||
groups[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
return sysfs_create_groups(&dev->kobj, groups);
|
||||
}
|
||||
|
||||
static void device_remove_groups(struct device *dev,
|
||||
const struct attribute_group **groups)
|
||||
void device_remove_groups(struct device *dev,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (groups)
|
||||
for (i = 0; groups[i]; i++)
|
||||
sysfs_remove_group(&dev->kobj, groups[i]);
|
||||
sysfs_remove_groups(&dev->kobj, groups);
|
||||
}
|
||||
|
||||
static int device_add_attrs(struct device *dev)
|
||||
|
@ -550,7 +528,7 @@ static int device_add_attrs(struct device *dev)
|
|||
goto err_remove_type_groups;
|
||||
|
||||
if (device_supports_offline(dev) && !dev->offline_disabled) {
|
||||
error = device_create_file(dev, &online_attr);
|
||||
error = device_create_file(dev, &dev_attr_online);
|
||||
if (error)
|
||||
goto err_remove_type_groups;
|
||||
}
|
||||
|
@ -578,7 +556,7 @@ static void device_remove_attrs(struct device *dev)
|
|||
struct class *class = dev->class;
|
||||
const struct device_type *type = dev->type;
|
||||
|
||||
device_remove_file(dev, &online_attr);
|
||||
device_remove_file(dev, &dev_attr_online);
|
||||
device_remove_groups(dev, dev->groups);
|
||||
|
||||
if (type)
|
||||
|
@ -591,15 +569,12 @@ static void device_remove_attrs(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return print_dev_t(buf, dev->devt);
|
||||
}
|
||||
|
||||
static struct device_attribute devt_attr =
|
||||
__ATTR(dev, S_IRUGO, show_dev, NULL);
|
||||
static DEVICE_ATTR_RO(dev);
|
||||
|
||||
/* /sys/devices/ */
|
||||
struct kset *devices_kset;
|
||||
|
@ -626,6 +601,7 @@ int device_create_file(struct device *dev,
|
|||
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_file);
|
||||
|
||||
/**
|
||||
* device_remove_file - remove sysfs attribute file.
|
||||
|
@ -638,6 +614,7 @@ void device_remove_file(struct device *dev,
|
|||
if (dev)
|
||||
sysfs_remove_file(&dev->kobj, &attr->attr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_remove_file);
|
||||
|
||||
/**
|
||||
* device_create_bin_file - create sysfs binary attribute file for device.
|
||||
|
@ -748,6 +725,7 @@ void device_initialize(struct device *dev)
|
|||
device_pm_init(dev);
|
||||
set_dev_node(dev, -1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_initialize);
|
||||
|
||||
struct kobject *virtual_device_parent(struct device *dev)
|
||||
{
|
||||
|
@ -1100,12 +1078,12 @@ int device_add(struct device *dev)
|
|||
if (platform_notify)
|
||||
platform_notify(dev);
|
||||
|
||||
error = device_create_file(dev, &uevent_attr);
|
||||
error = device_create_file(dev, &dev_attr_uevent);
|
||||
if (error)
|
||||
goto attrError;
|
||||
|
||||
if (MAJOR(dev->devt)) {
|
||||
error = device_create_file(dev, &devt_attr);
|
||||
error = device_create_file(dev, &dev_attr_dev);
|
||||
if (error)
|
||||
goto ueventattrError;
|
||||
|
||||
|
@ -1172,9 +1150,9 @@ done:
|
|||
device_remove_sys_dev_entry(dev);
|
||||
devtattrError:
|
||||
if (MAJOR(dev->devt))
|
||||
device_remove_file(dev, &devt_attr);
|
||||
device_remove_file(dev, &dev_attr_dev);
|
||||
ueventattrError:
|
||||
device_remove_file(dev, &uevent_attr);
|
||||
device_remove_file(dev, &dev_attr_uevent);
|
||||
attrError:
|
||||
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&dev->kobj);
|
||||
|
@ -1187,6 +1165,7 @@ name_error:
|
|||
dev->p = NULL;
|
||||
goto done;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_add);
|
||||
|
||||
/**
|
||||
* device_register - register a device with the system.
|
||||
|
@ -1211,6 +1190,7 @@ int device_register(struct device *dev)
|
|||
device_initialize(dev);
|
||||
return device_add(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_register);
|
||||
|
||||
/**
|
||||
* get_device - increment reference count for device.
|
||||
|
@ -1224,6 +1204,7 @@ struct device *get_device(struct device *dev)
|
|||
{
|
||||
return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_device);
|
||||
|
||||
/**
|
||||
* put_device - decrement reference count.
|
||||
|
@ -1235,6 +1216,7 @@ void put_device(struct device *dev)
|
|||
if (dev)
|
||||
kobject_put(&dev->kobj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(put_device);
|
||||
|
||||
/**
|
||||
* device_del - delete device from system.
|
||||
|
@ -1266,7 +1248,7 @@ void device_del(struct device *dev)
|
|||
if (MAJOR(dev->devt)) {
|
||||
devtmpfs_delete_node(dev);
|
||||
device_remove_sys_dev_entry(dev);
|
||||
device_remove_file(dev, &devt_attr);
|
||||
device_remove_file(dev, &dev_attr_dev);
|
||||
}
|
||||
if (dev->class) {
|
||||
device_remove_class_symlinks(dev);
|
||||
|
@ -1281,7 +1263,7 @@ void device_del(struct device *dev)
|
|||
klist_del(&dev->knode_class);
|
||||
mutex_unlock(&dev->class->p->mutex);
|
||||
}
|
||||
device_remove_file(dev, &uevent_attr);
|
||||
device_remove_file(dev, &dev_attr_uevent);
|
||||
device_remove_attrs(dev);
|
||||
bus_remove_device(dev);
|
||||
device_pm_remove(dev);
|
||||
|
@ -1297,6 +1279,7 @@ void device_del(struct device *dev)
|
|||
kobject_del(&dev->kobj);
|
||||
put_device(parent);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_del);
|
||||
|
||||
/**
|
||||
* device_unregister - unregister device from system.
|
||||
|
@ -1315,6 +1298,7 @@ void device_unregister(struct device *dev)
|
|||
device_del(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_unregister);
|
||||
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
{
|
||||
|
@ -1403,6 +1387,7 @@ int device_for_each_child(struct device *parent, void *data,
|
|||
klist_iter_exit(&i);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_for_each_child);
|
||||
|
||||
/**
|
||||
* device_find_child - device iterator for locating a particular device.
|
||||
|
@ -1437,6 +1422,7 @@ struct device *device_find_child(struct device *parent, void *data,
|
|||
klist_iter_exit(&i);
|
||||
return child;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_find_child);
|
||||
|
||||
int __init devices_init(void)
|
||||
{
|
||||
|
@ -1464,21 +1450,6 @@ int __init devices_init(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_for_each_child);
|
||||
EXPORT_SYMBOL_GPL(device_find_child);
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_initialize);
|
||||
EXPORT_SYMBOL_GPL(device_add);
|
||||
EXPORT_SYMBOL_GPL(device_register);
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_del);
|
||||
EXPORT_SYMBOL_GPL(device_unregister);
|
||||
EXPORT_SYMBOL_GPL(get_device);
|
||||
EXPORT_SYMBOL_GPL(put_device);
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_create_file);
|
||||
EXPORT_SYMBOL_GPL(device_remove_file);
|
||||
|
||||
static DEFINE_MUTEX(device_hotplug_lock);
|
||||
|
||||
void lock_device_hotplug(void)
|
||||
|
|
|
@ -43,11 +43,14 @@ static int __ref cpu_subsys_online(struct device *dev)
|
|||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
int cpuid = dev->id;
|
||||
int from_nid, to_nid;
|
||||
int ret;
|
||||
int ret = -ENODEV;
|
||||
|
||||
cpu_hotplug_driver_lock();
|
||||
|
||||
from_nid = cpu_to_node(cpuid);
|
||||
if (from_nid == NUMA_NO_NODE)
|
||||
goto out;
|
||||
|
||||
ret = cpu_up(cpuid);
|
||||
/*
|
||||
* When hot adding memory to memoryless node and enabling a cpu
|
||||
|
@ -57,6 +60,7 @@ static int __ref cpu_subsys_online(struct device *dev)
|
|||
if (from_nid != to_nid)
|
||||
change_cpu_under_node(cpu, from_nid, to_nid);
|
||||
|
||||
out:
|
||||
cpu_hotplug_driver_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
|
|||
|
||||
static DEFINE_MUTEX(cma_mutex);
|
||||
|
||||
static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
|
||||
static int __init cma_activate_area(unsigned long base_pfn, unsigned long count)
|
||||
{
|
||||
unsigned long pfn = base_pfn;
|
||||
unsigned i = count >> pageblock_order;
|
||||
|
@ -156,7 +156,7 @@ static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __init struct cma *cma_create_area(unsigned long base_pfn,
|
||||
static struct cma * __init cma_create_area(unsigned long base_pfn,
|
||||
unsigned long count)
|
||||
{
|
||||
int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include "base.h"
|
||||
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
|
@ -123,34 +124,16 @@ void driver_remove_file(struct device_driver *drv,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(driver_remove_file);
|
||||
|
||||
static int driver_add_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups)
|
||||
int driver_add_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
int error = 0;
|
||||
int i;
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; groups[i]; i++) {
|
||||
error = sysfs_create_group(&drv->p->kobj, groups[i]);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
sysfs_remove_group(&drv->p->kobj,
|
||||
groups[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
return sysfs_create_groups(&drv->p->kobj, groups);
|
||||
}
|
||||
|
||||
static void driver_remove_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups)
|
||||
void driver_remove_groups(struct device_driver *drv,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (groups)
|
||||
for (i = 0; groups[i]; i++)
|
||||
sysfs_remove_group(&drv->p->kobj, groups[i]);
|
||||
sysfs_remove_groups(&drv->p->kobj, groups);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -486,9 +486,8 @@ static struct notifier_block fw_shutdown_nb = {
|
|||
.notifier_call = fw_shutdown_notify,
|
||||
};
|
||||
|
||||
static ssize_t firmware_timeout_show(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", loading_timeout);
|
||||
}
|
||||
|
@ -506,9 +505,8 @@ static ssize_t firmware_timeout_show(struct class *class,
|
|||
*
|
||||
* Note: zero means 'wait forever'.
|
||||
**/
|
||||
static ssize_t firmware_timeout_store(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t timeout_store(struct class *class, struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
loading_timeout = simple_strtol(buf, NULL, 10);
|
||||
if (loading_timeout < 0)
|
||||
|
@ -518,8 +516,7 @@ static ssize_t firmware_timeout_store(struct class *class,
|
|||
}
|
||||
|
||||
static struct class_attribute firmware_class_attrs[] = {
|
||||
__ATTR(timeout, S_IWUSR | S_IRUGO,
|
||||
firmware_timeout_show, firmware_timeout_store),
|
||||
__ATTR_RW(timeout),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
|
@ -868,8 +865,15 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
|
|||
goto err_del_dev;
|
||||
}
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
list_add(&buf->pending_list, &pending_fw_head);
|
||||
mutex_unlock(&fw_lock);
|
||||
|
||||
retval = device_create_file(f_dev, &dev_attr_loading);
|
||||
if (retval) {
|
||||
mutex_lock(&fw_lock);
|
||||
list_del_init(&buf->pending_list);
|
||||
mutex_unlock(&fw_lock);
|
||||
dev_err(f_dev, "%s: device_create_file failed\n", __func__);
|
||||
goto err_del_bin_attr;
|
||||
}
|
||||
|
@ -884,10 +888,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
|
|||
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
list_add(&buf->pending_list, &pending_fw_head);
|
||||
mutex_unlock(&fw_lock);
|
||||
|
||||
wait_for_completion(&buf->completion);
|
||||
|
||||
cancel_delayed_work_sync(&fw_priv->timeout_work);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/capability.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -30,6 +29,8 @@ static DEFINE_MUTEX(mem_sysfs_mutex);
|
|||
|
||||
#define MEMORY_CLASS_NAME "memory"
|
||||
|
||||
#define to_memory_block(dev) container_of(dev, struct memory_block, dev)
|
||||
|
||||
static int sections_per_block;
|
||||
|
||||
static inline int base_memory_block_id(int section_nr)
|
||||
|
@ -77,7 +78,7 @@ EXPORT_SYMBOL(unregister_memory_isolate_notifier);
|
|||
|
||||
static void memory_block_release(struct device *dev)
|
||||
{
|
||||
struct memory_block *mem = container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
|
||||
kfree(mem);
|
||||
}
|
||||
|
@ -110,8 +111,7 @@ static unsigned long get_memory_block_size(void)
|
|||
static ssize_t show_mem_start_phys_index(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
unsigned long phys_index;
|
||||
|
||||
phys_index = mem->start_section_nr / sections_per_block;
|
||||
|
@ -121,8 +121,7 @@ static ssize_t show_mem_start_phys_index(struct device *dev,
|
|||
static ssize_t show_mem_end_phys_index(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
unsigned long phys_index;
|
||||
|
||||
phys_index = mem->end_section_nr / sections_per_block;
|
||||
|
@ -137,8 +136,7 @@ static ssize_t show_mem_removable(struct device *dev,
|
|||
{
|
||||
unsigned long i, pfn;
|
||||
int ret = 1;
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
|
||||
for (i = 0; i < sections_per_block; i++) {
|
||||
if (!present_section_nr(mem->start_section_nr + i))
|
||||
|
@ -156,8 +154,7 @@ static ssize_t show_mem_removable(struct device *dev,
|
|||
static ssize_t show_mem_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
ssize_t len = 0;
|
||||
|
||||
/*
|
||||
|
@ -263,9 +260,8 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __memory_block_change_state(struct memory_block *mem,
|
||||
unsigned long to_state, unsigned long from_state_req,
|
||||
int online_type)
|
||||
static int memory_block_change_state(struct memory_block *mem,
|
||||
unsigned long to_state, unsigned long from_state_req)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -275,105 +271,89 @@ static int __memory_block_change_state(struct memory_block *mem,
|
|||
if (to_state == MEM_OFFLINE)
|
||||
mem->state = MEM_GOING_OFFLINE;
|
||||
|
||||
ret = memory_block_action(mem->start_section_nr, to_state, online_type);
|
||||
ret = memory_block_action(mem->start_section_nr, to_state,
|
||||
mem->online_type);
|
||||
|
||||
mem->state = ret ? from_state_req : to_state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The device lock serializes operations on memory_subsys_[online|offline] */
|
||||
static int memory_subsys_online(struct device *dev)
|
||||
{
|
||||
struct memory_block *mem = container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mem->state_mutex);
|
||||
if (mem->state == MEM_ONLINE)
|
||||
return 0;
|
||||
|
||||
ret = mem->state == MEM_ONLINE ? 0 :
|
||||
__memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE,
|
||||
ONLINE_KEEP);
|
||||
/*
|
||||
* If we are called from store_mem_state(), online_type will be
|
||||
* set >= 0 Otherwise we were called from the device online
|
||||
* attribute and need to set the online_type.
|
||||
*/
|
||||
if (mem->online_type < 0)
|
||||
mem->online_type = ONLINE_KEEP;
|
||||
|
||||
ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
|
||||
|
||||
/* clear online_type */
|
||||
mem->online_type = -1;
|
||||
|
||||
mutex_unlock(&mem->state_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_subsys_offline(struct device *dev)
|
||||
{
|
||||
struct memory_block *mem = container_of(dev, struct memory_block, dev);
|
||||
int ret;
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
|
||||
mutex_lock(&mem->state_mutex);
|
||||
if (mem->state == MEM_OFFLINE)
|
||||
return 0;
|
||||
|
||||
ret = mem->state == MEM_OFFLINE ? 0 :
|
||||
__memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
|
||||
|
||||
mutex_unlock(&mem->state_mutex);
|
||||
return ret;
|
||||
return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
|
||||
}
|
||||
|
||||
static int __memory_block_change_state_uevent(struct memory_block *mem,
|
||||
unsigned long to_state, unsigned long from_state_req,
|
||||
int online_type)
|
||||
{
|
||||
int ret = __memory_block_change_state(mem, to_state, from_state_req,
|
||||
online_type);
|
||||
if (!ret) {
|
||||
switch (mem->state) {
|
||||
case MEM_OFFLINE:
|
||||
kobject_uevent(&mem->dev.kobj, KOBJ_OFFLINE);
|
||||
break;
|
||||
case MEM_ONLINE:
|
||||
kobject_uevent(&mem->dev.kobj, KOBJ_ONLINE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_block_change_state(struct memory_block *mem,
|
||||
unsigned long to_state, unsigned long from_state_req,
|
||||
int online_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mem->state_mutex);
|
||||
ret = __memory_block_change_state_uevent(mem, to_state, from_state_req,
|
||||
online_type);
|
||||
mutex_unlock(&mem->state_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
static ssize_t
|
||||
store_mem_state(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct memory_block *mem;
|
||||
bool offline;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mem = container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
int ret, online_type;
|
||||
|
||||
lock_device_hotplug();
|
||||
|
||||
if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) {
|
||||
offline = false;
|
||||
ret = memory_block_change_state(mem, MEM_ONLINE,
|
||||
MEM_OFFLINE, ONLINE_KERNEL);
|
||||
} else if (!strncmp(buf, "online_movable", min_t(int, count, 14))) {
|
||||
offline = false;
|
||||
ret = memory_block_change_state(mem, MEM_ONLINE,
|
||||
MEM_OFFLINE, ONLINE_MOVABLE);
|
||||
} else if (!strncmp(buf, "online", min_t(int, count, 6))) {
|
||||
offline = false;
|
||||
ret = memory_block_change_state(mem, MEM_ONLINE,
|
||||
MEM_OFFLINE, ONLINE_KEEP);
|
||||
} else if(!strncmp(buf, "offline", min_t(int, count, 7))) {
|
||||
offline = true;
|
||||
ret = memory_block_change_state(mem, MEM_OFFLINE,
|
||||
MEM_ONLINE, -1);
|
||||
if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
|
||||
online_type = ONLINE_KERNEL;
|
||||
else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
|
||||
online_type = ONLINE_MOVABLE;
|
||||
else if (!strncmp(buf, "online", min_t(int, count, 6)))
|
||||
online_type = ONLINE_KEEP;
|
||||
else if (!strncmp(buf, "offline", min_t(int, count, 7)))
|
||||
online_type = -1;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
switch (online_type) {
|
||||
case ONLINE_KERNEL:
|
||||
case ONLINE_MOVABLE:
|
||||
case ONLINE_KEEP:
|
||||
/*
|
||||
* mem->online_type is not protected so there can be a
|
||||
* race here. However, when racing online, the first
|
||||
* will succeed and the second will just return as the
|
||||
* block will already be online. The online type
|
||||
* could be either one, but that is expected.
|
||||
*/
|
||||
mem->online_type = online_type;
|
||||
ret = device_online(&mem->dev);
|
||||
break;
|
||||
case -1:
|
||||
ret = device_offline(&mem->dev);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL; /* should never happen */
|
||||
}
|
||||
if (!ret)
|
||||
dev->offline = offline;
|
||||
|
||||
unlock_device_hotplug();
|
||||
|
||||
|
@ -394,8 +374,7 @@ store_mem_state(struct device *dev,
|
|||
static ssize_t show_phys_device(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, dev);
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
return sprintf(buf, "%d\n", mem->phys_device);
|
||||
}
|
||||
|
||||
|
@ -471,7 +450,7 @@ store_soft_offline_page(struct device *dev,
|
|||
u64 pfn;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (strict_strtoull(buf, 0, &pfn) < 0)
|
||||
if (kstrtoull(buf, 0, &pfn) < 0)
|
||||
return -EINVAL;
|
||||
pfn >>= PAGE_SHIFT;
|
||||
if (!pfn_valid(pfn))
|
||||
|
@ -490,7 +469,7 @@ store_hard_offline_page(struct device *dev,
|
|||
u64 pfn;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (strict_strtoull(buf, 0, &pfn) < 0)
|
||||
if (kstrtoull(buf, 0, &pfn) < 0)
|
||||
return -EINVAL;
|
||||
pfn >>= PAGE_SHIFT;
|
||||
ret = memory_failure(pfn, 0, 0);
|
||||
|
@ -527,7 +506,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
|
|||
put_device(&hint->dev);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
return container_of(dev, struct memory_block, dev);
|
||||
return to_memory_block(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -567,16 +546,13 @@ static const struct attribute_group *memory_memblk_attr_groups[] = {
|
|||
static
|
||||
int register_memory(struct memory_block *memory)
|
||||
{
|
||||
int error;
|
||||
|
||||
memory->dev.bus = &memory_subsys;
|
||||
memory->dev.id = memory->start_section_nr / sections_per_block;
|
||||
memory->dev.release = memory_block_release;
|
||||
memory->dev.groups = memory_memblk_attr_groups;
|
||||
memory->dev.offline = memory->state == MEM_OFFLINE;
|
||||
|
||||
error = device_register(&memory->dev);
|
||||
return error;
|
||||
return device_register(&memory->dev);
|
||||
}
|
||||
|
||||
static int init_memory_block(struct memory_block **memory,
|
||||
|
@ -597,7 +573,6 @@ static int init_memory_block(struct memory_block **memory,
|
|||
mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
|
||||
mem->state = state;
|
||||
mem->section_count++;
|
||||
mutex_init(&mem->state_mutex);
|
||||
start_pfn = section_nr_to_pfn(mem->start_section_nr);
|
||||
mem->phys_device = arch_get_memory_phys_device(start_pfn);
|
||||
|
||||
|
@ -607,55 +582,57 @@ static int init_memory_block(struct memory_block **memory,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int add_memory_section(int nid, struct mem_section *section,
|
||||
struct memory_block **mem_p,
|
||||
unsigned long state, enum mem_add_context context)
|
||||
static int add_memory_block(int base_section_nr)
|
||||
{
|
||||
struct memory_block *mem = NULL;
|
||||
int scn_nr = __section_nr(section);
|
||||
int ret = 0;
|
||||
struct memory_block *mem;
|
||||
int i, ret, section_count = 0, section_nr;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
|
||||
if (context == BOOT) {
|
||||
/* same memory block ? */
|
||||
if (mem_p && *mem_p)
|
||||
if (scn_nr >= (*mem_p)->start_section_nr &&
|
||||
scn_nr <= (*mem_p)->end_section_nr) {
|
||||
mem = *mem_p;
|
||||
kobject_get(&mem->dev.kobj);
|
||||
}
|
||||
} else
|
||||
mem = find_memory_block(section);
|
||||
|
||||
if (mem) {
|
||||
mem->section_count++;
|
||||
kobject_put(&mem->dev.kobj);
|
||||
} else {
|
||||
ret = init_memory_block(&mem, section, state);
|
||||
/* store memory_block pointer for next loop */
|
||||
if (!ret && context == BOOT)
|
||||
if (mem_p)
|
||||
*mem_p = mem;
|
||||
for (i = base_section_nr;
|
||||
(i < base_section_nr + sections_per_block) && i < NR_MEM_SECTIONS;
|
||||
i++) {
|
||||
if (!present_section_nr(i))
|
||||
continue;
|
||||
if (section_count == 0)
|
||||
section_nr = i;
|
||||
section_count++;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
if (context == HOTPLUG &&
|
||||
mem->section_count == sections_per_block)
|
||||
ret = register_mem_sect_under_node(mem, nid);
|
||||
}
|
||||
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return ret;
|
||||
if (section_count == 0)
|
||||
return 0;
|
||||
ret = init_memory_block(&mem, __nr_to_section(section_nr), MEM_ONLINE);
|
||||
if (ret)
|
||||
return ret;
|
||||
mem->section_count = section_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* need an interface for the VM to add new memory regions,
|
||||
* but without onlining it.
|
||||
*/
|
||||
int register_new_memory(int nid, struct mem_section *section)
|
||||
{
|
||||
return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);
|
||||
int ret = 0;
|
||||
struct memory_block *mem;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
|
||||
mem = find_memory_block(section);
|
||||
if (mem) {
|
||||
mem->section_count++;
|
||||
put_device(&mem->dev);
|
||||
} else {
|
||||
ret = init_memory_block(&mem, section, MEM_OFFLINE);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mem->section_count == sections_per_block)
|
||||
ret = register_mem_sect_under_node(mem, nid);
|
||||
out:
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTREMOVE
|
||||
|
@ -665,7 +642,7 @@ unregister_memory(struct memory_block *memory)
|
|||
BUG_ON(memory->dev.bus != &memory_subsys);
|
||||
|
||||
/* drop the ref. we got in remove_memory_block() */
|
||||
kobject_put(&memory->dev.kobj);
|
||||
put_device(&memory->dev);
|
||||
device_unregister(&memory->dev);
|
||||
}
|
||||
|
||||
|
@ -682,7 +659,7 @@ static int remove_memory_block(unsigned long node_id,
|
|||
if (mem->section_count == 0)
|
||||
unregister_memory(mem);
|
||||
else
|
||||
kobject_put(&mem->dev.kobj);
|
||||
put_device(&mem->dev);
|
||||
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return 0;
|
||||
|
@ -735,7 +712,6 @@ int __init memory_dev_init(void)
|
|||
int ret;
|
||||
int err;
|
||||
unsigned long block_sz;
|
||||
struct memory_block *mem = NULL;
|
||||
|
||||
ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
|
||||
if (ret)
|
||||
|
@ -748,17 +724,13 @@ int __init memory_dev_init(void)
|
|||
* Create entries for memory sections that were found
|
||||
* during boot and have been initialized
|
||||
*/
|
||||
for (i = 0; i < NR_MEM_SECTIONS; i++) {
|
||||
if (!present_section_nr(i))
|
||||
continue;
|
||||
/* don't need to reuse memory_block if only one per block */
|
||||
err = add_memory_section(0, __nr_to_section(i),
|
||||
(sections_per_block == 1) ? NULL : &mem,
|
||||
MEM_ONLINE,
|
||||
BOOT);
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
|
||||
err = add_memory_block(i);
|
||||
if (!ret)
|
||||
ret = err;
|
||||
}
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
|
|
|
@ -672,11 +672,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
|||
|
||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct device_attribute platform_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *platform_dev_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(platform_dev);
|
||||
|
||||
static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
|
@ -893,7 +895,7 @@ static const struct dev_pm_ops platform_dev_pm_ops = {
|
|||
|
||||
struct bus_type platform_bus_type = {
|
||||
.name = "platform",
|
||||
.dev_attrs = platform_dev_attrs,
|
||||
.dev_groups = platform_dev_groups,
|
||||
.match = platform_match,
|
||||
.uevent = platform_uevent,
|
||||
.pm = &platform_dev_pm_ops,
|
||||
|
@ -1054,7 +1056,7 @@ void __init early_platform_driver_register_all(char *class_str)
|
|||
* @epdrv: early platform driver structure
|
||||
* @id: id to match against
|
||||
*/
|
||||
static __init struct platform_device *
|
||||
static struct platform_device * __init
|
||||
early_platform_match(struct early_platform_driver *epdrv, int id)
|
||||
{
|
||||
struct platform_device *pd;
|
||||
|
@ -1072,7 +1074,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id)
|
|||
* @epdrv: early platform driver structure
|
||||
* @id: return true if id or above exists
|
||||
*/
|
||||
static __init int early_platform_left(struct early_platform_driver *epdrv,
|
||||
static int __init early_platform_left(struct early_platform_driver *epdrv,
|
||||
int id)
|
||||
{
|
||||
struct platform_device *pd;
|
||||
|
|
|
@ -206,7 +206,7 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
|
|||
if (!dev->power.use_autosuspend)
|
||||
return -EIO;
|
||||
|
||||
if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
|
||||
if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay)
|
||||
return -EINVAL;
|
||||
|
||||
device_lock(dev);
|
||||
|
|
|
@ -281,7 +281,7 @@ static ssize_t regmap_map_write_file(struct file *file,
|
|||
reg = simple_strtoul(start, &start, 16);
|
||||
while (*start == ' ')
|
||||
start++;
|
||||
if (strict_strtoul(start, 16, &value))
|
||||
if (kstrtoul(start, 16, &value))
|
||||
return -EINVAL;
|
||||
|
||||
/* Userspace has been fiddling around behind the kernel's back */
|
||||
|
|
|
@ -62,25 +62,6 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef arch_provides_topology_pointers
|
||||
#define define_siblings_show_map(name) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
return show_cpumap(0, topology_##name(cpu), buf); \
|
||||
}
|
||||
|
||||
#define define_siblings_show_list(name) \
|
||||
static ssize_t show_##name##_list(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
return show_cpumap(1, topology_##name(cpu), buf); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define define_siblings_show_map(name) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
|
@ -95,7 +76,6 @@ static ssize_t show_##name##_list(struct device *dev, \
|
|||
{ \
|
||||
return show_cpumap(1, topology_##name(dev->id), buf); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define define_siblings_show_func(name) \
|
||||
define_siblings_show_map(name); define_siblings_show_list(name)
|
||||
|
|
|
@ -397,15 +397,19 @@ static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
|
|||
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
|
||||
static void rbd_spec_put(struct rbd_spec *spec);
|
||||
|
||||
static struct bus_attribute rbd_bus_attrs[] = {
|
||||
__ATTR(add, S_IWUSR, NULL, rbd_add),
|
||||
__ATTR(remove, S_IWUSR, NULL, rbd_remove),
|
||||
__ATTR_NULL
|
||||
static BUS_ATTR(add, S_IWUSR, NULL, rbd_add);
|
||||
static BUS_ATTR(remove, S_IWUSR, NULL, rbd_remove);
|
||||
|
||||
static struct attribute *rbd_bus_attrs[] = {
|
||||
&bus_attr_add.attr,
|
||||
&bus_attr_remove.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(rbd_bus);
|
||||
|
||||
static struct bus_type rbd_bus_type = {
|
||||
.name = "rbd",
|
||||
.bus_attrs = rbd_bus_attrs,
|
||||
.bus_groups = rbd_bus_groups,
|
||||
};
|
||||
|
||||
static void rbd_root_dev_release(struct device *dev)
|
||||
|
|
|
@ -95,6 +95,7 @@ bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
|
||||
}
|
||||
static DEVICE_ATTR_RO(bsr_size);
|
||||
|
||||
static ssize_t
|
||||
bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
|
@ -102,20 +103,23 @@ bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
|
||||
}
|
||||
static DEVICE_ATTR_RO(bsr_stride);
|
||||
|
||||
static ssize_t
|
||||
bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
|
||||
}
|
||||
static DEVICE_ATTR_RO(bsr_length);
|
||||
|
||||
static struct device_attribute bsr_dev_attrs[] = {
|
||||
__ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL),
|
||||
__ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL),
|
||||
__ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *bsr_dev_attrs[] = {
|
||||
&dev_attr_bsr_size.attr,
|
||||
&dev_attr_bsr_stride.attr,
|
||||
&dev_attr_bsr_length.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(bsr_dev);
|
||||
|
||||
static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
|
@ -308,7 +312,7 @@ static int __init bsr_init(void)
|
|||
ret = PTR_ERR(bsr_class);
|
||||
goto out_err_1;
|
||||
}
|
||||
bsr_class->dev_attrs = bsr_dev_attrs;
|
||||
bsr_class->dev_groups = bsr_dev_groups;
|
||||
|
||||
ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
|
||||
bsr_major = MAJOR(bsr_dev);
|
||||
|
|
|
@ -279,33 +279,37 @@ loff_t srom_llseek(struct file *file, loff_t offset, int origin)
|
|||
return fixed_size_llseek(file, offset, origin, srom->total_size);
|
||||
}
|
||||
|
||||
static ssize_t total_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t total_size_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct srom_dev *srom = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", srom->total_size);
|
||||
}
|
||||
static DEVICE_ATTR_RO(total_size);
|
||||
|
||||
static ssize_t sector_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t sector_size_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct srom_dev *srom = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", srom->sector_size);
|
||||
}
|
||||
static DEVICE_ATTR_RO(sector_size);
|
||||
|
||||
static ssize_t page_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t page_size_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct srom_dev *srom = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", srom->page_size);
|
||||
}
|
||||
static DEVICE_ATTR_RO(page_size);
|
||||
|
||||
static struct device_attribute srom_dev_attrs[] = {
|
||||
__ATTR(total_size, S_IRUGO, total_show, NULL),
|
||||
__ATTR(sector_size, S_IRUGO, sector_show, NULL),
|
||||
__ATTR(page_size, S_IRUGO, page_show, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *srom_dev_attrs[] = {
|
||||
&dev_attr_total_size.attr,
|
||||
&dev_attr_sector_size.attr,
|
||||
&dev_attr_page_size.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(srom_dev);
|
||||
|
||||
static char *srom_devnode(struct device *dev, umode_t *mode)
|
||||
{
|
||||
|
@ -418,7 +422,7 @@ static int srom_init(void)
|
|||
result = PTR_ERR(srom_class);
|
||||
goto fail_cdev;
|
||||
}
|
||||
srom_class->dev_attrs = srom_dev_attrs;
|
||||
srom_class->dev_groups = srom_dev_groups;
|
||||
srom_class->devnode = srom_devnode;
|
||||
|
||||
/* Do per-partition initialization */
|
||||
|
|
|
@ -703,7 +703,7 @@ err_out:
|
|||
}
|
||||
EXPORT_SYMBOL(devfreq_remove_governor);
|
||||
|
||||
static ssize_t show_governor(struct device *dev,
|
||||
static ssize_t governor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (!to_devfreq(dev)->governor)
|
||||
|
@ -712,7 +712,7 @@ static ssize_t show_governor(struct device *dev,
|
|||
return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
|
||||
}
|
||||
|
||||
static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct devfreq *df = to_devfreq(dev);
|
||||
|
@ -754,9 +754,11 @@ out:
|
|||
ret = count;
|
||||
return ret;
|
||||
}
|
||||
static ssize_t show_available_governors(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static DEVICE_ATTR_RW(governor);
|
||||
|
||||
static ssize_t available_governors_show(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct devfreq_governor *tmp_governor;
|
||||
ssize_t count = 0;
|
||||
|
@ -775,9 +777,10 @@ static ssize_t show_available_governors(struct device *d,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RO(available_governors);
|
||||
|
||||
static ssize_t show_freq(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
unsigned long freq;
|
||||
struct devfreq *devfreq = to_devfreq(dev);
|
||||
|
@ -788,20 +791,22 @@ static ssize_t show_freq(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%lu\n", devfreq->previous_freq);
|
||||
}
|
||||
static DEVICE_ATTR_RO(cur_freq);
|
||||
|
||||
static ssize_t show_target_freq(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t target_freq_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
|
||||
}
|
||||
static DEVICE_ATTR_RO(target_freq);
|
||||
|
||||
static ssize_t show_polling_interval(struct device *dev,
|
||||
static ssize_t polling_interval_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
|
||||
}
|
||||
|
||||
static ssize_t store_polling_interval(struct device *dev,
|
||||
static ssize_t polling_interval_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -821,8 +826,9 @@ static ssize_t store_polling_interval(struct device *dev,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RW(polling_interval);
|
||||
|
||||
static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct devfreq *df = to_devfreq(dev);
|
||||
|
@ -849,13 +855,13 @@ unlock:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t show_min_freq(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq);
|
||||
}
|
||||
|
||||
static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct devfreq *df = to_devfreq(dev);
|
||||
|
@ -881,16 +887,18 @@ unlock:
|
|||
mutex_unlock(&df->lock);
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RW(min_freq);
|
||||
|
||||
static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
|
||||
}
|
||||
static DEVICE_ATTR_RW(max_freq);
|
||||
|
||||
static ssize_t show_available_freqs(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t available_frequencies_show(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct devfreq *df = to_devfreq(d);
|
||||
struct device *dev = df->dev.parent;
|
||||
|
@ -918,9 +926,10 @@ static ssize_t show_available_freqs(struct device *d,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RO(available_frequencies);
|
||||
|
||||
static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t trans_stat_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct devfreq *devfreq = to_devfreq(dev);
|
||||
ssize_t len;
|
||||
|
@ -959,20 +968,21 @@ static ssize_t show_trans_table(struct device *dev, struct device_attribute *att
|
|||
devfreq->total_trans);
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(trans_stat);
|
||||
|
||||
static struct device_attribute devfreq_attrs[] = {
|
||||
__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
|
||||
__ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
|
||||
__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
|
||||
__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
|
||||
__ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
|
||||
__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
|
||||
store_polling_interval),
|
||||
__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
|
||||
__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
|
||||
__ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
|
||||
{ },
|
||||
static struct attribute *devfreq_attrs[] = {
|
||||
&dev_attr_governor.attr,
|
||||
&dev_attr_available_governors.attr,
|
||||
&dev_attr_cur_freq.attr,
|
||||
&dev_attr_available_frequencies.attr,
|
||||
&dev_attr_target_freq.attr,
|
||||
&dev_attr_polling_interval.attr,
|
||||
&dev_attr_min_freq.attr,
|
||||
&dev_attr_max_freq.attr,
|
||||
&dev_attr_trans_stat.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(devfreq);
|
||||
|
||||
static int __init devfreq_init(void)
|
||||
{
|
||||
|
@ -988,7 +998,7 @@ static int __init devfreq_init(void)
|
|||
pr_err("%s: couldn't create workqueue\n", __FILE__);
|
||||
return PTR_ERR(devfreq_wq);
|
||||
}
|
||||
devfreq_class->dev_attrs = devfreq_attrs;
|
||||
devfreq_class->dev_groups = devfreq_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@ static struct dma_chan *dev_to_dma_chan(struct device *dev)
|
|||
return chan_dev->chan;
|
||||
}
|
||||
|
||||
static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t memcpy_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
unsigned long count = 0;
|
||||
|
@ -106,9 +107,10 @@ static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *at
|
|||
|
||||
return err;
|
||||
}
|
||||
static DEVICE_ATTR_RO(memcpy_count);
|
||||
|
||||
static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t bytes_transferred_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
unsigned long count = 0;
|
||||
|
@ -127,8 +129,10 @@ static ssize_t show_bytes_transferred(struct device *dev, struct device_attribut
|
|||
|
||||
return err;
|
||||
}
|
||||
static DEVICE_ATTR_RO(bytes_transferred);
|
||||
|
||||
static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t in_use_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
int err;
|
||||
|
@ -143,13 +147,15 @@ static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, ch
|
|||
|
||||
return err;
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_use);
|
||||
|
||||
static struct device_attribute dma_attrs[] = {
|
||||
__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
|
||||
__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
|
||||
__ATTR(in_use, S_IRUGO, show_in_use, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *dma_dev_attrs[] = {
|
||||
&dev_attr_memcpy_count.attr,
|
||||
&dev_attr_bytes_transferred.attr,
|
||||
&dev_attr_in_use.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(dma_dev);
|
||||
|
||||
static void chan_dev_release(struct device *dev)
|
||||
{
|
||||
|
@ -167,7 +173,7 @@ static void chan_dev_release(struct device *dev)
|
|||
|
||||
static struct class dma_devclass = {
|
||||
.name = "dma",
|
||||
.dev_attrs = dma_attrs,
|
||||
.dev_groups = dma_dev_groups,
|
||||
.dev_release = chan_dev_release,
|
||||
};
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(state);
|
||||
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -163,6 +164,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return sprintf(buf, "%s\n", dev_name(edev->dev));
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t cable_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -527,11 +529,12 @@ int extcon_unregister_notifier(struct extcon_dev *edev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
|
||||
|
||||
static struct device_attribute extcon_attrs[] = {
|
||||
__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
|
||||
__ATTR_RO(name),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *extcon_attrs[] = {
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_name.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(extcon);
|
||||
|
||||
static int create_extcon_class(void)
|
||||
{
|
||||
|
@ -539,7 +542,7 @@ static int create_extcon_class(void)
|
|||
extcon_class = class_create(THIS_MODULE, "extcon");
|
||||
if (IS_ERR(extcon_class))
|
||||
return PTR_ERR(extcon_class);
|
||||
extcon_class->dev_attrs = extcon_attrs;
|
||||
extcon_class->dev_groups = extcon_groups;
|
||||
|
||||
#if defined(CONFIG_ANDROID)
|
||||
switch_class = class_compat_register("switch");
|
||||
|
|
|
@ -535,11 +535,12 @@ static struct attribute *dcdbas_dev_attrs[] = {
|
|||
|
||||
static struct attribute_group dcdbas_attr_group = {
|
||||
.attrs = dcdbas_dev_attrs,
|
||||
.bin_attrs = dcdbas_bin_attrs,
|
||||
};
|
||||
|
||||
static int dcdbas_probe(struct platform_device *dev)
|
||||
{
|
||||
int i, error;
|
||||
int error;
|
||||
|
||||
host_control_action = HC_ACTION_NONE;
|
||||
host_control_smi_type = HC_SMITYPE_NONE;
|
||||
|
@ -555,18 +556,6 @@ static int dcdbas_probe(struct platform_device *dev)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
for (i = 0; dcdbas_bin_attrs[i]; i++) {
|
||||
error = sysfs_create_bin_file(&dev->dev.kobj,
|
||||
dcdbas_bin_attrs[i]);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
sysfs_remove_bin_file(&dev->dev.kobj,
|
||||
dcdbas_bin_attrs[i]);
|
||||
sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
register_reboot_notifier(&dcdbas_reboot_nb);
|
||||
|
||||
dev_info(&dev->dev, "%s (version %s)\n",
|
||||
|
@ -577,11 +566,7 @@ static int dcdbas_probe(struct platform_device *dev)
|
|||
|
||||
static int dcdbas_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
unregister_reboot_notifier(&dcdbas_reboot_nb);
|
||||
for (i = 0; dcdbas_bin_attrs[i]; i++)
|
||||
sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]);
|
||||
sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1917,11 +1917,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
|||
|
||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct device_attribute hid_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *hid_dev_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(hid_dev);
|
||||
|
||||
static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
|
@ -1949,7 +1951,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
|
||||
static struct bus_type hid_bus_type = {
|
||||
.name = "hid",
|
||||
.dev_attrs = hid_dev_attrs,
|
||||
.dev_groups = hid_dev_groups,
|
||||
.match = hid_bus_match,
|
||||
.probe = hid_device_probe,
|
||||
.remove = hid_device_remove,
|
||||
|
|
|
@ -75,6 +75,8 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(mode_key, 0660,
|
||||
arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key);
|
||||
|
||||
static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -123,6 +125,8 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(key_mask, 0660,
|
||||
arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask);
|
||||
|
||||
/* retval is 1-5 on success, < 0 on error */
|
||||
static int arvo_get_actual_profile(struct usb_device *usb_dev)
|
||||
|
@ -179,6 +183,9 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
|
|||
mutex_unlock(&arvo->arvo_lock);
|
||||
return retval;
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0660,
|
||||
arvo_sysfs_show_actual_profile,
|
||||
arvo_sysfs_set_actual_profile);
|
||||
|
||||
static ssize_t arvo_sysfs_write(struct file *fp,
|
||||
struct kobject *kobj, void const *buf,
|
||||
|
@ -230,6 +237,8 @@ static ssize_t arvo_sysfs_write_button(struct file *fp,
|
|||
return arvo_sysfs_write(fp, kobj, buf, off, count,
|
||||
sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
|
||||
}
|
||||
static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button,
|
||||
sizeof(struct arvo_button));
|
||||
|
||||
static ssize_t arvo_sysfs_read_info(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
|
@ -238,31 +247,30 @@ static ssize_t arvo_sysfs_read_info(struct file *fp,
|
|||
return arvo_sysfs_read(fp, kobj, buf, off, count,
|
||||
sizeof(struct arvo_info), ARVO_COMMAND_INFO);
|
||||
}
|
||||
static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
|
||||
sizeof(struct arvo_info));
|
||||
|
||||
|
||||
static struct device_attribute arvo_attributes[] = {
|
||||
__ATTR(mode_key, 0660,
|
||||
arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key),
|
||||
__ATTR(key_mask, 0660,
|
||||
arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask),
|
||||
__ATTR(actual_profile, 0660,
|
||||
arvo_sysfs_show_actual_profile,
|
||||
arvo_sysfs_set_actual_profile),
|
||||
__ATTR_NULL
|
||||
static struct attribute *arvo_attrs[] = {
|
||||
&dev_attr_mode_key.attr,
|
||||
&dev_attr_key_mask.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute arvo_bin_attributes[] = {
|
||||
{
|
||||
.attr = { .name = "button", .mode = 0220 },
|
||||
.size = sizeof(struct arvo_button),
|
||||
.write = arvo_sysfs_write_button
|
||||
},
|
||||
{
|
||||
.attr = { .name = "info", .mode = 0440 },
|
||||
.size = sizeof(struct arvo_info),
|
||||
.read = arvo_sysfs_read_info
|
||||
},
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *arvo_bin_attributes[] = {
|
||||
&bin_attr_button,
|
||||
&bin_attr_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group arvo_group = {
|
||||
.attrs = arvo_attrs,
|
||||
.bin_attrs = arvo_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *arvo_groups[] = {
|
||||
&arvo_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -430,8 +438,7 @@ static int __init arvo_init(void)
|
|||
arvo_class = class_create(THIS_MODULE, "arvo");
|
||||
if (IS_ERR(arvo_class))
|
||||
return PTR_ERR(arvo_class);
|
||||
arvo_class->dev_attrs = arvo_attributes;
|
||||
arvo_class->dev_bin_attrs = arvo_bin_attributes;
|
||||
arvo_class->dev_groups = arvo_groups;
|
||||
|
||||
retval = hid_register_driver(&arvo_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -109,12 +109,12 @@ static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0660, isku_sysfs_show_actual_profile,
|
||||
isku_sysfs_set_actual_profile);
|
||||
|
||||
static struct device_attribute isku_attributes[] = {
|
||||
__ATTR(actual_profile, 0660,
|
||||
isku_sysfs_show_actual_profile,
|
||||
isku_sysfs_set_actual_profile),
|
||||
__ATTR_NULL
|
||||
static struct attribute *isku_attrs[] = {
|
||||
&dev_attr_actual_profile.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
|
||||
|
@ -184,7 +184,8 @@ ISKU_SYSFS_R(thingy, THINGY) \
|
|||
ISKU_SYSFS_W(thingy, THINGY)
|
||||
|
||||
#define ISKU_BIN_ATTR_RW(thingy, THINGY) \
|
||||
{ \
|
||||
ISKU_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = ISKU_SIZE_ ## THINGY, \
|
||||
.read = isku_sysfs_read_ ## thingy, \
|
||||
|
@ -192,52 +193,64 @@ ISKU_SYSFS_W(thingy, THINGY)
|
|||
}
|
||||
|
||||
#define ISKU_BIN_ATTR_R(thingy, THINGY) \
|
||||
{ \
|
||||
ISKU_SYSFS_R(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = ISKU_SIZE_ ## THINGY, \
|
||||
.read = isku_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define ISKU_BIN_ATTR_W(thingy, THINGY) \
|
||||
{ \
|
||||
ISKU_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = ISKU_SIZE_ ## THINGY, \
|
||||
.write = isku_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
ISKU_SYSFS_RW(macro, MACRO)
|
||||
ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION)
|
||||
ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE)
|
||||
ISKU_SYSFS_RW(keys_media, KEYS_MEDIA)
|
||||
ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER)
|
||||
ISKU_SYSFS_RW(keys_macro, KEYS_MACRO)
|
||||
ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK)
|
||||
ISKU_SYSFS_RW(light, LIGHT)
|
||||
ISKU_SYSFS_RW(key_mask, KEY_MASK)
|
||||
ISKU_SYSFS_RW(last_set, LAST_SET)
|
||||
ISKU_SYSFS_W(talk, TALK)
|
||||
ISKU_SYSFS_W(talkfx, TALKFX)
|
||||
ISKU_SYSFS_R(info, INFO)
|
||||
ISKU_SYSFS_W(control, CONTROL)
|
||||
ISKU_SYSFS_W(reset, RESET)
|
||||
ISKU_BIN_ATTR_RW(macro, MACRO);
|
||||
ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION);
|
||||
ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE);
|
||||
ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA);
|
||||
ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER);
|
||||
ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO);
|
||||
ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK);
|
||||
ISKU_BIN_ATTR_RW(light, LIGHT);
|
||||
ISKU_BIN_ATTR_RW(key_mask, KEY_MASK);
|
||||
ISKU_BIN_ATTR_RW(last_set, LAST_SET);
|
||||
ISKU_BIN_ATTR_W(talk, TALK);
|
||||
ISKU_BIN_ATTR_W(talkfx, TALKFX);
|
||||
ISKU_BIN_ATTR_W(control, CONTROL);
|
||||
ISKU_BIN_ATTR_W(reset, RESET);
|
||||
ISKU_BIN_ATTR_R(info, INFO);
|
||||
|
||||
static struct bin_attribute isku_bin_attributes[] = {
|
||||
ISKU_BIN_ATTR_RW(macro, MACRO),
|
||||
ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
|
||||
ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
|
||||
ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
|
||||
ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
|
||||
ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
|
||||
ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
|
||||
ISKU_BIN_ATTR_RW(light, LIGHT),
|
||||
ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
|
||||
ISKU_BIN_ATTR_RW(last_set, LAST_SET),
|
||||
ISKU_BIN_ATTR_W(talk, TALK),
|
||||
ISKU_BIN_ATTR_W(talkfx, TALKFX),
|
||||
ISKU_BIN_ATTR_R(info, INFO),
|
||||
ISKU_BIN_ATTR_W(control, CONTROL),
|
||||
ISKU_BIN_ATTR_W(reset, RESET),
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *isku_bin_attributes[] = {
|
||||
&bin_attr_macro,
|
||||
&bin_attr_keys_function,
|
||||
&bin_attr_keys_easyzone,
|
||||
&bin_attr_keys_media,
|
||||
&bin_attr_keys_thumbster,
|
||||
&bin_attr_keys_macro,
|
||||
&bin_attr_keys_capslock,
|
||||
&bin_attr_light,
|
||||
&bin_attr_key_mask,
|
||||
&bin_attr_last_set,
|
||||
&bin_attr_talk,
|
||||
&bin_attr_talkfx,
|
||||
&bin_attr_control,
|
||||
&bin_attr_reset,
|
||||
&bin_attr_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group isku_group = {
|
||||
.attrs = isku_attrs,
|
||||
.bin_attrs = isku_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *isku_groups[] = {
|
||||
&isku_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int isku_init_isku_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -427,8 +440,7 @@ static int __init isku_init(void)
|
|||
isku_class = class_create(THIS_MODULE, "isku");
|
||||
if (IS_ERR(isku_class))
|
||||
return PTR_ERR(isku_class);
|
||||
isku_class->dev_attrs = isku_attributes;
|
||||
isku_class->dev_bin_attrs = isku_bin_attributes;
|
||||
isku_class->dev_groups = isku_groups;
|
||||
|
||||
retval = hid_register_driver(&isku_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -324,6 +324,8 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
|
|||
|
||||
return sizeof(struct kone_settings);
|
||||
}
|
||||
static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
|
||||
kone_sysfs_write_settings, sizeof(struct kone_settings));
|
||||
|
||||
static ssize_t kone_sysfs_read_profilex(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr,
|
||||
|
@ -378,6 +380,19 @@ static ssize_t kone_sysfs_write_profilex(struct file *fp,
|
|||
|
||||
return sizeof(struct kone_profile);
|
||||
}
|
||||
#define PROFILE_ATTR(number) \
|
||||
static struct bin_attribute bin_attr_profile##number = { \
|
||||
.attr = { .name = "profile##number", .mode = 0660 }, \
|
||||
.size = sizeof(struct kone_profile), \
|
||||
.read = kone_sysfs_read_profilex, \
|
||||
.write = kone_sysfs_write_profilex, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
};
|
||||
PROFILE_ATTR(1);
|
||||
PROFILE_ATTR(2);
|
||||
PROFILE_ATTR(3);
|
||||
PROFILE_ATTR(4);
|
||||
PROFILE_ATTR(5);
|
||||
|
||||
static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -386,6 +401,7 @@ static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
|
||||
|
||||
static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -394,6 +410,7 @@ static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
|
||||
}
|
||||
static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
|
||||
|
||||
/* weight is read each time, since we don't get informed when it's changed */
|
||||
static ssize_t kone_sysfs_show_weight(struct device *dev,
|
||||
|
@ -416,6 +433,7 @@ static ssize_t kone_sysfs_show_weight(struct device *dev,
|
|||
return retval;
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", weight);
|
||||
}
|
||||
static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
|
||||
|
||||
static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -424,6 +442,8 @@ static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
|
||||
}
|
||||
static DEVICE_ATTR(firmware_version, 0440, kone_sysfs_show_firmware_version,
|
||||
NULL);
|
||||
|
||||
static ssize_t kone_sysfs_show_tcu(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -524,6 +544,7 @@ exit_unlock:
|
|||
mutex_unlock(&kone->kone_lock);
|
||||
return retval;
|
||||
}
|
||||
static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
|
||||
|
||||
static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -570,15 +591,17 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
|
|||
mutex_unlock(&kone->kone_lock);
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile,
|
||||
kone_sysfs_set_startup_profile);
|
||||
|
||||
static struct device_attribute kone_attributes[] = {
|
||||
static struct attribute *kone_attrs[] = {
|
||||
/*
|
||||
* Read actual dpi settings.
|
||||
* Returns raw value for further processing. Refer to enum
|
||||
* kone_polling_rates to get real value.
|
||||
*/
|
||||
__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
|
||||
__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
|
||||
&dev_attr_actual_dpi.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
|
||||
/*
|
||||
* The mouse can be equipped with one of four supplied weights from 5
|
||||
|
@ -587,7 +610,7 @@ static struct device_attribute kone_attributes[] = {
|
|||
* by software. Refer to enum kone_weights to get corresponding real
|
||||
* weight.
|
||||
*/
|
||||
__ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
|
||||
&dev_attr_weight.attr,
|
||||
|
||||
/*
|
||||
* Prints firmware version stored in mouse as integer.
|
||||
|
@ -595,66 +618,38 @@ static struct device_attribute kone_attributes[] = {
|
|||
* to get the real version number the decimal point has to be shifted 2
|
||||
* positions to the left. E.g. a value of 138 means 1.38.
|
||||
*/
|
||||
__ATTR(firmware_version, 0440,
|
||||
kone_sysfs_show_firmware_version, NULL),
|
||||
&dev_attr_firmware_version.attr,
|
||||
|
||||
/*
|
||||
* Prints state of Tracking Control Unit as number where 0 = off and
|
||||
* 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
|
||||
* activates the tcu
|
||||
*/
|
||||
__ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
|
||||
&dev_attr_tcu.attr,
|
||||
|
||||
/* Prints and takes the number of the profile the mouse starts with */
|
||||
__ATTR(startup_profile, 0660,
|
||||
kone_sysfs_show_startup_profile,
|
||||
kone_sysfs_set_startup_profile),
|
||||
__ATTR_NULL
|
||||
&dev_attr_startup_profile.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_bin_attributes[] = {
|
||||
{
|
||||
.attr = { .name = "settings", .mode = 0660 },
|
||||
.size = sizeof(struct kone_settings),
|
||||
.read = kone_sysfs_read_settings,
|
||||
.write = kone_sysfs_write_settings
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *kone_bin_attributes[] = {
|
||||
&bin_attr_settings,
|
||||
&bin_attr_profile1,
|
||||
&bin_attr_profile2,
|
||||
&bin_attr_profile3,
|
||||
&bin_attr_profile4,
|
||||
&bin_attr_profile5,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group kone_group = {
|
||||
.attrs = kone_attrs,
|
||||
.bin_attrs = kone_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *kone_groups[] = {
|
||||
&kone_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int kone_init_kone_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -891,8 +886,7 @@ static int __init kone_init(void)
|
|||
kone_class = class_create(THIS_MODULE, "kone");
|
||||
if (IS_ERR(kone_class))
|
||||
return PTR_ERR(kone_class);
|
||||
kone_class->dev_attrs = kone_attributes;
|
||||
kone_class->dev_bin_attrs = kone_bin_attributes;
|
||||
kone_class->dev_groups = kone_groups;
|
||||
|
||||
retval = hid_register_driver(&kone_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -156,7 +156,8 @@ KONEPLUS_SYSFS_W(thingy, THINGY) \
|
|||
KONEPLUS_SYSFS_R(thingy, THINGY)
|
||||
|
||||
#define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPLUS_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = KONEPLUS_SIZE_ ## THINGY, \
|
||||
.read = koneplus_sysfs_read_ ## thingy, \
|
||||
|
@ -164,28 +165,29 @@ KONEPLUS_SYSFS_R(thingy, THINGY)
|
|||
}
|
||||
|
||||
#define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPLUS_SYSFS_R(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = KONEPLUS_SIZE_ ## THINGY, \
|
||||
.read = koneplus_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPLUS_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = KONEPLUS_SIZE_ ## THINGY, \
|
||||
.write = koneplus_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
KONEPLUS_SYSFS_W(control, CONTROL)
|
||||
KONEPLUS_SYSFS_RW(info, INFO)
|
||||
KONEPLUS_SYSFS_W(talk, TALK)
|
||||
KONEPLUS_SYSFS_W(macro, MACRO)
|
||||
KONEPLUS_SYSFS_RW(sensor, SENSOR)
|
||||
KONEPLUS_SYSFS_RW(tcu, TCU)
|
||||
KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
|
||||
KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
|
||||
KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK);
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO);
|
||||
KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO);
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR);
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU);
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
|
||||
|
||||
static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
|
@ -225,6 +227,25 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
|
|||
KONEPLUS_COMMAND_PROFILE_BUTTONS);
|
||||
}
|
||||
|
||||
#define PROFILE_ATTR(number) \
|
||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, \
|
||||
.read = koneplus_sysfs_read_profilex_settings, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
}; \
|
||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS, \
|
||||
.read = koneplus_sysfs_read_profilex_buttons, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
};
|
||||
PROFILE_ATTR(1);
|
||||
PROFILE_ATTR(2);
|
||||
PROFILE_ATTR(3);
|
||||
PROFILE_ATTR(4);
|
||||
PROFILE_ATTR(5);
|
||||
|
||||
static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -274,6 +295,12 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0660,
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile);
|
||||
static DEVICE_ATTR(startup_profile, 0660,
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile);
|
||||
|
||||
static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -293,90 +320,47 @@ static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
|
|||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
|
||||
}
|
||||
static DEVICE_ATTR(firmware_version, 0440,
|
||||
koneplus_sysfs_show_firmware_version, NULL);
|
||||
|
||||
static struct device_attribute koneplus_attributes[] = {
|
||||
__ATTR(actual_profile, 0660,
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile),
|
||||
__ATTR(startup_profile, 0660,
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile),
|
||||
__ATTR(firmware_version, 0440,
|
||||
koneplus_sysfs_show_firmware_version, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *koneplus_attrs[] = {
|
||||
&dev_attr_actual_profile.attr,
|
||||
&dev_attr_startup_profile.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute koneplus_bin_attributes[] = {
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
|
||||
KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
|
||||
KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
|
||||
KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
|
||||
{
|
||||
.attr = { .name = "profile1_settings", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_settings", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_settings", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_settings", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_settings", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_buttons", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_buttons", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_buttons", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_buttons", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_buttons", .mode = 0440 },
|
||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *koneplus_bin_attributes[] = {
|
||||
&bin_attr_control,
|
||||
&bin_attr_talk,
|
||||
&bin_attr_macro,
|
||||
&bin_attr_tcu_image,
|
||||
&bin_attr_info,
|
||||
&bin_attr_sensor,
|
||||
&bin_attr_tcu,
|
||||
&bin_attr_profile_settings,
|
||||
&bin_attr_profile_buttons,
|
||||
&bin_attr_profile1_settings,
|
||||
&bin_attr_profile2_settings,
|
||||
&bin_attr_profile3_settings,
|
||||
&bin_attr_profile4_settings,
|
||||
&bin_attr_profile5_settings,
|
||||
&bin_attr_profile1_buttons,
|
||||
&bin_attr_profile2_buttons,
|
||||
&bin_attr_profile3_buttons,
|
||||
&bin_attr_profile4_buttons,
|
||||
&bin_attr_profile5_buttons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group koneplus_group = {
|
||||
.attrs = koneplus_attrs,
|
||||
.bin_attrs = koneplus_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *koneplus_groups[] = {
|
||||
&koneplus_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -572,8 +556,7 @@ static int __init koneplus_init(void)
|
|||
koneplus_class = class_create(THIS_MODULE, "koneplus");
|
||||
if (IS_ERR(koneplus_class))
|
||||
return PTR_ERR(koneplus_class);
|
||||
koneplus_class->dev_attrs = koneplus_attributes;
|
||||
koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
|
||||
koneplus_class->dev_groups = koneplus_groups;
|
||||
|
||||
retval = hid_register_driver(&koneplus_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -94,7 +94,8 @@ KONEPURE_SYSFS_W(thingy, THINGY) \
|
|||
KONEPURE_SYSFS_R(thingy, THINGY)
|
||||
|
||||
#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPURE_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = KONEPURE_SIZE_ ## THINGY, \
|
||||
.read = konepure_sysfs_read_ ## thingy, \
|
||||
|
@ -102,44 +103,56 @@ KONEPURE_SYSFS_R(thingy, THINGY)
|
|||
}
|
||||
|
||||
#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPURE_SYSFS_R(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = KONEPURE_SIZE_ ## THINGY, \
|
||||
.read = konepure_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \
|
||||
{ \
|
||||
KONEPURE_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = KONEPURE_SIZE_ ## THINGY, \
|
||||
.write = konepure_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE)
|
||||
KONEPURE_SYSFS_W(control, CONTROL)
|
||||
KONEPURE_SYSFS_RW(info, INFO)
|
||||
KONEPURE_SYSFS_W(talk, TALK)
|
||||
KONEPURE_SYSFS_W(macro, MACRO)
|
||||
KONEPURE_SYSFS_RW(sensor, SENSOR)
|
||||
KONEPURE_SYSFS_RW(tcu, TCU)
|
||||
KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE)
|
||||
KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
|
||||
KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE);
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(info, INFO);
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR);
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU);
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
|
||||
KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL);
|
||||
KONEPURE_BIN_ATTRIBUTE_W(talk, TALK);
|
||||
KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO);
|
||||
KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
|
||||
|
||||
static struct bin_attribute konepure_bin_attributes[] = {
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE),
|
||||
KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL),
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(info, INFO),
|
||||
KONEPURE_BIN_ATTRIBUTE_W(talk, TALK),
|
||||
KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO),
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR),
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU),
|
||||
KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
|
||||
KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *konepure_bin_attributes[] = {
|
||||
&bin_attr_actual_profile,
|
||||
&bin_attr_info,
|
||||
&bin_attr_sensor,
|
||||
&bin_attr_tcu,
|
||||
&bin_attr_profile_settings,
|
||||
&bin_attr_profile_buttons,
|
||||
&bin_attr_control,
|
||||
&bin_attr_talk,
|
||||
&bin_attr_macro,
|
||||
&bin_attr_tcu_image,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group konepure_group = {
|
||||
.bin_attrs = konepure_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *konepure_groups[] = {
|
||||
&konepure_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
|
||||
struct konepure_device *konepure)
|
||||
{
|
||||
|
@ -282,7 +295,7 @@ static int __init konepure_init(void)
|
|||
konepure_class = class_create(THIS_MODULE, "konepure");
|
||||
if (IS_ERR(konepure_class))
|
||||
return PTR_ERR(konepure_class);
|
||||
konepure_class->dev_bin_attrs = konepure_bin_attributes;
|
||||
konepure_class->dev_groups = konepure_groups;
|
||||
|
||||
retval = hid_register_driver(&konepure_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -197,31 +197,25 @@ KOVAPLUS_SYSFS_W(thingy, THINGY) \
|
|||
KOVAPLUS_SYSFS_R(thingy, THINGY)
|
||||
|
||||
#define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
|
||||
{ \
|
||||
KOVAPLUS_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = KOVAPLUS_SIZE_ ## THINGY, \
|
||||
.read = kovaplus_sysfs_read_ ## thingy, \
|
||||
.write = kovaplus_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
|
||||
{ \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = KOVAPLUS_SIZE_ ## THINGY, \
|
||||
.read = kovaplus_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
|
||||
{ \
|
||||
KOVAPLUS_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = KOVAPLUS_SIZE_ ## THINGY, \
|
||||
.write = kovaplus_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
KOVAPLUS_SYSFS_W(control, CONTROL)
|
||||
KOVAPLUS_SYSFS_RW(info, INFO)
|
||||
KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
|
||||
KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
|
||||
KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO);
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
|
||||
|
||||
static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
|
@ -261,6 +255,25 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
|
|||
KOVAPLUS_COMMAND_PROFILE_BUTTONS);
|
||||
}
|
||||
|
||||
#define PROFILE_ATTR(number) \
|
||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \
|
||||
.read = kovaplus_sysfs_read_profilex_settings, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
}; \
|
||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \
|
||||
.read = kovaplus_sysfs_read_profilex_buttons, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
};
|
||||
PROFILE_ATTR(1);
|
||||
PROFILE_ATTR(2);
|
||||
PROFILE_ATTR(3);
|
||||
PROFILE_ATTR(4);
|
||||
PROFILE_ATTR(5);
|
||||
|
||||
static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -310,6 +323,9 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0660,
|
||||
kovaplus_sysfs_show_actual_profile,
|
||||
kovaplus_sysfs_set_actual_profile);
|
||||
|
||||
static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -318,6 +334,7 @@ static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
|
||||
}
|
||||
static DEVICE_ATTR(actual_cpi, 0440, kovaplus_sysfs_show_actual_cpi, NULL);
|
||||
|
||||
static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -326,6 +343,8 @@ static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
|
||||
}
|
||||
static DEVICE_ATTR(actual_sensitivity_x, 0440,
|
||||
kovaplus_sysfs_show_actual_sensitivity_x, NULL);
|
||||
|
||||
static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -334,6 +353,8 @@ static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
|
||||
}
|
||||
static DEVICE_ATTR(actual_sensitivity_y, 0440,
|
||||
kovaplus_sysfs_show_actual_sensitivity_y, NULL);
|
||||
|
||||
static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -353,88 +374,44 @@ static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
|
|||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
|
||||
}
|
||||
static DEVICE_ATTR(firmware_version, 0440,
|
||||
kovaplus_sysfs_show_firmware_version, NULL);
|
||||
|
||||
static struct device_attribute kovaplus_attributes[] = {
|
||||
__ATTR(actual_cpi, 0440,
|
||||
kovaplus_sysfs_show_actual_cpi, NULL),
|
||||
__ATTR(firmware_version, 0440,
|
||||
kovaplus_sysfs_show_firmware_version, NULL),
|
||||
__ATTR(actual_profile, 0660,
|
||||
kovaplus_sysfs_show_actual_profile,
|
||||
kovaplus_sysfs_set_actual_profile),
|
||||
__ATTR(actual_sensitivity_x, 0440,
|
||||
kovaplus_sysfs_show_actual_sensitivity_x, NULL),
|
||||
__ATTR(actual_sensitivity_y, 0440,
|
||||
kovaplus_sysfs_show_actual_sensitivity_y, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *kovaplus_attrs[] = {
|
||||
&dev_attr_actual_cpi.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
&dev_attr_actual_sensitivity_x.attr,
|
||||
&dev_attr_actual_sensitivity_y.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute kovaplus_bin_attributes[] = {
|
||||
KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
|
||||
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
|
||||
{
|
||||
.attr = { .name = "profile1_settings", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = kovaplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_settings", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = kovaplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_settings", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = kovaplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_settings", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = kovaplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_settings", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
|
||||
.read = kovaplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_buttons", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = kovaplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_buttons", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = kovaplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_buttons", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = kovaplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_buttons", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = kovaplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_buttons", .mode = 0440 },
|
||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
|
||||
.read = kovaplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *kovaplus_bin_attributes[] = {
|
||||
&bin_attr_control,
|
||||
&bin_attr_info,
|
||||
&bin_attr_profile_settings,
|
||||
&bin_attr_profile_buttons,
|
||||
&bin_attr_profile1_settings,
|
||||
&bin_attr_profile2_settings,
|
||||
&bin_attr_profile3_settings,
|
||||
&bin_attr_profile4_settings,
|
||||
&bin_attr_profile5_settings,
|
||||
&bin_attr_profile1_buttons,
|
||||
&bin_attr_profile2_buttons,
|
||||
&bin_attr_profile3_buttons,
|
||||
&bin_attr_profile4_buttons,
|
||||
&bin_attr_profile5_buttons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group kovaplus_group = {
|
||||
.attrs = kovaplus_attrs,
|
||||
.bin_attrs = kovaplus_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *kovaplus_groups[] = {
|
||||
&kovaplus_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -662,8 +639,7 @@ static int __init kovaplus_init(void)
|
|||
kovaplus_class = class_create(THIS_MODULE, "kovaplus");
|
||||
if (IS_ERR(kovaplus_class))
|
||||
return PTR_ERR(kovaplus_class);
|
||||
kovaplus_class->dev_attrs = kovaplus_attributes;
|
||||
kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
|
||||
kovaplus_class->dev_groups = kovaplus_groups;
|
||||
|
||||
retval = hid_register_driver(&kovaplus_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -156,7 +156,8 @@ PYRA_SYSFS_W(thingy, THINGY) \
|
|||
PYRA_SYSFS_R(thingy, THINGY)
|
||||
|
||||
#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
|
||||
{ \
|
||||
PYRA_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = PYRA_SIZE_ ## THINGY, \
|
||||
.read = pyra_sysfs_read_ ## thingy, \
|
||||
|
@ -164,24 +165,25 @@ PYRA_SYSFS_R(thingy, THINGY)
|
|||
}
|
||||
|
||||
#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
|
||||
{ \
|
||||
PYRA_SYSFS_R(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = PYRA_SIZE_ ## THINGY, \
|
||||
.read = pyra_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
|
||||
{ \
|
||||
PYRA_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = PYRA_SIZE_ ## THINGY, \
|
||||
.write = pyra_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
PYRA_SYSFS_W(control, CONTROL)
|
||||
PYRA_SYSFS_RW(info, INFO)
|
||||
PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
|
||||
PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
|
||||
PYRA_SYSFS_R(settings, SETTINGS)
|
||||
PYRA_BIN_ATTRIBUTE_W(control, CONTROL);
|
||||
PYRA_BIN_ATTRIBUTE_RW(info, INFO);
|
||||
PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
|
||||
PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
|
||||
|
||||
static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
|
@ -221,6 +223,25 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
|
|||
PYRA_COMMAND_PROFILE_BUTTONS);
|
||||
}
|
||||
|
||||
#define PROFILE_ATTR(number) \
|
||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS, \
|
||||
.read = pyra_sysfs_read_profilex_settings, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
}; \
|
||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS, \
|
||||
.read = pyra_sysfs_read_profilex_buttons, \
|
||||
.private = &profile_numbers[number-1], \
|
||||
};
|
||||
PROFILE_ATTR(1);
|
||||
PROFILE_ATTR(2);
|
||||
PROFILE_ATTR(3);
|
||||
PROFILE_ATTR(4);
|
||||
PROFILE_ATTR(5);
|
||||
|
||||
static ssize_t pyra_sysfs_write_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
|
@ -258,6 +279,11 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
|
|||
return PYRA_SIZE_SETTINGS;
|
||||
}
|
||||
|
||||
PYRA_SYSFS_R(settings, SETTINGS);
|
||||
static struct bin_attribute bin_attr_settings =
|
||||
__BIN_ATTR(settings, (S_IWUSR | S_IRUGO),
|
||||
pyra_sysfs_read_settings, pyra_sysfs_write_settings,
|
||||
PYRA_SIZE_SETTINGS);
|
||||
|
||||
static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -266,6 +292,7 @@ static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
|
|||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
|
||||
}
|
||||
static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
|
||||
|
||||
static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -282,6 +309,8 @@ static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
|
|||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
|
||||
}
|
||||
static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
|
||||
static DEVICE_ATTR(startup_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
|
||||
|
||||
static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -301,84 +330,44 @@ static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
|
|||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
|
||||
}
|
||||
static DEVICE_ATTR(firmware_version, 0440, pyra_sysfs_show_firmware_version,
|
||||
NULL);
|
||||
|
||||
static struct device_attribute pyra_attributes[] = {
|
||||
__ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL),
|
||||
__ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL),
|
||||
__ATTR(firmware_version, 0440,
|
||||
pyra_sysfs_show_firmware_version, NULL),
|
||||
__ATTR(startup_profile, 0440,
|
||||
pyra_sysfs_show_actual_profile, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *pyra_attrs[] = {
|
||||
&dev_attr_actual_cpi.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
&dev_attr_startup_profile.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_bin_attributes[] = {
|
||||
PYRA_BIN_ATTRIBUTE_W(control, CONTROL),
|
||||
PYRA_BIN_ATTRIBUTE_RW(info, INFO),
|
||||
PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
|
||||
PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
|
||||
PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS),
|
||||
{
|
||||
.attr = { .name = "profile1_settings", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS,
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_settings", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS,
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_settings", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS,
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_settings", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS,
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_settings", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_SETTINGS,
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_buttons", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS,
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_buttons", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS,
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_buttons", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS,
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_buttons", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS,
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_buttons", .mode = 0440 },
|
||||
.size = PYRA_SIZE_PROFILE_BUTTONS,
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *pyra_bin_attributes[] = {
|
||||
&bin_attr_control,
|
||||
&bin_attr_info,
|
||||
&bin_attr_profile_settings,
|
||||
&bin_attr_profile_buttons,
|
||||
&bin_attr_settings,
|
||||
&bin_attr_profile1_settings,
|
||||
&bin_attr_profile2_settings,
|
||||
&bin_attr_profile3_settings,
|
||||
&bin_attr_profile4_settings,
|
||||
&bin_attr_profile5_settings,
|
||||
&bin_attr_profile1_buttons,
|
||||
&bin_attr_profile2_buttons,
|
||||
&bin_attr_profile3_buttons,
|
||||
&bin_attr_profile4_buttons,
|
||||
&bin_attr_profile5_buttons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group pyra_group = {
|
||||
.attrs = pyra_attrs,
|
||||
.bin_attrs = pyra_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *pyra_groups[] = {
|
||||
&pyra_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -600,8 +589,7 @@ static int __init pyra_init(void)
|
|||
pyra_class = class_create(THIS_MODULE, "pyra");
|
||||
if (IS_ERR(pyra_class))
|
||||
return PTR_ERR(pyra_class);
|
||||
pyra_class->dev_attrs = pyra_attributes;
|
||||
pyra_class->dev_bin_attrs = pyra_bin_attributes;
|
||||
pyra_class->dev_groups = pyra_groups;
|
||||
|
||||
retval = hid_register_driver(&pyra_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -94,44 +94,48 @@ SAVU_SYSFS_W(thingy, THINGY) \
|
|||
SAVU_SYSFS_R(thingy, THINGY)
|
||||
|
||||
#define SAVU_BIN_ATTRIBUTE_RW(thingy, THINGY) \
|
||||
{ \
|
||||
SAVU_SYSFS_RW(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0660 }, \
|
||||
.size = SAVU_SIZE_ ## THINGY, \
|
||||
.read = savu_sysfs_read_ ## thingy, \
|
||||
.write = savu_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
#define SAVU_BIN_ATTRIBUTE_R(thingy, THINGY) \
|
||||
{ \
|
||||
.attr = { .name = #thingy, .mode = 0440 }, \
|
||||
.size = SAVU_SIZE_ ## THINGY, \
|
||||
.read = savu_sysfs_read_ ## thingy, \
|
||||
}
|
||||
|
||||
#define SAVU_BIN_ATTRIBUTE_W(thingy, THINGY) \
|
||||
{ \
|
||||
SAVU_SYSFS_W(thingy, THINGY); \
|
||||
static struct bin_attribute bin_attr_##thingy = { \
|
||||
.attr = { .name = #thingy, .mode = 0220 }, \
|
||||
.size = SAVU_SIZE_ ## THINGY, \
|
||||
.write = savu_sysfs_write_ ## thingy \
|
||||
}
|
||||
|
||||
SAVU_SYSFS_W(control, CONTROL)
|
||||
SAVU_SYSFS_RW(profile, PROFILE)
|
||||
SAVU_SYSFS_RW(general, GENERAL)
|
||||
SAVU_SYSFS_RW(buttons, BUTTONS)
|
||||
SAVU_SYSFS_RW(macro, MACRO)
|
||||
SAVU_SYSFS_RW(info, INFO)
|
||||
SAVU_SYSFS_RW(sensor, SENSOR)
|
||||
SAVU_BIN_ATTRIBUTE_W(control, CONTROL);
|
||||
SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE);
|
||||
SAVU_BIN_ATTRIBUTE_RW(general, GENERAL);
|
||||
SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS);
|
||||
SAVU_BIN_ATTRIBUTE_RW(macro, MACRO);
|
||||
SAVU_BIN_ATTRIBUTE_RW(info, INFO);
|
||||
SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR);
|
||||
|
||||
static struct bin_attribute savu_bin_attributes[] = {
|
||||
SAVU_BIN_ATTRIBUTE_W(control, CONTROL),
|
||||
SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE),
|
||||
SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
|
||||
SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
|
||||
SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
|
||||
SAVU_BIN_ATTRIBUTE_RW(info, INFO),
|
||||
SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
|
||||
__ATTR_NULL
|
||||
static struct bin_attribute *savu_bin_attributes[] = {
|
||||
&bin_attr_control,
|
||||
&bin_attr_profile,
|
||||
&bin_attr_general,
|
||||
&bin_attr_buttons,
|
||||
&bin_attr_macro,
|
||||
&bin_attr_info,
|
||||
&bin_attr_sensor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group savu_group = {
|
||||
.bin_attrs = savu_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *savu_groups[] = {
|
||||
&savu_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int savu_init_savu_device_struct(struct usb_device *usb_dev,
|
||||
|
@ -294,7 +298,7 @@ static int __init savu_init(void)
|
|||
savu_class = class_create(THIS_MODULE, "savu");
|
||||
if (IS_ERR(savu_class))
|
||||
return PTR_ERR(savu_class);
|
||||
savu_class->dev_bin_attrs = savu_bin_attributes;
|
||||
savu_class->dev_groups = savu_groups;
|
||||
|
||||
retval = hid_register_driver(&savu_driver);
|
||||
if (retval)
|
||||
|
|
|
@ -639,16 +639,18 @@ EXPORT_SYMBOL(gameport_unregister_port);
|
|||
* Gameport driver operations
|
||||
*/
|
||||
|
||||
static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
|
||||
static ssize_t description_show(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct gameport_driver *driver = to_gameport_driver(drv);
|
||||
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
|
||||
}
|
||||
static DRIVER_ATTR_RO(description);
|
||||
|
||||
static struct driver_attribute gameport_driver_attrs[] = {
|
||||
__ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *gameport_driver_attrs[] = {
|
||||
&driver_attr_description.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(gameport_driver);
|
||||
|
||||
static int gameport_driver_probe(struct device *dev)
|
||||
{
|
||||
|
@ -749,7 +751,7 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
|
|||
static struct bus_type gameport_bus = {
|
||||
.name = "gameport",
|
||||
.dev_attrs = gameport_device_attrs,
|
||||
.drv_attrs = gameport_driver_attrs,
|
||||
.drv_groups = gameport_driver_groups,
|
||||
.match = gameport_bus_match,
|
||||
.probe = gameport_driver_probe,
|
||||
.remove = gameport_driver_remove,
|
||||
|
|
|
@ -732,19 +732,20 @@ EXPORT_SYMBOL(serio_unregister_child_port);
|
|||
* Serio driver operations
|
||||
*/
|
||||
|
||||
static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
|
||||
static ssize_t description_show(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct serio_driver *driver = to_serio_driver(drv);
|
||||
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
|
||||
}
|
||||
static DRIVER_ATTR_RO(description);
|
||||
|
||||
static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
|
||||
static ssize_t bind_mode_show(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct serio_driver *serio_drv = to_serio_driver(drv);
|
||||
return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
|
||||
}
|
||||
|
||||
static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
|
||||
static ssize_t bind_mode_store(struct device_driver *drv, const char *buf, size_t count)
|
||||
{
|
||||
struct serio_driver *serio_drv = to_serio_driver(drv);
|
||||
int retval;
|
||||
|
@ -760,14 +761,14 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char
|
|||
|
||||
return retval;
|
||||
}
|
||||
static DRIVER_ATTR_RW(bind_mode);
|
||||
|
||||
|
||||
static struct driver_attribute serio_driver_attrs[] = {
|
||||
__ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
|
||||
__ATTR(bind_mode, S_IWUSR | S_IRUGO,
|
||||
serio_driver_show_bind_mode, serio_driver_set_bind_mode),
|
||||
__ATTR_NULL
|
||||
static struct attribute *serio_driver_attrs[] = {
|
||||
&driver_attr_description.attr,
|
||||
&driver_attr_bind_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(serio_driver);
|
||||
|
||||
static int serio_driver_probe(struct device *dev)
|
||||
{
|
||||
|
@ -996,7 +997,7 @@ EXPORT_SYMBOL(serio_interrupt);
|
|||
static struct bus_type serio_bus = {
|
||||
.name = "serio",
|
||||
.dev_attrs = serio_device_attrs,
|
||||
.drv_attrs = serio_driver_attrs,
|
||||
.drv_groups = serio_driver_groups,
|
||||
.match = serio_bus_match,
|
||||
.uevent = serio_uevent,
|
||||
.probe = serio_driver_probe,
|
||||
|
|
|
@ -37,8 +37,8 @@ static void mISDN_dev_release(struct device *dev)
|
|||
/* nothing to do: the device is part of its parent's data structure */
|
||||
}
|
||||
|
||||
static ssize_t _show_id(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
|
||||
|
@ -46,9 +46,10 @@ static ssize_t _show_id(struct device *dev,
|
|||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", mdev->id);
|
||||
}
|
||||
static DEVICE_ATTR_RO(id);
|
||||
|
||||
static ssize_t _show_nrbchan(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t nrbchan_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
|
||||
|
@ -56,9 +57,10 @@ static ssize_t _show_nrbchan(struct device *dev,
|
|||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", mdev->nrbchan);
|
||||
}
|
||||
static DEVICE_ATTR_RO(nrbchan);
|
||||
|
||||
static ssize_t _show_d_protocols(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t d_protocols_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
|
||||
|
@ -66,9 +68,10 @@ static ssize_t _show_d_protocols(struct device *dev,
|
|||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", mdev->Dprotocols);
|
||||
}
|
||||
static DEVICE_ATTR_RO(d_protocols);
|
||||
|
||||
static ssize_t _show_b_protocols(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t b_protocols_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
|
||||
|
@ -76,9 +79,10 @@ static ssize_t _show_b_protocols(struct device *dev,
|
|||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
|
||||
}
|
||||
static DEVICE_ATTR_RO(b_protocols);
|
||||
|
||||
static ssize_t _show_protocol(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t protocol_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
|
||||
|
@ -86,17 +90,19 @@ static ssize_t _show_protocol(struct device *dev,
|
|||
return -ENODEV;
|
||||
return sprintf(buf, "%d\n", mdev->D.protocol);
|
||||
}
|
||||
static DEVICE_ATTR_RO(protocol);
|
||||
|
||||
static ssize_t _show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
strcpy(buf, dev_name(dev));
|
||||
return strlen(buf);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
#if 0 /* hangs */
|
||||
static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t name_set(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int err = 0;
|
||||
char *out = kmalloc(count + 1, GFP_KERNEL);
|
||||
|
@ -113,10 +119,11 @@ static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return (err < 0) ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(name);
|
||||
#endif
|
||||
|
||||
static ssize_t _show_channelmap(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t channelmap_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mISDNdevice *mdev = dev_to_mISDN(dev);
|
||||
char *bp = buf;
|
||||
|
@ -127,18 +134,19 @@ static ssize_t _show_channelmap(struct device *dev,
|
|||
|
||||
return bp - buf;
|
||||
}
|
||||
static DEVICE_ATTR_RO(channelmap);
|
||||
|
||||
static struct device_attribute mISDN_dev_attrs[] = {
|
||||
__ATTR(id, S_IRUGO, _show_id, NULL),
|
||||
__ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL),
|
||||
__ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL),
|
||||
__ATTR(protocol, S_IRUGO, _show_protocol, NULL),
|
||||
__ATTR(channelmap, S_IRUGO, _show_channelmap, NULL),
|
||||
__ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL),
|
||||
__ATTR(name, S_IRUGO, _show_name, NULL),
|
||||
/* __ATTR(name, S_IRUGO | S_IWUSR, _show_name, _set_name), */
|
||||
{}
|
||||
static struct attribute *mISDN_attrs[] = {
|
||||
&dev_attr_id.attr,
|
||||
&dev_attr_d_protocols.attr,
|
||||
&dev_attr_b_protocols.attr,
|
||||
&dev_attr_protocol.attr,
|
||||
&dev_attr_channelmap.attr,
|
||||
&dev_attr_nrbchan.attr,
|
||||
&dev_attr_name.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mISDN);
|
||||
|
||||
static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
|
@ -162,7 +170,7 @@ static struct class mISDN_class = {
|
|||
.name = "mISDN",
|
||||
.owner = THIS_MODULE,
|
||||
.dev_uevent = mISDN_uevent,
|
||||
.dev_attrs = mISDN_dev_attrs,
|
||||
.dev_groups = mISDN_groups,
|
||||
.dev_release = mISDN_dev_release,
|
||||
.class_release = mISDN_class_release,
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev)
|
|||
led_cdev->brightness = led_cdev->brightness_get(led_cdev);
|
||||
}
|
||||
|
||||
static ssize_t led_brightness_show(struct device *dev,
|
||||
static ssize_t brightness_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
|
@ -40,7 +40,7 @@ static ssize_t led_brightness_show(struct device *dev,
|
|||
return sprintf(buf, "%u\n", led_cdev->brightness);
|
||||
}
|
||||
|
||||
static ssize_t led_brightness_store(struct device *dev,
|
||||
static ssize_t brightness_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
|
@ -57,6 +57,7 @@ static ssize_t led_brightness_store(struct device *dev,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(brightness);
|
||||
|
||||
static ssize_t led_max_brightness_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -65,14 +66,35 @@ static ssize_t led_max_brightness_show(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%u\n", led_cdev->max_brightness);
|
||||
}
|
||||
static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL);
|
||||
|
||||
static struct device_attribute led_class_attrs[] = {
|
||||
__ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
|
||||
__ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
|
||||
#ifdef CONFIG_LEDS_TRIGGERS
|
||||
__ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
|
||||
static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
|
||||
static struct attribute *led_trigger_attrs[] = {
|
||||
&dev_attr_trigger.attr,
|
||||
NULL,
|
||||
};
|
||||
static const struct attribute_group led_trigger_group = {
|
||||
.attrs = led_trigger_attrs,
|
||||
};
|
||||
#endif
|
||||
__ATTR_NULL,
|
||||
|
||||
static struct attribute *led_class_attrs[] = {
|
||||
&dev_attr_brightness.attr,
|
||||
&dev_attr_max_brightness.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group led_group = {
|
||||
.attrs = led_class_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *led_groups[] = {
|
||||
&led_group,
|
||||
#ifdef CONFIG_LEDS_TRIGGERS
|
||||
&led_trigger_group,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void led_timer_function(unsigned long data)
|
||||
|
@ -258,7 +280,7 @@ static int __init leds_init(void)
|
|||
if (IS_ERR(leds_class))
|
||||
return PTR_ERR(leds_class);
|
||||
leds_class->pm = &leds_class_dev_pm_ops;
|
||||
leds_class->dev_attrs = led_class_attrs;
|
||||
leds_class->dev_groups = led_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,24 +38,25 @@
|
|||
* sysfs stuff
|
||||
*/
|
||||
|
||||
static ssize_t show_index(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t index_show(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct video_device *vdev = to_video_device(cd);
|
||||
|
||||
return sprintf(buf, "%i\n", vdev->index);
|
||||
}
|
||||
static DEVICE_ATTR_RO(index);
|
||||
|
||||
static ssize_t show_debug(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t debug_show(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct video_device *vdev = to_video_device(cd);
|
||||
|
||||
return sprintf(buf, "%i\n", vdev->debug);
|
||||
}
|
||||
|
||||
static ssize_t set_debug(struct device *cd, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
static ssize_t debug_store(struct device *cd, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct video_device *vdev = to_video_device(cd);
|
||||
int res = 0;
|
||||
|
@ -68,21 +69,24 @@ static ssize_t set_debug(struct device *cd, struct device_attribute *attr,
|
|||
vdev->debug = value;
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR_RW(debug);
|
||||
|
||||
static ssize_t show_name(struct device *cd,
|
||||
static ssize_t name_show(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct video_device *vdev = to_video_device(cd);
|
||||
|
||||
return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static struct device_attribute video_device_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, show_name, NULL),
|
||||
__ATTR(debug, 0644, show_debug, set_debug),
|
||||
__ATTR(index, S_IRUGO, show_index, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *video_device_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_debug.attr,
|
||||
&dev_attr_index.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(video_device);
|
||||
|
||||
/*
|
||||
* Active devices
|
||||
|
@ -217,7 +221,7 @@ static void v4l2_device_release(struct device *cd)
|
|||
|
||||
static struct class video_class = {
|
||||
.name = VIDEO_NAME,
|
||||
.dev_attrs = video_device_attrs,
|
||||
.dev_groups = video_device_groups,
|
||||
};
|
||||
|
||||
struct video_device *video_devdata(struct file *file)
|
||||
|
|
|
@ -311,6 +311,7 @@ static ssize_t c2port_show_name(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%s\n", c2dev->name);
|
||||
}
|
||||
static DEVICE_ATTR(name, 0444, c2port_show_name, NULL);
|
||||
|
||||
static ssize_t c2port_show_flash_blocks_num(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -320,6 +321,7 @@ static ssize_t c2port_show_flash_blocks_num(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d\n", ops->blocks_num);
|
||||
}
|
||||
static DEVICE_ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL);
|
||||
|
||||
static ssize_t c2port_show_flash_block_size(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -329,6 +331,7 @@ static ssize_t c2port_show_flash_block_size(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d\n", ops->block_size);
|
||||
}
|
||||
static DEVICE_ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL);
|
||||
|
||||
static ssize_t c2port_show_flash_size(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -338,18 +341,18 @@ static ssize_t c2port_show_flash_size(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size);
|
||||
}
|
||||
static DEVICE_ATTR(flash_size, 0444, c2port_show_flash_size, NULL);
|
||||
|
||||
static ssize_t c2port_show_access(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t access_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct c2port_device *c2dev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", c2dev->access);
|
||||
}
|
||||
|
||||
static ssize_t c2port_store_access(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t access_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct c2port_device *c2dev = dev_get_drvdata(dev);
|
||||
struct c2port_ops *ops = c2dev->ops;
|
||||
|
@ -375,6 +378,7 @@ static ssize_t c2port_store_access(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(access);
|
||||
|
||||
static ssize_t c2port_store_reset(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -395,6 +399,7 @@ static ssize_t c2port_store_reset(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(reset, 0200, NULL, c2port_store_reset);
|
||||
|
||||
static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf)
|
||||
{
|
||||
|
@ -431,6 +436,7 @@ static ssize_t c2port_show_dev_id(struct device *dev,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(dev_id, 0444, c2port_show_dev_id, NULL);
|
||||
|
||||
static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf)
|
||||
{
|
||||
|
@ -467,6 +473,7 @@ static ssize_t c2port_show_rev_id(struct device *dev,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(rev_id, 0444, c2port_show_rev_id, NULL);
|
||||
|
||||
static ssize_t c2port_show_flash_access(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -536,6 +543,8 @@ static ssize_t c2port_store_flash_access(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(flash_access, 0644, c2port_show_flash_access,
|
||||
c2port_store_flash_access);
|
||||
|
||||
static ssize_t __c2port_write_flash_erase(struct c2port_device *dev)
|
||||
{
|
||||
|
@ -616,6 +625,7 @@ static ssize_t c2port_store_flash_erase(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase);
|
||||
|
||||
static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
|
||||
char *buffer, loff_t offset, size_t count)
|
||||
|
@ -846,35 +856,40 @@ static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj,
|
|||
|
||||
return ret;
|
||||
}
|
||||
/* size is computed at run-time */
|
||||
static BIN_ATTR(flash_data, 0644, c2port_read_flash_data,
|
||||
c2port_write_flash_data, 0);
|
||||
|
||||
/*
|
||||
* Class attributes
|
||||
*/
|
||||
|
||||
static struct device_attribute c2port_attrs[] = {
|
||||
__ATTR(name, 0444, c2port_show_name, NULL),
|
||||
__ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL),
|
||||
__ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL),
|
||||
__ATTR(flash_size, 0444, c2port_show_flash_size, NULL),
|
||||
__ATTR(access, 0644, c2port_show_access, c2port_store_access),
|
||||
__ATTR(reset, 0200, NULL, c2port_store_reset),
|
||||
__ATTR(dev_id, 0444, c2port_show_dev_id, NULL),
|
||||
__ATTR(rev_id, 0444, c2port_show_rev_id, NULL),
|
||||
|
||||
__ATTR(flash_access, 0644, c2port_show_flash_access,
|
||||
c2port_store_flash_access),
|
||||
__ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *c2port_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_flash_blocks_num.attr,
|
||||
&dev_attr_flash_block_size.attr,
|
||||
&dev_attr_flash_size.attr,
|
||||
&dev_attr_access.attr,
|
||||
&dev_attr_reset.attr,
|
||||
&dev_attr_dev_id.attr,
|
||||
&dev_attr_rev_id.attr,
|
||||
&dev_attr_flash_access.attr,
|
||||
&dev_attr_flash_erase.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bin_attribute c2port_bin_attrs = {
|
||||
.attr = {
|
||||
.name = "flash_data",
|
||||
.mode = 0644
|
||||
},
|
||||
.read = c2port_read_flash_data,
|
||||
.write = c2port_write_flash_data,
|
||||
/* .size is computed at run-time */
|
||||
static struct bin_attribute *c2port_bin_attrs[] = {
|
||||
&bin_attr_flash_data,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group c2port_group = {
|
||||
.attrs = c2port_attrs,
|
||||
.bin_attrs = c2port_bin_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *c2port_groups[] = {
|
||||
&c2port_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -907,6 +922,8 @@ struct c2port_device *c2port_device_register(char *name,
|
|||
goto error_idr_alloc;
|
||||
c2dev->id = ret;
|
||||
|
||||
bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
|
||||
|
||||
c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
|
||||
"c2port%d", c2dev->id);
|
||||
if (unlikely(IS_ERR(c2dev->dev))) {
|
||||
|
@ -919,12 +936,6 @@ struct c2port_device *c2port_device_register(char *name,
|
|||
c2dev->ops = ops;
|
||||
mutex_init(&c2dev->mutex);
|
||||
|
||||
/* Create binary file */
|
||||
c2port_bin_attrs.size = ops->blocks_num * ops->block_size;
|
||||
ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs);
|
||||
if (unlikely(ret))
|
||||
goto error_device_create_bin_file;
|
||||
|
||||
/* By default C2 port access is off */
|
||||
c2dev->access = c2dev->flash_access = 0;
|
||||
ops->access(c2dev, 0);
|
||||
|
@ -937,9 +948,6 @@ struct c2port_device *c2port_device_register(char *name,
|
|||
|
||||
return c2dev;
|
||||
|
||||
error_device_create_bin_file:
|
||||
device_destroy(c2port_class, 0);
|
||||
|
||||
error_device_create:
|
||||
spin_lock_irq(&c2port_idr_lock);
|
||||
idr_remove(&c2port_idr, c2dev->id);
|
||||
|
@ -959,7 +967,6 @@ void c2port_device_unregister(struct c2port_device *c2dev)
|
|||
|
||||
dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name);
|
||||
|
||||
device_remove_bin_file(c2dev->dev, &c2port_bin_attrs);
|
||||
spin_lock_irq(&c2port_idr_lock);
|
||||
idr_remove(&c2port_idr, c2dev->id);
|
||||
spin_unlock_irq(&c2port_idr_lock);
|
||||
|
@ -984,7 +991,7 @@ static int __init c2port_init(void)
|
|||
printk(KERN_ERR "c2port: failed to allocate class\n");
|
||||
return PTR_ERR(c2port_class);
|
||||
}
|
||||
c2port_class->dev_attrs = c2port_attrs;
|
||||
c2port_class->dev_groups = c2port_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ static void enclosure_component_release(struct device *dev)
|
|||
put_device(dev->parent);
|
||||
}
|
||||
|
||||
static const struct attribute_group *enclosure_groups[];
|
||||
static const struct attribute_group *enclosure_component_groups[];
|
||||
|
||||
/**
|
||||
* enclosure_component_register - add a particular component to an enclosure
|
||||
|
@ -282,7 +282,7 @@ enclosure_component_register(struct enclosure_device *edev,
|
|||
dev_set_name(cdev, "%u", number);
|
||||
|
||||
cdev->release = enclosure_component_release;
|
||||
cdev->groups = enclosure_groups;
|
||||
cdev->groups = enclosure_component_groups;
|
||||
|
||||
err = device_register(cdev);
|
||||
if (err) {
|
||||
|
@ -365,25 +365,26 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
|
|||
* sysfs pieces below
|
||||
*/
|
||||
|
||||
static ssize_t enclosure_show_components(struct device *cdev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t components_show(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct enclosure_device *edev = to_enclosure_device(cdev);
|
||||
|
||||
return snprintf(buf, 40, "%d\n", edev->components);
|
||||
}
|
||||
static DEVICE_ATTR_RO(components);
|
||||
|
||||
static struct device_attribute enclosure_attrs[] = {
|
||||
__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *enclosure_class_attrs[] = {
|
||||
&dev_attr_components.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(enclosure_class);
|
||||
|
||||
static struct class enclosure_class = {
|
||||
.name = "enclosure",
|
||||
.owner = THIS_MODULE,
|
||||
.dev_release = enclosure_release,
|
||||
.dev_attrs = enclosure_attrs,
|
||||
.dev_groups = enclosure_class_groups,
|
||||
};
|
||||
|
||||
static const char *const enclosure_status [] = {
|
||||
|
@ -536,15 +537,7 @@ static struct attribute *enclosure_component_attrs[] = {
|
|||
&dev_attr_type.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group enclosure_group = {
|
||||
.attrs = enclosure_component_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *enclosure_groups[] = {
|
||||
&enclosure_group,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(enclosure_component);
|
||||
|
||||
static int __init enclosure_init(void)
|
||||
{
|
||||
|
|
|
@ -108,11 +108,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
|||
|
||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct device_attribute mei_cl_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *mei_cl_dev_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mei_cl_dev);
|
||||
|
||||
static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
|
@ -124,7 +126,7 @@ static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
|
||||
static struct bus_type mei_cl_bus_type = {
|
||||
.name = "mei",
|
||||
.dev_attrs = mei_cl_dev_attrs,
|
||||
.dev_groups = mei_cl_dev_groups,
|
||||
.match = mei_cl_device_match,
|
||||
.probe = mei_cl_device_probe,
|
||||
.remove = mei_cl_device_remove,
|
||||
|
|
|
@ -9478,7 +9478,7 @@ static struct niu_parent *niu_new_parent(struct niu *np,
|
|||
if (IS_ERR(plat_dev))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; attr_name(niu_parent_attributes[i]); i++) {
|
||||
for (i = 0; niu_parent_attributes[i].attr.name; i++) {
|
||||
int err = device_create_file(&plat_dev->dev,
|
||||
&niu_parent_attributes[i]);
|
||||
if (err)
|
||||
|
|
|
@ -693,11 +693,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return sprintf(buf, "wmi:%s\n", guid_string);
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static struct device_attribute wmi_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL
|
||||
static struct attribute *wmi_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(wmi);
|
||||
|
||||
static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
|
@ -732,7 +734,7 @@ static struct class wmi_class = {
|
|||
.name = "wmi",
|
||||
.dev_release = wmi_dev_free,
|
||||
.dev_uevent = wmi_dev_uevent,
|
||||
.dev_attrs = wmi_dev_attrs,
|
||||
.dev_groups = wmi_groups,
|
||||
};
|
||||
|
||||
static int wmi_create_device(const struct guid_block *gblock,
|
||||
|
|
|
@ -406,7 +406,7 @@ static int __init pps_init(void)
|
|||
pr_err("failed to allocate class\n");
|
||||
return PTR_ERR(pps_class);
|
||||
}
|
||||
pps_class->dev_attrs = pps_attrs;
|
||||
pps_class->dev_groups = pps_groups;
|
||||
|
||||
err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
|
||||
if (err < 0) {
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
* Attribute functions
|
||||
*/
|
||||
|
||||
static ssize_t pps_show_assert(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t assert_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -41,9 +41,10 @@ static ssize_t pps_show_assert(struct device *dev,
|
|||
(long long) pps->assert_tu.sec, pps->assert_tu.nsec,
|
||||
pps->assert_sequence);
|
||||
}
|
||||
static DEVICE_ATTR_RO(assert);
|
||||
|
||||
static ssize_t pps_show_clear(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t clear_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -54,45 +55,59 @@ static ssize_t pps_show_clear(struct device *dev,
|
|||
(long long) pps->clear_tu.sec, pps->clear_tu.nsec,
|
||||
pps->clear_sequence);
|
||||
}
|
||||
static DEVICE_ATTR_RO(clear);
|
||||
|
||||
static ssize_t pps_show_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%4x\n", pps->info.mode);
|
||||
}
|
||||
static DEVICE_ATTR_RO(mode);
|
||||
|
||||
static ssize_t pps_show_echo(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t echo_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", !!pps->info.echo);
|
||||
}
|
||||
static DEVICE_ATTR_RO(echo);
|
||||
|
||||
static ssize_t pps_show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", pps->info.name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t pps_show_path(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t path_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", pps->info.path);
|
||||
}
|
||||
static DEVICE_ATTR_RO(path);
|
||||
|
||||
struct device_attribute pps_attrs[] = {
|
||||
__ATTR(assert, S_IRUGO, pps_show_assert, NULL),
|
||||
__ATTR(clear, S_IRUGO, pps_show_clear, NULL),
|
||||
__ATTR(mode, S_IRUGO, pps_show_mode, NULL),
|
||||
__ATTR(echo, S_IRUGO, pps_show_echo, NULL),
|
||||
__ATTR(name, S_IRUGO, pps_show_name, NULL),
|
||||
__ATTR(path, S_IRUGO, pps_show_path, NULL),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *pps_attrs[] = {
|
||||
&dev_attr_assert.attr,
|
||||
&dev_attr_clear.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_echo.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_path.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group pps_group = {
|
||||
.attrs = pps_attrs,
|
||||
};
|
||||
|
||||
const struct attribute_group *pps_groups[] = {
|
||||
&pps_group,
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -330,7 +330,7 @@ static int __init ptp_init(void)
|
|||
goto no_region;
|
||||
}
|
||||
|
||||
ptp_class->dev_attrs = ptp_dev_attrs;
|
||||
ptp_class->dev_groups = ptp_groups;
|
||||
pr_info("PTP clock support registered\n");
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ uint ptp_poll(struct posix_clock *pc,
|
|||
* see ptp_sysfs.c
|
||||
*/
|
||||
|
||||
extern struct device_attribute ptp_dev_attrs[];
|
||||
extern const struct attribute_group *ptp_groups[];
|
||||
|
||||
int ptp_cleanup_sysfs(struct ptp_clock *ptp);
|
||||
|
||||
|
|
|
@ -27,36 +27,43 @@ static ssize_t clock_name_show(struct device *dev,
|
|||
struct ptp_clock *ptp = dev_get_drvdata(dev);
|
||||
return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
|
||||
}
|
||||
static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL);
|
||||
|
||||
#define PTP_SHOW_INT(name) \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
#define PTP_SHOW_INT(name, var) \
|
||||
static ssize_t var##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *page) \
|
||||
{ \
|
||||
struct ptp_clock *ptp = dev_get_drvdata(dev); \
|
||||
return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->name); \
|
||||
}
|
||||
return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->var); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, 0444, var##_show, NULL);
|
||||
|
||||
PTP_SHOW_INT(max_adj);
|
||||
PTP_SHOW_INT(n_alarm);
|
||||
PTP_SHOW_INT(n_ext_ts);
|
||||
PTP_SHOW_INT(n_per_out);
|
||||
PTP_SHOW_INT(pps);
|
||||
PTP_SHOW_INT(max_adjustment, max_adj);
|
||||
PTP_SHOW_INT(n_alarms, n_alarm);
|
||||
PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
|
||||
PTP_SHOW_INT(n_periodic_outputs, n_per_out);
|
||||
PTP_SHOW_INT(pps_available, pps);
|
||||
|
||||
#define PTP_RO_ATTR(_var, _name) { \
|
||||
.attr = { .name = __stringify(_name), .mode = 0444 }, \
|
||||
.show = _var##_show, \
|
||||
}
|
||||
|
||||
struct device_attribute ptp_dev_attrs[] = {
|
||||
PTP_RO_ATTR(clock_name, clock_name),
|
||||
PTP_RO_ATTR(max_adj, max_adjustment),
|
||||
PTP_RO_ATTR(n_alarm, n_alarms),
|
||||
PTP_RO_ATTR(n_ext_ts, n_external_timestamps),
|
||||
PTP_RO_ATTR(n_per_out, n_periodic_outputs),
|
||||
PTP_RO_ATTR(pps, pps_available),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *ptp_attrs[] = {
|
||||
&dev_attr_clock_name.attr,
|
||||
&dev_attr_max_adjustment.attr,
|
||||
&dev_attr_n_alarms.attr,
|
||||
&dev_attr_n_external_timestamps.attr,
|
||||
&dev_attr_n_periodic_outputs.attr,
|
||||
&dev_attr_pps_available.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ptp_group = {
|
||||
.attrs = ptp_attrs,
|
||||
};
|
||||
|
||||
const struct attribute_group *ptp_groups[] = {
|
||||
&ptp_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t extts_enable_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
|
|
@ -25,15 +25,14 @@
|
|||
*/
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
name_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
date_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct rtc_time tm;
|
||||
|
@ -46,10 +45,10 @@ rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return retval;
|
||||
}
|
||||
static DEVICE_ATTR_RO(date);
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
time_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct rtc_time tm;
|
||||
|
@ -62,10 +61,10 @@ rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return retval;
|
||||
}
|
||||
static DEVICE_ATTR_RO(time);
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct rtc_time tm;
|
||||
|
@ -79,16 +78,16 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return retval;
|
||||
}
|
||||
static DEVICE_ATTR_RO(since_epoch);
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
|
||||
max_user_freq_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t n)
|
||||
{
|
||||
struct rtc_device *rtc = to_rtc_device(dev);
|
||||
|
@ -101,6 +100,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return n;
|
||||
}
|
||||
static DEVICE_ATTR_RW(max_user_freq);
|
||||
|
||||
/**
|
||||
* rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
|
||||
|
@ -109,8 +109,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
|
|||
* boot or resume event.
|
||||
*/
|
||||
static ssize_t
|
||||
rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
#ifdef CONFIG_RTC_HCTOSYS_DEVICE
|
||||
if (rtc_hctosys_ret == 0 &&
|
||||
|
@ -121,17 +120,18 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
|
|||
#endif
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
static DEVICE_ATTR_RO(hctosys);
|
||||
|
||||
static struct device_attribute rtc_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
|
||||
__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
|
||||
__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
|
||||
__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
|
||||
__ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq,
|
||||
rtc_sysfs_set_max_user_freq),
|
||||
__ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL),
|
||||
{ },
|
||||
static struct attribute *rtc_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_date.attr,
|
||||
&dev_attr_time.attr,
|
||||
&dev_attr_since_epoch.attr,
|
||||
&dev_attr_max_user_freq.attr,
|
||||
&dev_attr_hctosys.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(rtc);
|
||||
|
||||
static ssize_t
|
||||
rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
|
||||
|
@ -261,5 +261,5 @@ void rtc_sysfs_del_device(struct rtc_device *rtc)
|
|||
|
||||
void __init rtc_sysfs_init(struct class *rtc_class)
|
||||
{
|
||||
rtc_class->dev_attrs = rtc_attrs;
|
||||
rtc_class->dev_groups = rtc_groups;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
|
|||
class_dev);
|
||||
return sprintf(buf, "%s\n", ould->odi.osdname);
|
||||
}
|
||||
static DEVICE_ATTR_RO(osdname);
|
||||
|
||||
static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -117,17 +118,19 @@ static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
|
|||
memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
|
||||
return ould->odi.systemid_len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(systemid);
|
||||
|
||||
static struct device_attribute osd_uld_attrs[] = {
|
||||
__ATTR(osdname, S_IRUGO, osdname_show, NULL),
|
||||
__ATTR(systemid, S_IRUGO, systemid_show, NULL),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *osd_uld_attrs[] = {
|
||||
&dev_attr_osdname.attr,
|
||||
&dev_attr_systemid.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(osd_uld);
|
||||
|
||||
static struct class osd_uld_class = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "scsi_osd",
|
||||
.dev_attrs = osd_uld_attrs,
|
||||
.dev_groups = osd_uld_groups,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -262,7 +262,7 @@ static int resize_async_buffer(struct comedi_device *dev,
|
|||
|
||||
/* sysfs attribute files */
|
||||
|
||||
static ssize_t show_max_read_buffer_kb(struct device *csdev,
|
||||
static ssize_t max_read_buffer_kb_show(struct device *csdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int minor = MINOR(csdev->devt);
|
||||
|
@ -283,7 +283,7 @@ static ssize_t show_max_read_buffer_kb(struct device *csdev,
|
|||
return snprintf(buf, PAGE_SIZE, "%i\n", size);
|
||||
}
|
||||
|
||||
static ssize_t store_max_read_buffer_kb(struct device *csdev,
|
||||
static ssize_t max_read_buffer_kb_store(struct device *csdev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -314,8 +314,9 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev,
|
|||
|
||||
return err ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(max_read_buffer_kb);
|
||||
|
||||
static ssize_t show_read_buffer_kb(struct device *csdev,
|
||||
static ssize_t read_buffer_kb_show(struct device *csdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int minor = MINOR(csdev->devt);
|
||||
|
@ -336,7 +337,7 @@ static ssize_t show_read_buffer_kb(struct device *csdev,
|
|||
return snprintf(buf, PAGE_SIZE, "%i\n", size);
|
||||
}
|
||||
|
||||
static ssize_t store_read_buffer_kb(struct device *csdev,
|
||||
static ssize_t read_buffer_kb_store(struct device *csdev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -367,8 +368,9 @@ static ssize_t store_read_buffer_kb(struct device *csdev,
|
|||
|
||||
return err ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(read_buffer_kb);
|
||||
|
||||
static ssize_t show_max_write_buffer_kb(struct device *csdev,
|
||||
static ssize_t max_write_buffer_kb_show(struct device *csdev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
|
@ -390,7 +392,7 @@ static ssize_t show_max_write_buffer_kb(struct device *csdev,
|
|||
return snprintf(buf, PAGE_SIZE, "%i\n", size);
|
||||
}
|
||||
|
||||
static ssize_t store_max_write_buffer_kb(struct device *csdev,
|
||||
static ssize_t max_write_buffer_kb_store(struct device *csdev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -421,8 +423,9 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev,
|
|||
|
||||
return err ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(max_write_buffer_kb);
|
||||
|
||||
static ssize_t show_write_buffer_kb(struct device *csdev,
|
||||
static ssize_t write_buffer_kb_show(struct device *csdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int minor = MINOR(csdev->devt);
|
||||
|
@ -443,7 +446,7 @@ static ssize_t show_write_buffer_kb(struct device *csdev,
|
|||
return snprintf(buf, PAGE_SIZE, "%i\n", size);
|
||||
}
|
||||
|
||||
static ssize_t store_write_buffer_kb(struct device *csdev,
|
||||
static ssize_t write_buffer_kb_store(struct device *csdev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -474,18 +477,16 @@ static ssize_t store_write_buffer_kb(struct device *csdev,
|
|||
|
||||
return err ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(write_buffer_kb);
|
||||
|
||||
static struct device_attribute comedi_dev_attrs[] = {
|
||||
__ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
|
||||
show_max_read_buffer_kb, store_max_read_buffer_kb),
|
||||
__ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
show_read_buffer_kb, store_read_buffer_kb),
|
||||
__ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
|
||||
show_max_write_buffer_kb, store_max_write_buffer_kb),
|
||||
__ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
show_write_buffer_kb, store_write_buffer_kb),
|
||||
__ATTR_NULL
|
||||
static struct attribute *comedi_dev_attrs[] = {
|
||||
&dev_attr_max_read_buffer_kb.attr,
|
||||
&dev_attr_read_buffer_kb.attr,
|
||||
&dev_attr_max_write_buffer_kb.attr,
|
||||
&dev_attr_write_buffer_kb.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(comedi_dev);
|
||||
|
||||
static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
|
||||
unsigned mask, unsigned bits)
|
||||
|
@ -2564,7 +2565,7 @@ static int __init comedi_init(void)
|
|||
return PTR_ERR(comedi_class);
|
||||
}
|
||||
|
||||
comedi_class->dev_attrs = comedi_dev_attrs;
|
||||
comedi_class->dev_groups = comedi_dev_groups;
|
||||
|
||||
/* XXX requires /proc interface */
|
||||
comedi_proc_init();
|
||||
|
|
|
@ -223,38 +223,42 @@ static struct kobj_type portio_attr_type = {
|
|||
.default_attrs = portio_attrs,
|
||||
};
|
||||
|
||||
static ssize_t show_name(struct device *dev,
|
||||
static ssize_t name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct uio_device *idev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", idev->info->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t show_version(struct device *dev,
|
||||
static ssize_t version_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct uio_device *idev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", idev->info->version);
|
||||
}
|
||||
static DEVICE_ATTR_RO(version);
|
||||
|
||||
static ssize_t show_event(struct device *dev,
|
||||
static ssize_t event_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct uio_device *idev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
|
||||
}
|
||||
static DEVICE_ATTR_RO(event);
|
||||
|
||||
static struct device_attribute uio_class_attributes[] = {
|
||||
__ATTR(name, S_IRUGO, show_name, NULL),
|
||||
__ATTR(version, S_IRUGO, show_version, NULL),
|
||||
__ATTR(event, S_IRUGO, show_event, NULL),
|
||||
{}
|
||||
static struct attribute *uio_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_version.attr,
|
||||
&dev_attr_event.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(uio);
|
||||
|
||||
/* UIO class infrastructure */
|
||||
static struct class uio_class = {
|
||||
.name = "uio",
|
||||
.dev_attrs = uio_class_attributes,
|
||||
.dev_groups = uio_groups,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -121,7 +121,7 @@ static int usb_serial_device_remove(struct device *dev)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_new_id(struct device_driver *driver,
|
||||
static ssize_t new_id_store(struct device_driver *driver,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
|
||||
|
@ -134,17 +134,19 @@ static ssize_t store_new_id(struct device_driver *driver,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t show_dynids(struct device_driver *driver, char *buf)
|
||||
static ssize_t new_id_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
|
||||
|
||||
return usb_show_dynids(&usb_drv->dynids, buf);
|
||||
}
|
||||
static DRIVER_ATTR_RW(new_id);
|
||||
|
||||
static struct driver_attribute drv_attrs[] = {
|
||||
__ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *usb_serial_drv_attrs[] = {
|
||||
&driver_attr_new_id.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(usb_serial_drv);
|
||||
|
||||
static void free_dynids(struct usb_serial_driver *drv)
|
||||
{
|
||||
|
@ -163,7 +165,7 @@ struct bus_type usb_serial_bus_type = {
|
|||
.match = usb_serial_device_match,
|
||||
.probe = usb_serial_device_probe,
|
||||
.remove = usb_serial_device_remove,
|
||||
.drv_attrs = drv_attrs,
|
||||
.drv_groups = usb_serial_drv_groups,
|
||||
};
|
||||
|
||||
int usb_serial_bus_register(struct usb_serial_driver *driver)
|
||||
|
|
|
@ -103,16 +103,16 @@ static void backlight_generate_event(struct backlight_device *bd,
|
|||
sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
|
||||
}
|
||||
|
||||
static ssize_t backlight_show_power(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", bd->props.power);
|
||||
}
|
||||
|
||||
static ssize_t backlight_store_power(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
@ -136,8 +136,9 @@ static ssize_t backlight_store_power(struct device *dev,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RW(bl_power);
|
||||
|
||||
static ssize_t backlight_show_brightness(struct device *dev,
|
||||
static ssize_t brightness_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
@ -145,7 +146,7 @@ static ssize_t backlight_show_brightness(struct device *dev,
|
|||
return sprintf(buf, "%d\n", bd->props.brightness);
|
||||
}
|
||||
|
||||
static ssize_t backlight_store_brightness(struct device *dev,
|
||||
static ssize_t brightness_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
|
@ -175,24 +176,27 @@ static ssize_t backlight_store_brightness(struct device *dev,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RW(brightness);
|
||||
|
||||
static ssize_t backlight_show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
|
||||
}
|
||||
static DEVICE_ATTR_RO(type);
|
||||
|
||||
static ssize_t backlight_show_max_brightness(struct device *dev,
|
||||
static ssize_t max_brightness_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", bd->props.max_brightness);
|
||||
}
|
||||
static DEVICE_ATTR_RO(max_brightness);
|
||||
|
||||
static ssize_t backlight_show_actual_brightness(struct device *dev,
|
||||
static ssize_t actual_brightness_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
|
@ -205,6 +209,7 @@ static ssize_t backlight_show_actual_brightness(struct device *dev,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RO(actual_brightness);
|
||||
|
||||
static struct class *backlight_class;
|
||||
|
||||
|
@ -247,16 +252,15 @@ static void bl_device_release(struct device *dev)
|
|||
kfree(bd);
|
||||
}
|
||||
|
||||
static struct device_attribute bl_device_attributes[] = {
|
||||
__ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
|
||||
__ATTR(brightness, 0644, backlight_show_brightness,
|
||||
backlight_store_brightness),
|
||||
__ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
|
||||
NULL),
|
||||
__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
|
||||
__ATTR(type, 0444, backlight_show_type, NULL),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *bl_device_attrs[] = {
|
||||
&dev_attr_bl_power.attr,
|
||||
&dev_attr_brightness.attr,
|
||||
&dev_attr_actual_brightness.attr,
|
||||
&dev_attr_max_brightness.attr,
|
||||
&dev_attr_type.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(bl_device);
|
||||
|
||||
/**
|
||||
* backlight_force_update - tell the backlight subsystem that hardware state
|
||||
|
@ -493,7 +497,7 @@ static int __init backlight_class_init(void)
|
|||
return PTR_ERR(backlight_class);
|
||||
}
|
||||
|
||||
backlight_class->dev_attrs = bl_device_attributes;
|
||||
backlight_class->dev_groups = bl_device_groups;
|
||||
backlight_class->pm = &backlight_class_dev_pm_ops;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ static inline void lcd_unregister_fb(struct lcd_device *ld)
|
|||
}
|
||||
#endif /* CONFIG_FB */
|
||||
|
||||
static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int rc;
|
||||
|
@ -105,7 +105,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_store_power(struct device *dev,
|
||||
static ssize_t lcd_power_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
|
@ -128,8 +128,9 @@ static ssize_t lcd_store_power(struct device *dev,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RW(lcd_power);
|
||||
|
||||
static ssize_t lcd_show_contrast(struct device *dev,
|
||||
static ssize_t contrast_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
|
@ -143,7 +144,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_store_contrast(struct device *dev,
|
||||
static ssize_t contrast_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
|
@ -166,14 +167,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RW(contrast);
|
||||
|
||||
static ssize_t lcd_show_max_contrast(struct device *dev,
|
||||
static ssize_t max_contrast_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lcd_device *ld = to_lcd_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", ld->props.max_contrast);
|
||||
}
|
||||
static DEVICE_ATTR_RO(max_contrast);
|
||||
|
||||
static struct class *lcd_class;
|
||||
|
||||
|
@ -183,12 +186,13 @@ static void lcd_device_release(struct device *dev)
|
|||
kfree(ld);
|
||||
}
|
||||
|
||||
static struct device_attribute lcd_device_attributes[] = {
|
||||
__ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power),
|
||||
__ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
|
||||
__ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *lcd_device_attrs[] = {
|
||||
&dev_attr_lcd_power.attr,
|
||||
&dev_attr_contrast.attr,
|
||||
&dev_attr_max_contrast.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(lcd_device);
|
||||
|
||||
/**
|
||||
* lcd_device_register - register a new object of lcd_device class.
|
||||
|
@ -344,7 +348,7 @@ static int __init lcd_class_init(void)
|
|||
return PTR_ERR(lcd_class);
|
||||
}
|
||||
|
||||
lcd_class->dev_attrs = lcd_device_attributes;
|
||||
lcd_class->dev_groups = lcd_device_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,10 +72,9 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_state(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t state_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
|
||||
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
|
||||
|
@ -85,10 +84,9 @@ static ssize_t w1_f29_read_state(
|
|||
return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_output(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t output_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
|
||||
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
|
||||
|
@ -99,10 +97,9 @@ static ssize_t w1_f29_read_output(
|
|||
W1_F29_REG_OUTPUT_LATCH_STATE, buf);
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_activity(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t activity_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
|
||||
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
|
||||
|
@ -113,10 +110,9 @@ static ssize_t w1_f29_read_activity(
|
|||
W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_cond_search_mask(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
|
||||
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
|
||||
|
@ -127,10 +123,10 @@ static ssize_t w1_f29_read_cond_search_mask(
|
|||
W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_cond_search_polarity(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t cond_search_polarity_read(struct file *filp,
|
||||
struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
if (count != 1 || off != 0)
|
||||
return -EFAULT;
|
||||
|
@ -138,10 +134,9 @@ static ssize_t w1_f29_read_cond_search_polarity(
|
|||
W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_read_status_control(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
if (count != 1 || off != 0)
|
||||
return -EFAULT;
|
||||
|
@ -149,13 +144,9 @@ static ssize_t w1_f29_read_status_control(
|
|||
W1_F29_REG_CONTROL_AND_STATUS, buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static ssize_t w1_f29_write_output(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t output_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
u8 w1_buf[3];
|
||||
|
@ -224,10 +215,9 @@ error:
|
|||
/**
|
||||
* Writing to the activity file resets the activity latches.
|
||||
*/
|
||||
static ssize_t w1_f29_write_activity(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t activity_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
unsigned int retries = W1_F29_RETRIES;
|
||||
|
@ -255,13 +245,9 @@ error:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t w1_f29_write_status_control(
|
||||
struct file *filp,
|
||||
struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf,
|
||||
loff_t off,
|
||||
size_t count)
|
||||
static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
u8 w1_buf[4];
|
||||
|
@ -330,91 +316,35 @@ out:
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_f29_sysfs_bin_files[] = {
|
||||
{
|
||||
.attr = {
|
||||
.name = "state",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_state,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "output",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_output,
|
||||
.write = w1_f29_write_output,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "activity",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_activity,
|
||||
.write = w1_f29_write_activity,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "cond_search_mask",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_cond_search_mask,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "cond_search_polarity",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_cond_search_polarity,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "status_control",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f29_read_status_control,
|
||||
.write = w1_f29_write_status_control,
|
||||
}
|
||||
static BIN_ATTR_RO(state, 1);
|
||||
static BIN_ATTR_RW(output, 1);
|
||||
static BIN_ATTR_RW(activity, 1);
|
||||
static BIN_ATTR_RO(cond_search_mask, 1);
|
||||
static BIN_ATTR_RO(cond_search_polarity, 1);
|
||||
static BIN_ATTR_RW(status_control, 1);
|
||||
|
||||
static struct bin_attribute *w1_f29_bin_attrs[] = {
|
||||
&bin_attr_state,
|
||||
&bin_attr_output,
|
||||
&bin_attr_activity,
|
||||
&bin_attr_cond_search_mask,
|
||||
&bin_attr_cond_search_polarity,
|
||||
&bin_attr_status_control,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_f29_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
static const struct attribute_group w1_f29_group = {
|
||||
.bin_attrs = w1_f29_bin_attrs,
|
||||
};
|
||||
|
||||
err = w1_f29_disable_test_mode(sl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
|
||||
err = sysfs_create_bin_file(
|
||||
&sl->dev.kobj,
|
||||
&(w1_f29_sysfs_bin_files[i]));
|
||||
if (err)
|
||||
while (--i >= 0)
|
||||
sysfs_remove_bin_file(&sl->dev.kobj,
|
||||
&(w1_f29_sysfs_bin_files[i]));
|
||||
return err;
|
||||
}
|
||||
|
||||
static void w1_f29_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
int i;
|
||||
for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
|
||||
sysfs_remove_bin_file(&sl->dev.kobj,
|
||||
&(w1_f29_sysfs_bin_files[i]));
|
||||
}
|
||||
static const struct attribute_group *w1_f29_groups[] = {
|
||||
&w1_f29_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct w1_family_ops w1_f29_fops = {
|
||||
.add_slave = w1_f29_add_slave,
|
||||
.remove_slave = w1_f29_remove_slave,
|
||||
.add_slave = w1_f29_disable_test_mode,
|
||||
.groups = w1_f29_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_29 = {
|
||||
|
|
|
@ -30,10 +30,9 @@ MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2413));
|
|||
#define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A
|
||||
#define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA
|
||||
|
||||
static ssize_t w1_f3a_read_state(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t state_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
dev_dbg(&sl->dev,
|
||||
|
@ -66,10 +65,11 @@ static ssize_t w1_f3a_read_state(
|
|||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t w1_f3a_write_output(
|
||||
struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static BIN_ATTR_RO(state, 1);
|
||||
|
||||
static ssize_t output_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
u8 w1_buf[3];
|
||||
|
@ -110,53 +110,25 @@ error:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
#define NB_SYSFS_BIN_FILES 2
|
||||
static struct bin_attribute w1_f3a_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
|
||||
{
|
||||
.attr = {
|
||||
.name = "state",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f3a_read_state,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "output",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
},
|
||||
.size = 1,
|
||||
.write = w1_f3a_write_output,
|
||||
}
|
||||
static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
|
||||
|
||||
static struct bin_attribute *w1_f3a_bin_attrs[] = {
|
||||
&bin_attr_state,
|
||||
&bin_attr_output,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_f3a_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
static const struct attribute_group w1_f3a_group = {
|
||||
.bin_attrs = w1_f3a_bin_attrs,
|
||||
};
|
||||
|
||||
for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
|
||||
err = sysfs_create_bin_file(
|
||||
&sl->dev.kobj,
|
||||
&(w1_f3a_sysfs_bin_files[i]));
|
||||
if (err)
|
||||
while (--i >= 0)
|
||||
sysfs_remove_bin_file(&sl->dev.kobj,
|
||||
&(w1_f3a_sysfs_bin_files[i]));
|
||||
return err;
|
||||
}
|
||||
|
||||
static void w1_f3a_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
int i;
|
||||
for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
|
||||
sysfs_remove_bin_file(&sl->dev.kobj,
|
||||
&(w1_f3a_sysfs_bin_files[i]));
|
||||
}
|
||||
static const struct attribute_group *w1_f3a_groups[] = {
|
||||
&w1_f3a_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct w1_family_ops w1_f3a_fops = {
|
||||
.add_slave = w1_f3a_add_slave,
|
||||
.remove_slave = w1_f3a_remove_slave,
|
||||
.groups = w1_f3a_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_3a = {
|
||||
|
|
|
@ -40,14 +40,8 @@
|
|||
#define COUNTER_COUNT 4
|
||||
#define READ_BYTE_COUNT 42
|
||||
|
||||
static ssize_t w1_counter_read(struct device *device,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
static struct device_attribute w1_counter_attr =
|
||||
__ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL);
|
||||
|
||||
static ssize_t w1_counter_read(struct device *device,
|
||||
struct device_attribute *attr, char *out_buf)
|
||||
static ssize_t w1_slave_show(struct device *device,
|
||||
struct device_attribute *attr, char *out_buf)
|
||||
{
|
||||
struct w1_slave *sl = dev_to_w1_slave(device);
|
||||
struct w1_master *dev = sl->master;
|
||||
|
@ -128,19 +122,16 @@ static ssize_t w1_counter_read(struct device *device,
|
|||
return PAGE_SIZE - c;
|
||||
}
|
||||
|
||||
static int w1_f1d_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
return device_create_file(&sl->dev, &w1_counter_attr);
|
||||
}
|
||||
static DEVICE_ATTR_RO(w1_slave);
|
||||
|
||||
static void w1_f1d_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
device_remove_file(&sl->dev, &w1_counter_attr);
|
||||
}
|
||||
static struct attribute *w1_f1d_attrs[] = {
|
||||
&dev_attr_w1_slave.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(w1_f1d);
|
||||
|
||||
static struct w1_family_ops w1_f1d_fops = {
|
||||
.add_slave = w1_f1d_add_slave,
|
||||
.remove_slave = w1_f1d_remove_slave,
|
||||
.groups = w1_f1d_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_1d = {
|
||||
|
|
|
@ -96,9 +96,9 @@ static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
int todo = count;
|
||||
|
@ -202,9 +202,9 @@ retry:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
int addr, len;
|
||||
|
@ -264,29 +264,24 @@ out_up:
|
|||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_f2d_bin_attr = {
|
||||
.attr = {
|
||||
.name = "eeprom",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = W1_F2D_EEPROM_SIZE,
|
||||
.read = w1_f2d_read_bin,
|
||||
.write = w1_f2d_write_bin,
|
||||
static BIN_ATTR_RW(eeprom, W1_F2D_EEPROM_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_f2d_bin_attrs[] = {
|
||||
&bin_attr_eeprom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_f2d_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
|
||||
}
|
||||
static const struct attribute_group w1_f2d_group = {
|
||||
.bin_attrs = w1_f2d_bin_attrs,
|
||||
};
|
||||
|
||||
static void w1_f2d_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
|
||||
}
|
||||
static const struct attribute_group *w1_f2d_groups[] = {
|
||||
&w1_f2d_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct w1_family_ops w1_f2d_fops = {
|
||||
.add_slave = w1_f2d_add_slave,
|
||||
.remove_slave = w1_f2d_remove_slave,
|
||||
.groups = w1_f2d_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_2d = {
|
||||
|
|
|
@ -93,9 +93,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
|
|||
}
|
||||
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
|
||||
|
||||
static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
|
||||
|
@ -207,9 +207,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
int addr, len, idx;
|
||||
|
@ -257,19 +257,24 @@ out_up:
|
|||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_f23_bin_attr = {
|
||||
.attr = {
|
||||
.name = "eeprom",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = W1_EEPROM_SIZE,
|
||||
.read = w1_f23_read_bin,
|
||||
.write = w1_f23_write_bin,
|
||||
static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_f23_bin_attributes[] = {
|
||||
&bin_attr_eeprom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group w1_f23_group = {
|
||||
.bin_attrs = w1_f23_bin_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group *w1_f23_groups[] = {
|
||||
&w1_f23_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_f23_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
int err;
|
||||
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
|
||||
struct w1_f23_data *data;
|
||||
|
||||
|
@ -279,15 +284,7 @@ static int w1_f23_add_slave(struct w1_slave *sl)
|
|||
sl->family_data = data;
|
||||
|
||||
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
|
||||
|
||||
err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
|
||||
|
||||
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
|
||||
if (err)
|
||||
kfree(data);
|
||||
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void w1_f23_remove_slave(struct w1_slave *sl)
|
||||
|
@ -296,12 +293,12 @@ static void w1_f23_remove_slave(struct w1_slave *sl)
|
|||
kfree(sl->family_data);
|
||||
sl->family_data = NULL;
|
||||
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
|
||||
}
|
||||
|
||||
static struct w1_family_ops w1_f23_fops = {
|
||||
.add_slave = w1_f23_add_slave,
|
||||
.remove_slave = w1_f23_remove_slave,
|
||||
.groups = w1_f23_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_23 = {
|
||||
|
|
|
@ -97,21 +97,28 @@ int w1_ds2760_recall_eeprom(struct device *dev, int addr)
|
|||
return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
|
||||
}
|
||||
|
||||
static ssize_t w1_ds2760_read_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
return w1_ds2760_read(dev, buf, off, count);
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_ds2760_bin_attr = {
|
||||
.attr = {
|
||||
.name = "w1_slave",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = DS2760_DATA_SIZE,
|
||||
.read = w1_ds2760_read_bin,
|
||||
static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_ds2760_bin_attrs[] = {
|
||||
&bin_attr_w1_slave,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group w1_ds2760_group = {
|
||||
.bin_attrs = w1_ds2760_bin_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *w1_ds2760_groups[] = {
|
||||
&w1_ds2760_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static DEFINE_IDA(bat_ida);
|
||||
|
@ -139,16 +146,10 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
|
|||
if (ret)
|
||||
goto pdev_add_failed;
|
||||
|
||||
ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
|
||||
if (ret)
|
||||
goto bin_attr_failed;
|
||||
|
||||
dev_set_drvdata(&sl->dev, pdev);
|
||||
|
||||
goto success;
|
||||
|
||||
bin_attr_failed:
|
||||
platform_device_del(pdev);
|
||||
pdev_add_failed:
|
||||
platform_device_put(pdev);
|
||||
pdev_alloc_failed:
|
||||
|
@ -165,12 +166,12 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
|
|||
|
||||
platform_device_unregister(pdev);
|
||||
ida_simple_remove(&bat_ida, id);
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
|
||||
}
|
||||
|
||||
static struct w1_family_ops w1_ds2760_fops = {
|
||||
.add_slave = w1_ds2760_add_slave,
|
||||
.remove_slave = w1_ds2760_remove_slave,
|
||||
.groups = w1_ds2760_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_ds2760_family = {
|
||||
|
|
|
@ -89,22 +89,28 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
|
|||
}
|
||||
EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
|
||||
|
||||
static ssize_t w1_ds2780_read_bin(struct file *filp,
|
||||
struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
return w1_ds2780_io(dev, buf, off, count, 0);
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_ds2780_bin_attr = {
|
||||
.attr = {
|
||||
.name = "w1_slave",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = DS2780_DATA_SIZE,
|
||||
.read = w1_ds2780_read_bin,
|
||||
static BIN_ATTR_RO(w1_slave, DS2780_DATA_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_ds2780_bin_attrs[] = {
|
||||
&bin_attr_w1_slave,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group w1_ds2780_group = {
|
||||
.bin_attrs = w1_ds2780_bin_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *w1_ds2780_groups[] = {
|
||||
&w1_ds2780_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static DEFINE_IDA(bat_ida);
|
||||
|
@ -132,16 +138,10 @@ static int w1_ds2780_add_slave(struct w1_slave *sl)
|
|||
if (ret)
|
||||
goto pdev_add_failed;
|
||||
|
||||
ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
|
||||
if (ret)
|
||||
goto bin_attr_failed;
|
||||
|
||||
dev_set_drvdata(&sl->dev, pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
bin_attr_failed:
|
||||
platform_device_del(pdev);
|
||||
pdev_add_failed:
|
||||
platform_device_put(pdev);
|
||||
pdev_alloc_failed:
|
||||
|
@ -157,12 +157,12 @@ static void w1_ds2780_remove_slave(struct w1_slave *sl)
|
|||
|
||||
platform_device_unregister(pdev);
|
||||
ida_simple_remove(&bat_ida, id);
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
|
||||
}
|
||||
|
||||
static struct w1_family_ops w1_ds2780_fops = {
|
||||
.add_slave = w1_ds2780_add_slave,
|
||||
.remove_slave = w1_ds2780_remove_slave,
|
||||
.groups = w1_ds2780_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_ds2780_family = {
|
||||
|
|
|
@ -87,22 +87,28 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd)
|
|||
}
|
||||
EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
|
||||
|
||||
static ssize_t w1_ds2781_read_bin(struct file *filp,
|
||||
struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
return w1_ds2781_io(dev, buf, off, count, 0);
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_ds2781_bin_attr = {
|
||||
.attr = {
|
||||
.name = "w1_slave",
|
||||
.mode = S_IRUGO,
|
||||
},
|
||||
.size = DS2781_DATA_SIZE,
|
||||
.read = w1_ds2781_read_bin,
|
||||
static BIN_ATTR_RO(w1_slave, DS2781_DATA_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_ds2781_bin_attrs[] = {
|
||||
&bin_attr_w1_slave,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group w1_ds2781_group = {
|
||||
.bin_attrs = w1_ds2781_bin_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *w1_ds2781_groups[] = {
|
||||
&w1_ds2781_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static DEFINE_IDA(bat_ida);
|
||||
|
@ -130,16 +136,10 @@ static int w1_ds2781_add_slave(struct w1_slave *sl)
|
|||
if (ret)
|
||||
goto pdev_add_failed;
|
||||
|
||||
ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr);
|
||||
if (ret)
|
||||
goto bin_attr_failed;
|
||||
|
||||
dev_set_drvdata(&sl->dev, pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
bin_attr_failed:
|
||||
platform_device_del(pdev);
|
||||
pdev_add_failed:
|
||||
platform_device_put(pdev);
|
||||
pdev_alloc_failed:
|
||||
|
@ -155,12 +155,12 @@ static void w1_ds2781_remove_slave(struct w1_slave *sl)
|
|||
|
||||
platform_device_unregister(pdev);
|
||||
ida_simple_remove(&bat_ida, id);
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr);
|
||||
}
|
||||
|
||||
static struct w1_family_ops w1_ds2781_fops = {
|
||||
.add_slave = w1_ds2781_add_slave,
|
||||
.remove_slave = w1_ds2781_remove_slave,
|
||||
.groups = w1_ds2781_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_ds2781_family = {
|
||||
|
|
|
@ -118,9 +118,9 @@ static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data)
|
|||
return w1_read_block(sl->master, data, len);
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
struct w1_f1C_data *data = sl->family_data;
|
||||
|
@ -226,9 +226,9 @@ static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
|
@ -280,9 +280,11 @@ out_up:
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
|
||||
|
||||
static ssize_t pio_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
|
@ -299,9 +301,9 @@ static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t pio_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
|
@ -339,8 +341,10 @@ static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_show_crccheck(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static BIN_ATTR_RW(pio, 1);
|
||||
|
||||
static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (put_user(w1_enable_crccheck + 0x30, buf))
|
||||
return -EFAULT;
|
||||
|
@ -348,9 +352,8 @@ static ssize_t w1_f1C_show_crccheck(struct device *dev,
|
|||
return sizeof(w1_enable_crccheck);
|
||||
}
|
||||
|
||||
static ssize_t w1_f1C_store_crccheck(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
char val;
|
||||
|
||||
|
@ -371,35 +374,31 @@ static ssize_t w1_f1C_store_crccheck(struct device *dev,
|
|||
return sizeof(w1_enable_crccheck);
|
||||
}
|
||||
|
||||
#define NB_SYSFS_BIN_FILES 2
|
||||
static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = {
|
||||
{
|
||||
.attr = {
|
||||
.name = "eeprom",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = W1_EEPROM_SIZE,
|
||||
.read = w1_f1C_read_bin,
|
||||
.write = w1_f1C_write_bin,
|
||||
},
|
||||
{
|
||||
.attr = {
|
||||
.name = "pio",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = 1,
|
||||
.read = w1_f1C_read_pio,
|
||||
.write = w1_f1C_write_pio,
|
||||
}
|
||||
static DEVICE_ATTR_RW(crccheck);
|
||||
|
||||
static struct attribute *w1_f1C_attrs[] = {
|
||||
&dev_attr_crccheck.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static DEVICE_ATTR(crccheck, S_IWUSR | S_IRUGO,
|
||||
w1_f1C_show_crccheck, w1_f1C_store_crccheck);
|
||||
static struct bin_attribute *w1_f1C_bin_attrs[] = {
|
||||
&bin_attr_eeprom,
|
||||
&bin_attr_pio,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group w1_f1C_group = {
|
||||
.attrs = w1_f1C_attrs,
|
||||
.bin_attrs = w1_f1C_bin_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *w1_f1C_groups[] = {
|
||||
&w1_f1C_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_f1C_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
struct w1_f1C_data *data = NULL;
|
||||
|
||||
if (w1_enable_crccheck) {
|
||||
|
@ -409,46 +408,19 @@ static int w1_f1C_add_slave(struct w1_slave *sl)
|
|||
sl->family_data = data;
|
||||
}
|
||||
|
||||
/* create binary sysfs attributes */
|
||||
for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
|
||||
err = sysfs_create_bin_file(
|
||||
&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
|
||||
|
||||
if (!err) {
|
||||
/* create device attributes */
|
||||
err = device_create_file(&sl->dev, &dev_attr_crccheck);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
/* remove binary sysfs attributes */
|
||||
for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
|
||||
sysfs_remove_bin_file(
|
||||
&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void w1_f1C_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
int i;
|
||||
|
||||
kfree(sl->family_data);
|
||||
sl->family_data = NULL;
|
||||
|
||||
/* remove device attributes */
|
||||
device_remove_file(&sl->dev, &dev_attr_crccheck);
|
||||
|
||||
/* remove binary sysfs attributes */
|
||||
for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
|
||||
}
|
||||
|
||||
static struct w1_family_ops w1_f1C_fops = {
|
||||
.add_slave = w1_f1C_add_slave,
|
||||
.remove_slave = w1_f1C_remove_slave,
|
||||
.groups = w1_f1C_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_family_1C = {
|
||||
|
|
|
@ -59,25 +59,19 @@ static int w1_strong_pullup = 1;
|
|||
module_param_named(strong_pullup, w1_strong_pullup, int, 0);
|
||||
|
||||
|
||||
static ssize_t w1_therm_read(struct device *device,
|
||||
static ssize_t w1_slave_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
static struct device_attribute w1_therm_attr =
|
||||
__ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL);
|
||||
static DEVICE_ATTR_RO(w1_slave);
|
||||
|
||||
static int w1_therm_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
return device_create_file(&sl->dev, &w1_therm_attr);
|
||||
}
|
||||
|
||||
static void w1_therm_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
device_remove_file(&sl->dev, &w1_therm_attr);
|
||||
}
|
||||
static struct attribute *w1_therm_attrs[] = {
|
||||
&dev_attr_w1_slave.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(w1_therm);
|
||||
|
||||
static struct w1_family_ops w1_therm_fops = {
|
||||
.add_slave = w1_therm_add_slave,
|
||||
.remove_slave = w1_therm_remove_slave,
|
||||
.groups = w1_therm_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_therm_family_DS18S20 = {
|
||||
|
@ -178,7 +172,7 @@ static inline int w1_convert_temp(u8 rom[9], u8 fid)
|
|||
}
|
||||
|
||||
|
||||
static ssize_t w1_therm_read(struct device *device,
|
||||
static ssize_t w1_slave_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct w1_slave *sl = dev_to_w1_slave(device);
|
||||
|
|
164
drivers/w1/w1.c
164
drivers/w1/w1.c
|
@ -96,14 +96,15 @@ static void w1_slave_release(struct device *dev)
|
|||
complete(&sl->released);
|
||||
}
|
||||
|
||||
static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct w1_slave *sl = dev_to_w1_slave(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", sl->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t w1_slave_read_id(struct device *dev,
|
||||
static ssize_t id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct w1_slave *sl = dev_to_w1_slave(dev);
|
||||
|
@ -112,17 +113,20 @@ static ssize_t w1_slave_read_id(struct device *dev,
|
|||
memcpy(buf, (u8 *)&sl->reg_num, count);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RO(id);
|
||||
|
||||
static struct device_attribute w1_slave_attr_name =
|
||||
__ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
|
||||
static struct device_attribute w1_slave_attr_id =
|
||||
__ATTR(id, S_IRUGO, w1_slave_read_id, NULL);
|
||||
static struct attribute *w1_slave_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_id.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(w1_slave);
|
||||
|
||||
/* Default family */
|
||||
|
||||
static ssize_t w1_default_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t rw_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
|
||||
|
@ -139,9 +143,9 @@ out_up:
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t w1_default_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
static ssize_t rw_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct w1_slave *sl = kobj_to_w1_slave(kobj);
|
||||
|
||||
|
@ -151,29 +155,24 @@ static ssize_t w1_default_read(struct file *filp, struct kobject *kobj,
|
|||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute w1_default_attr = {
|
||||
.attr = {
|
||||
.name = "rw",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = PAGE_SIZE,
|
||||
.read = w1_default_read,
|
||||
.write = w1_default_write,
|
||||
static BIN_ATTR_RW(rw, PAGE_SIZE);
|
||||
|
||||
static struct bin_attribute *w1_slave_bin_attrs[] = {
|
||||
&bin_attr_rw,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int w1_default_add_slave(struct w1_slave *sl)
|
||||
{
|
||||
return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr);
|
||||
}
|
||||
static const struct attribute_group w1_slave_default_group = {
|
||||
.bin_attrs = w1_slave_bin_attrs,
|
||||
};
|
||||
|
||||
static void w1_default_remove_slave(struct w1_slave *sl)
|
||||
{
|
||||
sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr);
|
||||
}
|
||||
static const struct attribute_group *w1_slave_default_groups[] = {
|
||||
&w1_slave_default_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct w1_family_ops w1_default_fops = {
|
||||
.add_slave = w1_default_add_slave,
|
||||
.remove_slave = w1_default_remove_slave,
|
||||
.groups = w1_slave_default_groups,
|
||||
};
|
||||
|
||||
static struct w1_family w1_default_family = {
|
||||
|
@ -587,6 +586,66 @@ end:
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle sysfs file creation and removal here, before userspace is told that
|
||||
* the device is added / removed from the system
|
||||
*/
|
||||
static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct w1_slave *sl;
|
||||
struct w1_family_ops *fops;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Only care about slave devices at the moment. Yes, we should use a
|
||||
* separate "type" for this, but for now, look at the release function
|
||||
* to know which type it is...
|
||||
*/
|
||||
if (dev->release != w1_slave_release)
|
||||
return 0;
|
||||
|
||||
sl = dev_to_w1_slave(dev);
|
||||
fops = sl->family->fops;
|
||||
|
||||
switch (action) {
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
/* if the family driver needs to initialize something... */
|
||||
if (fops->add_slave) {
|
||||
err = fops->add_slave(sl);
|
||||
if (err < 0) {
|
||||
dev_err(&sl->dev,
|
||||
"add_slave() call failed. err=%d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (fops->groups) {
|
||||
err = sysfs_create_groups(&sl->dev.kobj, fops->groups);
|
||||
if (err) {
|
||||
dev_err(&sl->dev,
|
||||
"sysfs group creation failed. err=%d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BUS_NOTIFY_DEL_DEVICE:
|
||||
if (fops->remove_slave)
|
||||
sl->family->fops->remove_slave(sl);
|
||||
if (fops->groups)
|
||||
sysfs_remove_groups(&sl->dev.kobj, fops->groups);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block w1_bus_nb = {
|
||||
.notifier_call = w1_bus_notify,
|
||||
};
|
||||
|
||||
static int __w1_attach_slave_device(struct w1_slave *sl)
|
||||
{
|
||||
int err;
|
||||
|
@ -595,6 +654,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
|
|||
sl->dev.driver = &w1_slave_driver;
|
||||
sl->dev.bus = &w1_bus_type;
|
||||
sl->dev.release = &w1_slave_release;
|
||||
sl->dev.groups = w1_slave_groups;
|
||||
|
||||
dev_set_name(&sl->dev, "%02x-%012llx",
|
||||
(unsigned int) sl->reg_num.family,
|
||||
|
@ -615,44 +675,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Create "name" entry */
|
||||
err = device_create_file(&sl->dev, &w1_slave_attr_name);
|
||||
if (err < 0) {
|
||||
dev_err(&sl->dev,
|
||||
"sysfs file creation for [%s] failed. err=%d\n",
|
||||
dev_name(&sl->dev), err);
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
/* Create "id" entry */
|
||||
err = device_create_file(&sl->dev, &w1_slave_attr_id);
|
||||
if (err < 0) {
|
||||
dev_err(&sl->dev,
|
||||
"sysfs file creation for [%s] failed. err=%d\n",
|
||||
dev_name(&sl->dev), err);
|
||||
goto out_rem1;
|
||||
}
|
||||
|
||||
/* if the family driver needs to initialize something... */
|
||||
if (sl->family->fops && sl->family->fops->add_slave &&
|
||||
((err = sl->family->fops->add_slave(sl)) < 0)) {
|
||||
dev_err(&sl->dev,
|
||||
"sysfs file creation for [%s] failed. err=%d\n",
|
||||
dev_name(&sl->dev), err);
|
||||
goto out_rem2;
|
||||
}
|
||||
dev_set_uevent_suppress(&sl->dev, false);
|
||||
kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
|
||||
|
||||
list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
|
||||
|
||||
return 0;
|
||||
|
||||
out_rem2:
|
||||
device_remove_file(&sl->dev, &w1_slave_attr_id);
|
||||
out_rem1:
|
||||
device_remove_file(&sl->dev, &w1_slave_attr_name);
|
||||
out_unreg:
|
||||
device_unregister(&sl->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
|
||||
|
@ -723,16 +752,11 @@ void w1_slave_detach(struct w1_slave *sl)
|
|||
|
||||
list_del(&sl->w1_slave_entry);
|
||||
|
||||
if (sl->family->fops && sl->family->fops->remove_slave)
|
||||
sl->family->fops->remove_slave(sl);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
|
||||
msg.type = W1_SLAVE_REMOVE;
|
||||
w1_netlink_send(sl->master, &msg);
|
||||
|
||||
device_remove_file(&sl->dev, &w1_slave_attr_id);
|
||||
device_remove_file(&sl->dev, &w1_slave_attr_name);
|
||||
device_unregister(&sl->dev);
|
||||
|
||||
wait_for_completion(&sl->released);
|
||||
|
@ -1017,6 +1041,10 @@ static int __init w1_init(void)
|
|||
goto err_out_exit_init;
|
||||
}
|
||||
|
||||
retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb);
|
||||
if (retval)
|
||||
goto err_out_bus_unregister;
|
||||
|
||||
retval = driver_register(&w1_master_driver);
|
||||
if (retval) {
|
||||
printk(KERN_ERR
|
||||
|
|
|
@ -52,6 +52,7 @@ struct w1_family_ops
|
|||
{
|
||||
int (* add_slave)(struct w1_slave *);
|
||||
void (* remove_slave)(struct w1_slave *);
|
||||
const struct attribute_group **groups;
|
||||
};
|
||||
|
||||
struct w1_family
|
||||
|
|
|
@ -568,6 +568,7 @@ static ssize_t cuse_class_waiting_show(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting));
|
||||
}
|
||||
static DEVICE_ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL);
|
||||
|
||||
static ssize_t cuse_class_abort_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -578,12 +579,14 @@ static ssize_t cuse_class_abort_store(struct device *dev,
|
|||
fuse_abort_conn(&cc->fc);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store);
|
||||
|
||||
static struct device_attribute cuse_class_dev_attrs[] = {
|
||||
__ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL),
|
||||
__ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store),
|
||||
{ }
|
||||
static struct attribute *cuse_class_dev_attrs[] = {
|
||||
&dev_attr_waiting.attr,
|
||||
&dev_attr_abort.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(cuse_class_dev);
|
||||
|
||||
static struct miscdevice cuse_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
|
@ -609,7 +612,7 @@ static int __init cuse_init(void)
|
|||
if (IS_ERR(cuse_class))
|
||||
return PTR_ERR(cuse_class);
|
||||
|
||||
cuse_class->dev_attrs = cuse_class_dev_attrs;
|
||||
cuse_class->dev_groups = cuse_class_dev_groups;
|
||||
|
||||
rc = misc_register(&cuse_miscdev);
|
||||
if (rc) {
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "sysfs.h"
|
||||
|
||||
|
@ -391,7 +390,7 @@ out_unlock:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int open(struct inode * inode, struct file * file)
|
||||
static int open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
||||
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
|
||||
|
@ -435,7 +434,7 @@ static int open(struct inode * inode, struct file * file)
|
|||
return error;
|
||||
}
|
||||
|
||||
static int release(struct inode * inode, struct file * file)
|
||||
static int release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct bin_buffer *bb = file->private_data;
|
||||
|
||||
|
@ -481,7 +480,6 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd)
|
|||
* @kobj: object.
|
||||
* @attr: attribute descriptor.
|
||||
*/
|
||||
|
||||
int sysfs_create_bin_file(struct kobject *kobj,
|
||||
const struct bin_attribute *attr)
|
||||
{
|
||||
|
@ -489,19 +487,16 @@ int sysfs_create_bin_file(struct kobject *kobj,
|
|||
|
||||
return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
|
||||
|
||||
/**
|
||||
* sysfs_remove_bin_file - remove binary file for object.
|
||||
* @kobj: object.
|
||||
* @attr: attribute descriptor.
|
||||
*/
|
||||
|
||||
void sysfs_remove_bin_file(struct kobject *kobj,
|
||||
const struct bin_attribute *attr)
|
||||
{
|
||||
sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
|
||||
|
|
|
@ -46,7 +46,7 @@ static unsigned int sysfs_name_hash(const void *ns, const char *name)
|
|||
unsigned int len = strlen(name);
|
||||
while (len--)
|
||||
hash = partial_name_hash(*name++, hash);
|
||||
hash = ( end_name_hash(hash) ^ hash_ptr( (void *)ns, 31 ) );
|
||||
hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31));
|
||||
hash &= 0x7fffffffU;
|
||||
/* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
|
||||
if (hash < 1)
|
||||
|
@ -258,7 +258,7 @@ static void sysfs_free_ino(unsigned int ino)
|
|||
spin_unlock(&sysfs_ino_lock);
|
||||
}
|
||||
|
||||
void release_sysfs_dirent(struct sysfs_dirent * sd)
|
||||
void release_sysfs_dirent(struct sysfs_dirent *sd)
|
||||
{
|
||||
struct sysfs_dirent *parent_sd;
|
||||
|
||||
|
@ -451,7 +451,7 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
|
|||
|
||||
if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
|
||||
WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
|
||||
sysfs_ns_type(acxt->parent_sd)? "required": "invalid",
|
||||
sysfs_ns_type(acxt->parent_sd) ? "required" : "invalid",
|
||||
acxt->parent_sd->s_name, sd->s_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
|
|||
|
||||
if (!!sysfs_ns_type(parent_sd) != !!ns) {
|
||||
WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
|
||||
sysfs_ns_type(parent_sd)? "required": "invalid",
|
||||
sysfs_ns_type(parent_sd) ? "required" : "invalid",
|
||||
parent_sd->s_name, name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
|
|||
enum kobj_ns_type type, const void *ns, const char *name,
|
||||
struct sysfs_dirent **p_sd)
|
||||
{
|
||||
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
|
||||
umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
|
||||
struct sysfs_addrm_cxt acxt;
|
||||
struct sysfs_dirent *sd;
|
||||
int rc;
|
||||
|
@ -735,9 +735,9 @@ static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
|
|||
|
||||
/**
|
||||
* sysfs_create_dir - create a directory for an object.
|
||||
* @kobj: object we're creating directory for.
|
||||
* @kobj: object we're creating directory for.
|
||||
*/
|
||||
int sysfs_create_dir(struct kobject * kobj)
|
||||
int sysfs_create_dir(struct kobject *kobj)
|
||||
{
|
||||
enum kobj_ns_type type;
|
||||
struct sysfs_dirent *parent_sd, *sd;
|
||||
|
@ -764,8 +764,8 @@ int sysfs_create_dir(struct kobject * kobj)
|
|||
return error;
|
||||
}
|
||||
|
||||
static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct dentry *ret = NULL;
|
||||
struct dentry *parent = dentry->d_parent;
|
||||
|
@ -857,7 +857,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
|
|||
* what used to be sysfs_rmdir() below, instead of calling separately.
|
||||
*/
|
||||
|
||||
void sysfs_remove_dir(struct kobject * kobj)
|
||||
void sysfs_remove_dir(struct kobject *kobj)
|
||||
{
|
||||
struct sysfs_dirent *sd = kobj->sd;
|
||||
|
||||
|
@ -896,7 +896,9 @@ int sysfs_rename(struct sysfs_dirent *sd,
|
|||
sd->s_name = new_name;
|
||||
}
|
||||
|
||||
/* Move to the appropriate place in the appropriate directories rbtree. */
|
||||
/*
|
||||
* Move to the appropriate place in the appropriate directories rbtree.
|
||||
*/
|
||||
sysfs_unlink_sibling(sd);
|
||||
sysfs_get(new_parent_sd);
|
||||
sysfs_put(sd->s_parent);
|
||||
|
@ -988,20 +990,21 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
|
|||
struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
|
||||
{
|
||||
pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
|
||||
if (pos) do {
|
||||
struct rb_node *node = rb_next(&pos->s_rb);
|
||||
if (!node)
|
||||
pos = NULL;
|
||||
else
|
||||
pos = to_sysfs_dirent(node);
|
||||
} while (pos && pos->s_ns != ns);
|
||||
if (pos)
|
||||
do {
|
||||
struct rb_node *node = rb_next(&pos->s_rb);
|
||||
if (!node)
|
||||
pos = NULL;
|
||||
else
|
||||
pos = to_sysfs_dirent(node);
|
||||
} while (pos && pos->s_ns != ns);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int sysfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
|
||||
struct sysfs_dirent *parent_sd = dentry->d_fsdata;
|
||||
struct sysfs_dirent *pos = file->private_data;
|
||||
enum kobj_ns_type type;
|
||||
const void *ns;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/limits.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "sysfs.h"
|
||||
|
||||
|
@ -45,8 +45,8 @@ struct sysfs_open_dirent {
|
|||
struct sysfs_buffer {
|
||||
size_t count;
|
||||
loff_t pos;
|
||||
char * page;
|
||||
const struct sysfs_ops * ops;
|
||||
char *page;
|
||||
const struct sysfs_ops *ops;
|
||||
struct mutex mutex;
|
||||
int needs_read_fill;
|
||||
int event;
|
||||
|
@ -59,16 +59,16 @@ struct sysfs_buffer {
|
|||
* @buffer: data buffer for file.
|
||||
*
|
||||
* Allocate @buffer->page, if it hasn't been already, then call the
|
||||
* kobject's show() method to fill the buffer with this attribute's
|
||||
* data.
|
||||
* kobject's show() method to fill the buffer with this attribute's
|
||||
* data.
|
||||
* This is called only once, on the file's first read unless an error
|
||||
* is returned.
|
||||
*/
|
||||
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
|
||||
static int fill_read_buffer(struct dentry *dentry, struct sysfs_buffer *buffer)
|
||||
{
|
||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||
const struct sysfs_ops * ops = buffer->ops;
|
||||
const struct sysfs_ops *ops = buffer->ops;
|
||||
int ret = 0;
|
||||
ssize_t count;
|
||||
|
||||
|
@ -106,7 +106,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
|
|||
}
|
||||
|
||||
/**
|
||||
* sysfs_read_file - read an attribute.
|
||||
* sysfs_read_file - read an attribute.
|
||||
* @file: file pointer.
|
||||
* @buf: buffer to fill.
|
||||
* @count: number of bytes to read.
|
||||
|
@ -127,12 +127,12 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
|
|||
static ssize_t
|
||||
sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct sysfs_buffer * buffer = file->private_data;
|
||||
struct sysfs_buffer *buffer = file->private_data;
|
||||
ssize_t retval = 0;
|
||||
|
||||
mutex_lock(&buffer->mutex);
|
||||
if (buffer->needs_read_fill || *ppos == 0) {
|
||||
retval = fill_read_buffer(file->f_path.dentry,buffer);
|
||||
retval = fill_read_buffer(file->f_path.dentry, buffer);
|
||||
if (retval)
|
||||
goto out;
|
||||
}
|
||||
|
@ -154,9 +154,8 @@ out:
|
|||
* Allocate @buffer->page if it hasn't been already, then
|
||||
* copy the user-supplied buffer into it.
|
||||
*/
|
||||
|
||||
static int
|
||||
fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
|
||||
static int fill_write_buffer(struct sysfs_buffer *buffer,
|
||||
const char __user *buf, size_t count)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -167,7 +166,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
|
|||
|
||||
if (count >= PAGE_SIZE)
|
||||
count = PAGE_SIZE - 1;
|
||||
error = copy_from_user(buffer->page,buf,count);
|
||||
error = copy_from_user(buffer->page, buf, count);
|
||||
buffer->needs_read_fill = 1;
|
||||
/* if buf is assumed to contain a string, terminate it by \0,
|
||||
so e.g. sscanf() can scan the string easily */
|
||||
|
@ -183,16 +182,15 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
|
|||
* @count: number of bytes
|
||||
*
|
||||
* Get the correct pointers for the kobject and the attribute we're
|
||||
* dealing with, then call the store() method for the attribute,
|
||||
* dealing with, then call the store() method for the attribute,
|
||||
* passing the buffer that we acquired in fill_write_buffer().
|
||||
*/
|
||||
|
||||
static int
|
||||
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
|
||||
static int flush_write_buffer(struct dentry *dentry,
|
||||
struct sysfs_buffer *buffer, size_t count)
|
||||
{
|
||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||
const struct sysfs_ops * ops = buffer->ops;
|
||||
const struct sysfs_ops *ops = buffer->ops;
|
||||
int rc;
|
||||
|
||||
/* need attr_sd for attr and ops, its parent for kobj */
|
||||
|
@ -219,15 +217,14 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
|
|||
* then push it to the kobject in flush_write_buffer().
|
||||
* There is no easy way for us to know if userspace is only doing a partial
|
||||
* write, so we don't support them. We expect the entire buffer to come
|
||||
* on the first write.
|
||||
* on the first write.
|
||||
* Hint: if you're writing a value, first read the file, modify only the
|
||||
* the value you're changing, then write entire buffer back.
|
||||
* the value you're changing, then write entire buffer back.
|
||||
*/
|
||||
|
||||
static ssize_t
|
||||
sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
static ssize_t sysfs_write_file(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct sysfs_buffer * buffer = file->private_data;
|
||||
struct sysfs_buffer *buffer = file->private_data;
|
||||
ssize_t len;
|
||||
|
||||
mutex_lock(&buffer->mutex);
|
||||
|
@ -339,13 +336,14 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
|
|||
if (kobj->ktype && kobj->ktype->sysfs_ops)
|
||||
ops = kobj->ktype->sysfs_ops;
|
||||
else {
|
||||
WARN(1, KERN_ERR "missing sysfs attribute operations for "
|
||||
"kobject: %s\n", kobject_name(kobj));
|
||||
WARN(1, KERN_ERR
|
||||
"missing sysfs attribute operations for kobject: %s\n",
|
||||
kobject_name(kobj));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* File needs write support.
|
||||
* The inode's perms must say it's ok,
|
||||
* The inode's perms must say it's ok,
|
||||
* and we must have a store method.
|
||||
*/
|
||||
if (file->f_mode & FMODE_WRITE) {
|
||||
|
@ -420,7 +418,7 @@ static int sysfs_release(struct inode *inode, struct file *filp)
|
|||
*/
|
||||
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
||||
{
|
||||
struct sysfs_buffer * buffer = filp->private_data;
|
||||
struct sysfs_buffer *buffer = filp->private_data;
|
||||
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
|
||||
struct sysfs_open_dirent *od = attr_sd->s_attr.open;
|
||||
|
||||
|
@ -518,8 +516,9 @@ static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
|
|||
ns = ops->namespace(kobj, attr);
|
||||
out:
|
||||
if (err) {
|
||||
WARN(1, KERN_ERR "missing sysfs namespace attribute operation for "
|
||||
"kobject: %s\n", kobject_name(kobj));
|
||||
WARN(1, KERN_ERR
|
||||
"missing sysfs namespace attribute operation for kobject: %s\n",
|
||||
kobject_name(kobj));
|
||||
}
|
||||
*pns = ns;
|
||||
return err;
|
||||
|
@ -566,17 +565,17 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
|
|||
|
||||
/**
|
||||
* sysfs_create_file - create an attribute file for an object.
|
||||
* @kobj: object we're creating for.
|
||||
* @kobj: object we're creating for.
|
||||
* @attr: attribute descriptor.
|
||||
*/
|
||||
|
||||
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
|
||||
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr)
|
||||
{
|
||||
BUG_ON(!kobj || !kobj->sd || !attr);
|
||||
|
||||
return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_file);
|
||||
|
||||
int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
|
||||
{
|
||||
|
@ -590,6 +589,7 @@ int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
|
|||
sysfs_remove_file(kobj, ptr[i]);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_files);
|
||||
|
||||
/**
|
||||
* sysfs_add_file_to_group - add an attribute file to a pre-existing group.
|
||||
|
@ -654,7 +654,6 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_chmod_file);
|
||||
|
||||
|
||||
/**
|
||||
* sysfs_remove_file - remove an object attribute.
|
||||
* @kobj: object we're acting for.
|
||||
|
@ -662,8 +661,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
|
|||
*
|
||||
* Hash the attribute name and kill the victim.
|
||||
*/
|
||||
|
||||
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
|
||||
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr)
|
||||
{
|
||||
const void *ns;
|
||||
|
||||
|
@ -672,13 +670,15 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
|
|||
|
||||
sysfs_hash_and_remove(kobj->sd, ns, attr->name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_file);
|
||||
|
||||
void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
|
||||
void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; ptr[i]; i++)
|
||||
sysfs_remove_file(kobj, ptr[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_files);
|
||||
|
||||
/**
|
||||
* sysfs_remove_file_from_group - remove an attribute file from a group.
|
||||
|
@ -793,9 +793,3 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
|
||||
|
||||
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_file);
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_file);
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_files);
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_files);
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
*
|
||||
* Copyright (c) 2003 Patrick Mochel
|
||||
* Copyright (c) 2003 Open Source Development Lab
|
||||
* Copyright (c) 2013 Greg Kroah-Hartman
|
||||
* Copyright (c) 2013 The Linux Foundation
|
||||
*
|
||||
* This file is released undert the GPL v2.
|
||||
* This file is released undert the GPL v2.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -19,8 +21,8 @@
|
|||
static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
|
||||
const struct attribute_group *grp)
|
||||
{
|
||||
struct attribute *const* attr;
|
||||
struct bin_attribute *const* bin_attr;
|
||||
struct attribute *const *attr;
|
||||
struct bin_attribute *const *bin_attr;
|
||||
|
||||
if (grp->attrs)
|
||||
for (attr = grp->attrs; *attr; attr++)
|
||||
|
@ -33,8 +35,8 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
|
|||
static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
|
||||
const struct attribute_group *grp, int update)
|
||||
{
|
||||
struct attribute *const* attr;
|
||||
struct bin_attribute *const* bin_attr;
|
||||
struct attribute *const *attr;
|
||||
struct bin_attribute *const *bin_attr;
|
||||
int error = 0, i;
|
||||
|
||||
if (grp->attrs) {
|
||||
|
@ -129,6 +131,41 @@ int sysfs_create_group(struct kobject *kobj,
|
|||
{
|
||||
return internal_create_group(kobj, 0, grp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_group);
|
||||
|
||||
/**
|
||||
* sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
|
||||
* @kobj: The kobject to create the group on
|
||||
* @groups: The attribute groups to create, NULL terminated
|
||||
*
|
||||
* This function creates a bunch of attribute groups. If an error occurs when
|
||||
* creating a group, all previously created groups will be removed, unwinding
|
||||
* everything back to the original state when this function was called.
|
||||
* It will explicitly warn and error if any of the attribute files being
|
||||
* created already exist.
|
||||
*
|
||||
* Returns 0 on success or error code from sysfs_create_group on error.
|
||||
*/
|
||||
int sysfs_create_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
int error = 0;
|
||||
int i;
|
||||
|
||||
if (!groups)
|
||||
return 0;
|
||||
|
||||
for (i = 0; groups[i]; i++) {
|
||||
error = sysfs_create_group(kobj, groups[i]);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
sysfs_remove_group(kobj, groups[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_groups);
|
||||
|
||||
/**
|
||||
* sysfs_update_group - given a directory kobject, update an attribute group
|
||||
|
@ -152,11 +189,18 @@ int sysfs_update_group(struct kobject *kobj,
|
|||
{
|
||||
return internal_create_group(kobj, 1, grp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_update_group);
|
||||
|
||||
|
||||
|
||||
void sysfs_remove_group(struct kobject * kobj,
|
||||
const struct attribute_group * grp)
|
||||
/**
|
||||
* sysfs_remove_group: remove a group from a kobject
|
||||
* @kobj: kobject to remove the group from
|
||||
* @grp: group to remove
|
||||
*
|
||||
* This function removes a group of attributes from a kobject. The attributes
|
||||
* previously have to have been created for this group, otherwise it will fail.
|
||||
*/
|
||||
void sysfs_remove_group(struct kobject *kobj,
|
||||
const struct attribute_group *grp)
|
||||
{
|
||||
struct sysfs_dirent *dir_sd = kobj->sd;
|
||||
struct sysfs_dirent *sd;
|
||||
|
@ -164,8 +208,9 @@ void sysfs_remove_group(struct kobject * kobj,
|
|||
if (grp->name) {
|
||||
sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
|
||||
if (!sd) {
|
||||
WARN(!sd, KERN_WARNING "sysfs group %p not found for "
|
||||
"kobject '%s'\n", grp, kobject_name(kobj));
|
||||
WARN(!sd, KERN_WARNING
|
||||
"sysfs group %p not found for kobject '%s'\n",
|
||||
grp, kobject_name(kobj));
|
||||
return;
|
||||
}
|
||||
} else
|
||||
|
@ -177,6 +222,27 @@ void sysfs_remove_group(struct kobject * kobj,
|
|||
|
||||
sysfs_put(sd);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_group);
|
||||
|
||||
/**
|
||||
* sysfs_remove_groups - remove a list of groups
|
||||
*
|
||||
* @kobj: The kobject for the groups to be removed from
|
||||
* @groups: NULL terminated list of groups to be removed
|
||||
*
|
||||
* If groups is not NULL, remove the specified groups from the kobject.
|
||||
*/
|
||||
void sysfs_remove_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!groups)
|
||||
return;
|
||||
for (i = 0; groups[i]; i++)
|
||||
sysfs_remove_group(kobj, groups[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_groups);
|
||||
|
||||
/**
|
||||
* sysfs_merge_group - merge files into a pre-existing attribute group.
|
||||
|
@ -273,7 +339,3 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
|
|||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
|
||||
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_group);
|
||||
EXPORT_SYMBOL_GPL(sysfs_update_group);
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_group);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/namei.h>
|
||||
|
@ -36,7 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
|
|||
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
|
||||
};
|
||||
|
||||
static const struct inode_operations sysfs_inode_operations ={
|
||||
static const struct inode_operations sysfs_inode_operations = {
|
||||
.permission = sysfs_permission,
|
||||
.setattr = sysfs_setattr,
|
||||
.getattr = sysfs_getattr,
|
||||
|
@ -67,7 +67,7 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
|
|||
return attrs;
|
||||
}
|
||||
|
||||
int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr)
|
||||
int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr)
|
||||
{
|
||||
struct sysfs_inode_attrs *sd_attrs;
|
||||
struct iattr *iattrs;
|
||||
|
@ -128,7 +128,8 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len)
|
||||
static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata,
|
||||
u32 *secdata_len)
|
||||
{
|
||||
struct sysfs_inode_attrs *iattrs;
|
||||
void *old_secdata;
|
||||
|
@ -186,13 +187,13 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
static inline void set_default_inode_attr(struct inode * inode, umode_t mode)
|
||||
static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
|
||||
{
|
||||
inode->i_mode = mode;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||
}
|
||||
|
||||
static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
|
||||
static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
|
||||
{
|
||||
inode->i_uid = iattr->ia_uid;
|
||||
inode->i_gid = iattr->ia_gid;
|
||||
|
@ -220,7 +221,8 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
|
|||
set_nlink(inode, sd->s_dir.subdirs + 2);
|
||||
}
|
||||
|
||||
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat)
|
||||
{
|
||||
struct sysfs_dirent *sd = dentry->d_fsdata;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
|
@ -285,7 +287,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
|
|||
* RETURNS:
|
||||
* Pointer to allocated inode on success, NULL on failure.
|
||||
*/
|
||||
struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
|
||||
struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
|
@ -312,7 +314,8 @@ void sysfs_evict_inode(struct inode *inode)
|
|||
sysfs_put(sd);
|
||||
}
|
||||
|
||||
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name)
|
||||
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
|
||||
const char *name)
|
||||
{
|
||||
struct sysfs_addrm_cxt acxt;
|
||||
struct sysfs_dirent *sd;
|
||||
|
|
|
@ -64,7 +64,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
/* instantiate and link root dentry */
|
||||
root = d_make_root(inode);
|
||||
if (!root) {
|
||||
pr_debug("%s: could not get root dentry!\n",__func__);
|
||||
pr_debug("%s: could not get root dentry!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
root->d_fsdata = &sysfs_root;
|
||||
|
|
|
@ -125,6 +125,7 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target,
|
|||
{
|
||||
return sysfs_do_create_link(kobj, target, name, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_link);
|
||||
|
||||
/**
|
||||
* sysfs_create_link_nowarn - create symlink between two objects.
|
||||
|
@ -166,8 +167,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
|
|||
* @kobj: object we're acting for.
|
||||
* @name: name of the symlink to remove.
|
||||
*/
|
||||
|
||||
void sysfs_remove_link(struct kobject * kobj, const char * name)
|
||||
void sysfs_remove_link(struct kobject *kobj, const char *name)
|
||||
{
|
||||
struct sysfs_dirent *parent_sd = NULL;
|
||||
|
||||
|
@ -178,6 +178,7 @@ void sysfs_remove_link(struct kobject * kobj, const char * name)
|
|||
|
||||
sysfs_hash_and_remove(parent_sd, NULL, name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_link);
|
||||
|
||||
/**
|
||||
* sysfs_rename_link - rename symlink in object's directory.
|
||||
|
@ -223,6 +224,7 @@ out:
|
|||
sysfs_put(sd);
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_rename_link);
|
||||
|
||||
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
|
||||
struct sysfs_dirent *target_sd, char *path)
|
||||
|
@ -276,7 +278,7 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sysfs_getlink(struct dentry *dentry, char * path)
|
||||
static int sysfs_getlink(struct dentry *dentry, char *path)
|
||||
{
|
||||
struct sysfs_dirent *sd = dentry->d_fsdata;
|
||||
struct sysfs_dirent *parent_sd = sd->s_parent;
|
||||
|
@ -295,7 +297,7 @@ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|||
int error = -ENOMEM;
|
||||
unsigned long page = get_zeroed_page(GFP_KERNEL);
|
||||
if (page) {
|
||||
error = sysfs_getlink(dentry, (char *) page);
|
||||
error = sysfs_getlink(dentry, (char *) page);
|
||||
if (error < 0)
|
||||
free_page((unsigned long)page);
|
||||
}
|
||||
|
@ -303,7 +305,8 @@ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
|
||||
static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd,
|
||||
void *cookie)
|
||||
{
|
||||
char *page = nd_get_link(nd);
|
||||
if (!IS_ERR(page))
|
||||
|
@ -319,8 +322,3 @@ const struct inode_operations sysfs_symlink_inode_operations = {
|
|||
.getattr = sysfs_getattr,
|
||||
.permission = sysfs_permission,
|
||||
};
|
||||
|
||||
|
||||
EXPORT_SYMBOL_GPL(sysfs_create_link);
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_link);
|
||||
EXPORT_SYMBOL_GPL(sysfs_rename_link);
|
||||
|
|
|
@ -78,7 +78,7 @@ struct sysfs_dirent {
|
|||
};
|
||||
|
||||
unsigned short s_flags;
|
||||
umode_t s_mode;
|
||||
umode_t s_mode;
|
||||
unsigned int s_ino;
|
||||
struct sysfs_inode_attrs *s_iattr;
|
||||
};
|
||||
|
@ -123,9 +123,9 @@ do { \
|
|||
key = &attr->skey; \
|
||||
\
|
||||
lockdep_init_map(&sd->dep_map, "s_active", key, 0); \
|
||||
} while(0)
|
||||
} while (0)
|
||||
#else
|
||||
#define sysfs_dirent_init_lockdep(sd) do {} while(0)
|
||||
#define sysfs_dirent_init_lockdep(sd) do {} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -186,8 +186,8 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
|
|||
struct sysfs_dirent **p_sd);
|
||||
void sysfs_remove_subdir(struct sysfs_dirent *sd);
|
||||
|
||||
int sysfs_rename(struct sysfs_dirent *sd,
|
||||
struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name);
|
||||
int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
|
||||
const void *ns, const char *new_name);
|
||||
|
||||
static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
|
||||
{
|
||||
|
@ -214,10 +214,12 @@ void sysfs_evict_inode(struct inode *inode);
|
|||
int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
|
||||
int sysfs_permission(struct inode *inode, int mask);
|
||||
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
|
||||
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name);
|
||||
size_t size, int flags);
|
||||
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
|
||||
const char *name);
|
||||
int sysfs_inode_init(void);
|
||||
|
||||
/*
|
||||
|
|
|
@ -192,6 +192,13 @@ static inline struct dentry *debugfs_create_x32(const char *name, umode_t mode,
|
|||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline struct dentry *debugfs_create_x64(const char *name, umode_t mode,
|
||||
struct dentry *parent,
|
||||
u64 *value)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline struct dentry *debugfs_create_size_t(const char *name, umode_t mode,
|
||||
struct dentry *parent,
|
||||
size_t *value)
|
||||
|
|
|
@ -66,6 +66,9 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
|
|||
* @bus_attrs: Default attributes of the bus.
|
||||
* @dev_attrs: Default attributes of the devices on the bus.
|
||||
* @drv_attrs: Default attributes of the device drivers on the bus.
|
||||
* @bus_groups: Default attributes of the bus.
|
||||
* @dev_groups: Default attributes of the devices on the bus.
|
||||
* @drv_groups: Default attributes of the device drivers on the bus.
|
||||
* @match: Called, perhaps multiple times, whenever a new device or driver
|
||||
* is added for this bus. It should return a nonzero value if the
|
||||
* given device can be handled by the given driver.
|
||||
|
@ -103,9 +106,12 @@ struct bus_type {
|
|||
const char *name;
|
||||
const char *dev_name;
|
||||
struct device *dev_root;
|
||||
struct bus_attribute *bus_attrs;
|
||||
struct device_attribute *dev_attrs;
|
||||
struct driver_attribute *drv_attrs;
|
||||
struct bus_attribute *bus_attrs; /* use bus_groups instead */
|
||||
struct device_attribute *dev_attrs; /* use dev_groups instead */
|
||||
struct driver_attribute *drv_attrs; /* use drv_groups instead */
|
||||
const struct attribute_group **bus_groups;
|
||||
const struct attribute_group **dev_groups;
|
||||
const struct attribute_group **drv_groups;
|
||||
|
||||
int (*match)(struct device *dev, struct device_driver *drv);
|
||||
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
|
||||
|
@ -271,6 +277,8 @@ struct driver_attribute {
|
|||
struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
|
||||
#define DRIVER_ATTR_RO(_name) \
|
||||
struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
|
||||
#define DRIVER_ATTR_WO(_name) \
|
||||
struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
|
||||
|
||||
extern int __must_check driver_create_file(struct device_driver *driver,
|
||||
const struct driver_attribute *attr);
|
||||
|
@ -528,6 +536,8 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
|
|||
struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
|
||||
#define DEVICE_ATTR_RO(_name) \
|
||||
struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
|
||||
#define DEVICE_ATTR_WO(_name) \
|
||||
struct device_attribute dev_attr_##_name = __ATTR_WO(_name)
|
||||
#define DEVICE_ULONG_ATTR(_name, _mode, _var) \
|
||||
struct dev_ext_attribute dev_attr_##_name = \
|
||||
{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define UEVENT_HELPER_PATH_LEN 256
|
||||
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
|
||||
|
@ -65,6 +66,9 @@ struct kobject {
|
|||
struct kobj_type *ktype;
|
||||
struct sysfs_dirent *sd;
|
||||
struct kref kref;
|
||||
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
|
||||
struct delayed_work release;
|
||||
#endif
|
||||
unsigned int state_initialized:1;
|
||||
unsigned int state_in_sysfs:1;
|
||||
unsigned int state_add_uevent_sent:1;
|
||||
|
|
|
@ -25,16 +25,9 @@
|
|||
struct memory_block {
|
||||
unsigned long start_section_nr;
|
||||
unsigned long end_section_nr;
|
||||
unsigned long state;
|
||||
int section_count;
|
||||
|
||||
/*
|
||||
* This serializes all state change requests. It isn't
|
||||
* held during creation because the control files are
|
||||
* created long after the critical areas during
|
||||
* initialization.
|
||||
*/
|
||||
struct mutex state_mutex;
|
||||
unsigned long state; /* serialized by the dev->lock */
|
||||
int section_count; /* serialized by mem_sysfs_mutex */
|
||||
int online_type; /* for passing data to online routine */
|
||||
int phys_device; /* to which fru does this belong? */
|
||||
void *hw; /* optional pointer to fw/hw data */
|
||||
int (*phys_callback)(struct memory_block *);
|
||||
|
@ -125,7 +118,6 @@ extern struct memory_block *find_memory_block_hinted(struct mem_section *,
|
|||
struct memory_block *);
|
||||
extern struct memory_block *find_memory_block(struct mem_section *);
|
||||
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
|
||||
enum mem_add_context { BOOT, HOTPLUG };
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
|
|
|
@ -80,7 +80,7 @@ struct pps_device {
|
|||
* Global variables
|
||||
*/
|
||||
|
||||
extern struct device_attribute pps_attrs[];
|
||||
extern const struct attribute_group *pps_groups[];
|
||||
|
||||
/*
|
||||
* Internal functions.
|
||||
|
|
|
@ -51,9 +51,9 @@ do { \
|
|||
static struct lock_class_key __key; \
|
||||
\
|
||||
(attr)->key = &__key; \
|
||||
} while(0)
|
||||
} while (0)
|
||||
#else
|
||||
#define sysfs_attr_init(attr) do {} while(0)
|
||||
#define sysfs_attr_init(attr) do {} while (0)
|
||||
#endif
|
||||
|
||||
struct attribute_group {
|
||||
|
@ -69,7 +69,7 @@ struct attribute_group {
|
|||
* for examples..
|
||||
*/
|
||||
|
||||
#define __ATTR(_name,_mode,_show,_store) { \
|
||||
#define __ATTR(_name, _mode, _show, _store) { \
|
||||
.attr = {.name = __stringify(_name), .mode = _mode }, \
|
||||
.show = _show, \
|
||||
.store = _store, \
|
||||
|
@ -80,6 +80,11 @@ struct attribute_group {
|
|||
.show = _name##_show, \
|
||||
}
|
||||
|
||||
#define __ATTR_WO(_name) { \
|
||||
.attr = { .name = __stringify(_name), .mode = S_IWUSR }, \
|
||||
.store = _name##_store, \
|
||||
}
|
||||
|
||||
#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \
|
||||
_name##_show, _name##_store)
|
||||
|
||||
|
@ -108,8 +113,6 @@ static const struct attribute_group _name##_group = { \
|
|||
}; \
|
||||
__ATTRIBUTE_GROUPS(_name)
|
||||
|
||||
#define attr_name(_attr) (_attr).attr.name
|
||||
|
||||
struct file;
|
||||
struct vm_area_struct;
|
||||
|
||||
|
@ -119,7 +122,7 @@ struct bin_attribute {
|
|||
void *private;
|
||||
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *,
|
||||
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
|
||||
struct vm_area_struct *vma);
|
||||
|
@ -153,7 +156,7 @@ struct bin_attribute {
|
|||
|
||||
#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name, \
|
||||
(S_IWUSR | S_IRUGO), _name##_read, \
|
||||
_name##_write)
|
||||
_name##_write, _size)
|
||||
|
||||
#define __BIN_ATTR_NULL __ATTR_NULL
|
||||
|
||||
|
@ -168,8 +171,8 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size)
|
|||
struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
|
||||
|
||||
struct sysfs_ops {
|
||||
ssize_t (*show)(struct kobject *, struct attribute *,char *);
|
||||
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
|
||||
ssize_t (*show)(struct kobject *, struct attribute *, char *);
|
||||
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
|
||||
const void *(*namespace)(struct kobject *, const struct attribute *);
|
||||
};
|
||||
|
||||
|
@ -215,10 +218,14 @@ void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
|
|||
|
||||
int __must_check sysfs_create_group(struct kobject *kobj,
|
||||
const struct attribute_group *grp);
|
||||
int __must_check sysfs_create_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups);
|
||||
int sysfs_update_group(struct kobject *kobj,
|
||||
const struct attribute_group *grp);
|
||||
void sysfs_remove_group(struct kobject *kobj,
|
||||
const struct attribute_group *grp);
|
||||
void sysfs_remove_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups);
|
||||
int sysfs_add_file_to_group(struct kobject *kobj,
|
||||
const struct attribute *attr, const char *group);
|
||||
void sysfs_remove_file_from_group(struct kobject *kobj,
|
||||
|
@ -343,6 +350,12 @@ static inline int sysfs_create_group(struct kobject *kobj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int sysfs_create_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sysfs_update_group(struct kobject *kobj,
|
||||
const struct attribute_group *grp)
|
||||
{
|
||||
|
@ -354,6 +367,11 @@ static inline void sysfs_remove_group(struct kobject *kobj,
|
|||
{
|
||||
}
|
||||
|
||||
static inline void sysfs_remove_groups(struct kobject *kobj,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int sysfs_add_file_to_group(struct kobject *kobj,
|
||||
const struct attribute *attr, const char *group)
|
||||
{
|
||||
|
|
|
@ -3095,25 +3095,26 @@ static struct workqueue_struct *dev_to_wq(struct device *dev)
|
|||
return wq_dev->wq;
|
||||
}
|
||||
|
||||
static ssize_t wq_per_cpu_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t per_cpu_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct workqueue_struct *wq = dev_to_wq(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND));
|
||||
}
|
||||
static DEVICE_ATTR_RO(per_cpu);
|
||||
|
||||
static ssize_t wq_max_active_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t max_active_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct workqueue_struct *wq = dev_to_wq(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
|
||||
}
|
||||
|
||||
static ssize_t wq_max_active_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t max_active_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct workqueue_struct *wq = dev_to_wq(dev);
|
||||
int val;
|
||||
|
@ -3124,12 +3125,14 @@ static ssize_t wq_max_active_store(struct device *dev,
|
|||
workqueue_set_max_active(wq, val);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(max_active);
|
||||
|
||||
static struct device_attribute wq_sysfs_attrs[] = {
|
||||
__ATTR(per_cpu, 0444, wq_per_cpu_show, NULL),
|
||||
__ATTR(max_active, 0644, wq_max_active_show, wq_max_active_store),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *wq_sysfs_attrs[] = {
|
||||
&dev_attr_per_cpu.attr,
|
||||
&dev_attr_max_active.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(wq_sysfs);
|
||||
|
||||
static ssize_t wq_pool_ids_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -3279,7 +3282,7 @@ static struct device_attribute wq_sysfs_unbound_attrs[] = {
|
|||
|
||||
static struct bus_type wq_subsys = {
|
||||
.name = "workqueue",
|
||||
.dev_attrs = wq_sysfs_attrs,
|
||||
.dev_groups = wq_sysfs_groups,
|
||||
};
|
||||
|
||||
static int __init wq_sysfs_init(void)
|
||||
|
|
|
@ -981,6 +981,25 @@ config DEBUG_KOBJECT
|
|||
If you say Y here, some extra kobject debugging messages will be sent
|
||||
to the syslog.
|
||||
|
||||
config DEBUG_KOBJECT_RELEASE
|
||||
bool "kobject release debugging"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
kobjects are reference counted objects. This means that their
|
||||
last reference count put is not predictable, and the kobject can
|
||||
live on past the point at which a driver decides to drop it's
|
||||
initial reference to the kobject gained on allocation. An
|
||||
example of this would be a struct device which has just been
|
||||
unregistered.
|
||||
|
||||
However, some buggy drivers assume that after such an operation,
|
||||
the memory backing the kobject can be immediately freed. This
|
||||
goes completely against the principles of a refcounted object.
|
||||
|
||||
If you say Y here, the kernel will delay the release of kobjects
|
||||
on the last reference count to improve the visibility of this
|
||||
kind of kobject release bug.
|
||||
|
||||
config HAVE_DEBUG_BUGVERBOSE
|
||||
bool
|
||||
|
||||
|
|
|
@ -309,7 +309,7 @@ static int ddebug_parse_query(char *words[], int nwords,
|
|||
struct ddebug_query *query, const char *modname)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
/* check we have an even number of words */
|
||||
if (nwords % 2 != 0) {
|
||||
|
|
|
@ -545,8 +545,8 @@ static void kobject_cleanup(struct kobject *kobj)
|
|||
struct kobj_type *t = get_ktype(kobj);
|
||||
const char *name = kobj->name;
|
||||
|
||||
pr_debug("kobject: '%s' (%p): %s\n",
|
||||
kobject_name(kobj), kobj, __func__);
|
||||
pr_debug("kobject: '%s' (%p): %s, parent %p\n",
|
||||
kobject_name(kobj), kobj, __func__, kobj->parent);
|
||||
|
||||
if (t && !t->release)
|
||||
pr_debug("kobject: '%s' (%p): does not have a release() "
|
||||
|
@ -580,9 +580,25 @@ static void kobject_cleanup(struct kobject *kobj)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
|
||||
static void kobject_delayed_cleanup(struct work_struct *work)
|
||||
{
|
||||
kobject_cleanup(container_of(to_delayed_work(work),
|
||||
struct kobject, release));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void kobject_release(struct kref *kref)
|
||||
{
|
||||
kobject_cleanup(container_of(kref, struct kobject, kref));
|
||||
struct kobject *kobj = container_of(kref, struct kobject, kref);
|
||||
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
|
||||
pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n",
|
||||
kobject_name(kobj), kobj, __func__, kobj->parent);
|
||||
INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
|
||||
schedule_delayed_work(&kobj->release, HZ);
|
||||
#else
|
||||
kobject_cleanup(kobj);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -180,7 +180,8 @@ static ssize_t name##_show(struct device *dev, \
|
|||
struct backing_dev_info *bdi = dev_get_drvdata(dev); \
|
||||
\
|
||||
return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr); \
|
||||
}
|
||||
} \
|
||||
static DEVICE_ATTR_RW(name);
|
||||
|
||||
BDI_SHOW(read_ahead_kb, K(bdi->ra_pages))
|
||||
|
||||
|
@ -231,14 +232,16 @@ static ssize_t stable_pages_required_show(struct device *dev,
|
|||
return snprintf(page, PAGE_SIZE-1, "%d\n",
|
||||
bdi_cap_stable_pages_required(bdi) ? 1 : 0);
|
||||
}
|
||||
static DEVICE_ATTR_RO(stable_pages_required);
|
||||
|
||||
static struct device_attribute bdi_dev_attrs[] = {
|
||||
__ATTR_RW(read_ahead_kb),
|
||||
__ATTR_RW(min_ratio),
|
||||
__ATTR_RW(max_ratio),
|
||||
__ATTR_RO(stable_pages_required),
|
||||
__ATTR_NULL,
|
||||
static struct attribute *bdi_dev_attrs[] = {
|
||||
&dev_attr_read_ahead_kb.attr,
|
||||
&dev_attr_min_ratio.attr,
|
||||
&dev_attr_max_ratio.attr,
|
||||
&dev_attr_stable_pages_required.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(bdi_dev);
|
||||
|
||||
static __init int bdi_class_init(void)
|
||||
{
|
||||
|
@ -246,7 +249,7 @@ static __init int bdi_class_init(void)
|
|||
if (IS_ERR(bdi_class))
|
||||
return PTR_ERR(bdi_class);
|
||||
|
||||
bdi_class->dev_attrs = bdi_dev_attrs;
|
||||
bdi_class->dev_groups = bdi_dev_groups;
|
||||
bdi_debug_init();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -60,12 +60,19 @@ static ssize_t format_##field(const struct net_device *net, char *buf) \
|
|||
{ \
|
||||
return sprintf(buf, format_string, net->field); \
|
||||
} \
|
||||
static ssize_t show_##field(struct device *dev, \
|
||||
static ssize_t field##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
return netdev_show(dev, attr, buf, format_##field); \
|
||||
}
|
||||
} \
|
||||
|
||||
#define NETDEVICE_SHOW_RO(field, format_string) \
|
||||
NETDEVICE_SHOW(field, format_string); \
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
#define NETDEVICE_SHOW_RW(field, format_string) \
|
||||
NETDEVICE_SHOW(field, format_string); \
|
||||
static DEVICE_ATTR_RW(field)
|
||||
|
||||
/* use same locking and permission rules as SIF* ioctl's */
|
||||
static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
|
||||
|
@ -96,16 +103,16 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
NETDEVICE_SHOW(dev_id, fmt_hex);
|
||||
NETDEVICE_SHOW(addr_assign_type, fmt_dec);
|
||||
NETDEVICE_SHOW(addr_len, fmt_dec);
|
||||
NETDEVICE_SHOW(iflink, fmt_dec);
|
||||
NETDEVICE_SHOW(ifindex, fmt_dec);
|
||||
NETDEVICE_SHOW(type, fmt_dec);
|
||||
NETDEVICE_SHOW(link_mode, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(dev_id, fmt_hex);
|
||||
NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(addr_len, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(iflink, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(ifindex, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(type, fmt_dec);
|
||||
NETDEVICE_SHOW_RO(link_mode, fmt_dec);
|
||||
|
||||
/* use same locking rules as GIFHWADDR ioctl's */
|
||||
static ssize_t show_address(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t address_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct net_device *net = to_net_dev(dev);
|
||||
|
@ -117,15 +124,17 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr,
|
|||
read_unlock(&dev_base_lock);
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RO(address);
|
||||
|
||||
static ssize_t show_broadcast(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t broadcast_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct net_device *net = to_net_dev(dev);
|
||||
if (dev_isalive(net))
|
||||
return sysfs_format_mac(buf, net->broadcast, net->addr_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_RO(broadcast);
|
||||
|
||||
static int change_carrier(struct net_device *net, unsigned long new_carrier)
|
||||
{
|
||||
|
@ -134,13 +143,13 @@ static int change_carrier(struct net_device *net, unsigned long new_carrier)
|
|||
return dev_change_carrier(net, (bool) new_carrier);
|
||||
}
|
||||
|
||||
static ssize_t store_carrier(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return netdev_store(dev, attr, buf, len, change_carrier);
|
||||
}
|
||||
|
||||
static ssize_t show_carrier(struct device *dev,
|
||||
static ssize_t carrier_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -149,8 +158,9 @@ static ssize_t show_carrier(struct device *dev,
|
|||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_RW(carrier);
|
||||
|
||||
static ssize_t show_speed(struct device *dev,
|
||||
static ssize_t speed_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -167,8 +177,9 @@ static ssize_t show_speed(struct device *dev,
|
|||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RO(speed);
|
||||
|
||||
static ssize_t show_duplex(struct device *dev,
|
||||
static ssize_t duplex_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -198,8 +209,9 @@ static ssize_t show_duplex(struct device *dev,
|
|||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RO(duplex);
|
||||
|
||||
static ssize_t show_dormant(struct device *dev,
|
||||
static ssize_t dormant_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -209,6 +221,7 @@ static ssize_t show_dormant(struct device *dev,
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_RO(dormant);
|
||||
|
||||
static const char *const operstates[] = {
|
||||
"unknown",
|
||||
|
@ -220,7 +233,7 @@ static const char *const operstates[] = {
|
|||
"up"
|
||||
};
|
||||
|
||||
static ssize_t show_operstate(struct device *dev,
|
||||
static ssize_t operstate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
const struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -237,35 +250,33 @@ static ssize_t show_operstate(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%s\n", operstates[operstate]);
|
||||
}
|
||||
static DEVICE_ATTR_RO(operstate);
|
||||
|
||||
/* read-write attributes */
|
||||
NETDEVICE_SHOW(mtu, fmt_dec);
|
||||
|
||||
static int change_mtu(struct net_device *net, unsigned long new_mtu)
|
||||
{
|
||||
return dev_set_mtu(net, (int) new_mtu);
|
||||
}
|
||||
|
||||
static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t mtu_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return netdev_store(dev, attr, buf, len, change_mtu);
|
||||
}
|
||||
|
||||
NETDEVICE_SHOW(flags, fmt_hex);
|
||||
NETDEVICE_SHOW_RW(mtu, fmt_dec);
|
||||
|
||||
static int change_flags(struct net_device *net, unsigned long new_flags)
|
||||
{
|
||||
return dev_change_flags(net, (unsigned int) new_flags);
|
||||
}
|
||||
|
||||
static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t flags_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return netdev_store(dev, attr, buf, len, change_flags);
|
||||
}
|
||||
|
||||
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
|
||||
NETDEVICE_SHOW_RW(flags, fmt_hex);
|
||||
|
||||
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
|
||||
{
|
||||
|
@ -273,7 +284,7 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_tx_queue_len(struct device *dev,
|
||||
static ssize_t tx_queue_len_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
|
@ -282,8 +293,9 @@ static ssize_t store_tx_queue_len(struct device *dev,
|
|||
|
||||
return netdev_store(dev, attr, buf, len, change_tx_queue_len);
|
||||
}
|
||||
NETDEVICE_SHOW_RW(tx_queue_len, fmt_ulong);
|
||||
|
||||
static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -306,7 +318,7 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
|
|||
return ret < 0 ? ret : len;
|
||||
}
|
||||
|
||||
static ssize_t show_ifalias(struct device *dev,
|
||||
static ssize_t ifalias_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
const struct net_device *netdev = to_net_dev(dev);
|
||||
|
@ -319,8 +331,7 @@ static ssize_t show_ifalias(struct device *dev,
|
|||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
NETDEVICE_SHOW(group, fmt_dec);
|
||||
static DEVICE_ATTR_RW(ifalias);
|
||||
|
||||
static int change_group(struct net_device *net, unsigned long new_group)
|
||||
{
|
||||
|
@ -328,35 +339,37 @@ static int change_group(struct net_device *net, unsigned long new_group)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_group(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
static ssize_t group_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return netdev_store(dev, attr, buf, len, change_group);
|
||||
}
|
||||
NETDEVICE_SHOW(group, fmt_dec);
|
||||
static DEVICE_ATTR(netdev_group, S_IRUGO | S_IWUSR, group_show, group_store);
|
||||
|
||||
static struct device_attribute net_class_attributes[] = {
|
||||
__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
|
||||
__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
|
||||
__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
|
||||
__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
|
||||
__ATTR(iflink, S_IRUGO, show_iflink, NULL),
|
||||
__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
|
||||
__ATTR(type, S_IRUGO, show_type, NULL),
|
||||
__ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
|
||||
__ATTR(address, S_IRUGO, show_address, NULL),
|
||||
__ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
|
||||
__ATTR(carrier, S_IRUGO | S_IWUSR, show_carrier, store_carrier),
|
||||
__ATTR(speed, S_IRUGO, show_speed, NULL),
|
||||
__ATTR(duplex, S_IRUGO, show_duplex, NULL),
|
||||
__ATTR(dormant, S_IRUGO, show_dormant, NULL),
|
||||
__ATTR(operstate, S_IRUGO, show_operstate, NULL),
|
||||
__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
|
||||
__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
|
||||
__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
|
||||
store_tx_queue_len),
|
||||
__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group),
|
||||
{}
|
||||
static struct attribute *net_class_attrs[] = {
|
||||
&dev_attr_netdev_group.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_dev_id.attr,
|
||||
&dev_attr_iflink.attr,
|
||||
&dev_attr_ifindex.attr,
|
||||
&dev_attr_addr_assign_type.attr,
|
||||
&dev_attr_addr_len.attr,
|
||||
&dev_attr_link_mode.attr,
|
||||
&dev_attr_address.attr,
|
||||
&dev_attr_broadcast.attr,
|
||||
&dev_attr_speed.attr,
|
||||
&dev_attr_duplex.attr,
|
||||
&dev_attr_dormant.attr,
|
||||
&dev_attr_operstate.attr,
|
||||
&dev_attr_ifalias.attr,
|
||||
&dev_attr_carrier.attr,
|
||||
&dev_attr_mtu.attr,
|
||||
&dev_attr_flags.attr,
|
||||
&dev_attr_tx_queue_len.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(net_class);
|
||||
|
||||
/* Show a given an attribute in the statistics group */
|
||||
static ssize_t netstat_show(const struct device *d,
|
||||
|
@ -382,13 +395,13 @@ static ssize_t netstat_show(const struct device *d,
|
|||
|
||||
/* generate a read-only statistics attribute */
|
||||
#define NETSTAT_ENTRY(name) \
|
||||
static ssize_t show_##name(struct device *d, \
|
||||
static ssize_t name##_show(struct device *d, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
return netstat_show(d, attr, buf, \
|
||||
offsetof(struct rtnl_link_stats64, name)); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
|
||||
static DEVICE_ATTR_RO(name)
|
||||
|
||||
NETSTAT_ENTRY(rx_packets);
|
||||
NETSTAT_ENTRY(tx_packets);
|
||||
|
@ -457,6 +470,9 @@ static struct attribute_group wireless_group = {
|
|||
.attrs = wireless_attrs,
|
||||
};
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_SYSFS */
|
||||
#define net_class_groups NULL
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
#ifdef CONFIG_RPS
|
||||
|
@ -1229,9 +1245,7 @@ static const void *net_namespace(struct device *d)
|
|||
static struct class net_class = {
|
||||
.name = "net",
|
||||
.dev_release = netdev_release,
|
||||
#ifdef CONFIG_SYSFS
|
||||
.dev_attrs = net_class_attributes,
|
||||
#endif /* CONFIG_SYSFS */
|
||||
.dev_groups = net_class_groups,
|
||||
.dev_uevent = netdev_uevent,
|
||||
.ns_type = &net_ns_type_operations,
|
||||
.namespace = net_namespace,
|
||||
|
|
|
@ -36,7 +36,8 @@ static ssize_t name ## _show(struct device *dev, \
|
|||
ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \
|
||||
mutex_unlock(&phy->pib_lock); \
|
||||
return ret; \
|
||||
}
|
||||
} \
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
#define MASTER_SHOW(field, format_string) \
|
||||
MASTER_SHOW_COMPLEX(field, format_string, phy->field)
|
||||
|
@ -66,15 +67,17 @@ static ssize_t channels_supported_show(struct device *dev,
|
|||
mutex_unlock(&phy->pib_lock);
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(channels_supported);
|
||||
|
||||
static struct device_attribute pmib_attrs[] = {
|
||||
__ATTR_RO(current_channel),
|
||||
__ATTR_RO(current_page),
|
||||
__ATTR_RO(channels_supported),
|
||||
__ATTR_RO(transmit_power),
|
||||
__ATTR_RO(cca_mode),
|
||||
{},
|
||||
static struct attribute *pmib_attrs[] = {
|
||||
&dev_attr_current_channel.attr,
|
||||
&dev_attr_current_page.attr,
|
||||
&dev_attr_channels_supported.attr,
|
||||
&dev_attr_transmit_power.attr,
|
||||
&dev_attr_cca_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(pmib);
|
||||
|
||||
static void wpan_phy_release(struct device *d)
|
||||
{
|
||||
|
@ -85,7 +88,7 @@ static void wpan_phy_release(struct device *d)
|
|||
static struct class wpan_phy_class = {
|
||||
.name = "ieee802154",
|
||||
.dev_release = wpan_phy_release,
|
||||
.dev_attrs = pmib_attrs,
|
||||
.dev_groups = pmib_groups,
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(wpan_phy_mutex);
|
||||
|
|
|
@ -576,14 +576,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
|||
}
|
||||
EXPORT_SYMBOL(rfkill_set_states);
|
||||
|
||||
static ssize_t rfkill_name_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", rfkill->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static const char *rfkill_get_type_str(enum rfkill_type type)
|
||||
{
|
||||
|
@ -611,54 +611,52 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t rfkill_type_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type));
|
||||
}
|
||||
static DEVICE_ATTR_RO(type);
|
||||
|
||||
static ssize_t rfkill_idx_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t index_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", rfkill->idx);
|
||||
}
|
||||
static DEVICE_ATTR_RO(index);
|
||||
|
||||
static ssize_t rfkill_persistent_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t persistent_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", rfkill->persistent);
|
||||
}
|
||||
static DEVICE_ATTR_RO(persistent);
|
||||
|
||||
static ssize_t rfkill_hard_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 );
|
||||
}
|
||||
static DEVICE_ATTR_RO(hard);
|
||||
|
||||
static ssize_t rfkill_soft_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
|
||||
}
|
||||
|
||||
static ssize_t rfkill_soft_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
unsigned long state;
|
||||
|
@ -680,6 +678,7 @@ static ssize_t rfkill_soft_store(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(soft);
|
||||
|
||||
static u8 user_state_from_blocked(unsigned long state)
|
||||
{
|
||||
|
@ -691,18 +690,16 @@ static u8 user_state_from_blocked(unsigned long state)
|
|||
return RFKILL_USER_STATE_UNBLOCKED;
|
||||
}
|
||||
|
||||
static ssize_t rfkill_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
|
||||
}
|
||||
|
||||
static ssize_t rfkill_state_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t state_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
unsigned long state;
|
||||
|
@ -725,32 +722,27 @@ static ssize_t rfkill_state_store(struct device *dev,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(state);
|
||||
|
||||
static ssize_t rfkill_claim_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", 0);
|
||||
}
|
||||
static DEVICE_ATTR_RO(claim);
|
||||
|
||||
static ssize_t rfkill_claim_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static struct device_attribute rfkill_dev_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, rfkill_name_show, NULL),
|
||||
__ATTR(type, S_IRUGO, rfkill_type_show, NULL),
|
||||
__ATTR(index, S_IRUGO, rfkill_idx_show, NULL),
|
||||
__ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL),
|
||||
__ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store),
|
||||
__ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
|
||||
__ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store),
|
||||
__ATTR(hard, S_IRUGO, rfkill_hard_show, NULL),
|
||||
__ATTR_NULL
|
||||
static struct attribute *rfkill_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_index.attr,
|
||||
&dev_attr_persistent.attr,
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_claim.attr,
|
||||
&dev_attr_soft.attr,
|
||||
&dev_attr_hard.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(rfkill_dev);
|
||||
|
||||
static void rfkill_release(struct device *dev)
|
||||
{
|
||||
|
@ -830,7 +822,7 @@ static int rfkill_resume(struct device *dev)
|
|||
static struct class rfkill_class = {
|
||||
.name = "rfkill",
|
||||
.dev_release = rfkill_release,
|
||||
.dev_attrs = rfkill_dev_attrs,
|
||||
.dev_groups = rfkill_dev_groups,
|
||||
.dev_uevent = rfkill_dev_uevent,
|
||||
.suspend = rfkill_suspend,
|
||||
.resume = rfkill_resume,
|
||||
|
|
|
@ -30,7 +30,8 @@ static ssize_t name ## _show(struct device *dev, \
|
|||
char *buf) \
|
||||
{ \
|
||||
return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
|
||||
}
|
||||
} \
|
||||
static DEVICE_ATTR_RO(name)
|
||||
|
||||
SHOW_FMT(index, "%d", wiphy_idx);
|
||||
SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
|
||||
|
@ -42,7 +43,7 @@ static ssize_t name_show(struct device *dev,
|
|||
struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
|
||||
return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static ssize_t addresses_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -60,15 +61,17 @@ static ssize_t addresses_show(struct device *dev,
|
|||
|
||||
return buf - start;
|
||||
}
|
||||
static DEVICE_ATTR_RO(addresses);
|
||||
|
||||
static struct device_attribute ieee80211_dev_attrs[] = {
|
||||
__ATTR_RO(index),
|
||||
__ATTR_RO(macaddress),
|
||||
__ATTR_RO(address_mask),
|
||||
__ATTR_RO(addresses),
|
||||
__ATTR_RO(name),
|
||||
{}
|
||||
static struct attribute *ieee80211_attrs[] = {
|
||||
&dev_attr_index.attr,
|
||||
&dev_attr_macaddress.attr,
|
||||
&dev_attr_address_mask.attr,
|
||||
&dev_attr_addresses.attr,
|
||||
&dev_attr_name.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ieee80211);
|
||||
|
||||
static void wiphy_dev_release(struct device *dev)
|
||||
{
|
||||
|
@ -146,7 +149,7 @@ struct class ieee80211_class = {
|
|||
.name = "ieee80211",
|
||||
.owner = THIS_MODULE,
|
||||
.dev_release = wiphy_dev_release,
|
||||
.dev_attrs = ieee80211_dev_attrs,
|
||||
.dev_groups = ieee80211_groups,
|
||||
.dev_uevent = wiphy_uevent,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = wiphy_suspend,
|
||||
|
|
Loading…
Reference in New Issue