Linux userland API discussions
 help / color / mirror / Atom feed
* [PATCH v7 35/44] [media] media controller: get rid of entity subtype on Kernel
From: Mauro Carvalho Chehab @ 2015-08-23 20:17 UTC (permalink / raw)
  To: Linux Media Mailing List
  Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-api
In-Reply-To: <cover.1440359643.git.mchehab@osg.samsung.com>

Don't use anymore the type/subtype entity data/macros
inside the Kernel.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 952867571429..796e4a490af8 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -185,16 +185,6 @@ struct media_intf_devnode {
 	u32				minor;
 };
 
-static inline u32 media_entity_type(struct media_entity *entity)
-{
-	return entity->type & MEDIA_ENT_TYPE_MASK;
-}
-
-static inline u32 media_entity_subtype(struct media_entity *entity)
-{
-	return entity->type & MEDIA_ENT_SUBTYPE_MASK;
-}
-
 static inline u32 media_entity_id(struct media_entity *entity)
 {
 	return entity->graph_obj.id;
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index e9e7ad268a7e..ceea791dd6e9 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -42,10 +42,8 @@ struct media_device_info {
 
 #define MEDIA_ENT_ID_FLAG_NEXT		(1 << 31)
 
-/* Used values for media_entity_desc::type */
-
 /*
- * Initial value when an entity is created
+ * Initial value to be used when a new entity is created
  * Drivers should change it to something useful
  */
 #define MEDIA_ENT_T_UNKNOWN	0x00000000
@@ -96,6 +94,7 @@ struct media_device_info {
 #define MEDIA_ENT_T_DVB_CA		(MEDIA_ENT_T_DVB_BASE + 7)
 #define MEDIA_ENT_T_DVB_NET_DECAP	(MEDIA_ENT_T_DVB_BASE + 8)
 
+#ifndef __KERNEL__
 /* Legacy symbols used to avoid userspace compilation breakages */
 #define MEDIA_ENT_TYPE_SHIFT		16
 #define MEDIA_ENT_TYPE_MASK		0x00ff0000
@@ -109,6 +108,7 @@ struct media_device_info {
 #define MEDIA_ENT_T_DEVNODE_FB		(MEDIA_ENT_T_DEVNODE + 2)
 #define MEDIA_ENT_T_DEVNODE_ALSA	(MEDIA_ENT_T_DEVNODE + 3)
 #define MEDIA_ENT_T_DEVNODE_DVB		(MEDIA_ENT_T_DEVNODE + 4)
+#endif
 
 /* Entity types */
 
-- 
2.4.3

^ permalink raw reply related

* [PATCH v7 34/44] [media] v4l2-subdev: use MEDIA_ENT_T_UNKNOWN for new subdevs
From: Mauro Carvalho Chehab @ 2015-08-23 20:17 UTC (permalink / raw)
  To: Linux Media Mailing List
  Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, Hans Verkuil,
	Laurent Pinchart, Prabhakar Lad, Sylwester Nawrocki,
	Lars-Peter Clausen, Markus Elfring,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <cover.1440359643.git.mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

Instead of abusing MEDIA_ENT_T_V4L2_SUBDEV, initialize
new subdev entities as MEDIA_ENT_T_UNKNOWN.

Signed-off-by: Mauro Carvalho Chehab <mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 60da43772de9..07600daf5490 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -584,7 +584,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
 	sd->host_priv = NULL;
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	sd->entity.name = sd->name;
-	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	sd->entity.type = MEDIA_ENT_T_UNKNOWN;
 #endif
 }
 EXPORT_SYMBOL(v4l2_subdev_init);
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 7306aeaff807..e9e7ad268a7e 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -42,6 +42,14 @@ struct media_device_info {
 
 #define MEDIA_ENT_ID_FLAG_NEXT		(1 << 31)
 
+/* Used values for media_entity_desc::type */
+
+/*
+ * Initial value when an entity is created
+ * Drivers should change it to something useful
+ */
+#define MEDIA_ENT_T_UNKNOWN	0x00000000
+
 /*
  * Base numbers for entity types
  *
@@ -52,7 +60,7 @@ struct media_device_info {
  * However, It is kept this way just to avoid binary breakages with the
  * namespace provided on legacy versions of this header.
  */
-#define MEDIA_ENT_T_DVB_BASE		0x00000000
+#define MEDIA_ENT_T_DVB_BASE		0x00000001
 #define MEDIA_ENT_T_V4L2_BASE		0x00010000
 #define MEDIA_ENT_T_V4L2_SUBDEV_BASE	0x00020000
 
-- 
2.4.3

^ permalink raw reply related

* [PATCH v7 24/44] [media] uapi/media.h: Fix entity namespace
From: Mauro Carvalho Chehab @ 2015-08-23 20:17 UTC (permalink / raw)
  To: Linux Media Mailing List
  Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, Hans Verkuil,
	Laurent Pinchart, Sakari Ailus, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <cover.1440359643.git.mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

Now that interfaces got created, we need to fix the entity
namespace.

So, let's create a consistent new namespace and add backward
compatibility macros to keep the old namespace preserved.

Signed-off-by: Mauro Carvalho Chehab <mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 5a2bd03f5dc0..acada5ba9442 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -229,17 +229,17 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMOD;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_DEMUX:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_CA:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
@@ -438,7 +438,7 @@ EXPORT_SYMBOL(dvb_unregister_device);
 void dvb_create_media_graph(struct dvb_adapter *adap)
 {
 	struct media_device *mdev = adap->mdev;
-	struct media_entity *entity, *tuner = NULL, *fe = NULL;
+	struct media_entity *entity, *tuner = NULL, *demod = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
 	struct media_interface *intf;
 
@@ -450,26 +450,26 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
 			tuner = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_FE:
-			fe = entity;
+		case MEDIA_ENT_T_DVB_DEMOD:
+			demod = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+		case MEDIA_ENT_T_DVB_DEMUX:
 			demux = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+		case MEDIA_ENT_T_DVB_TSOUT:
 			dvr = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_CA:
+		case MEDIA_ENT_T_DVB_CA:
 			ca = entity;
 			break;
 		}
 	}
 
-	if (tuner && fe)
-		media_create_pad_link(tuner, 0, fe, 0, 0);
+	if (tuner && demod)
+		media_create_pad_link(tuner, 0, demod, 0, 0);
 
-	if (fe && demux)
-		media_create_pad_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+	if (demod && demux)
+		media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
 
 	if (demux && dvr)
 		media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 21c96cd7a6ae..7306aeaff807 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -42,31 +42,67 @@ struct media_device_info {
 
 #define MEDIA_ENT_ID_FLAG_NEXT		(1 << 31)
 
+/*
+ * Base numbers for entity types
+ *
+ * Please notice that the huge gap of 16 bits for each base is overkill!
+ * 8 bits is more than enough to avoid starving entity types for each
+ * subsystem.
+ *
+ * However, It is kept this way just to avoid binary breakages with the
+ * namespace provided on legacy versions of this header.
+ */
+#define MEDIA_ENT_T_DVB_BASE		0x00000000
+#define MEDIA_ENT_T_V4L2_BASE		0x00010000
+#define MEDIA_ENT_T_V4L2_SUBDEV_BASE	0x00020000
+
+/* V4L2 entities */
+#define MEDIA_ENT_T_V4L2_VIDEO		(MEDIA_ENT_T_V4L2_BASE + 1)
+	/*
+	 * Please notice that numbers between MEDIA_ENT_T_V4L2_BASE + 2 and
+	 * MEDIA_ENT_T_V4L2_BASE + 4 can't be used, as those values used
+	 * to be declared for FB, ALSA and DVB entities.
+	 * As those values were never atually used in practice, we're just
+	 * adding them as backward compatibily macros and keeping the
+	 * numberspace cleaned here. This way, we avoid breaking compilation,
+	 * in the case of having some userspace application using the old
+	 * symbols.
+	 */
+#define MEDIA_ENT_T_V4L2_VBI		(MEDIA_ENT_T_V4L2_BASE + 5)
+#define MEDIA_ENT_T_V4L2_RADIO		(MEDIA_ENT_T_V4L2_BASE + 6)
+#define MEDIA_ENT_T_V4L2_SWRADIO	(MEDIA_ENT_T_V4L2_BASE + 7)
+
+/* V4L2 Sub-device entities */
+#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 1)
+#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 2)
+#define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 3)
+	/* A converter of analogue video to its digital representation. */
+#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 4)
+	/* Tuner entity is actually both V4L2 and DVB subdev */
+#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 5)
+
+/* DVB entities */
+#define MEDIA_ENT_T_DVB_DEMOD		(MEDIA_ENT_T_DVB_BASE + 4)
+#define MEDIA_ENT_T_DVB_DEMUX		(MEDIA_ENT_T_DVB_BASE + 5)
+#define MEDIA_ENT_T_DVB_TSOUT		(MEDIA_ENT_T_DVB_BASE + 6)
+#define MEDIA_ENT_T_DVB_CA		(MEDIA_ENT_T_DVB_BASE + 7)
+#define MEDIA_ENT_T_DVB_NET_DECAP	(MEDIA_ENT_T_DVB_BASE + 8)
+
+/* Legacy symbols used to avoid userspace compilation breakages */
 #define MEDIA_ENT_TYPE_SHIFT		16
 #define MEDIA_ENT_TYPE_MASK		0x00ff0000
 #define MEDIA_ENT_SUBTYPE_MASK		0x0000ffff
 
-#define MEDIA_ENT_T_DEVNODE		(1 << MEDIA_ENT_TYPE_SHIFT)
-#define MEDIA_ENT_T_DEVNODE_V4L		(MEDIA_ENT_T_DEVNODE + 1)
+#define MEDIA_ENT_T_DEVNODE		MEDIA_ENT_T_V4L2_BASE
+#define MEDIA_ENT_T_V4L2_SUBDEV		MEDIA_ENT_T_V4L2_SUBDEV_BASE
+
+#define MEDIA_ENT_T_DEVNODE_V4L		MEDIA_ENT_T_V4L2_VIDEO
+
 #define MEDIA_ENT_T_DEVNODE_FB		(MEDIA_ENT_T_DEVNODE + 2)
 #define MEDIA_ENT_T_DEVNODE_ALSA	(MEDIA_ENT_T_DEVNODE + 3)
-#define MEDIA_ENT_T_DEVNODE_DVB_FE	(MEDIA_ENT_T_DEVNODE + 4)
-#define MEDIA_ENT_T_DEVNODE_DVB_DEMUX	(MEDIA_ENT_T_DEVNODE + 5)
-#define MEDIA_ENT_T_DEVNODE_DVB_DVR	(MEDIA_ENT_T_DEVNODE + 6)
-#define MEDIA_ENT_T_DEVNODE_DVB_CA	(MEDIA_ENT_T_DEVNODE + 7)
-#define MEDIA_ENT_T_DEVNODE_DVB_NET	(MEDIA_ENT_T_DEVNODE + 8)
+#define MEDIA_ENT_T_DEVNODE_DVB		(MEDIA_ENT_T_DEVNODE + 4)
 
-/* Legacy symbol. Use it to avoid userspace compilation breakages */
-#define MEDIA_ENT_T_DEVNODE_DVB		MEDIA_ENT_T_DEVNODE_DVB_FE
-
-#define MEDIA_ENT_T_V4L2_SUBDEV		(2 << MEDIA_ENT_TYPE_SHIFT)
-#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV + 1)
-#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV + 2)
-#define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV + 3)
-/* A converter of analogue video to its digital representation. */
-#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV + 4)
-
-#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER	(MEDIA_ENT_T_V4L2_SUBDEV + 5)
+/* Entity types */
 
 #define MEDIA_ENT_FL_DEFAULT		(1 << 0)
 
-- 
2.4.3

^ permalink raw reply related

* [PATCH v7 13/44] [media] uapi/media.h: Declare interface types
From: Mauro Carvalho Chehab @ 2015-08-23 20:17 UTC (permalink / raw)
  To: Linux Media Mailing List
  Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <cover.1440359643.git.mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

Declare the interface types that will be used by the new
G_TOPOLOGY ioctl that will be defined latter on.

For now, we need those types, as they'll be used on the
internal structs associated with the new media_interface
graph object defined on the next patch.

Signed-off-by: Mauro Carvalho Chehab <mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 4e816be3de39..21c96cd7a6ae 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -167,6 +167,35 @@ struct media_links_enum {
 	__u32 reserved[4];
 };
 
+/* Interface type ranges */
+
+#define MEDIA_INTF_T_DVB_BASE	0x00000000
+#define MEDIA_INTF_T_V4L_BASE	0x00000100
+#define MEDIA_INTF_T_ALSA_BASE	0x00000200
+
+/* Interface types */
+
+#define MEDIA_INTF_T_DVB_FE    	(MEDIA_INTF_T_DVB_BASE)
+#define MEDIA_INTF_T_DVB_DEMUX  (MEDIA_INTF_T_DVB_BASE + 1)
+#define MEDIA_INTF_T_DVB_DVR    (MEDIA_INTF_T_DVB_BASE + 2)
+#define MEDIA_INTF_T_DVB_CA     (MEDIA_INTF_T_DVB_BASE + 3)
+#define MEDIA_INTF_T_DVB_NET    (MEDIA_INTF_T_DVB_BASE + 4)
+
+#define MEDIA_INTF_T_V4L_VIDEO  (MEDIA_INTF_T_V4L_BASE)
+#define MEDIA_INTF_T_V4L_VBI    (MEDIA_INTF_T_V4L_BASE + 1)
+#define MEDIA_INTF_T_V4L_RADIO  (MEDIA_INTF_T_V4L_BASE + 2)
+#define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
+#define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
+
+#define MEDIA_INTF_T_ALSA_PCM_CAPTURE   (MEDIA_INTF_T_ALSA_BASE)
+#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK  (MEDIA_INTF_T_ALSA_BASE + 1)
+#define MEDIA_INTF_T_ALSA_CONTROL       (MEDIA_INTF_T_ALSA_BASE + 2)
+#define MEDIA_INTF_T_ALSA_COMPRESS      (MEDIA_INTF_T_ALSA_BASE + 3)
+#define MEDIA_INTF_T_ALSA_RAWMIDI       (MEDIA_INTF_T_ALSA_BASE + 4)
+#define MEDIA_INTF_T_ALSA_HWDEP         (MEDIA_INTF_T_ALSA_BASE + 5)
+
+/* TBD: declare the structs needed for the new G_TOPOLOGY ioctl */
+
 #define MEDIA_IOC_DEVICE_INFO		_IOWR('|', 0x00, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES		_IOWR('|', 0x01, struct media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS		_IOWR('|', 0x02, struct media_links_enum)
-- 
2.4.3

^ permalink raw reply related

* [RFC v6 24/25] m68k/mac: Fix PRAM accessors
From: Finn Thain @ 2015-08-23 10:41 UTC (permalink / raw)
  To: linux-kernel, linux-m68k, linuxppc-dev, Geert Uytterhoeven,
	linux-api
In-Reply-To: <20150823104129.517600532@telegraphics.com.au>

[-- Attachment #1: mac68k-fix-pram-accessors --]
[-- Type: text/plain, Size: 3503 bytes --]

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>

---

Tested on a PowerBook 520 and Quadra 650.

Changes since v2:
- Make use of the RTC_* macros from the previous patch and add a few more
besides.

---
 arch/m68k/mac/misc.c     |   39 +++++++++++++++++++++++++++++++++------
 include/uapi/linux/pmu.h |    2 ++
 2 files changed, 35 insertions(+), 6 deletions(-)

Index: linux/arch/m68k/mac/misc.c
===================================================================
--- linux.orig/arch/m68k/mac/misc.c	2015-08-23 20:41:23.000000000 +1000
+++ linux/arch/m68k/mac/misc.c	2015-08-23 20:41:25.000000000 +1000
@@ -119,19 +119,22 @@ static void pmu_write_time(long data)
 static unsigned char pmu_pram_read_byte(int offset)
 {
 	struct adb_request req;
-	if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
-			(offset >> 8) & 0xFF, offset & 0xFF) < 0)
+
+	if (pmu_request(&req, NULL, 3, PMU_READ_XPRAM,
+	                offset & 0xFF, 1) < 0)
 		return 0;
 	while (!req.complete)
 		pmu_poll();
-	return req.reply[3];
+
+	return req.reply[1];
 }
 
 static void pmu_pram_write_byte(unsigned char data, int offset)
 {
 	struct adb_request req;
-	if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
-			(offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
+
+	if (pmu_request(&req, NULL, 4, PMU_WRITE_XPRAM,
+	                offset & 0xFF, 1, data) < 0)
 		return;
 	while (!req.complete)
 		pmu_poll();
@@ -257,6 +260,16 @@ static void via_rtc_send(__u8 data)
 #define RTC_REG_WRITE_PROTECT   13
 
 /*
+ * Inside Mac has no information about two-byte RTC commands but
+ * the MESS source code has the essentials.
+ */
+
+#define RTC_REG_XPRAM           14
+#define RTC_CMD_XPRAM_READ      (RTC_CMD_READ(RTC_REG_XPRAM) << 8)
+#define RTC_CMD_XPRAM_WRITE     (RTC_CMD_WRITE(RTC_REG_XPRAM) << 8)
+#define RTC_CMD_XPRAM_ARG(a)    (((a & 0xE0) << 3) | ((a & 0x1F) << 2))
+
+/*
  * Execute a VIA PRAM/RTC command. For read commands
  * data should point to a one-byte buffer for the
  * resulting data. For write commands it should point
@@ -303,11 +316,25 @@ static void via_rtc_command(int command,
 
 static unsigned char via_pram_read_byte(int offset)
 {
-	return 0;
+	unsigned char temp;
+
+	via_rtc_command(RTC_CMD_XPRAM_READ | RTC_CMD_XPRAM_ARG(offset), &temp);
+
+	return temp;
 }
 
 static void via_pram_write_byte(unsigned char data, int offset)
 {
+	unsigned char temp;
+
+	temp = 0x55;
+	via_rtc_command(RTC_CMD_WRITE(RTC_REG_WRITE_PROTECT), &temp);
+
+	temp = data;
+	via_rtc_command(RTC_CMD_XPRAM_WRITE | RTC_CMD_XPRAM_ARG(offset), &temp);
+
+	temp = 0x55 | RTC_FLG_WRITE_PROTECT;
+	via_rtc_command(RTC_CMD_WRITE(RTC_REG_WRITE_PROTECT), &temp);
 }
 
 /*
Index: linux/include/uapi/linux/pmu.h
===================================================================
--- linux.orig/include/uapi/linux/pmu.h	2015-08-23 20:40:53.000000000 +1000
+++ linux/include/uapi/linux/pmu.h	2015-08-23 20:41:25.000000000 +1000
@@ -18,7 +18,9 @@
 #define PMU_POWER_CTRL		0x11	/* control power of some devices */
 #define PMU_ADB_CMD		0x20	/* send ADB packet */
 #define PMU_ADB_POLL_OFF	0x21	/* disable ADB auto-poll */
+#define PMU_WRITE_XPRAM		0x32	/* write eXtended Parameter RAM */
 #define PMU_WRITE_NVRAM		0x33	/* write non-volatile RAM */
+#define PMU_READ_XPRAM		0x3a	/* read eXtended Parameter RAM */
 #define PMU_READ_NVRAM		0x3b	/* read non-volatile RAM */
 #define PMU_SET_RTC		0x30	/* set real-time clock */
 #define PMU_READ_RTC		0x38	/* read real-time clock */

^ permalink raw reply

* [ebeam PATCH v2 2/2] input: misc: New USB eBeam input driver
From: Yann Cantin @ 2015-08-22 22:06 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w, jkosina-AlSwsSmVLrQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, oneukum-IBi9RG/b67k,
	Yann Cantin
In-Reply-To: <1440281164-23111-1-git-send-email-yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>

Add new USB input driver for Luidia's eBeam devices.

Currently supported (tested) :
- eBeam classic projection and edge projection models
- Nec interactive solution NP01Wi1 & NP01Wi2 accessories.

Notable stuff :
- 13 sysfs custom files : 9 values for the transformation matrix,
  4 for xy ranges and a calibration trigger.
- need userspace gui tool for calibration (ebeam.tuxfamily.org)

Signed-off-by: Yann Cantin <yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-driver-ebeam |  53 ++
 drivers/input/misc/ebeam.c                   | 759 +++++++++++++++++++++++++++
 2 files changed, 812 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-ebeam
 create mode 100644 drivers/input/misc/ebeam.c

diff --git a/Documentation/ABI/testing/sysfs-driver-ebeam b/Documentation/ABI/testing/sysfs-driver-ebeam
new file mode 100644
index 0000000..3a663e8
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ebeam
@@ -0,0 +1,53 @@
+What:		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/min_x
+		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/min_y
+		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/max_x
+		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/max_y
+Date:		Jul 2015
+Kernel Version:	4.1
+Contact:	yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org
+		linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
+Description:
+		Reading from these files return the actually used range values of
+		the reported coordinates.
+		Writing to these files preset these range values.
+		See below for the calibration procedure.
+
+What:		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/h[1..9]
+Date:		Jul 2015
+Kernel Version:	4.1
+Contact:	yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org
+		linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
+Description:
+		Reading from these files return the 3x3 transformation matrix elements
+		actually used, in row-major.
+		Writing to these files preset these elements values.
+		See below for the calibration procedure.
+
+What:		/sys/bus/usb/drivers/ebeam/<busnum>-<devnum>:<confignum>.<ifacenum>/calibrated
+Date:		Jul 2015
+Kernel Version:	4.1
+Contact:	yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org
+		linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
+Description:
+		Reading from this file :
+		- Return 0 if the driver is in "un-calibrated" mode : it actually send
+		  raw coordinates in the device's internal coordinates system.
+		- Return 1 if the driver is in "calibrated" mode : it send computed coordinates
+		  that (hopefully) matches the screen's coordinates system.
+		Writing 1 to this file enable the "calibrated" mode, 0 reset the driver in
+		"un-calibrated" mode.
+
+Calibration procedure :
+
+When loaded, the driver is in "un-calibrated" mode : it send device's raw coordinates
+in the [0..65535]x[0..65535] range, the transformation matrix is the identity.
+
+A calibration program have to compute a homography transformation matrix that convert
+the device's raw coordinates to the matching screen's ones.
+It then write to the appropriate sysfs files the computed values, pre-setting the
+driver's parameters : xy range, and the matrix's elements.
+When all values are passed, it write 1 to the calibrated sysfs file to enable the "calibrated" mode.
+
+Warning : The parameters aren't used until 1 is writen to the calibrated sysfs file.
+
+These files can also be accessed via /sys/class/input/inputXX/device/
diff --git a/drivers/input/misc/ebeam.c b/drivers/input/misc/ebeam.c
new file mode 100644
index 0000000..e7b9f3e
--- /dev/null
+++ b/drivers/input/misc/ebeam.c
@@ -0,0 +1,759 @@
+/******************************************************************************
+ *
+ * eBeam driver
+ *
+ * Copyright (C) 2012-2015 Yann Cantin (yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of the
+ *	License, or (at your option) any later version.
+ *
+ *  based on
+ *
+ *	usbtouchscreen.c by Daniel Ritz <daniel.ritz-OI3hZJvNYWs@public.gmane.org>
+ *	aiptek.c (sysfs/settings) by Chris Atenasio <chris-v4AJ0sPprEc@public.gmane.org>
+ *				     Bryan W. Headley <bwheadley-ihVZJaRskl1bRRN4PJnoQQ@public.gmane.org>
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/math64.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <asm/unaligned.h>
+
+#define DRIVER_AUTHOR	"Yann Cantin <yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>"
+#define DRIVER_DESC	"USB eBeam Driver"
+
+/* Common values for eBeam devices */
+#define REPT_SIZE	8	/* packet size            */
+#define MIN_RAW_X	0	/* raw coordinates ranges */
+#define MAX_RAW_X	0xFFFF
+#define MIN_RAW_Y	0
+#define MAX_RAW_Y	0xFFFF
+
+#define EBEAM_BTN_TIP	0x1	/* tip    */
+#define EBEAM_BTN_LIT	0x2	/* little */
+#define EBEAM_BTN_BIG	0x4	/* big    */
+
+/* ebeam settings */
+struct ebeam_settings {
+	int min_x;	/* computed coordinates ranges for the input layer */
+	int max_x;
+	int min_y;
+	int max_y;
+
+	/* H matrix */
+	s64 h1;
+	s64 h2;
+	s64 h3;
+	s64 h4;
+	s64 h5;
+	s64 h6;
+	s64 h7;
+	s64 h8;
+	s64 h9;
+};
+
+/* ebeam device */
+struct ebeam_device {
+	unsigned char		*data;
+	dma_addr_t		data_dma;
+	unsigned char		*buffer;
+	int			buf_len;
+	struct urb		*irq;
+	struct usb_interface	*interface;
+	struct input_dev	*input;
+	char			name[128];
+	char			phys[64];
+	void			*priv;
+
+	struct ebeam_settings	cursetting;	/* device's current settings */
+	struct ebeam_settings	newsetting;	/* ... and new ones          */
+
+	bool			calibrated;	/* false : send raw          */
+						/* true  : send computed     */
+
+	u16			raw_x;		/* raw coordinates           */
+	u16			raw_y;
+	int			x;		/* computed coordinates      */
+	int			y;
+	int			btn_map;	/* internal buttons map      */
+};
+
+/* device types */
+enum {
+	DEVTYPE_EBEAM,
+};
+
+static const struct usb_device_id ebeam_devices[] = {
+	{USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB1),
+	 .driver_info = DEVTYPE_EBEAM},
+	{USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB2),
+	 .driver_info = DEVTYPE_EBEAM},
+	{USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB1),
+	 .driver_info = DEVTYPE_EBEAM},
+	{USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB2),
+	 .driver_info = DEVTYPE_EBEAM},
+	{}
+};
+
+static void ebeam_init_settings(struct ebeam_device *ebeam)
+{
+	ebeam->calibrated = false;
+
+	/* Init (x,y) min/max to raw ones */
+	ebeam->cursetting.min_x = ebeam->newsetting.min_x = MIN_RAW_X;
+	ebeam->cursetting.max_x = ebeam->newsetting.max_x = MAX_RAW_X;
+	ebeam->cursetting.min_y = ebeam->newsetting.min_y = MIN_RAW_Y;
+	ebeam->cursetting.max_y = ebeam->newsetting.max_y = MAX_RAW_Y;
+
+	/* Safe values for the H matrix (Identity) */
+	ebeam->cursetting.h1 = ebeam->newsetting.h1 = 1;
+	ebeam->cursetting.h2 = ebeam->newsetting.h2 = 0;
+	ebeam->cursetting.h3 = ebeam->newsetting.h3 = 0;
+
+	ebeam->cursetting.h4 = ebeam->newsetting.h4 = 0;
+	ebeam->cursetting.h5 = ebeam->newsetting.h5 = 1;
+	ebeam->cursetting.h6 = ebeam->newsetting.h6 = 0;
+
+	ebeam->cursetting.h7 = ebeam->newsetting.h7 = 0;
+	ebeam->cursetting.h8 = ebeam->newsetting.h8 = 0;
+	ebeam->cursetting.h9 = ebeam->newsetting.h9 = 1;
+}
+
+static void ebeam_setup_input(struct ebeam_device *ebeam,
+			      struct input_dev *input_dev)
+{
+	unsigned long flags;
+
+	/* Take event lock while modifying parameters */
+	spin_lock_irqsave(&input_dev->event_lock, flags);
+
+	/* Properties */
+	set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+	/* Events generated */
+	set_bit(EV_KEY, input_dev->evbit);
+	set_bit(EV_ABS, input_dev->evbit);
+
+	/* Keys */
+	set_bit(BTN_LEFT,	input_dev->keybit);
+	set_bit(BTN_MIDDLE,	input_dev->keybit);
+	set_bit(BTN_RIGHT,	input_dev->keybit);
+
+	/* Axis */
+	if (!ebeam->calibrated) {
+		ebeam->cursetting.min_x = MIN_RAW_X;
+		ebeam->cursetting.max_x = MAX_RAW_X;
+		ebeam->cursetting.min_y = MIN_RAW_Y;
+		ebeam->cursetting.max_y = MAX_RAW_Y;
+	}
+
+	input_set_abs_params(input_dev, ABS_X,
+			     ebeam->cursetting.min_x, ebeam->cursetting.max_x,
+			     0, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			     ebeam->cursetting.min_y, ebeam->cursetting.max_y,
+			     0, 0);
+
+	spin_unlock_irqrestore(&input_dev->event_lock, flags);
+}
+
+/*******************************************************************************
+ * sysfs part
+ */
+
+/*
+ * screen min/max and H matrix coefs
+ * _get return *current* value
+ * _set set new value
+ */
+#define DEVICE_MINMAX_ATTR(MM)						       \
+static ssize_t MM##_show(struct device *dev,				       \
+			 struct device_attribute *attr,			       \
+			 char *buf)					       \
+{									       \
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);		       \
+									       \
+	return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->cursetting.MM);	       \
+}									       \
+static ssize_t MM##_store(struct device *dev,				       \
+			  struct device_attribute *attr,		       \
+			  const char *buf,				       \
+			  size_t count)					       \
+{									       \
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);		       \
+	int err, MM;							       \
+									       \
+	err = kstrtoint(buf, 10, &MM);					       \
+	if (err)							       \
+		return err;						       \
+									       \
+	ebeam->newsetting.MM = MM;					       \
+	return count;							       \
+}									       \
+static DEVICE_ATTR_RW(MM)
+
+DEVICE_MINMAX_ATTR(min_x);
+DEVICE_MINMAX_ATTR(max_x);
+DEVICE_MINMAX_ATTR(min_y);
+DEVICE_MINMAX_ATTR(max_y);
+
+#define DEVICE_H_ATTR(SET_ID)						       \
+static ssize_t SET_ID##_show(struct device *dev,			       \
+			     struct device_attribute *attr,		       \
+			     char *buf)					       \
+{									       \
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);		       \
+									       \
+	return snprintf(buf, PAGE_SIZE, "%lld\n", ebeam->cursetting.SET_ID);   \
+}									       \
+static ssize_t SET_ID##_store(struct device *dev,			       \
+			      struct device_attribute *attr,		       \
+			      const char *buf,				       \
+			      size_t count)				       \
+{									       \
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);		       \
+	int err;							       \
+	u64 h;								       \
+									       \
+	err = kstrtoll(buf, 10, &h);					       \
+	if (err)							       \
+		return err;						       \
+									       \
+	ebeam->newsetting.SET_ID = h;					       \
+	return count;							       \
+}									       \
+static DEVICE_ATTR_RW(SET_ID)
+
+DEVICE_H_ATTR(h1);
+DEVICE_H_ATTR(h2);
+DEVICE_H_ATTR(h3);
+DEVICE_H_ATTR(h4);
+DEVICE_H_ATTR(h5);
+DEVICE_H_ATTR(h6);
+DEVICE_H_ATTR(h7);
+DEVICE_H_ATTR(h8);
+DEVICE_H_ATTR(h9);
+
+/*
+ * sysfs calibrated
+ * Once H matrix coefs are set, writing 1 to this file triggers
+ * coordinates mapping.
+ * Anything else reset the device to un-calibrated mode,
+ * storing cursetting in newsetting.
+*/
+static ssize_t calibrated_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->calibrated);
+}
+
+static ssize_t calibrated_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct ebeam_device *ebeam = dev_get_drvdata(dev);
+	int err, c;
+
+	err = kstrtoint(buf, 10, &c);
+	if (err)
+		return err;
+
+	if (c == 1) {
+		memcpy(&ebeam->cursetting, &ebeam->newsetting,
+		       sizeof(struct ebeam_settings));
+		ebeam->calibrated = true;
+		ebeam_setup_input(ebeam, ebeam->input);
+	} else {
+		memcpy(&ebeam->newsetting, &ebeam->cursetting,
+		       sizeof(struct ebeam_settings));
+		ebeam->calibrated = false;
+		ebeam_setup_input(ebeam, ebeam->input);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(calibrated);
+
+static struct attribute *ebeam_attrs[] = {
+	&dev_attr_min_x.attr,
+	&dev_attr_min_y.attr,
+	&dev_attr_max_x.attr,
+	&dev_attr_max_y.attr,
+	&dev_attr_h1.attr,
+	&dev_attr_h2.attr,
+	&dev_attr_h3.attr,
+	&dev_attr_h4.attr,
+	&dev_attr_h5.attr,
+	&dev_attr_h6.attr,
+	&dev_attr_h7.attr,
+	&dev_attr_h8.attr,
+	&dev_attr_h9.attr,
+	&dev_attr_calibrated.attr,
+	NULL
+};
+
+static const struct attribute_group ebeam_attr_group = {
+	.attrs = ebeam_attrs,
+};
+
+/* IRQ */
+static int ebeam_read_data(struct ebeam_device *ebeam, unsigned char *pkt)
+{
+
+/*
+ * Packet description : 8 bytes
+ *
+ *  nop packet : FF FF FF FF FF FF FF FF
+ *
+ *  pkt[0] : Sensors
+ *	bit 1 : ultrasound signal (guessed)
+ *	bit 2 : IR signal (tested with a remote...) ;
+ *	readings OK : 0x03 (anything else is a show-stopper)
+ *
+ *  pkt[1] : raw_x low
+ *  pkt[2] : raw_x high
+ *
+ *  pkt[3] : raw_y low
+ *  pkt[4] : raw_y high
+ *
+ *  pkt[5] : fiability ?
+ *	often 0xC0
+ *	> 0x80 : OK
+ *
+ *  pkt[6] :
+ *	buttons state (low 4 bits)
+ *		0x1 = no buttons
+ *		bit 0 : tip (WARNING inversed : 0=pressed)
+ *		bit 1 : ? (always 0 during tests)
+ *		bit 2 : little (1=pressed)
+ *		bit 3 : big (1=pressed)
+ *
+ *	pointer ID : (high 4 bits)
+ *		Tested  : 0x6=wand ;
+ *		Guessed : 0x1=red ; 0x2=blue ; 0x3=green ; 0x4=black ;
+ *			  0x5=eraser
+ *		bit 4 : pointer ID
+ *		bit 5 : pointer ID
+ *		bit 6 : pointer ID
+ *		bit 7 : pointer ID
+ *
+ *
+ *  pkt[7] : fiability ?
+ *	often 0xFF
+ *
+ */
+
+	/* Filtering bad/nop packet */
+	if (pkt[0] != 0x03)
+		return 0;
+
+	ebeam->raw_x = get_unaligned_le16(&pkt[1]);
+	ebeam->raw_y = get_unaligned_le16(&pkt[3]);
+
+	ebeam->btn_map = (!(pkt[6] & 0x1)) |
+			 ((pkt[6] & 0x4) >> 1) |
+			 ((pkt[6] & 0x8) >> 1);
+
+	return 1;
+}
+
+/*
+ * IRQ
+ * compute screen coordinates from raw
+ * Overflow and negative values are ignored
+ */
+static bool ebeam_calculate_xy(struct ebeam_device *ebeam)
+{
+	/* 64-bits divisions handled by div64_s64 */
+
+	s64 scale;
+
+	if (!ebeam->calibrated) {
+		ebeam->x = ebeam->raw_x;
+		ebeam->y = ebeam->raw_y;
+	} else {
+		scale = ebeam->cursetting.h7 * ebeam->raw_x +
+			ebeam->cursetting.h8 * ebeam->raw_y +
+			ebeam->cursetting.h9;
+
+		/* Who want a division by zero in kernel ? */
+		if (scale == 0) {
+			dev_err(&(ebeam->interface)->dev,
+				"%s - Division by zero, wrong calibration.\n",
+				__func__);
+			dev_err(&(ebeam->interface)->dev,
+				"%s - Resetting to un-calibrated mode.\n",
+				__func__);
+			ebeam->calibrated = false;
+			return 0;
+		}
+
+		/*
+		 * We *must* round the result, but can't do (int) (v1/v2 + 0.5)
+		 *
+		 * (int) (v1/v2 + 0.5) <=> (int) ( (2*v1 + v2)/(2*v2) )
+		 */
+		ebeam->x =
+		    (int)div64_s64((((ebeam->cursetting.h1 * ebeam->raw_x +
+				      ebeam->cursetting.h2 * ebeam->raw_y +
+				      ebeam->cursetting.h3) << 1) + scale),
+				   (scale << 1));
+		ebeam->y =
+		    (int)div64_s64((((ebeam->cursetting.h4 * ebeam->raw_x +
+				      ebeam->cursetting.h5 * ebeam->raw_y +
+				      ebeam->cursetting.h6) << 1) + scale),
+				   (scale << 1));
+
+		/* check range */
+		if ((ebeam->x < ebeam->cursetting.min_x) ||
+		    (ebeam->x > ebeam->cursetting.max_x) ||
+		    (ebeam->y < ebeam->cursetting.min_y) ||
+		    (ebeam->y > ebeam->cursetting.max_y))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* IRQ */
+static void ebeam_report_input(struct ebeam_device *ebeam)
+{
+	input_report_key(ebeam->input, BTN_LEFT,
+			 (ebeam->btn_map & EBEAM_BTN_TIP));
+	input_report_key(ebeam->input, BTN_MIDDLE,
+			 (ebeam->btn_map & EBEAM_BTN_LIT));
+	input_report_key(ebeam->input, BTN_RIGHT,
+			 (ebeam->btn_map & EBEAM_BTN_BIG));
+
+	input_report_abs(ebeam->input, ABS_X, ebeam->x);
+	input_report_abs(ebeam->input, ABS_Y, ebeam->y);
+
+	input_sync(ebeam->input);
+}
+
+/* IRQ */
+static void ebeam_process_pkt(struct ebeam_device *ebeam,
+			      unsigned char *pkt, int len)
+{
+	if (!ebeam_read_data(ebeam, pkt))
+		return;
+
+	if (!ebeam_calculate_xy(ebeam))
+		return;
+
+	ebeam_report_input(ebeam);
+}
+
+/* IRQ
+ * handler */
+static void ebeam_irq(struct urb *urb)
+{
+	struct ebeam_device *ebeam = urb->context;
+	struct device *dev = &ebeam->interface->dev;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ETIME:
+		/* this urb is timing out */
+		dev_dbg(dev,
+			"%s - urb timed out - was the device unplugged?\n",
+			__func__);
+		return;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+	case -EPIPE:
+		/* this urb is terminated, clean up */
+		dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+			__func__, urb->status);
+		return;
+	default:
+		dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+			__func__, urb->status);
+		goto exit;
+	}
+
+	ebeam_process_pkt(ebeam, ebeam->data, urb->actual_length);
+
+exit:
+	usb_mark_last_busy(interface_to_usbdev(ebeam->interface));
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
+			__func__, retval);
+}
+
+static int ebeam_open(struct input_dev *input)
+{
+	struct ebeam_device *ebeam = input_get_drvdata(input);
+	int r;
+
+	ebeam->irq->dev = interface_to_usbdev(ebeam->interface);
+
+	r = usb_autopm_get_interface(ebeam->interface) ? -EIO : 0;
+	if (r < 0)
+		goto out;
+
+	if (usb_submit_urb(ebeam->irq, GFP_KERNEL)) {
+		r = -EIO;
+		goto out_put;
+	}
+
+	ebeam->interface->needs_remote_wakeup = 1;
+out_put:
+	usb_autopm_put_interface(ebeam->interface);
+out:
+	return r;
+}
+
+static void ebeam_close(struct input_dev *input)
+{
+	struct ebeam_device *ebeam = input_get_drvdata(input);
+	int r;
+
+	r = usb_autopm_get_interface(ebeam->interface);
+
+	usb_kill_urb(ebeam->irq);
+	ebeam->interface->needs_remote_wakeup = 0;
+
+	if (!r)
+		usb_autopm_put_interface(ebeam->interface);
+}
+
+static int ebeam_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct ebeam_device *ebeam = usb_get_intfdata(intf);
+
+	usb_kill_urb(ebeam->irq);
+
+	return 0;
+}
+
+static int ebeam_resume(struct usb_interface *intf)
+{
+	struct ebeam_device *ebeam = usb_get_intfdata(intf);
+	struct input_dev *input = ebeam->input;
+	int result = 0;
+
+	mutex_lock(&input->mutex);
+	if (input->users)
+		result = usb_submit_urb(ebeam->irq, GFP_NOIO);
+	mutex_unlock(&input->mutex);
+
+	return result;
+}
+
+static void ebeam_free_buffers(struct usb_device *udev,
+			       struct ebeam_device *ebeam)
+{
+	usb_free_coherent(udev, REPT_SIZE, ebeam->data, ebeam->data_dma);
+	kfree(ebeam->buffer);
+}
+
+static struct usb_endpoint_descriptor
+*ebeam_get_input_endpoint(struct usb_host_interface *interface)
+{
+	int i;
+
+	for (i = 0; i < interface->desc.bNumEndpoints; i++)
+		if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
+			return &interface->endpoint[i].desc;
+
+	return NULL;
+}
+
+static int ebeam_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	struct ebeam_device *ebeam;
+	struct input_dev *input_dev;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_device *udev = interface_to_usbdev(intf);
+	int err = -ENOMEM;
+
+	endpoint = ebeam_get_input_endpoint(intf->cur_altsetting);
+	if (!endpoint)
+		return -ENXIO;
+
+	ebeam = kzalloc(sizeof(struct ebeam_device), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ebeam || !input_dev)
+		goto out_free;
+
+	ebeam_init_settings(ebeam);
+
+	ebeam->data = usb_alloc_coherent(udev, REPT_SIZE,
+					 GFP_KERNEL, &ebeam->data_dma);
+	if (!ebeam->data)
+		goto out_free;
+
+	ebeam->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ebeam->irq) {
+		dev_dbg(&intf->dev,
+			"%s - usb_alloc_urb failed: ebeam->irq\n", __func__);
+		goto out_free_buffers;
+	}
+
+	ebeam->interface = intf;
+	ebeam->input = input_dev;
+
+	/* setup name */
+	snprintf(ebeam->name, sizeof(ebeam->name),
+		 "USB eBeam %04x:%04x",
+		 le16_to_cpu(udev->descriptor.idVendor),
+		 le16_to_cpu(udev->descriptor.idProduct));
+
+	if (udev->manufacturer || udev->product) {
+		strlcat(ebeam->name, " (", sizeof(ebeam->name));
+
+		if (udev->manufacturer)
+			strlcat(ebeam->name,
+				udev->manufacturer,
+				sizeof(ebeam->name));
+
+		if (udev->product) {
+			if (udev->manufacturer)
+				strlcat(ebeam->name, " ", sizeof(ebeam->name));
+			strlcat(ebeam->name,
+				udev->product,
+				sizeof(ebeam->name));
+		}
+
+		if (strlcat(ebeam->name, ")", sizeof(ebeam->name))
+		    >= sizeof(ebeam->name)) {
+			/* overflowed, closing ) anyway */
+			ebeam->name[sizeof(ebeam->name) - 2] = ')';
+		}
+	}
+
+	/* usb tree */
+	usb_make_path(udev, ebeam->phys, sizeof(ebeam->phys));
+	strlcat(ebeam->phys, "/input0", sizeof(ebeam->phys));
+
+	/* input setup */
+	input_dev->name = ebeam->name;
+	input_dev->phys = ebeam->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, ebeam);
+
+	input_dev->open = ebeam_open;
+	input_dev->close = ebeam_close;
+
+	/* usb urb setup */
+	if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
+		usb_fill_int_urb(ebeam->irq,
+				 udev,
+				 usb_rcvintpipe(udev,
+						endpoint->bEndpointAddress),
+				 ebeam->data,
+				 REPT_SIZE,
+				 ebeam_irq,
+				 ebeam,
+				 endpoint->bInterval);
+	else
+		usb_fill_bulk_urb(ebeam->irq,
+				  udev,
+				  usb_rcvbulkpipe(udev,
+						  endpoint->bEndpointAddress),
+				  ebeam->data,
+				  REPT_SIZE,
+				  ebeam_irq,
+				  ebeam);
+
+	ebeam->irq->dev = udev;
+	ebeam->irq->transfer_dma = ebeam->data_dma;
+	ebeam->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* usb final setup */
+	usb_set_intfdata(intf, ebeam);
+
+	/* sysfs setup */
+	err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
+	if (err) {
+		dev_dbg(&intf->dev,
+			"%s - cannot create sysfs group, err: %d\n",
+			__func__, err);
+		goto out_free_usb;
+	}
+
+	/* input final setup */
+	ebeam_setup_input(ebeam, input_dev);
+
+	err = input_register_device(ebeam->input);
+	if (err) {
+		dev_dbg(&intf->dev,
+			"%s - input_register_device failed, err: %d\n",
+			__func__, err);
+		goto out_remove_sysfs;
+	}
+
+	return 0;
+
+out_remove_sysfs:
+	sysfs_remove_group(&intf->dev.kobj, &ebeam_attr_group);
+out_free_usb:
+	usb_set_intfdata(intf, NULL);
+	usb_free_urb(ebeam->irq);
+out_free_buffers:
+	ebeam_free_buffers(udev, ebeam);
+out_free:
+	input_free_device(input_dev);
+	kfree(ebeam);
+	return err;
+}
+
+static void ebeam_disconnect(struct usb_interface *intf)
+{
+	struct ebeam_device *ebeam = usb_get_intfdata(intf);
+
+	if (!ebeam)
+		return;
+
+	dev_dbg(&intf->dev,
+		"%s - ebeam is initialized, cleaning up\n", __func__);
+
+	usb_set_intfdata(intf, NULL);
+	/* this will stop IO via close */
+	input_unregister_device(ebeam->input);
+	sysfs_remove_group(&intf->dev.kobj, &ebeam_attr_group);
+	usb_free_urb(ebeam->irq);
+	ebeam_free_buffers(interface_to_usbdev(intf), ebeam);
+	kfree(ebeam);
+}
+
+MODULE_DEVICE_TABLE(usb, ebeam_devices);
+
+static struct usb_driver ebeam_driver = {
+	.name =			"ebeam",
+	.probe =		ebeam_probe,
+	.disconnect =		ebeam_disconnect,
+	.suspend =		ebeam_suspend,
+	.resume =		ebeam_resume,
+	.reset_resume =		ebeam_resume,
+	.id_table =		ebeam_devices,
+	.supports_autosuspend =	1,
+};
+
+module_usb_driver(ebeam_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
-- 
2.3.8

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [ebeam PATCH v2 1/2] hid: Blacklist eBeam devices
From: Yann Cantin @ 2015-08-22 22:06 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w, jkosina-AlSwsSmVLrQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, oneukum-IBi9RG/b67k,
	Yann Cantin
In-Reply-To: <1440281164-23111-1-git-send-email-yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>

Add known eBeam devices usb ids.
Prevent hid-generic to take over these devices. This breaks Luidia's
proprietary application suite.

Signed-off-by: Yann Cantin <yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>
---
 drivers/hid/hid-core.c      |  6 ++++++
 drivers/hid/hid-ids.h       |  6 ++++++
 drivers/input/misc/Kconfig  | 22 ++++++++++++++++++++++
 drivers/input/misc/Makefile |  1 +
 4 files changed, 35 insertions(+)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e6fce23..b5edb0f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2270,6 +2270,12 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) },
+#if defined(CONFIG_INPUT_EBEAM_USB)
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB1) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB1) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB2) },
+#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b3b225b..aa6f2da 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -306,6 +306,12 @@
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7	0x73f7
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001	0xa001
 
+#define USB_VENDOR_ID_EFI		0x2650
+#define USB_DEVICE_ID_EFI_EBEAM_USB1	0x1311
+#define USB_DEVICE_ID_EFI_EBEAM_USB2	0x1315
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB1	0x1313
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB2	0x1320
+
 #define USB_VENDOR_ID_ELAN		0x04f3
 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN	0x0089
 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B	0x009b
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d4f0a81..22c46a4 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -103,6 +103,28 @@ config INPUT_E3X0_BUTTON
 	  To compile this driver as a module, choose M here: the
 	  module will be called e3x0_button.
 
+config INPUT_EBEAM_USB
+	tristate "USB eBeam driver"
+	depends on USB_ARCH_HAS_HCD
+	select USB
+	help
+	  Say Y here if you have a USB eBeam pointing device and want to
+	  use it without any proprietary user space tools.
+
+	  Have a look at <http://ebeam.tuxfamily.org/> for
+	  a usage description and the required user-space tools.
+
+	  Supported devices :
+	    - Luidia eBeam Classic Projection and eBeam Edge Projection
+	    - Nec NP01Wi1 & NP01Wi2 interactive solution
+
+	  Supposed working devices, need test, may lack functionality :
+	    - Luidia eBeam Edge Whiteboard and eBeam Engage
+	    - Hitachi Starboard FX-63, FX-77, FX-82, FX-77GII
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ebeam.
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
 	depends on PCSPKR_PLATFORM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 53df07d..125f8a9 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_DA9055_ONKEY)	+= da9055_onkey.o
 obj-$(CONFIG_INPUT_DA9063_ONKEY)	+= da9063_onkey.o
 obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_INPUT_E3X0_BUTTON)		+= e3x0-button.o
+obj-$(CONFIG_INPUT_EBEAM_USB)		+= ebeam.o
 obj-$(CONFIG_INPUT_DRV260X_HAPTICS)	+= drv260x.o
 obj-$(CONFIG_INPUT_DRV2665_HAPTICS)	+= drv2665.o
 obj-$(CONFIG_INPUT_DRV2667_HAPTICS)	+= drv2667.o
-- 
2.3.8

^ permalink raw reply related

* [ebeam PATCH v2 0/2] Add a new USB eBeam input driver
From: Yann Cantin @ 2015-08-22 22:06 UTC (permalink / raw)
  To: linux-input, linux-usb
  Cc: linux-kernel, linux-api, dmitry.torokhov, jkosina, gregkh,
	oneukum, Yann Cantin

Hi,

New USB input driver for eBeam devices.

Notable stuff :
- need userspace gui tool for calibration (ebeam.tuxfamily.org)
- This driver breaks Luidia's proprietary application suite.

Patch 1 to blacklist the devices for hid generic-usb.

Patch 2 is the actual driver.

Changes :
RFC https://lkml.org/lkml/2015/7/20/634 : Use DEVICE_ATTR_RW()
RFC https://lkml.org/lkml/2015/7/21/107 : move usb id definitions out of ebeam.c
RFC https://lkml.org/lkml/2015/7/20/657 : Fix ABI documentation

Thanks for your help.


Yann Cantin (2):
hid: Blacklist eBeam devices
input: misc: New USB eBeam input driver

Documentation/ABI/testing/sysfs-driver-ebeam |  53 ++
drivers/hid/hid-core.c                       |   6 +
drivers/hid/hid-ids.h                        |   6 +
drivers/input/misc/Kconfig                   |  22 +
drivers/input/misc/Makefile                  |   1 +
drivers/input/misc/ebeam.c                   | 759 +++++++++++++++++++++++++++
6 files changed, 847 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-driver-ebeam
create mode 100644 drivers/input/misc/ebeam.c

--
2.3.8


^ permalink raw reply

* FINANCIAL GIFT
From: Maria-Elisabeth Schaeffler @ 2015-08-21 18:41 UTC (permalink / raw)
  To: Recipients

I intend to give to you a portion of my Wealth as a free-will financial donation to you. Respond now to partake.

Regards
Maria-Elisabeth Schaeffler
Email:mariaelisabt-1ViLX0X+lBJBDgjK7y7TUQ@public.gmane.org

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

^ permalink raw reply

* Re: [PATCH v7 3/6] mm: Introduce VM_LOCKONFAULT
From: Eric B Munson @ 2015-08-21 18:31 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet,
	Kirill A. Shutemov, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150821072552.GF23723-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 2963 bytes --]

On Fri, 21 Aug 2015, Michal Hocko wrote:

> On Thu 20-08-15 13:03:09, Eric B Munson wrote:
> > On Thu, 20 Aug 2015, Michal Hocko wrote:
> > 
> > > On Wed 19-08-15 17:33:45, Eric B Munson wrote:
> > > [...]
> > > > The group which asked for this feature here
> > > > wants the ability to distinguish between LOCKED and LOCKONFAULT regions
> > > > and without the VMA flag there isn't a way to do that.
> > > 
> > > Could you be more specific on why this is needed?
> > 
> > They want to keep metrics on the amount of memory used in a LOCKONFAULT
> > region versus the address space of the region.
> 
> /proc/<pid>/smaps already exports that information AFAICS. It exports
> VMA flags including VM_LOCKED and if rss < size then this is clearly
> LOCKONFAULT because the standard mlock semantic is to populate. Would
> that be sufficient?
> 
> Now, it is true that LOCKONFAULT wouldn't be distinguishable from
> MAP_LOCKED which failed to populate but does that really matter? It is
> LOCKONFAULT in a way as well.

Does that matter to my users?  No, they do not use MAP_LOCKED at all so
any VMA with VM_LOCKED set and rss < size is lock on fault.  Will it
matter to others?  I suspect so, but these are likely to be the same
group of users which will be suprised to learn that MAP_LOCKED does not
guarantee that the entire range is faulted in on return from mmap.

> 
> > > > Do we know that these last two open flags are needed right now or is
> > > > this speculation that they will be and that none of the other VMA flags
> > > > can be reclaimed?
> > > 
> > > I do not think they are needed by anybody right now but that is not a
> > > reason why it should be used without a really strong justification.
> > > If the discoverability is really needed then fair enough but I haven't
> > > seen any justification for that yet.
> > 
> > To be completely clear you believe that if the metrics collection is
> > not a strong enough justification, it is better to expand the mm_struct
> > by another unsigned long than to use one of these bits right?
> 
> A simple bool is sufficient for that. And yes I think we should go with
> per mm_struct flag rather than the additional vma flag if it has only
> the global (whole address space) scope - which would be the case if the
> LOCKONFAULT is always an mlock modifier and the persistance is needed
> only for MCL_FUTURE. Which is imho a sane semantic.

I am in the middle of implementing lock on fault this way, but I cannot
see how we will hanlde mremap of a lock on fault region.  Say we have
the following:

    addr = mmap(len, MAP_ANONYMOUS, ...);
    mlock(addr, len, MLOCK_ONFAULT);
    ...
    mremap(addr, len, 2 * len, ...)

There is no way for mremap to know that the area being remapped was lock
on fault so it will be locked and prefaulted by remap.  How can we avoid
this without tracking per vma if it was locked with lock or lock on
fault?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH RFC] watchdog: Add watchdog device control through sysfs attributes
From: Pratyush Anand @ 2015-08-21 17:48 UTC (permalink / raw)
  To: linux-0h96xk9xTtrk1uMJSBkQmQ
  Cc: linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, dzickus-H+wXaHxf7aLQT0dZR+AlfA,
	Pratyush Anand, open list:ABI/API, open list, Wim Van Sebroeck

This patch adds following attributes to watchdog device's sysfs interface.

* start - writes non zero value to start and zero to stop
* state - reads whether device is active or not(1 for active and 0 for
inactive)
* identity - reads Watchdog device's identity string.
* keepalive - writes to ping a watchdog device
* timeout - reads current timeout and writes to program a new timeout.
* timeleft - reads timeleft before watchdog generates a reset
* bootstatus - reads status of the watchdog device at boot
* status - reads watchdog device's  internal status bits
* nowayout - reads whether nowayout feature was set or not

Testing with iTCO_wdt:
 # cd /sys/class/watchdog/watchdog1/
 # ls
bootstatus  dev  device  identity  keepalive  nowayout  power  start  state
status  subsystem  timeleft  timeout  uevent
 # cat identity
iTCO_wdt
 # cat timeout
30
 # echo 1 > start
 # cat timeleft
26
 # echo 120 > timeout
 # cat timeleft
116
 # echo > keepalive
 # cat timeleft
118
 # cat state
1
 # echo 0 > start
 # cat state
0
 # cat bootstatus
0
 # cat nowayout
0
 # cat status
cat: status: Operation not supported

Signed-off-by: Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-class-watchdog |  74 +++++++++
 drivers/watchdog/watchdog_core.c               |   6 +-
 drivers/watchdog/watchdog_core.h               |   2 +
 drivers/watchdog/watchdog_dev.c                | 206 +++++++++++++++++++++++++
 4 files changed, 284 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-watchdog

diff --git a/Documentation/ABI/testing/sysfs-class-watchdog b/Documentation/ABI/testing/sysfs-class-watchdog
new file mode 100644
index 000000000000..31e7be53edf8
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-watchdog
@@ -0,0 +1,74 @@
+What:		/sys/class/watchdog/watchdogn/bootstatus
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. It contains status of the watchdog
+		device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of
+		ioctl interface.
+
+What:		/sys/class/watchdog/watchdogn/identity
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. It contains identity string of
+		watchdog device.
+
+What:		/sys/class/watchdog/watchdogn/keepalive
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a write only file. It is written to ping a watchdog
+		device to keep it alive. It is equivalent to
+		WDIOC_KEEPALIVE of ioctl interface.
+
+What:		/sys/class/watchdog/watchdogn/nowayout
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. While reading, it gives '1' if that
+		device supports nowayout feature else, it gives '0'.
+
+What:		/sys/class/watchdog/watchdogn/start
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a write only file. Writing '1' will trigger that
+		watchdog device and writing '0' will stop it. These are
+		equivalent to WDIOS_ENABLECARD and WDIOS_DISABLECARD of ioctl
+		interface. If a device has nowayout programmed, then that
+		can not be stopped. Therefore, it is recommended to read
+		state file to insure that whether watchdog device was
+		stopped or not after writing '0'.
+
+What:		/sys/class/watchdog/watchdogn/state
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. If it is read as '1' then a watchdog
+		device is active. If it is read as '0' then a watchdog
+		device is inactive.
+
+What:		/sys/class/watchdog/watchdogn/status
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. It contains watchdog device's
+		internal status bits. It is equivalent to WDIOC_GETSTATUS
+		of ioctl interface.
+
+What:		/sys/class/watchdog/watchdogn/timeleft
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read only file. It contains value of time left for
+		reset generation. It is equivalent to WDIOC_GETTIMELEFT of
+		ioctl interface.
+
+What:		/sys/class/watchdog/watchdogn/timeout
+Date:		August 2015
+Contact:	Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+Description:
+		It is a read/write file. It is read to know about current
+		timeout and written to program a new timeout value. These
+		are equivalent to WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT of
+		ioctl interface.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a8059455413..703ff7b23f31 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
 
 static int __watchdog_register_device(struct watchdog_device *wdd)
 {
-	int ret, id, devno;
+	int ret, id;
 
 	if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
 		return -EINVAL;
@@ -181,9 +181,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
 		}
 	}
 
-	devno = wdd->cdev.dev;
-	wdd->dev = device_create(watchdog_class, wdd->parent, devno,
-					NULL, "watchdog%d", wdd->id);
+	wdd->dev = watchdog_device_create(watchdog_class, wdd);
 	if (IS_ERR(wdd->dev)) {
 		watchdog_dev_unregister(wdd);
 		ida_simple_remove(&watchdog_ida, id);
diff --git a/drivers/watchdog/watchdog_core.h b/drivers/watchdog/watchdog_core.h
index 6c951418fca7..36abd15ffcea 100644
--- a/drivers/watchdog/watchdog_core.h
+++ b/drivers/watchdog/watchdog_core.h
@@ -31,6 +31,8 @@
 /*
  *	Functions/procedures to be called by the core
  */
+struct device * watchdog_device_create(struct class *,
+				struct watchdog_device *);
 extern int watchdog_dev_register(struct watchdog_device *);
 extern int watchdog_dev_unregister(struct watchdog_device *);
 extern int __init watchdog_dev_init(void);
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefbad303e..1186b5a918e9 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -248,6 +248,212 @@ out_timeleft:
 	return err;
 }
 
+static ssize_t nowayout_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	bool nowayout = false;
+
+	mutex_lock(&wdd->lock);
+	if (test_bit(WDOG_NO_WAY_OUT, &wdd->status))
+		nowayout = true;
+	mutex_unlock(&wdd->lock);
+
+	return sprintf(buf, "%d\n", nowayout);
+}
+static DEVICE_ATTR_RO(nowayout);
+
+static ssize_t status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status;
+	unsigned int val;
+
+	status = watchdog_get_status(wdd, &val);
+	if (!status)
+		status = sprintf(buf, "%u\n", val);
+
+	return status;
+}
+static DEVICE_ATTR_RO(status);
+
+static ssize_t bootstatus_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&wdd->lock);
+	status = sprintf(buf, "%u\n", wdd->bootstatus);
+	mutex_unlock(&wdd->lock);
+
+	return status;
+}
+static DEVICE_ATTR_RO(bootstatus);
+
+static ssize_t timeleft_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status;
+	unsigned int val;
+
+	status = watchdog_get_timeleft(wdd, &val);
+
+	if (!status)
+		status = sprintf(buf, "%u\n", val);
+
+	return status;
+}
+static DEVICE_ATTR_RO(timeleft);
+
+static ssize_t timeout_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	unsigned int val;
+	ssize_t status = 0;
+
+	status = kstrtouint(buf, 0, &val);
+	if (!status) {
+		status = watchdog_set_timeout(wdd, val);
+		if (status >= 0)
+			status = watchdog_ping(wdd);
+	}
+
+	if (status < 0)
+		return status;
+	else
+		return size;
+}
+
+static ssize_t timeout_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&wdd->lock);
+	if (wdd->timeout == 0)
+		status = -EOPNOTSUPP;
+	else
+		status = sprintf(buf, "%u\n", wdd->timeout);
+	mutex_unlock(&wdd->lock);
+
+	return status;
+}
+static DEVICE_ATTR_RW(timeout);
+
+static ssize_t keepalive_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status = 0;
+
+	mutex_lock(&wdd->lock);
+	if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
+		status = -EOPNOTSUPP;
+	mutex_unlock(&wdd->lock);
+
+	if (!status)
+		status = watchdog_ping(wdd);
+
+	if (status < 0)
+		return status;
+	else
+		return size;
+}
+static DEVICE_ATTR_WO(keepalive);
+
+static ssize_t identity_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&wdd->lock);
+	status = sprintf(buf, "%s\n", wdd->info->identity);
+	mutex_unlock(&wdd->lock);
+
+	return status;
+}
+static DEVICE_ATTR_RO(identity);
+
+static ssize_t state_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	bool active;
+
+	mutex_lock(&wdd->lock);
+	active = watchdog_active(wdd);
+	mutex_unlock(&wdd->lock);
+
+	return sprintf(buf, "%d\n", active);
+}
+static DEVICE_ATTR_RO(state);
+
+static ssize_t start_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct watchdog_device *wdd = dev_get_drvdata(dev);
+	ssize_t status = 0;
+	unsigned int val;
+
+	status = kstrtouint(buf, 0, &val);
+	if (status)
+		return status;
+	if (val)
+		status = watchdog_start(wdd);
+	else
+		status = watchdog_stop(wdd);
+
+	if (status < 0)
+		return status;
+	else
+		return size;
+}
+static DEVICE_ATTR_WO(start);
+
+static struct attribute *wdt_attrs[] = {
+	&dev_attr_start.attr,
+	&dev_attr_state.attr,
+	&dev_attr_identity.attr,
+	&dev_attr_keepalive.attr,
+	&dev_attr_timeout.attr,
+	&dev_attr_timeleft.attr,
+	&dev_attr_bootstatus.attr,
+	&dev_attr_status.attr,
+	&dev_attr_nowayout.attr,
+	NULL,
+};
+
+static const struct attribute_group wdt_group = {
+	.attrs = wdt_attrs,
+};
+
+static const struct attribute_group *wdt_groups[] = {
+	&wdt_group,
+	NULL
+};
+
+/*
+ *	watchdog_device_create: create a struct device for a given watchdog
+ *	device
+ *	@wdc: watchdog class with which created device is associated
+ *	@wdd: watchdog device
+ *
+ *	Creates a struct device corresponding to given watchdog device and
+ *	associates a device attribute_group with it.
+ */
+struct device * watchdog_device_create(struct class *wdc,
+					struct watchdog_device *wdd)
+{
+	return device_create_with_groups(wdc, wdd->parent, wdd->cdev.dev,
+			wdd, wdt_groups, "watchdog%d", wdd->id);
+}
+
 /*
  *	watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
  *	@wddev: the watchdog device to do the ioctl on
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH v7 3/6] mm: Introduce VM_LOCKONFAULT
From: Michal Hocko @ 2015-08-21  7:25 UTC (permalink / raw)
  To: Eric B Munson
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet,
	Kirill A. Shutemov, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150820170309.GA11557-JqFfY2XvxFXQT0dZR+AlfA@public.gmane.org>

On Thu 20-08-15 13:03:09, Eric B Munson wrote:
> On Thu, 20 Aug 2015, Michal Hocko wrote:
> 
> > On Wed 19-08-15 17:33:45, Eric B Munson wrote:
> > [...]
> > > The group which asked for this feature here
> > > wants the ability to distinguish between LOCKED and LOCKONFAULT regions
> > > and without the VMA flag there isn't a way to do that.
> > 
> > Could you be more specific on why this is needed?
> 
> They want to keep metrics on the amount of memory used in a LOCKONFAULT
> region versus the address space of the region.

/proc/<pid>/smaps already exports that information AFAICS. It exports
VMA flags including VM_LOCKED and if rss < size then this is clearly
LOCKONFAULT because the standard mlock semantic is to populate. Would
that be sufficient?

Now, it is true that LOCKONFAULT wouldn't be distinguishable from
MAP_LOCKED which failed to populate but does that really matter? It is
LOCKONFAULT in a way as well.

> > > Do we know that these last two open flags are needed right now or is
> > > this speculation that they will be and that none of the other VMA flags
> > > can be reclaimed?
> > 
> > I do not think they are needed by anybody right now but that is not a
> > reason why it should be used without a really strong justification.
> > If the discoverability is really needed then fair enough but I haven't
> > seen any justification for that yet.
> 
> To be completely clear you believe that if the metrics collection is
> not a strong enough justification, it is better to expand the mm_struct
> by another unsigned long than to use one of these bits right?

A simple bool is sufficient for that. And yes I think we should go with
per mm_struct flag rather than the additional vma flag if it has only
the global (whole address space) scope - which would be the case if the
LOCKONFAULT is always an mlock modifier and the persistance is needed
only for MCL_FUTURE. Which is imho a sane semantic.
-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* Re: Persistent Reservation API V2
From: Christoph Hellwig @ 2015-08-21  6:59 UTC (permalink / raw)
  To: Keith Busch
  Cc: Jens Axboe, linux-api, dm-devel, linux-nvme, linux-scsi,
	linux-kernel
In-Reply-To: <alpine.LNX.2.00.1508202317270.15930@localhost.lm.intel.com>

On Thu, Aug 20, 2015 at 11:56:36PM +0000, Keith Busch wrote:

> NVMe can also specify
> if whether or not a reservation should persist through power-loss.

SCSI does as well, it's the APTPL flag.  However reservations not persistent
through a power loss are basically useless, so I decided to force them on
in the API.  From the documentation:

"All implementations are expected to ensure the reservations survive
 a power loss"

So I would prefer not to add it, or if we really have to as a negative flag
to specifically opt out of the APTPL behavior.

> with it. For example, NVMe can ignore existing keys when acquiring a
> reservation in addition to registering a new key.

This sounds like a sensible addition to me, and I wouldn't be surprised
if future SPC versions will add this flag.

^ permalink raw reply

* Re: [PATCH v2 0/3] SysFS driver for QEMU fw_cfg device
From: Gabriel L. Somlo @ 2015-08-21  3:47 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-kernel@vger.kernel.org, Richard W.M. Jones, Jordan Justen,
	x86@kernel.org, QEMU Developers, Gleb Natapov, Matt Fleming,
	kernelnewbies, Gerd Hoffmann, Paolo Bonzini, Laszlo Ersek,
	gregkh@linuxfoundation.org, ralf, zajec5, paul, Kumar Gala,
	linux-api, Leif Lindholm
In-Reply-To: <CAKv+Gu9wr+BUDjoz9NAkLNXxViDOM_PRoZRU8sxHog-iX=yUpQ@mail.gmail.com>

On Thu, Aug 20, 2015 at 07:21:48AM +0200, Ard Biesheuvel wrote:
> On 19 August 2015 at 22:49, Gabriel L. Somlo <somlo@cmu.edu> wrote:
> >> > From: "Gabriel L. Somlo" <somlo@cmu.edu>
> >> >> Several different architectures supported by QEMU are set up with a
> >> >> "firmware configuration" (fw_cfg) device, used to pass configuration
> >> >> "blobs" into the guest by the host running QEMU.
> >> >>
> >> >> Historically, these config blobs were mostly of interest to the guest
> >> >> BIOS, but since QEMU v2.4 it is possible to insert arbitrary blobs via
> >> >> the command line, which makes them potentially interesting to userspace
> >> >> (e.g. for passing early boot environment variables, etc.).
> >> >>
> >> >
> >> > Does 'potentially interesting' mean you have a use case? Could you elaborate?
> >
> > My personal one would be something like:
> >
> > cat > guestinfo.txt << EOT
> >   KEY1="val1"
> >   KEY2="val2"
> >   ...
> > EOT
> >
> > qemu-system-x86_64 ... -fw-cfg name="opt/guestinfo",file=./guestinfo.txt ...
> >
> > Then, from inside the guest:
> >
> >   . /sys/firmware/qemu_fw_cfg/by_name/opt/guestinfo/raw
> >
> >   do_something_with $KEY1 $KEY2
> >   ...
> >
> > But I'm thinking this is only one of the many positive things one
> > could do with the ability to access random host-supplied blobs from
> > guest userspace :)
> >
> 
> 'random host-supplied blobs' sounds awfully like files in a file
> system to me, and that is already supported by QEMU and works with any
> guest OS unmodified. If you are in control of the command line, surely
> you can add a -drive xxx,fat:path/to/blobs -device xxx pair that
> simply turns up as a volume.

That did come up, here's the start of original thread on the qemu mailing
list from a while back:

https://lists.gnu.org/archive/html/qemu-devel/2015-02/msg00371.html

To recap, the main advantages to transfering data this way are:

	1. Asynchronous

	   The host can simply pass data via the qemu command line, and
	   not have to care if/when the guest is ready to accept the
	   data (i.e. has made it far enough to e.g. start a guest agent)

	2. Out-of-band

	   I don't have to take over a user-visible element such as a
	   disk drive. Same reason VSOCK (or VMWare VMCI for that matter)
	   exist and are NOT actual Ethernet/TCP-IP network interfaces :)

> > DT on ARM is fine, and I'm certainly happy to learn how to do it (even
> > though my main focus is, for now, x86). The unfortunate thing though
> > is that on x86, fw_cfg is *not* AFAICT in ACPI, so I'd have to detour into
> > first adding it in on the host side, before I can rewrite the guest side
> > driver to look it up in there :)
> >
> >> > I am not sure how relevant sun4 and ppc/mac are for what you are trying to
> >> > accomplish, but perhaps it would be best to focus on x86 and ARM for now
> >> > and do it correctly. If the probing is actually needed, you can always add
> >> > it later.
> >
> > I guess that's the direction things seem to be headed, although it would
> > make me a bit sad to leave out sun and ppc right from the very beginning :)
> >
> 
> Sorry to be blunt, but I am not convinced there is a need for this
> driver anyway.

See above (hopefully I'm being sufficiently persuasive :) )

In VMWare one would fetch similar "guestinfo" variables via something like

	FOO=$(vmware-tools --getinfo "FOO")

but I thought exposing fw_cfg in /sys/firmware/... would make access to
*any* blobs (including, but not limited to my particular use case) even
easier and more generic than that.

> > PS. If you have one .c file in the kernel which does any of the DT-on-arm
> > boilerplate I'm supposed to immitate, I'd appreciate the shortcut :)
> >
> 
> Check out drivers/tty/serial/amba-pl011.c

I'll check it out.

Thanks much!
--Gabriel

^ permalink raw reply

* Re: Persistent Reservation API V2
From: Keith Busch @ 2015-08-20 23:56 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jens Axboe, linux-api-u79uwXL29TY76Z2rM5mHXA,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA,
	linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1439360604-16192-1-git-send-email-hch-jcswGhMUV9g@public.gmane.org>

On Tue, 11 Aug 2015, Christoph Hellwig wrote:
> This series adds support for a simplified Persistent Reservation API
> to the block layer.  The intent is that both in-kernel and userspace
> consumers can use the API instead of having to hand craft SCSI or NVMe
> command through the various pass through interfaces.  It also adds
> DM support as getting reservations through dm-multipath is a major
> pain with the current scheme.
>
> NVMe support currently isn't included as I don't have a multihost
> NVMe setup to test on, but Keith offered to test it and I'll have
> a patch for it shortly.

Hi Christoph,

I wrote an nvme implementation and it seems to work as expected with your
pr-tests (minor modification to open an nvme target). While API appears to
work as designed, there are a few features of NVMe that are unreachable
with it. For example, NVMe can ignore existing keys when acquiring a
reservation in addition to registering a new key. NVMe can also specify
if whether or not a reservation should persist through power-loss.

Anyway, I don't think SCSI has these same options. Should this new IOCTL
API accommodate the common subset to maintain its simplicity, or make
it more expressive for all features? The more important question might
be if there are any users requiring these features, and I honestly don't
know that right now.

^ permalink raw reply

* Re: [PATCH v7 3/6] mm: Introduce VM_LOCKONFAULT
From: Eric B Munson @ 2015-08-20 17:03 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet,
	Kirill A. Shutemov, linux-kernel, dri-devel, linux-mm, linux-api
In-Reply-To: <20150820075611.GD4780@dhcp22.suse.cz>

[-- Attachment #1: Type: text/plain, Size: 1121 bytes --]

On Thu, 20 Aug 2015, Michal Hocko wrote:

> On Wed 19-08-15 17:33:45, Eric B Munson wrote:
> [...]
> > The group which asked for this feature here
> > wants the ability to distinguish between LOCKED and LOCKONFAULT regions
> > and without the VMA flag there isn't a way to do that.
> 
> Could you be more specific on why this is needed?

They want to keep metrics on the amount of memory used in a LOCKONFAULT
region versus the address space of the region.

> 
> > Do we know that these last two open flags are needed right now or is
> > this speculation that they will be and that none of the other VMA flags
> > can be reclaimed?
> 
> I do not think they are needed by anybody right now but that is not a
> reason why it should be used without a really strong justification.
> If the discoverability is really needed then fair enough but I haven't
> seen any justification for that yet.

To be completely clear you believe that if the metrics collection is
not a strong enough justification, it is better to expand the mm_struct
by another unsigned long than to use one of these bits right?


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH 2/2] PCI: Add support for Enhanced Allocation devices
From: Sean O. Stalley @ 2015-08-20 16:59 UTC (permalink / raw)
  To: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	rajatxjain-Re5JQEeQqe8AvxtiuMwx3w, mst-H+wXaHxf7aLQT0dZR+AlfA,
	zajec5-Re5JQEeQqe8AvxtiuMwx3w, gong.chen-VuQAYsv1563Yd54FQh9/CA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: sean.stalley-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <1440089947-2839-1-git-send-email-sean.stalley-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Add support for devices using Enhanced Allocation entries instead of BARs.
This patch allows the kernel to parse the EA Extended Capability structure
in PCI configspace and claim the BAR-equivalent resources.

Signed-off-by: Sean O. Stalley <sean.stalley-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/pci/pci.c   | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h   |   1 +
 drivers/pci/probe.c |   3 +
 3 files changed, 223 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0008c95..c8217a8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2134,6 +2134,225 @@ void pci_pm_init(struct pci_dev *dev)
 	}
 }
 
+static unsigned long pci_ea_set_flags(struct pci_dev *dev, u8 prop)
+{
+	unsigned long flags = IORESOURCE_PCI_FIXED;
+
+	switch (prop) {
+	case PCI_EA_P_MEM:
+		flags |= IORESOURCE_MEM;
+		break;
+	case PCI_EA_P_MEM_PREFETCH:
+		flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		break;
+	case PCI_EA_P_IO:
+		flags |= IORESOURCE_IO;
+		break;
+	default:
+		dev_warn(&dev->dev, "%s: Property type %x not supported\n",
+			__func__, prop);
+		return 0;
+	}
+
+	return flags;
+}
+
+static struct resource *pci_ea_get_parent_resource(struct pci_dev *dev,
+					struct resource *res)
+{
+	struct resource *parent;
+
+	parent = pci_find_parent_resource(dev, res);
+	if (parent)
+		return parent;
+
+	/* for resources not claimed by a bridge */
+	if (res->flags & IORESOURCE_MEM)
+		return &iomem_resource;
+
+	if (res->flags & IORESOURCE_IO)
+		return &ioport_resource;
+
+	return NULL;
+}
+
+/* claim the memory for this device in the proper location */
+static void pci_ea_claim_resource(struct pci_dev *dev, struct resource *res)
+{
+	struct resource *parent;
+	struct resource *conflict;
+
+	parent = pci_ea_get_parent_resource(dev, res);
+	if (!parent) {
+		dev_warn(&dev->dev, "can't find parent resource for EA entry %s %pR\n",
+			res->name, res);
+		return;
+	}
+
+	/* claim the appropriate resource */
+	conflict = request_resource_conflict(parent, res);
+	if (conflict) {
+		dev_warn(&dev->dev, "can't claim EA entry %s %pR: address conflict with %s %pR\n",
+			 res->name, res, conflict->name, conflict);
+	}
+}
+
+static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei)
+{
+	if (bei <= PCI_STD_RESOURCE_END)
+		return &dev->resource[bei];
+	else if (bei == PCI_EA_BEI_ROM)
+		return &dev->resource[PCI_ROM_RESOURCE];
+	else
+		return NULL;
+}
+
+/* Read an Enhanced Allocation (EA) entry */
+static int pci_ea_read(struct pci_dev *dev, int offset)
+{
+	struct resource *res;
+	int ent_offset = offset;
+	int ent_size;
+	resource_size_t start;
+	resource_size_t end;
+	unsigned long flags;
+	u32 dw0;
+	u32 base;
+	u32 max_offset;
+	bool support_64 = (sizeof(resource_size_t) >= 8);
+
+	pci_read_config_dword(dev, ent_offset, &dw0);
+	ent_offset += 4;
+
+	/* Entry size field indicates DWORDs after 1st */
+	ent_size = ((dw0 & PCI_EA_ES) + 1) << 2;
+
+	if (!(dw0 & PCI_EA_ENABLE)) {
+		dev_err(&dev->dev, "%s: Entry not enabled\n", __func__);
+		goto out;
+	}
+
+	res = pci_ea_get_resource(dev, PCI_EA_BEI(dw0));
+	if (!res) {
+		dev_err(&dev->dev, "%s: Unsupported EA entry BEI\n", __func__);
+		goto out;
+	}
+
+	flags = pci_ea_set_flags(dev, PCI_EA_PP(dw0));
+	if (!flags)
+		flags = pci_ea_set_flags(dev, PCI_EA_SP(dw0));
+	if (!flags) {
+		dev_err(&dev->dev, "%s: Entry EA properties not supported\n",
+			__func__);
+		goto out;
+	}
+
+	/* Read Base */
+	pci_read_config_dword(dev, ent_offset, &base);
+	start = (base & PCI_EA_FIELD_MASK);
+	ent_offset += 4;
+
+	/* Read MaxOffset */
+	pci_read_config_dword(dev, ent_offset, &max_offset);
+	ent_offset += 4;
+
+	/* Read Base MSBs (if 64-bit entry) */
+	if (base & PCI_EA_IS_64) {
+		u32 base_upper;
+
+		pci_read_config_dword(dev, ent_offset, &base_upper);
+		ent_offset += 4;
+
+		flags |= IORESOURCE_MEM_64;
+
+		/* entry starts above 32-bit boundary, can't use */
+		if (!support_64 && base_upper)
+			goto out;
+
+		if (support_64)
+			start |= ((u64)base_upper << 32);
+	}
+
+	dev_dbg(&dev->dev, "%s: start = %pa\n", __func__, &start);
+
+	end = start + (max_offset | 0x03);
+
+	/* Read MaxOffset MSBs (if 64-bit entry) */
+	if (max_offset & PCI_EA_IS_64) {
+		u32 max_offset_upper;
+
+		pci_read_config_dword(dev, ent_offset, &max_offset_upper);
+		ent_offset += 4;
+
+		flags |= IORESOURCE_MEM_64;
+
+		/* entry too big, can't use */
+		if (!support_64 && max_offset_upper)
+			goto out;
+
+		if (support_64)
+			end += ((u64)max_offset_upper << 32);
+	}
+
+	dev_dbg(&dev->dev, "%s: end = %pa\n", __func__, &end);
+
+	if (end < start) {
+		dev_err(&dev->dev, "EA Entry crosses address boundary\n");
+		goto out;
+	}
+
+	if (ent_size != ent_offset - offset) {
+		dev_err(&dev->dev, "EA entry size does not match length read\n"
+			"(Entry Size:%u Length Read:%u)\n",
+			ent_size, ent_offset - offset);
+		goto out;
+	}
+
+	res->name = pci_name(dev);
+	res->start = start;
+	res->end = end;
+	res->flags = flags;
+
+	pci_ea_claim_resource(dev, res);
+
+out:
+	return offset + ent_size;
+}
+
+/* Enhanced Allocation Initalization */
+void pci_ea_init(struct pci_dev *dev)
+{
+	int ea;
+	u8 num_ent;
+	int offset;
+	int i;
+
+	/* find PCI EA capability in list */
+	ea = pci_find_capability(dev, PCI_CAP_ID_EA);
+	if (!ea)
+		return;
+
+	dev_dbg(&dev->dev, "%s: capability found!\n", __func__);
+
+	/* determine the number of entries */
+	pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT,
+					&num_ent);
+	num_ent &= PCI_EA_NUM_ENT_MASK;
+
+	offset = ea + PCI_EA_FIRST_ENT;
+
+	/* Skip DWORD 2 for type 1 functions */
+	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+		offset += 4;
+		/* TODO: Support fixed bus numbers */
+
+	for (i = 0; i < num_ent; ++i) {
+		/* parse each EA entry */
+		dev_dbg(&dev->dev, "%s: parsing entry %i...\n", __func__, i);
+		offset = pci_ea_read(dev, offset);
+	}
+}
+
 static void pci_add_saved_cap(struct pci_dev *pci_dev,
 	struct pci_cap_saved_state *new_cap)
 {
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4ff0ff1..92fbef0 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -76,6 +76,7 @@ bool pci_dev_keep_suspended(struct pci_dev *dev);
 void pci_config_pm_runtime_get(struct pci_dev *dev);
 void pci_config_pm_runtime_put(struct pci_dev *dev);
 void pci_pm_init(struct pci_dev *dev);
+void pci_ea_init(struct pci_dev *dev);
 void pci_allocate_cap_save_buffers(struct pci_dev *dev);
 void pci_free_cap_save_buffers(struct pci_dev *dev);
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cefd636..4cadf35 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1522,6 +1522,9 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
 
 static void pci_init_capabilities(struct pci_dev *dev)
 {
+	/* Enhanced Allocation */
+	pci_ea_init(dev);
+
 	/* MSI/MSI-X list */
 	pci_msi_init_pci_dev(dev);
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/2] PCI: Add Enhanced Allocation register entries
From: Sean O. Stalley @ 2015-08-20 16:59 UTC (permalink / raw)
  To: bhelgaas, rajatxjain, mst, zajec5, gong.chen, linux-pci,
	linux-kernel, linux-api
  Cc: sean.stalley
In-Reply-To: <1440089947-2839-1-git-send-email-sean.stalley@intel.com>

Add registers defined in PCI-SIG's Enhanced allocation ECN.

Signed-off-by: Sean O. Stalley <sean.stalley@intel.com>
---
 include/uapi/linux/pci_regs.h | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 413417f..084ce98 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -216,7 +216,8 @@
 #define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
 #define  PCI_CAP_ID_SATA	0x12	/* SATA Data/Index Conf. */
 #define  PCI_CAP_ID_AF		0x13	/* PCI Advanced Features */
-#define  PCI_CAP_ID_MAX		PCI_CAP_ID_AF
+#define  PCI_CAP_ID_EA		0x14	/* PCI Enhanced Allocation */
+#define  PCI_CAP_ID_MAX		PCI_CAP_ID_EA
 #define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
 #define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
 #define PCI_CAP_SIZEOF		4
@@ -353,6 +354,43 @@
 #define  PCI_AF_STATUS_TP	0x01
 #define PCI_CAP_AF_SIZEOF	6	/* size of AF registers */
 
+/* PCI Enhanced Allocation registers */
+
+#define PCI_EA_NUM_ENT		2	/* Number of Capability Entries */
+#define PCI_EA_NUM_ENT_MASK	0x3f	/* Num Entries Mask */
+#define PCI_EA_FIRST_ENT	4	/* First EA Entry in List */
+#define PCI_EA_FIRST_ENT_BRIDGE	8	/* First EA Entry for Bridges */
+#define PCI_EA_ES		0x7	/* Entry Size */
+#define PCI_EA_BEI(x)	(((x) >> 4) & 0xf) /* BAR Equivalent Indicator */
+/* 0-5 map to BARs 0-5 respectively */
+#define  PCI_EA_BEI_BRIDGE	6	/* Resource behind bridge */
+#define  PCI_EA_BEI_ENI		7	/* Equivalent Not Indicated */
+#define  PCI_EA_BEI_ROM		8	/* Expansion ROM */
+/* 9-14 map to VF BARs 0-5 respectively */
+#define  PCI_EA_BEI_RESERVED	15	/* Reserved - Treat like ENI */
+
+#define PCI_EA_PP(x)	(((x) >>  8) & 0xff)	/* Primary Properties */
+#define PCI_EA_SP(x)	(((x) >> 16) & 0xff)	/* Secondary Properties */
+#define  PCI_EA_P_MEM			0x00	/* Non-Prefetch Memory */
+#define  PCI_EA_P_MEM_PREFETCH		0x01	/* Prefetchable Memory */
+#define  PCI_EA_P_IO			0x02	/* I/O Space */
+#define  PCI_EA_P_VIRT_MEM_PREFETCH	0x03	/* VF Prefetchable Memory */
+#define  PCI_EA_P_VIRT_MEM		0x04	/* VF Non-Prefetch Memory */
+#define  PCI_EA_P_BRIDGE_MEM		0x05	/* Bridge Non-Prefetch Memory */
+#define  PCI_EA_P_BRIDGE_MEM_PREFETCH	0x06	/* Bridge Prefetchable Memory */
+#define  PCI_EA_P_BRIDGE_IO		0x07	/* Bridge I/O Space */
+/* 0x08-0xfc reserved */
+#define  PCI_EA_P_MEM_RESERVED		0xfd	/* Reserved Memory */
+#define  PCI_EA_P_IO_RESERVED		0xfe	/* Reserved I/O Space */
+#define  PCI_EA_P_UNAVAILABLE		0xff	/* Entry Unavailable */
+#define PCI_EA_WRITEABLE	BIT(30) /* Writable, 1 = RW, 0 = HwInit */
+#define PCI_EA_ENABLE		BIT(31) /* Enable for this entry */
+#define PCI_EA_BASE		4	/* Base Address Offset */
+#define PCI_EA_MAX_OFFSET	8	/* MaxOffset (resource length) */
+/* bit 0 is reserved */
+#define PCI_EA_IS_64		BIT(1)	/* 64-bit field flag */
+#define PCI_EA_FIELD_MASK	0xfffffffc	/* For Base & Max Offset */
+
 /* PCI-X registers (Type 0 (non-bridge) devices) */
 
 #define PCI_X_CMD		2	/* Modes & Features */
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/2] PCI: Add support for PCI Enhanced Allocation "BARs"
From: Sean O. Stalley @ 2015-08-20 16:59 UTC (permalink / raw)
  To: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	rajatxjain-Re5JQEeQqe8AvxtiuMwx3w, mst-H+wXaHxf7aLQT0dZR+AlfA,
	zajec5-Re5JQEeQqe8AvxtiuMwx3w, gong.chen-VuQAYsv1563Yd54FQh9/CA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: sean.stalley-ral2JQCrhuEAvxtiuMwx3w

PCI Enhanced Allocation is a new method of allocating MMIO & IO
resources for PCI devices & bridges. It can be used instead
of the traditional PCI method of using BARs.

EA entries are hardware-initialized to a fixed address.
Unlike BARs, regions described by EA are cannot be moved.
Because of this, only devices which are permanently connected to
the PCI bus can use EA. A removable PCI card must not use EA.

This patchset adds support for using EA entries instead of BARs.

The Enhanced Allocation ECN is publicly available here:
https://www.pcisig.com/specifications/conventional/ECN_Enhanced_Allocation_23_Oct_2014_Final.pdf

Sean O. Stalley (2):
  PCI: Add Enhanced Allocation register entries
  PCI: Add parsing of Enhanced Allocation entries

 drivers/pci/pci.c             | 219 ++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h             |   1 +
 drivers/pci/probe.c           |   3 +
 include/uapi/linux/pci_regs.h |  40 +++++++-
 4 files changed, 262 insertions(+), 1 deletion(-)

-- 
1.9.1

^ permalink raw reply

* Re: [PATCH v7 3/6] mm: Introduce VM_LOCKONFAULT
From: Michal Hocko @ 2015-08-20  7:56 UTC (permalink / raw)
  To: Eric B Munson
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet,
	Kirill A. Shutemov, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150819213345.GB4536-JqFfY2XvxFXQT0dZR+AlfA@public.gmane.org>

On Wed 19-08-15 17:33:45, Eric B Munson wrote:
[...]
> The group which asked for this feature here
> wants the ability to distinguish between LOCKED and LOCKONFAULT regions
> and without the VMA flag there isn't a way to do that.

Could you be more specific on why this is needed?

> Do we know that these last two open flags are needed right now or is
> this speculation that they will be and that none of the other VMA flags
> can be reclaimed?

I do not think they are needed by anybody right now but that is not a
reason why it should be used without a really strong justification.
If the discoverability is really needed then fair enough but I haven't
seen any justification for that yet.

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* Re: [PATCH v7 3/6] mm: Introduce VM_LOCKONFAULT
From: Vlastimil Babka @ 2015-08-20  7:53 UTC (permalink / raw)
  To: Eric B Munson, Michal Hocko
  Cc: Andrew Morton, Jonathan Corbet, Kirill A. Shutemov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150819213345.GB4536-JqFfY2XvxFXQT0dZR+AlfA@public.gmane.org>

On 08/19/2015 11:33 PM, Eric B Munson wrote:
> On Wed, 12 Aug 2015, Michal Hocko wrote:
>
>> On Sun 09-08-15 01:22:53, Eric B Munson wrote:
>>
>> I do not like this very much to be honest. We have only few bits
>> left there and it seems this is not really necessary. I thought that
>> LOCKONFAULT acts as a modifier to the mlock call to tell whether to
>> poppulate or not. The only place we have to persist it is
>> mlockall(MCL_FUTURE) AFAICS. And this can be handled by an additional
>> field in the mm_struct. This could be handled at __mm_populate level.
>> So unless I am missing something this would be much more easier
>> in the end we no new bit in VM flags would be necessary.
>>
>> This would obviously mean that the LOCKONFAULT couldn't be exported to
>> the userspace but is this really necessary?
>
> Sorry for the latency here, I was on vacation and am now at plumbers.
>
> I am not sure that growing the mm_struct by another flags field instead
> of using available bits in the vm_flags is the right choice.

I was making the same objection on one of the earlier versions and since 
you sticked with a new vm flag, I thought it doesn't matter, as we could 
change it later if we run out of bits. But now I realize that since you 
export this difference to userspace (and below you say that it's by 
request), we won't be able to change it later. So it's a more difficult 
choice.

> After this
> patch, we still have 3 free bits on 32 bit architectures (2 after the
> userfaultfd set IIRC).  The group which asked for this feature here
> wants the ability to distinguish between LOCKED and LOCKONFAULT regions
> and without the VMA flag there isn't a way to do that.
>
> Do we know that these last two open flags are needed right now or is
> this speculation that they will be and that none of the other VMA flags
> can be reclaimed?

I think it's the latter, we can expect that flags will be added rather 
than removed, as removal is hard or impossible.

^ permalink raw reply

* Re: [PATCH v2 0/3] SysFS driver for QEMU fw_cfg device
From: Ard Biesheuvel @ 2015-08-20  5:21 UTC (permalink / raw)
  To: Gabriel L. Somlo
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Richard W.M. Jones, Jordan Justen,
	x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, QEMU Developers,
	Gleb Natapov, Matt Fleming,
	kernelnewbies-7JyXY6prKcjpASu1u0TL5ti2O/JbrIOy, Gerd Hoffmann,
	Paolo Bonzini, Laszlo Ersek,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org,
	ralf-6z/3iImG2C8G8FEW9MqTrA, zajec5-Re5JQEeQqe8AvxtiuMwx3w,
	paul-DWxLp4Yu+b8AvxtiuMwx3w, Kumar Gala,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Leif Lindholm
In-Reply-To: <20150819204915.GA6164-VPZ87SnTp2qKUezXOiBB2eW1CriLhL8O@public.gmane.org>

On 19 August 2015 at 22:49, Gabriel L. Somlo <somlo-D+Gtc/HYRWM@public.gmane.org> wrote:
> Hi Ard,
>
> On Wed, Aug 19, 2015 at 11:42:02AM +0200, Ard Biesheuvel wrote:
>> (missed some cc's)
>>
>> On 19 August 2015 at 11:38, Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> > From: "Gabriel L. Somlo" <somlo-D+Gtc/HYRWM@public.gmane.org>
>> >> Several different architectures supported by QEMU are set up with a
>> >> "firmware configuration" (fw_cfg) device, used to pass configuration
>> >> "blobs" into the guest by the host running QEMU.
>> >>
>> >> Historically, these config blobs were mostly of interest to the guest
>> >> BIOS, but since QEMU v2.4 it is possible to insert arbitrary blobs via
>> >> the command line, which makes them potentially interesting to userspace
>> >> (e.g. for passing early boot environment variables, etc.).
>> >>
>> >
>> > Does 'potentially interesting' mean you have a use case? Could you elaborate?
>
> My personal one would be something like:
>
> cat > guestinfo.txt << EOT
>   KEY1="val1"
>   KEY2="val2"
>   ...
> EOT
>
> qemu-system-x86_64 ... -fw-cfg name="opt/guestinfo",file=./guestinfo.txt ...
>
> Then, from inside the guest:
>
>   . /sys/firmware/qemu_fw_cfg/by_name/opt/guestinfo/raw
>
>   do_something_with $KEY1 $KEY2
>   ...
>
> But I'm thinking this is only one of the many positive things one
> could do with the ability to access random host-supplied blobs from
> guest userspace :)
>

'random host-supplied blobs' sounds awfully like files in a file
system to me, and that is already supported by QEMU and works with any
guest OS unmodified. If you are in control of the command line, surely
you can add a -drive xxx,fat:path/to/blobs -device xxx pair that
simply turns up as a volume.

>> >>   1/3 - probes for the qemu fw_cfg device in locations known to work on
>> >>       the supported architectures, in decreasing order of "likelihood".
>> >>
>> >>       While it *may* be possible to detect the presence of fw_cfg via
>> >>       acpi or dtb (on x86 and arm, respectively), there's no way I know
>> >>       of attempting that on sun4 and ppc/mac, so I've stuck with simply
>> >>       probing (the fw_cfg_modes[] structure and fw_cfg_io_probe() function)
>> >>       in fw_cfg.c. I could use some advice on how else that could be
>> >>       done more elegantly, if needed.
>> >>
>> >
>> > Sorry, but this is really out of the question, at least on ARM, but surely on
>> > other architectures as well. You can't just go around and probe random memory
>> > addresses. Perhaps QEMU tolerates it, but on anything that resembles a real
>> > system, this will immediately blow up. Also, what happens if the QEMU memory
>> > map changes? Add more probes addresses?
>> >
>> > It is not /that/ difficult to simply wire it up to the DT and ACPI
>> > infrastructures, there are plenty of examples in the kernel tree how to
>> > accomplish that. As a bonus, it removes all the arch specific knowledge
>> > from your code, which means that if QEMU grows support for another DT or
>> > ACPI based architecture, it will just work.
>
> I was *hoping* a successful call to request_[mem_]region() will be
> enough in the way of asking for permission before probing for the
> fw_cfg registers, but I realize that might still not be polite enough :)
>

No, all request_mem_region() does is check whether the region in
question is not occupied yet by another driver. So your probing could
access unpopulated memory space, or MMIO space owned by a peripheral
whose driver is not loaded. Neither are allowable, I'm afraid.

> DT on ARM is fine, and I'm certainly happy to learn how to do it (even
> though my main focus is, for now, x86). The unfortunate thing though
> is that on x86, fw_cfg is *not* AFAICT in ACPI, so I'd have to detour into
> first adding it in on the host side, before I can rewrite the guest side
> driver to look it up in there :)
>
>> > I am not sure how relevant sun4 and ppc/mac are for what you are trying to
>> > accomplish, but perhaps it would be best to focus on x86 and ARM for now
>> > and do it correctly. If the probing is actually needed, you can always add
>> > it later.
>
> I guess that's the direction things seem to be headed, although it would
> make me a bit sad to leave out sun and ppc right from the very beginning :)
>

Sorry to be blunt, but I am not convinced there is a need for this
driver anyway.

> PS. If you have one .c file in the kernel which does any of the DT-on-arm
> boilerplate I'm supposed to immitate, I'd appreciate the shortcut :)
>

Check out drivers/tty/serial/amba-pl011.c

> PS2. Do you happen to be in Seattle right now ? :)

Nope :-)

^ permalink raw reply

* Re: Next round: revised futex(2) man page for review
From: Thomas Gleixner @ 2015-08-19 23:17 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Darren Hart, Torvald Riegel, Carlos O'Donell, Ingo Molnar,
	Jakub Jelinek, linux-man, lkml, Davidlohr Bueso, Arnd Bergmann,
	Steven Rostedt, Peter Zijlstra, Linux API, Roland McGrath,
	Anton Blanchard, Eric Dumazet, bill o gallmeister, Jan Kiszka,
	Daniel Wagner, Rich Felker, Andy Lutomirski, bert hubert,
	Rusty Russell, Heinrich Schuchardt
In-Reply-To: <55C5A787.9010806-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 9334 bytes --]

On Sat, 8 Aug 2015, Michael Kerrisk (man-pages) wrote:
> >>        FUTEX_CMP_REQUEUE (since Linux 2.6.7)
> >>               This  operation  first  checks  whether the location uaddr
> >>               still contains the value  val3.   If  not,  the  operation
> >>               fails  with  the  error  EAGAIN.  Otherwise, the operation
> >>               wakes up a maximum of val waiters that are waiting on  the
> >>               futex  at uaddr.  If there are more than val waiters, then
> >>               the remaining waiters are removed from the wait  queue  of
> >>               the  source  futex at uaddr and added to the wait queue of
> >>               the target futex at uaddr2.  The val2  argument  specifies
> >>               an  upper limit on the number of waiters that are requeued
> >>               to the futex at uaddr2.
> >>
> >> .\" FIXME(Torvald) Is the following correct?  Or is just the decision
> >> .\" which threads to wake or requeue part of the atomic operation?
> >>
> >>               The load from uaddr is  an  atomic  memory  access  (i.e.,
> >>               using atomic machine instructions of the respective archi‐
> >>               tecture).  This load, the comparison with  val3,  and  the
> >>               requeueing  of  any  waiters  are performed atomically and
> >>               totally ordered with respect to other  operations  on  the
> >>               same futex word.
> > 
> > It's atomic as the other atomic operations on the futex word. It's
> > always performed with the proper lock(s) held in the kernel. That
> > means any concurrent operation will serialize on that lock(s). User
> > space has to make sure, that depending on the observed value no
> > concurrent operations happen, but that's something the kernel cannot
> > control.
> 
> ???
> Sorry, I'm not clear here. Is the current text correct then? Or is some
> change needed.

I think we need some change here because the meaning of atomic is
unclear. The basic rules of futexes are:

 - All modifying operations on the futex value have to be done with
   atomic instructions, usually cmpxchg. That applies to both kernel
   and user space.

   That's the atomicity at the futex value level.

 - In the kernel we have to create/modify/destroy state in order to
   provide the blocking/requeueing etc.

   This state needs protection as well. So all operations related to
   the kernel internal state are serialized on the hash bucket
   locks. The hash buckets are a scalability mechanism to avoid
   contention on a single lock protecting all kernel internal
   state. For simplicity reasons you can just think of a global lock
   protecting all kernel internal state.

   If the kernel creates/modifies state then it can be necessary to
   either reread the futex value or modify it. That happens under the
   locks as well.

   So in the case of requeue, we take the proper locks and perform the
   comparison with val3 and the requeueing with the locks held.
   
   So that lock protection makes these operations 'atomic'. The
   correct expression is 'serialized'.
 
> >> .\" FIXME We need some explanation in the following paragraph of *why*
> >> .\"       it is important to note that "the kernel will update the
> >> .\"       futex word's value prior
> >>        It is important to note to returning to user space" . Can someone
> >>        explain?   that  the  kernel  will  update the futex word's value
> >>        prior to returning to user space.  Unlike the other futex  opera‐
> >>        tions  described  above, the PI futex operations are designed for
> >>        the implementation of very specific IPC mechanisms.
> > 
> > If there are multiple waiters on a pi futex then a wake pi operation
> > will wake the first waiter and hand over the lock to this waiter. This
> > includes handing over the rtmutex which represents the futex in the
> > kernel. The strict requirement is that the futex owner and the rtmutex
> > owner must be the same, except for the update period which is
> > serialized by the futex internal locking. That means the kernel must
> > update the user space value prior to returning to user space.

And as noted above: It must update while holding the proper locks.

> >> .\" FIXME XXX In discussing errors for FUTEX_CMP_REQUEUE_PI, Darren Hart
> >> .\"       made the observation that "EINVAL is returned if the non-pi 
> >> .\"       to pi or op pairing semantics are violated."
> >> .\"       Probably there needs to be a general statement about this
> >> .\"       requirement, probably located at about this point in the page.
> >> .\"       Darren (or someone else), care to take a shot at this?
> > 
> > Well, that's hard to describe because the kernel only has a limited
> > way of detecting such mismatches. It only can detect it when there are
> > non PI waiters on a futex and a PI function is called or vice versa.
> 
> Hmmm. Okay, I filed your comments away for reference, but
> hopefully someone can help with some actual text.

I let Darren come up with something sensible :)
 
> >> .\" FIXME Somewhere on this page (I guess under the discussion of PI
> >> .\"       futexes) we need a discussion of the FUTEX_OWNER_DIED bit.
> >> .\"       Can someone propose a text?
> > 
> > If a futex has a rtmutex associated in the kernel, i.e. when there are
> > blocked waiters, and the owner of the futex/rtmutex dies unexpectedly,
> > then the kernel cleans up the rtmutex (as it holds a reference to the
> > dying task) and hands it over to the next waiter. That requires that
> > the user space value is updated accordingly. The kernel sets the
> > FUTEX_OWNER_DIED in the user space value along with the TID of the new
> > owner. User space is responsible for cleaning this up, though there
> > are cases where the kernel does the cleanup.
> >  
> > The FUTEX_OWNER_DIED bit can also be set on uncontended futexes, where
> > the kernel has no state associated. This happens via the robust futex
> > mechanism. In that case the futex value will be set to
> > FUTEX_OWNER_DIED. The robust futex mechanism is also available for non
> > PI futexes.
> 
> ???
> So, I added part of that text to the page, as follows:
> 
>        If  a futex has an associated RT-mutex in the kernel (i.e., there
>        are blocked waiters) and the owner  of  the  futex/RT-mutex  dies
>        unexpectedly, then the kernel cleans up the RT-mutex and hands it
>        over to the next waiter.  This in turn requires  that  the  user-
>        space  value  is  updated  accordingly.  To indicate that this is
>        required, the kernel sets the FUTEX_OWNER_DIED bit in  the  futex
>        word  along  with  the thread ID of the new owner.  User space is
>        then responsible for cleaning this up  (though  there  are  cases
>        where the kernel does the cleanup).
> 
> Okay?
> 
> I think the last sentence still requires a little work though. What does
> user space need to do in terms of clean up?

User space has usually state as well. So the FUTEX_OWNER_DIED bit
tells userspace that it needs to cleanup the stale state left over by
the dead owner.
 
> >> .\" FIXME In the next line, what type of "priority" are we talking about?
> >> .\"       Realtime priorities for SCHED_FIFO and SCHED_RR?
> >> .\"       Or something else?
> >>
> >>               The
> >>               enqueueing  of  the waiter is in descending priority order
> >>               if more than one waiter exists.  
> > 
> > That also covers sched deadline.
> 
> ???
> Thanks. If the realm is restricted purely to SCHED_OTHER (SCHED_NORMAL)
> processes, does the nice value come into play also?

No. SCHED_OTHER/NORMAL tasks are handled in FIFO order.
 
> So by now, I've reworked this text to be:
> 
>        FUTEX_TRYLOCK_PI (since Linux 2.6.18)
>               This operation tries to acquire the futex at uaddr.  It is
>               invoked when a user-space atomic acquire did  not  succeed
>               because the futex word was not 0.
> 
>               The trylock in kernel might succeed because the futex word
>               contains     stale     state     (FUTEX_WAITERS     and/or
>               FUTEX_OWNER_DIED).   This can happen when the owner of the
>               futex died.  User space cannot handle this condition in  a
>               race-free manner
> 
> Okay?
> 
> I must admit that I find "the trylock in kernel might succeed"hard
> to understand. Could you elaborate a little?

If the user space value has stale state, then the kernel can fix that
up and acquire the futex.
 
> ???
> So now I've reworded the opening text describing FUTEX_WAIT_REQUEUE_PI
> as follows:
> 
>        FUTEX_WAIT_REQUEUE_PI (since Linux 2.6.31)
>               Wait on  a  non-PI  futex  at  uaddr  and  potentially  be
>               requeued  (via a FUTEX_CMP_REQUEUE_PI operation in another
>               task) onto a PI futex at uaddr2.  The  wait  operation  on
>               uaddr is the same as for FUTEX_WAIT.
> 
>               The  waiter  can be removed from the wait on uaddr without
>               requeueing on uaddr2 via a FUTEX_WAIT operation in another

s/FUTEX_WAIT/FUTEX_WAKE/

>               task.   In  this case, the FUTEX_WAIT_REQUEUE_PI operation
>               returns with the error EWOULDBLOCK.
> 
> Okay?

Yes.

Thanks,

	tglx

^ permalink raw reply

* Re: [PATCH v2 0/3] SysFS driver for QEMU fw_cfg device
From: Leif Lindholm @ 2015-08-19 23:04 UTC (permalink / raw)
  To: Gabriel L. Somlo
  Cc: Ard Biesheuvel, linux-kernel@vger.kernel.org, x86@kernel.org,
	QEMU Developers, Matt Fleming, kernelnewbies, linux-api
In-Reply-To: <20150819204915.GA6164@GLSMBP.INI.CMU.EDU>

On Wed, Aug 19, 2015 at 04:49:15PM -0400, Gabriel L. Somlo wrote:
> Hi Ard,
> 
> On Wed, Aug 19, 2015 at 11:42:02AM +0200, Ard Biesheuvel wrote:
> > (missed some cc's)
> > 
> > On 19 August 2015 at 11:38, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > From: "Gabriel L. Somlo" <somlo@cmu.edu>
> > >> Several different architectures supported by QEMU are set up with a
> > >> "firmware configuration" (fw_cfg) device, used to pass configuration
> > >> "blobs" into the guest by the host running QEMU.
> > >>
> > >> Historically, these config blobs were mostly of interest to the guest
> > >> BIOS, but since QEMU v2.4 it is possible to insert arbitrary blobs via
> > >> the command line, which makes them potentially interesting to userspace
> > >> (e.g. for passing early boot environment variables, etc.).
> > >>
> > >
> > > Does 'potentially interesting' mean you have a use case? Could you elaborate?
> 
> My personal one would be something like:
> 
> cat > guestinfo.txt << EOT
>   KEY1="val1"
>   KEY2="val2"
>   ...
> EOT
> 
> qemu-system-x86_64 ... -fw-cfg name="opt/guestinfo",file=./guestinfo.txt ...
> 
> Then, from inside the guest:
> 
>   . /sys/firmware/qemu_fw_cfg/by_name/opt/guestinfo/raw
> 
>   do_something_with $KEY1 $KEY2
>   ...
> 
> But I'm thinking this is only one of the many positive things one
> could do with the ability to access random host-supplied blobs from
> guest userspace :)

> > >>   1/3 - probes for the qemu fw_cfg device in locations known to work on
> > >>       the supported architectures, in decreasing order of "likelihood".
> > >>
> > >>       While it *may* be possible to detect the presence of fw_cfg via
> > >>       acpi or dtb (on x86 and arm, respectively), there's no way I know
> > >>       of attempting that on sun4 and ppc/mac, so I've stuck with simply
> > >>       probing (the fw_cfg_modes[] structure and fw_cfg_io_probe() function)
> > >>       in fw_cfg.c. I could use some advice on how else that could be
> > >>       done more elegantly, if needed.
> > >>
> > >
> > > Sorry, but this is really out of the question, at least on ARM, but surely on
> > > other architectures as well. You can't just go around and probe random memory
> > > addresses. Perhaps QEMU tolerates it, but on anything that resembles a real
> > > system, this will immediately blow up. Also, what happens if the QEMU memory
> > > map changes? Add more probes addresses?
> > >
> > > It is not /that/ difficult to simply wire it up to the DT and ACPI
> > > infrastructures, there are plenty of examples in the kernel tree how to
> > > accomplish that. As a bonus, it removes all the arch specific knowledge
> > > from your code, which means that if QEMU grows support for another DT or
> > > ACPI based architecture, it will just work.
> 
> I was *hoping* a successful call to request_[mem_]region() will be
> enough in the way of asking for permission before probing for the
> fw_cfg registers, but I realize that might still not be polite enough :)

Either way, it would make sense to not probe in locations that
couldn't possibly work on the current platform. The cleanest way would
probably be a per-architecture probe function (or structure). But even
then, it needs to only probe when it is safe to do so.
 
> DT on ARM is fine, and I'm certainly happy to learn how to do it (even
> though my main focus is, for now, x86). The unfortunate thing though
> is that on x86, fw_cfg is *not* AFAICT in ACPI, so I'd have to detour into
> first adding it in on the host side, before I can rewrite the guest side
> driver to look it up in there :)

It is probaly the only non-hackish way to do it for arm*.

> > > I am not sure how relevant sun4 and ppc/mac are for what you are trying to
> > > accomplish, but perhaps it would be best to focus on x86 and ARM for now
> > > and do it correctly. If the probing is actually needed, you can always add
> > > it later.
> 
> I guess that's the direction things seem to be headed, although it would
> make me a bit sad to leave out sun and ppc right from the very beginning :) 
> 
> PS. If you have one .c file in the kernel which does any of the DT-on-arm
> boilerplate I'm supposed to immitate, I'd appreciate the shortcut :)
> 
> PS2. Do you happen to be in Seattle right now ? :)

Unfortunately, neither Ard nor myself is there. But Mark Rutland
should be around and someone useful to talk to about this.

/
    Leif

^ permalink raw reply

* Re: Next round: revised futex(2) man page for review
From: Thomas Gleixner @ 2015-08-19 22:40 UTC (permalink / raw)
  To: Darren Hart
  Cc: Michael Kerrisk (man-pages), Torvald Riegel, Carlos O'Donell,
	Ingo Molnar, Jakub Jelinek, linux-man, lkml, Davidlohr Bueso,
	Arnd Bergmann, Steven Rostedt, Peter Zijlstra, Linux API,
	Roland McGrath, Anton Blanchard, Eric Dumazet, bill o gallmeister,
	Jan Kiszka, Daniel Wagner, Rich Felker, Andy Lutomirski,
	bert hubert, Rusty Russell, Heinrich Schuchardt
In-Reply-To: <20150805222140.GA74817@vmdeb7>

On Wed, 5 Aug 2015, Darren Hart wrote:
> On Mon, Jul 27, 2015 at 02:07:15PM +0200, Michael Kerrisk (man-pages) wrote:
> > .\" FIXME XXX ===== Start of adapted Hart/Guniguntala text =====
> > .\"       The following text is drawn from the Hart/Guniguntala paper
> > .\"       (listed in SEE ALSO), but I have reworded some pieces
> > .\"       significantly. Please check it.
> > 
> >        The PI futex operations described below  differ  from  the  other
> >        futex  operations  in  that  they impose policy on the use of the
> >        value of the futex word:
> > 
> >        *  If the lock is not acquired, the futex word's value  shall  be
> >           0.
> > 
> >        *  If  the  lock is acquired, the futex word's value shall be the
> >           thread ID (TID; see gettid(2)) of the owning thread.
> > 
> >        *  If the lock is owned and there are threads contending for  the
> >           lock,  then  the  FUTEX_WAITERS  bit shall be set in the futex
> >           word's value; in other words, this value is:
> > 
> >               FUTEX_WAITERS | TID
> > 
> > 
> >        Note that a PI futex word never just has the value FUTEX_WAITERS,
> >        which is a permissible state for non-PI futexes.
> 
> The second clause is inappropriate. I don't know if that was yours or
> mine, but non-PI futexes do not have a kernel defined value policy, so
> ==FUTEX_WAITERS cannot be a "permissible state" as any value is
> permissible for non-PI futexes, and none have a kernel defined state.

Depends. If the regular futex is configured as robust, then we have a
kernel defined value policy as well.

> > .\" FIXME I'm not quite clear on the meaning of the following sentence.
> > .\"       Is this trying to say that while blocked in a
> > .\"       FUTEX_WAIT_REQUEUE_PI, it could happen that another
> > .\"       task does a FUTEX_WAKE on uaddr that simply causes
> > .\"       a normal wake, with the result that the FUTEX_WAIT_REQUEUE_PI
> > .\"       does not complete? What happens then to the FUTEX_WAIT_REQUEUE_PI
> > .\"       opertion? Does it remain blocked, or does it unblock
> > .\"       In which case, what does user space see?
> > 
> >               The
> >               waiter   can  be  removed  from  the  wait  on  uaddr  via
> >               FUTEX_WAKE without requeueing on uaddr2.
> 
> Userspace should see the task wake and continue executing. This would
> effectively be a cancelation operation - which I didn't think was
> supported. Thomas?

We probably never intended to support it, but looking at the code it
works (did not try it though). It returns to user space with
-EWOULDBLOCK. So it basically behaves like any other spurious wakeup.
 
Thanks,

	tglx

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox