Skip to content

Commit 879bc2d

Browse files
committed
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>
1 parent faade09 commit 879bc2d

3 files changed

Lines changed: 23 additions & 8 deletions

File tree

drivers/input/serio/hil_mlc.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(hil_mlc_unregister);
7474
static LIST_HEAD(hil_mlcs);
7575
static DEFINE_RWLOCK(hil_mlcs_lock);
7676
static struct timer_list hil_mlcs_kicker;
77-
static int hil_mlcs_probe;
77+
static int hil_mlcs_probe, hil_mlc_stop;
7878

7979
static void hil_mlcs_process(unsigned long unused);
8080
static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
@@ -702,9 +702,13 @@ static int hilse_donode(hil_mlc *mlc)
702702
if (!mlc->ostarted) {
703703
mlc->ostarted = 1;
704704
mlc->opacket = pack;
705-
mlc->out(mlc);
705+
rc = mlc->out(mlc);
706706
nextidx = HILSEN_DOZE;
707707
write_unlock_irqrestore(&mlc->lock, flags);
708+
if (rc) {
709+
hil_mlc_stop = 1;
710+
return 1;
711+
}
708712
break;
709713
}
710714
mlc->ostarted = 0;
@@ -715,8 +719,13 @@ static int hilse_donode(hil_mlc *mlc)
715719

716720
case HILSE_CTS:
717721
write_lock_irqsave(&mlc->lock, flags);
718-
nextidx = mlc->cts(mlc) ? node->bad : node->good;
722+
rc = mlc->cts(mlc);
723+
nextidx = rc ? node->bad : node->good;
719724
write_unlock_irqrestore(&mlc->lock, flags);
725+
if (rc) {
726+
hil_mlc_stop = 1;
727+
return 1;
728+
}
720729
break;
721730

722731
default:
@@ -780,6 +789,12 @@ static void hil_mlcs_process(unsigned long unused)
780789

781790
static void hil_mlcs_timer(struct timer_list *unused)
782791
{
792+
if (hil_mlc_stop) {
793+
/* could not send packet - stop immediately. */
794+
pr_warn(PREFIX "HIL seems stuck - Disabling HIL MLC.\n");
795+
return;
796+
}
797+
783798
hil_mlcs_probe = 1;
784799
tasklet_schedule(&hil_mlcs_tasklet);
785800
/* Re-insert the periodic task. */

drivers/input/serio/hp_sdc_mlc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static int hp_sdc_mlc_cts(hil_mlc *mlc)
210210
priv->tseq[2] = 1;
211211
priv->tseq[3] = 0;
212212
priv->tseq[4] = 0;
213-
__hp_sdc_enqueue_transaction(&priv->trans);
213+
return __hp_sdc_enqueue_transaction(&priv->trans);
214214
busy:
215215
return 1;
216216
done:
@@ -219,7 +219,7 @@ static int hp_sdc_mlc_cts(hil_mlc *mlc)
219219
return 0;
220220
}
221221

222-
static void hp_sdc_mlc_out(hil_mlc *mlc)
222+
static int hp_sdc_mlc_out(hil_mlc *mlc)
223223
{
224224
struct hp_sdc_mlc_priv_s *priv;
225225

@@ -234,7 +234,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
234234
do_data:
235235
if (priv->emtestmode) {
236236
up(&mlc->osem);
237-
return;
237+
return 0;
238238
}
239239
/* Shouldn't be sending commands when loop may be busy */
240240
BUG_ON(down_trylock(&mlc->csem));
@@ -296,7 +296,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
296296
BUG_ON(down_trylock(&mlc->csem));
297297
}
298298
enqueue:
299-
hp_sdc_enqueue_transaction(&priv->trans);
299+
return hp_sdc_enqueue_transaction(&priv->trans);
300300
}
301301

302302
static int __init hp_sdc_mlc_init(void)

include/linux/hil_mlc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct hilse_node {
103103

104104
/* Methods for back-end drivers, e.g. hp_sdc_mlc */
105105
typedef int (hil_mlc_cts) (hil_mlc *mlc);
106-
typedef void (hil_mlc_out) (hil_mlc *mlc);
106+
typedef int (hil_mlc_out) (hil_mlc *mlc);
107107
typedef int (hil_mlc_in) (hil_mlc *mlc, suseconds_t timeout);
108108

109109
struct hil_mlc_devinfo {

0 commit comments

Comments
 (0)