⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 salinfo.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	.open  = salinfo_event_open,	.read  = salinfo_event_read,};static intsalinfo_log_open(struct inode *inode, struct file *file){	struct proc_dir_entry *entry = PDE(inode);	struct salinfo_data *data = entry->data;	if (!capable(CAP_SYS_ADMIN))		return -EPERM;	spin_lock(&data_lock);	if (data->open) {		spin_unlock(&data_lock);		return -EBUSY;	}	data->open = 1;	spin_unlock(&data_lock);	if (data->state == STATE_NO_DATA &&	    !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) {		data->open = 0;		return -ENOMEM;	}	return 0;}static intsalinfo_log_release(struct inode *inode, struct file *file){	struct proc_dir_entry *entry = PDE(inode);	struct salinfo_data *data = entry->data;	if (data->state == STATE_NO_DATA) {		vfree(data->log_buffer);		vfree(data->oemdata);		data->log_buffer = NULL;		data->oemdata = NULL;	}	spin_lock(&data_lock);	data->open = 0;	spin_unlock(&data_lock);	return 0;}static voidcall_on_cpu(int cpu, void (*fn)(void *), void *arg){	cpumask_t save_cpus_allowed = current->cpus_allowed;	cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);	set_cpus_allowed(current, new_cpus_allowed);	(*fn)(arg);	set_cpus_allowed(current, save_cpus_allowed);}static voidsalinfo_log_read_cpu(void *context){	struct salinfo_data *data = context;	sal_log_record_header_t *rh;	data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);	rh = (sal_log_record_header_t *)(data->log_buffer);	/* Clear corrected errors as they are read from SAL */	if (rh->severity == sal_log_severity_corrected)		ia64_sal_clear_state_info(data->type);}static voidsalinfo_log_new_read(int cpu, struct salinfo_data *data){	struct salinfo_data_saved *data_saved;	unsigned long flags;	int i;	int saved_size = ARRAY_SIZE(data->data_saved);	data->saved_num = 0;	spin_lock_irqsave(&data_saved_lock, flags);retry:	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {		if (data_saved->buffer && data_saved->cpu == cpu) {			sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer);			data->log_size = data_saved->size;			memcpy(data->log_buffer, rh, data->log_size);			barrier();	/* id check must not be moved */			if (rh->id == data_saved->id) {				data->saved_num = i+1;				break;			}			/* saved record changed by mca.c since interrupt, discard it */			shift1_data_saved(data, i);			goto retry;		}	}	spin_unlock_irqrestore(&data_saved_lock, flags);	if (!data->saved_num)		call_on_cpu(cpu, salinfo_log_read_cpu, data);	if (!data->log_size) {		data->state = STATE_NO_DATA;		cpu_clear(cpu, data->cpu_event);	} else {		data->state = STATE_LOG_RECORD;	}}static ssize_tsalinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){	struct inode *inode = file->f_path.dentry->d_inode;	struct proc_dir_entry *entry = PDE(inode);	struct salinfo_data *data = entry->data;	u8 *buf;	u64 bufsize;	if (data->state == STATE_LOG_RECORD) {		buf = data->log_buffer;		bufsize = data->log_size;	} else if (data->state == STATE_OEMDATA) {		buf = data->oemdata;		bufsize = data->oemdata_size;	} else {		buf = NULL;		bufsize = 0;	}	return simple_read_from_buffer(buffer, count, ppos, buf, bufsize);}static voidsalinfo_log_clear_cpu(void *context){	struct salinfo_data *data = context;	ia64_sal_clear_state_info(data->type);}static intsalinfo_log_clear(struct salinfo_data *data, int cpu){	sal_log_record_header_t *rh;	unsigned long flags;	spin_lock_irqsave(&data_saved_lock, flags);	data->state = STATE_NO_DATA;	if (!cpu_isset(cpu, data->cpu_event)) {		spin_unlock_irqrestore(&data_saved_lock, flags);		return 0;	}	cpu_clear(cpu, data->cpu_event);	if (data->saved_num) {		shift1_data_saved(data, data->saved_num - 1);		data->saved_num = 0;	}	spin_unlock_irqrestore(&data_saved_lock, flags);	rh = (sal_log_record_header_t *)(data->log_buffer);	/* Corrected errors have already been cleared from SAL */	if (rh->severity != sal_log_severity_corrected)		call_on_cpu(cpu, salinfo_log_clear_cpu, data);	/* clearing a record may make a new record visible */	salinfo_log_new_read(cpu, data);	if (data->state == STATE_LOG_RECORD) {		spin_lock_irqsave(&data_saved_lock, flags);		cpu_set(cpu, data->cpu_event);		salinfo_work_to_do(data);		spin_unlock_irqrestore(&data_saved_lock, flags);	}	return 0;}static ssize_tsalinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos){	struct inode *inode = file->f_path.dentry->d_inode;	struct proc_dir_entry *entry = PDE(inode);	struct salinfo_data *data = entry->data;	char cmd[32];	size_t size;	u32 offset;	int cpu;	size = sizeof(cmd);	if (count < size)		size = count;	if (copy_from_user(cmd, buffer, size))		return -EFAULT;	if (sscanf(cmd, "read %d", &cpu) == 1) {		salinfo_log_new_read(cpu, data);	} else if (sscanf(cmd, "clear %d", &cpu) == 1) {		int ret;		if ((ret = salinfo_log_clear(data, cpu)))			count = ret;	} else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) {		if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA)			return -EINVAL;		if (offset > data->log_size - sizeof(efi_guid_t))			return -EINVAL;		data->state = STATE_OEMDATA;		if (salinfo_platform_oemdata) {			struct salinfo_platform_oemdata_parms parms = {				.efi_guid = data->log_buffer + offset,				.oemdata = &data->oemdata,				.oemdata_size = &data->oemdata_size			};			call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms);			if (parms.ret)				count = parms.ret;		} else			data->oemdata_size = 0;	} else		return -EINVAL;	return count;}static const struct file_operations salinfo_data_fops = {	.open    = salinfo_log_open,	.release = salinfo_log_release,	.read    = salinfo_log_read,	.write   = salinfo_log_write,};static int __cpuinitsalinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu){	unsigned int i, cpu = (unsigned long)hcpu;	unsigned long flags;	struct salinfo_data *data;	switch (action) {	case CPU_ONLINE:	case CPU_ONLINE_FROZEN:		spin_lock_irqsave(&data_saved_lock, flags);		for (i = 0, data = salinfo_data;		     i < ARRAY_SIZE(salinfo_data);		     ++i, ++data) {			cpu_set(cpu, data->cpu_event);			salinfo_work_to_do(data);		}		spin_unlock_irqrestore(&data_saved_lock, flags);		break;	case CPU_DEAD:	case CPU_DEAD_FROZEN:		spin_lock_irqsave(&data_saved_lock, flags);		for (i = 0, data = salinfo_data;		     i < ARRAY_SIZE(salinfo_data);		     ++i, ++data) {			struct salinfo_data_saved *data_saved;			int j;			for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;			     j >= 0;			     --j, --data_saved) {				if (data_saved->buffer && data_saved->cpu == cpu) {					shift1_data_saved(data, j);				}			}			cpu_clear(cpu, data->cpu_event);		}		spin_unlock_irqrestore(&data_saved_lock, flags);		break;	}	return NOTIFY_OK;}static struct notifier_block salinfo_cpu_notifier __cpuinitdata ={	.notifier_call = salinfo_cpu_callback,	.priority = 0,};static int __initsalinfo_init(void){	struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */	struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */	struct proc_dir_entry *dir, *entry;	struct salinfo_data *data;	int i, j;	salinfo_dir = proc_mkdir("sal", NULL);	if (!salinfo_dir)		return 0;	for (i=0; i < NR_SALINFO_ENTRIES; i++) {		/* pass the feature bit in question as misc data */		*sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,						  salinfo_read, (void *)salinfo_entries[i].feature);	}	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {		data = salinfo_data + i;		data->type = i;		init_MUTEX(&data->mutex);		dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);		if (!dir)			continue;		entry = create_proc_entry("event", S_IRUSR, dir);		if (!entry)			continue;		entry->data = data;		entry->proc_fops = &salinfo_event_fops;		*sdir++ = entry;		entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);		if (!entry)			continue;		entry->data = data;		entry->proc_fops = &salinfo_data_fops;		*sdir++ = entry;		/* we missed any events before now */		for_each_online_cpu(j)			cpu_set(j, data->cpu_event);		*sdir++ = dir;	}	*sdir++ = salinfo_dir;	init_timer(&salinfo_timer);	salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;	salinfo_timer.function = &salinfo_timeout;	add_timer(&salinfo_timer);	register_hotcpu_notifier(&salinfo_cpu_notifier);	return 0;}/* * 'data' contains an integer that corresponds to the feature we're * testing */static intsalinfo_read(char *page, char **start, off_t off, int count, int *eof, void *data){	int len = 0;	len = sprintf(page, (sal_platform_features & (unsigned long)data) ? "1\n" : "0\n");	if (len <= off+count) *eof = 1;	*start = page + off;	len   -= off;	if (len>count) len = count;	if (len<0) len = 0;	return len;}module_init(salinfo_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -