Linux userland API discussions
 help / color / mirror / Atom feed
* Re: [PATCH v2 04/18] clocksource: Add ARM System timer driver
From: Maxime Coquelin @ 2015-03-04 12:08 UTC (permalink / raw)
  To: Paul Bolle
  Cc: Uwe Kleine-König, Andreas Färber, Geert Uytterhoeven,
	Rob Herring, Philipp Zabel, Jonathan Corbet, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Daniel Lezcano, Thomas Gleixner, Linus Walleij,
	Greg Kroah-Hartman, Jiri Slaby, Arnd Bergmann, Andrew Morton,
	David S. Miller, Mauro Carvalho Chehab, Joe Perches
In-Reply-To: <1425411786.2606.24.camel@tiscali.nl>

2015-03-03 20:43 GMT+01:00 Paul Bolle <pebolle@tiscali.nl>:
> Maxime Coquelin schreef op ma 02-03-2015 om 17:53 [+0100]:
>> Do you agree if I define it like this:
>>
>> config ARMV7M_SYSTICK
>>     bool "Clocksource driver for ARMv7-M System timer"
>>     depends on OF && (CPU_V7M || COMPILE_TEST)
>>     select CLKSRC_OF
>>     select CLKSRC_MMIO
>>     help
>>       This options enables clocksource support for the ARMv7-M system
>>       timer unit.
>
> I don't really have strong feelings on whatever way you choose to fix
> the, well, minor problem I pointed out.
>
> Having said that, if a Kconfig entry without a prompt (and therefor,
> without help) actually does what you want it to do, why bother adding a
> prompt and a one line help text?

This is because I added also support for COMPILE_TEST coverage as per
Uwe advice,
and thought it was necessary to have an entry for this.
Maybe I'm just wrong?

Thanks,
Maxime

>
>
> Paul Bolle
>

^ permalink raw reply

* Re: [dmidecode] [Patch v4] firmware: dmi-sysfs: add SMBIOS entry point area attribute
From: Ivan.khoronzhuk @ 2015-03-04 12:30 UTC (permalink / raw)
  To: Jean Delvare, Ivan Khoronzhuk
  Cc: linux-kernel, ard.biesheuvel, grant.likely, matt.fleming,
	linux-api, linux-doc, dmidecode-devel, leif.lindholm, msalter
In-Reply-To: <20150226103622.09b9870a@endymion.delvare>


On 02/26/2015 11:36 AM, Jean Delvare wrote:
> Hi Ivan,
>
> Sorry for the late review.
>
> On Wed,  4 Feb 2015 19:06:03 +0200, Ivan Khoronzhuk wrote:
>> Some utils, like dmidecode and smbios, need to access SMBIOS entry
>> table area in order to get information like SMBIOS version, size, etc.
>> Currently it's done via /dev/mem. But for situation when /dev/mem
>> usage is disabled, the utils have to use dmi sysfs instead, which
>> doesn't represent SMBIOS entry. So this patch adds SMBIOS area to
>> dmi-sysfs in order to allow utils in question to work correctly with
>> dmi sysfs interface.
>>
>> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>> ---
>>
>> v1: https://lkml.org/lkml/2015/1/23/643
>> v2: https://lkml.org/lkml/2015/1/26/345
>> v3: https://lkml.org/lkml/2015/1/28/768
>>
>> v4..v2:
> Please always provide a list of changes from the previous version of
> the patch, otherwise it's quite confusing.

Typo v4..v2 -> v4..v3

>
>>    firmware: dmi_scan: add symbol to get SMBIOS entry area
>>    	- used u8 type for smbios_header var
>>    firmware: dmi-sysfs: add SMBIOS entry point area attribute
>>    	- replaced -ENODATA on -EINVAL
>>
>> v3..v2:
>>    firmware: dmi_scan: add symbol to get SMBIOS entry area
>>    firmware: dmi-sysfs: add SMBIOS entry point area attribute
>> 	- combined in one patch
>> 	- added SMBIOS information to ABI sysfs-dmi documentaton
>>
>> v2..v1:
>>    firmware: dmi_scan: add symbol to get SMBIOS entry area
>> 	- used additional static var to hold SMBIOS raw table size
>> 	- changed format of get_smbios_entry_area symbol
>> 	  returned pointer on const smbios table
>>
>>    firmware: dmi-sysfs: add SMBIOS entry point area attribute
>> 	- adopted to updated get_smbios_entry_area symbol
>>    	- removed redundant array to save smbios table
>>
>>   Documentation/ABI/testing/sysfs-firmware-dmi | 10 +++++++
>>   drivers/firmware/dmi-sysfs.c                 | 42 ++++++++++++++++++++++++++++
>>   drivers/firmware/dmi_scan.c                  | 26 +++++++++++++++++
>>   include/linux/dmi.h                          |  3 ++
>>   4 files changed, 81 insertions(+)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi b/Documentation/ABI/testing/sysfs-firmware-dmi
>> index c78f9ab..3a9ffe8 100644
>> --- a/Documentation/ABI/testing/sysfs-firmware-dmi
>> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi
>> @@ -12,6 +12,16 @@ Description:
>>   		cannot ensure that the data as exported to userland is
>>   		without error either.
>>   
>> +		The firmware provides DMI structures as a packed list of
>> +		data referenced by a SMBIOS table entry point. The SMBIOS
>> +		entry point contains general information, like SMBIOS
>> +		version, DMI table size, etc. The structure, content and
>> +		size of SMBIOS entry point is dependent on SMBIOS version.
>> +		That's why SMBIOS entry point is represented in dmi sysfs
>> +		like a raw attribute and is accessible via
>> +		/sys/firmware/dmi/smbios_raw_header. The format of SMBIOS
> As mentioned before, I don't like the name "smbios_raw_header". I think
> it should be "smbios_entry_point" or similar.

If Matt is OK to get another version,
Let it be smbios_entry_point.
If it's more convenient, it should be changed while it's possible.

>
>> +		entry point header can be read in SMBIOS specification.
>> +
>>   		DMI is structured as a large table of entries, where
>>   		each entry has a common header indicating the type and
>>   		length of the entry, as well as a firmware-provided
>> diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
>> index e0f1cb3..9b396d7 100644
>> --- a/drivers/firmware/dmi-sysfs.c
>> +++ b/drivers/firmware/dmi-sysfs.c
>> @@ -29,6 +29,8 @@
>>   #define MAX_ENTRY_TYPE 255 /* Most of these aren't used, but we consider
>>   			      the top entry type is only 8 bits */
>>   
>> +static const u8 *smbios_raw_header;
>> +
>>   struct dmi_sysfs_entry {
>>   	struct dmi_header dh;
>>   	struct kobject kobj;
>> @@ -646,9 +648,37 @@ static void cleanup_entry_list(void)
>>   	}
>>   }
>>   
>> +static ssize_t smbios_entry_area_raw_read(struct file *filp,
> This is confusing again, now it's named "entry_area"? Please be
> consistent and use entry_point everywhere.
>
> As mentioned before I believe that this code should live in dmi_scan
> and not dmi-sysfs.
>
>> +					  struct kobject *kobj,
>> +					  struct bin_attribute *bin_attr,
>> +					  char *buf, loff_t pos, size_t count)
>> +{
>> +	ssize_t size;
>> +
>> +	size = bin_attr->size;
>> +
>> +	if (size > pos)
>> +		size -= pos;
>> +	else
>> +		return 0;
>> +
>> +	if (count < size)
>> +		size = count;
>> +
>> +	memcpy(buf, &smbios_raw_header[pos], size);
>> +
>> +	return size;
>> +}
>> +
>> +static struct bin_attribute smbios_raw_area_attr = {
>> +	.read = smbios_entry_area_raw_read,
>> +	.attr = {.name = "smbios_raw_header", .mode = 0400},
>> +};
>> +
>>   static int __init dmi_sysfs_init(void)
>>   {
>>   	int error = -ENOMEM;
>> +	int size;
>>   	int val;
>>   
>>   	/* Set up our directory */
>> @@ -669,6 +699,18 @@ static int __init dmi_sysfs_init(void)
>>   		goto err;
>>   	}
>>   
>> +	smbios_raw_header = dmi_get_smbios_entry_area(&size);
>> +	if (!smbios_raw_header) {
>> +		pr_debug("dmi-sysfs: SMBIOS raw data is not available.\n");
>> +		error = -EINVAL;
>> +		goto err;
>> +	}
> I don't think this should have been a fatal error. Just because for
> some reason dmi_get_smbios_entry_area() returned NULL is no good reason
> for nor exposing /sys/firmware/dmi/entries as we used to.

It issues an error only in case of when entry table is not available,
if entry point is absent then dmi table is not available a fortiori.
So there is no reason to continue from that point.

> But anyway this is no longer relevant if the code is moved to dmi_scan
> as I suggested.
>
>> +
>> +	/* Create the raw binary file to access the entry area */
>> +	smbios_raw_area_attr.size = size;
>> +	if (sysfs_create_bin_file(dmi_kobj, &smbios_raw_area_attr))
>> +		goto err;
> I think this should have had a corresponding call to
> sysfs_remove_bin_file() in dmi_sysfs_exit(). (Again no longer relevant
> if the code is moved.)

The removing is done in kobject_del().
Doesn't it? In another way it should be done for
dmi/entries/*/raw attributes also.

>> +
>>   	pr_debug("dmi-sysfs: loaded.\n");
>>   
>>   	return 0;
>> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
>> index 420c8d8..99c5f6c 100644
>> --- a/drivers/firmware/dmi_scan.c
>> +++ b/drivers/firmware/dmi_scan.c
>> @@ -113,6 +113,8 @@ static void dmi_table(u8 *buf, int len, int num,
>>   	}
>>   }
>>   
>> +static u8 smbios_header[32];
>> +static int smbios_header_size;
>>   static phys_addr_t dmi_base;
>>   static u16 dmi_len;
>>   static u16 dmi_num;
>> @@ -474,6 +476,8 @@ static int __init dmi_present(const u8 *buf)
>>   	if (memcmp(buf, "_SM_", 4) == 0 &&
>>   	    buf[5] < 32 && dmi_checksum(buf, buf[5])) {
>>   		smbios_ver = get_unaligned_be16(buf + 6);
>> +		smbios_header_size = buf[5];
>> +		memcpy(smbios_header, buf, smbios_header_size);
>>   
>>   		/* Some BIOS report weird SMBIOS version, fix that up */
>>   		switch (smbios_ver) {
>> @@ -505,6 +509,8 @@ static int __init dmi_present(const u8 *buf)
>>   				pr_info("SMBIOS %d.%d present.\n",
>>   				       dmi_ver >> 8, dmi_ver & 0xFF);
>>   			} else {
>> +				smbios_header_size = 15;
>> +				memcpy(smbios_header, buf, smbios_header_size);
>>   				dmi_ver = (buf[14] & 0xF0) << 4 |
>>   					   (buf[14] & 0x0F);
>>   				pr_info("Legacy DMI %d.%d present.\n",
>> @@ -531,6 +537,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
>>   		dmi_ver &= 0xFFFFFF;
>>   		dmi_len = get_unaligned_le32(buf + 12);
>>   		dmi_base = get_unaligned_le64(buf + 16);
>> +		smbios_header_size = buf[6];
>> +		memcpy(smbios_header, buf, smbios_header_size);
>>   
>>   		/*
>>   		 * The 64-bit SMBIOS 3.0 entry point no longer has a field
>> @@ -944,3 +952,21 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device)
>>   	}
>>   }
>>   EXPORT_SYMBOL_GPL(dmi_memdev_name);
>> +
>> +/**
>> + * dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
>> + * @size - pointer to assign actual size of SMBIOS entry point area.
>> + *
>> + * returns NULL if table is not available, otherwise returns pointer on
>> + * SMBIOS entry point area array.
>> + */
>> +const u8 *dmi_get_smbios_entry_area(int *size)
>> +{
>> +	if (!smbios_header_size || !dmi_available)
> I don't see why you need to check for !dmi_available. If
> smbios_header_size is non-zero then the required data is available. It
> is independent from dmi_walk_early() having succeeded or not.

Probably you are right.
It's better to check only smbios_header_size.

>
> If you really believe that this function should return NULL if
> dmi_walk_early() failed (I don't), then you should be consistent and
> only fill up smbios_header after dmi_walk_early() has been successfully
> called.
>
>> +		return NULL;
>> +
>> +	*size = smbios_header_size;
>> +
>> +	return smbios_header;
>> +}
>> +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area);
>> diff --git a/include/linux/dmi.h b/include/linux/dmi.h
>> index f820f0a..8e1a28d 100644
>> --- a/include/linux/dmi.h
>> +++ b/include/linux/dmi.h
>> @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *),
>>   	void *private_data);
>>   extern bool dmi_match(enum dmi_field f, const char *str);
>>   extern void dmi_memdev_name(u16 handle, const char **bank, const char **device);
>> +const u8 *dmi_get_smbios_entry_area(int *size);
>>   
>>   #else
>>   
>> @@ -140,6 +141,8 @@ static inline void dmi_memdev_name(u16 handle, const char **bank,
>>   		const char **device) { }
>>   static inline const struct dmi_system_id *
>>   	dmi_first_match(const struct dmi_system_id *list) { return NULL; }
>> +static inline const u8 *dmi_get_smbios_entry_area(int *size)
>> +	{ return NULL; }
>>   
>>   #endif
>>   
> There's one thing I do not understand. I seem to understand that the
> goal behind this patch is to be able to run dmidecode without /dev/mem.
> Dmidecode currently reads 2 areas from /dev/mem: the 0xF0000-0xFFFFF
> area in search of the entry point, and the DMI data table itself. With
> this patch you make the entry point available through sysfs. But
> dmidecode will still need to access /dev/mem to access the DMI data
> table. So that does not really solve anything, does it?

It's supposed to read DMI table via entries presented by dmi-sysfs.
It contains raw attributes that can be used for these purposes.
No need to use /dev/mem.

Another case if you want to add binary of whole dmi table to be able to
read it directly in order to parse in dmidecode w/o any additional headache
with open/close. Well, it partly dupes currently present dmi-sysfs.
But it simplifies dmi table parsing for dmidecode, and who wants to use
dmi-sysfs, let them use it, but dmidecode will be reading raw entry.
Well let it be. Why not.

If others are OK, for dmidecode, and probably others tools also,
kernel can constantly expose two tables under /sys/firmware/dmi/tables/
smbios_entry_point and dmi_table. Independently on dmi-sysfs.


>
> If we expose the raw DMI/SMBIOS entry point through sysfs, I believe we
> want to expose the DMI table there too.
>
> Thanks,

-- 
Regards,
Ivan Khoronzhuk

^ permalink raw reply

* Re: [PATCH 2/2] user_namespaces.7: Update the documention to reflect the fixes for negative groups
From: Michael Kerrisk (man-pages) @ 2015-03-04 14:00 UTC (permalink / raw)
  To: Alban Crequy, Eric W. Biederman
  Cc: mtk.manpages, Linux Containers, Josh Triplett, Andrew Morton,
	Kees Cook, Linux API, linux-man, linux-kernel@vger.kernel.org,
	LSM, Casey Schaufler, Serge E. Hallyn, Richard Weinberger,
	Kenton Varda, stable, Andy Lutomirski
In-Reply-To: <CAMXgnP7phuYTko6fHnxjJTi=HRdoa32uH6dp8DyD9uWPWr2kAg@mail.gmail.com>

On 02/02/2015 10:31 PM, Alban Crequy wrote:
> Hello,
> 
> Thanks for updating the man page.
> 
> On 12 December 2014 at 22:54, Eric W. Biederman <ebiederm@xmission.com> wrote:
> (...)
>> Furthermore to preserve in some form the useful applications that have
>> been setting gid_map without privilege the file /proc/[pid]/setgroups
>> was added to allow disabling setgroups.  With the setgroups system
>> call permanently disabled in a user namespace it again becomes safe to
>> allow writes to gid_map without privilege.
>>
>> Here is my meager attempt to update user_namespaces.7 to reflect these
>> issues.
> 
> The program userns_child_exec.c in user_namespaces.7 should be updated
> to write in /proc/.../setgroups, near the line:
> /* Update the UID and GID maps in the child */
> 
> Otherwise, the example given in the manpage does not work:
> $ ./userns_child_exec -p -m -U -M '0 1000 1' -G '0 1000 1' bash

Thanks, Alban. I've added code to the example to handle /proc/PID/setgroups
(and tested).

Cheers,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

^ permalink raw reply

* [PATCH v5 1/4] vfio: implement iommu driver capabilities with an enum
From: Baptiste Reynal @ 2015-03-04 16:07 UTC (permalink / raw)
  To: iommu, kvmarm
  Cc: eric.auger, alex.williamson, tech, Antonios Motakis,
	Baptiste Reynal, open list:VFIO DRIVER, open list:ABI/API,
	open list
In-Reply-To: <1425485274-5709-1-git-send-email-b.reynal@virtualopensystems.com>

From: Antonios Motakis <a.motakis@virtualopensystems.com>

Currently a VFIO driver's IOMMU capabilities are encoded as a series of
numerical defines. Replace this with an enum for future maintainability.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 include/uapi/linux/vfio.h | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 82889c3..5fb3d46 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -19,22 +19,20 @@
 
 /* Kernel & User level defines for VFIO IOCTLs. */
 
-/* Extensions */
-
-#define VFIO_TYPE1_IOMMU		1
-#define VFIO_SPAPR_TCE_IOMMU		2
-#define VFIO_TYPE1v2_IOMMU		3
 /*
- * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping).  This
- * capability is subject to change as groups are added or removed.
+ * Capabilities exposed by the VFIO IOMMU driver. Some capabilities are subject
+ * to change as groups are added or removed.
  */
-#define VFIO_DMA_CC_IOMMU		4
-
-/* Check if EEH is supported */
-#define VFIO_EEH			5
+enum vfio_iommu_cap {
+	VFIO_TYPE1_IOMMU = 1,
+	VFIO_SPAPR_TCE_IOMMU = 2,
+	VFIO_TYPE1v2_IOMMU = 3,
+	VFIO_DMA_CC_IOMMU = 4,		/* IOMMU enforces DMA cache coherence
+					   (ex. PCIe NoSnoop stripping) */
+	VFIO_EEH = 5,			/* Check if EEH is supported */
+	VFIO_TYPE1_NESTING_IOMMU = 6,	/* Two-stage IOMMU, implies v2  */
+};
 
-/* Two-stage IOMMU */
-#define VFIO_TYPE1_NESTING_IOMMU	6	/* Implies v2 */
 
 /*
  * The IOCTL interface is designed for extensibility by embedding the
-- 
2.3.1

^ permalink raw reply related

* [PATCH v5 2/4] vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
From: Baptiste Reynal @ 2015-03-04 16:07 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	open list:ABI/API, open list, Antonios Motakis,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J
In-Reply-To: <1425485274-5709-1-git-send-email-b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>

From: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>

We introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag to the VFIO dma map call,
and expose its availability via the capability VFIO_DMA_NOEXEC_IOMMU.
This way the user can control whether the XN flag will be set on the
requested mappings. The IOMMU_NOEXEC flag needs to be available for all
the IOMMUs of the container used.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
Signed-off-by: Baptiste Reynal <b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 include/uapi/linux/vfio.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5fb3d46..30801a7 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -31,6 +31,7 @@ enum vfio_iommu_cap {
 					   (ex. PCIe NoSnoop stripping) */
 	VFIO_EEH = 5,			/* Check if EEH is supported */
 	VFIO_TYPE1_NESTING_IOMMU = 6,	/* Two-stage IOMMU, implies v2  */
+	VFIO_DMA_NOEXEC_IOMMU = 7,
 };
 
 
@@ -397,12 +398,17 @@ struct vfio_iommu_type1_info {
  *
  * Map process virtual addresses to IO virtual addresses using the
  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
+ *
+ * To use the VFIO_DMA_MAP_FLAG_NOEXEC flag, the container must support the
+ * VFIO_DMA_NOEXEC_IOMMU capability. If mappings are created using this flag,
+ * any groups subsequently added to the container must support this capability.
  */
 struct vfio_iommu_type1_dma_map {
 	__u32	argsz;
 	__u32	flags;
 #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
 #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
+#define VFIO_DMA_MAP_FLAG_NOEXEC (1 << 2)	/* not executable from device */
 	__u64	vaddr;				/* Process virtual address */
 	__u64	iova;				/* IO virtual address */
 	__u64	size;				/* Size of mapping (bytes) */
-- 
2.3.1

^ permalink raw reply related

* Re: [PATCH v5 tip 0/7] tracing: attach eBPF programs to kprobes
From: Alexei Starovoitov @ 2015-03-04 17:23 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Steven Rostedt, Namhyung Kim, Arnaldo Carvalho de Melo, Jiri Olsa,
	Masami Hiramatsu, David S. Miller, Daniel Borkmann,
	Peter Zijlstra, Linux API, Network Development, LKML
In-Reply-To: <1425252465-27527-1-git-send-email-ast@plumgrid.com>

On Sun, Mar 1, 2015 at 3:27 PM, Alexei Starovoitov <ast@plumgrid.com> wrote:
> Peter, Steven,
> I think this set addresses everything we've discussed.
> Please review/ack. Thanks!

icmp echo request

> V4->V5:
> - switched to ktime_get_mono_fast_ns() as suggested by Peter
> - in libbpf.c fixed zero init of 'union bpf_attr' padding
> - fresh rebase on tip/master
>
> Hi All,
>
> This is targeting 'tip' tree, since most of the changes are perf_event related.
> There will be a small conflict between net-next and tip, since they both
> add new bpf_prog_type (BPF_PROG_TYPE_SCHED_CLS and BPF_PROG_TYPE_KPROBE).
>
> V3 discussion:
> https://lkml.org/lkml/2015/2/9/738
>
> V3->V4:
> - since the boundary of stable ABI in bpf+tracepoints is not clear yet,
>   I've dropped them for now.
> - bpf+syscalls are ok from stable ABI point of view, but bpf+seccomp
>   would want to do very similar analysis of syscalls, so I've dropped
>   them as well to take time and define common bpf+syscalls and bpf+seccomp
>   infra in the future.
> - so only bpf+kprobes left. kprobes by definition is not a stable ABI,
>   so bpf+kprobe is not stable ABI either. To stress on that point added
>   kernel version attribute that user space must pass along with the program
>   and kernel will reject programs when version code doesn't match.
>   So bpf+kprobe is very similar to kernel modules, but unlike modules
>   version check is not used for safety, but for enforcing 'non-ABI-ness'.
>   (version check doesn't apply to bpf+sockets which are stable)
>
> Patch 1 is in net-next and needs to be in tip too, since patch 2 depends on it.
>
> Patch 2 actually adds bpf+kprobe infra:
> programs receive 'struct pt_regs' on input and can walk data structures
> using bpf_probe_read() helper which is a wrapper of probe_kernel_read()
>
> Programs are attached to kprobe events via API:
>
> prog_fd = bpf_prog_load(...);
> struct perf_event_attr attr = {
>   .type = PERF_TYPE_TRACEPOINT,
>   .config = event_id, /* ID of just created kprobe event */
> };
> event_fd = perf_event_open(&attr,...);
> ioctl(event_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
>
> Patch 3 adds bpf_ktime_get_ns() helper function, so that bpf programs can
> measure time delta between events to compute disk io latency, etc.
>
> Patch 4 adds bpf_trace_printk() helper that is used to debug programs.
> When bpf verifier sees that program is calling bpf_trace_printk() it inits
> trace_printk buffers which emits nasty 'this is debug only' banner.
> That's exactly what we want. bpf_trace_printk() is for debugging only.
>
> Patch 5 sample code that shows how to use bpf_probe_read/bpf_trace_printk
>
> Patch 6 sample code - combination of kfree_skb and sys_write tracing.
>
> Patch 7 sample code that computes disk io latency and prints it as 'heatmap'
>
> Interesting bit is that patch 6 has log2() function implemented in C
> and patch 7 has another log2() function using different algorithm in C.
> In the future if 'log2' usage becomes common, we can add it as in-kernel
> helper function, but for now bpf programs can implement them on bpf side.
>
> Another interesting bit from patch 7 is that it does approximation of
> floating point log10(X)*10 using integer arithmetic, which demonstrates
> the power of C->BPF vs traditional tracing language alternatives,
> where one would need to introduce new helper functions to add functionality,
> whereas bpf can just implement such things in C as part of the program.
>
> Next step is to prototype TCP stack instrumentation (like web10g) using
> bpf+kprobe, but without adding any new code tcp stack.
> Though kprobes are slow comparing to tracepoints, they are good enough
> for prototyping and trace_marker/debug_tracepoint ideas can accelerate
> them in the future.
>
> Alexei Starovoitov (6):
>   tracing: attach BPF programs to kprobes
>   tracing: allow BPF programs to call bpf_ktime_get_ns()
>   tracing: allow BPF programs to call bpf_trace_printk()
>   samples: bpf: simple non-portable kprobe filter example
>   samples: bpf: counting example for kfree_skb and write syscall
>   samples: bpf: IO latency analysis (iosnoop/heatmap)
>
> Daniel Borkmann (1):
>   bpf: make internal bpf API independent of CONFIG_BPF_SYSCALL ifdefs
>
>  include/linux/bpf.h             |   20 ++++-
>  include/linux/ftrace_event.h    |   14 +++
>  include/uapi/linux/bpf.h        |    5 ++
>  include/uapi/linux/perf_event.h |    1 +
>  kernel/bpf/syscall.c            |    7 +-
>  kernel/events/core.c            |   59 +++++++++++++
>  kernel/trace/Makefile           |    1 +
>  kernel/trace/bpf_trace.c        |  178 +++++++++++++++++++++++++++++++++++++++
>  kernel/trace/trace_kprobe.c     |   10 ++-
>  samples/bpf/Makefile            |   12 +++
>  samples/bpf/bpf_helpers.h       |    6 ++
>  samples/bpf/bpf_load.c          |  112 ++++++++++++++++++++++--
>  samples/bpf/bpf_load.h          |    3 +
>  samples/bpf/libbpf.c            |   14 ++-
>  samples/bpf/libbpf.h            |    5 +-
>  samples/bpf/sock_example.c      |    2 +-
>  samples/bpf/test_verifier.c     |    2 +-
>  samples/bpf/tracex1_kern.c      |   50 +++++++++++
>  samples/bpf/tracex1_user.c      |   25 ++++++
>  samples/bpf/tracex2_kern.c      |   86 +++++++++++++++++++
>  samples/bpf/tracex2_user.c      |   95 +++++++++++++++++++++
>  samples/bpf/tracex3_kern.c      |   89 ++++++++++++++++++++
>  samples/bpf/tracex3_user.c      |  150 +++++++++++++++++++++++++++++++++
>  23 files changed, 930 insertions(+), 16 deletions(-)
>  create mode 100644 kernel/trace/bpf_trace.c
>  create mode 100644 samples/bpf/tracex1_kern.c
>  create mode 100644 samples/bpf/tracex1_user.c
>  create mode 100644 samples/bpf/tracex2_kern.c
>  create mode 100644 samples/bpf/tracex2_user.c
>  create mode 100644 samples/bpf/tracex3_kern.c
>  create mode 100644 samples/bpf/tracex3_user.c
>
> --
> 1.7.9.5
>

^ permalink raw reply

* Re: [PATCHv2 0/2] N900 Modem Speech Support
From: Pavel Machek @ 2015-03-04 19:24 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Peter Ujfalusi, Kai Vehmanen, Pali Rohar, Aaro Koskinen,
	Ivaylo Dimitrov, linux-omap, linux-kernel, linux-api
In-Reply-To: <1425343454-6551-1-git-send-email-sre@kernel.org>

Hi!

> This patchset contains the missing speech data support for the
> Nokia N900 modem.
> 
> Userland access goes via /dev/cmt_speech. The API is implemented in
> libcmtspeechdata, which is used by ofono and the freesmartphone.org project.
> Apart from that the device is also used by the phone binaries distributed
> with Maemo. So while this is a new userland ABI for the mainline kernel it
> has been tested in the wild for some years.
> 
> Simple Testing of the API can be done by checking out libcmtspeechdata [0],
> building the test tool and executing it. The tool will loop back audio data
> received from the caller.
> 
> I have prepared a kernel branch for this patchset, which can be found at [1].
> 
> Changes since PATCHv1 [2]:
>  * Squash cmt-speech patches together
>  * cs_alloc_cmds(): GFP_ATOMIC -> GFP_KERNEL
>  * CS_SET_WAKELINE ioctl: Add sanity check

commit fd3492869b9387f7bd97821badb491e9c0be463f
Author: Pavel <pavel@ucw.cz>
Date:   Wed Mar 4 20:22:32 2015 +0100

Simple cleanups, improve consistency.
    
Signed-off-by: Pavel Machek <pavel@ucw.cz>

diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c
index a017292..9609766 100644
--- a/drivers/hsi/clients/cmt_speech.c
+++ b/drivers/hsi/clients/cmt_speech.c
@@ -115,6 +115,7 @@ struct cs_hsi_iface {
 	unsigned int			rx_ptr_boundary;
 	unsigned int			rx_offsets[CS_MAX_BUFFERS];
 	unsigned int			tx_offsets[CS_MAX_BUFFERS];
+
 	/* size of aligned memory blocks */
 	unsigned int			slot_size;
 	unsigned int			flags;
@@ -194,32 +195,27 @@ static void cs_notify_data(u32 message, int maxlength)
 	cs_notify(message, &cs_char_data.dataind_queue);
 
 	spin_lock(&cs_char_data.lock);
-	++cs_char_data.dataind_pending;
+	cs_char_data.dataind_pending++;
 	while (cs_char_data.dataind_pending > maxlength &&
 				!list_empty(&cs_char_data.dataind_queue)) {
 		dev_dbg(&cs_char_data.cl->device, "data notification "
 		"queue overrun (%u entries)\n", cs_char_data.dataind_pending);
 
 		cs_pop_entry(&cs_char_data.dataind_queue);
-		--cs_char_data.dataind_pending;
+		cs_char_data.dataind_pending--;
 	}
 	spin_unlock(&cs_char_data.lock);
 }
 
 static inline void cs_set_cmd(struct hsi_msg *msg, u32 cmd)
 {
-	u32 *data;
-
-	data = sg_virt(msg->sgt.sgl);
+	u32 *data = sg_virt(msg->sgt.sgl);
 	*data = cmd;
 }
 
 static inline u32 cs_get_cmd(struct hsi_msg *msg)
 {
-	u32 *data;
-
-	data = sg_virt(msg->sgt.sgl);
-
+	u32 *data = sg_virt(msg->sgt.sgl);
 	return *data;
 }
 
@@ -641,7 +637,7 @@ static void cs_hsi_peek_on_data_complete(struct hsi_msg *msg)
 		cs_hsi_data_read_error(hi, msg);
 }
 
-/**
+/*
  * Read/write transaction is ongoing. Returns false if in
  * SSI_CHANNEL_STATE_POLL state.
  */
@@ -651,7 +647,7 @@ static inline int cs_state_xfer_active(unsigned int state)
 		(state & SSI_CHANNEL_STATE_READING);
 }
 
-/**
+/*
  * No pending read/writes
  */
 static inline int cs_state_idle(unsigned int state)
@@ -1117,10 +1113,9 @@ static int cs_char_fasync(int fd, struct file *file, int on)
 {
 	struct cs_char *csdata = file->private_data;
 
-	if (fasync_helper(fd, file, on, &csdata->async_queue) >= 0)
-		return 0;
-	else
+	if (fasync_helper(fd, file, on, &csdata->async_queue) < 0)
 		return -EIO;
+	return 0;
 }
 
 static unsigned int cs_char_poll(struct file *file, poll_table *wait)
@@ -1149,7 +1144,7 @@ static ssize_t cs_char_read(struct file *file, char __user *buf, size_t count,
 	if (count < sizeof(data))
 		return -EINVAL;
 
-	for ( ; ; ) {
+	for (;;) {
 		DEFINE_WAIT(wait);
 
 		spin_lock_bh(&csdata->lock);
@@ -1157,7 +1152,7 @@ static ssize_t cs_char_read(struct file *file, char __user *buf, size_t count,
 			data = cs_pop_entry(&csdata->chardev_queue);
 		} else if (!list_empty(&csdata->dataind_queue)) {
 			data = cs_pop_entry(&csdata->dataind_queue);
-			--csdata->dataind_pending;
+			csdata->dataind_pending--;
 
 		} else {
 			data = 0;
@@ -1239,8 +1234,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
 
 		if (copy_to_user((void __user *)arg, &ifver, sizeof(ifver)))
 			r = -EFAULT;
-		break;
 	}
+		break;
 	case CS_CONFIG_BUFS: {
 		struct cs_buffer_config buf_cfg;
 
@@ -1249,8 +1244,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
 			r = -EFAULT;
 		else
 			r = cs_hsi_buf_config(csdata->hi, &buf_cfg);
-		break;
 	}
+		break;
 	default:
 		r = -ENOTTY;
 		break;


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply related

* Re: [PATCHv2 0/2] N900 Modem Speech Support
From: Aaro Koskinen @ 2015-03-04 19:36 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Sebastian Reichel, Peter Ujfalusi, Kai Vehmanen, Pali Rohar,
	Ivaylo Dimitrov, linux-omap, linux-kernel, linux-api
In-Reply-To: <20150304192419.GA8981@amd>

On Wed, Mar 04, 2015 at 08:24:19PM +0100, Pavel Machek wrote:
> @@ -1239,8 +1234,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
>  
>  		if (copy_to_user((void __user *)arg, &ifver, sizeof(ifver)))
>  			r = -EFAULT;
> -		break;
>  	}
> +		break;
>  	case CS_CONFIG_BUFS: {
>  		struct cs_buffer_config buf_cfg;
>  
> @@ -1249,8 +1244,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
>  			r = -EFAULT;
>  		else
>  			r = cs_hsi_buf_config(csdata->hi, &buf_cfg);
> -		break;
>  	}
> +		break;

I think having the break inside the block is more readable.
Now the indendation is mess.

A.

^ permalink raw reply

* Re: [PATCHv2 0/2] N900 Modem Speech Support
From: Pavel Machek @ 2015-03-04 19:41 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Peter Ujfalusi, Kai Vehmanen, Pali Rohar, Aaro Koskinen,
	Ivaylo Dimitrov, linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150304192419.GA8981@amd>

Hi!

  CMT speech (CMT_SPEECH) [N/m/y/?] (NEW) ?

CONFIG_CMT_SPEECH:

If you say Y here, you will enable the CMT speech protocol used
by Nokia modems.

If unsure, say N.

Normally, we also specify name of the module in config text. .. which
is strange, because I selected "m" and can't find cmt_speech.ko
anywhere.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCHv2 0/2] N900 Modem Speech Support
From: Pavel Machek @ 2015-03-04 19:55 UTC (permalink / raw)
  To: Aaro Koskinen
  Cc: Sebastian Reichel, Peter Ujfalusi, Kai Vehmanen, Pali Rohar,
	Ivaylo Dimitrov, linux-omap, linux-kernel, linux-api
In-Reply-To: <20150304193650.GA587@fuloong-minipc.musicnaut.iki.fi>

On Wed 2015-03-04 21:36:50, Aaro Koskinen wrote:
> On Wed, Mar 04, 2015 at 08:24:19PM +0100, Pavel Machek wrote:
> > @@ -1239,8 +1234,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
> >  
> >  		if (copy_to_user((void __user *)arg, &ifver, sizeof(ifver)))
> >  			r = -EFAULT;
> > -		break;
> >  	}
> > +		break;
> >  	case CS_CONFIG_BUFS: {
> >  		struct cs_buffer_config buf_cfg;
> >  
> > @@ -1249,8 +1244,8 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
> >  			r = -EFAULT;
> >  		else
> >  			r = cs_hsi_buf_config(csdata->hi, &buf_cfg);
> > -		break;
> >  	}
> > +		break;
> 
> I think having the break inside the block is more readable.
> Now the indendation is mess.

Half the function does it one way, one the other way. I don't care
which way, but it should be consistent.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCH v5 tip 0/7] tracing: attach eBPF programs to kprobes
From: Ingo Molnar @ 2015-03-04 20:33 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Namhyung Kim, Arnaldo Carvalho de Melo, Jiri Olsa,
	Masami Hiramatsu, David S. Miller, Daniel Borkmann,
	Peter Zijlstra, Linux API, Network Development, LKML
In-Reply-To: <CAMEtUuzOQqyXgZaytwOPxAfn5ucu08HjAMrFUgeSaLRVg9E0rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>


* Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org> wrote:

> On Sun, Mar 1, 2015 at 3:27 PM, Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org> wrote:
> > Peter, Steven,
> > I think this set addresses everything we've discussed.
> > Please review/ack. Thanks!
> 
> icmp echo request

I'd really like to have an Acked-by from Steve (propagated into the 
changelogs) before looking at applying these patches.

Thanks,

	Ingo

^ permalink raw reply

* Re: [PATCH v5 tip 0/7] tracing: attach eBPF programs to kprobes
From: Steven Rostedt @ 2015-03-04 20:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alexei Starovoitov, Namhyung Kim, Arnaldo Carvalho de Melo,
	Jiri Olsa, Masami Hiramatsu, David S. Miller, Daniel Borkmann,
	Peter Zijlstra, Linux API, Network Development, LKML
In-Reply-To: <20150304203316.GA7142@gmail.com>

On Wed, 4 Mar 2015 21:33:16 +0100
Ingo Molnar <mingo@kernel.org> wrote:

> 
> * Alexei Starovoitov <ast@plumgrid.com> wrote:
> 
> > On Sun, Mar 1, 2015 at 3:27 PM, Alexei Starovoitov <ast@plumgrid.com> wrote:
> > > Peter, Steven,
> > > I think this set addresses everything we've discussed.
> > > Please review/ack. Thanks!
> > 
> > icmp echo request
> 
> I'd really like to have an Acked-by from Steve (propagated into the 
> changelogs) before looking at applying these patches.

I'll have to look at this tomorrow. I'm a bit swamped with other things
at the moment :-/

-- Steve

^ permalink raw reply

* Re: [PATCH v3 0/3] epoll: introduce round robin wakeup mode
From: Ingo Molnar @ 2015-03-05  0:02 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jason Baron, peterz, mingo, viro, normalperson, davidel,
	mtk.manpages, luto, linux-kernel, linux-fsdevel, linux-api,
	Linus Torvalds, Alexander Viro
In-Reply-To: <20150227143158.afa4ec39d49d5815cbbd6a6c@linux-foundation.org>


* Andrew Morton <akpm@linux-foundation.org> wrote:

> On Fri, 27 Feb 2015 17:01:32 -0500 Jason Baron <jbaron@akamai.com> wrote:
> 
> > 
> > >
> > > I don't really understand the need for rotation/round-robin.  We can
> > > solve the thundering herd via exclusive wakeups, but what is the point
> > > in choosing to wake the task which has been sleeping for the longest
> > > time?  Why is that better than waking the task which has been sleeping
> > > for the *least* time?  That's probably faster as that task's data is
> > > more likely to still be in cache.
> > >
> > > The changelogs talks about "starvation" but they don't really say what
> > > this term means in this context, nor why it is a bad thing.
> > >
> 
> I'm still not getting it.
> 
> > So the idea with the 'rotation' is to try and distribute the
> > workload more evenly across the worker threads.
> 
> Why?
> 
> > We currently
> > tend to wake up the 'head' of the queue over and over and
> > thus the workload for us is not evenly distributed.
> 
> What's wrong with that?
> 
> > In fact, we
> > have a workload where we have to remove all the epoll sets
> > and then re-add them in a different order to improve the situation.
> 
> Why?

So my guess would be (but Jason would know this more precisely) that 
spreading the workload to more tasks in a FIFO manner, the individual 
tasks can move between CPUs better, and fill in available CPU 
bandwidth better, increasing concurrency.

With the current LIFO distribution of wakeups, the 'busiest' threads 
will get many wakeups (potentially from different CPUs), making them 
cache-hot, which may interfere with them easily migrating across CPUs.

So while technically both approaches have similar concurrency, the 
more 'spread out' task hierarchy schedules in a more consistent 
manner.

But ... this is just a wild guess and even if my description is 
accurate then it should still be backed by robust measurements and 
observations, before we extend the ABI.

This hypothesis could be tested by the patch below: with the patch 
applied if the performance difference between FIFO and LIFO epoll 
wakeups disappears, then the root cause is the cache-hotness code in 
the scheduler.

Thanks,

	Ingo

---

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index ee595ef30470..89af04e946d2 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5354,7 +5354,7 @@ static int task_hot(struct task_struct *p, struct lb_env *env)
 
 	lockdep_assert_held(&env->src_rq->lock);
 
-	if (p->sched_class != &fair_sched_class)
+	if (1 || p->sched_class != &fair_sched_class)
 		return 0;
 
 	if (unlikely(p->policy == SCHED_IDLE))

^ permalink raw reply related

* Re: [PATCH v3 0/3] epoll: introduce round robin wakeup mode
From: Jason Baron @ 2015-03-05  3:53 UTC (permalink / raw)
  To: Ingo Molnar, Andrew Morton
  Cc: peterz, mingo, viro, normalperson, davidel, mtk.manpages, luto,
	linux-kernel, linux-fsdevel, linux-api, Linus Torvalds,
	Alexander Viro
In-Reply-To: <20150305000225.GA27592@gmail.com>

On 03/04/2015 07:02 PM, Ingo Molnar wrote:
> * Andrew Morton <akpm@linux-foundation.org> wrote:
>
>> On Fri, 27 Feb 2015 17:01:32 -0500 Jason Baron <jbaron@akamai.com> wrote:
>>
>>>> I don't really understand the need for rotation/round-robin.  We can
>>>> solve the thundering herd via exclusive wakeups, but what is the point
>>>> in choosing to wake the task which has been sleeping for the longest
>>>> time?  Why is that better than waking the task which has been sleeping
>>>> for the *least* time?  That's probably faster as that task's data is
>>>> more likely to still be in cache.
>>>>
>>>> The changelogs talks about "starvation" but they don't really say what
>>>> this term means in this context, nor why it is a bad thing.
>>>>
>> I'm still not getting it.
>>
>>> So the idea with the 'rotation' is to try and distribute the
>>> workload more evenly across the worker threads.
>> Why?
>>
>>> We currently
>>> tend to wake up the 'head' of the queue over and over and
>>> thus the workload for us is not evenly distributed.
>> What's wrong with that?
>>
>>> In fact, we
>>> have a workload where we have to remove all the epoll sets
>>> and then re-add them in a different order to improve the situation.
>> Why?
> So my guess would be (but Jason would know this more precisely) that 
> spreading the workload to more tasks in a FIFO manner, the individual 
> tasks can move between CPUs better, and fill in available CPU 
> bandwidth better, increasing concurrency.
>
> With the current LIFO distribution of wakeups, the 'busiest' threads 
> will get many wakeups (potentially from different CPUs), making them 
> cache-hot, which may interfere with them easily migrating across CPUs.
>
> So while technically both approaches have similar concurrency, the 
> more 'spread out' task hierarchy schedules in a more consistent 
> manner.
>
> But ... this is just a wild guess and even if my description is 
> accurate then it should still be backed by robust measurements and 
> observations, before we extend the ABI.
>
> This hypothesis could be tested by the patch below: with the patch 
> applied if the performance difference between FIFO and LIFO epoll 
> wakeups disappears, then the root cause is the cache-hotness code in 
> the scheduler.
>
>

So what I think you are describing here fits the model
where you have single epoll fd (returned by epoll_create()),
which is then attached to wakeup fds. So that can be thought
of as having a single 'event' queue (the single epoll fd), where
multiple threads are competing to grab events via epoll_wait()
and things are currently LIFO there as you describe.

However, the use-case I was trying to get at is where you have
multiple epoll fds (or event queues), and really just one thread
doing epoll_wait() against a single epoll fd. So instead of having
all threads competing for all events, we have divided up the
events into separate queues.

Now, the 'problematic' case is where there may be an event
source that is shared among all these epoll fds - such as a listen
socket or a pipe. Now there are two distinct issues in this case
that this series is trying to address.

1) All epoll fds will receive a wakeup (and hence the threads
that are potentially blocking there, although they may not
return to user-space if the event has already been consumed).
I think the test case I posted shows this pretty clearly -
http://lwn.net/Articles/632590/. The number of context switches
without adding the to the wait queue is 50x the case where
they are added exclusively. That's a lot of extra cpu usage.

2) We are using the wakeup in this case to 'assign' work more
permanently to the thread. That is, in the case of a listen socket
we then add the connected socket to the woken up threads
local set of epoll events. So the load persists past the wake up.
And in this case, doing the round robin wakeups, simply allows
us to access more cpu bandwidth. (I'm also looking into potentially
using cpu affinity to do the wakeups as well as you suggested.)

Thanks,

-Jason

^ permalink raw reply

* Re: [PATCH v3 0/3] epoll: introduce round robin wakeup mode
From: Ingo Molnar @ 2015-03-05  9:15 UTC (permalink / raw)
  To: Jason Baron
  Cc: Andrew Morton, peterz, mingo, viro, normalperson, davidel,
	mtk.manpages, luto, linux-kernel, linux-fsdevel, linux-api,
	Linus Torvalds, Alexander Viro
In-Reply-To: <54F7D343.5090106@akamai.com>


* Jason Baron <jbaron@akamai.com> wrote:

> 2) We are using the wakeup in this case to 'assign' work more 
> permanently to the thread. That is, in the case of a listen socket 
> we then add the connected socket to the woken up threads local set 
> of epoll events. So the load persists past the wake up. And in this 
> case, doing the round robin wakeups, simply allows us to access more 
> cpu bandwidth. (I'm also looking into potentially using cpu affinity 
> to do the wakeups as well as you suggested.)

So this is the part that I still don't understand.

What difference does LIFO versus FIFO wakeups make to CPU utilization: 
a thread waiting for work is idle, no matter whether it ran most 
recently or least recently.

Once an idle worker thread is woken it will compute its own work, for 
whatever time it needs to, and won't be bothered by epoll again until 
it finished its work and starts waiting again.

So regardless the wakeup order it's the same principal bandwidth 
utilization, modulo caching artifacts [*] and modulo scheduling 
artifacts [**]:

[*]  Caching artifacts: in that sense Andrew's point stands: given 
     multiple equivalent choices it's more beneficial to pick a thread 
     that was most recently used (and is thus most cache-hot - i.e. 
     the current wakeup behavior), versus a thread that was least 
     recently used (and is thus the most cache-cold - i.e. the 
     round-robin wakeup you introduce).

[**] The hack patch I posted in my previous reply.

Thanks,

	Ingo

^ permalink raw reply

* [PATCH v1 0/6] Add simple EEPROM Framework via regmap.
From: Srinivas Kandagatla @ 2015-03-05  9:44 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, Arnd Bergmann, broonie,
	Greg Kroah-Hartman, andrew, Srinivas Kandagatla
In-Reply-To: <1424365639-26634-1-git-send-email-srinivas.kandagatla@linaro.org>

Thankyou all for providing inputs and comments on RFC patchset.
Here is the v1 of the patchset addressing all the issues raised as
part of RFC review.

This patchset adds a new simple EEPROM framework to kernel.

Up until now, EEPROM drivers were stored in drivers/misc, where they all had to
duplicate pretty much the same code to register a sysfs file, allow in-kernel
users to access the content of the devices they were driving, etc.
    
This was also a problem as far as other in-kernel users were involved, since
the solutions used were pretty much different from on driver to another, there
was a rather big abstraction leak.
    
This introduction of this framework aims at solving this. It also introduces DT
representation for consumer devices to go get the data they require (MAC
Addresses, SoC/Revision ID, part numbers, and so on) from the EEPROMs.
    
Having regmap interface to this framework would give much better
abstraction for eeproms on different buses.

patch 1-4 Introduces the EEPROM framework.
Patch 5 migrates an existing driver to eeprom framework.
Patch 6 Adds Qualcomm specific qfprom driver.

Its also possible to migrate other eeprom drivers to this framework.
Patch 6 can also be made a generic mmio-eeprom driver.

Providers APIs:
	eeprom_register/unregister();

Consumers APIs:
	eeprom_cell_get()/of_eeprom_cell_get()/of_eeprom_cell_get_byname();
	eeprom_cell_read()/eeprom_cell_write();

Device Tree:

	/* Provider */
	qfprom: qfprom@00700000 {
		compatible 	= "qcom,qfprom";
		reg		= <0x00700000 0x1000>;
		...

		/* Data cells */
		tsens_calibration: calib@404 {
			reg = <0x404 0x10>;
		};

		serial_number: sn {
			reg = <0x104 0x4>, <0x204 0x4>, <0x30c 0x4>;

		};
		...
	};
	
	/* Consumer node */
	tsens: tsens {
		...
		eeproms = <&tsens_calibration>;
		eeprom-names = "calib";
		...
	};

userspace interface:

hexdump /sys/class/eeprom/qfprom0/eeprom
                                                                                                                                                                                                                  
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
0000000 0000 0000 0000 0000 0000 0000 0000 0000
...
*
0001000


Changes since RFC(https://lkml.org/lkml/2015/2/19/307)
 * Fix documentation and error checks in read/write spotted by Andrew Lunn
 * Kconfig fix suggested by Stephen Boyd.
 * Add module owner suggested by Stephen Boyd and others.
 * Fix unsafe handling of eeprom in unregister spotted by Russell and Mark Brown.
 * seperate bindings patch as suggested by Rob.
 * Add MAINTAINERS as suggested by Rob.
 * Added support to allow reading eeprom for things like serial number which
 * canbe scatters across.
 * Added eeprom data using reg property suggested by Sascha and Stephen.
 * Added non-DT support.
 * Move kerneldoc to the src files spotted by Mark Brown.
 * Remove local list and do eeprom lookup by using class_find_device()


Thanks,
srini


Maxime Ripard (1):
  eeprom: sunxi: Move the SID driver to the eeprom framework

Srinivas Kandagatla (5):
  eeprom: Add a simple EEPROM framework for eeprom providers
  eeprom: Add a simple EEPROM framework for eeprom consumers
  eeprom: Add bindings for simple eeprom framework
  eeprom: qfprom: Add Qualcomm QFPROM support.
  eeprom: Add to MAINTAINERS for eeprom framework

 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |  22 -
 .../devicetree/bindings/eeprom/eeprom.txt          |  70 +++
 MAINTAINERS                                        |   9 +
 drivers/Kconfig                                    |   2 +
 drivers/Makefile                                   |   1 +
 drivers/eeprom/Kconfig                             |  38 ++
 drivers/eeprom/Makefile                            |  11 +
 drivers/eeprom/core.c                              | 506 +++++++++++++++++++++
 drivers/eeprom/eeprom-sunxi-sid.c                  | 129 ++++++
 drivers/eeprom/qfprom.c                            |  74 +++
 drivers/misc/eeprom/Kconfig                        |  13 -
 drivers/misc/eeprom/Makefile                       |   1 -
 drivers/misc/eeprom/sunxi_sid.c                    | 156 -------
 include/linux/eeprom-consumer.h                    |  67 +++
 include/linux/eeprom-provider.h                    |  47 ++
 15 files changed, 954 insertions(+), 192 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 create mode 100644 Documentation/devicetree/bindings/eeprom/eeprom.txt
 create mode 100644 drivers/eeprom/Kconfig
 create mode 100644 drivers/eeprom/Makefile
 create mode 100644 drivers/eeprom/core.c
 create mode 100644 drivers/eeprom/eeprom-sunxi-sid.c
 create mode 100644 drivers/eeprom/qfprom.c
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 include/linux/eeprom-consumer.h
 create mode 100644 include/linux/eeprom-provider.h

-- 
1.9.1

^ permalink raw reply

* [PATCH v1 1/6] eeprom: Add a simple EEPROM framework for eeprom providers
From: Srinivas Kandagatla @ 2015-03-05  9:45 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds just providers part of the framework just to enable easy
review.

Up until now, EEPROM drivers were stored in drivers/misc, where they all had to
duplicate pretty much the same code to register a sysfs file, allow in-kernel
users to access the content of the devices they were driving, etc.

This was also a problem as far as other in-kernel users were involved, since
the solutions used were pretty much different from on driver to another, there
was a rather big abstraction leak.

This introduction of this framework aims at solving this. It also introduces DT
representation for consumer devices to go get the data they require (MAC
Addresses, SoC/Revision ID, part numbers, and so on) from the EEPROMs.

Having regmap interface to this framework would give much better
abstraction for eeproms on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/Kconfig                 |   2 +
 drivers/Makefile                |   1 +
 drivers/eeprom/Kconfig          |  20 ++++
 drivers/eeprom/Makefile         |   9 ++
 drivers/eeprom/core.c           | 208 ++++++++++++++++++++++++++++++++++++++++
 include/linux/eeprom-provider.h |  47 +++++++++
 6 files changed, 287 insertions(+)
 create mode 100644 drivers/eeprom/Kconfig
 create mode 100644 drivers/eeprom/Makefile
 create mode 100644 drivers/eeprom/core.c
 create mode 100644 include/linux/eeprom-provider.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c70d6e4..d7afc82 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -184,4 +184,6 @@ source "drivers/thunderbolt/Kconfig"
 
 source "drivers/android/Kconfig"
 
+source "drivers/eeprom/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 527a6da..57eb5b0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,4 @@ obj-$(CONFIG_RAS)		+= ras/
 obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
 obj-$(CONFIG_CORESIGHT)		+= coresight/
 obj-$(CONFIG_ANDROID)		+= android/
+obj-$(CONFIG_EEPROM)		+= eeprom/
diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
new file mode 100644
index 0000000..d00f7d2
--- /dev/null
+++ b/drivers/eeprom/Kconfig
@@ -0,0 +1,20 @@
+menuconfig EEPROM
+	bool "EEPROM Support"
+	depends on OF
+	select REGMAP
+	help
+	  Support for EEPROM alike devices.
+
+	  This framework is designed to provide a generic interface to EEPROM
+	  from both the Linux Kernel and the userspace.
+
+	  If unsure, say no.
+
+if EEPROM
+
+config EEPROM_DEBUG
+	bool "EEPROM debug support"
+	help
+	  Say yes here to enable debugging support.
+
+endif
diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
new file mode 100644
index 0000000..e130079
--- /dev/null
+++ b/drivers/eeprom/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for eeprom drivers.
+#
+
+ccflags-$(CONFIG_EEPROM_DEBUG) += -DDEBUG
+
+obj-$(CONFIG_EEPROM)		+= core.o
+
+# Devices
diff --git a/drivers/eeprom/core.c b/drivers/eeprom/core.c
new file mode 100644
index 0000000..243e466
--- /dev/null
+++ b/drivers/eeprom/core.c
@@ -0,0 +1,208 @@
+/*
+ * EEPROM framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/device.h>
+#include <linux/eeprom-provider.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+struct eeprom_device {
+	struct regmap		*regmap;
+	int			stride;
+	size_t			size;
+
+	struct module		*owner;
+	struct device		dev;
+	int			id;
+	atomic_t		users;
+};
+
+static DEFINE_MUTEX(eeprom_mutex);
+static DEFINE_IDA(eeprom_ida);
+
+#define to_eeprom(d) container_of(d, struct eeprom_device, dev)
+
+static ssize_t bin_attr_eeprom_read(struct file *filp, struct kobject *kobj,
+				    struct bin_attribute *attr,
+				    char *buf, loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct eeprom_device *eeprom = to_eeprom(dev);
+	int rc;
+
+	if (offset > eeprom->size)
+		return -EINVAL;
+
+	if (offset + count > eeprom->size)
+		count = eeprom->size - offset;
+
+	rc = regmap_bulk_read(eeprom->regmap, offset,
+			      buf, count/eeprom->stride);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count - count % eeprom->stride;
+}
+
+static ssize_t bin_attr_eeprom_write(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct eeprom_device *eeprom = to_eeprom(dev);
+	int rc;
+
+	if (offset > eeprom->size)
+		return -EINVAL;
+
+	if (offset + count > eeprom->size)
+		count = eeprom->size - offset;
+
+	rc = regmap_bulk_write(eeprom->regmap, offset,
+			       buf, count/eeprom->stride);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count - count % eeprom->stride;
+}
+
+static struct bin_attribute bin_attr_eeprom = {
+	.attr	= {
+		.name	= "eeprom",
+		.mode	= S_IWUSR | S_IRUGO,
+	},
+	.read	= bin_attr_eeprom_read,
+	.write	= bin_attr_eeprom_write,
+};
+
+static struct bin_attribute *eeprom_bin_attributes[] = {
+	&bin_attr_eeprom,
+	NULL,
+};
+
+static const struct attribute_group eeprom_bin_group = {
+	.bin_attrs	= eeprom_bin_attributes,
+};
+
+static const struct attribute_group *eeprom_dev_groups[] = {
+	&eeprom_bin_group,
+	NULL,
+};
+
+static void eeprom_release(struct device *dev)
+{
+	kfree(to_eeprom(dev));
+}
+
+static struct class eeprom_class = {
+	.name		= "eeprom",
+	.dev_groups	= eeprom_dev_groups,
+	.dev_release	= eeprom_release,
+};
+
+/**
+ * eeprom_register(): Register a eeprom device for given eeprom.
+ * Also creates an binary entry in /sys/class/eeprom/name-id/eeprom
+ *
+ * @eeprom: eeprom device that needs to be created
+ *
+ * The return value will be an error code on error or a zero on success.
+ * The eeprom_device and sysfs entery will be freed by the eeprom_unregister().
+ */
+
+struct eeprom_device *eeprom_register(struct eeprom_config *config)
+{
+	struct eeprom_device *eeprom;
+	int rval;
+
+	if (!config->regmap || !config->size) {
+		dev_err(config->dev, "Regmap not found\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL);
+	if (!eeprom)
+		return ERR_PTR(-ENOMEM);
+
+	eeprom->id = ida_simple_get(&eeprom_ida, 0, 0, GFP_KERNEL);
+	if (eeprom->id < 0)
+		return ERR_PTR(eeprom->id);
+
+	eeprom->owner = config->owner;
+	eeprom->regmap = config->regmap;
+	eeprom->stride = config->stride;
+	eeprom->size = config->size;
+	eeprom->dev.class = &eeprom_class;
+	eeprom->dev.parent = config->dev;
+	eeprom->dev.of_node = config->dev ? config->dev->of_node : NULL;
+	dev_set_name(&eeprom->dev, "%s%d",
+		     config->name ? : "eeprom", config->id);
+
+	device_initialize(&eeprom->dev);
+
+	dev_dbg(&eeprom->dev, "Registering eeprom device %s\n",
+		dev_name(&eeprom->dev));
+
+	rval = device_add(&eeprom->dev);
+	if (rval)
+		return ERR_PTR(rval);
+
+	return eeprom;
+}
+EXPORT_SYMBOL(eeprom_register);
+
+/**
+ * eeprom_unregister(): Unregister previously registered eeprom device
+ *
+ * @eeprom: Pointer to previously registered eeprom device.
+ *
+ * The return value will be an non zero on error or a zero on success.
+ */
+int eeprom_unregister(struct eeprom_device *eeprom)
+{
+	mutex_lock(&eeprom_mutex);
+	if (atomic_read(&eeprom->users)) {
+		mutex_unlock(&eeprom_mutex);
+		return -EBUSY;
+	}
+
+	device_del(&eeprom->dev);
+	mutex_unlock(&eeprom_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(eeprom_unregister);
+
+static int eeprom_init(void)
+{
+	return class_register(&eeprom_class);
+}
+
+static void eeprom_exit(void)
+{
+	class_unregister(&eeprom_class);
+}
+
+subsys_initcall(eeprom_init);
+module_exit(eeprom_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("EEPROM Driver Core");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/eeprom-provider.h b/include/linux/eeprom-provider.h
new file mode 100644
index 0000000..51dc654
--- /dev/null
+++ b/include/linux/eeprom-provider.h
@@ -0,0 +1,47 @@
+/*
+ * EEPROM framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_EEPROM_PROVIDER_H
+#define _LINUX_EEPROM_PROVIDER_H
+
+#include <linux/regmap.h>
+
+struct eeprom_device;
+
+struct eeprom_config {
+	struct device		*dev;
+	struct regmap		*regmap;
+	const char		*name;
+	int			id;
+	int			stride;
+	size_t			size;
+	struct module		*owner;
+};
+
+#ifdef CONFIG_EEPROM
+
+struct eeprom_device *eeprom_register(struct eeprom_config *cfg);
+int eeprom_unregister(struct eeprom_device *eeprom);
+
+#else
+
+static inline struct eeprom_device *eeprom_register(struct eeprom_config *cfg)
+{
+	return NULL;
+}
+static inline int eeprom_unregister(struct eeprom_device *eeprom)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_EEPROM */
+
+#endif  /* ifndef _LINUX_EEPROM_PROVIDER_H */
-- 
1.9.1

^ permalink raw reply related

* [PATCH v1 2/6] eeprom: Add a simple EEPROM framework for eeprom consumers
From: Srinivas Kandagatla @ 2015-03-05  9:45 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds just consumers part of the framework just to enable easy
review.

Up until now, EEPROM drivers were stored in drivers/misc, where they all had to
duplicate pretty much the same code to register a sysfs file, allow in-kernel
users to access the content of the devices they were driving, etc.

This was also a problem as far as other in-kernel users were involved, since
the solutions used were pretty much different from on driver to another, there
was a rather big abstraction leak.

This introduction of this framework aims at solving this. It also introduces DT
representation for consumer devices to go get the data they require (MAC
Addresses, SoC/Revision ID, part numbers, and so on) from the EEPROMs.

Having regmap interface to this framework would give much better
abstraction for eeproms on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of the framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/eeprom/core.c           | 298 ++++++++++++++++++++++++++++++++++++++++
 include/linux/eeprom-consumer.h |  67 +++++++++
 2 files changed, 365 insertions(+)
 create mode 100644 include/linux/eeprom-consumer.h

diff --git a/drivers/eeprom/core.c b/drivers/eeprom/core.c
index 243e466..75ae39c 100644
--- a/drivers/eeprom/core.c
+++ b/drivers/eeprom/core.c
@@ -11,6 +11,7 @@
 
 #include <linux/device.h>
 #include <linux/eeprom-provider.h>
+#include <linux/eeprom-consumer.h>
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
@@ -31,6 +32,13 @@ struct eeprom_device {
 	atomic_t		users;
 };
 
+struct eeprom_cell {
+	struct eeprom_device *eeprom;
+	int nblocks;
+	int size;
+	struct eeprom_block blocks[0];
+};
+
 static DEFINE_MUTEX(eeprom_mutex);
 static DEFINE_IDA(eeprom_ida);
 
@@ -116,6 +124,37 @@ static struct class eeprom_class = {
 	.dev_release	= eeprom_release,
 };
 
+static int of_eeprom_match(struct device *dev, const void *eeprom_np)
+{
+	return dev->of_node == eeprom_np;
+}
+
+static struct eeprom_device *of_eeprom_find(struct device_node *eeprom_np)
+{
+	struct device *d;
+
+	if (!eeprom_np)
+		return NULL;
+
+	d = class_find_device(&eeprom_class, NULL, eeprom_np, of_eeprom_match);
+
+	return d ? to_eeprom(d) : NULL;
+}
+
+static int eeprom_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), (const char *)data);
+}
+
+static struct eeprom_device *eeprom_find(const char *name)
+{
+	struct device *d;
+
+	d = class_find_device(&eeprom_class, NULL, (void *)name, eeprom_match);
+
+	return d ? to_eeprom(d) : NULL;
+}
+
 /**
  * eeprom_register(): Register a eeprom device for given eeprom.
  * Also creates an binary entry in /sys/class/eeprom/name-id/eeprom
@@ -189,6 +228,265 @@ int eeprom_unregister(struct eeprom_device *eeprom)
 }
 EXPORT_SYMBOL(eeprom_unregister);
 
+static struct eeprom_cell *eeprom_cell_sanity_check(struct eeprom_cell *cell)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	int i;
+
+	/* byte aligned, no need to check for stride sanity */
+	if (eeprom->stride == 1)
+		return cell;
+
+	for (i = 0; i < cell->nblocks; i++) {
+		if (!IS_ALIGNED(cell->blocks[i].offset, eeprom->stride) ||
+		    !IS_ALIGNED(cell->blocks[i].count, eeprom->stride)) {
+			dev_err(&eeprom->dev,
+				"cell unaligned to eeprom stride %d\n",
+				eeprom->stride);
+			atomic_dec(&eeprom->users);
+			module_put(eeprom->owner);
+			kfree(cell);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return cell;
+}
+
+/**
+ * eeprom_cell_get(): Get eeprom cell of device form a given eeprom name
+ * and blocks.
+ *
+ * @ename: eeprom device name that needs to be looked-up.
+ * @blocks: eeprom blocks containing offset and length information.
+ * @nblocks: number of eeprom blocks.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks)
+{
+	struct eeprom_cell *cell;
+	struct eeprom_device *eeprom = NULL;
+	int i;
+
+	mutex_lock(&eeprom_mutex);
+	eeprom = eeprom_find(ename);
+	if (!eeprom) {
+		mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+	atomic_inc(&eeprom->users);
+
+	if (!try_module_get(eeprom->owner)) {
+		dev_err(&eeprom->dev,
+			"could not increase module refcount for cell %s\n",
+			ename);
+			mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EINVAL);
+	}
+	mutex_unlock(&eeprom_mutex);
+
+	cell = kzalloc(sizeof(*cell) + nblocks * sizeof(*blocks), GFP_KERNEL);
+	if (!cell)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(cell->blocks, blocks, nblocks * sizeof(*blocks));
+	cell->nblocks = nblocks;
+	cell->eeprom = eeprom;
+	cell->size = 0;
+
+	for (i = 0; i < nblocks; i++)
+		cell->size += blocks[i].count;
+
+	return eeprom_cell_sanity_check(cell);
+}
+EXPORT_SYMBOL(eeprom_cell_get);
+
+/**
+ * of_eeprom_cell_get(): Get eeprom cell of device form a given index
+ *
+ * @dev: Device that will be interacted with
+ * @index: eeprom index in eeproms property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *of_eeprom_cell_get(struct device *dev, int index)
+{
+	struct device_node *cell_np;
+	struct eeprom_cell *cell;
+	struct eeprom_device *eeprom = NULL;
+	int i, nblocks;
+	struct property *prop;
+	const __be32 *vp;
+	u32 pv;
+
+	if (!dev || !dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	cell_np = of_parse_phandle(dev->of_node, "eeproms", index);
+	if (!cell_np)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	mutex_lock(&eeprom_mutex);
+	eeprom = of_eeprom_find(cell_np->parent);
+	if (!eeprom) {
+		mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	atomic_inc(&eeprom->users);
+
+	if (!try_module_get(eeprom->owner)) {
+		dev_err(&eeprom->dev,
+			"could not increase module refcount for cell %d\n",
+			index);
+			mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EINVAL);
+	}
+	mutex_unlock(&eeprom_mutex);
+
+	nblocks = of_property_count_u32_elems(cell_np, "reg") / 2;
+
+	cell = kzalloc(sizeof(*cell) + nblocks * sizeof(struct eeprom_block),
+		       GFP_KERNEL);
+	cell->nblocks = nblocks;
+	cell->eeprom = eeprom;
+	cell->size = 0;
+	i = 0;
+
+	of_property_for_each_u32(cell_np, "reg", prop, vp, pv) {
+		cell->blocks[i].offset = pv;
+		vp = of_prop_next_u32(prop, vp, &pv);
+		cell->blocks[i].count = pv;
+		cell->size += pv;
+		i++;
+	}
+
+	return eeprom_cell_sanity_check(cell);
+}
+EXPORT_SYMBOL(of_eeprom_cell_get);
+
+/**
+ * of_eeprom_cell_get_byname(): Get eeprom cell of device form a given name
+ *
+ * @dev: Device that will be interacted with
+ * @name: eeprom name in eeprom-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+					      const char *id)
+{
+	int index = 0;
+
+	if (!dev || !dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	if (id)
+		index = of_property_match_string(dev->of_node,
+						 "eeprom-names",
+						 id);
+	return of_eeprom_cell_get(dev, index);
+
+}
+EXPORT_SYMBOL(of_eeprom_cell_get_byname);
+
+/**
+ * eeprom_cell_put(): Release previously allocated eeprom cell.
+ *
+ * @cell: Previously allocated eeprom cell by eeprom_cell_get()
+ * or of_eeprom_cell_get() or of_eeprom_cell_get_byname().
+ */
+void eeprom_cell_put(struct eeprom_cell *cell)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+
+	atomic_dec(&eeprom->users);
+	module_put(eeprom->owner);
+	kfree(cell);
+}
+EXPORT_SYMBOL(eeprom_cell_put);
+
+/**
+ * eeprom_cell_read(): Read a given eeprom cell
+ *
+ * @cell: eeprom cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a char * bufffer.  The buffer should be freed by the consumer with a
+ * kfree().
+ */
+char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	char *buf;
+	int rc, i, offset = 0;
+
+	if (!eeprom || !eeprom->regmap)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(cell->size, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < cell->nblocks; i++) {
+		rc = regmap_bulk_read(eeprom->regmap, cell->blocks[i].offset,
+				      buf + offset,
+				      cell->blocks[i].count);
+
+		if (IS_ERR_VALUE(rc)) {
+			kfree(buf);
+			return ERR_PTR(rc);
+		}
+		offset += cell->blocks[i].count;
+	}
+
+	*len = cell->size;
+
+	return buf;
+}
+EXPORT_SYMBOL(eeprom_cell_read);
+
+/**
+ * eeprom_cell_write(): Write to a given eeprom cell
+ *
+ * @cell: eeprom cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to eeprom cell.
+ *
+ * The return value will be an non zero on error or a zero on successful write.
+ */
+int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	int i, rc, offset = 0;
+
+	if (!eeprom || !eeprom->regmap || len != cell->size)
+		return -EINVAL;
+
+	for (i = 0; i < cell->nblocks; i++) {
+		rc = regmap_bulk_write(eeprom->regmap, cell->blocks[i].offset,
+				 buf + offset,
+				 cell->blocks[i].count);
+
+		if (IS_ERR_VALUE(rc))
+			return rc;
+
+		offset += cell->blocks[i].count;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL(eeprom_cell_write);
+
 static int eeprom_init(void)
 {
 	return class_register(&eeprom_class);
diff --git a/include/linux/eeprom-consumer.h b/include/linux/eeprom-consumer.h
new file mode 100644
index 0000000..e06f5e5
--- /dev/null
+++ b/include/linux/eeprom-consumer.h
@@ -0,0 +1,67 @@
+/*
+ * EEPROM framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_EEPROM_CONSUMER_H
+#define _LINUX_EEPROM_CONSUMER_H
+
+struct eeprom_cell;
+
+struct eeprom_block {
+	loff_t offset;
+	size_t count;
+};
+#ifdef CONFIG_EEPROM
+struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks);
+void eeprom_cell_put(struct eeprom_cell *cell);
+char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len);
+int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len);
+#else
+
+static inline struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks)
+{
+	return NULL;
+}
+
+static inline void eeprom_cell_put(struct eeprom_cell *cell)
+{
+}
+
+static inline char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
+{
+	return NULL;
+}
+
+static inline int eeprom_cell_write(struct eeprom_cell *cell,
+				    const char *buf, ssize_t len)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_EEPROM */
+
+#if defined(CONFIG_EEPROM) && defined(CONFIG_OF)
+struct eeprom_cell *of_eeprom_cell_get(struct device *dev, int index);
+struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+					      const char *name);
+#else
+static inline struct eeprom_cell *of_eeprom_cell_get(
+					struct device *dev, int index)
+{
+	return NULL;
+}
+static inline struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+							    const char *name)
+{
+	return NULL;
+}
+#endif
+#endif  /* ifndef _LINUX_EEPROM_CONSUMER_H */
-- 
1.9.1

^ permalink raw reply related

* [PATCH v1 3/6] eeprom: Add bindings for simple eeprom framework
From: Srinivas Kandagatla @ 2015-03-05  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds bindings for simple eeprom framework which allows eeprom
consumers to talk to eeprom providers to get access to eeprom cell data.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 .../devicetree/bindings/eeprom/eeprom.txt          | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/eeprom/eeprom.txt

diff --git a/Documentation/devicetree/bindings/eeprom/eeprom.txt b/Documentation/devicetree/bindings/eeprom/eeprom.txt
new file mode 100644
index 0000000..dbfb95c
--- /dev/null
+++ b/Documentation/devicetree/bindings/eeprom/eeprom.txt
@@ -0,0 +1,70 @@
+= EEPROM Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in EEPROMs.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on an EEPROM-like device, for the OS to be able to retrieve
+these information and act upon it. Obviously, the OS has to know
+about where to retrieve these data from, and where they are stored on
+the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+to this node.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in eeprom provider.
+
+Required properties:
+reg:	specifies the offset in byte within that storage device, and the length
+	in bytes of the data we care about.
+	There could be more then one offset-length pairs in this property.
+
+Optional properties:
+As required by specific data parsers/interpreters.
+
+For example:
+
+	/* Provider */
+	qfprom: qfprom@00700000 {
+		compatible 	= "qcom,qfprom";
+		reg		= <0x00700000 0x1000>;
+		...
+
+		/* Data cells */
+		tsens_calibration: calib@404 {
+			reg = <0x404 0x10>;
+		};
+
+		serial_number: sn {
+			reg = <0x104 0x4>, <0x204 0x4>, <0x30c 0x4>;
+
+		};
+		...
+	};
+
+= Data consumers =
+Are drivers which consume eeprom data cells.
+
+Required properties:
+
+eeproms: List of phandle and data cell the device might be interested in.
+
+Optional properties:
+
+eeprom-names: List of data cell name strings sorted in the same order
+ 	      as the resets property. Consumers drivers will use
+ 	      eeprom-names to differentiate between multiple cells,
+ 	      and hence being able to know what these cells are for.
+
+For example:
+
+	tsens {
+		...
+		eeproms = <&tsens_calibration>;
+		eeprom-names = "calibration";
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v1 4/6] eeprom: sunxi: Move the SID driver to the eeprom framework
From: Srinivas Kandagatla @ 2015-03-05  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

From: Maxime Ripard <maxime.ripard@free-electrons.com>

Now that we have the EEPROM framework, we can consolidate the common driver
code. Move the driver to the framework, and hopefully, it will fix the sysfs
file creation race.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[srinivas.kandagatla: Moved to regmap based EEPROM framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/ABI/testing/sysfs-driver-sunxi-sid |  22 ----
 drivers/eeprom/Kconfig                           |  11 ++
 drivers/eeprom/Makefile                          |   1 +
 drivers/eeprom/eeprom-sunxi-sid.c                | 129 +++++++++++++++++++
 drivers/misc/eeprom/Kconfig                      |  13 --
 drivers/misc/eeprom/Makefile                     |   1 -
 drivers/misc/eeprom/sunxi_sid.c                  | 156 -----------------------
 7 files changed, 141 insertions(+), 192 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 create mode 100644 drivers/eeprom/eeprom-sunxi-sid.c
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c

diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644
index ffb9536..0000000
--- a/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+++ /dev/null
@@ -1,22 +0,0 @@
-What:		/sys/devices/*/<our-device>/eeprom
-Date:		August 2013
-Contact:	Oliver Schinagl <oliver@schinagl.nl>
-Description:	read-only access to the SID (Security-ID) on current
-		A-series SoC's from Allwinner. Currently supports A10, A10s, A13
-		and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
-		whereas the newer A20 SoC exposes 512 bytes split into sections.
-		Besides the 16 bytes of SID, there's also an SJTAG area,
-		HDMI-HDCP key and some custom keys. Below a quick overview, for
-		details see the user manual:
-		0x000  128 bit root-key (sun[457]i)
-		0x010  128 bit boot-key (sun7i)
-		0x020   64 bit security-jtag-key (sun7i)
-		0x028   16 bit key configuration (sun7i)
-		0x02b   16 bit custom-vendor-key (sun7i)
-		0x02c  320 bit low general key (sun7i)
-		0x040   32 bit read-control access (sun7i)
-		0x064  224 bit low general key (sun7i)
-		0x080 2304 bit HDCP-key (sun7i)
-		0x1a0  768 bit high general key (sun7i)
-Users:		any user space application which wants to read the SID on
-		Allwinner's A-series of CPU's.
diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
index d00f7d2..bff8ecb 100644
--- a/drivers/eeprom/Kconfig
+++ b/drivers/eeprom/Kconfig
@@ -17,4 +17,15 @@ config EEPROM_DEBUG
 	help
 	  Say yes here to enable debugging support.
 
+config EEPROM_SUNXI_SID
+	depends on ARCH_SUNXI
+	tristate "Allwinner SoCs SID support"
+	select REGMAP_MMIO
+	help
+	  This is a driver for the 'security ID' available on various Allwinner
+	  devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called sunxi_sid.
+
 endif
diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
index e130079..661422c 100644
--- a/drivers/eeprom/Makefile
+++ b/drivers/eeprom/Makefile
@@ -7,3 +7,4 @@ ccflags-$(CONFIG_EEPROM_DEBUG) += -DDEBUG
 obj-$(CONFIG_EEPROM)		+= core.o
 
 # Devices
+obj-$(CONFIG_EEPROM_SUNXI_SID)	+= eeprom-sunxi-sid.o
diff --git a/drivers/eeprom/eeprom-sunxi-sid.c b/drivers/eeprom/eeprom-sunxi-sid.c
new file mode 100644
index 0000000..eb32afb
--- /dev/null
+++ b/drivers/eeprom/eeprom-sunxi-sid.c
@@ -0,0 +1,129 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/device.h>
+#include <linux/eeprom-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+struct eeprom_sid {
+	void __iomem	*membase;
+	struct eeprom_device *eeprom;
+};
+
+static struct eeprom_config econfig = {
+	.stride = 1,
+	.name = "sunix-sid",
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static int sunxi_sid_reg_read(void *context,
+			      unsigned int offset, unsigned int *val)
+{
+	struct eeprom_sid *sid  = context;
+	u32 sid_key;
+
+	sid_key = ioread32be(sid->membase + round_down(offset, 4));
+	sid_key >>= (offset % 4) * 8;
+
+	*val = sid_key;
+
+	return 0;
+}
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
+	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct regmap_config sunxi_sid_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.reg_read = sunxi_sid_reg_read,
+	.writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *device;
+	struct eeprom_sid *sid;
+	struct resource *res;
+	struct eeprom_device *eeprom;
+	struct device *dev = &pdev->dev;
+
+	sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+	if (!sid)
+		return -ENOMEM;
+
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sid->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sid->membase))
+		return PTR_ERR(sid->membase);
+
+	device = of_match_device(sunxi_sid_of_match, dev);
+	if (!device)
+		return -ENODEV;
+
+	sunxi_sid_regmap_config.max_register = (unsigned int)device->data - 1;
+
+	econfig.regmap = devm_regmap_init(dev, NULL,
+					  sid, &sunxi_sid_regmap_config);
+	if (IS_ERR(econfig.regmap))
+		return PTR_ERR(econfig.regmap);
+
+	econfig.dev = dev;
+	econfig.owner = THIS_MODULE;
+	econfig.size = sunxi_sid_regmap_config.max_register;
+
+	eeprom = eeprom_register(&econfig);
+	if (IS_ERR(eeprom))
+		return PTR_ERR(eeprom);
+
+	platform_set_drvdata(pdev, eeprom);
+
+	return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+	struct eeprom_device *eeprom = platform_get_drvdata(pdev);
+
+	return eeprom_unregister(eeprom);
+}
+
+static struct platform_driver sunxi_sid_driver = {
+	.probe = sunxi_sid_probe,
+	.remove = sunxi_sid_remove,
+	.driver = {
+		.name = "sunxi-sid",
+		.of_match_table = sunxi_sid_of_match,
+	},
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..04f2e1f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,17 +96,4 @@ config EEPROM_DIGSY_MTC_CFG
 
 	  If unsure, say N.
 
-config EEPROM_SUNXI_SID
-	tristate "Allwinner sunxi security ID support"
-	depends on ARCH_SUNXI && SYSFS
-	help
-	  This is a driver for the 'security ID' available on various Allwinner
-	  devices.
-
-	  Due to the potential risks involved with changing e-fuses,
-	  this driver is read-only.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called sunxi_sid.
-
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,5 +4,4 @@ obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID)	+= sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644
index 8385177..0000000
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://www.linux-sunxi.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
-	void __iomem *reg_base;
-	unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
-			      const unsigned int offset)
-{
-	u32 sid_key;
-
-	if (offset >= sid_data->keysize)
-		return 0;
-
-	sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
-	sid_key >>= (offset % 4) * 8;
-
-	return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
-			struct bin_attribute *attr, char *buf,
-			loff_t pos, size_t size)
-{
-	struct platform_device *pdev;
-	struct sunxi_sid_data *sid_data;
-	int i;
-
-	pdev = to_platform_device(kobj_to_dev(kobj));
-	sid_data = platform_get_drvdata(pdev);
-
-	if (pos < 0 || pos >= sid_data->keysize)
-		return 0;
-	if (size > sid_data->keysize - pos)
-		size = sid_data->keysize - pos;
-
-	for (i = 0; i < size; i++)
-		buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
-	return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
-	.attr = { .name = "eeprom", .mode = S_IRUGO, },
-	.read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
-	device_remove_bin_file(&pdev->dev, &sid_bin_attr);
-	dev_dbg(&pdev->dev, "driver unloaded\n");
-
-	return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
-	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
-	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
-	{/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
-	struct sunxi_sid_data *sid_data;
-	struct resource *res;
-	const struct of_device_id *of_dev_id;
-	u8 *entropy;
-	unsigned int i;
-
-	sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
-				GFP_KERNEL);
-	if (!sid_data)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(sid_data->reg_base))
-		return PTR_ERR(sid_data->reg_base);
-
-	of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
-	if (!of_dev_id)
-		return -ENODEV;
-	sid_data->keysize = (int)of_dev_id->data;
-
-	platform_set_drvdata(pdev, sid_data);
-
-	sid_bin_attr.size = sid_data->keysize;
-	if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
-		return -ENODEV;
-
-	entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
-	for (i = 0; i < sid_data->keysize; i++)
-		entropy[i] = sunxi_sid_read_byte(sid_data, i);
-	add_device_randomness(entropy, sid_data->keysize);
-	kfree(entropy);
-
-	dev_dbg(&pdev->dev, "loaded\n");
-
-	return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
-	.probe = sunxi_sid_probe,
-	.remove = sunxi_sid_remove,
-	.driver = {
-		.name = DRV_NAME,
-		.of_match_table = sunxi_sid_of_match,
-	},
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v1 5/6] eeprom: qfprom: Add Qualcomm QFPROM support.
From: Srinivas Kandagatla @ 2015-03-05  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds QFPROM support driver which is used by other drivers
like thermal sensor and cpufreq.

On MSM parts there are some efuses (called qfprom) these fuses store things like
calibration data, speed bins.. etc. Drivers like cpufreq, thermal sensors would
read out this data for configuring the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/eeprom/Kconfig  |  7 +++++
 drivers/eeprom/Makefile |  1 +
 drivers/eeprom/qfprom.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+)
 create mode 100644 drivers/eeprom/qfprom.c

diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
index bff8ecb..65325c7 100644
--- a/drivers/eeprom/Kconfig
+++ b/drivers/eeprom/Kconfig
@@ -28,4 +28,11 @@ config EEPROM_SUNXI_SID
 	  This driver can also be built as a module. If so, the module
 	  will be called sunxi_sid.
 
+config QCOM_QFPROM
+	tristate "QCOM QFPROM Support"
+        depends on EEPROM
+	select REGMAP_MMIO
+	help
+          Say y here to enable QFPROM support. The QFPROM provides access
+          functions for QFPROM data to rest of the drivers via eeprom interface.
 endif
diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
index 661422c..f99c824 100644
--- a/drivers/eeprom/Makefile
+++ b/drivers/eeprom/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_EEPROM)		+= core.o
 
 # Devices
 obj-$(CONFIG_EEPROM_SUNXI_SID)	+= eeprom-sunxi-sid.o
+obj-$(CONFIG_QCOM_QFPROM)	+= qfprom.o
diff --git a/drivers/eeprom/qfprom.c b/drivers/eeprom/qfprom.c
new file mode 100644
index 0000000..371a8c0
--- /dev/null
+++ b/drivers/eeprom/qfprom.c
@@ -0,0 +1,74 @@
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/eeprom-provider.h>
+
+static struct regmap_config qfprom_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+};
+
+static struct eeprom_config econfig = {
+	.stride = 1,
+	.name = "qfprom",
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+	struct eeprom_device *eeprom = platform_get_drvdata(pdev);
+
+	return eeprom_unregister(eeprom);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *base;
+	struct device *dev = &pdev->dev;
+	struct eeprom_device *eeprom;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+	econfig.regmap = devm_regmap_init_mmio(dev, base,
+					       &qfprom_regmap_config);
+	if (IS_ERR(econfig.regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(econfig.regmap);
+	}
+	econfig.owner = THIS_MODULE;
+	econfig.dev = dev;
+	econfig.size = resource_size(res) - 1;
+	eeprom = eeprom_register(&econfig);
+	if (IS_ERR(eeprom))
+		return PTR_ERR(eeprom);
+
+	platform_set_drvdata(pdev, eeprom);
+	return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+	{ .compatible = "qcom,qfprom"},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+	.probe = qfprom_probe,
+	.remove = qfprom_remove,
+	.driver = {
+		.name = "qcom,qfprom",
+		.of_match_table = qfprom_of_match,
+	},
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL2");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v1 6/6] eeprom: Add to MAINTAINERS for eeprom framework
From: Srinivas Kandagatla @ 2015-03-05  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
	linux-kernel, devicetree, Stephen Boyd, andrew, Arnd Bergmann,
	broonie, Greg Kroah-Hartman, Srinivas Kandagatla
In-Reply-To: <1425548685-12887-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds MAINTAINERS to eeprom framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d66a97d..ee7ba92 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3657,6 +3657,15 @@ T:	git git://git.alsa-project.org/alsa-kernel.git
 S:	Maintained
 F:	sound/usb/misc/ua101.c
 
+EEPROM FRAMEWORK
+M:	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+S:	Maintained
+F:	drivers/eeprom/
+F:	Documentation/devicetree/bindings/eeprom/
+F:	include/linux/eeprom-provider.h
+F:	include/linux/eeprom-consumer.h
+
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:	Matt Fleming <matt.fleming@intel.com>
 L:	linux-efi@vger.kernel.org
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v1 5/6] eeprom: qfprom: Add Qualcomm QFPROM support.
From: Paul Bolle @ 2015-03-05 10:02 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard,
	Rob Herring, Pawel Moll, Kumar Gala,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Stephen Boyd,
	andrew-g2DYL2Zd6BY, Arnd Bergmann, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	Greg Kroah-Hartman
In-Reply-To: <1425548783-13110-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Thu, 2015-03-05 at 09:46 +0000, Srinivas Kandagatla wrote:
> diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
> index bff8ecb..65325c7 100644
> --- a/drivers/eeprom/Kconfig
> +++ b/drivers/eeprom/Kconfig
> @@ -28,4 +28,11 @@ config EEPROM_SUNXI_SID
>  	  This driver can also be built as a module. If so, the module
>  	  will be called sunxi_sid.
>  
> +config QCOM_QFPROM
> +	tristate "QCOM QFPROM Support"
> +        depends on EEPROM

Make this one tab, please.

> +	select REGMAP_MMIO
> +	help
> +          Say y here to enable QFPROM support. The QFPROM provides access
> +          functions for QFPROM data to rest of the drivers via eeprom interface.

And this one tab and two spaces, please.

All utterly trivial, of course, but I found a less trivial problem with
this patch, so I included these two comments anyway.

>  endif
> diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
> index 661422c..f99c824 100644
> --- a/drivers/eeprom/Makefile
> +++ b/drivers/eeprom/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_EEPROM)		+= core.o
>  
>  # Devices
>  obj-$(CONFIG_EEPROM_SUNXI_SID)	+= eeprom-sunxi-sid.o
> +obj-$(CONFIG_QCOM_QFPROM)	+= qfprom.o
> diff --git a/drivers/eeprom/qfprom.c b/drivers/eeprom/qfprom.c
> new file mode 100644
> index 0000000..371a8c0
> --- /dev/null
> +++ b/drivers/eeprom/qfprom.c
> @@ -0,0 +1,74 @@
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/eeprom-provider.h>

[...]

> +MODULE_LICENSE("GPL2");

This will taint the kernel on module load. I guess you meant
    MODULE_LICENSE("GPL v2");

but there's no comment with some lines about the license at the top of
this file, so I can't be sure.


Paul Bolle

(Chances are that by the end of this week everybody is so tired of
messages like this that people actually check this stuff before
submitting, and there's no need to review this anymore for the rest of
this year. That would be mission accomplished, I guess.)

^ permalink raw reply

* Re: [PATCH v1 5/6] eeprom: qfprom: Add Qualcomm QFPROM support.
From: Srinivas Kandagatla @ 2015-03-05 10:10 UTC (permalink / raw)
  To: Paul Bolle
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard,
	Rob Herring, Pawel Moll, Kumar Gala,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Stephen Boyd,
	andrew-g2DYL2Zd6BY, Arnd Bergmann, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	Greg Kroah-Hartman
In-Reply-To: <1425549757.24292.204.camel@x220>

Thankyou for the comments,

On 05/03/15 10:02, Paul Bolle wrote:
> On Thu, 2015-03-05 at 09:46 +0000, Srinivas Kandagatla wrote:
>> diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
>> index bff8ecb..65325c7 100644
>> --- a/drivers/eeprom/Kconfig
>> +++ b/drivers/eeprom/Kconfig
>> @@ -28,4 +28,11 @@ config EEPROM_SUNXI_SID
>>   	  This driver can also be built as a module. If so, the module
>>   	  will be called sunxi_sid.
>>
>> +config QCOM_QFPROM
>> +	tristate "QCOM QFPROM Support"
>> +        depends on EEPROM
>
> Make this one tab, please.
>
>> +	select REGMAP_MMIO
>> +	help
>> +          Say y here to enable QFPROM support. The QFPROM provides access
>> +          functions for QFPROM data to rest of the drivers via eeprom interface.
>
> And this one tab and two spaces, please.
>
> All utterly trivial, of course, but I found a less trivial problem with
> this patch, so I included these two comments anyway.
>
Will fix it in next version.
>>   endif
>> diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
>> index 661422c..f99c824 100644
>> --- a/drivers/eeprom/Makefile
>> +++ b/drivers/eeprom/Makefile
>> @@ -8,3 +8,4 @@ obj-$(CONFIG_EEPROM)		+= core.o
>>
>>   # Devices
>>   obj-$(CONFIG_EEPROM_SUNXI_SID)	+= eeprom-sunxi-sid.o
>> +obj-$(CONFIG_QCOM_QFPROM)	+= qfprom.o
>> diff --git a/drivers/eeprom/qfprom.c b/drivers/eeprom/qfprom.c
>> new file mode 100644
>> index 0000000..371a8c0
>> --- /dev/null
>> +++ b/drivers/eeprom/qfprom.c
>> @@ -0,0 +1,74 @@
>> +#include <linux/device.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/eeprom-provider.h>
>
> [...]
>
>> +MODULE_LICENSE("GPL2");
>
> This will taint the kernel on module load. I guess you meant
>      MODULE_LICENSE("GPL v2");
>
> but there's no comment with some lines about the license at the top of
> this file, so I can't be sure.
>
Yes, I meant GPL v2, and will fix the license header too in next version.

--srini

>
> Paul Bolle
>
> (Chances are that by the end of this week everybody is so tired of
> messages like this that people actually check this stuff before
> submitting, and there's no need to review this anymore for the rest of
> this year. That would be mission accomplished, I guess.)
>

^ permalink raw reply

* Re: [PATCH v1 4/6] eeprom: sunxi: Move the SID driver to the eeprom framework
From: Paul Bolle @ 2015-03-05 10:15 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard,
	Rob Herring, Pawel Moll, Kumar Gala,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Stephen Boyd,
	andrew-g2DYL2Zd6BY, Arnd Bergmann, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	Greg Kroah-Hartman
In-Reply-To: <1425548775-13067-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Thu, 2015-03-05 at 09:46 +0000, Srinivas Kandagatla wrote:
> --- a/drivers/eeprom/Kconfig
> +++ b/drivers/eeprom/Kconfig
> @@ -17,4 +17,15 @@ config EEPROM_DEBUG
>  	help
>  	  Say yes here to enable debugging support.
>  
> +config EEPROM_SUNXI_SID
> +	depends on ARCH_SUNXI
> +	tristate "Allwinner SoCs SID support"

Nit: make this the first option, please.

> +	select REGMAP_MMIO
> +	help
> +	  This is a driver for the 'security ID' available on various Allwinner
> +	  devices.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called sunxi_sid.

I think it will be called "eeprom-sunxi-sid". Am I right?

(There must be thousands of lines like this in the various Kconfig
files. Has anyone ever tried to autogenerate this info for the make
*config tools? Probably rather complicated...)

> +
>  endif
> diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
> index e130079..661422c 100644
> --- a/drivers/eeprom/Makefile
> +++ b/drivers/eeprom/Makefile
> @@ -7,3 +7,4 @@ ccflags-$(CONFIG_EEPROM_DEBUG) += -DDEBUG
>  obj-$(CONFIG_EEPROM)		+= core.o
>  
>  # Devices
> +obj-$(CONFIG_EEPROM_SUNXI_SID)	+= eeprom-sunxi-sid.o
> diff --git a/drivers/eeprom/eeprom-sunxi-sid.c b/drivers/eeprom/eeprom-sunxi-sid.c
> new file mode 100644
> index 0000000..eb32afb
> --- /dev/null
> +++ b/drivers/eeprom/eeprom-sunxi-sid.c
> @@ -0,0 +1,129 @@
> +/*
> + * Allwinner sunXi SoCs Security ID support.
> + *
> + * Copyright (c) 2013 Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>
> + * Copyright (C) 2014 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */

So the license is GPL v2.

> +MODULE_LICENSE("GPL");

Which means you probably want
    MODULE_LICENSE("GPL v2");

> --- a/drivers/misc/eeprom/sunxi_sid.c
> +++ /dev/null
> @@ -1,156 +0,0 @@
> -/*
> - * Copyright (c) 2013 Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>
> - * http://www.linux-sunxi.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.

But the previous driver was GPL v2 or later.

> -MODULE_LICENSE("GPL");

And this matches that.

Was it intended to re-license this, or is the code basically new? (I
haven't compared the before and after code, to be honest.)


Paul Bolle

^ 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