TTY: allow selecting on translated minors
Due to the existence of /dev/console and /dev/log, and the new "console=" setting, it is now possible that a single non-PTY object (e.g. serial) is accessible through two different minor numbers. This poses a problem when sending late select replies (CDEV_SEL2_REPLY), because the object's minor number can not be used to identify the device. Since selecting on such objects through translated minor numbers is actually required, we now save the minor number used to initiate the select query in order to send a late reply. The solution is suboptimal, as it is not possible to use two different minors to select on the same object at once. In the future, there should be at least one select record for each minor that can be used with each object. Change-Id: I4d39681d2ffd68b4047daf933d45b7bafe3c885e
This commit is contained in:
parent
913340b559
commit
ec2359d566
2 changed files with 15 additions and 8 deletions
|
@ -873,8 +873,8 @@ int select_retry(struct tty *tp)
|
||||||
int ops;
|
int ops;
|
||||||
|
|
||||||
if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) {
|
if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) {
|
||||||
chardriver_reply_select(tp->tty_select_proc, tp->tty_minor,
|
chardriver_reply_select(tp->tty_select_proc,
|
||||||
ops);
|
tp->tty_select_minor, ops);
|
||||||
tp->tty_select_ops &= ~ops;
|
tp->tty_select_ops &= ~ops;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -891,10 +891,6 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
||||||
if ((tp = line2tty(minor)) == NULL)
|
if ((tp = line2tty(minor)) == NULL)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
|
|
||||||
/* Translated minor numbers are a problem when sending late replies. */
|
|
||||||
if (tp->tty_minor != minor)
|
|
||||||
return EBADF;
|
|
||||||
|
|
||||||
watch = (ops & CDEV_NOTIFY);
|
watch = (ops & CDEV_NOTIFY);
|
||||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||||
|
|
||||||
|
@ -902,11 +898,21 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
||||||
|
|
||||||
ops &= ~ready_ops;
|
ops &= ~ready_ops;
|
||||||
if (ops && watch) {
|
if (ops && watch) {
|
||||||
|
/* Translated minor numbers are a problem with late select replies. We
|
||||||
|
* have to save the minor number used to do the select, since otherwise
|
||||||
|
* VFS won't be able to make sense of those late replies. We do not
|
||||||
|
* support selecting on two different minors for the same object.
|
||||||
|
*/
|
||||||
|
if (tp->tty_select_ops != 0 && tp->tty_select_minor != minor) {
|
||||||
|
printf("TTY: select on one object with two minors (%d, %d)\n",
|
||||||
|
tp->tty_select_minor, minor);
|
||||||
|
return EBADF;
|
||||||
|
}
|
||||||
tp->tty_select_ops |= ops;
|
tp->tty_select_ops |= ops;
|
||||||
tp->tty_select_proc = endpt;
|
tp->tty_select_proc = endpt;
|
||||||
|
tp->tty_select_minor = minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tp->tty_minor == minor);
|
|
||||||
return ready_ops;
|
return ready_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,9 @@ typedef struct tty {
|
||||||
cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */
|
cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */
|
||||||
|
|
||||||
/* select() data */
|
/* select() data */
|
||||||
int tty_select_ops; /* which operations are interesting */
|
unsigned int tty_select_ops; /* which operations are interesting */
|
||||||
endpoint_t tty_select_proc; /* which process wants notification */
|
endpoint_t tty_select_proc; /* which process wants notification */
|
||||||
|
devminor_t tty_select_minor; /* minor used to start select query */
|
||||||
|
|
||||||
/* Miscellaneous. */
|
/* Miscellaneous. */
|
||||||
devfun_t tty_ioctl; /* set line speed, etc. at the device level */
|
devfun_t tty_ioctl; /* set line speed, etc. at the device level */
|
||||||
|
|
Loading…
Reference in a new issue