Beispiel #1
0
static void do_profile_hits(int type, void *__pc, unsigned int nr_hits)
{
	unsigned long primary, secondary, flags, pc = (unsigned long)__pc;
	int i, j, cpu;
	struct profile_hit *hits;

	pc = min((pc - (unsigned long)_stext) >> prof_shift, prof_len - 1);
	i = primary = (pc & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT;
	secondary = (~(pc << 1) & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT;
	cpu = get_cpu();
	hits = per_cpu(cpu_profile_hits, cpu)[per_cpu(cpu_profile_flip, cpu)];
	if (!hits) {
		put_cpu();
		return;
	}
	/*
	 * We buffer the global profiler buffer into a per-CPU
	 * queue and thus reduce the number of global (and possibly
	 * NUMA-alien) accesses. The write-queue is self-coalescing:
	 */
	local_irq_save(flags);
	do {
		for (j = 0; j < PROFILE_GRPSZ; ++j) {
			if (hits[i + j].pc == pc) {
				hits[i + j].hits += nr_hits;
				goto out;
			} else if (!hits[i + j].hits) {
				hits[i + j].pc = pc;
				hits[i + j].hits = nr_hits;
				goto out;
			}
		}
		i = (i + secondary) & (NR_PROFILE_HIT - 1);
	} while (i != primary);

	/*
	 * Add the current hit(s) and flush the write-queue out
	 * to the global buffer:
	 */
	atomic_add_unchecked(nr_hits, &prof_buffer[pc]);
	for (i = 0; i < NR_PROFILE_HIT; ++i) {
		atomic_add_unchecked(hits[i].hits, &prof_buffer[hits[i].pc]);
		hits[i].pc = hits[i].hits = 0;
	}
out:
	local_irq_restore(flags);
	put_cpu();
}
Beispiel #2
0
static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int zero)
{
	struct sonet_stats tmp;
 	int error = 0;

	atomic_add_unchecked(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
	sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp);
	if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
	if (zero && !error) {
		/* unused fields are reported as -1, but we must not "adjust"
		   them */
		tmp.corr_hcs = tmp.tx_cells = tmp.rx_cells = 0;
		sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp);
	}
	return error ? -EFAULT : 0;
}
Beispiel #3
0
static void profile_flip_buffers(void)
{
	int i, j, cpu;

	mutex_lock(&profile_flip_mutex);
	j = per_cpu(cpu_profile_flip, get_cpu());
	put_cpu();
	on_each_cpu(__profile_flip_buffers, NULL, 1);
	for_each_online_cpu(cpu) {
		struct profile_hit *hits = per_cpu(cpu_profile_hits, cpu)[j];
		for (i = 0; i < NR_PROFILE_HIT; ++i) {
			if (!hits[i].hits) {
				if (hits[i].pc)
					hits[i].pc = 0;
				continue;
			}
			atomic_add_unchecked(hits[i].hits, &prof_buffer[hits[i].pc]);
			hits[i].hits = hits[i].pc = 0;
		}
	}
	mutex_unlock(&profile_flip_mutex);
}
Beispiel #4
0
static void uPD98402_int(struct atm_dev *dev)
{
	static unsigned long silence = 0;
	unsigned char reason;

	while ((reason = GET(PICR))) {
		if (reason & uPD98402_INT_LOS)
			printk(KERN_NOTICE "%s(itf %d): signal lost\n",
			    dev->type,dev->number);
		if (reason & uPD98402_INT_PFM) stat_event(dev);
		if (reason & uPD98402_INT_PCO) {
			(void) GET(PCOCR); /* clear interrupt cause */
			atomic_add_unchecked(GET(HECCT),
			    &PRIV(dev)->sonet_stats.uncorr_hcs);
		}
		if ((reason & uPD98402_INT_RFO) && 
		    (time_after(jiffies, silence) || silence == 0)) {
			printk(KERN_WARNING "%s(itf %d): uPD98402 receive "
			    "FIFO overflow\n",dev->type,dev->number);
			silence = (jiffies+HZ/2)|1;
		}
	}
}
Beispiel #5
0
static void do_profile_hits(int type, void *__pc, unsigned int nr_hits)
{
	unsigned long pc;
	pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
	atomic_add_unchecked(nr_hits, &prof_buffer[min(pc, prof_len - 1)]);
}