drivers/tty/hvc/hvcs.c

Source file repositories/reference/linux-study-clean/drivers/tty/hvc/hvcs.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/hvc/hvcs.c
Extension
.c
Size
43925 bytes
Lines
1546
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static ssize_t rescan_show(struct device_driver *ddp, char *buf)
{
	/* A 1 means it is updating, a 0 means it is done updating */
	return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
}

static ssize_t rescan_store(struct device_driver *ddp, const char * buf,
		size_t count)
{
	if ((simple_strtol(buf, NULL, 0) != 1)
		&& (hvcs_rescan_status != 0))
		return -EINVAL;

	hvcs_rescan_status = 1;
	printk(KERN_INFO "HVCS: rescanning partner info for all"
		" vty-servers.\n");
	hvcs_rescan_devices_list();
	hvcs_rescan_status = 0;
	return count;
}

static DRIVER_ATTR_RW(rescan);

static struct attribute *hvcs_attrs[] = {
	&driver_attr_rescan.attr,
	NULL,
};

ATTRIBUTE_GROUPS(hvcs);

static void hvcs_kick(void)
{
	hvcs_kicked = 1;
	wmb();
	wake_up_process(hvcs_task);
}

static void hvcs_unthrottle(struct tty_struct *tty)
{
	struct hvcs_struct *hvcsd = tty->driver_data;
	unsigned long flags;

	spin_lock_irqsave(&hvcsd->lock, flags);
	hvcsd->todo_mask |= HVCS_SCHED_READ;
	spin_unlock_irqrestore(&hvcsd->lock, flags);
	hvcs_kick();
}

static void hvcs_throttle(struct tty_struct *tty)
{
	struct hvcs_struct *hvcsd = tty->driver_data;
	unsigned long flags;

	spin_lock_irqsave(&hvcsd->lock, flags);
	vio_disable_interrupts(hvcsd->vdev);
	spin_unlock_irqrestore(&hvcsd->lock, flags);
}

/*
 * If the device is being removed we don't have to worry about this interrupt
 * handler taking any further interrupts because they are disabled which means
 * the hvcs_struct will always be valid in this handler.
 */
static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
{
	struct hvcs_struct *hvcsd = dev_instance;

	spin_lock(&hvcsd->lock);
	vio_disable_interrupts(hvcsd->vdev);
	hvcsd->todo_mask |= HVCS_SCHED_READ;
	spin_unlock(&hvcsd->lock);
	hvcs_kick();

	return IRQ_HANDLED;
}

/* This function must be called with the hvcsd->lock held */
static void hvcs_try_write(struct hvcs_struct *hvcsd)
{
	uint32_t unit_address = hvcsd->vdev->unit_address;
	struct tty_struct *tty = hvcsd->port.tty;
	int sent;

	if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
		/* won't send partial writes */
		sent = hvc_put_chars(unit_address,
				&hvcsd->buffer[0],
				hvcsd->chars_in_buffer );
		if (sent > 0) {
			hvcsd->chars_in_buffer = 0;

Annotation

Implementation Notes