lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Fri, 24 Jul 2009 18:13:22 +0200
From:	Richard Röjfors 
	<richard.rojfors.ext@...ean-labs.com>
To:	linux-input@...r.kernel.org
Cc:	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Dmitry Torokhov <dmitry.torokhov@...il.com>,
	kwangwoo.lee@...il.com,
	Thierry Reding <thierry.reding@...onic-design.de>,
	Trilok Soni <soni.trilok@...il.com>
Subject: [PATCH 1/2] tsc2007: IRQ balancing when stopping work during removal

The implementation is proposed by Dmitry Torokhov, I have just made some 
changes so it applied to my previous patches, and I tried it out.

The idea is to balance the IRQ:s in the case where the poll worker is 
running, so it won't get disabled twice.

Also using __devinit/__devexit macros on probe/remove functions.

Signed-off-by: Richard Röjfors <richard.rojfors.ext@...ean-labs.com>
---
Index: linux-2.6.31-rc2/drivers/input/touchscreen/tsc2007.c
===================================================================
--- linux-2.6.31-rc2/drivers/input/touchscreen/tsc2007.c	(revision 997)
+++ linux-2.6.31-rc2/drivers/input/touchscreen/tsc2007.c	(revision 1040)
@@ -61,7 +61,7 @@

  #define PEN_STATE_UP	0x00
  #define PEN_STATE_DOWN	0x01
-#define PEN_STATE_IRQ	0x01
+#define PEN_STATE_IRQ	0x02

  struct ts_event {
  	u16	x;
@@ -141,8 +141,6 @@
  	 */
  	if (rt > MAX_12BIT) {
  		dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
-
-		schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
  		return;
  	}

@@ -178,8 +176,6 @@
  	} else if (!ts->get_pendown_state)
  		/* no callback to check pendown state, use pressure */
  		ts->penstate = PEN_STATE_UP;
-
-	schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
  }

  static int tsc2007_read_values(struct tsc2007 *tsc)
@@ -228,6 +224,7 @@

  		tsc2007_read_values(ts);
  		tsc2007_send_event(ts);
+		schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
  	}
  }

@@ -238,7 +235,7 @@
  	if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
  		disable_irq_nosync(ts->irq);
  		ts->penstate = PEN_STATE_IRQ;
-		schedule_delayed_work(&ts->work, 0);
+		schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
  	}

  	if (ts->clear_penirq)
@@ -247,15 +244,25 @@
  	return IRQ_HANDLED;
  }

-static int tsc2007_probe(struct i2c_client *client,
+static void tsc2007_free_irq(struct tsc2007 *ts)
+{
+	free_irq(ts->irq, ts);
+	if (cancel_delayed_work_sync(&ts->work))
+		/* Work was pending, therefore we need to enable IRQ here to
+		 * balance the disable done in the interrupt handler.
+		 */
+		enable_irq(ts->irq);
+}
+
+static int __devinit tsc2007_probe(struct i2c_client *client,
  			const struct i2c_device_id *id)
  {
  	struct tsc2007 *ts;
-	struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
+	struct tsc2007_platform_data *pdata = client->dev.platform_data;
  	struct input_dev *input_dev;
  	int err;

-	if (!pdata || !pdata->get_pendown_state) {
+	if (!pdata) {
  		dev_err(&client->dev, "platform data is required!\n");
  		return -EINVAL;
  	}
@@ -320,25 +327,24 @@
  	return 0;

   err_free_irq:
-	free_irq(ts->irq, ts);
+	tsc2007_free_irq(ts);
   err_free_mem:
+	if (pdata->exit_platform_hw)
+		pdata->exit_platform_hw();
  	input_free_device(input_dev);
  	kfree(ts);
  	return err;
  }

-static int tsc2007_remove(struct i2c_client *client)
+static int __devexit tsc2007_remove(struct i2c_client *client)
  {
  	struct tsc2007	*ts = i2c_get_clientdata(client);
-	struct tsc2007_platform_data *pdata;
+	struct tsc2007_platform_data *pdata = client->dev.platform_data;

-	cancel_delayed_work_sync(&ts->work);
-
-	pdata = client->dev.platform_data;
+	tsc2007_free_irq(ts);
  	if (pdata->exit_platform_hw)
  		pdata->exit_platform_hw();

-	free_irq(ts->irq, ts);
  	input_unregister_device(ts->input);
  	kfree(ts);

@@ -359,7 +365,7 @@
  	},
  	.id_table	= tsc2007_idtable,
  	.probe		= tsc2007_probe,
-	.remove		= tsc2007_remove,
+	.remove		= __devexit_p(tsc2007_remove),
  };

  static int __init tsc2007_init(void)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ