diff options
Diffstat (limited to 'drivers/tty/hvc/hvc_console.c')
| -rw-r--r-- | drivers/tty/hvc/hvc_console.c | 96 | 
1 files changed, 46 insertions, 50 deletions
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 8880adf5fc6..2d691eb7c40 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -107,7 +107,7 @@ static struct hvc_struct *hvc_get_by_index(int index)  	list_for_each_entry(hp, &hvc_structs, next) {  		spin_lock_irqsave(&hp->lock, flags);  		if (hp->index == index) { -			kref_get(&hp->kref); +			tty_port_get(&hp->port);  			spin_unlock_irqrestore(&hp->lock, flags);  			spin_unlock(&hvc_structs_lock);  			return hp; @@ -229,9 +229,9 @@ static int __init hvc_console_init(void)  console_initcall(hvc_console_init);  /* callback when the kboject ref count reaches zero. */ -static void destroy_hvc_struct(struct kref *kref) +static void hvc_port_destruct(struct tty_port *port)  { -	struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref); +	struct hvc_struct *hp = container_of(port, struct hvc_struct, port);  	unsigned long flags;  	spin_lock(&hvc_structs_lock); @@ -264,7 +264,7 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)  	/* make sure no no tty has been registered in this index */  	hp = hvc_get_by_index(index);  	if (hp) { -		kref_put(&hp->kref, destroy_hvc_struct); +		tty_port_put(&hp->port);  		return -1;  	} @@ -313,20 +313,17 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)  	if (!(hp = hvc_get_by_index(tty->index)))  		return -ENODEV; -	spin_lock_irqsave(&hp->lock, flags); +	spin_lock_irqsave(&hp->port.lock, flags);  	/* Check and then increment for fast path open. */ -	if (hp->count++ > 0) { -		tty_kref_get(tty); -		spin_unlock_irqrestore(&hp->lock, flags); +	if (hp->port.count++ > 0) { +		spin_unlock_irqrestore(&hp->port.lock, flags);  		hvc_kick();  		return 0;  	} /* else count == 0 */ +	spin_unlock_irqrestore(&hp->port.lock, flags);  	tty->driver_data = hp; - -	hp->tty = tty_kref_get(tty); - -	spin_unlock_irqrestore(&hp->lock, flags); +	tty_port_tty_set(&hp->port, tty);  	if (hp->ops->notifier_add)  		rc = hp->ops->notifier_add(hp, hp->data); @@ -338,12 +335,9 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)  	 * tty fields and return the kref reference.  	 */  	if (rc) { -		spin_lock_irqsave(&hp->lock, flags); -		hp->tty = NULL; -		spin_unlock_irqrestore(&hp->lock, flags); -		tty_kref_put(tty); +		tty_port_tty_set(&hp->port, NULL);  		tty->driver_data = NULL; -		kref_put(&hp->kref, destroy_hvc_struct); +		tty_port_put(&hp->port);  		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);  	}  	/* Force wakeup of the polling thread */ @@ -370,12 +364,12 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)  	hp = tty->driver_data; -	spin_lock_irqsave(&hp->lock, flags); +	spin_lock_irqsave(&hp->port.lock, flags); -	if (--hp->count == 0) { +	if (--hp->port.count == 0) { +		spin_unlock_irqrestore(&hp->port.lock, flags);  		/* We are done with the tty pointer now. */ -		hp->tty = NULL; -		spin_unlock_irqrestore(&hp->lock, flags); +		tty_port_tty_set(&hp->port, NULL);  		if (hp->ops->notifier_del)  			hp->ops->notifier_del(hp, hp->data); @@ -390,14 +384,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)  		 */  		tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);  	} else { -		if (hp->count < 0) +		if (hp->port.count < 0)  			printk(KERN_ERR "hvc_close %X: oops, count is %d\n", -				hp->vtermno, hp->count); -		spin_unlock_irqrestore(&hp->lock, flags); +				hp->vtermno, hp->port.count); +		spin_unlock_irqrestore(&hp->port.lock, flags);  	} -	tty_kref_put(tty); -	kref_put(&hp->kref, destroy_hvc_struct); +	tty_port_put(&hp->port);  }  static void hvc_hangup(struct tty_struct *tty) @@ -412,32 +405,31 @@ static void hvc_hangup(struct tty_struct *tty)  	/* cancel pending tty resize work */  	cancel_work_sync(&hp->tty_resize); -	spin_lock_irqsave(&hp->lock, flags); +	spin_lock_irqsave(&hp->port.lock, flags);  	/*  	 * The N_TTY line discipline has problems such that in a close vs  	 * open->hangup case this can be called after the final close so prevent  	 * that from happening for now.  	 */ -	if (hp->count <= 0) { -		spin_unlock_irqrestore(&hp->lock, flags); +	if (hp->port.count <= 0) { +		spin_unlock_irqrestore(&hp->port.lock, flags);  		return;  	} -	temp_open_count = hp->count; -	hp->count = 0; -	hp->n_outbuf = 0; -	hp->tty = NULL; +	temp_open_count = hp->port.count; +	hp->port.count = 0; +	spin_unlock_irqrestore(&hp->port.lock, flags); +	tty_port_tty_set(&hp->port, NULL); -	spin_unlock_irqrestore(&hp->lock, flags); +	hp->n_outbuf = 0;  	if (hp->ops->notifier_hangup)  		hp->ops->notifier_hangup(hp, hp->data);  	while(temp_open_count) {  		--temp_open_count; -		tty_kref_put(tty); -		kref_put(&hp->kref, destroy_hvc_struct); +		tty_port_put(&hp->port);  	}  } @@ -478,7 +470,8 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count  	if (!hp)  		return -EPIPE; -	if (hp->count <= 0) +	/* FIXME what's this (unprotected) check for? */ +	if (hp->port.count <= 0)  		return -EIO;  	spin_lock_irqsave(&hp->lock, flags); @@ -526,13 +519,12 @@ static void hvc_set_winsz(struct work_struct *work)  	hp = container_of(work, struct hvc_struct, tty_resize); -	spin_lock_irqsave(&hp->lock, hvc_flags); -	if (!hp->tty) { -		spin_unlock_irqrestore(&hp->lock, hvc_flags); +	tty = tty_port_tty_get(&hp->port); +	if (!tty)  		return; -	} -	ws  = hp->ws; -	tty = tty_kref_get(hp->tty); + +	spin_lock_irqsave(&hp->lock, hvc_flags); +	ws = hp->ws;  	spin_unlock_irqrestore(&hp->lock, hvc_flags);  	tty_do_resize(tty, &ws); @@ -601,7 +593,7 @@ int hvc_poll(struct hvc_struct *hp)  	}  	/* No tty attached, just skip */ -	tty = tty_kref_get(hp->tty); +	tty = tty_port_tty_get(&hp->port);  	if (tty == NULL)  		goto bail; @@ -681,8 +673,7 @@ int hvc_poll(struct hvc_struct *hp)  		tty_flip_buffer_push(tty);  	} -	if (tty) -		tty_kref_put(tty); +	tty_kref_put(tty);  	return poll_mask;  } @@ -817,6 +808,10 @@ static const struct tty_operations hvc_ops = {  #endif  }; +static const struct tty_port_operations hvc_port_ops = { +	.destruct = hvc_port_destruct, +}; +  struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,  			     const struct hv_ops *ops,  			     int outbuf_size) @@ -842,7 +837,8 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,  	hp->outbuf_size = outbuf_size;  	hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; -	kref_init(&hp->kref); +	tty_port_init(&hp->port); +	hp->port.ops = &hvc_port_ops;  	INIT_WORK(&hp->tty_resize, hvc_set_winsz);  	spin_lock_init(&hp->lock); @@ -875,9 +871,9 @@ int hvc_remove(struct hvc_struct *hp)  	unsigned long flags;  	struct tty_struct *tty; -	spin_lock_irqsave(&hp->lock, flags); -	tty = tty_kref_get(hp->tty); +	tty = tty_port_tty_get(&hp->port); +	spin_lock_irqsave(&hp->lock, flags);  	if (hp->index < MAX_NR_HVC_CONSOLES)  		vtermnos[hp->index] = -1; @@ -891,7 +887,7 @@ int hvc_remove(struct hvc_struct *hp)  	 * kref cause it to be removed, which will probably be the tty_vhangup  	 * below.  	 */ -	kref_put(&hp->kref, destroy_hvc_struct); +	tty_port_put(&hp->port);  	/*  	 * This function call will auto chain call hvc_hangup.  |