summaryrefslogtreecommitdiff
path: root/drivers/staging/speakup/spk_ttyio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-05 10:36:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-05 10:36:26 -0700
commitbf1d6b2c76eda86159519bf5c427b1fa8f51f733 (patch)
tree030fb04185223a03254aa1092750d9c1b819618c /drivers/staging/speakup/spk_ttyio.c
parente63a94f12b5fc67b2b92a89d4058e7a9021e900e (diff)
parent28eb51f7468a43769bd9dca19a54d97ec7a447ed (diff)
Merge tag 'staging-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging/IIO driver updates from Greg KH: "Here is the big staging and IIO driver update for 4.14-rc1. Lots of staging driver fixes and cleanups, including some reorginizing of the lustre header files to try to impose some sanity on what is, and what is not, the uapi for that filesystem. There are some tty core changes in here as well, as the speakup drivers need them, and that's ok with me, they are sane and the speakup code is getting nicer because of it. There is also the addition of the obiligatory new wifi driver, just because it has been a release or two since we added our last one... Other than that, lots and lots of small coding style fixes, as usual. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (612 commits) staging:rtl8188eu:core Fix remove unneccessary else block staging: typec: fusb302: make structure fusb302_psy_desc static staging: unisys: visorbus: make two functions static staging: fsl-dpaa2/eth: fix off-by-one FD ctrl bitmaks staging: r8822be: Simplify deinit_priv() staging: r8822be: Remove some dead code staging: vboxvideo: Use CONFIG_DRM_KMS_FB_HELPER to check for fbdefio availability staging:rtl8188eu Fix comparison to NULL staging: rts5208: rename mmc_ddr_tunning_rx_cmd to mmc_ddr_tuning_rx_cmd Staging: Pi433: style fix - tabs and spaces staging: pi433: fix spelling mistake: "preample" -> "preamble" staging:rtl8188eu:core Fix Code Indent staging: typec: fusb302: Export current-limit through a power_supply class dev staging: typec: fusb302: Add support for USB2 charger detection through extcon staging: typec: fusb302: Use client->irq as irq if set staging: typec: fusb302: Get max snk mv/ma/mw from device-properties staging: typec: fusb302: Set max supply voltage to 5V staging: typec: tcpm: Add get_current_limit tcpc_dev callback staging:rtl8188eu Use __func__ instead of function name staging: lustre: coding style fixes found by checkpatch.pl ...
Diffstat (limited to 'drivers/staging/speakup/spk_ttyio.c')
-rw-r--r--drivers/staging/speakup/spk_ttyio.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index fe340b07c482..4d7d8f2f66ea 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -7,11 +7,6 @@
#include "spk_types.h"
#include "spk_priv.h"
-#define DEV_PREFIX_LP "lp"
-
-static const char * const lp_supported[] = { "acntsa", "bns", "dummy",
- "txprt" };
-
struct spk_ldisc_data {
char buf;
struct semaphore sem;
@@ -20,6 +15,11 @@ struct spk_ldisc_data {
static struct spk_synth *spk_ttyio_synth;
static struct tty_struct *speakup_tty;
+/* mutex to protect against speakup_tty disappearing from underneath us while
+ * we are using it. this can happen when the device physically unplugged,
+ * while in use. it also serialises access to speakup_tty.
+ */
+static DEFINE_MUTEX(speakup_tty_mutex);
static int ser_to_dev(int ser, dev_t *dev_no)
{
@@ -36,24 +36,8 @@ static int get_dev_to_use(struct spk_synth *synth, dev_t *dev_no)
{
/* use ser only when dev is not specified */
if (strcmp(synth->dev_name, SYNTH_DEFAULT_DEV) ||
- synth->ser == SYNTH_DEFAULT_SER) {
- /* for /dev/lp* check if synth is supported */
- if (strncmp(synth->dev_name, DEV_PREFIX_LP,
- strlen(DEV_PREFIX_LP)) == 0)
- if (match_string(lp_supported, ARRAY_SIZE(lp_supported),
- synth->name) < 0) {
- int i;
-
- pr_err("speakup: lp* is only supported on:");
- for (i = 0; i < ARRAY_SIZE(lp_supported); i++)
- pr_cont(" %s", lp_supported[i]);
- pr_cont("\n");
-
- return -ENOTSUPP;
- }
-
+ synth->ser == SYNTH_DEFAULT_SER)
return tty_dev_name_to_number(synth->dev_name, dev_no);
- }
return ser_to_dev(synth->ser, dev_no);
}
@@ -81,8 +65,10 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ mutex_lock(&speakup_tty_mutex);
kfree(speakup_tty->disc_data);
speakup_tty = NULL;
+ mutex_unlock(&speakup_tty_mutex);
}
static int spk_ttyio_receive_buf2(struct tty_struct *tty,
@@ -158,7 +144,7 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
if (ret)
return ret;
- tty = tty_open_by_driver(dev, NULL, NULL);
+ tty = tty_kopen(dev);
if (IS_ERR(tty))
return PTR_ERR(tty);
@@ -210,9 +196,11 @@ void spk_ttyio_unregister_ldisc(void)
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
{
+ mutex_lock(&speakup_tty_mutex);
if (in_synth->alive && speakup_tty && speakup_tty->ops->write) {
int ret = speakup_tty->ops->write(speakup_tty, &ch, 1);
+ mutex_unlock(&speakup_tty_mutex);
if (ret == 0)
/* No room */
return 0;
@@ -228,17 +216,50 @@ static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
}
return 1;
}
+
+ mutex_unlock(&speakup_tty_mutex);
+ return 0;
+}
+
+static int check_tty(struct tty_struct *tty)
+{
+ if (!tty) {
+ pr_warn("%s: I/O error, deactivating speakup\n",
+ spk_ttyio_synth->long_name);
+ /* No synth any more, so nobody will restart TTYs, and we thus
+ * need to do it ourselves. Now that there is no synth we can
+ * let application flood anyway
+ */
+ spk_ttyio_synth->alive = 0;
+ speakup_start_ttys();
+ return 1;
+ }
+
return 0;
}
static void spk_ttyio_send_xchar(char ch)
{
+ mutex_lock(&speakup_tty_mutex);
+ if (check_tty(speakup_tty)) {
+ mutex_unlock(&speakup_tty_mutex);
+ return;
+ }
+
speakup_tty->ops->send_xchar(speakup_tty, ch);
+ mutex_unlock(&speakup_tty_mutex);
}
static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
{
+ mutex_lock(&speakup_tty_mutex);
+ if (check_tty(speakup_tty)) {
+ mutex_unlock(&speakup_tty_mutex);
+ return;
+ }
+
speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+ mutex_unlock(&speakup_tty_mutex);
}
static unsigned char ttyio_in(int timeout)
@@ -278,8 +299,16 @@ static unsigned char spk_ttyio_in_nowait(void)
static void spk_ttyio_flush_buffer(void)
{
+ mutex_lock(&speakup_tty_mutex);
+ if (check_tty(speakup_tty)) {
+ mutex_unlock(&speakup_tty_mutex);
+ return;
+ }
+
if (speakup_tty->ops->flush_buffer)
speakup_tty->ops->flush_buffer(speakup_tty);
+
+ mutex_unlock(&speakup_tty_mutex);
}
int spk_ttyio_synth_probe(struct spk_synth *synth)
@@ -308,7 +337,7 @@ void spk_ttyio_release(void)
tty_ldisc_flush(speakup_tty);
tty_unlock(speakup_tty);
- tty_release_struct(speakup_tty, speakup_tty->index);
+ tty_kclose(speakup_tty);
}
EXPORT_SYMBOL_GPL(spk_ttyio_release);