Exemple #1
0
/* Helper for device init; the self_node_db is used in hsr_rcv() to recognize
 * frames from self that's been looped over the HSR ring.
 */
int hsr_create_self_node(struct list_head *self_node_db,
			 unsigned char addr_a[ETH_ALEN],
			 unsigned char addr_b[ETH_ALEN])
{
	struct hsr_node *node, *oldnode;

	node = kmalloc(sizeof(*node), GFP_KERNEL);
	if (!node)
		return -ENOMEM;

	ether_addr_copy(node->MacAddressA, addr_a);
	ether_addr_copy(node->MacAddressB, addr_b);

	rcu_read_lock();
	oldnode = list_first_or_null_rcu(self_node_db,
						struct hsr_node, mac_list);
	if (oldnode) {
		list_replace_rcu(&oldnode->mac_list, &node->mac_list);
		rcu_read_unlock();
		synchronize_rcu();
		kfree(oldnode);
	} else {
		rcu_read_unlock();
		list_add_tail_rcu(&node->mac_list, self_node_db);
	}

	return 0;
}
Exemple #2
0
static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
{
	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
	int cpuid, cpuphys;

	cpuid = first_cpu(mask);
	cpuphys = cpu_physical_id(cpuid);

	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
				 sn_irq_lh[irq], list) {
		u64 bridge;
		int local_widget, status;
		nasid_t local_nasid;
		struct sn_irq_info *new_irq_info;
		struct sn_pcibus_provider *pci_provider;

		new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
		if (new_irq_info == NULL)
			break;
		memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));

		bridge = (u64) new_irq_info->irq_bridge;
		if (!bridge) {
			kfree(new_irq_info);
			break; /* irq is not a device interrupt */
		}

		local_nasid = NASID_GET(bridge);

		if (local_nasid & 1)
			local_widget = TIO_SWIN_WIDGETNUM(bridge);
		else
			local_widget = SWIN_WIDGETNUM(bridge);

		/* Free the old PROM new_irq_info structure */
		sn_intr_free(local_nasid, local_widget, new_irq_info);
		/* Update kernels new_irq_info with new target info */
		unregister_intr_pda(new_irq_info);

		/* allocate a new PROM new_irq_info struct */
		status = sn_intr_alloc(local_nasid, local_widget,
				       __pa(new_irq_info), irq,
				       cpuid_to_nasid(cpuid),
				       cpuid_to_slice(cpuid));

		/* SAL call failed */
		if (status) {
			kfree(new_irq_info);
			break;
		}

		new_irq_info->irq_cpuid = cpuid;
		register_intr_pda(new_irq_info);

		pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
		if (pci_provider && pci_provider->target_interrupt)
			(pci_provider->target_interrupt)(new_irq_info);

		spin_lock(&sn_irq_info_lock);
		list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
		spin_unlock(&sn_irq_info_lock);
		call_rcu(&sn_irq_info->rcu, sn_irq_info_free);

#ifdef CONFIG_SMP
		set_irq_affinity_info((irq & 0xff), cpuphys, 0);
#endif
	}
Exemple #3
0
struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
				       nasid_t nasid, int slice)
{
	int vector;
	int cpuid;
#ifdef CONFIG_SMP
	int cpuphys;
#endif
	int64_t bridge;
	int local_widget, status;
	nasid_t local_nasid;
	struct sn_irq_info *new_irq_info;
	struct sn_pcibus_provider *pci_provider;

	new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
	if (new_irq_info == NULL)
		return NULL;

	memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));

	bridge = (u64) new_irq_info->irq_bridge;
	if (!bridge) {
		kfree(new_irq_info);
		return NULL; /* irq is not a device interrupt */
	}

	local_nasid = NASID_GET(bridge);

	if (local_nasid & 1)
		local_widget = TIO_SWIN_WIDGETNUM(bridge);
	else
		local_widget = SWIN_WIDGETNUM(bridge);

	vector = sn_irq_info->irq_irq;
	/* Free the old PROM new_irq_info structure */
	sn_intr_free(local_nasid, local_widget, new_irq_info);
	unregister_intr_pda(new_irq_info);

	/* allocate a new PROM new_irq_info struct */
	status = sn_intr_alloc(local_nasid, local_widget,
			       new_irq_info, vector,
			       nasid, slice);

	/* SAL call failed */
	if (status) {
		kfree(new_irq_info);
		return NULL;
	}

	/* Update kernels new_irq_info with new target info */
	cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
				     new_irq_info->irq_slice);
	new_irq_info->irq_cpuid = cpuid;
	register_intr_pda(new_irq_info);

	pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];

	/*
	 * If this represents a line interrupt, target it.  If it's
	 * an msi (irq_int_bit < 0), it's already targeted.
	 */
	if (new_irq_info->irq_int_bit >= 0 &&
	    pci_provider && pci_provider->target_interrupt)
		(pci_provider->target_interrupt)(new_irq_info);

	spin_lock(&sn_irq_info_lock);
	list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
	spin_unlock(&sn_irq_info_lock);
	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);

#ifdef CONFIG_SMP
	cpuphys = cpu_physical_id(cpuid);
	set_irq_affinity_info((vector & 0xff), cpuphys, 0);
#endif

	return new_irq_info;
}