arch/powerpc/platforms/powernv/opal-prd.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powernv/opal-prd.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/powernv/opal-prd.c
Extension
.c
Size
10066 bytes
Lines
454
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations opal_prd_fops = {
	.open		= opal_prd_open,
	.mmap		= opal_prd_mmap,
	.poll		= opal_prd_poll,
	.read		= opal_prd_read,
	.write		= opal_prd_write,
	.unlocked_ioctl	= opal_prd_ioctl,
	.release	= opal_prd_release,
	.owner		= THIS_MODULE,
};

static struct miscdevice opal_prd_dev = {
	.minor		= MISC_DYNAMIC_MINOR,
	.name		= "opal-prd",
	.fops		= &opal_prd_fops,
};

/* opal interface */
static int opal_prd_msg_notifier(struct notifier_block *nb,
		unsigned long msg_type, void *_msg)
{
	struct opal_prd_msg_queue_item *item;
	struct opal_prd_msg_header *hdr;
	struct opal_msg *msg = _msg;
	int msg_size, item_size;
	unsigned long flags;

	if (msg_type != OPAL_MSG_PRD && msg_type != OPAL_MSG_PRD2)
		return 0;

	/* Calculate total size of the message and item we need to store. The
	 * 'size' field in the header includes the header itself. */
	hdr = (void *)msg->params;
	msg_size = be16_to_cpu(hdr->size);
	item_size = msg_size + sizeof(*item) - sizeof(item->msg);

	item = kzalloc(item_size, GFP_ATOMIC);
	if (!item)
		return -ENOMEM;

	memcpy(&item->msg.data, msg->params, msg_size);

	spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
	list_add_tail(&item->list, &opal_prd_msg_queue);
	spin_unlock_irqrestore(&opal_prd_msg_queue_lock, flags);

	wake_up_interruptible(&opal_prd_msg_wait);

	return 0;
}

static struct notifier_block opal_prd_event_nb = {
	.notifier_call	= opal_prd_msg_notifier,
	.next		= NULL,
	.priority	= 0,
};

static struct notifier_block opal_prd_event_nb2 = {
	.notifier_call	= opal_prd_msg_notifier,
	.next		= NULL,
	.priority	= 0,
};

static int opal_prd_probe(struct platform_device *pdev)
{
	int rc;

	if (!pdev || !pdev->dev.of_node)
		return -ENODEV;

	/* We should only have one prd driver instance per machine; ensure
	 * that we only get a valid probe on a single OF node.
	 */
	if (prd_node)
		return -EBUSY;

	prd_node = pdev->dev.of_node;

	rc = opal_message_notifier_register(OPAL_MSG_PRD, &opal_prd_event_nb);
	if (rc) {
		pr_err("Couldn't register event notifier\n");
		return rc;
	}

	rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb2);
	if (rc) {
		pr_err("Couldn't register PRD2 event notifier\n");
		opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb);
		return rc;
	}

Annotation

Implementation Notes