コード例 #1
0
ファイル: salinfo.c プロジェクト: camelguo/linux-2.6-trimedia
static int
salinfo_log_clear(struct salinfo_data *data, int cpu)
{
	sal_log_record_header_t *rh;
	data->state = STATE_NO_DATA;
	if (!test_bit(cpu, &data->cpu_event))
		return 0;
	down(&data->sem);
	clear_bit(cpu, &data->cpu_event);
	if (data->saved_num) {
		unsigned long flags;
		spin_lock_irqsave(&data_saved_lock, flags);
		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 &&
	    !test_and_set_bit(cpu,  &data->cpu_event))
		up(&data->sem);
	return 0;
}
コード例 #2
0
ファイル: salinfo.c プロジェクト: 0x7f454c46/linux
static int
salinfo_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 (!cpumask_test_cpu(cpu, &data->cpu_event)) {
		spin_unlock_irqrestore(&data_saved_lock, flags);
		return 0;
	}
	cpumask_clear_cpu(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)
		work_on_cpu_safe(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);
		cpumask_set_cpu(cpu, &data->cpu_event);
		wake_up_interruptible(&data->read_wait);
		spin_unlock_irqrestore(&data_saved_lock, flags);
	}
	return 0;
}
コード例 #3
0
ファイル: salinfo.c プロジェクト: dduval/kernel-rhel3
static int
salinfo_log_clear(struct salinfo_data *data, int cpu)
{
	data->state = STATE_NO_DATA;
	if (!test_bit(cpu, &data->cpu_event))
		return 0;
	down(&data->sem);
	clear_bit(cpu, &data->cpu_event);
	if (data->saved_num) {
		unsigned long flags;
		spin_lock_irqsave(&data_saved_lock, flags);
		shift1_data_saved(data, data->saved_num - 1 );
		data->saved_num = 0;
		spin_unlock_irqrestore(&data_saved_lock, flags);
	}
	/* ia64_mca_log_sal_error_record or salinfo_log_read_cpu already cleared
	 * CPE and CMC errors
	 */
	if (data->type != SAL_INFO_TYPE_CPE && data->type != SAL_INFO_TYPE_CMC)
		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 &&
	    !test_and_set_bit(cpu,  &data->cpu_event))
		up(&data->sem);
	return 0;
}
コード例 #4
0
ファイル: salinfo.c プロジェクト: dduval/kernel-rhel3
/* This routine is invoked in interrupt context.  Note: mca.c enables
 * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
 * not irq safe, do not call any routines that use spinlocks, they may deadlock.
 * MCA and INIT records are recorded, a timer event will look for any
 * outstanding events and wake up the user space code.
 *
 * The buffer passed from mca.c points to the output from ia64_log_get. This is
 * a persistent buffer but its contents can change between the interrupt and
 * when user space processes the record.  Save the record id to identify
 * changes.
 */
void
salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
{
	struct salinfo_data *data = salinfo_data + type;
	struct salinfo_data_saved *data_saved;
	unsigned long flags = 0;
	int i;
	int saved_size = ARRAY_SIZE(data->data_saved);

	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));

	if (irqsafe)
		spin_lock_irqsave(&data_saved_lock, flags);
	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
		if (!data_saved->buffer)
			break;
	}
	if (i == saved_size) {
		if (!data->saved_num) {
			shift1_data_saved(data, 0);
			data_saved = data->data_saved + saved_size - 1;
		} else
			data_saved = NULL;
	}
	if (data_saved) {
		data_saved->cpu = smp_processor_id();
		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
		data_saved->size = size;
		if (irqsafe && (data_saved->buffer = kmalloc(size, GFP_ATOMIC))) {
			memcpy(data_saved->buffer, buffer, size);
			data_saved->kmalloced = 1;
		} else {
		data_saved->buffer = buffer;
			data_saved->kmalloced = 0;
		}
	}
	if (irqsafe)
		spin_unlock_irqrestore(&data_saved_lock, flags);

	if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
		if (irqsafe)
			up(&data->sem);
	}
}
コード例 #5
0
ファイル: salinfo.c プロジェクト: 10x-Amin/nAa-kernel
/* This routine is invoked in interrupt context.  Note: mca.c enables
 * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
 * not irq safe, do not call any routines that use spinlocks, they may deadlock.
 * MCA and INIT records are recorded, a timer event will look for any
 * outstanding events and wake up the user space code.
 *
 * The buffer passed from mca.c points to the output from ia64_log_get. This is
 * a persistent buffer but its contents can change between the interrupt and
 * when user space processes the record.  Save the record id to identify
 * changes.  If the buffer is NULL then just update the bitmap.
 */
void
salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
{
	struct salinfo_data *data = salinfo_data + type;
	struct salinfo_data_saved *data_saved;
	unsigned long flags = 0;
	int i;
	int saved_size = ARRAY_SIZE(data->data_saved);

	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));

	if (irqsafe)
		spin_lock_irqsave(&data_saved_lock, flags);
	if (buffer) {
		for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
			if (!data_saved->buffer)
				break;
		}
		if (i == saved_size) {
			if (!data->saved_num) {
				shift1_data_saved(data, 0);
				data_saved = data->data_saved + saved_size - 1;
			} else
				data_saved = NULL;
		}
		if (data_saved) {
			data_saved->cpu = smp_processor_id();
			data_saved->id = ((sal_log_record_header_t *)buffer)->id;
			data_saved->size = size;
			data_saved->buffer = buffer;
		}
	}
	cpu_set(smp_processor_id(), data->cpu_event);
	if (irqsafe) {
		salinfo_work_to_do(data);
		spin_unlock_irqrestore(&data_saved_lock, flags);
	}
}
コード例 #6
0
ファイル: salinfo.c プロジェクト: camelguo/linux-2.6-trimedia
static void
salinfo_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;
	        clear_bit(cpu, &data->cpu_event);
	} else {
	        data->state = STATE_LOG_RECORD;
	}
}