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

📄 spu_base.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (stat & 4) /* SPU halted */		spu->stop_callback(spu);	if (stat & 8) /* DMA tag group complete */		spu->mfc_callback(spu);	if (stat & 0x10) /* SPU mailbox threshold */		spu->wbox_callback(spu);	spu->stats.class2_intr++;	return stat ? IRQ_HANDLED : IRQ_NONE;}static int spu_request_irqs(struct spu *spu){	int ret = 0;	if (spu->irqs[0] != NO_IRQ) {		snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",			 spu->number);		ret = request_irq(spu->irqs[0], spu_irq_class_0,				  IRQF_DISABLED,				  spu->irq_c0, spu);		if (ret)			goto bail0;	}	if (spu->irqs[1] != NO_IRQ) {		snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",			 spu->number);		ret = request_irq(spu->irqs[1], spu_irq_class_1,				  IRQF_DISABLED,				  spu->irq_c1, spu);		if (ret)			goto bail1;	}	if (spu->irqs[2] != NO_IRQ) {		snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",			 spu->number);		ret = request_irq(spu->irqs[2], spu_irq_class_2,				  IRQF_DISABLED,				  spu->irq_c2, spu);		if (ret)			goto bail2;	}	return 0;bail2:	if (spu->irqs[1] != NO_IRQ)		free_irq(spu->irqs[1], spu);bail1:	if (spu->irqs[0] != NO_IRQ)		free_irq(spu->irqs[0], spu);bail0:	return ret;}static void spu_free_irqs(struct spu *spu){	if (spu->irqs[0] != NO_IRQ)		free_irq(spu->irqs[0], spu);	if (spu->irqs[1] != NO_IRQ)		free_irq(spu->irqs[1], spu);	if (spu->irqs[2] != NO_IRQ)		free_irq(spu->irqs[2], spu);}void spu_init_channels(struct spu *spu){	static const struct {		 unsigned channel;		 unsigned count;	} zero_list[] = {		{ 0x00, 1, }, { 0x01, 1, }, { 0x03, 1, }, { 0x04, 1, },		{ 0x18, 1, }, { 0x19, 1, }, { 0x1b, 1, }, { 0x1d, 1, },	}, count_list[] = {		{ 0x00, 0, }, { 0x03, 0, }, { 0x04, 0, }, { 0x15, 16, },		{ 0x17, 1, }, { 0x18, 0, }, { 0x19, 0, }, { 0x1b, 0, },		{ 0x1c, 1, }, { 0x1d, 0, }, { 0x1e, 1, },	};	struct spu_priv2 __iomem *priv2;	int i;	priv2 = spu->priv2;	/* initialize all channel data to zero */	for (i = 0; i < ARRAY_SIZE(zero_list); i++) {		int count;		out_be64(&priv2->spu_chnlcntptr_RW, zero_list[i].channel);		for (count = 0; count < zero_list[i].count; count++)			out_be64(&priv2->spu_chnldata_RW, 0);	}	/* initialize channel counts to meaningful values */	for (i = 0; i < ARRAY_SIZE(count_list); i++) {		out_be64(&priv2->spu_chnlcntptr_RW, count_list[i].channel);		out_be64(&priv2->spu_chnlcnt_RW, count_list[i].count);	}}EXPORT_SYMBOL_GPL(spu_init_channels);static int spu_shutdown(struct sys_device *sysdev){	struct spu *spu = container_of(sysdev, struct spu, sysdev);	spu_free_irqs(spu);	spu_destroy_spu(spu);	return 0;}static struct sysdev_class spu_sysdev_class = {	set_kset_name("spu"),	.shutdown = spu_shutdown,};int spu_add_sysdev_attr(struct sysdev_attribute *attr){	struct spu *spu;	mutex_lock(&spu_full_list_mutex);	list_for_each_entry(spu, &spu_full_list, full_list)		sysdev_create_file(&spu->sysdev, attr);	mutex_unlock(&spu_full_list_mutex);	return 0;}EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);int spu_add_sysdev_attr_group(struct attribute_group *attrs){	struct spu *spu;	mutex_lock(&spu_full_list_mutex);	list_for_each_entry(spu, &spu_full_list, full_list)		sysfs_create_group(&spu->sysdev.kobj, attrs);	mutex_unlock(&spu_full_list_mutex);	return 0;}EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);void spu_remove_sysdev_attr(struct sysdev_attribute *attr){	struct spu *spu;	mutex_lock(&spu_full_list_mutex);	list_for_each_entry(spu, &spu_full_list, full_list)		sysdev_remove_file(&spu->sysdev, attr);	mutex_unlock(&spu_full_list_mutex);}EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);void spu_remove_sysdev_attr_group(struct attribute_group *attrs){	struct spu *spu;	mutex_lock(&spu_full_list_mutex);	list_for_each_entry(spu, &spu_full_list, full_list)		sysfs_remove_group(&spu->sysdev.kobj, attrs);	mutex_unlock(&spu_full_list_mutex);}EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);static int spu_create_sysdev(struct spu *spu){	int ret;	spu->sysdev.id = spu->number;	spu->sysdev.cls = &spu_sysdev_class;	ret = sysdev_register(&spu->sysdev);	if (ret) {		printk(KERN_ERR "Can't register SPU %d with sysfs\n",				spu->number);		return ret;	}	sysfs_add_device_to_node(&spu->sysdev, spu->node);	return 0;}static int __init create_spu(void *data){	struct spu *spu;	int ret;	static int number;	unsigned long flags;	struct timespec ts;	ret = -ENOMEM;	spu = kzalloc(sizeof (*spu), GFP_KERNEL);	if (!spu)		goto out;	spu->alloc_state = SPU_FREE;	spin_lock_init(&spu->register_lock);	spin_lock(&spu_lock);	spu->number = number++;	spin_unlock(&spu_lock);	ret = spu_create_spu(spu, data);	if (ret)		goto out_free;	spu_mfc_sdr_setup(spu);	spu_mfc_sr1_set(spu, 0x33);	ret = spu_request_irqs(spu);	if (ret)		goto out_destroy;	ret = spu_create_sysdev(spu);	if (ret)		goto out_free_irqs;	mutex_lock(&cbe_spu_info[spu->node].list_mutex);	list_add(&spu->cbe_list, &cbe_spu_info[spu->node].spus);	cbe_spu_info[spu->node].n_spus++;	mutex_unlock(&cbe_spu_info[spu->node].list_mutex);	mutex_lock(&spu_full_list_mutex);	spin_lock_irqsave(&spu_full_list_lock, flags);	list_add(&spu->full_list, &spu_full_list);	spin_unlock_irqrestore(&spu_full_list_lock, flags);	mutex_unlock(&spu_full_list_mutex);	spu->stats.util_state = SPU_UTIL_IDLE_LOADED;	ktime_get_ts(&ts);	spu->stats.tstamp = timespec_to_ns(&ts);	INIT_LIST_HEAD(&spu->aff_list);	goto out;out_free_irqs:	spu_free_irqs(spu);out_destroy:	spu_destroy_spu(spu);out_free:	kfree(spu);out:	return ret;}static const char *spu_state_names[] = {	"user", "system", "iowait", "idle"};static unsigned long long spu_acct_time(struct spu *spu,		enum spu_utilization_state state){	struct timespec ts;	unsigned long long time = spu->stats.times[state];	/*	 * If the spu is idle or the context is stopped, utilization	 * statistics are not updated.  Apply the time delta from the	 * last recorded state of the spu.	 */	if (spu->stats.util_state == state) {		ktime_get_ts(&ts);		time += timespec_to_ns(&ts) - spu->stats.tstamp;	}	return time / NSEC_PER_MSEC;}static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf){	struct spu *spu = container_of(sysdev, struct spu, sysdev);	return sprintf(buf, "%s %llu %llu %llu %llu "		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",		spu_state_names[spu->stats.util_state],		spu_acct_time(spu, SPU_UTIL_USER),		spu_acct_time(spu, SPU_UTIL_SYSTEM),		spu_acct_time(spu, SPU_UTIL_IOWAIT),		spu_acct_time(spu, SPU_UTIL_IDLE_LOADED),		spu->stats.vol_ctx_switch,		spu->stats.invol_ctx_switch,		spu->stats.slb_flt,		spu->stats.hash_flt,		spu->stats.min_flt,		spu->stats.maj_flt,		spu->stats.class2_intr,		spu->stats.libassist);}static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);static int __init init_spu_base(void){	int i, ret = 0;	for (i = 0; i < MAX_NUMNODES; i++) {		mutex_init(&cbe_spu_info[i].list_mutex);		INIT_LIST_HEAD(&cbe_spu_info[i].spus);	}	if (!spu_management_ops)		goto out;	/* create sysdev class for spus */	ret = sysdev_class_register(&spu_sysdev_class);	if (ret)		goto out;	ret = spu_enumerate_spus(create_spu);	if (ret < 0) {		printk(KERN_WARNING "%s: Error initializing spus\n",			__FUNCTION__);		goto out_unregister_sysdev_class;	}	if (ret > 0) {		/*		 * We cannot put the forward declaration in		 * <linux/linux_logo.h> because of conflicting session type		 * conflicts for const and __initdata with different compiler		 * versions		 */		extern const struct linux_logo logo_spe_clut224;		fb_append_extra_logo(&logo_spe_clut224, ret);	}	mutex_lock(&spu_full_list_mutex);	xmon_register_spus(&spu_full_list);	crash_register_spus(&spu_full_list);	mutex_unlock(&spu_full_list_mutex);	spu_add_sysdev_attr(&attr_stat);	spu_init_affinity();	return 0; out_unregister_sysdev_class:	sysdev_class_unregister(&spu_sysdev_class); out:	return ret;}module_init(init_spu_base);MODULE_LICENSE("GPL");MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");

⌨️ 快捷键说明

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