Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Nov 2019 20:53:13 +0000 (UTC)
From:      Vladimir Kondratyev <wulf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r354302 - head/sys/dev/ichiic
Message-ID:  <201911032053.xA3KrDLq065045@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: wulf
Date: Sun Nov  3 20:53:13 2019
New Revision: 354302
URL: https://svnweb.freebsd.org/changeset/base/354302

Log:
  [ig4] Allow enabling of polled mode from iicbus allocation callback
  
  If controller is allocated with IIC_NOWAIT option ig4 enables polled mode
  for a period of allocation that makes possible to start I2C transfers
  from the contexts where sleeping is not allowed e.g. from ithreads or
  callouts.

Modified:
  head/sys/dev/ichiic/ig4_acpi.c
  head/sys/dev/ichiic/ig4_iic.c
  head/sys/dev/ichiic/ig4_pci.c
  head/sys/dev/ichiic/ig4_var.h

Modified: head/sys/dev/ichiic/ig4_acpi.c
==============================================================================
--- head/sys/dev/ichiic/ig4_acpi.c	Sun Nov  3 20:51:22 2019	(r354301)
+++ head/sys/dev/ichiic/ig4_acpi.c	Sun Nov  3 20:53:13 2019	(r354302)
@@ -154,7 +154,7 @@ static device_method_t ig4iic_acpi_methods[] = {
 	/* iicbus interface */
 	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
 	DEVMETHOD(iicbus_reset, ig4iic_reset),
-	DEVMETHOD(iicbus_callback, iicbus_null_callback),
+	DEVMETHOD(iicbus_callback, ig4iic_callback),
 
 	DEVMETHOD_END
 };

Modified: head/sys/dev/ichiic/ig4_iic.c
==============================================================================
--- head/sys/dev/ichiic/ig4_iic.c	Sun Nov  3 20:51:22 2019	(r354301)
+++ head/sys/dev/ichiic/ig4_iic.c	Sun Nov  3 20:53:13 2019	(r354302)
@@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$");
 #define TRANS_PCALL	2
 #define TRANS_BLOCK	3
 
-#define DO_POLL(sc)	(cold || kdb_active || SCHEDULER_STOPPED())
+#define DO_POLL(sc)	(cold || kdb_active || SCHEDULER_STOPPED() || sc->poll)
 
 static void ig4iic_start(void *xdev);
 static void ig4iic_intr(void *cookie);
@@ -350,6 +350,7 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, ui
 	int unit;
 	bool rpstart;
 	bool stop;
+	bool allocated;
 
 	/*
 	 * The hardware interface imposes limits on allowed I2C messages.
@@ -410,7 +411,10 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, ui
 		return (IIC_ENOTSUPP);
 	}
 
-	sx_xlock(&sc->call_lock);
+	/* Check if device is already allocated with iicbus_request_bus() */
+	allocated = sx_xlocked(&sc->call_lock) != 0;
+	if (!allocated)
+		sx_xlock(&sc->call_lock);
 
 	/* Debugging - dump registers. */
 	if (ig4_dump) {
@@ -458,7 +462,8 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, ui
 		rpstart = !stop;
 	}
 
-	sx_unlock(&sc->call_lock);
+	if (!allocated)
+		sx_unlock(&sc->call_lock);
 	return (error);
 }
 
@@ -466,8 +471,11 @@ int
 ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
 {
 	ig4iic_softc_t *sc = device_get_softc(dev);
+	bool allocated;
 
-	sx_xlock(&sc->call_lock);
+	allocated = sx_xlocked(&sc->call_lock) != 0;
+	if (!allocated)
+		sx_xlock(&sc->call_lock);
 
 	/* TODO handle speed configuration? */
 	if (oldaddr != NULL)
@@ -476,8 +484,41 @@ ig4iic_reset(device_t dev, u_char speed, u_char addr, 
 	if (addr == IIC_UNKNOWN)
 		sc->slave_valid = false;
 
-	sx_unlock(&sc->call_lock);
+	if (!allocated)
+		sx_unlock(&sc->call_lock);
 	return (0);
+}
+
+int
+ig4iic_callback(device_t dev, int index, caddr_t data)
+{
+	ig4iic_softc_t *sc = device_get_softc(dev);
+	int error = 0;
+	int how;
+
+	switch (index) {
+	case IIC_REQUEST_BUS:
+		/* force polling if ig4iic is requested with IIC_DONTWAIT */
+		how = *(int *)data;
+		if ((how & IIC_WAIT) == 0) {
+			if (sx_try_xlock(&sc->call_lock) == 0)
+				error = IIC_EBUSBSY;
+			else
+				sc->poll = true;
+		} else
+			sx_xlock(&sc->call_lock);
+		break;
+
+	case IIC_RELEASE_BUS:
+		sc->poll = false;
+		sx_unlock(&sc->call_lock);
+		break;
+
+	default:
+		error = errno2iic(EINVAL);
+	}
+
+	return (error);
 }
 
 /*

Modified: head/sys/dev/ichiic/ig4_pci.c
==============================================================================
--- head/sys/dev/ichiic/ig4_pci.c	Sun Nov  3 20:51:22 2019	(r354301)
+++ head/sys/dev/ichiic/ig4_pci.c	Sun Nov  3 20:53:13 2019	(r354302)
@@ -214,7 +214,7 @@ static device_method_t ig4iic_pci_methods[] = {
 
 	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
 	DEVMETHOD(iicbus_reset, ig4iic_reset),
-	DEVMETHOD(iicbus_callback, iicbus_null_callback),
+	DEVMETHOD(iicbus_callback, ig4iic_callback),
 
 	DEVMETHOD_END
 };

Modified: head/sys/dev/ichiic/ig4_var.h
==============================================================================
--- head/sys/dev/ichiic/ig4_var.h	Sun Nov  3 20:51:22 2019	(r354301)
+++ head/sys/dev/ichiic/ig4_var.h	Sun Nov  3 20:53:13 2019	(r354302)
@@ -67,6 +67,7 @@ struct ig4iic_softc {
 	int		slave_valid : 1;
 	int		read_started : 1;
 	int		write_started : 1;
+	int		poll: 1;
 
 	/*
 	 * Locking semantics:
@@ -95,5 +96,6 @@ int ig4iic_detach(ig4iic_softc_t *sc);
 /* iicbus methods */
 extern iicbus_transfer_t ig4iic_transfer;
 extern iicbus_reset_t   ig4iic_reset;
+extern iicbus_callback_t ig4iic_callback;
 
 #endif /* _ICHIIC_IG4_VAR_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911032053.xA3KrDLq065045>