Re: [PATCH 0/2] FTDI CBUS GPIO support
Am 21.06.2015 um 00:12 schrieb Stefan Agner: There are three GPIO modes supported by FTDI devices: 1. Asynchronous Bit Bang Mode (used in Sacha's patch) 2. Synchronous Bit Bang Mode (used in Philipp's patch) 3. CBUS Bit Bang Mode (used in Philipp's patch and this patchset) 1. No idea, could be 2. wrong 3. wrong This is more complicated as I remember. The chip (I speak of FT232H here, because it's "my" chip) has quite a lot of options. Reference: http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf I did not use a bit bang mode. My patches were about synchronous FIFO mode and CBUS control. I'll try to explain. There are eight data lines called ADBUS[7:0] and ten "other" lines called ACBUS[9:0]. When the chip is configured (EEPROM!) for UART mode (default), the RX, TX and modem status lines are assigned to ADBUS[7:0]. ACBUS7 can be used as an USB voltage detect input (and for nothing else in any case as it looks). The other ACBUS lines can be configured for several tasks like TXLED, RXLED, SLEEP, clock output etc. The ACBUS5, ACBUS6, ACBUS8 and ACBUS9 can also individually be configured to I/O mode which the datasheet calls "ACBUS BitBang". These up to four (depending on user's choice) GPIO lines can be accessed from the host. They're usable for extra control to attached hardware. Controlling these CBUS lines was the intent of my CBUS patch. My usblink board (FT232H plus FPGA etc.) makes use of the FT232H's asynchronous and synchronous FIFO modes. The asynchronous FIFO mode has to be selected by EEPROM settings. This works out of the box with the ftdi_sio driver. The driver doesn't notice anything. Just works. Baud rate settings etc. become meaningless, of course :-) If you want to get the full USB 2.0 speed you have to use the synchronous FIFO mode. For this to work the chip has to be eeprom configured to asynchronous FIFO mode and then the driver has to select synchronous FIFO mode. This was subject of my other patch. The chip has some other more or less cool modes but I have no idea if and how they work with the ftdi_sio driver. Two of them are named asynchronous and synchronous BitBang mode. Conclusion: The FTDI chip has different *modes* of operation which can be selected by eeprom and/or software. The mode determines the use of the *ADBUS* and some ACBUS pins. Two of modes are called bit bang modes. ACBUS bit bang is an additional functionality which is *not to be confused* with the chip's operation mode! The confusion comes from things like FTDI_SIO_SET_BITBANG_REQUEST to do anything... I have not forgotten about the comments on my patches a year ago. I just did not yet find the time to do add that GPIO stuff. Two interfaces have to be added to the driver: - One for setting the mode (here: switch to synchronous FIFO) I suggest adding a sysfs property here. - One for the four CBUS bits I *still* suggest adding a sysfs property *and* adding GPIO support as well. I will most probably get back to the stuff in July. Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V5 2/3] mm/memblock: Add support for excluded memory areas
Hi again, I'd like to remind that the s390 development relies on this patch (and the next one, for cleanliness, of course) being added. It would be very good to see it being added to the -mm tree resp. linux-next. Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] Small fixes to memblock and nobootmem
While working on the conversion of the s390 port to use memblock and nobootmem instead of bootmem I discovered two small bugs: alloc_memory_core_early() in mm/nobootmem.c called memblock_reserve() without forwarding the return value of memblock_reserve(). free_low_memory_core() (used by free_all_bootmem) in mm/nobootmem.c already took care of releasing the memblock.reserved array in case it has been allocated using memblock itself. This behaviour was missing for memblock.memory. Cases where memblock.memory grows bigger than the initial 128 entries have been seen. So this should be supported as well. Philipp Hachtmann (2): mm, nobootmem: Add return value check in __alloc_memory_core_early() mm: free memblock.memory in free_all_bootmem include/linux/memblock.h | 1 + mm/memblock.c| 12 mm/nobootmem.c | 11 +-- 3 files changed, 22 insertions(+), 2 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] mm: free memblock.memory in free_all_bootmem
When calling free_all_bootmem() the free areas under memblock's control are released to the buddy allocator. Additionally the reserved list is freed if it was reallocated by memblock. The same should apply for the memory list. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 1 + mm/memblock.c| 12 mm/nobootmem.c | 7 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 77c60e5..d174922 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -52,6 +52,7 @@ phys_addr_t memblock_find_in_range_node(phys_addr_t start, phys_addr_t end, phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr); +phys_addr_t get_allocated_memblock_memory_regions_info(phys_addr_t *addr); void memblock_allow_resize(void); int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid); int memblock_add(phys_addr_t base, phys_addr_t size); diff --git a/mm/memblock.c b/mm/memblock.c index 53e477b..1a11d04 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -271,6 +271,18 @@ phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( memblock.reserved.max); } +phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( + phys_addr_t *addr) +{ + if (memblock.memory.regions == memblock_memory_init_regions) + return 0; + + *addr = __pa(memblock.memory.regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +} + /** * memblock_double_array - double the size of the memblock regions array * @type: memblock type of the regions array being doubled diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 3a7e14d..83f36d3 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -122,11 +122,16 @@ static unsigned long __init free_low_memory_core_early(void) for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) count += __free_memory_core(start, end); - /* free range that is used for reserved array if we allocate it */ + /* Free memblock.reserved array if it was allocated */ size = get_allocated_memblock_reserved_regions_info(&start); if (size) count += __free_memory_core(start, start + size); + /* Free memblock.memory array if it was allocated */ + size = get_allocated_memblock_memory_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); + return count; } -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] mm, nobootmem: Add return value check in __alloc_memory_core_early()
When memblock_reserve() fails because memblock.reserved.regions cannot be resized, the caller (e.g. alloc_bootmem()) is not informed of the failed allocation. Therefore alloc_bootmem() silently returns the same pointer again and again. This patch adds a check for the return value of memblock_reserve() in __alloc_memory_core(). Signed-off-by: Philipp Hachtmann --- mm/nobootmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 2c254d3..3a7e14d 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -45,7 +45,9 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align, if (!addr) return NULL; - memblock_reserve(addr, size); + if (memblock_reserve(addr, size)) + return NULL; + ptr = phys_to_virt(addr); memset(ptr, 0, size); /* -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] mm: free memblock.memory in free_all_bootmem
Am Wed, 8 Jan 2014 12:08:04 +0800 schrieb Jianguo Wu : > For some archs, like arm64, would use memblock.memory after system > booting, so we can not simply released to the buddy allocator, maybe > need !defined(CONFIG_ARCH_DISCARD_MEMBLOCK). Oh, I see. I have added some ifdefs to prevent memblock.memory from being freed when CONFIG_ARCH_DISCARD_MEMBLOCK is not set. Here is a replacement for the patch. Kind regards Philipp >From aca95bcb9d79388b68bf18e7bae4353259b6758f Mon Sep 17 00:00:00 2001 From: Philipp Hachtmann Date: Thu, 19 Dec 2013 15:53:46 +0100 Subject: [PATCH 2/2] mm: free memblock.memory in free_all_bootmem When calling free_all_bootmem() the free areas under memblock's control are released to the buddy allocator. Additionally the reserved list is freed if it was reallocated by memblock. The same should apply for the memory list. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 1 + mm/memblock.c| 16 mm/nobootmem.c | 10 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 77c60e5..d174922 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -52,6 +52,7 @@ phys_addr_t memblock_find_in_range_node(phys_addr_t start, phys_addr_t end, phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr); +phys_addr_t get_allocated_memblock_memory_regions_info(phys_addr_t *addr); void memblock_allow_resize(void); int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid); int memblock_add(phys_addr_t base, phys_addr_t size); diff --git a/mm/memblock.c b/mm/memblock.c index 53e477b..a78b2e9 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -271,6 +271,22 @@ phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( memblock.reserved.max); } +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + +phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( + phys_addr_t *addr) +{ + if (memblock.memory.regions == memblock_memory_init_regions) + return 0; + + *addr = __pa(memblock.memory.regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +} + +#endif + /** * memblock_double_array - double the size of the memblock regions array * @type: memblock type of the regions array being doubled diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 3a7e14d..63ff3f6 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -122,11 +122,19 @@ static unsigned long __init free_low_memory_core_early(void) for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) count += __free_memory_core(start, end); - /* free range that is used for reserved array if we allocate it */ + /* Free memblock.reserved array if it was allocated */ size = get_allocated_memblock_reserved_regions_info(&start); if (size) count += __free_memory_core(start, start + size); +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + + /* Free memblock.memory array if it was allocated */ + size = get_allocated_memblock_memory_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); +#endif + return count; } -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] mm/memblock: Excluded memory, free_all_bootmem
These two patches fit (only) on top of linux-next! The first patch changes back the behavior of free_all_bootmem() to a more generic way: With CONFIG_DISCARD_MEMBLOCK memblock.memory and memblock.reserved will be freed (if allocated, of course). Removed the debugfs dependency. Think this is cleaner. While further working on the s390 migration to memblock it is desirable to have memblock support unmapped (i.e. completely forgotten and unused) memory areas. The usual way of just forgetting about them by means of truncating the memblocks does not work for us because we still need the information about the real full memory structure at a later time. Philipp Hachtmann (2): mm/nobootmem: free_all_bootmem again mm/memblock: Add support for excluded memory areas include/linux/memblock.h | 50 ++-- mm/memblock.c| 324 +++ mm/nobootmem.c | 13 +- 3 files changed, 271 insertions(+), 116 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] mm/nobootmem: free_all_bootmem again
get_allocated_memblock_reserved_regions_info() should work if it is compiled in. Extended the ifdef around get_allocated_memblock_memory_regions_info() to include get_allocated_memblock_reserved_regions_info() as well. Similar changes in nobootmem.c/free_low_memory_core_early() where the two functions are called. Signed-off-by: Philipp Hachtmann --- mm/memblock.c | 17 ++--- mm/nobootmem.c | 4 ++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 64ed243..9c0aeef 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -266,33 +266,20 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u } } +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( phys_addr_t *addr) { if (memblock.reserved.regions == memblock_reserved_init_regions) return 0; - /* -* Don't allow nobootmem allocator to free reserved memory regions -* array if -* - CONFIG_DEBUG_FS is enabled; -* - CONFIG_ARCH_DISCARD_MEMBLOCK is not enabled; -* - reserved memory regions array have been resized during boot. -* Otherwise debug_fs entry "sys/kernel/debug/memblock/reserved" -* will show garbage instead of state of memory reservations. -*/ - if (IS_ENABLED(CONFIG_DEBUG_FS) && - !IS_ENABLED(CONFIG_ARCH_DISCARD_MEMBLOCK)) - return 0; - *addr = __pa(memblock.reserved.regions); return PAGE_ALIGN(sizeof(struct memblock_region) * memblock.reserved.max); } -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( phys_addr_t *addr) { diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 17c8902..e2906a5 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -122,13 +122,13 @@ static unsigned long __init free_low_memory_core_early(void) for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL) count += __free_memory_core(start, end); +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + /* Free memblock.reserved array if it was allocated */ size = get_allocated_memblock_reserved_regions_info(&start); if (size) count += __free_memory_core(start, start + size); -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - /* Free memblock.memory array if it was allocated */ size = get_allocated_memblock_memory_regions_info(&start); if (size) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] mm/memblock: Add support for excluded memory areas
Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 50 ++-- mm/memblock.c| 307 +-- mm/nobootmem.c | 9 ++ 3 files changed, 267 insertions(+), 99 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..2333d3f 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -113,8 +121,9 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a, + struct memblock_type *type_b, phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range - iterate through free memblock areas @@ -129,12 +138,31 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, \ + p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, p_start, \ + p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid)) +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, \ + p_start, p_end, p_nid)) +#endif -void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range_rev(u64 *idx, int nid, + struct memblock_type *type_a, + struct memblock_type *type_b, + phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range_reverse - rev-iterate through free memblock areas @@ -149,9 +177,15 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \ for (i = (u64)ULLONG_MAX, \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \ +
[PATCH V2 1/2] mm/nobootmem: free_all_bootmem again
get_allocated_memblock_reserved_regions_info() should work if it is compiled in. Extended the ifdef around get_allocated_memblock_memory_regions_info() to include get_allocated_memblock_reserved_regions_info() as well. Similar changes in nobootmem.c/free_low_memory_core_early() where the two functions are called. Signed-off-by: Philipp Hachtmann --- mm/memblock.c | 17 ++--- mm/nobootmem.c | 4 ++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 64ed243..9c0aeef 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -266,33 +266,20 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u } } +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( phys_addr_t *addr) { if (memblock.reserved.regions == memblock_reserved_init_regions) return 0; - /* -* Don't allow nobootmem allocator to free reserved memory regions -* array if -* - CONFIG_DEBUG_FS is enabled; -* - CONFIG_ARCH_DISCARD_MEMBLOCK is not enabled; -* - reserved memory regions array have been resized during boot. -* Otherwise debug_fs entry "sys/kernel/debug/memblock/reserved" -* will show garbage instead of state of memory reservations. -*/ - if (IS_ENABLED(CONFIG_DEBUG_FS) && - !IS_ENABLED(CONFIG_ARCH_DISCARD_MEMBLOCK)) - return 0; - *addr = __pa(memblock.reserved.regions); return PAGE_ALIGN(sizeof(struct memblock_region) * memblock.reserved.max); } -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( phys_addr_t *addr) { diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 17c8902..e2906a5 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -122,13 +122,13 @@ static unsigned long __init free_low_memory_core_early(void) for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL) count += __free_memory_core(start, end); +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + /* Free memblock.reserved array if it was allocated */ size = get_allocated_memblock_reserved_regions_info(&start); if (size) count += __free_memory_core(start, start + size); -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - /* Free memblock.memory array if it was allocated */ size = get_allocated_memblock_memory_regions_info(&start); if (size) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V2 2/2] mm/memblock: Add support for excluded memory areas
Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 50 +++-- mm/Kconfig | 3 + mm/memblock.c| 259 +++ mm/nobootmem.c | 9 ++ 4 files changed, 251 insertions(+), 70 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..2333d3f 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -113,8 +121,9 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a, + struct memblock_type *type_b, phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range - iterate through free memblock areas @@ -129,12 +138,31 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, \ + p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, p_start, \ + p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid)) +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, \ + p_start, p_end, p_nid)) +#endif -void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range_rev(u64 *idx, int nid, + struct memblock_type *type_a, + struct memblock_type *type_b, + phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range_reverse - rev-iterate through free memblock areas @@ -149,9 +177,15 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \ for (i = (u64)ULLONG_MAX, \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \
[PATCH V2 0/2] mm/memblock: Excluded memory, free_all_bootmem
These two patches fit (only) on top of linux-next! The first patch changes back the behavior of free_all_bootmem() to a more generic way: With CONFIG_DISCARD_MEMBLOCK memblock.memory and memblock.reserved will be freed (if allocated, of course). Removed the debugfs dependency. Think this is cleaner. While further working on the s390 migration to memblock it is desirable to have memblock support unmapped (i.e. completely forgotten and unused) memory areas. The usual way of just forgetting about them by means of truncating the memblocks does not work for us because we still need the information about the real full memory structure at a later time. Philipp Hachtmann (2): mm/nobootmem: free_all_bootmem again mm/memblock: Add support for excluded memory areas include/linux/memblock.h | 50 +++-- mm/Kconfig | 3 + mm/memblock.c| 276 ++- mm/nobootmem.c | 13 ++- 4 files changed, 255 insertions(+), 87 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V3 1/2] mm/nobootmem: free_all_bootmem again
get_allocated_memblock_reserved_regions_info() should work if it is compiled in. Extended the ifdef around get_allocated_memblock_memory_regions_info() to include get_allocated_memblock_reserved_regions_info() as well. Similar changes in nobootmem.c/free_low_memory_core_early() where the two functions are called. Signed-off-by: Philipp Hachtmann --- mm/memblock.c | 17 ++--- mm/nobootmem.c | 4 ++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 64ed243..9c0aeef 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -266,33 +266,20 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u } } +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( phys_addr_t *addr) { if (memblock.reserved.regions == memblock_reserved_init_regions) return 0; - /* -* Don't allow nobootmem allocator to free reserved memory regions -* array if -* - CONFIG_DEBUG_FS is enabled; -* - CONFIG_ARCH_DISCARD_MEMBLOCK is not enabled; -* - reserved memory regions array have been resized during boot. -* Otherwise debug_fs entry "sys/kernel/debug/memblock/reserved" -* will show garbage instead of state of memory reservations. -*/ - if (IS_ENABLED(CONFIG_DEBUG_FS) && - !IS_ENABLED(CONFIG_ARCH_DISCARD_MEMBLOCK)) - return 0; - *addr = __pa(memblock.reserved.regions); return PAGE_ALIGN(sizeof(struct memblock_region) * memblock.reserved.max); } -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( phys_addr_t *addr) { diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 17c8902..e2906a5 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -122,13 +122,13 @@ static unsigned long __init free_low_memory_core_early(void) for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL) count += __free_memory_core(start, end); +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + /* Free memblock.reserved array if it was allocated */ size = get_allocated_memblock_reserved_regions_info(&start); if (size) count += __free_memory_core(start, start + size); -#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - /* Free memblock.memory array if it was allocated */ size = get_allocated_memblock_memory_regions_info(&start); if (size) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V3 0/2] mm/memblock: Excluded memory, free_all_bootmem
These two patches fit (only) on top of linux-next! The first patch changes back the behavior of free_all_bootmem() to a more generic way: With CONFIG_DISCARD_MEMBLOCK memblock.memory and memblock.reserved will be freed (if allocated, of course). Removed the debugfs dependency. Think this is cleaner. While further working on the s390 migration to memblock it is desirable to have memblock support unmapped (i.e. completely forgotten and unused) memory areas. The usual way of just forgetting about them by means of truncating the memblocks does not work for us because we still need the information about the real full memory structure at a later time. (sorry for the two too bad versions before) Philipp Hachtmann (2): mm/nobootmem: free_all_bootmem again mm/memblock: Add support for excluded memory areas arch/s390/Kconfig| 1 + include/linux/memblock.h | 50 +++-- mm/Kconfig | 3 + mm/memblock.c| 278 ++- mm/nobootmem.c | 13 ++- 5 files changed, 258 insertions(+), 87 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V3 2/2] mm/memblock: Add support for excluded memory areas
Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- arch/s390/Kconfig| 1 + include/linux/memblock.h | 50 +++-- mm/Kconfig | 3 + mm/memblock.c| 261 --- mm/nobootmem.c | 9 ++ 5 files changed, 254 insertions(+), 70 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 4f858f7..9346e2c 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -61,6 +61,7 @@ config PCI_QUIRKS config S390 def_bool y select ARCH_DISCARD_MEMBLOCK + select ARCH_MEMBLOCK_NOMAP select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS select ARCH_HAVE_NMI_SAFE_CMPXCHG diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..2333d3f 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -113,8 +121,9 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a, + struct memblock_type *type_b, phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range - iterate through free memblock areas @@ -129,12 +138,31 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, \ + p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, p_start, \ + p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid)) +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, \ + p_start, p_end, p_nid)) +#endif -void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range_rev(u64 *idx, int nid, + struct memblock_type *type_a, + struct memblock_type *type_b, + phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range_reverse - rev-iterate through free memblock areas @@ -149,9 +177,15 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,
Re: [PATCH V3 2/2] mm/memblock: Add support for excluded memory areas
Am Mon, 13 Jan 2014 16:36:20 -0800 schrieb Andrew Morton : > Patch is big. I'll toss this in for some testing but it does look too > large and late for 3.14. How will this affect your s390 development? It is needed for s390 bootmem -> memblock transition. The s390 dump mechanisms cannot be switched to memblock (from using something s390 specific called memory_chunk) without the nomap list. I'm also working on another enhancement on s390 that will rely on a clean transition to memblock. I have written and tested the stuff on top of our local development tree. And then realised that it does not fit the linux-next tree. So I converted it to fit linux-next and posted it. Have to maintain two versions now. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V3 2/2] mm/memblock: Add support for excluded memory areas
Hello Grygorii, thank you for your comments. To clarify we have the following requirements for memblock: (1) Reserved areas can be declared before memory is added. (2) The physical memory is detected once only. (3) The free memory (i.e. not reserved) memory can be iterated to add it to the buddy allocator. (4) Memory designated to be mapped into the kernel address space can be iterated. (5) Kdump on s390 requires knowledge about the full system memory layout. The s390 kdump implementation works a bit different from the implementation on other architectures: The layout is not taken from the production system and saved for the kdump kernel. Instead the kdump kernel needs to gather information about the whole memory without respect to locked out areas (like mem= and OLDMEM etc.). Without kdump's requirement it would of course be suitable and easy just to remove memory from memblock.memory. But then this information is lost for later use by kdump. The patch does not change any behaviour of the current API - whether it is enabled or not. The current patch seems to be overly complicated. The following patch contains only the nomap functionality without any cleanup and refactoring. I will post a V4 patch set which will contain this patch. Kind regards Philipp >From eb1ad42c19c6f7bfdf3258a83dc54461c5f02d55 Mon Sep 17 00:00:00 2001 From: Philipp Hachtmann Date: Tue, 14 Jan 2014 19:49:39 +0100 Subject: [PATCH] mm/memblock: Add support for excluded memory areas Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 25 +++ mm/Kconfig | 3 + mm/memblock.c| 175 ++- mm/nobootmem.c | 9 +++ 4 files changed, 211 insertions(+), 1 deletion(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..be1c819 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -133,6 +141,23 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, i != (u64)ULLONG_MAX; \ __next_free_mem_range(&i, nid, p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ + &memblock.nomap, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ +&memblock.nomap, \ +p_start, p_end, p_nid)) + +void __next_mapped_mem_range(u64 *idx, int nid, phys_addr_t *out_start, +phys_addr_t *out_end, int *out_nid); + +#endif + void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, phys_addr_t *out_end, int *out_nid); diff --git a/mm/Kconfig b/mm/Kconfig index 2d9f150..6907654 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -137,6 +137,9 @@ config HAVE_MEMBLOCK_NODE_MAP config ARCH_DISCARD_MEMBLOCK boolean +config ARCH_MEMBLOCK_NOMAP + boolean + config NO_BOOTMEM boolean diff --git a/mm/memblock.c b/mm/memblock.c index 9c0aeef..b36f5d3 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -28,6 +28,11 @@ static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; static struct memblock_region memblock_reserved_init_regions[INIT_ME
Re: linux-next: build warning after merge of the final tree (akpm-current related)
Hi Stephen, thanks for reminding me... Am Thu, 16 Jan 2014 17:36:38 +1100 schrieb Stephen Rothwell : > mm/nobootmem.c: In function 'free_low_memory_core_early': > mm/nobootmem.c:119:26: warning: unused variable > 'size' [-Wunused-variable] > Introduced by commit dd3ff251123c ("mm/nobootmem: free_all_bootmem > again") from the akpm-current tree. Will send a new version of the patch today. Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V4 0/2] mm/memblock: Excluded memory
Here is a new version of the memblock.nomap patch. This time without the first patch (that has already been taken by akpm). The second patch is now split into the functional part (Add support...) and the cleanup/refactoring part. This has been done for clarity as announced before. Philipp Hachtmann (2): mm/memblock: Add support for excluded memory areas mm/memblock: Cleanup and refactoring after addition of nomap include/linux/memblock.h | 57 +--- mm/Kconfig | 3 + mm/memblock.c| 233 +++ mm/nobootmem.c | 9 ++ 4 files changed, 231 insertions(+), 71 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V4 2/2] mm/memblock: Cleanup and refactoring after addition of nomap
Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 50 ++- mm/memblock.c| 214 +-- 2 files changed, 107 insertions(+), 157 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index be1c819..ec2da3b 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -121,8 +121,9 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a, + struct memblock_type *type_b, phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range - iterate through free memblock areas @@ -137,29 +138,31 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, p_start, \ + p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid)) - +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, \ + p_start, p_end, p_nid)) #ifdef CONFIG_ARCH_MEMBLOCK_NOMAP #define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_mapped_mem_range(&i, nid, &memblock.memory, \ +__next_mem_range(&i, nid, &memblock.memory,\ &memblock.nomap, p_start, \ p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_mapped_mem_range(&i, nid, &memblock.memory, \ -&memblock.nomap, \ -p_start, p_end, p_nid)) - -void __next_mapped_mem_range(u64 *idx, int nid, phys_addr_t *out_start, -phys_addr_t *out_end, int *out_nid); - +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, \ + p_start, p_end, p_nid)) #endif -void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range_rev(u64 *idx, int nid, + struct memblock_type *type_a, + struct memblock_type *type_b, + phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range_reverse - rev-iterate through free memblock areas @@ -174,9 +177,15 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \ for (i = (u64)ULLONG_MAX, \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \ + p_start, p_end, p_nid); \ i != (u64)ULLONG_MAX; \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \ + p_start, p_end, p_nid)) static inline void memblock_set_region_flags(struct memblock_region *r, unsigned long flags) @@ -321,12 +330,11 @@ static inline unsigned long memblock_region_reserved_end_pfn(cons
[PATCH V4 1/2] mm/memblock: Add support for excluded memory areas
Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 25 +++ mm/Kconfig | 3 + mm/memblock.c| 175 ++- mm/nobootmem.c | 9 +++ 4 files changed, 211 insertions(+), 1 deletion(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..be1c819 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -133,6 +141,23 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, i != (u64)ULLONG_MAX; \ __next_free_mem_range(&i, nid, p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ + &memblock.nomap, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ +&memblock.nomap, \ +p_start, p_end, p_nid)) + +void __next_mapped_mem_range(u64 *idx, int nid, phys_addr_t *out_start, +phys_addr_t *out_end, int *out_nid); + +#endif + void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, phys_addr_t *out_end, int *out_nid); diff --git a/mm/Kconfig b/mm/Kconfig index 2d9f150..6907654 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -137,6 +137,9 @@ config HAVE_MEMBLOCK_NODE_MAP config ARCH_DISCARD_MEMBLOCK boolean +config ARCH_MEMBLOCK_NOMAP + boolean + config NO_BOOTMEM boolean diff --git a/mm/memblock.c b/mm/memblock.c index 9c0aeef..b36f5d3 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -28,6 +28,11 @@ static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +static struct memblock_region +memblock_nomap_init_regions[INIT_MEMBLOCK_NOMAP_REGIONS] __initdata_memblock; +#endif + struct memblock memblock __initdata_memblock = { .memory.regions = memblock_memory_init_regions, .memory.cnt = 1,/* empty dummy entry */ @@ -37,6 +42,11 @@ struct memblock memblock __initdata_memblock = { .reserved.cnt = 1,/* empty dummy entry */ .reserved.max = INIT_MEMBLOCK_REGIONS, +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + .nomap.regions = memblock_nomap_init_regions, + .nomap.cnt = 1, /* empty dummy entry */ + .nomap.max = INIT_MEMBLOCK_NOMAP_REGIONS, +#endif .bottom_up = false, .current_limit = MEMBLOCK_ALLOC_ANYWHERE, }; @@ -292,6 +302,20 @@ phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( memblock.memory.max); } +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +phys_addr_t __init_memblock get_allocated_memblock_nomap_regions_info( + phys_addr_t *addr) +{ + if (memblock.memory.regions == memblock_memory_init_regions) + return 0; + + *addr = __pa(memblock.memory.regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +} + +#endif /* CONFIG_ARCH_MEMB
[PATCH] mm/nobootmem: Fix unused variable
This fixes an unused variable warning in nobootmem.c Signed-off-by: Philipp Hachtmann --- mm/nobootmem.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mm/nobootmem.c b/mm/nobootmem.c index e2906a5..12cbb04 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -116,9 +116,13 @@ static unsigned long __init __free_memory_core(phys_addr_t start, static unsigned long __init free_low_memory_core_early(void) { unsigned long count = 0; - phys_addr_t start, end, size; + phys_addr_t start, end; u64 i; +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + phys_addr_t size; +#endif + for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL) count += __free_memory_core(start, end); -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] mm/nobootmem: Fix unused variable
Hi Robin, > Maybe you are working off a different repo than > Linus' latest? Your line 116 is my 114. Maybe the message needs to > be a bit more descriptive Ah, yes. This fits Andrew's linux-next. Regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V4 0/2] mm/memblock: Excluded memory
Patch fits Andrew's linux-next. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] mm/nobootmem: Fix unused variable
> I would think you would be better off making > get_allocated_memblock_reserved_regions_info() and > get_allocated_memblock_memory_regions_info be static inline functions > when #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK. Possible, of course. But the size variable has still to be #ifdef'd. And that's what the patch is about. It's just an addition to another patch. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH V3 2/2] mm/memblock: Add support for excluded memory areas
Am Fri, 17 Jan 2014 18:08:13 + schrieb "Strashko, Grygorii" : Hello Grygorii, > > The current patch seems to be overly complicated. > > The following patch contains only the nomap functionality without > > any cleanup and refactoring. I will post a V4 patch set which will > > contain this patch. please see the V4 patch set I've sent to the list. There you will clearly see that nothing is changed. No API is broken by the patch. The patch only adds functionality. Everything that worked before keeps working as before without any changes needed in any arch's code. Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] mm/nobootmem: Fix unused variable
Am Fri, 17 Jan 2014 13:38:31 -0800 schrieb Andrew Morton : > Yes, that is a bit of an eyesore. We often approach the problem this > way, which is nicer: > [ ... ] > #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK > { > phys_addr_t size; > > [ ... ] > } > #endif This is a very nice idea! I have updated my fix. This leads to a V5 patch series (which I will post now) because the following to patches had to be slightly updated to fit on top of the fix. Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 1/3] mm/nobootmem: Fix unused variable
This fixes an unused variable warning in nobootmem.c Signed-off-by: Philipp Hachtmann --- mm/nobootmem.c | 28 +--- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/mm/nobootmem.c b/mm/nobootmem.c index e2906a5..0215c77 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -116,23 +116,29 @@ static unsigned long __init __free_memory_core(phys_addr_t start, static unsigned long __init free_low_memory_core_early(void) { unsigned long count = 0; - phys_addr_t start, end, size; + phys_addr_t start, end; u64 i; +#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + phys_addr_t size; +#endif + for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL) count += __free_memory_core(start, end); #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK - - /* Free memblock.reserved array if it was allocated */ - size = get_allocated_memblock_reserved_regions_info(&start); - if (size) - count += __free_memory_core(start, start + size); - - /* Free memblock.memory array if it was allocated */ - size = get_allocated_memblock_memory_regions_info(&start); - if (size) - count += __free_memory_core(start, start + size); + { + phys_addr_t size; + /* Free memblock.reserved array if it was allocated */ + size = get_allocated_memblock_reserved_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); + + /* Free memblock.memory array if it was allocated */ + size = get_allocated_memblock_memory_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); + } #endif return count; -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 0/3] mm/memblock: Excluded memory
This all fits linux-next. The first patch is a fix (not a replacement) to a patch that has already been put into linux-next. The original patch generates a warning for an unused variable in case that CONFIG_ARCH_DISCARD_MEMBLOCK is not set. It's now made the way Andrew suggested. The second patch adds support for exluded memory region handling in memblock. This is needed by the current s390 development in conjunction with kdump. The patch is straightforward and adds some redundancy. This has been done to clarify that this patch does not intend to change any of the current memblock API's behaviour. The third patch does some cleanup and refactoring to memblock. It removes the redundancies introduced by the patch before. It also is not intended to change or break any behaviour or API of memblock. Philipp Hachtmann (3): mm/nobootmem: Fix unused variable mm/memblock: Add support for excluded memory areas mm/memblock: Cleanup and refactoring after addition of nomap include/linux/memblock.h | 57 +--- mm/Kconfig | 3 + mm/memblock.c| 233 +++ mm/nobootmem.c | 30 -- 4 files changed, 243 insertions(+), 80 deletions(-) -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 3/3] mm/memblock: Cleanup and refactoring after addition of nomap
Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 50 ++- mm/memblock.c| 214 +-- 2 files changed, 107 insertions(+), 157 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index be1c819..ec2da3b 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -121,8 +121,9 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a, + struct memblock_type *type_b, phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range - iterate through free memblock areas @@ -137,29 +138,31 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, p_start, \ + p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_free_mem_range(&i, nid, p_start, p_end, p_nid)) - +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.reserved, \ + p_start, p_end, p_nid)) #ifdef CONFIG_ARCH_MEMBLOCK_NOMAP #define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ for (i = 0, \ -__next_mapped_mem_range(&i, nid, &memblock.memory, \ +__next_mem_range(&i, nid, &memblock.memory,\ &memblock.nomap, p_start, \ p_end, p_nid);\ i != (u64)ULLONG_MAX; \ -__next_mapped_mem_range(&i, nid, &memblock.memory, \ -&memblock.nomap, \ -p_start, p_end, p_nid)) - -void __next_mapped_mem_range(u64 *idx, int nid, phys_addr_t *out_start, -phys_addr_t *out_end, int *out_nid); - +__next_mem_range(&i, nid, &memblock.memory,\ + &memblock.nomap, \ + p_start, p_end, p_nid)) #endif -void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, - phys_addr_t *out_end, int *out_nid); +void __next_mem_range_rev(u64 *idx, int nid, + struct memblock_type *type_a, + struct memblock_type *type_b, + phys_addr_t *out_start, + phys_addr_t *out_end, int *out_nid); /** * for_each_free_mem_range_reverse - rev-iterate through free memblock areas @@ -174,9 +177,15 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, */ #define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \ for (i = (u64)ULLONG_MAX, \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \ +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \ + p_start, p_end, p_nid); \ i != (u64)ULLONG_MAX; \ -__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) +__next_mem_range_rev(&i, nid, \ + &memblock.memory, \ + &memblock.reserved, \ + p_start, p_end, p_nid)) static inline void memblock_set_region_flags(struct memblock_region *r, unsigned long flags) @@ -321,12 +330,11 @@ static inline unsigned long memblock_region_reserved_end_pfn(cons
[PATCH V5 2/3] mm/memblock: Add support for excluded memory areas
Add a new memory state "nomap" to memblock. This can be used to truncate the usable memory in the system without forgetting about what is really installed. Signed-off-by: Philipp Hachtmann --- include/linux/memblock.h | 25 +++ mm/Kconfig | 3 + mm/memblock.c| 175 ++- mm/nobootmem.c | 8 ++- 4 files changed, 209 insertions(+), 2 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 1ef6636..be1c819 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -18,6 +18,7 @@ #include #define INIT_MEMBLOCK_REGIONS 128 +#define INIT_MEMBLOCK_NOMAP_REGIONS 4 /* Definition of memblock flags. */ #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ @@ -43,6 +44,9 @@ struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + struct memblock_type nomap; +#endif }; extern struct memblock memblock; @@ -68,6 +72,10 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +int memblock_nomap(phys_addr_t base, phys_addr_t size); +int memblock_remap(phys_addr_t base, phys_addr_t size); +#endif void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); @@ -133,6 +141,23 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, i != (u64)ULLONG_MAX; \ __next_free_mem_range(&i, nid, p_start, p_end, p_nid)) + +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +#define for_each_mapped_mem_range(i, nid, p_start, p_end, p_nid) \ + for (i = 0, \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ + &memblock.nomap, p_start, \ + p_end, p_nid);\ +i != (u64)ULLONG_MAX; \ +__next_mapped_mem_range(&i, nid, &memblock.memory, \ +&memblock.nomap, \ +p_start, p_end, p_nid)) + +void __next_mapped_mem_range(u64 *idx, int nid, phys_addr_t *out_start, +phys_addr_t *out_end, int *out_nid); + +#endif + void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, phys_addr_t *out_end, int *out_nid); diff --git a/mm/Kconfig b/mm/Kconfig index 2d9f150..6907654 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -137,6 +137,9 @@ config HAVE_MEMBLOCK_NODE_MAP config ARCH_DISCARD_MEMBLOCK boolean +config ARCH_MEMBLOCK_NOMAP + boolean + config NO_BOOTMEM boolean diff --git a/mm/memblock.c b/mm/memblock.c index 9c0aeef..b36f5d3 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -28,6 +28,11 @@ static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +static struct memblock_region +memblock_nomap_init_regions[INIT_MEMBLOCK_NOMAP_REGIONS] __initdata_memblock; +#endif + struct memblock memblock __initdata_memblock = { .memory.regions = memblock_memory_init_regions, .memory.cnt = 1,/* empty dummy entry */ @@ -37,6 +42,11 @@ struct memblock memblock __initdata_memblock = { .reserved.cnt = 1,/* empty dummy entry */ .reserved.max = INIT_MEMBLOCK_REGIONS, +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP + .nomap.regions = memblock_nomap_init_regions, + .nomap.cnt = 1, /* empty dummy entry */ + .nomap.max = INIT_MEMBLOCK_NOMAP_REGIONS, +#endif .bottom_up = false, .current_limit = MEMBLOCK_ALLOC_ANYWHERE, }; @@ -292,6 +302,20 @@ phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( memblock.memory.max); } +#ifdef CONFIG_ARCH_MEMBLOCK_NOMAP +phys_addr_t __init_memblock get_allocated_memblock_nomap_regions_info( + phys_addr_t *addr) +{ + if (memblock.memory.regions == memblock_memory_init_regions) + return 0; + + *addr = __pa(memblock.memory.regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +} + +#endif /* CONFIG_ARCH_MEMB
Re: [PATCH V5 1/3] mm/nobootmem: Fix unused variable
Am Mon, 20 Jan 2014 22:16:33 -0800 (PST) schrieb David Rientjes : > Not sure why you don't just do a one line patch: > > - phys_addr_t size; > + phys_addr_t size __maybe_unused; > to fix it. Just because I did not know that __maybe_unused thing. Discussion of this fix seems to be obsolete because Andrew already took the patch int the form he suggested: One #ifdef in the function with a basic block declaring size once inside. Regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] usb/ftdi_sio: Add support for setting CBUS pins on FT232H
This patch adds a sysfs attribute "cbus" which allows to set the four CBUS pins on the FT232H. CBUS support could probably extended to all supporting FTDI chips. Signed-off-by: Philipp Hachtmann --- drivers/usb/serial/ftdi_sio.c | 66 ++- drivers/usb/serial/ftdi_sio.h | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index cacba4a..c84e27c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1354,9 +1354,39 @@ static int set_syncmode(struct usb_serial_port *port, int enable) urb_value, priv->interface, NULL, 0, WDR_SHORT_TIMEOUT); +} + +static int set_cbus(struct usb_serial_port *port, u8 data) +{ + struct ftdi_private *priv = usb_get_serial_port_data(port); + + __u16 urb_value = 0; + int rv = 0; + + urb_value = FTDI_BITMODE_CBUS << 8 | data; + + rv = usb_control_msg(port->serial->dev, +usb_sndctrlpipe(port->serial->dev, 0), +FTDI_SIO_SET_BITBANG_REQUEST, +FTDI_SIO_SET_BITBANG_REQUEST_TYPE, +urb_value, priv->interface, +NULL, 0, WDR_SHORT_TIMEOUT); + + if (rv) + return rv; + if (priv->syncmode) { + priv->syncmode = 0; + rv = set_syncmode(port, 1); + } + return rv; } +static int get_cbus(struct usb_serial_port *port) +{ + return -EIO; +} + static int write_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1684,6 +1714,34 @@ static ssize_t syncmode_store(struct device *dev, } static DEVICE_ATTR_RW(syncmode); +static ssize_t cbus_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int retval; + struct usb_serial_port *port = to_usb_serial_port(dev); + retval = get_cbus(port); + if (retval < 0) + return retval; + return sprintf(buf, "%#-x\n", get_cbus(port)); +} + +static ssize_t cbus_store(struct device *dev, + struct device_attribute *attr, + const char *valbuf, size_t count) +{ + unsigned long value; + struct usb_serial_port *port = to_usb_serial_port(dev); + int retval = kstrtoul(valbuf, 0, &value); + + if (retval) + return -EINVAL; + retval = set_cbus(port, value); + if (retval < 0) + return -EIO; + return count; +} +static DEVICE_ATTR_RW(cbus); + /* Write an event character directly to the FTDI register. The ASCII value is in the low 8 bits, with the enable bit in the 9th bit. */ static ssize_t store_event_char(struct device *dev, @@ -1736,6 +1794,10 @@ static int create_sysfs_attrs(struct usb_serial_port *port) } if ((!retval) && priv->chip_type == FT232H) { retval = device_create_file(&port->dev, + &dev_attr_cbus); + if (retval) + return retval; + retval = device_create_file(&port->dev, &dev_attr_syncmode); } return retval; @@ -1758,8 +1820,10 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) device_remove_file(&port->dev, &dev_attr_latency_timer); } } - if (priv->chip_type == FT232H) + if (priv->chip_type == FT232H) { device_remove_file(&port->dev, &dev_attr_syncmode); + device_remove_file(&port->dev, &dev_attr_cbus); + } } /* diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 04a29f8..f9de34c 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -357,6 +357,7 @@ enum ftdi_sio_baudrate { #define FTDI_SIO_SET_BITBANG_REQUEST_TYPE 0x40 #define FTDI_BITMODE_RESET 0x00 /* Switch back to normal operation */ +#define FTDI_BITMODE_CBUS 0x20 /* Configure CBUS pins */ #define FTDI_BITMODE_SYNCFIFO 0x40 /* Switch to syncronous FIFO mode */ /* -- 2.0.0.rc2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] usb/ftdi_sio: Add synchronous FIFO mode support for FT232H
This patch adds support for the synchronous FIFO mode of the FT232H serial converter chip. This might also be extended to be usable with other FTDI chips. Signed-off-by: Philipp Hachtmann --- drivers/usb/serial/ftdi_sio.c | 65 +-- drivers/usb/serial/ftdi_sio.h | 15 ++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7c6e1de..cacba4a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -73,7 +73,7 @@ struct ftdi_private { this value */ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ - + int syncmode; /* FIFO device in synchronous 245 mode */ unsigned int latency; /* latency setting in use */ unsigned short max_packet_size; struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */ @@ -1327,6 +1327,36 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) return rv; } +static int set_syncmode(struct usb_serial_port *port, int enable) +{ + struct ftdi_private *priv = usb_get_serial_port_data(port); + + __u16 urb_value = 0; + int rv = 0; + + enable = enable ? 1 : 0; + if (enable == priv->syncmode) + return 0; + + priv->syncmode = enable; + + /* FTDI seems to say that the urb_value should be or'ed with 0xff. But +* when done this way the port gets quite slow. 0x00 seems to work much +* better. +*/ + if (enable) + urb_value = FTDI_BITMODE_SYNCFIFO << 8 | 0x00; + + rv = usb_control_msg(port->serial->dev, +usb_sndctrlpipe(port->serial->dev, 0), +FTDI_SIO_SET_BITBANG_REQUEST, +FTDI_SIO_SET_BITBANG_REQUEST_TYPE, +urb_value, priv->interface, +NULL, 0, WDR_SHORT_TIMEOUT); + + return rv; +} + static int write_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1628,6 +1658,32 @@ static ssize_t latency_timer_store(struct device *dev, } static DEVICE_ATTR_RW(latency_timer); +static ssize_t syncmode_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct usb_serial_port *port = to_usb_serial_port(dev); + struct ftdi_private *priv = usb_get_serial_port_data(port); + return sprintf(buf, "%i\n", priv->syncmode); +} + +static ssize_t syncmode_store(struct device *dev, + struct device_attribute *attr, + const char *valbuf, size_t count) +{ + unsigned long value; + int rv; + struct usb_serial_port *port = to_usb_serial_port(dev); + int ret = kstrtoul(valbuf, 0, &value); + if (ret) + return -EINVAL; + + rv = set_syncmode(port, value); + if (rv < 0) + return -EIO; + return count; +} +static DEVICE_ATTR_RW(syncmode); + /* Write an event character directly to the FTDI register. The ASCII value is in the low 8 bits, with the enable bit in the 9th bit. */ static ssize_t store_event_char(struct device *dev, @@ -1678,6 +1734,10 @@ static int create_sysfs_attrs(struct usb_serial_port *port) &dev_attr_latency_timer); } } + if ((!retval) && priv->chip_type == FT232H) { + retval = device_create_file(&port->dev, + &dev_attr_syncmode); + } return retval; } @@ -1698,7 +1758,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) device_remove_file(&port->dev, &dev_attr_latency_timer); } } - + if (priv->chip_type == FT232H) + device_remove_file(&port->dev, &dev_attr_syncmode); } /* diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index ed58c6f..04a29f8 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -35,6 +35,7 @@ #define FTDI_SIO_SET_ERROR_CHAR7 /* Set the error character */ #define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ #define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */ +#define FTDI_SIO_SET_BITBANG11 /* Set the bitbang mode */ /* Interface indices for FT2232, FT2232H and FT4232H devices */ #define INTERFACE_A1 @@ -345,6 +346,20 @@ enum ftdi_sio_baudrate { */ /* + * FTDI_SIO_SET_BITBANG + * + * Set the chip's bitbang mode.
[PATCH 0/2] Add synchronous FIFO and CBUS support for FT232H
Hi folks, I am currently developing hardware around the FTDI FT232H chip. The chip can be programmed into asynchronous FIFO mode by EEPROM settings. Using it with ftdi_sio in asynchronous mode works out of the box. 1. Synchronous FIFO mode The even more wonderful synchronous FIFO mode has to be enabled in software. I first tried to use libftdi which worked in *some way*. But I think having support for the synchronous FIFO mode in the ftdi_sio driver would be very nice. So I took some inspiration from libftdi and prepared a patch which adds the support to the driver. Only for FT232H. The patch adds a sysfs attribute "syncmode" which can be set and reset by the user. Currently only exactly the FT232H is supported. But I know that there are more FTDI chips (which ones? how?) which also support the sync FIFO mode. The patch won't change any behaviour unless a) you have an FT232H connected AND b) you use the syncmode attribute. 2. CBUS bitbang support === The FT232H also supports software control of four CBUS lines. In my application I use two of them for signalling purposes. The CBUS patch adds a sysfs attribute which allows to set the CBUS mask and pins like libftdi does it. The attribute is read/write but the read function is currently just a stub which returns -EIO. 3. The buffer thing === With the sync mode patch I get transfer rates about 5 to 8 MB/sec in each direction and simultaneously. That's not that much. FTDI says (in an application note) that one should increase send and receive buffer sizes. I don't know too much about USB and even less about the usb-serial stuff. Then I made this experiment: diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3eabacf..de57931 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1002,8 +1002,10 @@ static struct usb_serial_driver ftdi_sio_device = { .description = "FTDI USB Serial Device", .id_table = id_table_combined, .num_ports =1, - .bulk_in_size = 512, - .bulk_out_size =256, + // .bulk_in_size = 512, + // .bulk_out_size =256, + .bulk_in_size = 48*1024, + .bulk_out_size =48*1024, .probe =ftdi_sio_probe, .port_probe = ftdi_sio_port_probe, .port_remove = ftdi_sio_port_remove, @@ -1326,0 +1328,0 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) With that rude hack I get transfer rates of at least 15 MB/s into each direction simultaneously and approx. 30MB/sec in one direction only. The usb_serial_driver structure is a static global thing for all FTDI chips. I *know* that the above diff is absolutely impossible to apply. It was just an experiment. I just don't know how to get this third thing right. So I would appreciate any support getting this right. Kind regards Philipp Philipp Hachtmann (2): usb/ftdi_sio: Add synchronous FIFO mode support for FT232H usb/ftdi_sio: Add support for setting CBUS pins on FT232H drivers/usb/serial/ftdi_sio.c | 129 +- drivers/usb/serial/ftdi_sio.h | 16 ++ 2 files changed, 143 insertions(+), 2 deletions(-) -- 2.0.0.rc2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] usb/ftdi_sio: Add support for setting CBUS pins on FT232H
On 01.06.2014 01:31, Philipp Hachtmann wrote: This patch adds a sysfs attribute "cbus" which allows to set the four CBUS pins on the FT232H. The patch contains a *small* error that happened when splitting up my modifications. Next series will contain the clean variant. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] usb/ftdi_sio: Add support for setting CBUS pins on FT232H
On 01.06.2014 02:00, Peter Stuge wrote: Philipp Hachtmann wrote: This patch adds a sysfs attribute "cbus" which allows to set the four CBUS pins on the FT232H. I think this should be implemented with the gpio subsystem instead. The GPIO subsystem seems to be made for GPIO pins connected directly to the computer. The Beaglebone with its AM335x SoC seems to be a good example of a computer with many GPIOs in the sense of the GPIO subsystem. And the GPIO pins have fixed unique numbers. No, I don't think that the GPIO subsystem has anything to do with the additional pins on some USB device. Please correct me if I'm completely wrong. Kind regards, Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] usb/ftdi_sio: Add support for setting CBUS pins on FT232H
On 01.06.2014 04:31, Greg KH wrote: As they are GPIO pins on this device, it should be the subsystem that controls it. That way, userspace programs that are used to talk to a GPIO device will "just work", and not have to be customized just for this specific device and sysfs file. So please use the GPIO subsystem instead of creating your own interface. Yes but... I should have avoided the term "GPIO". The FT232H (and other chips of the family) are communication controller ICs that support several operation modes. The usb-serial driver partially supports the chips' functionalities by supplying a tty device to the system. At least the FT232H has something called CBUS: Four (!) bits of GPIO that *might* be available depending on the device's configuration stored in an EEPROM attached to the chip. For example if the chip is in sync FIFO mode, only two of those bits reach the chip's surface. I'll try to discuss two use cases: 1. Someone builds hardware with an FT chip and some general functionality attached to the four usable CBUS lines, totally unrelated to the chip's FIFO/UART etc. functionality. In that case I would strongly recommend to register the CBUS stuff with the GPIO subsystem. The user then could - as you noted - run any program used to deal with official GPIO pins on top of the four lines. But I think that this use case is one of the less likely ones. 2. Someone builds hardware which uses some CBUS pins to control external circuitry that also uses the UART/FIFO interface. Both with tight functional integration. The CBUS pins become something in the rank of modem status lines. An application that uses the port also wants to easily access the CBUS pins. And it really knows what it does because it knows what it is doing. From my point of view this is the more common use case. Consequently the best way to cover the CBUS pins would be via the device's ioctls. But as the device is driven by common tty and usb-serial code which handles the ioctls I currently see how to achieve that without breaking a lot. The second best way I see is adding a property to sysfs. This would already help a lot. A program knowing about the hardware then *can* sanely play with the CBUS. Adding the functionality to sysfs should not interfere with a possible provision of an "official" GPIO device (struct gpio_chip). For me personally it's most important to get access to CBUS in any way where the relation of the tty and the CBUS is *not* lost. I see no point in exposing the CBUS to any userspace application that thinks it can play blinkenlights on them. But I also see no problem if someone wants the possibility and adds general GPIO support. The patch will provide a stable base to do so. So please consider the patches as a starting point. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] usb/ftdi_sio: Add support for setting CBUS pins on FT232H
On 02.06.2014 03:38, Greg KH wrote: >> Yes but... I should have avoided the term "GPIO".> No, you used the right term :) Sorry for using the right term :) > No, I am not going to add custom ioctls to a single driver for this. I did neither request nor expect that - did it sound that way? > It would not be lost at all, you can see that relationship in sysfs > between the gpio device and the tty device, they are both attached to > the same "parent" usb interface. Ok, I understand. This is a real argument for the GPIO stuff. I'm just beginning to understand that using the GPIO stuff will make everyone happy. > This comes up every 6 months or so, you aren't the first to ask for > custom ioctls / sysfs files for this chip. But no one seems to want to > to do the work to make it a proper gpio device, which is sad :( Ok, ok. I will do it but it will take some time. I will resend my two patches then. Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] USB: ftdi_sio: add GPIO support
Hi, Would this patch interfere with adding support for using the CBUS pins as GPIOs while operating in normal UART mode? Most interesting question! Care was taken to prevent using GPIOs if the serial device is in use and vice versa. What about CBUS GPIO support? Ok, so we're not extending the serial driver with support for controlling some unused pins (e.g. CBUS) but rather implementing support for a mutually exclusive mode. For bitbang mode (on the data lines) - yes. But for bitbang on CBUS - no. I have sent a proposal a few weeks ago but Greg did not like special sysfs stuff :-P He asked me to use the GPIO subsystem for the CBUS pins. I am out of time until july. But I still want and need CBUS support in parallel with serial/FIFO operation. Regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] USB: symbolserial: Fix OOPS (regression) and data length
I bought a Symbol DS3508 2D imager barcode scanner, configured it to behave as "simple COM port", and my machine OOPSed immediately. The result are the two attached patches. The first one is actually needed to get the whole thing again without that nasty NULL pointer dereference. The second patch makes the driver exclude useless zero bytes from the payload data. I assume this could lead to discussions because I found (and removed) a comment that says that the driver will send all data from the urb buffer to the tty layer without taking the communicated length (from the scanner, in the first byte of a buffer) into account. For your amusement here's what happened to my machine before writing the first patch: [ 3801.712295] usb 6-2: new full-speed USB device number 12 using uhci_hcd [ 3801.883708] usb 6-2: New USB device found, idVendor=05e0, idProduct=0600 [ 3801.883712] usb 6-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 3801.883714] usb 6-2: Product: Symbol Bar Code Scanner [ 3801.883716] usb 6-2: Manufacturer: Symbol Technologies, Inc, 2008 [ 3801.883718] usb 6-2: SerialNumber: S/N:5520B838ED22C34CBC619E74103732B8 Rev:PAAALS00-002-R01- [ 3801.889804] symbolserial 6-2:1.0: symbol converter detected [ 3801.889962] usb 6-2: symbol converter now attached to ttyUSB0 [ 3801.896738] BUG: unable to handle kernel NULL pointer dereference at (null) [ 3801.896741] IP: [] _raw_spin_lock_irqsave+0xb/0x30 [ 3801.896746] PGD 61fb5b067 PUD 6208dd067 PMD 0 [ 3801.896748] Oops: 0002 [#1] SMP [ 3801.896749] Modules linked in: nvidia(O) [ 3801.896751] CPU: 7 PID: 8640 Comm: ModemManager Tainted: G O 4.2.0-rc7 #27 [ 3801.896752] Hardware name: System manufacturer System Product Name/P6T WS PRO, BIOS 120409/16/2010 [ 3801.896753] task: 88061daaba80 ti: 8800ba608000 task.ti: 8800ba608000 [ 3801.896754] RIP: 0010:[] [] _raw_spin_lock_irqsave+0xb/0x30 [ 3801.896756] RSP: 0018:8800ba60bba8 EFLAGS: 00010046 [ 3801.896757] RAX: RBX: 0296 RCX: 8806220b4800 [ 3801.896757] RDX: 0001 RSI: 8806220b4800 RDI: [ 3801.896758] RBP: 8806220b4800 R08: 0001 R09: c94d6000 [ 3801.896759] R10: 3000 R11: c94d5fff R12: 880623832780 [ 3801.896759] R13: 880591b09000 R14: 880591b09000 R15: 88061daaba80 [ 3801.896760] FS: 7fc35e569840() GS:88063fce() knlGS: [ 3801.896761] CS: 0010 DS: ES: CR0: 80050033 [ 3801.896762] CR2: CR3: 00061df01000 CR4: 06e0 [ 3801.896762] Stack: [ 3801.896763] 8153267b 8806243dd0a8 8806220b4808 [ 3801.896764] 8806238327e8 81511cc6 880591b09000 813c4b2e [ 3801.896765] 880591b09000 8806220b4808 880591b09000 8806220b4918 [ 3801.896766] Call Trace: [ 3801.896769] [] ? symbol_open+0x1b/0x70 [ 3801.896772] [] ? serial_port_activate+0x56/0x90 [ 3801.896775] [] ? tty_port_tty_set+0x2e/0x90 [ 3801.896776] [] ? tty_port_open+0x76/0xc0 [ 3801.896778] [] ? tty_init_dev+0x8f/0x1a0 [ 3801.896779] [] ? tty_open+0xf5/0x5a0 [ 3801.896782] [] ? mount_fs+0x160/0x160 [ 3801.896784] [] ? chrdev_open+0x9c/0x170 [ 3801.896785] [] ? cdev_put+0x20/0x20 [ 3801.896786] [] ? do_dentry_open+0x1c0/0x2f0 [ 3801.896788] [] ? path_openat+0x380/0x1030 [ 3801.896789] [] ? terminate_walk+0xa2/0xb0 [ 3801.896790] [] ? do_filp_open+0x70/0xd0 [ 3801.896792] [] ? __alloc_fd+0x37/0x100 [ 3801.896794] [] ? do_sys_open+0x11e/0x200 [ 3801.896795] [] ? entry_SYSCALL_64_fastpath+0x12/0x6a [ 3801.896795] Code: 31 c0 ba 01 00 00 00 f0 0f b1 17 85 c0 75 02 f3 c3 89 c6 e9 68 6d 91 ff 0f 1f 84 00 00 00 00 00 53 9c 5b fa 31 c0 ba 01 00 00 00 0f b1 17 85 c0 75 05 48 89 d8 5b c3 89 c6 e8 41 6d 91 ff 48 [ 3801.896809] RIP [] _raw_spin_lock_irqsave+0xb/0x30 [ 3801.896811] RSP [ 3801.896812] CR2: [ 3801.896813] ---[ end trace 196415182e1cd411 ]--- Philipp Hachtmann (2): USB: symbolserial: Use usb_get_serial_port_data USB: symbolserial: Correct transferred data size drivers/usb/serial/symbolserial.c | 24 +++- 1 file changed, 11 insertions(+), 13 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] USB: symbolserial: Use usb_get_serial_port_data
The driver used usb_get_serial_data(port->serial) which compiled but resulted in a NULL pointer being returned (and subsequently used). I did not go deeper into this but I guess this is a regression. Signed-off-by: Philipp Hachtmann --- drivers/usb/serial/symbolserial.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 8fceec7..6ed8044 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -94,7 +94,7 @@ exit: static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct symbol_private *priv = usb_get_serial_data(port->serial); + struct symbol_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result = 0; @@ -120,7 +120,7 @@ static void symbol_close(struct usb_serial_port *port) static void symbol_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - struct symbol_private *priv = usb_get_serial_data(port->serial); + struct symbol_private *priv = usb_get_serial_port_data(port); spin_lock_irq(&priv->lock); priv->throttled = true; @@ -130,7 +130,7 @@ static void symbol_throttle(struct tty_struct *tty) static void symbol_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - struct symbol_private *priv = usb_get_serial_data(port->serial); + struct symbol_private *priv = usb_get_serial_port_data(port); int result; bool was_throttled; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] USB: symbolserial: Correct transferred data size
The scanner (here DS3508) always returns 64 bytes per urb buffer. The first byte indicates the data length used in the current buffer. There even was a comment describing this. But the comment also said that we'll send everything in the buffer to the tty layer. That means sending the actual barcode data and lots of trailing zeroes. This patch lets the driver only send the real data. Signed-off-by: Philipp Hachtmann --- drivers/usb/serial/symbolserial.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 6ed8044..37f3ad1 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -60,17 +60,15 @@ static void symbol_int_callback(struct urb *urb) usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); + /* +* Data from the device comes with a 1 byte header: +* +* ... +*/ if (urb->actual_length > 1) { - data_length = urb->actual_length - 1; - - /* -* Data from the device comes with a 1 byte header: -* -* data... -* This is real data to be sent to the tty layer -* we pretty much just ignore the size and send everything -* else to the tty layer. -*/ + data_length = data[0]; + if (data_length > (urb->actual_length - 1)) + data_length = urb->actual_length - 1; tty_insert_flip_string(&port->port, &data[1], data_length); tty_flip_buffer_push(&port->port); } else { -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
VFS: Parallel unmounting of filesystems produces system call error
Hi Al, I just ran some tests involving many parallel mount and unmount operations. I sometimes get EINVAL and the umount program says "not mounted". Which is definitively wrong. It feels like a race condition somewhere in the VFS code. I use todays master branch (commit fc14f9c1272f62c3) on s390 with 1024 DASD devices. In fs/namespace.c, sys_umount: > retval = user_path_mountpoint_at(AT_FDCWD, name, > lookup_flags, &path); ... > retval = -EINVAL; > if (path.dentry != path.mnt->mnt_root) > goto dput_and_out; This seems to be erroneously true from time to time. The script does something equivalent to: > for n in $DEVNODES; do > umount $n & > done Do you have any idea what's wrong? Kind regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] sched: Support for CPU runtime and SMT based adaption
On virtualized systems like s390 the CPU runtimes used for the scheduler's calculations must be adapted to correctly represent real cpu working time instead of slices of wall time. Furthermore this real cpu runtime may have to be further adapted on SMT CPUs depending on the number of threads (Linux: CPUs) being active in the same core. This patch changes some calls to sched_clock_cpu into calls to cpu_exec_time. cpu_exec_time is defined as sched_clock_cpu by default but can be overridden by architecture code to provide precise CPU runtime timestamps. One might think that it would be better to override the weak symbol sched_clock instead of adding something new. This seems to be impossible because sched_clock is used by other facilities (like printk timestamping) which assume it to deliver wall time instead of some pure virtual time stamp which differs from CPU to CPU. The second hook is a call to an architecture function scale_rq_clock_delta which additionally scales the calculated delta by an SMT based factor. Signed-off-by: Philipp Hachtmann --- kernel/sched/core.c | 4 +++- kernel/sched/fair.c | 8 kernel/sched/sched.h | 8 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 89e7283..c611055 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -122,9 +122,11 @@ void update_rq_clock(struct rq *rq) if (rq->skip_clock_update > 0) return; - delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; + delta = cpu_exec_time(cpu_of(rq)) - rq->clock; if (delta < 0) return; + + scale_rq_clock_delta(&delta); rq->clock += delta; update_rq_clock_task(rq, delta); } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ef2b104..4921d1d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3180,7 +3180,7 @@ static inline u64 sched_cfs_bandwidth_slice(void) /* * Replenish runtime according to assigned quota and update expiration time. - * We use sched_clock_cpu directly instead of rq->clock to avoid adding + * We use cpu_exec_time directly instead of rq->clock to avoid adding * additional synchronization around rq->lock. * * requires cfs_b->lock @@ -3192,7 +3192,7 @@ void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b) if (cfs_b->quota == RUNTIME_INF) return; - now = sched_clock_cpu(smp_processor_id()); + now = cpu_exec_time(smp_processor_id()); cfs_b->runtime = cfs_b->quota; cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period); } @@ -6969,13 +6969,13 @@ static int idle_balance(struct rq *this_rq) } if (sd->flags & SD_BALANCE_NEWIDLE) { - t0 = sched_clock_cpu(this_cpu); + t0 = cpu_exec_time(this_cpu); pulled_task = load_balance(this_cpu, this_rq, sd, CPU_NEWLY_IDLE, &continue_balancing); - domain_cost = sched_clock_cpu(this_cpu) - t0; + domain_cost = cpu_exec_time(this_cpu) - t0; if (domain_cost > sd->max_newidle_lb_cost) sd->max_newidle_lb_cost = domain_cost; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 2df8ef0..720664f 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1569,3 +1569,11 @@ static inline u64 irq_time_read(int cpu) } #endif /* CONFIG_64BIT */ #endif /* CONFIG_IRQ_TIME_ACCOUNTING */ + +#ifndef cpu_exec_time +#define cpu_exec_time sched_clock_cpu +#endif + +#ifndef scale_rq_clock_delta +#define scale_rq_clock_delta(arg) +#endif -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] s390/cputime: SMT based scaling of CPU runtime deltas
The scheduler calculates CPU runtime deltas to account for a task's runtime. These deltas have to be adapted on SMT CPUs to reflect the real processing power consumed during the last delta. This patch introduces scale_rq_clock_delta which is used by the scheduler to scale the calculated delta by an SMT based factor. Signed-off-by: Philipp Hachtmann --- arch/s390/include/asm/cputime.h | 17 - arch/s390/kernel/vtime.c| 4 ++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index fee50dd..e44f285 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -8,6 +8,8 @@ #define _S390_CPUTIME_H #include +#include +#include #include #define CPUTIME_PER_USEC 4096ULL @@ -20,6 +22,9 @@ typedef unsigned long long __nocast cputime64_t; #define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new) +DECLARE_PER_CPU(u64, mt_scaling_mult); +DECLARE_PER_CPU(u64, mt_scaling_div); + static inline unsigned long __div(unsigned long long n, unsigned long base) { #ifndef CONFIG_64BIT @@ -172,6 +177,7 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime) * * Returns an incrementing time stamp in ns. */ +#define cpu_exec_time cpu_exec_time static inline u64 cpu_exec_time(int cpu_unused) { u64 timer; @@ -181,7 +187,16 @@ static inline u64 cpu_exec_time(int cpu_unused) return ((ULLONG_MAX - timer) * 1000) / 4096; } -#define cpu_exec_time cpu_exec_time + +#define scale_rq_clock_delta scale_rq_clock_delta +static inline void scale_rq_clock_delta(u64 *delta) +{ + u64 mult = __get_cpu_var(mt_scaling_mult); + u64 div = __get_cpu_var(mt_scaling_div); + + if (smp_cpu_mtid) + *delta = (*delta * mult) / div; +} cputime64_t arch_cpu_idle_time(int cpu); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 97b3c12..5d9bbd0 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -26,8 +26,8 @@ static atomic64_t virt_timer_current; static atomic64_t virt_timer_elapsed; static DEFINE_PER_CPU(u64, mt_cycles[32]); -static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 }; -static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 }; +DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 }; +DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 }; static inline u64 get_vtimer(void) { -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC] [PATCH 0/3] sched: Support for real CPU runtime and SMT scaling
Hello, when using "real" processors the scheduler can make its decisions based on wall time. But CPUs under hypervisor control are sometimes unavailable without further notice to the guest operating system. Using wall time for scheduling decisions in this case will lead to unfair decisions and erroneous distribution of CPU bandwidth when using cgroups. On (at least) S390 every CPU has a timer that counts the real execution time from IPL. When the hypervisor has sheduled out the CPU, the timer is stopped. So it is desirable to use this timer as a source for the scheduler's rq runtime calculations. On SMT systems the consumed runtime of a task might be worth more or less depending on the fact that the task can have run alone or not during the last delta. This should be scalable based on the current CPU utilization. The first patch introduces two little hooks to the optional architecture funtions cpu_exec_time and scale_rq_clock_delta. Calls to cpu_exec_time replace calls to sched_clock_cpu a few times but are mapped back to sched_clock_cpu if architecture does not define cpu_exec_time. The call to scale_rq_clock_delta is added into update_rq_clock (sched/core.c) and defaults to a NOP when not defined by architecture code. Regards Philipp Philipp Hachtmann (3): sched: Support for CPU runtime and SMT based adaption s390/cputime: Provide CPU runtime since IPL s390/cputime: SMT based scaling of CPU runtime deltas arch/s390/include/asm/cputime.h | 31 +++ arch/s390/kernel/vtime.c| 4 ++-- kernel/sched/core.c | 4 +++- kernel/sched/fair.c | 8 kernel/sched/sched.h| 8 5 files changed, 48 insertions(+), 7 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/3] s390/cputime: Provide CPU runtime since IPL
The cpu maintains a cpu timer which runs only while the cpu is available to the system (i.e. not scheduled away by the hypervisor). This patch introduces a function cpu_exec_time that returns a time stamp which reflects the cpu's real processing time since IPL. Signed-off-by: Philipp Hachtmann --- arch/s390/include/asm/cputime.h | 16 1 file changed, 16 insertions(+) diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index b91e960..fee50dd 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -167,6 +167,22 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime) return clock; } +/* + * Read out the current CPU's timer + * + * Returns an incrementing time stamp in ns. + */ +static inline u64 cpu_exec_time(int cpu_unused) +{ + u64 timer; + asm volatile( + " stpt%0\n" /* Store current cpu timer value */ + : "=m" (timer)); + + return ((ULLONG_MAX - timer) * 1000) / 4096; +} +#define cpu_exec_time cpu_exec_time + cputime64_t arch_cpu_idle_time(int cpu); #define arch_idle_time(cpu) arch_cpu_idle_time(cpu) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH linux-next] fs: remove void * casting in init_once()
On 16.05.2017 20:38, Fabian Frederick wrote: See Documentation/process/coding-style.rst: "Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language." This will stop copy/paste cascade warnings. Signed-off-by: Fabian Frederick --- I like that patch.