/******************************************************************************/
/***以subsys_register为线索:
和驱动架构里的subsys_registet的名字是重复的,driver framework中的是static的****/
/******************************************************************************/
kernel/drivers/base/bus.c
static int subsys_register(struct bus_type *subsys,
const struct attribute_group **groups,
struct kobject *parent_of_root)
{}
/**
* subsys_system_register - register a subsystem at /sys/devices/system/
* @subsys: system subsystem
* @groups: default attributes for the root device
*
* All 'system' subsystems have a /sys/devices/system/<name> root device
* with the name of the subsystem. The root device can carry subsystem-
* wide attributes. All registered devices are below this single root
* device and are named after the subsystem with a simple enumeration
* number appended. The registered devices are not explicitly named;
* only 'id' in the device needs to be set.
*
* Do not use this interface for anything new, it exists for compatibility
* with bad ideas only. New subsystems should use plain subsystems; and
* add the subsystem-wide attributes should be added to the subsystem
* directory itself and not some create fake root-device placed in
* /sys/devices/system/<name>.
*/
int subsys_system_register(struct bus_type *subsys,
const struct attribute_group **groups)
{
return subsys_register(subsys, groups, &system_kset->kobj);
}
EXPORT_SYMBOL_GPL(subsys_system_register);
/******************************************************************************/
kernel/drivers/soc/qcom/subsystem_restart.c
static int __init subsys_restart_init(void)
{
int ret;
ssr_wq = alloc_workqueue("ssr_wq", WQ_CPU_INTENSIVE, 0);
/*registet bus_type*/
ret = bus_register(&subsys_bus_type);
/*create debugfs: msm_subsys*/
ret = subsys_debugfs_init();
char_class = class_create(THIS_MODULE, "subsys");
ret = atomic_notifier_chain_register(&panic_notifier_list,
&panic_nb);
return 0;
}
arch_initcall(subsys_restart_init);
static struct device_attribute subsys_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(state),
__ATTR_RO(crash_count),
__ATTR(restart_level, 0644, restart_level_show, restart_level_store),
__ATTR(firmware_name, 0644, firmware_name_show, firmware_name_store),
__ATTR(system_debug, 0644, system_debug_show, system_debug_store),
__ATTR_NULL,
};
static struct bus_type subsys_bus_type = {
.name = "msm_subsys",
.dev_attrs = subsys_attrs,
};
/**
* struct subsys_desc - subsystem descriptor
* @name: name of subsystem
* @fw_name: firmware name
* @depends_on: subsystem this subsystem depends on to operate
* @dev: parent device
* @owner: module the descriptor belongs to
* @shutdown: Stop a subsystem
* @powerup: Start a subsystem
* @crash_shutdown: Shutdown a subsystem when the system crashes (can't sleep)
* @ramdump: Collect a ramdump of the subsystem
* @free_memory: Free the memory associated with this subsystem
* @is_not_loadable: Indicate if subsystem firmware is not loadable via pil
* framework
* @no_auth: Set if subsystem does not rely on PIL to authenticate and bring
* it out of reset
* @ssctl_instance_id: Instance id used to connect with SSCTL service
* @sysmon_pid: pdev id that sysmon is probed with for the subsystem
* @sysmon_shutdown_ret: Return value for the call to sysmon_send_shutdown
* @system_debug: If "set", triggers a device restart when the
* subsystem's wdog bite handler is invoked.
* @edge: GLINK logical name of the subsystem
*/
struct subsys_desc {
const char *name;
char fw_name[256];
const char *depends_on;
struct device *dev;
struct module *owner;
int (*shutdown)(const struct subsys_desc *desc, bool force_stop);
int (*powerup)(const struct subsys_desc *desc);
void (*crash_shutdown)(const struct subsys_desc *desc);
int (*ramdump)(int, const struct subsys_desc *desc);
void (*free_memory)(const struct subsys_desc *desc);
irqreturn_t (*err_fatal_handler) (int irq, void *dev_id);
irqreturn_t (*stop_ack_handler) (int irq, void *dev_id);
irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id);
int is_not_loadable;
int err_fatal_gpio;
unsigned int err_fatal_irq;
unsigned int err_ready_irq;
unsigned int stop_ack_irq;
unsigned int wdog_bite_irq;
int force_stop_gpio;
int ramdump_disable_gpio;
int shutdown_ack_gpio;
int ramdump_disable;
bool no_auth;
int ssctl_instance_id;
u32 sysmon_pid;
int sysmon_shutdown_ret;
bool system_debug;
const char *edge;
};
/**
* struct subsys_device - subsystem device
* @desc: subsystem descriptor
* @work: context for subsystem_restart_wq_func() for this device
* @ssr_wlock: prevents suspend during subsystem_restart()
* @wlname: name of wakeup source
* @device_restart_work: work struct for device restart
* @track: state tracking and locking
* @notify: subsys notify handle
* @dev: device
* @owner: module that provides @desc
* @count: reference count of subsystem_get()/subsystem_put()
* @id: ida
* @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
* @restart_order: order of other devices this devices restarts with
* @crash_count: number of times the device has crashed
* @dentry: debugfs directory for this device
* @do_ramdump_on_put: ramdump on subsystem_put() if true
* @err_ready: completion variable to record error ready from subsystem
* @crashed: indicates if subsystem has crashed
* @notif_state: current state of subsystem in terms of subsys notifications
*/
struct subsys_device {
struct subsys_desc *desc;
struct work_struct work;
struct wakeup_source ssr_wlock;
char wlname[64];
struct work_struct device_restart_work;
struct subsys_tracking track;
void *notify;
struct device dev;
struct module *owner;
int count;
int id;
int restart_level;
int crash_count;
struct subsys_soc_restart_order *restart_order;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
#endif
bool do_ramdump_on_put;
struct cdev char_dev;
dev_t dev_no;
struct completion err_ready;
bool crashed;
int notif_state;
struct list_head list;
};
struct subsys_device *subsys_register(struct subsys_desc *desc)
{
struct subsys_device *subsys;
struct device_node *ofnode = desc->dev->of_node;
int ret;
subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
subsys->desc = desc;
subsys->owner = desc->owner;
subsys->dev.parent = desc->dev;
subsys->dev.bus = &subsys_bus_type;
subsys->dev.release = subsys_device_release;
subsys->notif_state = -1;
subsys->desc->sysmon_pid = -1;
strlcpy(subsys->desc->fw_name, desc->name,
sizeof(subsys->desc->fw_name));
subsys->notify = subsys_notif_add_subsys(desc->name);
snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
wakeup_source_init(&subsys->ssr_wlock, subsys->wlname);
INIT_WORK(&subsys->work, subsystem_restart_wq_func);
INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr);
spin_lock_init(&subsys->track.s_lock);
subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
dev_set_name(&subsys->dev, "subsys%d", subsys->id);
mutex_init(&subsys->track.lock);
ret = subsys_debugfs_add(subsys);
ret = device_register(&subsys->dev);
ret = subsys_char_device_add(subsys);
if (ofnode) {
}
return subsys
}
root@gemini:/sys/bus/msm_subsys/devices # ls -al
lrwxrwxrwx root root 1970-02-23 07:58 subsys0 -> ../../../devices/soc/ce0000.qcom,venus/subsys0
lrwxrwxrwx root root 1970-02-23 07:58 subsys1 -> ../../../devices/soc/soc:qcom,kgsl-hyp/subsys1
lrwxrwxrwx root root 1970-02-23 07:58 subsys2 -> ../../../devices/soc/soc:qcom,cnss/subsys2
lrwxrwxrwx root root 1970-02-23 07:58 subsys3 -> ../../../devices/soc/9300000.qcom,lpass/subsys3
lrwxrwxrwx root root 1970-02-23 07:58 subsys4 -> ../../../devices/soc/1c00000.qcom,ssc/subsys4
lrwxrwxrwx root root 1970-02-23 07:58 subsys5 -> ../../../devices/soc/2080000.qcom,mss/subsys5
root@gemini:/sys/bus/msm_subsys/devices/subsys0 # ls -al
-r--r--r-- root root 4096 2016-10-31 17:58 crash_count
-rw-r--r-- root root 4096 2016-10-31 17:58 firmware_name
-r--r--r-- root root 4096 1970-02-23 07:58 name
drwxr-xr-x root root 1970-02-23 07:58 power
-rw-r--r-- root root 4096 1970-02-23 07:58 restart_level
-r--r--r-- root root 4096 2016-10-31 17:58 state
lrwxrwxrwx root root 2016-10-31 17:58 subsystem -> ../../../../bus/msm_subsys
-rw-r--r-- root root 4096 2016-10-31 17:58 system_debug
-rw-r--r-- root root 4096 1970-02-23 07:58 uevent
/***以subsys_register为线索:
和驱动架构里的subsys_registet的名字是重复的,driver framework中的是static的****/
/******************************************************************************/
kernel/drivers/base/bus.c
static int subsys_register(struct bus_type *subsys,
const struct attribute_group **groups,
struct kobject *parent_of_root)
{}
/**
* subsys_system_register - register a subsystem at /sys/devices/system/
* @subsys: system subsystem
* @groups: default attributes for the root device
*
* All 'system' subsystems have a /sys/devices/system/<name> root device
* with the name of the subsystem. The root device can carry subsystem-
* wide attributes. All registered devices are below this single root
* device and are named after the subsystem with a simple enumeration
* number appended. The registered devices are not explicitly named;
* only 'id' in the device needs to be set.
*
* Do not use this interface for anything new, it exists for compatibility
* with bad ideas only. New subsystems should use plain subsystems; and
* add the subsystem-wide attributes should be added to the subsystem
* directory itself and not some create fake root-device placed in
* /sys/devices/system/<name>.
*/
int subsys_system_register(struct bus_type *subsys,
const struct attribute_group **groups)
{
return subsys_register(subsys, groups, &system_kset->kobj);
}
EXPORT_SYMBOL_GPL(subsys_system_register);
/******************************************************************************/
kernel/drivers/soc/qcom/subsystem_restart.c
static int __init subsys_restart_init(void)
{
int ret;
ssr_wq = alloc_workqueue("ssr_wq", WQ_CPU_INTENSIVE, 0);
/*registet bus_type*/
ret = bus_register(&subsys_bus_type);
/*create debugfs: msm_subsys*/
ret = subsys_debugfs_init();
char_class = class_create(THIS_MODULE, "subsys");
ret = atomic_notifier_chain_register(&panic_notifier_list,
&panic_nb);
return 0;
}
arch_initcall(subsys_restart_init);
static struct device_attribute subsys_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(state),
__ATTR_RO(crash_count),
__ATTR(restart_level, 0644, restart_level_show, restart_level_store),
__ATTR(firmware_name, 0644, firmware_name_show, firmware_name_store),
__ATTR(system_debug, 0644, system_debug_show, system_debug_store),
__ATTR_NULL,
};
static struct bus_type subsys_bus_type = {
.name = "msm_subsys",
.dev_attrs = subsys_attrs,
};
/**
* struct subsys_desc - subsystem descriptor
* @name: name of subsystem
* @fw_name: firmware name
* @depends_on: subsystem this subsystem depends on to operate
* @dev: parent device
* @owner: module the descriptor belongs to
* @shutdown: Stop a subsystem
* @powerup: Start a subsystem
* @crash_shutdown: Shutdown a subsystem when the system crashes (can't sleep)
* @ramdump: Collect a ramdump of the subsystem
* @free_memory: Free the memory associated with this subsystem
* @is_not_loadable: Indicate if subsystem firmware is not loadable via pil
* framework
* @no_auth: Set if subsystem does not rely on PIL to authenticate and bring
* it out of reset
* @ssctl_instance_id: Instance id used to connect with SSCTL service
* @sysmon_pid: pdev id that sysmon is probed with for the subsystem
* @sysmon_shutdown_ret: Return value for the call to sysmon_send_shutdown
* @system_debug: If "set", triggers a device restart when the
* subsystem's wdog bite handler is invoked.
* @edge: GLINK logical name of the subsystem
*/
struct subsys_desc {
const char *name;
char fw_name[256];
const char *depends_on;
struct device *dev;
struct module *owner;
int (*shutdown)(const struct subsys_desc *desc, bool force_stop);
int (*powerup)(const struct subsys_desc *desc);
void (*crash_shutdown)(const struct subsys_desc *desc);
int (*ramdump)(int, const struct subsys_desc *desc);
void (*free_memory)(const struct subsys_desc *desc);
irqreturn_t (*err_fatal_handler) (int irq, void *dev_id);
irqreturn_t (*stop_ack_handler) (int irq, void *dev_id);
irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id);
int is_not_loadable;
int err_fatal_gpio;
unsigned int err_fatal_irq;
unsigned int err_ready_irq;
unsigned int stop_ack_irq;
unsigned int wdog_bite_irq;
int force_stop_gpio;
int ramdump_disable_gpio;
int shutdown_ack_gpio;
int ramdump_disable;
bool no_auth;
int ssctl_instance_id;
u32 sysmon_pid;
int sysmon_shutdown_ret;
bool system_debug;
const char *edge;
};
/**
* struct subsys_device - subsystem device
* @desc: subsystem descriptor
* @work: context for subsystem_restart_wq_func() for this device
* @ssr_wlock: prevents suspend during subsystem_restart()
* @wlname: name of wakeup source
* @device_restart_work: work struct for device restart
* @track: state tracking and locking
* @notify: subsys notify handle
* @dev: device
* @owner: module that provides @desc
* @count: reference count of subsystem_get()/subsystem_put()
* @id: ida
* @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
* @restart_order: order of other devices this devices restarts with
* @crash_count: number of times the device has crashed
* @dentry: debugfs directory for this device
* @do_ramdump_on_put: ramdump on subsystem_put() if true
* @err_ready: completion variable to record error ready from subsystem
* @crashed: indicates if subsystem has crashed
* @notif_state: current state of subsystem in terms of subsys notifications
*/
struct subsys_device {
struct subsys_desc *desc;
struct work_struct work;
struct wakeup_source ssr_wlock;
char wlname[64];
struct work_struct device_restart_work;
struct subsys_tracking track;
void *notify;
struct device dev;
struct module *owner;
int count;
int id;
int restart_level;
int crash_count;
struct subsys_soc_restart_order *restart_order;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
#endif
bool do_ramdump_on_put;
struct cdev char_dev;
dev_t dev_no;
struct completion err_ready;
bool crashed;
int notif_state;
struct list_head list;
};
struct subsys_device *subsys_register(struct subsys_desc *desc)
{
struct subsys_device *subsys;
struct device_node *ofnode = desc->dev->of_node;
int ret;
subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
subsys->desc = desc;
subsys->owner = desc->owner;
subsys->dev.parent = desc->dev;
subsys->dev.bus = &subsys_bus_type;
subsys->dev.release = subsys_device_release;
subsys->notif_state = -1;
subsys->desc->sysmon_pid = -1;
strlcpy(subsys->desc->fw_name, desc->name,
sizeof(subsys->desc->fw_name));
subsys->notify = subsys_notif_add_subsys(desc->name);
snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
wakeup_source_init(&subsys->ssr_wlock, subsys->wlname);
INIT_WORK(&subsys->work, subsystem_restart_wq_func);
INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr);
spin_lock_init(&subsys->track.s_lock);
subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
dev_set_name(&subsys->dev, "subsys%d", subsys->id);
mutex_init(&subsys->track.lock);
ret = subsys_debugfs_add(subsys);
ret = device_register(&subsys->dev);
ret = subsys_char_device_add(subsys);
if (ofnode) {
}
return subsys
}
root@gemini:/sys/bus/msm_subsys/devices # ls -al
lrwxrwxrwx root root 1970-02-23 07:58 subsys0 -> ../../../devices/soc/ce0000.qcom,venus/subsys0
lrwxrwxrwx root root 1970-02-23 07:58 subsys1 -> ../../../devices/soc/soc:qcom,kgsl-hyp/subsys1
lrwxrwxrwx root root 1970-02-23 07:58 subsys2 -> ../../../devices/soc/soc:qcom,cnss/subsys2
lrwxrwxrwx root root 1970-02-23 07:58 subsys3 -> ../../../devices/soc/9300000.qcom,lpass/subsys3
lrwxrwxrwx root root 1970-02-23 07:58 subsys4 -> ../../../devices/soc/1c00000.qcom,ssc/subsys4
lrwxrwxrwx root root 1970-02-23 07:58 subsys5 -> ../../../devices/soc/2080000.qcom,mss/subsys5
root@gemini:/sys/bus/msm_subsys/devices/subsys0 # ls -al
-r--r--r-- root root 4096 2016-10-31 17:58 crash_count
-rw-r--r-- root root 4096 2016-10-31 17:58 firmware_name
-r--r--r-- root root 4096 1970-02-23 07:58 name
drwxr-xr-x root root 1970-02-23 07:58 power
-rw-r--r-- root root 4096 1970-02-23 07:58 restart_level
-r--r--r-- root root 4096 2016-10-31 17:58 state
lrwxrwxrwx root root 2016-10-31 17:58 subsystem -> ../../../../bus/msm_subsys
-rw-r--r-- root root 4096 2016-10-31 17:58 system_debug
-rw-r--r-- root root 4096 1970-02-23 07:58 uevent