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:
Linus Torvalds 2013-09-03 11:37:15 -07:00
commit 542a086ac7
99 changed files with 1950 additions and 1907 deletions

View File

@ -182,8 +182,8 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H
프로젝트를 봐야 한다. 프로젝트를 봐야 한다.
http://kernelnewbies.org http://kernelnewbies.org
그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저 그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저
아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할수있는 도움이 아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할 있는 도움이
될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할수 있는 IRC 채널도 될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할 수 있는 IRC 채널도
가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다. 가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다.
웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들 웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들
@ -245,7 +245,7 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H
것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가 것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가
드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은 드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은
회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해 회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해
생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이 생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은 배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은
공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다. 공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다.
- 새로운 -rc는 Linus가 현재 git tree가 테스트 하기에 충분히 안정된 상태에 - 새로운 -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년동안 이것을 해왔다. 그러므로..." - "나는 20년동안 이것을 해왔다. 그러므로..."
- "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다." - "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다."
- "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다." - "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다."
- "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다." - "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다."
- "나는 6달동안 이것을 했으니..." - "나는 6달동안 이것을 했으니..."
- "여기에 5000라인 짜리 패치가 있으니..." - "여기에 5000 라인 짜리 패치가 있으니..."
- "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..." - "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..."
- "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다." - "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다."
@ -574,6 +574,7 @@ Pat이라는 이름을 가진 여자가 있을 수도 있는 것이다. 리눅
또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는 또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는
패치들은 받아들여지지 않을 것이라는 점을 유념하라. 패치들은 받아들여지지 않을 것이라는 점을 유념하라.
변경을 정당화해라 변경을 정당화해라
----------------- -----------------

View File

@ -106,12 +106,12 @@ Greg Kroah-Hartman <greg@kroah.com>
--------------------------------- ---------------------------------
리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고 리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고
유지보수하려고 하는 사들과 이 문제를 논의하게 되면 훨씬 더 유지보수하려고 하는 사들과 이 문제를 논의하게 되면 훨씬 더
"논란의 여지가 많은" 주제가 될 것이다. "논란의 여지가 많은" 주제가 될 것이다.
리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코 리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코
느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를 느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를
발견하거나 무엇인가 할수 있는 더 좋은 방법을 찾게 되었다고 하자. 발견하거나 무엇인가 할 수 있는 더 좋은 방법을 찾게 되었다고 하자.
그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을 그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을
수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고, 수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고,
구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다. 구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다.
@ -174,7 +174,7 @@ GPL을 따르는 배포 드라이버에 관해 얘기하고 있다는 것을 상
동작하는 것을 보장한다. 동작하는 것을 보장한다.
메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다. 메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다.
- 관리 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다. - 관리 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
- 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다. - 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다.
- 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다. - 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다.
- 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다. - 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다.

View File

@ -2064,8 +2064,7 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you.
support.
config ATAGS_PROC config ATAGS_PROC
bool "Export atags in procfs" bool "Export atags in procfs"

View File

@ -565,9 +565,9 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you. As of this writing the exact hardware
support. As of this writing the exact hardware interface is interface is strongly in flux, so no good recommendation can be
strongly in flux, so no good recommendation can be made. made.
config CRASH_DUMP config CRASH_DUMP
bool "kernel crash dumps" bool "kernel crash dumps"

View File

@ -2305,9 +2305,9 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you. As of this writing the exact hardware
support. As of this writing the exact hardware interface is interface is strongly in flux, so no good recommendation can be
strongly in flux, so no good recommendation can be made. made.
config CRASH_DUMP config CRASH_DUMP
bool "Kernel crash dumps" bool "Kernel crash dumps"

View File

@ -1335,8 +1335,9 @@ static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
return len; 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) char *buf)
{ {
struct vpe *vpe = get_vpe(tclimit); 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); 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) const char *buf, size_t len)
{ {
struct vpe *vpe = get_vpe(tclimit); struct vpe *vpe = get_vpe(tclimit);
@ -1365,12 +1366,14 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
out_einval: out_einval:
return -EINVAL; return -EINVAL;
} }
static DEVICE_ATTR_RW(ntcs);
static struct device_attribute vpe_class_attributes[] = { static struct attribute vpe_attrs[] = {
__ATTR(kill, S_IWUSR, NULL, store_kill), &dev_attr_kill.attr,
__ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs), &dev_attr_ntcs.attr,
{} NULL,
}; };
ATTRIBUTE_GROUPS(vpe);
static void vpe_device_release(struct device *cd) static void vpe_device_release(struct device *cd)
{ {
@ -1381,7 +1384,7 @@ struct class vpe_class = {
.name = "vpe", .name = "vpe",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_release = vpe_device_release, .dev_release = vpe_device_release,
.dev_attrs = vpe_class_attributes, .dev_groups = vpe_groups,
}; };
struct device vpe_device; struct device vpe_device;

View File

@ -369,9 +369,9 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you. As of this writing the exact hardware
support. As of this writing the exact hardware interface is interface is strongly in flux, so no good recommendation can be
strongly in flux, so no good recommendation can be made. made.
config CRASH_DUMP config CRASH_DUMP
bool "Build a kdump crash kernel" bool "Build a kdump crash kernel"

View File

@ -643,9 +643,9 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you. As of this writing the exact hardware
support. As of this writing the exact hardware interface is interface is strongly in flux, so no good recommendation can be
strongly in flux, so no good recommendation can be made. made.
config CRASH_DUMP config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)" bool "kernel crash dumps (EXPERIMENTAL)"

View File

@ -89,9 +89,6 @@ static inline const struct cpumask *cpumask_of_node(int node)
#define topology_core_id(cpu) (cpu) #define topology_core_id(cpu) (cpu)
#define topology_core_cpumask(cpu) ((void)(cpu), cpu_online_mask) #define topology_core_cpumask(cpu) ((void)(cpu), cpu_online_mask)
#define topology_thread_cpumask(cpu) cpumask_of(cpu) #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
#endif /* _ASM_TILE_TOPOLOGY_H */ #endif /* _ASM_TILE_TOPOLOGY_H */

View File

@ -1628,9 +1628,9 @@ config KEXEC
It is an ongoing process to be certain the hardware in a machine 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 is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging initially work for you. As of this writing the exact hardware
support. As of this writing the exact hardware interface is interface is strongly in flux, so no good recommendation can be
strongly in flux, so no good recommendation can be made. made.
config CRASH_DUMP config CRASH_DUMP
bool "kernel crash dumps" bool "kernel crash dumps"

View File

@ -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_id(cpu) (cpu_data(cpu).cpu_core_id)
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_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 #endif
static inline void arch_fix_phys_package_id(int num, u32 slot) static inline void arch_fix_phys_package_id(int num, u32 slot)

View File

@ -51,20 +51,14 @@ static ssize_t show_yoffset(struct device *dev,
} }
static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); 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) struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{ {
memcpy(buf, attr->private + off, count); memcpy(buf, attr->private + off, count);
return count; return count;
} }
static struct bin_attribute image_attr = { static BIN_ATTR_RO(image, 0); /* size gets filled in later */
.attr = {
.name = "image",
.mode = S_IRUGO,
},
.read = show_image,
};
static struct attribute *bgrt_attributes[] = { static struct attribute *bgrt_attributes[] = {
&dev_attr_version.attr, &dev_attr_version.attr,
@ -75,8 +69,14 @@ static struct attribute *bgrt_attributes[] = {
NULL, NULL,
}; };
static struct bin_attribute *bgrt_bin_attributes[] = {
&bin_attr_image,
NULL,
};
static struct attribute_group bgrt_attribute_group = { static struct attribute_group bgrt_attribute_group = {
.attrs = bgrt_attributes, .attrs = bgrt_attributes,
.bin_attrs = bgrt_bin_attributes,
}; };
static int __init bgrt_init(void) static int __init bgrt_init(void)
@ -86,9 +86,8 @@ static int __init bgrt_init(void)
if (!bgrt_image) if (!bgrt_image)
return -ENODEV; return -ENODEV;
sysfs_bin_attr_init(&image_attr); bin_attr_image.private = bgrt_image;
image_attr.private = bgrt_image; bin_attr_image.size = bgrt_image_size;
image_attr.size = bgrt_image_size;
bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
if (!bgrt_kobj) if (!bgrt_kobj)
@ -98,14 +97,8 @@ static int __init bgrt_init(void)
if (ret) if (ret)
goto out_kobject; goto out_kobject;
ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
if (ret)
goto out_group;
return 0; return 0;
out_group:
sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
out_kobject: out_kobject:
kobject_put(bgrt_kobj); kobject_put(bgrt_kobj);
return ret; return ret;

View File

@ -119,6 +119,16 @@ static inline int driver_match_device(struct device_driver *drv,
return drv->bus->match ? drv->bus->match(dev, drv) : 1; 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 char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev); extern int devres_release_all(struct device *dev);

View File

@ -17,6 +17,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sysfs.h>
#include "base.h" #include "base.h"
#include "power/power.h" #include "power/power.h"
@ -165,8 +166,8 @@ static const struct kset_uevent_ops bus_uevent_ops = {
static struct kset *bus_kset; static struct kset *bus_kset;
/* Manually detach a device from its associated driver. */ /* Manually detach a device from its associated driver. */
static ssize_t driver_unbind(struct device_driver *drv, static ssize_t unbind_store(struct device_driver *drv, const char *buf,
const char *buf, size_t count) size_t count)
{ {
struct bus_type *bus = bus_get(drv->bus); struct bus_type *bus = bus_get(drv->bus);
struct device *dev; struct device *dev;
@ -185,15 +186,15 @@ static ssize_t driver_unbind(struct device_driver *drv,
bus_put(bus); bus_put(bus);
return err; return err;
} }
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); static DRIVER_ATTR_WO(unbind);
/* /*
* Manually attach a device to a driver. * Manually attach a device to a driver.
* Note: the driver must want to bind to the device, * Note: the driver must want to bind to the device,
* it is not possible to override the driver's id table. * it is not possible to override the driver's id table.
*/ */
static ssize_t driver_bind(struct device_driver *drv, static ssize_t bind_store(struct device_driver *drv, const char *buf,
const char *buf, size_t count) size_t count)
{ {
struct bus_type *bus = bus_get(drv->bus); struct bus_type *bus = bus_get(drv->bus);
struct device *dev; struct device *dev;
@ -221,7 +222,7 @@ static ssize_t driver_bind(struct device_driver *drv,
bus_put(bus); bus_put(bus);
return err; 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) 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) if (!bus->dev_attrs)
return 0; 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]); error = device_create_file(dev, &bus->dev_attrs[i]);
if (error) { if (error) {
while (--i >= 0) while (--i >= 0)
@ -476,7 +477,7 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev)
int i; int i;
if (bus->dev_attrs) { 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]); 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); error = device_add_attrs(bus, dev);
if (error) if (error)
goto out_put; 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, error = sysfs_create_link(&bus->p->devices_kset->kobj,
&dev->kobj, dev_name(dev)); &dev->kobj, dev_name(dev));
if (error) if (error)
@ -513,6 +517,8 @@ int bus_add_device(struct device *dev)
out_subsys: out_subsys:
sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev)); sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
out_groups:
device_remove_groups(dev, bus->dev_groups);
out_id: out_id:
device_remove_attrs(bus, dev); device_remove_attrs(bus, dev);
out_put: out_put:
@ -575,6 +581,7 @@ void bus_remove_device(struct device *dev)
sysfs_remove_link(&dev->bus->p->devices_kset->kobj, sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
dev_name(dev)); dev_name(dev));
device_remove_attrs(dev->bus, dev); device_remove_attrs(dev->bus, dev);
device_remove_groups(dev, dev->bus->dev_groups);
if (klist_node_attached(&dev->p->knode_bus)) if (klist_node_attached(&dev->p->knode_bus))
klist_del(&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; int i;
if (bus->drv_attrs) { 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]); error = driver_create_file(drv, &bus->drv_attrs[i]);
if (error) if (error)
goto err; goto err;
@ -610,7 +617,7 @@ static void driver_remove_attrs(struct bus_type *bus,
int i; int i;
if (bus->drv_attrs) { 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]); 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); bus_remove_file(bus, &bus_attr_drivers_probe);
} }
static ssize_t driver_uevent_store(struct device_driver *drv, static ssize_t uevent_store(struct device_driver *drv, const char *buf,
const char *buf, size_t count) size_t count)
{ {
enum kobject_action action; enum kobject_action action;
@ -668,7 +675,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv,
kobject_uevent(&drv->p->kobj, action); kobject_uevent(&drv->p->kobj, action);
return count; 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. * 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", printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name); __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) { if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv); error = add_bind_files(drv);
@ -756,6 +767,7 @@ void bus_remove_driver(struct device_driver *drv)
if (!drv->suppress_bind_attrs) if (!drv->suppress_bind_attrs)
remove_bind_files(drv); remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv); driver_remove_attrs(drv->bus, drv);
driver_remove_groups(drv, drv->bus->drv_groups);
driver_remove_file(drv, &driver_attr_uevent); driver_remove_file(drv, &driver_attr_uevent);
klist_remove(&drv->p->knode_bus); klist_remove(&drv->p->knode_bus);
pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name); 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; int i;
if (bus->bus_attrs) { 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]); error = bus_create_file(bus, &bus->bus_attrs[i]);
if (error) if (error)
goto err; goto err;
@ -865,11 +877,23 @@ static void bus_remove_attrs(struct bus_type *bus)
int i; int i;
if (bus->bus_attrs) { 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]); 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) static void klist_devices_get(struct klist_node *n)
{ {
struct device_private *dev_prv = to_device_private_bus(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); retval = bus_add_attrs(bus);
if (retval) if (retval)
goto bus_attrs_fail; 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); pr_debug("bus: '%s': registered\n", bus->name);
return 0; return 0;
bus_groups_fail:
bus_remove_attrs(bus);
bus_attrs_fail: bus_attrs_fail:
remove_probe_files(bus); remove_probe_files(bus);
bus_probe_files_fail: bus_probe_files_fail:
@ -996,6 +1025,7 @@ void bus_unregister(struct bus_type *bus)
if (bus->dev_root) if (bus->dev_root)
device_unregister(bus->dev_root); device_unregister(bus->dev_root);
bus_remove_attrs(bus); bus_remove_attrs(bus);
bus_remove_groups(bus, bus->bus_groups);
remove_probe_files(bus); remove_probe_files(bus);
kset_unregister(bus->p->drivers_kset); kset_unregister(bus->p->drivers_kset);
kset_unregister(bus->p->devices_kset); kset_unregister(bus->p->devices_kset);

View File

@ -135,7 +135,7 @@ static int add_class_attrs(struct class *cls)
int error = 0; int error = 0;
if (cls->class_attrs) { 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]); error = class_create_file(cls, &cls->class_attrs[i]);
if (error) if (error)
goto error; goto error;
@ -154,7 +154,7 @@ static void remove_class_attrs(struct class *cls)
int i; int i;
if (cls->class_attrs) { 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]); class_remove_file(cls, &cls->class_attrs[i]);
} }
} }

View File

@ -26,6 +26,7 @@
#include <linux/async.h> #include <linux/async.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/sysfs.h>
#include "base.h" #include "base.h"
#include "power/power.h" #include "power/power.h"
@ -36,9 +37,9 @@ long sysfs_deprecated = 1;
#else #else
long sysfs_deprecated = 0; long sysfs_deprecated = 0;
#endif #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); early_param("sysfs.deprecated", sysfs_deprecated_setup);
#endif #endif
@ -345,7 +346,7 @@ static const struct kset_uevent_ops device_uevent_ops = {
.uevent = dev_uevent, .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) char *buf)
{ {
struct kobject *top_kobj; struct kobject *top_kobj;
@ -388,7 +389,7 @@ out:
return count; 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) const char *buf, size_t count)
{ {
enum kobject_action action; 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"); dev_err(dev, "uevent: unknown action-string\n");
return count; return count;
} }
static DEVICE_ATTR_RW(uevent);
static struct device_attribute uevent_attr = static ssize_t online_show(struct device *dev, struct device_attribute *attr,
__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
static ssize_t show_online(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
bool val; bool val;
@ -414,7 +413,7 @@ static ssize_t show_online(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%u\n", val); 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) const char *buf, size_t count)
{ {
bool val; bool val;
@ -429,9 +428,7 @@ static ssize_t store_online(struct device *dev, struct device_attribute *attr,
unlock_device_hotplug(); unlock_device_hotplug();
return ret < 0 ? ret : count; return ret < 0 ? ret : count;
} }
static DEVICE_ATTR_RW(online);
static struct device_attribute online_attr =
__ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online);
static int device_add_attributes(struct device *dev, static int device_add_attributes(struct device *dev,
struct device_attribute *attrs) struct device_attribute *attrs)
@ -440,7 +437,7 @@ static int device_add_attributes(struct device *dev,
int i; int i;
if (attrs) { 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]); error = device_create_file(dev, &attrs[i]);
if (error) if (error)
break; break;
@ -458,7 +455,7 @@ static void device_remove_attributes(struct device *dev,
int i; int i;
if (attrs) if (attrs)
for (i = 0; attr_name(attrs[i]); i++) for (i = 0; attrs[i].attr.name; i++)
device_remove_file(dev, &attrs[i]); device_remove_file(dev, &attrs[i]);
} }
@ -469,7 +466,7 @@ static int device_add_bin_attributes(struct device *dev,
int i; int i;
if (attrs) { 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]); error = device_create_bin_file(dev, &attrs[i]);
if (error) if (error)
break; break;
@ -487,38 +484,19 @@ static void device_remove_bin_attributes(struct device *dev,
int i; int i;
if (attrs) 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]); device_remove_bin_file(dev, &attrs[i]);
} }
static int device_add_groups(struct device *dev, int device_add_groups(struct device *dev, const struct attribute_group **groups)
const struct attribute_group **groups)
{ {
int error = 0; return sysfs_create_groups(&dev->kobj, groups);
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;
} }
static void device_remove_groups(struct device *dev, void device_remove_groups(struct device *dev,
const struct attribute_group **groups) const struct attribute_group **groups)
{ {
int i; sysfs_remove_groups(&dev->kobj, groups);
if (groups)
for (i = 0; groups[i]; i++)
sysfs_remove_group(&dev->kobj, groups[i]);
} }
static int device_add_attrs(struct device *dev) 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; goto err_remove_type_groups;
if (device_supports_offline(dev) && !dev->offline_disabled) { 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) if (error)
goto err_remove_type_groups; goto err_remove_type_groups;
} }
@ -578,7 +556,7 @@ static void device_remove_attrs(struct device *dev)
struct class *class = dev->class; struct class *class = dev->class;
const struct device_type *type = dev->type; 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); device_remove_groups(dev, dev->groups);
if (type) if (type)
@ -591,15 +569,12 @@ static void device_remove_attrs(struct device *dev)
} }
} }
static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
return print_dev_t(buf, dev->devt); return print_dev_t(buf, dev->devt);
} }
static DEVICE_ATTR_RO(dev);
static struct device_attribute devt_attr =
__ATTR(dev, S_IRUGO, show_dev, NULL);
/* /sys/devices/ */ /* /sys/devices/ */
struct kset *devices_kset; struct kset *devices_kset;
@ -626,6 +601,7 @@ int device_create_file(struct device *dev,
return error; return error;
} }
EXPORT_SYMBOL_GPL(device_create_file);
/** /**
* device_remove_file - remove sysfs attribute file. * device_remove_file - remove sysfs attribute file.
@ -638,6 +614,7 @@ void device_remove_file(struct device *dev,
if (dev) if (dev)
sysfs_remove_file(&dev->kobj, &attr->attr); sysfs_remove_file(&dev->kobj, &attr->attr);
} }
EXPORT_SYMBOL_GPL(device_remove_file);
/** /**
* device_create_bin_file - create sysfs binary attribute file for device. * 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); device_pm_init(dev);
set_dev_node(dev, -1); set_dev_node(dev, -1);
} }
EXPORT_SYMBOL_GPL(device_initialize);
struct kobject *virtual_device_parent(struct device *dev) struct kobject *virtual_device_parent(struct device *dev)
{ {
@ -1100,12 +1078,12 @@ int device_add(struct device *dev)
if (platform_notify) if (platform_notify)
platform_notify(dev); platform_notify(dev);
error = device_create_file(dev, &uevent_attr); error = device_create_file(dev, &dev_attr_uevent);
if (error) if (error)
goto attrError; goto attrError;
if (MAJOR(dev->devt)) { if (MAJOR(dev->devt)) {
error = device_create_file(dev, &devt_attr); error = device_create_file(dev, &dev_attr_dev);
if (error) if (error)
goto ueventattrError; goto ueventattrError;
@ -1172,9 +1150,9 @@ done:
device_remove_sys_dev_entry(dev); device_remove_sys_dev_entry(dev);
devtattrError: devtattrError:
if (MAJOR(dev->devt)) if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr); device_remove_file(dev, &dev_attr_dev);
ueventattrError: ueventattrError:
device_remove_file(dev, &uevent_attr); device_remove_file(dev, &dev_attr_uevent);
attrError: attrError:
kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj); kobject_del(&dev->kobj);
@ -1187,6 +1165,7 @@ name_error:
dev->p = NULL; dev->p = NULL;
goto done; goto done;
} }
EXPORT_SYMBOL_GPL(device_add);
/** /**
* device_register - register a device with the system. * device_register - register a device with the system.
@ -1211,6 +1190,7 @@ int device_register(struct device *dev)
device_initialize(dev); device_initialize(dev);
return device_add(dev); return device_add(dev);
} }
EXPORT_SYMBOL_GPL(device_register);
/** /**
* get_device - increment reference count for device. * 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; return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
} }
EXPORT_SYMBOL_GPL(get_device);
/** /**
* put_device - decrement reference count. * put_device - decrement reference count.
@ -1235,6 +1216,7 @@ void put_device(struct device *dev)
if (dev) if (dev)
kobject_put(&dev->kobj); kobject_put(&dev->kobj);
} }
EXPORT_SYMBOL_GPL(put_device);
/** /**
* device_del - delete device from system. * device_del - delete device from system.
@ -1266,7 +1248,7 @@ void device_del(struct device *dev)
if (MAJOR(dev->devt)) { if (MAJOR(dev->devt)) {
devtmpfs_delete_node(dev); devtmpfs_delete_node(dev);
device_remove_sys_dev_entry(dev); device_remove_sys_dev_entry(dev);
device_remove_file(dev, &devt_attr); device_remove_file(dev, &dev_attr_dev);
} }
if (dev->class) { if (dev->class) {
device_remove_class_symlinks(dev); device_remove_class_symlinks(dev);
@ -1281,7 +1263,7 @@ void device_del(struct device *dev)
klist_del(&dev->knode_class); klist_del(&dev->knode_class);
mutex_unlock(&dev->class->p->mutex); mutex_unlock(&dev->class->p->mutex);
} }
device_remove_file(dev, &uevent_attr); device_remove_file(dev, &dev_attr_uevent);
device_remove_attrs(dev); device_remove_attrs(dev);
bus_remove_device(dev); bus_remove_device(dev);
device_pm_remove(dev); device_pm_remove(dev);
@ -1297,6 +1279,7 @@ void device_del(struct device *dev)
kobject_del(&dev->kobj); kobject_del(&dev->kobj);
put_device(parent); put_device(parent);
} }
EXPORT_SYMBOL_GPL(device_del);
/** /**
* device_unregister - unregister device from system. * device_unregister - unregister device from system.
@ -1315,6 +1298,7 @@ void device_unregister(struct device *dev)
device_del(dev); device_del(dev);
put_device(dev); put_device(dev);
} }
EXPORT_SYMBOL_GPL(device_unregister);
static struct device *next_device(struct klist_iter *i) 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); klist_iter_exit(&i);
return error; return error;
} }
EXPORT_SYMBOL_GPL(device_for_each_child);
/** /**
* device_find_child - device iterator for locating a particular device. * 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); klist_iter_exit(&i);
return child; return child;
} }
EXPORT_SYMBOL_GPL(device_find_child);
int __init devices_init(void) int __init devices_init(void)
{ {
@ -1464,21 +1450,6 @@ int __init devices_init(void)
return -ENOMEM; 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); static DEFINE_MUTEX(device_hotplug_lock);
void lock_device_hotplug(void) void lock_device_hotplug(void)

View File

@ -43,11 +43,14 @@ static int __ref cpu_subsys_online(struct device *dev)
struct cpu *cpu = container_of(dev, struct cpu, dev); struct cpu *cpu = container_of(dev, struct cpu, dev);
int cpuid = dev->id; int cpuid = dev->id;
int from_nid, to_nid; int from_nid, to_nid;
int ret; int ret = -ENODEV;
cpu_hotplug_driver_lock(); cpu_hotplug_driver_lock();
from_nid = cpu_to_node(cpuid); from_nid = cpu_to_node(cpuid);
if (from_nid == NUMA_NO_NODE)
goto out;
ret = cpu_up(cpuid); ret = cpu_up(cpuid);
/* /*
* When hot adding memory to memoryless node and enabling a cpu * 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) if (from_nid != to_nid)
change_cpu_under_node(cpu, from_nid, to_nid); change_cpu_under_node(cpu, from_nid, to_nid);
out:
cpu_hotplug_driver_unlock(); cpu_hotplug_driver_unlock();
return ret; return ret;
} }

View File

@ -134,7 +134,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
static DEFINE_MUTEX(cma_mutex); 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 long pfn = base_pfn;
unsigned i = count >> pageblock_order; unsigned i = count >> pageblock_order;
@ -156,7 +156,7 @@ static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
return 0; 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) unsigned long count)
{ {
int bitmap_size = BITS_TO_LONGS(count) * sizeof(long); int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);

View File

@ -15,6 +15,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/sysfs.h>
#include "base.h" #include "base.h"
static struct device *next_device(struct klist_iter *i) 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); EXPORT_SYMBOL_GPL(driver_remove_file);
static int driver_add_groups(struct device_driver *drv, int driver_add_groups(struct device_driver *drv,
const struct attribute_group **groups) const struct attribute_group **groups)
{ {
int error = 0; return sysfs_create_groups(&drv->p->kobj, groups);
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;
} }
static void driver_remove_groups(struct device_driver *drv, void driver_remove_groups(struct device_driver *drv,
const struct attribute_group **groups) const struct attribute_group **groups)
{ {
int i; sysfs_remove_groups(&drv->p->kobj, groups);
if (groups)
for (i = 0; groups[i]; i++)
sysfs_remove_group(&drv->p->kobj, groups[i]);
} }
/** /**

View File

@ -486,9 +486,8 @@ static struct notifier_block fw_shutdown_nb = {
.notifier_call = fw_shutdown_notify, .notifier_call = fw_shutdown_notify,
}; };
static ssize_t firmware_timeout_show(struct class *class, static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
struct class_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", loading_timeout); 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'. * Note: zero means 'wait forever'.
**/ **/
static ssize_t firmware_timeout_store(struct class *class, static ssize_t timeout_store(struct class *class, struct class_attribute *attr,
struct class_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
loading_timeout = simple_strtol(buf, NULL, 10); loading_timeout = simple_strtol(buf, NULL, 10);
if (loading_timeout < 0) if (loading_timeout < 0)
@ -518,8 +516,7 @@ static ssize_t firmware_timeout_store(struct class *class,
} }
static struct class_attribute firmware_class_attrs[] = { static struct class_attribute firmware_class_attrs[] = {
__ATTR(timeout, S_IWUSR | S_IRUGO, __ATTR_RW(timeout),
firmware_timeout_show, firmware_timeout_store),
__ATTR_NULL __ATTR_NULL
}; };
@ -868,8 +865,15 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
goto err_del_dev; 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); retval = device_create_file(f_dev, &dev_attr_loading);
if (retval) { 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__); dev_err(f_dev, "%s: device_create_file failed\n", __func__);
goto err_del_bin_attr; 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); 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); wait_for_completion(&buf->completion);
cancel_delayed_work_sync(&fw_priv->timeout_work); cancel_delayed_work_sync(&fw_priv->timeout_work);

View File

@ -16,7 +16,6 @@
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/memory.h> #include <linux/memory.h>
#include <linux/kobject.h>
#include <linux/memory_hotplug.h> #include <linux/memory_hotplug.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mutex.h> #include <linux/mutex.h>
@ -30,6 +29,8 @@ static DEFINE_MUTEX(mem_sysfs_mutex);
#define MEMORY_CLASS_NAME "memory" #define MEMORY_CLASS_NAME "memory"
#define to_memory_block(dev) container_of(dev, struct memory_block, dev)
static int sections_per_block; static int sections_per_block;
static inline int base_memory_block_id(int section_nr) 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) 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); 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, static ssize_t show_mem_start_phys_index(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct memory_block *mem = struct memory_block *mem = to_memory_block(dev);
container_of(dev, struct memory_block, dev);
unsigned long phys_index; unsigned long phys_index;
phys_index = mem->start_section_nr / sections_per_block; 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, static ssize_t show_mem_end_phys_index(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct memory_block *mem = struct memory_block *mem = to_memory_block(dev);
container_of(dev, struct memory_block, dev);
unsigned long phys_index; unsigned long phys_index;
phys_index = mem->end_section_nr / sections_per_block; 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; unsigned long i, pfn;
int ret = 1; int ret = 1;
struct memory_block *mem = struct memory_block *mem = to_memory_block(dev);
container_of(dev, struct memory_block, dev);
for (i = 0; i < sections_per_block; i++) { for (i = 0; i < sections_per_block; i++) {
if (!present_section_nr(mem->start_section_nr + 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, static ssize_t show_mem_state(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct memory_block *mem = struct memory_block *mem = to_memory_block(dev);
container_of(dev, struct memory_block, dev);
ssize_t len = 0; ssize_t len = 0;
/* /*
@ -263,9 +260,8 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
return ret; return ret;
} }
static int __memory_block_change_state(struct memory_block *mem, static int memory_block_change_state(struct memory_block *mem,
unsigned long to_state, unsigned long from_state_req, unsigned long to_state, unsigned long from_state_req)
int online_type)
{ {
int ret = 0; int ret = 0;
@ -275,105 +271,89 @@ static int __memory_block_change_state(struct memory_block *mem,
if (to_state == MEM_OFFLINE) if (to_state == MEM_OFFLINE)
mem->state = MEM_GOING_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; mem->state = ret ? from_state_req : to_state;
return ret; return ret;
} }
/* The device lock serializes operations on memory_subsys_[online|offline] */
static int memory_subsys_online(struct device *dev) 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; 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, * If we are called from store_mem_state(), online_type will be
ONLINE_KEEP); * 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; return ret;
} }
static int memory_subsys_offline(struct device *dev) static int memory_subsys_offline(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_OFFLINE)
return 0;
ret = mem->state == MEM_OFFLINE ? 0 : return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
__memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
mutex_unlock(&mem->state_mutex);
return ret;
} }
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 static ssize_t
store_mem_state(struct device *dev, store_mem_state(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr, const char *buf, size_t count)
{ {
struct memory_block *mem; struct memory_block *mem = to_memory_block(dev);
bool offline; int ret, online_type;
int ret = -EINVAL;
mem = container_of(dev, struct memory_block, dev);
lock_device_hotplug(); lock_device_hotplug();
if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) { if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
offline = false; online_type = ONLINE_KERNEL;
ret = memory_block_change_state(mem, MEM_ONLINE, else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
MEM_OFFLINE, ONLINE_KERNEL); online_type = ONLINE_MOVABLE;
} else if (!strncmp(buf, "online_movable", min_t(int, count, 14))) { else if (!strncmp(buf, "online", min_t(int, count, 6)))
offline = false; online_type = ONLINE_KEEP;
ret = memory_block_change_state(mem, MEM_ONLINE, else if (!strncmp(buf, "offline", min_t(int, count, 7)))
MEM_OFFLINE, ONLINE_MOVABLE); online_type = -1;
} else if (!strncmp(buf, "online", min_t(int, count, 6))) { else
offline = false; return -EINVAL;
ret = memory_block_change_state(mem, MEM_ONLINE,
MEM_OFFLINE, ONLINE_KEEP); switch (online_type) {
} else if(!strncmp(buf, "offline", min_t(int, count, 7))) { case ONLINE_KERNEL:
offline = true; case ONLINE_MOVABLE:
ret = memory_block_change_state(mem, MEM_OFFLINE, case ONLINE_KEEP:
MEM_ONLINE, -1); /*
* 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(); unlock_device_hotplug();
@ -394,8 +374,7 @@ store_mem_state(struct device *dev,
static ssize_t show_phys_device(struct device *dev, static ssize_t show_phys_device(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct memory_block *mem = struct memory_block *mem = to_memory_block(dev);
container_of(dev, struct memory_block, dev);
return sprintf(buf, "%d\n", mem->phys_device); return sprintf(buf, "%d\n", mem->phys_device);
} }
@ -471,7 +450,7 @@ store_soft_offline_page(struct device *dev,
u64 pfn; u64 pfn;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (strict_strtoull(buf, 0, &pfn) < 0) if (kstrtoull(buf, 0, &pfn) < 0)
return -EINVAL; return -EINVAL;
pfn >>= PAGE_SHIFT; pfn >>= PAGE_SHIFT;
if (!pfn_valid(pfn)) if (!pfn_valid(pfn))
@ -490,7 +469,7 @@ store_hard_offline_page(struct device *dev,
u64 pfn; u64 pfn;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (strict_strtoull(buf, 0, &pfn) < 0) if (kstrtoull(buf, 0, &pfn) < 0)
return -EINVAL; return -EINVAL;
pfn >>= PAGE_SHIFT; pfn >>= PAGE_SHIFT;
ret = memory_failure(pfn, 0, 0); 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); put_device(&hint->dev);
if (!dev) if (!dev)
return NULL; 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 static
int register_memory(struct memory_block *memory) int register_memory(struct memory_block *memory)
{ {
int error;
memory->dev.bus = &memory_subsys; memory->dev.bus = &memory_subsys;
memory->dev.id = memory->start_section_nr / sections_per_block; memory->dev.id = memory->start_section_nr / sections_per_block;
memory->dev.release = memory_block_release; memory->dev.release = memory_block_release;
memory->dev.groups = memory_memblk_attr_groups; memory->dev.groups = memory_memblk_attr_groups;
memory->dev.offline = memory->state == MEM_OFFLINE; memory->dev.offline = memory->state == MEM_OFFLINE;
error = device_register(&memory->dev); return device_register(&memory->dev);
return error;
} }
static int init_memory_block(struct memory_block **memory, 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->end_section_nr = mem->start_section_nr + sections_per_block - 1;
mem->state = state; mem->state = state;
mem->section_count++; mem->section_count++;
mutex_init(&mem->state_mutex);
start_pfn = section_nr_to_pfn(mem->start_section_nr); start_pfn = section_nr_to_pfn(mem->start_section_nr);
mem->phys_device = arch_get_memory_phys_device(start_pfn); 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; return ret;
} }
static int add_memory_section(int nid, struct mem_section *section, static int add_memory_block(int base_section_nr)
struct memory_block **mem_p,
unsigned long state, enum mem_add_context context)
{ {
struct memory_block *mem = NULL; struct memory_block *mem;
int scn_nr = __section_nr(section); int i, ret, section_count = 0, section_nr;
int ret = 0;
mutex_lock(&mem_sysfs_mutex); for (i = base_section_nr;
(i < base_section_nr + sections_per_block) && i < NR_MEM_SECTIONS;
if (context == BOOT) { i++) {
/* same memory block ? */ if (!present_section_nr(i))
if (mem_p && *mem_p) continue;
if (scn_nr >= (*mem_p)->start_section_nr && if (section_count == 0)
scn_nr <= (*mem_p)->end_section_nr) { section_nr = i;
mem = *mem_p; section_count++;
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;
} }
if (!ret) { if (section_count == 0)
if (context == HOTPLUG && return 0;
mem->section_count == sections_per_block) ret = init_memory_block(&mem, __nr_to_section(section_nr), MEM_ONLINE);
ret = register_mem_sect_under_node(mem, nid); if (ret)
} return ret;
mem->section_count = section_count;
mutex_unlock(&mem_sysfs_mutex); return 0;
return ret;
} }
/* /*
* need an interface for the VM to add new memory regions, * need an interface for the VM to add new memory regions,
* but without onlining it. * but without onlining it.
*/ */
int register_new_memory(int nid, struct mem_section *section) 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 #ifdef CONFIG_MEMORY_HOTREMOVE
@ -665,7 +642,7 @@ unregister_memory(struct memory_block *memory)
BUG_ON(memory->dev.bus != &memory_subsys); BUG_ON(memory->dev.bus != &memory_subsys);
/* drop the ref. we got in remove_memory_block() */ /* drop the ref. we got in remove_memory_block() */
kobject_put(&memory->dev.kobj); put_device(&memory->dev);
device_unregister(&memory->dev); device_unregister(&memory->dev);
} }
@ -682,7 +659,7 @@ static int remove_memory_block(unsigned long node_id,
if (mem->section_count == 0) if (mem->section_count == 0)
unregister_memory(mem); unregister_memory(mem);
else else
kobject_put(&mem->dev.kobj); put_device(&mem->dev);
mutex_unlock(&mem_sysfs_mutex); mutex_unlock(&mem_sysfs_mutex);
return 0; return 0;
@ -735,7 +712,6 @@ int __init memory_dev_init(void)
int ret; int ret;
int err; int err;
unsigned long block_sz; unsigned long block_sz;
struct memory_block *mem = NULL;
ret = subsys_system_register(&memory_subsys, memory_root_attr_groups); ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
if (ret) if (ret)
@ -748,17 +724,13 @@ int __init memory_dev_init(void)
* Create entries for memory sections that were found * Create entries for memory sections that were found
* during boot and have been initialized * during boot and have been initialized
*/ */
for (i = 0; i < NR_MEM_SECTIONS; i++) { mutex_lock(&mem_sysfs_mutex);
if (!present_section_nr(i)) for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
continue; err = add_memory_block(i);
/* 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);
if (!ret) if (!ret)
ret = err; ret = err;
} }
mutex_unlock(&mem_sysfs_mutex);
out: out:
if (ret) if (ret)

View File

@ -672,11 +672,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
} }
static DEVICE_ATTR_RO(modalias);
static struct device_attribute platform_dev_attrs[] = { static struct attribute *platform_dev_attrs[] = {
__ATTR_RO(modalias), &dev_attr_modalias.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(platform_dev);
static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) 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 = { struct bus_type platform_bus_type = {
.name = "platform", .name = "platform",
.dev_attrs = platform_dev_attrs, .dev_groups = platform_dev_groups,
.match = platform_match, .match = platform_match,
.uevent = platform_uevent, .uevent = platform_uevent,
.pm = &platform_dev_pm_ops, .pm = &platform_dev_pm_ops,
@ -1054,7 +1056,7 @@ void __init early_platform_driver_register_all(char *class_str)
* @epdrv: early platform driver structure * @epdrv: early platform driver structure
* @id: id to match against * @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) early_platform_match(struct early_platform_driver *epdrv, int id)
{ {
struct platform_device *pd; struct platform_device *pd;
@ -1072,7 +1074,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id)
* @epdrv: early platform driver structure * @epdrv: early platform driver structure
* @id: return true if id or above exists * @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) int id)
{ {
struct platform_device *pd; struct platform_device *pd;

View File

@ -206,7 +206,7 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
if (!dev->power.use_autosuspend) if (!dev->power.use_autosuspend)
return -EIO; return -EIO;
if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay) if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay)
return -EINVAL; return -EINVAL;
device_lock(dev); device_lock(dev);

View File

@ -281,7 +281,7 @@ static ssize_t regmap_map_write_file(struct file *file,
reg = simple_strtoul(start, &start, 16); reg = simple_strtoul(start, &start, 16);
while (*start == ' ') while (*start == ' ')
start++; start++;
if (strict_strtoul(start, 16, &value)) if (kstrtoul(start, 16, &value))
return -EINVAL; return -EINVAL;
/* Userspace has been fiddling around behind the kernel's back */ /* Userspace has been fiddling around behind the kernel's back */

View File

@ -62,25 +62,6 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
} }
#endif #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) \ #define define_siblings_show_map(name) \
static ssize_t show_##name(struct device *dev, \ static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \ 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); \ return show_cpumap(1, topology_##name(dev->id), buf); \
} }
#endif
#define define_siblings_show_func(name) \ #define define_siblings_show_func(name) \
define_siblings_show_map(name); define_siblings_show_list(name) define_siblings_show_map(name); define_siblings_show_list(name)

View File

@ -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 int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
static void rbd_spec_put(struct rbd_spec *spec); static void rbd_spec_put(struct rbd_spec *spec);
static struct bus_attribute rbd_bus_attrs[] = { static BUS_ATTR(add, S_IWUSR, NULL, rbd_add);
__ATTR(add, S_IWUSR, NULL, rbd_add), static BUS_ATTR(remove, S_IWUSR, NULL, rbd_remove);
__ATTR(remove, S_IWUSR, NULL, rbd_remove),
__ATTR_NULL 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 = { static struct bus_type rbd_bus_type = {
.name = "rbd", .name = "rbd",
.bus_attrs = rbd_bus_attrs, .bus_groups = rbd_bus_groups,
}; };
static void rbd_root_dev_release(struct device *dev) static void rbd_root_dev_release(struct device *dev)

View File

@ -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); struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", bsr_dev->bsr_bytes); return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
} }
static DEVICE_ATTR_RO(bsr_size);
static ssize_t static ssize_t
bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf) 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); struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", bsr_dev->bsr_stride); return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
} }
static DEVICE_ATTR_RO(bsr_stride);
static ssize_t 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); struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
return sprintf(buf, "%llu\n", bsr_dev->bsr_len); return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
} }
static DEVICE_ATTR_RO(bsr_length);
static struct device_attribute bsr_dev_attrs[] = { static struct attribute *bsr_dev_attrs[] = {
__ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL), &dev_attr_bsr_size.attr,
__ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL), &dev_attr_bsr_stride.attr,
__ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL), &dev_attr_bsr_length.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(bsr_dev);
static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) 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); ret = PTR_ERR(bsr_class);
goto out_err_1; 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"); ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
bsr_major = MAJOR(bsr_dev); bsr_major = MAJOR(bsr_dev);

View File

@ -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); return fixed_size_llseek(file, offset, origin, srom->total_size);
} }
static ssize_t total_show(struct device *dev, static ssize_t total_size_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct srom_dev *srom = dev_get_drvdata(dev); struct srom_dev *srom = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", srom->total_size); return sprintf(buf, "%u\n", srom->total_size);
} }
static DEVICE_ATTR_RO(total_size);
static ssize_t sector_show(struct device *dev, static ssize_t sector_size_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct srom_dev *srom = dev_get_drvdata(dev); struct srom_dev *srom = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", srom->sector_size); return sprintf(buf, "%u\n", srom->sector_size);
} }
static DEVICE_ATTR_RO(sector_size);
static ssize_t page_show(struct device *dev, static ssize_t page_size_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct srom_dev *srom = dev_get_drvdata(dev); struct srom_dev *srom = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", srom->page_size); return sprintf(buf, "%u\n", srom->page_size);
} }
static DEVICE_ATTR_RO(page_size);
static struct device_attribute srom_dev_attrs[] = { static struct attribute *srom_dev_attrs[] = {
__ATTR(total_size, S_IRUGO, total_show, NULL), &dev_attr_total_size.attr,
__ATTR(sector_size, S_IRUGO, sector_show, NULL), &dev_attr_sector_size.attr,
__ATTR(page_size, S_IRUGO, page_show, NULL), &dev_attr_page_size.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(srom_dev);
static char *srom_devnode(struct device *dev, umode_t *mode) static char *srom_devnode(struct device *dev, umode_t *mode)
{ {
@ -418,7 +422,7 @@ static int srom_init(void)
result = PTR_ERR(srom_class); result = PTR_ERR(srom_class);
goto fail_cdev; goto fail_cdev;
} }
srom_class->dev_attrs = srom_dev_attrs; srom_class->dev_groups = srom_dev_groups;
srom_class->devnode = srom_devnode; srom_class->devnode = srom_devnode;
/* Do per-partition initialization */ /* Do per-partition initialization */

View File

@ -703,7 +703,7 @@ err_out:
} }
EXPORT_SYMBOL(devfreq_remove_governor); 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) struct device_attribute *attr, char *buf)
{ {
if (!to_devfreq(dev)->governor) 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); 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) const char *buf, size_t count)
{ {
struct devfreq *df = to_devfreq(dev); struct devfreq *df = to_devfreq(dev);
@ -754,9 +754,11 @@ out:
ret = count; ret = count;
return ret; return ret;
} }
static ssize_t show_available_governors(struct device *d, static DEVICE_ATTR_RW(governor);
struct device_attribute *attr,
char *buf) static ssize_t available_governors_show(struct device *d,
struct device_attribute *attr,
char *buf)
{ {
struct devfreq_governor *tmp_governor; struct devfreq_governor *tmp_governor;
ssize_t count = 0; ssize_t count = 0;
@ -775,9 +777,10 @@ static ssize_t show_available_governors(struct device *d,
return count; return count;
} }
static DEVICE_ATTR_RO(available_governors);
static ssize_t show_freq(struct device *dev, static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
unsigned long freq; unsigned long freq;
struct devfreq *devfreq = to_devfreq(dev); 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); return sprintf(buf, "%lu\n", devfreq->previous_freq);
} }
static DEVICE_ATTR_RO(cur_freq);
static ssize_t show_target_freq(struct device *dev, static ssize_t target_freq_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq); 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) struct device_attribute *attr, char *buf)
{ {
return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms); 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, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
@ -821,8 +826,9 @@ static ssize_t store_polling_interval(struct device *dev,
return ret; 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) const char *buf, size_t count)
{ {
struct devfreq *df = to_devfreq(dev); struct devfreq *df = to_devfreq(dev);
@ -849,13 +855,13 @@ unlock:
return ret; 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) char *buf)
{ {
return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq); 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) const char *buf, size_t count)
{ {
struct devfreq *df = to_devfreq(dev); struct devfreq *df = to_devfreq(dev);
@ -881,16 +887,18 @@ unlock:
mutex_unlock(&df->lock); mutex_unlock(&df->lock);
return ret; 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) char *buf)
{ {
return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); 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, static ssize_t available_frequencies_show(struct device *d,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct devfreq *df = to_devfreq(d); struct devfreq *df = to_devfreq(d);
struct device *dev = df->dev.parent; struct device *dev = df->dev.parent;
@ -918,9 +926,10 @@ static ssize_t show_available_freqs(struct device *d,
return count; return count;
} }
static DEVICE_ATTR_RO(available_frequencies);
static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr, static ssize_t trans_stat_show(struct device *dev,
char *buf) struct device_attribute *attr, char *buf)
{ {
struct devfreq *devfreq = to_devfreq(dev); struct devfreq *devfreq = to_devfreq(dev);
ssize_t len; ssize_t len;
@ -959,20 +968,21 @@ static ssize_t show_trans_table(struct device *dev, struct device_attribute *att
devfreq->total_trans); devfreq->total_trans);
return len; return len;
} }
static DEVICE_ATTR_RO(trans_stat);
static struct device_attribute devfreq_attrs[] = { static struct attribute *devfreq_attrs[] = {
__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor), &dev_attr_governor.attr,
__ATTR(available_governors, S_IRUGO, show_available_governors, NULL), &dev_attr_available_governors.attr,
__ATTR(cur_freq, S_IRUGO, show_freq, NULL), &dev_attr_cur_freq.attr,
__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL), &dev_attr_available_frequencies.attr,
__ATTR(target_freq, S_IRUGO, show_target_freq, NULL), &dev_attr_target_freq.attr,
__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, &dev_attr_polling_interval.attr,
store_polling_interval), &dev_attr_min_freq.attr,
__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq), &dev_attr_max_freq.attr,
__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq), &dev_attr_trans_stat.attr,
__ATTR(trans_stat, S_IRUGO, show_trans_table, NULL), NULL,
{ },
}; };
ATTRIBUTE_GROUPS(devfreq);
static int __init devfreq_init(void) 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__); pr_err("%s: couldn't create workqueue\n", __FILE__);
return PTR_ERR(devfreq_wq); return PTR_ERR(devfreq_wq);
} }
devfreq_class->dev_attrs = devfreq_attrs; devfreq_class->dev_groups = devfreq_groups;
return 0; return 0;
} }

View File

@ -87,7 +87,8 @@ static struct dma_chan *dev_to_dma_chan(struct device *dev)
return chan_dev->chan; 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; struct dma_chan *chan;
unsigned long count = 0; unsigned long count = 0;
@ -106,9 +107,10 @@ static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *at
return err; return err;
} }
static DEVICE_ATTR_RO(memcpy_count);
static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr, static ssize_t bytes_transferred_show(struct device *dev,
char *buf) struct device_attribute *attr, char *buf)
{ {
struct dma_chan *chan; struct dma_chan *chan;
unsigned long count = 0; unsigned long count = 0;
@ -127,8 +129,10 @@ static ssize_t show_bytes_transferred(struct device *dev, struct device_attribut
return err; 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; struct dma_chan *chan;
int err; int err;
@ -143,13 +147,15 @@ static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, ch
return err; return err;
} }
static DEVICE_ATTR_RO(in_use);
static struct device_attribute dma_attrs[] = { static struct attribute *dma_dev_attrs[] = {
__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL), &dev_attr_memcpy_count.attr,
__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL), &dev_attr_bytes_transferred.attr,
__ATTR(in_use, S_IRUGO, show_in_use, NULL), &dev_attr_in_use.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(dma_dev);
static void chan_dev_release(struct device *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 = { static struct class dma_devclass = {
.name = "dma", .name = "dma",
.dev_attrs = dma_attrs, .dev_groups = dma_dev_groups,
.dev_release = chan_dev_release, .dev_release = chan_dev_release,
}; };

View File

@ -148,6 +148,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static DEVICE_ATTR_RW(state);
static ssize_t name_show(struct device *dev, struct device_attribute *attr, static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf) 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)); return sprintf(buf, "%s\n", dev_name(edev->dev));
} }
static DEVICE_ATTR_RO(name);
static ssize_t cable_name_show(struct device *dev, static ssize_t cable_name_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
@ -527,11 +529,12 @@ int extcon_unregister_notifier(struct extcon_dev *edev,
} }
EXPORT_SYMBOL_GPL(extcon_unregister_notifier); EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
static struct device_attribute extcon_attrs[] = { static struct attribute *extcon_attrs[] = {
__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store), &dev_attr_state.attr,
__ATTR_RO(name), &dev_attr_name.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(extcon);
static int create_extcon_class(void) static int create_extcon_class(void)
{ {
@ -539,7 +542,7 @@ static int create_extcon_class(void)
extcon_class = class_create(THIS_MODULE, "extcon"); extcon_class = class_create(THIS_MODULE, "extcon");
if (IS_ERR(extcon_class)) if (IS_ERR(extcon_class))
return PTR_ERR(extcon_class); return PTR_ERR(extcon_class);
extcon_class->dev_attrs = extcon_attrs; extcon_class->dev_groups = extcon_groups;
#if defined(CONFIG_ANDROID) #if defined(CONFIG_ANDROID)
switch_class = class_compat_register("switch"); switch_class = class_compat_register("switch");

View File

@ -535,11 +535,12 @@ static struct attribute *dcdbas_dev_attrs[] = {
static struct attribute_group dcdbas_attr_group = { static struct attribute_group dcdbas_attr_group = {
.attrs = dcdbas_dev_attrs, .attrs = dcdbas_dev_attrs,
.bin_attrs = dcdbas_bin_attrs,
}; };
static int dcdbas_probe(struct platform_device *dev) static int dcdbas_probe(struct platform_device *dev)
{ {
int i, error; int error;
host_control_action = HC_ACTION_NONE; host_control_action = HC_ACTION_NONE;
host_control_smi_type = HC_SMITYPE_NONE; host_control_smi_type = HC_SMITYPE_NONE;
@ -555,18 +556,6 @@ static int dcdbas_probe(struct platform_device *dev)
if (error) if (error)
return 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); register_reboot_notifier(&dcdbas_reboot_nb);
dev_info(&dev->dev, "%s (version %s)\n", 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) static int dcdbas_remove(struct platform_device *dev)
{ {
int i;
unregister_reboot_notifier(&dcdbas_reboot_nb); 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); sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
return 0; return 0;

View File

@ -1917,11 +1917,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
} }
static DEVICE_ATTR_RO(modalias);
static struct device_attribute hid_dev_attrs[] = { static struct attribute *hid_dev_attrs[] = {
__ATTR_RO(modalias), &dev_attr_modalias.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(hid_dev);
static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) 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 = { static struct bus_type hid_bus_type = {
.name = "hid", .name = "hid",
.dev_attrs = hid_dev_attrs, .dev_groups = hid_dev_groups,
.match = hid_bus_match, .match = hid_bus_match,
.probe = hid_device_probe, .probe = hid_device_probe,
.remove = hid_device_remove, .remove = hid_device_remove,

View File

@ -75,6 +75,8 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
return size; 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, static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
@ -123,6 +125,8 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
return size; 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 */ /* retval is 1-5 on success, < 0 on error */
static int arvo_get_actual_profile(struct usb_device *usb_dev) 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); mutex_unlock(&arvo->arvo_lock);
return retval; 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, static ssize_t arvo_sysfs_write(struct file *fp,
struct kobject *kobj, void const *buf, 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, return arvo_sysfs_write(fp, kobj, buf, off, count,
sizeof(struct arvo_button), ARVO_COMMAND_BUTTON); 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, static ssize_t arvo_sysfs_read_info(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf, 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, return arvo_sysfs_read(fp, kobj, buf, off, count,
sizeof(struct arvo_info), ARVO_COMMAND_INFO); sizeof(struct arvo_info), ARVO_COMMAND_INFO);
} }
static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
sizeof(struct arvo_info));
static struct attribute *arvo_attrs[] = {
static struct device_attribute arvo_attributes[] = { &dev_attr_mode_key.attr,
__ATTR(mode_key, 0660, &dev_attr_key_mask.attr,
arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key), &dev_attr_actual_profile.attr,
__ATTR(key_mask, 0660, NULL,
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 bin_attribute arvo_bin_attributes[] = { static struct bin_attribute *arvo_bin_attributes[] = {
{ &bin_attr_button,
.attr = { .name = "button", .mode = 0220 }, &bin_attr_info,
.size = sizeof(struct arvo_button), NULL,
.write = arvo_sysfs_write_button };
},
{ static const struct attribute_group arvo_group = {
.attr = { .name = "info", .mode = 0440 }, .attrs = arvo_attrs,
.size = sizeof(struct arvo_info), .bin_attrs = arvo_bin_attributes,
.read = arvo_sysfs_read_info };
},
__ATTR_NULL static const struct attribute_group *arvo_groups[] = {
&arvo_group,
NULL,
}; };
static int arvo_init_arvo_device_struct(struct usb_device *usb_dev, 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"); arvo_class = class_create(THIS_MODULE, "arvo");
if (IS_ERR(arvo_class)) if (IS_ERR(arvo_class))
return PTR_ERR(arvo_class); return PTR_ERR(arvo_class);
arvo_class->dev_attrs = arvo_attributes; arvo_class->dev_groups = arvo_groups;
arvo_class->dev_bin_attrs = arvo_bin_attributes;
retval = hid_register_driver(&arvo_driver); retval = hid_register_driver(&arvo_driver);
if (retval) if (retval)

View File

@ -109,12 +109,12 @@ static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
return size; return size;
} }
static DEVICE_ATTR(actual_profile, 0660, isku_sysfs_show_actual_profile,
isku_sysfs_set_actual_profile);
static struct device_attribute isku_attributes[] = { static struct attribute *isku_attrs[] = {
__ATTR(actual_profile, 0660, &dev_attr_actual_profile.attr,
isku_sysfs_show_actual_profile, NULL,
isku_sysfs_set_actual_profile),
__ATTR_NULL
}; };
static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, 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) ISKU_SYSFS_W(thingy, THINGY)
#define ISKU_BIN_ATTR_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = ISKU_SIZE_ ## THINGY, \ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \ .read = isku_sysfs_read_ ## thingy, \
@ -192,52 +193,64 @@ ISKU_SYSFS_W(thingy, THINGY)
} }
#define ISKU_BIN_ATTR_R(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 }, \ .attr = { .name = #thingy, .mode = 0440 }, \
.size = ISKU_SIZE_ ## THINGY, \ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \ .read = isku_sysfs_read_ ## thingy, \
} }
#define ISKU_BIN_ATTR_W(thingy, 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 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = ISKU_SIZE_ ## THINGY, \ .size = ISKU_SIZE_ ## THINGY, \
.write = isku_sysfs_write_ ## thingy \ .write = isku_sysfs_write_ ## thingy \
} }
ISKU_SYSFS_RW(macro, MACRO) ISKU_BIN_ATTR_RW(macro, MACRO);
ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION) ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION);
ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE) ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE);
ISKU_SYSFS_RW(keys_media, KEYS_MEDIA) ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA);
ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER) ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER);
ISKU_SYSFS_RW(keys_macro, KEYS_MACRO) ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO);
ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK) ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK);
ISKU_SYSFS_RW(light, LIGHT) ISKU_BIN_ATTR_RW(light, LIGHT);
ISKU_SYSFS_RW(key_mask, KEY_MASK) ISKU_BIN_ATTR_RW(key_mask, KEY_MASK);
ISKU_SYSFS_RW(last_set, LAST_SET) ISKU_BIN_ATTR_RW(last_set, LAST_SET);
ISKU_SYSFS_W(talk, TALK) ISKU_BIN_ATTR_W(talk, TALK);
ISKU_SYSFS_W(talkfx, TALKFX) ISKU_BIN_ATTR_W(talkfx, TALKFX);
ISKU_SYSFS_R(info, INFO) ISKU_BIN_ATTR_W(control, CONTROL);
ISKU_SYSFS_W(control, CONTROL) ISKU_BIN_ATTR_W(reset, RESET);
ISKU_SYSFS_W(reset, RESET) ISKU_BIN_ATTR_R(info, INFO);
static struct bin_attribute isku_bin_attributes[] = { static struct bin_attribute *isku_bin_attributes[] = {
ISKU_BIN_ATTR_RW(macro, MACRO), &bin_attr_macro,
ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION), &bin_attr_keys_function,
ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE), &bin_attr_keys_easyzone,
ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA), &bin_attr_keys_media,
ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER), &bin_attr_keys_thumbster,
ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO), &bin_attr_keys_macro,
ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK), &bin_attr_keys_capslock,
ISKU_BIN_ATTR_RW(light, LIGHT), &bin_attr_light,
ISKU_BIN_ATTR_RW(key_mask, KEY_MASK), &bin_attr_key_mask,
ISKU_BIN_ATTR_RW(last_set, LAST_SET), &bin_attr_last_set,
ISKU_BIN_ATTR_W(talk, TALK), &bin_attr_talk,
ISKU_BIN_ATTR_W(talkfx, TALKFX), &bin_attr_talkfx,
ISKU_BIN_ATTR_R(info, INFO), &bin_attr_control,
ISKU_BIN_ATTR_W(control, CONTROL), &bin_attr_reset,
ISKU_BIN_ATTR_W(reset, RESET), &bin_attr_info,
__ATTR_NULL 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, 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"); isku_class = class_create(THIS_MODULE, "isku");
if (IS_ERR(isku_class)) if (IS_ERR(isku_class))
return PTR_ERR(isku_class); return PTR_ERR(isku_class);
isku_class->dev_attrs = isku_attributes; isku_class->dev_groups = isku_groups;
isku_class->dev_bin_attrs = isku_bin_attributes;
retval = hid_register_driver(&isku_driver); retval = hid_register_driver(&isku_driver);
if (retval) if (retval)

View File

@ -324,6 +324,8 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
return sizeof(struct kone_settings); 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, static ssize_t kone_sysfs_read_profilex(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, 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); 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, static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile); 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, static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi); 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 */ /* 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, 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 retval;
return snprintf(buf, PAGE_SIZE, "%d\n", weight); 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, static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version); 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, static ssize_t kone_sysfs_show_tcu(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
@ -524,6 +544,7 @@ exit_unlock:
mutex_unlock(&kone->kone_lock); mutex_unlock(&kone->kone_lock);
return retval; 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, static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
struct device_attribute *attr, char *buf) 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); mutex_unlock(&kone->kone_lock);
return size; 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. * Read actual dpi settings.
* Returns raw value for further processing. Refer to enum * Returns raw value for further processing. Refer to enum
* kone_polling_rates to get real value. * kone_polling_rates to get real value.
*/ */
__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL), &dev_attr_actual_dpi.attr,
__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL), &dev_attr_actual_profile.attr,
/* /*
* The mouse can be equipped with one of four supplied weights from 5 * 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 * by software. Refer to enum kone_weights to get corresponding real
* weight. * weight.
*/ */
__ATTR(weight, 0440, kone_sysfs_show_weight, NULL), &dev_attr_weight.attr,
/* /*
* Prints firmware version stored in mouse as integer. * 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 * 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. * positions to the left. E.g. a value of 138 means 1.38.
*/ */
__ATTR(firmware_version, 0440, &dev_attr_firmware_version.attr,
kone_sysfs_show_firmware_version, NULL),
/* /*
* Prints state of Tracking Control Unit as number where 0 = off and * Prints state of Tracking Control Unit as number where 0 = off and
* 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
* activates the tcu * 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 */ /* Prints and takes the number of the profile the mouse starts with */
__ATTR(startup_profile, 0660, &dev_attr_startup_profile.attr,
kone_sysfs_show_startup_profile, NULL,
kone_sysfs_set_startup_profile),
__ATTR_NULL
}; };
static struct bin_attribute kone_bin_attributes[] = { static struct bin_attribute *kone_bin_attributes[] = {
{ &bin_attr_settings,
.attr = { .name = "settings", .mode = 0660 }, &bin_attr_profile1,
.size = sizeof(struct kone_settings), &bin_attr_profile2,
.read = kone_sysfs_read_settings, &bin_attr_profile3,
.write = kone_sysfs_write_settings &bin_attr_profile4,
}, &bin_attr_profile5,
{ NULL,
.attr = { .name = "profile1", .mode = 0660 }, };
.size = sizeof(struct kone_profile),
.read = kone_sysfs_read_profilex, static const struct attribute_group kone_group = {
.write = kone_sysfs_write_profilex, .attrs = kone_attrs,
.private = &profile_numbers[0] .bin_attrs = kone_bin_attributes,
}, };
{
.attr = { .name = "profile2", .mode = 0660 }, static const struct attribute_group *kone_groups[] = {
.size = sizeof(struct kone_profile), &kone_group,
.read = kone_sysfs_read_profilex, NULL,
.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 int kone_init_kone_device_struct(struct usb_device *usb_dev, 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"); kone_class = class_create(THIS_MODULE, "kone");
if (IS_ERR(kone_class)) if (IS_ERR(kone_class))
return PTR_ERR(kone_class); return PTR_ERR(kone_class);
kone_class->dev_attrs = kone_attributes; kone_class->dev_groups = kone_groups;
kone_class->dev_bin_attrs = kone_bin_attributes;
retval = hid_register_driver(&kone_driver); retval = hid_register_driver(&kone_driver);
if (retval) if (retval)

View File

@ -156,7 +156,8 @@ KONEPLUS_SYSFS_W(thingy, THINGY) \
KONEPLUS_SYSFS_R(thingy, THINGY) KONEPLUS_SYSFS_R(thingy, THINGY)
#define KONEPLUS_BIN_ATTRIBUTE_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = KONEPLUS_SIZE_ ## THINGY, \ .size = KONEPLUS_SIZE_ ## THINGY, \
.read = koneplus_sysfs_read_ ## thingy, \ .read = koneplus_sysfs_read_ ## thingy, \
@ -164,28 +165,29 @@ KONEPLUS_SYSFS_R(thingy, THINGY)
} }
#define KONEPLUS_BIN_ATTRIBUTE_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 }, \ .attr = { .name = #thingy, .mode = 0440 }, \
.size = KONEPLUS_SIZE_ ## THINGY, \ .size = KONEPLUS_SIZE_ ## THINGY, \
.read = koneplus_sysfs_read_ ## thingy, \ .read = koneplus_sysfs_read_ ## thingy, \
} }
#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, 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 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = KONEPLUS_SIZE_ ## THINGY, \ .size = KONEPLUS_SIZE_ ## THINGY, \
.write = koneplus_sysfs_write_ ## thingy \ .write = koneplus_sysfs_write_ ## thingy \
} }
KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
KONEPLUS_SYSFS_W(control, CONTROL) KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK);
KONEPLUS_SYSFS_RW(info, INFO) KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO);
KONEPLUS_SYSFS_W(talk, TALK) KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
KONEPLUS_SYSFS_W(macro, MACRO) KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO);
KONEPLUS_SYSFS_RW(sensor, SENSOR) KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR);
KONEPLUS_SYSFS_RW(tcu, TCU) KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU);
KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE) KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS) KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf, 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); 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, static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
@ -274,6 +295,12 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
return size; 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, static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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[] = { static struct attribute *koneplus_attrs[] = {
__ATTR(actual_profile, 0660, &dev_attr_actual_profile.attr,
koneplus_sysfs_show_actual_profile, &dev_attr_startup_profile.attr,
koneplus_sysfs_set_actual_profile), &dev_attr_firmware_version.attr,
__ATTR(startup_profile, 0660, NULL,
koneplus_sysfs_show_actual_profile,
koneplus_sysfs_set_actual_profile),
__ATTR(firmware_version, 0440,
koneplus_sysfs_show_firmware_version, NULL),
__ATTR_NULL
}; };
static struct bin_attribute koneplus_bin_attributes[] = { static struct bin_attribute *koneplus_bin_attributes[] = {
KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL), &bin_attr_control,
KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO), &bin_attr_talk,
KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK), &bin_attr_macro,
KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO), &bin_attr_tcu_image,
KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR), &bin_attr_info,
KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU), &bin_attr_sensor,
KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE), &bin_attr_tcu,
KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), &bin_attr_profile_settings,
KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), &bin_attr_profile_buttons,
{ &bin_attr_profile1_settings,
.attr = { .name = "profile1_settings", .mode = 0440 }, &bin_attr_profile2_settings,
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, &bin_attr_profile3_settings,
.read = koneplus_sysfs_read_profilex_settings, &bin_attr_profile4_settings,
.private = &profile_numbers[0] &bin_attr_profile5_settings,
}, &bin_attr_profile1_buttons,
{ &bin_attr_profile2_buttons,
.attr = { .name = "profile2_settings", .mode = 0440 }, &bin_attr_profile3_buttons,
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, &bin_attr_profile4_buttons,
.read = koneplus_sysfs_read_profilex_settings, &bin_attr_profile5_buttons,
.private = &profile_numbers[1] NULL,
}, };
{
.attr = { .name = "profile3_settings", .mode = 0440 }, static const struct attribute_group koneplus_group = {
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, .attrs = koneplus_attrs,
.read = koneplus_sysfs_read_profilex_settings, .bin_attrs = koneplus_bin_attributes,
.private = &profile_numbers[2] };
},
{ static const struct attribute_group *koneplus_groups[] = {
.attr = { .name = "profile4_settings", .mode = 0440 }, &koneplus_group,
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, NULL,
.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 int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 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"); koneplus_class = class_create(THIS_MODULE, "koneplus");
if (IS_ERR(koneplus_class)) if (IS_ERR(koneplus_class))
return PTR_ERR(koneplus_class); return PTR_ERR(koneplus_class);
koneplus_class->dev_attrs = koneplus_attributes; koneplus_class->dev_groups = koneplus_groups;
koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
retval = hid_register_driver(&koneplus_driver); retval = hid_register_driver(&koneplus_driver);
if (retval) if (retval)

View File

@ -94,7 +94,8 @@ KONEPURE_SYSFS_W(thingy, THINGY) \
KONEPURE_SYSFS_R(thingy, THINGY) KONEPURE_SYSFS_R(thingy, THINGY)
#define KONEPURE_BIN_ATTRIBUTE_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = KONEPURE_SIZE_ ## THINGY, \ .size = KONEPURE_SIZE_ ## THINGY, \
.read = konepure_sysfs_read_ ## thingy, \ .read = konepure_sysfs_read_ ## thingy, \
@ -102,44 +103,56 @@ KONEPURE_SYSFS_R(thingy, THINGY)
} }
#define KONEPURE_BIN_ATTRIBUTE_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 }, \ .attr = { .name = #thingy, .mode = 0440 }, \
.size = KONEPURE_SIZE_ ## THINGY, \ .size = KONEPURE_SIZE_ ## THINGY, \
.read = konepure_sysfs_read_ ## thingy, \ .read = konepure_sysfs_read_ ## thingy, \
} }
#define KONEPURE_BIN_ATTRIBUTE_W(thingy, 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 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = KONEPURE_SIZE_ ## THINGY, \ .size = KONEPURE_SIZE_ ## THINGY, \
.write = konepure_sysfs_write_ ## thingy \ .write = konepure_sysfs_write_ ## thingy \
} }
KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE) KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE);
KONEPURE_SYSFS_W(control, CONTROL) KONEPURE_BIN_ATTRIBUTE_RW(info, INFO);
KONEPURE_SYSFS_RW(info, INFO) KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR);
KONEPURE_SYSFS_W(talk, TALK) KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU);
KONEPURE_SYSFS_W(macro, MACRO) KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
KONEPURE_SYSFS_RW(sensor, SENSOR) KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
KONEPURE_SYSFS_RW(tcu, TCU) KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL);
KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE) KONEPURE_BIN_ATTRIBUTE_W(talk, TALK);
KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS) KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO);
KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS) KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
static struct bin_attribute konepure_bin_attributes[] = { static struct bin_attribute *konepure_bin_attributes[] = {
KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE), &bin_attr_actual_profile,
KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL), &bin_attr_info,
KONEPURE_BIN_ATTRIBUTE_RW(info, INFO), &bin_attr_sensor,
KONEPURE_BIN_ATTRIBUTE_W(talk, TALK), &bin_attr_tcu,
KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO), &bin_attr_profile_settings,
KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR), &bin_attr_profile_buttons,
KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU), &bin_attr_control,
KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE), &bin_attr_talk,
KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), &bin_attr_macro,
KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), &bin_attr_tcu_image,
__ATTR_NULL 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, static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
struct konepure_device *konepure) struct konepure_device *konepure)
{ {
@ -282,7 +295,7 @@ static int __init konepure_init(void)
konepure_class = class_create(THIS_MODULE, "konepure"); konepure_class = class_create(THIS_MODULE, "konepure");
if (IS_ERR(konepure_class)) if (IS_ERR(konepure_class))
return PTR_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); retval = hid_register_driver(&konepure_driver);
if (retval) if (retval)

View File

@ -197,31 +197,25 @@ KOVAPLUS_SYSFS_W(thingy, THINGY) \
KOVAPLUS_SYSFS_R(thingy, THINGY) KOVAPLUS_SYSFS_R(thingy, THINGY)
#define KOVAPLUS_BIN_ATTRIBUTE_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = KOVAPLUS_SIZE_ ## THINGY, \ .size = KOVAPLUS_SIZE_ ## THINGY, \
.read = kovaplus_sysfs_read_ ## thingy, \ .read = kovaplus_sysfs_read_ ## thingy, \
.write = kovaplus_sysfs_write_ ## 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) \ #define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
{ \ KOVAPLUS_SYSFS_W(thingy, THINGY); \
static struct bin_attribute bin_attr_##thingy = { \
.attr = { .name = #thingy, .mode = 0220 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = KOVAPLUS_SIZE_ ## THINGY, \ .size = KOVAPLUS_SIZE_ ## THINGY, \
.write = kovaplus_sysfs_write_ ## thingy \ .write = kovaplus_sysfs_write_ ## thingy \
} }
KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
KOVAPLUS_SYSFS_W(control, CONTROL) KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO);
KOVAPLUS_SYSFS_RW(info, INFO) KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS) KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf, 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); 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, static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
@ -310,6 +323,9 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
return size; 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, static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi); 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, static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity); 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, static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity); 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, static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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[] = { static struct attribute *kovaplus_attrs[] = {
__ATTR(actual_cpi, 0440, &dev_attr_actual_cpi.attr,
kovaplus_sysfs_show_actual_cpi, NULL), &dev_attr_firmware_version.attr,
__ATTR(firmware_version, 0440, &dev_attr_actual_profile.attr,
kovaplus_sysfs_show_firmware_version, NULL), &dev_attr_actual_sensitivity_x.attr,
__ATTR(actual_profile, 0660, &dev_attr_actual_sensitivity_y.attr,
kovaplus_sysfs_show_actual_profile, NULL,
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 bin_attribute kovaplus_bin_attributes[] = { static struct bin_attribute *kovaplus_bin_attributes[] = {
KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL), &bin_attr_control,
KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO), &bin_attr_info,
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), &bin_attr_profile_settings,
KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), &bin_attr_profile_buttons,
{ &bin_attr_profile1_settings,
.attr = { .name = "profile1_settings", .mode = 0440 }, &bin_attr_profile2_settings,
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, &bin_attr_profile3_settings,
.read = kovaplus_sysfs_read_profilex_settings, &bin_attr_profile4_settings,
.private = &profile_numbers[0] &bin_attr_profile5_settings,
}, &bin_attr_profile1_buttons,
{ &bin_attr_profile2_buttons,
.attr = { .name = "profile2_settings", .mode = 0440 }, &bin_attr_profile3_buttons,
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, &bin_attr_profile4_buttons,
.read = kovaplus_sysfs_read_profilex_settings, &bin_attr_profile5_buttons,
.private = &profile_numbers[1] NULL,
}, };
{
.attr = { .name = "profile3_settings", .mode = 0440 }, static const struct attribute_group kovaplus_group = {
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, .attrs = kovaplus_attrs,
.read = kovaplus_sysfs_read_profilex_settings, .bin_attrs = kovaplus_bin_attributes,
.private = &profile_numbers[2] };
},
{ static const struct attribute_group *kovaplus_groups[] = {
.attr = { .name = "profile4_settings", .mode = 0440 }, &kovaplus_group,
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, NULL,
.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 int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev, 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"); kovaplus_class = class_create(THIS_MODULE, "kovaplus");
if (IS_ERR(kovaplus_class)) if (IS_ERR(kovaplus_class))
return PTR_ERR(kovaplus_class); return PTR_ERR(kovaplus_class);
kovaplus_class->dev_attrs = kovaplus_attributes; kovaplus_class->dev_groups = kovaplus_groups;
kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
retval = hid_register_driver(&kovaplus_driver); retval = hid_register_driver(&kovaplus_driver);
if (retval) if (retval)

View File

@ -156,7 +156,8 @@ PYRA_SYSFS_W(thingy, THINGY) \
PYRA_SYSFS_R(thingy, THINGY) PYRA_SYSFS_R(thingy, THINGY)
#define PYRA_BIN_ATTRIBUTE_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = PYRA_SIZE_ ## THINGY, \ .size = PYRA_SIZE_ ## THINGY, \
.read = pyra_sysfs_read_ ## thingy, \ .read = pyra_sysfs_read_ ## thingy, \
@ -164,24 +165,25 @@ PYRA_SYSFS_R(thingy, THINGY)
} }
#define PYRA_BIN_ATTRIBUTE_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 }, \ .attr = { .name = #thingy, .mode = 0440 }, \
.size = PYRA_SIZE_ ## THINGY, \ .size = PYRA_SIZE_ ## THINGY, \
.read = pyra_sysfs_read_ ## thingy, \ .read = pyra_sysfs_read_ ## thingy, \
} }
#define PYRA_BIN_ATTRIBUTE_W(thingy, 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 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = PYRA_SIZE_ ## THINGY, \ .size = PYRA_SIZE_ ## THINGY, \
.write = pyra_sysfs_write_ ## thingy \ .write = pyra_sysfs_write_ ## thingy \
} }
PYRA_SYSFS_W(control, CONTROL) PYRA_BIN_ATTRIBUTE_W(control, CONTROL);
PYRA_SYSFS_RW(info, INFO) PYRA_BIN_ATTRIBUTE_RW(info, INFO);
PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS) PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS) PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
PYRA_SYSFS_R(settings, SETTINGS)
static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf, 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); 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, static ssize_t pyra_sysfs_write_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf, struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count) loff_t off, size_t count)
@ -258,6 +279,11 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
return PYRA_SIZE_SETTINGS; 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, static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
struct device_attribute *attr, char *buf) 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)); hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); 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, static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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, static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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[] = { static struct attribute *pyra_attrs[] = {
__ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL), &dev_attr_actual_cpi.attr,
__ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL), &dev_attr_actual_profile.attr,
__ATTR(firmware_version, 0440, &dev_attr_firmware_version.attr,
pyra_sysfs_show_firmware_version, NULL), &dev_attr_startup_profile.attr,
__ATTR(startup_profile, 0440, NULL,
pyra_sysfs_show_actual_profile, NULL),
__ATTR_NULL
}; };
static struct bin_attribute pyra_bin_attributes[] = { static struct bin_attribute *pyra_bin_attributes[] = {
PYRA_BIN_ATTRIBUTE_W(control, CONTROL), &bin_attr_control,
PYRA_BIN_ATTRIBUTE_RW(info, INFO), &bin_attr_info,
PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), &bin_attr_profile_settings,
PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), &bin_attr_profile_buttons,
PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS), &bin_attr_settings,
{ &bin_attr_profile1_settings,
.attr = { .name = "profile1_settings", .mode = 0440 }, &bin_attr_profile2_settings,
.size = PYRA_SIZE_PROFILE_SETTINGS, &bin_attr_profile3_settings,
.read = pyra_sysfs_read_profilex_settings, &bin_attr_profile4_settings,
.private = &profile_numbers[0] &bin_attr_profile5_settings,
}, &bin_attr_profile1_buttons,
{ &bin_attr_profile2_buttons,
.attr = { .name = "profile2_settings", .mode = 0440 }, &bin_attr_profile3_buttons,
.size = PYRA_SIZE_PROFILE_SETTINGS, &bin_attr_profile4_buttons,
.read = pyra_sysfs_read_profilex_settings, &bin_attr_profile5_buttons,
.private = &profile_numbers[1] NULL,
}, };
{
.attr = { .name = "profile3_settings", .mode = 0440 }, static const struct attribute_group pyra_group = {
.size = PYRA_SIZE_PROFILE_SETTINGS, .attrs = pyra_attrs,
.read = pyra_sysfs_read_profilex_settings, .bin_attrs = pyra_bin_attributes,
.private = &profile_numbers[2] };
},
{ static const struct attribute_group *pyra_groups[] = {
.attr = { .name = "profile4_settings", .mode = 0440 }, &pyra_group,
.size = PYRA_SIZE_PROFILE_SETTINGS, NULL,
.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 int pyra_init_pyra_device_struct(struct usb_device *usb_dev, 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"); pyra_class = class_create(THIS_MODULE, "pyra");
if (IS_ERR(pyra_class)) if (IS_ERR(pyra_class))
return PTR_ERR(pyra_class); return PTR_ERR(pyra_class);
pyra_class->dev_attrs = pyra_attributes; pyra_class->dev_groups = pyra_groups;
pyra_class->dev_bin_attrs = pyra_bin_attributes;
retval = hid_register_driver(&pyra_driver); retval = hid_register_driver(&pyra_driver);
if (retval) if (retval)

View File

@ -94,44 +94,48 @@ SAVU_SYSFS_W(thingy, THINGY) \
SAVU_SYSFS_R(thingy, THINGY) SAVU_SYSFS_R(thingy, THINGY)
#define SAVU_BIN_ATTRIBUTE_RW(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 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = SAVU_SIZE_ ## THINGY, \ .size = SAVU_SIZE_ ## THINGY, \
.read = savu_sysfs_read_ ## thingy, \ .read = savu_sysfs_read_ ## thingy, \
.write = savu_sysfs_write_ ## 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) \ #define SAVU_BIN_ATTRIBUTE_W(thingy, THINGY) \
{ \ SAVU_SYSFS_W(thingy, THINGY); \
static struct bin_attribute bin_attr_##thingy = { \
.attr = { .name = #thingy, .mode = 0220 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = SAVU_SIZE_ ## THINGY, \ .size = SAVU_SIZE_ ## THINGY, \
.write = savu_sysfs_write_ ## thingy \ .write = savu_sysfs_write_ ## thingy \
} }
SAVU_SYSFS_W(control, CONTROL) SAVU_BIN_ATTRIBUTE_W(control, CONTROL);
SAVU_SYSFS_RW(profile, PROFILE) SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE);
SAVU_SYSFS_RW(general, GENERAL) SAVU_BIN_ATTRIBUTE_RW(general, GENERAL);
SAVU_SYSFS_RW(buttons, BUTTONS) SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS);
SAVU_SYSFS_RW(macro, MACRO) SAVU_BIN_ATTRIBUTE_RW(macro, MACRO);
SAVU_SYSFS_RW(info, INFO) SAVU_BIN_ATTRIBUTE_RW(info, INFO);
SAVU_SYSFS_RW(sensor, SENSOR) SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR);
static struct bin_attribute savu_bin_attributes[] = { static struct bin_attribute *savu_bin_attributes[] = {
SAVU_BIN_ATTRIBUTE_W(control, CONTROL), &bin_attr_control,
SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE), &bin_attr_profile,
SAVU_BIN_ATTRIBUTE_RW(general, GENERAL), &bin_attr_general,
SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS), &bin_attr_buttons,
SAVU_BIN_ATTRIBUTE_RW(macro, MACRO), &bin_attr_macro,
SAVU_BIN_ATTRIBUTE_RW(info, INFO), &bin_attr_info,
SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR), &bin_attr_sensor,
__ATTR_NULL 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, 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"); savu_class = class_create(THIS_MODULE, "savu");
if (IS_ERR(savu_class)) if (IS_ERR(savu_class))
return PTR_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); retval = hid_register_driver(&savu_driver);
if (retval) if (retval)

View File

@ -639,16 +639,18 @@ EXPORT_SYMBOL(gameport_unregister_port);
* Gameport driver operations * 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); struct gameport_driver *driver = to_gameport_driver(drv);
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)"); return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
} }
static DRIVER_ATTR_RO(description);
static struct driver_attribute gameport_driver_attrs[] = { static struct attribute *gameport_driver_attrs[] = {
__ATTR(description, S_IRUGO, gameport_driver_show_description, NULL), &driver_attr_description.attr,
__ATTR_NULL NULL
}; };
ATTRIBUTE_GROUPS(gameport_driver);
static int gameport_driver_probe(struct device *dev) 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 = { static struct bus_type gameport_bus = {
.name = "gameport", .name = "gameport",
.dev_attrs = gameport_device_attrs, .dev_attrs = gameport_device_attrs,
.drv_attrs = gameport_driver_attrs, .drv_groups = gameport_driver_groups,
.match = gameport_bus_match, .match = gameport_bus_match,
.probe = gameport_driver_probe, .probe = gameport_driver_probe,
.remove = gameport_driver_remove, .remove = gameport_driver_remove,

View File

@ -732,19 +732,20 @@ EXPORT_SYMBOL(serio_unregister_child_port);
* Serio driver operations * 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); struct serio_driver *driver = to_serio_driver(drv);
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)"); 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); struct serio_driver *serio_drv = to_serio_driver(drv);
return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto"); 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); struct serio_driver *serio_drv = to_serio_driver(drv);
int retval; int retval;
@ -760,14 +761,14 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char
return retval; return retval;
} }
static DRIVER_ATTR_RW(bind_mode);
static struct attribute *serio_driver_attrs[] = {
static struct driver_attribute serio_driver_attrs[] = { &driver_attr_description.attr,
__ATTR(description, S_IRUGO, serio_driver_show_description, NULL), &driver_attr_bind_mode.attr,
__ATTR(bind_mode, S_IWUSR | S_IRUGO, NULL,
serio_driver_show_bind_mode, serio_driver_set_bind_mode),
__ATTR_NULL
}; };
ATTRIBUTE_GROUPS(serio_driver);
static int serio_driver_probe(struct device *dev) static int serio_driver_probe(struct device *dev)
{ {
@ -996,7 +997,7 @@ EXPORT_SYMBOL(serio_interrupt);
static struct bus_type serio_bus = { static struct bus_type serio_bus = {
.name = "serio", .name = "serio",
.dev_attrs = serio_device_attrs, .dev_attrs = serio_device_attrs,
.drv_attrs = serio_driver_attrs, .drv_groups = serio_driver_groups,
.match = serio_bus_match, .match = serio_bus_match,
.uevent = serio_uevent, .uevent = serio_uevent,
.probe = serio_driver_probe, .probe = serio_driver_probe,

View File

@ -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 */ /* nothing to do: the device is part of its parent's data structure */
} }
static ssize_t _show_id(struct device *dev, static ssize_t id_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
@ -46,9 +46,10 @@ static ssize_t _show_id(struct device *dev,
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d\n", mdev->id); return sprintf(buf, "%d\n", mdev->id);
} }
static DEVICE_ATTR_RO(id);
static ssize_t _show_nrbchan(struct device *dev, static ssize_t nrbchan_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
@ -56,9 +57,10 @@ static ssize_t _show_nrbchan(struct device *dev,
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d\n", mdev->nrbchan); return sprintf(buf, "%d\n", mdev->nrbchan);
} }
static DEVICE_ATTR_RO(nrbchan);
static ssize_t _show_d_protocols(struct device *dev, static ssize_t d_protocols_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
@ -66,9 +68,10 @@ static ssize_t _show_d_protocols(struct device *dev,
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d\n", mdev->Dprotocols); return sprintf(buf, "%d\n", mdev->Dprotocols);
} }
static DEVICE_ATTR_RO(d_protocols);
static ssize_t _show_b_protocols(struct device *dev, static ssize_t b_protocols_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
@ -76,9 +79,10 @@ static ssize_t _show_b_protocols(struct device *dev,
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
} }
static DEVICE_ATTR_RO(b_protocols);
static ssize_t _show_protocol(struct device *dev, static ssize_t protocol_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
@ -86,17 +90,19 @@ static ssize_t _show_protocol(struct device *dev,
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d\n", mdev->D.protocol); return sprintf(buf, "%d\n", mdev->D.protocol);
} }
static DEVICE_ATTR_RO(protocol);
static ssize_t _show_name(struct device *dev, static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
strcpy(buf, dev_name(dev)); strcpy(buf, dev_name(dev));
return strlen(buf); return strlen(buf);
} }
static DEVICE_ATTR_RO(name);
#if 0 /* hangs */ #if 0 /* hangs */
static ssize_t _set_name(struct device *dev, struct device_attribute *attr, static ssize_t name_set(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int err = 0; int err = 0;
char *out = kmalloc(count + 1, GFP_KERNEL); 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; return (err < 0) ? err : count;
} }
static DEVICE_ATTR_RW(name);
#endif #endif
static ssize_t _show_channelmap(struct device *dev, static ssize_t channelmap_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mISDNdevice *mdev = dev_to_mISDN(dev); struct mISDNdevice *mdev = dev_to_mISDN(dev);
char *bp = buf; char *bp = buf;
@ -127,18 +134,19 @@ static ssize_t _show_channelmap(struct device *dev,
return bp - buf; return bp - buf;
} }
static DEVICE_ATTR_RO(channelmap);
static struct device_attribute mISDN_dev_attrs[] = { static struct attribute *mISDN_attrs[] = {
__ATTR(id, S_IRUGO, _show_id, NULL), &dev_attr_id.attr,
__ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL), &dev_attr_d_protocols.attr,
__ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL), &dev_attr_b_protocols.attr,
__ATTR(protocol, S_IRUGO, _show_protocol, NULL), &dev_attr_protocol.attr,
__ATTR(channelmap, S_IRUGO, _show_channelmap, NULL), &dev_attr_channelmap.attr,
__ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL), &dev_attr_nrbchan.attr,
__ATTR(name, S_IRUGO, _show_name, NULL), &dev_attr_name.attr,
/* __ATTR(name, S_IRUGO | S_IWUSR, _show_name, _set_name), */ NULL,
{}
}; };
ATTRIBUTE_GROUPS(mISDN);
static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env) static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
@ -162,7 +170,7 @@ static struct class mISDN_class = {
.name = "mISDN", .name = "mISDN",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_uevent = mISDN_uevent, .dev_uevent = mISDN_uevent,
.dev_attrs = mISDN_dev_attrs, .dev_groups = mISDN_groups,
.dev_release = mISDN_dev_release, .dev_release = mISDN_dev_release,
.class_release = mISDN_class_release, .class_release = mISDN_class_release,
}; };

View File

@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev)
led_cdev->brightness = led_cdev->brightness_get(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 device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); 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); 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 device_attribute *attr, const char *buf, size_t size)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_classdev *led_cdev = dev_get_drvdata(dev);
@ -57,6 +57,7 @@ static ssize_t led_brightness_store(struct device *dev,
return size; return size;
} }
static DEVICE_ATTR_RW(brightness);
static ssize_t led_max_brightness_show(struct device *dev, static ssize_t led_max_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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 #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 #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) static void led_timer_function(unsigned long data)
@ -258,7 +280,7 @@ static int __init leds_init(void)
if (IS_ERR(leds_class)) if (IS_ERR(leds_class))
return PTR_ERR(leds_class); return PTR_ERR(leds_class);
leds_class->pm = &leds_class_dev_pm_ops; leds_class->pm = &leds_class_dev_pm_ops;
leds_class->dev_attrs = led_class_attrs; leds_class->dev_groups = led_groups;
return 0; return 0;
} }

View File

@ -38,24 +38,25 @@
* sysfs stuff * sysfs stuff
*/ */
static ssize_t show_index(struct device *cd, static ssize_t index_show(struct device *cd,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct video_device *vdev = to_video_device(cd); struct video_device *vdev = to_video_device(cd);
return sprintf(buf, "%i\n", vdev->index); return sprintf(buf, "%i\n", vdev->index);
} }
static DEVICE_ATTR_RO(index);
static ssize_t show_debug(struct device *cd, static ssize_t debug_show(struct device *cd,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct video_device *vdev = to_video_device(cd); struct video_device *vdev = to_video_device(cd);
return sprintf(buf, "%i\n", vdev->debug); return sprintf(buf, "%i\n", vdev->debug);
} }
static ssize_t set_debug(struct device *cd, struct device_attribute *attr, static ssize_t debug_store(struct device *cd, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
struct video_device *vdev = to_video_device(cd); struct video_device *vdev = to_video_device(cd);
int res = 0; int res = 0;
@ -68,21 +69,24 @@ static ssize_t set_debug(struct device *cd, struct device_attribute *attr,
vdev->debug = value; vdev->debug = value;
return len; 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 device_attribute *attr, char *buf)
{ {
struct video_device *vdev = to_video_device(cd); struct video_device *vdev = to_video_device(cd);
return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name); return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name);
} }
static DEVICE_ATTR_RO(name);
static struct device_attribute video_device_attrs[] = { static struct attribute *video_device_attrs[] = {
__ATTR(name, S_IRUGO, show_name, NULL), &dev_attr_name.attr,
__ATTR(debug, 0644, show_debug, set_debug), &dev_attr_debug.attr,
__ATTR(index, S_IRUGO, show_index, NULL), &dev_attr_index.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(video_device);
/* /*
* Active devices * Active devices
@ -217,7 +221,7 @@ static void v4l2_device_release(struct device *cd)
static struct class video_class = { static struct class video_class = {
.name = VIDEO_NAME, .name = VIDEO_NAME,
.dev_attrs = video_device_attrs, .dev_groups = video_device_groups,
}; };
struct video_device *video_devdata(struct file *file) struct video_device *video_devdata(struct file *file)

View File

@ -311,6 +311,7 @@ static ssize_t c2port_show_name(struct device *dev,
return sprintf(buf, "%s\n", c2dev->name); 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, static ssize_t c2port_show_flash_blocks_num(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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, static ssize_t c2port_show_flash_block_size(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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, static ssize_t c2port_show_flash_size(struct device *dev,
struct device_attribute *attr, char *buf) 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); 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, static ssize_t access_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct c2port_device *c2dev = dev_get_drvdata(dev); struct c2port_device *c2dev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", c2dev->access); return sprintf(buf, "%d\n", c2dev->access);
} }
static ssize_t c2port_store_access(struct device *dev, static ssize_t access_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct c2port_device *c2dev = dev_get_drvdata(dev); struct c2port_device *c2dev = dev_get_drvdata(dev);
struct c2port_ops *ops = c2dev->ops; struct c2port_ops *ops = c2dev->ops;
@ -375,6 +378,7 @@ static ssize_t c2port_store_access(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR_RW(access);
static ssize_t c2port_store_reset(struct device *dev, static ssize_t c2port_store_reset(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
@ -395,6 +399,7 @@ static ssize_t c2port_store_reset(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(reset, 0200, NULL, c2port_store_reset);
static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf) 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; 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) 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; return ret;
} }
static DEVICE_ATTR(rev_id, 0444, c2port_show_rev_id, NULL);
static ssize_t c2port_show_flash_access(struct device *dev, static ssize_t c2port_show_flash_access(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
@ -536,6 +543,8 @@ static ssize_t c2port_store_flash_access(struct device *dev,
return count; 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) 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; return count;
} }
static DEVICE_ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase);
static ssize_t __c2port_read_flash_data(struct c2port_device *dev, static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
char *buffer, loff_t offset, size_t count) 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; 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 * Class attributes
*/ */
static struct attribute *c2port_attrs[] = {
static struct device_attribute c2port_attrs[] = { &dev_attr_name.attr,
__ATTR(name, 0444, c2port_show_name, NULL), &dev_attr_flash_blocks_num.attr,
__ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL), &dev_attr_flash_block_size.attr,
__ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL), &dev_attr_flash_size.attr,
__ATTR(flash_size, 0444, c2port_show_flash_size, NULL), &dev_attr_access.attr,
__ATTR(access, 0644, c2port_show_access, c2port_store_access), &dev_attr_reset.attr,
__ATTR(reset, 0200, NULL, c2port_store_reset), &dev_attr_dev_id.attr,
__ATTR(dev_id, 0444, c2port_show_dev_id, NULL), &dev_attr_rev_id.attr,
__ATTR(rev_id, 0444, c2port_show_rev_id, NULL), &dev_attr_flash_access.attr,
&dev_attr_flash_erase.attr,
__ATTR(flash_access, 0644, c2port_show_flash_access, NULL,
c2port_store_flash_access),
__ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
__ATTR_NULL,
}; };
static struct bin_attribute c2port_bin_attrs = { static struct bin_attribute *c2port_bin_attrs[] = {
.attr = { &bin_attr_flash_data,
.name = "flash_data", NULL,
.mode = 0644 };
},
.read = c2port_read_flash_data, static const struct attribute_group c2port_group = {
.write = c2port_write_flash_data, .attrs = c2port_attrs,
/* .size is computed at run-time */ .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; goto error_idr_alloc;
c2dev->id = ret; c2dev->id = ret;
bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
"c2port%d", c2dev->id); "c2port%d", c2dev->id);
if (unlikely(IS_ERR(c2dev->dev))) { if (unlikely(IS_ERR(c2dev->dev))) {
@ -919,12 +936,6 @@ struct c2port_device *c2port_device_register(char *name,
c2dev->ops = ops; c2dev->ops = ops;
mutex_init(&c2dev->mutex); 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 */ /* By default C2 port access is off */
c2dev->access = c2dev->flash_access = 0; c2dev->access = c2dev->flash_access = 0;
ops->access(c2dev, 0); ops->access(c2dev, 0);
@ -937,9 +948,6 @@ struct c2port_device *c2port_device_register(char *name,
return c2dev; return c2dev;
error_device_create_bin_file:
device_destroy(c2port_class, 0);
error_device_create: error_device_create:
spin_lock_irq(&c2port_idr_lock); spin_lock_irq(&c2port_idr_lock);
idr_remove(&c2port_idr, c2dev->id); 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); 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); spin_lock_irq(&c2port_idr_lock);
idr_remove(&c2port_idr, c2dev->id); idr_remove(&c2port_idr, c2dev->id);
spin_unlock_irq(&c2port_idr_lock); 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"); printk(KERN_ERR "c2port: failed to allocate class\n");
return PTR_ERR(c2port_class); return PTR_ERR(c2port_class);
} }
c2port_class->dev_attrs = c2port_attrs; c2port_class->dev_groups = c2port_groups;
return 0; return 0;
} }

View File

@ -239,7 +239,7 @@ static void enclosure_component_release(struct device *dev)
put_device(dev->parent); 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 * 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); dev_set_name(cdev, "%u", number);
cdev->release = enclosure_component_release; cdev->release = enclosure_component_release;
cdev->groups = enclosure_groups; cdev->groups = enclosure_component_groups;
err = device_register(cdev); err = device_register(cdev);
if (err) { if (err) {
@ -365,25 +365,26 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
* sysfs pieces below * sysfs pieces below
*/ */
static ssize_t enclosure_show_components(struct device *cdev, static ssize_t components_show(struct device *cdev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
struct enclosure_device *edev = to_enclosure_device(cdev); struct enclosure_device *edev = to_enclosure_device(cdev);
return snprintf(buf, 40, "%d\n", edev->components); return snprintf(buf, 40, "%d\n", edev->components);
} }
static DEVICE_ATTR_RO(components);
static struct device_attribute enclosure_attrs[] = { static struct attribute *enclosure_class_attrs[] = {
__ATTR(components, S_IRUGO, enclosure_show_components, NULL), &dev_attr_components.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(enclosure_class);
static struct class enclosure_class = { static struct class enclosure_class = {
.name = "enclosure", .name = "enclosure",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_release = enclosure_release, .dev_release = enclosure_release,
.dev_attrs = enclosure_attrs, .dev_groups = enclosure_class_groups,
}; };
static const char *const enclosure_status [] = { static const char *const enclosure_status [] = {
@ -536,15 +537,7 @@ static struct attribute *enclosure_component_attrs[] = {
&dev_attr_type.attr, &dev_attr_type.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(enclosure_component);
static struct attribute_group enclosure_group = {
.attrs = enclosure_component_attrs,
};
static const struct attribute_group *enclosure_groups[] = {
&enclosure_group,
NULL
};
static int __init enclosure_init(void) static int __init enclosure_init(void)
{ {

View File

@ -108,11 +108,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
} }
static DEVICE_ATTR_RO(modalias);
static struct device_attribute mei_cl_dev_attrs[] = { static struct attribute *mei_cl_dev_attrs[] = {
__ATTR_RO(modalias), &dev_attr_modalias.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(mei_cl_dev);
static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env) 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 = { static struct bus_type mei_cl_bus_type = {
.name = "mei", .name = "mei",
.dev_attrs = mei_cl_dev_attrs, .dev_groups = mei_cl_dev_groups,
.match = mei_cl_device_match, .match = mei_cl_device_match,
.probe = mei_cl_device_probe, .probe = mei_cl_device_probe,
.remove = mei_cl_device_remove, .remove = mei_cl_device_remove,

View File

@ -9478,7 +9478,7 @@ static struct niu_parent *niu_new_parent(struct niu *np,
if (IS_ERR(plat_dev)) if (IS_ERR(plat_dev))
return NULL; 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, int err = device_create_file(&plat_dev->dev,
&niu_parent_attributes[i]); &niu_parent_attributes[i]);
if (err) if (err)

View File

@ -693,11 +693,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "wmi:%s\n", guid_string); return sprintf(buf, "wmi:%s\n", guid_string);
} }
static DEVICE_ATTR_RO(modalias);
static struct device_attribute wmi_dev_attrs[] = { static struct attribute *wmi_attrs[] = {
__ATTR_RO(modalias), &dev_attr_modalias.attr,
__ATTR_NULL NULL,
}; };
ATTRIBUTE_GROUPS(wmi);
static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
@ -732,7 +734,7 @@ static struct class wmi_class = {
.name = "wmi", .name = "wmi",
.dev_release = wmi_dev_free, .dev_release = wmi_dev_free,
.dev_uevent = wmi_dev_uevent, .dev_uevent = wmi_dev_uevent,
.dev_attrs = wmi_dev_attrs, .dev_groups = wmi_groups,
}; };
static int wmi_create_device(const struct guid_block *gblock, static int wmi_create_device(const struct guid_block *gblock,

View File

@ -406,7 +406,7 @@ static int __init pps_init(void)
pr_err("failed to allocate class\n"); pr_err("failed to allocate class\n");
return PTR_ERR(pps_class); 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"); err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
if (err < 0) { if (err < 0) {

View File

@ -29,8 +29,8 @@
* Attribute functions * Attribute functions
*/ */
static ssize_t pps_show_assert(struct device *dev, static ssize_t assert_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); 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, (long long) pps->assert_tu.sec, pps->assert_tu.nsec,
pps->assert_sequence); pps->assert_sequence);
} }
static DEVICE_ATTR_RO(assert);
static ssize_t pps_show_clear(struct device *dev, static ssize_t clear_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); 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, (long long) pps->clear_tu.sec, pps->clear_tu.nsec,
pps->clear_sequence); pps->clear_sequence);
} }
static DEVICE_ATTR_RO(clear);
static ssize_t pps_show_mode(struct device *dev, static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); struct pps_device *pps = dev_get_drvdata(dev);
return sprintf(buf, "%4x\n", pps->info.mode); return sprintf(buf, "%4x\n", pps->info.mode);
} }
static DEVICE_ATTR_RO(mode);
static ssize_t pps_show_echo(struct device *dev, static ssize_t echo_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); struct pps_device *pps = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", !!pps->info.echo); return sprintf(buf, "%d\n", !!pps->info.echo);
} }
static DEVICE_ATTR_RO(echo);
static ssize_t pps_show_name(struct device *dev, static ssize_t name_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); struct pps_device *pps = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", pps->info.name); return sprintf(buf, "%s\n", pps->info.name);
} }
static DEVICE_ATTR_RO(name);
static ssize_t pps_show_path(struct device *dev, static ssize_t path_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct pps_device *pps = dev_get_drvdata(dev); struct pps_device *pps = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", pps->info.path); return sprintf(buf, "%s\n", pps->info.path);
} }
static DEVICE_ATTR_RO(path);
struct device_attribute pps_attrs[] = { static struct attribute *pps_attrs[] = {
__ATTR(assert, S_IRUGO, pps_show_assert, NULL), &dev_attr_assert.attr,
__ATTR(clear, S_IRUGO, pps_show_clear, NULL), &dev_attr_clear.attr,
__ATTR(mode, S_IRUGO, pps_show_mode, NULL), &dev_attr_mode.attr,
__ATTR(echo, S_IRUGO, pps_show_echo, NULL), &dev_attr_echo.attr,
__ATTR(name, S_IRUGO, pps_show_name, NULL), &dev_attr_name.attr,
__ATTR(path, S_IRUGO, pps_show_path, NULL), &dev_attr_path.attr,
__ATTR_NULL, NULL,
};
static const struct attribute_group pps_group = {
.attrs = pps_attrs,
};
const struct attribute_group *pps_groups[] = {
&pps_group,
NULL,
}; };

View File

@ -330,7 +330,7 @@ static int __init ptp_init(void)
goto no_region; goto no_region;
} }
ptp_class->dev_attrs = ptp_dev_attrs; ptp_class->dev_groups = ptp_groups;
pr_info("PTP clock support registered\n"); pr_info("PTP clock support registered\n");
return 0; return 0;

View File

@ -84,7 +84,7 @@ uint ptp_poll(struct posix_clock *pc,
* see ptp_sysfs.c * 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); int ptp_cleanup_sysfs(struct ptp_clock *ptp);

View File

@ -27,36 +27,43 @@ static ssize_t clock_name_show(struct device *dev,
struct ptp_clock *ptp = dev_get_drvdata(dev); struct ptp_clock *ptp = dev_get_drvdata(dev);
return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name); 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) \ #define PTP_SHOW_INT(name, var) \
static ssize_t name##_show(struct device *dev, \ static ssize_t var##_show(struct device *dev, \
struct device_attribute *attr, char *page) \ struct device_attribute *attr, char *page) \
{ \ { \
struct ptp_clock *ptp = dev_get_drvdata(dev); \ 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(max_adjustment, max_adj);
PTP_SHOW_INT(n_alarm); PTP_SHOW_INT(n_alarms, n_alarm);
PTP_SHOW_INT(n_ext_ts); PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
PTP_SHOW_INT(n_per_out); PTP_SHOW_INT(n_periodic_outputs, n_per_out);
PTP_SHOW_INT(pps); PTP_SHOW_INT(pps_available, pps);
#define PTP_RO_ATTR(_var, _name) { \ static struct attribute *ptp_attrs[] = {
.attr = { .name = __stringify(_name), .mode = 0444 }, \ &dev_attr_clock_name.attr,
.show = _var##_show, \ &dev_attr_max_adjustment.attr,
} &dev_attr_n_alarms.attr,
&dev_attr_n_external_timestamps.attr,
struct device_attribute ptp_dev_attrs[] = { &dev_attr_n_periodic_outputs.attr,
PTP_RO_ATTR(clock_name, clock_name), &dev_attr_pps_available.attr,
PTP_RO_ATTR(max_adj, max_adjustment), NULL,
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 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, static ssize_t extts_enable_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)

View File

@ -25,15 +25,14 @@
*/ */
static ssize_t static ssize_t
rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, name_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%s\n", to_rtc_device(dev)->name); return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
} }
static DEVICE_ATTR_RO(name);
static ssize_t static ssize_t
rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, date_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
ssize_t retval; ssize_t retval;
struct rtc_time tm; struct rtc_time tm;
@ -46,10 +45,10 @@ rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
return retval; return retval;
} }
static DEVICE_ATTR_RO(date);
static ssize_t static ssize_t
rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, time_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
ssize_t retval; ssize_t retval;
struct rtc_time tm; struct rtc_time tm;
@ -62,10 +61,10 @@ rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
return retval; return retval;
} }
static DEVICE_ATTR_RO(time);
static ssize_t static ssize_t
rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
ssize_t retval; ssize_t retval;
struct rtc_time tm; struct rtc_time tm;
@ -79,16 +78,16 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
return retval; return retval;
} }
static DEVICE_ATTR_RO(since_epoch);
static ssize_t static ssize_t
rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
} }
static ssize_t 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) const char *buf, size_t n)
{ {
struct rtc_device *rtc = to_rtc_device(dev); 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; return n;
} }
static DEVICE_ATTR_RW(max_user_freq);
/** /**
* rtc_sysfs_show_hctosys - indicate if the given RTC set the system time * 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. * boot or resume event.
*/ */
static ssize_t static ssize_t
rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
#ifdef CONFIG_RTC_HCTOSYS_DEVICE #ifdef CONFIG_RTC_HCTOSYS_DEVICE
if (rtc_hctosys_ret == 0 && if (rtc_hctosys_ret == 0 &&
@ -121,17 +120,18 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
#endif #endif
return sprintf(buf, "0\n"); return sprintf(buf, "0\n");
} }
static DEVICE_ATTR_RO(hctosys);
static struct device_attribute rtc_attrs[] = { static struct attribute *rtc_attrs[] = {
__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), &dev_attr_name.attr,
__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), &dev_attr_date.attr,
__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), &dev_attr_time.attr,
__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), &dev_attr_since_epoch.attr,
__ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, &dev_attr_max_user_freq.attr,
rtc_sysfs_set_max_user_freq), &dev_attr_hctosys.attr,
__ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), NULL,
{ },
}; };
ATTRIBUTE_GROUPS(rtc);
static ssize_t static ssize_t
rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, 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) void __init rtc_sysfs_init(struct class *rtc_class)
{ {
rtc_class->dev_attrs = rtc_attrs; rtc_class->dev_groups = rtc_groups;
} }

View File

@ -107,6 +107,7 @@ static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
class_dev); class_dev);
return sprintf(buf, "%s\n", ould->odi.osdname); 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, static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
char *buf) 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); memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
return ould->odi.systemid_len; return ould->odi.systemid_len;
} }
static DEVICE_ATTR_RO(systemid);
static struct device_attribute osd_uld_attrs[] = { static struct attribute *osd_uld_attrs[] = {
__ATTR(osdname, S_IRUGO, osdname_show, NULL), &dev_attr_osdname.attr,
__ATTR(systemid, S_IRUGO, systemid_show, NULL), &dev_attr_systemid.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(osd_uld);
static struct class osd_uld_class = { static struct class osd_uld_class = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "scsi_osd", .name = "scsi_osd",
.dev_attrs = osd_uld_attrs, .dev_groups = osd_uld_groups,
}; };
/* /*

View File

@ -262,7 +262,7 @@ static int resize_async_buffer(struct comedi_device *dev,
/* sysfs attribute files */ /* 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) struct device_attribute *attr, char *buf)
{ {
unsigned int minor = MINOR(csdev->devt); 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); 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, struct device_attribute *attr,
const char *buf, size_t count) 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; 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) struct device_attribute *attr, char *buf)
{ {
unsigned int minor = MINOR(csdev->devt); 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); 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, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
@ -367,8 +368,9 @@ static ssize_t store_read_buffer_kb(struct device *csdev,
return err ? err : count; 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, struct device_attribute *attr,
char *buf) 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); 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, struct device_attribute *attr,
const char *buf, size_t count) 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; 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) struct device_attribute *attr, char *buf)
{ {
unsigned int minor = MINOR(csdev->devt); 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); 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, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
@ -474,18 +477,16 @@ static ssize_t store_write_buffer_kb(struct device *csdev,
return err ? err : count; return err ? err : count;
} }
static DEVICE_ATTR_RW(write_buffer_kb);
static struct device_attribute comedi_dev_attrs[] = { static struct attribute *comedi_dev_attrs[] = {
__ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR, &dev_attr_max_read_buffer_kb.attr,
show_max_read_buffer_kb, store_max_read_buffer_kb), &dev_attr_read_buffer_kb.attr,
__ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP, &dev_attr_max_write_buffer_kb.attr,
show_read_buffer_kb, store_read_buffer_kb), &dev_attr_write_buffer_kb.attr,
__ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR, NULL,
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
}; };
ATTRIBUTE_GROUPS(comedi_dev);
static void comedi_set_subdevice_runflags(struct comedi_subdevice *s, static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
unsigned mask, unsigned bits) unsigned mask, unsigned bits)
@ -2564,7 +2565,7 @@ static int __init comedi_init(void)
return PTR_ERR(comedi_class); return PTR_ERR(comedi_class);
} }
comedi_class->dev_attrs = comedi_dev_attrs; comedi_class->dev_groups = comedi_dev_groups;
/* XXX requires /proc interface */ /* XXX requires /proc interface */
comedi_proc_init(); comedi_proc_init();

View File

@ -223,38 +223,42 @@ static struct kobj_type portio_attr_type = {
.default_attrs = portio_attrs, .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 device_attribute *attr, char *buf)
{ {
struct uio_device *idev = dev_get_drvdata(dev); struct uio_device *idev = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", idev->info->name); 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 device_attribute *attr, char *buf)
{ {
struct uio_device *idev = dev_get_drvdata(dev); struct uio_device *idev = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", idev->info->version); 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 device_attribute *attr, char *buf)
{ {
struct uio_device *idev = dev_get_drvdata(dev); struct uio_device *idev = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event)); return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
} }
static DEVICE_ATTR_RO(event);
static struct device_attribute uio_class_attributes[] = { static struct attribute *uio_attrs[] = {
__ATTR(name, S_IRUGO, show_name, NULL), &dev_attr_name.attr,
__ATTR(version, S_IRUGO, show_version, NULL), &dev_attr_version.attr,
__ATTR(event, S_IRUGO, show_event, NULL), &dev_attr_event.attr,
{} NULL,
}; };
ATTRIBUTE_GROUPS(uio);
/* UIO class infrastructure */ /* UIO class infrastructure */
static struct class uio_class = { static struct class uio_class = {
.name = "uio", .name = "uio",
.dev_attrs = uio_class_attributes, .dev_groups = uio_groups,
}; };
/* /*

View File

@ -121,7 +121,7 @@ static int usb_serial_device_remove(struct device *dev)
return retval; 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) const char *buf, size_t count)
{ {
struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); 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; 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); struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
return usb_show_dynids(&usb_drv->dynids, buf); return usb_show_dynids(&usb_drv->dynids, buf);
} }
static DRIVER_ATTR_RW(new_id);
static struct driver_attribute drv_attrs[] = { static struct attribute *usb_serial_drv_attrs[] = {
__ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id), &driver_attr_new_id.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(usb_serial_drv);
static void free_dynids(struct usb_serial_driver *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, .match = usb_serial_device_match,
.probe = usb_serial_device_probe, .probe = usb_serial_device_probe,
.remove = usb_serial_device_remove, .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) int usb_serial_bus_register(struct usb_serial_driver *driver)

View File

@ -103,16 +103,16 @@ static void backlight_generate_event(struct backlight_device *bd,
sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness"); sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
} }
static ssize_t backlight_show_power(struct device *dev, static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct backlight_device *bd = to_backlight_device(dev); struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%d\n", bd->props.power); return sprintf(buf, "%d\n", bd->props.power);
} }
static ssize_t backlight_store_power(struct device *dev, static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count) const char *buf, size_t count)
{ {
int rc; int rc;
struct backlight_device *bd = to_backlight_device(dev); struct backlight_device *bd = to_backlight_device(dev);
@ -136,8 +136,9 @@ static ssize_t backlight_store_power(struct device *dev,
return rc; 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 device_attribute *attr, char *buf)
{ {
struct backlight_device *bd = to_backlight_device(dev); 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); 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) struct device_attribute *attr, const char *buf, size_t count)
{ {
int rc; int rc;
@ -175,24 +176,27 @@ static ssize_t backlight_store_brightness(struct device *dev,
return rc; return rc;
} }
static DEVICE_ATTR_RW(brightness);
static ssize_t backlight_show_type(struct device *dev, static ssize_t type_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct backlight_device *bd = to_backlight_device(dev); struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%s\n", backlight_types[bd->props.type]); 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 device_attribute *attr, char *buf)
{ {
struct backlight_device *bd = to_backlight_device(dev); struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%d\n", bd->props.max_brightness); 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) struct device_attribute *attr, char *buf)
{ {
int rc = -ENXIO; int rc = -ENXIO;
@ -205,6 +209,7 @@ static ssize_t backlight_show_actual_brightness(struct device *dev,
return rc; return rc;
} }
static DEVICE_ATTR_RO(actual_brightness);
static struct class *backlight_class; static struct class *backlight_class;
@ -247,16 +252,15 @@ static void bl_device_release(struct device *dev)
kfree(bd); kfree(bd);
} }
static struct device_attribute bl_device_attributes[] = { static struct attribute *bl_device_attrs[] = {
__ATTR(bl_power, 0644, backlight_show_power, backlight_store_power), &dev_attr_bl_power.attr,
__ATTR(brightness, 0644, backlight_show_brightness, &dev_attr_brightness.attr,
backlight_store_brightness), &dev_attr_actual_brightness.attr,
__ATTR(actual_brightness, 0444, backlight_show_actual_brightness, &dev_attr_max_brightness.attr,
NULL), &dev_attr_type.attr,
__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), NULL,
__ATTR(type, 0444, backlight_show_type, NULL),
__ATTR_NULL,
}; };
ATTRIBUTE_GROUPS(bl_device);
/** /**
* backlight_force_update - tell the backlight subsystem that hardware state * 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); 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; backlight_class->pm = &backlight_class_dev_pm_ops;
return 0; return 0;
} }

View File

@ -89,7 +89,7 @@ static inline void lcd_unregister_fb(struct lcd_device *ld)
} }
#endif /* CONFIG_FB */ #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) char *buf)
{ {
int rc; int rc;
@ -105,7 +105,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
return rc; 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) struct device_attribute *attr, const char *buf, size_t count)
{ {
int rc; int rc;
@ -128,8 +128,9 @@ static ssize_t lcd_store_power(struct device *dev,
return rc; 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) struct device_attribute *attr, char *buf)
{ {
int rc = -ENXIO; int rc = -ENXIO;
@ -143,7 +144,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
return rc; 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) struct device_attribute *attr, const char *buf, size_t count)
{ {
int rc; int rc;
@ -166,14 +167,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
return rc; 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 device_attribute *attr, char *buf)
{ {
struct lcd_device *ld = to_lcd_device(dev); struct lcd_device *ld = to_lcd_device(dev);
return sprintf(buf, "%d\n", ld->props.max_contrast); return sprintf(buf, "%d\n", ld->props.max_contrast);
} }
static DEVICE_ATTR_RO(max_contrast);
static struct class *lcd_class; static struct class *lcd_class;
@ -183,12 +186,13 @@ static void lcd_device_release(struct device *dev)
kfree(ld); kfree(ld);
} }
static struct device_attribute lcd_device_attributes[] = { static struct attribute *lcd_device_attrs[] = {
__ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power), &dev_attr_lcd_power.attr,
__ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), &dev_attr_contrast.attr,
__ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), &dev_attr_max_contrast.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(lcd_device);
/** /**
* lcd_device_register - register a new object of lcd_device class. * 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); return PTR_ERR(lcd_class);
} }
lcd_class->dev_attrs = lcd_device_attributes; lcd_class->dev_groups = lcd_device_groups;
return 0; return 0;
} }

View File

@ -72,10 +72,9 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
return 1; return 1;
} }
static ssize_t w1_f29_read_state( static ssize_t state_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off,
struct bin_attribute *bin_attr, size_t count)
char *buf, loff_t off, size_t count)
{ {
dev_dbg(&kobj_to_w1_slave(kobj)->dev, dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", "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); return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
} }
static ssize_t w1_f29_read_output( static ssize_t output_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
dev_dbg(&kobj_to_w1_slave(kobj)->dev, dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", "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); W1_F29_REG_OUTPUT_LATCH_STATE, buf);
} }
static ssize_t w1_f29_read_activity( static ssize_t activity_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
dev_dbg(&kobj_to_w1_slave(kobj)->dev, dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", "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); W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
} }
static ssize_t w1_f29_read_cond_search_mask( static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
dev_dbg(&kobj_to_w1_slave(kobj)->dev, dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", "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); W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
} }
static ssize_t w1_f29_read_cond_search_polarity( static ssize_t cond_search_polarity_read(struct file *filp,
struct file *filp, struct kobject *kobj, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
if (count != 1 || off != 0) if (count != 1 || off != 0)
return -EFAULT; return -EFAULT;
@ -138,10 +134,9 @@ static ssize_t w1_f29_read_cond_search_polarity(
W1_F29_REG_COND_SEARCH_POL_SELECT, buf); W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
} }
static ssize_t w1_f29_read_status_control( static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
if (count != 1 || off != 0) if (count != 1 || off != 0)
return -EFAULT; return -EFAULT;
@ -149,13 +144,9 @@ static ssize_t w1_f29_read_status_control(
W1_F29_REG_CONTROL_AND_STATUS, buf); W1_F29_REG_CONTROL_AND_STATUS, buf);
} }
static ssize_t output_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
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)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
u8 w1_buf[3]; u8 w1_buf[3];
@ -224,10 +215,9 @@ error:
/** /**
* Writing to the activity file resets the activity latches. * Writing to the activity file resets the activity latches.
*/ */
static ssize_t w1_f29_write_activity( static ssize_t activity_write(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
unsigned int retries = W1_F29_RETRIES; unsigned int retries = W1_F29_RETRIES;
@ -255,13 +245,9 @@ error:
return -EIO; return -EIO;
} }
static ssize_t w1_f29_write_status_control( static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
struct file *filp, struct bin_attribute *bin_attr, char *buf,
struct kobject *kobj, loff_t off, size_t count)
struct bin_attribute *bin_attr,
char *buf,
loff_t off,
size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
u8 w1_buf[4]; u8 w1_buf[4];
@ -330,91 +316,35 @@ out:
return res; return res;
} }
static struct bin_attribute w1_f29_sysfs_bin_files[] = { static BIN_ATTR_RO(state, 1);
{ static BIN_ATTR_RW(output, 1);
.attr = { static BIN_ATTR_RW(activity, 1);
.name = "state", static BIN_ATTR_RO(cond_search_mask, 1);
.mode = S_IRUGO, static BIN_ATTR_RO(cond_search_polarity, 1);
}, static BIN_ATTR_RW(status_control, 1);
.size = 1,
.read = w1_f29_read_state, static struct bin_attribute *w1_f29_bin_attrs[] = {
}, &bin_attr_state,
{ &bin_attr_output,
.attr = { &bin_attr_activity,
.name = "output", &bin_attr_cond_search_mask,
.mode = S_IRUGO | S_IWUSR | S_IWGRP, &bin_attr_cond_search_polarity,
}, &bin_attr_status_control,
.size = 1, NULL,
.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 int w1_f29_add_slave(struct w1_slave *sl) static const struct attribute_group w1_f29_group = {
{ .bin_attrs = w1_f29_bin_attrs,
int err = 0; };
int i;
err = w1_f29_disable_test_mode(sl); static const struct attribute_group *w1_f29_groups[] = {
if (err) &w1_f29_group,
return err; NULL,
};
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 struct w1_family_ops w1_f29_fops = { static struct w1_family_ops w1_f29_fops = {
.add_slave = w1_f29_add_slave, .add_slave = w1_f29_disable_test_mode,
.remove_slave = w1_f29_remove_slave, .groups = w1_f29_groups,
}; };
static struct w1_family w1_family_29 = { static struct w1_family w1_family_29 = {

View File

@ -30,10 +30,9 @@ MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2413));
#define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A
#define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA #define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA
static ssize_t w1_f3a_read_state( static ssize_t state_read(struct file *filp, struct kobject *kobj,
struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off,
struct bin_attribute *bin_attr, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
dev_dbg(&sl->dev, dev_dbg(&sl->dev,
@ -66,10 +65,11 @@ static ssize_t w1_f3a_read_state(
return 1; return 1;
} }
static ssize_t w1_f3a_write_output( static BIN_ATTR_RO(state, 1);
struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, static ssize_t output_write(struct file *filp, struct kobject *kobj,
char *buf, loff_t off, size_t count) struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
u8 w1_buf[3]; u8 w1_buf[3];
@ -110,53 +110,25 @@ error:
return -EIO; return -EIO;
} }
#define NB_SYSFS_BIN_FILES 2 static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
static struct bin_attribute w1_f3a_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
{ static struct bin_attribute *w1_f3a_bin_attrs[] = {
.attr = { &bin_attr_state,
.name = "state", &bin_attr_output,
.mode = S_IRUGO, NULL,
},
.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 int w1_f3a_add_slave(struct w1_slave *sl) static const struct attribute_group w1_f3a_group = {
{ .bin_attrs = w1_f3a_bin_attrs,
int err = 0; };
int i;
for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) static const struct attribute_group *w1_f3a_groups[] = {
err = sysfs_create_bin_file( &w1_f3a_group,
&sl->dev.kobj, NULL,
&(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 struct w1_family_ops w1_f3a_fops = { static struct w1_family_ops w1_f3a_fops = {
.add_slave = w1_f3a_add_slave, .groups = w1_f3a_groups,
.remove_slave = w1_f3a_remove_slave,
}; };
static struct w1_family w1_family_3a = { static struct w1_family w1_family_3a = {

View File

@ -40,14 +40,8 @@
#define COUNTER_COUNT 4 #define COUNTER_COUNT 4
#define READ_BYTE_COUNT 42 #define READ_BYTE_COUNT 42
static ssize_t w1_counter_read(struct device *device, static ssize_t w1_slave_show(struct device *device,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *out_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)
{ {
struct w1_slave *sl = dev_to_w1_slave(device); struct w1_slave *sl = dev_to_w1_slave(device);
struct w1_master *dev = sl->master; struct w1_master *dev = sl->master;
@ -128,19 +122,16 @@ static ssize_t w1_counter_read(struct device *device,
return PAGE_SIZE - c; return PAGE_SIZE - c;
} }
static int w1_f1d_add_slave(struct w1_slave *sl) static DEVICE_ATTR_RO(w1_slave);
{
return device_create_file(&sl->dev, &w1_counter_attr);
}
static void w1_f1d_remove_slave(struct w1_slave *sl) static struct attribute *w1_f1d_attrs[] = {
{ &dev_attr_w1_slave.attr,
device_remove_file(&sl->dev, &w1_counter_attr); NULL,
} };
ATTRIBUTE_GROUPS(w1_f1d);
static struct w1_family_ops w1_f1d_fops = { static struct w1_family_ops w1_f1d_fops = {
.add_slave = w1_f1d_add_slave, .groups = w1_f1d_groups,
.remove_slave = w1_f1d_remove_slave,
}; };
static struct w1_family w1_family_1d = { static struct w1_family w1_family_1d = {

View File

@ -96,9 +96,9 @@ static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
return -1; return -1;
} }
static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
int todo = count; int todo = count;
@ -202,9 +202,9 @@ retry:
return 0; return 0;
} }
static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
int addr, len; int addr, len;
@ -264,29 +264,24 @@ out_up:
return count; return count;
} }
static struct bin_attribute w1_f2d_bin_attr = { static BIN_ATTR_RW(eeprom, W1_F2D_EEPROM_SIZE);
.attr = {
.name = "eeprom", static struct bin_attribute *w1_f2d_bin_attrs[] = {
.mode = S_IRUGO | S_IWUSR, &bin_attr_eeprom,
}, NULL,
.size = W1_F2D_EEPROM_SIZE,
.read = w1_f2d_read_bin,
.write = w1_f2d_write_bin,
}; };
static int w1_f2d_add_slave(struct w1_slave *sl) static const struct attribute_group w1_f2d_group = {
{ .bin_attrs = w1_f2d_bin_attrs,
return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr); };
}
static void w1_f2d_remove_slave(struct w1_slave *sl) static const struct attribute_group *w1_f2d_groups[] = {
{ &w1_f2d_group,
sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr); NULL,
} };
static struct w1_family_ops w1_f2d_fops = { static struct w1_family_ops w1_f2d_fops = {
.add_slave = w1_f2d_add_slave, .groups = w1_f2d_groups,
.remove_slave = w1_f2d_remove_slave,
}; };
static struct w1_family w1_family_2d = { static struct w1_family w1_family_2d = {

View File

@ -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 */ #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
#ifdef CONFIG_W1_SLAVE_DS2433_CRC #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; return 0;
} }
static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
int addr, len, idx; int addr, len, idx;
@ -257,19 +257,24 @@ out_up:
return count; return count;
} }
static struct bin_attribute w1_f23_bin_attr = { static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
.attr = {
.name = "eeprom", static struct bin_attribute *w1_f23_bin_attributes[] = {
.mode = S_IRUGO | S_IWUSR, &bin_attr_eeprom,
}, NULL,
.size = W1_EEPROM_SIZE, };
.read = w1_f23_read_bin,
.write = w1_f23_write_bin, 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) static int w1_f23_add_slave(struct w1_slave *sl)
{ {
int err;
#ifdef CONFIG_W1_SLAVE_DS2433_CRC #ifdef CONFIG_W1_SLAVE_DS2433_CRC
struct w1_f23_data *data; struct w1_f23_data *data;
@ -279,15 +284,7 @@ static int w1_f23_add_slave(struct w1_slave *sl)
sl->family_data = data; sl->family_data = data;
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */ #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
return 0;
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;
} }
static void w1_f23_remove_slave(struct w1_slave *sl) 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); kfree(sl->family_data);
sl->family_data = NULL; sl->family_data = NULL;
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */ #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 = { static struct w1_family_ops w1_f23_fops = {
.add_slave = w1_f23_add_slave, .add_slave = w1_f23_add_slave,
.remove_slave = w1_f23_remove_slave, .remove_slave = w1_f23_remove_slave,
.groups = w1_f23_groups,
}; };
static struct w1_family w1_family_23 = { static struct w1_family w1_family_23 = {

View File

@ -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); return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
} }
static ssize_t w1_ds2760_read_bin(struct file *filp, struct kobject *kobj, static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
return w1_ds2760_read(dev, buf, off, count); return w1_ds2760_read(dev, buf, off, count);
} }
static struct bin_attribute w1_ds2760_bin_attr = { static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
.attr = {
.name = "w1_slave", static struct bin_attribute *w1_ds2760_bin_attrs[] = {
.mode = S_IRUGO, &bin_attr_w1_slave,
}, NULL,
.size = DS2760_DATA_SIZE, };
.read = w1_ds2760_read_bin,
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); static DEFINE_IDA(bat_ida);
@ -139,16 +146,10 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
if (ret) if (ret)
goto pdev_add_failed; 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); dev_set_drvdata(&sl->dev, pdev);
goto success; goto success;
bin_attr_failed:
platform_device_del(pdev);
pdev_add_failed: pdev_add_failed:
platform_device_put(pdev); platform_device_put(pdev);
pdev_alloc_failed: pdev_alloc_failed:
@ -165,12 +166,12 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
platform_device_unregister(pdev); platform_device_unregister(pdev);
ida_simple_remove(&bat_ida, id); 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 = { static struct w1_family_ops w1_ds2760_fops = {
.add_slave = w1_ds2760_add_slave, .add_slave = w1_ds2760_add_slave,
.remove_slave = w1_ds2760_remove_slave, .remove_slave = w1_ds2760_remove_slave,
.groups = w1_ds2760_groups,
}; };
static struct w1_family w1_ds2760_family = { static struct w1_family w1_ds2760_family = {

View File

@ -89,22 +89,28 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
} }
EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
static ssize_t w1_ds2780_read_bin(struct file *filp, static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
return w1_ds2780_io(dev, buf, off, count, 0); return w1_ds2780_io(dev, buf, off, count, 0);
} }
static struct bin_attribute w1_ds2780_bin_attr = { static BIN_ATTR_RO(w1_slave, DS2780_DATA_SIZE);
.attr = {
.name = "w1_slave", static struct bin_attribute *w1_ds2780_bin_attrs[] = {
.mode = S_IRUGO, &bin_attr_w1_slave,
}, NULL,
.size = DS2780_DATA_SIZE, };
.read = w1_ds2780_read_bin,
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); static DEFINE_IDA(bat_ida);
@ -132,16 +138,10 @@ static int w1_ds2780_add_slave(struct w1_slave *sl)
if (ret) if (ret)
goto pdev_add_failed; 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); dev_set_drvdata(&sl->dev, pdev);
return 0; return 0;
bin_attr_failed:
platform_device_del(pdev);
pdev_add_failed: pdev_add_failed:
platform_device_put(pdev); platform_device_put(pdev);
pdev_alloc_failed: pdev_alloc_failed:
@ -157,12 +157,12 @@ static void w1_ds2780_remove_slave(struct w1_slave *sl)
platform_device_unregister(pdev); platform_device_unregister(pdev);
ida_simple_remove(&bat_ida, id); 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 = { static struct w1_family_ops w1_ds2780_fops = {
.add_slave = w1_ds2780_add_slave, .add_slave = w1_ds2780_add_slave,
.remove_slave = w1_ds2780_remove_slave, .remove_slave = w1_ds2780_remove_slave,
.groups = w1_ds2780_groups,
}; };
static struct w1_family w1_ds2780_family = { static struct w1_family w1_ds2780_family = {

View File

@ -87,22 +87,28 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd)
} }
EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
static ssize_t w1_ds2781_read_bin(struct file *filp, static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
struct kobject *kobj, struct bin_attribute *bin_attr, char *buf,
struct bin_attribute *bin_attr, loff_t off, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
return w1_ds2781_io(dev, buf, off, count, 0); return w1_ds2781_io(dev, buf, off, count, 0);
} }
static struct bin_attribute w1_ds2781_bin_attr = { static BIN_ATTR_RO(w1_slave, DS2781_DATA_SIZE);
.attr = {
.name = "w1_slave", static struct bin_attribute *w1_ds2781_bin_attrs[] = {
.mode = S_IRUGO, &bin_attr_w1_slave,
}, NULL,
.size = DS2781_DATA_SIZE, };
.read = w1_ds2781_read_bin,
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); static DEFINE_IDA(bat_ida);
@ -130,16 +136,10 @@ static int w1_ds2781_add_slave(struct w1_slave *sl)
if (ret) if (ret)
goto pdev_add_failed; 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); dev_set_drvdata(&sl->dev, pdev);
return 0; return 0;
bin_attr_failed:
platform_device_del(pdev);
pdev_add_failed: pdev_add_failed:
platform_device_put(pdev); platform_device_put(pdev);
pdev_alloc_failed: pdev_alloc_failed:
@ -155,12 +155,12 @@ static void w1_ds2781_remove_slave(struct w1_slave *sl)
platform_device_unregister(pdev); platform_device_unregister(pdev);
ida_simple_remove(&bat_ida, id); 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 = { static struct w1_family_ops w1_ds2781_fops = {
.add_slave = w1_ds2781_add_slave, .add_slave = w1_ds2781_add_slave,
.remove_slave = w1_ds2781_remove_slave, .remove_slave = w1_ds2781_remove_slave,
.groups = w1_ds2781_groups,
}; };
static struct w1_family w1_ds2781_family = { static struct w1_family w1_ds2781_family = {

View File

@ -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); return w1_read_block(sl->master, data, len);
} }
static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
struct w1_f1C_data *data = sl->family_data; 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; return 0;
} }
static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj, static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf,
char *buf, loff_t off, size_t count) loff_t off, size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
@ -280,9 +280,11 @@ out_up:
return count; return count;
} }
static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj, static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) 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); 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; return ret;
} }
static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj, static ssize_t pio_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf, loff_t off,
char *buf, loff_t off, size_t count) size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); 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; return count;
} }
static ssize_t w1_f1C_show_crccheck(struct device *dev, static BIN_ATTR_RW(pio, 1);
struct device_attribute *attr, char *buf)
static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr,
char *buf)
{ {
if (put_user(w1_enable_crccheck + 0x30, buf)) if (put_user(w1_enable_crccheck + 0x30, buf))
return -EFAULT; return -EFAULT;
@ -348,9 +352,8 @@ static ssize_t w1_f1C_show_crccheck(struct device *dev,
return sizeof(w1_enable_crccheck); return sizeof(w1_enable_crccheck);
} }
static ssize_t w1_f1C_store_crccheck(struct device *dev, static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
char val; char val;
@ -371,35 +374,31 @@ static ssize_t w1_f1C_store_crccheck(struct device *dev,
return sizeof(w1_enable_crccheck); return sizeof(w1_enable_crccheck);
} }
#define NB_SYSFS_BIN_FILES 2 static DEVICE_ATTR_RW(crccheck);
static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = {
{ static struct attribute *w1_f1C_attrs[] = {
.attr = { &dev_attr_crccheck.attr,
.name = "eeprom", NULL,
.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(crccheck, S_IWUSR | S_IRUGO, static struct bin_attribute *w1_f1C_bin_attrs[] = {
w1_f1C_show_crccheck, w1_f1C_store_crccheck); &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) static int w1_f1C_add_slave(struct w1_slave *sl)
{ {
int err = 0;
int i;
struct w1_f1C_data *data = NULL; struct w1_f1C_data *data = NULL;
if (w1_enable_crccheck) { if (w1_enable_crccheck) {
@ -409,46 +408,19 @@ static int w1_f1C_add_slave(struct w1_slave *sl)
sl->family_data = data; sl->family_data = data;
} }
/* create binary sysfs attributes */ return 0;
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;
} }
static void w1_f1C_remove_slave(struct w1_slave *sl) static void w1_f1C_remove_slave(struct w1_slave *sl)
{ {
int i;
kfree(sl->family_data); kfree(sl->family_data);
sl->family_data = NULL; 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 = { static struct w1_family_ops w1_f1C_fops = {
.add_slave = w1_f1C_add_slave, .add_slave = w1_f1C_add_slave,
.remove_slave = w1_f1C_remove_slave, .remove_slave = w1_f1C_remove_slave,
.groups = w1_f1C_groups,
}; };
static struct w1_family w1_family_1C = { static struct w1_family w1_family_1C = {

View File

@ -59,25 +59,19 @@ static int w1_strong_pullup = 1;
module_param_named(strong_pullup, w1_strong_pullup, int, 0); 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); struct device_attribute *attr, char *buf);
static struct device_attribute w1_therm_attr = static DEVICE_ATTR_RO(w1_slave);
__ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL);
static int w1_therm_add_slave(struct w1_slave *sl) static struct attribute *w1_therm_attrs[] = {
{ &dev_attr_w1_slave.attr,
return device_create_file(&sl->dev, &w1_therm_attr); NULL,
} };
ATTRIBUTE_GROUPS(w1_therm);
static void w1_therm_remove_slave(struct w1_slave *sl)
{
device_remove_file(&sl->dev, &w1_therm_attr);
}
static struct w1_family_ops w1_therm_fops = { static struct w1_family_ops w1_therm_fops = {
.add_slave = w1_therm_add_slave, .groups = w1_therm_groups,
.remove_slave = w1_therm_remove_slave,
}; };
static struct w1_family w1_therm_family_DS18S20 = { 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 device_attribute *attr, char *buf)
{ {
struct w1_slave *sl = dev_to_w1_slave(device); struct w1_slave *sl = dev_to_w1_slave(device);

View File

@ -96,14 +96,15 @@ static void w1_slave_release(struct device *dev)
complete(&sl->released); 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); struct w1_slave *sl = dev_to_w1_slave(dev);
return sprintf(buf, "%s\n", sl->name); 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 device_attribute *attr, char *buf)
{ {
struct w1_slave *sl = dev_to_w1_slave(dev); 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); memcpy(buf, (u8 *)&sl->reg_num, count);
return count; return count;
} }
static DEVICE_ATTR_RO(id);
static struct device_attribute w1_slave_attr_name = static struct attribute *w1_slave_attrs[] = {
__ATTR(name, S_IRUGO, w1_slave_read_name, NULL); &dev_attr_name.attr,
static struct device_attribute w1_slave_attr_id = &dev_attr_id.attr,
__ATTR(id, S_IRUGO, w1_slave_read_id, NULL); NULL,
};
ATTRIBUTE_GROUPS(w1_slave);
/* Default family */ /* Default family */
static ssize_t w1_default_write(struct file *filp, struct kobject *kobj, static ssize_t rw_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf, loff_t off,
char *buf, loff_t off, size_t count) size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_slave *sl = kobj_to_w1_slave(kobj);
@ -139,9 +143,9 @@ out_up:
return count; return count;
} }
static ssize_t w1_default_read(struct file *filp, struct kobject *kobj, static ssize_t rw_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr, char *buf, loff_t off,
char *buf, loff_t off, size_t count) size_t count)
{ {
struct w1_slave *sl = kobj_to_w1_slave(kobj); 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; return count;
} }
static struct bin_attribute w1_default_attr = { static BIN_ATTR_RW(rw, PAGE_SIZE);
.attr = {
.name = "rw", static struct bin_attribute *w1_slave_bin_attrs[] = {
.mode = S_IRUGO | S_IWUSR, &bin_attr_rw,
}, NULL,
.size = PAGE_SIZE,
.read = w1_default_read,
.write = w1_default_write,
}; };
static int w1_default_add_slave(struct w1_slave *sl) static const struct attribute_group w1_slave_default_group = {
{ .bin_attrs = w1_slave_bin_attrs,
return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr); };
}
static void w1_default_remove_slave(struct w1_slave *sl) static const struct attribute_group *w1_slave_default_groups[] = {
{ &w1_slave_default_group,
sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr); NULL,
} };
static struct w1_family_ops w1_default_fops = { static struct w1_family_ops w1_default_fops = {
.add_slave = w1_default_add_slave, .groups = w1_slave_default_groups,
.remove_slave = w1_default_remove_slave,
}; };
static struct w1_family w1_default_family = { static struct w1_family w1_default_family = {
@ -587,6 +586,66 @@ end:
return err; 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) static int __w1_attach_slave_device(struct w1_slave *sl)
{ {
int err; int err;
@ -595,6 +654,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
sl->dev.driver = &w1_slave_driver; sl->dev.driver = &w1_slave_driver;
sl->dev.bus = &w1_bus_type; sl->dev.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release; sl->dev.release = &w1_slave_release;
sl->dev.groups = w1_slave_groups;
dev_set_name(&sl->dev, "%02x-%012llx", dev_set_name(&sl->dev, "%02x-%012llx",
(unsigned int) sl->reg_num.family, (unsigned int) sl->reg_num.family,
@ -615,44 +675,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
return err; 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 */ dev_set_uevent_suppress(&sl->dev, false);
err = device_create_file(&sl->dev, &w1_slave_attr_id); kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
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;
}
list_add_tail(&sl->w1_slave_entry, &sl->master->slist); list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
return 0; 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) 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); 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)); memset(&msg, 0, sizeof(msg));
memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id)); memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
msg.type = W1_SLAVE_REMOVE; msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg); 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); device_unregister(&sl->dev);
wait_for_completion(&sl->released); wait_for_completion(&sl->released);
@ -1017,6 +1041,10 @@ static int __init w1_init(void)
goto err_out_exit_init; 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); retval = driver_register(&w1_master_driver);
if (retval) { if (retval) {
printk(KERN_ERR printk(KERN_ERR

View File

@ -52,6 +52,7 @@ struct w1_family_ops
{ {
int (* add_slave)(struct w1_slave *); int (* add_slave)(struct w1_slave *);
void (* remove_slave)(struct w1_slave *); void (* remove_slave)(struct w1_slave *);
const struct attribute_group **groups;
}; };
struct w1_family struct w1_family

View File

@ -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)); 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, static ssize_t cuse_class_abort_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
@ -578,12 +579,14 @@ static ssize_t cuse_class_abort_store(struct device *dev,
fuse_abort_conn(&cc->fc); fuse_abort_conn(&cc->fc);
return count; return count;
} }
static DEVICE_ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store);
static struct device_attribute cuse_class_dev_attrs[] = { static struct attribute *cuse_class_dev_attrs[] = {
__ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL), &dev_attr_waiting.attr,
__ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store), &dev_attr_abort.attr,
{ } NULL,
}; };
ATTRIBUTE_GROUPS(cuse_class_dev);
static struct miscdevice cuse_miscdev = { static struct miscdevice cuse_miscdev = {
.minor = MISC_DYNAMIC_MINOR, .minor = MISC_DYNAMIC_MINOR,
@ -609,7 +612,7 @@ static int __init cuse_init(void)
if (IS_ERR(cuse_class)) if (IS_ERR(cuse_class))
return PTR_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); rc = misc_register(&cuse_miscdev);
if (rc) { if (rc) {

View File

@ -22,8 +22,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include "sysfs.h" #include "sysfs.h"
@ -391,7 +390,7 @@ out_unlock:
return rc; 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 sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; 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; 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; struct bin_buffer *bb = file->private_data;
@ -481,7 +480,6 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd)
* @kobj: object. * @kobj: object.
* @attr: attribute descriptor. * @attr: attribute descriptor.
*/ */
int sysfs_create_bin_file(struct kobject *kobj, int sysfs_create_bin_file(struct kobject *kobj,
const struct bin_attribute *attr) 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); 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. * sysfs_remove_bin_file - remove binary file for object.
* @kobj: object. * @kobj: object.
* @attr: attribute descriptor. * @attr: attribute descriptor.
*/ */
void sysfs_remove_bin_file(struct kobject *kobj, void sysfs_remove_bin_file(struct kobject *kobj,
const struct bin_attribute *attr) const struct bin_attribute *attr)
{ {
sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name); sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
} }
EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);

View File

@ -46,7 +46,7 @@ static unsigned int sysfs_name_hash(const void *ns, const char *name)
unsigned int len = strlen(name); unsigned int len = strlen(name);
while (len--) while (len--)
hash = partial_name_hash(*name++, hash); 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; hash &= 0x7fffffffU;
/* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
if (hash < 1) if (hash < 1)
@ -258,7 +258,7 @@ static void sysfs_free_ino(unsigned int ino)
spin_unlock(&sysfs_ino_lock); 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; 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) { if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", 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); acxt->parent_sd->s_name, sd->s_name);
return -EINVAL; return -EINVAL;
} }
@ -619,7 +619,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
if (!!sysfs_ns_type(parent_sd) != !!ns) { if (!!sysfs_ns_type(parent_sd) != !!ns) {
WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", 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); parent_sd->s_name, name);
return NULL; 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, enum kobj_ns_type type, const void *ns, const char *name,
struct sysfs_dirent **p_sd) 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_addrm_cxt acxt;
struct sysfs_dirent *sd; struct sysfs_dirent *sd;
int rc; 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. * 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; enum kobj_ns_type type;
struct sysfs_dirent *parent_sd, *sd; struct sysfs_dirent *parent_sd, *sd;
@ -764,8 +764,8 @@ int sysfs_create_dir(struct kobject * kobj)
return error; return error;
} }
static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags) unsigned int flags)
{ {
struct dentry *ret = NULL; struct dentry *ret = NULL;
struct dentry *parent = dentry->d_parent; 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. * 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; struct sysfs_dirent *sd = kobj->sd;
@ -896,7 +896,9 @@ int sysfs_rename(struct sysfs_dirent *sd,
sd->s_name = new_name; 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_unlink_sibling(sd);
sysfs_get(new_parent_sd); sysfs_get(new_parent_sd);
sysfs_put(sd->s_parent); 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) struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
{ {
pos = sysfs_dir_pos(ns, parent_sd, ino, pos); pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
if (pos) do { if (pos)
struct rb_node *node = rb_next(&pos->s_rb); do {
if (!node) struct rb_node *node = rb_next(&pos->s_rb);
pos = NULL; if (!node)
else pos = NULL;
pos = to_sysfs_dirent(node); else
} while (pos && pos->s_ns != ns); pos = to_sysfs_dirent(node);
} while (pos && pos->s_ns != ns);
return pos; return pos;
} }
static int sysfs_readdir(struct file *file, struct dir_context *ctx) static int sysfs_readdir(struct file *file, struct dir_context *ctx)
{ {
struct dentry *dentry = file->f_path.dentry; 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; struct sysfs_dirent *pos = file->private_data;
enum kobj_ns_type type; enum kobj_ns_type type;
const void *ns; const void *ns;

View File

@ -20,7 +20,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include "sysfs.h" #include "sysfs.h"
@ -45,8 +45,8 @@ struct sysfs_open_dirent {
struct sysfs_buffer { struct sysfs_buffer {
size_t count; size_t count;
loff_t pos; loff_t pos;
char * page; char *page;
const struct sysfs_ops * ops; const struct sysfs_ops *ops;
struct mutex mutex; struct mutex mutex;
int needs_read_fill; int needs_read_fill;
int event; int event;
@ -59,16 +59,16 @@ struct sysfs_buffer {
* @buffer: data buffer for file. * @buffer: data buffer for file.
* *
* Allocate @buffer->page, if it hasn't been already, then call the * Allocate @buffer->page, if it hasn't been already, then call the
* kobject's show() method to fill the buffer with this attribute's * kobject's show() method to fill the buffer with this attribute's
* data. * data.
* This is called only once, on the file's first read unless an error * This is called only once, on the file's first read unless an error
* is returned. * 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 sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 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; int ret = 0;
ssize_t count; 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. * @file: file pointer.
* @buf: buffer to fill. * @buf: buffer to fill.
* @count: number of bytes to read. * @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 static ssize_t
sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) 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; ssize_t retval = 0;
mutex_lock(&buffer->mutex); mutex_lock(&buffer->mutex);
if (buffer->needs_read_fill || *ppos == 0) { 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) if (retval)
goto out; goto out;
} }
@ -154,9 +154,8 @@ out:
* Allocate @buffer->page if it hasn't been already, then * Allocate @buffer->page if it hasn't been already, then
* copy the user-supplied buffer into it. * copy the user-supplied buffer into it.
*/ */
static int fill_write_buffer(struct sysfs_buffer *buffer,
static int const char __user *buf, size_t count)
fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
{ {
int error; int error;
@ -167,7 +166,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
if (count >= PAGE_SIZE) if (count >= PAGE_SIZE)
count = PAGE_SIZE - 1; 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; buffer->needs_read_fill = 1;
/* if buf is assumed to contain a string, terminate it by \0, /* if buf is assumed to contain a string, terminate it by \0,
so e.g. sscanf() can scan the string easily */ 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 * @count: number of bytes
* *
* Get the correct pointers for the kobject and the attribute we're * 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(). * passing the buffer that we acquired in fill_write_buffer().
*/ */
static int flush_write_buffer(struct dentry *dentry,
static int struct sysfs_buffer *buffer, size_t count)
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
{ {
struct sysfs_dirent *attr_sd = dentry->d_fsdata; struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 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; int rc;
/* need attr_sd for attr and ops, its parent for kobj */ /* 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(). * 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 * 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 * 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 * 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,
static ssize_t size_t count, loff_t *ppos)
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; ssize_t len;
mutex_lock(&buffer->mutex); 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) if (kobj->ktype && kobj->ktype->sysfs_ops)
ops = kobj->ktype->sysfs_ops; ops = kobj->ktype->sysfs_ops;
else { else {
WARN(1, KERN_ERR "missing sysfs attribute operations for " WARN(1, KERN_ERR
"kobject: %s\n", kobject_name(kobj)); "missing sysfs attribute operations for kobject: %s\n",
kobject_name(kobj));
goto err_out; goto err_out;
} }
/* File needs write support. /* 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. * and we must have a store method.
*/ */
if (file->f_mode & FMODE_WRITE) { 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) 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_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
struct sysfs_open_dirent *od = attr_sd->s_attr.open; 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); ns = ops->namespace(kobj, attr);
out: out:
if (err) { if (err) {
WARN(1, KERN_ERR "missing sysfs namespace attribute operation for " WARN(1, KERN_ERR
"kobject: %s\n", kobject_name(kobj)); "missing sysfs namespace attribute operation for kobject: %s\n",
kobject_name(kobj));
} }
*pns = ns; *pns = ns;
return err; 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. * 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. * @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); BUG_ON(!kobj || !kobj->sd || !attr);
return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_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) 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]); sysfs_remove_file(kobj, ptr[i]);
return err; return err;
} }
EXPORT_SYMBOL_GPL(sysfs_create_files);
/** /**
* sysfs_add_file_to_group - add an attribute file to a pre-existing group. * 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); EXPORT_SYMBOL_GPL(sysfs_chmod_file);
/** /**
* sysfs_remove_file - remove an object attribute. * sysfs_remove_file - remove an object attribute.
* @kobj: object we're acting for. * @kobj: object we're acting for.
@ -662,8 +661,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
* *
* Hash the attribute name and kill the victim. * 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; 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); 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; int i;
for (i = 0; ptr[i]; i++) for (i = 0; ptr[i]; i++)
sysfs_remove_file(kobj, ptr[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. * 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; return 0;
} }
EXPORT_SYMBOL_GPL(sysfs_schedule_callback); 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);

View File

@ -3,8 +3,10 @@
* *
* Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Patrick Mochel
* Copyright (c) 2003 Open Source Development Lab * 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, static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
const struct attribute_group *grp) const struct attribute_group *grp)
{ {
struct attribute *const* attr; struct attribute *const *attr;
struct bin_attribute *const* bin_attr; struct bin_attribute *const *bin_attr;
if (grp->attrs) if (grp->attrs)
for (attr = grp->attrs; *attr; attr++) 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, static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
const struct attribute_group *grp, int update) const struct attribute_group *grp, int update)
{ {
struct attribute *const* attr; struct attribute *const *attr;
struct bin_attribute *const* bin_attr; struct bin_attribute *const *bin_attr;
int error = 0, i; int error = 0, i;
if (grp->attrs) { if (grp->attrs) {
@ -129,6 +131,41 @@ int sysfs_create_group(struct kobject *kobj,
{ {
return internal_create_group(kobj, 0, grp); 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 * 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); return internal_create_group(kobj, 1, grp);
} }
EXPORT_SYMBOL_GPL(sysfs_update_group);
/**
* sysfs_remove_group: remove a group from a kobject
void sysfs_remove_group(struct kobject * kobj, * @kobj: kobject to remove the group from
const struct attribute_group * grp) * @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 *dir_sd = kobj->sd;
struct sysfs_dirent *sd; struct sysfs_dirent *sd;
@ -164,8 +208,9 @@ void sysfs_remove_group(struct kobject * kobj,
if (grp->name) { if (grp->name) {
sd = sysfs_get_dirent(dir_sd, NULL, grp->name); sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
if (!sd) { if (!sd) {
WARN(!sd, KERN_WARNING "sysfs group %p not found for " WARN(!sd, KERN_WARNING
"kobject '%s'\n", grp, kobject_name(kobj)); "sysfs group %p not found for kobject '%s'\n",
grp, kobject_name(kobj));
return; return;
} }
} else } else
@ -177,6 +222,27 @@ void sysfs_remove_group(struct kobject * kobj,
sysfs_put(sd); 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. * 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_remove_link_from_group);
EXPORT_SYMBOL_GPL(sysfs_create_group);
EXPORT_SYMBOL_GPL(sysfs_update_group);
EXPORT_SYMBOL_GPL(sysfs_remove_group);

View File

@ -10,7 +10,7 @@
* Please see Documentation/filesystems/sysfs.txt for more information. * Please see Documentation/filesystems/sysfs.txt for more information.
*/ */
#undef DEBUG #undef DEBUG
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/namei.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, .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, .permission = sysfs_permission,
.setattr = sysfs_setattr, .setattr = sysfs_setattr,
.getattr = sysfs_getattr, .getattr = sysfs_getattr,
@ -67,7 +67,7 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
return attrs; 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 sysfs_inode_attrs *sd_attrs;
struct iattr *iattrs; struct iattr *iattrs;
@ -128,7 +128,8 @@ out:
return error; 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; struct sysfs_inode_attrs *iattrs;
void *old_secdata; void *old_secdata;
@ -186,13 +187,13 @@ out:
return error; 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_mode = mode;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 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_uid = iattr->ia_uid;
inode->i_gid = iattr->ia_gid; 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); 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 sysfs_dirent *sd = dentry->d_fsdata;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
@ -285,7 +287,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
* RETURNS: * RETURNS:
* Pointer to allocated inode on success, NULL on failure. * 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; struct inode *inode;
@ -312,7 +314,8 @@ void sysfs_evict_inode(struct inode *inode)
sysfs_put(sd); 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_addrm_cxt acxt;
struct sysfs_dirent *sd; struct sysfs_dirent *sd;

View File

@ -64,7 +64,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
/* instantiate and link root dentry */ /* instantiate and link root dentry */
root = d_make_root(inode); root = d_make_root(inode);
if (!root) { if (!root) {
pr_debug("%s: could not get root dentry!\n",__func__); pr_debug("%s: could not get root dentry!\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
root->d_fsdata = &sysfs_root; root->d_fsdata = &sysfs_root;

View File

@ -125,6 +125,7 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target,
{ {
return sysfs_do_create_link(kobj, target, name, 1); return sysfs_do_create_link(kobj, target, name, 1);
} }
EXPORT_SYMBOL_GPL(sysfs_create_link);
/** /**
* sysfs_create_link_nowarn - create symlink between two objects. * 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. * @kobj: object we're acting for.
* @name: name of the symlink to remove. * @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; 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); sysfs_hash_and_remove(parent_sd, NULL, name);
} }
EXPORT_SYMBOL_GPL(sysfs_remove_link);
/** /**
* sysfs_rename_link - rename symlink in object's directory. * sysfs_rename_link - rename symlink in object's directory.
@ -223,6 +224,7 @@ out:
sysfs_put(sd); sysfs_put(sd);
return result; return result;
} }
EXPORT_SYMBOL_GPL(sysfs_rename_link);
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd, char *path) struct sysfs_dirent *target_sd, char *path)
@ -276,7 +278,7 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
return 0; 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 *sd = dentry->d_fsdata;
struct sysfs_dirent *parent_sd = sd->s_parent; 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; int error = -ENOMEM;
unsigned long page = get_zeroed_page(GFP_KERNEL); unsigned long page = get_zeroed_page(GFP_KERNEL);
if (page) { if (page) {
error = sysfs_getlink(dentry, (char *) page); error = sysfs_getlink(dentry, (char *) page);
if (error < 0) if (error < 0)
free_page((unsigned long)page); free_page((unsigned long)page);
} }
@ -303,7 +305,8 @@ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL; 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); char *page = nd_get_link(nd);
if (!IS_ERR(page)) if (!IS_ERR(page))
@ -319,8 +322,3 @@ const struct inode_operations sysfs_symlink_inode_operations = {
.getattr = sysfs_getattr, .getattr = sysfs_getattr,
.permission = sysfs_permission, .permission = sysfs_permission,
}; };
EXPORT_SYMBOL_GPL(sysfs_create_link);
EXPORT_SYMBOL_GPL(sysfs_remove_link);
EXPORT_SYMBOL_GPL(sysfs_rename_link);

View File

@ -78,7 +78,7 @@ struct sysfs_dirent {
}; };
unsigned short s_flags; unsigned short s_flags;
umode_t s_mode; umode_t s_mode;
unsigned int s_ino; unsigned int s_ino;
struct sysfs_inode_attrs *s_iattr; struct sysfs_inode_attrs *s_iattr;
}; };
@ -123,9 +123,9 @@ do { \
key = &attr->skey; \ key = &attr->skey; \
\ \
lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ lockdep_init_map(&sd->dep_map, "s_active", key, 0); \
} while(0) } while (0)
#else #else
#define sysfs_dirent_init_lockdep(sd) do {} while(0) #define sysfs_dirent_init_lockdep(sd) do {} while (0)
#endif #endif
/* /*
@ -186,8 +186,8 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
struct sysfs_dirent **p_sd); struct sysfs_dirent **p_sd);
void sysfs_remove_subdir(struct sysfs_dirent *sd); void sysfs_remove_subdir(struct sysfs_dirent *sd);
int sysfs_rename(struct sysfs_dirent *sd, int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name); const void *ns, const char *new_name);
static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) 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_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
int sysfs_permission(struct inode *inode, int mask); int sysfs_permission(struct inode *inode, int mask);
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 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, int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags); size_t size, int flags);
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);
int sysfs_inode_init(void); int sysfs_inode_init(void);
/* /*

View File

@ -192,6 +192,13 @@ static inline struct dentry *debugfs_create_x32(const char *name, umode_t mode,
return ERR_PTR(-ENODEV); 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, static inline struct dentry *debugfs_create_size_t(const char *name, umode_t mode,
struct dentry *parent, struct dentry *parent,
size_t *value) size_t *value)

View File

@ -66,6 +66,9 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
* @bus_attrs: Default attributes of the bus. * @bus_attrs: Default attributes of the bus.
* @dev_attrs: Default attributes of the devices on the bus. * @dev_attrs: Default attributes of the devices on the bus.
* @drv_attrs: Default attributes of the device drivers 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 * @match: Called, perhaps multiple times, whenever a new device or driver
* is added for this bus. It should return a nonzero value if the * is added for this bus. It should return a nonzero value if the
* given device can be handled by the given driver. * given device can be handled by the given driver.
@ -103,9 +106,12 @@ struct bus_type {
const char *name; const char *name;
const char *dev_name; const char *dev_name;
struct device *dev_root; struct device *dev_root;
struct bus_attribute *bus_attrs; struct bus_attribute *bus_attrs; /* use bus_groups instead */
struct device_attribute *dev_attrs; struct device_attribute *dev_attrs; /* use dev_groups instead */
struct driver_attribute *drv_attrs; 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 (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env); 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) struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
#define DRIVER_ATTR_RO(_name) \ #define DRIVER_ATTR_RO(_name) \
struct driver_attribute driver_attr_##_name = __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, extern int __must_check driver_create_file(struct device_driver *driver,
const struct driver_attribute *attr); 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) struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
#define DEVICE_ATTR_RO(_name) \ #define DEVICE_ATTR_RO(_name) \
struct device_attribute dev_attr_##_name = __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) \ #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
struct dev_ext_attribute dev_attr_##_name = \ struct dev_ext_attribute dev_attr_##_name = \
{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }

View File

@ -26,6 +26,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/workqueue.h>
#define UEVENT_HELPER_PATH_LEN 256 #define UEVENT_HELPER_PATH_LEN 256
#define UEVENT_NUM_ENVP 32 /* number of env pointers */ #define UEVENT_NUM_ENVP 32 /* number of env pointers */
@ -65,6 +66,9 @@ struct kobject {
struct kobj_type *ktype; struct kobj_type *ktype;
struct sysfs_dirent *sd; struct sysfs_dirent *sd;
struct kref kref; struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:1; unsigned int state_initialized:1;
unsigned int state_in_sysfs:1; unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1; unsigned int state_add_uevent_sent:1;

View File

@ -25,16 +25,9 @@
struct memory_block { struct memory_block {
unsigned long start_section_nr; unsigned long start_section_nr;
unsigned long end_section_nr; unsigned long end_section_nr;
unsigned long state; unsigned long state; /* serialized by the dev->lock */
int section_count; int section_count; /* serialized by mem_sysfs_mutex */
int online_type; /* for passing data to online routine */
/*
* 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;
int phys_device; /* to which fru does this belong? */ int phys_device; /* to which fru does this belong? */
void *hw; /* optional pointer to fw/hw data */ void *hw; /* optional pointer to fw/hw data */
int (*phys_callback)(struct memory_block *); int (*phys_callback)(struct memory_block *);
@ -125,7 +118,6 @@ extern struct memory_block *find_memory_block_hinted(struct mem_section *,
struct memory_block *); struct memory_block *);
extern struct memory_block *find_memory_block(struct mem_section *); extern struct memory_block *find_memory_block(struct mem_section *);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
enum mem_add_context { BOOT, HOTPLUG };
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG

View File

@ -80,7 +80,7 @@ struct pps_device {
* Global variables * Global variables
*/ */
extern struct device_attribute pps_attrs[]; extern const struct attribute_group *pps_groups[];
/* /*
* Internal functions. * Internal functions.

View File

@ -51,9 +51,9 @@ do { \
static struct lock_class_key __key; \ static struct lock_class_key __key; \
\ \
(attr)->key = &__key; \ (attr)->key = &__key; \
} while(0) } while (0)
#else #else
#define sysfs_attr_init(attr) do {} while(0) #define sysfs_attr_init(attr) do {} while (0)
#endif #endif
struct attribute_group { struct attribute_group {
@ -69,7 +69,7 @@ struct attribute_group {
* for examples.. * for examples..
*/ */
#define __ATTR(_name,_mode,_show,_store) { \ #define __ATTR(_name, _mode, _show, _store) { \
.attr = {.name = __stringify(_name), .mode = _mode }, \ .attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \ .show = _show, \
.store = _store, \ .store = _store, \
@ -80,6 +80,11 @@ struct attribute_group {
.show = _name##_show, \ .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), \ #define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \
_name##_show, _name##_store) _name##_show, _name##_store)
@ -108,8 +113,6 @@ static const struct attribute_group _name##_group = { \
}; \ }; \
__ATTRIBUTE_GROUPS(_name) __ATTRIBUTE_GROUPS(_name)
#define attr_name(_attr) (_attr).attr.name
struct file; struct file;
struct vm_area_struct; struct vm_area_struct;
@ -119,7 +122,7 @@ struct bin_attribute {
void *private; void *private;
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t); 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); char *, loff_t, size_t);
int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr, int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma); struct vm_area_struct *vma);
@ -153,7 +156,7 @@ struct bin_attribute {
#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name, \ #define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name, \
(S_IWUSR | S_IRUGO), _name##_read, \ (S_IWUSR | S_IRUGO), _name##_read, \
_name##_write) _name##_write, _size)
#define __BIN_ATTR_NULL __ATTR_NULL #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 bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
struct sysfs_ops { struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
const void *(*namespace)(struct kobject *, const struct attribute *); 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, int __must_check sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp); 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, int sysfs_update_group(struct kobject *kobj,
const struct attribute_group *grp); const struct attribute_group *grp);
void sysfs_remove_group(struct kobject *kobj, void sysfs_remove_group(struct kobject *kobj,
const struct attribute_group *grp); 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, int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group); const struct attribute *attr, const char *group);
void sysfs_remove_file_from_group(struct kobject *kobj, void sysfs_remove_file_from_group(struct kobject *kobj,
@ -343,6 +350,12 @@ static inline int sysfs_create_group(struct kobject *kobj,
return 0; 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, static inline int sysfs_update_group(struct kobject *kobj,
const struct attribute_group *grp) 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, static inline int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group) const struct attribute *attr, const char *group)
{ {

View File

@ -3095,25 +3095,26 @@ static struct workqueue_struct *dev_to_wq(struct device *dev)
return wq_dev->wq; return wq_dev->wq;
} }
static ssize_t wq_per_cpu_show(struct device *dev, static ssize_t per_cpu_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
struct workqueue_struct *wq = dev_to_wq(dev); struct workqueue_struct *wq = dev_to_wq(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND)); 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, static ssize_t max_active_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct workqueue_struct *wq = dev_to_wq(dev); struct workqueue_struct *wq = dev_to_wq(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active); return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
} }
static ssize_t wq_max_active_store(struct device *dev, static ssize_t max_active_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, const char *buf,
const char *buf, size_t count) size_t count)
{ {
struct workqueue_struct *wq = dev_to_wq(dev); struct workqueue_struct *wq = dev_to_wq(dev);
int val; int val;
@ -3124,12 +3125,14 @@ static ssize_t wq_max_active_store(struct device *dev,
workqueue_set_max_active(wq, val); workqueue_set_max_active(wq, val);
return count; return count;
} }
static DEVICE_ATTR_RW(max_active);
static struct device_attribute wq_sysfs_attrs[] = { static struct attribute *wq_sysfs_attrs[] = {
__ATTR(per_cpu, 0444, wq_per_cpu_show, NULL), &dev_attr_per_cpu.attr,
__ATTR(max_active, 0644, wq_max_active_show, wq_max_active_store), &dev_attr_max_active.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(wq_sysfs);
static ssize_t wq_pool_ids_show(struct device *dev, static ssize_t wq_pool_ids_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
@ -3279,7 +3282,7 @@ static struct device_attribute wq_sysfs_unbound_attrs[] = {
static struct bus_type wq_subsys = { static struct bus_type wq_subsys = {
.name = "workqueue", .name = "workqueue",
.dev_attrs = wq_sysfs_attrs, .dev_groups = wq_sysfs_groups,
}; };
static int __init wq_sysfs_init(void) static int __init wq_sysfs_init(void)

View File

@ -981,6 +981,25 @@ config DEBUG_KOBJECT
If you say Y here, some extra kobject debugging messages will be sent If you say Y here, some extra kobject debugging messages will be sent
to the syslog. 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 config HAVE_DEBUG_BUGVERBOSE
bool bool

View File

@ -309,7 +309,7 @@ static int ddebug_parse_query(char *words[], int nwords,
struct ddebug_query *query, const char *modname) struct ddebug_query *query, const char *modname)
{ {
unsigned int i; unsigned int i;
int rc; int rc = 0;
/* check we have an even number of words */ /* check we have an even number of words */
if (nwords % 2 != 0) { if (nwords % 2 != 0) {

View File

@ -545,8 +545,8 @@ static void kobject_cleanup(struct kobject *kobj)
struct kobj_type *t = get_ktype(kobj); struct kobj_type *t = get_ktype(kobj);
const char *name = kobj->name; const char *name = kobj->name;
pr_debug("kobject: '%s' (%p): %s\n", pr_debug("kobject: '%s' (%p): %s, parent %p\n",
kobject_name(kobj), kobj, __func__); kobject_name(kobj), kobj, __func__, kobj->parent);
if (t && !t->release) if (t && !t->release)
pr_debug("kobject: '%s' (%p): does not have a 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) 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
} }
/** /**

View File

@ -180,7 +180,8 @@ static ssize_t name##_show(struct device *dev, \
struct backing_dev_info *bdi = dev_get_drvdata(dev); \ struct backing_dev_info *bdi = dev_get_drvdata(dev); \
\ \
return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr); \ 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)) 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", return snprintf(page, PAGE_SIZE-1, "%d\n",
bdi_cap_stable_pages_required(bdi) ? 1 : 0); bdi_cap_stable_pages_required(bdi) ? 1 : 0);
} }
static DEVICE_ATTR_RO(stable_pages_required);
static struct device_attribute bdi_dev_attrs[] = { static struct attribute *bdi_dev_attrs[] = {
__ATTR_RW(read_ahead_kb), &dev_attr_read_ahead_kb.attr,
__ATTR_RW(min_ratio), &dev_attr_min_ratio.attr,
__ATTR_RW(max_ratio), &dev_attr_max_ratio.attr,
__ATTR_RO(stable_pages_required), &dev_attr_stable_pages_required.attr,
__ATTR_NULL, NULL,
}; };
ATTRIBUTE_GROUPS(bdi_dev);
static __init int bdi_class_init(void) static __init int bdi_class_init(void)
{ {
@ -246,7 +249,7 @@ static __init int bdi_class_init(void)
if (IS_ERR(bdi_class)) if (IS_ERR(bdi_class))
return PTR_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(); bdi_debug_init();
return 0; return 0;
} }

View File

@ -60,12 +60,19 @@ static ssize_t format_##field(const struct net_device *net, char *buf) \
{ \ { \
return sprintf(buf, format_string, net->field); \ 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) \ struct device_attribute *attr, char *buf) \
{ \ { \
return netdev_show(dev, attr, buf, format_##field); \ 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 */ /* use same locking and permission rules as SIF* ioctl's */
static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, 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; return ret;
} }
NETDEVICE_SHOW(dev_id, fmt_hex); NETDEVICE_SHOW_RO(dev_id, fmt_hex);
NETDEVICE_SHOW(addr_assign_type, fmt_dec); NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
NETDEVICE_SHOW(addr_len, fmt_dec); NETDEVICE_SHOW_RO(addr_len, fmt_dec);
NETDEVICE_SHOW(iflink, fmt_dec); NETDEVICE_SHOW_RO(iflink, fmt_dec);
NETDEVICE_SHOW(ifindex, fmt_dec); NETDEVICE_SHOW_RO(ifindex, fmt_dec);
NETDEVICE_SHOW(type, fmt_dec); NETDEVICE_SHOW_RO(type, fmt_dec);
NETDEVICE_SHOW(link_mode, fmt_dec); NETDEVICE_SHOW_RO(link_mode, fmt_dec);
/* use same locking rules as GIFHWADDR ioctl's */ /* 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) char *buf)
{ {
struct net_device *net = to_net_dev(dev); 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); read_unlock(&dev_base_lock);
return ret; return ret;
} }
static DEVICE_ATTR_RO(address);
static ssize_t show_broadcast(struct device *dev, static ssize_t broadcast_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct net_device *net = to_net_dev(dev); struct net_device *net = to_net_dev(dev);
if (dev_isalive(net)) if (dev_isalive(net))
return sysfs_format_mac(buf, net->broadcast, net->addr_len); return sysfs_format_mac(buf, net->broadcast, net->addr_len);
return -EINVAL; return -EINVAL;
} }
static DEVICE_ATTR_RO(broadcast);
static int change_carrier(struct net_device *net, unsigned long new_carrier) 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); return dev_change_carrier(net, (bool) new_carrier);
} }
static ssize_t store_carrier(struct device *dev, struct device_attribute *attr, static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
return netdev_store(dev, attr, buf, len, change_carrier); 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 device_attribute *attr, char *buf)
{ {
struct net_device *netdev = to_net_dev(dev); struct net_device *netdev = to_net_dev(dev);
@ -149,8 +158,9 @@ static ssize_t show_carrier(struct device *dev,
} }
return -EINVAL; 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 device_attribute *attr, char *buf)
{ {
struct net_device *netdev = to_net_dev(dev); struct net_device *netdev = to_net_dev(dev);
@ -167,8 +177,9 @@ static ssize_t show_speed(struct device *dev,
rtnl_unlock(); rtnl_unlock();
return ret; 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 device_attribute *attr, char *buf)
{ {
struct net_device *netdev = to_net_dev(dev); struct net_device *netdev = to_net_dev(dev);
@ -198,8 +209,9 @@ static ssize_t show_duplex(struct device *dev,
rtnl_unlock(); rtnl_unlock();
return ret; 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 device_attribute *attr, char *buf)
{ {
struct net_device *netdev = to_net_dev(dev); struct net_device *netdev = to_net_dev(dev);
@ -209,6 +221,7 @@ static ssize_t show_dormant(struct device *dev,
return -EINVAL; return -EINVAL;
} }
static DEVICE_ATTR_RO(dormant);
static const char *const operstates[] = { static const char *const operstates[] = {
"unknown", "unknown",
@ -220,7 +233,7 @@ static const char *const operstates[] = {
"up" "up"
}; };
static ssize_t show_operstate(struct device *dev, static ssize_t operstate_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
const struct net_device *netdev = to_net_dev(dev); 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]); return sprintf(buf, "%s\n", operstates[operstate]);
} }
static DEVICE_ATTR_RO(operstate);
/* read-write attributes */ /* read-write attributes */
NETDEVICE_SHOW(mtu, fmt_dec);
static int change_mtu(struct net_device *net, unsigned long new_mtu) static int change_mtu(struct net_device *net, unsigned long new_mtu)
{ {
return dev_set_mtu(net, (int) 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) const char *buf, size_t len)
{ {
return netdev_store(dev, attr, buf, len, change_mtu); return netdev_store(dev, attr, buf, len, change_mtu);
} }
NETDEVICE_SHOW_RW(mtu, fmt_dec);
NETDEVICE_SHOW(flags, fmt_hex);
static int change_flags(struct net_device *net, unsigned long new_flags) static int change_flags(struct net_device *net, unsigned long new_flags)
{ {
return dev_change_flags(net, (unsigned int) 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) const char *buf, size_t len)
{ {
return netdev_store(dev, attr, buf, len, change_flags); return netdev_store(dev, attr, buf, len, change_flags);
} }
NETDEVICE_SHOW_RW(flags, fmt_hex);
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
static int change_tx_queue_len(struct net_device *net, unsigned long new_len) 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; 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, struct device_attribute *attr,
const char *buf, size_t len) 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); 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) const char *buf, size_t len)
{ {
struct net_device *netdev = to_net_dev(dev); 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; 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) struct device_attribute *attr, char *buf)
{ {
const struct net_device *netdev = to_net_dev(dev); const struct net_device *netdev = to_net_dev(dev);
@ -319,8 +331,7 @@ static ssize_t show_ifalias(struct device *dev,
rtnl_unlock(); rtnl_unlock();
return ret; return ret;
} }
static DEVICE_ATTR_RW(ifalias);
NETDEVICE_SHOW(group, fmt_dec);
static int change_group(struct net_device *net, unsigned long new_group) 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; return 0;
} }
static ssize_t store_group(struct device *dev, struct device_attribute *attr, static ssize_t group_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
return netdev_store(dev, attr, buf, len, change_group); 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[] = { static struct attribute *net_class_attrs[] = {
__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL), &dev_attr_netdev_group.attr,
__ATTR(addr_len, S_IRUGO, show_addr_len, NULL), &dev_attr_type.attr,
__ATTR(dev_id, S_IRUGO, show_dev_id, NULL), &dev_attr_dev_id.attr,
__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), &dev_attr_iflink.attr,
__ATTR(iflink, S_IRUGO, show_iflink, NULL), &dev_attr_ifindex.attr,
__ATTR(ifindex, S_IRUGO, show_ifindex, NULL), &dev_attr_addr_assign_type.attr,
__ATTR(type, S_IRUGO, show_type, NULL), &dev_attr_addr_len.attr,
__ATTR(link_mode, S_IRUGO, show_link_mode, NULL), &dev_attr_link_mode.attr,
__ATTR(address, S_IRUGO, show_address, NULL), &dev_attr_address.attr,
__ATTR(broadcast, S_IRUGO, show_broadcast, NULL), &dev_attr_broadcast.attr,
__ATTR(carrier, S_IRUGO | S_IWUSR, show_carrier, store_carrier), &dev_attr_speed.attr,
__ATTR(speed, S_IRUGO, show_speed, NULL), &dev_attr_duplex.attr,
__ATTR(duplex, S_IRUGO, show_duplex, NULL), &dev_attr_dormant.attr,
__ATTR(dormant, S_IRUGO, show_dormant, NULL), &dev_attr_operstate.attr,
__ATTR(operstate, S_IRUGO, show_operstate, NULL), &dev_attr_ifalias.attr,
__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), &dev_attr_carrier.attr,
__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), &dev_attr_mtu.attr,
__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, &dev_attr_flags.attr,
store_tx_queue_len), &dev_attr_tx_queue_len.attr,
__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group), NULL,
{}
}; };
ATTRIBUTE_GROUPS(net_class);
/* Show a given an attribute in the statistics group */ /* Show a given an attribute in the statistics group */
static ssize_t netstat_show(const struct device *d, 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 */ /* generate a read-only statistics attribute */
#define NETSTAT_ENTRY(name) \ #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) \ struct device_attribute *attr, char *buf) \
{ \ { \
return netstat_show(d, attr, buf, \ return netstat_show(d, attr, buf, \
offsetof(struct rtnl_link_stats64, name)); \ 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(rx_packets);
NETSTAT_ENTRY(tx_packets); NETSTAT_ENTRY(tx_packets);
@ -457,6 +470,9 @@ static struct attribute_group wireless_group = {
.attrs = wireless_attrs, .attrs = wireless_attrs,
}; };
#endif #endif
#else /* CONFIG_SYSFS */
#define net_class_groups NULL
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
#ifdef CONFIG_RPS #ifdef CONFIG_RPS
@ -1229,9 +1245,7 @@ static const void *net_namespace(struct device *d)
static struct class net_class = { static struct class net_class = {
.name = "net", .name = "net",
.dev_release = netdev_release, .dev_release = netdev_release,
#ifdef CONFIG_SYSFS .dev_groups = net_class_groups,
.dev_attrs = net_class_attributes,
#endif /* CONFIG_SYSFS */
.dev_uevent = netdev_uevent, .dev_uevent = netdev_uevent,
.ns_type = &net_ns_type_operations, .ns_type = &net_ns_type_operations,
.namespace = net_namespace, .namespace = net_namespace,

View File

@ -36,7 +36,8 @@ static ssize_t name ## _show(struct device *dev, \
ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \ ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \
mutex_unlock(&phy->pib_lock); \ mutex_unlock(&phy->pib_lock); \
return ret; \ return ret; \
} } \
static DEVICE_ATTR_RO(name);
#define MASTER_SHOW(field, format_string) \ #define MASTER_SHOW(field, format_string) \
MASTER_SHOW_COMPLEX(field, format_string, phy->field) 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); mutex_unlock(&phy->pib_lock);
return len; return len;
} }
static DEVICE_ATTR_RO(channels_supported);
static struct device_attribute pmib_attrs[] = { static struct attribute *pmib_attrs[] = {
__ATTR_RO(current_channel), &dev_attr_current_channel.attr,
__ATTR_RO(current_page), &dev_attr_current_page.attr,
__ATTR_RO(channels_supported), &dev_attr_channels_supported.attr,
__ATTR_RO(transmit_power), &dev_attr_transmit_power.attr,
__ATTR_RO(cca_mode), &dev_attr_cca_mode.attr,
{}, NULL,
}; };
ATTRIBUTE_GROUPS(pmib);
static void wpan_phy_release(struct device *d) 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 = { static struct class wpan_phy_class = {
.name = "ieee802154", .name = "ieee802154",
.dev_release = wpan_phy_release, .dev_release = wpan_phy_release,
.dev_attrs = pmib_attrs, .dev_groups = pmib_groups,
}; };
static DEFINE_MUTEX(wpan_phy_mutex); static DEFINE_MUTEX(wpan_phy_mutex);

View File

@ -576,14 +576,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
} }
EXPORT_SYMBOL(rfkill_set_states); EXPORT_SYMBOL(rfkill_set_states);
static ssize_t rfkill_name_show(struct device *dev, static ssize_t name_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%s\n", rfkill->name); return sprintf(buf, "%s\n", rfkill->name);
} }
static DEVICE_ATTR_RO(name);
static const char *rfkill_get_type_str(enum rfkill_type type) 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, static ssize_t type_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); 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, static ssize_t index_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", rfkill->idx); return sprintf(buf, "%d\n", rfkill->idx);
} }
static DEVICE_ATTR_RO(index);
static ssize_t rfkill_persistent_show(struct device *dev, static ssize_t persistent_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", rfkill->persistent); return sprintf(buf, "%d\n", rfkill->persistent);
} }
static DEVICE_ATTR_RO(persistent);
static ssize_t rfkill_hard_show(struct device *dev, static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); 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, static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
} }
static ssize_t rfkill_soft_store(struct device *dev, static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
unsigned long state; unsigned long state;
@ -680,6 +678,7 @@ static ssize_t rfkill_soft_store(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR_RW(soft);
static u8 user_state_from_blocked(unsigned long state) 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; return RFKILL_USER_STATE_UNBLOCKED;
} }
static ssize_t rfkill_state_show(struct device *dev, static ssize_t state_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
} }
static ssize_t rfkill_state_store(struct device *dev, static ssize_t state_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
unsigned long state; unsigned long state;
@ -725,32 +722,27 @@ static ssize_t rfkill_state_store(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR_RW(state);
static ssize_t rfkill_claim_show(struct device *dev, static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", 0); return sprintf(buf, "%d\n", 0);
} }
static DEVICE_ATTR_RO(claim);
static ssize_t rfkill_claim_store(struct device *dev, static struct attribute *rfkill_dev_attrs[] = {
struct device_attribute *attr, &dev_attr_name.attr,
const char *buf, size_t count) &dev_attr_type.attr,
{ &dev_attr_index.attr,
return -EOPNOTSUPP; &dev_attr_persistent.attr,
} &dev_attr_state.attr,
&dev_attr_claim.attr,
static struct device_attribute rfkill_dev_attrs[] = { &dev_attr_soft.attr,
__ATTR(name, S_IRUGO, rfkill_name_show, NULL), &dev_attr_hard.attr,
__ATTR(type, S_IRUGO, rfkill_type_show, NULL), 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
}; };
ATTRIBUTE_GROUPS(rfkill_dev);
static void rfkill_release(struct device *dev) static void rfkill_release(struct device *dev)
{ {
@ -830,7 +822,7 @@ static int rfkill_resume(struct device *dev)
static struct class rfkill_class = { static struct class rfkill_class = {
.name = "rfkill", .name = "rfkill",
.dev_release = rfkill_release, .dev_release = rfkill_release,
.dev_attrs = rfkill_dev_attrs, .dev_groups = rfkill_dev_groups,
.dev_uevent = rfkill_dev_uevent, .dev_uevent = rfkill_dev_uevent,
.suspend = rfkill_suspend, .suspend = rfkill_suspend,
.resume = rfkill_resume, .resume = rfkill_resume,

View File

@ -30,7 +30,8 @@ static ssize_t name ## _show(struct device *dev, \
char *buf) \ char *buf) \
{ \ { \
return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
} } \
static DEVICE_ATTR_RO(name)
SHOW_FMT(index, "%d", wiphy_idx); SHOW_FMT(index, "%d", wiphy_idx);
SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); 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; struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
return sprintf(buf, "%s\n", dev_name(&wiphy->dev)); return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
} }
static DEVICE_ATTR_RO(name);
static ssize_t addresses_show(struct device *dev, static ssize_t addresses_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
@ -60,15 +61,17 @@ static ssize_t addresses_show(struct device *dev,
return buf - start; return buf - start;
} }
static DEVICE_ATTR_RO(addresses);
static struct device_attribute ieee80211_dev_attrs[] = { static struct attribute *ieee80211_attrs[] = {
__ATTR_RO(index), &dev_attr_index.attr,
__ATTR_RO(macaddress), &dev_attr_macaddress.attr,
__ATTR_RO(address_mask), &dev_attr_address_mask.attr,
__ATTR_RO(addresses), &dev_attr_addresses.attr,
__ATTR_RO(name), &dev_attr_name.attr,
{} NULL,
}; };
ATTRIBUTE_GROUPS(ieee80211);
static void wiphy_dev_release(struct device *dev) static void wiphy_dev_release(struct device *dev)
{ {
@ -146,7 +149,7 @@ struct class ieee80211_class = {
.name = "ieee80211", .name = "ieee80211",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_release = wiphy_dev_release, .dev_release = wiphy_dev_release,
.dev_attrs = ieee80211_dev_attrs, .dev_groups = ieee80211_groups,
.dev_uevent = wiphy_uevent, .dev_uevent = wiphy_uevent,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = wiphy_suspend, .suspend = wiphy_suspend,