summaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/hil_mlc.c
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2020-10-19 16:57:50 +0200
committerHelge Deller <deller@gmx.de>2020-10-22 22:44:35 +0200
commit879bc2d27904354b98ca295b6168718e045c4aa2 (patch)
treebb1177563374ebfa1916464cc43fe898e76ba7c9 /drivers/input/serio/hil_mlc.c
parentfaade0986e840884438a6e8a21b782c34eb1109c (diff)
downloadlinux-879bc2d27904354b98ca295b6168718e045c4aa2.tar.gz
linux-879bc2d27904354b98ca295b6168718e045c4aa2.tar.bz2
linux-879bc2d27904354b98ca295b6168718e045c4aa2.zip
hil/parisc: Disable HIL driver when it gets stuck
When starting a HP machine with HIL driver but without an HIL keyboard or HIL mouse attached, it may happen that data written to the HIL loop gets stuck (e.g. because the transaction queue is full). Usually one will then have to reboot the machine because all you see is and endless output of: Transaction add failed: transaction already queued? In the higher layers hp_sdc_enqueue_transaction() is called to queued up a HIL packet. This function returns an error code, and this patch adds the necessary checks for this return code and disables the HIL driver if further packets can't be sent. Tested on a HP 730 and a HP 715/64 machine. Signed-off-by: Helge Deller <deller@gmx.de> Cc: <stable@vger.kernel.org>
Diffstat (limited to 'drivers/input/serio/hil_mlc.c')
-rw-r--r--drivers/input/serio/hil_mlc.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65f4e9d62a67..d36e89d6fc54 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(hil_mlc_unregister);
static LIST_HEAD(hil_mlcs);
static DEFINE_RWLOCK(hil_mlcs_lock);
static struct timer_list hil_mlcs_kicker;
-static int hil_mlcs_probe;
+static int hil_mlcs_probe, hil_mlc_stop;
static void hil_mlcs_process(unsigned long unused);
static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
@@ -702,9 +702,13 @@ static int hilse_donode(hil_mlc *mlc)
if (!mlc->ostarted) {
mlc->ostarted = 1;
mlc->opacket = pack;
- mlc->out(mlc);
+ rc = mlc->out(mlc);
nextidx = HILSEN_DOZE;
write_unlock_irqrestore(&mlc->lock, flags);
+ if (rc) {
+ hil_mlc_stop = 1;
+ return 1;
+ }
break;
}
mlc->ostarted = 0;
@@ -715,8 +719,13 @@ static int hilse_donode(hil_mlc *mlc)
case HILSE_CTS:
write_lock_irqsave(&mlc->lock, flags);
- nextidx = mlc->cts(mlc) ? node->bad : node->good;
+ rc = mlc->cts(mlc);
+ nextidx = rc ? node->bad : node->good;
write_unlock_irqrestore(&mlc->lock, flags);
+ if (rc) {
+ hil_mlc_stop = 1;
+ return 1;
+ }
break;
default:
@@ -780,6 +789,12 @@ static void hil_mlcs_process(unsigned long unused)
static void hil_mlcs_timer(struct timer_list *unused)
{
+ if (hil_mlc_stop) {
+ /* could not send packet - stop immediately. */
+ pr_warn(PREFIX "HIL seems stuck - Disabling HIL MLC.\n");
+ return;
+ }
+
hil_mlcs_probe = 1;
tasklet_schedule(&hil_mlcs_tasklet);
/* Re-insert the periodic task. */